Skip to content

Commit

Permalink
feat: add codemods for rcfile files, middleware and env validations
Browse files Browse the repository at this point in the history
  • Loading branch information
thetutlage committed Aug 21, 2023
1 parent b0a097a commit 6f24670
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 26 deletions.
95 changes: 85 additions & 10 deletions commands/configure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
*/

import { slash } from '@poppinss/utils'
import { EnvEditor } from '@adonisjs/env/editor'
import type { AddMiddlewareEntry, EnvValidationDefinition } from '@adonisjs/assembler/types'
import { installPackage, detectPackageManager } from '@antfu/install-pkg'
import type { CodeTransformer } from '@adonisjs/assembler/code_transformer'

import { EnvEditor } from '@adonisjs/env/editor'
import { args, BaseCommand, flags } from '../modules/ace/main.js'
import { RcFileEditor } from '@adonisjs/application/rc_file_editor'

/**
* The configure command is used to configure packages after installation
Expand All @@ -33,6 +34,17 @@ export default class Configure extends BaseCommand {
*/
declare stubsRoot: string

/**
* Flag to know if assembler is installed as a
* peer dependency or not.
*/
#isAssemblerInstalled?: boolean

/**
* Reference to lazily imported assembler code transformer
*/
#codeTransformer?: typeof import('@adonisjs/assembler/code_transformer')

/**
* Returns the package main exports
*/
Expand Down Expand Up @@ -65,6 +77,16 @@ export default class Configure extends BaseCommand {
}
}

/**
* Lazily installs assembler
*/
async #installAssembler() {
if (this.#isAssemblerInstalled === undefined) {
this.#codeTransformer = await import('@adonisjs/assembler/code_transformer')
this.#isAssemblerInstalled = !!this.#codeTransformer
}
}

/**
* Publish a stub file to the user project
*/
Expand All @@ -91,29 +113,82 @@ export default class Configure extends BaseCommand {
* Define one or more environment variables
*/
async defineEnvVariables(environmentVariables: Record<string, number | string | boolean>) {
const logs: string[] = []
const editor = new EnvEditor(this.app.appRoot)
await editor.load()

Object.keys(environmentVariables).forEach((key) => {
const value = environmentVariables[key]
editor.add(key, value)
logs.push(` ${this.colors.dim(`${key}=${value}`)}`)
})

await editor.save()
this.logger.action('update .env file').succeeded()
this.logger.log(logs.join('\n'))
}

/**
* Define validations for the environment variables
*/
async defineEnvValidations(validations: EnvValidationDefinition) {
await this.#installAssembler()
if (!this.#codeTransformer) {
this.logger.warning(
'Cannot update "start/env.ts" file. Install "@adonisjs/assembler" to modify source files'
)
return
}

const transformer = new this.#codeTransformer.CodeTransformer(this.app.appRoot)
const action = this.logger.action('update start/env.ts file')
try {
await transformer.defineEnvValidations(validations)
action.succeeded()
} catch (error) {
action.failed(error.message)
}
}

/**
* Define validations for the environment variables
*/
async registerMiddleware(stack: 'server' | 'router' | 'named', middleware: AddMiddlewareEntry[]) {
await this.#installAssembler()
if (!this.#codeTransformer) {
this.logger.warning(
'Cannot update "start/kernel.ts" file. Install "@adonisjs/assembler" to modify source files'
)
return
}

const transformer = new this.#codeTransformer.CodeTransformer(this.app.appRoot)
const action = this.logger.action('update start/kernel.ts file')

try {
await transformer.addMiddlewareToStack(stack, middleware)
action.succeeded()
} catch (error) {
action.failed(error.message)
}
}

/**
* Update rcFile
*/
async updateRcFile(callback: (rcFileEditor: RcFileEditor) => Promise<void> | void) {
const rcFileEditor = new RcFileEditor(this.app.makeURL('.adonisrc.json'), this.app.rcFile.raw)
await callback(rcFileEditor)
await rcFileEditor.save()
this.logger.action('update .adonisrc.json file').succeeded()
async updateRcFile(...params: Parameters<CodeTransformer['updateRcFile']>) {
await this.#installAssembler()
if (!this.#codeTransformer) {
this.logger.warning(
'Cannot update "adonisrc.ts" file. Install "@adonisjs/assembler" to modify source files'
)
return
}

const action = this.logger.action('update adonisrc.ts file')
try {
await new this.#codeTransformer.CodeTransformer(this.app.appRoot).updateRcFile(...params)
action.succeeded()
} catch (error) {
action.failed(error.message)
}
}

/**
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
"index:commands": "node --loader=ts-node/esm toolkit/main.js index build/commands"
},
"devDependencies": {
"@adonisjs/assembler": "^6.1.3-17",
"@adonisjs/assembler": "^6.1.3-18",
"@adonisjs/eslint-config": "^1.1.8",
"@adonisjs/prettier-config": "^1.1.8",
"@adonisjs/tsconfig": "^1.1.8",
Expand Down Expand Up @@ -138,7 +138,7 @@
"youch-terminal": "^2.2.2"
},
"peerDependencies": {
"@adonisjs/assembler": "^6.1.3-17",
"@adonisjs/assembler": "^6.1.3-18",
"@vinejs/vine": "^1.6.0",
"argon2": "^0.30.3",
"bcrypt": "^5.0.1",
Expand Down
79 changes: 65 additions & 14 deletions tests/commands/configure.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,6 @@ test.group('Configure command | environment variables', () => {
message: 'green(DONE:) update .env file',
stream: 'stdout',
},
{
message: [
' dim(CORS_MODE=strict)',
' dim(CORS_ENABLED=true)',
].join('\n'),
stream: 'stdout',
},
])

await assert.fileContains('.env', 'CORS_MODE=strict')
Expand All @@ -138,16 +131,42 @@ test.group('Configure command | environment variables', () => {
message: 'green(DONE:) update .env file',
stream: 'stdout',
},
])

await assert.fileNotExists('.env')
})

test('define env variables validations', async ({ assert, fs }) => {
const ace = await new AceFactory().make(fs.baseUrl, {
importer: (filePath) => import(filePath),
})
await ace.app.init()
ace.ui.switchMode('raw')

await fs.createJson('tsconfig.json', {})

/**
* Creating .env file so that we can update it.
*/
await fs.create('start/env.ts', `export default Env.create(new URL('./'), {})`)

const command = await ace.create(Configure, ['../dummy-pkg.js'])
command.stubsRoot = join(fs.basePath, 'stubs')

await command.defineEnvValidations({
variables: {
CORS_MODE: 'Env.schema.string()',
},
})

assert.deepEqual(command.ui.logger.getLogs(), [
{
message: [
' dim(CORS_MODE=strict)',
' dim(CORS_ENABLED=true)',
].join('\n'),
message: 'green(DONE:) update start/env.ts file',
stream: 'stdout',
},
])

await assert.fileNotExists('.env')
await assert.fileContains('start/env.ts', 'CORS_MODE: Env.schema.string()')
})
})

Expand All @@ -159,21 +178,53 @@ test.group('Configure command | rcFile', () => {
await ace.app.init()
ace.ui.switchMode('raw')

await fs.createJson('tsconfig.json', {})
await fs.create('adonisrc.ts', 'export default defineConfig({})')

const command = await ace.create(Configure, ['../dummy-pkg.js'])
command.stubsRoot = join(fs.basePath, 'stubs')

await command.updateRcFile((rcFile) => {
rcFile.addProvider('@adonisjs/core')
rcFile.addCommand('@adonisjs/core/commands')
})

assert.deepEqual(command.ui.logger.getLogs(), [
{
message: 'green(DONE:) update adonisrc.ts file',
stream: 'stdout',
},
])

await assert.fileContains('adonisrc.ts', '@adonisjs/core')
await assert.fileContains('adonisrc.ts', '@adonisjs/core/commands')
})
})

test.group('Configure command | registerMiddleware', () => {
test('register middleware', async ({ assert, fs }) => {
const ace = await new AceFactory().make(fs.baseUrl, {
importer: (filePath) => import(filePath),
})
await ace.app.init()
ace.ui.switchMode('raw')

await fs.createJson('tsconfig.json', {})
await fs.create('start/kernel.ts', 'router.use([])')

const command = await ace.create(Configure, ['../dummy-pkg.js'])
command.stubsRoot = join(fs.basePath, 'stubs')

await command.registerMiddleware('router', [{ path: '@adonisjs/core/bodyparser_middleware' }])

assert.deepEqual(command.ui.logger.getLogs(), [
{
message: 'green(DONE:) update .adonisrc.json file',
message: 'green(DONE:) update start/kernel.ts file',
stream: 'stdout',
},
])

await assert.fileContains('.adonisrc.json', '@adonisjs/core')
await assert.fileContains('start/kernel.ts', '@adonisjs/core/bodyparser_middleware')
})
})

Expand Down

0 comments on commit 6f24670

Please sign in to comment.