@adonisjs/assembler 7.0.0-0 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -390,6 +390,36 @@ export const plugins: Config['plugins'] = [
390
390
  ]
391
391
  ```
392
392
 
393
+ ### addPolicies
394
+ Register AdonisJS bouncer policies to the list of `policies` object exported from the `app/policies/main.ts` file.
395
+
396
+ > [!IMPORTANT]
397
+ > This codemod expects the `app/policies/main.ts` file to exist and must export a `policies` object from it.
398
+
399
+ ```ts
400
+ const transformer = new CodeTransformer(appRoot)
401
+
402
+ try {
403
+ await transformer.addPolicies([
404
+ {
405
+ name: 'PostPolicy',
406
+ path: '#policies/post_policy'
407
+ }
408
+ ])
409
+ } catch (error) {
410
+ console.error('Unable to register policy')
411
+ console.error(error)
412
+ }
413
+ ```
414
+
415
+ Output
416
+
417
+ ```ts
418
+ export const policies = {
419
+ UserPolicy: () => import('#policies/post_policy')
420
+ }
421
+ ```
422
+
393
423
  ## Contributing
394
424
  One of the primary goals of AdonisJS is to have a vibrant community of users and contributors who believe in the framework's principles.
395
425
 
package/build/index.js CHANGED
@@ -26,10 +26,6 @@ var debug_default = debuglog("adonisjs:assembler");
26
26
  var DEFAULT_NODE_ARGS = [
27
27
  // Use ts-node/esm loader. The project must install it
28
28
  "--loader=ts-node/esm",
29
- // Disable annoying warnings
30
- "--no-warnings",
31
- // Enable expiremental meta resolve for cases where someone uses magic import string
32
- "--experimental-import-meta-resolve",
33
29
  // Enable source maps, since TSNode source maps are broken
34
30
  "--enable-source-maps"
35
31
  ];
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bundler.ts","../src/helpers.ts","../src/debug.ts","../src/dev_server.ts","../src/assets_dev_server.ts","../src/test_runner.ts"],"sourcesContent":["/*\n * @adonisjs/assembler\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport slash from 'slash'\nimport fs from 'node:fs/promises'\nimport { relative } from 'node:path'\nimport type tsStatic from 'typescript'\nimport { fileURLToPath } from 'node:url'\nimport { cliui, type Logger } from '@poppinss/cliui'\nimport { detectPackageManager } from '@antfu/install-pkg'\n\nimport type { BundlerOptions } from './types.js'\nimport { run, parseConfig, copyFiles } from './helpers.js'\n\ntype SupportedPackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun'\n\n/**\n * List of package managers we support in order to\n * copy lockfiles\n */\nconst SUPPORT_PACKAGE_MANAGERS: {\n [K in SupportedPackageManager]: {\n lockFile: string\n installCommand: string\n }\n} = {\n npm: {\n lockFile: 'package-lock.json',\n installCommand: 'npm ci --omit=\"dev\"',\n },\n yarn: {\n lockFile: 'yarn.lock',\n installCommand: 'yarn install --production',\n },\n pnpm: {\n lockFile: 'pnpm-lock.yaml',\n installCommand: 'pnpm i --prod',\n },\n bun: {\n lockFile: 'bun.lockb',\n installCommand: 'bun install --production',\n },\n}\n\n/**\n * Instance of CLIUI\n */\nconst ui = cliui()\n\n/**\n * The bundler class exposes the API to build an AdonisJS project.\n */\nexport class Bundler {\n #cwd: URL\n #cwdPath: string\n #ts: typeof tsStatic\n #logger = ui.logger\n #options: BundlerOptions\n\n /**\n * Getting reference to colors library from logger\n */\n get #colors() {\n return this.#logger.getColors()\n }\n\n constructor(cwd: URL, ts: typeof tsStatic, options: BundlerOptions) {\n this.#cwd = cwd\n this.#cwdPath = fileURLToPath(this.#cwd)\n this.#ts = ts\n this.#options = options\n }\n\n /**\n * Returns the relative unix path for an absolute\n * file path\n */\n #getRelativeName(filePath: string) {\n return slash(relative(this.#cwdPath, filePath))\n }\n\n /**\n * Cleans up the build directory\n */\n async #cleanupBuildDirectory(outDir: string) {\n await fs.rm(outDir, { recursive: true, force: true, maxRetries: 5 })\n }\n\n /**\n * Runs assets bundler command to build assets\n */\n async #buildAssets(): Promise<boolean> {\n const assetsBundler = this.#options.assets\n if (!assetsBundler?.enabled) {\n return true\n }\n\n try {\n this.#logger.info('compiling frontend assets', { suffix: assetsBundler.cmd })\n await run(this.#cwd, {\n stdio: 'inherit',\n script: assetsBundler.cmd,\n scriptArgs: assetsBundler.args,\n })\n return true\n } catch {\n return false\n }\n }\n\n /**\n * Runs tsc command to build the source.\n */\n async #runTsc(outDir: string): Promise<boolean> {\n try {\n await run(this.#cwd, {\n stdio: 'inherit',\n script: 'tsc',\n scriptArgs: ['--outDir', outDir],\n })\n return true\n } catch {\n return false\n }\n }\n\n /**\n * Copy meta files to the output directory\n */\n async #copyMetaFiles(outDir: string, additionalFilesToCopy: string[]) {\n const metaFiles = (this.#options.metaFiles || [])\n .map((file) => file.pattern)\n .concat(additionalFilesToCopy)\n\n await copyFiles(metaFiles, this.#cwdPath, outDir)\n }\n\n /**\n * Detect the package manager used by the project\n * and return the lockfile name and install command\n * related to it.\n */\n async #getPackageManager(client?: SupportedPackageManager) {\n let pkgManager: string | null | undefined = client\n\n if (!pkgManager) {\n pkgManager = await detectPackageManager(this.#cwdPath)\n }\n if (!pkgManager) {\n pkgManager = 'npm'\n }\n\n if (!Object.keys(SUPPORT_PACKAGE_MANAGERS).includes(pkgManager)) {\n return null\n }\n\n return SUPPORT_PACKAGE_MANAGERS[pkgManager as SupportedPackageManager]\n }\n\n /**\n * Set a custom CLI UI logger\n */\n setLogger(logger: Logger) {\n this.#logger = logger\n return this\n }\n\n /**\n * Bundles the application to be run in production\n */\n async bundle(stopOnError: boolean = true, client?: SupportedPackageManager): Promise<boolean> {\n /**\n * Step 1: Parse config file to get the build output directory\n */\n const config = parseConfig(this.#cwd, this.#ts)\n if (!config) {\n return false\n }\n\n /**\n * Step 2: Cleanup existing build directory (if any)\n */\n const outDir = config.options.outDir || fileURLToPath(new URL('build/', this.#cwd))\n this.#logger.info('cleaning up output directory', { suffix: this.#getRelativeName(outDir) })\n await this.#cleanupBuildDirectory(outDir)\n\n /**\n * Step 3: Build frontend assets\n */\n if (!(await this.#buildAssets())) {\n return false\n }\n\n /**\n * Step 4: Build typescript source code\n */\n this.#logger.info('compiling typescript source', { suffix: 'tsc' })\n const buildCompleted = await this.#runTsc(outDir)\n await copyFiles(['ace.js'], this.#cwdPath, outDir)\n\n /**\n * Remove incomplete build directory when tsc build\n * failed and stopOnError is set to true.\n */\n if (!buildCompleted && stopOnError) {\n await this.#cleanupBuildDirectory(outDir)\n const instructions = ui\n .sticker()\n .fullScreen()\n .drawBorder((borderChar, colors) => colors.red(borderChar))\n\n instructions.add(\n this.#colors.red('Cannot complete the build process as there are TypeScript errors.')\n )\n instructions.add(\n this.#colors.red(\n 'Use \"--ignore-ts-errors\" flag to ignore TypeScript errors and continue the build.'\n )\n )\n\n this.#logger.logError(instructions.prepare())\n return false\n }\n\n /**\n * Step 5: Copy meta files to the build directory\n */\n const pkgManager = await this.#getPackageManager(client)\n const pkgFiles = pkgManager ? ['package.json', pkgManager.lockFile] : ['package.json']\n this.#logger.info('copying meta files to the output directory')\n await this.#copyMetaFiles(outDir, pkgFiles)\n\n this.#logger.success('build completed')\n this.#logger.log('')\n\n /**\n * Next steps\n */\n ui.instructions()\n .useRenderer(this.#logger.getRenderer())\n .heading('Run the following commands to start the server in production')\n .add(this.#colors.cyan(`cd ${this.#getRelativeName(outDir)}`))\n .add(\n this.#colors.cyan(\n pkgManager ? pkgManager.installCommand : 'Install production dependencies'\n )\n )\n .add(this.#colors.cyan('node bin/server.js'))\n .render()\n\n return true\n }\n}\n","/*\n * @adonisjs/assembler\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { isJunk } from 'junk'\nimport fastGlob from 'fast-glob'\nimport getRandomPort from 'get-port'\nimport { existsSync } from 'node:fs'\nimport type tsStatic from 'typescript'\nimport { fileURLToPath } from 'node:url'\nimport { execaNode, execa } from 'execa'\nimport { copyFile, mkdir } from 'node:fs/promises'\nimport { EnvLoader, EnvParser } from '@adonisjs/env'\nimport { ConfigParser, Watcher } from '@poppinss/chokidar-ts'\nimport { basename, dirname, isAbsolute, join, relative } from 'node:path'\n\nimport type { RunOptions, WatchOptions } from './types.js'\nimport debug from './debug.js'\n\n/**\n * Default set of args to pass in order to run TypeScript\n * source. Used by \"run\" and \"runNode\" scripts\n */\nconst DEFAULT_NODE_ARGS = [\n // Use ts-node/esm loader. The project must install it\n '--loader=ts-node/esm',\n // Disable annoying warnings\n '--no-warnings',\n // Enable expiremental meta resolve for cases where someone uses magic import string\n '--experimental-import-meta-resolve',\n // Enable source maps, since TSNode source maps are broken\n '--enable-source-maps',\n]\n\n/**\n * Parses tsconfig.json and prints errors using typescript compiler\n * host\n */\nexport function parseConfig(cwd: string | URL, ts: typeof tsStatic) {\n const { config, error } = new ConfigParser(cwd, 'tsconfig.json', ts).parse()\n if (error) {\n const compilerHost = ts.createCompilerHost({})\n console.log(ts.formatDiagnosticsWithColorAndContext([error], compilerHost))\n return\n }\n\n if (config!.errors.length) {\n const compilerHost = ts.createCompilerHost({})\n console.log(ts.formatDiagnosticsWithColorAndContext(config!.errors, compilerHost))\n return\n }\n\n return config\n}\n\n/**\n * Runs a Node.js script as a child process and inherits the stdio streams\n */\nexport function runNode(cwd: string | URL, options: RunOptions) {\n const childProcess = execaNode(options.script, options.scriptArgs, {\n nodeOptions: DEFAULT_NODE_ARGS.concat(options.nodeArgs),\n preferLocal: true,\n windowsHide: false,\n localDir: cwd,\n cwd,\n buffer: false,\n stdio: options.stdio || 'inherit',\n env: {\n ...(options.stdio === 'pipe' ? { FORCE_COLOR: 'true' } : {}),\n ...options.env,\n },\n })\n\n return childProcess\n}\n\n/**\n * Runs a script as a child process and inherits the stdio streams\n */\nexport function run(cwd: string | URL, options: Omit<RunOptions, 'nodeArgs'>) {\n const childProcess = execa(options.script, options.scriptArgs, {\n preferLocal: true,\n windowsHide: false,\n localDir: cwd,\n cwd,\n buffer: false,\n stdio: options.stdio || 'inherit',\n env: {\n ...(options.stdio === 'pipe' ? { FORCE_COLOR: 'true' } : {}),\n ...options.env,\n },\n })\n\n return childProcess\n}\n\n/**\n * Watches the file system using tsconfig file\n */\nexport function watch(cwd: string | URL, ts: typeof tsStatic, options: WatchOptions) {\n const config = parseConfig(cwd, ts)\n if (!config) {\n return\n }\n\n const watcher = new Watcher(typeof cwd === 'string' ? cwd : fileURLToPath(cwd), config!)\n const chokidar = watcher.watch(['.'], { usePolling: options.poll })\n return { watcher, chokidar }\n}\n\n/**\n * Check if file is an .env file\n */\nexport function isDotEnvFile(filePath: string) {\n if (filePath === '.env') {\n return true\n }\n\n return filePath.includes('.env.')\n}\n\n/**\n * Returns the port to use after inspect the dot-env files inside\n * a given directory.\n *\n * A random port is used when the specified port is in use. Following\n * is the logic for finding a specified port.\n *\n * - The \"process.env.PORT\" value is used if exists.\n * - The dot-env files are loaded using the \"EnvLoader\" and the PORT\n * value is used by iterating over all the loaded files. The\n * iteration stops after first find.\n */\nexport async function getPort(cwd: URL): Promise<number> {\n /**\n * Use existing port if exists\n */\n if (process.env.PORT) {\n return getRandomPort({ port: Number(process.env.PORT) })\n }\n\n /**\n * Loop over files and use the port from their contents. Stops\n * after first match\n */\n const files = await new EnvLoader(cwd).load()\n for (let file of files) {\n const envVariables = new EnvParser(file.contents).parse()\n if (envVariables.PORT) {\n return getRandomPort({ port: Number(envVariables.PORT) })\n }\n }\n\n /**\n * Use 3333 as the port\n */\n return getRandomPort({ port: 3333 })\n}\n\n/**\n * Helper function to copy files from relative paths or glob\n * patterns\n */\nexport async function copyFiles(files: string[], cwd: string, outDir: string) {\n /**\n * Looping over files and create a new collection with paths\n * and glob patterns\n */\n const { paths, patterns } = files.reduce<{ patterns: string[]; paths: string[] }>(\n (result, file) => {\n /**\n * If file is a glob pattern, then push it to patterns\n */\n if (fastGlob.isDynamicPattern(file)) {\n result.patterns.push(file)\n return result\n }\n\n /**\n * Otherwise, check if file exists and push it to paths to copy\n */\n if (existsSync(join(cwd, file))) {\n result.paths.push(file)\n }\n\n return result\n },\n { patterns: [], paths: [] }\n )\n\n debug('copyFiles inputs: %O, paths: %O, patterns: %O', files, paths, patterns)\n\n /**\n * Getting list of relative paths from glob patterns\n */\n const filePaths = paths.concat(await fastGlob(patterns, { cwd, dot: true })).filter((file) => {\n return !isJunk(basename(file))\n })\n\n /**\n * Finally copy files to the destination by keeping the same\n * directory structure and ignoring junk files\n */\n debug('copying files %O to destination \"%s\"', filePaths, outDir)\n const copyPromises = filePaths.map(async (file) => {\n const src = isAbsolute(file) ? file : join(cwd, file)\n const dest = join(outDir, relative(cwd, src))\n\n await mkdir(dirname(dest), { recursive: true })\n return copyFile(src, dest)\n })\n\n return await Promise.all(copyPromises)\n}\n","/*\n * @adonisjs/assembler\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { debuglog } from 'node:util'\n\nexport default debuglog('adonisjs:assembler')\n","/*\n * @adonisjs/assembler\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport picomatch from 'picomatch'\nimport type tsStatic from 'typescript'\nimport prettyHrtime from 'pretty-hrtime'\nimport { type ExecaChildProcess } from 'execa'\nimport { cliui, type Logger } from '@poppinss/cliui'\nimport type { Watcher } from '@poppinss/chokidar-ts'\n\nimport type { DevServerOptions } from './types.js'\nimport { AssetsDevServer } from './assets_dev_server.js'\nimport { getPort, isDotEnvFile, runNode, watch } from './helpers.js'\n\n/**\n * Instance of CLIUI\n */\nconst ui = cliui()\n\n/**\n * Exposes the API to start the development. Optionally, the watch API can be\n * used to watch for file changes and restart the development server.\n *\n * The Dev server performs the following actions\n *\n * - Assigns a random PORT, when PORT inside .env file is in use.\n * - Uses tsconfig.json file to collect a list of files to watch.\n * - Uses metaFiles from adonisrc.ts file to collect a list of files to watch.\n * - Restart HTTP server on every file change.\n */\nexport class DevServer {\n #cwd: URL\n #logger = ui.logger\n #options: DevServerOptions\n\n /**\n * Flag to know if the dev server is running in watch\n * mode\n */\n #isWatching: boolean = false\n\n /**\n * Script file to start the development server\n */\n #scriptFile: string = 'bin/server.js'\n\n /**\n * Picomatch matcher function to know if a file path is a\n * meta file with reloadServer option enabled\n */\n #isMetaFileWithReloadsEnabled: picomatch.Matcher\n\n /**\n * Picomatch matcher function to know if a file path is a\n * meta file with reloadServer option disabled\n */\n #isMetaFileWithReloadsDisabled: picomatch.Matcher\n\n /**\n * External listeners that are invoked when child process\n * gets an error or closes\n */\n #onError?: (error: any) => any\n #onClose?: (exitCode: number) => any\n\n /**\n * Reference to the child process\n */\n #httpServer?: ExecaChildProcess<string>\n\n /**\n * Reference to the watcher\n */\n #watcher?: ReturnType<Watcher['watch']>\n\n /**\n * Reference to the assets server\n */\n #assetsServer?: AssetsDevServer\n\n /**\n * Getting reference to colors library from logger\n */\n get #colors() {\n return this.#logger.getColors()\n }\n\n constructor(cwd: URL, options: DevServerOptions) {\n this.#cwd = cwd\n this.#options = options\n\n this.#isMetaFileWithReloadsEnabled = picomatch(\n (this.#options.metaFiles || [])\n .filter(({ reloadServer }) => reloadServer === true)\n .map(({ pattern }) => pattern)\n )\n\n this.#isMetaFileWithReloadsDisabled = picomatch(\n (this.#options.metaFiles || [])\n .filter(({ reloadServer }) => reloadServer !== true)\n .map(({ pattern }) => pattern)\n )\n }\n\n /**\n * Inspect if child process message is from AdonisJS HTTP server\n */\n #isAdonisJSReadyMessage(message: unknown): message is {\n isAdonisJS: true\n environment: 'web'\n port: number\n host: string\n duration?: [number, number]\n } {\n return (\n message !== null &&\n typeof message === 'object' &&\n 'isAdonisJS' in message &&\n 'environment' in message &&\n message.environment === 'web'\n )\n }\n\n /**\n * Conditionally clear the terminal screen\n */\n #clearScreen() {\n if (this.#options.clearScreen) {\n process.stdout.write('\\u001Bc')\n }\n }\n\n /**\n * Starts the HTTP server\n */\n #startHTTPServer(port: string, mode: 'blocking' | 'nonblocking') {\n this.#httpServer = runNode(this.#cwd, {\n script: this.#scriptFile,\n env: { PORT: port, ...this.#options.env },\n nodeArgs: this.#options.nodeArgs,\n scriptArgs: this.#options.scriptArgs,\n })\n\n this.#httpServer.on('message', (message) => {\n if (this.#isAdonisJSReadyMessage(message)) {\n const host = message.host === '0.0.0.0' ? '127.0.0.1' : message.host\n\n const displayMessage = ui\n .sticker()\n .useColors(this.#colors)\n .useRenderer(this.#logger.getRenderer())\n .add(`Server address: ${this.#colors.cyan(`http://${host}:${message.port}`)}`)\n .add(\n `File system watcher: ${this.#colors.cyan(\n `${this.#isWatching ? 'enabled' : 'disabled'}`\n )}`\n )\n\n if (message.duration) {\n displayMessage.add(`Ready in: ${this.#colors.cyan(prettyHrtime(message.duration))}`)\n }\n\n displayMessage.render()\n }\n })\n\n this.#httpServer\n .then((result) => {\n if (mode === 'nonblocking') {\n this.#onClose?.(result.exitCode)\n this.#watcher?.close()\n this.#assetsServer?.stop()\n } else {\n this.#logger.info('Underlying HTTP server closed. Still watching for changes')\n }\n })\n .catch((error) => {\n if (mode === 'nonblocking') {\n this.#onError?.(error)\n this.#watcher?.close()\n this.#assetsServer?.stop()\n } else {\n this.#logger.info('Underlying HTTP server died. Still watching for changes')\n }\n })\n }\n\n /**\n * Starts the assets server\n */\n #startAssetsServer() {\n this.#assetsServer = new AssetsDevServer(this.#cwd, this.#options.assets)\n this.#assetsServer.setLogger(this.#logger)\n this.#assetsServer.start()\n }\n\n /**\n * Restarts the HTTP server in the watch mode. Do not call this\n * method when not in watch mode\n */\n #restartHTTPServer(port: string) {\n if (this.#httpServer) {\n this.#httpServer.removeAllListeners()\n this.#httpServer.kill('SIGKILL')\n }\n\n this.#startHTTPServer(port, 'blocking')\n }\n\n /**\n * Handles a non TypeScript file change\n */\n #handleFileChange(action: string, port: string, relativePath: string) {\n if (isDotEnvFile(relativePath)) {\n this.#clearScreen()\n this.#logger.log(`${this.#colors.green(action)} ${relativePath}`)\n this.#restartHTTPServer(port)\n return\n }\n\n if (this.#isMetaFileWithReloadsEnabled(relativePath)) {\n this.#clearScreen()\n this.#logger.log(`${this.#colors.green(action)} ${relativePath}`)\n this.#restartHTTPServer(port)\n return\n }\n\n if (this.#isMetaFileWithReloadsDisabled(relativePath)) {\n this.#clearScreen()\n this.#logger.log(`${this.#colors.green(action)} ${relativePath}`)\n }\n }\n\n /**\n * Handles TypeScript source file change\n */\n #handleSourceFileChange(action: string, port: string, relativePath: string) {\n this.#clearScreen()\n this.#logger.log(`${this.#colors.green(action)} ${relativePath}`)\n this.#restartHTTPServer(port)\n }\n\n /**\n * Set a custom CLI UI logger\n */\n setLogger(logger: Logger) {\n this.#logger = logger\n this.#assetsServer?.setLogger(logger)\n return this\n }\n\n /**\n * Add listener to get notified when dev server is\n * closed\n */\n onClose(callback: (exitCode: number) => any): this {\n this.#onClose = callback\n return this\n }\n\n /**\n * Add listener to get notified when dev server exists\n * with an error\n */\n onError(callback: (error: any) => any): this {\n this.#onError = callback\n return this\n }\n\n /**\n * Close watchers and running child processes\n */\n async close() {\n await this.#watcher?.close()\n this.#assetsServer?.stop()\n if (this.#httpServer) {\n this.#httpServer.removeAllListeners()\n this.#httpServer.kill('SIGKILL')\n }\n }\n\n /**\n * Start the development server\n */\n async start() {\n this.#clearScreen()\n this.#logger.info('starting HTTP server...')\n this.#startHTTPServer(String(await getPort(this.#cwd)), 'nonblocking')\n this.#startAssetsServer()\n }\n\n /**\n * Start the development server in watch mode\n */\n async startAndWatch(ts: typeof tsStatic, options?: { poll: boolean }) {\n const port = String(await getPort(this.#cwd))\n this.#isWatching = true\n\n this.#clearScreen()\n\n this.#logger.info('starting HTTP server...')\n this.#startHTTPServer(port, 'blocking')\n\n this.#startAssetsServer()\n\n /**\n * Create watcher using tsconfig.json file\n */\n const output = watch(this.#cwd, ts, options || {})\n if (!output) {\n this.#onClose?.(1)\n return\n }\n\n /**\n * Storing reference to watcher, so that we can close it\n * when HTTP server exists with error\n */\n this.#watcher = output.chokidar\n\n /**\n * Notify the watcher is ready\n */\n output.watcher.on('watcher:ready', () => {\n this.#logger.info('watching file system for changes...')\n })\n\n /**\n * Cleanup when watcher dies\n */\n output.chokidar.on('error', (error) => {\n this.#logger.warning('file system watcher failure')\n this.#logger.fatal(error)\n this.#onError?.(error)\n output.chokidar.close()\n })\n\n /**\n * Changes in TypeScript source file\n */\n output.watcher.on('source:add', ({ relativePath }) =>\n this.#handleSourceFileChange('add', port, relativePath)\n )\n output.watcher.on('source:change', ({ relativePath }) =>\n this.#handleSourceFileChange('update', port, relativePath)\n )\n output.watcher.on('source:unlink', ({ relativePath }) =>\n this.#handleSourceFileChange('delete', port, relativePath)\n )\n\n /**\n * Changes in non-TypeScript source files\n */\n output.watcher.on('add', ({ relativePath }) =>\n this.#handleFileChange('add', port, relativePath)\n )\n output.watcher.on('change', ({ relativePath }) =>\n this.#handleFileChange('update', port, relativePath)\n )\n output.watcher.on('unlink', ({ relativePath }) =>\n this.#handleFileChange('delete', port, relativePath)\n )\n }\n}\n","/*\n * @adonisjs/core\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport type { ExecaChildProcess } from 'execa'\nimport { type Logger, cliui } from '@poppinss/cliui'\n\nimport { run } from './helpers.js'\nimport type { AssetsBundlerOptions } from './types.js'\n\n/**\n * Instance of CLIUI\n */\nconst ui = cliui()\n\n/**\n * Exposes the API to start the development server for processing assets during\n * development.\n *\n * - Here we are running the assets dev server in a child process.\n * - Piping the output from the child process and reformatting it before writing it to\n * process streams.\n *\n * AssetsDevServer is agnostic and can run any assets dev server. Be it Vite or Encore or\n * even Webpack directly.\n */\nexport class AssetsDevServer {\n #cwd: URL\n #logger = ui.logger\n #options?: AssetsBundlerOptions\n #devServer?: ExecaChildProcess<string>\n\n /**\n * Getting reference to colors library from logger\n */\n get #colors() {\n return this.#logger.getColors()\n }\n\n constructor(cwd: URL, options?: AssetsBundlerOptions) {\n this.#cwd = cwd\n this.#options = options\n }\n\n /**\n * Logs messages from vite dev server stdout and stderr\n */\n #logViteDevServerMessage(data: Buffer) {\n const dataString = data.toString()\n const lines = dataString.split('\\n')\n\n /**\n * Put a wrapper around vite network address log\n */\n if (dataString.includes('Local') && dataString.includes('Network')) {\n const sticker = ui.sticker().useColors(this.#colors).useRenderer(this.#logger.getRenderer())\n\n lines.forEach((line: string) => {\n if (line.trim()) {\n sticker.add(line)\n }\n })\n\n sticker.render()\n return\n }\n\n /**\n * Logging VITE ready in message with proper\n * spaces and newlines\n */\n if (dataString.includes('ready in')) {\n console.log('')\n console.log(dataString.trim())\n return\n }\n\n /**\n * Log rest of the lines\n */\n lines.forEach((line: string) => {\n if (line.trim()) {\n console.log(line)\n }\n })\n }\n\n /**\n * Logs messages from assets dev server stdout and stderr\n */\n #logAssetsDevServerMessage(data: Buffer) {\n const dataString = data.toString()\n const lines = dataString.split('\\n')\n lines.forEach((line: string) => {\n if (line.trim()) {\n console.log(line)\n }\n })\n }\n\n /**\n * Set a custom CLI UI logger\n */\n setLogger(logger: Logger) {\n this.#logger = logger\n return this\n }\n\n /**\n * Starts the assets bundler server. The assets bundler server process is\n * considered as the secondary process and therefore we do not perform\n * any cleanup if it dies.\n */\n start() {\n if (!this.#options?.enabled) {\n return\n }\n\n this.#logger.info(`starting \"${this.#options.driver}\" dev server...`)\n\n /**\n * Create child process\n */\n this.#devServer = run(this.#cwd, {\n script: this.#options.cmd,\n\n /**\n * We do not inherit the stdio for vite and encore, because in\n * inherit mode they own the stdin and interrupts the\n * `Ctrl + C` command.\n */\n stdio: 'pipe',\n scriptArgs: this.#options.args,\n })\n\n /**\n * Log child process messages\n */\n this.#devServer.stdout?.on('data', (data) => {\n if (this.#options!.driver === 'vite') {\n this.#logViteDevServerMessage(data)\n } else {\n this.#logAssetsDevServerMessage(data)\n }\n })\n\n this.#devServer.stderr?.on('data', (data) => {\n if (this.#options!.driver === 'vite') {\n this.#logViteDevServerMessage(data)\n } else {\n this.#logAssetsDevServerMessage(data)\n }\n })\n\n this.#devServer\n .then((result) => {\n this.#logger.warning(\n `\"${this.#options!.driver}\" dev server closed with status code \"${result.exitCode}\"`\n )\n })\n .catch((error) => {\n this.#logger.warning(`unable to connect to \"${this.#options!.driver}\" dev server`)\n this.#logger.fatal(error)\n })\n }\n\n /**\n * Stop the dev server\n */\n stop() {\n if (this.#devServer) {\n this.#devServer.removeAllListeners()\n this.#devServer.kill('SIGKILL')\n this.#devServer = undefined\n }\n }\n}\n","/*\n * @adonisjs/assembler\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport picomatch from 'picomatch'\nimport type tsStatic from 'typescript'\nimport { type ExecaChildProcess } from 'execa'\nimport { cliui, type Logger } from '@poppinss/cliui'\nimport type { Watcher } from '@poppinss/chokidar-ts'\n\nimport type { TestRunnerOptions } from './types.js'\nimport { AssetsDevServer } from './assets_dev_server.js'\nimport { getPort, isDotEnvFile, runNode, watch } from './helpers.js'\n\n/**\n * Instance of CLIUI\n */\nconst ui = cliui()\n\n/**\n * Exposes the API to run Japa tests and optionally watch for file\n * changes to re-run the tests.\n *\n * The watch mode functions as follows.\n *\n * - If the changed file is a test file, then only tests for that file\n * will be re-run.\n * - Otherwise, all tests will re-run with respect to the initial\n * filters applied when running the `node ace test` command.\n *\n */\nexport class TestRunner {\n #cwd: URL\n #logger = ui.logger\n #options: TestRunnerOptions\n\n /**\n * The script file to run as a child process\n */\n #scriptFile: string = 'bin/test.js'\n\n /**\n * Pico matcher function to check if the filepath is\n * part of the `metaFiles` glob patterns\n */\n #isMetaFile: picomatch.Matcher\n\n /**\n * Pico matcher function to check if the filepath is\n * part of a test file.\n */\n #isTestFile: picomatch.Matcher\n\n /**\n * Arguments to pass to the \"bin/test.js\" file.\n */\n #scriptArgs: string[]\n\n /**\n * Set of initial filters applied when running the test\n * command. In watch mode, we will append an additional\n * filter to run tests only for the file that has been\n * changed.\n */\n #initialFiltersArgs: string[]\n\n /**\n * In watch mode, after a file is changed, we wait for the current\n * set of tests to finish before triggering a re-run. Therefore,\n * we use this flag to know if we are already busy in running\n * tests and ignore file-changes.\n */\n #isBusy: boolean = false\n\n /**\n * External listeners that are invoked when child process\n * gets an error or closes\n */\n #onError?: (error: any) => any\n #onClose?: (exitCode: number) => any\n\n /**\n * Reference to the test script child process\n */\n #testScript?: ExecaChildProcess<string>\n\n /**\n * Reference to the watcher\n */\n #watcher?: ReturnType<Watcher['watch']>\n\n /**\n * Reference to the assets server\n */\n #assetsServer?: AssetsDevServer\n\n /**\n * Getting reference to colors library from logger\n */\n get #colors() {\n return this.#logger.getColors()\n }\n\n constructor(cwd: URL, options: TestRunnerOptions) {\n this.#cwd = cwd\n this.#options = options\n\n this.#isMetaFile = picomatch((this.#options.metaFiles || []).map(({ pattern }) => pattern))\n\n /**\n * Create a test file watch by collection all the globs\n * used by all the suites. However, if a suite filter\n * was used, then we only collect glob for the mentioned\n * suites.\n */\n this.#isTestFile = picomatch(\n this.#options.suites\n .filter((suite) => {\n if (this.#options.filters.suites) {\n return this.#options.filters.suites.includes(suite.name)\n }\n return true\n })\n .map((suite) => suite.files)\n .flat(1)\n )\n\n this.#scriptArgs = this.#convertOptionsToArgs().concat(this.#options.scriptArgs)\n this.#initialFiltersArgs = this.#convertFiltersToArgs(this.#options.filters)\n }\n\n /**\n * Convert test runner options to the CLI args\n */\n #convertOptionsToArgs() {\n const args: string[] = []\n\n if (this.#options.reporters) {\n args.push('--reporters')\n args.push(this.#options.reporters.join(','))\n }\n\n if (this.#options.timeout !== undefined) {\n args.push('--timeout')\n args.push(String(this.#options.timeout))\n }\n\n if (this.#options.failed) {\n args.push('--failed')\n }\n\n if (this.#options.retries !== undefined) {\n args.push('--retries')\n args.push(String(this.#options.retries))\n }\n\n return args\n }\n\n /**\n * Converts all known filters to CLI args.\n *\n * The following code snippet may seem like repetitive code. But, it\n * is done intentionally to have visibility around how each filter\n * is converted to an arg.\n */\n #convertFiltersToArgs(filters: TestRunnerOptions['filters']): string[] {\n const args: string[] = []\n\n if (filters.suites) {\n args.push(...filters.suites)\n }\n\n if (filters.files) {\n args.push('--files')\n args.push(filters.files.join(','))\n }\n\n if (filters.groups) {\n args.push('--groups')\n args.push(filters.groups.join(','))\n }\n\n if (filters.tags) {\n args.push('--tags')\n args.push(filters.tags.join(','))\n }\n\n if (filters.tests) {\n args.push('--tests')\n args.push(filters.tests.join(','))\n }\n\n return args\n }\n\n /**\n * Conditionally clear the terminal screen\n */\n #clearScreen() {\n if (this.#options.clearScreen) {\n process.stdout.write('\\u001Bc')\n }\n }\n\n /**\n * Runs tests\n */\n #runTests(\n port: string,\n mode: 'blocking' | 'nonblocking',\n filters?: TestRunnerOptions['filters']\n ) {\n this.#isBusy = true\n\n /**\n * If inline filters are defined, then we ignore the\n * initial filters\n */\n const scriptArgs = filters\n ? this.#convertFiltersToArgs(filters).concat(this.#scriptArgs)\n : this.#initialFiltersArgs.concat(this.#scriptArgs)\n\n this.#testScript = runNode(this.#cwd, {\n script: this.#scriptFile,\n env: { PORT: port, ...this.#options.env },\n nodeArgs: this.#options.nodeArgs,\n scriptArgs,\n })\n\n this.#testScript\n .then((result) => {\n if (mode === 'nonblocking') {\n this.#onClose?.(result.exitCode)\n this.close()\n }\n })\n .catch((error) => {\n if (mode === 'nonblocking') {\n this.#onError?.(error)\n this.close()\n }\n })\n .finally(() => {\n this.#isBusy = false\n })\n }\n\n /**\n * Re-run tests with additional inline filters. Should be\n * executed in watch mode only.\n */\n #rerunTests(port: string, filters?: TestRunnerOptions['filters']) {\n if (this.#testScript) {\n this.#testScript.removeAllListeners()\n this.#testScript.kill('SIGKILL')\n }\n\n this.#runTests(port, 'blocking', filters)\n }\n\n /**\n * Starts the assets server\n */\n #startAssetsServer() {\n this.#assetsServer = new AssetsDevServer(this.#cwd, this.#options.assets)\n this.#assetsServer.setLogger(this.#logger)\n this.#assetsServer.start()\n }\n\n /**\n * Handles a non TypeScript file change\n */\n #handleFileChange(action: string, port: string, relativePath: string) {\n if (this.#isBusy) {\n return\n }\n\n if (isDotEnvFile(relativePath) || this.#isMetaFile(relativePath)) {\n this.#clearScreen()\n this.#logger.log(`${this.#colors.green(action)} ${relativePath}`)\n this.#rerunTests(port)\n }\n }\n\n /**\n * Handles TypeScript source file change\n */\n #handleSourceFileChange(action: string, port: string, relativePath: string) {\n if (this.#isBusy) {\n return\n }\n\n this.#clearScreen()\n this.#logger.log(`${this.#colors.green(action)} ${relativePath}`)\n\n /**\n * If changed file is a test file after considering the initial filters,\n * then only run that file\n */\n if (this.#isTestFile(relativePath)) {\n this.#rerunTests(port, {\n ...this.#options.filters,\n files: [relativePath],\n })\n return\n }\n\n this.#rerunTests(port)\n }\n\n /**\n * Set a custom CLI UI logger\n */\n setLogger(logger: Logger) {\n this.#logger = logger\n this.#assetsServer?.setLogger(logger)\n return this\n }\n\n /**\n * Add listener to get notified when dev server is\n * closed\n */\n onClose(callback: (exitCode: number) => any): this {\n this.#onClose = callback\n return this\n }\n\n /**\n * Add listener to get notified when dev server exists\n * with an error\n */\n onError(callback: (error: any) => any): this {\n this.#onError = callback\n return this\n }\n\n /**\n * Close watchers and running child processes\n */\n async close() {\n await this.#watcher?.close()\n this.#assetsServer?.stop()\n if (this.#testScript) {\n this.#testScript.removeAllListeners()\n this.#testScript.kill('SIGKILL')\n }\n }\n\n /**\n * Runs tests\n */\n async run() {\n const port = String(await getPort(this.#cwd))\n\n this.#clearScreen()\n this.#startAssetsServer()\n\n this.#logger.info('booting application to run tests...')\n this.#runTests(port, 'nonblocking')\n }\n\n /**\n * Run tests in watch mode\n */\n async runAndWatch(ts: typeof tsStatic, options?: { poll: boolean }) {\n const port = String(await getPort(this.#cwd))\n\n this.#clearScreen()\n this.#startAssetsServer()\n\n this.#logger.info('booting application to run tests...')\n this.#runTests(port, 'blocking')\n\n /**\n * Create watcher using tsconfig.json file\n */\n const output = watch(this.#cwd, ts, options || {})\n if (!output) {\n this.#onClose?.(1)\n return\n }\n\n /**\n * Storing reference to watcher, so that we can close it\n * when HTTP server exists with error\n */\n this.#watcher = output.chokidar\n\n /**\n * Notify the watcher is ready\n */\n output.watcher.on('watcher:ready', () => {\n this.#logger.info('watching file system for changes...')\n })\n\n /**\n * Cleanup when watcher dies\n */\n output.chokidar.on('error', (error) => {\n this.#logger.warning('file system watcher failure')\n this.#logger.fatal(error)\n this.#onError?.(error)\n output.chokidar.close()\n })\n\n /**\n * Changes in TypeScript source file\n */\n output.watcher.on('source:add', ({ relativePath }) =>\n this.#handleSourceFileChange('add', port, relativePath)\n )\n output.watcher.on('source:change', ({ relativePath }) =>\n this.#handleSourceFileChange('update', port, relativePath)\n )\n output.watcher.on('source:unlink', ({ relativePath }) =>\n this.#handleSourceFileChange('delete', port, relativePath)\n )\n\n /**\n * Changes in non-TypeScript source files\n */\n output.watcher.on('add', ({ relativePath }) =>\n this.#handleFileChange('add', port, relativePath)\n )\n output.watcher.on('change', ({ relativePath }) =>\n this.#handleFileChange('update', port, relativePath)\n )\n output.watcher.on('unlink', ({ relativePath }) =>\n this.#handleFileChange('delete', port, relativePath)\n )\n }\n}\n"],"mappings":"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","names":["relative","fileURLToPath","fileURLToPath","relative","cliui","cliui","ui","cliui","ui","cliui","picomatch","cliui","ui","cliui","picomatch"]}
1
+ {"version":3,"sources":["../src/bundler.ts","../src/helpers.ts","../src/debug.ts","../src/dev_server.ts","../src/assets_dev_server.ts","../src/test_runner.ts"],"sourcesContent":["/*\n * @adonisjs/assembler\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport slash from 'slash'\nimport fs from 'node:fs/promises'\nimport { relative } from 'node:path'\nimport type tsStatic from 'typescript'\nimport { fileURLToPath } from 'node:url'\nimport { cliui, type Logger } from '@poppinss/cliui'\nimport { detectPackageManager } from '@antfu/install-pkg'\n\nimport type { BundlerOptions } from './types.js'\nimport { run, parseConfig, copyFiles } from './helpers.js'\n\ntype SupportedPackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun'\n\n/**\n * List of package managers we support in order to\n * copy lockfiles\n */\nconst SUPPORT_PACKAGE_MANAGERS: {\n [K in SupportedPackageManager]: {\n lockFile: string\n installCommand: string\n }\n} = {\n npm: {\n lockFile: 'package-lock.json',\n installCommand: 'npm ci --omit=\"dev\"',\n },\n yarn: {\n lockFile: 'yarn.lock',\n installCommand: 'yarn install --production',\n },\n pnpm: {\n lockFile: 'pnpm-lock.yaml',\n installCommand: 'pnpm i --prod',\n },\n bun: {\n lockFile: 'bun.lockb',\n installCommand: 'bun install --production',\n },\n}\n\n/**\n * Instance of CLIUI\n */\nconst ui = cliui()\n\n/**\n * The bundler class exposes the API to build an AdonisJS project.\n */\nexport class Bundler {\n #cwd: URL\n #cwdPath: string\n #ts: typeof tsStatic\n #logger = ui.logger\n #options: BundlerOptions\n\n /**\n * Getting reference to colors library from logger\n */\n get #colors() {\n return this.#logger.getColors()\n }\n\n constructor(cwd: URL, ts: typeof tsStatic, options: BundlerOptions) {\n this.#cwd = cwd\n this.#cwdPath = fileURLToPath(this.#cwd)\n this.#ts = ts\n this.#options = options\n }\n\n /**\n * Returns the relative unix path for an absolute\n * file path\n */\n #getRelativeName(filePath: string) {\n return slash(relative(this.#cwdPath, filePath))\n }\n\n /**\n * Cleans up the build directory\n */\n async #cleanupBuildDirectory(outDir: string) {\n await fs.rm(outDir, { recursive: true, force: true, maxRetries: 5 })\n }\n\n /**\n * Runs assets bundler command to build assets\n */\n async #buildAssets(): Promise<boolean> {\n const assetsBundler = this.#options.assets\n if (!assetsBundler?.enabled) {\n return true\n }\n\n try {\n this.#logger.info('compiling frontend assets', { suffix: assetsBundler.cmd })\n await run(this.#cwd, {\n stdio: 'inherit',\n script: assetsBundler.cmd,\n scriptArgs: assetsBundler.args,\n })\n return true\n } catch {\n return false\n }\n }\n\n /**\n * Runs tsc command to build the source.\n */\n async #runTsc(outDir: string): Promise<boolean> {\n try {\n await run(this.#cwd, {\n stdio: 'inherit',\n script: 'tsc',\n scriptArgs: ['--outDir', outDir],\n })\n return true\n } catch {\n return false\n }\n }\n\n /**\n * Copy meta files to the output directory\n */\n async #copyMetaFiles(outDir: string, additionalFilesToCopy: string[]) {\n const metaFiles = (this.#options.metaFiles || [])\n .map((file) => file.pattern)\n .concat(additionalFilesToCopy)\n\n await copyFiles(metaFiles, this.#cwdPath, outDir)\n }\n\n /**\n * Detect the package manager used by the project\n * and return the lockfile name and install command\n * related to it.\n */\n async #getPackageManager(client?: SupportedPackageManager) {\n let pkgManager: string | null | undefined = client\n\n if (!pkgManager) {\n pkgManager = await detectPackageManager(this.#cwdPath)\n }\n if (!pkgManager) {\n pkgManager = 'npm'\n }\n\n if (!Object.keys(SUPPORT_PACKAGE_MANAGERS).includes(pkgManager)) {\n return null\n }\n\n return SUPPORT_PACKAGE_MANAGERS[pkgManager as SupportedPackageManager]\n }\n\n /**\n * Set a custom CLI UI logger\n */\n setLogger(logger: Logger) {\n this.#logger = logger\n return this\n }\n\n /**\n * Bundles the application to be run in production\n */\n async bundle(stopOnError: boolean = true, client?: SupportedPackageManager): Promise<boolean> {\n /**\n * Step 1: Parse config file to get the build output directory\n */\n const config = parseConfig(this.#cwd, this.#ts)\n if (!config) {\n return false\n }\n\n /**\n * Step 2: Cleanup existing build directory (if any)\n */\n const outDir = config.options.outDir || fileURLToPath(new URL('build/', this.#cwd))\n this.#logger.info('cleaning up output directory', { suffix: this.#getRelativeName(outDir) })\n await this.#cleanupBuildDirectory(outDir)\n\n /**\n * Step 3: Build frontend assets\n */\n if (!(await this.#buildAssets())) {\n return false\n }\n\n /**\n * Step 4: Build typescript source code\n */\n this.#logger.info('compiling typescript source', { suffix: 'tsc' })\n const buildCompleted = await this.#runTsc(outDir)\n await copyFiles(['ace.js'], this.#cwdPath, outDir)\n\n /**\n * Remove incomplete build directory when tsc build\n * failed and stopOnError is set to true.\n */\n if (!buildCompleted && stopOnError) {\n await this.#cleanupBuildDirectory(outDir)\n const instructions = ui\n .sticker()\n .fullScreen()\n .drawBorder((borderChar, colors) => colors.red(borderChar))\n\n instructions.add(\n this.#colors.red('Cannot complete the build process as there are TypeScript errors.')\n )\n instructions.add(\n this.#colors.red(\n 'Use \"--ignore-ts-errors\" flag to ignore TypeScript errors and continue the build.'\n )\n )\n\n this.#logger.logError(instructions.prepare())\n return false\n }\n\n /**\n * Step 5: Copy meta files to the build directory\n */\n const pkgManager = await this.#getPackageManager(client)\n const pkgFiles = pkgManager ? ['package.json', pkgManager.lockFile] : ['package.json']\n this.#logger.info('copying meta files to the output directory')\n await this.#copyMetaFiles(outDir, pkgFiles)\n\n this.#logger.success('build completed')\n this.#logger.log('')\n\n /**\n * Next steps\n */\n ui.instructions()\n .useRenderer(this.#logger.getRenderer())\n .heading('Run the following commands to start the server in production')\n .add(this.#colors.cyan(`cd ${this.#getRelativeName(outDir)}`))\n .add(\n this.#colors.cyan(\n pkgManager ? pkgManager.installCommand : 'Install production dependencies'\n )\n )\n .add(this.#colors.cyan('node bin/server.js'))\n .render()\n\n return true\n }\n}\n","/*\n * @adonisjs/assembler\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { isJunk } from 'junk'\nimport fastGlob from 'fast-glob'\nimport getRandomPort from 'get-port'\nimport { existsSync } from 'node:fs'\nimport type tsStatic from 'typescript'\nimport { fileURLToPath } from 'node:url'\nimport { execaNode, execa } from 'execa'\nimport { copyFile, mkdir } from 'node:fs/promises'\nimport { EnvLoader, EnvParser } from '@adonisjs/env'\nimport { ConfigParser, Watcher } from '@poppinss/chokidar-ts'\nimport { basename, dirname, isAbsolute, join, relative } from 'node:path'\n\nimport type { RunOptions, WatchOptions } from './types.js'\nimport debug from './debug.js'\n\n/**\n * Default set of args to pass in order to run TypeScript\n * source. Used by \"run\" and \"runNode\" scripts\n */\nconst DEFAULT_NODE_ARGS = [\n // Use ts-node/esm loader. The project must install it\n '--loader=ts-node/esm',\n // Enable source maps, since TSNode source maps are broken\n '--enable-source-maps',\n]\n\n/**\n * Parses tsconfig.json and prints errors using typescript compiler\n * host\n */\nexport function parseConfig(cwd: string | URL, ts: typeof tsStatic) {\n const { config, error } = new ConfigParser(cwd, 'tsconfig.json', ts).parse()\n if (error) {\n const compilerHost = ts.createCompilerHost({})\n console.log(ts.formatDiagnosticsWithColorAndContext([error], compilerHost))\n return\n }\n\n if (config!.errors.length) {\n const compilerHost = ts.createCompilerHost({})\n console.log(ts.formatDiagnosticsWithColorAndContext(config!.errors, compilerHost))\n return\n }\n\n return config\n}\n\n/**\n * Runs a Node.js script as a child process and inherits the stdio streams\n */\nexport function runNode(cwd: string | URL, options: RunOptions) {\n const childProcess = execaNode(options.script, options.scriptArgs, {\n nodeOptions: DEFAULT_NODE_ARGS.concat(options.nodeArgs),\n preferLocal: true,\n windowsHide: false,\n localDir: cwd,\n cwd,\n buffer: false,\n stdio: options.stdio || 'inherit',\n env: {\n ...(options.stdio === 'pipe' ? { FORCE_COLOR: 'true' } : {}),\n ...options.env,\n },\n })\n\n return childProcess\n}\n\n/**\n * Runs a script as a child process and inherits the stdio streams\n */\nexport function run(cwd: string | URL, options: Omit<RunOptions, 'nodeArgs'>) {\n const childProcess = execa(options.script, options.scriptArgs, {\n preferLocal: true,\n windowsHide: false,\n localDir: cwd,\n cwd,\n buffer: false,\n stdio: options.stdio || 'inherit',\n env: {\n ...(options.stdio === 'pipe' ? { FORCE_COLOR: 'true' } : {}),\n ...options.env,\n },\n })\n\n return childProcess\n}\n\n/**\n * Watches the file system using tsconfig file\n */\nexport function watch(cwd: string | URL, ts: typeof tsStatic, options: WatchOptions) {\n const config = parseConfig(cwd, ts)\n if (!config) {\n return\n }\n\n const watcher = new Watcher(typeof cwd === 'string' ? cwd : fileURLToPath(cwd), config!)\n const chokidar = watcher.watch(['.'], { usePolling: options.poll })\n return { watcher, chokidar }\n}\n\n/**\n * Check if file is an .env file\n */\nexport function isDotEnvFile(filePath: string) {\n if (filePath === '.env') {\n return true\n }\n\n return filePath.includes('.env.')\n}\n\n/**\n * Returns the port to use after inspect the dot-env files inside\n * a given directory.\n *\n * A random port is used when the specified port is in use. Following\n * is the logic for finding a specified port.\n *\n * - The \"process.env.PORT\" value is used if exists.\n * - The dot-env files are loaded using the \"EnvLoader\" and the PORT\n * value is used by iterating over all the loaded files. The\n * iteration stops after first find.\n */\nexport async function getPort(cwd: URL): Promise<number> {\n /**\n * Use existing port if exists\n */\n if (process.env.PORT) {\n return getRandomPort({ port: Number(process.env.PORT) })\n }\n\n /**\n * Loop over files and use the port from their contents. Stops\n * after first match\n */\n const files = await new EnvLoader(cwd).load()\n for (let file of files) {\n const envVariables = new EnvParser(file.contents).parse()\n if (envVariables.PORT) {\n return getRandomPort({ port: Number(envVariables.PORT) })\n }\n }\n\n /**\n * Use 3333 as the port\n */\n return getRandomPort({ port: 3333 })\n}\n\n/**\n * Helper function to copy files from relative paths or glob\n * patterns\n */\nexport async function copyFiles(files: string[], cwd: string, outDir: string) {\n /**\n * Looping over files and create a new collection with paths\n * and glob patterns\n */\n const { paths, patterns } = files.reduce<{ patterns: string[]; paths: string[] }>(\n (result, file) => {\n /**\n * If file is a glob pattern, then push it to patterns\n */\n if (fastGlob.isDynamicPattern(file)) {\n result.patterns.push(file)\n return result\n }\n\n /**\n * Otherwise, check if file exists and push it to paths to copy\n */\n if (existsSync(join(cwd, file))) {\n result.paths.push(file)\n }\n\n return result\n },\n { patterns: [], paths: [] }\n )\n\n debug('copyFiles inputs: %O, paths: %O, patterns: %O', files, paths, patterns)\n\n /**\n * Getting list of relative paths from glob patterns\n */\n const filePaths = paths.concat(await fastGlob(patterns, { cwd, dot: true })).filter((file) => {\n return !isJunk(basename(file))\n })\n\n /**\n * Finally copy files to the destination by keeping the same\n * directory structure and ignoring junk files\n */\n debug('copying files %O to destination \"%s\"', filePaths, outDir)\n const copyPromises = filePaths.map(async (file) => {\n const src = isAbsolute(file) ? file : join(cwd, file)\n const dest = join(outDir, relative(cwd, src))\n\n await mkdir(dirname(dest), { recursive: true })\n return copyFile(src, dest)\n })\n\n return await Promise.all(copyPromises)\n}\n","/*\n * @adonisjs/assembler\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { debuglog } from 'node:util'\n\nexport default debuglog('adonisjs:assembler')\n","/*\n * @adonisjs/assembler\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport picomatch from 'picomatch'\nimport type tsStatic from 'typescript'\nimport prettyHrtime from 'pretty-hrtime'\nimport { type ExecaChildProcess } from 'execa'\nimport { cliui, type Logger } from '@poppinss/cliui'\nimport type { Watcher } from '@poppinss/chokidar-ts'\n\nimport type { DevServerOptions } from './types.js'\nimport { AssetsDevServer } from './assets_dev_server.js'\nimport { getPort, isDotEnvFile, runNode, watch } from './helpers.js'\n\n/**\n * Instance of CLIUI\n */\nconst ui = cliui()\n\n/**\n * Exposes the API to start the development. Optionally, the watch API can be\n * used to watch for file changes and restart the development server.\n *\n * The Dev server performs the following actions\n *\n * - Assigns a random PORT, when PORT inside .env file is in use.\n * - Uses tsconfig.json file to collect a list of files to watch.\n * - Uses metaFiles from adonisrc.ts file to collect a list of files to watch.\n * - Restart HTTP server on every file change.\n */\nexport class DevServer {\n #cwd: URL\n #logger = ui.logger\n #options: DevServerOptions\n\n /**\n * Flag to know if the dev server is running in watch\n * mode\n */\n #isWatching: boolean = false\n\n /**\n * Script file to start the development server\n */\n #scriptFile: string = 'bin/server.js'\n\n /**\n * Picomatch matcher function to know if a file path is a\n * meta file with reloadServer option enabled\n */\n #isMetaFileWithReloadsEnabled: picomatch.Matcher\n\n /**\n * Picomatch matcher function to know if a file path is a\n * meta file with reloadServer option disabled\n */\n #isMetaFileWithReloadsDisabled: picomatch.Matcher\n\n /**\n * External listeners that are invoked when child process\n * gets an error or closes\n */\n #onError?: (error: any) => any\n #onClose?: (exitCode: number) => any\n\n /**\n * Reference to the child process\n */\n #httpServer?: ExecaChildProcess<string>\n\n /**\n * Reference to the watcher\n */\n #watcher?: ReturnType<Watcher['watch']>\n\n /**\n * Reference to the assets server\n */\n #assetsServer?: AssetsDevServer\n\n /**\n * Getting reference to colors library from logger\n */\n get #colors() {\n return this.#logger.getColors()\n }\n\n constructor(cwd: URL, options: DevServerOptions) {\n this.#cwd = cwd\n this.#options = options\n\n this.#isMetaFileWithReloadsEnabled = picomatch(\n (this.#options.metaFiles || [])\n .filter(({ reloadServer }) => reloadServer === true)\n .map(({ pattern }) => pattern)\n )\n\n this.#isMetaFileWithReloadsDisabled = picomatch(\n (this.#options.metaFiles || [])\n .filter(({ reloadServer }) => reloadServer !== true)\n .map(({ pattern }) => pattern)\n )\n }\n\n /**\n * Inspect if child process message is from AdonisJS HTTP server\n */\n #isAdonisJSReadyMessage(message: unknown): message is {\n isAdonisJS: true\n environment: 'web'\n port: number\n host: string\n duration?: [number, number]\n } {\n return (\n message !== null &&\n typeof message === 'object' &&\n 'isAdonisJS' in message &&\n 'environment' in message &&\n message.environment === 'web'\n )\n }\n\n /**\n * Conditionally clear the terminal screen\n */\n #clearScreen() {\n if (this.#options.clearScreen) {\n process.stdout.write('\\u001Bc')\n }\n }\n\n /**\n * Starts the HTTP server\n */\n #startHTTPServer(port: string, mode: 'blocking' | 'nonblocking') {\n this.#httpServer = runNode(this.#cwd, {\n script: this.#scriptFile,\n env: { PORT: port, ...this.#options.env },\n nodeArgs: this.#options.nodeArgs,\n scriptArgs: this.#options.scriptArgs,\n })\n\n this.#httpServer.on('message', (message) => {\n if (this.#isAdonisJSReadyMessage(message)) {\n const host = message.host === '0.0.0.0' ? '127.0.0.1' : message.host\n\n const displayMessage = ui\n .sticker()\n .useColors(this.#colors)\n .useRenderer(this.#logger.getRenderer())\n .add(`Server address: ${this.#colors.cyan(`http://${host}:${message.port}`)}`)\n .add(\n `File system watcher: ${this.#colors.cyan(\n `${this.#isWatching ? 'enabled' : 'disabled'}`\n )}`\n )\n\n if (message.duration) {\n displayMessage.add(`Ready in: ${this.#colors.cyan(prettyHrtime(message.duration))}`)\n }\n\n displayMessage.render()\n }\n })\n\n this.#httpServer\n .then((result) => {\n if (mode === 'nonblocking') {\n this.#onClose?.(result.exitCode)\n this.#watcher?.close()\n this.#assetsServer?.stop()\n } else {\n this.#logger.info('Underlying HTTP server closed. Still watching for changes')\n }\n })\n .catch((error) => {\n if (mode === 'nonblocking') {\n this.#onError?.(error)\n this.#watcher?.close()\n this.#assetsServer?.stop()\n } else {\n this.#logger.info('Underlying HTTP server died. Still watching for changes')\n }\n })\n }\n\n /**\n * Starts the assets server\n */\n #startAssetsServer() {\n this.#assetsServer = new AssetsDevServer(this.#cwd, this.#options.assets)\n this.#assetsServer.setLogger(this.#logger)\n this.#assetsServer.start()\n }\n\n /**\n * Restarts the HTTP server in the watch mode. Do not call this\n * method when not in watch mode\n */\n #restartHTTPServer(port: string) {\n if (this.#httpServer) {\n this.#httpServer.removeAllListeners()\n this.#httpServer.kill('SIGKILL')\n }\n\n this.#startHTTPServer(port, 'blocking')\n }\n\n /**\n * Handles a non TypeScript file change\n */\n #handleFileChange(action: string, port: string, relativePath: string) {\n if (isDotEnvFile(relativePath)) {\n this.#clearScreen()\n this.#logger.log(`${this.#colors.green(action)} ${relativePath}`)\n this.#restartHTTPServer(port)\n return\n }\n\n if (this.#isMetaFileWithReloadsEnabled(relativePath)) {\n this.#clearScreen()\n this.#logger.log(`${this.#colors.green(action)} ${relativePath}`)\n this.#restartHTTPServer(port)\n return\n }\n\n if (this.#isMetaFileWithReloadsDisabled(relativePath)) {\n this.#clearScreen()\n this.#logger.log(`${this.#colors.green(action)} ${relativePath}`)\n }\n }\n\n /**\n * Handles TypeScript source file change\n */\n #handleSourceFileChange(action: string, port: string, relativePath: string) {\n this.#clearScreen()\n this.#logger.log(`${this.#colors.green(action)} ${relativePath}`)\n this.#restartHTTPServer(port)\n }\n\n /**\n * Set a custom CLI UI logger\n */\n setLogger(logger: Logger) {\n this.#logger = logger\n this.#assetsServer?.setLogger(logger)\n return this\n }\n\n /**\n * Add listener to get notified when dev server is\n * closed\n */\n onClose(callback: (exitCode: number) => any): this {\n this.#onClose = callback\n return this\n }\n\n /**\n * Add listener to get notified when dev server exists\n * with an error\n */\n onError(callback: (error: any) => any): this {\n this.#onError = callback\n return this\n }\n\n /**\n * Close watchers and running child processes\n */\n async close() {\n await this.#watcher?.close()\n this.#assetsServer?.stop()\n if (this.#httpServer) {\n this.#httpServer.removeAllListeners()\n this.#httpServer.kill('SIGKILL')\n }\n }\n\n /**\n * Start the development server\n */\n async start() {\n this.#clearScreen()\n this.#logger.info('starting HTTP server...')\n this.#startHTTPServer(String(await getPort(this.#cwd)), 'nonblocking')\n this.#startAssetsServer()\n }\n\n /**\n * Start the development server in watch mode\n */\n async startAndWatch(ts: typeof tsStatic, options?: { poll: boolean }) {\n const port = String(await getPort(this.#cwd))\n this.#isWatching = true\n\n this.#clearScreen()\n\n this.#logger.info('starting HTTP server...')\n this.#startHTTPServer(port, 'blocking')\n\n this.#startAssetsServer()\n\n /**\n * Create watcher using tsconfig.json file\n */\n const output = watch(this.#cwd, ts, options || {})\n if (!output) {\n this.#onClose?.(1)\n return\n }\n\n /**\n * Storing reference to watcher, so that we can close it\n * when HTTP server exists with error\n */\n this.#watcher = output.chokidar\n\n /**\n * Notify the watcher is ready\n */\n output.watcher.on('watcher:ready', () => {\n this.#logger.info('watching file system for changes...')\n })\n\n /**\n * Cleanup when watcher dies\n */\n output.chokidar.on('error', (error) => {\n this.#logger.warning('file system watcher failure')\n this.#logger.fatal(error)\n this.#onError?.(error)\n output.chokidar.close()\n })\n\n /**\n * Changes in TypeScript source file\n */\n output.watcher.on('source:add', ({ relativePath }) =>\n this.#handleSourceFileChange('add', port, relativePath)\n )\n output.watcher.on('source:change', ({ relativePath }) =>\n this.#handleSourceFileChange('update', port, relativePath)\n )\n output.watcher.on('source:unlink', ({ relativePath }) =>\n this.#handleSourceFileChange('delete', port, relativePath)\n )\n\n /**\n * Changes in non-TypeScript source files\n */\n output.watcher.on('add', ({ relativePath }) =>\n this.#handleFileChange('add', port, relativePath)\n )\n output.watcher.on('change', ({ relativePath }) =>\n this.#handleFileChange('update', port, relativePath)\n )\n output.watcher.on('unlink', ({ relativePath }) =>\n this.#handleFileChange('delete', port, relativePath)\n )\n }\n}\n","/*\n * @adonisjs/core\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport type { ExecaChildProcess } from 'execa'\nimport { type Logger, cliui } from '@poppinss/cliui'\n\nimport { run } from './helpers.js'\nimport type { AssetsBundlerOptions } from './types.js'\n\n/**\n * Instance of CLIUI\n */\nconst ui = cliui()\n\n/**\n * Exposes the API to start the development server for processing assets during\n * development.\n *\n * - Here we are running the assets dev server in a child process.\n * - Piping the output from the child process and reformatting it before writing it to\n * process streams.\n *\n * AssetsDevServer is agnostic and can run any assets dev server. Be it Vite or Encore or\n * even Webpack directly.\n */\nexport class AssetsDevServer {\n #cwd: URL\n #logger = ui.logger\n #options?: AssetsBundlerOptions\n #devServer?: ExecaChildProcess<string>\n\n /**\n * Getting reference to colors library from logger\n */\n get #colors() {\n return this.#logger.getColors()\n }\n\n constructor(cwd: URL, options?: AssetsBundlerOptions) {\n this.#cwd = cwd\n this.#options = options\n }\n\n /**\n * Logs messages from vite dev server stdout and stderr\n */\n #logViteDevServerMessage(data: Buffer) {\n const dataString = data.toString()\n const lines = dataString.split('\\n')\n\n /**\n * Put a wrapper around vite network address log\n */\n if (dataString.includes('Local') && dataString.includes('Network')) {\n const sticker = ui.sticker().useColors(this.#colors).useRenderer(this.#logger.getRenderer())\n\n lines.forEach((line: string) => {\n if (line.trim()) {\n sticker.add(line)\n }\n })\n\n sticker.render()\n return\n }\n\n /**\n * Logging VITE ready in message with proper\n * spaces and newlines\n */\n if (dataString.includes('ready in')) {\n console.log('')\n console.log(dataString.trim())\n return\n }\n\n /**\n * Log rest of the lines\n */\n lines.forEach((line: string) => {\n if (line.trim()) {\n console.log(line)\n }\n })\n }\n\n /**\n * Logs messages from assets dev server stdout and stderr\n */\n #logAssetsDevServerMessage(data: Buffer) {\n const dataString = data.toString()\n const lines = dataString.split('\\n')\n lines.forEach((line: string) => {\n if (line.trim()) {\n console.log(line)\n }\n })\n }\n\n /**\n * Set a custom CLI UI logger\n */\n setLogger(logger: Logger) {\n this.#logger = logger\n return this\n }\n\n /**\n * Starts the assets bundler server. The assets bundler server process is\n * considered as the secondary process and therefore we do not perform\n * any cleanup if it dies.\n */\n start() {\n if (!this.#options?.enabled) {\n return\n }\n\n this.#logger.info(`starting \"${this.#options.driver}\" dev server...`)\n\n /**\n * Create child process\n */\n this.#devServer = run(this.#cwd, {\n script: this.#options.cmd,\n\n /**\n * We do not inherit the stdio for vite and encore, because in\n * inherit mode they own the stdin and interrupts the\n * `Ctrl + C` command.\n */\n stdio: 'pipe',\n scriptArgs: this.#options.args,\n })\n\n /**\n * Log child process messages\n */\n this.#devServer.stdout?.on('data', (data) => {\n if (this.#options!.driver === 'vite') {\n this.#logViteDevServerMessage(data)\n } else {\n this.#logAssetsDevServerMessage(data)\n }\n })\n\n this.#devServer.stderr?.on('data', (data) => {\n if (this.#options!.driver === 'vite') {\n this.#logViteDevServerMessage(data)\n } else {\n this.#logAssetsDevServerMessage(data)\n }\n })\n\n this.#devServer\n .then((result) => {\n this.#logger.warning(\n `\"${this.#options!.driver}\" dev server closed with status code \"${result.exitCode}\"`\n )\n })\n .catch((error) => {\n this.#logger.warning(`unable to connect to \"${this.#options!.driver}\" dev server`)\n this.#logger.fatal(error)\n })\n }\n\n /**\n * Stop the dev server\n */\n stop() {\n if (this.#devServer) {\n this.#devServer.removeAllListeners()\n this.#devServer.kill('SIGKILL')\n this.#devServer = undefined\n }\n }\n}\n","/*\n * @adonisjs/assembler\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport picomatch from 'picomatch'\nimport type tsStatic from 'typescript'\nimport { type ExecaChildProcess } from 'execa'\nimport { cliui, type Logger } from '@poppinss/cliui'\nimport type { Watcher } from '@poppinss/chokidar-ts'\n\nimport type { TestRunnerOptions } from './types.js'\nimport { AssetsDevServer } from './assets_dev_server.js'\nimport { getPort, isDotEnvFile, runNode, watch } from './helpers.js'\n\n/**\n * Instance of CLIUI\n */\nconst ui = cliui()\n\n/**\n * Exposes the API to run Japa tests and optionally watch for file\n * changes to re-run the tests.\n *\n * The watch mode functions as follows.\n *\n * - If the changed file is a test file, then only tests for that file\n * will be re-run.\n * - Otherwise, all tests will re-run with respect to the initial\n * filters applied when running the `node ace test` command.\n *\n */\nexport class TestRunner {\n #cwd: URL\n #logger = ui.logger\n #options: TestRunnerOptions\n\n /**\n * The script file to run as a child process\n */\n #scriptFile: string = 'bin/test.js'\n\n /**\n * Pico matcher function to check if the filepath is\n * part of the `metaFiles` glob patterns\n */\n #isMetaFile: picomatch.Matcher\n\n /**\n * Pico matcher function to check if the filepath is\n * part of a test file.\n */\n #isTestFile: picomatch.Matcher\n\n /**\n * Arguments to pass to the \"bin/test.js\" file.\n */\n #scriptArgs: string[]\n\n /**\n * Set of initial filters applied when running the test\n * command. In watch mode, we will append an additional\n * filter to run tests only for the file that has been\n * changed.\n */\n #initialFiltersArgs: string[]\n\n /**\n * In watch mode, after a file is changed, we wait for the current\n * set of tests to finish before triggering a re-run. Therefore,\n * we use this flag to know if we are already busy in running\n * tests and ignore file-changes.\n */\n #isBusy: boolean = false\n\n /**\n * External listeners that are invoked when child process\n * gets an error or closes\n */\n #onError?: (error: any) => any\n #onClose?: (exitCode: number) => any\n\n /**\n * Reference to the test script child process\n */\n #testScript?: ExecaChildProcess<string>\n\n /**\n * Reference to the watcher\n */\n #watcher?: ReturnType<Watcher['watch']>\n\n /**\n * Reference to the assets server\n */\n #assetsServer?: AssetsDevServer\n\n /**\n * Getting reference to colors library from logger\n */\n get #colors() {\n return this.#logger.getColors()\n }\n\n constructor(cwd: URL, options: TestRunnerOptions) {\n this.#cwd = cwd\n this.#options = options\n\n this.#isMetaFile = picomatch((this.#options.metaFiles || []).map(({ pattern }) => pattern))\n\n /**\n * Create a test file watch by collection all the globs\n * used by all the suites. However, if a suite filter\n * was used, then we only collect glob for the mentioned\n * suites.\n */\n this.#isTestFile = picomatch(\n this.#options.suites\n .filter((suite) => {\n if (this.#options.filters.suites) {\n return this.#options.filters.suites.includes(suite.name)\n }\n return true\n })\n .map((suite) => suite.files)\n .flat(1)\n )\n\n this.#scriptArgs = this.#convertOptionsToArgs().concat(this.#options.scriptArgs)\n this.#initialFiltersArgs = this.#convertFiltersToArgs(this.#options.filters)\n }\n\n /**\n * Convert test runner options to the CLI args\n */\n #convertOptionsToArgs() {\n const args: string[] = []\n\n if (this.#options.reporters) {\n args.push('--reporters')\n args.push(this.#options.reporters.join(','))\n }\n\n if (this.#options.timeout !== undefined) {\n args.push('--timeout')\n args.push(String(this.#options.timeout))\n }\n\n if (this.#options.failed) {\n args.push('--failed')\n }\n\n if (this.#options.retries !== undefined) {\n args.push('--retries')\n args.push(String(this.#options.retries))\n }\n\n return args\n }\n\n /**\n * Converts all known filters to CLI args.\n *\n * The following code snippet may seem like repetitive code. But, it\n * is done intentionally to have visibility around how each filter\n * is converted to an arg.\n */\n #convertFiltersToArgs(filters: TestRunnerOptions['filters']): string[] {\n const args: string[] = []\n\n if (filters.suites) {\n args.push(...filters.suites)\n }\n\n if (filters.files) {\n args.push('--files')\n args.push(filters.files.join(','))\n }\n\n if (filters.groups) {\n args.push('--groups')\n args.push(filters.groups.join(','))\n }\n\n if (filters.tags) {\n args.push('--tags')\n args.push(filters.tags.join(','))\n }\n\n if (filters.tests) {\n args.push('--tests')\n args.push(filters.tests.join(','))\n }\n\n return args\n }\n\n /**\n * Conditionally clear the terminal screen\n */\n #clearScreen() {\n if (this.#options.clearScreen) {\n process.stdout.write('\\u001Bc')\n }\n }\n\n /**\n * Runs tests\n */\n #runTests(\n port: string,\n mode: 'blocking' | 'nonblocking',\n filters?: TestRunnerOptions['filters']\n ) {\n this.#isBusy = true\n\n /**\n * If inline filters are defined, then we ignore the\n * initial filters\n */\n const scriptArgs = filters\n ? this.#convertFiltersToArgs(filters).concat(this.#scriptArgs)\n : this.#initialFiltersArgs.concat(this.#scriptArgs)\n\n this.#testScript = runNode(this.#cwd, {\n script: this.#scriptFile,\n env: { PORT: port, ...this.#options.env },\n nodeArgs: this.#options.nodeArgs,\n scriptArgs,\n })\n\n this.#testScript\n .then((result) => {\n if (mode === 'nonblocking') {\n this.#onClose?.(result.exitCode)\n this.close()\n }\n })\n .catch((error) => {\n if (mode === 'nonblocking') {\n this.#onError?.(error)\n this.close()\n }\n })\n .finally(() => {\n this.#isBusy = false\n })\n }\n\n /**\n * Re-run tests with additional inline filters. Should be\n * executed in watch mode only.\n */\n #rerunTests(port: string, filters?: TestRunnerOptions['filters']) {\n if (this.#testScript) {\n this.#testScript.removeAllListeners()\n this.#testScript.kill('SIGKILL')\n }\n\n this.#runTests(port, 'blocking', filters)\n }\n\n /**\n * Starts the assets server\n */\n #startAssetsServer() {\n this.#assetsServer = new AssetsDevServer(this.#cwd, this.#options.assets)\n this.#assetsServer.setLogger(this.#logger)\n this.#assetsServer.start()\n }\n\n /**\n * Handles a non TypeScript file change\n */\n #handleFileChange(action: string, port: string, relativePath: string) {\n if (this.#isBusy) {\n return\n }\n\n if (isDotEnvFile(relativePath) || this.#isMetaFile(relativePath)) {\n this.#clearScreen()\n this.#logger.log(`${this.#colors.green(action)} ${relativePath}`)\n this.#rerunTests(port)\n }\n }\n\n /**\n * Handles TypeScript source file change\n */\n #handleSourceFileChange(action: string, port: string, relativePath: string) {\n if (this.#isBusy) {\n return\n }\n\n this.#clearScreen()\n this.#logger.log(`${this.#colors.green(action)} ${relativePath}`)\n\n /**\n * If changed file is a test file after considering the initial filters,\n * then only run that file\n */\n if (this.#isTestFile(relativePath)) {\n this.#rerunTests(port, {\n ...this.#options.filters,\n files: [relativePath],\n })\n return\n }\n\n this.#rerunTests(port)\n }\n\n /**\n * Set a custom CLI UI logger\n */\n setLogger(logger: Logger) {\n this.#logger = logger\n this.#assetsServer?.setLogger(logger)\n return this\n }\n\n /**\n * Add listener to get notified when dev server is\n * closed\n */\n onClose(callback: (exitCode: number) => any): this {\n this.#onClose = callback\n return this\n }\n\n /**\n * Add listener to get notified when dev server exists\n * with an error\n */\n onError(callback: (error: any) => any): this {\n this.#onError = callback\n return this\n }\n\n /**\n * Close watchers and running child processes\n */\n async close() {\n await this.#watcher?.close()\n this.#assetsServer?.stop()\n if (this.#testScript) {\n this.#testScript.removeAllListeners()\n this.#testScript.kill('SIGKILL')\n }\n }\n\n /**\n * Runs tests\n */\n async run() {\n const port = String(await getPort(this.#cwd))\n\n this.#clearScreen()\n this.#startAssetsServer()\n\n this.#logger.info('booting application to run tests...')\n this.#runTests(port, 'nonblocking')\n }\n\n /**\n * Run tests in watch mode\n */\n async runAndWatch(ts: typeof tsStatic, options?: { poll: boolean }) {\n const port = String(await getPort(this.#cwd))\n\n this.#clearScreen()\n this.#startAssetsServer()\n\n this.#logger.info('booting application to run tests...')\n this.#runTests(port, 'blocking')\n\n /**\n * Create watcher using tsconfig.json file\n */\n const output = watch(this.#cwd, ts, options || {})\n if (!output) {\n this.#onClose?.(1)\n return\n }\n\n /**\n * Storing reference to watcher, so that we can close it\n * when HTTP server exists with error\n */\n this.#watcher = output.chokidar\n\n /**\n * Notify the watcher is ready\n */\n output.watcher.on('watcher:ready', () => {\n this.#logger.info('watching file system for changes...')\n })\n\n /**\n * Cleanup when watcher dies\n */\n output.chokidar.on('error', (error) => {\n this.#logger.warning('file system watcher failure')\n this.#logger.fatal(error)\n this.#onError?.(error)\n output.chokidar.close()\n })\n\n /**\n * Changes in TypeScript source file\n */\n output.watcher.on('source:add', ({ relativePath }) =>\n this.#handleSourceFileChange('add', port, relativePath)\n )\n output.watcher.on('source:change', ({ relativePath }) =>\n this.#handleSourceFileChange('update', port, relativePath)\n )\n output.watcher.on('source:unlink', ({ relativePath }) =>\n this.#handleSourceFileChange('delete', port, relativePath)\n )\n\n /**\n * Changes in non-TypeScript source files\n */\n output.watcher.on('add', ({ relativePath }) =>\n this.#handleFileChange('add', port, relativePath)\n )\n output.watcher.on('change', ({ relativePath }) =>\n this.#handleFileChange('update', port, relativePath)\n )\n output.watcher.on('unlink', ({ relativePath }) =>\n this.#handleFileChange('delete', port, relativePath)\n )\n }\n}\n"],"mappings":"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","names":["relative","fileURLToPath","fileURLToPath","relative","cliui","cliui","ui","cliui","ui","cliui","picomatch","cliui","ui","cliui","picomatch"]}
@@ -1,7 +1,7 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
2
  import { installPackage, detectPackageManager } from '@antfu/install-pkg';
3
3
  import { RcFileTransformer } from './rc_file_transformer.js';
4
- import type { MiddlewareNode, EnvValidationNode } from '../types.js';
4
+ import type { MiddlewareNode, EnvValidationNode, BouncerPolicyNode } from '../types.js';
5
5
  /**
6
6
  * This class is responsible for updating
7
7
  */
@@ -40,4 +40,9 @@ export declare class CodeTransformer {
40
40
  module: string;
41
41
  identifier: string;
42
42
  }[]): Promise<void>;
43
+ /**
44
+ * Adds a policy to the list of `policies` object configured
45
+ * inside the `app/policies/main.ts` file.
46
+ */
47
+ addPolicies(policies: BouncerPolicyNode[]): Promise<void>;
43
48
  }
@@ -337,6 +337,17 @@ var CodeTransformer = class {
337
337
  namedMiddlewareObject.insertProperty(0, middleware);
338
338
  }
339
339
  }
340
+ /**
341
+ * Add a policy to the list of pre-registered policy
342
+ */
343
+ #addToPoliciesList(file, policyEntry) {
344
+ const policiesObject = file.getVariableDeclarationOrThrow("policies").getInitializerIfKindOrThrow(SyntaxKind2.ObjectLiteralExpression);
345
+ const existingProperty = policiesObject.getProperty(policyEntry.name);
346
+ if (!existingProperty) {
347
+ const policy = `${policyEntry.name}: () => import('${policyEntry.path}')`;
348
+ policiesObject.insertProperty(0, policy);
349
+ }
350
+ }
340
351
  /**
341
352
  * Write a leading comment
342
353
  */
@@ -447,6 +458,19 @@ var CodeTransformer = class {
447
458
  file.formatText(this.#editorSettings);
448
459
  await file.save();
449
460
  }
461
+ /**
462
+ * Adds a policy to the list of `policies` object configured
463
+ * inside the `app/policies/main.ts` file.
464
+ */
465
+ async addPolicies(policies) {
466
+ const kernelUrl = fileURLToPath2(new URL("./app/policies/main.ts", this.#cwd));
467
+ const file = this.#project.getSourceFileOrThrow(kernelUrl);
468
+ for (const policy of policies) {
469
+ this.#addToPoliciesList(file, policy);
470
+ }
471
+ file.formatText(this.#editorSettings);
472
+ await file.save();
473
+ }
450
474
  };
451
475
  export {
452
476
  CodeTransformer
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/code_transformer/main.ts","../../../src/code_transformer/rc_file_transformer.ts"],"sourcesContent":["/*\n * @adonisjs/assembler\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { installPackage, detectPackageManager } from '@antfu/install-pkg'\nimport {\n Node,\n Project,\n QuoteKind,\n SourceFile,\n SyntaxKind,\n CodeBlockWriter,\n FormatCodeSettings,\n} from 'ts-morph'\n\nimport { RcFileTransformer } from './rc_file_transformer.js'\nimport type { MiddlewareNode, EnvValidationNode } from '../types.js'\n\n/**\n * This class is responsible for updating\n */\nexport class CodeTransformer {\n /**\n * Exporting utilities to install package and detect\n * the package manager\n */\n installPackage = installPackage\n detectPackageManager = detectPackageManager\n\n /**\n * Directory of the adonisjs project\n */\n #cwd: URL\n\n /**\n * The TsMorph project\n */\n #project: Project\n\n /**\n * Settings to use when persisting files\n */\n #editorSettings: FormatCodeSettings = {\n indentSize: 2,\n convertTabsToSpaces: true,\n trimTrailingWhitespace: true,\n ensureNewLineAtEndOfFile: true,\n indentStyle: 2,\n // @ts-expect-error SemicolonPreference doesn't seem to be re-exported from ts-morph\n semicolons: 'remove',\n }\n\n constructor(cwd: URL) {\n this.#cwd = cwd\n this.#project = new Project({\n tsConfigFilePath: join(fileURLToPath(this.#cwd), 'tsconfig.json'),\n manipulationSettings: { quoteKind: QuoteKind.Single },\n })\n }\n\n /**\n * Add a new middleware to the middleware array of the\n * given file\n */\n #addToMiddlewareArray(file: SourceFile, target: string, middlewareEntry: MiddlewareNode) {\n const callExpressions = file\n .getDescendantsOfKind(SyntaxKind.CallExpression)\n .filter((statement) => statement.getExpression().getText() === target)\n\n if (!callExpressions.length) {\n throw new Error(`Cannot find ${target} statement in the file.`)\n }\n\n const arrayLiteralExpression = callExpressions[0].getArguments()[0]\n if (!arrayLiteralExpression || !Node.isArrayLiteralExpression(arrayLiteralExpression)) {\n throw new Error(`Cannot find middleware array in ${target} statement.`)\n }\n\n const middleware = `() => import('${middlewareEntry.path}')`\n\n /**\n * Delete the existing middleware if it exists\n */\n const existingMiddlewareIndex = arrayLiteralExpression\n .getElements()\n .findIndex((element) => element.getText() === middleware)\n\n if (existingMiddlewareIndex === -1) {\n /**\n * Add the middleware to the top or bottom of the array\n */\n if (middlewareEntry.position === 'before') {\n arrayLiteralExpression.insertElement(0, middleware)\n } else {\n arrayLiteralExpression.addElement(middleware)\n }\n }\n }\n\n /**\n * Add a new middleware to the named middleware of the given file\n */\n #addToNamedMiddleware(file: SourceFile, middlewareEntry: MiddlewareNode) {\n if (!middlewareEntry.name) {\n throw new Error('Named middleware requires a name.')\n }\n\n const callArguments = file\n .getVariableDeclarationOrThrow('middleware')\n .getInitializerIfKindOrThrow(SyntaxKind.CallExpression)\n .getArguments()\n\n if (callArguments.length === 0) {\n throw new Error('Named middleware call has no arguments.')\n }\n\n const namedMiddlewareObject = callArguments[0]\n if (!Node.isObjectLiteralExpression(namedMiddlewareObject)) {\n throw new Error('The argument of the named middleware call is not an object literal.')\n }\n\n /**\n * Check if property is already defined. If so, remove it\n */\n const existingProperty = namedMiddlewareObject.getProperty(middlewareEntry.name)\n if (!existingProperty) {\n /**\n * Add the named middleware\n */\n const middleware = `${middlewareEntry.name}: () => import('${middlewareEntry.path}')`\n namedMiddlewareObject!.insertProperty(0, middleware)\n }\n }\n\n /**\n * Write a leading comment\n */\n #addLeadingComment(writer: CodeBlockWriter, comment?: string) {\n if (!comment) {\n return writer.blankLine()\n }\n\n return writer\n .blankLine()\n .writeLine('/*')\n .writeLine(`|----------------------------------------------------------`)\n .writeLine(`| ${comment}`)\n .writeLine(`|----------------------------------------------------------`)\n .writeLine(`*/`)\n }\n\n /**\n * Add new env variable validation in the\n * `env.ts` file\n */\n async defineEnvValidations(definition: EnvValidationNode) {\n /**\n * Get the `start/env.ts` source file\n */\n const kernelUrl = fileURLToPath(new URL('./start/env.ts', this.#cwd))\n const file = this.#project.getSourceFileOrThrow(kernelUrl)\n\n /**\n * Get the `Env.create` call expression\n */\n const callExpressions = file\n .getDescendantsOfKind(SyntaxKind.CallExpression)\n .filter((statement) => statement.getExpression().getText() === 'Env.create')\n\n if (!callExpressions.length) {\n throw new Error(`Cannot find Env.create statement in the file.`)\n }\n\n const objectLiteralExpression = callExpressions[0].getArguments()[1]\n if (!Node.isObjectLiteralExpression(objectLiteralExpression)) {\n throw new Error(`The second argument of Env.create is not an object literal.`)\n }\n\n let shouldAddComment = true\n\n /**\n * Add each variable validation\n */\n for (const [variable, validation] of Object.entries(definition.variables)) {\n /**\n * Check if the variable is already defined. If so, remove it\n */\n const existingProperty = objectLiteralExpression.getProperty(variable)\n\n /**\n * Do not add leading comment if one or more properties\n * already exists\n */\n if (existingProperty) {\n shouldAddComment = false\n }\n\n /**\n * Add property only when the property does not exist\n */\n if (!existingProperty) {\n objectLiteralExpression.addPropertyAssignment({\n name: variable,\n initializer: validation,\n leadingTrivia: (writer) => {\n if (!shouldAddComment) {\n return\n }\n\n shouldAddComment = false\n return this.#addLeadingComment(writer, definition.leadingComment)\n },\n })\n }\n }\n\n file.formatText(this.#editorSettings)\n await file.save()\n }\n\n /**\n * Define new middlewares inside the `start/kernel.ts`\n * file\n *\n * This function is highly based on some assumptions\n * and will not work if you significantly tweaked\n * your `start/kernel.ts` file.\n */\n async addMiddlewareToStack(stack: 'server' | 'router' | 'named', middleware: MiddlewareNode[]) {\n /**\n * Get the `start/kernel.ts` source file\n */\n const kernelUrl = fileURLToPath(new URL('./start/kernel.ts', this.#cwd))\n const file = this.#project.getSourceFileOrThrow(kernelUrl)\n\n /**\n * Process each middleware entry\n */\n for (const middlewareEntry of middleware) {\n if (stack === 'named') {\n this.#addToNamedMiddleware(file, middlewareEntry)\n } else {\n this.#addToMiddlewareArray(file!, `${stack}.use`, middlewareEntry)\n }\n }\n\n file.formatText(this.#editorSettings)\n await file.save()\n }\n\n /**\n * Update the `adonisrc.ts` file\n */\n async updateRcFile(callback: (transformer: RcFileTransformer) => void) {\n const rcFileTransformer = new RcFileTransformer(this.#cwd, this.#project)\n callback(rcFileTransformer)\n await rcFileTransformer.save()\n }\n\n /**\n * Add a new Japa plugin in the `tests/bootstrap.ts` file\n */\n async addJapaPlugin(\n pluginCall: string,\n importDeclarations: { isNamed: boolean; module: string; identifier: string }[]\n ) {\n /**\n * Get the `tests/bootstrap.ts` source file\n */\n const testBootstrapUrl = fileURLToPath(new URL('./tests/bootstrap.ts', this.#cwd))\n const file = this.#project.getSourceFileOrThrow(testBootstrapUrl)\n\n /**\n * Add the import declaration\n */\n const existingImports = file.getImportDeclarations()\n\n importDeclarations.forEach((importDeclaration) => {\n const existingImport = existingImports.find(\n (mod) => mod.getModuleSpecifierValue() === importDeclaration.module\n )\n\n /**\n * Add a new named import to existing import for the\n * same module\n */\n if (existingImport && importDeclaration.isNamed) {\n if (\n !existingImport\n .getNamedImports()\n .find((namedImport) => namedImport.getName() === importDeclaration.identifier)\n ) {\n existingImport.addNamedImport(importDeclaration.identifier)\n }\n return\n }\n\n /**\n * Ignore default import when the same module is already imported.\n * The chances are the existing default import and the importDeclaration\n * identifiers are not the same. But we should not modify existing source\n */\n if (existingImport) {\n return\n }\n\n file.addImportDeclaration({\n ...(importDeclaration.isNamed\n ? { namedImports: [importDeclaration.identifier] }\n : { defaultImport: importDeclaration.identifier }),\n moduleSpecifier: importDeclaration.module,\n })\n })\n\n /**\n * Insert the plugin call in the `plugins` array\n */\n const pluginsArray = file\n .getVariableDeclaration('plugins')\n ?.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression)\n\n /**\n * Add plugin call to the plugins array\n */\n if (pluginsArray) {\n if (!pluginsArray.getElements().find((element) => element.getText() === pluginCall)) {\n pluginsArray.addElement(pluginCall)\n }\n }\n\n file.formatText(this.#editorSettings)\n await file.save()\n }\n}\n","/*\n * @adonisjs/assembler\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { fileURLToPath } from 'node:url'\nimport type { AppEnvironments } from '@adonisjs/application/types'\nimport {\n Node,\n Project,\n SourceFile,\n SyntaxKind,\n CallExpression,\n PropertyAssignment,\n FormatCodeSettings,\n ArrayLiteralExpression,\n} from 'ts-morph'\n\n/**\n * RcFileTransformer is used to transform the `adonisrc.ts` file\n * for adding new commands, providers, meta files etc\n */\nexport class RcFileTransformer {\n #cwd: URL\n #project: Project\n\n /**\n * Settings to use when persisting files\n */\n #editorSettings: FormatCodeSettings = {\n indentSize: 2,\n convertTabsToSpaces: true,\n trimTrailingWhitespace: true,\n ensureNewLineAtEndOfFile: true,\n indentStyle: 2,\n // @ts-expect-error SemicolonPreference doesn't seem to be re-exported from ts-morph\n semicolons: 'remove',\n }\n\n constructor(cwd: URL, project: Project) {\n this.#cwd = cwd\n this.#project = project\n }\n\n /**\n * Get the `adonisrc.ts` source file\n */\n #getRcFileOrThrow() {\n const kernelUrl = fileURLToPath(new URL('./adonisrc.ts', this.#cwd))\n return this.#project.getSourceFileOrThrow(kernelUrl)\n }\n\n /**\n * Check if environments array has a subset of available environments\n */\n #isInSpecificEnvironment(environments?: AppEnvironments[]): boolean {\n if (!environments) {\n return false\n }\n\n return !!(['web', 'console', 'test', 'repl'] as const).find(\n (env) => !environments.includes(env)\n )\n }\n\n /**\n * Locate the `defineConfig` call inside the `adonisrc.ts` file\n */\n #locateDefineConfigCallOrThrow(file: SourceFile) {\n const call = file\n .getDescendantsOfKind(SyntaxKind.CallExpression)\n .find((statement) => statement.getExpression().getText() === 'defineConfig')\n\n if (!call) {\n throw new Error('Could not locate the defineConfig call.')\n }\n\n return call\n }\n\n /**\n * Return the ObjectLiteralExpression of the defineConfig call\n */\n #getDefineConfigObjectOrThrow(defineConfigCall: CallExpression) {\n const configObject = defineConfigCall\n .getArguments()[0]\n .asKindOrThrow(SyntaxKind.ObjectLiteralExpression)\n\n return configObject\n }\n\n /**\n * Check if the defineConfig() call has the property assignment\n * inside it or not. If not, it will create one and return it.\n */\n #getPropertyAssignmentInDefineConfigCall(propertyName: string, initializer: string) {\n const file = this.#getRcFileOrThrow()\n const defineConfigCall = this.#locateDefineConfigCallOrThrow(file)\n const configObject = this.#getDefineConfigObjectOrThrow(defineConfigCall)\n\n let property = configObject.getProperty(propertyName)\n\n if (!property) {\n configObject.addPropertyAssignment({ name: propertyName, initializer })\n property = configObject.getProperty(propertyName)\n }\n\n return property as PropertyAssignment\n }\n\n /**\n * Extract list of imported modules from an ArrayLiteralExpression\n *\n * It assumes that the array can have two types of elements:\n *\n * - Simple lazy imported modules: [() => import('path/to/file')]\n * - Or an object entry: [{ file: () => import('path/to/file'), environment: ['web', 'console'] }]\n * where the `file` property is a lazy imported module.\n */\n #extractModulesFromArray(array: ArrayLiteralExpression) {\n const modules = array.getElements().map((element) => {\n /**\n * Simple lazy imported module\n */\n if (Node.isArrowFunction(element)) {\n const importExp = element.getFirstDescendantByKindOrThrow(SyntaxKind.CallExpression)\n const literal = importExp.getFirstDescendantByKindOrThrow(SyntaxKind.StringLiteral)\n return literal.getLiteralValue()\n }\n\n /**\n * Object entry\n */\n if (Node.isObjectLiteralExpression(element)) {\n const fileProp = element.getPropertyOrThrow('file') as PropertyAssignment\n const arrowFn = fileProp.getFirstDescendantByKindOrThrow(SyntaxKind.ArrowFunction)\n const importExp = arrowFn.getFirstDescendantByKindOrThrow(SyntaxKind.CallExpression)\n const literal = importExp.getFirstDescendantByKindOrThrow(SyntaxKind.StringLiteral)\n return literal.getLiteralValue()\n }\n })\n\n return modules.filter(Boolean) as string[]\n }\n\n /**\n * Extract a specific property from an ArrayLiteralExpression\n * that contains object entries.\n *\n * This function is mainly used for extractring the `pattern` property\n * when adding a new meta files entry, or the `name` property when\n * adding a new test suite.\n */\n #extractPropertyFromArray(array: ArrayLiteralExpression, propertyName: string) {\n const property = array.getElements().map((el) => {\n if (!Node.isObjectLiteralExpression(el)) return\n\n const nameProp = el.getPropertyOrThrow(propertyName)\n if (!Node.isPropertyAssignment(nameProp)) return\n\n const name = nameProp.getInitializerIfKindOrThrow(SyntaxKind.StringLiteral)\n return name.getLiteralValue()\n })\n\n return property.filter(Boolean) as string[]\n }\n\n /**\n * Build a new module entry for the preloads and providers array\n * based upon the environments specified\n */\n #buildNewModuleEntry(modulePath: string, environments?: AppEnvironments[]) {\n if (!this.#isInSpecificEnvironment(environments)) {\n return `() => import('${modulePath}')`\n }\n\n return `{\n file: () => import('${modulePath}'),\n environment: [${environments?.map((env) => `'${env}'`).join(', ')}],\n }`\n }\n\n /**\n * Add a new command to the rcFile\n */\n addCommand(commandPath: string) {\n const commandsProperty = this.#getPropertyAssignmentInDefineConfigCall('commands', '[]')\n const commandsArray = commandsProperty.getInitializerIfKindOrThrow(\n SyntaxKind.ArrayLiteralExpression\n )\n\n const commandString = `() => import('${commandPath}')`\n\n /**\n * If the command already exists, do nothing\n */\n if (commandsArray.getElements().some((el) => el.getText() === commandString)) {\n return this\n }\n\n /**\n * Add the command to the array\n */\n commandsArray.addElement(commandString)\n return this\n }\n\n /**\n * Add a new preloaded file to the rcFile\n */\n addPreloadFile(modulePath: string, environments?: AppEnvironments[]) {\n const preloadsProperty = this.#getPropertyAssignmentInDefineConfigCall('preloads', '[]')\n const preloadsArray = preloadsProperty.getInitializerIfKindOrThrow(\n SyntaxKind.ArrayLiteralExpression\n )\n\n /**\n * Check for duplicates\n */\n const existingPreloadedFiles = this.#extractModulesFromArray(preloadsArray)\n const isDuplicate = existingPreloadedFiles.includes(modulePath)\n if (isDuplicate) {\n return this\n }\n\n /**\n * Add the preloaded file to the array\n */\n preloadsArray.addElement(this.#buildNewModuleEntry(modulePath, environments))\n return this\n }\n\n /**\n * Add a new provider to the rcFile\n */\n addProvider(providerPath: string, environments?: AppEnvironments[]) {\n const property = this.#getPropertyAssignmentInDefineConfigCall('providers', '[]')\n const providersArray = property.getInitializerIfKindOrThrow(SyntaxKind.ArrayLiteralExpression)\n\n /**\n * Check for duplicates\n */\n const existingProviderPaths = this.#extractModulesFromArray(providersArray)\n const isDuplicate = existingProviderPaths.includes(providerPath)\n if (isDuplicate) {\n return this\n }\n\n /**\n * Add the provider to the array\n */\n providersArray.addElement(this.#buildNewModuleEntry(providerPath, environments))\n\n return this\n }\n\n /**\n * Add a new meta file to the rcFile\n */\n addMetaFile(globPattern: string, reloadServer = false) {\n const property = this.#getPropertyAssignmentInDefineConfigCall('metaFiles', '[]')\n const metaFilesArray = property.getInitializerIfKindOrThrow(SyntaxKind.ArrayLiteralExpression)\n\n /**\n * Check for duplicates\n */\n const alreadyDefinedPatterns = this.#extractPropertyFromArray(metaFilesArray, 'pattern')\n if (alreadyDefinedPatterns.includes(globPattern)) {\n return this\n }\n\n /**\n * Add the meta file to the array\n */\n metaFilesArray.addElement(\n `{\n pattern: '${globPattern}',\n reloadServer: ${reloadServer},\n }`\n )\n\n return this\n }\n\n /**\n * Set directory name and path\n */\n setDirectory(key: string, value: string) {\n const property = this.#getPropertyAssignmentInDefineConfigCall('directories', '{}')\n const directories = property.getInitializerIfKindOrThrow(SyntaxKind.ObjectLiteralExpression)\n directories.addPropertyAssignment({ name: key, initializer: `'${value}'` })\n\n return this\n }\n\n /**\n * Set command alias\n */\n setCommandAlias(alias: string, command: string) {\n const aliasProperty = this.#getPropertyAssignmentInDefineConfigCall('commandsAliases', '{}')\n const aliases = aliasProperty.getInitializerIfKindOrThrow(SyntaxKind.ObjectLiteralExpression)\n aliases.addPropertyAssignment({ name: alias, initializer: `'${command}'` })\n\n return this\n }\n\n /**\n * Add a new test suite to the rcFile\n */\n addSuite(suiteName: string, files: string | string[], timeout?: number) {\n const testProperty = this.#getPropertyAssignmentInDefineConfigCall(\n 'tests',\n `{ suites: [], forceExit: true, timeout: 2000 }`\n )\n\n const property = testProperty\n .getInitializerIfKindOrThrow(SyntaxKind.ObjectLiteralExpression)\n .getPropertyOrThrow('suites') as PropertyAssignment\n\n const suitesArray = property.getInitializerIfKindOrThrow(SyntaxKind.ArrayLiteralExpression)\n\n /**\n * Check for duplicates\n */\n const existingSuitesNames = this.#extractPropertyFromArray(suitesArray, 'name')\n if (existingSuitesNames.includes(suiteName)) {\n return this\n }\n\n /**\n * Add the suite to the array\n */\n const filesArray = Array.isArray(files) ? files : [files]\n suitesArray.addElement(\n `{\n name: '${suiteName}',\n files: [${filesArray.map((file) => `'${file}'`).join(', ')}],\n timeout: ${timeout ?? 2000},\n }`\n )\n\n return this\n }\n\n /**\n * Save the adonisrc.ts file\n */\n save() {\n const file = this.#getRcFileOrThrow()\n file.formatText(this.#editorSettings)\n return file.save()\n }\n}\n"],"mappings":"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","names":["fileURLToPath","Node","Project","SyntaxKind","Project","fileURLToPath","SyntaxKind","Node"]}
1
+ {"version":3,"sources":["../../../src/code_transformer/main.ts","../../../src/code_transformer/rc_file_transformer.ts"],"sourcesContent":["/*\n * @adonisjs/assembler\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { installPackage, detectPackageManager } from '@antfu/install-pkg'\nimport {\n Node,\n Project,\n QuoteKind,\n SourceFile,\n SyntaxKind,\n CodeBlockWriter,\n FormatCodeSettings,\n} from 'ts-morph'\n\nimport { RcFileTransformer } from './rc_file_transformer.js'\nimport type { MiddlewareNode, EnvValidationNode, BouncerPolicyNode } from '../types.js'\n\n/**\n * This class is responsible for updating\n */\nexport class CodeTransformer {\n /**\n * Exporting utilities to install package and detect\n * the package manager\n */\n installPackage = installPackage\n detectPackageManager = detectPackageManager\n\n /**\n * Directory of the adonisjs project\n */\n #cwd: URL\n\n /**\n * The TsMorph project\n */\n #project: Project\n\n /**\n * Settings to use when persisting files\n */\n #editorSettings: FormatCodeSettings = {\n indentSize: 2,\n convertTabsToSpaces: true,\n trimTrailingWhitespace: true,\n ensureNewLineAtEndOfFile: true,\n indentStyle: 2,\n // @ts-expect-error SemicolonPreference doesn't seem to be re-exported from ts-morph\n semicolons: 'remove',\n }\n\n constructor(cwd: URL) {\n this.#cwd = cwd\n this.#project = new Project({\n tsConfigFilePath: join(fileURLToPath(this.#cwd), 'tsconfig.json'),\n manipulationSettings: { quoteKind: QuoteKind.Single },\n })\n }\n\n /**\n * Add a new middleware to the middleware array of the\n * given file\n */\n #addToMiddlewareArray(file: SourceFile, target: string, middlewareEntry: MiddlewareNode) {\n const callExpressions = file\n .getDescendantsOfKind(SyntaxKind.CallExpression)\n .filter((statement) => statement.getExpression().getText() === target)\n\n if (!callExpressions.length) {\n throw new Error(`Cannot find ${target} statement in the file.`)\n }\n\n const arrayLiteralExpression = callExpressions[0].getArguments()[0]\n if (!arrayLiteralExpression || !Node.isArrayLiteralExpression(arrayLiteralExpression)) {\n throw new Error(`Cannot find middleware array in ${target} statement.`)\n }\n\n const middleware = `() => import('${middlewareEntry.path}')`\n\n /**\n * Delete the existing middleware if it exists\n */\n const existingMiddlewareIndex = arrayLiteralExpression\n .getElements()\n .findIndex((element) => element.getText() === middleware)\n\n if (existingMiddlewareIndex === -1) {\n /**\n * Add the middleware to the top or bottom of the array\n */\n if (middlewareEntry.position === 'before') {\n arrayLiteralExpression.insertElement(0, middleware)\n } else {\n arrayLiteralExpression.addElement(middleware)\n }\n }\n }\n\n /**\n * Add a new middleware to the named middleware of the given file\n */\n #addToNamedMiddleware(file: SourceFile, middlewareEntry: MiddlewareNode) {\n if (!middlewareEntry.name) {\n throw new Error('Named middleware requires a name.')\n }\n\n const callArguments = file\n .getVariableDeclarationOrThrow('middleware')\n .getInitializerIfKindOrThrow(SyntaxKind.CallExpression)\n .getArguments()\n\n if (callArguments.length === 0) {\n throw new Error('Named middleware call has no arguments.')\n }\n\n const namedMiddlewareObject = callArguments[0]\n if (!Node.isObjectLiteralExpression(namedMiddlewareObject)) {\n throw new Error('The argument of the named middleware call is not an object literal.')\n }\n\n /**\n * Check if property is already defined. If so, remove it\n */\n const existingProperty = namedMiddlewareObject.getProperty(middlewareEntry.name)\n if (!existingProperty) {\n /**\n * Add the named middleware\n */\n const middleware = `${middlewareEntry.name}: () => import('${middlewareEntry.path}')`\n namedMiddlewareObject!.insertProperty(0, middleware)\n }\n }\n\n /**\n * Add a policy to the list of pre-registered policy\n */\n #addToPoliciesList(file: SourceFile, policyEntry: BouncerPolicyNode) {\n const policiesObject = file\n .getVariableDeclarationOrThrow('policies')\n .getInitializerIfKindOrThrow(SyntaxKind.ObjectLiteralExpression)\n\n /**\n * Only define policy when one with the existing name does not\n * exist.\n */\n const existingProperty = policiesObject.getProperty(policyEntry.name)\n if (!existingProperty) {\n const policy = `${policyEntry.name}: () => import('${policyEntry.path}')`\n policiesObject!.insertProperty(0, policy)\n }\n }\n\n /**\n * Write a leading comment\n */\n #addLeadingComment(writer: CodeBlockWriter, comment?: string) {\n if (!comment) {\n return writer.blankLine()\n }\n\n return writer\n .blankLine()\n .writeLine('/*')\n .writeLine(`|----------------------------------------------------------`)\n .writeLine(`| ${comment}`)\n .writeLine(`|----------------------------------------------------------`)\n .writeLine(`*/`)\n }\n\n /**\n * Add new env variable validation in the\n * `env.ts` file\n */\n async defineEnvValidations(definition: EnvValidationNode) {\n /**\n * Get the `start/env.ts` source file\n */\n const kernelUrl = fileURLToPath(new URL('./start/env.ts', this.#cwd))\n const file = this.#project.getSourceFileOrThrow(kernelUrl)\n\n /**\n * Get the `Env.create` call expression\n */\n const callExpressions = file\n .getDescendantsOfKind(SyntaxKind.CallExpression)\n .filter((statement) => statement.getExpression().getText() === 'Env.create')\n\n if (!callExpressions.length) {\n throw new Error(`Cannot find Env.create statement in the file.`)\n }\n\n const objectLiteralExpression = callExpressions[0].getArguments()[1]\n if (!Node.isObjectLiteralExpression(objectLiteralExpression)) {\n throw new Error(`The second argument of Env.create is not an object literal.`)\n }\n\n let shouldAddComment = true\n\n /**\n * Add each variable validation\n */\n for (const [variable, validation] of Object.entries(definition.variables)) {\n /**\n * Check if the variable is already defined. If so, remove it\n */\n const existingProperty = objectLiteralExpression.getProperty(variable)\n\n /**\n * Do not add leading comment if one or more properties\n * already exists\n */\n if (existingProperty) {\n shouldAddComment = false\n }\n\n /**\n * Add property only when the property does not exist\n */\n if (!existingProperty) {\n objectLiteralExpression.addPropertyAssignment({\n name: variable,\n initializer: validation,\n leadingTrivia: (writer) => {\n if (!shouldAddComment) {\n return\n }\n\n shouldAddComment = false\n return this.#addLeadingComment(writer, definition.leadingComment)\n },\n })\n }\n }\n\n file.formatText(this.#editorSettings)\n await file.save()\n }\n\n /**\n * Define new middlewares inside the `start/kernel.ts`\n * file\n *\n * This function is highly based on some assumptions\n * and will not work if you significantly tweaked\n * your `start/kernel.ts` file.\n */\n async addMiddlewareToStack(stack: 'server' | 'router' | 'named', middleware: MiddlewareNode[]) {\n /**\n * Get the `start/kernel.ts` source file\n */\n const kernelUrl = fileURLToPath(new URL('./start/kernel.ts', this.#cwd))\n const file = this.#project.getSourceFileOrThrow(kernelUrl)\n\n /**\n * Process each middleware entry\n */\n for (const middlewareEntry of middleware) {\n if (stack === 'named') {\n this.#addToNamedMiddleware(file, middlewareEntry)\n } else {\n this.#addToMiddlewareArray(file!, `${stack}.use`, middlewareEntry)\n }\n }\n\n file.formatText(this.#editorSettings)\n await file.save()\n }\n\n /**\n * Update the `adonisrc.ts` file\n */\n async updateRcFile(callback: (transformer: RcFileTransformer) => void) {\n const rcFileTransformer = new RcFileTransformer(this.#cwd, this.#project)\n callback(rcFileTransformer)\n await rcFileTransformer.save()\n }\n\n /**\n * Add a new Japa plugin in the `tests/bootstrap.ts` file\n */\n async addJapaPlugin(\n pluginCall: string,\n importDeclarations: { isNamed: boolean; module: string; identifier: string }[]\n ) {\n /**\n * Get the `tests/bootstrap.ts` source file\n */\n const testBootstrapUrl = fileURLToPath(new URL('./tests/bootstrap.ts', this.#cwd))\n const file = this.#project.getSourceFileOrThrow(testBootstrapUrl)\n\n /**\n * Add the import declaration\n */\n const existingImports = file.getImportDeclarations()\n\n importDeclarations.forEach((importDeclaration) => {\n const existingImport = existingImports.find(\n (mod) => mod.getModuleSpecifierValue() === importDeclaration.module\n )\n\n /**\n * Add a new named import to existing import for the\n * same module\n */\n if (existingImport && importDeclaration.isNamed) {\n if (\n !existingImport\n .getNamedImports()\n .find((namedImport) => namedImport.getName() === importDeclaration.identifier)\n ) {\n existingImport.addNamedImport(importDeclaration.identifier)\n }\n return\n }\n\n /**\n * Ignore default import when the same module is already imported.\n * The chances are the existing default import and the importDeclaration\n * identifiers are not the same. But we should not modify existing source\n */\n if (existingImport) {\n return\n }\n\n file.addImportDeclaration({\n ...(importDeclaration.isNamed\n ? { namedImports: [importDeclaration.identifier] }\n : { defaultImport: importDeclaration.identifier }),\n moduleSpecifier: importDeclaration.module,\n })\n })\n\n /**\n * Insert the plugin call in the `plugins` array\n */\n const pluginsArray = file\n .getVariableDeclaration('plugins')\n ?.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression)\n\n /**\n * Add plugin call to the plugins array\n */\n if (pluginsArray) {\n if (!pluginsArray.getElements().find((element) => element.getText() === pluginCall)) {\n pluginsArray.addElement(pluginCall)\n }\n }\n\n file.formatText(this.#editorSettings)\n await file.save()\n }\n\n /**\n * Adds a policy to the list of `policies` object configured\n * inside the `app/policies/main.ts` file.\n */\n async addPolicies(policies: BouncerPolicyNode[]) {\n /**\n * Get the `app/policies/main.ts` source file\n */\n const kernelUrl = fileURLToPath(new URL('./app/policies/main.ts', this.#cwd))\n const file = this.#project.getSourceFileOrThrow(kernelUrl)\n\n /**\n * Process each middleware entry\n */\n for (const policy of policies) {\n this.#addToPoliciesList(file, policy)\n }\n\n file.formatText(this.#editorSettings)\n await file.save()\n }\n}\n","/*\n * @adonisjs/assembler\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { fileURLToPath } from 'node:url'\nimport type { AppEnvironments } from '@adonisjs/application/types'\nimport {\n Node,\n Project,\n SourceFile,\n SyntaxKind,\n CallExpression,\n PropertyAssignment,\n FormatCodeSettings,\n ArrayLiteralExpression,\n} from 'ts-morph'\n\n/**\n * RcFileTransformer is used to transform the `adonisrc.ts` file\n * for adding new commands, providers, meta files etc\n */\nexport class RcFileTransformer {\n #cwd: URL\n #project: Project\n\n /**\n * Settings to use when persisting files\n */\n #editorSettings: FormatCodeSettings = {\n indentSize: 2,\n convertTabsToSpaces: true,\n trimTrailingWhitespace: true,\n ensureNewLineAtEndOfFile: true,\n indentStyle: 2,\n // @ts-expect-error SemicolonPreference doesn't seem to be re-exported from ts-morph\n semicolons: 'remove',\n }\n\n constructor(cwd: URL, project: Project) {\n this.#cwd = cwd\n this.#project = project\n }\n\n /**\n * Get the `adonisrc.ts` source file\n */\n #getRcFileOrThrow() {\n const kernelUrl = fileURLToPath(new URL('./adonisrc.ts', this.#cwd))\n return this.#project.getSourceFileOrThrow(kernelUrl)\n }\n\n /**\n * Check if environments array has a subset of available environments\n */\n #isInSpecificEnvironment(environments?: AppEnvironments[]): boolean {\n if (!environments) {\n return false\n }\n\n return !!(['web', 'console', 'test', 'repl'] as const).find(\n (env) => !environments.includes(env)\n )\n }\n\n /**\n * Locate the `defineConfig` call inside the `adonisrc.ts` file\n */\n #locateDefineConfigCallOrThrow(file: SourceFile) {\n const call = file\n .getDescendantsOfKind(SyntaxKind.CallExpression)\n .find((statement) => statement.getExpression().getText() === 'defineConfig')\n\n if (!call) {\n throw new Error('Could not locate the defineConfig call.')\n }\n\n return call\n }\n\n /**\n * Return the ObjectLiteralExpression of the defineConfig call\n */\n #getDefineConfigObjectOrThrow(defineConfigCall: CallExpression) {\n const configObject = defineConfigCall\n .getArguments()[0]\n .asKindOrThrow(SyntaxKind.ObjectLiteralExpression)\n\n return configObject\n }\n\n /**\n * Check if the defineConfig() call has the property assignment\n * inside it or not. If not, it will create one and return it.\n */\n #getPropertyAssignmentInDefineConfigCall(propertyName: string, initializer: string) {\n const file = this.#getRcFileOrThrow()\n const defineConfigCall = this.#locateDefineConfigCallOrThrow(file)\n const configObject = this.#getDefineConfigObjectOrThrow(defineConfigCall)\n\n let property = configObject.getProperty(propertyName)\n\n if (!property) {\n configObject.addPropertyAssignment({ name: propertyName, initializer })\n property = configObject.getProperty(propertyName)\n }\n\n return property as PropertyAssignment\n }\n\n /**\n * Extract list of imported modules from an ArrayLiteralExpression\n *\n * It assumes that the array can have two types of elements:\n *\n * - Simple lazy imported modules: [() => import('path/to/file')]\n * - Or an object entry: [{ file: () => import('path/to/file'), environment: ['web', 'console'] }]\n * where the `file` property is a lazy imported module.\n */\n #extractModulesFromArray(array: ArrayLiteralExpression) {\n const modules = array.getElements().map((element) => {\n /**\n * Simple lazy imported module\n */\n if (Node.isArrowFunction(element)) {\n const importExp = element.getFirstDescendantByKindOrThrow(SyntaxKind.CallExpression)\n const literal = importExp.getFirstDescendantByKindOrThrow(SyntaxKind.StringLiteral)\n return literal.getLiteralValue()\n }\n\n /**\n * Object entry\n */\n if (Node.isObjectLiteralExpression(element)) {\n const fileProp = element.getPropertyOrThrow('file') as PropertyAssignment\n const arrowFn = fileProp.getFirstDescendantByKindOrThrow(SyntaxKind.ArrowFunction)\n const importExp = arrowFn.getFirstDescendantByKindOrThrow(SyntaxKind.CallExpression)\n const literal = importExp.getFirstDescendantByKindOrThrow(SyntaxKind.StringLiteral)\n return literal.getLiteralValue()\n }\n })\n\n return modules.filter(Boolean) as string[]\n }\n\n /**\n * Extract a specific property from an ArrayLiteralExpression\n * that contains object entries.\n *\n * This function is mainly used for extractring the `pattern` property\n * when adding a new meta files entry, or the `name` property when\n * adding a new test suite.\n */\n #extractPropertyFromArray(array: ArrayLiteralExpression, propertyName: string) {\n const property = array.getElements().map((el) => {\n if (!Node.isObjectLiteralExpression(el)) return\n\n const nameProp = el.getPropertyOrThrow(propertyName)\n if (!Node.isPropertyAssignment(nameProp)) return\n\n const name = nameProp.getInitializerIfKindOrThrow(SyntaxKind.StringLiteral)\n return name.getLiteralValue()\n })\n\n return property.filter(Boolean) as string[]\n }\n\n /**\n * Build a new module entry for the preloads and providers array\n * based upon the environments specified\n */\n #buildNewModuleEntry(modulePath: string, environments?: AppEnvironments[]) {\n if (!this.#isInSpecificEnvironment(environments)) {\n return `() => import('${modulePath}')`\n }\n\n return `{\n file: () => import('${modulePath}'),\n environment: [${environments?.map((env) => `'${env}'`).join(', ')}],\n }`\n }\n\n /**\n * Add a new command to the rcFile\n */\n addCommand(commandPath: string) {\n const commandsProperty = this.#getPropertyAssignmentInDefineConfigCall('commands', '[]')\n const commandsArray = commandsProperty.getInitializerIfKindOrThrow(\n SyntaxKind.ArrayLiteralExpression\n )\n\n const commandString = `() => import('${commandPath}')`\n\n /**\n * If the command already exists, do nothing\n */\n if (commandsArray.getElements().some((el) => el.getText() === commandString)) {\n return this\n }\n\n /**\n * Add the command to the array\n */\n commandsArray.addElement(commandString)\n return this\n }\n\n /**\n * Add a new preloaded file to the rcFile\n */\n addPreloadFile(modulePath: string, environments?: AppEnvironments[]) {\n const preloadsProperty = this.#getPropertyAssignmentInDefineConfigCall('preloads', '[]')\n const preloadsArray = preloadsProperty.getInitializerIfKindOrThrow(\n SyntaxKind.ArrayLiteralExpression\n )\n\n /**\n * Check for duplicates\n */\n const existingPreloadedFiles = this.#extractModulesFromArray(preloadsArray)\n const isDuplicate = existingPreloadedFiles.includes(modulePath)\n if (isDuplicate) {\n return this\n }\n\n /**\n * Add the preloaded file to the array\n */\n preloadsArray.addElement(this.#buildNewModuleEntry(modulePath, environments))\n return this\n }\n\n /**\n * Add a new provider to the rcFile\n */\n addProvider(providerPath: string, environments?: AppEnvironments[]) {\n const property = this.#getPropertyAssignmentInDefineConfigCall('providers', '[]')\n const providersArray = property.getInitializerIfKindOrThrow(SyntaxKind.ArrayLiteralExpression)\n\n /**\n * Check for duplicates\n */\n const existingProviderPaths = this.#extractModulesFromArray(providersArray)\n const isDuplicate = existingProviderPaths.includes(providerPath)\n if (isDuplicate) {\n return this\n }\n\n /**\n * Add the provider to the array\n */\n providersArray.addElement(this.#buildNewModuleEntry(providerPath, environments))\n\n return this\n }\n\n /**\n * Add a new meta file to the rcFile\n */\n addMetaFile(globPattern: string, reloadServer = false) {\n const property = this.#getPropertyAssignmentInDefineConfigCall('metaFiles', '[]')\n const metaFilesArray = property.getInitializerIfKindOrThrow(SyntaxKind.ArrayLiteralExpression)\n\n /**\n * Check for duplicates\n */\n const alreadyDefinedPatterns = this.#extractPropertyFromArray(metaFilesArray, 'pattern')\n if (alreadyDefinedPatterns.includes(globPattern)) {\n return this\n }\n\n /**\n * Add the meta file to the array\n */\n metaFilesArray.addElement(\n `{\n pattern: '${globPattern}',\n reloadServer: ${reloadServer},\n }`\n )\n\n return this\n }\n\n /**\n * Set directory name and path\n */\n setDirectory(key: string, value: string) {\n const property = this.#getPropertyAssignmentInDefineConfigCall('directories', '{}')\n const directories = property.getInitializerIfKindOrThrow(SyntaxKind.ObjectLiteralExpression)\n directories.addPropertyAssignment({ name: key, initializer: `'${value}'` })\n\n return this\n }\n\n /**\n * Set command alias\n */\n setCommandAlias(alias: string, command: string) {\n const aliasProperty = this.#getPropertyAssignmentInDefineConfigCall('commandsAliases', '{}')\n const aliases = aliasProperty.getInitializerIfKindOrThrow(SyntaxKind.ObjectLiteralExpression)\n aliases.addPropertyAssignment({ name: alias, initializer: `'${command}'` })\n\n return this\n }\n\n /**\n * Add a new test suite to the rcFile\n */\n addSuite(suiteName: string, files: string | string[], timeout?: number) {\n const testProperty = this.#getPropertyAssignmentInDefineConfigCall(\n 'tests',\n `{ suites: [], forceExit: true, timeout: 2000 }`\n )\n\n const property = testProperty\n .getInitializerIfKindOrThrow(SyntaxKind.ObjectLiteralExpression)\n .getPropertyOrThrow('suites') as PropertyAssignment\n\n const suitesArray = property.getInitializerIfKindOrThrow(SyntaxKind.ArrayLiteralExpression)\n\n /**\n * Check for duplicates\n */\n const existingSuitesNames = this.#extractPropertyFromArray(suitesArray, 'name')\n if (existingSuitesNames.includes(suiteName)) {\n return this\n }\n\n /**\n * Add the suite to the array\n */\n const filesArray = Array.isArray(files) ? files : [files]\n suitesArray.addElement(\n `{\n name: '${suiteName}',\n files: [${filesArray.map((file) => `'${file}'`).join(', ')}],\n timeout: ${timeout ?? 2000},\n }`\n )\n\n return this\n }\n\n /**\n * Save the adonisrc.ts file\n */\n save() {\n const file = this.#getRcFileOrThrow()\n file.formatText(this.#editorSettings)\n return file.save()\n }\n}\n"],"mappings":"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","names":["fileURLToPath","Node","Project","SyntaxKind","Project","fileURLToPath","SyntaxKind","Node"]}
@@ -196,6 +196,19 @@ export type MiddlewareNode = {
196
196
  */
197
197
  position?: 'before' | 'after';
198
198
  };
199
+ /**
200
+ * Policy node to be added to the list of policies.
201
+ */
202
+ export type BouncerPolicyNode = {
203
+ /**
204
+ * Policy name
205
+ */
206
+ name: string;
207
+ /**
208
+ * Policy import path
209
+ */
210
+ path: string;
211
+ };
199
212
  /**
200
213
  * Defines the structure of an environment variable validation
201
214
  * definition
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@adonisjs/assembler",
3
3
  "description": "Provides utilities to run AdonisJS development server and build project for production",
4
- "version": "7.0.0-0",
4
+ "version": "7.0.0",
5
5
  "engines": {
6
6
  "node": ">=18.16.0"
7
7
  },
@@ -34,21 +34,21 @@
34
34
  "quick:test": "cross-env NODE_DEBUG=adonisjs:assembler node --enable-source-maps --loader=ts-node/esm bin/test.ts"
35
35
  },
36
36
  "devDependencies": {
37
- "@adonisjs/application": "^8.0.0-3",
38
- "@adonisjs/eslint-config": "^1.2.0",
39
- "@adonisjs/prettier-config": "^1.2.0",
40
- "@adonisjs/tsconfig": "^1.2.0",
41
- "@commitlint/cli": "^18.4.3",
42
- "@commitlint/config-conventional": "^18.4.3",
37
+ "@adonisjs/application": "^8.0.0",
38
+ "@adonisjs/eslint-config": "^1.2.1",
39
+ "@adonisjs/prettier-config": "^1.2.1",
40
+ "@adonisjs/tsconfig": "^1.2.1",
41
+ "@commitlint/cli": "^18.4.4",
42
+ "@commitlint/config-conventional": "^18.4.4",
43
43
  "@japa/assert": "^2.1.0",
44
44
  "@japa/file-system": "^2.1.0",
45
45
  "@japa/runner": "^3.1.1",
46
46
  "@japa/snapshot": "^2.0.4",
47
- "@swc/core": "^1.3.101",
48
- "@types/node": "^20.10.5",
47
+ "@swc/core": "^1.3.102",
48
+ "@types/node": "^20.10.7",
49
49
  "@types/picomatch": "^2.3.3",
50
50
  "@types/pretty-hrtime": "^1.0.3",
51
- "c8": "^8.0.1",
51
+ "c8": "^9.0.0",
52
52
  "cross-env": "^7.0.3",
53
53
  "dedent": "^1.5.1",
54
54
  "del-cli": "^5.0.0",
@@ -63,10 +63,10 @@
63
63
  "typescript": "^5.3.3"
64
64
  },
65
65
  "dependencies": {
66
- "@adonisjs/env": "^4.2.0-7",
66
+ "@adonisjs/env": "^5.0.0",
67
67
  "@antfu/install-pkg": "^0.3.1",
68
68
  "@poppinss/chokidar-ts": "^4.1.3",
69
- "@poppinss/cliui": "^6.2.3",
69
+ "@poppinss/cliui": "^6.3.0",
70
70
  "cpy": "^11.0.0",
71
71
  "execa": "^8.0.1",
72
72
  "fast-glob": "^3.3.2",
@@ -106,11 +106,11 @@
106
106
  },
107
107
  "publishConfig": {
108
108
  "access": "public",
109
- "tag": "next"
109
+ "tag": "latest"
110
110
  },
111
111
  "np": {
112
112
  "message": "chore(release): %s",
113
- "tag": "next",
113
+ "tag": "latest",
114
114
  "branch": "main",
115
115
  "anyBranch": false
116
116
  },
@@ -133,6 +133,7 @@
133
133
  "tsup": {
134
134
  "entry": [
135
135
  "./index.ts",
136
+ "./src/types.ts",
136
137
  "./src/code_transformer/main.ts"
137
138
  ],
138
139
  "outDir": "./build",