feat: add Drupal application module
This commit is contained in:
@@ -132,9 +132,9 @@ async function renderCompose(c: AuroraConfig): Promise<string> {
|
||||
async function writePhpDockerfile(root: string, xdebug = false): Promise<void> {
|
||||
await writeFile(phpDockerfilePath(root), `ARG PHP_VERSION=8.4
|
||||
FROM php:${'${PHP_VERSION}'}-fpm-alpine
|
||||
RUN apk add --no-cache icu-dev libzip-dev libpng-dev libjpeg-turbo-dev freetype-dev oniguruma-dev postgresql-dev \
|
||||
RUN apk add --no-cache icu-dev libzip-dev libpng-dev libjpeg-turbo-dev freetype-dev oniguruma-dev postgresql-dev curl-dev libxml2-dev \
|
||||
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
|
||||
&& docker-php-ext-install -j2 mysqli pdo_mysql pdo_pgsql intl zip gd mbstring
|
||||
&& docker-php-ext-install -j2 mysqli pdo_mysql pdo_pgsql intl zip gd mbstring curl dom opcache
|
||||
COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer
|
||||
${xdebug ? 'RUN apk add --no-cache $PHPIZE_DEPS linux-headers && pecl install xdebug && docker-php-ext-enable xdebug' : ''}
|
||||
`)
|
||||
@@ -211,7 +211,9 @@ export async function createProject(root: string, name: string, type: string, do
|
||||
if (stack?.adminer !== false) modules.push('adminer')
|
||||
if (stack?.redis) modules.push('redis')
|
||||
if (stack?.mailpit) modules.push('mailpit')
|
||||
const config: AuroraConfig = { name, type: normalizedType, docroot: defaultDocroot, php: stack?.phpVersion || '8.4', node: stack?.nodeVersion || '24', webserver: stack?.webServer || 'nginx', database: stack?.database || 'mariadb', databaseVersion: stack?.databaseVersion || '11.8', modules, moduleSettings: {}, primaryProtocol: 'https', xdebug: stack?.xdebug === true }
|
||||
const phpVersion = stack?.phpVersion || application.creation?.phpVersions?.[0] || '8.4'
|
||||
if (application.creation?.phpVersions?.length && !application.creation.phpVersions.includes(phpVersion)) throw new Error(`${application.name} does not support PHP ${phpVersion}`)
|
||||
const config: AuroraConfig = { name, type: normalizedType, docroot: defaultDocroot, php: phpVersion, node: stack?.nodeVersion || '24', webserver: stack?.webServer || 'nginx', database: stack?.database || 'mariadb', databaseVersion: stack?.databaseVersion || '11.8', modules, moduleSettings: {}, primaryProtocol: 'https', xdebug: stack?.xdebug === true }
|
||||
await writeConfig(root, config); await writeWebServerConfig(root, config); await writePhpDockerfile(root, config.xdebug)
|
||||
const reg = await loadRegistry(); reg.projects[name] = root; await saveRegistry(reg)
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ describe('external module registry', () => {
|
||||
expect(() => validateModuleManifest({ ...manifest, main: '../outside.cjs' })).toThrow(/may not leave/)
|
||||
expect(() => validateModuleManifest({ ...manifest, dependencies: ['../escape'] })).toThrow(/module id array/)
|
||||
expect(() => validateModuleManifest({ ...manifest, project: { adminPath: 'admin' } })).toThrow(/must start with/)
|
||||
expect(() => validateModuleManifest({ ...manifest, creation: { phpVersions: ['latest'] } })).toThrow(/PHP minor versions/)
|
||||
})
|
||||
it('rejects symbolic links in package paths', async () => {
|
||||
const userData = await temp('aurora-user-'); const source = await packageDir(); await mkdir(join(source, 'main')); await symlink('/tmp', join(source, 'main', 'escape'))
|
||||
@@ -135,4 +136,14 @@ describe('external module registry', () => {
|
||||
expect((await installModulePackage(archive, userData)).manifest.id).toBe('wordpress')
|
||||
expect((await getModuleRegistry(userData)).map((item) => item.id)).toEqual(['wordpress'])
|
||||
})
|
||||
|
||||
it('accepts and packages the Drupal application module contract', async () => {
|
||||
const packageRoot = resolve(process.cwd(), 'packages/aurora-module-drupal')
|
||||
const actual = JSON.parse(await readFile(join(packageRoot, 'manifest.json'), 'utf8'))
|
||||
expect(validateModuleManifest(actual)).toMatchObject({ id: 'drupal', defaults: { docroot: 'web' } })
|
||||
const archive = join(await temp('aurora-pac-'), 'drupal.pac')
|
||||
await execFileAsync('zip', ['-qr', archive, '.'], { cwd: packageRoot })
|
||||
const userData = await temp('aurora-user-')
|
||||
expect((await installModulePackage(archive, userData)).manifest.id).toBe('drupal')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -51,7 +51,11 @@ export function validateModuleManifest(value: unknown): AuroraModuleManifest {
|
||||
if (!compatible(aurora.core, CORE_VERSION)) throw new Error(`Module requires Aurora Core '${aurora.core}', running '${CORE_VERSION}'`)
|
||||
if (!compatible(aurora.moduleApi, MODULE_API_VERSION)) throw new Error(`Module API '${aurora.moduleApi}' is incompatible with '${MODULE_API_VERSION}'`)
|
||||
if (m.main !== undefined) validateRelativePackagePath(m.main, 'main')
|
||||
if (m.creation && typeof m.creation === 'object') validateSettings((m.creation as Record<string, unknown>).setup ?? [], 'creation.setup')
|
||||
if (m.creation && typeof m.creation === 'object') {
|
||||
const creation = m.creation as Record<string, unknown>
|
||||
validateSettings(creation.setup ?? [], 'creation.setup')
|
||||
if (creation.phpVersions !== undefined && (!Array.isArray(creation.phpVersions) || !creation.phpVersions.every((version) => typeof version === 'string' && /^\d+\.\d+$/.test(version)))) throw new Error('creation.phpVersions must contain PHP minor versions')
|
||||
}
|
||||
if (m.project !== undefined) {
|
||||
if (!m.project || typeof m.project !== 'object' || Array.isArray(m.project)) throw new Error('project must be an object')
|
||||
const project = m.project as Record<string, unknown>
|
||||
|
||||
@@ -35,6 +35,7 @@ export async function runModuleLifecycleHook(moduleId: string, hook: AuroraModul
|
||||
if (typeof handler !== 'function') return false
|
||||
const directory = options.directory
|
||||
const urls = options.projectName ? projectUrls(options.projectName) : undefined
|
||||
const projectConfig = directory ? await getProjectConfig(directory) : undefined
|
||||
const run = async (label: string, command: string, args: string[]): Promise<void> => {
|
||||
if (options.sender && options.operationId) {
|
||||
if (!options.sender.isDestroyed()) options.sender.send('terminal:data', { operationId: options.operationId, stream: 'stdout', chunk: `\n[${manifest.name}] ${label}\n` })
|
||||
@@ -49,6 +50,7 @@ export async function runModuleLifecycleHook(moduleId: string, hook: AuroraModul
|
||||
projectName: options.projectName,
|
||||
toolId: options.toolId,
|
||||
settings: Object.freeze({ ...(options.settings ?? {}) }),
|
||||
environment: projectConfig ? Object.freeze({ php: projectConfig.php, node: projectConfig.node, webserver: projectConfig.webserver, database: projectConfig.database, databaseVersion: projectConfig.databaseVersion, docroot: projectConfig.docroot }) : undefined,
|
||||
urls: urls ? Object.freeze(urls) : undefined,
|
||||
run,
|
||||
ensureRouter,
|
||||
|
||||
Reference in New Issue
Block a user