[
  {
    "path": ".editorconfig",
    "content": "# http://editorconfig.org\n\n[*]\nindent_style = space\nindent_size = 2\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[*.json]\ninsert_final_newline = ignore\n\n[**.min.js]\nindent_style = ignore\ninsert_final_newline = ignore\n\n[MakeFile]\nindent_style = space\n\n[*.md]\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": ".github/workflows/checks.yml",
    "content": "name: checks\non:\n  - push\n  - pull_request\n  - workflow_call\njobs:\n  test:\n    uses: adonisjs/core/.github/workflows/test.yml@7.x\n    with:\n      install-pnpm: true\n\n  lint:\n    uses: adonisjs/.github/.github/workflows/lint.yml@main\n\n  typecheck:\n    uses: adonisjs/.github/.github/workflows/typecheck.yml@main\n"
  },
  {
    "path": ".github/workflows/labels.yml",
    "content": "name: Sync labels\non:\n  workflow_dispatch:\npermissions:\n  issues: write\njobs:\n  labels:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: EndBug/label-sync@v2\n        with:\n          config-file: 'https://raw.githubusercontent.com/thetutlage/static/main/labels.yml'\n          delete-other-labels: true\n          token: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: release\non: workflow_dispatch\npermissions:\n  contents: write\n  id-token: write\njobs:\n  checks:\n    uses: ./.github/workflows/checks.yml\n  release:\n    needs: checks\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n\n      - uses: actions/setup-node@v4\n        with:\n          node-version: 24\n\n      - name: git config\n        run: |\n          git config user.name \"${GITHUB_ACTOR}\"\n          git config user.email \"${GITHUB_ACTOR}@users.noreply.github.com\"\n\n      - name: Init npm config\n        run: npm config set //registry.npmjs.org/:_authToken $NPM_TOKEN\n        env:\n          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n\n      - run: npm install\n\n      - run: npm run release -- --ci\n        env:\n          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/stale.yml",
    "content": "name: 'Close stale issues and PRs'\non:\n  schedule:\n    - cron: '30 0 * * *'\n\njobs:\n  stale:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/stale@v9\n        with:\n          stale-issue-message: 'This issue has been marked as stale because it has been inactive for more than 21 days. Please reopen if you still need help on this issue'\n          stale-pr-message: 'This pull request has been marked as stale because it has been inactive for more than 21 days. Please reopen if you still intend to submit this pull request'\n          close-issue-message: 'This issue has been automatically closed because it has been inactive for more than 4 weeks. Please reopen if you still need help on this issue'\n          close-pr-message: 'This pull request has been automatically closed because it has been inactive for more than 4 weeks. Please reopen if you still intend to submit this pull request'\n          exempt-issue-labels: 'Status: On Hold,Pinned'\n          days-before-stale: 21\n          days-before-close: 5\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "on:\n  workflow_call:\n    inputs:\n      disable-windows:\n        description: Disable running tests on Windows\n        type: boolean\n        default: false\n        required: false\n      install-pnpm:\n        description: Install pnpm before running tests\n        type: boolean\n        default: false\n        required: false\n\njobs:\n  test_linux:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        node-version: ['lts/krypton', 'latest']\n\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: ${{ matrix.node-version }}\n\n      - name: Install pnpm\n        if: ${{ inputs.install-pnpm }}\n        uses: pnpm/action-setup@v4\n        with:\n          version: 10\n\n      - name: Install dependencies\n        run: npm install\n\n      - name: Run tests\n        run: npm test\n\n  test_windows:\n    if: ${{ !inputs.disable-windows }}\n    runs-on: windows-latest\n    strategy:\n      matrix:\n        node-version: ['lts/krypton', 'latest']\n\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: ${{ matrix.node-version }}\n\n      - name: Install pnpm\n        if: ${{ inputs.install-pnpm }}\n        uses: pnpm/action-setup@v4\n        with:\n          version: 10\n\n      - name: Install dependencies\n        run: npm install\n\n      - name: Run tests\n        run: npm test\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\ncoverage\n.DS_STORE\n.nyc_output\n.idea\n.vscode/\n*.sublime-project\n*.sublime-workspace\n*.log\nbuild\ndist\nyarn.lock\nshrinkwrap.yaml\npackage-lock.json\ntest/__app\n.env\nbackup\n"
  },
  {
    "path": ".npmrc",
    "content": "package-lock=false\n"
  },
  {
    "path": ".prettierignore",
    "content": "build\ndocs\ncoverage\n"
  },
  {
    "path": "LICENSE.md",
    "content": "# The MIT License\n\nCopyright 2022 Harminder Virk, contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# @adonisjs/core\n\n**Featured sponsors**\n\n<table>\n\n<tr>\n<td>\n\n<a href=\"https://route4me.com/?utm_source=adonisjs.com\">\n  <img src=\"https://raw.githubusercontent.com/thetutlage/static/refs/heads/main/featured_sponsors/logos/route4me.jpg\" />\n</a>\n\n</td>\n\n<td>\n\n<a href=\"https://ezycourse.com/?utm_source=adonisjs.com\">\n  <img src=\"https://raw.githubusercontent.com/thetutlage/static/refs/heads/main/featured_sponsors/logos/ezycourse.jpg\" />\n</a>\n\n</td>\n\n</tr>\n\n<tr>\n\n<td>\n\n<a href=\"https://meteor.software/g6h?utm_source=adonisjs.com\">\n  <img src=\"https://raw.githubusercontent.com/thetutlage/static/refs/heads/main/featured_sponsors/logos/galaxy.jpg\" />\n</a>\n\n</td>\n\n<td>\n\n<a href=\"https://www.testmuai.com/?utm_source=adonisjs.com\">\n  <img src=\"https://raw.githubusercontent.com/thetutlage/static/refs/heads/main/featured_sponsors/logos/testmu.jpg\" />\n</a>\n\n</td>\n\n</tr>\n\n<tr>\n\n<td>\n\n<a href=\"https://relancer.com/?utm_source=adonisjs.com\">\n  <img src=\"https://raw.githubusercontent.com/thetutlage/static/refs/heads/main/featured_sponsors/logos/relancer.jpg\" />\n</a>\n\n</td>\n\n<td>\n\n</td>\n\n</tr>\n\n</table>\n\n![](https://github.com/thetutlage/static/blob/main/sponsorkit/sponsors.png?raw=true)\n\n<hr>\n<br />\n\n<div align=\"center\">\n  <h3>Fullstack MVC framework for Node.js</h3>\n  <p>AdonisJs is a fullstack Web framework with focus on <strong> ergonomics and speed </strong>. It takes care of much of the Web development hassles, offering you a clean and stable API to build Web apps and micro services.</p>\n</div>\n\n<br />\n\n<div align=\"center\">\n\n[![gh-workflow-image]][gh-workflow-url] [![npm-image]][npm-url] ![][typescript-image] [![license-image]][license-url]\n\n</div>\n\n<div align=\"center\">\n  <h3>\n    <a href=\"https://adonisjs.com\">\n      Website\n    </a>\n    <span> | </span>\n    <a href=\"https://docs.adonisjs.com\">\n      Guides\n    </a>\n    <span> | </span>\n    <a href=\"https://github.com/adonisjs/.github/blob/main/docs/CONTRIBUTING.md\">\n      Contributing\n    </a>\n  </h3>\n</div>\n\n<div align=\"center\">\n  <sub>Built with ❤︎ by <a href=\"https://github.com/thetutlage\">Harminder Virk</a>\n</div>\n\n[gh-workflow-image]: https://img.shields.io/github/actions/workflow/status/adonisjs/core/checks.yml?label=Tests&style=for-the-badge\n[gh-workflow-url]: https://github.com/adonisjs/core/actions/workflows/checks.yml 'Github action'\n[npm-image]: https://img.shields.io/npm/v/@adonisjs/core/latest.svg?style=for-the-badge&logo=npm\n[npm-url]: https://www.npmjs.com/package/@adonisjs/core/v/latest 'npm'\n[typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript\n[license-url]: LICENSE.md\n[license-image]: https://img.shields.io/github/license/adonisjs/adonis-framework?style=for-the-badge\n"
  },
  {
    "path": "bin/test.ts",
    "content": "import { assert } from '@japa/assert'\nimport { snapshot } from '@japa/snapshot'\nimport { fileSystem } from '@japa/file-system'\nimport { expectTypeOf } from '@japa/expect-type'\nimport { processCLIArgs, configure, run } from '@japa/runner'\n\n/*\n|--------------------------------------------------------------------------\n| Configure tests\n|--------------------------------------------------------------------------\n|\n| The configure method accepts the configuration to configure the Japa\n| tests runner.\n|\n| The first method call \"processCLIArgs\" process the command line arguments\n| and turns them into a config object. Using this method is not mandatory.\n|\n| Please consult japa.dev/runner-config for the config docs.\n*/\nprocessCLIArgs(process.argv.slice(2))\nconfigure({\n  files: ['tests/**/*.spec.ts'],\n  plugins: [assert(), expectTypeOf(), fileSystem(), snapshot()],\n})\n\n/*\n|--------------------------------------------------------------------------\n| Run tests\n|--------------------------------------------------------------------------\n|\n| The following \"run\" method is required to execute all the tests.\n|\n*/\nrun()\n"
  },
  {
    "path": "commands/add.ts",
    "content": "/*\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 { prettyPrintError } from '../index.ts'\nimport { type CommandOptions } from '../types/ace.ts'\nimport { args, BaseCommand, flags } from '../modules/ace/main.ts'\nimport { type SupportedPackageManager } from '@adonisjs/assembler/types'\n\n/**\n * The install command is used to `npm install` and `node ace configure` one or more packages\n * in one go.\n *\n * @example\n * ```\n * ace add @adonisjs/lucid\n * ace add @adonisjs/lucid @adonisjs/auth @adonisjs/session\n * ace add @adonisjs/session --dev\n * ace add vinejs --force\n * ace add edge --package-manager=pnpm\n * ```\n */\nexport default class Add extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'add'\n  /**\n   * The command description\n   */\n  static description =\n    'Install and configure one or more AdonisJS packages. Runs npm install followed by the package configure hook'\n\n  static help = [\n    'Use this command instead of manually running npm install + configure separately.',\n    'Accepts shorthand names: \"vinejs\" for @vinejs/vine, \"edge\" for edge.js.',\n    '```',\n    '{{ binaryName }} add @adonisjs/lucid',\n    '{{ binaryName }} add @adonisjs/auth @adonisjs/session',\n    '```',\n  ]\n  /**\n   * Command options configuration\n   */\n  static options: CommandOptions = {\n    allowUnknownFlags: true,\n  }\n\n  /**\n   * Package names to install and configure\n   */\n  @args.spread({ description: 'Package names to install and configure', required: true })\n  declare names: string[]\n\n  /**\n   * Display logs in verbose mode\n   */\n  @flags.boolean({ description: 'Display logs in verbose mode' })\n  declare verbose?: boolean\n\n  /**\n   * Define the package manager you want to use\n   */\n  @flags.string({ description: 'Define the package manager you want to use' })\n  declare packageManager?: SupportedPackageManager\n\n  /**\n   * Should we install the package as a dev dependency\n   */\n  @flags.boolean({ description: 'Should we install the package as a dev dependency', alias: 'D' })\n  declare dev?: boolean\n\n  /**\n   * Forcefully overwrite existing files\n   */\n  @flags.boolean({ description: 'Forcefully overwrite existing files' })\n  declare force?: boolean\n\n  /**\n   * Resolve the npm package name from the user-provided name\n   */\n  #resolveNpmPackageName(name: string): string {\n    if (name === 'vinejs') {\n      return '@vinejs/vine'\n    }\n    if (name === 'edge') {\n      return 'edge.js'\n    }\n\n    return name\n  }\n\n  /**\n   * Configure the package by delegating the work to the `node ace configure` command\n   */\n  async #configurePackage(packageName: string) {\n    const flagValueArray = this.parsed.unknownFlags\n      .filter((flag) => !!this.parsed.flags[flag])\n      .map((flag) => [`--${flag}`, this.parsed.flags[flag].toString()])\n\n    const configureArgs = [\n      packageName,\n      this.force ? '--force' : undefined,\n      this.verbose ? '--verbose' : undefined,\n      ...flagValueArray.flat(),\n    ].filter(Boolean) as string[]\n\n    return await this.kernel.exec('configure', configureArgs)\n  }\n\n  /**\n   * Run method is invoked by ace automatically\n   */\n  async run() {\n    const packages = this.names.map((name) => ({\n      name,\n      npmName: this.#resolveNpmPackageName(name),\n    }))\n\n    /**\n     * Install all packages\n     */\n    const codemods = await this.createCodemods()\n    codemods.verboseInstallOutput = !!this.verbose\n\n    const packagesWereInstalled = await codemods.installPackages(\n      packages.map((pkg) => ({ name: pkg.npmName, isDevDependency: !!this.dev })),\n      this.packageManager\n    )\n    if (!packagesWereInstalled) {\n      return\n    }\n\n    /**\n     * Configure each package sequentially\n     */\n    const succeeded: string[] = []\n    const failed: { name: string; error?: Error }[] = []\n\n    for (const pkg of packages) {\n      const { exitCode, error } = await this.#configurePackage(pkg.name)\n      if (exitCode === 0) {\n        succeeded.push(pkg.name)\n      } else {\n        failed.push({ name: pkg.name, error })\n      }\n    }\n\n    /**\n     * Report results\n     */\n    if (succeeded.length > 0) {\n      const names = succeeded.map((name) => this.colors.green(name)).join(', ')\n      this.logger.success(`Installed and configured ${names}`)\n    }\n\n    if (failed.length > 0) {\n      this.exitCode = 1\n      for (const pkg of failed) {\n        this.logger.error(`Unable to configure ${this.colors.green(pkg.name)}`)\n        if (pkg.error) {\n          await prettyPrintError(pkg.error.cause || pkg.error)\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "commands/build.ts",
    "content": "/*\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 { BaseCommand, flags } from '../modules/ace/main.ts'\nimport { importAssembler, importTypeScript } from '../src/utils.ts'\n\n/**\n * Create the production build by compiling TypeScript source and the\n * frontend assets\n *\n * @example\n * ```\n * ace build\n * ace build --ignore-ts-errors\n * ace build --package-manager=pnpm\n * ```\n */\nexport default class Build extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'build'\n  /**\n   * The command description\n   */\n  static description =\n    'Build application for production by compiling frontend assets and TypeScript source to JavaScript'\n\n  /**\n   * Help text for the command\n   */\n  static help = [\n    'Create the production build using the following command.',\n    '```',\n    '{{ binaryName }} build',\n    '```',\n    '',\n    'The assets bundler dev server runs automatically after detecting vite config or webpack config files',\n    'You may pass vite CLI args using the --assets-args command line flag.',\n    '```',\n    '{{ binaryName }} build --assets-args=\"--debug --base=/public\"',\n    '```',\n  ]\n\n  /**\n   * Ignore TypeScript errors and continue with the build process\n   */\n  @flags.boolean({ description: 'Ignore TypeScript errors and continue with the build process' })\n  declare ignoreTsErrors?: boolean\n\n  /**\n   * Define the package manager to copy the appropriate lock file\n   */\n  @flags.string({\n    description: 'Define the package manager to copy the appropriate lock file',\n  })\n  declare packageManager?: 'npm' | 'pnpm' | 'yarn' | 'yarn@berry' | 'bun'\n\n  /**\n   * Log a development dependency is missing\n   *\n   * @param dependency - The name of the missing dependency\n   */\n  #logMissingDevelopmentDependency(dependency: string) {\n    this.logger.error(\n      [\n        `Cannot find package \"${dependency}\"`,\n        '',\n        `The \"${dependency}\" package is a development dependency and therefore you should use the build command with development dependencies installed.`,\n        '',\n        'If you are using the build command inside a CI or with a deployment platform, make sure the NODE_ENV is set to \"development\"',\n      ].join('\\n')\n    )\n  }\n\n  /**\n   * Build application\n   */\n  async run() {\n    const assembler = await importAssembler(this.app)\n    if (!assembler) {\n      this.#logMissingDevelopmentDependency('@adonisjs/assembler')\n      this.exitCode = 1\n      return\n    }\n\n    const ts = await importTypeScript(this.app)\n    if (!ts) {\n      this.#logMissingDevelopmentDependency('typescript')\n      this.exitCode = 1\n      return\n    }\n\n    const bundler = new assembler.Bundler(this.app.appRoot, ts, {\n      metaFiles: this.app.rcFile.metaFiles,\n      hooks: this.app.rcFile.hooks,\n    })\n\n    /**\n     * Share command logger with assembler, so that CLI flags like --no-ansi has\n     * similar impact for assembler logs as well.\n     */\n    bundler.ui.logger = this.logger\n\n    /**\n     * Bundle project for production\n     */\n    const stopOnError = this.ignoreTsErrors === true ? false : true\n    const builtSuccessfully = await bundler.bundle(stopOnError, this.packageManager)\n    if (!builtSuccessfully) {\n      this.exitCode = 1\n    }\n  }\n}\n"
  },
  {
    "path": "commands/configure.ts",
    "content": "/*\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 { RuntimeException } from '@poppinss/utils/exception'\n\nimport { stubsRoot } from '../stubs/main.ts'\nimport type { CommandOptions } from '../types/ace.ts'\nimport { args, BaseCommand, flags } from '../modules/ace/main.ts'\n\n/**\n * Command to configure packages after installation by running their configuration hooks.\n * Supports built-in configurations for VineJS, Edge, and health checks, or can execute\n * custom configure functions exported by packages.\n *\n * @example\n * ```\n * ace configure @adonisjs/lucid\n * ace configure vinejs\n * ace configure edge\n * ace configure health_checks\n * ace configure @adonisjs/auth --force --verbose\n * ```\n */\nexport default class Configure extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'configure'\n\n  /**\n   * The command description\n   */\n  static description =\n    'Run the configure hook of an already-installed package. Use \"add\" command instead to both install and configure in one step'\n\n  /**\n   * Command options configuration.\n   * Allows unknown flags to be passed to package configure functions.\n   */\n  static options: CommandOptions = {\n    allowUnknownFlags: true,\n  }\n\n  /**\n   * Expose all flags from the protected property \"parsed\" for access by package configure functions\n   */\n  get parsedFlags() {\n    return this.parsed.flags\n  }\n\n  /**\n   * Expose all arguments from the protected property \"parsed\" for access by package configure functions\n   */\n  get parsedArgs() {\n    return this.parsed._\n  }\n\n  /**\n   * Name of the package to configure\n   */\n  @args.string({ description: 'Package name' })\n  declare name: string\n\n  /**\n   * Enable verbose logging during package installation and configuration\n   */\n  @flags.boolean({ description: 'Display logs in verbose mode', alias: 'v' })\n  declare verbose?: boolean\n\n  /**\n   * Forcefully overwrite existing files during configuration\n   */\n  @flags.boolean({ description: 'Forcefully overwrite existing files', alias: 'f' })\n  declare force?: boolean\n\n  /**\n   * The root directory path of the package's stubs.\n   * Set automatically when the package exports a stubsRoot property.\n   */\n  declare stubsRoot: string\n\n  /**\n   * Import and return the main exports of a package.\n   * Returns null if the package is not found, rethrows other errors.\n   *\n   * @param packageName - The name of the package to import\n   * @returns The package exports or null if not found\n   */\n  async #getPackageSource(packageName: string) {\n    try {\n      const packageExports = await this.app.import(packageName)\n      return packageExports\n    } catch (error) {\n      if (\n        (error.code && error.code === 'ERR_MODULE_NOT_FOUND') ||\n        error.message.startsWith('Cannot find module')\n      ) {\n        return null\n      }\n      throw error\n    }\n  }\n\n  /**\n   * Configure VineJS validation library by registering its provider in the RC file\n   */\n  async #configureVineJS() {\n    const codemods = await this.createCodemods()\n    await codemods.updateRcFile((rcFile) => {\n      rcFile.addProvider('@adonisjs/core/providers/vinejs_provider')\n    })\n  }\n\n  /**\n   * Configure Edge template engine by registering its provider and adding view meta files\n   */\n  async #configureEdge() {\n    const codemods = await this.createCodemods()\n    await codemods.updateRcFile((rcFile) => {\n      rcFile.addProvider('@adonisjs/core/providers/edge_provider')\n      rcFile.addMetaFile('resources/views/**/*.edge', false)\n    })\n  }\n\n  /**\n   * Configure health checks feature by generating the main health file and controller\n   */\n  async #configureHealthChecks() {\n    const codemods = await this.createCodemods()\n    await codemods.makeUsingStub(stubsRoot, 'make/health/main.stub', {\n      flags: this.parsed.flags,\n      entity: this.app.generators.createEntity('health'),\n    })\n    await codemods.makeUsingStub(stubsRoot, 'make/health/controller.stub', {\n      flags: this.parsed.flags,\n      entity: this.app.generators.createEntity('health_checks'),\n    })\n  }\n\n  /**\n   * Create a codemods instance configured with command options.\n   * Sets overwrite and verbose flags based on command arguments.\n   */\n  async createCodemods() {\n    const codemods = await super.createCodemods()\n    codemods.overwriteExisting = this.force === true\n    codemods.verboseInstallOutput = this.verbose === true\n    return codemods\n  }\n\n  /**\n   * Execute the configure command. Handles built-in configurations for VineJS, Edge,\n   * and health checks, or imports and executes the configure function from the specified package.\n   */\n  async run() {\n    if (this.name === 'vinejs') {\n      return this.#configureVineJS()\n    }\n    if (this.name === 'edge') {\n      return this.#configureEdge()\n    }\n    if (this.name === 'health_checks') {\n      return this.#configureHealthChecks()\n    }\n\n    const packageExports = await this.#getPackageSource(this.name)\n    if (!packageExports) {\n      this.logger.error(`Cannot find module \"${this.name}\". Make sure to install it`)\n      this.exitCode = 1\n      return\n    }\n\n    /**\n     * Warn, there are not instructions to run\n     */\n    if (!packageExports.configure) {\n      this.logger.warning(\n        `Cannot configure module \"${this.name}\". The module does not export the configure hook`\n      )\n      return\n    }\n\n    /**\n     * Set stubsRoot property when package exports it\n     */\n    if (packageExports.stubsRoot) {\n      this.stubsRoot = packageExports.stubsRoot\n    }\n\n    /**\n     * Run instructions\n     */\n    try {\n      await packageExports.configure(this)\n    } catch (error) {\n      throw new RuntimeException(`Unable to configure package \"${this.name}\"`, {\n        cause: error,\n      })\n    }\n  }\n}\n"
  },
  {
    "path": "commands/eject.ts",
    "content": "/*\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 { args, BaseCommand, flags } from '../modules/ace/main.ts'\nimport stringHelpers from '../src/helpers/string.ts'\n\n/**\n * Command to eject scaffolding stubs from packages to your application root.\n * This allows you to customize templates used by make commands and other\n * code generation features by copying them to your local application.\n *\n * @example\n * ```\n * ace eject make/controller\n * ace eject make/controller --pkg=@adonisjs/lucid\n * ace eject stubs/\n * ```\n */\nexport default class Eject extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'eject'\n\n  /**\n   * The command description\n   */\n  static description =\n    'Copy scaffolding stubs from a package to your application for customization. Stubs are templates used by make:* commands'\n\n  /**\n   * Path to the stubs directory or a single stub file to eject\n   */\n  @args.string({ description: 'Path to the stubs directory or a single stub file' })\n  declare stubPath: string\n\n  /**\n   * Package name to search for stubs. Defaults to @adonisjs/core\n   */\n  @flags.string({\n    description: 'Mention package name for searching stubs',\n    default: '@adonisjs/core',\n  })\n  declare pkg: string\n\n  /**\n   * Execute the command to eject stubs from the specified package.\n   * Copies the stubs to the application root and logs success messages\n   * for each ejected file.\n   */\n  async run() {\n    const stubs = await this.app.stubs.create()\n    const copied = await stubs.copy(this.stubPath, {\n      pkg: this.pkg,\n    })\n\n    copied.forEach((stubPath) => {\n      this.logger.success(`eject ${stringHelpers.toUnixSlash(this.app.relativePath(stubPath))}`)\n    })\n  }\n}\n"
  },
  {
    "path": "commands/env/add.ts",
    "content": "/*\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 CommandOptions } from '../../types/ace.ts'\nimport stringHelpers from '../../src/helpers/string.ts'\nimport { args, BaseCommand, flags } from '../../modules/ace/main.ts'\n\nconst ALLOWED_TYPES = ['string', 'boolean', 'number', 'enum'] as const\ntype AllowedTypes = (typeof ALLOWED_TYPES)[number]\n\n/**\n * Command to add a new environment variable to the application.\n * Updates .env, .env.example, and start/env.ts files with the new variable,\n * including appropriate validation schema based on the variable type.\n *\n * @example\n * ```\n * ace env:add\n * ace env:add DATABASE_URL postgres://localhost:5432/mydb\n * ace env:add API_KEY secret --type=string\n * ace env:add PORT 3333 --type=number\n * ace env:add DEBUG true --type=boolean\n * ace env:add LOG_LEVEL info --type=enum --enum-values=debug,info,warn,error\n * ```\n */\nexport default class EnvAdd extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'env:add'\n\n  /**\n   * The command description\n   */\n  static description =\n    'Add a new environment variable to .env, .env.example, and its validation rule to start/env.ts'\n\n  /**\n   * Command options configuration.\n   * Allows unknown flags to be passed through.\n   */\n  static options: CommandOptions = {\n    allowUnknownFlags: true,\n  }\n\n  /**\n   * Environment variable name (will be converted to SCREAMING_SNAKE_CASE)\n   */\n  @args.string({\n    description: 'Variable name. Will be converted to screaming snake case',\n    required: false,\n  })\n  declare name: string\n\n  /**\n   * Environment variable value\n   */\n  @args.string({ description: 'Variable value', required: false })\n  declare value: string\n\n  /**\n   * Data type of the environment variable (string, boolean, number, enum)\n   */\n  @flags.string({ description: 'Type of the variable' })\n  declare type: AllowedTypes\n\n  /**\n   * Allowed values for enum type variables\n   */\n  @flags.array({\n    description: 'Allowed values for the enum type in a comma-separated list',\n    default: [''],\n    required: false,\n  })\n  declare enumValues: string[]\n\n  /**\n   * Validate that the provided type is one of the allowed types.\n   *\n   * @returns True if the type is valid, false otherwise\n   */\n  #isTypeFlagValid() {\n    return ALLOWED_TYPES.includes(this.type)\n  }\n\n  /**\n   * Execute the command to add a new environment variable.\n   * Prompts for missing values, validates inputs, and updates all relevant files.\n   */\n  async run() {\n    /**\n     * Prompt for missing name\n     */\n    if (!this.name) {\n      this.name = await this.prompt.ask('Enter the variable name', {\n        validate: (value) => !!value,\n        format: (value) => stringHelpers.snakeCase(value).toUpperCase(),\n      })\n    }\n\n    /**\n     * Prompt for missing value\n     */\n    if (!this.value) {\n      this.value = await this.prompt.ask('Enter the variable value')\n    }\n\n    /**\n     * Prompt for missing type\n     */\n    if (!this.type) {\n      this.type = await this.prompt.choice('Select the variable type', ALLOWED_TYPES)\n    }\n\n    /**\n     * Prompt for missing enum values if the selected env type is `enum`\n     */\n    if (this.type === 'enum' && !this.enumValues) {\n      this.enumValues = await this.prompt.ask('Enter the enum values separated by a comma', {\n        result: (value) => value.split(',').map((one) => one.trim()),\n      })\n    }\n\n    /**\n     * Validate inputs\n     */\n    if (!this.#isTypeFlagValid()) {\n      this.logger.error(`Invalid type \"${this.type}\". Must be one of ${ALLOWED_TYPES.join(', ')}`)\n      return\n    }\n\n    /**\n     * Add the environment variable to the `.env` and `.env.example` files\n     */\n    const codemods = await this.createCodemods()\n    const transformedName = stringHelpers.snakeCase(this.name).toUpperCase()\n    await codemods.defineEnvVariables(\n      { [transformedName]: this.value },\n      { omitFromExample: [transformedName] }\n    )\n\n    /**\n     * Add the environment variable to the `start/env.ts` file\n     */\n    const validation = {\n      string: 'Env.schema.string()',\n      number: 'Env.schema.number()',\n      boolean: 'Env.schema.boolean()',\n      enum: `Env.schema.enum(['${this.enumValues.join(\"','\")}'] as const)`,\n    }[this.type]\n\n    await codemods.defineEnvValidations({ variables: { [transformedName]: validation } })\n\n    this.logger.success('Environment variable added successfully')\n  }\n}\n"
  },
  {
    "path": "commands/generate_key.ts",
    "content": "/*\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 string from '@poppinss/utils/string'\nimport { EnvEditor } from '@adonisjs/env/editor'\nimport { BaseCommand, flags } from '../modules/ace/main.ts'\n\n/**\n * The generate key command is used to generate the app key\n * and write it inside the .env file.\n *\n * @example\n * ```\n * ace generate:key\n * ace generate:key --show\n * ace generate:key --force\n * ```\n */\nexport default class GenerateKey extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'generate:key'\n  /**\n   * The command description\n   */\n  static description =\n    'Generate a cryptographically secure APP_KEY and write it to the .env file. Use --show to print without writing'\n\n  /**\n   * Display the key on the terminal, instead of writing it to .env file\n   */\n  @flags.boolean({\n    description: 'Display the key on the terminal, instead of writing it to .env file',\n  })\n  declare show: boolean\n\n  /**\n   * Force update .env file in production environment\n   */\n  @flags.boolean({\n    description: 'Force update .env file in production environment',\n  })\n  declare force: boolean\n\n  async run() {\n    let writeToFile = process.env.NODE_ENV !== 'production'\n    if (this.force) {\n      writeToFile = true\n    }\n\n    if (this.show) {\n      writeToFile = false\n    }\n\n    const secureKey = string.random(32)\n\n    if (writeToFile) {\n      const editor = await EnvEditor.create(this.app.appRoot)\n      editor.add('APP_KEY', secureKey, true)\n      await editor.save()\n      this.logger.action('add APP_KEY to .env').succeeded()\n    } else {\n      this.logger.log(`APP_KEY = ${secureKey}`)\n    }\n  }\n}\n"
  },
  {
    "path": "commands/inspect_rcfile.ts",
    "content": "/*\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 { BaseCommand } from '../modules/ace/main.ts'\n\n/**\n * Command to inspect and display the AdonisJS RC file contents with default values.\n * The RC file contains configuration for providers, preloads, commands, and other\n * application settings. This command formats and displays the contents in a readable JSON format.\n *\n * @example\n * ```\n * ace inspect:rcfile\n * ```\n */\nexport default class InspectRCFile extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'inspect:rcfile'\n\n  /**\n   * The command description\n   */\n  static description =\n    'Display the resolved adonisrc.ts configuration as JSON, including providers, preloads, commands, and meta files'\n\n  /**\n   * Execute the command to display RC file contents.\n   * Transforms provider, preload, and command entries to display their file paths\n   * as strings and formats the output as readable JSON.\n   */\n  async run() {\n    const { raw, providers, preloads, commands, ...rest } = this.app.rcFile\n    this.logger.log(\n      JSON.stringify(\n        {\n          ...rest,\n          providers: providers.map((provider) => {\n            return {\n              ...provider,\n              file: provider.file.toString(),\n            }\n          }),\n          preloads: preloads.map((preload) => {\n            return {\n              ...preload,\n              file: preload.file.toString(),\n            }\n          }),\n          commands: commands.map((command) => {\n            return command.toString()\n          }),\n        },\n        null,\n        2\n      )\n    )\n  }\n}\n"
  },
  {
    "path": "commands/list/routes.ts",
    "content": "/*\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 { CommandOptions } from '../../types/ace.ts'\nimport { args, BaseCommand, flags } from '../../modules/ace/main.ts'\nimport { RoutesListFormatter } from '../../src/cli_formatters/routes_list.ts'\n\n/**\n * Command to display a list of all registered routes in the application.\n * Supports filtering by keywords, middleware, and output formatting options.\n * Routes can be displayed as a formatted list, table, or JSON.\n *\n * @example\n * ```\n * ace list:routes\n * ace list:routes user\n * ace list:routes --middleware=auth\n * ace list:routes --ignore-middleware=guest\n * ace list:routes --json\n * ace list:routes --table\n * ```\n */\nexport default class ListRoutes extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'list:routes'\n\n  /**\n   * The command description\n   */\n  static description =\n    'List all registered routes with their HTTP methods, URL patterns, handlers, and middleware'\n\n  /**\n   * Command options configuration.\n   * Requires the application to be started so routes are loaded.\n   */\n  static options: CommandOptions = {\n    startApp: true,\n  }\n\n  /**\n   * Keyword to match against route names, patterns, and controller names\n   */\n  @args.string({\n    description:\n      'Find routes matching the given keyword. Route name, pattern and controller name will be searched against the keyword',\n    required: false,\n  })\n  declare match: string\n\n  /**\n   * Filter routes that include all specified middleware names\n   */\n  @flags.array({\n    description:\n      'View routes that includes all the mentioned middleware names. Use * to see routes that are using one or more middleware',\n  })\n  declare middleware: string[]\n\n  /**\n   * Filter routes that do not include all specified middleware names\n   */\n  @flags.array({\n    description:\n      'View routes that does not include all the mentioned middleware names. Use * to see routes that are using zero middleware',\n  })\n  declare ignoreMiddleware: string[]\n\n  /**\n   * Output routes as JSON format\n   */\n  @flags.boolean({ description: 'Get routes list as a JSON string' })\n  declare json: boolean\n\n  /**\n   * Output routes as a CLI table format\n   */\n  @flags.boolean({ description: 'View list of routes as a table' })\n  declare table: boolean\n\n  /**\n   * Output routes as JSONL (one JSON object per line), optimized for\n   * machine consumption by AI agents and CLI tools\n   */\n  @flags.boolean({\n    description: 'Get routes as JSONL, one JSON object per line (optimized for AI agents)',\n  })\n  declare jsonl: boolean\n\n  /**\n   * Execute the command to list application routes.\n   * Creates a formatter with the specified filters and outputs routes\n   * in the requested format (JSON, table, or formatted list).\n   */\n  async run() {\n    const router = await this.app.container.make('router')\n    const formatter = new RoutesListFormatter(\n      router,\n      this.ui,\n      {},\n      {\n        ignoreMiddleware: this.ignoreMiddleware,\n        middleware: this.middleware,\n        match: this.match,\n      }\n    )\n\n    /**\n     * Display as JSONL (one JSON object per line).\n     * Auto-selected when running inside an AI agent and no\n     * explicit format flag is provided.\n     */\n    if (this.jsonl || (!this.json && !this.table && this.app.runningInAIAgent)) {\n      const lines = await formatter.formatAsJSONL()\n      for (const line of lines) {\n        this.logger.log(line)\n      }\n      return\n    }\n\n    /**\n     * Display as JSON\n     */\n    if (this.json) {\n      this.logger.log(JSON.stringify(await formatter.formatAsJSON(), null, 2))\n      return\n    }\n\n    /**\n     * Display as a standard table\n     */\n    if (this.table) {\n      const tables = await formatter.formatAsAnsiTable()\n      tables.forEach((table) => {\n        this.logger.log('')\n        if (table.heading) {\n          this.logger.log(table.heading)\n          this.logger.log('')\n        }\n        table.table.render()\n      })\n      return\n    }\n\n    /**\n     * Display as a list\n     */\n    const list = await formatter.formatAsAnsiList()\n    list.forEach((item) => {\n      this.logger.log('')\n      if (item.heading) {\n        this.logger.log(item.heading)\n        this.logger.log('')\n      }\n      this.logger.log(item.rows.join('\\n'))\n    })\n  }\n}\n"
  },
  {
    "path": "commands/make/command.ts",
    "content": "/*\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 { stubsRoot } from '../../stubs/main.ts'\nimport { args, flags } from '../../modules/ace/main.ts'\nimport { BaseCommand } from '../../modules/ace/main.ts'\n\n/**\n * Command to create a new Ace command class.\n * Ace commands are CLI commands that can be executed via the `ace` binary,\n * allowing you to create custom functionality for your application's command line interface.\n *\n * @example\n * ```\n * ace make:command SendEmails\n * ace make:command ProcessPayments\n * ace make:command GenerateReports\n * ace make:command CleanupFiles\n * ```\n */\nexport default class MakeCommand extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'make:command'\n\n  /**\n   * The command description\n   */\n  static description = 'Create a new Ace CLI command class in commands/'\n\n  /**\n   * Name of the command class to create\n   */\n  @args.string({ description: 'Name of the command' })\n  declare name: string\n\n  /**\n   * Read the contents from this file (if the flag exists) and use\n   * it as the raw contents\n   */\n  @flags.string({ description: 'Use the contents of the given file as the generated output' })\n  declare contentsFrom: string\n\n  /**\n   * The stub template file to use for generating the command class\n   */\n  protected stubPath: string = 'make/command/main.stub'\n\n  /**\n   * Execute the command to create a new Ace command class.\n   * Generates the command file with proper CLI command structure.\n   */\n  async run() {\n    const codemods = await this.createCodemods()\n    await codemods.makeUsingStub(\n      stubsRoot,\n      this.stubPath,\n      {\n        flags: this.parsed.flags,\n        entity: this.app.generators.createEntity(this.name),\n      },\n      {\n        contentsFromFile: this.contentsFrom,\n      }\n    )\n  }\n}\n"
  },
  {
    "path": "commands/make/controller.ts",
    "content": "/*\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 string from '@poppinss/utils/string'\nimport { stubsRoot } from '../../stubs/main.ts'\nimport { args, flags, BaseCommand } from '../../modules/ace/main.ts'\nimport { type CommandOptions } from '../../types/ace.ts'\n\n/**\n * The make controller command to create an HTTP controller\n *\n * @example\n * ```\n * ace make:controller User\n * ace make:controller User store update\n * ace make:controller User --resource\n * ace make:controller User --api\n * ace make:controller User --singular\n * ```\n */\nexport default class MakeController extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'make:controller'\n  /**\n   * The command description\n   */\n  static description =\n    'Create a new HTTP controller class in app/controllers. Use --resource for CRUD methods or --api for API-only CRUD (no create/edit)'\n\n  /**\n   * Command options configuration\n   */\n  static options: CommandOptions = {\n    allowUnknownFlags: true,\n  }\n\n  /**\n   * The name of the controller\n   */\n  @args.string({ description: 'The name of the controller' })\n  declare name: string\n\n  /**\n   * Create controller with custom method names\n   */\n  @args.spread({ description: 'Create controller with custom method names', required: false })\n  declare actions?: string[]\n\n  /**\n   * Generate controller in singular form\n   */\n  @flags.boolean({\n    description: 'Generate controller in singular form',\n    alias: 's',\n  })\n  declare singular: boolean\n\n  /**\n   * Generate resourceful controller with methods to perform CRUD actions on a resource\n   */\n  @flags.boolean({\n    description:\n      'Generate resourceful controller with methods to perform CRUD actions on a resource',\n    alias: 'r',\n  })\n  declare resource: boolean\n\n  /**\n   * Generate resourceful controller without the \"edit\" and the \"create\" methods\n   */\n  @flags.boolean({\n    description: 'Generate resourceful controller without the \"edit\" and the \"create\" methods',\n    alias: 'a',\n  })\n  declare api: boolean\n\n  /**\n   * Read the contents from this file (if the flag exists) and use\n   * it as the raw contents\n   */\n  @flags.string({ description: 'Use the contents of the given file as the generated output' })\n  declare contentsFrom: string\n\n  /**\n   * The stub to use for generating the controller\n   */\n  protected stubPath: string = 'make/controller/main.stub'\n\n  /**\n   * Preparing the command state\n   */\n  async prepare() {\n    /**\n     * Use actions stub\n     */\n    if (this.actions) {\n      this.stubPath = 'make/controller/actions.stub'\n    }\n\n    /**\n     * Use resource stub\n     */\n    if (this.resource) {\n      if (this.actions) {\n        this.logger.warning('Cannot use --resource flag with actions. Ignoring --resource')\n      } else {\n        this.stubPath = 'make/controller/resource.stub'\n      }\n    }\n\n    /**\n     * Use api stub\n     */\n    if (this.api) {\n      if (this.actions) {\n        this.logger.warning('Cannot use --api flag with actions. Ignoring --api')\n      } else {\n        this.stubPath = 'make/controller/api.stub'\n      }\n    }\n\n    /**\n     * Log warning when both flags are used together\n     */\n    if (this.resource && this.api && !this.actions) {\n      this.logger.warning('--api and --resource flags cannot be used together. Ignoring --resource')\n    }\n  }\n\n  async run() {\n    const codemods = await this.createCodemods()\n    await codemods.makeUsingStub(\n      stubsRoot,\n      this.stubPath,\n      {\n        flags: this.parsed.flags,\n        actions: this.actions?.map((action) => string.camelCase(action)),\n        entity: this.app.generators.createEntity(this.name),\n        singular: this.singular,\n      },\n      {\n        contentsFromFile: this.contentsFrom,\n      }\n    )\n  }\n}\n"
  },
  {
    "path": "commands/make/event.ts",
    "content": "/*\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 { stubsRoot } from '../../stubs/main.ts'\nimport { args, flags, BaseCommand } from '../../modules/ace/main.ts'\nimport { type CommandOptions } from '../../types/ace.ts'\n\n/**\n * Command to create a new event class.\n * Events are data objects that encapsulate information about something\n * that happened in your application and can be dispatched to listeners.\n *\n * @example\n * ```\n * ace make:event UserRegistered\n * ace make:event OrderCompleted\n * ace make:event EmailSent\n * ```\n */\nexport default class MakeEvent extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'make:event'\n\n  /**\n   * The command description\n   */\n  static description =\n    'Create a new event class in app/events. Events are dispatched via emitter and handled by listeners'\n\n  /**\n   * Command options configuration.\n   * Allows unknown flags to be passed through.\n   */\n  static options: CommandOptions = {\n    allowUnknownFlags: true,\n  }\n\n  /**\n   * Name of the event class to create\n   */\n  @args.string({ description: 'Name of the event' })\n  declare name: string\n\n  /**\n   * Read the contents from this file (if the flag exists) and use\n   * it as the raw contents\n   */\n  @flags.string({ description: 'Use the contents of the given file as the generated output' })\n  declare contentsFrom: string\n\n  /**\n   * The stub template file to use for generating the event class\n   */\n  protected stubPath: string = 'make/event/main.stub'\n\n  /**\n   * Execute the command to create a new event class.\n   * Generates the event file with proper event structure.\n   */\n  async run() {\n    const codemods = await this.createCodemods()\n    await codemods.makeUsingStub(\n      stubsRoot,\n      this.stubPath,\n      {\n        flags: this.parsed.flags,\n        entity: this.app.generators.createEntity(this.name),\n      },\n      {\n        contentsFromFile: this.contentsFrom,\n      }\n    )\n  }\n}\n"
  },
  {
    "path": "commands/make/exception.ts",
    "content": "/*\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 { stubsRoot } from '../../stubs/main.ts'\nimport { args, flags, BaseCommand } from '../../modules/ace/main.ts'\nimport { type CommandOptions } from '../../types/ace.ts'\n\n/**\n * Command to create a new custom exception class.\n * Custom exceptions allow you to define specific error types for your application\n * with custom error messages, status codes, and error handling logic.\n *\n * @example\n * ```\n * ace make:exception ValidationException\n * ace make:exception UnauthorizedException\n * ace make:exception ResourceNotFoundException\n * ```\n */\nexport default class MakeException extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'make:exception'\n\n  /**\n   * The command description\n   */\n  static description =\n    'Create a new custom exception class in app/exceptions with handle and report methods'\n\n  /**\n   * Command options configuration.\n   * Allows unknown flags to be passed through.\n   */\n  static options: CommandOptions = {\n    allowUnknownFlags: true,\n  }\n\n  /**\n   * Name of the exception class to create\n   */\n  @args.string({ description: 'Name of the exception' })\n  declare name: string\n\n  /**\n   * Read the contents from this file (if the flag exists) and use\n   * it as the raw contents\n   */\n  @flags.string({ description: 'Use the contents of the given file as the generated output' })\n  declare contentsFrom: string\n\n  /**\n   * The stub template file to use for generating the exception class\n   */\n  protected stubPath: string = 'make/exception/main.stub'\n\n  /**\n   * Execute the command to create a new custom exception class.\n   * Generates the exception file with proper error handling structure.\n   */\n  async run() {\n    const codemods = await this.createCodemods()\n    await codemods.makeUsingStub(\n      stubsRoot,\n      this.stubPath,\n      {\n        flags: this.parsed.flags,\n        entity: this.app.generators.createEntity(this.name),\n      },\n      {\n        contentsFromFile: this.contentsFrom,\n      }\n    )\n  }\n}\n"
  },
  {
    "path": "commands/make/listener.ts",
    "content": "/*\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 { stubsRoot } from '../../stubs/main.ts'\nimport { args, flags, BaseCommand } from '../../modules/ace/main.ts'\nimport { type CommandOptions } from '../../types/ace.ts'\n\n/**\n * Command to create a new event listener class.\n * Event listeners handle events dispatched by the application and can optionally\n * generate the corresponding event class automatically.\n *\n * @example\n * ```\n * ace make:listener UserRegistered\n * ace make:listener EmailSent --event=EmailSent\n * ace make:listener OrderCompleted --event=OrderEvent\n * ```\n */\nexport default class MakeListener extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'make:listener'\n\n  /**\n   * The command description\n   */\n  static description =\n    'Create a new event listener class in app/listeners. Use --event to also generate the event class and bind them together'\n\n  /**\n   * Command options configuration.\n   * Allows unknown flags to be passed through.\n   */\n  static options: CommandOptions = {\n    allowUnknownFlags: true,\n  }\n\n  /**\n   * Name of the event listener class to create\n   */\n  @args.string({ description: 'Name of the event listener' })\n  declare name: string\n\n  /**\n   * Generate an event class alongside the listener and bind them together\n   */\n  @flags.string({\n    description: 'Generate an event class alongside the listener',\n    alias: 'e',\n  })\n  declare event: string\n\n  /**\n   * Read the contents from this file (if the flag exists) and use\n   * it as the raw contents\n   */\n  @flags.string({ description: 'Use the contents of the given file as the generated output' })\n  declare contentsFrom: string\n\n  /**\n   * The stub template file to use for generating the event listener\n   */\n  protected stubPath: string = 'make/listener/main.stub'\n\n  /**\n   * Prepare the command by selecting the appropriate stub based on options.\n   * Uses a different stub when generating a listener for a specific event.\n   */\n  prepare() {\n    if (this.event) {\n      this.stubPath = 'make/listener/for_event.stub'\n    }\n  }\n\n  /**\n   * Execute the command to create a new event listener.\n   * If an event is specified, creates the event class first,\n   * then generates the listener with proper event binding.\n   */\n  async run() {\n    const codemods = await this.createCodemods()\n\n    if (this.event) {\n      const { exitCode } = await this.kernel.exec('make:event', [this.event])\n\n      /**\n       * Create listener only when make:event is completed successfully\n       */\n      if (exitCode === 0) {\n        const eventEntity = this.app.generators.createEntity(this.event)\n        await codemods.makeUsingStub(\n          stubsRoot,\n          this.stubPath,\n          {\n            event: eventEntity,\n            flags: this.parsed.flags,\n            entity: this.app.generators.createEntity(this.name),\n          },\n          {\n            contentsFromFile: this.contentsFrom,\n          }\n        )\n      }\n\n      return\n    }\n\n    await codemods.makeUsingStub(\n      stubsRoot,\n      this.stubPath,\n      {\n        flags: this.parsed.flags,\n        entity: this.app.generators.createEntity(this.name),\n      },\n      {\n        contentsFromFile: this.contentsFrom,\n      }\n    )\n  }\n}\n"
  },
  {
    "path": "commands/make/middleware.ts",
    "content": "/*\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 string from '@poppinss/utils/string'\nimport { basename, extname, relative } from 'node:path'\n\nimport { stubsRoot } from '../../stubs/main.ts'\nimport { type CommandOptions } from '../../types/ace.ts'\nimport stringHelpers from '../../src/helpers/string.ts'\nimport { args, BaseCommand, flags } from '../../modules/ace/main.ts'\n\n/**\n * The make middleware command to create a new middleware\n * class.\n *\n * @example\n * ```\n * ace make:middleware Auth\n * ace make:middleware Auth --stack=server\n * ace make:middleware Auth --stack=named\n * ace make:middleware Auth --stack=router\n * ```\n */\nexport default class MakeMiddleware extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'make:middleware'\n  /**\n   * The command description\n   */\n  static description =\n    'Create a new middleware class in app/middleware and register it in start/kernel.ts under the chosen stack (server, router, or named)'\n\n  /**\n   * Command options configuration\n   */\n  static options: CommandOptions = {\n    allowUnknownFlags: true,\n  }\n\n  /**\n   * Name of the middleware\n   */\n  @args.string({ description: 'Name of the middleware' })\n  declare name: string\n\n  /**\n   * The stack in which to register the middleware\n   */\n  @flags.string({ description: 'The stack in which to register the middleware', alias: 's' })\n  declare stack?: 'server' | 'named' | 'router'\n\n  /**\n   * Read the contents from this file (if the flag exists) and use\n   * it as the raw contents\n   */\n  @flags.string({ description: 'Use the contents of the given file as the generated output' })\n  declare contentsFrom: string\n\n  /**\n   * The stub to use for generating the middleware\n   */\n  protected stubPath: string = 'make/middleware/main.stub'\n\n  async run() {\n    const stackChoices = ['server', 'router', 'named']\n\n    /**\n     * Prompt to select the stack under which to register\n     * the middleware\n     */\n    if (!this.stack) {\n      this.stack = await this.prompt.choice(\n        'Under which stack you want to register the middleware?',\n        stackChoices\n      )\n    }\n\n    /**\n     * Error out when mentioned stack is invalid\n     */\n    if (!stackChoices.includes(this.stack)) {\n      this.exitCode = 1\n      this.logger.error(\n        `Invalid middleware stack \"${this.stack}\". Select from \"${stackChoices.join(', ')}\"`\n      )\n      return\n    }\n\n    /**\n     * Create middleware\n     */\n    const codemods = await this.createCodemods()\n    const { destination } = await codemods.makeUsingStub(\n      stubsRoot,\n      this.stubPath,\n      {\n        flags: this.parsed.flags,\n        entity: this.app.generators.createEntity(this.name),\n      },\n      {\n        contentsFromFile: this.contentsFrom,\n      }\n    )\n\n    /**\n     * Creative relative path for the middleware file from\n     * the \"./app/middleware\" directory\n     */\n    const middlewareRelativePath = stringHelpers.toUnixSlash(\n      relative(this.app.middlewarePath(), destination).replace(extname(destination), '')\n    )\n\n    /**\n     * Take the middleware relative path, remove `_middleware` prefix from it\n     * and convert everything to camelcase\n     */\n    const name = string.camelCase(basename(middlewareRelativePath).replace(/_middleware$/, ''))\n\n    /**\n     * Register middleware\n     */\n    await codemods.registerMiddleware(this.stack, [\n      {\n        name: name,\n        path: `#middleware/${middlewareRelativePath}`,\n      },\n    ])\n  }\n}\n"
  },
  {
    "path": "commands/make/preload.ts",
    "content": "/*\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 { extname, relative } from 'node:path'\nimport type { AppEnvironments } from '@adonisjs/application/types'\n\nimport { stubsRoot } from '../../stubs/main.ts'\nimport stringHelpers from '../../src/helpers/string.ts'\nimport { args, flags, BaseCommand } from '../../modules/ace/main.ts'\n\nconst ALLOWED_ENVIRONMENTS = ['web', 'console', 'test', 'repl'] satisfies AppEnvironments[]\ntype AllowedAppEnvironments = typeof ALLOWED_ENVIRONMENTS\n\n/**\n * Command to create a new preload file in the start directory.\n * Preload files are executed during application startup and can be used\n * to set up global configurations, register global bindings, or perform\n * application-wide initialization tasks.\n *\n * @example\n * ```\n * ace make:preload routes\n * ace make:preload database --register\n * ace make:preload events --no-register\n * ace make:preload kernel --environments=web,console\n * ```\n */\nexport default class MakePreload extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'make:preload'\n\n  /**\n   * The command description\n   */\n  static description =\n    'Create a new preload file in start/ and optionally register it in adonisrc.ts. Preload files run during app boot'\n\n  /**\n   * Name of the preload file to create\n   */\n  @args.string({ description: 'Name of the preload file' })\n  declare name: string\n\n  /**\n   * Automatically register the preload file in the .adonisrc.ts file\n   */\n  @flags.boolean({\n    description: 'Auto register the preload file inside the .adonisrc.ts file',\n    showNegatedVariantInHelp: true,\n    alias: 'r',\n  })\n  declare register?: boolean\n\n  /**\n   * Application environments where the preload file should be loaded\n   */\n  @flags.array({\n    description: `Define the preload file's environment. Accepted values are \"${ALLOWED_ENVIRONMENTS}\"`,\n    alias: 'e',\n  })\n  declare environments?: AllowedAppEnvironments\n\n  /**\n   * Read the contents from this file (if the flag exists) and use\n   * it as the raw contents\n   */\n  @flags.string({ description: 'Use the contents of the given file as the generated output' })\n  declare contentsFrom: string\n\n  /**\n   * The stub template file to use for generating the preload file\n   */\n  protected stubPath: string = 'make/preload/main.stub'\n\n  /**\n   * Validate that all specified environments are valid application environments.\n   *\n   * @returns True if all environments are valid or none specified, false otherwise\n   */\n  #isEnvironmentsFlagValid() {\n    if (!this.environments || !this.environments.length) {\n      return true\n    }\n\n    return this.environments.every((one) => ALLOWED_ENVIRONMENTS.includes(one))\n  }\n\n  /**\n   * Execute the command to create a new preload file.\n   * Validates inputs, generates the preload file, and optionally registers it in .adonisrc.ts.\n   */\n  async run() {\n    /**\n     * Ensure the environments are valid when provided via flag\n     */\n    if (!this.#isEnvironmentsFlagValid()) {\n      this.logger.error(\n        `Invalid environment(s) \"${this.environments}\". Only \"${ALLOWED_ENVIRONMENTS}\" are allowed`\n      )\n      return\n    }\n\n    /**\n     * Display prompt to know if we should register the preload\n     * file inside the \".adonisrc.ts\" file.\n     */\n    if (this.register === undefined) {\n      this.register = await this.prompt.confirm(\n        'Do you want to register the preload file in .adonisrc.ts file?'\n      )\n    }\n\n    const codemods = await this.createCodemods()\n    const { destination } = await codemods.makeUsingStub(\n      stubsRoot,\n      this.stubPath,\n      {\n        flags: this.parsed.flags,\n        entity: this.app.generators.createEntity(this.name),\n      },\n      {\n        contentsFromFile: this.contentsFrom,\n      }\n    )\n\n    /**\n     * Do not register when prompt has been denied or \"--no-register\"\n     * flag was used\n     */\n    if (!this.register) {\n      return\n    }\n\n    /**\n     * Creative relative path for the preload file from\n     * the \"./start\" directory\n     */\n    const preloadFileRelativePath = stringHelpers.toUnixSlash(\n      relative(this.app.startPath(), destination).replace(extname(destination), '')\n    )\n\n    await codemods.updateRcFile((rcFile) => {\n      rcFile.addPreloadFile(`#start/${preloadFileRelativePath}`, this.environments)\n    })\n  }\n}\n"
  },
  {
    "path": "commands/make/provider.ts",
    "content": "/*\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 { extname, relative } from 'node:path'\n\nimport { stubsRoot } from '../../stubs/main.ts'\nimport type { AppEnvironments } from '../../types/app.ts'\nimport stringHelpers from '../../src/helpers/string.ts'\nimport { args, BaseCommand, flags } from '../../modules/ace/main.ts'\n\nconst ALLOWED_ENVIRONMENTS = ['web', 'console', 'test', 'repl'] satisfies AppEnvironments[]\ntype AllowedAppEnvironments = typeof ALLOWED_ENVIRONMENTS\n\n/**\n * Command to create a new service provider class.\n * Service providers are used to register bindings, configure services,\n * and bootstrap application components during startup.\n *\n * @example\n * ```\n * ace make:provider AuthProvider\n * ace make:provider DatabaseProvider --register\n * ace make:provider AppProvider --no-register\n * ace make:provider CacheProvider --environments=web,console\n * ```\n */\nexport default class MakeProvider extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'make:provider'\n\n  /**\n   * The command description\n   */\n  static description =\n    'Create a new service provider in providers/ and optionally register it in adonisrc.ts. Providers register IoC container bindings'\n\n  /**\n   * Name of the service provider to create\n   */\n  @args.string({ description: 'Name of the provider' })\n  declare name: string\n\n  /**\n   * Automatically register the provider in the .adonisrc.ts file\n   */\n  @flags.boolean({\n    description: 'Auto register the provider inside the .adonisrc.ts file',\n    showNegatedVariantInHelp: true,\n    alias: 'r',\n  })\n  declare register?: boolean\n\n  /**\n   * Application environments where the provider should be loaded\n   */\n  @flags.array({\n    description: `Define the provider environment. Accepted values are \"${ALLOWED_ENVIRONMENTS}\"`,\n    alias: 'e',\n  })\n  declare environments?: AllowedAppEnvironments\n\n  /**\n   * Read the contents from this file (if the flag exists) and use\n   * it as the raw contents\n   */\n  @flags.string({ description: 'Use the contents of the given file as the generated output' })\n  declare contentsFrom: string\n\n  /**\n   * The stub template file to use for generating the provider class\n   */\n  protected stubPath: string = 'make/provider/main.stub'\n\n  /**\n   * Validate that all specified environments are valid application environments.\n   *\n   * @returns True if all environments are valid or none specified, false otherwise\n   */\n  #isEnvironmentsFlagValid() {\n    if (!this.environments || !this.environments.length) {\n      return true\n    }\n    return this.environments.every((one) => ALLOWED_ENVIRONMENTS.includes(one))\n  }\n\n  /**\n   * Execute the command to create a new service provider.\n   * Validates inputs, generates the provider file, and optionally registers it in .adonisrc.ts.\n   */\n  async run() {\n    /**\n     * Ensure the environments are valid when provided via flag\n     */\n    if (!this.#isEnvironmentsFlagValid()) {\n      this.logger.error(\n        `Invalid environment(s) \"${this.environments}\". Only \"${ALLOWED_ENVIRONMENTS}\" are allowed`\n      )\n      return\n    }\n\n    /**\n     * Display prompt to know if we should register the provider\n     * file inside the \".adonisrc.ts\" file.\n     */\n    if (this.register === undefined) {\n      this.register = await this.prompt.confirm(\n        'Do you want to register the provider in .adonisrc.ts file?'\n      )\n    }\n\n    const codemods = await this.createCodemods()\n    const { destination } = await codemods.makeUsingStub(\n      stubsRoot,\n      this.stubPath,\n      {\n        flags: this.parsed.flags,\n        entity: this.app.generators.createEntity(this.name),\n      },\n      {\n        contentsFromFile: this.contentsFrom,\n      }\n    )\n\n    /**\n     * Do not register when prompt has been denied or \"--no-register\"\n     * flag was used\n     */\n    if (!this.register) {\n      return\n    }\n\n    /**\n     * Creative relative path for the provider file from\n     * the \"./start\" directory\n     */\n    const providerRelativePath = stringHelpers.toUnixSlash(\n      relative(this.app.providersPath(), destination).replace(extname(destination), '')\n    )\n\n    await codemods.updateRcFile((rcFile) => {\n      rcFile.addProvider(`#providers/${providerRelativePath}`, this.environments)\n    })\n  }\n}\n"
  },
  {
    "path": "commands/make/service.ts",
    "content": "/*\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 { stubsRoot } from '../../stubs/main.ts'\nimport { args, flags, BaseCommand } from '../../modules/ace/main.ts'\nimport { type CommandOptions } from '../../types/ace.ts'\n\n/**\n * Make a new service class\n *\n * @example\n * ```\n * ace make:service UserService\n * ace make:service AuthService\n * ace make:service User/ProfileService\n * ```\n */\nexport default class MakeService extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'make:service'\n  /**\n   * The command description\n   */\n  static description =\n    'Create a new service class in app/services. Services encapsulate reusable business logic outside of controllers'\n\n  /**\n   * Command options configuration\n   */\n  static options: CommandOptions = {\n    allowUnknownFlags: true,\n  }\n\n  /**\n   * Name of the service\n   */\n  @args.string({ description: 'Name of the service' })\n  declare name: string\n\n  /**\n   * Read the contents from this file (if the flag exists) and use\n   * it as the raw contents\n   */\n  @flags.string({ description: 'Use the contents of the given file as the generated output' })\n  declare contentsFrom: string\n\n  /**\n   * The stub to use for generating the service class\n   */\n  protected stubPath: string = 'make/service/main.stub'\n\n  async run() {\n    const codemods = await this.createCodemods()\n    await codemods.makeUsingStub(\n      stubsRoot,\n      this.stubPath,\n      {\n        flags: this.parsed.flags,\n        entity: this.app.generators.createEntity(this.name),\n      },\n      {\n        contentsFromFile: this.contentsFrom,\n      }\n    )\n  }\n}\n"
  },
  {
    "path": "commands/make/test.ts",
    "content": "/*\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 { stubsRoot } from '../../stubs/main.ts'\nimport { args, flags, BaseCommand } from '../../modules/ace/main.ts'\n\n/**\n * Command to create a new Japa test file.\n * Supports multiple test suites and automatically detects or prompts for\n * the appropriate suite and directory based on application configuration.\n *\n * @example\n * ```\n * ace make:test UserController\n * ace make:test UserModel --suite=unit\n * ace make:test AuthService --suite=integration\n * ```\n */\nexport default class MakeTest extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'make:test'\n\n  /**\n   * The command description\n   */\n  static description =\n    'Create a new Japa test file in tests/. Use --suite to specify the test suite (unit, functional, etc.)'\n\n  /**\n   * Name of the test file to create\n   */\n  @args.string({ description: 'Name of the test file' })\n  declare name: string\n\n  /**\n   * Test suite name where the test file should be created\n   */\n  @flags.string({ description: 'The suite for which to create the test file', alias: 's' })\n  declare suite?: string\n\n  /**\n   * Read the contents from this file (if the flag exists) and use\n   * it as the raw contents\n   */\n  @flags.string({ description: 'Use the contents of the given file as the generated output' })\n  declare contentsFrom: string\n\n  /**\n   * The stub template file to use for generating the test file\n   */\n  protected stubPath: string = 'make/test/main.stub'\n\n  /**\n   * Determine the test suite name for creating the test file.\n   * Uses the provided suite flag, or automatically selects if only one suite exists,\n   * or prompts the user to choose from available suites.\n   *\n   * @returns The name of the selected test suite\n   */\n  async #getSuite(): Promise<string> {\n    if (this.suite) {\n      return this.suite\n    }\n\n    /**\n     * Use the first suite from the rcFile when there is only\n     * one suite\n     */\n    const rcFileSuites = this.app.rcFile.tests.suites\n    if (rcFileSuites.length === 1) {\n      return rcFileSuites[0].name\n    }\n\n    /**\n     * Prompt the user to select a suite manually\n     */\n    return this.prompt.choice(\n      'Select the suite for the test file',\n      this.app.rcFile.tests.suites.map((suite) => {\n        return suite.name\n      }),\n      {\n        validate(choice) {\n          return choice ? true : 'Please select a suite'\n        },\n      }\n    )\n  }\n\n  /**\n   * Determine the directory path for the test file within the selected suite.\n   * Automatically selects if only one directory exists, otherwise prompts the user.\n   *\n   * @param directories - Array of available directories for the suite\n   * @returns The selected directory path\n   */\n  async #getSuiteDirectory(directories: string[]): Promise<string> {\n    if (directories.length === 1) {\n      return directories[0]\n    }\n\n    return this.prompt.choice('Select directory for the test file', directories, {\n      validate(choice) {\n        return choice ? true : 'Please select a directory'\n      },\n    })\n  }\n\n  /**\n   * Find suite configuration from the RC file by name.\n   *\n   * @param suiteName - The name of the suite to find\n   * @returns The suite configuration or undefined if not found\n   */\n  #findSuite(suiteName: string) {\n    return this.app.rcFile.tests.suites.find((suite) => {\n      return suite.name === suiteName\n    })\n  }\n\n  /**\n   * Execute the command to create a new test file.\n   * Validates the suite exists, prompts for missing information,\n   * and generates the test file in the appropriate location.\n   */\n  async run() {\n    const suite = this.#findSuite(await this.#getSuite())\n\n    /**\n     * Show error when mentioned/selected suite does not exist\n     */\n    if (!suite) {\n      this.logger.error(`The \"${this.suite}\" suite is not configured inside the \"adonisrc.js\" file`)\n      this.exitCode = 1\n      return\n    }\n\n    /**\n     * Generate entity\n     */\n    const codemods = await this.createCodemods()\n    await codemods.makeUsingStub(\n      stubsRoot,\n      this.stubPath,\n      {\n        flags: this.parsed.flags,\n        entity: this.app.generators.createEntity(this.name),\n        suite: {\n          directory: await this.#getSuiteDirectory(suite.directories),\n        },\n      },\n      {\n        contentsFromFile: this.contentsFrom,\n      }\n    )\n  }\n}\n"
  },
  {
    "path": "commands/make/transformer.ts",
    "content": "/*\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 { stubsRoot } from '../../stubs/main.ts'\nimport { args, flags, BaseCommand } from '../../modules/ace/main.ts'\nimport { type CommandOptions } from '../../types/ace.ts'\n\n/**\n * Command to create a new transformer class.\n * Transformers are used to serialize data objects (like models) into specific\n * formats for API responses, allowing you to control which fields are exposed\n * and how data is structured for clients.\n *\n * @example\n * ```\n * ace make:transformer User\n * ace make:transformer Post\n * ace make:transformer ProductTransformer\n * ```\n */\nexport default class MakeTransformer extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'make:transformer'\n\n  /**\n   * The command description\n   */\n  static description =\n    'Create a new transformer class in app/transformers for serializing data in API responses'\n\n  /**\n   * Command options configuration.\n   * Allows unknown flags to be passed through.\n   */\n  static options: CommandOptions = {\n    allowUnknownFlags: true,\n  }\n\n  /**\n   * Name of the entity for which to generate the transformer\n   */\n  @args.string({ description: 'Entity name for which to generate the transformer' })\n  declare name: string\n\n  /**\n   * Read the contents from this file (if the flag exists) and use\n   * it as the raw contents\n   */\n  @flags.string({ description: 'Use the contents of the given file as the generated output' })\n  declare contentsFrom: string\n\n  /**\n   * The stub template file to use for generating the transformer class\n   */\n  protected stubPath: string = 'make/transformer/main.stub'\n\n  /**\n   * Execute the command to create a new transformer class.\n   * Generates the transformer file with proper data serialization structure.\n   */\n  async run() {\n    const codemods = await this.createCodemods()\n\n    await codemods.makeUsingStub(\n      stubsRoot,\n      this.stubPath,\n      {\n        flags: this.parsed.flags,\n        entity: this.app.generators.createEntity(this.name),\n        model: this.app.generators.createEntity(this.name),\n      },\n      {\n        contentsFromFile: this.contentsFrom,\n      }\n    )\n  }\n}\n"
  },
  {
    "path": "commands/make/validator.ts",
    "content": "/*\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 { stubsRoot } from '../../stubs/main.ts'\nimport { args, flags, BaseCommand } from '../../modules/ace/main.ts'\nimport { type CommandOptions } from '../../types/ace.ts'\n\n/**\n * Command to create a new VineJS validator file.\n * Validators define reusable validation schemas for request validation,\n * and can be generated as simple validators or resource-based validators\n * with create and update schemas.\n *\n * @example\n * ```\n * ace make:validator UserValidator\n * ace make:validator PostValidator --resource\n * ace make:validator ContactValidator\n * ```\n */\nexport default class MakeValidator extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'make:validator'\n\n  /**\n   * The command description\n   */\n  static description =\n    'Create a new VineJS validator file in app/validators. Use --resource to generate both create and update validation schemas'\n\n  /**\n   * Command options configuration.\n   * Allows unknown flags to be passed through.\n   */\n  static options: CommandOptions = {\n    allowUnknownFlags: true,\n  }\n\n  /**\n   * Name of the validator file to create\n   */\n  @args.string({ description: 'Name of the validator file' })\n  declare name: string\n\n  /**\n   * Generate a resource validator with create and update schemas\n   */\n  @flags.boolean({\n    description: 'Create a file with pre-defined validators for create and update actions',\n  })\n  declare resource: boolean\n\n  /**\n   * Read the contents from this file (if the flag exists) and use\n   * it as the raw contents\n   */\n  @flags.string({ description: 'Use the contents of the given file as the generated output' })\n  declare contentsFrom: string\n\n  /**\n   * The stub template file to use for generating the validator\n   */\n  protected stubPath: string = 'make/validator/main.stub'\n\n  /**\n   * Prepare the command by selecting the appropriate stub based on options.\n   * Uses a resource stub when generating validators for CRUD operations.\n   */\n  async prepare() {\n    /**\n     * Use resource stub\n     */\n    if (this.resource) {\n      this.stubPath = 'make/validator/resource.stub'\n    }\n  }\n\n  /**\n   * Execute the command to create a new VineJS validator file.\n   * Generates the validator with the appropriate stub template.\n   */\n  async run() {\n    const codemods = await this.createCodemods()\n    await codemods.makeUsingStub(\n      stubsRoot,\n      this.stubPath,\n      {\n        flags: this.parsed.flags,\n        entity: this.app.generators.createEntity(this.name),\n      },\n      {\n        contentsFromFile: this.contentsFrom,\n      }\n    )\n  }\n}\n"
  },
  {
    "path": "commands/make/view.ts",
    "content": "/*\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 { stubsRoot } from '../../stubs/main.ts'\nimport { args, flags, BaseCommand } from '../../modules/ace/main.ts'\n\n/**\n * Command to create a new Edge.js template file.\n * Edge templates are used for rendering HTML views in your web application,\n * supporting layouts, partials, components, and template inheritance.\n *\n * @example\n * ```\n * ace make:view home\n * ace make:view users/profile\n * ace make:view components/navbar\n * ace make:view layouts/app\n * ```\n */\nexport default class MakeView extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'make:view'\n\n  /**\n   * The command description\n   */\n  static description = 'Create a new Edge.js template file in resources/views'\n\n  /**\n   * Name of the template file to create\n   */\n  @args.string({ description: 'Name of the template' })\n  declare name: string\n\n  /**\n   * Read the contents from this file (if the flag exists) and use\n   * it as the raw contents\n   */\n  @flags.string({ description: 'Use the contents of the given file as the generated output' })\n  declare contentsFrom: string\n\n  /**\n   * The stub template file to use for generating the Edge template\n   */\n  protected stubPath: string = 'make/view/main.stub'\n\n  /**\n   * Execute the command to create a new Edge.js template file.\n   * Generates the template file in the views directory.\n   */\n  async run() {\n    const codemods = await this.createCodemods()\n    await codemods.makeUsingStub(\n      stubsRoot,\n      this.stubPath,\n      {\n        flags: this.parsed.flags,\n        entity: this.app.generators.createEntity(this.name),\n      },\n      {\n        contentsFromFile: this.contentsFrom,\n      }\n    )\n  }\n}\n"
  },
  {
    "path": "commands/repl.ts",
    "content": "/*\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 { BaseCommand } from '../modules/ace/main.ts'\nimport { type CommandOptions } from '../types/ace.ts'\n\n/**\n * Command to start an interactive REPL (Read-Eval-Print Loop) session for AdonisJS.\n * The REPL provides a command-line interface where you can execute JavaScript code\n * in the context of your AdonisJS application, allowing you to interact with models,\n * services, and other application components in real-time.\n *\n * @example\n * ```\n * ace repl\n * ```\n */\nexport default class ReplCommand extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'repl'\n\n  /**\n   * The command description\n   */\n  static description =\n    'Start an interactive REPL session with the application booted and IoC container available'\n\n  /**\n   * Command options configuration.\n   * Requires the application to be started and keeps the process alive.\n   */\n  static options: CommandOptions = {\n    startApp: true,\n    staysAlive: true,\n  }\n\n  /**\n   * Execute the command to start the REPL server.\n   * Creates a REPL instance from the container and sets up an exit handler\n   * that properly terminates the application when the REPL session ends.\n   */\n  async run() {\n    const repl = await this.app.container.make('repl')\n    repl.start()\n    repl.server!.on('exit', async () => {\n      await this.terminate()\n    })\n  }\n}\n"
  },
  {
    "path": "commands/serve.ts",
    "content": "/*\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 { DevServer } from '@adonisjs/assembler'\nimport { importAssembler } from '../src/utils.ts'\nimport type { CommandOptions } from '../types/ace.ts'\nimport { BaseCommand, flags } from '../modules/ace/main.ts'\n\n/**\n * Serve command is used to run the AdonisJS HTTP server during development. The\n * command under the hood runs the \"bin/server.ts\" file and watches for file\n * system changes\n *\n * @example\n * ```\n * ace serve\n * ace serve --watch\n * ace serve --hmr\n * ace serve --poll\n * ace serve --no-clear\n * ```\n */\nexport default class Serve extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'serve'\n  /**\n   * The command description\n   */\n  static description =\n    'Start the development HTTP server. Use --watch for auto-restart on file change or --hmr for hot module replacement'\n\n  /**\n   * Help text for the command\n   */\n  static help = [\n    'Start the development server with file watcher using the following command.',\n    '```',\n    '{{ binaryName }} serve --watch',\n    '```',\n    '',\n    'You can also start the server with HMR support using the following command.',\n    '```',\n    '{{ binaryName }} serve --hmr',\n    '```',\n    '',\n    'The assets bundler dev server runs automatically after detecting vite config or webpack config files',\n    'You may pass vite CLI args using the --assets-args command line flag.',\n    '```',\n    '{{ binaryName }} serve --assets-args=\"--debug --base=/public\"',\n    '```',\n  ]\n\n  /**\n   * Command options configuration\n   */\n  static options: CommandOptions = {\n    staysAlive: true,\n  }\n\n  /**\n   * The development server instance\n   */\n  declare devServer: DevServer\n\n  /**\n   * Start the server with HMR support\n   */\n  @flags.boolean({ description: 'Start the server with HMR support' })\n  declare hmr?: boolean\n\n  /**\n   * Watch filesystem and restart the HTTP server on file change\n   */\n  @flags.boolean({\n    description: 'Watch filesystem and restart the HTTP server on file change',\n    alias: 'w',\n  })\n  declare watch?: boolean\n\n  /**\n   * Use polling to detect filesystem changes\n   */\n  @flags.boolean({ description: 'Use polling to detect filesystem changes', alias: 'p' })\n  declare poll?: boolean\n\n  /**\n   * Clear the terminal for new logs after file change\n   */\n  @flags.boolean({\n    description: 'Clear the terminal for new logs after file change',\n    showNegatedVariantInHelp: true,\n    default: true,\n  })\n  declare clear?: boolean\n\n  /**\n   * Log a development dependency is missing\n   *\n   * @param dependency - The name of the missing dependency\n   */\n  #logMissingDevelopmentDependency(dependency: string) {\n    this.logger.error(\n      [\n        `Cannot find package \"${dependency}\"`,\n        '',\n        `The \"${dependency}\" package is a development dependency and therefore you should use the serve command during development only.`,\n        '',\n        'If you are running your application in production, then use \"node bin/server.js\" command to start the HTTP server',\n      ].join('\\n')\n    )\n  }\n\n  /**\n   * Runs the HTTP server\n   */\n  async run() {\n    const assembler = await importAssembler(this.app)\n    if (!assembler) {\n      this.#logMissingDevelopmentDependency('@adonisjs/assembler')\n      this.exitCode = 1\n      return\n    }\n\n    if (this.watch && this.hmr) {\n      this.logger.error('Cannot use --watch and --hmr flags together. Choose one of them')\n      this.exitCode = 1\n      return\n    }\n\n    this.devServer = new assembler.DevServer(this.app.appRoot, {\n      hmr: this.hmr === true ? true : false,\n      clearScreen: this.clear === false ? false : true,\n      nodeArgs: this.parsed.nodeArgs,\n      scriptArgs: [],\n      metaFiles: this.app.rcFile.metaFiles,\n      hooks: this.app.rcFile.hooks,\n    })\n\n    /**\n     * Share command logger with assembler, so that CLI flags like --no-ansi has\n     * similar impact for assembler logs as well.\n     */\n    this.devServer.ui.logger = this.logger\n\n    /**\n     * Exit command when the dev server is closed\n     */\n    this.devServer.onClose((exitCode) => {\n      this.exitCode = exitCode\n      this.terminate()\n    })\n\n    /**\n     * Exit command when the dev server crashes\n     */\n    this.devServer.onError(() => {\n      this.exitCode = 1\n      this.terminate()\n    })\n\n    /**\n     * Start the development server\n     */\n    if (this.watch) {\n      await this.devServer.startAndWatch({ poll: this.poll || false })\n    } else {\n      await this.devServer.start()\n    }\n  }\n}\n"
  },
  {
    "path": "commands/test.ts",
    "content": "/*\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 { TestRunner } from '@adonisjs/assembler'\n\nimport { importAssembler } from '../src/utils.ts'\nimport type { CommandOptions } from '../types/ace.ts'\nimport { BaseCommand, flags, args } from '../modules/ace/main.ts'\n\n/**\n * Command to run application tests using the Japa test runner.\n * Supports filtering tests by suites, files, tags, groups, and individual tests.\n * Can run in watch mode to automatically re-run tests when files change.\n *\n * @example\n * ```\n * ace test\n * ace test unit integration\n * ace test --watch\n * ace test --files=user.spec.ts\n * ace test --tags=slow --groups=\"User tests\"\n * ace test --reporters=spec,dot\n * ace test --timeout=5000 --retries=2\n * ```\n */\nexport default class Test extends BaseCommand {\n  /**\n   * The command name\n   */\n  static commandName = 'test'\n\n  /**\n   * The command description\n   */\n  static description =\n    'Run tests using Japa test runner. Supports filtering by suite, file, tag, and group. Use --watch for re-runs on file change'\n\n  /**\n   * Command options configuration.\n   * Allows unknown flags to be passed to Japa and keeps the process alive.\n   */\n  static options: CommandOptions = {\n    allowUnknownFlags: true,\n    staysAlive: true,\n  }\n\n  /**\n   * The test runner instance from the assembler package\n   */\n  declare testsRunner: TestRunner\n\n  /**\n   * Test suite names to run. When provided, only tests from the specified suites will be executed\n   */\n  @args.spread({\n    description: 'Mention suite names to run tests for selected suites',\n    required: false,\n  })\n  declare suites?: string[]\n\n  /**\n   * Filter tests by filename patterns\n   */\n  @flags.array({ description: 'Filter tests by the filename' })\n  declare files?: string[]\n\n  /**\n   * Filter tests by tags\n   */\n  @flags.array({ description: 'Filter tests by tags' })\n  declare tags?: string[]\n\n  /**\n   * Filter tests by parent group title\n   */\n  @flags.array({ description: 'Filter tests by parent group title' })\n  declare groups?: string[]\n\n  /**\n   * Filter tests by test title\n   */\n  @flags.array({ description: 'Filter tests by test title' })\n  declare tests?: string[]\n\n  /**\n   * Specify one or more test reporters to use for output formatting\n   */\n  @flags.array({ description: 'Activate one or more test reporters' })\n  declare reporters?: string[]\n\n  /**\n   * Enable watch mode to automatically re-run tests when files change\n   */\n  @flags.boolean({ description: 'Watch filesystem and re-run tests on file change' })\n  declare watch?: boolean\n\n  /**\n   * Use polling instead of native filesystem events to detect file changes\n   */\n  @flags.boolean({ description: 'Use polling to detect filesystem changes' })\n  declare poll?: boolean\n\n  /**\n   * Default timeout in milliseconds for all tests\n   */\n  @flags.number({ description: 'Define default timeout for all tests' })\n  declare timeout?: number\n\n  /**\n   * Default number of retries for failed tests\n   */\n  @flags.number({ description: 'Define default retries for all tests' })\n  declare retries?: number\n\n  /**\n   * Execute only tests that failed during the last run\n   */\n  @flags.boolean({ description: 'Execute tests failed during the last run' })\n  declare failed?: boolean\n\n  /**\n   * Clear the terminal for new logs after file change in watch mode\n   */\n  @flags.boolean({\n    description: 'Clear the terminal for new logs after file change',\n    showNegatedVariantInHelp: true,\n    default: true,\n  })\n  declare clear?: boolean\n\n  /**\n   * Log an error message when a required development dependency is missing.\n   * Provides helpful instructions for resolving the issue.\n   *\n   * @param dependency - The name of the missing dependency package\n   */\n  #logMissingDevelopmentDependency(dependency: string) {\n    this.logger.error(\n      [\n        `Cannot find package \"${dependency}\"`,\n        '',\n        `The \"${dependency}\" package is a development dependency and therefore you should run tests with development dependencies installed.`,\n        '',\n        'If you are run tests inside a CI, make sure the NODE_ENV is set to \"development\"',\n      ].join('\\n')\n    )\n  }\n\n  /**\n   * Collect unknown flags and format them to pass to the Japa test runner.\n   * Handles boolean flags, arrays, and single values appropriately.\n   *\n   * @returns Array of formatted command-line arguments for Japa\n   */\n  #getPassthroughFlags(): string[] {\n    return this.parsed.unknownFlags\n      .map((flag) => {\n        const value = this.parsed.flags[flag]\n\n        /**\n         * Not mentioning value when value is \"true\"\n         */\n        if (value === true) {\n          return [`--${flag}`] as string[]\n        }\n\n        /**\n         * Repeating flag multiple times when value is an array\n         */\n        if (Array.isArray(value)) {\n          return value.map((v) => [`--${flag}`, v]) as string[][]\n        }\n\n        return [`--${flag}`, value] as string[]\n      })\n      .flat(2)\n  }\n\n  /**\n   * Execute the test command. Sets up the test runner with all configured options\n   * and filters, then runs tests either once or in watch mode. Handles missing\n   * dependencies and properly configures the test environment.\n   */\n  async run() {\n    process.env.NODE_ENV = 'test'\n\n    const assembler = await importAssembler(this.app)\n    if (!assembler) {\n      this.#logMissingDevelopmentDependency('@adonisjs/assembler')\n      this.exitCode = 1\n      return\n    }\n\n    this.testsRunner = new assembler.TestRunner(this.app.appRoot, {\n      clearScreen: this.clear === false ? false : true,\n      nodeArgs: this.parsed.nodeArgs,\n      scriptArgs: this.#getPassthroughFlags(),\n      filters: {\n        suites: this.suites,\n        files: this.files,\n        groups: this.groups,\n        tags: this.tags,\n        tests: this.tests,\n      },\n      failed: this.failed,\n      retries: this.retries,\n      timeout: this.timeout,\n      reporters: this.reporters,\n      suites: this.app.rcFile.tests.suites.map((suite) => {\n        return {\n          name: suite.name,\n          files: suite.files,\n        }\n      }),\n      env: {\n        NODE_ENV: 'test',\n      },\n      hooks: this.app.rcFile.hooks,\n      metaFiles: this.app.rcFile.metaFiles,\n    })\n\n    /**\n     * Share command logger with assembler, so that CLI flags like --no-ansi has\n     * similar impact for assembler logs as well.\n     */\n    this.testsRunner.ui.logger = this.logger\n\n    /**\n     * Exit command when the test runner is closed\n     */\n    this.testsRunner.onClose((exitCode) => {\n      this.exitCode = exitCode\n      this.terminate()\n    })\n\n    /**\n     * Exit command when the dev server crashes\n     */\n    this.testsRunner.onError(() => {\n      this.exitCode = 1\n      this.terminate()\n    })\n\n    /**\n     * Start the test runner in watch mode\n     */\n    if (this.watch) {\n      await this.testsRunner.runAndWatch({ poll: this.poll || false })\n    } else {\n      await this.testsRunner.run()\n    }\n  }\n}\n"
  },
  {
    "path": "eslint.config.js",
    "content": "import { configPkg } from '@adonisjs/eslint-config'\nexport default configPkg({\n  ignores: ['coverage'],\n})\n"
  },
  {
    "path": "factories/app.ts",
    "content": "/*\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\nexport * from '@adonisjs/application/factories'\n"
  },
  {
    "path": "factories/bodyparser.ts",
    "content": "/*\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\nexport * from '@adonisjs/bodyparser/factories'\n"
  },
  {
    "path": "factories/core/ace.ts",
    "content": "/*\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 { IgnitorFactory } from './ignitor.ts'\nimport { Ignitor } from '../../src/ignitor/main.ts'\nimport type { IgnitorOptions } from '../../src/types.ts'\nimport type { Kernel } from '../../modules/ace/kernel.ts'\nimport { createAceKernel } from '../../modules/ace/create_kernel.ts'\n\n/**\n * Factory for creating and configuring Ace command kernel instances.\n * This factory provides a convenient way to create Ace kernels either from\n * an existing Ignitor instance or by creating a new one from scratch.\n *\n * @example\n * ```ts\n * // Create from URL\n * const aceFactory = new AceFactory()\n * const kernel = await aceFactory.make(new URL('../', import.meta.url))\n *\n * // Create from existing ignitor\n * const ignitor = new Ignitor(appRoot)\n * const kernel = await aceFactory.make(ignitor)\n *\n * // Run commands\n * await kernel.handle(['make:controller', 'UserController'])\n * ```\n */\nexport class AceFactory {\n  /**\n   * Create an Ace kernel from an existing Ignitor instance\n   *\n   * @param ignitor - Existing Ignitor instance\n   */\n  async make(ignitor: Ignitor): Promise<Kernel>\n  /**\n   * Create an Ace kernel from application root URL\n   *\n   * @param appRoot - Application root directory URL\n   * @param options - Optional Ignitor configuration options\n   */\n  async make(appRoot: URL, options?: IgnitorOptions): Promise<Kernel>\n  async make(ignitorOrAppRoot: URL | Ignitor, options?: IgnitorOptions): Promise<Kernel> {\n    if (ignitorOrAppRoot instanceof Ignitor) {\n      const app = ignitorOrAppRoot.createApp('console')\n      await app.init()\n      return createAceKernel(app)\n    }\n\n    const app = new IgnitorFactory()\n      .withCoreConfig()\n      .withCoreProviders()\n      .create(ignitorOrAppRoot, options!)\n      .createApp('console')\n\n    await app.init()\n    return createAceKernel(app)\n  }\n}\n"
  },
  {
    "path": "factories/core/ignitor.ts",
    "content": "/*\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 { Ignitor } from '../../src/ignitor/main.ts'\nimport type { ProviderNode } from '../../types/app.ts'\nimport { drivers as hashDrivers } from '../../modules/hash/define_config.ts'\nimport type { ApplicationService, IgnitorOptions } from '../../src/types.ts'\nimport { defineConfig as defineLoggerConfig } from '../../modules/logger.ts'\nimport { defineConfig as defineHashConfig } from '../../modules/hash/main.ts'\nimport { defineConfig as defineHttpConfig } from '../../modules/http/main.ts'\nimport { defineConfig as defineBodyParserConfig } from '../../modules/bodyparser/main.ts'\nimport {\n  defineConfig as defineEncryptionConfig,\n  drivers as encryptionDrivers,\n} from '../../modules/encryption/define_config.ts'\n\ntype FactoryParameters = {\n  rcFileContents: Record<string, any>\n  config: Record<string, any>\n}\n\n/**\n * Factory for creating and configuring AdonisJS Ignitor instances.\n * This factory provides a fluent API to set up applications with core providers,\n * configurations, and preload actions for testing and development scenarios.\n *\n * @example\n * ```ts\n * const ignitor = new IgnitorFactory()\n *   .withCoreProviders()\n *   .withCoreConfig()\n *   .preload((app) => {\n *     // Custom initialization logic\n *   })\n *   .create(new URL('../', import.meta.url))\n *\n * const app = ignitor.createApp('web')\n * await app.boot()\n * ```\n */\nexport class IgnitorFactory {\n  #preloadActions: ((app: ApplicationService) => Promise<void> | void)[] = []\n  #parameters: Partial<FactoryParameters> = {}\n\n  /**\n   * A flag to know if we should load the core providers\n   */\n  #loadCoreProviders: boolean = false\n\n  /**\n   * Define preload actions to run during application initialization.\n   * These actions are executed after the application is booted.\n   *\n   * @param action - Function to execute during preload phase\n   *\n   * @example\n   * ```ts\n   * factory.preload((app) => {\n   *   // Register custom bindings\n   *   app.container.bind('customService', () => new CustomService())\n   * })\n   * ```\n   */\n  preload(action: (app: ApplicationService) => void | Promise<void>): this {\n    this.#preloadActions.push(action)\n    return this\n  }\n\n  /**\n   * Merge core providers with user defined providers\n   */\n  #mergeCoreProviders(providers?: ProviderNode['file'][]): ProviderNode['file'][] {\n    const coreProviders: ProviderNode['file'][] = [\n      () => import('@adonisjs/core/providers/app_provider'),\n      () => import('@adonisjs/core/providers/hash_provider'),\n      () => import('@adonisjs/core/providers/repl_provider'),\n    ]\n\n    return coreProviders.concat(providers || [])\n  }\n\n  /**\n   * Merge custom factory parameters with existing ones.\n   * This allows you to customize RC file contents and application configuration.\n   *\n   * @param params - Parameters to merge\n   * @param params.config - Application configuration to merge\n   * @param params.rcFileContents - RC file contents to merge\n   *\n   * @example\n   * ```ts\n   * factory.merge({\n   *   config: {\n   *     database: { connection: 'mysql' }\n   *   },\n   *   rcFileContents: {\n   *     commands: ['./commands/CustomCommand']\n   *   }\n   * })\n   * ```\n   */\n  merge(params: Partial<FactoryParameters>): this {\n    if (params.config) {\n      this.#parameters.config = Object.assign(this.#parameters.config || {}, params.config)\n    }\n\n    if (params.rcFileContents) {\n      this.#parameters.rcFileContents = Object.assign(\n        this.#parameters.rcFileContents || {},\n        params.rcFileContents\n      )\n    }\n\n    return this\n  }\n\n  /**\n   * Include core AdonisJS providers when booting the application.\n   * This adds essential providers like app, hash, and REPL providers.\n   *\n   * @example\n   * ```ts\n   * const ignitor = new IgnitorFactory()\n   *   .withCoreProviders()\n   *   .create(appRoot)\n   * ```\n   */\n  withCoreProviders(): this {\n    this.#loadCoreProviders = true\n    return this\n  }\n\n  /**\n   * Merge default configuration for core AdonisJS features.\n   * This includes configurations for HTTP, hash, logger, and bodyparser.\n   * A shallow merge is performed with existing config.\n   *\n   * @example\n   * ```ts\n   * const ignitor = new IgnitorFactory()\n   *   .withCoreConfig()\n   *   .create(appRoot)\n   * ```\n   */\n  withCoreConfig(): this {\n    this.merge({\n      config: {\n        app: {\n          appUrl: 'http://localhost:3333',\n          http: defineHttpConfig({}),\n        },\n        validator: {},\n        encryption: defineEncryptionConfig({\n          default: 'gcm',\n          list: {\n            gcm: encryptionDrivers.aes256gcm({\n              id: 'gcm',\n              keys: ['averylongrandomsecretkey'],\n            }),\n          },\n        }),\n        bodyparser: defineBodyParserConfig({}),\n        hash: defineHashConfig({\n          default: 'scrypt',\n          list: {\n            scrypt: hashDrivers.scrypt({}),\n          },\n        }),\n        logger: defineLoggerConfig({\n          default: 'app',\n          loggers: {\n            app: {},\n          },\n        }),\n      },\n    })\n    return this\n  }\n\n  /**\n   * Create a configured Ignitor instance with all specified parameters.\n   *\n   * @param appRoot - Application root directory URL\n   * @param options - Optional Ignitor configuration options\n   *\n   * @example\n   * ```ts\n   * const ignitor = new IgnitorFactory()\n   *   .withCoreConfig()\n   *   .withCoreProviders()\n   *   .create(new URL('../', import.meta.url))\n   * ```\n   */\n  create(appRoot: URL, options?: IgnitorOptions): Ignitor {\n    return new Ignitor(appRoot, options).tap((app) => {\n      app.booted(async () => {\n        for (let action of this.#preloadActions) {\n          await action(app)\n        }\n      })\n\n      if (this.#loadCoreProviders) {\n        this.#parameters.rcFileContents = this.#parameters.rcFileContents || {}\n        this.#parameters.rcFileContents.providers = this.#mergeCoreProviders(\n          this.#parameters.rcFileContents.providers\n        )\n      }\n      this.#parameters.rcFileContents && app.rcContents(this.#parameters.rcFileContents)\n      this.#parameters.config && app.useConfig(this.#parameters.config)\n    })\n  }\n}\n"
  },
  {
    "path": "factories/core/main.ts",
    "content": "/*\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\nexport { AceFactory } from './ace.ts'\nexport { IgnitorFactory } from './ignitor.ts'\nexport { TestUtilsFactory } from './test_utils.ts'\n"
  },
  {
    "path": "factories/core/test_utils.ts",
    "content": "/*\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 { Ignitor } from '../../index.ts'\nimport { IgnitorFactory } from './ignitor.ts'\nimport type { IgnitorOptions } from '../../src/types.ts'\nimport { TestUtils } from '../../src/test_utils/main.ts'\n\n/**\n * Factory for creating TestUtils instances used in AdonisJS testing scenarios.\n * This factory provides convenient methods to set up test utilities either from\n * an existing Ignitor instance or by creating a new configured one.\n *\n * @example\n * ```ts\n * // Create from URL for testing\n * const factory = new TestUtilsFactory()\n * const testUtils = factory.create(new URL('../', import.meta.url))\n *\n * // Use in tests\n * const app = testUtils.app()\n * await app.boot()\n *\n * // Create HTTP client\n * const client = testUtils.httpClient()\n * const response = await client.get('/users')\n * ```\n */\nexport class TestUtilsFactory {\n  /**\n   * Create TestUtils from an existing Ignitor instance\n   *\n   * @param ignitor - Existing Ignitor instance configured for testing\n   */\n  create(ignitor: Ignitor): TestUtils\n  /**\n   * Create TestUtils from application root URL with optional configuration\n   *\n   * @param appRoot - Application root directory URL\n   * @param options - Optional Ignitor configuration options\n   */\n  create(appRoot: URL, options?: IgnitorOptions): TestUtils\n  create(ignitorOrAppRoot: URL | Ignitor, options?: IgnitorOptions): TestUtils {\n    if (ignitorOrAppRoot instanceof Ignitor) {\n      return new TestUtils(ignitorOrAppRoot.createApp('test'))\n    }\n\n    return new TestUtils(\n      new IgnitorFactory()\n        .withCoreConfig()\n        .withCoreProviders()\n        .create(ignitorOrAppRoot, options!)\n        .createApp('console')\n    )\n  }\n}\n"
  },
  {
    "path": "factories/encryption.ts",
    "content": "/*\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\nexport * from '@boringnode/encryption/factories'\n"
  },
  {
    "path": "factories/events.ts",
    "content": "/*\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\nexport * from '@adonisjs/events/factories'\n"
  },
  {
    "path": "factories/hash.ts",
    "content": "/*\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\nexport * from '@adonisjs/hash/factories'\n"
  },
  {
    "path": "factories/http.ts",
    "content": "/*\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\nexport * from '@adonisjs/http-server/factories'\n"
  },
  {
    "path": "factories/logger.ts",
    "content": "/*\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\nexport * from '@adonisjs/logger/factories'\n"
  },
  {
    "path": "factories/stubs.ts",
    "content": "/*\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 { AppFactory } from '@adonisjs/application/factories'\n\nimport { stubsRoot } from '../index.ts'\nimport type { ApplicationService } from '../src/types.ts'\n\ntype FactoryParameters = {\n  app: ApplicationService\n}\n\n/**\n * Factory for preparing and processing stub templates from the \"@adonisjs/core\" package.\n * This factory is designed for internal testing and development purposes, utilizing\n * the core package's stub root directory.\n *\n * Note: This class is not published as it's intended for internal testing only.\n *\n * @example\n * ```ts\n * const stubsFactory = new StubsFactory()\n *\n * // Prepare a controller stub\n * const preparedStub = await stubsFactory.prepare('controller.stub', {\n *   filename: 'UserController',\n *   entity: { name: 'User' },\n *   resourceful: true\n * })\n *\n * console.log(preparedStub.contents)\n * ```\n */\nexport class StubsFactory {\n  #parameters: Partial<FactoryParameters> = {}\n\n  /**\n   * Returns an instance of application, either from parameters or creates a default one\n   */\n  #getApp() {\n    return this.#parameters.app || new AppFactory().create(new URL('./', import.meta.url))\n  }\n\n  /**\n   * Merge custom factory parameters to override defaults.\n   * This allows you to provide a custom application instance.\n   *\n   * @param params - Parameters to merge\n   * @param params.app - Custom application service instance\n   *\n   * @example\n   * ```ts\n   * const customApp = new AppFactory().create(appRoot)\n   * const stubsFactory = new StubsFactory().merge({ app: customApp })\n   * ```\n   */\n  merge(params: Partial<FactoryParameters>): this {\n    this.#parameters = Object.assign(this.#parameters, params)\n    return this\n  }\n\n  /**\n   * Prepare a stub template with the provided data and return the processed content.\n   * This method initializes the application, loads the stub, and processes it with\n   * the given template variables.\n   *\n   * @param stubPath - Path to the stub file relative to the stubs root\n   * @param data - Template data to populate the stub placeholders\n   *\n   * @example\n   * ```ts\n   * const stubsFactory = new StubsFactory()\n   * const preparedStub = await stubsFactory.prepare('controller.stub', {\n   *   filename: 'UserController',\n   *   entity: {\n   *     name: 'User',\n   *     modelName: 'User',\n   *     pluralName: 'users'\n   *   },\n   *   resourceful: true\n   * })\n   *\n   * // Access the processed stub content\n   * console.log(preparedStub.contents)\n   * ```\n   */\n  async prepare(stubPath: string, data: Record<string, any>) {\n    const app = this.#getApp()\n    await app.init()\n\n    const stubs = await app.stubs.create()\n    const stub = await stubs.build(stubPath, {\n      source: stubsRoot,\n    })\n    return stub.prepare(data)\n  }\n}\n"
  },
  {
    "path": "funding.json",
    "content": "{\n  \"version\": \"v1.0.0\",\n  \"entity\": {\n    \"type\": \"individual\",\n    \"role\": \"owner\",\n    \"name\": \"Harminder Virk\",\n    \"email\": \"virk@adonisjs.com\",\n    \"description\": \"Hi 👋 I'm Harminder Virk, the creator of a family of open-source tools loved by the Node.js community — including AdonisJS, VineJS, Japa, Edge, Lucid ORM, and Youch.\\n\\nI pour my heart into building tools that make developers' lives easier — from crafting elegant APIs to sweating the little details that improve your everyday workflow. My goal is to provide you with strong, reliable building blocks, so you can focus on shipping great products instead of fighting with your stack.\\n\\nBy sponsoring my work, you're helping me keep these projects fast, stable, and well-maintained, while also making room for new ideas that could become your next favorite tool. ❤️\\n\\nCurrent focus\\n\\n- AdonisJS v7\\n- Improving E2E type-safety in AdonisJS applications\\n- Isomorphic VineJS (Validation library)\\n- Lucid Rewrite (ORM)\\nAdonisJS Plus (Sponsors can access Plus at a discounted rate)\",\n    \"webpageUrl\": {\n      \"url\": \"https://adonisjs.com\"\n    }\n  },\n  \"projects\": [\n    {\n      \"guid\": \"adonisjs\",\n      \"name\": \"AdonisJS\",\n      \"description\": \"AdonisJS is a fully typed TypeScript framework that includes everything you need to build robust applications. ORM, authentication, caching, rate limiter, file uploads, and support for testing - all in a single cohesive package\",\n      \"webpageUrl\": {\n        \"url\": \"https://adonisjs.com\"\n      },\n      \"repositoryUrl\": {\n        \"url\": \"https://github.com/adonisjs/core\"\n      },\n      \"licenses\": [\"MIT\"],\n      \"tags\": [\n        \"web-framework\",\n        \"batteries-included\",\n        \"fullstack\",\n        \"typescript\",\n        \"nodejs\",\n        \"javascript\"\n      ]\n    },\n    {\n      \"guid\": \"japa\",\n      \"name\": \"Japa\",\n      \"description\": \"Japa is a testing framework for Node.js that focuses primarily on testing backend applications. Japa does not require using any build tools and is significantly smaller and faster than Jest and Vitest\",\n      \"webpageUrl\": {\n        \"url\": \"https://japa.dev\"\n      },\n      \"repositoryUrl\": {\n        \"url\": \"https://github.com/japa/runner\"\n      },\n      \"licenses\": [\"MIT\"],\n      \"tags\": [\"testing\", \"nodejs\", \"typescript\", \"javascript\"]\n    },\n    {\n      \"guid\": \"vinejs\",\n      \"name\": \"VineJS\",\n      \"description\": \"VineJS is a fast and type-safe validation library for Node.js, designed for validating form data and JSON payloads. It offers 50+ built-in rules, 12 schema types, customizable error messages, and first-class support for extending with custom rules or schema types — all while being one of the fastest libraries in the Node.js ecosystem.\",\n      \"webpageUrl\": {\n        \"url\": \"https://vinejs.dev\"\n      },\n      \"repositoryUrl\": {\n        \"url\": \"https://github.com/vinejs/vine\"\n      },\n      \"licenses\": [\"MIT\"],\n      \"tags\": [\"validation\", \"validator\", \"javascript\", \"nodejs\", \"typescript\"]\n    },\n    {\n      \"guid\": \"edgejs\",\n      \"name\": \"EdgeJS\",\n      \"description\": \"Edge is a simple, Modern, and batteries included template engine for Node.js. In the age of frontend frameworks, Edge allows you to embrace the simplicity of server-side templates.\",\n      \"webpageUrl\": {\n        \"url\": \"https://edgejs.dev\"\n      },\n      \"repositoryUrl\": {\n        \"url\": \"https://github.com/edge-js/edge\"\n      },\n      \"licenses\": [\"MIT\"],\n      \"tags\": [\"templating\", \"template-engine\", \"nodejs\", \"javascript\"]\n    },\n    {\n      \"guid\": \"youch\",\n      \"name\": \"Youch\",\n      \"description\": \"Youch is an error-parsing library that pretty prints JavaScript errors on a web page or the terminal.\",\n      \"webpageUrl\": {\n        \"url\": \"https://github.com/poppinss/youch\"\n      },\n      \"repositoryUrl\": {\n        \"url\": \"https://github.com/poppinss/youch\"\n      },\n      \"licenses\": [\"MIT\"],\n      \"tags\": [\"error-parser\", \"error-printer\", \"pretty-print\", \"javascript\", \"typescript\"]\n    }\n  ],\n  \"funding\": {\n    \"channels\": [\n      {\n        \"guid\": \"gh-sponsors\",\n        \"type\": \"payment-provider\",\n        \"address\": \"https://github.com/sponsors/thetutlage\",\n        \"description\": \"Support me through GitHub Sponsors\"\n      },\n      {\n        \"guid\": \"my-paypal\",\n        \"type\": \"payment-provider\",\n        \"address\": \"https://paypal.me/adonisjs\",\n        \"description\": \"Support me through Paypal. Supports various payment options\"\n      }\n    ],\n    \"plans\": [\n      {\n        \"guid\": \"fan\",\n        \"status\": \"active\",\n        \"name\": \"AdonisJS fan\",\n        \"description\": \"You have directly benefited from my work and want to support me continue working on AdonisJS and other related packages.\",\n        \"amount\": 5,\n        \"currency\": \"USD\",\n        \"frequency\": \"monthly\",\n        \"channels\": [\"gh-sponsors\", \"my-paypal\"]\n      },\n      {\n        \"guid\": \"insiders-individual\",\n        \"status\": \"active\",\n        \"name\": \"Insiders program - Individual\",\n        \"description\": \"All sponsors under this tier are automatically invited to the Insiders program, which provides them with exclusive benefits.\\n\\n- Open-source packages: Gain early access to alpha release packages with complete documentation, allowing you to provide feedback and influence features before public release.\\n- Example projects: Get early access to the source code of production-ready example apps built using AdonisJS. Ask questions around the design decisions, or contribute features to it.\",\n        \"amount\": 19,\n        \"currency\": \"USD\",\n        \"frequency\": \"monthly\",\n        \"channels\": [\"gh-sponsors\", \"my-paypal\"]\n      },\n      {\n        \"guid\": \"insiders-team\",\n        \"status\": \"active\",\n        \"name\": \"Insiders program - Teams\",\n        \"description\": \"Access to Insiders benefits for your entire team (upto 10 members). Along with that you will have access to the following benefits\\n\\n- Prominent logo placement on the AdonisJS website homepage\\n- Featured announcement across AdonisJS social and newsletter channels\\n- Thank-you highlight on AdonisJS social channels\",\n        \"amount\": 499,\n        \"currency\": \"USD\",\n        \"frequency\": \"monthly\",\n        \"channels\": [\"gh-sponsors\", \"my-paypal\"]\n      },\n      {\n        \"guid\": \"community\",\n        \"status\": \"active\",\n        \"name\": \"Community Sponsor\",\n        \"description\": \"Community Sponsors are companies and teams who use AdonisJS and want to give back to the tools they depend on. Every contribution helps sustain development and community support.\\n\\nBenefits:\\n\\n- Prominent logo placement on the AdonisJS website homepage\\n- Thank-you highlight on AdonisJS social channels\",\n        \"amount\": 1000,\n        \"currency\": \"USD\",\n        \"frequency\": \"yearly\",\n        \"channels\": [\"gh-sponsors\", \"my-paypal\"]\n      },\n      {\n        \"guid\": \"core\",\n        \"status\": \"active\",\n        \"name\": \"Core Sponsor\",\n        \"description\": \"Core Sponsors ensure AdonisJS continues to grow and remain dependable for production use. Their support directly funds ongoing maintenance and new integrations.\\n\\nBenefits:\\n\\n- Prominent logo placement on the AdonisJS website homepage\\n- Featured announcement across AdonisJS social and newsletter channels\\n- Thank-you highlight on AdonisJS social channels\",\n        \"amount\": 5000,\n        \"currency\": \"USD\",\n        \"frequency\": \"yearly\",\n        \"channels\": [\"gh-sponsors\", \"my-paypal\"]\n      },\n      {\n        \"guid\": \"prime\",\n        \"status\": \"active\",\n        \"name\": \"Prime Sponsor\",\n        \"description\": \"Prime Sponsors help maintain the momentum behind AdonisJS, supporting consistent releases, improvements, and ecosystem maintenance.\\n\\nBenefits:\\n\\n- Logo featured on the AdonisJS sponsor page\\n- Mention in annual sponsor announcement post\\n- Invitations to private feedback sessions and early previews\\n- Thank-you highlight on AdonisJS social channels\",\n        \"amount\": 10000,\n        \"currency\": \"USD\",\n        \"frequency\": \"yearly\",\n        \"channels\": [\"gh-sponsors\", \"my-paypal\"]\n      },\n      {\n        \"guid\": \"divine\",\n        \"status\": \"active\",\n        \"name\": \"Divine Sponsor\",\n        \"description\": \"Divine Sponsors play a foundational role in keeping the AdonisJS ecosystem strong and evolving. Their support enables full-time open-source work, new feature development, and community initiatives.\\n\\nBenefits:\\n\\n- Prominent logo placement on the AdonisJS website homepage\\n- Featured announcement across AdonisJS social and newsletter channels\\n- Priority access to roadmap insights and private technical sessions\\n- Option to collaborate on ecosystem initiatives\",\n        \"amount\": 25000,\n        \"currency\": \"USD\",\n        \"frequency\": \"yearly\",\n        \"channels\": [\"gh-sponsors\", \"my-paypal\"]\n      }\n    ],\n    \"history\": []\n  }\n}\n"
  },
  {
    "path": "index.ts",
    "content": "/*\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 { errors as aceErrors } from '@adonisjs/ace'\nimport { errors as envErrors } from '@adonisjs/env'\nimport { errors as appErrors } from '@adonisjs/application'\nimport { errors as encryptionErrors } from '@boringnode/encryption'\nimport { errors as httpServerErrors } from '@adonisjs/http-server'\n\nexport { stubsRoot } from './stubs/main.ts'\nexport { inject } from './modules/container.ts'\nexport { Ignitor } from './src/ignitor/main.ts'\nexport { configProvider } from './src/config_provider.ts'\nexport { indexEntities } from './src/assembler_hooks/index_entities.ts'\n\n/**\n * Aggregated errors from all modules.\n */\nexport const errors: typeof encryptionErrors &\n  typeof httpServerErrors &\n  typeof appErrors &\n  typeof aceErrors &\n  typeof envErrors = {\n  ...encryptionErrors,\n  ...httpServerErrors,\n  ...appErrors,\n  ...aceErrors,\n  ...envErrors,\n}\n\n/**\n * Pretty prints an error with colorful output using\n * Youch terminal\n */\nexport async function prettyPrintError(error: any) {\n  if (error && typeof error === 'object' && error.code === 'E_DUMP_DIE_EXCEPTION') {\n    console.error(error)\n    return\n  }\n\n  try {\n    const { Youch } = await import('youch')\n    const youch = new Youch()\n    console.error(await youch.toANSI(error))\n  } catch {\n    console.error(error)\n  }\n}\n"
  },
  {
    "path": "modules/ace/codemods.ts",
    "content": "/*\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 { isAbsolute } from 'node:path'\nimport { EventEmitter } from 'node:events'\nimport { readFile } from 'node:fs/promises'\nimport { EnvEditor } from '@adonisjs/env/editor'\nimport type { UIPrimitives } from '@adonisjs/ace/types'\nimport type { CodeTransformer } from '@adonisjs/assembler/code_transformer'\nimport type {\n  MiddlewareNode,\n  EnvValidationNode,\n  BouncerPolicyNode,\n  SupportedPackageManager,\n} from '@adonisjs/assembler/types'\n\nimport debug from '../../src/debug.ts'\nimport type { Application } from '../app.ts'\nimport stringHelpers from '../../src/helpers/string.ts'\nimport { type GeneratedStub } from '../../types/app.ts'\n\n/**\n * Codemods class for programmatically modifying AdonisJS source files.\n * This class provides APIs to modify configuration files, register middleware,\n * generate stubs, and install packages.\n *\n * The codemod APIs rely on the \"@adonisjs/assembler\" package, which must be\n * installed as a dependency in the user application.\n *\n * @example\n * ```ts\n * const codemods = new Codemods(app, logger)\n *\n * // Generate a controller from a stub\n * await codemods.makeUsingStub(stubsRoot, 'controller.stub', {\n *   filename: 'UserController',\n *   entity: { name: 'User' }\n * })\n *\n * // Install packages\n * await codemods.installPackages([\n *   { name: '@adonisjs/lucid', isDevDependency: false }\n * ])\n * ```\n */\nexport class Codemods extends EventEmitter {\n  /**\n   * Reference to lazily imported assembler code transformer\n   */\n  #codeTransformer?: CodeTransformer\n\n  /**\n   * Reference to AdonisJS application\n   */\n  #app: Application<any>\n\n  /**\n   * Reference to CLI logger to write logs\n   */\n  #cliLogger: UIPrimitives['logger']\n\n  /**\n   * Overwrite existing files when generating files\n   * from stubs\n   */\n  overwriteExisting = false\n\n  /**\n   * Display verbose logs for package installation\n   */\n  verboseInstallOutput = false\n\n  constructor(app: Application<any>, cliLogger: UIPrimitives['logger']) {\n    super()\n    this.#app = app\n    this.#cliLogger = cliLogger\n  }\n\n  /**\n   * - Lazily import the code transformer\n   * - Return a fresh or reused instance of the code transformer\n   */\n  async #getCodeTransformer() {\n    try {\n      if (!this.#codeTransformer) {\n        const { CodeTransformer } = await import('@adonisjs/assembler/code_transformer')\n        this.#codeTransformer = new CodeTransformer(this.#app.appRoot)\n      }\n\n      return this.#codeTransformer\n    } catch {\n      return null\n    }\n  }\n\n  /**\n   * Returns the installation command for different\n   * package managers\n   */\n  #getInstallationCommands(packages: string[], packageManager: string, isDev: boolean) {\n    if (!packages.length) {\n      return ''\n    }\n\n    const colors = this.#cliLogger.getColors()\n    const devFlag = isDev ? ' -D' : ''\n\n    switch (packageManager) {\n      case 'yarn':\n      case 'yarn@berry':\n        return `${colors.yellow(`yarn add${devFlag}`)} ${packages.join(' ')}`\n      case 'pnpm':\n        return `${colors.yellow(`pnpm add${devFlag}`)} ${packages.join(' ')}`\n      case 'npm':\n      default:\n        return `${colors.yellow(`npm i${devFlag}`)} ${packages.join(' ')}`\n    }\n  }\n\n  /**\n   * Define one or more environment variables in the .env file\n   *\n   * @param environmentVariables - Key-value pairs of environment variables\n   * @param options - Configuration options\n   * @param options.omitFromExample - Keys to exclude from .env.example file\n   *\n   * @example\n   * ```ts\n   * await codemods.defineEnvVariables({\n   *   DB_CONNECTION: 'mysql',\n   *   DB_HOST: 'localhost',\n   *   SECRET_KEY: 'abc123'\n   * }, {\n   *   omitFromExample: ['SECRET_KEY']\n   * })\n   * ```\n   */\n  async defineEnvVariables<T extends Record<string, number | string | boolean>>(\n    environmentVariables: T,\n    options?: { omitFromExample?: Array<keyof T> }\n  ) {\n    const editor = new EnvEditor(this.#app.appRoot)\n    await editor.load()\n\n    Object.keys(environmentVariables).forEach((key) => {\n      const value = environmentVariables[key]\n      editor.add(key, value, options?.omitFromExample?.includes(key))\n    })\n\n    await editor.save()\n    this.#cliLogger.action('update .env file').succeeded()\n  }\n\n  /**\n   * Returns the TsMorph project instance for advanced AST manipulations.\n   * See https://ts-morph.com/ for documentation.\n   *\n   * @example\n   * ```ts\n   * const project = await codemods.getTsMorphProject()\n   * if (project) {\n   *   const sourceFile = project.getSourceFile('app/controllers/user_controller.ts')\n   *   // Perform advanced AST operations\n   * }\n   * ```\n   */\n  async getTsMorphProject(): Promise<CodeTransformer['project'] | undefined> {\n    const transformer = await this.#getCodeTransformer()\n    if (!transformer) {\n      this.#cliLogger.warning(\n        'Cannot create CodeTransformer. Install \"@adonisjs/assembler\" to modify source files'\n      )\n      return\n    }\n\n    return transformer.project\n  }\n\n  /**\n   * Define validations for the environment variables in the start/env.ts file.\n   * This method updates the environment validation schema using the assembler.\n   *\n   * @param validations - Validation schema node for environment variables\n   *\n   * @example\n   * ```ts\n   * await codemods.defineEnvValidations({\n   *   NODE_ENV: 'Env.schema.enum([\"development\", \"production\", \"test\"] as const)',\n   *   PORT: 'Env.schema.number()',\n   *   HOST: 'Env.schema.string({ format: \"host\" })'\n   * })\n   * ```\n   */\n  async defineEnvValidations(validations: EnvValidationNode) {\n    const transformer = await this.#getCodeTransformer()\n    if (!transformer) {\n      this.#cliLogger.warning(\n        'Cannot update \"start/env.ts\" file. Install \"@adonisjs/assembler\" to modify source files'\n      )\n      return\n    }\n\n    const action = this.#cliLogger.action('update start/env.ts file')\n    try {\n      await transformer.defineEnvValidations(validations)\n      action.succeeded()\n    } catch (error) {\n      this.emit('error', error)\n      action.failed(error.message)\n    }\n  }\n\n  /**\n   * Register middleware in the start/kernel.ts file.\n   * This method adds middleware to the specified stack (server, router, or named).\n   *\n   * @param stack - The middleware stack to register to ('server' | 'router' | 'named')\n   * @param middleware - Array of middleware nodes to register\n   *\n   * @example\n   * ```ts\n   * await codemods.registerMiddleware('server', [\n   *   {\n   *     name: 'cors',\n   *     path: '@adonisjs/cors/cors_middleware'\n   *   }\n   * ])\n   * ```\n   */\n  async registerMiddleware(stack: 'server' | 'router' | 'named', middleware: MiddlewareNode[]) {\n    const transformer = await this.#getCodeTransformer()\n    if (!transformer) {\n      this.#cliLogger.warning(\n        'Cannot update \"start/kernel.ts\" file. Install \"@adonisjs/assembler\" to modify source files'\n      )\n      return\n    }\n\n    const action = this.#cliLogger.action('update start/kernel.ts file')\n    try {\n      await transformer.addMiddlewareToStack(stack, middleware)\n      action.succeeded()\n    } catch (error) {\n      this.emit('error', error)\n      action.failed(error.message)\n    }\n  }\n\n  /**\n   * Register bouncer policies to the list of policies collection exported from\n   * the \"app/policies/main.ts\" file. This method adds new policy definitions\n   * to the policies export.\n   *\n   * @param policies - Array of policy nodes to register\n   *\n   * @example\n   * ```ts\n   * await codemods.registerPolicies([\n   *   {\n   *     name: 'UserPolicy',\n   *     path: '#policies/user_policy'\n   *   }\n   * ])\n   * ```\n   */\n  async registerPolicies(policies: BouncerPolicyNode[]) {\n    const transformer = await this.#getCodeTransformer()\n    if (!transformer) {\n      this.#cliLogger.warning(\n        'Cannot update \"app/policies/main.ts\" file. Install \"@adonisjs/assembler\" to modify source files'\n      )\n      return\n    }\n\n    const action = this.#cliLogger.action('update app/policies/main.ts file')\n    try {\n      await transformer.addPolicies(policies)\n      action.succeeded()\n    } catch (error) {\n      this.emit('error', error)\n      action.failed(error.message)\n    }\n  }\n\n  /**\n   * Update the adonisrc.ts file with new configuration settings.\n   * This method allows modification of the AdonisJS runtime configuration.\n   *\n   * @param params - Parameters for updating the RC file (varies based on update type)\n   *\n   * @example\n   * ```ts\n   * await codemods.updateRcFile((rcFile) => {\n   *   rcFile.addCommand('make:custom')\n   *   rcFile.addPreloadFile('#app/events/main')\n   * })\n   * ```\n   */\n  async updateRcFile(...params: Parameters<CodeTransformer['updateRcFile']>) {\n    const transformer = await this.#getCodeTransformer()\n    if (!transformer) {\n      this.#cliLogger.warning(\n        'Cannot update \"adonisrc.ts\" file. Install \"@adonisjs/assembler\" to modify source files'\n      )\n      return\n    }\n\n    const action = this.#cliLogger.action('update adonisrc.ts file')\n    try {\n      await transformer.updateRcFile(...params)\n      action.succeeded()\n    } catch (error) {\n      this.emit('error', error)\n      action.failed(error.message)\n    }\n  }\n\n  /**\n   * Register a new Vite plugin in the vite.config.ts file.\n   * This method adds plugin configuration to the Vite build configuration.\n   *\n   * @param params - Parameters for adding the Vite plugin (varies based on plugin type)\n   *\n   * @example\n   * ```ts\n   * await codemods.registerVitePlugin({\n   *   name: 'vue',\n   *   import: 'import vue from \"@vitejs/plugin-vue\"',\n   *   options: '()'\n   * })\n   * ```\n   */\n  async registerVitePlugin(...params: Parameters<CodeTransformer['addVitePlugin']>) {\n    const transformer = await this.#getCodeTransformer()\n    if (!transformer) {\n      this.#cliLogger.warning(\n        'Cannot update \"vite.config.ts\" file. Install \"@adonisjs/assembler\" to modify source files'\n      )\n      return\n    }\n\n    const action = this.#cliLogger.action('update vite.config.ts file')\n    try {\n      await transformer.addVitePlugin(...params)\n      action.succeeded()\n    } catch (error) {\n      this.emit('error', error)\n      action.failed(error.message)\n    }\n  }\n\n  /**\n   * Register a new Japa plugin in the tests/bootstrap.ts file.\n   * This method adds plugin configuration to the test runner setup.\n   *\n   * @param params - Parameters for adding the Japa plugin (varies based on plugin type)\n   *\n   * @example\n   * ```ts\n   * await codemods.registerJapaPlugin({\n   *   name: 'expect',\n   *   import: 'import { expect } from \"@japa/expect\"'\n   * })\n   * ```\n   */\n  async registerJapaPlugin(...params: Parameters<CodeTransformer['addJapaPlugin']>) {\n    const transformer = await this.#getCodeTransformer()\n    if (!transformer) {\n      this.#cliLogger.warning(\n        'Cannot update \"tests/bootstrap.ts\" file. Install \"@adonisjs/assembler\" to modify source files'\n      )\n      return\n    }\n\n    const action = this.#cliLogger.action('update tests/bootstrap.ts file')\n    try {\n      await transformer.addJapaPlugin(...params)\n      action.succeeded()\n    } catch (error) {\n      this.emit('error', error)\n      action.failed(error.message)\n    }\n  }\n\n  /**\n   * Add a new validator file to the validators directory.\n   * This method creates a new validator file with the provided definition.\n   *\n   * @param params - Parameters for adding the validator\n   *\n   * @example\n   * ```ts\n   * await codemods.addValidator({\n   *   validatorFileName: 'create_user',\n   *   exportName: 'createUserValidator',\n   *   contents: 'export const createUserValidator = vine.compile(...)'\n   * })\n   * ```\n   */\n  async addValidator(...params: Parameters<CodeTransformer['addValidator']>) {\n    const transformer = await this.#getCodeTransformer()\n    if (!transformer) {\n      this.#cliLogger.warning(\n        'Cannot create validator file. Install \"@adonisjs/assembler\" to modify source files'\n      )\n      return\n    }\n\n    const action = this.#cliLogger.action('create validator file')\n    try {\n      await transformer.addValidator(...params)\n      action.succeeded()\n    } catch (error) {\n      this.emit('error', error)\n      action.failed(error.message)\n    }\n  }\n\n  /**\n   * Add a new rate limiter file to the limiters directory.\n   * This method creates a new limiter file with the provided definition.\n   *\n   * @param params - Parameters for adding the limiter\n   *\n   * @example\n   * ```ts\n   * await codemods.addLimiter({\n   *   limiterFileName: 'api_throttle',\n   *   exportName: 'apiThrottleLimiter',\n   *   contents: 'export const apiThrottleLimiter = limiter.define(...)'\n   * })\n   * ```\n   */\n  async addLimiter(...params: Parameters<CodeTransformer['addLimiter']>) {\n    const transformer = await this.#getCodeTransformer()\n    if (!transformer) {\n      this.#cliLogger.warning(\n        'Cannot create limiter file. Install \"@adonisjs/assembler\" to modify source files'\n      )\n      return\n    }\n\n    const action = this.#cliLogger.action('create limiter file')\n    try {\n      await transformer.addLimiter(...params)\n      action.succeeded()\n    } catch (error) {\n      this.emit('error', error)\n      action.failed(error.message)\n    }\n  }\n\n  /**\n   * Add mixins to a model class.\n   * This method adds mixin calls to the specified model file.\n   *\n   * @param params - Parameters for adding model mixins (modelFileName, mixins array)\n   *\n   * @example\n   * ```ts\n   * await codemods.addModelMixins('user', [\n   *   {\n   *     name: 'SoftDeletes',\n   *     importPath: '@adonisjs/lucid/mixins/soft_deletes',\n   *     importType: 'named'\n   *   }\n   * ])\n   * ```\n   */\n  async addModelMixins(...params: Parameters<CodeTransformer['addModelMixins']>) {\n    const transformer = await this.#getCodeTransformer()\n    if (!transformer) {\n      this.#cliLogger.warning(\n        'Cannot update model file. Install \"@adonisjs/assembler\" to modify source files'\n      )\n      return\n    }\n\n    const action = this.#cliLogger.action('update model file')\n    try {\n      await transformer.addModelMixins(...params)\n      action.succeeded()\n    } catch (error) {\n      this.emit('error', error)\n      action.failed(error.message)\n    }\n  }\n\n  /**\n   * Add a new method to an existing controller class.\n   * This method injects a new method into the specified controller file.\n   *\n   * @param params - Parameters for adding the controller method\n   *\n   * @example\n   * ```ts\n   * await codemods.addControllerMethod({\n   *   controllerFileName: 'users_controller',\n   *   className: 'UsersController',\n   *   name: 'destroy',\n   *   contents: 'async destroy({ params, response }: HttpContext) { ... }',\n   *   imports: [\n   *     { isType: false, isNamed: true, name: 'HttpContext', path: '@adonisjs/core/http' }\n   *   ]\n   * })\n   * ```\n   */\n  async addControllerMethod(...params: Parameters<CodeTransformer['addControllerMethod']>) {\n    const transformer = await this.#getCodeTransformer()\n    if (!transformer) {\n      this.#cliLogger.warning(\n        'Cannot update controller file. Install \"@adonisjs/assembler\" to modify source files'\n      )\n      return\n    }\n\n    const action = this.#cliLogger.action('update controller file')\n    try {\n      await transformer.addControllerMethod(...params)\n      action.succeeded()\n    } catch (error) {\n      this.emit('error', error)\n      action.failed(error.message)\n    }\n  }\n\n  /**\n   * Generate a file using a stub template\n   *\n   * @param stubsRoot - Root directory containing stub files\n   * @param stubPath - Path to the specific stub file\n   * @param stubState - Template variables for stub generation\n   *\n   * @example\n   * ```ts\n   * const result = await codemods.makeUsingStub(\n   *   './stubs',\n   *   'controller.stub',\n   *   {\n   *     filename: 'UserController',\n   *     entity: { name: 'User', modelName: 'User' },\n   *     resourceful: true\n   *   }\n   * )\n   * ```\n   */\n  async makeUsingStub(\n    stubsRoot: string,\n    stubPath: string,\n    stubState: Record<string, any>,\n    options?: {\n      contentsFromFile?: string\n    }\n  ): Promise<GeneratedStub> {\n    const stubs = await this.#app.stubs.create()\n    const stub = await stubs.build(stubPath, { source: stubsRoot })\n\n    /**\n     * Overwrite the contents of the stub output with the contents\n     * of the provided file.\n     */\n    if (options?.contentsFromFile) {\n      const source = isAbsolute(options.contentsFromFile)\n        ? options.contentsFromFile\n        : this.#app.makePath(options.contentsFromFile)\n\n      try {\n        debug('overwriting stub output with contents from file %s', source)\n        stub.replaceWith(await readFile(source, 'utf-8'))\n      } catch (error) {\n        if (error.code === 'ENOENT') {\n          throw new Error(\n            `Cannot replace stub output with \"${options.contentsFromFile}\" file contents as the file is missing`,\n            { cause: error }\n          )\n        }\n        throw error\n      }\n    }\n\n    const output = await stub.generate({ force: this.overwriteExisting, ...stubState })\n    debug('generating file %O', output)\n\n    const entityFileName = stringHelpers.toUnixSlash(this.#app.relativePath(output.destination))\n    const result = { ...output, relativeFileName: entityFileName }\n\n    if (output.status === 'skipped') {\n      this.#cliLogger.action(`create ${entityFileName}`).skipped(output.skipReason)\n      return result\n    }\n\n    this.#cliLogger.action(`create ${entityFileName}`).succeeded()\n    return result\n  }\n\n  /**\n   * Install packages using the detected or specified package manager.\n   * Automatically detects npm, yarn, or pnpm and installs dependencies accordingly.\n   * You can specify version of each package by setting it in the name like '@adonisjs/lucid'.\n   *\n   * @param packages - Array of packages with their dependency type\n   * @param packageManager - Optional package manager to use (auto-detected if not provided)\n   *\n   * @example\n   * ```ts\n   * const success = await codemods.installPackages([\n   *   { name: '@adonisjs/lucid', isDevDependency: false },\n   *   { name: '@types/node', isDevDependency: true }\n   * ])\n   * ```\n   */\n  async installPackages(\n    packages: { name: string; isDevDependency: boolean }[],\n    packageManager?: SupportedPackageManager | 'pnpm@6' | 'deno'\n  ): Promise<boolean> {\n    const transformer = await this.#getCodeTransformer()\n    const appPath = this.#app.makePath()\n    const colors = this.#cliLogger.getColors()\n    const devDependencies = packages.filter((pkg) => pkg.isDevDependency).map(({ name }) => name)\n    const dependencies = packages.filter((pkg) => !pkg.isDevDependency).map(({ name }) => name)\n\n    if (!transformer) {\n      this.#cliLogger.warning(\n        'Cannot install packages. Install \"@adonisjs/assembler\" or manually install following packages'\n      )\n      this.#cliLogger.log(`devDependencies: ${devDependencies.join(',')}`)\n      this.#cliLogger.log(`dependencies: ${dependencies.join(',')}`)\n      return false\n    }\n\n    packageManager = packageManager ?? (await transformer.detectPackageManager(appPath)) ?? 'npm'\n    const spinner = this.#cliLogger.await(`installing dependencies using ${packageManager} `)\n\n    const silentLogs = !this.verboseInstallOutput\n    if (silentLogs) {\n      spinner.start()\n    }\n\n    try {\n      if (dependencies.length) {\n        await transformer.installPackage(dependencies, {\n          cwd: appPath,\n          silent: silentLogs,\n          packageManager,\n        })\n      }\n\n      if (devDependencies.length) {\n        await transformer.installPackage(devDependencies, {\n          dev: true,\n          cwd: appPath,\n          silent: silentLogs,\n          packageManager,\n        })\n      }\n\n      if (silentLogs) {\n        spinner.stop()\n      }\n\n      this.#cliLogger.success('Packages installed')\n      this.#cliLogger.log(\n        devDependencies.map((dependency) => `    ${colors.dim('dev')} ${dependency} `).join('\\n')\n      )\n      this.#cliLogger.log(\n        dependencies.map((dependency) => `    ${colors.dim('prod')} ${dependency} `).join('\\n')\n      )\n      return true\n    } catch (error) {\n      if (silentLogs) {\n        spinner.update('unable to install dependencies')\n        spinner.stop()\n      }\n      this.#cliLogger.fatal(error)\n      this.emit('error', error)\n      return false\n    }\n  }\n\n  /**\n   * List the packages that should be installed manually.\n   * This method displays installation commands for different package managers\n   * when automatic installation is not available or desired.\n   *\n   * @param packages - Array of packages with their dependency type\n   *\n   * @example\n   * ```ts\n   * await codemods.listPackagesToInstall([\n   *   { name: '@adonisjs/lucid', isDevDependency: false },\n   *   { name: '@types/node', isDevDependency: true }\n   * ])\n   * // Output:\n   * // Please install following packages\n   * // npm i -D @types/node\n   * // npm i @adonisjs/lucid\n   * ```\n   */\n  async listPackagesToInstall(packages: { name: string; isDevDependency: boolean }[]) {\n    const appPath = this.#app.makePath()\n    const devDependencies = packages.filter((pkg) => pkg.isDevDependency).map(({ name }) => name)\n    const dependencies = packages.filter((pkg) => !pkg.isDevDependency).map(({ name }) => name)\n\n    let packageManager: string | null = null\n    const transformer = await this.#getCodeTransformer()\n    if (transformer) packageManager = await transformer.detectPackageManager(appPath)\n\n    this.#cliLogger.log('Please install following packages')\n    this.#cliLogger.log(\n      this.#getInstallationCommands(devDependencies, packageManager || 'npm', true)\n    )\n    this.#cliLogger.log(this.#getInstallationCommands(dependencies, packageManager || 'npm', false))\n  }\n}\n"
  },
  {
    "path": "modules/ace/commands.ts",
    "content": "/*\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 { BaseCommand as AceBaseCommand, ListCommand as AceListCommand } from '@adonisjs/ace'\n\nimport { type Kernel } from './kernel.ts'\nimport type { ApplicationService } from '../../src/types.ts'\nimport type { CommandOptions, ParsedOutput, UIPrimitives } from '../../types/ace.ts'\n\n/**\n * The base command class for creating custom Ace commands in AdonisJS applications.\n * This class extends the base Ace command with AdonisJS-specific functionality like\n * dependency injection and application lifecycle management.\n *\n * @example\n * ```ts\n * export default class MakeUser extends BaseCommand {\n *   static commandName = 'make:user'\n *   static description = 'Create a new user'\n *\n *   async run() {\n *     this.logger.info('Creating user...')\n *     // Command implementation\n *   }\n * }\n * ```\n */\nexport class BaseCommand extends AceBaseCommand {\n  static options: CommandOptions = {}\n\n  get staysAlive() {\n    return (this.constructor as typeof BaseCommand).options.staysAlive\n  }\n\n  get startApp() {\n    return (this.constructor as typeof BaseCommand).options.startApp\n  }\n\n  constructor(\n    public app: ApplicationService,\n    public kernel: Kernel,\n    parsed: ParsedOutput,\n    ui: UIPrimitives,\n    prompt: Kernel['prompt']\n  ) {\n    super(kernel, parsed, ui, prompt)\n  }\n\n  /**\n   * Creates the codemods module to modify source files programmatically.\n   * This method provides access to AST-based code transformations.\n   *\n   * @example\n   * ```ts\n   * const codemods = await this.createCodemods()\n   * await codemods.makeUsingStub(stubsRoot, 'controller.stub', {\n   *   filename: 'UserController',\n   *   entity: { name: 'User' }\n   * })\n   * ```\n   */\n  async createCodemods() {\n    const { Codemods } = await import('./codemods.js')\n    const codemods = new Codemods(this.app, this.logger)\n    codemods.on('error', () => {\n      this.exitCode = 1\n    })\n\n    return codemods\n  }\n\n  /**\n   * The prepare template method is used to prepare the\n   * state for the command. This is the first method\n   * executed on a given command instance.\n   */\n  prepare?(..._: any[]): any\n\n  /**\n   * The interact template method is used to display the prompts\n   * to the user. The method is called after the prepare\n   * method.\n   */\n  interact?(..._: any[]): any\n\n  /**\n   * The completed method is the method invoked after the command\n   * finishes or results in an error.\n   *\n   * You can access the command error using the `this.error` property.\n   * Returning `true` from completed method supresses the error\n   * reporting to the kernel layer.\n   */\n  completed?(..._: any[]): any\n\n  /**\n   * Executes the lifecycle hooks and the run method from the command\n   */\n  async exec() {\n    this.hydrate()\n\n    try {\n      /**\n       * Executing the template methods\n       */\n      this.prepare && (await this.app.container.call<any, 'prepare'>(this, 'prepare'))\n      this.interact && (await this.app.container.call<any, 'interact'>(this, 'interact'))\n      const result = await this.app.container.call<BaseCommand, 'run'>(this, 'run')\n\n      /**\n       * Set exit code\n       */\n      this.result = this.result === undefined ? result : this.result\n      this.exitCode = this.exitCode ?? 0\n    } catch (error) {\n      this.error = error\n      this.exitCode = this.exitCode ?? 1\n    }\n\n    /**\n     * Run the completed method (if exists) and check if has handled\n     * the error\n     */\n    let errorHandled = this.completed\n      ? await this.app.container.call<any, 'completed'>(this, 'completed')\n      : false\n\n    if (this.error && !errorHandled) {\n      await this.kernel.errorHandler.render(this.error, this.kernel)\n    }\n\n    return this.result\n  }\n\n  /**\n   * Terminate the application gracefully. This method should be preferred over\n   * calling `app.terminate()` directly as it only triggers termination when\n   * the current command is the main command responsible for the process.\n   *\n   * @example\n   * ```ts\n   * export default class SomeCommand extends BaseCommand {\n   *   async run() {\n   *     // Do some work\n   *     await this.terminate()\n   *   }\n   * }\n   * ```\n   */\n  async terminate() {\n    if (this.kernel.getMainCommand() === this) {\n      await this.app.terminate()\n    }\n  }\n}\n\n/**\n * The List command is used to display a list of available commands.\n * This command extends the base Ace ListCommand with AdonisJS-specific functionality.\n */\nexport class ListCommand extends AceListCommand implements BaseCommand {\n  static options: CommandOptions = {}\n\n  get staysAlive() {\n    return (this.constructor as typeof BaseCommand).options.staysAlive\n  }\n\n  get startApp() {\n    return (this.constructor as typeof BaseCommand).options.startApp\n  }\n\n  constructor(\n    public app: ApplicationService,\n    public kernel: Kernel,\n    parsed: ParsedOutput,\n    ui: UIPrimitives,\n    prompt: Kernel['prompt']\n  ) {\n    super(kernel, parsed, ui, prompt)\n  }\n\n  /**\n   * Auto-select JSON output when running inside an AI agent\n   * and no explicit format flag is provided.\n   */\n  async run() {\n    if (!this.json && this.app.runningInAIAgent) {\n      this.json = true\n    }\n    return super.run()\n  }\n\n  /**\n   * Creates the codemods module to modify source files programmatically.\n   * This method provides access to AST-based code transformations.\n   */\n  async createCodemods() {\n    const { Codemods } = await import('./codemods.js')\n    return new Codemods(this.app, this.logger)\n  }\n\n  /**\n   * Terminate the app. A command should prefer calling this method\n   * over the \"app.terminate\", because this method only triggers\n   * app termination when the current command is in the charge\n   * of the process.\n   */\n  async terminate() {\n    if (this.kernel.getMainCommand() === this) {\n      await this.app.terminate()\n    }\n  }\n}\n"
  },
  {
    "path": "modules/ace/create_kernel.ts",
    "content": "/*\n * @adonisjs/ace\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 { Kernel } from './main.ts'\nimport type { ApplicationService } from '../../src/types.ts'\nimport { FsLoader, HelpCommand, type BaseCommand } from '../../modules/ace/main.ts'\n\n/**\n * Create and configure an Ace command kernel for AdonisJS applications.\n * This function abstracts the kernel setup logic and can be used in different\n * environments with appropriate configurations.\n *\n * - In console environment, Ace manages the lifecycle of the process\n * - In other environments, Ace can be pulled from the container to run commands\n *\n * @param app - The AdonisJS application service instance\n * @param commandName - Optional specific command name for optimized loading\n *\n * @example\n * ```ts\n * const app = new Application(new URL('../', import.meta.url))\n * const kernel = createAceKernel(app)\n *\n * // Run a specific command\n * await kernel.handle(['make:controller', 'UserController'])\n * ```\n */\nexport function createAceKernel(app: ApplicationService, commandName?: string) {\n  const kernel = new Kernel(app)\n  kernel.info.set('binary', 'node ace')\n\n  /**\n   * Lazy import commands mentioned in the \"commands\" array\n   * of rcFile\n   */\n  app.rcFile.commands.forEach((commandModule) => {\n    kernel.addLoader(() =>\n      typeof commandModule === 'function' ? commandModule() : app.import(commandModule)\n    )\n  })\n\n  /**\n   * When we know the command we are running ahead of time, then we\n   * defer loading the application commands if the command has\n   * already been registered by other loaders.\n   */\n  const fsLoader = new FsLoader<typeof BaseCommand>(app.commandsPath())\n  kernel.addLoader({\n    async getMetaData() {\n      if (!commandName || !kernel.getCommand(commandName)) {\n        return fsLoader.getMetaData()\n      }\n      return []\n    },\n    getCommand(command) {\n      return fsLoader.getCommand(command)\n    },\n  })\n\n  /**\n   * Custom global flags\n   */\n  kernel.defineFlag('ansi', {\n    type: 'boolean',\n    showNegatedVariantInHelp: true,\n    description: 'Force enable or disable colorful output',\n  })\n\n  kernel.defineFlag('help', {\n    type: 'boolean',\n    description: HelpCommand.description,\n  })\n\n  /**\n   * Flag listener to turn colors on/off\n   */\n  kernel.on('ansi', (_, $kernel, parsed) => {\n    if (parsed.flags.ansi === false) {\n      $kernel.ui.switchMode('silent')\n    }\n\n    if (parsed.flags.ansi === true) {\n      $kernel.ui.switchMode('normal')\n    }\n  })\n\n  /**\n   * Flag listener to display the help\n   */\n  kernel.on('help', async (command, $kernel, parsed) => {\n    parsed.args.unshift(command.commandName)\n    const help = new HelpCommand($kernel, parsed, kernel.ui, kernel.prompt)\n    await help.exec()\n    return $kernel.shortcircuit()\n  })\n\n  return kernel\n}\n"
  },
  {
    "path": "modules/ace/kernel.ts",
    "content": "/*\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 { Kernel as AceKernel } from '@adonisjs/ace'\nimport { type BaseCommand, ListCommand } from './commands.ts'\nimport type { ApplicationService } from '../../src/types.ts'\n\n/**\n * The Ace command kernel for AdonisJS applications. This kernel extends the base\n * Ace kernel with AdonisJS-specific functionality like dependency injection and\n * application lifecycle management.\n *\n * @example\n * ```ts\n * const app = new Application(new URL('../', import.meta.url))\n * const kernel = new Kernel(app)\n *\n * await kernel.handle(['make:controller', 'UserController'])\n * ```\n */\nexport class Kernel extends AceKernel<typeof BaseCommand> {\n  /**\n   * Create a new Ace kernel instance\n   *\n   * @param app - The AdonisJS application instance\n   */\n  constructor(public app: ApplicationService) {\n    super(ListCommand, {\n      create: async (command, parsedOutput, $kernel) => {\n        return app.container.make(command, [app, $kernel, parsedOutput, $kernel.ui, $kernel.prompt])\n      },\n\n      run: (command) => command.exec(),\n    })\n  }\n}\n"
  },
  {
    "path": "modules/ace/main.ts",
    "content": "/*\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\n/**\n * Ace command line interface module for AdonisJS applications.\n * Provides the kernel, base commands, and utilities for building CLI applications.\n *\n * @example\n * // Create and use the Ace kernel\n * import { Kernel, BaseCommand } from '@adonisjs/core/ace'\n *\n * const kernel = new Kernel(app)\n * await kernel.handle(['make:controller', 'UserController'])\n *\n * @example\n * // Create a custom command\n * import { BaseCommand, args, flags } from '@adonisjs/core/ace'\n *\n * export default class MakeUser extends BaseCommand {\n *   static commandName = 'make:user'\n *   static description = 'Create a new user'\n *\n *   @args.string({ description: 'Name of the user' })\n *   declare name: string\n *\n *   @flags.boolean({ description: 'Create admin user' })\n *   declare admin: boolean\n *\n *   async run() {\n *     this.logger.info(`Creating user: ${this.name}`)\n *   }\n * }\n */\nexport { Kernel } from './kernel.ts'\nexport { BaseCommand, ListCommand } from './commands.ts'\nexport {\n  args,\n  flags,\n  errors,\n  Parser,\n  FsLoader,\n  ListLoader,\n  cliHelpers,\n  HelpCommand,\n  IndexGenerator,\n  tracingChannels,\n} from '@adonisjs/ace'\n"
  },
  {
    "path": "modules/app.ts",
    "content": "/*\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\n/**\n * Application module re-exports all functionality from @adonisjs/application.\n * This includes the main Application class and related types for managing\n * the AdonisJS application lifecycle, container bindings, and service providers.\n *\n * @example\n * // Import the Application class\n * import { Application } from '@adonisjs/core/app'\n *\n * const app = new Application(new URL('../', import.meta.url))\n * await app.init()\n * await app.boot()\n *\n * @example\n * // Import application types\n * import type { ApplicationService, ContainerBindings } from '@adonisjs/core/app'\n */\nexport * from '@adonisjs/application'\n"
  },
  {
    "path": "modules/bodyparser/bodyparser_middleware.ts",
    "content": "/*\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 { BodyParserMiddleware } from '@adonisjs/bodyparser/bodyparser_middleware'\n\n/**\n * Default export allows lazy importing middleware with\n * destructuring the named exports\n */\nexport default BodyParserMiddleware\n"
  },
  {
    "path": "modules/bodyparser/main.ts",
    "content": "/*\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\nexport * from '@adonisjs/bodyparser'\n"
  },
  {
    "path": "modules/config.ts",
    "content": "/*\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\n/**\n * Configuration module re-exports all functionality from @adonisjs/config.\n * This includes the Config class and related types for managing application\n * configuration files and environment-specific settings.\n *\n * @example\n * // Import the Config class\n * import { Config } from '@adonisjs/core/config'\n *\n * const config = new Config()\n * config.set('database.connection', 'mysql')\n * const dbConnection = config.get('database.connection')\n *\n * @example\n * // Import configuration types\n * import type { ConfigProvider } from '@adonisjs/core/config'\n */\nexport * from '@adonisjs/config'\n"
  },
  {
    "path": "modules/container.ts",
    "content": "/*\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\nexport * from '@adonisjs/fold'\n"
  },
  {
    "path": "modules/dumper/define_config.ts",
    "content": "/*\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 ConsoleDumpConfig } from '@poppinss/dumper/console/types'\nimport { type HTMLDumpConfig } from '@poppinss/dumper/html/types'\n\n/**\n * Define configuration for the dumper service exported by the\n * \"@adonisjs/core/services/dumper\" module. This function allows\n * you to customize HTML and console output formatting options.\n *\n * @param dumperConfig - Configuration object with HTML and console options\n * @param dumperConfig.html - HTML output formatting configuration\n * @param dumperConfig.console - Console output formatting configuration\n *\n * @example\n * ```ts\n * export default defineConfig({\n *   html: {\n *     showHidden: true,\n *     depth: 5,\n *     colors: true\n *   },\n *   console: {\n *     showHidden: false,\n *     depth: 3,\n *     collapse: ['Date', 'DateTime']\n *   }\n * })\n * ```\n */\nexport function defineConfig(\n  dumperConfig: Partial<{ html: HTMLDumpConfig; console: ConsoleDumpConfig }>\n) {\n  return dumperConfig\n}\n"
  },
  {
    "path": "modules/dumper/dumper.ts",
    "content": "/*\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 useColors from '@poppinss/colors'\nimport { dump as consoleDump } from '@poppinss/dumper/console'\nimport type { HTMLDumpConfig } from '@poppinss/dumper/html/types'\nimport type { ConsoleDumpConfig } from '@poppinss/dumper/console/types'\nimport { createScript, createStyleSheet, dump } from '@poppinss/dumper/html'\n\nimport type { Application } from '../app.ts'\nimport { E_DUMP_DIE_EXCEPTION } from './errors.ts'\n\nconst colors = useColors.ansi()\n\nconst DUMP_TITLE_STYLES = `\n.adonisjs-dump-header {\n  font-family: JetBrains Mono, monaspace argon, Menlo, Monaco, Consolas, monospace;\n  background: #ff1639;\n  border-radius: 4px;\n  color: #fff;\n  border-bottom-left-radius: 0;\n  border-bottom-right-radius: 0;\n  padding: 0.4rem 1.2rem;\n  font-size: 1em;\n  display: flex;\n  justify-content: space-between;\n}\n.adonisjs-dump-header .adonisjs-dump-header-title {\n  font-weight: bold;\n  text-transform: uppercase;\n}\n.adonisjs-dump-header .adonisjs-dump-header-source {\n  font-weight: bold;\n  color: inherit;\n  text-decoration: underline;\n}\n.dumper-dump pre {\n  border-radius: 4px;\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n}`\n\nconst IDE = process.env.ADONIS_IDE ?? process.env.EDITOR ?? ''\n\n/**\n * Dumper exposes the API to dump or die/dump values in your\n * AdonisJS application. An singleton instance of the Dumper\n * is shared as a service and may use it follows.\n *\n * ```ts\n * const dumper = container.make('dumper')\n *\n * dumper.configureHtmlOutput({\n *   // parser + html formatter config\n * })\n *\n * dumper.configureAnsiOutput({\n *   // parser + console formatter config\n * })\n *\n * const html = dumper.dumpToHtml(value)\n * const ansi = dumper.dumpToAnsi(value)\n *\n * // Returns style and script tags that must be\n * // injeted to the head of the HTML document\n *\n * const head = dumper.getHeadElements()\n * ```\n */\nexport class Dumper {\n  #app: Application<any>\n\n  /**\n   * Configuration for the HTML formatter\n   */\n  #htmlConfig: HTMLDumpConfig = {}\n\n  /**\n   * Configuration for the Console formatter\n   */\n  #consoleConfig: ConsoleDumpConfig = {\n    collapse: ['DateTime', 'Date'],\n  }\n\n  /**\n   * A collections of known editors to create URLs to open\n   * them\n   */\n  #editors: Record<string, string> = {\n    textmate: 'txmt://open?url=file://%f&line=%l',\n    macvim: 'mvim://open?url=file://%f&line=%l',\n    emacs: 'emacs://open?url=file://%f&line=%l',\n    sublime: 'subl://open?url=file://%f&line=%l',\n    phpstorm: 'phpstorm://open?file=%f&line=%l',\n    atom: 'atom://core/open/file?filename=%f&line=%l',\n    vscode: 'vscode://file/%f:%l',\n  }\n\n  /**\n   * Creates a new Dumper instance\n   *\n   * @param app - The AdonisJS application instance\n   */\n  constructor(app: Application<any>) {\n    this.#app = app\n  }\n\n  /**\n   * Returns the link to open the file using dd inside one\n   * of the known code editors. Constructs a URL that can be used\n   * to open the file at a specific line in supported editors.\n   *\n   * @param source - Optional source file information\n   * @param source.location - The file path to open\n   * @param source.line - The line number to jump to\n   */\n  #getEditorLink(source?: {\n    location: string\n    line: number\n  }): { href: string; text: string } | undefined {\n    const editorURL = this.#editors[IDE] || IDE\n    if (!editorURL || !source) {\n      return\n    }\n\n    return {\n      href: editorURL.replace('%f', source.location).replace('%l', String(source.line)),\n      text: `${this.#app.relativePath(source.location)}:${source.line}`,\n    }\n  }\n\n  /**\n   * Configure the HTML formatter output options\n   *\n   * @param config - Configuration options for HTML dump formatting\n   *\n   * @example\n   * ```ts\n   * dumper.configureHtmlOutput({\n   *   showHidden: true,\n   *   depth: 5,\n   *   colors: false\n   * })\n   * ```\n   */\n  configureHtmlOutput(config: HTMLDumpConfig): this {\n    this.#htmlConfig = config\n    return this\n  }\n\n  /**\n   * Configure the ANSI formatter output options for console display\n   *\n   * @param config - Configuration options for ANSI console formatting\n   *\n   * @example\n   * ```ts\n   * dumper.configureAnsiOutput({\n   *   showHidden: true,\n   *   depth: 3,\n   *   collapse: ['Date', 'DateTime']\n   * })\n   * ```\n   */\n  configureAnsiOutput(config: ConsoleDumpConfig): this {\n    this.#consoleConfig = config\n    return this\n  }\n\n  /**\n   * Returns the style and script elements that need to be injected into\n   * the HTML document head for proper dump visualization\n   *\n   * @param cspNonce - Optional Content Security Policy nonce for inline scripts\n   *\n   * @example\n   * ```ts\n   * const headElements = dumper.getHeadElements('abc123')\n   * // Insert into your HTML head section\n   * ```\n   */\n  getHeadElements(cspNonce?: string): string {\n    return (\n      `<style id=\"dumper-styles\">` +\n      createStyleSheet() +\n      DUMP_TITLE_STYLES +\n      '</style>' +\n      `<script id=\"dumper-script\"${cspNonce ? ` nonce=\"${cspNonce}\"` : ''}>` +\n      createScript() +\n      '</script>'\n    )\n  }\n\n  /**\n   * Dump a value to formatted HTML output\n   *\n   * @param value - The value to dump and inspect\n   * @param options - Options for HTML output formatting\n   * @param options.cspNonce - Optional Content Security Policy nonce\n   * @param options.title - Optional title to display in the dump header\n   * @param options.source - Optional source file information for editor links\n   *\n   * @example\n   * ```ts\n   * const htmlOutput = dumper.dumpToHtml(user, {\n   *   title: 'User Object',\n   *   source: { location: '/app/controllers/user.ts', line: 42 }\n   * })\n   * ```\n   */\n  dumpToHtml(\n    value: unknown,\n    options: {\n      cspNonce?: string\n      title?: string\n      source?: {\n        location: string\n        line: number\n      }\n    } = {}\n  ) {\n    const link = this.#getEditorLink(options.source) ?? null\n    const title = options.title || 'DUMP'\n\n    return (\n      '<div class=\"adonisjs-dump-header\">' +\n      `<span class=\"adonisjs-dump-header-title\">${title}</span>` +\n      (link ? `<a href=\"${link.href}\" class=\"adonisjs-dump-header-source\">${link.text}</a>` : '') +\n      '</div>' +\n      dump(value, { cspNonce: options.cspNonce, ...this.#htmlConfig })\n    )\n  }\n\n  /**\n   * Dump a value to formatted ANSI output for console display\n   *\n   * @param value - The value to dump and inspect\n   * @param options - Options for ANSI output formatting\n   * @param options.title - Optional title to display in the dump header\n   * @param options.source - Optional source file information for editor links\n   *\n   * @example\n   * ```ts\n   * const ansiOutput = dumper.dumpToAnsi(user, {\n   *   title: 'User Debug',\n   *   source: { location: '/app/controllers/user.ts', line: 42 }\n   * })\n   * console.log(ansiOutput)\n   * ```\n   */\n  dumpToAnsi(\n    value: unknown,\n    options: {\n      title?: string\n      source?: {\n        location: string\n        line: number\n      }\n    } = {}\n  ) {\n    const columns = process.stdout.columns\n\n    /**\n     * Link to the source file\n     */\n    const link = `${this.#getEditorLink(options.source)?.text ?? ''} `\n\n    /**\n     * Dump title\n     */\n    const title = ` ${options.title || 'DUMP'}`\n\n    /**\n     * Whitespace between the title and the link to align them\n     * on each side of x axis\n     */\n    const whiteSpaceLength = columns ? columns - link.length - title.length - 4 : 2\n    const whiteSpace = new Array(whiteSpaceLength <= 0 ? 2 : whiteSpaceLength).join(' ')\n\n    /**\n     * Styled heading with background color and bold text\n     */\n    const heading = colors.bgRed().bold(`${title}${whiteSpace}${link}`)\n\n    return `${heading}\\n${consoleDump(value, this.#consoleConfig)}`\n  }\n\n  /**\n   * Dump values and die. This method dumps the provided value and then\n   * terminates the application. The output format is automatically chosen\n   * based on the execution context.\n   *\n   * - During an HTTP request, HTML output will be sent to the browser\n   * - Otherwise the value will be logged to the console in ANSI format\n   *\n   * @param value - The value to dump before terminating\n   * @param traceSourceIndex - Stack trace index for source location (default: 1)\n   *\n   * @example\n   * ```ts\n   * // This will dump the user object and terminate the application\n   * dumper.dd(user)\n   *\n   * // This will never execute\n   * console.log('This line will not run')\n   * ```\n   */\n  dd(value: unknown, traceSourceIndex: number = 1) {\n    const error = new E_DUMP_DIE_EXCEPTION(value, this)\n    error.setTraceSourceIndex(traceSourceIndex)\n    throw error\n  }\n}\n"
  },
  {
    "path": "modules/dumper/errors.ts",
    "content": "/*\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 { inspect } from 'node:util'\nimport { parse } from 'error-stack-parser-es'\nimport { Exception } from '@poppinss/utils/exception'\n\nimport type { Dumper } from './dumper.ts'\nimport type { Kernel } from '../ace/kernel.ts'\nimport type { HttpContext } from '../http/main.ts'\n\n/**\n * DumpDie exception raised by the \"dd\" (dump and die) function.\n * This special exception terminates execution while dumping the provided\n * value as HTML (during HTTP requests) or ANSI (in console/CLI).\n *\n * @example\n * ```ts\n * // This will dump the user object and terminate\n * dumper.dd(user)\n *\n * // In HTTP context: sends HTML dump to browser\n * // In CLI context: prints ANSI dump to console\n * ```\n */\nclass DumpDieException extends Exception {\n  static status: number = 500\n  static code: string = 'E_DUMP_DIE_EXCEPTION'\n\n  declare fileName: string\n  declare lineNumber: number\n\n  #dumper: Dumper\n  #traceSourceIndex: number = 1\n  value: unknown\n\n  constructor(value: unknown, dumper: Dumper) {\n    super('Dump and Die exception')\n    this.#dumper = dumper\n    this.value = value\n  }\n\n  /**\n   * Returns the source file and line number location for the error\n   */\n  #getErrorSource(): { location: string; line: number } | undefined {\n    if (this.fileName && this.lineNumber) {\n      return {\n        location: this.fileName,\n        line: this.lineNumber,\n      }\n    }\n\n    const source = parse(this)[this.#traceSourceIndex]\n    if (!source.fileName || !source.lineNumber) {\n      return\n    }\n\n    return {\n      location: source.fileName,\n      line: source.lineNumber,\n    }\n  }\n\n  /**\n   * Set the stack trace index for determining the source location.\n   * This is useful when building nested helpers on top of dump/die functionality.\n   *\n   * @param index - Stack trace index (0 = current function, 1 = caller, etc.)\n   */\n  setTraceSourceIndex(index: number) {\n    this.#traceSourceIndex = index\n    return this\n  }\n\n  /**\n   * Preventing itself from getting reported by the\n   * AdonisJS exception reporter\n   */\n  report() {}\n\n  /**\n   * HTTP exception handler that renders the dump as HTML output.\n   * This method is called automatically by AdonisJS when a DumpDieException\n   * is thrown during an HTTP request.\n   *\n   * @param error - The DumpDieException instance\n   * @param ctx - HTTP context for the current request\n   */\n  async handle(error: DumpDieException, ctx: HttpContext) {\n    const source = this.#getErrorSource()\n\n    /**\n     * Comes from the shield package\n     */\n    const cspNonce = 'nonce' in ctx.response ? (ctx.response.nonce as string) : undefined\n\n    ctx.response\n      .status(500)\n      .send(\n        '<!DOCTYPE html>' +\n          '<html>' +\n          '<head>' +\n          '<meta charset=\"utf-8\">' +\n          '<meta name=\"viewport\" content=\"width=device-width\">' +\n          `${this.#dumper.getHeadElements(cspNonce)}` +\n          '</head>' +\n          '<body>' +\n          `${this.#dumper.dumpToHtml(error.value, { cspNonce, source, title: 'DUMP DIE' })}` +\n          '</body>' +\n          '</html>'\n      )\n  }\n\n  /**\n   * Ace command exception handler that renders the dump as ANSI output.\n   * This method is called automatically by the Ace kernel when a DumpDieException\n   * is thrown during command execution.\n   *\n   * @param error - The DumpDieException instance\n   * @param kernel - Ace kernel instance\n   */\n  async render(error: DumpDieException, kernel: Kernel) {\n    const source = this.#getErrorSource()\n    kernel.ui.logger.log(this.#dumper.dumpToAnsi(error.value, { source, title: 'DUMP DIE' }))\n  }\n\n  /**\n   * Custom output for the Node.js util inspect\n   */\n  [inspect.custom]() {\n    const source = this.#getErrorSource()\n    return this.#dumper.dumpToAnsi(this.value, { source, title: 'DUMP DIE' })\n  }\n}\n\nexport const E_DUMP_DIE_EXCEPTION = DumpDieException\n"
  },
  {
    "path": "modules/dumper/main.ts",
    "content": "/*\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\n/**\n * Dumper module provides debugging and inspection utilities for AdonisJS applications.\n * Includes the Dumper class for formatting output, error classes, and configuration helpers.\n *\n * @example\n * // Use the dumper service\n * import { Dumper } from '@adonisjs/core/dumper'\n *\n * const dumper = new Dumper(app)\n * const htmlOutput = dumper.dumpToHtml(user, { title: 'User Data' })\n * const ansiOutput = dumper.dumpToAnsi(user, { title: 'Debug User' })\n *\n * @example\n * // Configure dumper output\n * import { defineConfig } from '@adonisjs/core/dumper'\n *\n * export default defineConfig({\n *   html: { showHidden: true, depth: 5 },\n *   console: { collapse: ['Date', 'DateTime'] }\n * })\n */\nexport * as errors from './errors.ts'\nexport { Dumper } from './dumper.ts'\nexport { defineConfig } from './define_config.ts'\n"
  },
  {
    "path": "modules/dumper/plugins/edge.ts",
    "content": "/*\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 Edge, Template } from 'edge.js'\nimport { type Dumper } from '../dumper.ts'\n\n/**\n * Returns an edge plugin that integrates with a given\n * dumper instance\n */\nexport function pluginEdgeDumper(dumper: Dumper) {\n  Template.macro('dumper' as any, dumper)\n\n  return (edge: Edge) => {\n    edge.registerTag({\n      tagName: 'dump',\n      block: false,\n      seekable: true,\n      noNewLine: true,\n      compile(parser, buffer, token) {\n        const parsed = parser.utils.transformAst(\n          parser.utils.generateAST(token.properties.jsArg, token.loc, token.filename),\n          token.filename,\n          parser\n        )\n\n        buffer.writeExpression(\n          `template.stacks.pushOnceTo('dumper', 'dumper_globals', template.dumper.getHeadElements(state.cspNonce))`,\n          token.filename,\n          token.loc.start.line\n        )\n\n        buffer.outputExpression(\n          `template.dumper.dumpToHtml(${parser.utils.stringify(parsed)}, { cspNonce: state.cspNonce, source: { location: $filename, line: $lineNumber } })`,\n          token.filename,\n          token.loc.start.line,\n          true\n        )\n      },\n    })\n\n    edge.registerTag({\n      tagName: 'dd',\n      block: false,\n      seekable: true,\n      noNewLine: true,\n      compile(parser, buffer, token) {\n        const parsed = parser.utils.transformAst(\n          parser.utils.generateAST(token.properties.jsArg, token.loc, token.filename),\n          token.filename,\n          parser\n        )\n\n        /**\n         * Dump/Die statement to catch error and convert it into\n         * an Edge error\n         */\n        const ddStatement = [\n          'try {',\n          `  template.dumper.dd(${parser.utils.stringify(parsed)})`,\n          '} catch (error) {',\n          `  if (error.code === 'E_DUMP_DIE_EXCEPTION') {`,\n          '    const edgeError = template.createError(error.message, $filename, $lineNumber)',\n          '    error.fileName = $filename',\n          '    error.lineNumber = $lineNumber',\n          '    edgeError.handle = function (_, ctx) {',\n          '      return error.handle(error, ctx)',\n          '    }',\n          '    edgeError.report = function () {',\n          '      return error.report(error)',\n          '    }',\n          '    throw edgeError',\n          '  }',\n          '  throw error',\n          '}',\n        ].join('\\n')\n\n        buffer.writeStatement(ddStatement, token.filename, token.loc.start.line)\n      },\n    })\n  }\n}\n"
  },
  {
    "path": "modules/encryption/define_config.ts",
    "content": "/*\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 debug from '../../src/debug.ts'\nimport { configProvider } from '../../src/config_provider.ts'\nimport { type ConfigProvider } from '../../src/types.ts'\n\nimport {\n  type AESSIVDriverConfig,\n  type AES256CBCDriverConfig,\n  type AES256GCMDriverConfig,\n  type ChaCha20Poly1305DriverConfig,\n  type LegacyDriverConfig,\n} from '../../types/encryption.ts'\nimport { type EncryptionConfig } from '../../types/encryption.ts'\nimport { InvalidArgumentsException } from '../../src/exceptions.ts'\n\n/**\n * Resolved configuration from the config provider that will be\n * accepted by the encryption manager.\n *\n * This type unwraps ConfigProvider types to their resolved values,\n * ensuring all encryptors in the list are concrete EncryptionConfig\n * objects rather than providers.\n *\n * @template KnownEncryptors - Record of encryptor names to their configurations\n */\ntype ResolvedConfig<\n  KnownEncryptors extends Record<string, EncryptionConfig | ConfigProvider<EncryptionConfig>>,\n> = {\n  /**\n   * The default encryptor name to use when no specific\n   * encryptor is requested\n   */\n  default?: keyof KnownEncryptors\n\n  /**\n   * Map of encryptor names to their resolved configurations.\n   * ConfigProvider types are unwrapped to their underlying\n   * EncryptionConfig values.\n   */\n  list: {\n    [K in keyof KnownEncryptors]: KnownEncryptors[K] extends ConfigProvider<infer A>\n      ? A\n      : KnownEncryptors[K]\n  }\n}\n\n/**\n * Defines the encryption configuration for the application.\n *\n * This function creates a configuration provider that lazily resolves\n * encryption drivers. It validates that the default encryptor (if specified)\n * exists in the list and resolves any ConfigProvider instances to their\n * concrete values.\n *\n * @template KnownEncryptors - Record of encryptor names to their configurations\n *\n * @param config - The encryption configuration object\n * @param config.default - Optional default encryptor name\n * @param config.list - Map of encryptor names to their configurations or providers\n *\n * @example\n * ```ts\n * const encryptionConfig = defineConfig({\n *   default: 'app',\n *   list: {\n *     app: drivers.aes256gcm({\n *       id: 'app',\n *       keys: [env.get('APP_KEY')]\n *     }),\n *     backup: drivers.chacha20({\n *       id: 'backup',\n *       keys: [env.get('BACKUP_KEY')]\n *     })\n *   }\n * })\n * ```\n */\nexport function defineConfig<\n  KnownEncryptors extends Record<string, EncryptionConfig | ConfigProvider<EncryptionConfig>>,\n>(config: {\n  default?: keyof KnownEncryptors\n  list: KnownEncryptors\n}): ConfigProvider<ResolvedConfig<KnownEncryptors>> {\n  /**\n   * Encryption list should always be provided\n   */\n  if (!config.list) {\n    throw new InvalidArgumentsException('Missing \"list\" property in encryption config')\n  }\n\n  /**\n   * The default encryption should be mentioned in the list\n   */\n  if (config.default && !config.list[config.default]) {\n    throw new InvalidArgumentsException(\n      `Missing \"list.${String(\n        config.default\n      )}\" in encryption config. It is referenced by the \"default\" property`\n    )\n  }\n\n  /**\n   * Config provider to lazily import drivers as they are used inside\n   * the user application\n   */\n  return configProvider.create<ResolvedConfig<KnownEncryptors>>(async (app) => {\n    debug('resolving encryption config')\n\n    const encryptorsList = Object.keys(config.list)\n    const encryptors = {} as Record<string, EncryptionConfig | ConfigProvider<EncryptionConfig>>\n\n    for (let encryptorName of encryptorsList) {\n      const encryptor = config.list[encryptorName]\n      if ('resolver' in encryptor) {\n        encryptors[encryptorName] = await encryptor.resolver(app)\n      } else {\n        encryptors[encryptorName] = encryptor\n      }\n    }\n\n    return {\n      default: config.default,\n      list: encryptors as ResolvedConfig<KnownEncryptors>['list'],\n    }\n  })\n}\n\n/**\n * Collection of encryption driver factory functions.\n *\n * Each driver factory creates a ConfigProvider that lazily imports\n * and configures the corresponding encryption driver. This allows\n * for efficient code splitting and on-demand loading of encryption\n * algorithms.\n */\nexport const drivers: {\n  /**\n   * Creates a ChaCha20-Poly1305 encryption driver configuration.\n   *\n   * ChaCha20-Poly1305 is a modern authenticated encryption algorithm\n   * that provides excellent performance on systems without AES hardware\n   * acceleration.\n   *\n   * @param config - The ChaCha20-Poly1305 driver configuration\n   *\n   * @example\n   * ```ts\n   * drivers.chacha20({\n   *   id: 'app',\n   *   keys: [env.get('APP_KEY')]\n   * })\n   * ```\n   */\n  chacha20: (config: ChaCha20Poly1305DriverConfig) => ConfigProvider<EncryptionConfig>\n\n  /**\n   * Creates an AES-256-CBC encryption driver configuration.\n   *\n   * AES-256-CBC is a widely-supported block cipher mode. However,\n   * consider using AES-256-GCM for new applications as it provides\n   * authenticated encryption.\n   *\n   * @param config - The AES-256-CBC driver configuration\n   *\n   * @example\n   * ```ts\n   * drivers.aes256cbc({\n   *   id: 'legacy',\n   *   keys: [env.get('LEGACY_KEY')]\n   * })\n   * ```\n   */\n  aes256cbc: (config: AES256CBCDriverConfig) => ConfigProvider<EncryptionConfig>\n\n  /**\n   * Creates an AES-256-GCM encryption driver configuration.\n   *\n   * AES-256-GCM is an authenticated encryption algorithm that provides\n   * both confidentiality and integrity. It offers excellent performance\n   * on systems with AES hardware acceleration.\n   *\n   * @param config - The AES-256-GCM driver configuration\n   *\n   * @example\n   * ```ts\n   * drivers.aes256gcm({\n   *   id: 'app',\n   *   keys: [env.get('APP_KEY')]\n   * })\n   * ```\n   */\n  aes256gcm: (config: AES256GCMDriverConfig) => ConfigProvider<EncryptionConfig>\n\n  /**\n   * Creates an AES-SIV encryption driver configuration.\n   *\n   * @param config - The AES-SIV driver configuration\n   *\n   * @example\n   * ```ts\n   * drivers.aessiv({\n   *   id: 'app',\n   *   key: env.get('APP_KEY')\n   * })\n   * ```\n   */\n  aessiv: (config: AESSIVDriverConfig) => ConfigProvider<EncryptionConfig>\n\n  /**\n   * Creates a Legacy encryption driver configuration.\n   *\n   * The Legacy driver maintains compatibility with the old AdonisJS v6\n   * encryption format. It uses AES-256-CBC with HMAC SHA-256.\n   *\n   * Use this driver to decrypt values encrypted with older versions\n   * of AdonisJS or when migrating to newer encryption drivers.\n   *\n   * @param config - The Legacy driver configuration\n   *\n   * @example\n   * ```ts\n   * drivers.legacy({\n   *   keys: [env.get('APP_KEY')]\n   * })\n   * ```\n   */\n  legacy: (config: LegacyDriverConfig) => ConfigProvider<EncryptionConfig>\n} = {\n  chacha20: (config) => {\n    return configProvider.create(async () => {\n      const { ChaCha20Poly1305 } = await import('./drivers/chacha20_poly1305.ts')\n      debug('configuring chacha20 encryption driver')\n      return {\n        driver: (key) => new ChaCha20Poly1305({ id: config.id, key }),\n        keys: config.keys.filter((key) => !!key),\n      }\n    })\n  },\n\n  aes256cbc: (config) => {\n    return configProvider.create(async () => {\n      const { AES256CBC } = await import('./drivers/aes_256_cbc.ts')\n      debug('configuring aes256cbc encryption driver')\n      return {\n        driver: (key) => new AES256CBC({ id: config.id, key }),\n        keys: config.keys.filter((key) => !!key),\n      }\n    })\n  },\n\n  aes256gcm: (config) => {\n    return configProvider.create(async () => {\n      const { AES256GCM } = await import('./drivers/aes_256_gcm.ts')\n      debug('configuring aes256gcm encryption driver')\n      return {\n        driver: (key) => new AES256GCM({ id: config.id, key }),\n        keys: config.keys.filter((key) => !!key),\n      }\n    })\n  },\n\n  aessiv: (config) => {\n    return configProvider.create(async () => {\n      const { AESSIV } = await import('./drivers/aes_siv.ts')\n      debug('configuring aessiv encryption driver')\n      return {\n        driver: (key) => new AESSIV({ id: config.id, key }),\n        keys: [config.key].filter((key) => !!key),\n      }\n    })\n  },\n\n  legacy: (config) => {\n    return configProvider.create(async () => {\n      const { Legacy } = await import('./drivers/legacy.ts')\n      debug('configuring legacy encryption driver')\n      return {\n        driver: (key) => new Legacy({ key }),\n        keys: config.keys.filter((key) => !!key),\n      }\n    })\n  },\n}\n"
  },
  {
    "path": "modules/encryption/drivers/aes_256_cbc.ts",
    "content": "/*\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\n/**\n * AES-256-CBC encryption driver implementation.\n *\n * This driver provides encryption and decryption using the AES-256-CBC\n * (Advanced Encryption Standard with 256-bit key in Cipher Block Chaining mode)\n * algorithm. While widely supported, AES-256-CBC does not provide authenticated\n * encryption. Consider using AES-256-GCM for new applications.\n *\n * @example\n * ```ts\n * const driver = new AES256CBC({\n *   id: 'app',\n *   key: 'your-256-bit-key-here'\n * })\n *\n * const encrypted = driver.encrypt('sensitive data')\n * const decrypted = driver.decrypt(encrypted)\n * ```\n */\nexport { AES256CBC } from '@boringnode/encryption/drivers/aes_256_cbc'\n"
  },
  {
    "path": "modules/encryption/drivers/aes_256_gcm.ts",
    "content": "/*\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\n/**\n * AES-256-GCM encryption driver implementation.\n *\n * This driver provides authenticated encryption and decryption using the\n * AES-256-GCM (Advanced Encryption Standard with 256-bit key in Galois/Counter Mode)\n * algorithm. GCM mode provides both confidentiality and authenticity, making it\n * the recommended choice for modern applications. It offers excellent performance\n * on systems with AES hardware acceleration.\n *\n * @example\n * ```ts\n * const driver = new AES256GCM({\n *   id: 'app',\n *   key: 'your-256-bit-key-here'\n * })\n *\n * const encrypted = driver.encrypt('sensitive data')\n * const decrypted = driver.decrypt(encrypted)\n * ```\n */\nexport { AES256GCM } from '@boringnode/encryption/drivers/aes_256_gcm'\n"
  },
  {
    "path": "modules/encryption/drivers/aes_siv.ts",
    "content": "/*\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\n/**\n * AES-SIV encryption driver implementation.\n *\n * This driver provides deterministic authenticated encryption using AES-SIV\n * (Synthetic Initialization Vector). It is useful when you need equality\n * queries over encrypted values while preserving authenticity guarantees.\n *\n * @example\n * ```ts\n * const driver = new AESSIV({\n *   id: 'app',\n *   key: 'your-256-bit-key-here'\n * })\n *\n * const encrypted = driver.encrypt('sensitive data')\n * const decrypted = driver.decrypt(encrypted)\n * ```\n */\nexport { AESSIV } from '@boringnode/encryption/drivers/aes_siv'\n"
  },
  {
    "path": "modules/encryption/drivers/chacha20_poly1305.ts",
    "content": "/*\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\n/**\n * ChaCha20-Poly1305 encryption driver implementation.\n *\n * This driver provides authenticated encryption and decryption using the\n * ChaCha20-Poly1305 algorithm. ChaCha20 is a modern stream cipher that\n * provides excellent performance on systems without AES hardware acceleration.\n * Combined with Poly1305 for authentication, it offers both confidentiality\n * and authenticity.\n *\n * @example\n * ```ts\n * const driver = new ChaCha20Poly1305({\n *   id: 'app',\n *   key: 'your-256-bit-key-here'\n * })\n *\n * const encrypted = driver.encrypt('sensitive data')\n * const decrypted = driver.decrypt(encrypted)\n * ```\n */\nexport { ChaCha20Poly1305 } from '@boringnode/encryption/drivers/chacha20_poly1305'\n"
  },
  {
    "path": "modules/encryption/drivers/legacy.ts",
    "content": "/*\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 { errors } from '@boringnode/encryption'\nimport { MessageBuilder, type Secret } from '@poppinss/utils'\nimport { createCipheriv, createDecipheriv, randomBytes } from 'node:crypto'\nimport { BaseDriver, Hmac, base64UrlDecode, base64UrlEncode } from '@boringnode/encryption'\nimport type {\n  CypherText,\n  EncryptOptions,\n  EncryptionDriverContract,\n} from '@boringnode/encryption/types'\nimport { E_BLIND_INDEX_NOT_SUPPORTED } from '../errors.ts'\n\n/**\n * Configuration for the Legacy encryption driver.\n *\n * The Legacy driver maintains compatibility with the old AdonisJS v6\n * encryption format using AES-256-CBC with HMAC SHA-256.\n */\nexport interface LegacyConfig {\n  key: string | Secret<string>\n}\n\n/**\n * Configuration for the Legacy encryption driver factory.\n *\n * Used when configuring the driver through the defineConfig function.\n */\nexport interface LegacyDriverConfig {\n  keys: (string | Secret<string>)[]\n}\n\n/**\n * Factory function to create a Legacy encryption configuration.\n *\n * @example\n * ```ts\n * drivers.legacy({\n *   keys: [env.get('APP_KEY')]\n * })\n * ```\n */\nexport function legacy(config: LegacyDriverConfig) {\n  return {\n    driver: (key: string | Secret<string>) => new Legacy({ key }),\n    keys: config.keys,\n  }\n}\n\n/**\n * Legacy encryption driver for AdonisJS.\n *\n * This driver maintains compatibility with the old AdonisJS v6 encryption\n * format. It uses:\n * - AES-256-CBC for encryption\n * - HMAC SHA-256 for integrity verification\n * - MessageBuilder from @poppinss/utils for encoding values\n *\n * Encrypted format: `[encrypted_base64url].[iv_base64url].[hmac]`\n *\n * @example\n * ```ts\n * const driver = new Legacy({ key: 'your-32-character-secret-key!!' })\n *\n * const encrypted = driver.encrypt('sensitive data')\n * const decrypted = driver.decrypt(encrypted)\n * ```\n */\nexport class Legacy extends BaseDriver implements EncryptionDriverContract {\n  constructor(config: LegacyConfig) {\n    super(config)\n\n    /**\n     * The key length must be at least 16 characters\n     */\n    if (this.cryptoKey.length < 16) {\n      throw new errors.E_INSECURE_ENCRYPTER_KEY()\n    }\n  }\n\n  /**\n   * Encrypt a given piece of value using the app secret. A wide range of\n   * data types are supported.\n   *\n   * - String\n   * - Arrays\n   * - Objects\n   * - Booleans\n   * - Numbers\n   * - Dates\n   *\n   * You can optionally define a purpose for which the value was encrypted and\n   * mentioning a different purpose/no purpose during decrypt will fail.\n   */\n  encrypt(payload: any, options?: EncryptOptions): CypherText\n  encrypt(payload: any, expiresIn?: string | number, purpose?: string): CypherText\n  encrypt(\n    payload: any,\n    expiresInOrOptions?: string | number | EncryptOptions,\n    purpose?: string\n  ): CypherText {\n    let expiresIn: string | number | undefined\n    let actualPurpose: string | undefined\n\n    if (typeof expiresInOrOptions === 'object' && expiresInOrOptions !== null) {\n      expiresIn = expiresInOrOptions.expiresIn\n      actualPurpose = expiresInOrOptions.purpose\n    } else {\n      expiresIn = expiresInOrOptions\n      actualPurpose = purpose\n    }\n\n    const iv = randomBytes(16)\n\n    /**\n     * Use the first 32 bytes of the key for AES-256\n     */\n    const encryptionKey = this.cryptoKey.subarray(0, 32)\n\n    const cipher = createCipheriv('aes-256-cbc', encryptionKey, iv)\n    const plainText = new MessageBuilder().build(payload, expiresIn, actualPurpose)\n    const cipherText = Buffer.concat([cipher.update(plainText), cipher.final()])\n\n    const macPayload = `${base64UrlEncode(cipherText)}${this.separator}${base64UrlEncode(iv)}`\n    const hmac = new Hmac(this.cryptoKey).generate(macPayload)\n\n    return this.computeReturns([macPayload, hmac])\n  }\n\n  /**\n   * Decrypt value and verify it against a purpose\n   */\n  decrypt<T extends any>(value: string, purpose?: string): T | null {\n    if (typeof value !== 'string') {\n      return null\n    }\n\n    const [cipherEncoded, ivEncoded, macEncoded] = value.split(this.separator)\n\n    if (!cipherEncoded || !ivEncoded || !macEncoded) {\n      return null\n    }\n\n    const cipherText = base64UrlDecode(cipherEncoded)\n    if (!cipherText) {\n      return null\n    }\n\n    const iv = base64UrlDecode(ivEncoded)\n    if (!iv) {\n      return null\n    }\n\n    /**\n     * Verify the HMAC\n     */\n    const isValidHmac = new Hmac(this.cryptoKey).compare(\n      `${cipherEncoded}${this.separator}${ivEncoded}`,\n      macEncoded\n    )\n\n    if (!isValidHmac) {\n      return null\n    }\n\n    try {\n      /**\n       * Use the first 32 bytes of the key for AES-256\n       */\n      const encryptionKey = this.cryptoKey.subarray(0, 32)\n\n      const decipher = createDecipheriv('aes-256-cbc', encryptionKey, iv)\n      const plainTextBuffer = Buffer.concat([decipher.update(cipherText), decipher.final()])\n\n      return new MessageBuilder().verify<T>(plainTextBuffer, purpose)\n    } catch {\n      return null\n    }\n  }\n\n  /**\n   * Legacy driver does not support blind indexes.\n   */\n  blindIndex(_payload: any, _purpose: string): string {\n    throw new E_BLIND_INDEX_NOT_SUPPORTED(['legacy'])\n  }\n\n  /**\n   * Legacy driver does not support blind indexes.\n   */\n  blindIndexes(_payload: any, _purpose: string): string[] {\n    throw new E_BLIND_INDEX_NOT_SUPPORTED(['legacy'])\n  }\n}\n"
  },
  {
    "path": "modules/encryption/errors.ts",
    "content": "/*\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 { createError } from '../../src/exceptions.ts'\nimport { errors as boringnodeErrors } from '@boringnode/encryption'\n\n/**\n * Raised when attempting to compute blind indexes using the legacy driver.\n */\nexport const E_BLIND_INDEX_NOT_SUPPORTED = createError<[string]>(\n  'Blind indexes are not supported by the \"%s\" encryption driver',\n  'E_BLIND_INDEX_NOT_SUPPORTED'\n)\n\n/**\n * Encryption errors exposed by this package.\n */\nexport const errors = {\n  ...boringnodeErrors,\n  E_BLIND_INDEX_NOT_SUPPORTED,\n}\n"
  },
  {
    "path": "modules/encryption/main.ts",
    "content": "/*\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\n/**\n * Main encryption class for encrypting and decrypting values.\n *\n * Provides methods to encrypt strings and objects with optional purpose\n * binding, decrypt values, and manage encryption keys.\n *\n * @example\n * ```ts\n * const encryption = new Encryption({ key: 'secret-key' })\n * const encrypted = encryption.encrypt('sensitive data')\n * const decrypted = encryption.decrypt(encrypted)\n * ```\n */\nexport { Encryption } from '@boringnode/encryption'\n\n/**\n * Manager class for handling multiple encryption instances.\n *\n * Allows you to configure and manage multiple encryption drivers,\n * switch between them, and use different encryption keys for\n * different purposes.\n *\n * @example\n * ```ts\n * const manager = new EncryptionManager({\n *   default: 'app',\n *   list: {\n *     app: {\n *       driver: (key) => new AES256GCM({ key }),\n *       keys: ['app-key']\n *     }\n *   }\n * })\n * const encryptor = manager.use('app')\n * ```\n */\nexport { EncryptionManager } from '@boringnode/encryption'\n\n/**\n * HMAC (Hash-based Message Authentication Code) class for creating\n * and verifying message authentication codes.\n *\n * Provides methods to generate cryptographic hashes with a secret key\n * and verify them to ensure data integrity and authenticity.\n *\n * @example\n * ```ts\n * const hmac = new Hmac('secret-key')\n * const signature = hmac.generate('message')\n * const isValid = hmac.verify('message', signature)\n * ```\n */\nexport { Hmac } from '@boringnode/encryption'\n\n/**\n * Base class for implementing custom encryption drivers.\n *\n * Extend this class to create custom encryption implementations\n * that can be used with the EncryptionManager.\n *\n * @example\n * ```ts\n * class CustomDriver extends BaseDriver {\n *   encrypt(value: string) {\n *     // Custom encryption logic\n *   }\n *   decrypt(payload: string) {\n *     // Custom decryption logic\n *   }\n * }\n * ```\n */\nexport { BaseDriver } from '@boringnode/encryption'\n\n/**\n * Encryption module specific exceptions.\n */\nexport { errors } from './errors.ts'\n\n/**\n * Defines the encryption configuration for the application.\n *\n * @see {defineConfig} in define_config.ts for detailed documentation\n */\nexport { defineConfig } from './define_config.ts'\n\n/**\n * Collection of built-in encryption driver factory functions.\n *\n * Includes factories for ChaCha20-Poly1305, AES-256-CBC,\n * AES-256-GCM, and AES-SIV encryption algorithms.\n *\n * @see {drivers} in define_config.ts for detailed documentation\n */\nexport { drivers } from './define_config.ts'\n"
  },
  {
    "path": "modules/env/editor.ts",
    "content": "/*\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\nexport * from '@adonisjs/env/editor'\n"
  },
  {
    "path": "modules/env/main.ts",
    "content": "/*\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\n/**\n * Environment module re-exports all functionality from @adonisjs/env.\n * This includes the Env class, validation schemas, and utilities for managing\n * environment variables with type safety and validation.\n *\n * @example\n * // Import the Env class and validation\n * import { Env } from '@adonisjs/core/env'\n *\n * const env = await Env.create(new URL('../', import.meta.url), {\n *   NODE_ENV: Env.schema.enum(['development', 'production', 'test'] as const),\n *   PORT: Env.schema.number(),\n *   HOST: Env.schema.string({ format: 'host' })\n * })\n *\n * @example\n * // Import environment types and utilities\n * import type { EnvParser, EnvEditor } from '@adonisjs/core/env'\n */\nexport * from '@adonisjs/env'\n"
  },
  {
    "path": "modules/events.ts",
    "content": "/*\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\nexport * from '@adonisjs/events'\n"
  },
  {
    "path": "modules/hash/define_config.ts",
    "content": "/*\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 { InvalidArgumentsException } from '@poppinss/utils/exception'\n\nimport debug from '../../src/debug.ts'\nimport type { Argon } from './drivers/argon.ts'\nimport type { Scrypt } from './drivers/scrypt.ts'\nimport type { Bcrypt } from './drivers/bcrypt.ts'\nimport type { ConfigProvider } from '../../src/types.ts'\nimport { configProvider } from '../../src/config_provider.ts'\nimport type {\n  ArgonConfig,\n  BcryptConfig,\n  ScryptConfig,\n  ManagerDriverFactory,\n} from '../../types/hash.ts'\n\n/**\n * Resolved config from the config provider will be\n * the config accepted by the hash manager\n */\ntype ResolvedConfig<\n  KnownHashers extends Record<string, ManagerDriverFactory | ConfigProvider<ManagerDriverFactory>>,\n> = {\n  default?: keyof KnownHashers\n  list: {\n    [K in keyof KnownHashers]: KnownHashers[K] extends ConfigProvider<infer A> ? A : KnownHashers[K]\n  }\n}\n\n/**\n * Define config for the hash service. This function creates a configuration\n * provider that lazily imports and resolves hash drivers when needed.\n *\n * @param config - Configuration object containing default hasher and list of hashers\n * @param config.default - Optional default hasher name (must exist in the list)\n * @param config.list - Record of hasher configurations or config providers\n *\n * @example\n * ```ts\n * const hashConfig = defineConfig({\n *   default: 'scrypt',\n *   list: {\n *     scrypt: drivers.scrypt({\n *       cost: 16384,\n *       blockSize: 8,\n *       parallelization: 1,\n *       saltSize: 16,\n *       keyLength: 64,\n *     }),\n *     bcrypt: drivers.bcrypt({\n *       rounds: 10,\n *     })\n *   }\n * })\n * ```\n */\nexport function defineConfig<\n  KnownHashers extends Record<string, ManagerDriverFactory | ConfigProvider<ManagerDriverFactory>>,\n>(config: {\n  default?: keyof KnownHashers\n  list: KnownHashers\n}): ConfigProvider<ResolvedConfig<KnownHashers>> {\n  /**\n   * Hashers list should always be provided\n   */\n  if (!config.list) {\n    throw new InvalidArgumentsException('Missing \"list\" property in hash config')\n  }\n\n  /**\n   * The default hasher should be mentioned in the list\n   */\n  if (config.default && !config.list[config.default]) {\n    throw new InvalidArgumentsException(\n      `Missing \"list.${String(\n        config.default\n      )}\" in hash config. It is referenced by the \"default\" property`\n    )\n  }\n\n  /**\n   * Config provider to lazily import drivers as they are used inside\n   * the user application\n   */\n  return configProvider.create<ResolvedConfig<KnownHashers>>(async (app) => {\n    debug('resolving hash config')\n\n    const hashersList = Object.keys(config.list)\n    const hashers = {} as Record<\n      string,\n      ManagerDriverFactory | ConfigProvider<ManagerDriverFactory>\n    >\n\n    for (let hasherName of hashersList) {\n      const hasher = config.list[hasherName]\n      if (typeof hasher === 'function') {\n        hashers[hasherName] = hasher\n      } else {\n        hashers[hasherName] = await hasher.resolver(app)\n      }\n    }\n\n    return {\n      default: config.default,\n      list: hashers as ResolvedConfig<KnownHashers>['list'],\n    }\n  })\n}\n\n/**\n * Helpers to configure drivers inside the config file. These functions create\n * configuration providers that lazily import and instantiate hash drivers.\n *\n * - Import happens when you first use the hash module\n * - Construction of drivers happens when you first use a driver\n *\n * @example\n * ```ts\n * const hashConfig = defineConfig({\n *   default: 'bcrypt',\n *   list: {\n *     bcrypt: drivers.bcrypt({ rounds: 12 }),\n *     argon2: drivers.argon2({\n *       variant: 'id',\n *       memory: 65536,\n *       time: 3,\n *       parallelism: 4\n *     }),\n *     scrypt: drivers.scrypt({\n *       cost: 16384,\n *       blockSize: 8,\n *       parallelization: 1\n *     })\n *   }\n * })\n * ```\n */\nexport const drivers: {\n  argon2: (config: ArgonConfig) => ConfigProvider<() => Argon>\n  bcrypt: (config: BcryptConfig) => ConfigProvider<() => Bcrypt>\n  scrypt: (config: ScryptConfig) => ConfigProvider<() => Scrypt>\n} = {\n  argon2: (config) => {\n    return configProvider.create(async () => {\n      const { Argon } = await import('./drivers/argon.js')\n      debug('configuring argon driver')\n      return () => new Argon(config)\n    })\n  },\n  bcrypt: (config) => {\n    return configProvider.create(async () => {\n      const { Bcrypt } = await import('./drivers/bcrypt.js')\n      debug('configuring bcrypt driver')\n      return () => new Bcrypt(config)\n    })\n  },\n  scrypt: (config) => {\n    return configProvider.create(async () => {\n      const { Scrypt } = await import('./drivers/scrypt.js')\n      debug('configuring scrypt driver')\n      return () => new Scrypt(config)\n    })\n  },\n}\n"
  },
  {
    "path": "modules/hash/drivers/argon.ts",
    "content": "/*\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\nexport * from '@adonisjs/hash/drivers/argon'\n"
  },
  {
    "path": "modules/hash/drivers/bcrypt.ts",
    "content": "/*\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\n/**\n * Bcrypt hash driver re-exports from @adonisjs/hash.\n * Provides bcrypt password hashing functionality with configurable rounds.\n *\n * @example\n * import { Bcrypt } from '@adonisjs/core/hash/drivers/bcrypt'\n *\n * const bcrypt = new Bcrypt({ rounds: 12 })\n * const hashed = await bcrypt.make('password')\n * const isValid = await bcrypt.verify(hashed, 'password')\n */\nexport * from '@adonisjs/hash/drivers/bcrypt'\n"
  },
  {
    "path": "modules/hash/drivers/scrypt.ts",
    "content": "/*\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\nexport * from '@adonisjs/hash/drivers/scrypt'\n"
  },
  {
    "path": "modules/hash/main.ts",
    "content": "/*\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\n/**\n * Hash module provides password hashing functionality with multiple driver support.\n * Re-exports all functionality from @adonisjs/hash along with configuration utilities.\n *\n * @example\n * // Import the Hash manager and drivers\n * import { HashManager, Hash } from '@adonisjs/core/hash'\n *\n * const manager = new HashManager(config)\n * const hasher = manager.use('scrypt')\n * const hashed = await hasher.make('password')\n * const verified = await hasher.verify(hashed, 'password')\n *\n * @example\n * // Import configuration and driver types\n * import { defineConfig, drivers } from '@adonisjs/core/hash'\n * import type { HashConfig, ScryptConfig } from '@adonisjs/core/types/hash'\n */\nexport * from '@adonisjs/hash'\nexport { defineConfig, drivers } from './define_config.ts'\n"
  },
  {
    "path": "modules/hash/phc_formatter.ts",
    "content": "/*\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\nexport * from '@adonisjs/hash/phc_formatter'\n"
  },
  {
    "path": "modules/health.ts",
    "content": "/*\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\nexport * from '@adonisjs/health'\n"
  },
  {
    "path": "modules/http/helpers.ts",
    "content": "/*\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\nexport * from '@adonisjs/http-server/helpers'\n"
  },
  {
    "path": "modules/http/main.ts",
    "content": "/*\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\n/**\n * Bodyparser import is needed to merge types of Request\n * class augmented by the bodyparser package\n */\nimport '@adonisjs/bodyparser'\nexport * from '@adonisjs/http-server'\nexport { RequestValidator } from './request_validator.ts'\n"
  },
  {
    "path": "modules/http/request_validator.ts",
    "content": "/*\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 { ValidationError, VineValidator } from '@vinejs/vine'\nimport type {\n  Infer,\n  SchemaTypes,\n  ErrorReporterContract,\n  MessagesProviderContact,\n} from '@vinejs/vine/types'\n\nimport type { HttpContext } from './main.ts'\nimport type { RequestValidationOptions } from '../../types/http.ts'\n\n/**\n * Request validator for validating HTTP request data using VineJS validators.\n * This class provides a convenient way to validate request body, files, cookies,\n * headers, and URL parameters in AdonisJS applications.\n *\n * @example\n * ```ts\n * // Inside a controller method\n * const data = await request.validateUsing(createUserValidator, {\n *   messagesProvider: customMessages\n * })\n * ```\n */\nexport class RequestValidator {\n  #ctx: HttpContext\n\n  constructor(ctx: HttpContext) {\n    this.#ctx = ctx\n  }\n\n  /**\n   * The error reporter method returns the error reporter\n   * to use for reporting errors.\n   *\n   * You can use this function to pick a different error reporter\n   * for each HTTP request\n   */\n  static errorReporter?: (_: HttpContext) => ErrorReporterContract\n\n  /**\n   * The messages provider method returns the messages provider to use\n   * finding custom error messages\n   *\n   * You can use this function to pick a different messages provider for\n   * each HTTP request\n   */\n  static messagesProvider?: (_: HttpContext) => MessagesProviderContact\n\n  #requestData() {\n    const requestBody = this.#ctx.request.all()\n    return {\n      ...requestBody,\n      params: this.#ctx.request.params(),\n      headers: this.#ctx.request.headers(),\n      cookies: this.#ctx.request.cookiesList(),\n    }\n  }\n\n  #processValidatorOptions<MetaData extends undefined | Record<string, any>>(\n    options: RequestValidationOptions<MetaData> | undefined\n  ): RequestValidationOptions<any> {\n    const validatorOptions: RequestValidationOptions<any> = options || {}\n\n    /**\n     * Assign request specific error reporter\n     */\n    if (RequestValidator.errorReporter && !validatorOptions.errorReporter) {\n      const errorReporter = RequestValidator.errorReporter(this.#ctx)\n      validatorOptions.errorReporter = () => errorReporter\n    }\n\n    /**\n     * Assign request specific messages provider\n     */\n    if (RequestValidator.messagesProvider && !validatorOptions.messagesProvider) {\n      validatorOptions.messagesProvider = RequestValidator.messagesProvider(this.#ctx)\n    }\n\n    return validatorOptions\n  }\n\n  /**\n   * Validate the current HTTP request data using a VineJS validator.\n   * This method automatically includes request body, files, URL parameters,\n   * headers, and cookies in the validation data.\n   *\n   * @param validator - VineJS validator instance\n   * @param options - Optional validation options including custom error reporters and messages\n   *\n   * @example\n   * ```ts\n   * const createUserValidator = vine.compile(\n   *   vine.object({\n   *     email: vine.string().email(),\n   *     name: vine.string().minLength(3)\n   *   })\n   * )\n   *\n   * const data = await request.validateUsing(createUserValidator, {\n   *   errorReporter: () => vine.errors.SimpleErrorReporter,\n   *   messagesProvider: customMessages\n   * })\n   * ```\n   */\n  validateUsing<Schema extends SchemaTypes, MetaData extends undefined | Record<string, any>>(\n    validator: VineValidator<Schema, MetaData>,\n    ...[options]: [undefined] extends MetaData\n      ? [options?: RequestValidationOptions<MetaData> | undefined]\n      : [options: RequestValidationOptions<MetaData>]\n  ): Promise<Infer<Schema>> {\n    /**\n     * Process the validation options\n     */\n    const validatorOptions = this.#processValidatorOptions(options)\n\n    /**\n     * Data to validate\n     */\n    const data = validatorOptions.data || this.#requestData()\n\n    return validator.validate(data, validatorOptions as any)\n  }\n\n  async tryValidateUsing<\n    Schema extends SchemaTypes,\n    MetaData extends undefined | Record<string, any>,\n  >(\n    validator: VineValidator<Schema, MetaData>,\n    ...[options]: [undefined] extends MetaData\n      ? [options?: RequestValidationOptions<MetaData> | undefined]\n      : [options: RequestValidationOptions<MetaData>]\n  ): Promise<[ValidationError, null] | [null, Infer<Schema>]> {\n    /**\n     * Process the validation options\n     */\n    const validatorOptions = this.#processValidatorOptions(options)\n\n    /**\n     * Data to validate\n     */\n    const data = validatorOptions.data || this.#requestData()\n\n    return validator.tryValidate(data, validatorOptions as any)\n  }\n}\n"
  },
  {
    "path": "modules/http/url_builder_client.ts",
    "content": "/*\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\nexport * from '@adonisjs/http-server/client/url_builder'\n"
  },
  {
    "path": "modules/logger.ts",
    "content": "/*\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 LoggerConfig, type PrettyTargetOptions } from '@adonisjs/logger/types'\n\nimport { destination } from '@adonisjs/logger'\nexport * from '@adonisjs/logger'\n\n/**\n * Creates a synchronous Pino Pretty stream for formatted log output.\n *\n * This function is specifically designed for testing and development environments\n * where synchronous log output is preferred. By default, Pino uses asynchronous\n * logging which can make it difficult to correlate logs with specific actions\n * during debugging or testing.\n *\n * @param options - Configuration options for the pretty printer\n *\n * @example\n * const loggerConfig = defineConfig({\n *   default: 'app',\n *   loggers: {\n *     app: {\n *       enabled: true,\n *       name: env.get('APP_NAME'),\n *       level: env.get('LOG_LEVEL'),\n *       desination: !app.inProduction && (await syncDestination()),\n *       transport: {\n *         targets: [targets.file({ destination: 1 })],\n *       },\n *     },\n *   }\n * })\n *\n * @returns A promise that resolves to a PrettyStream instance\n */\nexport async function syncDestination(\n  options?: PrettyTargetOptions\n): Promise<LoggerConfig['desination']> {\n  const { default: pinoPretty, isColorSupported } = await import('pino-pretty')\n  return isColorSupported ? pinoPretty({ ...options, sync: true }) : destination(1)\n}\n"
  },
  {
    "path": "modules/repl.ts",
    "content": "/*\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\nexport * from '@adonisjs/repl'\n"
  },
  {
    "path": "modules/transformers/main.ts",
    "content": "/*\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\nexport * from '@adonisjs/http-transformers'\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"@adonisjs/core\",\n  \"description\": \"Core of AdonisJS\",\n  \"version\": \"7.1.1\",\n  \"engines\": {\n    \"node\": \">=24.0.0\"\n  },\n  \"main\": \"build/index.js\",\n  \"type\": \"module\",\n  \"files\": [\n    \"build\",\n    \"!build/bin\",\n    \"!build/tests\"\n  ],\n  \"bin\": {\n    \"adonis-kit\": \"./build/toolkit/main.js\"\n  },\n  \"exports\": {\n    \".\": \"./build/index.js\",\n    \"./commands\": \"./build/commands/main.js\",\n    \"./commands/*\": \"./build/commands/*.js\",\n    \"./factories\": \"./build/factories/core/main.js\",\n    \"./factories/*\": \"./build/factories/*.js\",\n    \"./types\": \"./build/src/types.js\",\n    \"./types/*\": \"./build/types/*.js\",\n    \"./services/*\": \"./build/services/*.js\",\n    \"./providers/*\": \"./build/providers/*.js\",\n    \"./helpers\": \"./build/src/helpers/main.js\",\n    \"./helpers/*\": \"./build/src/helpers/*.js\",\n    \"./ace\": \"./build/modules/ace/main.js\",\n    \"./ace/codemods\": \"./build/modules/ace/codemods.js\",\n    \"./bodyparser\": \"./build/modules/bodyparser/main.js\",\n    \"./bodyparser_middleware\": \"./build/modules/bodyparser/bodyparser_middleware.js\",\n    \"./hash\": \"./build/modules/hash/main.js\",\n    \"./hash/phc_formatter\": \"./build/modules/hash/phc_formatter.js\",\n    \"./hash/drivers/argon\": \"./build/modules/hash/drivers/argon.js\",\n    \"./hash/drivers/bcrypt\": \"./build/modules/hash/drivers/bcrypt.js\",\n    \"./hash/drivers/scrypt\": \"./build/modules/hash/drivers/scrypt.js\",\n    \"./app\": \"./build/modules/app.js\",\n    \"./config\": \"./build/modules/config.js\",\n    \"./container\": \"./build/modules/container.js\",\n    \"./encryption\": \"./build/modules/encryption/main.js\",\n    \"./encryption/drivers/aes_256_cbc\": \"./build/modules/encryption/drivers/aes_256_cbc.js\",\n    \"./encryption/drivers/aes_256_gcm\": \"./build/modules/encryption/drivers/aes_256_gcm.js\",\n    \"./encryption/drivers/aes_siv\": \"./build/modules/encryption/drivers/aes_siv.js\",\n    \"./encryption/drivers/chacha20_poly1305\": \"./build/modules/encryption/drivers/chacha20_poly1305.js\",\n    \"./env\": \"./build/modules/env/main.js\",\n    \"./dumper\": \"./build/modules/dumper/main.js\",\n    \"./dumper/plugin_edge\": \"./build/modules/dumper/plugins/edge.js\",\n    \"./env/editor\": \"./build/modules/env/editor.js\",\n    \"./events\": \"./build/modules/events.js\",\n    \"./http\": \"./build/modules/http/main.js\",\n    \"./http/helpers\": \"./build/modules/http/helpers.js\",\n    \"./http/url_builder_client\": \"./build/modules/http/url_builder_client.js\",\n    \"./logger\": \"./build/modules/logger.js\",\n    \"./repl\": \"./build/modules/repl.js\",\n    \"./transformers\": \"./build/modules/transformers/main.js\",\n    \"./package.json\": \"./package.json\",\n    \"./exceptions\": \"./build/src/exceptions.js\",\n    \"./test_utils\": \"./build/src/test_utils/main.js\",\n    \"./health\": \"./build/modules/health.js\",\n    \"./vine\": \"./build/src/vine.js\"\n  },\n  \"scripts\": {\n    \"pretest\": \"npm run lint\",\n    \"test\": \"cross-env NODE_DEBUG=adonisjs:core npm run quick:test\",\n    \"clean\": \"del-cli build\",\n    \"copy:templates\": \"copyfiles \\\"stubs/**/**/*.stub\\\" --up=1 build\",\n    \"precompile\": \"npm run lint\",\n    \"compile\": \"npm run clean && tsdown && tsc --emitDeclarationOnly --declaration\",\n    \"postcompile\": \"npm run copy:templates && npm run index:commands\",\n    \"build\": \"npm run compile\",\n    \"docs\": \"typedoc\",\n    \"release\": \"npx release-it\",\n    \"version\": \"npm run build\",\n    \"prepublishOnly\": \"npm run build\",\n    \"lint\": \"eslint .\",\n    \"typecheck\": \"tsc --noEmit\",\n    \"format\": \"prettier --write .\",\n    \"quick:test\": \"node --import=@poppinss/ts-exec --enable-source-maps bin/test.ts --force-exit\",\n    \"citgm\": \"cross-env FORCE_COLOR=0 node --import=@poppinss/ts-exec bin/test.ts --force-exit\",\n    \"index:commands\": \"node --import=@poppinss/ts-exec toolkit/main.js index build/commands\"\n  },\n  \"devDependencies\": {\n    \"@adonisjs/assembler\": \"^8.0.1\",\n    \"@adonisjs/eslint-config\": \"^3.0.0\",\n    \"@adonisjs/prettier-config\": \"^1.4.5\",\n    \"@adonisjs/tsconfig\": \"^2.0.0\",\n    \"@japa/assert\": \"^4.2.0\",\n    \"@japa/expect-type\": \"^2.0.4\",\n    \"@japa/file-system\": \"^3.0.0\",\n    \"@japa/runner\": \"^5.3.0\",\n    \"@japa/snapshot\": \"^2.0.10\",\n    \"@poppinss/ts-exec\": \"^1.4.4\",\n    \"@release-it/conventional-changelog\": \"^10.0.6\",\n    \"@types/node\": \"~25.5.0\",\n    \"@types/pretty-hrtime\": \"^1.0.3\",\n    \"@types/sinon\": \"^21.0.0\",\n    \"@types/supertest\": \"^7.2.0\",\n    \"@types/test-console\": \"^2.0.3\",\n    \"@vinejs/vine\": \"^4.3.0\",\n    \"argon2\": \"^0.44.0\",\n    \"bcrypt\": \"^6.0.0\",\n    \"c8\": \"^11.0.0\",\n    \"copyfiles\": \"^2.4.1\",\n    \"cross-env\": \"^10.1.0\",\n    \"del-cli\": \"^7.0.0\",\n    \"edge.js\": \"^6.5.0\",\n    \"eslint\": \"^10.0.3\",\n    \"execa\": \"^9.6.1\",\n    \"get-port\": \"^7.1.0\",\n    \"pino-pretty\": \"^13.1.3\",\n    \"prettier\": \"^3.8.1\",\n    \"release-it\": \"^19.2.4\",\n    \"sinon\": \"^21.0.3\",\n    \"supertest\": \"^7.2.2\",\n    \"test-console\": \"^2.0.0\",\n    \"timekeeper\": \"^2.3.1\",\n    \"tsdown\": \"^0.21.4\",\n    \"typedoc\": \"^0.28.17\",\n    \"typescript\": \"^5.9.3\",\n    \"youch\": \"^4.1.0\"\n  },\n  \"dependencies\": {\n    \"@adonisjs/ace\": \"^14.0.1\",\n    \"@adonisjs/application\": \"^9.0.0\",\n    \"@adonisjs/bodyparser\": \"^11.0.0\",\n    \"@adonisjs/config\": \"^6.1.0\",\n    \"@adonisjs/env\": \"^7.0.0\",\n    \"@adonisjs/events\": \"^10.1.0\",\n    \"@adonisjs/fold\": \"^11.0.0\",\n    \"@adonisjs/hash\": \"^10.0.0\",\n    \"@adonisjs/health\": \"^3.1.0\",\n    \"@adonisjs/http-server\": \"^8.0.0\",\n    \"@adonisjs/http-transformers\": \"^2.3.1\",\n    \"@adonisjs/logger\": \"^7.1.1\",\n    \"@adonisjs/repl\": \"^5.0.0\",\n    \"@boringnode/encryption\": \"^1.0.0\",\n    \"@poppinss/colors\": \"^4.1.6\",\n    \"@poppinss/dumper\": \"^0.7.0\",\n    \"@poppinss/macroable\": \"^1.1.1\",\n    \"@poppinss/utils\": \"^7.0.1\",\n    \"@sindresorhus/is\": \"^7.2.0\",\n    \"@types/he\": \"^1.2.3\",\n    \"error-stack-parser-es\": \"^1.0.5\",\n    \"he\": \"^1.2.0\",\n    \"pretty-hrtime\": \"^1.0.3\",\n    \"string-width\": \"^8.2.0\"\n  },\n  \"peerDependencies\": {\n    \"@adonisjs/assembler\": \"^8.0.0-next.23 || ^8.0.0\",\n    \"@vinejs/vine\": \"^4.0.0\",\n    \"argon2\": \"^0.44.0\",\n    \"bcrypt\": \"^6.0.0\",\n    \"edge.js\": \"^6.2.0\",\n    \"pino-pretty\": \"^13.1.3\",\n    \"youch\": \"^4.1.0-beta.13 || ^4.1.0\"\n  },\n  \"peerDependenciesMeta\": {\n    \"argon2\": {\n      \"optional\": true\n    },\n    \"bcrypt\": {\n      \"optional\": true\n    },\n    \"@adonisjs/assembler\": {\n      \"optional\": true\n    },\n    \"@vinejs/vine\": {\n      \"optional\": true\n    },\n    \"edge.js\": {\n      \"optional\": true\n    },\n    \"youch\": {\n      \"optional\": true\n    },\n    \"pino-pretty\": {\n      \"optional\": true\n    }\n  },\n  \"homepage\": \"https://github.com/adonisjs/core#readme\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/adonisjs/core.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/adonisjs/core/issues\"\n  },\n  \"keywords\": [\n    \"adonisjs\",\n    \"framework\",\n    \"mvc\"\n  ],\n  \"author\": \"Harminder Virk <virk@adonisjs.com>\",\n  \"contributors\": [\n    \"Romain Lanz <romain.lanz@pm.me>\",\n    \"Julien Ripouteau <julien@ripouteau.com>\",\n    \"Michaël Zasso\"\n  ],\n  \"license\": \"MIT\",\n  \"publishConfig\": {\n    \"provenance\": true,\n    \"access\": \"public\"\n  },\n  \"c8\": {\n    \"reporter\": [\n      \"text\",\n      \"html\"\n    ],\n    \"exclude\": [\n      \"tests/**\",\n      \"build/**\",\n      \"factories/**\",\n      \".yalc/**\"\n    ]\n  },\n  \"commitlint\": {\n    \"extends\": [\n      \"@commitlint/config-conventional\"\n    ]\n  },\n  \"tsdown\": {\n    \"entry\": [\n      \"index.ts\",\n      \"commands/main.ts\",\n      \"commands/**/*.ts\",\n      \"factories/core/main.ts\",\n      \"factories/**/*.ts\",\n      \"src/types.ts\",\n      \"toolkit/main.ts\",\n      \"types/**/*.ts\",\n      \"services/**/*.ts\",\n      \"providers/**/*.ts\",\n      \"src/helpers/main.ts\",\n      \"src/helpers/**/*.ts\",\n      \"modules/ace/main.ts\",\n      \"modules/ace/codemods.ts\",\n      \"modules/bodyparser/main.ts\",\n      \"modules/bodyparser/bodyparser_middleware.ts\",\n      \"modules/hash/main.ts\",\n      \"modules/hash/phc_formatter.ts\",\n      \"modules/hash/drivers/*.ts\",\n      \"modules/app.ts\",\n      \"modules/config.ts\",\n      \"modules/container.ts\",\n      \"modules/encryption/main.ts\",\n      \"modules/encryption/drivers/*.ts\",\n      \"modules/env/main.ts\",\n      \"modules/dumper/main.ts\",\n      \"modules/dumper/plugins/edge.ts\",\n      \"modules/env/editor.ts\",\n      \"modules/events.ts\",\n      \"modules/http/main.ts\",\n      \"modules/http/helpers.ts\",\n      \"modules/http/url_builder_client.ts\",\n      \"modules/logger.ts\",\n      \"modules/repl.ts\",\n      \"modules/transformers/main.ts\",\n      \"src/exceptions.ts\",\n      \"src/test_utils/main.ts\",\n      \"modules/health.ts\",\n      \"src/vine.ts\"\n    ],\n    \"outDir\": \"./build\",\n    \"clean\": true,\n    \"format\": \"esm\",\n    \"minify\": \"dce-only\",\n    \"fixedExtension\": false,\n    \"dts\": false,\n    \"treeshake\": false,\n    \"sourcemaps\": false,\n    \"target\": \"esnext\"\n  },\n  \"release-it\": {\n    \"git\": {\n      \"requireCleanWorkingDir\": true,\n      \"requireUpstream\": true,\n      \"commitMessage\": \"chore(release): ${version}\",\n      \"tagAnnotation\": \"v${version}\",\n      \"push\": true,\n      \"tagName\": \"v${version}\"\n    },\n    \"github\": {\n      \"release\": true\n    },\n    \"npm\": {\n      \"publish\": true,\n      \"skipChecks\": true\n    },\n    \"plugins\": {\n      \"@release-it/conventional-changelog\": {\n        \"preset\": {\n          \"name\": \"angular\"\n        }\n      }\n    }\n  },\n  \"prettier\": \"@adonisjs/prettier-config\"\n}\n"
  },
  {
    "path": "providers/app_provider.ts",
    "content": "/*\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 { dirname } from 'node:path'\nimport { mkdir, writeFile } from 'node:fs/promises'\n\nimport { Config } from '../modules/config.ts'\nimport { Logger } from '../modules/logger.ts'\nimport { Application } from '../modules/app.ts'\nimport { Dumper } from '../modules/dumper/dumper.ts'\nimport { RuntimeException } from '../src/exceptions.ts'\nimport { Router, Server } from '../modules/http/main.ts'\nimport { BaseEvent, Emitter } from '../modules/events.ts'\nimport { Encryption } from '../modules/encryption/main.ts'\nimport { configProvider } from '../src/config_provider.ts'\nimport type { ApplicationService, LoggerService } from '../src/types.ts'\nimport BodyParserMiddleware from '../modules/bodyparser/bodyparser_middleware.ts'\n\n/**\n * The Application Service provider registers all the baseline\n * features required to run the framework.\n *\n * This provider handles the registration of core services including:\n * - Application instance\n * - Logger and logger manager\n * - Configuration\n * - Event emitter\n * - Encryption service\n * - HTTP server and router\n * - Body parser middleware\n * - Dumper for debugging\n * - Test utilities and ACE kernel\n *\n * @example\n * const provider = new AppServiceProvider(app)\n * provider.register()\n * await provider.boot()\n * await provider.ready()\n */\nexport default class AppServiceProvider {\n  /**\n   * Application service provider constructor\n   *\n   * @param app - The application service instance\n   */\n  constructor(protected app: ApplicationService) {}\n\n  /**\n   * Registers test utils with the container\n   *\n   * Creates a singleton binding for 'testUtils' that lazily imports\n   * and instantiates the TestUtils class when first accessed.\n   *\n   * @example\n   * const testUtils = await app.container.make('testUtils')\n   * testUtils.createHttpContext()\n   */\n  protected registerTestUtils() {\n    this.app.container.singleton('testUtils', async () => {\n      const { TestUtils } = await import('../src/test_utils/main.js')\n      return new TestUtils(this.app)\n    })\n  }\n\n  /**\n   * Registers ace with the container\n   *\n   * Creates a singleton binding for 'ace' that lazily creates\n   * the ACE kernel for command-line interface functionality.\n   *\n   * @example\n   * const ace = await app.container.make('ace')\n   * await ace.exec('make:controller', ['UserController'])\n   */\n  protected registerAce() {\n    this.app.container.singleton('ace', async () => {\n      const { createAceKernel } = await import('../modules/ace/create_kernel.js')\n      return createAceKernel(this.app)\n    })\n  }\n\n  /**\n   * Registers the application to the container\n   *\n   * Binds the application instance as both a class binding and an alias.\n   * This allows access to the app instance throughout the container.\n   *\n   * @example\n   * const app = await container.make('app')\n   * const appPath = app.makePath('tmp')\n   */\n  protected registerApp() {\n    this.app.container.singleton(Application, () => this.app)\n    this.app.container.alias('app', Application)\n  }\n\n  /**\n   * Registers the logger class to resolve the default logger\n   *\n   * Creates a singleton binding for the Logger class that resolves\n   * the default logger instance from the logger manager.\n   *\n   * @example\n   * const logger = await container.make(Logger)\n   * logger.info('Application started')\n   */\n  protected registerLogger() {\n    this.app.container.singleton(Logger, async (resolver) => {\n      const loggerManager = await resolver.make('logger')\n      return loggerManager.use()\n    })\n  }\n\n  /**\n   * Registers the logger manager to the container\n   *\n   * Creates a singleton binding for 'logger' that instantiates\n   * the LoggerManager with configuration from config/logger.ts\n   *\n   * @example\n   * const loggerManager = await container.make('logger')\n   * const fileLogger = loggerManager.use('file')\n   */\n  protected registerLoggerManager() {\n    this.app.container.singleton('logger', async () => {\n      const { LoggerManager } = await import('../modules/logger.js')\n      const config = this.app.config.get<any>('logger')\n      return new LoggerManager<any>(config) as LoggerService\n    })\n  }\n\n  /**\n   * Registers the config to the container\n   *\n   * Binds the application's config instance as both a class binding\n   * and an alias, allowing access to configuration values.\n   *\n   * @example\n   * const config = await container.make('config')\n   * const appKey = config.get('app.appKey')\n   */\n  protected registerConfig() {\n    this.app.container.singleton(Config, () => this.app.config)\n    this.app.container.alias('config', Config)\n  }\n\n  /**\n   * Registers emitter service to the container\n   *\n   * Creates a singleton binding for the event emitter that handles\n   * application-wide event dispatching and listening.\n   *\n   * @example\n   * const emitter = await container.make('emitter')\n   * emitter.emit('user:created', { userId: 123 })\n   */\n  protected registerEmitter() {\n    this.app.container.singleton(Emitter, async () => {\n      return new Emitter(this.app) as Emitter<any>\n    })\n    this.app.container.alias('emitter', Emitter)\n  }\n\n  /**\n   * Registers the encryption service with the container\n   *\n   * Creates singleton bindings for both the encryption manager and\n   * the default encryption instance. Resolves configuration from\n   * config/encryption.ts file.\n   *\n   * @example\n   * const encryption = await container.make('encryption')\n   * const encrypted = encryption.encrypt('secret-data')\n   */\n  protected registerEncryption() {\n    this.app.container.singleton('encryption', async () => {\n      const encryptionConfigProvider = this.app.config.get('encryption')\n\n      /**\n       * Resolve config from the provider\n       */\n      const config = await configProvider.resolve<any>(this.app, encryptionConfigProvider)\n      if (!config) {\n        throw new RuntimeException(\n          'Invalid \"config/encryption.ts\" file. Make sure you are using the \"defineConfig\" method'\n        )\n      }\n\n      const { EncryptionManager } = await import('../modules/encryption/main.js')\n      return new EncryptionManager(config)\n    })\n\n    this.app.container.singleton(Encryption, async (resolver) => {\n      const encryptionManager = await resolver.make('encryption')\n      return encryptionManager.use()\n    })\n  }\n\n  /**\n   * Registers the HTTP server with the container as a singleton\n   *\n   * Creates a singleton binding for the HTTP server that handles\n   * incoming requests, with dependencies on encryption, emitter,\n   * logger, and HTTP configuration.\n   *\n   * @example\n   * const server = await container.make('server')\n   * server.start()\n   */\n  protected registerServer() {\n    this.app.container.singleton(Server, async (resolver) => {\n      const encryption = await resolver.make(Encryption)\n      const emitter = await resolver.make('emitter')\n      const logger = await resolver.make('logger')\n      const config = this.app.config.get<any>('app.http')\n      return new Server(this.app, encryption, emitter, logger, config)\n    })\n\n    this.app.container.alias('server', Server)\n  }\n\n  /**\n   * Registers router with the container as a singleton\n   *\n   * Creates a singleton binding for the router by getting it from\n   * the HTTP server instance. The router handles URL routing.\n   *\n   * @example\n   * const router = await container.make('router')\n   * router.get('/', ({ response }) => response.send('Hello'))\n   */\n  protected registerRouter() {\n    this.app.container.singleton(Router, async (resolver) => {\n      const server = await resolver.make('server')\n      return server.getRouter()\n    })\n    this.app.container.alias('router', Router)\n  }\n\n  /**\n   * Self construct bodyparser middleware class, since it needs\n   * config that cannot be resolved by the container\n   *\n   * Binds the BodyParserMiddleware with bodyparser configuration\n   * and experimental flags for parsing request bodies.\n   *\n   * @example\n   * const middleware = await container.make(BodyParserMiddleware)\n   * await middleware.handle(ctx, next)\n   */\n  protected registerBodyParserMiddleware() {\n    this.app.container.singleton(BodyParserMiddleware, () => {\n      const config = this.app.config.get<any>('bodyparser')\n      return new BodyParserMiddleware(config, this.app.experimentalFlags)\n    })\n  }\n\n  /**\n   * Registeres singleton instance of the \"Dumper\" module configured\n   * via the \"config/app.ts\" file.\n   *\n   * The dumper is used for debugging and variable inspection with\n   * configurable HTML and console output formats.\n   *\n   * @example\n   * const dumper = await container.make('dumper')\n   * dumper.dump({ user: { name: 'John' } })\n   */\n  protected registerDumper() {\n    this.app.container.singleton(Dumper, async () => {\n      const config = this.app.config.get<any>('app.dumper', {})\n      const dumper = new Dumper(this.app)\n\n      if (config.html) {\n        dumper.configureHtmlOutput(config.html)\n      }\n      if (config.console) {\n        dumper.configureAnsiOutput(config.console)\n      }\n\n      return dumper\n    })\n\n    this.app.container.alias('dumper', Dumper)\n  }\n\n  /**\n   * Generates TypeScript type definitions and JSON representation of routes\n   *\n   * Creates route type definitions for better IDE support and a JSON file\n   * containing all registered routes. This is used in development mode for\n   * tooling integration and type-safety.\n   *\n   * @param router - The router instance containing registered routes\n   *\n   * @example\n   * const router = await container.make('router')\n   * await this.emitRoutes(router)\n   * // Generates .adonisjs/server/routes.d.ts and routes.json\n   */\n  protected async emitRoutes(router: Router) {\n    try {\n      const { routes, imports, types } = router.generateTypes(2)\n      const routesTypesPath = this.app.generatedServerPath('routes.d.ts')\n      const routesJsonPath = this.app.generatedServerPath('routes.json')\n\n      await mkdir(dirname(routesTypesPath), { recursive: true })\n      await Promise.all([\n        writeFile(\n          routesTypesPath,\n          [\n            `import '@adonisjs/core/types/http'`,\n            ...imports,\n            '',\n            ...types,\n            '',\n            'export type ScannedRoutes = {',\n            routes,\n            '}',\n            `declare module '@adonisjs/core/types/http' {`,\n            '  export interface RoutesList extends ScannedRoutes {}',\n            '}',\n          ].join('\\n')\n        ),\n        writeFile(routesJsonPath, JSON.stringify(router.toJSON())),\n      ])\n\n      this.app.notify({ isAdonisJS: true, routesFileLocation: routesJsonPath })\n    } catch (error) {\n      console.error(\n        \"Unable to generate routes types file due to the following error. This won't impact the dev-server\"\n      )\n      console.error(error)\n    }\n  }\n\n  /**\n   * Registers bindings\n   *\n   * Called during the application bootstrap phase to register\n   * all core service bindings with the IoC container.\n   *\n   * @example\n   * const provider = new AppServiceProvider(app)\n   * provider.register() // Registers all core services\n   */\n  register() {\n    this.registerApp()\n    this.registerAce()\n    this.registerDumper()\n    this.registerLoggerManager()\n    this.registerLogger()\n    this.registerConfig()\n    this.registerEmitter()\n    this.registerEncryption()\n    this.registerTestUtils()\n    this.registerServer()\n    this.registerRouter()\n    this.registerBodyParserMiddleware()\n  }\n\n  /**\n   * Boot the service provider\n   *\n   * Called after all providers have been registered. Sets up\n   * event emitter for BaseEvent and adds transform macro to HttpContext.\n   *\n   * @example\n   * await provider.boot()\n   * // Now HttpContext has transform method available\n   */\n  async boot() {\n    BaseEvent.useEmitter(await this.app.container.make('emitter'))\n  }\n\n  /**\n   * Called when the application is ready\n   *\n   * In non-production environments, generates route types and\n   * JSON files for development tooling when router is committed.\n   *\n   * @example\n   * await provider.ready()\n   * // Route types and JSON generated in development\n   */\n  async ready() {\n    if (!this.app.inProduction) {\n      const router = await this.app.container.make('router')\n      if (router.commited) {\n        await this.emitRoutes(router)\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "providers/edge_provider.ts",
    "content": "/*\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 edge, { type Edge } from 'edge.js'\nimport { type URLOptions } from '../types/http.ts'\nimport type { ApplicationService } from '../src/types.ts'\nimport { pluginEdgeDumper } from '../modules/dumper/plugins/edge.ts'\nimport { BriskRoute, HttpContext, Qs, type Route, type Router } from '../modules/http/main.ts'\nimport { type ClientRouteJSON } from '@adonisjs/http-server/client/url_builder'\n\ndeclare module '@adonisjs/core/http' {\n  interface HttpContext {\n    /**\n     * Reference to the edge renderer to render templates\n     * during an HTTP request\n     */\n    view: ReturnType<Edge['createRenderer']>\n  }\n\n  interface BriskRoute {\n    /**\n     * Render an edge template without defining an\n     * explicit route handler\n     */\n    render(template: string, data?: Record<string, any>): Route\n  }\n}\n\n/**\n * The Edge service provider configures Edge to work within\n * an AdonisJS application environment\n *\n * This provider integrates EdgeJS template engine with AdonisJS by:\n * - Mounting the views directory\n * - Configuring template caching for production\n * - Adding global helpers for route generation\n * - Creating isolated renderer instances for HTTP contexts\n * - Adding render macro to BriskRoute for template rendering\n *\n * @example\n * const provider = new EdgeServiceProvider(app)\n * await provider.boot()\n */\nexport default class EdgeServiceProvider {\n  /**\n   * Edge service provider constructor\n   *\n   * Sets the usingEdgeJS flag to true to indicate EdgeJS is being used.\n   *\n   * @param app - The application service instance\n   */\n  constructor(protected app: ApplicationService) {\n    this.app.usingEdgeJS = true\n  }\n\n  /**\n   * Bridge AdonisJS and Edge\n   *\n   * Configures EdgeJS integration by:\n   * - Setting up template mounting and caching\n   * - Defining global helpers (route, signedRoute, app, config)\n   * - Adding view getter to HttpContext for isolated rendering\n   * - Adding render macro to BriskRoute\n   * - Registering dumper plugin\n   *\n   * @example\n   * await provider.boot()\n   * // Now edge templates can use {{ route('home') }} helper\n   */\n  async boot() {\n    const app = this.app\n    const qs = new Qs(app.config.get<any>('app.http.qs', {}))\n    const router = await this.app.container.make('router')\n    const dumper = await this.app.container.make('dumper')\n\n    /**\n     * Resolves configuration values for Edge templates\n     *\n     * Provides access to application configuration within templates.\n     * Includes a 'has' method to check for config key existence.\n     *\n     * @param key - The configuration key to retrieve\n     * @param defaultValue - Optional default value if key doesn't exist\n     */\n    function edgeConfigResolver(key: string, defaultValue?: any) {\n      return app.config.get(key, defaultValue)\n    }\n    edgeConfigResolver.has = function (key: string) {\n      return app.config.has(key)\n    }\n\n    /**\n     * Generates client-side route definitions for frontend use\n     *\n     * Transforms router definitions into a serializable format that\n     * can be used in client-side JavaScript for route generation.\n     * Only includes named routes.\n     */\n    function clientRoutes() {\n      const routes = router.toJSON()\n      return Object.keys(routes).reduce<Record<string, ClientRouteJSON[]>>((result, domain) => {\n        result[domain] = routes[domain].reduce<ClientRouteJSON[]>((routesResult, route) => {\n          if (!route.name) {\n            return routesResult\n          }\n          routesResult.push({\n            domain: route.domain,\n            methods: route.methods,\n            pattern: route.pattern,\n            tokens: route.tokens,\n            name: route.name,\n          })\n          return routesResult\n        }, [])\n        return result\n      }, {})\n    }\n\n    /**\n     * Mount the default disk\n     */\n    edge.mount(app.viewsPath())\n\n    /**\n     * Cache templates in production\n     */\n    edge.configure({ cache: app.inProduction })\n\n    /**\n     * Define Edge global helpers\n     * @deprecated\n     */\n    edge.global('route', function (...args: Parameters<Router['makeUrl']>) {\n      return router.makeUrl(...args)\n    })\n    edge.global('signedRoute', function (...args: Parameters<Router['makeSignedUrl']>) {\n      return router.makeSignedUrl(...args)\n    })\n\n    edge.global('app', app)\n    edge.global('config', edgeConfigResolver)\n    edge.global('routes', function () {\n      return clientRoutes()\n    })\n    edge.global('routesJSON', function () {\n      return JSON.stringify(clientRoutes())\n    })\n\n    /**\n     * Route helpers\n     */\n    edge.global('urlFor', function (...args: any[]) {\n      return (router.urlBuilder.urlFor as any)(...args)\n    })\n    edge.global('signedUrlFor', function (...args: any[]) {\n      return (router.urlBuilder.signedUrlFor as any)(...args)\n    })\n\n    /**\n     * Sharing qs parser with templates\n     */\n    edge.global('qs', qs)\n\n    edge.global('formAttributes', function (route: string, params: any, options: URLOptions) {\n      const matchingRoute = router.findOrFail(route)\n\n      /**\n       * Normalize method and keep a reference to the original method\n       */\n      options = options ?? {}\n      let method = matchingRoute.methods[0].toUpperCase()\n      const original = method\n\n      /**\n       * In case of HEAD, we must use the GET method\n       */\n      if (method === 'HEAD') {\n        method = 'GET'\n      }\n\n      /**\n       * If method if not GET and POST, then use the querystring _method\n       * to and force update the method to \"POST\"\n       */\n      if (method !== 'GET' && method !== 'POST') {\n        method = 'POST'\n        options = { ...options, qs: { _method: original, ...options.qs } }\n      }\n\n      const { action } = (router.urlBuilder.urlFor.method as any)(\n        original,\n        route,\n        params,\n        options\n      ).form\n\n      return {\n        action,\n        method,\n      }\n    })\n\n    /**\n     * Creating a isolated instance of edge renderer\n     */\n    HttpContext.getter(\n      'view',\n      function (this: HttpContext) {\n        return edge.createRenderer().share({\n          request: this.request,\n        })\n      },\n      true\n    )\n\n    /**\n     * Adding brisk route to render templates without an\n     * explicit handler\n     */\n    BriskRoute.macro('render', function (this: BriskRoute, template, data) {\n      function rendersTemplate({ view }: HttpContext) {\n        return view.render(template, data)\n      }\n      Object.defineProperty(rendersTemplate, 'listArgs', { value: template, writable: false })\n      return this.setHandler(rendersTemplate)\n    })\n\n    edge.use(pluginEdgeDumper(dumper))\n  }\n}\n"
  },
  {
    "path": "providers/hash_provider.ts",
    "content": "/*\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 { RuntimeException } from '@poppinss/utils/exception'\n\nimport { Hash } from '../modules/hash/main.ts'\nimport { configProvider } from '../src/config_provider.ts'\nimport type { ApplicationService } from '../src/types.ts'\n\n/**\n * Registers the passwords hasher with the container\n *\n * This provider sets up password hashing functionality by:\n * - Registering the HashManager with configuration from config/hash.ts\n * - Providing a Hash class that uses the default hasher\n * - Supporting multiple hashing drivers (bcrypt, argon2, etc.)\n *\n * @example\n * const provider = new HashServiceProvider(app)\n * provider.register()\n * const hash = await app.container.make('hash')\n */\nexport default class HashServiceProvider {\n  /**\n   * Hash service provider constructor\n   *\n   * @param app - The application service instance\n   */\n  constructor(protected app: ApplicationService) {}\n\n  /**\n   * Registering the hash class to resolve an instance with the\n   * default hasher.\n   *\n   * Creates a singleton binding for the Hash class that resolves\n   * the default hasher from the hash manager.\n   *\n   * @example\n   * const hash = await container.make(Hash)\n   * const hashed = await hash.make('password')\n   */\n  protected registerHash() {\n    this.app.container.singleton(Hash, async (resolver) => {\n      const hashManager = await resolver.make('hash')\n      return hashManager.use()\n    })\n  }\n\n  /**\n   * Registers the hash manager with the container\n   *\n   * Creates a singleton binding for 'hash' that instantiates\n   * the HashManager with configuration from config/hash.ts file.\n   * Throws an error if the configuration is invalid.\n   *\n   * @example\n   * const hashManager = await container.make('hash')\n   * const bcryptHasher = hashManager.use('bcrypt')\n   */\n  protected registerHashManager() {\n    this.app.container.singleton('hash', async () => {\n      const hashConfigProvider = this.app.config.get('hash')\n\n      /**\n       * Resolve config from the provider\n       */\n      const config = await configProvider.resolve<any>(this.app, hashConfigProvider)\n      if (!config) {\n        throw new RuntimeException(\n          'Invalid \"config/hash.ts\" file. Make sure you are using the \"defineConfig\" method'\n        )\n      }\n\n      const { HashManager } = await import('../modules/hash/main.js')\n      return new HashManager(config)\n    })\n  }\n\n  /**\n   * Registers bindings\n   *\n   * Called during the application bootstrap phase to register\n   * the hash manager and hash class with the IoC container.\n   *\n   * @example\n   * const provider = new HashServiceProvider(app)\n   * provider.register() // Registers hash services\n   */\n  register() {\n    this.registerHashManager()\n    this.registerHash()\n  }\n}\n"
  },
  {
    "path": "providers/repl_provider.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { homedir } from 'node:os'\nimport { fsImportAll } from '@poppinss/utils/fs'\n\nimport { Repl } from '../modules/repl.ts'\nimport type { ApplicationService, ContainerBindings } from '../src/types.ts'\n\n/**\n * Resolves a container binding and sets it on the REPL\n * context\n *\n * This helper function makes a service from the container and\n * adds it to the REPL context with a notification message.\n *\n * @param app - The application service instance\n * @param repl - The REPL instance to add the binding to\n * @param binding - The container binding key to resolve\n *\n * @example\n * await resolveBindingForRepl(app, repl, 'router')\n * // Now 'router' variable is available in REPL\n */\nasync function resolveBindingForRepl(\n  app: ApplicationService,\n  repl: Repl,\n  binding: keyof ContainerBindings\n) {\n  repl.server!.context[binding] = await app.container.make(binding)\n  repl.notify(\n    `Loaded \"${binding}\" service. You can access it using the \"${repl.colors.underline(\n      binding\n    )}\" variable`\n  )\n}\n\n/**\n * REPL Service Provider configures the interactive Node.js REPL\n * for AdonisJS applications\n *\n * This provider sets up:\n * - REPL instance with history file support\n * - Helper methods for importing modules and making container bindings\n * - Quick access methods for loading common services (app, router, etc.)\n * - Utility methods for development and debugging\n *\n * @example\n * const provider = new ReplServiceProvider(app)\n * provider.register()\n * await provider.boot()\n */\nexport default class ReplServiceProvider {\n  /**\n   * REPL service provider constructor\n   *\n   * @param app - The application service instance\n   */\n  constructor(protected app: ApplicationService) {}\n\n  /**\n   * Registers the REPL binding\n   *\n   * Creates a singleton binding for the REPL with history file\n   * support in the user's home directory.\n   *\n   * @example\n   * const provider = new ReplServiceProvider(app)\n   * provider.register()\n   * const repl = await app.container.make('repl')\n   */\n  register() {\n    this.app.container.singleton(Repl, async () => {\n      return new Repl({\n        historyFilePath: join(homedir(), '.adonisjs_v6_repl_history'),\n      })\n    })\n    this.app.container.alias('repl', Repl)\n  }\n\n  /**\n   * Registering REPL bindings during provider boot\n   *\n   * Adds helper methods to the REPL instance including:\n   * - importDefault: Import default export from modules\n   * - importAll: Import all files from a directory\n   * - make: Create instances using container.make\n   * - load* methods: Quick access to common services\n   * - loadHelpers: Load utility helper functions\n   *\n   * @example\n   * await provider.boot()\n   * // REPL now has helper methods available\n   */\n  async boot() {\n    this.app.container.resolving('repl', (repl) => {\n      repl.addMethod(\n        'importDefault',\n        (_, modulePath: string) => {\n          return this.app.importDefault(modulePath)\n        },\n        {\n          description: 'Returns the default export for a module',\n        }\n      )\n\n      repl.addMethod(\n        'importAll',\n        (_, dirPath: string) => {\n          return fsImportAll(this.app.makeURL(dirPath), {\n            ignoreMissingRoot: false,\n          })\n        },\n        {\n          description: 'Import all files from a directory and assign them to a variable',\n        }\n      )\n\n      repl.addMethod(\n        'make',\n        (_, service: any, runtimeValues?: any[]) => {\n          return this.app.container.make(service, runtimeValues)\n        },\n        {\n          description: 'Make class instance using \"container.make\" method',\n        }\n      )\n\n      repl.addMethod(\n        'loadApp',\n        () => {\n          return resolveBindingForRepl(this.app, repl, 'app')\n        },\n        {\n          description: 'Load \"app\" service in the REPL context',\n        }\n      )\n\n      repl.addMethod(\n        'loadEncryption',\n        () => {\n          return resolveBindingForRepl(this.app, repl, 'encryption')\n        },\n        {\n          description: 'Load \"encryption\" service in the REPL context',\n        }\n      )\n\n      repl.addMethod(\n        'loadHash',\n        () => {\n          return resolveBindingForRepl(this.app, repl, 'hash')\n        },\n        {\n          description: 'Load \"hash\" service in the REPL context',\n        }\n      )\n\n      repl.addMethod(\n        'loadRouter',\n        () => {\n          return resolveBindingForRepl(this.app, repl, 'router')\n        },\n        {\n          description: 'Load \"router\" service in the REPL context',\n        }\n      )\n\n      repl.addMethod(\n        'loadConfig',\n        () => {\n          return resolveBindingForRepl(this.app, repl, 'config')\n        },\n        {\n          description: 'Load \"config\" service in the REPL context',\n        }\n      )\n\n      repl.addMethod(\n        'loadTestUtils',\n        () => {\n          return resolveBindingForRepl(this.app, repl, 'testUtils')\n        },\n        {\n          description: 'Load \"testUtils\" service in the REPL context',\n        }\n      )\n\n      repl.addMethod(\n        'loadHelpers',\n        async () => {\n          const { default: isModule } = await import('../src/helpers/is.js')\n          const { default: stringModule } = await import('../src/helpers/string.js')\n          const helpers = await import('../src/helpers/main.js')\n          repl.server!.context.helpers = {\n            string: stringModule,\n            is: isModule,\n            ...helpers,\n          }\n\n          repl.notify(\n            `Loaded \"helpers\" module. You can access it using the \"${repl.colors.underline(\n              'helpers'\n            )}\" variable`\n          )\n        },\n        {\n          description: 'Load \"helpers\" module in the REPL context',\n        }\n      )\n\n      repl.addMethod(\n        'loadUrlBuilder',\n        async () => {\n          const router = await this.app.container.make('router')\n          repl.server!.context.urlBuilder = router.urlBuilder\n          repl.notify(\n            `Loaded \"urlBuilder\" service. You can access it using the \"${repl.colors.underline(\n              'urlBuilder'\n            )}\" variable`\n          )\n        },\n        {\n          description: 'Load \"urlBuilder\" service in the REPL context',\n        }\n      )\n    })\n  }\n}\n"
  },
  {
    "path": "providers/vinejs_provider.ts",
    "content": "/*\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 { Vine } from '@vinejs/vine'\nimport type { ApplicationService } from '../src/types.ts'\nimport { HttpRequest, RequestValidator } from '../modules/http/main.ts'\nimport { type FileRuleValidationOptions, VineMultipartFile } from '../src/vine.ts'\n\n/**\n * Extend VineJS\n */\ndeclare module '@vinejs/vine' {\n  interface Vine {\n    file(options?: FileRuleValidationOptions): VineMultipartFile\n  }\n}\n\n/**\n * Extend HTTP request class\n */\ndeclare module '@adonisjs/core/http' {\n  interface HttpRequest extends RequestValidator {}\n}\n\n/**\n * The VineJS service provider integrates VineJS validation\n * library with AdonisJS application environment\n *\n * This provider sets up:\n * - File validation rule for multipart file uploads\n * - Request validation macro for easy validation in HTTP contexts\n * - Extension of VineJS with AdonisJS-specific validation features\n *\n * @example\n * const provider = new VineJSServiceProvider(app)\n * provider.boot()\n * // Now Request has validateUsing method\n */\nexport default class VineJSServiceProvider {\n  /**\n   * VineJS service provider constructor\n   *\n   * Sets the usingVineJS flag to true to indicate VineJS is being used.\n   *\n   * @param app - The application service instance\n   */\n  constructor(protected app: ApplicationService) {\n    this.app.usingVineJS = true\n  }\n\n  /**\n   * Boot the VineJS service provider\n   *\n   * Extends VineJS with file validation macro and adds validateUsing\n   * method to the Request class for easy validation in HTTP contexts.\n   *\n   * @example\n   * provider.boot()\n   * // Now vine.file() and request.validateUsing() are available\n   */\n  boot() {\n    /**\n     * The file method is used to validate a field to be a valid\n     * multipart file.\n     */\n    Vine.macro('file', function (this: Vine, options) {\n      return new VineMultipartFile(options)\n    })\n\n    /**\n     * The validate method can be used to validate the request\n     * data for the current request using VineJS validators\n     */\n    HttpRequest.macro('validateUsing', function (this: HttpRequest, ...args) {\n      return new RequestValidator(this.ctx!).validateUsing(...args)\n    })\n\n    HttpRequest.macro('tryValidateUsing', function (this: HttpRequest, ...args) {\n      return new RequestValidator(this.ctx!).tryValidateUsing(...args)\n    })\n  }\n}\n"
  },
  {
    "path": "services/ace.ts",
    "content": "/*\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 app from './app.ts'\nimport type { Kernel } from '../modules/ace/main.ts'\n\nlet ace: Kernel\n\n/**\n * Returns a singleton instance of the ace kernel\n * from the container.\n *\n * ace service is an instance of the \"Kernel\" class stored inside\n * the \"modules/ace/kernel.ts\" file\n */\nawait app.booted(async () => {\n  ace = await app.container.make('ace')\n})\n\nexport { ace as default }\n"
  },
  {
    "path": "services/app.ts",
    "content": "/*\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 { ApplicationService } from '../src/types.ts'\n\nlet app: ApplicationService\n\n/**\n * Set the application instance the app service should\n * be using. Other services relies on the same app\n * instance as well.\n *\n * app service is an instance of the \"Application\" exported from\n * the \"modules/app.ts\" file.\n */\nexport function setApp(appService: ApplicationService) {\n  app = appService\n}\n\nexport { app as default }\n"
  },
  {
    "path": "services/config.ts",
    "content": "/*\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 app from './app.ts'\nimport type { ApplicationService } from '../src/types.ts'\n\nlet config: ApplicationService['config']\n\n/**\n * The config service uses the config instance from the app service\n */\nawait app.booted(() => {\n  config = app.config\n})\n\nexport { config as default }\n"
  },
  {
    "path": "services/dumper.ts",
    "content": "/*\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 app from './app.ts'\nimport type { Dumper } from '../modules/dumper/dumper.ts'\n\nlet dumper: Dumper\n\n/**\n * dumper service is an instance of the \"Dumper\" class stored inside\n * the \"modules/dumper/dumper.ts\" file\n */\nawait app.booted(async () => {\n  dumper = await app.container.make('dumper')\n})\n\n/**\n * Dump a value and die. The dumped value will be displayed\n * using the HTML printer during an HTTP request or within\n * the console otherwise.\n */\nexport const dd = (value: unknown) => {\n  dumper.dd(value, 2)\n}\n"
  },
  {
    "path": "services/emitter.ts",
    "content": "/*\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 app from './app.ts'\nimport type { EmitterService } from '../src/types.ts'\n\nlet emitter: EmitterService\n\n/**\n * Returns a singleton instance of the emitter class\n * from the container\n */\nawait app.booted(async () => {\n  emitter = await app.container.make('emitter')\n})\n\nexport { emitter as default }\n"
  },
  {
    "path": "services/encryption.ts",
    "content": "/*\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 app from './app.ts'\nimport type { EncryptionService } from '../src/types.ts'\n\nlet encryption: EncryptionService\n\n/**\n * Returns a singleton instance of the encryption class\n * from the container\n */\nawait app.booted(async () => {\n  encryption = await app.container.make('encryption')\n})\n\nexport { encryption as default }\n"
  },
  {
    "path": "services/hash.ts",
    "content": "/*\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 app from './app.ts'\nimport type { HashService } from '../src/types.ts'\n\nlet hash: HashService\n\n/**\n * Returns a singleton instance of the Hash manager from the\n * container\n */\nawait app.booted(async () => {\n  hash = await app.container.make('hash')\n})\n\nexport { hash as default }\n"
  },
  {
    "path": "services/logger.ts",
    "content": "/*\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 app from './app.ts'\nimport type { LoggerService } from '../src/types.ts'\n\nlet logger: LoggerService\n\n/**\n * Returns a singleton instance of the logger class\n * from the container\n */\nawait app.booted(async () => {\n  logger = await app.container.make('logger')\n})\n\nexport { logger as default }\n"
  },
  {
    "path": "services/repl.ts",
    "content": "/*\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 app from './app.ts'\nimport type { Repl } from '../modules/repl.ts'\n\nlet repl: Repl\n\n/**\n * Returns a singleton instance of the Repl class from\n * the container\n */\nawait app.booted(async () => {\n  repl = await app.container.make('repl')\n})\n\nexport { repl as default }\n"
  },
  {
    "path": "services/router.ts",
    "content": "/*\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 app from './app.ts'\nimport type { HttpRouterService } from '../src/types.ts'\n\nlet router: HttpRouterService\n\n/**\n * Returns a singleton instance of the router class from\n * the container\n */\nawait app.booted(async () => {\n  router = await app.container.make('router')\n})\n\nexport { router as default }\n"
  },
  {
    "path": "services/server.ts",
    "content": "/*\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 app from './app.ts'\nimport type { HttpServerService } from '../src/types.ts'\n\nlet server: HttpServerService\n\n/**\n * Returns a singleton instance of the HTTP server\n * from the container\n */\nawait app.booted(async () => {\n  server = await app.container.make('server')\n})\n\nexport { server as default }\n"
  },
  {
    "path": "services/test_utils.ts",
    "content": "/*\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 app from './app.ts'\nimport type { TestUtils } from '../src/test_utils/main.ts'\n\nlet testUtils: TestUtils\n\n/**\n * Returns a singleton instance of the TestUtils class\n * from the container.\n *\n * testUtils service is an instance of the \"TestUtils\" exported from\n * the \"src/test_utils/main.ts\" file.\n */\nawait app.booted(async () => {\n  testUtils = await app.container.make('testUtils')\n})\n\nexport { testUtils as default }\n"
  },
  {
    "path": "services/url_builder.ts",
    "content": "/*\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 app from './app.ts'\nimport type { UrlBuilderSignedUrlFor, UrlBuilderUrlFor } from '../src/types.ts'\n\nlet urlFor: UrlBuilderUrlFor\nlet signedUrlFor: UrlBuilderSignedUrlFor\n\n/**\n * Returns a singleton instance of the router class from\n * the container\n */\nawait app.booted(async () => {\n  const router = await app.container.make('router')\n  urlFor = router.urlBuilder.urlFor\n  signedUrlFor = router.urlBuilder.signedUrlFor\n})\n\nexport { urlFor, signedUrlFor }\n"
  },
  {
    "path": "src/assembler_hooks/index_entities.ts",
    "content": "/*\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 CommonHooks } from '@adonisjs/assembler/types'\nimport stringHelpers from '../helpers/string.ts'\nimport { type IndexEntitiesConfig } from '../types.ts'\nimport { outputTransformerDataObjects } from '../utils.ts'\n\n/**\n * Configures the IndexGenerator to create barrel files for \"controllers\", \"events\",\n * and \"listeners\". This function is used as an assembler hook to automatically generate\n * index files that export all modules from specified directories.\n *\n * @param {IndexEntitiesConfig} entities - Configuration object for entities indexing\n *\n * @example\n * // Basic usage with default configuration\n * indexEntities({})\n *\n * @example\n * // Custom configuration for specific entities\n * indexEntities({\n *   events: {\n *     enabled: true,\n *     source: 'app/custom-events',\n *     importAlias: '#custom-events'\n *   },\n *   transformers: {\n *     enabled: true,\n *     withSharedProps: true,\n *     inertiaMiddlewareImportPath: '#middleware/inertia_middleware'\n *   },\n *   controllers: {\n *     enabled: false\n *   }\n * })\n *\n * @example\n * // Using custom glob patterns\n * indexEntities({\n *   listeners: {\n *     source: 'app/handlers',\n *     glob: '**\\/*_handler.ts'\n *   }\n * })\n */\nexport function indexEntities(entities: IndexEntitiesConfig = {}) {\n  const events = Object.assign(\n    {\n      enabled: true,\n      source: 'app/events',\n      importAlias: '#events',\n      skipSegments: ['events'],\n      output: '.adonisjs/server/events.ts',\n    },\n    entities.events\n  )\n  const listeners = Object.assign(\n    {\n      enabled: true,\n      source: 'app/listeners',\n      importAlias: '#listeners',\n      skipSegments: ['listeners'],\n      output: '.adonisjs/server/listeners.ts',\n    },\n    entities.listeners\n  )\n  const controllers = Object.assign(\n    {\n      enabled: true,\n      source: 'app/controllers',\n      importAlias: '#controllers',\n      skipSegments: ['controllers'],\n      output: '.adonisjs/server/controllers.ts',\n    },\n    entities.controllers\n  )\n  const transformers = Object.assign(\n    {\n      enabled: false,\n      source: 'app/transformers',\n      importAlias: '#transformers',\n      withSharedProps: false,\n      inertiaMiddlewareImportPath: '#middleware/inertia_middleware',\n      skipSegments: ['transformers'],\n      output: '.adonisjs/client/data.d.ts',\n    },\n    entities.transformers\n  )\n  const manifest = {\n    enabled: entities.manifest?.enabled ?? transformers.enabled,\n    source: 'config',\n    output: '.adonisjs/client/manifest.d.ts',\n    exclude: entities.manifest?.exclude ?? [\n      'app.ts',\n      'bodyparser.ts',\n      'cors.ts',\n      'database.ts',\n      'encryption.ts',\n      'inertia.ts',\n      'session.ts',\n      'shield.ts',\n      'static.ts',\n      'vite.ts',\n    ],\n  }\n\n  return {\n    run(_, __, indexGenerator) {\n      if (events.enabled) {\n        indexGenerator.add('events', {\n          source: events.source,\n          disableLazyImports: true,\n          glob: events.glob,\n          as: 'barrelFile',\n          exportName: 'events',\n          importAlias: events.importAlias,\n          skipSegments: events.skipSegments,\n          output: events.output,\n          comment: true,\n        })\n      }\n\n      if (listeners.enabled) {\n        indexGenerator.add('listeners', {\n          source: listeners.source,\n          glob: listeners.glob,\n          as: 'barrelFile',\n          exportName: 'listeners',\n          importAlias: listeners.importAlias,\n          skipSegments: listeners.skipSegments,\n          output: listeners.output,\n          comment: true,\n        })\n      }\n\n      if (controllers.enabled) {\n        indexGenerator.add('controllers', {\n          source: controllers.source,\n          glob: controllers.glob,\n          as: 'barrelFile',\n          exportName: 'controllers',\n          importAlias: controllers.importAlias,\n          skipSegments: controllers.skipSegments,\n          removeSuffix: 'controller',\n          output: controllers.output,\n          comment: true,\n        })\n      }\n\n      if (transformers.enabled) {\n        indexGenerator.add('transformers', {\n          source: transformers.source,\n          glob: transformers.glob,\n          as(vfs, buffer, ___, helpers) {\n            const transformersList = vfs.asTree({\n              transformKey(key) {\n                let segments = key.split('/')\n                const baseName = segments.pop()!\n\n                if (transformers.skipSegments?.length) {\n                  segments = segments.filter((s) => !transformers.skipSegments!.includes(s))\n                }\n\n                return [\n                  ...segments.map((segment) => stringHelpers.pascalCase(segment)),\n                  stringHelpers.create(baseName).removeSuffix('transformer').pascalCase(),\n                ].join('/')\n              },\n              transformValue: helpers.toImportPath,\n            })\n            outputTransformerDataObjects(\n              transformersList,\n              buffer,\n              transformers.withSharedProps,\n              transformers.inertiaMiddlewareImportPath\n            )\n          },\n          importAlias: transformers.importAlias,\n          output: transformers.output,\n          comment: true,\n        })\n      }\n\n      if (manifest.enabled) {\n        indexGenerator.add('manifest', {\n          source: manifest.source,\n          filter: (filePath, isDirectory) => {\n            if (isDirectory) {\n              return true\n            }\n            if (!manifest.exclude?.length) {\n              return true\n            }\n            return !manifest.exclude.find((include) => filePath.endsWith(include))\n          },\n          as(vfs, buffer, ___, helpers) {\n            const configFilesList = vfs.asList()\n            buffer.write(`/// <reference path=\"../../adonisrc.ts\" />`)\n            Object.values(configFilesList).forEach((value) => {\n              buffer.write(`/// <reference path=\"${helpers.toImportPath(value)}\" />`)\n            })\n          },\n          output: manifest.output,\n          comment: true,\n        })\n      }\n    },\n  } satisfies CommonHooks['init'][number]\n}\n"
  },
  {
    "path": "src/cli_formatters/routes_list.ts",
    "content": "/*\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 stringWidth from 'string-width'\nimport type { UIPrimitives } from '../../types/ace.ts'\nimport { cliHelpers } from '../../modules/ace/main.ts'\nimport { type Router } from '../../modules/http/main.ts'\nimport { middlewareInfo, routeInfo } from '@adonisjs/http-server/helpers'\nimport type { MiddlewareHandlerInfo, RouteHandlerInfo, RouteJSON } from '../../types/http.ts'\n\n/**\n * Shape of the serialized route specific to the formatter\n */\ntype SerializedRoute = {\n  name: string\n  pattern: string\n  methods: string[]\n  middleware: MiddlewareHandlerInfo[]\n  handler: RouteHandlerInfo\n}\n\n/**\n * Routes list formatter is used to format the routes to JSON or an ANSI string\n * with pretty output.\n *\n * The decisions of colors, padding, alignment are all handled by the lists formatter\n *\n * @example\n * const formatter = new RoutesListFormatter(router, ui, {\n *   displayHeadRoutes: false,\n *   maxPrettyPrintWidth: 120\n * }, {\n *   match: 'api',\n *   middleware: ['auth']\n * })\n *\n * const ansiOutput = await formatter.formatAsAnsiList()\n */\nexport class RoutesListFormatter {\n  /**\n   * Router instance containing all registered routes\n   */\n  #router: Router\n\n  /**\n   * Colors utility for ANSI formatting\n   */\n  #colors: UIPrimitives['colors']\n\n  /**\n   * Table utility for creating formatted tables\n   */\n  #table: UIPrimitives['table']\n\n  /**\n   * Options for printing routes\n   */\n  #options: {\n    displayHeadRoutes?: boolean\n    maxPrettyPrintWidth?: number\n  }\n\n  /**\n   * Filters to apply when finding routes\n   */\n  #filters: {\n    match?: string\n    middleware?: string[]\n    ignoreMiddleware?: string[]\n  }\n\n  /**\n   * Creates a new instance of the routes list formatter\n   *\n   * @param router - Router instance containing routes to format\n   * @param ui - UI primitives for colors and table formatting\n   * @param options - Display options for route formatting\n   * @param filters - Filters to apply when displaying routes\n   */\n  constructor(\n    router: Router,\n    ui: UIPrimitives,\n    options: {\n      displayHeadRoutes?: boolean\n      maxPrettyPrintWidth?: number\n    },\n    filters: {\n      match?: string\n      middleware?: string[]\n      ignoreMiddleware?: string[]\n    }\n  ) {\n    this.#router = router\n    this.#colors = ui.colors\n    this.#table = ui.table\n    this.#filters = filters\n    this.#options = options\n    this.#router.commit()\n  }\n\n  /**\n   * Test if a route clears the applied filters based on middleware, name, pattern, and handler.\n   *\n   * @param route - The serialized route to test against filters\n   */\n  #isAllowedByFilters(route: SerializedRoute) {\n    let allowRoute = true\n\n    /**\n     * Check if the route is allowed by applying the middleware\n     * filter\n     */\n    if (this.#filters.middleware) {\n      allowRoute = this.#filters.middleware.every((name) => {\n        if (name === '*') {\n          return route.middleware.length > 0\n        }\n\n        return route.middleware.find((middleware) => middleware.name === name)\n      })\n    }\n\n    /**\n     * Check if the route has any or the ignored middleware. If yes, do not\n     * display the route\n     */\n    if (allowRoute && this.#filters.ignoreMiddleware) {\n      allowRoute = this.#filters.ignoreMiddleware.every((name) => {\n        if (name === '*') {\n          return route.middleware.length === 0\n        }\n\n        return !route.middleware.find((middleware) => middleware.name === name)\n      })\n    }\n\n    /**\n     * No more filters to be applied\n     */\n    if (!this.#filters.match) {\n      return allowRoute\n    }\n\n    /**\n     * Check if the route name has the match keyword\n     */\n    if (route.name.includes(this.#filters.match)) {\n      return true\n    }\n\n    /**\n     * Check if the route pattern has the match keyword\n     */\n    if (route.pattern.includes(this.#filters.match)) {\n      return true\n    }\n\n    /**\n     * Check if the route handler has the match keyword\n     */\n    if (\n      route.handler.type === 'controller'\n        ? route.handler.moduleNameOrPath.includes(this.#filters.match)\n        : route.handler.name.includes(this.#filters.match)\n    ) {\n      return true\n    }\n\n    /**\n     * Disallow route\n     */\n    return false\n  }\n\n  /**\n   * Serializes routes JSON to an object that can be used for pretty printing.\n   * Converts RouteJSON into a format suitable for display and filtering.\n   *\n   * @param route - The route JSON object to serialize\n   */\n  async #serializeRoute(route: RouteJSON): Promise<SerializedRoute> {\n    let methods = route.methods\n    if (!this.#options.displayHeadRoutes) {\n      methods = methods.filter((method) => method !== 'HEAD')\n    }\n\n    const middlewareList = await Promise.all(\n      [...route.middleware.all()].map((middleware) => {\n        return middlewareInfo(middleware)\n      })\n    )\n\n    return {\n      name: route.name || '',\n      pattern: route.pattern,\n      methods: methods,\n      handler: await routeInfo(route),\n      middleware: middlewareList.filter((info) => info.type !== 'global'),\n    }\n  }\n\n  /**\n   * Formats the route method for the ansi list and table with dim styling.\n   *\n   * @param method - The HTTP method to format (GET, POST, etc.)\n   */\n  #formatRouteMethod(method: string) {\n    return this.#colors.dim(method)\n  }\n\n  /**\n   * Formats route pattern for the ansi list and table with colored parameters and route name.\n   *\n   * @param route - The serialized route containing pattern and name information\n   */\n  #formatRoutePattern(route: SerializedRoute) {\n    const pattern = this.#router\n      .parsePattern(route.pattern)\n      .map((token) => {\n        if (token.type === 1) {\n          return this.#colors.yellow(`:${token.val}`)\n        }\n\n        if (token.type === 3) {\n          return this.#colors.yellow(`:${token.val}?`)\n        }\n\n        if (token.type === 2) {\n          return this.#colors.red(token.val)\n        }\n\n        return token.val\n      })\n      .join('/')\n\n    return `${pattern === '/' ? pattern : `/${pattern}`}${\n      route.name ? ` ${this.#colors.dim(`(${route.name})`)}` : ''\n    } `\n  }\n\n  /**\n   * Formats controller name for the ansi list and table with cyan coloring.\n   *\n   * @param route - The serialized route containing handler information\n   */\n  #formatControllerName(route: SerializedRoute) {\n    return route.handler.type === 'controller'\n      ? ` ${this.#colors.cyan(route.handler.moduleNameOrPath)}.`\n      : ''\n  }\n\n  /**\n   * Formats action name for the ansi list and table with cyan coloring and arguments.\n   *\n   * @param route - The serialized route containing handler information\n   */\n  #formatAction(route: SerializedRoute) {\n    if (route.handler.type === 'controller') {\n      return `${this.#colors.cyan(route.handler.method)}`\n    }\n\n    const functionName = ` ${this.#colors.cyan(route.handler.name)}`\n    if (route.handler.args) {\n      return ` ${functionName}${this.#colors.dim(`(${route.handler.args})`)}`\n    }\n\n    return functionName\n  }\n\n  /**\n   * Formats route middleware for the ansi list and table with optional compacting.\n   *\n   * @param route - The serialized route containing middleware information\n   * @param mode - Display mode: 'normal' shows all middleware, 'compact' truncates long lists\n   */\n  #formatMiddleware(route: SerializedRoute, mode: 'normal' | 'compact' = 'normal') {\n    if (mode === 'compact' && route.middleware.length > 3) {\n      const firstMiddleware = route.middleware[0].name\n      const secondMiddleware = route.middleware[1].name\n      const diff = route.middleware.length - 2\n      return this.#colors.dim(`${firstMiddleware}, ${secondMiddleware}, and ${diff} more`)\n    }\n\n    return this.#colors.dim(\n      `${route.middleware\n        .map((one) => one.name)\n        .filter((one) => one)\n        .join(', ')}`\n    )\n  }\n\n  /**\n   * Formatting the domain headling to be in green color with\n   * dots around it\n   */\n  #formatDomainHeadline(domain: string) {\n    if (domain !== 'root') {\n      return cliHelpers.justify([`${this.#colors.dim('..')} ${this.#colors.green(domain)} `], {\n        maxWidth: this.#options.maxPrettyPrintWidth || cliHelpers.TERMINAL_SIZE,\n        paddingChar: this.#colors.dim('.'),\n      })[0]\n    }\n    return ''\n  }\n\n  /**\n   * Justify the ansi list\n   */\n  #justifyListTables(tables: { heading: string; rows: [string, string, string, string][] }[]) {\n    return tables.map((table) => {\n      /**\n       * Formatting methods\n       */\n      const methods = table.rows.map((columns) => columns[0])\n      const largestMethodsLength = Math.max(...methods.map((method) => stringWidth(method)))\n      const formattedMethods = cliHelpers.justify(methods, {\n        maxWidth: largestMethodsLength,\n      })\n\n      /**\n       * Formatting patterns\n       */\n      const patterns = table.rows.map((columns) => columns[1])\n      const largestPatternLength = Math.max(...patterns.map((pattern) => stringWidth(pattern)))\n      const formattedPatterns = cliHelpers.justify(patterns, {\n        maxWidth: largestPatternLength,\n        paddingChar: this.#colors.dim('.'),\n      })\n\n      /**\n       * Formatting middleware to be right aligned\n       */\n      const middleware = table.rows.map((columns) => columns[3])\n      const largestMiddlewareLength = Math.max(...middleware.map((one) => stringWidth(one)))\n      const formattedMiddleware = cliHelpers.justify(middleware, {\n        maxWidth: largestMiddlewareLength,\n        align: 'right',\n        paddingChar: ' ',\n      })\n\n      /**\n       * Formatting controllers to be right aligned and take all the remaining\n       * space after printing route method, pattern and middleware.\n       */\n      const controllers = table.rows.map((columns) => columns[2])\n      const largestControllerLength =\n        (this.#options.maxPrettyPrintWidth || cliHelpers.TERMINAL_SIZE) -\n        (largestPatternLength + largestMethodsLength + largestMiddlewareLength)\n\n      const formattedControllers = cliHelpers.truncate(\n        cliHelpers.justify(controllers, {\n          maxWidth: largestControllerLength,\n          align: 'right',\n          paddingChar: this.#colors.dim('.'),\n        }),\n        {\n          maxWidth: largestControllerLength,\n        }\n      )\n\n      return {\n        heading: table.heading,\n        rows: formattedMethods.reduce<string[]>((result, method, index) => {\n          result.push(\n            `${method}${formattedPatterns[index]}${formattedControllers[index]}${formattedMiddleware[index]}`\n          )\n          return result\n        }, []),\n      }\n    })\n  }\n\n  /**\n   * Formats middleware info into a compact string representation.\n   * Named middleware with args becomes \"name:args\", closures use their name as-is.\n   */\n  #formatMiddlewareAsString(middleware: MiddlewareHandlerInfo): string | undefined {\n    if (middleware.type === 'named' && middleware.args) {\n      return `${middleware.name}:${middleware.args}`\n    }\n    return middleware.name\n  }\n\n  /**\n   * Formats routes as JSONL (one JSON object per line). Each line is a\n   * self-contained route object with flattened domain, simplified handler,\n   * and middleware as a string array. Optimized for machine consumption\n   * by AI agents and CLI tools.\n   */\n  async formatAsJSONL(): Promise<string[]> {\n    const routes = this.#router.toJSON()\n    const domains = Object.keys(routes)\n    const lines: string[] = []\n\n    for (let domain of domains) {\n      for (let route of routes[domain]) {\n        const serializedRoute = await this.#serializeRoute(route)\n        if (!this.#isAllowedByFilters(serializedRoute)) {\n          continue\n        }\n\n        const handler =\n          serializedRoute.handler.type === 'controller'\n            ? {\n                type: 'controller' as const,\n                module: serializedRoute.handler.moduleNameOrPath,\n                method: serializedRoute.handler.method,\n              }\n            : {\n                type:\n                  serializedRoute.handler.name === 'redirectsToRoute'\n                    ? ('redirect' as const)\n                    : ('closure' as const),\n                name: serializedRoute.handler.name,\n                ...(serializedRoute.handler.args ? { args: serializedRoute.handler.args } : {}),\n              }\n\n        const middleware = serializedRoute.middleware\n          .map((m) => this.#formatMiddlewareAsString(m))\n          .filter((m) => !!m)\n\n        for (let method of serializedRoute.methods) {\n          const entry: Record<string, unknown> = {\n            method,\n            pattern: serializedRoute.pattern,\n            handler,\n          }\n\n          if (serializedRoute.name) {\n            entry.name = serializedRoute.name\n          }\n\n          if (domain !== 'root') {\n            entry.domain = domain\n          }\n\n          if (middleware.length > 0) {\n            entry.middleware = middleware\n          }\n\n          lines.push(JSON.stringify(entry))\n        }\n      }\n    }\n\n    return lines\n  }\n\n  /**\n   * Formats routes as an array of objects. Routes are grouped by\n   * domain.\n   */\n  async formatAsJSON() {\n    const routes = this.#router.toJSON()\n    const domains = Object.keys(routes)\n    let routesJSON: { domain: string; routes: SerializedRoute[] }[] = []\n\n    for (let domain of domains) {\n      const domainRoutes = await Promise.all(\n        routes[domain].map((route) => this.#serializeRoute(route))\n      )\n\n      routesJSON.push({\n        domain,\n        routes: domainRoutes.filter((route) => this.#isAllowedByFilters(route)),\n      })\n    }\n\n    return routesJSON\n  }\n\n  /**\n   * Format routes to ansi list of tables. Each domain has its own table\n   * with heading and rows. Each row has colums with colors and spacing\n   * around them.\n   */\n  async formatAsAnsiList() {\n    const routes = this.#router.toJSON()\n    const domains = Object.keys(routes)\n    const tables: { heading: string; rows: [string, string, string, string][] }[] = []\n\n    for (let domain of domains) {\n      const list: (typeof tables)[number] = {\n        heading: this.#formatDomainHeadline(domain),\n        rows: [\n          [\n            this.#colors.dim('METHOD'),\n            ` ${this.#colors.dim('ROUTE')} `,\n            ` ${this.#colors.dim('HANDLER')}`,\n            ` ${this.#colors.dim('MIDDLEWARE')}`,\n          ],\n        ],\n      }\n\n      /**\n       * Computing table rows. Each route+method will have its\n       * own row\n       */\n      for (let route of routes[domain]) {\n        const serializedRoute = await this.#serializeRoute(route)\n        if (this.#isAllowedByFilters(serializedRoute)) {\n          serializedRoute.methods.forEach((method) => {\n            list.rows.push([\n              this.#formatRouteMethod(method),\n              ` ${this.#formatRoutePattern(serializedRoute)}`,\n              `${this.#formatControllerName(serializedRoute)}${this.#formatAction(\n                serializedRoute\n              )}`,\n              ` ${this.#formatMiddleware(serializedRoute, 'compact')}`,\n            ])\n          })\n        }\n      }\n\n      tables.push(list)\n    }\n\n    return this.#justifyListTables(tables)\n  }\n\n  /**\n   * Format routes to ansi tables. Each domain has its own table\n   * with heading and rows. Each row has colums with colors and spacing\n   * around them.\n   */\n  async formatAsAnsiTable() {\n    const routes = this.#router.toJSON()\n    const domains = Object.keys(routes)\n    const tables: { heading: string; table: ReturnType<UIPrimitives['table']> }[] = []\n\n    for (let domain of domains) {\n      const list: (typeof tables)[number] = {\n        heading: this.#formatDomainHeadline(domain),\n        table: this.#table()\n          .fullWidth()\n          .fluidColumnIndex(2)\n          .head([\n            this.#colors.dim('METHOD'),\n            this.#colors.dim('ROUTE'),\n            { hAlign: 'right', content: this.#colors.dim('HANDLER') },\n            { content: this.#colors.dim('MIDDLEWARE'), hAlign: 'right' },\n          ]),\n      }\n\n      /**\n       * Computing table rows. Each route+method will have its\n       * own row\n       */\n      for (let route of routes[domain]) {\n        const serializedRoute = await this.#serializeRoute(route)\n        if (this.#isAllowedByFilters(serializedRoute)) {\n          serializedRoute.methods.forEach((method) => {\n            list.table.row([\n              this.#formatRouteMethod(method),\n              this.#formatRoutePattern(serializedRoute),\n              {\n                content: `${this.#formatControllerName(serializedRoute)}${this.#formatAction(\n                  serializedRoute\n                )}`,\n                hAlign: 'right',\n              },\n              { content: this.#formatMiddleware(serializedRoute), hAlign: 'right' },\n            ])\n          })\n        }\n      }\n\n      tables.push(list)\n    }\n\n    return tables\n  }\n}\n"
  },
  {
    "path": "src/config_provider.ts",
    "content": "/*\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 ApplicationService, type ConfigProvider } from './types.ts'\n\n/**\n * Helper utilities to create and resolve config providers. Config providers\n * are used to defer configuration resolution until the application is booted,\n * allowing access to environment variables and other application services.\n *\n * @example\n * // Creating a database config provider\n * const databaseConfig = configProvider.create(async (app) => ({\n *   connection: app.env.get('DB_CONNECTION', 'sqlite'),\n *   host: app.env.get('DB_HOST', 'localhost'),\n *   port: app.env.get('DB_PORT', 5432)\n * }))\n *\n * @example\n * // Resolving a config provider\n * const config = await configProvider.resolve(app, databaseConfig)\n * if (config) {\n *   console.log(`Database connection: ${config.connection}`)\n * }\n */\nexport const configProvider = {\n  /**\n   * Creates a new config provider that will resolve configuration\n   * when the application is booted.\n   *\n   * @param resolver - Function that receives the application service and returns the configuration\n   *\n   * @example\n   * const mailConfig = configProvider.create(async (app) => ({\n   *   driver: app.env.get('MAIL_DRIVER', 'smtp'),\n   *   host: app.env.get('SMTP_HOST'),\n   *   port: app.env.get('SMTP_PORT', 587)\n   * }))\n   */\n  create<T>(resolver: ConfigProvider<T>['resolver']): ConfigProvider<T> {\n    return {\n      type: 'provider',\n      resolver,\n    }\n  },\n\n  /**\n   * Resolves a config provider if the provided value is a valid config provider,\n   * otherwise returns null.\n   *\n   * @param app - The application service instance\n   * @param provider - The potential config provider to resolve\n   *\n   * @example\n   * const resolved = await configProvider.resolve(app, someProvider)\n   * if (resolved) {\n   *   // Use the resolved configuration\n   *   console.log('Config resolved:', resolved)\n   * } else {\n   *   console.log('Not a valid config provider')\n   * }\n   */\n  async resolve<T>(app: ApplicationService, provider: unknown): Promise<T | null> {\n    if (provider && typeof provider === 'object' && 'type' in provider) {\n      return (provider as ConfigProvider<T>).resolver(app)\n    }\n\n    return null\n  },\n}\n"
  },
  {
    "path": "src/debug.ts",
    "content": "/*\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 { debuglog } from 'node:util'\n\n/**\n * Debug utility for AdonisJS core. This uses Node.js built-in debuglog\n * utility to provide debugging information when the NODE_DEBUG environment\n * variable includes 'adonisjs:core'.\n *\n * @example\n * // Enable debugging by setting environment variable\n * // NODE_DEBUG=adonisjs:core node app.js\n *\n * @example\n * // Usage in code\n * import debug from '@adonisjs/core/debug'\n * debug('Application started')\n * debug('Processing request: %s', req.url)\n */\nexport default debuglog('adonisjs:core')\n"
  },
  {
    "path": "src/exceptions.ts",
    "content": "/*\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\n/**\n * Core exception classes and utilities for AdonisJS. This module re-exports\n * commonly used exception classes from @poppinss/utils for creating and\n * handling errors in AdonisJS applications.\n *\n * @example\n * // Creating a custom exception\n * import { Exception } from '@adonisjs/core/exceptions'\n *\n * class ValidationException extends Exception {\n *   static status = 422\n *   static code = 'E_VALIDATION_FAILURE'\n * }\n *\n * @example\n * // Using createError to create custom error classes\n * import { createError } from '@adonisjs/core/exceptions'\n *\n * const UserNotFound = createError('User not found', 'E_USER_NOT_FOUND', 404)\n * throw new UserNotFound()\n */\nexport {\n  /**\n   * Base exception class for creating custom exceptions with status codes,\n   * error codes, and additional context.\n   */\n  Exception,\n\n  /**\n   * Utility function to create custom error classes with predefined\n   * message, code, and status.\n   */\n  createError,\n\n  /**\n   * Runtime exception class for errors that occur during application runtime.\n   */\n  RuntimeException,\n\n  /**\n   * Exception class for invalid argument errors, typically used in function\n   * parameter validation.\n   */\n  InvalidArgumentsException,\n} from '@poppinss/utils/exception'\n"
  },
  {
    "path": "src/helpers/assert.ts",
    "content": "/*\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\n/**\n * Assertion utilities for type-safe programming in AdonisJS. These functions\n * provide runtime type assertions that help with TypeScript type narrowing\n * and catching potential null/undefined issues early.\n *\n * @example\n * // Type-safe null checking\n * import { assertExists } from '@adonisjs/core/helpers'\n *\n * function processUser(user: User | null) {\n *   assertExists(user) // TypeScript now knows user is not null\n *   console.log(user.name) // Safe to access properties\n * }\n *\n * @example\n * // Exhaustiveness checking in switch statements\n * import { assertUnreachable } from '@adonisjs/core/helpers'\n *\n * function handleStatus(status: 'pending' | 'completed') {\n *   switch (status) {\n *     case 'pending': return 'Processing...'\n *     case 'completed': return 'Done!'\n *     default: return assertUnreachable(status)\n *   }\n * }\n */\nexport {\n  /**\n   * Assert that a value exists (is not null or undefined).\n   * Throws an error if the value is null or undefined.\n   */\n  assertExists,\n\n  /**\n   * Assert that a value is not null.\n   * Throws an error if the value is null.\n   */\n  assertNotNull,\n\n  /**\n   * Assert that a value is defined (is not undefined).\n   * Throws an error if the value is undefined.\n   */\n  assertIsDefined,\n\n  /**\n   * Assert that code should never reach this point.\n   * Useful for exhaustiveness checking in switch statements.\n   */\n  assertUnreachable,\n} from '@poppinss/utils/assert'\n"
  },
  {
    "path": "src/helpers/http.ts",
    "content": "/*\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\n/**\n * HTTP helper utilities re-exported from @adonisjs/http-server. This module\n * provides a convenient entry point for accessing all HTTP-related utilities\n * including route helpers, middleware utilities, and request/response helpers.\n *\n * @example\n * // Import specific HTTP helpers\n * import { middlewareInfo, routeInfo } from '@adonisjs/core/helpers'\n *\n * const middleware = middlewareInfo('cors', CorsMiddleware)\n * const route = routeInfo('users.show', '/users/:id')\n *\n * @example\n * // Access all HTTP helpers\n * import * as httpHelpers from '@adonisjs/core/helpers/http'\n *\n * // Use any helper from the http-server package\n * const routeData = httpHelpers.routeInfo('api.posts', '/api/posts')\n */\nexport * from '@adonisjs/http-server/helpers'\n"
  },
  {
    "path": "src/helpers/is.ts",
    "content": "/*\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 is from '@sindresorhus/is'\n\n/**\n * Type checking utilities re-exported from @sindresorhus/is. Provides\n * a comprehensive set of type-checking functions with TypeScript type guards.\n *\n * @example\n * // Basic type checking\n * import { is } from '@adonisjs/core/helpers'\n *\n * if (is.string(value)) {\n *   // TypeScript knows value is string\n *   console.log(value.toUpperCase())\n * }\n *\n * @example\n * // Complex type checking\n * import { is } from '@adonisjs/core/helpers'\n *\n * is.array(value) && is.nonEmptyArray(value)\n * is.plainObject(obj) && is.hasProperty(obj, 'name')\n * is.number(num) && is.integer(num) && is.positive(num)\n */\nexport default is\n"
  },
  {
    "path": "src/helpers/main.ts",
    "content": "/*\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\n/**\n * Core helper utilities for AdonisJS applications. This module provides\n * a collection of commonly used utilities including file system operations,\n * cryptographic functions, composition utilities, and HTTP server helpers.\n *\n * @example\n * // File system utilities\n * import { fsReadAll, fsImportAll } from '@adonisjs/core/helpers'\n *\n * const files = await fsReadAll(url('app/controllers'))\n * const modules = await fsImportAll(url('app/events'))\n *\n * @example\n * // Cryptographic utilities\n * import { base64, safeEqual, Secret } from '@adonisjs/core/helpers'\n *\n * const encoded = base64.encode('sensitive data')\n * const isEqual = safeEqual(hash1, hash2)\n * const secret = new Secret('my-secret-key')\n *\n * @example\n * // HTTP server helpers\n * import { middlewareInfo, routeInfo } from '@adonisjs/core/helpers'\n *\n * const middleware = middlewareInfo('cors', () => {})\n * const route = routeInfo('users.show', '/users/:id')\n */\n\n/**\n * File system utilities for reading and importing files recursively.\n */\nexport { fsReadAll, fsImportAll } from '@poppinss/utils/fs'\n\n/**\n * Base64 encoding and decoding utilities.\n */\nexport { default as base64 } from '@poppinss/utils/base64'\n\n/**\n * Core utilities including function composition, secret management,\n * safe equality comparison, and message building.\n */\nexport { compose, Secret, safeEqual, MessageBuilder, defineStaticProperty } from '@poppinss/utils'\n\n/**\n * Verification token utility for creating secure tokens.\n */\nexport { VerificationToken } from './verification_token.ts'\n"
  },
  {
    "path": "src/helpers/string.ts",
    "content": "/*\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 prettyHrTime from 'pretty-hrtime'\nimport string from '@poppinss/utils/string'\nimport he, { type EncodeOptions } from 'he'\nimport StringBuilder from '@poppinss/utils/string_builder'\n\n/**\n * Collection of string helpers to transform a string value. This object extends\n * the base string utilities from @poppinss/utils with additional AdonisJS-specific\n * string manipulation methods.\n *\n * @example\n * // Basic string transformations\n * stringHelpers.camelCase('hello_world') // 'helloWorld'\n * stringHelpers.snakeCase('HelloWorld')   // 'hello_world'\n * stringHelpers.pascalCase('hello world') // 'HelloWorld'\n *\n * @example\n * // HTML escaping and encoding\n * stringHelpers.escapeHTML('<script>alert(\"xss\")</script>')\n * stringHelpers.encodeSymbols('© 2023 AdonisJS')\n */\nconst stringHelpers: typeof string & {\n  /**\n   * Creates an instance of the StringBuilder for efficient string concatenation.\n   *\n   * @param value - Initial string value or existing StringBuilder instance\n   *\n   * @example\n   * const builder = stringHelpers.create('Hello')\n   * builder.append(' ').append('World')\n   * console.log(builder.toString()) // 'Hello World'\n   */\n  create(value: string | StringBuilder): StringBuilder\n\n  /**\n   * Convert a number to its ordinal form (1st, 2nd, 3rd, etc.).\n   * Alias for the `ordinal` method from @poppinss/utils.\n   *\n   * @example\n   * stringHelpers.ordinalize(1)  // '1st'\n   * stringHelpers.ordinalize(22) // '22nd'\n   */\n  ordinalize: (typeof string)['ordinal']\n\n  /**\n   * Convert a string to a readable sentence format.\n   * Alias for the `sentence` method from @poppinss/utils.\n   *\n   * @example\n   * stringHelpers.toSentence('hello_world') // 'Hello world'\n   * stringHelpers.toSentence('firstName')   // 'First name'\n   */\n  toSentence: (typeof string)['sentence']\n\n  /**\n   * Generate a cryptographically secure random string of specified length.\n   * Alias for the `random` method from @poppinss/utils.\n   *\n   * @example\n   * stringHelpers.generateRandom(16) // 'a1b2c3d4e5f6g7h8'\n   * stringHelpers.generateRandom(32) // Long random string\n   */\n  generateRandom: (typeof string)['random']\n\n  /**\n   * Convert high-resolution time difference to a human-readable format.\n   *\n   * @param time - High-resolution time tuple from process.hrtime()\n   * @param options - Formatting options\n   * @param options.verbose - Use verbose format (e.g., '1 second' vs '1s')\n   * @param options.precise - Show precise decimal places\n   *\n   * @example\n   * const start = process.hrtime()\n   * // ... some operation\n   * const diff = process.hrtime(start)\n   * stringHelpers.prettyHrTime(diff) // '2.5ms'\n   * stringHelpers.prettyHrTime(diff, { verbose: true }) // '2 milliseconds'\n   */\n  prettyHrTime(\n    time: [number, number],\n    options?: { verbose?: boolean | undefined; precise?: boolean | undefined }\n  ): string\n\n  /**\n   * Check if a string is empty or contains only whitespace characters.\n   *\n   * @param value - The string to check\n   *\n   * @example\n   * stringHelpers.isEmpty('')      // true\n   * stringHelpers.isEmpty('   ')   // true\n   * stringHelpers.isEmpty('hello') // false\n   */\n  isEmpty(value: string): boolean\n\n  /**\n   * Escape HTML entities to prevent XSS attacks and display HTML safely.\n   *\n   * @param value - The string to escape\n   * @param options - Escaping options\n   * @param options.encodeSymbols - Whether to encode symbols as HTML entities\n   *\n   * @example\n   * stringHelpers.escapeHTML('<script>alert(\"xss\")</script>')\n   * // '&lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;'\n   *\n   * @example\n   * stringHelpers.escapeHTML('© 2023', { encodeSymbols: true })\n   * // '&copy; 2023'\n   */\n  escapeHTML(value: string, options?: { encodeSymbols?: boolean }): string\n\n  /**\n   * Encode Unicode symbols and special characters as HTML entities.\n   *\n   * @param value - The string containing symbols to encode\n   * @param options - Encoding options from the 'he' library\n   *\n   * @example\n   * stringHelpers.encodeSymbols('© 2023 AdonisJS ™')\n   * // '&copy; 2023 AdonisJS &trade;'\n   *\n   * @example\n   * stringHelpers.encodeSymbols('Café', { decimal: true })\n   * // 'Caf&#233;'\n   */\n  encodeSymbols(value: string, options?: EncodeOptions): string\n} = {\n  ...string,\n  toSentence: string.sentence,\n  ordinalize: string.ordinal,\n  generateRandom: string.random,\n\n  create(value: string | StringBuilder): StringBuilder {\n    return new StringBuilder(value)\n  },\n\n  /**\n   * Formats Node.js hrtime output into a human-readable string.\n   *\n   * @param time - Tuple of [seconds, nanoseconds] from process.hrtime()\n   * @param options - Formatting options for output style and precision\n   */\n  prettyHrTime(time, options) {\n    return prettyHrTime(time, options)\n  },\n\n  /**\n   * Check if a string is empty or contains only whitespace characters.\n   *\n   * @param value - The string to check for emptiness\n   */\n  isEmpty(value: string): boolean {\n    return value.trim().length === 0\n  },\n\n  /**\n   * Escape HTML entities to prevent XSS attacks and display HTML safely.\n   *\n   * @param value - The string containing HTML to escape\n   * @param options - Optional configuration for escaping behavior\n   * @param options.encodeSymbols - Whether to also encode Unicode symbols as HTML entities\n   */\n  escapeHTML(value: string, options?: { encodeSymbols?: boolean }): string {\n    value = he.escape(value)\n    if (options && options.encodeSymbols) {\n      value = this.encodeSymbols(value, { allowUnsafeSymbols: true })\n    }\n    return value\n  },\n\n  /**\n   * Encode Unicode symbols and special characters as HTML entities.\n   *\n   * @param value - The string containing symbols to encode\n   * @param options - Encoding options from the 'he' library\n   */\n  encodeSymbols(value: string, options?: EncodeOptions): string {\n    return he.encode(value, options)\n  },\n}\n\nexport default stringHelpers\n"
  },
  {
    "path": "src/helpers/types.ts",
    "content": "/*\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 is from '@sindresorhus/is'\n\n/**\n * @deprecated\n * Use \"is\" helpers instead. The types helpers exist for backward compatibility.\n *\n * @example\n * // Instead of using types helpers (deprecated)\n * types.isString('hello')\n * types.isNumber(42)\n *\n * @example\n * // Use the new \"is\" helpers\n * import { is } from '@adonisjs/core/helpers'\n * is.string('hello')\n * is.number(42)\n */\nconst types = {\n  /**\n   * Direct reference to the is utility for type checking lookups.\n   * @deprecated Use the is helpers directly instead\n   */\n  lookup: is,\n\n  /**\n   * Check if value is null.\n   * @deprecated Use is.null instead\n   */\n  isNull: is.null,\n\n  /**\n   * Check if value is a boolean.\n   * @deprecated Use is.boolean instead\n   */\n  isBoolean: is.boolean,\n\n  /**\n   * Check if value is a Buffer.\n   * @deprecated Use is.buffer instead\n   */\n  isBuffer: is.buffer,\n\n  /**\n   * Check if value is a number.\n   * @deprecated Use is.number instead\n   */\n  isNumber: is.number,\n\n  /**\n   * Check if value is a string.\n   * @deprecated Use is.string instead\n   */\n  isString: is.string,\n\n  /**\n   * Check if value is an arguments object.\n   * @deprecated Use is.arguments instead\n   */\n  isArguments: is.arguments,\n\n  /**\n   * Check if value is an object.\n   * @deprecated Use is.object instead\n   */\n  isObject: is.object,\n\n  /**\n   * Check if value is a Date.\n   * @deprecated Use is.date instead\n   */\n  isDate: is.date,\n\n  /**\n   * Check if value is an array.\n   * @deprecated Use is.array instead\n   */\n  isArray: is.array,\n\n  /**\n   * Check if value is a regular expression.\n   * @deprecated Use is.regExp instead\n   */\n  isRegexp: is.regExp,\n\n  /**\n   * Check if value is an error object.\n   * @deprecated Use is.error instead\n   */\n  isError: is.error,\n\n  /**\n   * Check if value is a function.\n   * @deprecated Use is.function instead\n   */\n  isFunction: is.function,\n\n  /**\n   * Check if value is a class.\n   * @deprecated Use is.class instead\n   */\n  isClass: is.class,\n\n  /**\n   * Check if value is an integer.\n   * @deprecated Use is.integer instead\n   */\n  isInteger: is.integer,\n\n  /**\n   * Check if a number is a float (has decimal places).\n   *\n   * @param value - The number to check\n   * @deprecated Use is.decimal or custom logic instead\n   *\n   * @example\n   * types.isFloat(3.14) // true\n   * types.isFloat(42)   // false\n   */\n  isFloat(value: number): value is number {\n    return value !== (value | 0)\n  },\n\n  /**\n   * Check if a value represents a decimal number with specific decimal places.\n   *\n   * @param value - The value to check (string or number)\n   * @param options - Options for decimal validation\n   * @param options.decimalPlaces - Regex pattern for allowed decimal places (default: '1,')\n   * @deprecated Use a validation library like Vine or custom logic instead\n   *\n   * @example\n   * types.isDecimal('3.14')     // true\n   * types.isDecimal('42.0')     // true\n   * types.isDecimal('42')       // false\n   * types.isDecimal('3.141', { decimalPlaces: '1,3' }) // true\n   */\n  isDecimal(value: string | number, options?: { decimalPlaces?: string }): boolean {\n    if (typeof value === 'number') {\n      value = value.toString()\n    }\n\n    const decimalPlaces = (options && options.decimalPlaces) || '1,'\n    return new RegExp(`^[-+]?([0-9]+)?(\\\\.[0-9]{${decimalPlaces}})$`).test(value)\n  },\n}\n\nexport default types\n"
  },
  {
    "path": "src/helpers/verification_token.ts",
    "content": "/*\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 { createHash } from 'node:crypto'\nimport string from '@poppinss/utils/string'\nimport { safeEqual, Secret } from '@poppinss/utils'\nimport base64 from '@poppinss/utils/base64'\n\n/**\n * Verification token class can be used to create tokens publicly\n * shareable tokens while storing the token hash within the database.\n *\n * This class is used by the Auth and the Persona packages to manage\n * tokens for authentication and authorization purposes.\n *\n * @example\n * class UserToken extends VerificationToken {\n *   constructor(user: User, secret: Secret<string>) {\n *     super()\n *     this.tokenableId = user.id\n *     this.computeValue(secret)\n *   }\n * }\n */\nexport abstract class VerificationToken {\n  /**\n   * Decodes a publicly shared token and return the series\n   * and the token value from it.\n   *\n   * Returns null when unable to decode the token because of\n   * invalid format or encoding.\n   *\n   * @param value - The token string to decode\n   */\n  static decode(value: string): null | { identifier: string; secret: Secret<string> } {\n    /**\n     * Ensure value is a string and starts with the prefix.\n     */\n    if (typeof value !== 'string') {\n      return null\n    }\n\n    /**\n     * Remove prefix from the rest of the token.\n     */\n    if (!value) {\n      return null\n    }\n\n    const [identifier, ...tokenValue] = value.split('.')\n    if (!identifier || tokenValue.length === 0) {\n      return null\n    }\n\n    const decodedIdentifier = base64.urlDecode(identifier)\n    const decodedSecret = base64.urlDecode(tokenValue.join('.'))\n    if (!decodedIdentifier || !decodedSecret) {\n      return null\n    }\n\n    return {\n      identifier: decodedIdentifier,\n      secret: new Secret(decodedSecret),\n    }\n  }\n\n  /**\n   * Creates a transient token that can be shared with the persistence\n   * layer.\n   *\n   * @param userId - The user ID for whom the token is being created\n   * @param size - The size of the random token seed\n   * @param expiresIn - Token expiration time (string like '2h' or number in seconds)\n   */\n  static createTransientToken(\n    userId: string | number | BigInt,\n    size: number,\n    expiresIn: string | number\n  ) {\n    const expiresAt = new Date()\n    expiresAt.setSeconds(expiresAt.getSeconds() + string.seconds.parse(expiresIn))\n\n    return {\n      userId,\n      expiresAt,\n      ...this.seed(size),\n    }\n  }\n\n  /**\n   * Creates a secret opaque token and its hash.\n   *\n   * @param size - The length of the random token to generate\n   */\n  static seed(size: number) {\n    const seed = string.random(size)\n    const secret = new Secret(seed)\n    const hash = createHash('sha256').update(secret.release()).digest('hex')\n    return { secret, hash }\n  }\n\n  /**\n   * Identifer is a unique sequence to identify the\n   * token within database. It should be the\n   * primary/unique key\n   */\n  declare identifier: string | number | BigInt\n\n  /**\n   * Reference to the user id for whom the token\n   * is generated.\n   */\n  declare tokenableId: string | number | BigInt\n\n  /**\n   * Hash is computed from the seed to later verify the validity\n   * of seed\n   */\n  declare hash: string\n\n  /**\n   * Timestamp at which the token will expire\n   */\n  declare expiresAt: Date\n\n  /**\n   * The value is a public representation of a token. It is created\n   * by combining the \"identifier\".\"secret\" via the \"computeValue\"\n   * method\n   */\n  declare value?: Secret<string>\n\n  /**\n   * Compute the value property using the given secret. You can\n   * get secret via the static \"createTransientToken\" method.\n   *\n   * @param secret - The secret value to compute the public token value from\n   */\n  protected computeValue(secret: Secret<string>) {\n    this.value = new Secret(\n      `${base64.urlEncode(String(this.identifier))}.${base64.urlEncode(secret.release())}`\n    )\n  }\n\n  /**\n   * Check if the token has been expired. Verifies\n   * the \"expiresAt\" timestamp with the current\n   * date.\n   */\n  isExpired() {\n    return this.expiresAt < new Date()\n  }\n\n  /**\n   * Verifies the value of a token against the pre-defined hash\n   *\n   * @param secret - The secret to verify against the stored hash\n   */\n  verify(secret: Secret<string>): boolean {\n    const newHash = createHash('sha256').update(secret.release()).digest('hex')\n    return safeEqual(this.hash, newHash)\n  }\n}\n"
  },
  {
    "path": "src/ignitor/ace.ts",
    "content": "/*\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 Ignitor } from './main.ts'\nimport type { ApplicationService } from '../types.ts'\n\n/**\n * The Ace process is used to start the application in the\n * console environment. It manages the Ace kernel lifecycle\n * and command execution.\n *\n * @example\n * const ignitor = new Ignitor()\n * const aceProcess = new AceProcess(ignitor)\n *\n * await aceProcess\n *   .configure((app) => {\n *     // Configure ace kernel\n *   })\n *   .handle(['make:controller', 'UserController'])\n */\nexport class AceProcess {\n  /**\n   * Ignitor reference\n   */\n  #ignitor: Ignitor\n\n  /**\n   * The callback that configures the ace instance before the\n   * handle method is called\n   */\n  #configureCallback: (app: ApplicationService) => Promise<void> | void = () => {}\n\n  /**\n   * Creates a new Ace process instance\n   *\n   * @param ignitor - The ignitor instance used to create and manage the app\n   */\n  constructor(ignitor: Ignitor) {\n    this.#ignitor = ignitor\n  }\n\n  /**\n   * Register a callback that can be used to configure the ace\n   * kernel before the handle method is called\n   *\n   * @param callback - Configuration callback function\n   */\n  configure(callback: (app: ApplicationService) => Promise<void> | void): this {\n    this.#configureCallback = callback\n    return this\n  }\n\n  /**\n   * Handles the command line arguments and executes\n   * the matching ace commands\n   *\n   * @param argv - Command line arguments array\n   */\n  async handle(argv: string[]) {\n    const app = this.#ignitor.createApp('console')\n    await app.init()\n\n    const { createAceKernel } = await import('../../modules/ace/create_kernel.js')\n    const commandNameIndex = argv.findIndex((value) => !value.startsWith('-'))\n    const commandName = argv[commandNameIndex]\n\n    const kernel = createAceKernel(app, commandName)\n    app.container.bindValue('ace', kernel)\n\n    /**\n     * Hook into kernel and start the app when the\n     * command needs the app.\n     *\n     * Since multiple commands can be executed in a single process,\n     * we add a check to only start the app only once.\n     */\n    kernel.loading(async (metaData) => {\n      if (metaData.options.startApp && !app.isReady) {\n        if (metaData.commandName === 'repl') {\n          app.setEnvironment('repl')\n        }\n        await app.boot()\n        await app.start(() => {})\n      }\n    })\n\n    await this.#configureCallback(app)\n\n    /**\n     * Register terminating callback BEFORE handling the command.\n     * This ensures the callback is registered even if a staysAlive\n     * command calls app.terminate() during its execution.\n     */\n    app.terminating(() => {\n      const mainCommand = kernel.getMainCommand()\n      if (mainCommand?.staysAlive) {\n        process.exitCode = mainCommand.exitCode\n      }\n    })\n\n    /**\n     * Handle command line args\n     */\n    await kernel.handle(argv)\n\n    /**\n     * Terminate the app when the command does not want to\n     * hold a long running process\n     */\n    const mainCommand = kernel.getMainCommand()\n    if (!mainCommand || !mainCommand.staysAlive) {\n      process.exitCode = kernel.exitCode\n      await app.terminate()\n    }\n  }\n}\n"
  },
  {
    "path": "src/ignitor/http.ts",
    "content": "/*\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 { Server as NodeHttpsServer } from 'node:https'\nimport {\n  type IncomingMessage,\n  type ServerResponse,\n  type Server as NodeHttpServer,\n  createServer,\n} from 'node:http'\n\nimport debug from '../debug.ts'\nimport { type Ignitor } from './main.ts'\nimport type { ApplicationService, EmitterService, LoggerService } from '../types.ts'\n\n/**\n * The HTTP server process is used to start the application in the\n * web environment. It creates and manages the Node.js HTTP server\n * instance, handling lifecycle events and monitoring.\n *\n * @example\n * const ignitor = new Ignitor()\n * const httpProcess = new HttpServerProcess(ignitor)\n * await httpProcess.start()\n */\nexport class HttpServerProcess {\n  /**\n   * Ignitor reference\n   */\n  #ignitor: Ignitor\n\n  /**\n   * Creates a new HTTP server process instance\n   *\n   * @param ignitor - The ignitor instance used to create and manage the app\n   */\n  constructor(ignitor: Ignitor) {\n    this.#ignitor = ignitor\n  }\n\n  /**\n   * Calling this method closes the underlying HTTP server gracefully.\n   *\n   * @param nodeHttpServer - The Node.js HTTP or HTTPS server instance to close\n   */\n  #close(nodeHttpServer: NodeHttpsServer | NodeHttpServer): Promise<void> {\n    return new Promise((resolve) => {\n      debug('closing http server process')\n      nodeHttpServer.close(() => resolve())\n    })\n  }\n\n  /**\n   * Monitors the app and the server to close the HTTP server when\n   * either one of them goes down. Sets up event listeners for graceful shutdown.\n   *\n   * @param nodeHttpServer - The Node.js HTTP or HTTPS server instance to monitor\n   * @param app - The application service instance\n   * @param logger - The logger service for error reporting\n   */\n  #monitorAppAndServer(\n    nodeHttpServer: NodeHttpsServer | NodeHttpServer,\n    app: ApplicationService,\n    logger: LoggerService\n  ) {\n    /**\n     * Close the HTTP server when the application begins to\n     * terminate\n     */\n    app.terminating(async () => {\n      debug('terminating signal received')\n      await this.#close(nodeHttpServer)\n    })\n\n    /**\n     * Terminate the app when the HTTP server crashes\n     */\n    nodeHttpServer.once('error', (error: NodeJS.ErrnoException) => {\n      debug('http server crashed with error \"%O\"', error)\n      logger.fatal({ err: error }, error.message)\n      process.exitCode = 1\n      app.terminate()\n    })\n  }\n\n  /**\n   * Starts the HTTP server on a given host and port using environment variables.\n   *\n   * @param nodeHttpServer - The Node.js HTTP or HTTPS server instance to start listening\n   */\n  #listen(\n    nodeHttpServer: NodeHttpsServer | NodeHttpServer\n  ): Promise<{ port: number; host: string }> {\n    return new Promise((resolve, reject) => {\n      const host = process.env.HOST || '0.0.0.0'\n      const port = Number(process.env.PORT || '3333')\n\n      nodeHttpServer.listen(port, host)\n      nodeHttpServer.once('listening', () => {\n        debug('listening to http server, host :%s, port: %s', host, port)\n        resolve({ port, host })\n      })\n\n      nodeHttpServer.once('error', (error: NodeJS.ErrnoException) => {\n        reject(error)\n      })\n    })\n  }\n\n  /**\n   * Notifies the app and the parent process that the HTTP server is ready.\n   * Sends notifications through multiple channels: parent process, logger, and event emitter.\n   *\n   * @param app - The application service instance for parent process notification\n   * @param logger - The logger service for console output\n   * @param emitter - The event emitter for app-level notifications\n   * @param payload - Server startup information including host, port, and duration\n   */\n  #notifyServerHasStarted(\n    app: ApplicationService,\n    logger: LoggerService,\n    emitter: EmitterService,\n    payload: { host: string; port: number; duration: [number, number] }\n  ) {\n    /**\n     * Notify parent process\n     */\n    app.notify({ isAdonisJS: true, environment: 'web', ...payload })\n\n    /**\n     * Visual notification\n     */\n    logger.info('started HTTP server on %s:%s', payload.host, payload.port)\n\n    /**\n     * Notify app\n     */\n    emitter.emit('http:server_ready', payload)\n  }\n\n  /**\n   * Start the HTTP server by wiring up the application\n   *\n   * @param serverCallback - Optional callback to create custom HTTP server instance\n   */\n  async start(\n    serverCallback?: (\n      handler: (req: IncomingMessage, res: ServerResponse) => any\n    ) => NodeHttpsServer | NodeHttpServer\n  ) {\n    const startTime = process.hrtime()\n\n    /**\n     * Method to create the HTTP server\n     */\n    const createHTTPServer = serverCallback || createServer\n    const app = this.#ignitor.createApp('web')\n\n    await app.init()\n    await app.boot()\n    await app.start(async () => {\n      /**\n       * Resolve and boot the AdonisJS HTTP server\n       */\n      const server = await app.container.make('server')\n      await server.boot()\n\n      /**\n       * Create Node.js HTTP server instance and share it with the\n       * AdonisJS HTTP server\n       */\n      const httpServer = createHTTPServer(server.handle.bind(server))\n      server.setNodeServer(httpServer)\n\n      const logger = await app.container.make('logger')\n      const emitter = await app.container.make('emitter')\n\n      /**\n       * Start the server by listening on a port of host\n       */\n      const payload = await this.#listen(httpServer)\n\n      /**\n       * Notify\n       */\n      this.#notifyServerHasStarted(app, logger, emitter, {\n        ...payload,\n        duration: process.hrtime(startTime),\n      })\n\n      /**\n       * Monitor app and the server (after the server is listening)\n       */\n      this.#monitorAppAndServer(httpServer, app, logger)\n    })\n  }\n}\n"
  },
  {
    "path": "src/ignitor/main.ts",
    "content": "/*\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 debug from '../debug.ts'\nimport { AceProcess } from './ace.ts'\nimport { TestRunnerProcess } from './test.ts'\nimport { HttpServerProcess } from './http.ts'\nimport { setApp } from '../../services/app.ts'\nimport { Application } from '../../modules/app.ts'\nimport type { AppEnvironments } from '../../types/app.ts'\nimport type { ApplicationService, IgnitorOptions } from '../types.ts'\n\n/**\n * Ignitor is used to instantiate an AdonisJS application in different\n * known environments. It serves as the main entry point for creating\n * and managing application processes.\n *\n * @example\n * const ignitor = new Ignitor(new URL(import.meta.url))\n *\n * // For HTTP server\n * await ignitor.httpServer().start()\n *\n * // For CLI commands\n * await ignitor.ace().handle(process.argv.slice(2))\n *\n * // For tests\n * await ignitor.testRunner().run(() => {})\n */\nexport class Ignitor {\n  /**\n   * Ignitor options\n   */\n  #options: IgnitorOptions\n\n  /**\n   * Application root URL\n   */\n  #appRoot: URL\n\n  /**\n   * Reference to the application instance created using\n   * the \"createApp\" method.\n   *\n   * We store the output of the last call made to \"createApp\" method\n   * and assume that in one process only one entrypoint will\n   * call this method.\n   */\n  #app?: ApplicationService\n\n  /**\n   * Reference to the created application\n   */\n  #tapCallbacks: Set<(app: ApplicationService) => void> = new Set()\n\n  /**\n   * Creates a new Ignitor instance\n   *\n   * @param appRoot - The root URL of the application\n   * @param options - Configuration options for the ignitor\n   */\n  constructor(appRoot: URL, options: IgnitorOptions = {}) {\n    this.#appRoot = appRoot\n    this.#options = options\n  }\n\n  /**\n   * Runs all the tap callbacks\n   */\n  #runTapCallbacks(app: ApplicationService) {\n    this.#tapCallbacks.forEach((tapCallback) => tapCallback(app))\n  }\n\n  /**\n   * Get access to the application instance created\n   * by either the http server process or the ace\n   * process\n   */\n  getApp() {\n    return this.#app\n  }\n\n  /**\n   * Create an instance of AdonisJS application\n   *\n   * @param environment - The environment in which to create the app (web, console, test, repl)\n   */\n  createApp(environment: AppEnvironments) {\n    debug('creating application instance')\n    this.#app = new Application(this.#appRoot, { environment, importer: this.#options.importer })\n\n    setApp(this.#app)\n    this.#runTapCallbacks(this.#app)\n    return this.#app\n  }\n\n  /**\n   * Tap to access the application class instance.\n   *\n   * @param callback - Callback function to execute when app is created\n   */\n  tap(callback: (app: ApplicationService) => void): this {\n    this.#tapCallbacks.add(callback)\n    return this\n  }\n\n  /**\n   * Get instance of the HTTPServerProcess\n   */\n  httpServer() {\n    return new HttpServerProcess(this)\n  }\n\n  /**\n   * Get an instance of the AceProcess class\n   */\n  ace() {\n    return new AceProcess(this)\n  }\n\n  /**\n   * Get an instance of the TestRunnerProcess class\n   */\n  testRunner() {\n    return new TestRunnerProcess(this)\n  }\n\n  /**\n   * Terminates the app by calling the \"app.terminate\"\n   * method\n   */\n  async terminate() {\n    await this.#app?.terminate()\n  }\n}\n"
  },
  {
    "path": "src/ignitor/test.ts",
    "content": "/*\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 Ignitor } from './main.ts'\nimport type { ApplicationService } from '../types.ts'\n\n/**\n * The Test runner process is used to start the tests runner process.\n * It provides lifecycle hooks for configuring the test environment\n * and running tests within the AdonisJS application context.\n *\n * @example\n * const ignitor = new Ignitor()\n * const testProcess = new TestRunnerProcess(ignitor)\n *\n * await testProcess\n *   .configure((app) => {\n *     // Configure test environment\n *   })\n *   .run(async (app) => {\n *     // Run your tests\n *   })\n */\nexport class TestRunnerProcess {\n  /**\n   * Ignitor reference\n   */\n  #ignitor: Ignitor\n\n  /**\n   * The callback that configures the tests runner. This callback\n   * runs at the time of starting the app.\n   */\n  #configureCallback: (app: ApplicationService) => Promise<void> | void = () => {}\n\n  /**\n   * Creates a new test runner process instance\n   *\n   * @param ignitor - The ignitor instance used to create and manage the app\n   */\n  constructor(ignitor: Ignitor) {\n    this.#ignitor = ignitor\n  }\n\n  /**\n   * Register a callback that runs after booting the AdonisJS app\n   * and just before the provider's ready hook\n   *\n   * @param callback - Configuration callback function\n   */\n  configure(callback: (app: ApplicationService) => Promise<void> | void): this {\n    this.#configureCallback = callback\n    return this\n  }\n\n  /**\n   * Runs a callback after starting the app\n   *\n   * @param callback - Test execution callback function\n   */\n  async run(callback: (app: ApplicationService) => Promise<void> | void) {\n    const app = this.#ignitor.createApp('test')\n    await app.init()\n    await app.boot()\n    await app.start(this.#configureCallback)\n    await callback(app)\n  }\n}\n"
  },
  {
    "path": "src/test_utils/http.ts",
    "content": "/*\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 debug from '../debug.ts'\nimport type { TestUtils } from './main.ts'\nimport type { Server as NodeHttpsServer } from 'node:https'\nimport {\n  type IncomingMessage,\n  type ServerResponse,\n  type Server as NodeHttpServer,\n  createServer,\n} from 'node:http'\n\n/**\n * Http server utils are used to start the AdonisJS HTTP server\n * during testing. It provides methods to start and stop the server\n * for integration testing.\n *\n * @example\n * const testUtils = new TestUtils(app)\n * const httpUtils = testUtils.httpServer()\n *\n * const closeServer = await httpUtils.start()\n * // Make HTTP requests to test endpoints\n * await closeServer() // Clean up\n */\nexport class HttpServerUtils {\n  /**\n   * Reference to the test utils instance\n   */\n  #utils: TestUtils\n\n  /**\n   * Creates a new HttpServerUtils instance\n   *\n   * @param utils - The test utils instance\n   */\n  constructor(utils: TestUtils) {\n    this.#utils = utils\n  }\n\n  /**\n   * Starts the http server a given host and port\n   *\n   * @param nodeHttpServer - The Node.js HTTP server instance\n   */\n  #listen(\n    nodeHttpServer: NodeHttpsServer | NodeHttpServer\n  ): Promise<{ port: number; host: string }> {\n    return new Promise((resolve, reject) => {\n      const host = process.env.HOST || '0.0.0.0'\n      const port = Number(process.env.PORT || '3333')\n\n      nodeHttpServer.listen(port, host)\n      nodeHttpServer.once('listening', () => {\n        debug('listening to utils http server, host :%s, port: %s', host, port)\n        resolve({ port, host })\n      })\n\n      nodeHttpServer.once('error', (error: NodeJS.ErrnoException) => {\n        reject(error)\n      })\n    })\n  }\n\n  /**\n   * Testing hook to start the HTTP server to listen for new request.\n   * The return value is a function to close the HTTP server.\n   *\n   * @param serverCallback - Optional callback to create custom HTTP server instance\n   */\n  async start(\n    serverCallback?: (\n      handler: (req: IncomingMessage, res: ServerResponse) => any\n    ) => NodeHttpsServer | NodeHttpServer\n  ): Promise<() => Promise<void>> {\n    const createHTTPServer = serverCallback || createServer\n\n    const server = await this.#utils.app.container.make('server')\n    await server.boot()\n\n    const httpServer = createHTTPServer(server.handle.bind(server))\n    server.setNodeServer(httpServer)\n\n    await this.#listen(httpServer)\n\n    return () => {\n      return new Promise<void>((resolve, reject) => {\n        httpServer.close((error) => {\n          if (error) {\n            reject(error)\n          } else {\n            resolve()\n          }\n        })\n      })\n    }\n  }\n}\n"
  },
  {
    "path": "src/test_utils/main.ts",
    "content": "/*\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 { Socket } from 'node:net'\nimport Macroable from '@poppinss/macroable'\nimport { IncomingMessage, ServerResponse } from 'node:http'\n\nimport { HttpServerUtils } from './http.ts'\nimport type { ApplicationService } from '../types.ts'\nimport { Encryption } from '../../modules/encryption/main.ts'\nimport { CookieClient, type HttpContext } from '../../modules/http/main.ts'\n\n/**\n * Test utils has a collection of helper methods to make testing\n * experience great for AdonisJS applications. It provides utilities\n * for HTTP testing, context creation, and cookie handling.\n *\n * @example\n * const testUtils = new TestUtils(app)\n * await testUtils.boot()\n *\n * const ctx = await testUtils.createHttpContext()\n * const httpUtils = testUtils.httpServer()\n */\nexport class TestUtils extends Macroable {\n  /**\n   * Flag to track if test utils have been booted\n   */\n  #booted: boolean = false\n\n  /**\n   * Check if utils have been booted\n   */\n  get isBooted() {\n    return this.#booted\n  }\n\n  /**\n   * Cookie client instance for handling cookies in tests\n   */\n  declare cookies: CookieClient\n\n  /**\n   * Creates a new TestUtils instance\n   *\n   * @param app - The application service instance\n   */\n  constructor(public app: ApplicationService) {\n    super()\n  }\n\n  /**\n   * Boot test utils. It requires the app to be booted\n   * and container to have all the bindings\n   */\n  async boot() {\n    if (!this.isBooted) {\n      this.#booted = true\n      this.cookies = new CookieClient(await this.app.container.make(Encryption))\n    }\n  }\n\n  /**\n   * Returns an instance of the HTTP server testing\n   * utils\n   */\n  httpServer() {\n    return new HttpServerUtils(this)\n  }\n\n  /**\n   * Create an instance of HTTP context for testing\n   *\n   * @param options - Options for creating HTTP context with custom req/res objects\n   */\n  async createHttpContext(\n    options: { req?: IncomingMessage; res?: ServerResponse } = {}\n  ): Promise<HttpContext> {\n    const req = options.req || new IncomingMessage(new Socket())\n    const res = options.res || new ServerResponse(req)\n    const server = await this.app.container.make('server')\n\n    const request = server.createRequest(req, res)\n    const response = server.createResponse(req, res)\n    return server.createHttpContext(request, response, this.app.container.createResolver())\n  }\n}\n"
  },
  {
    "path": "src/types.ts",
    "content": "/*\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 { Repl } from '../modules/repl.ts'\nimport type { Importer } from '../types/app.ts'\nimport type { Emitter } from '../modules/events.ts'\nimport type { Kernel } from '../modules/ace/main.ts'\nimport type { Application } from '../modules/app.ts'\nimport type { TestUtils } from './test_utils/main.ts'\nimport type {\n  HttpServerEvents,\n  LookupList,\n  RoutesList,\n  SignedURLOptions,\n  UrlFor,\n  URLOptions,\n} from '../types/http.ts'\nimport type { Dumper } from '../modules/dumper/dumper.ts'\nimport type { LoggerManager } from '../modules/logger.ts'\nimport type { HashManager } from '../modules/hash/main.ts'\nimport type { ManagerDriverFactory } from '../types/hash.ts'\nimport type { Router, Server } from '../modules/http/main.ts'\nimport { type EncryptionConfig } from '../types/encryption.ts'\nimport type { EncryptionManager } from '../modules/encryption/main.ts'\nimport type { ContainerResolveEventData } from '../types/container.ts'\nimport type { LoggerConfig, LoggerManagerConfig } from '../types/logger.ts'\n\n/**\n * A config provider waits for the application to get booted\n * and then resolves the config. It receives an instance\n * of the application service.\n *\n * @template T - The type of configuration object that the provider resolves\n *\n * @example\n * const databaseProvider: ConfigProvider<DatabaseConfig> = {\n *   type: 'provider',\n *   resolver: async (app) => {\n *     return {\n *       connection: app.env.get('DB_CONNECTION', 'sqlite'),\n *       host: app.env.get('DB_HOST', 'localhost')\n *     }\n *   }\n * }\n */\nexport type ConfigProvider<T> = {\n  /** Identifies this as a config provider */\n  type: 'provider'\n  /** Function that resolves the configuration using the application service */\n  resolver: (app: ApplicationService) => Promise<T>\n}\n\n/**\n * Options accepted by ignitor for configuring the application bootstrap process.\n *\n * @example\n * const options: IgnitorOptions = {\n *   importer: (filePath) => import(filePath)\n * }\n */\nexport type IgnitorOptions = {\n  /** Optional custom importer function for loading modules */\n  importer?: Importer\n}\n\n/**\n * A list of known events. The interface must be extended in\n * user land code or packages to register events and their\n * types.\n *\n * @example\n * // Extending EventsList in user code\n * declare module '@adonisjs/core' {\n *   interface EventsList {\n *     'user:created': { user: User }\n *     'order:placed': { orderId: string, amount: number }\n *   }\n * }\n */\nexport interface EventsList extends HttpServerEvents {\n  /** Event fired when a container binding is resolved */\n  'container_binding:resolved': ContainerResolveEventData<ContainerBindings>\n  /** Event fired when the HTTP server is ready and listening */\n  'http:server_ready': { port: number; host: string; duration: [number, number] }\n}\n\n/**\n * The loggers list inferred from the user application\n * config. This interface should be extended in user code\n * to register custom loggers.\n *\n * @example\n * // Extending LoggersList in user code\n * declare module '@adonisjs/core' {\n *   interface LoggersList {\n *     default: LoggerConfig\n *     file: LoggerConfig\n *   }\n * }\n */\nexport interface LoggersList {}\n\n/**\n * Utility type to infer logger configurations from a LoggerManagerConfig.\n *\n * @template T - The logger manager configuration type\n */\nexport type InferLoggers<T extends LoggerManagerConfig<any>> = T['loggers']\n\n/**\n * A list of known hashers inferred from the user config.\n * This interface should be extended in user code to register\n * custom hashers.\n *\n * @example\n * // Extending HashersList in user code\n * declare module '@adonisjs/core' {\n *   interface HashersList {\n *     scrypt: ManagerDriverFactory\n *     argon: ManagerDriverFactory\n *   }\n * }\n */\nexport interface HashersList {}\n\n/**\n * Utility type to infer hasher configurations from a config provider.\n *\n * @template T - The config provider type that resolves to an object with a 'list' property\n */\nexport type InferHashers<T extends ConfigProvider<{ list: Record<string, ManagerDriverFactory> }>> =\n  Awaited<ReturnType<T['resolver']>>['list']\n\n/**\n * A list of known encryptors inferred from the user config.\n * This interface should be extended in user code to register\n * custom encryptors.\n *\n * @example\n * // Extending EncryptorsList in user code\n * declare module '@adonisjs/core' {\n *   interface EncryptorsList {\n *     default: EncryptionConfig\n *     secondary: EncryptionConfig\n *   }\n * }\n */\nexport interface EncryptorsList {}\n\n/**\n * Utility type to infer encryptors configurations from a config provider.\n *\n * @template T - The config provider type that resolves to an object with a 'list' property\n */\nexport type InferEncryptors<\n  T extends ConfigProvider<{\n    list: Record<string, EncryptionConfig>\n  }>,\n> = Awaited<ReturnType<T['resolver']>>['list']\n\n/**\n * ----------------------------------------------------------------\n * Container services\n * -----------------------------------------------------------------\n *\n * Types for the container singleton services. Defining them\n * upfront so that we do not have to define them in\n * multiple places.\n */\n\n/**\n * Application service is a singleton resolved from\n * the container. It provides access to the core application\n * instance with all registered bindings.\n */\nexport interface ApplicationService extends Application<\n  ContainerBindings extends Record<any, any> ? ContainerBindings : never\n> {}\n\n/**\n * Logger service is a singleton logger instance registered\n * to the container. It provides access to configured loggers.\n */\nexport interface LoggerService extends LoggerManager<\n  LoggersList extends Record<string, LoggerConfig> ? LoggersList : never\n> {}\n\n/**\n * Emitter service is a singleton emitter instance registered\n * to the container. It provides type-safe event emission and listening.\n */\nexport interface EmitterService extends Emitter<EventsList> {}\n\n/**\n * Encryption service is a singleton instance of the EncryptionManager\n * registered in the container. It provides encryption and decryption\n * functionality with support for multiple encryptors.\n */\nexport interface EncryptionService extends EncryptionManager<\n  EncryptorsList extends Record<string, EncryptionConfig> ? EncryptorsList : never\n> {}\n\n/**\n * Http server service added to the container as a singleton.\n * It provides access to the HTTP server instance for handling\n * requests and responses.\n */\nexport interface HttpServerService extends Server {}\n\n/**\n * Http router service added to the container as a singleton.\n * It provides access to the application's router for defining\n * and managing routes.\n */\nexport interface HttpRouterService extends Router {}\n\n/**\n * Url builder service offers a type-safe API for creating URLs\n * for pre-registered routes. It ensures type safety when building\n * URLs with parameters.\n */\nexport interface UrlBuilderUrlFor extends UrlFor<\n  RoutesList extends LookupList ? RoutesList : never,\n  URLOptions\n> {}\n\n/**\n * Url builder service offers a type-safe API for creating signed URLs\n * for pre-registered routes. Signed URLs include a signature that prevents\n * tampering and can have expiration times.\n */\nexport interface UrlBuilderSignedUrlFor extends UrlFor<\n  RoutesList extends LookupList ? RoutesList : never,\n  SignedURLOptions\n> {}\n\n/**\n * Hash service is a singleton instance of the HashManager\n * registered in the container. It provides password hashing\n * and verification functionality.\n */\nexport interface HashService extends HashManager<\n  HashersList extends Record<string, ManagerDriverFactory> ? HashersList : never\n> {}\n\n/**\n * A list of known container bindings. This interface defines\n * all the services that are registered in the IoC container\n * and available for dependency injection.\n */\nexport interface ContainerBindings {\n  /** Ace command-line kernel */\n  ace: Kernel\n  /** Database query dumper */\n  dumper: Dumper\n  /** Main application instance */\n  app: ApplicationService\n  /** Logger manager instance */\n  logger: LoggerService\n  /** Application configuration */\n  config: ApplicationService['config']\n  /** Event emitter instance */\n  emitter: EmitterService\n  /** Encryption service */\n  encryption: EncryptionService\n  /** Hash manager for password hashing */\n  hash: HashService\n  /** HTTP server instance */\n  server: HttpServerService\n  /** HTTP router instance */\n  router: HttpRouterService\n  /** Test utilities */\n  testUtils: TestUtils\n  /** REPL instance */\n  repl: Repl\n}\n\n/**\n * Configuration options for the IndexEntities assembler hook.\n * This type defines the settings for automatically generating\n * barrel files for controllers, listeners, and events.\n *\n * @example\n * // Basic configuration\n * const config: IndexEntitiesConfig = {\n *   controllers: { enabled: true },\n *   events: { source: 'app/custom-events' }\n * }\n *\n * @example\n * // Detailed configuration with custom paths\n * const config: IndexEntitiesConfig = {\n *   controllers: {\n *     enabled: true,\n *     source: 'app/http/controllers',\n *     importAlias: '#controllers',\n *     glob: ['**\\/*_controller.ts']\n *   },\n *   listeners: {\n *     enabled: false\n *   }\n * }\n */\nexport type IndexEntitiesConfig = {\n  /** Configuration for controllers indexing */\n  controllers?: {\n    /** Whether to enable controllers indexing */\n    enabled?: boolean\n    /** Source directory for controllers */\n    source?: string\n    /** Import alias for controllers */\n    importAlias?: string\n    /** Glob patterns for matching controller files */\n    glob?: string[]\n    /** Path segments to skip from generated keys. Defaults to ['controllers'] */\n    skipSegments?: string[]\n  }\n  /** Configuration for listeners indexing */\n  listeners?: {\n    /** Whether to enable listeners indexing */\n    enabled?: boolean\n    /** Source directory for listeners */\n    source?: string\n    /** Import alias for listeners */\n    importAlias?: string\n    /** Glob patterns for matching listener files */\n    glob?: string[]\n    /** Path segments to skip from generated keys. Defaults to ['listeners'] */\n    skipSegments?: string[]\n  }\n  /** Configuration for events indexing */\n  events?: {\n    /** Whether to enable events indexing */\n    enabled?: boolean\n    /** Source directory for events */\n    source?: string\n    /** Import alias for events */\n    importAlias?: string\n    /** Glob patterns for matching event files */\n    glob?: string[]\n    /** Path segments to skip from generated keys. Defaults to ['events'] */\n    skipSegments?: string[]\n  }\n  /** Configuration for transformers indexing */\n  transformers?: {\n    /** Whether to enable transformers indexing */\n    enabled?: boolean\n    /** Whether to include shared props in transformers */\n    withSharedProps?: boolean\n    inertiaMiddlewareImportPath?: string\n    /** Source directory for transformers */\n    source?: string\n    /** Import alias for transformers */\n    importAlias?: string\n    /** Glob patterns for matching transformer files */\n    glob?: string[]\n    /** Path segments to skip from generated keys. Defaults to ['transformers'] */\n    skipSegments?: string[]\n  }\n  /** Configuration for manifest generation */\n  manifest?: {\n    /** Whether to enable manifest generation */\n    enabled?: boolean\n    exclude?: string[]\n  }\n}\n"
  },
  {
    "path": "src/utils.ts",
    "content": "/*\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 typescript from 'typescript'\nimport type * as Assembler from '@adonisjs/assembler'\nimport { type RecursiveFileTree } from '@adonisjs/assembler/types'\nimport { type ApplicationService } from './types.ts'\n\n/**\n * Imports the AdonisJS assembler package optionally. This function attempts\n * to import the assembler and returns undefined if it's not available,\n * making it safe to use in environments where the assembler might not be installed.\n *\n * @param app - The application service instance used for importing the assembler\n *\n * @example\n * const assembler = await importAssembler(app)\n * if (assembler) {\n *   // Use assembler functionality\n *   const generator = new assembler.IndexGenerator()\n * }\n */\nexport async function importAssembler(\n  app: ApplicationService\n): Promise<typeof Assembler | undefined> {\n  try {\n    return await app.import('@adonisjs/assembler')\n  } catch {}\n}\n\n/**\n * Imports the TypeScript compiler package optionally. This function attempts\n * to import TypeScript and returns undefined if it's not available,\n * making it safe to use in environments where TypeScript might not be installed.\n *\n * @param app - The application service instance used for importing TypeScript\n *\n * @example\n * const ts = await importTypeScript(app)\n * if (ts) {\n *   // Use TypeScript compiler API\n *   const program = ts.createProgram(['file.ts'], {})\n *   const sourceFile = program.getSourceFile('file.ts')\n * }\n */\nexport async function importTypeScript(\n  app: ApplicationService\n): Promise<typeof typescript | undefined> {\n  try {\n    return await app.importDefault('typescript')\n  } catch {}\n}\n\n/**\n * Outputs transformer data objects by generating TypeScript type definitions\n * for all transformers in the provided file tree. This function creates\n * InferData types for each transformer and organizes them in namespaces.\n *\n * @param transformersList - A recursive file tree containing transformer file paths\n * @param buffer - The file buffer to write the generated types to\n *\n * @example\n * const transformersList = {\n *   User: '#app/transformers/user_transformer',\n *   Auth: {\n *     Login: '#app/transformers/auth/login_transformer'\n *   }\n * }\n * await outputTransformerDataObjects(transformersList, buffer)\n * // Generates:\n * // export namespace Data {\n * //   export type User = InferData<UserTransformer>\n * //   export namespace Auth {\n * //     export type Login = InferData<AuthLoginTransformer>\n * //   }\n * // }\n */\nexport async function outputTransformerDataObjects(\n  transformersList: RecursiveFileTree,\n  buffer: Assembler.FileBuffer,\n  withSharedProps: boolean,\n  inertiaMiddlewareImportPath: string = '#middleware/inertia_middleware'\n) {\n  const importsBuffer = buffer.create()\n  importsBuffer.write(`/// <reference path=\"./manifest.d.ts\" />`)\n  importsBuffer.write(\n    `import type { InferData, InferVariants } from '@adonisjs/core/types/transformers'`\n  )\n\n  if (withSharedProps) {\n    importsBuffer.write(`import type { InferSharedProps } from '@adonisjs/inertia/types'`)\n  }\n\n  buffer.writeLine(importsBuffer)\n  buffer.write('export namespace Data {').indent()\n\n  /**\n   * Recursively generates namespace tree structure for transformers.\n   * Creates nested namespaces for directory structures and type exports\n   * for individual transformer files.\n   *\n   * @param input - The current level of the file tree to process\n   * @param parents - Array of parent namespace names for import naming\n   */\n  function generateNamespaceTree(input: RecursiveFileTree, parents: string[]) {\n    Object.keys(input).forEach((key) => {\n      const value = input[key]\n      if (typeof value === 'string') {\n        const importName = `${parents.join('')}${key}Transformer`\n        importsBuffer.write(`import type ${importName} from '${value}'`)\n        buffer.write(`export type ${key} = InferData<${importName}>`)\n        buffer.write(`export namespace ${key} {`).indent()\n        buffer.write(`export type Variants = InferVariants<${importName}>`)\n        buffer.dedent().write('}')\n      } else {\n        buffer.write(`export namespace ${key} {`).indent()\n        generateNamespaceTree(value, [...parents, key])\n        buffer.dedent().write(`}`)\n      }\n    })\n  }\n\n  generateNamespaceTree(transformersList, [])\n\n  if (withSharedProps) {\n    importsBuffer.write(`import type InertiaMiddleware from '${inertiaMiddlewareImportPath}'`)\n    buffer.write('export type SharedProps = InferSharedProps<InertiaMiddleware>')\n  }\n\n  buffer.dedent().write('}')\n}\n"
  },
  {
    "path": "src/vine.ts",
    "content": "/*\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 vine, { symbols, BaseLiteralType } from '@vinejs/vine'\nimport type { Validation, FieldContext, FieldOptions } from '@vinejs/vine/types'\nimport type { MultipartFile, FileValidationOptions } from '@adonisjs/bodyparser/types'\n\nconst MULTIPART_FILE: typeof symbols.SUBTYPE = symbols.SUBTYPE ?? Symbol.for('subtype')\n\n/**\n * Validation options accepted by the \"file\" rule\n */\nexport type FileRuleValidationOptions =\n  | Partial<FileValidationOptions>\n  | ((field: FieldContext) => Partial<FileValidationOptions>)\n\n/**\n * Checks if the value is an instance of multipart file from bodyparser.\n * Used internally for type guarding in file validation.\n *\n * @param file - The value to check for MultipartFile instance\n */\nfunction isBodyParserFile(file: unknown): file is MultipartFile {\n  return !!(file && typeof file === 'object' && 'isMultipartFile' in file)\n}\n\n/**\n * VineJS validation rule that validates the file to be an instance of BodyParser\n * MultipartFile class and applies size/extension validation if configured.\n *\n * @param file - The file value to validate\n * @param options - Validation options for file size and extensions\n * @param field - The field context from VineJS validation\n */\nconst isMultipartFile = vine.createRule<FileRuleValidationOptions>((file, options, field) => {\n  if (!field.isDefined) {\n    return false\n  }\n\n  /**\n   * Report error when value is not a field multipart\n   * file object\n   */\n  if (!isBodyParserFile(file)) {\n    field.report('The {{ field }} must be a file', 'file', field)\n    return false\n  }\n\n  const validationOptions = typeof options === 'function' ? options(field) : options\n\n  /**\n   * Set size when it's defined in the options and missing\n   * on the file instance\n   */\n  if (file.sizeLimit === undefined && validationOptions.size) {\n    file.sizeLimit = validationOptions.size\n  }\n\n  /**\n   * Set extensions when it's defined in the options and missing\n   * on the file instance\n   */\n  if (file.allowedExtensions === undefined && validationOptions.extnames) {\n    file.allowedExtensions = validationOptions.extnames\n  }\n\n  /**\n   * Validate file\n   */\n  file.validate()\n\n  /**\n   * Report errors\n   */\n  file.errors.forEach((error) => {\n    field.report(error.message, `file.${error.type}`, field, validationOptions)\n  })\n\n  return file.isValid\n})\n\n/**\n * Represents a multipart file uploaded via multipart/form-data HTTP\n * request. This class extends VineJS's BaseLiteralType to provide\n * specialized validation for uploaded files.\n *\n * @example\n * const fileSchema = vine.object({\n *   avatar: vine.file({\n *     size: '2mb',\n *     extnames: ['jpg', 'png']\n *   })\n * })\n */\nexport class VineMultipartFile extends BaseLiteralType<\n  MultipartFile,\n  MultipartFile,\n  MultipartFile\n> {\n  /**\n   * Private validation options for file validation\n   */\n  #validationOptions?: FileRuleValidationOptions;\n\n  /**\n   * Symbol identifier for multipart file subtype\n   */\n  [MULTIPART_FILE] = 'multipartFile'\n\n  /**\n   * Creates a new VineMultipartFile instance\n   *\n   * @param validationOptions - File validation options like size limits and allowed extensions\n   * @param options - Field options from VineJS\n   * @param validations - Array of validation functions to apply\n   */\n  constructor(\n    validationOptions?: FileRuleValidationOptions,\n    options?: FieldOptions,\n    validations?: Validation<any>[]\n  ) {\n    super(options, validations || [])\n    this.#validationOptions = validationOptions\n    this.dataTypeValidator = isMultipartFile(validationOptions || {})\n  }\n\n  /**\n   * Creates a clone of the current VineMultipartFile instance\n   * with the same validation options and configurations\n   */\n  clone() {\n    return new VineMultipartFile(\n      this.#validationOptions,\n      this.cloneOptions(),\n      this.cloneValidations()\n    ) as this\n  }\n}\n"
  },
  {
    "path": "stubs/main.ts",
    "content": "/*\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\nexport const stubsRoot = import.meta.dirname\n"
  },
  {
    "path": "stubs/make/command/main.stub",
    "content": "{{#var commandName = generators.commandName(entity.name)}}\n{{#var commandTerminalName = generators.commandTerminalName(entity.name)}}\n{{#var commandFileName = generators.commandFileName(entity.name)}}\n{{{\n  exports({\n    to: app.commandsPath(entity.path, commandFileName)\n  })\n}}}\nimport { BaseCommand } from '@adonisjs/core/ace'\nimport type { CommandOptions } from '@adonisjs/core/types/ace'\n\nexport default class {{ commandName }} extends BaseCommand {\n  static commandName = '{{ commandTerminalName }}'\n  static description = ''\n\n  static options: CommandOptions = {}\n\n  async run() {\n    this.logger.info('Hello world from \"{{ commandName }}\"')\n  }\n}\n"
  },
  {
    "path": "stubs/make/controller/actions.stub",
    "content": "{{#var controllerName = generators.controllerName(entity.name, singular)}}\n{{#var controllerFileName = generators.controllerFileName(entity.name, singular)}}\n{{{\n  exports({\n    to: app.httpControllersPath(entity.path, controllerFileName)\n  })\n}}}\nimport type { HttpContext } from '@adonisjs/core/http'\n\nexport default class {{ controllerName }} {\n  {{#each actions as action}}\n  async {{action}}({}: HttpContext) {}\n  {{/each}}\n}\n"
  },
  {
    "path": "stubs/make/controller/api.stub",
    "content": "{{#var controllerName = generators.controllerName(entity.name, singular)}}\n{{#var controllerFileName = generators.controllerFileName(entity.name, singular)}}\n{{{\n  exports({\n    to: app.httpControllersPath(entity.path, controllerFileName)\n  })\n}}}\nimport type { HttpContext } from '@adonisjs/core/http'\n\nexport default class {{ controllerName }} {\n  /**\n   * Display a list of resource\n   */\n  async index({}: HttpContext) {}\n\n  /**\n   * Handle form submission for the create action\n   */\n  async store({ request }: HttpContext) {}\n\n  /**\n   * Show individual record\n   */\n  async show({ params }: HttpContext) {}\n\n  /**\n   * Handle form submission for the edit action\n   */\n  async update({ params, request }: HttpContext) {}\n\n  /**\n   * Delete record\n   */\n  async destroy({ params }: HttpContext) {}\n}\n"
  },
  {
    "path": "stubs/make/controller/main.stub",
    "content": "{{#var controllerName = generators.controllerName(entity.name, singular)}}\n{{#var controllerFileName = generators.controllerFileName(entity.name, singular)}}\n{{{\n  exports({\n    to: app.httpControllersPath(entity.path, controllerFileName)\n  })\n}}}\n// import type { HttpContext } from '@adonisjs/core/http'\n\nexport default class {{ controllerName }} {\n}\n"
  },
  {
    "path": "stubs/make/controller/resource.stub",
    "content": "{{#var controllerName = generators.controllerName(entity.name, singular)}}\n{{#var controllerFileName = generators.controllerFileName(entity.name, singular)}}\n{{{\n  exports({\n    to: app.httpControllersPath(entity.path, controllerFileName)\n  })\n}}}\nimport type { HttpContext } from '@adonisjs/core/http'\n\nexport default class {{ controllerName }} {\n  /**\n   * Display a list of resource\n   */\n  async index({}: HttpContext) {}\n\n  /**\n   * Display form to create a new record\n   */\n  async create({}: HttpContext) {}\n\n  /**\n   * Handle form submission for the create action\n   */\n  async store({ request }: HttpContext) {}\n\n  /**\n   * Show individual record\n   */\n  async show({ params }: HttpContext) {}\n\n  /**\n   * Edit individual record\n   */\n  async edit({ params }: HttpContext) {}\n\n  /**\n   * Handle form submission for the edit action\n   */\n  async update({ params, request }: HttpContext) {}\n\n  /**\n   * Delete record\n   */\n  async destroy({ params }: HttpContext) {}\n}\n"
  },
  {
    "path": "stubs/make/event/main.stub",
    "content": "{{#var eventName = generators.eventName(entity.name)}}\n{{#var eventFileName = generators.eventFileName(entity.name)}}\n{{{\n  exports({\n    to: app.eventsPath(entity.path, eventFileName)\n  })\n}}}\nimport { BaseEvent } from '@adonisjs/core/events'\n\nexport default class {{ eventName }} extends BaseEvent {\n  /**\n   * Accept event data as constructor parameters\n   */\n  constructor() {\n    super()\n  }\n}\n"
  },
  {
    "path": "stubs/make/exception/main.stub",
    "content": "{{#var exceptionName = generators.exceptionName(entity.name)}}\n{{#var exceptionFileName = generators.exceptionFileName(entity.name)}}\n{{{\n  exports({\n    to: app.exceptionsPath(entity.path, exceptionFileName)\n  })\n}}}\nimport { Exception } from '@adonisjs/core/exceptions'\n\nexport default class {{ exceptionName }} extends Exception {\n  static status = 500\n}\n"
  },
  {
    "path": "stubs/make/health/controller.stub",
    "content": "{{#var controllerName = generators.controllerName(entity.name, false)}}\n{{#var controllerFileName = generators.controllerFileName(entity.name, false)}}\n{{{\n  exports({\n    to: app.httpControllersPath(entity.path, controllerFileName)\n  })\n}}}\nimport { healthChecks } from '#start/health'\nimport type { HttpContext } from '@adonisjs/core/http'\n\nexport default class {{ controllerName }} {\n  async live({ response }: HttpContext) {\n    return response.ok()\n  }\n\n  async ready({ response }: HttpContext) {\n    const report = await healthChecks.run()\n    if (report.isHealthy) {\n      return response.ok(report)\n    }\n\n    return response.serviceUnavailable(report)\n  }\n}\n"
  },
  {
    "path": "stubs/make/health/main.stub",
    "content": "{{#var preloadFileName = string(entity.name).snakeCase().removeExtension().ext('.ts').toString()}}\n{{{\n  exports({\n    to: app.startPath(entity.path, preloadFileName)\n  })\n}}}\nimport { HealthChecks, DiskSpaceCheck, MemoryHeapCheck } from '@adonisjs/core/health'\n\nexport const healthChecks = new HealthChecks().register([\n  new DiskSpaceCheck(),\n  new MemoryHeapCheck(),\n])\n"
  },
  {
    "path": "stubs/make/listener/for_event.stub",
    "content": "{{#var listenerName = generators.listenerName(entity.name)}}\n{{#var listenerFileName = generators.listenerFileName(entity.name)}}\n{{#var eventName = generators.eventName(event.name)}}\n{{#var eventFileName = generators.eventFileName(event.name)}}\n{{#var eventImportPath = generators.importPath('#events', event.path, eventFileName)}}\n{{{\n  exports({\n    to: app.listenersPath(entity.path, listenerFileName)\n  })\n}}}\nimport type {{ eventName }} from '{{ eventImportPath }}'\n\nexport default class {{ listenerName }} {\n  async handle(event: {{ eventName }}) {}\n}\n"
  },
  {
    "path": "stubs/make/listener/main.stub",
    "content": "{{#var listenerName = generators.listenerName(entity.name)}}\n{{#var listenerFileName = generators.listenerFileName(entity.name)}}\n{{{\n  exports({\n    to: app.listenersPath(entity.path, listenerFileName)\n  })\n}}}\nexport default class {{ listenerName }} {\n}\n"
  },
  {
    "path": "stubs/make/middleware/main.stub",
    "content": "{{#var middlewareName = generators.middlewareName(entity.name)}}\n{{#var middlewareFileName = generators.middlewareFileName(entity.name)}}\n{{{\n  exports({\n    to: app.middlewarePath(entity.path, middlewareFileName)\n  })\n}}}\nimport type { HttpContext } from '@adonisjs/core/http'\nimport type { NextFn } from '@adonisjs/core/types/http'\n\nexport default class {{ middlewareName }} {\n  async handle(ctx: HttpContext, next: NextFn) {\n    /**\n     * Middleware logic goes here (before the next call)\n     */\n    console.log(ctx)\n\n    /**\n     * Call next method in the pipeline and return its output\n     */\n    const output = await next()\n    return output\n  }\n}\n"
  },
  {
    "path": "stubs/make/preload/main.stub",
    "content": "{{#var preloadFileName = string(entity.name).snakeCase().removeExtension().ext('.ts').toString()}}\n{{{\n  exports({\n    to: app.startPath(entity.path, preloadFileName)\n  })\n}}}\n"
  },
  {
    "path": "stubs/make/provider/main.stub",
    "content": "{{#var providerName = generators.providerName(entity.name)}}\n{{#var providerFileName = generators.providerFileName(entity.name)}}\n{{{\n  exports({\n    to: app.providersPath(entity.path, providerFileName)\n  })\n}}}\nimport type { ApplicationService } from '@adonisjs/core/types'\n\nexport default class {{ providerName }} {\n  constructor(protected app: ApplicationService) {}\n\n  /**\n   * Register bindings to the container\n   */\n  register() {}\n\n  /**\n   * The container bindings have booted\n   */\n  async boot() {}\n\n  /**\n   * The application has been booted\n   */\n  async start() {}\n\n  /**\n   * The process has been started\n   */\n  async ready() {}\n\n  /**\n   * Preparing to shutdown the app\n   */\n  async shutdown() {}\n}\n"
  },
  {
    "path": "stubs/make/service/main.stub",
    "content": "{{#var serviceName = generators.serviceName(entity.name)}}\n{{#var serviceFileName = generators.serviceFileName(entity.name)}}\n{{{\n  exports({\n    to: app.servicesPath(entity.path, serviceFileName)\n  })\n}}}\nexport class {{ serviceName }} {\n  // Your code here\n}\n"
  },
  {
    "path": "stubs/make/test/main.stub",
    "content": "{{#var testGroupName = generators.testGroupName(entity)}}\n{{#var testFileName = generators.testFileName(entity.name)}}\n{{{\n  exports({\n    to: app.makePath(suite.directory, entity.path, testFileName)\n  })\n}}}\nimport { test } from '@japa/runner'\n\ntest.group('{{ testGroupName }}', () => {\n  test('example test', async ({ assert }) => {\n  })\n})\n"
  },
  {
    "path": "stubs/make/transformer/main.stub",
    "content": "{{#var transformerName = generators.transformerName(entity.name)}}\n{{#var transformerFileName = generators.transformerFileName(entity.name)}}\n{{#var modelName = generators.modelName(model.name)}}\n{{#var modelFileName = generators.modelFileName(model.name)}}\n{{#var modelImportPath = generators.importPath('#models', model.path, modelFileName.replace(/\\.ts$/, ''))}}\n{{{\n  exports({\n    to: app.transformersPath(entity.path, transformerFileName)\n  })\n}}}\nimport { BaseTransformer } from '@adonisjs/core/transformers'\nimport {{ modelName }} from '{{ modelImportPath }}'\n\nexport default class {{ transformerName }} extends BaseTransformer<{{modelName}}> {\n  toObject() {\n    return this.pick(this.resource, ['id'])\n  }\n}\n"
  },
  {
    "path": "stubs/make/validator/main.stub",
    "content": "{{#var validatorFileName = generators.validatorFileName(entity.name)}}\n{{{\n  exports({\n    to: app.validatorsPath(entity.path, validatorFileName)\n  })\n}}}\nimport vine from '@vinejs/vine'\n"
  },
  {
    "path": "stubs/make/validator/resource.stub",
    "content": "{{#var validatorName = string(generators.validatorName(entity.name)).noCase()}}\n{{#var validatorFileName = generators.validatorFileName(entity.name)}}\n{{#var createAction = generators.validatorActionName(entity.name, 'create')}}\n{{#var updateAction = generators.validatorActionName(entity.name, 'update')}}\n{{{\n  exports({\n    to: app.validatorsPath(entity.path, validatorFileName)\n  })\n}}}\nimport vine from '@vinejs/vine'\n\n/**\n * Validator to validate the payload when creating\n * a new {{ validatorName }}.\n */\nexport const {{ createAction }} = vine.compile(\n  vine.object({})\n)\n\n/**\n * Validator to validate the payload when updating\n * an existing {{ validatorName }}.\n */\nexport const {{ updateAction }} = vine.compile(\n  vine.object({})\n)\n"
  },
  {
    "path": "stubs/make/view/main.stub",
    "content": "{{#var viewFileName = generators.viewFileName(entity.name)}}\n{{{\n  exports({\n    to: app.viewsPath(entity.path, viewFileName)\n  })\n}}}\n"
  },
  {
    "path": "tests/ace/base_command.spec.ts",
    "content": "/*\n * @adonisjs/ace\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 sinon from 'sinon'\nimport { test } from '@japa/runner'\nimport { BaseCommand } from '../../modules/ace/main.ts'\nimport { ListCommand } from '../../modules/ace/commands.ts'\nimport { IgnitorFactory } from '../../factories/core/ignitor.ts'\nimport { createAceKernel } from '../../modules/ace/create_kernel.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\n\ntest.group('Base command', () => {\n  test('infer staysAlive and startApp flags from command options', async ({ assert }) => {\n    const ignitor = new IgnitorFactory().withCoreConfig().create(BASE_URL)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n\n    class MakeController extends BaseCommand {\n      static options = {\n        startApp: true,\n        staysAlive: true,\n      }\n    }\n\n    const kernel = createAceKernel(app)\n    const command = await kernel.create(MakeController, [])\n    const listCommand = await kernel.create(ListCommand, [])\n\n    assert.isTrue(command.startApp)\n    assert.isTrue(command.staysAlive)\n\n    assert.isUndefined(listCommand.startApp)\n    assert.isUndefined(listCommand.staysAlive)\n  })\n\n  test('execute command template methods', async ({ assert }) => {\n    const ignitor = new IgnitorFactory().withCoreConfig().create(BASE_URL)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n\n    class MakeController extends BaseCommand {\n      static commandName: string = 'make:controller'\n\n      stack: string[] = []\n      async prepare() {\n        this.stack.push('prepare')\n      }\n\n      async interact() {\n        this.stack.push('interact')\n      }\n\n      async run() {\n        this.stack.push('run')\n      }\n\n      async completed() {\n        this.stack.push('completed')\n      }\n    }\n\n    const kernel = createAceKernel(app)\n    const command = await kernel.create(MakeController, [])\n    await command.exec()\n\n    assert.deepEqual(command.stack, ['prepare', 'interact', 'run', 'completed'])\n  })\n\n  test('do not run template methods when do not exists', async ({ assert }) => {\n    const ignitor = new IgnitorFactory().withCoreConfig().create(BASE_URL)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n\n    class MakeController extends BaseCommand {\n      static commandName: string = 'make:controller'\n      stack: string[] = []\n\n      async run() {\n        this.stack.push('run')\n      }\n    }\n\n    const kernel = createAceKernel(app)\n    const command = await kernel.create(MakeController, [])\n    await command.exec()\n\n    assert.deepEqual(command.stack, ['run'])\n  })\n\n  test('fail when prepare method raises exception', async ({ assert }) => {\n    const ignitor = new IgnitorFactory().withCoreConfig().create(BASE_URL)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n\n    class MakeController extends BaseCommand {\n      static commandName: string = 'make:controller'\n      async prepare() {\n        throw new Error('prepare failed')\n      }\n    }\n\n    const kernel = createAceKernel(app)\n    kernel.ui.switchMode('raw')\n    kernel.errorHandler.render = async function (error: Error) {\n      command.logger.fatal(error)\n    }\n\n    const command = await kernel.create(MakeController, [])\n    await command.exec()\n\n    assert.equal(command.error.message, 'prepare failed')\n    assert.equal(command.exitCode, 1)\n    assert.lengthOf(command.logger.getLogs(), 1)\n    assert.equal(command.logger.getLogs()[0].stream, 'stderr')\n  })\n\n  test('fail when interact method raises exception', async ({ assert }) => {\n    const ignitor = new IgnitorFactory().withCoreConfig().create(BASE_URL)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n\n    class MakeController extends BaseCommand {\n      static commandName: string = 'make:controller'\n      async interact() {\n        throw new Error('interact failed')\n      }\n    }\n\n    const kernel = createAceKernel(app)\n    kernel.ui.switchMode('raw')\n    kernel.errorHandler.render = async function (error: Error) {\n      command.logger.fatal(error)\n    }\n\n    const command = await kernel.create(MakeController, [])\n    await command.exec()\n\n    assert.equal(command.error.message, 'interact failed')\n    assert.equal(command.exitCode, 1)\n    assert.lengthOf(command.logger.getLogs(), 1)\n    assert.equal(command.logger.getLogs()[0].stream, 'stderr')\n  })\n\n  test('fail when run method raises exception', async ({ assert }) => {\n    const ignitor = new IgnitorFactory().withCoreConfig().create(BASE_URL)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n\n    class MakeController extends BaseCommand {\n      static commandName: string = 'make:controller'\n      async run() {\n        throw new Error('run failed')\n      }\n    }\n\n    const kernel = createAceKernel(app)\n    kernel.ui.switchMode('raw')\n    kernel.errorHandler.render = async function (error: Error) {\n      command.logger.fatal(error)\n    }\n\n    const command = await kernel.create(MakeController, [])\n    await command.exec()\n\n    assert.equal(command.error.message, 'run failed')\n    assert.equal(command.exitCode, 1)\n    assert.lengthOf(command.logger.getLogs(), 1)\n    assert.equal(command.logger.getLogs()[0].stream, 'stderr')\n  })\n\n  test('do not print errors when completed method handles exception', async ({ assert }) => {\n    const ignitor = new IgnitorFactory().withCoreConfig().create(BASE_URL)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n\n    class MakeController extends BaseCommand {\n      static commandName: string = 'make:controller'\n      async run() {\n        throw new Error('run failed')\n      }\n\n      async completed() {\n        return true\n      }\n    }\n\n    const kernel = createAceKernel(app)\n    kernel.ui.switchMode('raw')\n\n    const command = await kernel.create(MakeController, [])\n    await command.exec()\n\n    assert.equal(command.error.message, 'run failed')\n    assert.equal(command.exitCode, 1)\n    assert.lengthOf(command.logger.getLogs(), 0)\n  })\n\n  test('print error when completed method does not handles exception', async ({ assert }) => {\n    const ignitor = new IgnitorFactory().withCoreConfig().create(BASE_URL)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n\n    class MakeController extends BaseCommand {\n      static commandName: string = 'make:controller'\n      async run() {\n        throw new Error('run failed')\n      }\n\n      async completed() {\n        return false\n      }\n    }\n\n    const kernel = createAceKernel(app)\n    kernel.ui.switchMode('raw')\n    kernel.errorHandler.render = async function (error: Error) {\n      command.logger.fatal(error)\n    }\n\n    const command = await kernel.create(MakeController, [])\n    await command.exec()\n\n    assert.equal(command.error.message, 'run failed')\n    assert.equal(command.exitCode, 1)\n    assert.lengthOf(command.logger.getLogs(), 1)\n    assert.equal(command.logger.getLogs()[0].stream, 'stderr')\n  })\n\n  test('throw exception when completed method raises exception', async ({ assert }) => {\n    const ignitor = new IgnitorFactory().withCoreConfig().create(BASE_URL)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n\n    class MakeController extends BaseCommand {\n      static commandName: string = 'make:controller'\n      async completed() {\n        throw new Error('completed failed')\n      }\n    }\n\n    const kernel = createAceKernel(app)\n    const command = await kernel.create(MakeController, [])\n\n    await assert.rejects(() => command.exec(), 'completed failed')\n  })\n\n  test('call app terminate when main command terminate method is called', async () => {\n    const ignitor = new IgnitorFactory().withCoreConfig().create(BASE_URL)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n\n    class MakeController extends BaseCommand {\n      static options = {\n        startApp: true,\n        staysAlive: true,\n      }\n    }\n\n    const kernel = createAceKernel(app)\n    const command = await kernel.create(MakeController, [])\n    const listCommand = await kernel.create(ListCommand, [])\n\n    const appMock = sinon.mock(app)\n    appMock.expects('terminate').twice()\n\n    kernel.getMainCommand = () => command\n    await command.terminate()\n\n    kernel.getMainCommand = () => listCommand\n    await listCommand.terminate()\n\n    appMock.verify()\n  })\n})\n"
  },
  {
    "path": "tests/ace/codemods.spec.ts",
    "content": "/*\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 { test } from '@japa/runner'\nimport { Codemods } from '../../modules/ace/codemods.ts'\nimport { AceFactory } from '../../factories/core/ace.ts'\n\ntest.group('Codemods', (group) => {\n  group.tap((t) => t.timeout(60 * 1000))\n\n  test('get ts morph project', async ({ assert, fs }) => {\n    await fs.createJson('tsconfig.json', {})\n\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n\n    const codemods = new Codemods(ace.app, ace.ui.logger)\n    const project = await codemods.getTsMorphProject()\n\n    assert.exists(project)\n  })\n\n  test('reuse the same CodeTransformer instance', async ({ assert, fs }) => {\n    await fs.createJson('tsconfig.json', {})\n\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n\n    const codemods = new Codemods(ace.app, ace.ui.logger)\n    const project1 = await codemods.getTsMorphProject()\n    const project2 = await codemods.getTsMorphProject()\n\n    assert.deepEqual(project1, project2)\n  })\n})\n\ntest.group('Codemods | environment variables', (group) => {\n  group.tap((t) => t.timeout(60 * 1000))\n\n  test('define env variables', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    /**\n     * Creating .env file so that we can update it.\n     */\n    await fs.create('.env', '')\n\n    const codemods = new Codemods(ace.app, ace.ui.logger)\n    await codemods.defineEnvVariables({ CORS_MODE: 'strict', CORS_ENABLED: true })\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    update .env file',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileContains('.env', 'CORS_MODE=strict')\n    await assert.fileContains('.env', 'CORS_ENABLED=true')\n  })\n\n  test('do not insert env value in .env.example if specified', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    /**\n     * Creating .env file so that we can update it.\n     */\n    await fs.create('.env', '')\n    await fs.create('.env.example', '')\n\n    const codemods = new Codemods(ace.app, ace.ui.logger)\n    await codemods.defineEnvVariables(\n      { SECRET_VALUE: 'secret' },\n      { omitFromExample: ['SECRET_VALUE'] }\n    )\n    await assert.fileContains('.env', 'SECRET_VALUE=secret')\n    await assert.fileContains('.env.example', 'SECRET_VALUE=')\n  })\n\n  test('do not define env variables when file does not exists', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const codemods = new Codemods(ace.app, ace.ui.logger)\n\n    await codemods.defineEnvVariables({ CORS_MODE: 'strict', CORS_ENABLED: true })\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    update .env file',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileNotExists('.env')\n  })\n\n  test('define env variables validations', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.createJson('tsconfig.json', {})\n\n    /**\n     * Creating .env file so that we can update it.\n     */\n    await fs.create('start/env.ts', `export default Env.create(new URL('./'), {})`)\n\n    const codemods = new Codemods(ace.app, ace.ui.logger)\n\n    await codemods.defineEnvValidations({\n      variables: {\n        CORS_MODE: 'Env.schema.string()',\n      },\n    })\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    update start/env.ts file',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileContains('start/env.ts', 'CORS_MODE: Env.schema.string()')\n  })\n})\n\ntest.group('Codemods | rcFile', (group) => {\n  group.tap((t) => t.timeout(60 * 1000))\n\n  test('update rcfile', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('adonisrc.ts', 'export default defineConfig({})')\n\n    const codemods = new Codemods(ace.app, ace.ui.logger)\n\n    await codemods.updateRcFile((rcFile) => {\n      rcFile.addProvider('@adonisjs/core')\n      rcFile.addCommand('@adonisjs/core/commands')\n    })\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    update adonisrc.ts file',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileContains('adonisrc.ts', '@adonisjs/core')\n    await assert.fileContains('adonisrc.ts', '@adonisjs/core/commands')\n  })\n})\n\ntest.group('Codemods | registerMiddleware', (group) => {\n  group.tap((t) => t.timeout(60 * 1000))\n\n  test('register middleware', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('start/kernel.ts', 'router.use([])')\n\n    const codemods = new Codemods(ace.app, ace.ui.logger)\n    await codemods.registerMiddleware('router', [{ path: '@adonisjs/core/bodyparser_middleware' }])\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    update start/kernel.ts file',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileContains('start/kernel.ts', '@adonisjs/core/bodyparser_middleware')\n  })\n})\n\ntest.group('Codemods | registerPolicies', (group) => {\n  group.tap((t) => t.timeout(60 * 1000))\n\n  test('register bouncer policies', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('app/policies/main.ts', 'export const policies = {}')\n\n    const codemods = new Codemods(ace.app, ace.ui.logger)\n    await codemods.registerPolicies([{ name: 'PostPolicy', path: '#policies/post_policy' }])\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    update app/policies/main.ts file',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileContains('app/policies/main.ts', '#policies/post_policy')\n  })\n})\n\ntest.group('Codemods | registerVitePlugin', (group) => {\n  group.tap((t) => t.timeout(60 * 1000))\n\n  test('register vite plugin', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.createJson('tsconfig.json', {})\n    await fs.createJson('package.json', {})\n    await fs.create('vite.config.ts', 'export default { plugins: [] }')\n\n    const codemods = new Codemods(ace.app, ace.ui.logger)\n    await codemods.registerVitePlugin('vue()', [\n      { identifier: 'vue', module: '@vitejs/plugin-vue', isNamed: false },\n    ])\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    update vite.config.ts file',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileContains('vite.config.ts', 'vue()')\n  })\n})\n\ntest.group('Codemods | registerJapaPlugin', (group) => {\n  group.tap((t) => t.timeout(60 * 1000))\n\n  test('register japa plugin', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.createJson('tsconfig.json', {})\n    await fs.createJson('package.json', {})\n    await fs.create('tests/bootstrap.ts', 'export const plugins = []')\n\n    const codemods = new Codemods(ace.app, ace.ui.logger)\n    await codemods.registerJapaPlugin('apiClient()', [\n      { identifier: 'apiClient', module: '@japa/api-client', isNamed: true },\n    ])\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    update tests/bootstrap.ts file',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileContains('tests/bootstrap.ts', 'apiClient()')\n  })\n})\n\ntest.group('Codemods | install packages', (group) => {\n  group.tap((t) => t.timeout(60 * 1000))\n\n  test('install packages', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n\n    await fs.createJson('tsconfig.json', {})\n    await fs.createJson('package.json', {})\n    await fs.create('app/policies/main.ts', 'export const policies = {}')\n\n    const codemods = new Codemods(ace.app, ace.ui.logger)\n    await codemods.installPackages([{ name: '@adonisjs/assembler', isDevDependency: true }])\n\n    await assert.dirExists('node_modules/@adonisjs/assembler')\n  })\n\n  test('install packages in verbose mode', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n\n    await fs.createJson('tsconfig.json', {})\n    await fs.createJson('package.json', {})\n    await fs.create('app/policies/main.ts', 'export const policies = {}')\n\n    const codemods = new Codemods(ace.app, ace.ui.logger)\n    codemods.verboseInstallOutput = true\n    await codemods.installPackages([{ name: '@adonisjs/assembler', isDevDependency: true }])\n\n    await assert.dirExists('node_modules/@adonisjs/assembler')\n  })\n})\n\ntest.group('Codemods | addValidator', (group) => {\n  group.tap((t) => t.timeout(60 * 1000))\n\n  test('add validator file', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.createJson('tsconfig.json', {})\n\n    const codemods = new Codemods(ace.app, ace.ui.logger)\n    await codemods.addValidator({\n      validatorFileName: 'create_user.ts',\n      exportName: 'createUserValidator',\n      contents: 'export const createUserValidator = vine.compile(vine.object({}))',\n    })\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create validator file',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileExists('app/validators/create_user.ts')\n    await assert.fileContains('app/validators/create_user.ts', 'createUserValidator')\n  })\n})\n\ntest.group('Codemods | addLimiter', (group) => {\n  group.tap((t) => t.timeout(60 * 1000))\n\n  test('add limiter file', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.createJson('tsconfig.json', {})\n\n    const codemods = new Codemods(ace.app, ace.ui.logger)\n    await codemods.addLimiter({\n      limiterFileName: 'limiter.ts',\n      exportName: 'apiThrottleLimiter',\n      contents: 'export const apiThrottleLimiter = limiter.define(\"api\", () => {})',\n    })\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create limiter file',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileExists('start/limiter.ts')\n    await assert.fileContains('start/limiter.ts', 'apiThrottleLimiter')\n  })\n})\n\ntest.group('Codemods | addModelMixins', (group) => {\n  group.tap((t) => t.timeout(60 * 1000))\n\n  test('add mixins to model', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.createJson('tsconfig.json', {})\n    await fs.create(\n      'app/models/user.ts',\n      `import { BaseModel } from '@adonisjs/lucid/orm'\nexport default class User extends BaseModel {}`\n    )\n\n    const codemods = new Codemods(ace.app, ace.ui.logger)\n    await codemods.addModelMixins('user.ts', [\n      {\n        name: 'SoftDeletes',\n        importPath: '@adonisjs/lucid/mixins/soft_deletes',\n        importType: 'named',\n      },\n    ])\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    update model file',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileContains('app/models/user.ts', 'SoftDeletes')\n    await assert.fileContains('app/models/user.ts', '@adonisjs/lucid/mixins/soft_deletes')\n  })\n})\n\ntest.group('Codemods | addControllerMethod', (group) => {\n  group.tap((t) => t.timeout(60 * 1000))\n\n  test('add method to controller', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.createJson('tsconfig.json', {})\n    await fs.create(\n      'app/controllers/users_controller.ts',\n      `export default class UsersController {\n  async index() {}\n}`\n    )\n\n    const codemods = new Codemods(ace.app, ace.ui.logger)\n    await codemods.addControllerMethod({\n      controllerFileName: 'users_controller.ts',\n      className: 'UsersController',\n      name: 'destroy',\n      contents: 'async destroy({ params }: HttpContext) { return params.id }',\n      imports: [\n        {\n          source: '@adonisjs/core/http',\n          typeImports: ['HttpContext'],\n        },\n      ],\n    })\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    update controller file',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileContains('app/controllers/users_controller.ts', 'destroy')\n    await assert.fileContains('app/controllers/users_controller.ts', 'HttpContext')\n  })\n})\n"
  },
  {
    "path": "tests/ace/kernel.spec.ts",
    "content": "/*\n * @adonisjs/ace\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 sinon from 'sinon'\nimport { test } from '@japa/runner'\nimport { HelpCommand } from '../../modules/ace/main.ts'\nimport { IgnitorFactory } from '../../factories/core/ignitor.ts'\nimport { createAceKernel } from '../../modules/ace/create_kernel.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\n\ntest.group('Kernel', () => {\n  test('create kernel instance with global flags', async ({ assert }) => {\n    const ignitor = new IgnitorFactory().withCoreConfig().create(BASE_URL)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n\n    const kernel = createAceKernel(app)\n    assert.deepEqual(kernel.flags, [\n      {\n        name: 'ansi',\n        flagName: 'ansi',\n        required: false,\n        type: 'boolean',\n        showNegatedVariantInHelp: true,\n        description: 'Force enable or disable colorful output',\n      },\n      {\n        name: 'help',\n        flagName: 'help',\n        required: false,\n        type: 'boolean',\n        description: 'View help for a given command',\n      },\n    ])\n  })\n\n  test('turn off colors when --no-ansi flag is mentioned', async () => {\n    const ignitor = new IgnitorFactory().withCoreConfig().create(BASE_URL)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n\n    const kernel = createAceKernel(app)\n    const switchMode = sinon.spy(kernel.ui.switchMode)\n\n    await kernel.handle(['--no-ansi'])\n    switchMode.calledWith('silent')\n  })\n\n  test('turn off colors when --no-ansi flag is mentioned', async () => {\n    const ignitor = new IgnitorFactory().withCoreConfig().create(BASE_URL)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n\n    const kernel = createAceKernel(app)\n    const switchMode = sinon.spy(kernel.ui.switchMode)\n\n    await kernel.handle(['--no-ansi'])\n    switchMode.calledWith('silent')\n  })\n\n  test('turn on colors when --ansi flag is mentioned', async () => {\n    const ignitor = new IgnitorFactory().withCoreConfig().create(BASE_URL)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n\n    const kernel = createAceKernel(app)\n    const switchMode = sinon.spy(kernel.ui.switchMode)\n\n    await kernel.handle(['--ansi'])\n    switchMode.calledWith('normal')\n  })\n\n  test('display command help when --help flag is mentioned', async () => {\n    const ignitor = new IgnitorFactory().withCoreConfig().create(BASE_URL)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n\n    const kernel = createAceKernel(app)\n    const execMock = sinon.mock(HelpCommand.prototype)\n    execMock.expects('exec')\n\n    await kernel.handle(['--help'])\n    execMock.verify()\n  })\n\n  test('load commands from a module identifier', async ({ assert }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          commands: ['../commands'],\n        },\n      })\n      .create(BASE_URL, {\n        importer: (filePath) => {\n          if (filePath === '../commands') {\n            return {\n              async getMetaData() {\n                return [\n                  {\n                    commandName: 'make:controller',\n                    aliases: [],\n                  },\n                ]\n              },\n            }\n          }\n          import(filePath)\n        },\n      })\n\n    const app = ignitor.createApp('console')\n    await app.init()\n\n    const kernel = createAceKernel(app)\n    await kernel.boot()\n    assert.exists(kernel.getCommand('make:controller'))\n  })\n})\n"
  },
  {
    "path": "tests/bindings/edge.spec.ts",
    "content": "/*\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 edge from 'edge.js'\nimport { test } from '@japa/runner'\n\nimport '../../providers/edge_provider.js'\nimport { Qs } from '../../modules/http/main.ts'\nimport { HttpContextFactory } from '../../factories/http.ts'\nimport { IgnitorFactory } from '../../factories/core/ignitor.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\n\ntest.group('Bindings | Edge', () => {\n  test('register edge globals', async ({ assert }) => {\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../../providers/app_provider.js'),\n            () => import('../../providers/edge_provider.js'),\n          ],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n\n    assert.equal(edge.globals.config('app.appUrl'), 'http://localhost:3333')\n    assert.isTrue(edge.globals.config.has('app.appUrl'))\n    assert.isFalse(edge.globals.config.has('foobar'))\n    assert.strictEqual(edge.globals.app, app)\n    assert.instanceOf(edge.globals.qs, Qs)\n\n    const router = await app.container.make('router')\n    router.get('/users/:id', () => {})\n    router.commit()\n\n    assert.equal(edge.globals.route('/users/:id', [1]), '/users/1')\n    assert.match(edge.globals.signedRoute('/users/:id', [1]), /\\/users\\/1\\?signature=/)\n  })\n\n  test('render template using router', async ({ assert }) => {\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../../providers/app_provider.js'),\n            () => import('../../providers/edge_provider.js'),\n          ],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n\n    edge.registerTemplate('welcome', {\n      template: `Hello {{ username }}`,\n    })\n\n    const router = await app.container.make('router')\n    router.on('/').render('welcome', { username: 'virk' })\n    router.commit()\n\n    const route = router.match('/', 'GET', false)\n    const ctx = new HttpContextFactory().create()\n\n    await route?.route.execute(route.route, app.container.createResolver(), ctx, () => {})\n    assert.equal(ctx.response.getBody(), 'Hello virk')\n  })\n\n  test('make form action using formAttributes helper', async ({ assert }) => {\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../../providers/app_provider.js'),\n            () => import('../../providers/edge_provider.js'),\n          ],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n\n    const router = await app.container.make('router')\n    router.get('/users/:id', () => {}).as('users.show')\n    router.commit()\n\n    assert.deepEqual(edge.globals.formAttributes('users.show', { id: 1 }), {\n      action: '/users/1',\n      method: 'GET',\n    })\n  })\n\n  test('make action via method spoofing', async ({ assert }) => {\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../../providers/app_provider.js'),\n            () => import('../../providers/edge_provider.js'),\n          ],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n\n    const router = await app.container.make('router')\n    router.put('/users/:id', () => {}).as('users.update')\n    router.commit()\n\n    assert.deepEqual(edge.globals.formAttributes('users.update', { id: 1 }), {\n      action: '/users/1?_method=PUT',\n      method: 'POST',\n    })\n  })\n\n  test('make action via method spoofing and append to existing query string', async ({\n    assert,\n  }) => {\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../../providers/app_provider.js'),\n            () => import('../../providers/edge_provider.js'),\n          ],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n\n    const router = await app.container.make('router')\n    router.put('/users/:id', () => {}).as('users.update')\n    router.commit()\n    const options = {\n      qs: {\n        view: 'card',\n      },\n    }\n\n    assert.deepEqual(edge.globals.formAttributes('users.update', { id: 1 }, options), {\n      action: '/users/1?_method=PUT&view=card',\n      method: 'POST',\n    })\n\n    /**\n     * Making sure we do not mutate the options internally\n     */\n    assert.deepEqual(options, {\n      qs: {\n        view: 'card',\n      },\n    })\n  })\n\n  test('share routes with names with edge', async ({ assert }) => {\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../../providers/app_provider.js'),\n            () => import('../../providers/edge_provider.js'),\n          ],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n\n    const UsersController = () => import('#controllers/users_controller' as any)\n\n    const router = await app.container.make('router')\n    router.get('/users/:id', () => {})\n    router.get('/users', [UsersController, 'index'])\n    router.commit()\n\n    assert\n      .snapshot(edge.globals.routesJSON())\n      .matchInline(\n        '\"{\\\\\"root\\\\\":[{\\\\\"domain\\\\\":\\\\\"root\\\\\",\\\\\"methods\\\\\":[\\\\\"GET\\\\\",\\\\\"HEAD\\\\\"],\\\\\"pattern\\\\\":\\\\\"/users\\\\\",\\\\\"tokens\\\\\":[{\\\\\"old\\\\\":\\\\\"/users\\\\\",\\\\\"type\\\\\":0,\\\\\"val\\\\\":\\\\\"users\\\\\",\\\\\"end\\\\\":\\\\\"\\\\\"}],\\\\\"name\\\\\":\\\\\"users.index\\\\\"}]}\"'\n      )\n  })\n})\n"
  },
  {
    "path": "tests/bindings/repl.spec.ts",
    "content": "/*\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 { test } from '@japa/runner'\n\nimport is from '../../src/helpers/is.ts'\nimport stringHelpers from '../../src/helpers/string.ts'\nimport { IgnitorFactory } from '../../factories/core/ignitor.ts'\nimport AppServiceProvider from '../../providers/app_provider.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\n\ntest.group('Bindings | Repl', () => {\n  test('load services to REPL context', async ({ assert }) => {\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../../providers/app_provider.js'),\n            () => import('../../providers/hash_provider.js'),\n            () => import('../../providers/repl_provider.js'),\n          ],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL, {\n        importer(filePath: string) {\n          return import(new URL(filePath, new URL('../', import.meta.url)).href)\n        },\n      })\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n\n    /**\n     * Setting up REPL with fake server\n     * and context\n     */\n    const repl = await app.container.make('repl')\n    repl.server = {\n      context: {},\n      displayPrompt() {},\n    } as any\n\n    /**\n     * Define REPL bindings\n     */\n    // await new ReplServiceProvider(app).boot()\n    const methods = repl.getMethods()\n\n    await methods.loadEncryption.handler(repl)\n    assert.deepEqual(repl.server!.context.encryption, await app.container.make('encryption'))\n\n    await methods.loadApp.handler(repl)\n    assert.deepEqual(repl.server!.context.app, await app.container.make('app'))\n\n    await methods.loadHash.handler(repl)\n    assert.deepEqual(repl.server!.context.hash, await app.container.make('hash'))\n\n    await methods.loadRouter.handler(repl)\n    assert.deepEqual(repl.server!.context.router, await app.container.make('router'))\n\n    await methods.loadConfig.handler(repl)\n    assert.deepEqual(repl.server!.context.config, await app.container.make('config'))\n\n    await methods.loadTestUtils.handler(repl)\n    assert.deepEqual(repl.server!.context.testUtils, await app.container.make('testUtils'))\n\n    await methods.loadHelpers.handler(repl)\n    assert.deepEqual(repl.server!.context.helpers.string, stringHelpers)\n    assert.deepEqual(repl.server!.context.helpers.is, is)\n\n    await methods.loadUrlBuilder.handler(repl)\n    const router = await app.container.make('router')\n    assert.strictEqual(repl.server!.context.urlBuilder, router.urlBuilder)\n\n    const output = await methods.importDefault.handler(repl, '../providers/app_provider.js')\n    assert.deepEqual(output, AppServiceProvider)\n\n    assert.deepEqual(await methods.make.handler(repl, 'router'), await app.container.make('router'))\n\n    const exportedMods = await methods.importAll.handler(repl, '../../../factories')\n    assert.properties(exportedMods, [\n      'core',\n      'app',\n      'bodyparser',\n      'encryption',\n      'events',\n      'hash',\n      'logger',\n      'http',\n    ])\n  })\n})\n"
  },
  {
    "path": "tests/bindings/vinejs.spec.ts",
    "content": "/*\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 vine from '@vinejs/vine'\nimport { test } from '@japa/runner'\n\nimport { IgnitorFactory } from '../../factories/core/ignitor.ts'\nimport { MultipartFileFactory } from '../../factories/bodyparser.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\n\ntest.group('Bindings | VineJS', (group) => {\n  group.setup(async () => {\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../../providers/app_provider.js'),\n            () => import('../../providers/hash_provider.js'),\n            () => import('../../providers/vinejs_provider.js'),\n          ],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL, {\n        importer(filePath: string) {\n          return import(new URL(filePath, new URL('../', import.meta.url)).href)\n        },\n      })\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n  })\n\n  test('clone schema type', async ({ assert }) => {\n    const file = vine.file()\n    assert.notStrictEqual(file, file.clone())\n  })\n\n  test('raise error when value is not a file', async ({ assert }) => {\n    const validator = vine.create(\n      vine.object({\n        avatar: vine.file(),\n      })\n    )\n\n    try {\n      await validator.validate({\n        avatar: 'foo',\n      })\n    } catch (error) {\n      assert.deepEqual(error.messages, [\n        {\n          field: 'avatar',\n          message: 'The avatar must be a file',\n          rule: 'file',\n        },\n      ])\n    }\n  })\n\n  test('raise error when file size is greater than the allowed size', async ({ assert }) => {\n    const validator = vine.create(\n      vine.object({\n        avatar: vine.file({ size: '2mb' }),\n      })\n    )\n\n    try {\n      await validator.validate({\n        avatar: new MultipartFileFactory()\n          .merge({\n            size: 4000000,\n          })\n          .create(),\n      })\n    } catch (error) {\n      assert.deepEqual(error.messages, [\n        {\n          field: 'avatar',\n          message: 'File size should be less than 2MB',\n          rule: 'file.size',\n          meta: {\n            size: '2mb',\n          },\n        },\n      ])\n    }\n  })\n\n  test('raise error when file extension is not allowed', async ({ assert }) => {\n    const validator = vine.create(\n      vine.object({\n        avatar: vine.file({ extnames: ['jpg'] }),\n      })\n    )\n\n    try {\n      await validator.validate({\n        avatar: new MultipartFileFactory()\n          .merge({\n            size: 4000000,\n            extname: 'png',\n          })\n          .create(),\n      })\n    } catch (error) {\n      assert.deepEqual(error.messages, [\n        {\n          field: 'avatar',\n          message: 'Invalid file extension png. Only jpg is allowed',\n          rule: 'file.extname',\n          meta: {\n            extnames: ['jpg'],\n          },\n        },\n      ])\n    }\n  })\n\n  test('compute file options lazily', async ({ assert }) => {\n    const validator = vine.create(\n      vine.object({\n        avatar: vine.file(() => {\n          return { extnames: ['jpg'] }\n        }),\n      })\n    )\n\n    try {\n      await validator.validate({\n        avatar: new MultipartFileFactory()\n          .merge({\n            size: 4000000,\n            extname: 'png',\n          })\n          .create(),\n      })\n    } catch (error) {\n      assert.deepEqual(error.messages, [\n        {\n          field: 'avatar',\n          message: 'Invalid file extension png. Only jpg is allowed',\n          rule: 'file.extname',\n          meta: {\n            extnames: ['jpg'],\n          },\n        },\n      ])\n    }\n  })\n\n  test('pass validation when file is valid', async ({ assert }) => {\n    const validator = vine.create(\n      vine.object({\n        avatar: vine.file(() => {\n          return { extnames: ['jpg'] }\n        }),\n      })\n    )\n\n    const { avatar } = await validator.validate({\n      avatar: new MultipartFileFactory()\n        .merge({\n          size: 4000000,\n          extname: 'jpg',\n        })\n        .create(),\n    })\n\n    assert.equal(avatar.size, 4000000)\n    assert.lengthOf(avatar.errors, 0)\n  })\n\n  test('pass validation when file is null and marked as nullable', async ({ assert }) => {\n    const validator = vine.create(\n      vine.object({\n        avatar: vine\n          .file(() => {\n            return { extnames: ['jpg'] }\n          })\n          .nullable(),\n      })\n    )\n\n    const payload = await validator.validate({\n      avatar: null,\n    })\n    assert.isNull(payload.avatar)\n  })\n\n  test('pass validation when file is null and marked as optional', async ({ assert }) => {\n    const validator = vine.create(\n      vine.object({\n        avatar: vine\n          .file(() => {\n            return { extnames: ['jpg'] }\n          })\n          .optional(),\n      })\n    )\n\n    const payload = await validator.validate({\n      avatar: null,\n    })\n    assert.isUndefined(payload.avatar)\n  })\n\n  test('pass validation when file is missing and marked as optional', async ({ assert }) => {\n    const validator = vine.create(\n      vine.object({\n        avatar: vine\n          .file(() => {\n            return { extnames: ['jpg'] }\n          })\n          .optional(),\n      })\n    )\n\n    const payload = await validator.validate({})\n    assert.isUndefined(payload.avatar)\n  })\n\n  test('raise error when field is marked as nullable, but missing', async ({ assert }) => {\n    const validator = vine.create(\n      vine.object({\n        avatar: vine\n          .file(() => {\n            return { extnames: ['jpg'] }\n          })\n          .nullable(),\n      })\n    )\n\n    try {\n      await validator.validate({})\n    } catch (error) {\n      assert.deepEqual(error.messages, [\n        {\n          field: 'avatar',\n          message: 'The avatar field must be defined',\n          rule: 'required',\n        },\n      ])\n    }\n  })\n})\n"
  },
  {
    "path": "tests/cli_formatters/routes_list.spec.ts",
    "content": "/*\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 { test } from '@japa/runner'\nimport type { ApplicationService } from '../../src/types.ts'\nimport { IgnitorFactory } from '../../factories/core/ignitor.ts'\nimport { createAceKernel } from '../../modules/ace/create_kernel.ts'\nimport { RoutesListFormatter } from '../../src/cli_formatters/routes_list.ts'\n\n/**\n * Registers routes for testing\n */\nasync function registerRoutes(app: ApplicationService) {\n  class AboutController {\n    async handle() {}\n  }\n  class UsersController {\n    async handle() {}\n  }\n  class AuthMiddleware {\n    async handle() {}\n  }\n  const ContactController = () => import('#controllers/contacts_controller' as any)\n\n  const router = await app.container.make('router')\n  const middleware = router.named({\n    auth: async () => {\n      return {\n        default: AuthMiddleware,\n      }\n    },\n    throttle: async () => {\n      return {\n        default: class ThrottleMiddleware {\n          async handle() {}\n        },\n      }\n    },\n    signed: async () => {\n      return {\n        default: class SignedMiddleware {\n          async handle() {}\n        },\n      }\n    },\n    acl: async () => import('#middleware/acl_middleware' as any),\n  })\n\n  router.use([\n    async () => {\n      return {\n        default: class BodyParserMiddleware {\n          async handle() {}\n        },\n      }\n    },\n  ])\n\n  router.get('/', () => {})\n  router.get('/files/:directory/*', () => {})\n  router.get('/home', '#controllers/home_controller').as('home')\n  router\n    .get('/about', [AboutController])\n    .as('about')\n    .use(() => {})\n\n  router.post('/contact', [ContactController, 'store']).as('contact.store')\n  router.get('/contact', [ContactController, 'create']).as('contact.create')\n\n  router\n    .get('users', [UsersController, 'handle'])\n    .use(middleware.auth())\n    .use(function canViewUsers() {})\n    .use(() => {})\n\n  router\n    .get('payments', [() => import('#controllers/payments_controller' as any), 'index'])\n    .use(middleware.auth())\n    .use(middleware.acl())\n    .use(middleware.signed())\n    .use(middleware.throttle())\n\n  router\n    .get('/articles', [() => import('#controllers/articles_controller' as any), 'index'])\n    .as('articles')\n    .domain('blog.adonisjs.com')\n\n  router\n    .get('/articles/:id/:slug?', [() => import('#controllers/articles_controller' as any), 'show'])\n    .as('articles.show')\n    .domain('blog.adonisjs.com')\n\n  /**\n   * The redirect method is now typed\n   */\n  ;(router.on('/blog').redirect as any)('/articles')\n}\n\ntest.group('Formatters | List routes | toJSON', () => {\n  test('format routes as JSON', async ({ assert, fs }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(fs.baseUrl)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n    await registerRoutes(app)\n\n    const router = await app.container.make('router')\n    const formatter = new RoutesListFormatter(router, createAceKernel(app).ui, {}, {})\n    assert.snapshot(await formatter.formatAsJSON()).matchInline(`\n      [\n        {\n          \"domain\": \"root\",\n          \"routes\": [\n            {\n              \"handler\": {\n                \"args\": undefined,\n                \"name\": \"closure\",\n                \"type\": \"closure\",\n              },\n              \"methods\": [\n                \"GET\",\n              ],\n              \"middleware\": [],\n              \"name\": \"\",\n              \"pattern\": \"/\",\n            },\n            {\n              \"handler\": {\n                \"args\": undefined,\n                \"name\": \"closure\",\n                \"type\": \"closure\",\n              },\n              \"methods\": [\n                \"GET\",\n              ],\n              \"middleware\": [],\n              \"name\": \"\",\n              \"pattern\": \"/files/:directory/*\",\n            },\n            {\n              \"handler\": {\n                \"method\": \"handle\",\n                \"moduleNameOrPath\": \"#controllers/home_controller\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"GET\",\n              ],\n              \"middleware\": [],\n              \"name\": \"home\",\n              \"pattern\": \"/home\",\n            },\n            {\n              \"handler\": {\n                \"method\": \"handle\",\n                \"moduleNameOrPath\": \"AboutController\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"GET\",\n              ],\n              \"middleware\": [\n                {\n                  \"name\": \"closure\",\n                  \"type\": \"closure\",\n                },\n              ],\n              \"name\": \"about\",\n              \"pattern\": \"/about\",\n            },\n            {\n              \"handler\": {\n                \"method\": \"store\",\n                \"moduleNameOrPath\": \"#controllers/contacts_controller\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"POST\",\n              ],\n              \"middleware\": [],\n              \"name\": \"contact.store\",\n              \"pattern\": \"/contact\",\n            },\n            {\n              \"handler\": {\n                \"method\": \"create\",\n                \"moduleNameOrPath\": \"#controllers/contacts_controller\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"GET\",\n              ],\n              \"middleware\": [],\n              \"name\": \"contact.create\",\n              \"pattern\": \"/contact\",\n            },\n            {\n              \"handler\": {\n                \"method\": \"handle\",\n                \"moduleNameOrPath\": \"UsersController\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"GET\",\n              ],\n              \"middleware\": [\n                {\n                  \"args\": undefined,\n                  \"method\": \"handle\",\n                  \"moduleNameOrPath\": \"auth\",\n                  \"name\": \"auth\",\n                  \"type\": \"named\",\n                },\n                {\n                  \"name\": \"canViewUsers\",\n                  \"type\": \"closure\",\n                },\n                {\n                  \"name\": \"closure\",\n                  \"type\": \"closure\",\n                },\n              ],\n              \"name\": \"users\",\n              \"pattern\": \"/users\",\n            },\n            {\n              \"handler\": {\n                \"method\": \"index\",\n                \"moduleNameOrPath\": \"#controllers/payments_controller\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"GET\",\n              ],\n              \"middleware\": [\n                {\n                  \"args\": undefined,\n                  \"method\": \"handle\",\n                  \"moduleNameOrPath\": \"auth\",\n                  \"name\": \"auth\",\n                  \"type\": \"named\",\n                },\n                {\n                  \"args\": undefined,\n                  \"method\": \"handle\",\n                  \"moduleNameOrPath\": \"#middleware/acl_middleware\",\n                  \"name\": \"acl\",\n                  \"type\": \"named\",\n                },\n                {\n                  \"args\": undefined,\n                  \"method\": \"handle\",\n                  \"moduleNameOrPath\": \"signed\",\n                  \"name\": \"signed\",\n                  \"type\": \"named\",\n                },\n                {\n                  \"args\": undefined,\n                  \"method\": \"handle\",\n                  \"moduleNameOrPath\": \"throttle\",\n                  \"name\": \"throttle\",\n                  \"type\": \"named\",\n                },\n              ],\n              \"name\": \"\",\n              \"pattern\": \"/payments\",\n            },\n            {\n              \"handler\": {\n                \"args\": \"/articles\",\n                \"name\": \"redirectsToRoute\",\n                \"type\": \"closure\",\n              },\n              \"methods\": [\n                \"GET\",\n              ],\n              \"middleware\": [],\n              \"name\": \"\",\n              \"pattern\": \"/blog\",\n            },\n          ],\n        },\n        {\n          \"domain\": \"blog.adonisjs.com\",\n          \"routes\": [\n            {\n              \"handler\": {\n                \"method\": \"index\",\n                \"moduleNameOrPath\": \"#controllers/articles_controller\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"GET\",\n              ],\n              \"middleware\": [],\n              \"name\": \"articles\",\n              \"pattern\": \"/articles\",\n            },\n            {\n              \"handler\": {\n                \"method\": \"show\",\n                \"moduleNameOrPath\": \"#controllers/articles_controller\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"GET\",\n              ],\n              \"middleware\": [],\n              \"name\": \"articles.show\",\n              \"pattern\": \"/articles/:id/:slug?\",\n            },\n          ],\n        },\n      ]\n    `)\n  })\n\n  test('show HEAD routes', async ({ assert, fs }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(fs.baseUrl)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n    await registerRoutes(app)\n\n    const router = await app.container.make('router')\n    const formatter = new RoutesListFormatter(\n      router,\n      createAceKernel(app).ui,\n      { displayHeadRoutes: true },\n      {}\n    )\n    assert.snapshot(await formatter.formatAsJSON()).matchInline(`\n      [\n        {\n          \"domain\": \"root\",\n          \"routes\": [\n            {\n              \"handler\": {\n                \"args\": undefined,\n                \"name\": \"closure\",\n                \"type\": \"closure\",\n              },\n              \"methods\": [\n                \"GET\",\n                \"HEAD\",\n              ],\n              \"middleware\": [],\n              \"name\": \"\",\n              \"pattern\": \"/\",\n            },\n            {\n              \"handler\": {\n                \"args\": undefined,\n                \"name\": \"closure\",\n                \"type\": \"closure\",\n              },\n              \"methods\": [\n                \"GET\",\n                \"HEAD\",\n              ],\n              \"middleware\": [],\n              \"name\": \"\",\n              \"pattern\": \"/files/:directory/*\",\n            },\n            {\n              \"handler\": {\n                \"method\": \"handle\",\n                \"moduleNameOrPath\": \"#controllers/home_controller\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"GET\",\n                \"HEAD\",\n              ],\n              \"middleware\": [],\n              \"name\": \"home\",\n              \"pattern\": \"/home\",\n            },\n            {\n              \"handler\": {\n                \"method\": \"handle\",\n                \"moduleNameOrPath\": \"AboutController\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"GET\",\n                \"HEAD\",\n              ],\n              \"middleware\": [\n                {\n                  \"name\": \"closure\",\n                  \"type\": \"closure\",\n                },\n              ],\n              \"name\": \"about\",\n              \"pattern\": \"/about\",\n            },\n            {\n              \"handler\": {\n                \"method\": \"store\",\n                \"moduleNameOrPath\": \"#controllers/contacts_controller\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"POST\",\n              ],\n              \"middleware\": [],\n              \"name\": \"contact.store\",\n              \"pattern\": \"/contact\",\n            },\n            {\n              \"handler\": {\n                \"method\": \"create\",\n                \"moduleNameOrPath\": \"#controllers/contacts_controller\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"GET\",\n                \"HEAD\",\n              ],\n              \"middleware\": [],\n              \"name\": \"contact.create\",\n              \"pattern\": \"/contact\",\n            },\n            {\n              \"handler\": {\n                \"method\": \"handle\",\n                \"moduleNameOrPath\": \"UsersController\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"GET\",\n                \"HEAD\",\n              ],\n              \"middleware\": [\n                {\n                  \"args\": undefined,\n                  \"method\": \"handle\",\n                  \"moduleNameOrPath\": \"auth\",\n                  \"name\": \"auth\",\n                  \"type\": \"named\",\n                },\n                {\n                  \"name\": \"canViewUsers\",\n                  \"type\": \"closure\",\n                },\n                {\n                  \"name\": \"closure\",\n                  \"type\": \"closure\",\n                },\n              ],\n              \"name\": \"users\",\n              \"pattern\": \"/users\",\n            },\n            {\n              \"handler\": {\n                \"method\": \"index\",\n                \"moduleNameOrPath\": \"#controllers/payments_controller\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"GET\",\n                \"HEAD\",\n              ],\n              \"middleware\": [\n                {\n                  \"args\": undefined,\n                  \"method\": \"handle\",\n                  \"moduleNameOrPath\": \"auth\",\n                  \"name\": \"auth\",\n                  \"type\": \"named\",\n                },\n                {\n                  \"args\": undefined,\n                  \"method\": \"handle\",\n                  \"moduleNameOrPath\": \"#middleware/acl_middleware\",\n                  \"name\": \"acl\",\n                  \"type\": \"named\",\n                },\n                {\n                  \"args\": undefined,\n                  \"method\": \"handle\",\n                  \"moduleNameOrPath\": \"signed\",\n                  \"name\": \"signed\",\n                  \"type\": \"named\",\n                },\n                {\n                  \"args\": undefined,\n                  \"method\": \"handle\",\n                  \"moduleNameOrPath\": \"throttle\",\n                  \"name\": \"throttle\",\n                  \"type\": \"named\",\n                },\n              ],\n              \"name\": \"\",\n              \"pattern\": \"/payments\",\n            },\n            {\n              \"handler\": {\n                \"args\": \"/articles\",\n                \"name\": \"redirectsToRoute\",\n                \"type\": \"closure\",\n              },\n              \"methods\": [\n                \"GET\",\n                \"HEAD\",\n              ],\n              \"middleware\": [],\n              \"name\": \"\",\n              \"pattern\": \"/blog\",\n            },\n          ],\n        },\n        {\n          \"domain\": \"blog.adonisjs.com\",\n          \"routes\": [\n            {\n              \"handler\": {\n                \"method\": \"index\",\n                \"moduleNameOrPath\": \"#controllers/articles_controller\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"GET\",\n                \"HEAD\",\n              ],\n              \"middleware\": [],\n              \"name\": \"articles\",\n              \"pattern\": \"/articles\",\n            },\n            {\n              \"handler\": {\n                \"method\": \"show\",\n                \"moduleNameOrPath\": \"#controllers/articles_controller\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"GET\",\n                \"HEAD\",\n              ],\n              \"middleware\": [],\n              \"name\": \"articles.show\",\n              \"pattern\": \"/articles/:id/:slug?\",\n            },\n          ],\n        },\n      ]\n    `)\n  })\n\n  test('format routes as ANSI list', async ({ assert, fs }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(fs.baseUrl)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n    await registerRoutes(app)\n\n    const cliUi = createAceKernel(app).ui\n    cliUi.switchMode('silent')\n\n    const router = await app.container.make('router')\n    const formatter = new RoutesListFormatter(\n      router,\n      cliUi,\n      {\n        maxPrettyPrintWidth: 100,\n      },\n      {}\n    )\n\n    assert.deepEqual(await formatter.formatAsAnsiList(), [\n      {\n        heading: '',\n        rows: [\n          `METHOD ROUTE ................................................... HANDLER                  MIDDLEWARE`,\n          `GET    / ....................................................... closure                            `,\n          `GET    /files/:directory/* ..................................... closure                            `,\n          `GET    /home (home) ................ #controllers/home_controller.handle                            `,\n          `GET    /about (about) ........................... AboutController.handle                     closure`,\n          `POST   /contact (contact.store) . #controllers/contacts_controller.store                            `,\n          `GET    /contact (contact.create)  #controllers/contacts_controller.crea…                            `,\n          `GET    /users (users) ........................... UsersController.handle auth, canViewUsers, closure`,\n          `GET    /payments ................ #controllers/payments_controller.index       auth, acl, and 2 more`,\n          `GET    /blog ..............................  redirectsToRoute(/articles)                            `,\n        ],\n      },\n      {\n        heading:\n          '.. blog.adonisjs.com ...............................................................................',\n        rows: [\n          `METHOD ROUTE .................................................................... HANDLER MIDDLEWARE`,\n          `GET    /articles (articles) ...................... #controllers/articles_controller.index           `,\n          `GET    /articles/:id/:slug? (articles.show) ....... #controllers/articles_controller.show           `,\n        ],\n      },\n    ])\n  })\n\n  test('format routes as ANSI table', async ({ assert, fs }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(fs.baseUrl)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n    await registerRoutes(app)\n\n    const cliUi = createAceKernel(app).ui\n    cliUi.switchMode('raw')\n\n    const router = await app.container.make('router')\n    const formatter = new RoutesListFormatter(\n      router,\n      cliUi,\n      {\n        maxPrettyPrintWidth: 100,\n      },\n      {}\n    )\n\n    const tables = await formatter.formatAsAnsiTable()\n    tables[0].table.render()\n\n    assert.deepEqual(cliUi.logger.getLogs(), [\n      {\n        message: 'dim(METHOD)|dim(ROUTE)|dim(HANDLER)|dim(MIDDLEWARE)',\n        stream: 'stdout',\n      },\n      {\n        message: `dim(GET)|/ | cyan(closure)|dim()`,\n        stream: 'stdout',\n      },\n      {\n        message: `dim(GET)|/files/yellow(:directory)/red(*) | cyan(closure)|dim()`,\n        stream: 'stdout',\n      },\n      {\n        message: `dim(GET)|/home dim((home)) | cyan(#controllers/home_controller).cyan(handle)|dim()`,\n        stream: 'stdout',\n      },\n      {\n        message: `dim(GET)|/about dim((about)) | cyan(AboutController).cyan(handle)|dim(closure)`,\n        stream: 'stdout',\n      },\n      {\n        message: `dim(POST)|/contact dim((contact.store)) | cyan(#controllers/contacts_controller).cyan(store)|dim()`,\n        stream: 'stdout',\n      },\n      {\n        message: `dim(GET)|/contact dim((contact.create)) | cyan(#controllers/contacts_controller).cyan(create)|dim()`,\n        stream: 'stdout',\n      },\n      {\n        message: `dim(GET)|/users dim((users)) | cyan(UsersController).cyan(handle)|dim(auth, canViewUsers, closure)`,\n        stream: 'stdout',\n      },\n      {\n        message: `dim(GET)|/payments | cyan(#controllers/payments_controller).cyan(index)|dim(auth, acl, signed, throttle)`,\n        stream: 'stdout',\n      },\n      {\n        message: `dim(GET)|/blog |  cyan(redirectsToRoute)dim((/articles))|dim()`,\n        stream: 'stdout',\n      },\n    ])\n  })\n})\n\ntest.group('Formatters | List routes | toJSONL', () => {\n  test('format routes as JSONL', async ({ assert, fs }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(fs.baseUrl)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n    await registerRoutes(app)\n\n    const router = await app.container.make('router')\n    const formatter = new RoutesListFormatter(router, createAceKernel(app).ui, {}, {})\n    const lines = await formatter.formatAsJSONL()\n    const parsed = lines.map((line) => JSON.parse(line))\n\n    assert.snapshot(parsed).matchInline(`\n      [\n        {\n          \"handler\": {\n            \"name\": \"closure\",\n            \"type\": \"closure\",\n          },\n          \"method\": \"GET\",\n          \"pattern\": \"/\",\n        },\n        {\n          \"handler\": {\n            \"name\": \"closure\",\n            \"type\": \"closure\",\n          },\n          \"method\": \"GET\",\n          \"pattern\": \"/files/:directory/*\",\n        },\n        {\n          \"handler\": {\n            \"method\": \"handle\",\n            \"module\": \"#controllers/home_controller\",\n            \"type\": \"controller\",\n          },\n          \"method\": \"GET\",\n          \"name\": \"home\",\n          \"pattern\": \"/home\",\n        },\n        {\n          \"handler\": {\n            \"method\": \"handle\",\n            \"module\": \"AboutController\",\n            \"type\": \"controller\",\n          },\n          \"method\": \"GET\",\n          \"middleware\": [\n            \"closure\",\n          ],\n          \"name\": \"about\",\n          \"pattern\": \"/about\",\n        },\n        {\n          \"handler\": {\n            \"method\": \"store\",\n            \"module\": \"#controllers/contacts_controller\",\n            \"type\": \"controller\",\n          },\n          \"method\": \"POST\",\n          \"name\": \"contact.store\",\n          \"pattern\": \"/contact\",\n        },\n        {\n          \"handler\": {\n            \"method\": \"create\",\n            \"module\": \"#controllers/contacts_controller\",\n            \"type\": \"controller\",\n          },\n          \"method\": \"GET\",\n          \"name\": \"contact.create\",\n          \"pattern\": \"/contact\",\n        },\n        {\n          \"handler\": {\n            \"method\": \"handle\",\n            \"module\": \"UsersController\",\n            \"type\": \"controller\",\n          },\n          \"method\": \"GET\",\n          \"middleware\": [\n            \"auth\",\n            \"canViewUsers\",\n            \"closure\",\n          ],\n          \"name\": \"users\",\n          \"pattern\": \"/users\",\n        },\n        {\n          \"handler\": {\n            \"method\": \"index\",\n            \"module\": \"#controllers/payments_controller\",\n            \"type\": \"controller\",\n          },\n          \"method\": \"GET\",\n          \"middleware\": [\n            \"auth\",\n            \"acl\",\n            \"signed\",\n            \"throttle\",\n          ],\n          \"pattern\": \"/payments\",\n        },\n        {\n          \"handler\": {\n            \"args\": \"/articles\",\n            \"name\": \"redirectsToRoute\",\n            \"type\": \"redirect\",\n          },\n          \"method\": \"GET\",\n          \"pattern\": \"/blog\",\n        },\n        {\n          \"domain\": \"blog.adonisjs.com\",\n          \"handler\": {\n            \"method\": \"index\",\n            \"module\": \"#controllers/articles_controller\",\n            \"type\": \"controller\",\n          },\n          \"method\": \"GET\",\n          \"name\": \"articles\",\n          \"pattern\": \"/articles\",\n        },\n        {\n          \"domain\": \"blog.adonisjs.com\",\n          \"handler\": {\n            \"method\": \"show\",\n            \"module\": \"#controllers/articles_controller\",\n            \"type\": \"controller\",\n          },\n          \"method\": \"GET\",\n          \"name\": \"articles.show\",\n          \"pattern\": \"/articles/:id/:slug?\",\n        },\n      ]\n    `)\n  })\n\n  test('each line is valid JSON', async ({ assert, fs }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(fs.baseUrl)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n    await registerRoutes(app)\n\n    const router = await app.container.make('router')\n    const formatter = new RoutesListFormatter(router, createAceKernel(app).ui, {}, {})\n    const lines = await formatter.formatAsJSONL()\n\n    for (const line of lines) {\n      assert.doesNotThrow(() => JSON.parse(line))\n    }\n  })\n\n  test('omits name, domain, and middleware when empty or default', async ({ assert, fs }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(fs.baseUrl)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n    await registerRoutes(app)\n\n    const router = await app.container.make('router')\n    const formatter = new RoutesListFormatter(router, createAceKernel(app).ui, {}, {})\n    const lines = await formatter.formatAsJSONL()\n\n    /**\n     * The root closure route \"/\" has no name, no middleware, and root domain.\n     * None of those keys should be present.\n     */\n    const rootRoute = JSON.parse(lines[0])\n    assert.notProperty(rootRoute, 'name')\n    assert.notProperty(rootRoute, 'domain')\n    assert.notProperty(rootRoute, 'middleware')\n  })\n\n  test('includes domain for non-root routes', async ({ assert, fs }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(fs.baseUrl)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n    await registerRoutes(app)\n\n    const router = await app.container.make('router')\n    const formatter = new RoutesListFormatter(router, createAceKernel(app).ui, {}, {})\n    const lines = await formatter.formatAsJSONL()\n    const parsed = lines.map((line) => JSON.parse(line))\n\n    const domainRoutes = parsed.filter((r) => r.domain === 'blog.adonisjs.com')\n    assert.lengthOf(domainRoutes, 2)\n  })\n\n  test('respects filters', async ({ assert, fs }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(fs.baseUrl)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n    await registerRoutes(app)\n\n    const router = await app.container.make('router')\n    const formatter = new RoutesListFormatter(\n      router,\n      createAceKernel(app).ui,\n      {},\n      { middleware: ['auth'] }\n    )\n    const lines = await formatter.formatAsJSONL()\n    const parsed = lines.map((line) => JSON.parse(line))\n\n    assert.isTrue(parsed.every((r) => r.middleware && r.middleware.includes('auth')))\n  })\n})\n\ntest.group('Formatters | List routes | filters', () => {\n  test('show routes that has one or more middleware', async ({ assert, fs }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(fs.baseUrl)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n    await registerRoutes(app)\n\n    const router = await app.container.make('router')\n    const formatter = new RoutesListFormatter(\n      router,\n      createAceKernel(app).ui,\n      {},\n      {\n        middleware: ['*'],\n      }\n    )\n\n    assert.snapshot(await formatter.formatAsJSON()).matchInline(`\n      [\n        {\n          \"domain\": \"root\",\n          \"routes\": [\n            {\n              \"handler\": {\n                \"method\": \"handle\",\n                \"moduleNameOrPath\": \"AboutController\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"GET\",\n              ],\n              \"middleware\": [\n                {\n                  \"name\": \"closure\",\n                  \"type\": \"closure\",\n                },\n              ],\n              \"name\": \"about\",\n              \"pattern\": \"/about\",\n            },\n            {\n              \"handler\": {\n                \"method\": \"handle\",\n                \"moduleNameOrPath\": \"UsersController\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"GET\",\n              ],\n              \"middleware\": [\n                {\n                  \"args\": undefined,\n                  \"method\": \"handle\",\n                  \"moduleNameOrPath\": \"auth\",\n                  \"name\": \"auth\",\n                  \"type\": \"named\",\n                },\n                {\n                  \"name\": \"canViewUsers\",\n                  \"type\": \"closure\",\n                },\n                {\n                  \"name\": \"closure\",\n                  \"type\": \"closure\",\n                },\n              ],\n              \"name\": \"users\",\n              \"pattern\": \"/users\",\n            },\n            {\n              \"handler\": {\n                \"method\": \"index\",\n                \"moduleNameOrPath\": \"#controllers/payments_controller\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"GET\",\n              ],\n              \"middleware\": [\n                {\n                  \"args\": undefined,\n                  \"method\": \"handle\",\n                  \"moduleNameOrPath\": \"auth\",\n                  \"name\": \"auth\",\n                  \"type\": \"named\",\n                },\n                {\n                  \"args\": undefined,\n                  \"method\": \"handle\",\n                  \"moduleNameOrPath\": \"#middleware/acl_middleware\",\n                  \"name\": \"acl\",\n                  \"type\": \"named\",\n                },\n                {\n                  \"args\": undefined,\n                  \"method\": \"handle\",\n                  \"moduleNameOrPath\": \"signed\",\n                  \"name\": \"signed\",\n                  \"type\": \"named\",\n                },\n                {\n                  \"args\": undefined,\n                  \"method\": \"handle\",\n                  \"moduleNameOrPath\": \"throttle\",\n                  \"name\": \"throttle\",\n                  \"type\": \"named\",\n                },\n              ],\n              \"name\": \"\",\n              \"pattern\": \"/payments\",\n            },\n          ],\n        },\n        {\n          \"domain\": \"blog.adonisjs.com\",\n          \"routes\": [],\n        },\n      ]\n    `)\n  })\n\n  test('show routes that has zero middleware', async ({ assert, fs }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(fs.baseUrl)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n    await registerRoutes(app)\n\n    const router = await app.container.make('router')\n    const formatter = new RoutesListFormatter(\n      router,\n      createAceKernel(app).ui,\n      {},\n      {\n        ignoreMiddleware: ['*'],\n      }\n    )\n\n    assert.deepEqual(await formatter.formatAsJSON(), [\n      {\n        domain: 'root',\n        routes: [\n          {\n            name: '',\n            pattern: '/',\n            methods: ['GET'],\n            handler: {\n              type: 'closure',\n              name: 'closure',\n              args: undefined,\n            },\n            middleware: [],\n          },\n          {\n            name: '',\n            pattern: '/files/:directory/*',\n            methods: ['GET'],\n            handler: {\n              type: 'closure',\n              name: 'closure',\n              args: undefined,\n            },\n            middleware: [],\n          },\n          {\n            name: 'home',\n            pattern: '/home',\n            methods: ['GET'],\n            handler: {\n              type: 'controller',\n              moduleNameOrPath: '#controllers/home_controller',\n              method: 'handle',\n            },\n            middleware: [],\n          },\n          {\n            name: 'contact.store',\n            pattern: '/contact',\n            methods: ['POST'],\n            handler: {\n              type: 'controller',\n              moduleNameOrPath: '#controllers/contacts_controller',\n              method: 'store',\n            },\n            middleware: [],\n          },\n          {\n            name: 'contact.create',\n            pattern: '/contact',\n            methods: ['GET'],\n            handler: {\n              type: 'controller',\n              moduleNameOrPath: '#controllers/contacts_controller',\n              method: 'create',\n            },\n            middleware: [],\n          },\n          {\n            handler: {\n              args: '/articles',\n              name: 'redirectsToRoute',\n              type: 'closure',\n            },\n            methods: ['GET'],\n            middleware: [],\n            name: '',\n            pattern: '/blog',\n          },\n        ],\n      },\n      {\n        domain: 'blog.adonisjs.com',\n        routes: [\n          {\n            pattern: '/articles',\n            name: 'articles',\n            methods: ['GET'],\n            handler: {\n              type: 'controller',\n              moduleNameOrPath: '#controllers/articles_controller',\n              method: 'index',\n            },\n            middleware: [],\n          },\n          {\n            pattern: '/articles/:id/:slug?',\n            name: 'articles.show',\n            methods: ['GET'],\n            handler: {\n              type: 'controller',\n              moduleNameOrPath: '#controllers/articles_controller',\n              method: 'show',\n            },\n            middleware: [],\n          },\n        ],\n      },\n    ])\n  })\n\n  test('show routes that has specific middleware', async ({ assert, fs }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(fs.baseUrl)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n    await registerRoutes(app)\n\n    const router = await app.container.make('router')\n    const formatter = new RoutesListFormatter(\n      router,\n      createAceKernel(app).ui,\n      {},\n      {\n        middleware: ['auth'],\n      }\n    )\n\n    assert.snapshot(await formatter.formatAsJSON()).matchInline(`\n      [\n        {\n          \"domain\": \"root\",\n          \"routes\": [\n            {\n              \"handler\": {\n                \"method\": \"handle\",\n                \"moduleNameOrPath\": \"UsersController\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"GET\",\n              ],\n              \"middleware\": [\n                {\n                  \"args\": undefined,\n                  \"method\": \"handle\",\n                  \"moduleNameOrPath\": \"auth\",\n                  \"name\": \"auth\",\n                  \"type\": \"named\",\n                },\n                {\n                  \"name\": \"canViewUsers\",\n                  \"type\": \"closure\",\n                },\n                {\n                  \"name\": \"closure\",\n                  \"type\": \"closure\",\n                },\n              ],\n              \"name\": \"users\",\n              \"pattern\": \"/users\",\n            },\n            {\n              \"handler\": {\n                \"method\": \"index\",\n                \"moduleNameOrPath\": \"#controllers/payments_controller\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"GET\",\n              ],\n              \"middleware\": [\n                {\n                  \"args\": undefined,\n                  \"method\": \"handle\",\n                  \"moduleNameOrPath\": \"auth\",\n                  \"name\": \"auth\",\n                  \"type\": \"named\",\n                },\n                {\n                  \"args\": undefined,\n                  \"method\": \"handle\",\n                  \"moduleNameOrPath\": \"#middleware/acl_middleware\",\n                  \"name\": \"acl\",\n                  \"type\": \"named\",\n                },\n                {\n                  \"args\": undefined,\n                  \"method\": \"handle\",\n                  \"moduleNameOrPath\": \"signed\",\n                  \"name\": \"signed\",\n                  \"type\": \"named\",\n                },\n                {\n                  \"args\": undefined,\n                  \"method\": \"handle\",\n                  \"moduleNameOrPath\": \"throttle\",\n                  \"name\": \"throttle\",\n                  \"type\": \"named\",\n                },\n              ],\n              \"name\": \"\",\n              \"pattern\": \"/payments\",\n            },\n          ],\n        },\n        {\n          \"domain\": \"blog.adonisjs.com\",\n          \"routes\": [],\n        },\n      ]\n    `)\n  })\n\n  test('combine middleware and ignoreMiddleware filters', async ({ assert, fs }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(fs.baseUrl)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n    await registerRoutes(app)\n\n    const router = await app.container.make('router')\n    const formatter = new RoutesListFormatter(\n      router,\n      createAceKernel(app).ui,\n      {},\n      {\n        middleware: ['auth'],\n        ignoreMiddleware: ['acl'],\n      }\n    )\n\n    assert.snapshot(await formatter.formatAsJSON()).matchInline(`\n      [\n        {\n          \"domain\": \"root\",\n          \"routes\": [\n            {\n              \"handler\": {\n                \"method\": \"handle\",\n                \"moduleNameOrPath\": \"UsersController\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"GET\",\n              ],\n              \"middleware\": [\n                {\n                  \"args\": undefined,\n                  \"method\": \"handle\",\n                  \"moduleNameOrPath\": \"auth\",\n                  \"name\": \"auth\",\n                  \"type\": \"named\",\n                },\n                {\n                  \"name\": \"canViewUsers\",\n                  \"type\": \"closure\",\n                },\n                {\n                  \"name\": \"closure\",\n                  \"type\": \"closure\",\n                },\n              ],\n              \"name\": \"users\",\n              \"pattern\": \"/users\",\n            },\n          ],\n        },\n        {\n          \"domain\": \"blog.adonisjs.com\",\n          \"routes\": [],\n        },\n      ]\n    `)\n  })\n\n  test('show routes by controller name', async ({ assert, fs }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(fs.baseUrl)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n    await registerRoutes(app)\n\n    const router = await app.container.make('router')\n    const formatter = new RoutesListFormatter(\n      router,\n      createAceKernel(app).ui,\n      {},\n      {\n        middleware: ['auth'],\n        match: 'UsersController',\n      }\n    )\n\n    assert.snapshot(await formatter.formatAsJSON()).matchInline(`\n      [\n        {\n          \"domain\": \"root\",\n          \"routes\": [\n            {\n              \"handler\": {\n                \"method\": \"handle\",\n                \"moduleNameOrPath\": \"UsersController\",\n                \"type\": \"controller\",\n              },\n              \"methods\": [\n                \"GET\",\n              ],\n              \"middleware\": [\n                {\n                  \"args\": undefined,\n                  \"method\": \"handle\",\n                  \"moduleNameOrPath\": \"auth\",\n                  \"name\": \"auth\",\n                  \"type\": \"named\",\n                },\n                {\n                  \"name\": \"canViewUsers\",\n                  \"type\": \"closure\",\n                },\n                {\n                  \"name\": \"closure\",\n                  \"type\": \"closure\",\n                },\n              ],\n              \"name\": \"users\",\n              \"pattern\": \"/users\",\n            },\n          ],\n        },\n        {\n          \"domain\": \"blog.adonisjs.com\",\n          \"routes\": [],\n        },\n      ]\n    `)\n  })\n\n  test('show routes by route name', async ({ assert, fs }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(fs.baseUrl)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n    await registerRoutes(app)\n\n    const router = await app.container.make('router')\n    const formatter = new RoutesListFormatter(\n      router,\n      createAceKernel(app).ui,\n      {},\n      {\n        middleware: ['auth'],\n        match: 'contact.',\n      }\n    )\n\n    assert.deepEqual(await formatter.formatAsJSON(), [\n      {\n        domain: 'root',\n        routes: [\n          {\n            name: 'contact.store',\n            pattern: '/contact',\n            methods: ['POST'],\n            handler: {\n              type: 'controller',\n              moduleNameOrPath: '#controllers/contacts_controller',\n              method: 'store',\n            },\n            middleware: [],\n          },\n          {\n            name: 'contact.create',\n            pattern: '/contact',\n            methods: ['GET'],\n            handler: {\n              type: 'controller',\n              moduleNameOrPath: '#controllers/contacts_controller',\n              method: 'create',\n            },\n            middleware: [],\n          },\n        ],\n      },\n      {\n        domain: 'blog.adonisjs.com',\n        routes: [],\n      },\n    ])\n  })\n\n  test('show routes by pattern name', async ({ assert, fs }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(fs.baseUrl)\n\n    const app = ignitor.createApp('console')\n    await app.init()\n    await app.boot()\n    await registerRoutes(app)\n\n    const router = await app.container.make('router')\n    const formatter = new RoutesListFormatter(\n      router,\n      createAceKernel(app).ui,\n      {},\n      {\n        middleware: ['auth'],\n        match: '/contact',\n      }\n    )\n\n    assert.deepEqual(await formatter.formatAsJSON(), [\n      {\n        domain: 'root',\n        routes: [\n          {\n            name: 'contact.store',\n            pattern: '/contact',\n            methods: ['POST'],\n            handler: {\n              type: 'controller',\n              moduleNameOrPath: '#controllers/contacts_controller',\n              method: 'store',\n            },\n            middleware: [],\n          },\n          {\n            name: 'contact.create',\n            pattern: '/contact',\n            methods: ['GET'],\n            handler: {\n              type: 'controller',\n              moduleNameOrPath: '#controllers/contacts_controller',\n              method: 'create',\n            },\n            middleware: [],\n          },\n        ],\n      },\n      {\n        domain: 'blog.adonisjs.com',\n        routes: [],\n      },\n    ])\n  })\n})\n"
  },
  {
    "path": "tests/commands/add.spec.ts",
    "content": "/*\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 { test } from '@japa/runner'\nimport { ListLoader } from '@adonisjs/ace'\n\nimport Add from '../../commands/add.ts'\nimport Configure from '../../commands/configure.ts'\nimport { AceFactory } from '../../factories/core/ace.ts'\nimport { setupPackage, setupNamedPackage, setupProject } from '../helpers.ts'\n\nconst VERBOSE = !!process.env.CI\nconst createFileImporter = (baseUrl: URL) => {\n  return function (folder: string) {\n    return import(new URL(`${folder}/index.js?${Math.random()}`, baseUrl).toString())\n  }\n}\n\ntest.group('Install', (group) => {\n  group.tap((t) => t.disableTimeout())\n\n  test('install packages using npm', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: createFileImporter(fs.baseUrl),\n    })\n\n    await setupProject(fs, 'npm')\n    await setupPackage(fs)\n\n    await ace.app.init()\n\n    ace.addLoader(new ListLoader([Configure]))\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Add, ['./packages/foo'])\n    command.verbose = VERBOSE\n\n    await command.exec()\n\n    await assert.fileIsNotEmpty('package-lock.json')\n  })\n\n  test('install package using pnpm', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: createFileImporter(fs.baseUrl),\n    })\n\n    await setupProject(fs, 'pnpm')\n    await setupPackage(fs)\n\n    await ace.app.init()\n\n    ace.addLoader(new ListLoader([Configure]))\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Add, ['./packages/foo'])\n    command.verbose = VERBOSE\n\n    await command.exec()\n\n    await assert.fileIsNotEmpty('pnpm-lock.yaml')\n  })\n\n  test('explicitly set the package manager to pnpm', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: createFileImporter(fs.baseUrl),\n    })\n\n    await setupProject(fs, 'npm')\n    await setupPackage(fs)\n\n    await ace.app.init()\n\n    ace.addLoader(new ListLoader([Configure]))\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Add, ['./packages/foo'])\n    command.verbose = VERBOSE\n    command.packageManager = 'pnpm'\n\n    await command.exec()\n\n    await assert.fileIsNotEmpty('pnpm-lock.yaml')\n  })\n\n  test('install dependencies', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: createFileImporter(fs.baseUrl),\n    })\n\n    await setupProject(fs, 'npm')\n    await setupPackage(fs)\n\n    await ace.app.init()\n\n    ace.addLoader(new ListLoader([Configure]))\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Add, ['./packages/foo'])\n    command.verbose = VERBOSE\n\n    await command.exec()\n\n    await assert.fileContains('package.json', '@adonisjs/foo')\n  })\n\n  test('install dev dependencies', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: createFileImporter(fs.baseUrl),\n    })\n\n    await setupProject(fs, 'npm')\n    await setupPackage(fs)\n\n    await ace.app.init()\n\n    ace.addLoader(new ListLoader([Configure]))\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Add, ['./packages/foo', '-D'])\n    command.verbose = VERBOSE\n\n    await command.exec()\n\n    const pkgJson = await fs.contentsJson('package.json')\n    assert.deepEqual(pkgJson.devDependencies, { '@adonisjs/foo': 'file:packages/foo' })\n  })\n\n  test('pass unknown args to configure', async ({ fs, assert }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: createFileImporter(fs.baseUrl),\n    })\n\n    await setupProject(fs, 'npm')\n    await setupPackage(fs, `command.logger.log(command.parsedFlags)`)\n\n    await ace.app.init()\n\n    ace.addLoader(new ListLoader([Configure]))\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Add, ['./packages/foo', '--foo', '--auth=session', '-x'])\n    command.verbose = VERBOSE\n\n    await command.exec()\n\n    const logs = command.logger.getLogs()\n\n    assert.deepInclude(logs, {\n      message: { foo: 'true', auth: 'session', x: 'true', ...(VERBOSE ? { verbose: true } : {}) },\n      stream: 'stdout',\n    })\n  })\n\n  test('configure package', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: createFileImporter(fs.baseUrl),\n    })\n\n    await setupProject(fs, 'npm')\n    await setupPackage(\n      fs,\n      ` const codemods = await command.createCodemods()\n        await codemods.updateRcFile((rcFile) => {\n          rcFile.addProvider('@adonisjs/cache/cache_provider')\n        })`\n    )\n\n    await ace.app.init()\n\n    ace.addLoader(new ListLoader([Configure]))\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Add, ['./packages/foo'])\n    command.verbose = VERBOSE\n\n    await command.exec()\n\n    await assert.fileContains('adonisrc.ts', '@adonisjs/cache/cache_provider')\n  })\n\n  test('display error and stop if package install fail', async ({ fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: createFileImporter(fs.baseUrl),\n    })\n\n    await setupProject(fs, 'npm')\n    await setupPackage(fs)\n\n    await ace.app.init()\n\n    ace.addLoader(new ListLoader([Configure]))\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Add, ['./packages/nonexistent'])\n    command.verbose = VERBOSE\n\n    await command.exec()\n\n    command.assertExitCode(1)\n    command.assertLogMatches(/Process exited with non-zero status/)\n  })\n\n  test('display error if configure command fails', async ({ fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: createFileImporter(fs.baseUrl),\n    })\n\n    await setupProject(fs, 'npm')\n    await setupPackage(fs, 'throw new Error(\"Invalid configure\")')\n\n    await ace.app.init()\n    ace.addLoader(new ListLoader([Configure]))\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Add, ['./packages/foo'])\n    command.verbose = VERBOSE\n    ace.errorHandler.render = async function (error: Error) {\n      command.logger.fatal(error)\n    }\n\n    await command.exec()\n\n    command.assertExitCode(1)\n    command.assertLogMatches(/Unable to configure/)\n  })\n\n  test('configure edge', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => import(filePath),\n    })\n\n    await setupProject(fs, 'npm')\n\n    await ace.app.init()\n    ace.addLoader(new ListLoader([Configure]))\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Add, ['edge'])\n    command.verbose = VERBOSE\n\n    await command.exec()\n\n    await assert.fileContains('package.json', 'edge.js')\n    await assert.fileContains('adonisrc.ts', '@adonisjs/core/providers/edge_provider')\n  })\n\n  test('configure vinejs', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => import(filePath),\n    })\n\n    await setupProject(fs, 'npm')\n\n    await ace.app.init()\n    ace.addLoader(new ListLoader([Configure]))\n\n    const command = await ace.create(Add, ['vinejs'])\n    command.verbose = VERBOSE\n\n    await command.exec()\n\n    await assert.fileContains('package.json', '@vinejs/vine')\n    await assert.fileContains('adonisrc.ts', '@adonisjs/core/providers/vinejs_provider')\n  })\n\n  test('install adonisjs dependencies as next version', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: createFileImporter(fs.baseUrl),\n    })\n\n    await setupProject(fs, 'npm')\n    await setupPackage(fs)\n\n    await ace.app.init()\n\n    ace.addLoader(new ListLoader([Configure]))\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Add, ['@adonisjs/fold'])\n    command.verbose = VERBOSE\n\n    await command.exec()\n    await assert.fileContains('package.json', /\"@adonisjs\\/fold\":\"\\^[\\d.]+/)\n  })\n\n  test('install and configure multiple packages', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: createFileImporter(fs.baseUrl),\n    })\n\n    await setupProject(fs, 'npm')\n    await setupNamedPackage(fs, {\n      name: 'foo',\n      configureContent: `\n        const codemods = await command.createCodemods()\n        await codemods.updateRcFile((rcFile) => {\n          rcFile.addProvider('@adonisjs/foo/foo_provider')\n        })\n      `,\n    })\n    await setupNamedPackage(fs, {\n      name: 'bar',\n      configureContent: `\n        const codemods = await command.createCodemods()\n        await codemods.updateRcFile((rcFile) => {\n          rcFile.addProvider('@adonisjs/bar/bar_provider')\n        })\n      `,\n    })\n\n    await ace.app.init()\n\n    ace.addLoader(new ListLoader([Configure]))\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Add, ['./packages/foo', './packages/bar'])\n    command.verbose = VERBOSE\n\n    await command.exec()\n\n    command.assertExitCode(0)\n    await assert.fileContains('package.json', '@adonisjs/foo')\n    await assert.fileContains('package.json', '@adonisjs/bar')\n    await assert.fileContains('adonisrc.ts', '@adonisjs/foo/foo_provider')\n    await assert.fileContains('adonisrc.ts', '@adonisjs/bar/bar_provider')\n    command.assertLogMatches(/Installed and configured/)\n  })\n\n  test('continue configuring other packages when one fails', async ({ fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: createFileImporter(fs.baseUrl),\n    })\n\n    await setupProject(fs, 'npm')\n    await setupNamedPackage(fs, {\n      name: 'foo',\n      configureContent: `throw new Error(\"Configure failed\")`,\n    })\n    await setupNamedPackage(fs, {\n      name: 'bar',\n      configureContent: `\n        const codemods = await command.createCodemods()\n        await codemods.updateRcFile((rcFile) => {\n          rcFile.addProvider('@adonisjs/bar/bar_provider')\n        })\n      `,\n    })\n\n    await ace.app.init()\n\n    ace.addLoader(new ListLoader([Configure]))\n    ace.ui.switchMode('raw')\n    ace.errorHandler.render = async () => {}\n\n    const command = await ace.create(Add, ['./packages/foo', './packages/bar'])\n    command.verbose = VERBOSE\n\n    await command.exec()\n\n    command.assertExitCode(1)\n    command.assertLogMatches(/Unable to configure.*foo/)\n    command.assertLogMatches(/Installed and configured.*bar/)\n  })\n\n  test('pass unknown flags to all configure commands', async ({ fs, assert }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: createFileImporter(fs.baseUrl),\n    })\n\n    await setupProject(fs, 'npm')\n    await setupNamedPackage(fs, {\n      name: 'foo',\n      configureContent: `command.logger.log({ pkg: 'foo', flags: command.parsedFlags })`,\n    })\n    await setupNamedPackage(fs, {\n      name: 'bar',\n      configureContent: `command.logger.log({ pkg: 'bar', flags: command.parsedFlags })`,\n    })\n\n    await ace.app.init()\n\n    ace.addLoader(new ListLoader([Configure]))\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Add, ['./packages/foo', './packages/bar', '--auth=session'])\n    command.verbose = VERBOSE\n\n    await command.exec()\n\n    const logs = command.logger.getLogs()\n    const fooLog = logs.find((log: any) => log.message?.pkg === 'foo')\n    const barLog = logs.find((log: any) => log.message?.pkg === 'bar')\n\n    assert.equal((fooLog?.message as any)?.flags?.auth, 'session')\n    assert.equal((barLog?.message as any)?.flags?.auth, 'session')\n  })\n})\n"
  },
  {
    "path": "tests/commands/build.spec.ts",
    "content": "/*\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 ts from 'typescript'\nimport { execa } from 'execa'\nimport { test } from '@japa/runner'\nimport Build from '../../commands/build.ts'\nimport { AceFactory } from '../../factories/core/ace.ts'\n\ntest.group('Build command', (group) => {\n  group.tap((t) => t.timeout(30 * 1000))\n\n  test('show error when assembler is not installed', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        if (filePath === '@adonisjs/assembler') {\n          return import(new URL(filePath, fs.baseUrl).href)\n        }\n\n        return import(filePath)\n      },\n    })\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Build, [])\n    await command.exec()\n\n    assert.equal(command.exitCode, 1)\n    assert.lengthOf(ace.ui.logger.getLogs(), 1)\n    assert.equal(ace.ui.logger.getLogs()[0].stream, 'stderr')\n    assert.match(ace.ui.logger.getLogs()[0].message, /Cannot find package \"@adonisjs\\/assembler/)\n  })\n\n  test('show error when typescript is not installed', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        if (filePath === 'typescript') {\n          return import(new URL(filePath, fs.baseUrl).href)\n        }\n\n        return import(filePath)\n      },\n    })\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Build, [])\n    await command.exec()\n\n    assert.equal(command.exitCode, 1)\n    assert.lengthOf(ace.ui.logger.getLogs(), 1)\n    assert.equal(ace.ui.logger.getLogs()[0].stream, 'stderr')\n    assert.match(ace.ui.logger.getLogs()[0].message, /Cannot find package \"typescript/)\n  })\n\n  test('fail when tsconfig file is missing', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        return import(filePath)\n      },\n    })\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Build, [])\n    await command.exec()\n\n    assert.equal(command.exitCode, 1)\n  })\n\n  test('build project inside build directory', async ({ assert, fs }) => {\n    await fs.create(\n      'tsconfig.json',\n      JSON.stringify({\n        include: ['**/*'],\n        compilerOptions: { skipLibCheck: true },\n        exclude: [],\n      })\n    )\n\n    await fs.create('adonisrc.ts', `export default {}`)\n    await fs.create('index.ts', '')\n    await fs.create(\n      'package.json',\n      JSON.stringify({\n        name: 'app',\n        dependencies: {\n          typescript: ts.version,\n        },\n      })\n    )\n\n    await execa('npm', ['install'], {\n      cwd: fs.basePath,\n      stdio: 'inherit',\n    })\n\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        return import(filePath)\n      },\n    })\n\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Build, [])\n    await command.exec()\n\n    assert.equal(command.exitCode, 0)\n\n    await assert.fileExists('build/index.js')\n    await assert.fileExists('build/adonisrc.js')\n  })\n\n  test('do not output when typescript build has errors', async ({ assert, fs }) => {\n    await fs.create(\n      'tsconfig.json',\n      JSON.stringify({\n        include: ['**/*'],\n        exclude: [],\n        compilerOptions: {\n          target: 'ESNext',\n          module: 'NodeNext',\n          lib: ['ESNext'],\n          strict: true,\n          noUnusedLocals: true,\n        },\n      })\n    )\n\n    await fs.create('adonisrc.ts', `export default {}`)\n    await fs.create('index.ts', 'const foo = `a`')\n    await fs.create(\n      'package.json',\n      JSON.stringify({\n        name: 'app',\n        dependencies: {\n          typescript: ts.version,\n        },\n      })\n    )\n\n    await execa('npm', ['install'], {\n      cwd: fs.basePath,\n      stdio: 'inherit',\n    })\n\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        return import(filePath)\n      },\n    })\n\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Build, [])\n    await command.exec()\n\n    assert.equal(command.exitCode, 1)\n    await assert.fileNotExists('build/index.js')\n  })\n\n  test('output with --ignore-ts-errors flags when typescript build has errors', async ({\n    assert,\n    fs,\n  }) => {\n    await fs.create(\n      'tsconfig.json',\n      JSON.stringify({\n        include: ['**/*'],\n        exclude: [],\n        compilerOptions: {\n          target: 'ESNext',\n          module: 'NodeNext',\n          lib: ['ESNext'],\n          strict: true,\n          noUnusedLocals: true,\n        },\n      })\n    )\n\n    await fs.create('adonisrc.ts', `export default {}`)\n    await fs.create('index.ts', 'const foo = `a`')\n    await fs.create(\n      'package.json',\n      JSON.stringify({\n        name: 'app',\n        dependencies: {\n          typescript: ts.version,\n        },\n      })\n    )\n\n    await execa('npm', ['install'], {\n      cwd: fs.basePath,\n      stdio: 'inherit',\n    })\n\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        return import(filePath)\n      },\n    })\n\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Build, [])\n    command.ignoreTsErrors = true\n    await command.exec()\n\n    assert.equal(command.exitCode, 0)\n    await assert.fileExists('build/index.js')\n    await assert.fileExists('build/adonisrc.js')\n  })\n\n  test('do not attempt to build assets when assets bundler is not configured', async ({\n    assert,\n    fs,\n  }) => {\n    await fs.create(\n      'tsconfig.json',\n      JSON.stringify({\n        include: ['**/*'],\n        exclude: [],\n        compilerOptions: {\n          target: 'ESNext',\n          module: 'NodeNext',\n          lib: ['ESNext'],\n          strict: true,\n          noUnusedLocals: true,\n        },\n      })\n    )\n\n    await fs.create('adonisrc.ts', `export default {}`)\n    await fs.create('index.ts', '')\n\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        return import(filePath)\n      },\n    })\n\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Build, [])\n    await command.exec()\n\n    assert.equal(command.exitCode, 0)\n    assert.notExists(\n      ace.ui.logger.getLogs().find((log) => {\n        return log.message.match(/compiling frontend assets/)\n      })\n    )\n  })\n\n  test('correctly pass hooks to the bundler', async ({ assert, fs }) => {\n    assert.plan(2)\n\n    await fs.create(\n      'tsconfig.json',\n      JSON.stringify({\n        include: ['**/*'],\n        exclude: [],\n        compilerOptions: {\n          target: 'ESNext',\n          module: 'NodeNext',\n          lib: ['ESNext'],\n          strict: true,\n          noUnusedLocals: true,\n        },\n      })\n    )\n\n    await fs.create('adonisrc.ts', `export default {}`)\n    await fs.create('index.ts', '')\n\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        return import(filePath)\n      },\n    })\n\n    ace.app.rcFile.hooks = {\n      buildFinished: [\n        async () => ({\n          default: async () => {\n            assert.isTrue(true)\n          },\n        }),\n      ],\n      buildStarting: [\n        async () => ({\n          default: async () => {\n            assert.isTrue(true)\n          },\n        }),\n      ],\n    }\n\n    ace.ui.switchMode('normal')\n\n    const command = await ace.create(Build, [])\n    await command.exec()\n  })\n})\n"
  },
  {
    "path": "tests/commands/configure.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { fileURLToPath } from 'node:url'\nimport Configure from '../../commands/configure.ts'\nimport { AceFactory } from '../../factories/core/ace.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\nconst BASE_PATH = fileURLToPath(BASE_URL)\n\ntest.group('Configure command | list dependencies', (group) => {\n  group.each.disableTimeout()\n\n  test('list development dependencies to install', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Configure, ['../dummy-pkg.js'])\n    command.stubsRoot = join(fs.basePath, 'stubs')\n\n    const codemods = await command.createCodemods()\n    await codemods.listPackagesToInstall([\n      {\n        name: '@japa/runner',\n        isDevDependency: true,\n      },\n      {\n        name: '@japa/preset-adonis',\n        isDevDependency: true,\n      },\n      {\n        name: 'playwright',\n        isDevDependency: true,\n      },\n    ])\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: ['Please install following packages'].join('\\n'),\n        stream: 'stdout',\n      },\n      {\n        message: ['yellow(npm i -D) @japa/runner @japa/preset-adonis playwright'].join('\\n'),\n        stream: 'stdout',\n      },\n      {\n        message: [''].join('\\n'),\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('list development and prod dependencies to install', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Configure, ['../dummy-pkg.js'])\n    command.stubsRoot = join(fs.basePath, 'stubs')\n\n    const codemods = await command.createCodemods()\n    await codemods.listPackagesToInstall([\n      {\n        name: '@japa/runner',\n        isDevDependency: true,\n      },\n      {\n        name: '@japa/preset-adonis',\n        isDevDependency: true,\n      },\n      {\n        name: 'playwright',\n        isDevDependency: false,\n      },\n    ])\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: ['Please install following packages'].join('\\n'),\n        stream: 'stdout',\n      },\n      {\n        message: ['yellow(npm i -D) @japa/runner @japa/preset-adonis'].join('\\n'),\n        stream: 'stdout',\n      },\n      {\n        message: ['yellow(npm i) playwright'].join('\\n'),\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('list prod dependencies to install', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Configure, ['../dummy-pkg.js'])\n    command.stubsRoot = join(fs.basePath, 'stubs')\n\n    const codemods = await command.createCodemods()\n    await codemods.listPackagesToInstall([\n      {\n        name: 'playwright',\n        isDevDependency: false,\n      },\n    ])\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: ['Please install following packages'].join('\\n'),\n        stream: 'stdout',\n      },\n      {\n        message: [].join('\\n'),\n        stream: 'stdout',\n      },\n      {\n        message: ['yellow(npm i) playwright'].join('\\n'),\n        stream: 'stdout',\n      },\n    ])\n  })\n})\n\ntest.group('Configure command | run', (group) => {\n  group.each.setup(({ context }) => {\n    context.fs.baseUrl = BASE_URL\n    context.fs.basePath = BASE_PATH\n  })\n\n  group.each.disableTimeout()\n\n  test('error when unable to import package', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: async (filePath) => {\n        await import(filePath)\n      },\n    })\n\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Configure, ['./dummy-pkg.js'])\n    await command.exec()\n\n    command.assertLog('[ red(error) ] Cannot find module \"./dummy-pkg.js\". Make sure to install it')\n    assert.equal(command.exitCode, 1)\n  })\n\n  test('error when package cannot be configured', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        return import(new URL(filePath, fs.baseUrl).href)\n      },\n    })\n\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.create('dummy-pkg.js', `export const stubsRoot = './'`)\n\n    const command = await ace.create(Configure, ['./dummy-pkg.js?v=1'])\n    await command.exec()\n\n    command.assertLog(\n      '[ yellow(warn) ] Cannot configure module \"./dummy-pkg.js?v=1\". The module does not export the configure hook'\n    )\n    assert.equal(command.exitCode, 0)\n  })\n\n  test('run package configure method', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        return import(new URL(filePath, fs.baseUrl).href)\n      },\n    })\n\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.create(\n      'dummy-pkg.js',\n      `\n      export const stubsRoot = './'\n      export function configure (command) {\n        command.result = 'configured'\n      }\n    `\n    )\n\n    const command = await ace.create(Configure, ['./dummy-pkg.js?v=2'])\n    await command.exec()\n    assert.equal(command.result, 'configured')\n  })\n\n  test('install packages', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        return import(new URL(filePath, fs.baseUrl).href)\n      },\n    })\n\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.createJson('package.json', { type: 'module' })\n    await fs.createJson('tsconfig.json', {})\n    await fs.create(\n      'dummy-pkg.js',\n      `\n      export const stubsRoot = './'\n      export async function configure (command) {\n        const codemods = await command.createCodemods()\n        await codemods.installPackages([\n          { name: 'is-odd@2.0.0', isDevDependency: true },\n          { name: 'is-even@1.0.0', isDevDependency: false }\n        ])\n      }\n    `\n    )\n\n    const command = await ace.create(Configure, ['./dummy-pkg.js?v=3'])\n    command.verbose = true\n    await command.exec()\n\n    assert.equal(command.exitCode, 0)\n    const packageJson = await fs.contentsJson('package.json')\n    assert.deepEqual(packageJson.dependencies, { 'is-even': '^1.0.0' })\n    assert.deepEqual(packageJson.devDependencies, { 'is-odd': '^2.0.0' })\n  })\n\n  test('install packages using pnpm when pnpm-lock file exists', async ({ fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        return import(new URL(filePath, fs.baseUrl).href)\n      },\n    })\n\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.create('pnpm-lock.yaml', '')\n    await fs.createJson('tsconfig.json', {})\n    await fs.createJson('package.json', { type: 'module' })\n    await fs.create(\n      'dummy-pkg.js',\n      `\n      export const stubsRoot = './'\n      export async function configure (command) {\n        const codemods = await command.createCodemods()\n        await codemods.installPackages([\n          { name: 'is-odd@2.0.0', isDevDependency: true, },\n        ])\n      }\n    `\n    )\n\n    const command = await ace.create(Configure, ['./dummy-pkg.js?v=4'])\n    await command.exec()\n\n    command.assertSucceeded()\n    command.assertLog('[ cyan(wait) ] installing dependencies using pnpm  .  ')\n  })\n\n  test('install packages using npm when package-lock file exists', async ({ fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        return import(new URL(filePath, fs.baseUrl).href)\n      },\n    })\n\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.createJson('package-lock.json', {})\n    await fs.createJson('tsconfig.json', {})\n    await fs.createJson('package.json', { type: 'module' })\n    await fs.create(\n      'dummy-pkg.js',\n      `\n      export const stubsRoot = './'\n      export async function configure (command) {\n        const codemods = await command.createCodemods()\n        await codemods.installPackages([\n          { name: 'is-odd@2.0.0', isDevDependency: true, },\n        ])\n      }\n    `\n    )\n\n    const command = await ace.create(Configure, ['./dummy-pkg.js?v=5'])\n    await command.exec()\n\n    command.assertSucceeded()\n    command.assertLog('[ cyan(wait) ] installing dependencies using npm  .  ')\n  })\n\n  test('display error when installation fails', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        return import(new URL(filePath, fs.baseUrl).href)\n      },\n    })\n\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.createJson('package-lock.json', {})\n    await fs.createJson('tsconfig.json', {})\n    await fs.createJson('package.json', { type: 'module' })\n    await fs.create(\n      'dummy-pkg.js',\n      `\n      export const stubsRoot = './'\n      export async function configure (command) {\n        const codemods = await command.createCodemods()\n        await codemods.installPackages([\n          { name: 'is-odd@15.0.0', isDevDependency: true, },\n        ])\n      }\n    `\n    )\n\n    const command = await ace.create(Configure, ['./dummy-pkg.js?v=6'])\n    await command.exec()\n\n    command.assertFailed()\n\n    const logs = ace.ui.logger.getLogs()\n    assert.deepInclude(logs, {\n      message: '[ cyan(wait) ] unable to install dependencies ...',\n      stream: 'stdout',\n    })\n\n    const lastLog = logs[logs.length - 1]\n    assert.equal(command.exitCode, 1)\n    console.log(lastLog.message)\n    assert.include(lastLog.message, '[ red(error) ] Process exited with non-zero status')\n  })\n})\n\ntest.group('Configure command | vinejs', (group) => {\n  group.each.disableTimeout()\n\n  test('register vinejs provider', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('adonisrc.ts', 'export default defineConfig({})')\n\n    const command = await ace.create(Configure, ['vinejs'])\n    command.stubsRoot = join(fs.basePath, 'stubs')\n\n    await command.run()\n\n    assert.deepEqual(command.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    update adonisrc.ts file',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileContains('adonisrc.ts', '@adonisjs/core/providers/vinejs_provider')\n  })\n})\n\ntest.group('Configure command | edge', (group) => {\n  group.each.disableTimeout()\n\n  test('register edge provider', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('adonisrc.ts', 'export default defineConfig({})')\n\n    const command = await ace.create(Configure, ['edge'])\n    command.stubsRoot = join(fs.basePath, 'stubs')\n\n    await command.run()\n\n    assert.deepEqual(command.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    update adonisrc.ts file',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileContains('adonisrc.ts', '@adonisjs/core/providers/edge_provider')\n    await assert.fileContains(\n      'adonisrc.ts',\n      `metaFiles: [{\n    pattern: 'resources/views/**/*.edge',\n    reloadServer: false,\n  }]`\n    )\n  })\n})\n\ntest.group('Configure command | health checks', (group) => {\n  group.each.disableTimeout()\n\n  test('create start/health file with some default checks', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('adonisrc.ts', 'export default defineConfig({})')\n\n    const command = await ace.create(Configure, ['health_checks'])\n\n    await command.run()\n\n    assert.deepEqual(command.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create start/health.ts',\n        stream: 'stdout',\n      },\n      {\n        message: 'green(DONE:)    create app/controllers/health_checks_controller.ts',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileContains('start/health.ts', [\n      'new DiskSpaceCheck()',\n      'new MemoryHeapCheck()',\n      'export const healthChecks = ',\n    ])\n    await assert.fileContains('app/controllers/health_checks_controller.ts', [\n      `import { healthChecks } from '#start/health'`,\n      'const report = await healthChecks.run()',\n      'export default class HealthChecksController',\n    ])\n  })\n})\n"
  },
  {
    "path": "tests/commands/eject.spec.ts",
    "content": "/*\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 { test } from '@japa/runner'\nimport EjectCommand from '../../commands/eject.ts'\nimport { AceFactory } from '../../factories/core/ace.ts'\n\ntest.group('Eject', () => {\n  test('eject a single stub', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => import(filePath),\n    })\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(EjectCommand, [\n      'make/controller/main.stub',\n      '--pkg=\"../../index.js\"',\n    ])\n    await command.exec()\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: '[ green(success) ] eject stubs/make/controller/main.stub',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.hasFiles(['stubs/make/controller/main.stub'])\n  })\n\n  test('eject a directory', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => import(filePath),\n    })\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(EjectCommand, ['make/controller', '--pkg=\"../../index.js\"'])\n    await command.exec()\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: '[ green(success) ] eject stubs/make/controller/actions.stub',\n        stream: 'stdout',\n      },\n      {\n        message: '[ green(success) ] eject stubs/make/controller/api.stub',\n        stream: 'stdout',\n      },\n      {\n        message: '[ green(success) ] eject stubs/make/controller/main.stub',\n        stream: 'stdout',\n      },\n      {\n        message: '[ green(success) ] eject stubs/make/controller/resource.stub',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.hasFiles([\n      'stubs/make/controller/main.stub',\n      'stubs/make/controller/api.stub',\n      'stubs/make/controller/resource.stub',\n    ])\n  })\n})\n"
  },
  {
    "path": "tests/commands/env_add.spec.ts",
    "content": "/*\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 { test } from '@japa/runner'\nimport EnvAdd from '../../commands/env/add.ts'\nimport { AceFactory } from '../../factories/core/ace.ts'\n\ntest.group('Env Add command', () => {\n  test('add new env variable to the different files', async ({ assert, fs }) => {\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('.env', '')\n    await fs.create('.env.example', '')\n    await fs.create(\n      './start/env.ts',\n      `import { Env } from '@adonisjs/core/env'\n      export default await Env.create(new URL('../', import.meta.url), {})`\n    )\n\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(EnvAdd, ['variable', 'value', '--type=string'])\n    await command.exec()\n\n    await assert.fileContains('.env', 'VARIABLE=value')\n    await assert.fileContains('.env.example', 'VARIABLE=')\n    await assert.fileContains('./start/env.ts', 'VARIABLE: Env.schema.string()')\n  })\n\n  test('convert variable to screaming snake case', async ({ assert, fs }) => {\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('.env', '')\n    await fs.create('.env.example', '')\n    await fs.create(\n      './start/env.ts',\n      `import { Env } from '@adonisjs/core/env'\n      export default await Env.create(new URL('../', import.meta.url), {})`\n    )\n\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(EnvAdd, ['stripe_ApiKey', 'value', '--type=string'])\n    await command.exec()\n\n    await assert.fileContains('.env', 'STRIPE_API_KEY=value')\n    await assert.fileContains('.env.example', 'STRIPE_API_KEY=')\n    await assert.fileContains('./start/env.ts', 'STRIPE_API_KEY: Env.schema.string()')\n  })\n\n  test('enum type with allowed values', async ({ assert, fs }) => {\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('.env', '')\n    await fs.create('.env.example', '')\n    await fs.create(\n      './start/env.ts',\n      `import { Env } from '@adonisjs/core/env'\n      export default await Env.create(new URL('../', import.meta.url), {})`\n    )\n\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(EnvAdd, [\n      'variable',\n      'bar',\n      '--type=enum',\n      '--enum-values=foo',\n      '--enum-values=bar',\n    ])\n    await command.exec()\n\n    await assert.fileContains('.env', 'VARIABLE=bar')\n    await assert.fileContains('.env.example', 'VARIABLE=')\n    await assert.fileContains(\n      './start/env.ts',\n      \"VARIABLE: Env.schema.enum(['foo', 'bar'] as const)\"\n    )\n  })\n\n  test('prompt when nothing is passed to the command', async ({ assert, fs }) => {\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('.env', '')\n    await fs.create('.env.example', '')\n    await fs.create(\n      './start/env.ts',\n      `import { Env } from '@adonisjs/core/env'\n      export default await Env.create(new URL('../', import.meta.url), {})`\n    )\n\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(EnvAdd, [])\n\n    command.prompt.trap('Enter the variable name').replyWith('my_variable_name')\n    command.prompt.trap('Enter the variable value').replyWith('my_value')\n    command.prompt.trap('Select the variable type').replyWith('string')\n\n    await command.exec()\n\n    await assert.fileContains('.env', 'MY_VARIABLE_NAME=my_value')\n    await assert.fileContains('.env.example', 'MY_VARIABLE_NAME=')\n    await assert.fileContains('./start/env.ts', 'MY_VARIABLE_NAME: Env.schema.string()')\n  })\n})\n"
  },
  {
    "path": "tests/commands/generate_key.spec.ts",
    "content": "/*\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 { test } from '@japa/runner'\nimport GenerateKey from '../../commands/generate_key.ts'\nimport { AceFactory } from '../../factories/core/ace.ts'\n\ntest.group('Generate key', () => {\n  test('create key and write it to .env file', async ({ assert, fs }) => {\n    await fs.create('.env', '')\n    await fs.create('.env.example', '')\n\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(GenerateKey, [])\n    await command.exec()\n\n    await assert.fileContains('.env', 'APP_KEY=')\n    await assert.fileContains('.env.example', 'APP_KEY=')\n  })\n\n  test('do not write to the file when --show flag is set', async ({ assert, fs }) => {\n    await fs.create('.env', '')\n    await fs.create('.env.example', '')\n\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(GenerateKey, ['--show'])\n    await command.exec()\n\n    await assert.fileEquals('.env', '')\n    await assert.fileEquals('.env.example', '')\n\n    assert.deepEqual(ace.ui.logger.getLogs()[0].stream, 'stdout')\n    assert.match(ace.ui.logger.getLogs()[0].message, /APP_KEY =/)\n  })\n\n  test('do not write to the file when in production envionment', async ({\n    assert,\n    fs,\n    cleanup,\n  }) => {\n    await fs.create('.env', '')\n    await fs.create('.env.example', '')\n\n    cleanup(() => {\n      delete process.env.NODE_ENV\n    })\n\n    process.env.NODE_ENV = 'production'\n\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(GenerateKey, [])\n    await command.exec()\n\n    await assert.fileEquals('.env', '')\n    await assert.fileEquals('.env.example', '')\n\n    assert.deepEqual(ace.ui.logger.getLogs()[0].stream, 'stdout')\n    assert.match(ace.ui.logger.getLogs()[0].message, /APP_KEY =/)\n  })\n\n  test('write to the file when in production envionment and --force flag is set', async ({\n    assert,\n    fs,\n    cleanup,\n  }) => {\n    await fs.create('.env', '')\n    await fs.create('.env.example', '')\n\n    cleanup(() => {\n      delete process.env.NODE_ENV\n    })\n\n    process.env.NODE_ENV = 'production'\n\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(GenerateKey, ['--force'])\n    await command.exec()\n\n    await assert.fileContains('.env', 'APP_KEY=')\n    await assert.fileContains('.env.example', 'APP_KEY=')\n  })\n})\n"
  },
  {
    "path": "tests/commands/inspect_rcfile.spec.ts",
    "content": "/*\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 { test } from '@japa/runner'\nimport { AceFactory } from '../../factories/core/ace.ts'\nimport InspectRCFile from '../../commands/inspect_rcfile.ts'\n\ntest.group('Inspect RCFile', () => {\n  test('inspect rcfile contents', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const inspect = await ace.create(InspectRCFile, [])\n    await inspect.exec()\n\n    inspect.assertSucceeded()\n\n    const { raw, providers, preloads, commands, ...rcContents } = ace.app.rcFile\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: JSON.stringify(\n          {\n            ...rcContents,\n            providers: providers.map((provider) => {\n              return {\n                ...provider,\n                file: provider.file.toString(),\n              }\n            }),\n            preloads: preloads.map((preload) => {\n              return {\n                ...preload,\n                file: preload.file.toString(),\n              }\n            }),\n            commands: commands.map((command) => {\n              return command.toString()\n            }),\n          },\n          null,\n          2\n        ),\n        stream: 'stdout',\n      },\n    ])\n  })\n})\n"
  },
  {
    "path": "tests/commands/make_command.spec.ts",
    "content": "/*\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 { test } from '@japa/runner'\nimport MakeCommand from '../../commands/make/command.ts'\nimport { AceFactory } from '../../factories/core/ace.ts'\nimport { StubsFactory } from '../../factories/stubs.ts'\nimport { join } from 'node:path'\n\ntest.group('Make command', () => {\n  test('create command class', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeCommand, ['listRoutes'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/command/main.stub', {\n      entity: ace.app.generators.createEntity('listRoutes'),\n    })\n\n    await assert.fileEquals('commands/list_routes.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create commands/list_routes.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('overwrite file contents', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.create('my-command.txt', 'export class MyCommand {}')\n\n    const command = await ace.create(MakeCommand, [\n      'listRoutes',\n      '--contents-from',\n      join(fs.basePath, 'my-command.txt'),\n    ])\n    await command.exec()\n\n    await assert.fileEquals('commands/list_routes.ts', `export class MyCommand {}`)\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create commands/list_routes.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n})\n"
  },
  {
    "path": "tests/commands/make_controller.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { AceFactory } from '../../factories/core/ace.ts'\nimport { StubsFactory } from '../../factories/stubs.ts'\nimport MakeControllerCommand from '../../commands/make/controller.ts'\n\ntest.group('Make controller', () => {\n  test('create controller', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeControllerCommand, ['user'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/controller/main.stub', {\n      entity: ace.app.generators.createEntity('user'),\n      singular: false,\n    })\n\n    await assert.fileEquals('app/controllers/users_controller.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/controllers/users_controller.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('skip when controller already exists', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.create('app/controllers/users_controller.ts', `export default class {}`)\n\n    const command = await ace.create(MakeControllerCommand, ['user'])\n    await command.exec()\n\n    await assert.fileEquals('app/controllers/users_controller.ts', `export default class {}`)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message:\n          'cyan(SKIPPED:) create app/controllers/users_controller.ts dim((File already exists))',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('create resource controller', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeControllerCommand, ['user', '--resource'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/controller/resource.stub', {\n      entity: ace.app.generators.createEntity('user'),\n      singular: false,\n    })\n\n    await assert.fileEquals('app/controllers/users_controller.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/controllers/users_controller.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('create api controller', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeControllerCommand, ['user', '--api'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/controller/api.stub', {\n      entity: ace.app.generators.createEntity('user'),\n      singular: false,\n    })\n\n    await assert.fileEquals('app/controllers/users_controller.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/controllers/users_controller.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('create api controller when both api and resource flags are used', async ({\n    assert,\n    fs,\n  }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeControllerCommand, ['user', '--api', '--resource'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/controller/api.stub', {\n      entity: ace.app.generators.createEntity('user'),\n      singular: false,\n    })\n\n    await assert.fileEquals('app/controllers/users_controller.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message:\n          '[ yellow(warn) ] --api and --resource flags cannot be used together. Ignoring --resource',\n        stream: 'stdout',\n      },\n      {\n        message: 'green(DONE:)    create app/controllers/users_controller.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('create controller with actions', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeControllerCommand, [\n      'user',\n      'index',\n      'show',\n      'delete-profile',\n    ])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/controller/actions.stub', {\n      entity: ace.app.generators.createEntity('user'),\n      singular: false,\n      actions: ['index', 'show', 'deleteProfile'],\n    })\n\n    await assert.fileEquals('app/controllers/users_controller.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/controllers/users_controller.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('warn when using --resource flag with actions', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeControllerCommand, [\n      'user',\n      'index',\n      'show',\n      'delete-profile',\n      '--resource',\n    ])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/controller/actions.stub', {\n      entity: ace.app.generators.createEntity('user'),\n      singular: false,\n      actions: ['index', 'show', 'deleteProfile'],\n    })\n\n    await assert.fileEquals('app/controllers/users_controller.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: '[ yellow(warn) ] Cannot use --resource flag with actions. Ignoring --resource',\n        stream: 'stdout',\n      },\n      {\n        message: 'green(DONE:)    create app/controllers/users_controller.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('warn when using --resource and --api flag with actions', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeControllerCommand, [\n      'user',\n      'index',\n      'show',\n      'delete-profile',\n      '--resource',\n      '--api',\n    ])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/controller/actions.stub', {\n      entity: ace.app.generators.createEntity('user'),\n      singular: false,\n      actions: ['index', 'show', 'deleteProfile'],\n    })\n\n    await assert.fileEquals('app/controllers/users_controller.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: '[ yellow(warn) ] Cannot use --resource flag with actions. Ignoring --resource',\n        stream: 'stdout',\n      },\n      {\n        message: '[ yellow(warn) ] Cannot use --api flag with actions. Ignoring --api',\n        stream: 'stdout',\n      },\n      {\n        message: 'green(DONE:)    create app/controllers/users_controller.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('create singular controller', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeControllerCommand, ['user', '-s'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/controller/main.stub', {\n      entity: ace.app.generators.createEntity('user'),\n      singular: true,\n    })\n\n    await assert.fileEquals('app/controllers/user_controller.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/controllers/user_controller.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('create singular resource controller', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeControllerCommand, ['user', '--resource', '-s'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/controller/resource.stub', {\n      entity: ace.app.generators.createEntity('user'),\n      singular: true,\n    })\n\n    await assert.fileEquals('app/controllers/user_controller.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/controllers/user_controller.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('create singular controller with actions', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeControllerCommand, [\n      'user',\n      'index',\n      'show',\n      'delete-profile',\n      '-s',\n    ])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/controller/actions.stub', {\n      entity: ace.app.generators.createEntity('user'),\n      actions: ['index', 'show', 'deleteProfile'],\n      singular: true,\n    })\n\n    await assert.fileEquals('app/controllers/user_controller.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/controllers/user_controller.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('create singular api controller', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeControllerCommand, ['user', '--api', '-s'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/controller/api.stub', {\n      entity: ace.app.generators.createEntity('user'),\n      singular: true,\n    })\n\n    await assert.fileEquals('app/controllers/user_controller.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/controllers/user_controller.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('overwrite file contents', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.create('my-controller.txt', 'export class MyController {}')\n\n    const command = await ace.create(MakeControllerCommand, [\n      'user',\n      '--contents-from',\n      join(fs.basePath, 'my-controller.txt'),\n    ])\n    await command.exec()\n\n    await assert.fileEquals('app/controllers/users_controller.ts', `export class MyController {}`)\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/controllers/users_controller.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n})\n"
  },
  {
    "path": "tests/commands/make_event.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { AceFactory } from '../../factories/core/ace.ts'\nimport { StubsFactory } from '../../factories/stubs.ts'\nimport MakeEventCommand from '../../commands/make/event.ts'\n\ntest.group('Make event', () => {\n  test('create event class', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeEventCommand, ['orderShipped'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/event/main.stub', {\n      entity: ace.app.generators.createEntity('orderShipped'),\n    })\n\n    await assert.fileEquals('app/events/order_shipped.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/events/order_shipped.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('overwrite file contents', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.create('my-event.txt', 'export class MyEvent {}')\n\n    const command = await ace.create(MakeEventCommand, [\n      'orderShipped',\n      '--contents-from',\n      join(fs.basePath, 'my-event.txt'),\n    ])\n    await command.exec()\n\n    await assert.fileEquals('app/events/order_shipped.ts', `export class MyEvent {}`)\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/events/order_shipped.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n})\n"
  },
  {
    "path": "tests/commands/make_exception.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { AceFactory } from '../../factories/core/ace.ts'\nimport { StubsFactory } from '../../factories/stubs.ts'\nimport MakeException from '../../commands/make/exception.ts'\n\ntest.group('Make exception command', () => {\n  test('create exception class', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeException, ['Unauthorized'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/exception/main.stub', {\n      entity: ace.app.generators.createEntity('Unauthorized'),\n    })\n\n    await assert.fileEquals('app/exceptions/unauthorized_exception.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/exceptions/unauthorized_exception.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('overwrite file contents', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.create('my-exception.txt', 'export class MyException {}')\n\n    const command = await ace.create(MakeException, [\n      'Unauthorized',\n      '--contents-from',\n      join(fs.basePath, 'my-exception.txt'),\n    ])\n    await command.exec()\n\n    await assert.fileEquals(\n      'app/exceptions/unauthorized_exception.ts',\n      `export class MyException {}`\n    )\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/exceptions/unauthorized_exception.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n})\n"
  },
  {
    "path": "tests/commands/make_listener.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { ListLoader } from '../../modules/ace/main.ts'\nimport { AceFactory } from '../../factories/core/ace.ts'\nimport { StubsFactory } from '../../factories/stubs.ts'\nimport MakeEventCommand from '../../commands/make/event.ts'\nimport MakeListenerCommand from '../../commands/make/listener.ts'\n\ntest.group('Make listener', () => {\n  test('create listener class', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeListenerCommand, ['sendEmail'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/listener/main.stub', {\n      entity: ace.app.generators.createEntity('sendEmail'),\n    })\n\n    await assert.fileEquals('app/listeners/send_email.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/listeners/send_email.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('create a listener with an event class', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n\n    ace.addLoader(new ListLoader([MakeEventCommand]))\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeListenerCommand, ['sendEmail', '-e=orderShipped'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/listener/for_event.stub', {\n      entity: ace.app.generators.createEntity('sendEmail'),\n      event: ace.app.generators.createEntity('orderShipped'),\n    })\n\n    const { contents: eventContents } = await new StubsFactory().prepare('make/event/main.stub', {\n      entity: ace.app.generators.createEntity('orderShipped'),\n    })\n\n    await assert.fileEquals('app/listeners/send_email.ts', contents)\n    await assert.fileEquals('app/events/order_shipped.ts', eventContents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/events/order_shipped.ts',\n        stream: 'stdout',\n      },\n      {\n        message: 'green(DONE:)    create app/listeners/send_email.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('overwrite file contents', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.create('my-listener.txt', 'export class MyListener {}')\n\n    const command = await ace.create(MakeListenerCommand, [\n      'sendEmail',\n      '--contents-from',\n      join(fs.basePath, 'my-listener.txt'),\n    ])\n    await command.exec()\n\n    await assert.fileEquals('app/listeners/send_email.ts', `export class MyListener {}`)\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/listeners/send_email.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n})\n"
  },
  {
    "path": "tests/commands/make_middleware.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { AceFactory } from '../../factories/core/ace.ts'\nimport { StubsFactory } from '../../factories/stubs.ts'\nimport MakeMiddleware from '../../commands/make/middleware.ts'\n\ntest.group('Make middleware', (group) => {\n  group.tap((t) => t.disableTimeout())\n\n  test('create middleware class', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('start/kernel.ts', 'server.use([])')\n\n    const command = await ace.create(MakeMiddleware, ['auth', '--stack=server'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/middleware/main.stub', {\n      entity: ace.app.generators.createEntity('auth'),\n    })\n\n    await assert.fileEquals('app/middleware/auth_middleware.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/middleware/auth_middleware.ts',\n        stream: 'stdout',\n      },\n      {\n        message: 'green(DONE:)    update start/kernel.ts file',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileContains(\n      'start/kernel.ts',\n      `server.use([() => import('#middleware/auth_middleware')])`\n    )\n  })\n\n  test('register middleware under named stack', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('start/kernel.ts', 'export const middleware = router.named({})')\n\n    const command = await ace.create(MakeMiddleware, ['auth', '--stack=named'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/middleware/main.stub', {\n      entity: ace.app.generators.createEntity('auth'),\n    })\n\n    await assert.fileEquals('app/middleware/auth_middleware.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/middleware/auth_middleware.ts',\n        stream: 'stdout',\n      },\n      {\n        message: 'green(DONE:)    update start/kernel.ts file',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileContains(\n      'start/kernel.ts',\n      `auth: () => import('#middleware/auth_middleware')`\n    )\n  })\n\n  test('create nested middleware', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('start/kernel.ts', 'export const middleware = router.named({})')\n\n    const command = await ace.create(MakeMiddleware, ['blog/auth', '--stack=named'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/middleware/main.stub', {\n      entity: ace.app.generators.createEntity('auth'),\n    })\n\n    await assert.fileEquals('app/middleware/blog/auth_middleware.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/middleware/blog/auth_middleware.ts',\n        stream: 'stdout',\n      },\n      {\n        message: 'green(DONE:)    update start/kernel.ts file',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileContains(\n      'start/kernel.ts',\n      `auth: () => import('#middleware/blog/auth_middleware')`\n    )\n  })\n\n  test('show error when selected middleware stack is invalid', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('start/kernel.ts', 'export const middleware = router.named({})')\n\n    const command = await ace.create(MakeMiddleware, ['auth', '--stack=foo'])\n    await command.exec()\n    await assert.fileNotExists('app/middleware/auth_middleware.ts')\n\n    command.assertFailed()\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message:\n          '[ red(error) ] Invalid middleware stack \"foo\". Select from \"server, router, named\"',\n        stream: 'stderr',\n      },\n    ])\n  })\n\n  test('overwrite file contents', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('start/kernel.ts', 'server.use([])')\n    await fs.create('my-middleware.txt', 'export class MyMiddleware {}')\n\n    const command = await ace.create(MakeMiddleware, [\n      'auth',\n      '--stack=server',\n      '--contents-from',\n      join(fs.basePath, 'my-middleware.txt'),\n    ])\n    await command.exec()\n\n    await assert.fileEquals('app/middleware/auth_middleware.ts', `export class MyMiddleware {}`)\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/middleware/auth_middleware.ts',\n        stream: 'stdout',\n      },\n      {\n        message: 'green(DONE:)    update start/kernel.ts file',\n        stream: 'stdout',\n      },\n    ])\n  })\n})\n"
  },
  {
    "path": "tests/commands/make_preload.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { StubsFactory } from '../../factories/stubs.ts'\nimport { AceFactory } from '../../factories/core/ace.ts'\nimport MakePreload from '../../commands/make/preload.ts'\n\ntest.group('Make preload file', () => {\n  test('create a preload file for all environments', async ({ assert, fs }) => {\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('adonisrc.ts', `export default defineConfig({})`)\n\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakePreload, ['app'])\n    command.prompt.trap('Do you want to register the preload file in .adonisrc.ts file?').accept()\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/preload/main.stub', {\n      entity: ace.app.generators.createEntity('app'),\n    })\n    await assert.fileEquals('start/app.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create start/app.ts',\n        stream: 'stdout',\n      },\n      {\n        message: 'green(DONE:)    update adonisrc.ts file',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileContains('adonisrc.ts', `() => import('#start/app')`)\n  })\n\n  test('do not prompt when --register flag is used', async ({ assert, fs }) => {\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('adonisrc.ts', `export default defineConfig({})`)\n\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakePreload, ['app', '--register'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/preload/main.stub', {\n      entity: ace.app.generators.createEntity('app'),\n    })\n    await assert.fileEquals('start/app.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create start/app.ts',\n        stream: 'stdout',\n      },\n      {\n        message: 'green(DONE:)    update adonisrc.ts file',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileContains('adonisrc.ts', `() => import('#start/app')`)\n  })\n\n  test('do not register preload file when --no-register flag is used', async ({ assert, fs }) => {\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('adonisrc.ts', `export default defineConfig({})`)\n\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakePreload, ['app', '--no-register'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/preload/main.stub', {\n      entity: ace.app.generators.createEntity('app'),\n    })\n    await assert.fileEquals('start/app.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create start/app.ts',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileEquals('adonisrc.ts', `export default defineConfig({})`)\n  })\n\n  test('use environment flag to make preload file in a specific env', async ({ assert, fs }) => {\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('adonisrc.ts', `export default defineConfig({})`)\n\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakePreload, [\n      'app',\n      '--environments=web',\n      '--environments=repl',\n    ])\n    command.prompt.trap('Do you want to register the preload file in .adonisrc.ts file?').accept()\n    await command.exec()\n\n    await assert.fileContains('adonisrc.ts', [\n      `() => import('#start/app')`,\n      `environment: ['web', 'repl']`,\n    ])\n  })\n\n  test('display error when defined environment is not allowed', async ({ fs }) => {\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('adonisrc.ts', `export default defineConfig({})`)\n\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakePreload, ['app'])\n    command.environments = ['foo' as any]\n    command.prompt.trap('Do you want to register the preload file in .adonisrc.ts file?').accept()\n    await command.exec()\n\n    command.assertLog(\n      '[ red(error) ] Invalid environment(s) \"foo\". Only \"web,console,test,repl\" are allowed'\n    )\n  })\n\n  test('overwrite file contents', async ({ assert, fs }) => {\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('adonisrc.ts', `export default defineConfig({})`)\n    await fs.create('my-preload.txt', 'export class MyPreload {}')\n\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakePreload, [\n      'app',\n      '--no-register',\n      '--contents-from',\n      join(fs.basePath, 'my-preload.txt'),\n    ])\n    await command.exec()\n\n    await assert.fileEquals('start/app.ts', `export class MyPreload {}`)\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create start/app.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n})\n"
  },
  {
    "path": "tests/commands/make_provider.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { AceFactory } from '../../factories/core/ace.ts'\nimport MakeProvider from '../../commands/make/provider.ts'\nimport { StubsFactory } from '../../factories/stubs.ts'\n\ntest.group('Make provider', () => {\n  test('create provider class', async ({ assert, fs }) => {\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('adonisrc.ts', `export default defineConfig({})`)\n\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeProvider, ['app'])\n    command.prompt.trap('Do you want to register the provider in .adonisrc.ts file?').accept()\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/provider/main.stub', {\n      entity: ace.app.generators.createEntity('app'),\n    })\n\n    await assert.fileEquals('providers/app_provider.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create providers/app_provider.ts',\n        stream: 'stdout',\n      },\n      {\n        message: 'green(DONE:)    update adonisrc.ts file',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileContains('adonisrc.ts', `() => import('#providers/app_provider')`)\n  })\n\n  test('do not display prompt when --register flag is used', async ({ assert, fs }) => {\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('adonisrc.ts', `export default defineConfig({})`)\n\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeProvider, ['app', '--register'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/provider/main.stub', {\n      entity: ace.app.generators.createEntity('app'),\n    })\n\n    await assert.fileEquals('providers/app_provider.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create providers/app_provider.ts',\n        stream: 'stdout',\n      },\n      {\n        message: 'green(DONE:)    update adonisrc.ts file',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileContains('adonisrc.ts', `() => import('#providers/app_provider')`)\n  })\n\n  test('do not register provider when --no-register flag is used', async ({ assert, fs }) => {\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('adonisrc.ts', `export default defineConfig({})`)\n\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeProvider, ['app', '--no-register'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/provider/main.stub', {\n      entity: ace.app.generators.createEntity('app'),\n    })\n\n    await assert.fileEquals('providers/app_provider.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create providers/app_provider.ts',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileEquals('adonisrc.ts', `export default defineConfig({})`)\n  })\n\n  test('create provider class for a specific environment', async ({ assert, fs }) => {\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('adonisrc.ts', `export default defineConfig({})`)\n\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeProvider, ['app', '-e=web', '-e=repl'])\n    command.prompt.trap('Do you want to register the provider in .adonisrc.ts file?').accept()\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/provider/main.stub', {\n      entity: ace.app.generators.createEntity('app'),\n    })\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create providers/app_provider.ts',\n        stream: 'stdout',\n      },\n      {\n        message: 'green(DONE:)    update adonisrc.ts file',\n        stream: 'stdout',\n      },\n    ])\n\n    await assert.fileEquals('providers/app_provider.ts', contents)\n    await assert.fileContains('adonisrc.ts', [\n      `() => import('#providers/app_provider')`,\n      `environment: ['web', 'repl']`,\n    ])\n  })\n\n  test('show error when selected environment is invalid', async ({ assert, fs }) => {\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('adonisrc.ts', `export default defineConfig({})`)\n\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeProvider, ['app', '--environments=foo'])\n    command.prompt.trap('Do you want to register the provider in .adonisrc.ts file?').accept()\n    await command.exec()\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message:\n          '[ red(error) ] Invalid environment(s) \"foo\". Only \"web,console,test,repl\" are allowed',\n        stream: 'stderr',\n      },\n    ])\n  })\n\n  test('overwrite file contents', async ({ assert, fs }) => {\n    await fs.createJson('tsconfig.json', {})\n    await fs.create('adonisrc.ts', `export default defineConfig({})`)\n    await fs.create('my-provider.txt', 'export class MyProvider {}')\n\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeProvider, [\n      'app',\n      '--no-register',\n      '--contents-from',\n      join(fs.basePath, 'my-provider.txt'),\n    ])\n    await command.exec()\n\n    await assert.fileEquals('providers/app_provider.ts', `export class MyProvider {}`)\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create providers/app_provider.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n})\n"
  },
  {
    "path": "tests/commands/make_service.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { AceFactory } from '../../factories/core/ace.ts'\nimport { StubsFactory } from '../../factories/stubs.ts'\nimport MakeService from '../../commands/make/service.ts'\n\ntest.group('Make service', () => {\n  test('create service class', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeService, ['app'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/service/main.stub', {\n      entity: ace.app.generators.createEntity('app'),\n    })\n\n    await assert.fileEquals('app/services/app_service.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/services/app_service.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('overwrite file contents', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.create('my-service.txt', 'export class MyService {}')\n\n    const command = await ace.create(MakeService, [\n      'app',\n      '--contents-from',\n      join(fs.basePath, 'my-service.txt'),\n    ])\n    await command.exec()\n\n    await assert.fileEquals('app/services/app_service.ts', `export class MyService {}`)\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/services/app_service.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n})\n"
  },
  {
    "path": "tests/commands/make_test.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport MakeTest from '../../commands/make/test.ts'\nimport { StubsFactory } from '../../factories/stubs.ts'\nimport { AceFactory } from '../../factories/core/ace.ts'\nimport { IgnitorFactory } from '../../factories/core/ignitor.ts'\n\ntest.group('Make test', () => {\n  test('--suite flag: make inside suite directory', async ({ assert, fs }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n          tests: {\n            suites: [\n              {\n                name: 'functional',\n                files: ['tests/functional/**/*.spec.ts'],\n              },\n            ],\n          },\n        },\n      })\n      .create(fs.baseUrl)\n\n    const ace = await new AceFactory().make(ignitor)\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeTest, ['posts/create', '--suite', 'functional'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/test/main.stub', {\n      entity: ace.app.generators.createEntity('posts/create'),\n      suite: {\n        directory: 'tests/functional',\n      },\n    })\n\n    await assert.fileEquals('tests/functional/posts/create.spec.ts', contents)\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create tests/functional/posts/create.spec.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('--suite flag: show error when mentioned suite does not exists', async ({ assert, fs }) => {\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .withCoreConfig()\n      .create(fs.baseUrl)\n\n    const ace = await new AceFactory().make(ignitor)\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeTest, ['posts/create', '--suite', 'functional'])\n    await command.exec()\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message:\n          '[ red(error) ] The \"functional\" suite is not configured inside the \"adonisrc.js\" file',\n        stream: 'stderr',\n      },\n    ])\n  })\n\n  test('auto pick first suite when only one suite is configured in rcfile', async ({\n    assert,\n    fs,\n  }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n          tests: {\n            suites: [\n              {\n                name: 'functional',\n                files: ['tests/functional/**/*.spec.ts'],\n              },\n            ],\n          },\n        },\n      })\n      .create(fs.baseUrl)\n\n    const ace = await new AceFactory().make(ignitor)\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeTest, ['posts/create'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/test/main.stub', {\n      entity: ace.app.generators.createEntity('posts/create'),\n      suite: {\n        directory: 'tests/functional',\n      },\n    })\n\n    await assert.fileEquals('tests/functional/posts/create.spec.ts', contents)\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create tests/functional/posts/create.spec.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('prompt for suite selection when multiple suites are configured in rc file', async ({\n    assert,\n    fs,\n  }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n          tests: {\n            suites: [\n              {\n                name: 'functional',\n                files: ['tests/functional/**/*.spec.ts'],\n              },\n              {\n                name: 'unit',\n                files: ['tests/unit/**/*.spec.ts'],\n              },\n            ],\n          },\n        },\n      })\n      .create(fs.baseUrl)\n\n    const ace = await new AceFactory().make(ignitor)\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeTest, ['posts/create'])\n    command.prompt\n      .trap('Select the suite for the test file')\n      .assertFails('', 'Please select a suite')\n      .assertPasses('functional')\n      .chooseOption(1)\n\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/test/main.stub', {\n      entity: ace.app.generators.createEntity('posts/create'),\n      suite: {\n        directory: 'tests/unit',\n      },\n    })\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create tests/unit/posts/create.spec.ts',\n        stream: 'stdout',\n      },\n    ])\n    await assert.fileEquals('tests/unit/posts/create.spec.ts', contents)\n  })\n\n  test('prompt for directory selection when suite has multiple directories', async ({\n    assert,\n    fs,\n  }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n          tests: {\n            suites: [\n              {\n                name: 'functional',\n                files: ['tests/functional/**/*.spec.ts', 'features/tests/functional/*.spec.ts'],\n              },\n            ],\n          },\n        },\n      })\n      .create(fs.baseUrl)\n\n    const ace = await new AceFactory().make(ignitor)\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeTest, ['posts/create'])\n    command.prompt\n      .trap('Select directory for the test file')\n      .assertPasses('features/tests/functional')\n      .assertFails('', 'Please select a directory')\n      .chooseOption(1)\n\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/test/main.stub', {\n      entity: ace.app.generators.createEntity('posts/create'),\n      suite: {\n        directory: 'features/tests/functional',\n      },\n    })\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create features/tests/functional/posts/create.spec.ts',\n        stream: 'stdout',\n      },\n    ])\n    await assert.fileEquals('features/tests/functional/posts/create.spec.ts', contents)\n  })\n\n  test('overwrite file contents', async ({ assert, fs }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n          tests: {\n            suites: [\n              {\n                name: 'functional',\n                files: ['tests/functional/**/*.spec.ts'],\n              },\n            ],\n          },\n        },\n      })\n      .create(fs.baseUrl)\n\n    const ace = await new AceFactory().make(ignitor)\n    ace.ui.switchMode('raw')\n\n    await fs.create('my-test.txt', 'export class MyTest {}')\n\n    const command = await ace.create(MakeTest, [\n      'posts/create',\n      '--suite',\n      'functional',\n      '--contents-from',\n      join(fs.basePath, 'my-test.txt'),\n    ])\n    await command.exec()\n\n    await assert.fileEquals('tests/functional/posts/create.spec.ts', `export class MyTest {}`)\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create tests/functional/posts/create.spec.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n})\n"
  },
  {
    "path": "tests/commands/make_transformer.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { AceFactory } from '../../factories/core/ace.ts'\nimport { StubsFactory } from '../../factories/stubs.ts'\nimport MakeTransformer from '../../commands/make/transformer.ts'\n\ntest.group('Make transformer', () => {\n  test('create transformer class', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeTransformer, ['user'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/transformer/main.stub', {\n      entity: ace.app.generators.createEntity('user'),\n      model: ace.app.generators.createEntity('user'),\n    })\n\n    await assert.fileEquals('app/transformers/user_transformer.ts', contents)\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/transformers/user_transformer.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('overwrite file contents', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.create('my-transformer.txt', 'export class MyTransformer {}')\n\n    const command = await ace.create(MakeTransformer, [\n      'user',\n      '--contents-from',\n      join(fs.basePath, 'my-transformer.txt'),\n    ])\n    await command.exec()\n\n    await assert.fileEquals('app/transformers/user_transformer.ts', `export class MyTransformer {}`)\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/transformers/user_transformer.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n})\n"
  },
  {
    "path": "tests/commands/make_validator.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { AceFactory } from '../../factories/core/ace.ts'\nimport { StubsFactory } from '../../factories/stubs.ts'\nimport MakeValidator from '../../commands/make/validator.ts'\n\ntest.group('Make validator', () => {\n  test('create validator file', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeValidator, ['invoice'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/validator/main.stub', {\n      entity: ace.app.generators.createEntity('invoice'),\n    })\n\n    await assert.fileEquals('app/validators/invoice.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/validators/invoice.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('create validator file for a resource', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeValidator, ['invoice', '--resource'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/validator/resource.stub', {\n      entity: ace.app.generators.createEntity('invoice'),\n    })\n\n    await assert.fileEquals('app/validators/invoice.ts', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/validators/invoice.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('overwrite file contents', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.create('my-validator.txt', 'export class MyValidator {}')\n\n    const command = await ace.create(MakeValidator, [\n      'invoice',\n      '--contents-from',\n      join(fs.basePath, 'my-validator.txt'),\n    ])\n    await command.exec()\n\n    await assert.fileEquals('app/validators/invoice.ts', `export class MyValidator {}`)\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create app/validators/invoice.ts',\n        stream: 'stdout',\n      },\n    ])\n  })\n})\n"
  },
  {
    "path": "tests/commands/make_view.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\n\nimport MakeView from '../../commands/make/view.ts'\nimport { StubsFactory } from '../../factories/stubs.ts'\nimport { AceFactory } from '../../factories/core/ace.ts'\n\ntest.group('Make view', () => {\n  test('create view template', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(MakeView, ['welcome'])\n    await command.exec()\n\n    const { contents } = await new StubsFactory().prepare('make/view/main.stub', {\n      entity: ace.app.generators.createEntity('welcome'),\n    })\n\n    await assert.fileEquals('resources/views/welcome.edge', contents)\n\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create resources/views/welcome.edge',\n        stream: 'stdout',\n      },\n    ])\n  })\n\n  test('overwrite file contents', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl)\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    await fs.create('my-view.txt', '<h1>My View</h1>')\n\n    const command = await ace.create(MakeView, [\n      'welcome',\n      '--contents-from',\n      join(fs.basePath, 'my-view.txt'),\n    ])\n    await command.exec()\n\n    await assert.fileEquals('resources/views/welcome.edge', `<h1>My View</h1>`)\n    assert.deepEqual(ace.ui.logger.getLogs(), [\n      {\n        message: 'green(DONE:)    create resources/views/welcome.edge',\n        stream: 'stdout',\n      },\n    ])\n  })\n})\n"
  },
  {
    "path": "tests/commands/serve.spec.ts",
    "content": "/*\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 { test } from '@japa/runner'\nimport Serve from '../../commands/serve.ts'\nimport { AceFactory } from '../../factories/core/ace.ts'\nimport { setupTypeScriptProject } from '../helpers.ts'\nimport { indexEntities } from '../../src/assembler_hooks/index_entities.ts'\n\nconst sleep = (duration: number) => new Promise((resolve) => setTimeout(resolve, duration))\n\ntest.group('Serve command', () => {\n  test('show error when assembler is not installed', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        if (filePath === '@adonisjs/assembler') {\n          return import(new URL(filePath, fs.baseUrl).href)\n        }\n\n        return import(filePath)\n      },\n    })\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Serve, ['--no-clear'])\n    await command.exec()\n    await sleep(600)\n\n    assert.equal(command.exitCode, 1)\n    assert.lengthOf(ace.ui.logger.getLogs(), 1)\n    assert.equal(ace.ui.logger.getLogs()[0].stream, 'stderr')\n    assert.match(ace.ui.logger.getLogs()[0].message, /Cannot find package \"@adonisjs\\/assembler/)\n  })\n\n  test('fail when bin/server.js file is missing', async ({ assert, fs, cleanup }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        if (filePath === 'typescript') {\n          return import(new URL(filePath, fs.baseUrl).href)\n        }\n\n        return import(filePath)\n      },\n    })\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Serve, ['--no-clear'])\n    cleanup(() => command.devServer.close())\n    await command.exec()\n\n    await sleep(600)\n\n    assert.equal(command.exitCode, 1)\n  })\n\n  test('fail in watch mode when tsconfig file is missing', async ({ assert, fs, cleanup }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        return import(filePath)\n      },\n    })\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Serve, ['--no-clear'])\n    cleanup(() => command.devServer.close())\n    command.watch = true\n    await command.exec()\n\n    await sleep(600)\n\n    assert.equal(command.exitCode, 1)\n  })\n\n  test('correctly pass hooks to the DevServer', async ({ assert, fs, cleanup }) => {\n    assert.plan(1)\n    await fs.create('bin/server.ts', `process.send({ isAdonisJS: true, environment: 'web' });`)\n\n    await setupTypeScriptProject()\n\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => import(filePath),\n    })\n\n    ace.app.rcFile.hooks = {\n      devServerStarted: [\n        async () => ({\n          default: async () => {\n            assert.isTrue(true)\n          },\n        }),\n      ],\n    }\n\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Serve, ['--no-clear'])\n    cleanup(() => command.devServer.close())\n    await command.exec()\n    await sleep(1200)\n  })\n\n  test('error if --hmr and --watch are used together', async ({ assert, fs }) => {\n    await fs.create('node_modules/ts-node-maintained/esm.js', '')\n\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => import(filePath),\n    })\n\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Serve, ['--hmr', '--watch', '--no-clear'])\n    await command.exec()\n\n    assert.equal(command.exitCode, 1)\n    assert.lengthOf(ace.ui.logger.getLogs(), 1)\n    assert.equal(ace.ui.logger.getLogs()[0].stream, 'stderr')\n    assert.match(ace.ui.logger.getLogs()[0].message, /Cannot use --watch and --hmr flags together/)\n  })\n\n  test('generate barrel file for controllers, events and listeners', async ({\n    assert,\n    fs,\n    cleanup,\n  }) => {\n    await fs.create('bin/server.ts', `process.send({ isAdonisJS: true, environment: 'web' });`)\n    await setupTypeScriptProject()\n\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => import(filePath),\n    })\n\n    ace.app.rcFile.hooks = {\n      init: [indexEntities()],\n    }\n\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Serve, ['--no-clear'])\n    cleanup(() => command.devServer.close())\n    await command.exec()\n\n    assert.snapshot(await fs.contents('.adonisjs/server/controllers.ts')).matchInline(`\n      \"/**\n       * This file is automatically generated.\n       * DO NOT EDIT manually\n       */\n\n      export const controllers = {}\n      \"\n    `)\n    assert.snapshot(await fs.contents('.adonisjs/server/events.ts')).matchInline(`\n      \"/**\n       * This file is automatically generated.\n       * DO NOT EDIT manually\n       */\n\n      export const events = {}\n      \"\n    `)\n    assert.snapshot(await fs.contents('.adonisjs/server/listeners.ts')).matchInline(`\n      \"/**\n       * This file is automatically generated.\n       * DO NOT EDIT manually\n       */\n\n      export const listeners = {}\n      \"\n    `)\n  })\n\n  test('disable listeners and events barrel file generation', async ({ assert, fs, cleanup }) => {\n    await fs.create('bin/server.ts', `process.send({ isAdonisJS: true, environment: 'web' });`)\n    await setupTypeScriptProject()\n\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => import(filePath),\n    })\n\n    ace.app.rcFile.hooks = {\n      init: [indexEntities({ events: { enabled: false }, listeners: { enabled: false } })],\n    }\n\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Serve, ['--no-clear'])\n    cleanup(() => command.devServer.close())\n    await command.exec()\n\n    assert.snapshot(await fs.contents('.adonisjs/server/controllers.ts')).matchInline(`\n      \"/**\n       * This file is automatically generated.\n       * DO NOT EDIT manually\n       */\n\n      export const controllers = {}\n      \"\n    `)\n    await assert.fileNotExists('.adonisjs/server/events.ts')\n    await assert.fileNotExists('.adonisjs/server/listeners.ts')\n  })\n})\n"
  },
  {
    "path": "tests/commands/test.spec.ts",
    "content": "/*\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 { test } from '@japa/runner'\nimport Test from '../../commands/test.ts'\nimport { AceFactory } from '../../factories/core/ace.ts'\nimport { setupTypeScriptProject } from '../helpers.ts'\n\nconst sleep = (duration: number) => new Promise((resolve) => setTimeout(resolve, duration))\n\ntest.group('Test command', () => {\n  test('show error when assembler is not installed', async ({ assert, fs }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        if (filePath === '@adonisjs/assembler') {\n          return import(new URL(filePath, fs.baseUrl).href)\n        }\n\n        return import(filePath)\n      },\n    })\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Test, ['--no-clear'])\n    await command.exec()\n    await sleep(600)\n\n    assert.equal(command.exitCode, 1)\n    assert.lengthOf(ace.ui.logger.getLogs(), 1)\n    assert.equal(ace.ui.logger.getLogs()[0].stream, 'stderr')\n    assert.match(ace.ui.logger.getLogs()[0].message, /Cannot find package \"@adonisjs\\/assembler/)\n  })\n\n  test('fail when bin/test.js file is missing', async ({ assert, fs, cleanup }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        if (filePath === 'typescript') {\n          return import(new URL(filePath, fs.baseUrl).href)\n        }\n\n        return import(filePath)\n      },\n    })\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Test, ['--no-clear'])\n    cleanup(() => command.testsRunner.close())\n    await command.exec()\n\n    await sleep(600)\n    assert.equal(command.exitCode, 1)\n  })\n\n  test('show error in watch mode when tsconfig file is missing', async ({\n    assert,\n    fs,\n    cleanup,\n  }) => {\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        return import(filePath)\n      },\n    })\n    await ace.app.init()\n    ace.ui.switchMode('raw')\n\n    const command = await ace.create(Test, ['--no-clear'])\n    cleanup(() => command.testsRunner.close())\n    command.watch = true\n    await command.exec()\n\n    await sleep(600)\n\n    assert.equal(command.exitCode, 1)\n  })\n\n  test('pass filters to bin/test.js script', async ({ assert, fs, cleanup }) => {\n    await fs.create(\n      'package.json',\n      JSON.stringify({\n        type: 'module',\n      })\n    )\n\n    await fs.create(\n      'bin/test.ts',\n      `\n      import { writeFile } from 'node:fs/promises'\n      await writeFile('argv.json', JSON.stringify(process.argv.splice(2), null, 2))\n    `\n    )\n\n    await setupTypeScriptProject()\n\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        return import(filePath)\n      },\n    })\n\n    ace.ui.switchMode('raw')\n    ace.app.rcFile.tests.suites = [\n      {\n        name: 'unit',\n        files: ['tests/unit/**/*.spec(.js|.ts)'],\n        directories: ['tests/unit'],\n      },\n    ]\n\n    const command = await ace.create(Test, [\n      '--no-clear',\n      '--files=math.spec',\n      '--groups=foo',\n      '--tags=bar',\n      '--tests=\"2 + 2 = 4\"',\n    ])\n    cleanup(() => command.testsRunner.close())\n    await command.exec()\n    await sleep(600)\n\n    await assert.fileEquals(\n      'argv.json',\n      JSON.stringify(\n        ['--files', 'math.spec', '--groups', 'foo', '--tags', 'bar', '--tests', '2 + 2 = 4'],\n        null,\n        2\n      )\n    )\n  })\n\n  test('pass suites to bin/test.js script', async ({ assert, fs, cleanup }) => {\n    await fs.create(\n      'package.json',\n      JSON.stringify({\n        type: 'module',\n      })\n    )\n\n    await fs.create(\n      'bin/test.ts',\n      `\n      import { writeFile } from 'node:fs/promises'\n      await writeFile('argv.json', JSON.stringify(process.argv.splice(2), null, 2))\n    `\n    )\n\n    await setupTypeScriptProject()\n\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        return import(filePath)\n      },\n    })\n\n    ace.ui.switchMode('raw')\n    ace.app.rcFile.tests.suites = [\n      {\n        name: 'unit',\n        files: 'tests/unit/**/*.spec(.js|.ts)',\n        directories: ['tests/unit'],\n      },\n    ]\n\n    const command = await ace.create(Test, ['unit', 'functional', '--no-clear'])\n    cleanup(() => command.testsRunner.close())\n    await command.exec()\n    await sleep(600)\n\n    await assert.fileEquals('argv.json', JSON.stringify(['unit', 'functional'], null, 2))\n  })\n\n  test('pass unknown flags to bin/test.js script', async ({ assert, fs, cleanup }) => {\n    await fs.create(\n      'package.json',\n      JSON.stringify({\n        type: 'module',\n      })\n    )\n\n    await fs.create(\n      'bin/test.ts',\n      `\n      import { writeFile } from 'node:fs/promises'\n      await writeFile('argv.json', JSON.stringify(process.argv.splice(2), null, 2))\n    `\n    )\n\n    await setupTypeScriptProject()\n\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        return import(filePath)\n      },\n    })\n\n    ace.ui.switchMode('raw')\n    ace.app.rcFile.tests.suites = [\n      {\n        name: 'unit',\n        files: 'tests/unit/**/*.spec(.js|.ts)',\n        directories: ['tests/unit'],\n      },\n    ]\n\n    const command = await ace.create(Test, ['--browser=firefox', '--inspect', '--no-clear'])\n    cleanup(() => command.testsRunner.close())\n    await command.exec()\n    await sleep(600)\n\n    await assert.fileEquals(\n      'argv.json',\n      JSON.stringify(['--browser', 'firefox', '--inspect'], null, 2)\n    )\n  })\n\n  test('pass unknown flags with array values to bin/test.js script', async ({\n    assert,\n    fs,\n    cleanup,\n  }) => {\n    await fs.create(\n      'package.json',\n      JSON.stringify({\n        type: 'module',\n      })\n    )\n\n    await fs.create(\n      'bin/test.ts',\n      `\n      import { writeFile } from 'node:fs/promises'\n      await writeFile('argv.json', JSON.stringify(process.argv.splice(2), null, 2))\n    `\n    )\n\n    await setupTypeScriptProject()\n\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        return import(filePath)\n      },\n    })\n\n    ace.ui.switchMode('raw')\n    ace.app.rcFile.tests.suites = [\n      {\n        name: 'unit',\n        files: ['tests/unit/**/*.spec(.js|.ts)'],\n        directories: ['tests/unit'],\n      },\n    ]\n\n    const command = await ace.create(Test, [\n      '--browser=firefox',\n      '--browser=chrome',\n      '--inspect',\n      '--no-clear',\n    ])\n    await command.exec()\n    cleanup(() => command.testsRunner.close())\n    await sleep(600)\n\n    await assert.fileEquals(\n      'argv.json',\n      JSON.stringify(['--browser', 'firefox', '--browser', 'chrome', '--inspect'], null, 2)\n    )\n  })\n\n  test('pass all japa flags to the script', async ({ assert, fs, cleanup }) => {\n    await fs.create(\n      'package.json',\n      JSON.stringify({\n        type: 'module',\n      })\n    )\n\n    await fs.create(\n      'bin/test.ts',\n      `\n      import { writeFile } from 'node:fs/promises'\n      await writeFile('argv.json', JSON.stringify(process.argv.splice(2), null, 2))\n    `\n    )\n\n    await setupTypeScriptProject()\n\n    const ace = await new AceFactory().make(fs.baseUrl, {\n      importer: (filePath) => {\n        return import(filePath)\n      },\n    })\n\n    ace.ui.switchMode('raw')\n    ace.app.rcFile.tests.suites = [\n      {\n        name: 'unit',\n        files: ['tests/unit/**/*.spec(.js|.ts)'],\n        directories: ['tests/unit'],\n      },\n    ]\n\n    const command = await ace.create(Test, [\n      '--no-clear',\n      '--reporters=ndjson,spec',\n      '--failed',\n      '--retries=2',\n      '--timeout=3000',\n    ])\n    cleanup(() => command.testsRunner.close())\n    await command.exec()\n    await sleep(600)\n\n    await assert.fileEquals(\n      'argv.json',\n      JSON.stringify(\n        ['--reporters', 'ndjson,spec', '--timeout', '3000', '--failed', '--retries', '2'],\n        null,\n        2\n      )\n    )\n  })\n})\n"
  },
  {
    "path": "tests/dumper/dumper.spec.ts",
    "content": "/*\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 { test } from '@japa/runner'\nimport { fileURLToPath } from 'node:url'\nimport { AppFactory } from '@adonisjs/application/factories'\nimport { HttpContextFactory } from '@adonisjs/http-server/factories'\n\nimport { Dumper } from '../../modules/dumper/dumper.ts'\nimport { AceFactory } from '../../factories/core/ace.ts'\nimport { E_DUMP_DIE_EXCEPTION } from '../../modules/dumper/errors.ts'\n\ntest.group('Dumper', () => {\n  test('dump and die', ({ fs }) => {\n    const app = new AppFactory().create(fs.baseUrl)\n    const dumper = new Dumper(app)\n\n    dumper.dd('hello')\n  }).throws('Dump and Die exception', E_DUMP_DIE_EXCEPTION)\n\n  test('render dump as HTML', async ({ fs, assert }) => {\n    assert.plan(3)\n    const app = new AppFactory().create(fs.baseUrl)\n    const dumper = new Dumper(app)\n\n    const ctx = new HttpContextFactory().create()\n\n    try {\n      dumper.dd('hello')\n    } catch (error) {\n      await error.handle(error, ctx)\n      assert.include(ctx.response.getBody(), '<style id=\"dumper-styles\">')\n      assert.include(ctx.response.getBody(), '<script id=\"dumper-script\">')\n      assert.include(ctx.response.getBody(), '<script>dumperActivate')\n    }\n  })\n\n  test('render dump as HTML with csp nonce', async ({ fs, assert }) => {\n    assert.plan(3)\n    const app = new AppFactory().create(fs.baseUrl)\n    const dumper = new Dumper(app)\n\n    const ctx = new HttpContextFactory().create()\n    ;(ctx.response as any).nonce = 'inline-code'\n\n    try {\n      dumper.dd('hello')\n    } catch (error) {\n      await error.handle(error, ctx)\n      assert.include(ctx.response.getBody(), '<style id=\"dumper-styles\">')\n      assert.include(ctx.response.getBody(), '<script id=\"dumper-script\" nonce=\"inline-code\">')\n      assert.include(ctx.response.getBody(), '<script nonce=\"inline-code\">dumperActivate')\n    }\n  })\n\n  test('render dump as ansi output', async ({ fs, assert }) => {\n    assert.plan(2)\n    const app = new AppFactory().create(fs.baseUrl)\n    const ace = await new AceFactory().make(fs.baseUrl)\n    ace.ui.switchMode('raw')\n    const dumper = new Dumper(app)\n\n    try {\n      dumper.dd({ hello: 'world' })\n    } catch (error) {\n      await error.render(error, ace)\n\n      assert.lengthOf(ace.ui.logger.getLogs(), 1)\n      assert.include(\n        ace.ui.logger.getLogs()[0].message.toLowerCase(),\n        dumper\n          .dumpToAnsi(\n            { hello: 'world' },\n            {\n              title: 'DUMP DIE',\n              source: {\n                location: fileURLToPath(new URL('', import.meta.url)),\n                line: 70,\n              },\n            }\n          )\n          .toLowerCase()\n      )\n    }\n  })\n})\n"
  },
  {
    "path": "tests/encryption/legacy.spec.ts",
    "content": "/*\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 { test } from '@japa/runner'\nimport { setTimeout } from 'node:timers/promises'\n\nimport type { ApplicationService } from '../../src/types.ts'\nimport { Legacy, legacy } from '../../modules/encryption/drivers/legacy.ts'\nimport { drivers, defineConfig } from '../../modules/encryption/define_config.ts'\n\nconst SECRET_KEY = 'averylongsecretkeythatshouldbe32'\n\ntest.group('Legacy | driver', () => {\n  test('throw error when key is too short', ({ assert }) => {\n    assert.throws(\n      () => new Legacy({ key: 'short' }),\n      'The value of your key should be at least 16 characters long'\n    )\n  })\n\n  test('encrypt and decrypt a string value', ({ assert }) => {\n    const encryption = new Legacy({ key: SECRET_KEY })\n\n    const encrypted = encryption.encrypt('hello world')\n    const decrypted = encryption.decrypt<string>(encrypted)\n\n    assert.equal(decrypted, 'hello world')\n  })\n\n  test('encrypt and decrypt an object', ({ assert }) => {\n    const encryption = new Legacy({ key: SECRET_KEY })\n\n    const payload = { name: 'John', age: 30 }\n    const encrypted = encryption.encrypt(payload)\n    const decrypted = encryption.decrypt<typeof payload>(encrypted)\n\n    assert.deepEqual(decrypted, payload)\n  })\n\n  test('encrypt and decrypt an array', ({ assert }) => {\n    const encryption = new Legacy({ key: SECRET_KEY })\n\n    const payload = [1, 2, 3, 'four', { five: 5 }]\n    const encrypted = encryption.encrypt(payload)\n    const decrypted = encryption.decrypt<typeof payload>(encrypted)\n\n    assert.deepEqual(decrypted, payload)\n  })\n\n  test('encrypt and decrypt a number', ({ assert }) => {\n    const encryption = new Legacy({ key: SECRET_KEY })\n\n    const encrypted = encryption.encrypt(42)\n    const decrypted = encryption.decrypt<number>(encrypted)\n\n    assert.equal(decrypted, 42)\n  })\n\n  test('encrypt and decrypt a boolean', ({ assert }) => {\n    const encryption = new Legacy({ key: SECRET_KEY })\n\n    const encrypted = encryption.encrypt(true)\n    const decrypted = encryption.decrypt<boolean>(encrypted)\n\n    assert.equal(decrypted, true)\n  })\n\n  test('generate different ciphertext for the same value (random IV)', ({ assert }) => {\n    const encryption = new Legacy({ key: SECRET_KEY })\n\n    const encrypted1 = encryption.encrypt('hello')\n    const encrypted2 = encryption.encrypt('hello')\n\n    assert.notEqual(encrypted1, encrypted2)\n  })\n\n  test('return null when decrypting non-string value', ({ assert }) => {\n    const encryption = new Legacy({ key: SECRET_KEY })\n\n    // @ts-expect-error - testing invalid input\n    const decrypted = encryption.decrypt(123)\n\n    assert.isNull(decrypted)\n  })\n\n  test('return null when decrypting invalid format', ({ assert }) => {\n    const encryption = new Legacy({ key: SECRET_KEY })\n\n    const decrypted = encryption.decrypt('invalid')\n\n    assert.isNull(decrypted)\n  })\n\n  test('return null when ciphertext is tampered', ({ assert }) => {\n    const encryption = new Legacy({ key: SECRET_KEY })\n\n    const encrypted = encryption.encrypt('hello')\n    const [cipher, iv, hmac] = encrypted.split('.')\n    const tampered = `${cipher}x.${iv}.${hmac}`\n\n    const decrypted = encryption.decrypt(tampered)\n\n    assert.isNull(decrypted)\n  })\n\n  test('return null when HMAC is tampered', ({ assert }) => {\n    const encryption = new Legacy({ key: SECRET_KEY })\n\n    const encrypted = encryption.encrypt('hello')\n    const [cipher, iv, hmac] = encrypted.split('.')\n    const tampered = `${cipher}.${iv}.${hmac}x`\n\n    const decrypted = encryption.decrypt(tampered)\n\n    assert.isNull(decrypted)\n  })\n\n  test('return null when IV is tampered', ({ assert }) => {\n    const encryption = new Legacy({ key: SECRET_KEY })\n\n    const encrypted = encryption.encrypt('hello')\n    const [cipher, iv, hmac] = encrypted.split('.')\n    const tampered = `${cipher}.${iv}x.${hmac}`\n\n    const decrypted = encryption.decrypt(tampered)\n\n    assert.isNull(decrypted)\n  })\n})\n\ntest.group('Legacy | purpose', () => {\n  test('encrypt and decrypt with a purpose', ({ assert }) => {\n    const encryption = new Legacy({ key: SECRET_KEY })\n\n    const encrypted = encryption.encrypt('hello', undefined, 'login')\n    const decrypted = encryption.decrypt<string>(encrypted, 'login')\n\n    assert.equal(decrypted, 'hello')\n  })\n\n  test('return null when purpose does not match', ({ assert }) => {\n    const encryption = new Legacy({ key: SECRET_KEY })\n\n    const encrypted = encryption.encrypt('hello', undefined, 'login')\n    const decrypted = encryption.decrypt(encrypted, 'different-purpose')\n\n    assert.isNull(decrypted)\n  })\n\n  test('return null when decrypting without purpose but was encrypted with one', ({ assert }) => {\n    const encryption = new Legacy({ key: SECRET_KEY })\n\n    const encrypted = encryption.encrypt('hello', undefined, 'login')\n    const decrypted = encryption.decrypt(encrypted)\n\n    assert.isNull(decrypted)\n  })\n\n  test('return null when decrypting with purpose but was encrypted without one', ({ assert }) => {\n    const encryption = new Legacy({ key: SECRET_KEY })\n\n    const encrypted = encryption.encrypt('hello')\n    const decrypted = encryption.decrypt(encrypted, 'login')\n\n    assert.isNull(decrypted)\n  })\n})\n\ntest.group('Legacy | expiration', () => {\n  test('encrypt with expiration time', async ({ assert }) => {\n    const encryption = new Legacy({ key: SECRET_KEY })\n\n    const encrypted = encryption.encrypt('hello', '100ms')\n    const decrypted = encryption.decrypt<string>(encrypted)\n\n    assert.equal(decrypted, 'hello')\n  })\n\n  test('return null when value has expired', async ({ assert }) => {\n    const encryption = new Legacy({ key: SECRET_KEY })\n\n    const encrypted = encryption.encrypt('hello', '50ms')\n\n    await setTimeout(100)\n\n    const decrypted = encryption.decrypt(encrypted)\n\n    assert.isNull(decrypted)\n  })\n\n  test('encrypt with expiration and purpose using options object', ({ assert }) => {\n    const encryption = new Legacy({ key: SECRET_KEY })\n\n    const encrypted = encryption.encrypt('hello', { expiresIn: '1h', purpose: 'login' })\n    const decrypted = encryption.decrypt<string>(encrypted, 'login')\n\n    assert.equal(decrypted, 'hello')\n  })\n})\n\ntest.group('Legacy | factory', () => {\n  test('legacy factory creates driver correctly', ({ assert }) => {\n    const config = legacy({ keys: [SECRET_KEY] })\n\n    assert.isFunction(config.driver)\n    assert.deepEqual(config.keys, [SECRET_KEY])\n\n    const driver = config.driver(SECRET_KEY)\n    assert.instanceOf(driver, Legacy)\n  })\n\n  test('filter empty keys', async ({ assert }) => {\n    const provider = drivers.legacy({\n      keys: [SECRET_KEY, '', undefined as any, null as any, SECRET_KEY],\n    })\n\n    const config = await provider.resolver({} as ApplicationService)\n\n    assert.deepEqual(config.keys, [SECRET_KEY, SECRET_KEY])\n  })\n})\n\ntest.group('Legacy | backward compatibility', () => {\n  test('decrypt value encrypted with old AdonisJS v6 encryption', ({ assert }) => {\n    const encryption = new Legacy({ key: SECRET_KEY })\n\n    const encryptedByOldSystem =\n      'WtKqAdiMsHKkm8NJ48U8elvrqqlNZF3gbPR0yHqdAEs.cGVBcldtc18tWDlzWHg0Zw.nBYFM-3atE7LnGlqIGTSybo-dv-HNPxnmmOmWzafZYA'\n    const decrypted = encryption.decrypt<string>(encryptedByOldSystem)\n\n    assert.equal(decrypted, 'test')\n  })\n\n  test('decrypt value encrypted with old AdonisJS v6 encryption with purpose', ({ assert }) => {\n    const encryption = new Legacy({ key: SECRET_KEY })\n\n    const encryptedByOldSystem =\n      '7xxhKUhXeeZJ-CnNNh5TFuPQ0jbkhFoaU-YEQCm-vbzC2CQUKSSlvFnNak-ZP6Nt.UURhOWQzb0Fqajh2MU9YVQ.4ktctGpLDjBPWbLMO3zF2Q38Ta8b4UWT2oRETKKp0Dw'\n\n    const decrypted = encryption.decrypt<string>(encryptedByOldSystem, 'blabla')\n    assert.equal(decrypted, 'test')\n\n    const decryptedNoPurpose = encryption.decrypt(encryptedByOldSystem)\n    assert.isNull(decryptedNoPurpose)\n\n    const decryptedWrongPurpose = encryption.decrypt(encryptedByOldSystem, 'wrong')\n    assert.isNull(decryptedWrongPurpose)\n  })\n})\n\ntest.group('Legacy | defineConfig', () => {\n  test('defineConfig with legacy driver', async ({ assert }) => {\n    const configProvider = defineConfig({\n      default: 'legacy',\n      list: {\n        legacy: drivers.legacy({\n          keys: [SECRET_KEY],\n        }),\n      },\n    })\n\n    const config = await configProvider.resolver({} as ApplicationService)\n\n    assert.isDefined(config.list.legacy)\n    assert.isFunction(config.list.legacy.driver)\n    assert.deepEqual(config.list.legacy.keys, [SECRET_KEY])\n  })\n})\n\ntest.group('Legacy | blind indexes', () => {\n  test('throw when computing blind index', ({ assert }) => {\n    const encryption = new Legacy({ key: SECRET_KEY })\n\n    assert.throws(\n      () => encryption.blindIndex('foo@example.com', 'users.email'),\n      'Blind indexes are not supported by the \"legacy\" encryption driver'\n    )\n  })\n\n  test('throw when computing blind indexes', ({ assert }) => {\n    const encryption = new Legacy({ key: SECRET_KEY })\n\n    assert.throws(\n      () => encryption.blindIndexes('foo@example.com', 'users.email'),\n      'Blind indexes are not supported by the \"legacy\" encryption driver'\n    )\n  })\n})\n"
  },
  {
    "path": "tests/hash.spec.ts",
    "content": "/*\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 { test } from '@japa/runner'\n\nimport { Argon } from '../modules/hash/drivers/argon.ts'\nimport type { ApplicationService } from '../src/types.ts'\nimport { Bcrypt } from '../modules/hash/drivers/bcrypt.ts'\nimport { drivers } from '../modules/hash/define_config.ts'\nimport { Scrypt } from '../modules/hash/drivers/scrypt.ts'\nimport { IgnitorFactory } from '../factories/core/ignitor.ts'\nimport { Hash, HashManager, defineConfig } from '../modules/hash/main.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\n\ntest.group('Hash | drivers', () => {\n  test('define driver provider', async ({ assert, expectTypeOf }) => {\n    const scryptProvider = drivers.scrypt({})\n    const scryptFactory = await scryptProvider.resolver({} as ApplicationService)\n\n    assert.isFunction(scryptFactory)\n    assert.instanceOf(scryptFactory(), Scrypt)\n    expectTypeOf(scryptFactory).returns.toMatchTypeOf<Scrypt>()\n\n    const bcryptProvider = drivers.bcrypt({})\n    const bcryptFactory = await bcryptProvider.resolver({} as ApplicationService)\n\n    assert.isFunction(bcryptFactory)\n    assert.instanceOf(bcryptFactory(), Bcrypt)\n    expectTypeOf(bcryptFactory).returns.toMatchTypeOf<Bcrypt>()\n\n    const argonProvider = drivers.argon2({})\n    const argonFactory = await argonProvider.resolver({} as ApplicationService)\n\n    assert.isFunction(argonFactory)\n    assert.instanceOf(argonFactory(), Argon)\n    expectTypeOf(argonFactory).returns.toMatchTypeOf<Argon>()\n  })\n})\n\ntest.group('Hash | defineConfig', () => {\n  test('defineConfig to lazily register hash drivers', async ({ assert, expectTypeOf }) => {\n    const configProvider = defineConfig({\n      list: {\n        scrypt: drivers.scrypt({}),\n      },\n    })\n\n    const config = await configProvider.resolver({} as ApplicationService)\n    expectTypeOf(config).toMatchTypeOf<{\n      default?: 'scrypt'\n      list: {\n        scrypt: () => Scrypt\n      }\n    }>()\n\n    const hash = new HashManager(config)\n    assert.instanceOf(hash.use('scrypt'), Hash)\n    expectTypeOf(hash.use).parameters.toMatchTypeOf<['scrypt'?]>()\n  })\n\n  test('raise error when list is not defined', async ({ assert }) => {\n    // @ts-expect-error\n    assert.throws(() => defineConfig({}), 'Missing \"list\" property in hash config')\n  })\n\n  test('raise error when default hasher is not defined in the list', async ({ assert }) => {\n    assert.throws(\n      () =>\n        defineConfig({\n          // @ts-expect-error\n          default: 'scrypt',\n          list: {},\n        }),\n      'Missing \"list.scrypt\" in hash config. It is referenced by the \"default\" property'\n    )\n  })\n})\n\ntest.group('Hash | provider', () => {\n  test('create instance of drivers registered in config file', async ({ assert }) => {\n    const ignitor = new IgnitorFactory()\n      .merge({\n        config: {\n          hash: defineConfig({\n            default: 'bcrypt',\n            list: {\n              bcrypt: drivers.bcrypt({}),\n            },\n          }),\n        },\n        rcFileContents: {\n          providers: [\n            () => import('../providers/app_provider.js'),\n            () => import('../providers/hash_provider.js'),\n          ],\n        },\n      })\n      .create(BASE_URL)\n\n    const app = ignitor.createApp('web')\n    await app.init()\n    await app.boot()\n\n    const hash = await app.container.make('hash')\n\n    assert.instanceOf(hash.use('bcrypt'), Hash)\n    assert.throws(() => hash.use('scrypt'), 'driverFactory is not a function')\n    assert.throws(() => hash.use('argon2'), 'driverFactory is not a function')\n  })\n})\n"
  },
  {
    "path": "tests/helpers.spec.ts",
    "content": "/*\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 { test } from '@japa/runner'\nimport StringBuilder from '@poppinss/utils/string_builder'\nimport stringHelpers from '../src/helpers/string.ts'\n\ntest.group('String helpers', () => {\n  test('check if string is empty', ({ assert }) => {\n    assert.isTrue(stringHelpers.isEmpty(''))\n    assert.isTrue(stringHelpers.isEmpty('    '))\n  })\n\n  test('escape html entities', ({ assert }) => {\n    assert.equal(stringHelpers.escapeHTML('<p> foo © bar </p>'), '&lt;p&gt; foo © bar &lt;/p&gt;')\n  })\n\n  test('escape html entities and encode symbols', ({ assert }) => {\n    assert.equal(\n      stringHelpers.escapeHTML('<p> foo © bar </p>', { encodeSymbols: true }),\n      '&lt;p&gt; foo &#xA9; bar &lt;/p&gt;'\n    )\n  })\n\n  test('prettify hrtime', async ({ assert }) => {\n    const startTime = process.hrtime()\n    await new Promise((resolve) => setTimeout(resolve, 1200))\n    const endTime = process.hrtime(startTime)\n\n    assert.match(stringHelpers.prettyHrTime(endTime), /^\\d(\\.\\d+)? s$/)\n  })\n\n  test('create string builder instance', async ({ assert }) => {\n    assert.instanceOf(stringHelpers.create('foo'), StringBuilder)\n  })\n})\n"
  },
  {
    "path": "tests/helpers.ts",
    "content": "/*\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 { test } from '@japa/runner'\nimport { type FileSystem } from '@japa/file-system'\n\n/**\n * Setup a TypeScript project by creating a \"tsconfig.json\" file and\n * \"@poppinss/ts-exec\" package within the node_modules.\n *\n * The \"@poppinss/ts-exec\" package is setup in a way to prevent missing module\n * errors. However, it does not offer actual runtime functionality.\n */\nexport const setupTypeScriptProject = test.macro(async ({ context }) => {\n  const { fs } = context\n\n  await fs.create(\n    'tsconfig.json',\n    JSON.stringify({\n      include: ['**/*'],\n    })\n  )\n\n  await fs.create(\n    'node_modules/@poppinss/ts-exec/package.json',\n    JSON.stringify({\n      name: '@poppinss/ts-exec',\n      exports: { '.': './index.js' },\n    })\n  )\n\n  await fs.create('node_modules/@poppinss/ts-exec/index.js', '')\n})\n\n/**\n * Setup a fake adonis project in the file system\n */\nexport async function setupProject(\n  fs: FileSystem,\n  pkgManager?: 'npm' | 'pnpm' | 'yarn' | 'yarn@berry'\n) {\n  await fs.create(\n    'package.json',\n    JSON.stringify({ type: 'module', name: 'test', dependencies: {} })\n  )\n\n  if (pkgManager === 'pnpm') {\n    await fs.create('pnpm-lock.yaml', '')\n  } else if (pkgManager === 'yarn' || pkgManager === 'yarn@berry') {\n    await fs.create('yarn.lock', '')\n  } else {\n    await fs.create('package-lock.json', '')\n  }\n\n  await fs.create('tsconfig.json', JSON.stringify({ compilerOptions: {} }))\n  await fs.create('adonisrc.ts', `export default defineConfig({})`)\n  await fs.create('start/env.ts', `export default Env.create(new URL('./'), {})`)\n  await fs.create('start/kernel.ts', `export default Env.create(new URL('./'), {})`)\n  await fs.create('.env', '')\n}\n\n/**\n * Setup a fake package inside the node_modules directory\n */\nexport async function setupPackage(fs: FileSystem, configureContent?: string) {\n  await setupNamedPackage(fs, { name: 'foo', configureContent })\n}\n\n/**\n * Setup a fake package with a custom name inside the packages directory\n */\nexport async function setupNamedPackage(\n  fs: FileSystem,\n  options: { name: string; configureContent?: string }\n) {\n  await fs.create(\n    `packages/${options.name}/package.json`,\n    JSON.stringify({\n      type: 'module',\n      name: `@adonisjs/${options.name}`,\n      main: 'index.js',\n      dependencies: {},\n    })\n  )\n\n  await fs.create(\n    `packages/${options.name}/index.js`,\n    `export const stubsRoot = './'\n     export async function configure(command) { ${options.configureContent ?? ''} }`\n  )\n}\n"
  },
  {
    "path": "tests/ignitor/ace_process.spec.ts",
    "content": "/*\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 { test } from '@japa/runner'\nimport { ListLoader } from '../../modules/ace/main.ts'\nimport type { CommandOptions } from '../../types/ace.ts'\nimport { BaseCommand } from '../../modules/ace/commands.ts'\nimport { IgnitorFactory } from '../../factories/core/ignitor.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\n\ntest.group('Ignitor | Ace process', (group) => {\n  group.each.setup(() => {\n    return () => {\n      process.exitCode = undefined\n    }\n  })\n\n  test('run command', async ({ cleanup, assert }) => {\n    cleanup(async () => {\n      await ignitor.terminate()\n    })\n\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    let greetCommandExecuted = false\n    class Greet extends BaseCommand {\n      static commandName: string = 'greet'\n      async run() {\n        greetCommandExecuted = true\n      }\n    }\n\n    await ignitor\n      .ace()\n      .configure(async (app) => {\n        const kernel = await app.container.make('ace')\n        kernel.addLoader(new ListLoader([Greet]))\n      })\n      .handle(['greet'])\n\n    assert.isTrue(greetCommandExecuted)\n    assert.equal(process.exitCode, 0)\n    assert.equal(ignitor.getApp()?.getEnvironment(), 'console')\n    assert.equal(ignitor.getApp()?.getState(), 'terminated')\n  })\n\n  test('start app when command needs app', async ({ cleanup, assert }) => {\n    cleanup(async () => {\n      await ignitor.terminate()\n    })\n\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    let greetCommandExecuted = false\n    class Greet extends BaseCommand {\n      static commandName: string = 'greet'\n      static options: CommandOptions = {\n        startApp: true,\n      }\n\n      async run() {\n        greetCommandExecuted = true\n        assert.equal(this.app.getState(), 'ready')\n      }\n    }\n\n    await ignitor\n      .ace()\n      .configure(async (app) => {\n        const kernel = await app.container.make('ace')\n        kernel.addLoader(new ListLoader([Greet]))\n      })\n      .handle(['greet'])\n\n    assert.isTrue(greetCommandExecuted)\n    assert.equal(process.exitCode, 0)\n    assert.equal(ignitor.getApp()?.getState(), 'terminated')\n  })\n\n  test('exit with status = 1 when command raises an exception', async ({ cleanup, assert }) => {\n    cleanup(async () => {\n      process.exitCode = undefined\n      await ignitor.terminate()\n    })\n\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    class Greet extends BaseCommand {\n      static commandName: string = 'greet'\n      async run() {\n        throw new Error('failed')\n      }\n    }\n\n    await ignitor\n      .ace()\n      .configure(async (app) => {\n        const kernel = await app.container.make('ace')\n        kernel.addLoader(new ListLoader([Greet]))\n      })\n      .handle(['greet'])\n\n    assert.equal(process.exitCode, 1)\n  })\n\n  test('exit with status = 1 when command exitCode = 1', async ({ cleanup, assert }) => {\n    cleanup(async () => {\n      process.exitCode = undefined\n      await ignitor.terminate()\n    })\n\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    class Greet extends BaseCommand {\n      static commandName: string = 'greet'\n      async run() {\n        this.exitCode = 1\n      }\n    }\n\n    await ignitor\n      .ace()\n      .configure(async (app) => {\n        const kernel = await app.container.make('ace')\n        kernel.addLoader(new ListLoader([Greet]))\n      })\n      .handle(['greet'])\n\n    assert.equal(process.exitCode, 1)\n  })\n\n  test('wait for command to terminate in stayAlive mode', async ({ cleanup, assert }) => {\n    cleanup(async () => {\n      await ignitor.terminate()\n    })\n\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    let greetCommandExecuted = false\n    class Greet extends BaseCommand {\n      static commandName: string = 'greet'\n      static options = {\n        staysAlive: true,\n      }\n\n      async run() {\n        greetCommandExecuted = true\n      }\n    }\n\n    await ignitor\n      .ace()\n      .configure(async (app) => {\n        const kernel = await app.container.make('ace')\n        kernel.addLoader(new ListLoader([Greet]))\n      })\n      .handle(['greet'])\n\n    assert.isTrue(greetCommandExecuted)\n    assert.equal(ignitor.getApp()?.getEnvironment(), 'console')\n    assert.isUndefined(process.exitCode)\n    assert.equal(ignitor.getApp()?.getState(), 'initiated')\n\n    const kernel = await ignitor.getApp()!.container.make('ace')\n    await kernel.getMainCommand()?.terminate()\n\n    assert.equal(process.exitCode, 0)\n    assert.equal(ignitor.getApp()?.getState(), 'terminated')\n  })\n\n  test('fail when command exits with an error in staysAlive mode', async ({ cleanup, assert }) => {\n    cleanup(async () => {\n      await ignitor.terminate()\n    })\n\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    let greetCommandExecuted = false\n    class Greet extends BaseCommand {\n      static commandName: string = 'greet'\n      static options = {\n        staysAlive: true,\n      }\n\n      async run() {\n        greetCommandExecuted = true\n      }\n    }\n\n    await ignitor\n      .ace()\n      .configure(async (app) => {\n        const kernel = await app.container.make('ace')\n        kernel.addLoader(new ListLoader([Greet]))\n      })\n      .handle(['greet'])\n\n    assert.isTrue(greetCommandExecuted)\n    assert.equal(ignitor.getApp()?.getEnvironment(), 'console')\n    assert.isUndefined(process.exitCode)\n    assert.equal(ignitor.getApp()?.getState(), 'initiated')\n\n    const kernel = await ignitor.getApp()!.container.make('ace')\n    const mainCommand = kernel.getMainCommand()!\n    mainCommand.exitCode = 1\n    await mainCommand.terminate()\n\n    assert.equal(process.exitCode, 1)\n    assert.equal(ignitor.getApp()?.getState(), 'terminated')\n  })\n\n  test('set process.exitCode when staysAlive command calls app.terminate() during execution', async ({\n    cleanup,\n    assert,\n  }) => {\n    cleanup(async () => {\n      process.exitCode = undefined\n      await ignitor.terminate()\n    })\n\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    class Greet extends BaseCommand {\n      static commandName: string = 'greet'\n      static options = {\n        staysAlive: true,\n      }\n\n      async run() {\n        this.exitCode = 1\n        await this.app.terminate()\n      }\n    }\n\n    await ignitor\n      .ace()\n      .configure(async (app) => {\n        const kernel = await app.container.make('ace')\n        kernel.addLoader(new ListLoader([Greet]))\n      })\n      .handle(['greet'])\n\n    assert.equal(process.exitCode, 1)\n    assert.equal(ignitor.getApp()?.getState(), 'terminated')\n  })\n\n  test('switch app environment to repl when running repl command', async ({ cleanup, assert }) => {\n    cleanup(async () => {\n      await ignitor.terminate()\n    })\n\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    class CustomRepl extends BaseCommand {\n      static commandName: string = 'repl'\n      static options = {\n        startApp: true,\n      }\n\n      async run() {}\n    }\n\n    await ignitor\n      .ace()\n      .configure(async (app) => {\n        const kernel = await app.container.make('ace')\n        kernel.addLoader(new ListLoader([CustomRepl]))\n      })\n      .handle(['repl'])\n\n    assert.equal(process.exitCode, 0)\n    assert.equal(ignitor.getApp()?.getEnvironment(), 'repl')\n    assert.equal(ignitor.getApp()?.getState(), 'terminated')\n  })\n})\n"
  },
  {
    "path": "tests/ignitor/http_server_process.spec.ts",
    "content": "/*\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 getPort from 'get-port'\nimport supertest from 'supertest'\nimport { test } from '@japa/runner'\nimport { createServer } from 'node:http'\nimport { fileURLToPath } from 'node:url'\n\nimport type { ApplicationService } from '../../src/types.ts'\nimport { IgnitorFactory } from '../../factories/core/ignitor.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\nconst BASE_PATH = fileURLToPath(BASE_URL)\n\ntest.group('Ignitor | Http server process', (group) => {\n  group.each.setup(($test) => {\n    $test.context.fs.basePath = BASE_PATH\n    $test.context.fs.baseUrl = BASE_URL\n  })\n\n  test('start http server using the http server process', async ({ assert, cleanup }) => {\n    cleanup(async () => {\n      delete process.env.HOST\n      delete process.env.PORT\n      await ignitor.terminate()\n    })\n\n    process.env.HOST = 'localhost'\n    process.env.PORT = String(await getPort())\n    const serverURL = `http://${process.env.HOST}:${process.env.PORT}`\n\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .withCoreConfig()\n      .preload(async (app) => {\n        const router = await app.container.make('router')\n        router.get('/', () => {\n          return 'hello world'\n        })\n      })\n      .create(BASE_URL)\n\n    await ignitor.httpServer().start()\n\n    const { text } = await supertest(serverURL).get('/')\n    assert.equal(text, 'hello world')\n  })\n\n  test('use port 3333 when PORT env variable is not defined', async ({ assert, cleanup }) => {\n    cleanup(async () => {\n      await ignitor.terminate()\n    })\n\n    const serverURL = 'http://127.0.0.1:3333'\n\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .withCoreConfig()\n      .preload(async (app) => {\n        const router = await app.container.make('router')\n        router.get('/', () => {\n          return 'hello world'\n        })\n      })\n      .create(BASE_URL)\n\n    await ignitor.httpServer().start()\n\n    const { text } = await supertest(serverURL).get('/')\n    assert.equal(text, 'hello world')\n  })\n\n  test('shutdown server when app terminates', async ({ assert, cleanup }) => {\n    let app: ApplicationService\n\n    cleanup(async () => {\n      delete process.env.HOST\n      delete process.env.PORT\n    })\n\n    process.env.HOST = 'localhost'\n    process.env.PORT = String(await getPort())\n\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    ignitor.tap((application) => {\n      app = application\n    })\n\n    await ignitor.httpServer().start()\n    const server = await app!.container.make('server')\n    assert.isTrue(server.getNodeServer()!.listening)\n\n    await ignitor.terminate()\n    assert.isFalse(server.getNodeServer()!.listening)\n  })\n\n  test('throw error if port is already in use', async ({ assert, cleanup }) => {\n    const nodeServer = createServer(() => {})\n\n    cleanup(async () => {\n      delete process.env.HOST\n      delete process.env.PORT\n      nodeServer.close()\n    })\n\n    process.env.HOST = 'localhost'\n    process.env.PORT = String(await getPort())\n\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    await new Promise<void>((resolve) => {\n      nodeServer.listen(Number(process.env.PORT), process.env.HOST, () => {\n        resolve()\n      })\n    })\n\n    await assert.rejects(\n      () => ignitor.httpServer().start(),\n      /listen EADDRINUSE: address already in use/\n    )\n  })\n\n  test('terminate app if server crashes after starting', async ({ cleanup, assert }, done) => {\n    let app: ApplicationService\n    cleanup(async () => {\n      process.exitCode = undefined\n      delete process.env.HOST\n      delete process.env.PORT\n    })\n\n    process.env.HOST = 'localhost'\n    process.env.PORT = String(await getPort())\n\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    ignitor.tap((application) => {\n      app = application\n    })\n\n    await ignitor.httpServer().start()\n    app!.terminating(() => {\n      done()\n    })\n\n    const server = await app!.container.make('server')\n    server.getNodeServer()!.emit('error', new Error('crash'))\n    assert.equal(process.exitCode, 1)\n  }).waitForDone()\n})\n"
  },
  {
    "path": "tests/ignitor/main.spec.ts",
    "content": "/*\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 { test } from '@japa/runner'\nimport { Ignitor } from '../../index.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\n\ntest.group('Ignitor', () => {\n  test('create app instance using the ignitor', async ({ assert }) => {\n    const app = new Ignitor(BASE_URL).createApp('web')\n    assert.equal(app.getState(), 'created')\n  })\n\n  test('tap into application instance using the tap method', async ({ assert }) => {\n    assert.plan(2)\n\n    const ignitor = new Ignitor(BASE_URL)\n    ignitor.tap((app) => {\n      assert.equal(app.getState(), 'created')\n    })\n\n    const app = ignitor.createApp('web')\n    assert.equal(app.getState(), 'created')\n  })\n})\n"
  },
  {
    "path": "tests/ignitor/test_process.spec.ts",
    "content": "/*\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 { test } from '@japa/runner'\nimport { IgnitorFactory } from '../../factories/core/ignitor.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\n\ntest.group('Ignitor | Test process', () => {\n  test('start application in test environment', async ({ cleanup, assert }) => {\n    cleanup(async () => {\n      await ignitor.terminate()\n    })\n\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n    await ignitor.testRunner().run(() => {})\n    assert.equal(ignitor.getApp()?.getEnvironment(), 'test')\n    assert.equal(ignitor.getApp()?.getState(), 'ready')\n  })\n\n  test('call configure method before starting the app', async ({ cleanup, assert }) => {\n    cleanup(async () => {\n      await ignitor.terminate()\n    })\n\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    await ignitor\n      .testRunner()\n      .configure((app) => {\n        assert.equal(app.getState(), 'booted')\n      })\n      .run(() => {})\n    assert.equal(ignitor.getApp()?.getEnvironment(), 'test')\n    assert.equal(ignitor.getApp()?.getState(), 'ready')\n  })\n})\n"
  },
  {
    "path": "tests/index_generator.spec.ts",
    "content": "/*\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 { test } from '@japa/runner'\nimport { Kernel } from '@adonisjs/ace'\nimport { IndexGenerator } from '@adonisjs/assembler/index_generator'\n\nimport stringHelpers from '../src/helpers/string.ts'\nimport { indexEntities } from '../src/assembler_hooks/index_entities.ts'\n\ntest.group('Index generator', () => {\n  test('generate controllers index', async ({ assert, fs }) => {\n    const cliUi = Kernel.create().ui\n    cliUi.switchMode('raw')\n\n    await fs.create('app/controllers/users_controller.ts', '')\n    await fs.create('app/controllers/blog/posts_controller.ts', '')\n\n    const generator = new IndexGenerator(stringHelpers.toUnixSlash(fs.basePath), cliUi.logger)\n    const indexer = indexEntities({\n      controllers: {\n        enabled: true,\n      },\n      events: {\n        enabled: false,\n      },\n      listeners: {\n        enabled: false,\n      },\n      transformers: {\n        enabled: false,\n      },\n    })\n\n    indexer.run({} as any, {} as any, generator)\n    await generator.generate()\n\n    await assert.fileExists('.adonisjs/server/controllers.ts')\n    await assert.fileContains('.adonisjs/server/controllers.ts', [\n      `export const controllers = {`,\n      `Users: () => import('#controllers/users_controller')`,\n      `Posts: () => import('#controllers/blog/posts_controller')`,\n    ])\n    assert.isDefined(\n      cliUi.logger\n        .getLogs()\n        .find(({ message }) => message.includes('[ blue(info) ] codegen: created'))\n    )\n  })\n\n  test('generate events index', async ({ assert, fs }) => {\n    const cliUi = Kernel.create().ui\n    cliUi.switchMode('raw')\n\n    await fs.create('app/events/user_registered.ts', '')\n    await fs.create('app/events/billing/invoice_created.ts', '')\n\n    const generator = new IndexGenerator(stringHelpers.toUnixSlash(fs.basePath), cliUi.logger)\n    const indexer = indexEntities({\n      controllers: {\n        enabled: false,\n      },\n      events: {\n        enabled: true,\n      },\n      listeners: {\n        enabled: false,\n      },\n      transformers: {\n        enabled: false,\n      },\n    })\n\n    indexer.run({} as any, {} as any, generator)\n    await generator.generate()\n\n    await assert.fileExists('.adonisjs/server/events.ts')\n    await assert.fileContains('.adonisjs/server/events.ts', [\n      `import BillingInvoiceCreated from '#events/billing/invoice_created'`,\n      `import UserRegistered from '#events/user_registered'`,\n      `export const events = {`,\n      `UserRegistered: UserRegistered`,\n      `InvoiceCreated: BillingInvoiceCreated`,\n    ])\n    assert.isDefined(\n      cliUi.logger\n        .getLogs()\n        .find(({ message }) => message.includes('[ blue(info) ] codegen: created'))\n    )\n  })\n\n  test('generate listeners index', async ({ assert, fs }) => {\n    const cliUi = Kernel.create().ui\n    cliUi.switchMode('raw')\n\n    await fs.create('app/listeners/send_welcome_email.ts', '')\n    await fs.create('app/listeners/billing/send_invoice.ts', '')\n\n    const generator = new IndexGenerator(stringHelpers.toUnixSlash(fs.basePath), cliUi.logger)\n    const indexer = indexEntities({\n      controllers: {\n        enabled: false,\n      },\n      events: {\n        enabled: false,\n      },\n      listeners: {\n        enabled: true,\n      },\n      transformers: {\n        enabled: false,\n      },\n    })\n\n    indexer.run({} as any, {} as any, generator)\n    await generator.generate()\n\n    await assert.fileExists('.adonisjs/server/listeners.ts')\n    await assert.fileContains('.adonisjs/server/listeners.ts', [\n      `export const listeners = {`,\n      `SendWelcomeEmail: () => import('#listeners/send_welcome_email')`,\n      `SendInvoice: () => import('#listeners/billing/send_invoice')`,\n    ])\n    assert.isDefined(\n      cliUi.logger\n        .getLogs()\n        .find(({ message }) => message.includes('[ blue(info) ] codegen: created'))\n    )\n  })\n\n  test('generate transformers index', async ({ assert, fs }) => {\n    const cliUi = Kernel.create().ui\n    cliUi.switchMode('raw')\n\n    await fs.create('app/transformers/user_transformer.ts', '')\n    await fs.create('app/transformers/blog/post_transformer.ts', '')\n\n    const generator = new IndexGenerator(stringHelpers.toUnixSlash(fs.basePath), cliUi.logger)\n    const indexer = indexEntities({\n      controllers: {\n        enabled: false,\n      },\n      events: {\n        enabled: false,\n      },\n      listeners: {\n        enabled: false,\n      },\n      transformers: {\n        enabled: true,\n      },\n    })\n\n    indexer.run({} as any, {} as any, generator)\n    await generator.generate()\n\n    await assert.fileExists('.adonisjs/client/data.d.ts')\n    assert.snapshot(await fs.contents('.adonisjs/client/data.d.ts')).matchInline(`\n      \"/**\n       * This file is automatically generated.\n       * DO NOT EDIT manually\n       */\n\n      /// <reference path=\\\\\"./manifest.d.ts\\\\\" />\n      import type { InferData, InferVariants } from '@adonisjs/core/types/transformers'\n      import type BlogPostTransformer from '#transformers/blog/post_transformer'\n      import type UserTransformer from '#transformers/user_transformer'\n\n      export namespace Data {\n        export namespace Blog {\n          export type Post = InferData<BlogPostTransformer>\n          export namespace Post {\n            export type Variants = InferVariants<BlogPostTransformer>\n          }\n        }\n        export type User = InferData<UserTransformer>\n        export namespace User {\n          export type Variants = InferVariants<UserTransformer>\n        }\n      }\n      \"\n    `)\n    assert.isDefined(\n      cliUi.logger\n        .getLogs()\n        .find(({ message }) => message.includes('[ blue(info) ] codegen: created'))\n    )\n  })\n\n  test('generate transformers index with shared props', async ({ assert, fs }) => {\n    const cliUi = Kernel.create().ui\n    cliUi.switchMode('raw')\n\n    await fs.create('app/transformers/user_transformer.ts', '')\n    await fs.create('app/transformers/blog/post_transformer.ts', '')\n\n    const generator = new IndexGenerator(stringHelpers.toUnixSlash(fs.basePath), cliUi.logger)\n    const indexer = indexEntities({\n      controllers: {\n        enabled: false,\n      },\n      events: {\n        enabled: false,\n      },\n      listeners: {\n        enabled: false,\n      },\n      transformers: {\n        enabled: true,\n        withSharedProps: true,\n      },\n    })\n\n    indexer.run({} as any, {} as any, generator)\n    await generator.generate()\n\n    await assert.fileExists('.adonisjs/client/data.d.ts')\n    assert.snapshot(await fs.contents('.adonisjs/client/data.d.ts')).matchInline(`\n      \"/**\n       * This file is automatically generated.\n       * DO NOT EDIT manually\n       */\n\n      /// <reference path=\\\\\"./manifest.d.ts\\\\\" />\n      import type { InferData, InferVariants } from '@adonisjs/core/types/transformers'\n      import type { InferSharedProps } from '@adonisjs/inertia/types'\n      import type BlogPostTransformer from '#transformers/blog/post_transformer'\n      import type UserTransformer from '#transformers/user_transformer'\n      import type InertiaMiddleware from '#middleware/inertia_middleware'\n\n      export namespace Data {\n        export namespace Blog {\n          export type Post = InferData<BlogPostTransformer>\n          export namespace Post {\n            export type Variants = InferVariants<BlogPostTransformer>\n          }\n        }\n        export type User = InferData<UserTransformer>\n        export namespace User {\n          export type Variants = InferVariants<UserTransformer>\n        }\n        export type SharedProps = InferSharedProps<InertiaMiddleware>\n      }\n      \"\n    `)\n    assert.isDefined(\n      cliUi.logger\n        .getLogs()\n        .find(({ message }) => message.includes('[ blue(info) ] codegen: created'))\n    )\n  })\n\n  test('generate transformers index with shared props and custom inertia middleware import path', async ({\n    assert,\n    fs,\n  }) => {\n    const cliUi = Kernel.create().ui\n    cliUi.switchMode('raw')\n\n    await fs.create('app/transformers/user_transformer.ts', '')\n    await fs.create('app/transformers/blog/post_transformer.ts', '')\n\n    const generator = new IndexGenerator(stringHelpers.toUnixSlash(fs.basePath), cliUi.logger)\n    const indexer = indexEntities({\n      controllers: {\n        enabled: false,\n      },\n      events: {\n        enabled: false,\n      },\n      listeners: {\n        enabled: false,\n      },\n      transformers: {\n        enabled: true,\n        withSharedProps: true,\n        inertiaMiddlewareImportPath: '#core/middleware/inertia_middleware',\n      },\n    })\n\n    indexer.run({} as any, {} as any, generator)\n    await generator.generate()\n\n    await assert.fileExists('.adonisjs/client/data.d.ts')\n    assert.snapshot(await fs.contents('.adonisjs/client/data.d.ts')).matchInline(`\n      \"/**\n       * This file is automatically generated.\n       * DO NOT EDIT manually\n       */\n\n      /// <reference path=\\\\\"./manifest.d.ts\\\\\" />\n      import type { InferData, InferVariants } from '@adonisjs/core/types/transformers'\n      import type { InferSharedProps } from '@adonisjs/inertia/types'\n      import type BlogPostTransformer from '#transformers/blog/post_transformer'\n      import type UserTransformer from '#transformers/user_transformer'\n      import type InertiaMiddleware from '#core/middleware/inertia_middleware'\n\n      export namespace Data {\n        export namespace Blog {\n          export type Post = InferData<BlogPostTransformer>\n          export namespace Post {\n            export type Variants = InferVariants<BlogPostTransformer>\n          }\n        }\n        export type User = InferData<UserTransformer>\n        export namespace User {\n          export type Variants = InferVariants<UserTransformer>\n        }\n        export type SharedProps = InferSharedProps<InertiaMiddleware>\n      }\n      \"\n    `)\n    assert.isDefined(\n      cliUi.logger\n        .getLogs()\n        .find(({ message }) => message.includes('[ blue(info) ] codegen: created'))\n    )\n  })\n\n  test('generate transformers index with deeply nested directories', async ({ assert, fs }) => {\n    const cliUi = Kernel.create().ui\n    cliUi.switchMode('raw')\n\n    await fs.create('app/transformers/identity/auth/login_transformer.ts', '')\n    await fs.create('app/transformers/billing/invoices/invoice_transformer.ts', '')\n\n    const generator = new IndexGenerator(stringHelpers.toUnixSlash(fs.basePath), cliUi.logger)\n    const indexer = indexEntities({\n      controllers: {\n        enabled: false,\n      },\n      events: {\n        enabled: false,\n      },\n      listeners: {\n        enabled: false,\n      },\n      transformers: {\n        enabled: true,\n      },\n    })\n\n    indexer.run({} as any, {} as any, generator)\n    await generator.generate()\n\n    await assert.fileExists('.adonisjs/client/data.d.ts')\n    assert.snapshot(await fs.contents('.adonisjs/client/data.d.ts')).matchInline(`\n      \"/**\n       * This file is automatically generated.\n       * DO NOT EDIT manually\n       */\n\n      /// <reference path=\\\\\"./manifest.d.ts\\\\\" />\n      import type { InferData, InferVariants } from '@adonisjs/core/types/transformers'\n      import type BillingInvoicesInvoiceTransformer from '#transformers/billing/invoices/invoice_transformer'\n      import type IdentityAuthLoginTransformer from '#transformers/identity/auth/login_transformer'\n\n      export namespace Data {\n        export namespace Billing {\n          export namespace Invoices {\n            export type Invoice = InferData<BillingInvoicesInvoiceTransformer>\n            export namespace Invoice {\n              export type Variants = InferVariants<BillingInvoicesInvoiceTransformer>\n            }\n          }\n        }\n        export namespace Identity {\n          export namespace Auth {\n            export type Login = InferData<IdentityAuthLoginTransformer>\n            export namespace Login {\n              export type Variants = InferVariants<IdentityAuthLoginTransformer>\n            }\n          }\n        }\n      }\n      \"\n    `)\n  })\n\n  test('skip segments from controllers index with module-based folder structure', async ({\n    assert,\n    fs,\n  }) => {\n    const cliUi = Kernel.create().ui\n    cliUi.switchMode('raw')\n\n    await fs.create('app/identity/controllers/auth_controller.ts', '')\n    await fs.create('app/identity/controllers/users_controller.ts', '')\n    await fs.create('app/billing/controllers/invoices_controller.ts', '')\n\n    const generator = new IndexGenerator(stringHelpers.toUnixSlash(fs.basePath), cliUi.logger)\n    const indexer = indexEntities({\n      controllers: {\n        enabled: true,\n        source: 'app',\n        glob: ['**/controllers/*_controller.ts'],\n        importAlias: '#app',\n      },\n      events: {\n        enabled: false,\n      },\n      listeners: {\n        enabled: false,\n      },\n      transformers: {\n        enabled: false,\n      },\n    })\n\n    indexer.run({} as any, {} as any, generator)\n    await generator.generate()\n\n    await assert.fileExists('.adonisjs/server/controllers.ts')\n    assert.snapshot(await fs.contents('.adonisjs/server/controllers.ts')).matchInline(`\n      \"/**\n       * This file is automatically generated.\n       * DO NOT EDIT manually\n       */\n\n      export const controllers = {\n        billing: {\n          Invoices: () => import('#app/billing/controllers/invoices_controller'),\n        },\n        identity: {\n          Auth: () => import('#app/identity/controllers/auth_controller'),\n          Users: () => import('#app/identity/controllers/users_controller'),\n        },\n      }\n      \"\n    `)\n    await assert.fileNotContains('.adonisjs/server/controllers.ts', [`controllers: {`])\n  })\n\n  test('skip segments from transformers index with module-based folder structure', async ({\n    assert,\n    fs,\n  }) => {\n    const cliUi = Kernel.create().ui\n    cliUi.switchMode('raw')\n\n    await fs.create('app/identity/transformers/user_transformer.ts', '')\n    await fs.create('app/billing/transformers/invoice_transformer.ts', '')\n\n    const generator = new IndexGenerator(stringHelpers.toUnixSlash(fs.basePath), cliUi.logger)\n    const indexer = indexEntities({\n      controllers: {\n        enabled: false,\n      },\n      events: {\n        enabled: false,\n      },\n      listeners: {\n        enabled: false,\n      },\n      transformers: {\n        enabled: true,\n        source: 'app',\n        glob: ['**/transformers/*_transformer.ts'],\n        importAlias: '#app',\n      },\n    })\n\n    indexer.run({} as any, {} as any, generator)\n    await generator.generate()\n\n    await assert.fileExists('.adonisjs/client/data.d.ts')\n    assert.snapshot(await fs.contents('.adonisjs/client/data.d.ts')).matchInline(`\n      \"/**\n       * This file is automatically generated.\n       * DO NOT EDIT manually\n       */\n\n      /// <reference path=\\\\\"./manifest.d.ts\\\\\" />\n      import type { InferData, InferVariants } from '@adonisjs/core/types/transformers'\n      import type BillingInvoiceTransformer from '#app/billing/transformers/invoice_transformer'\n      import type IdentityUserTransformer from '#app/identity/transformers/user_transformer'\n\n      export namespace Data {\n        export namespace Billing {\n          export type Invoice = InferData<BillingInvoiceTransformer>\n          export namespace Invoice {\n            export type Variants = InferVariants<BillingInvoiceTransformer>\n          }\n        }\n        export namespace Identity {\n          export type User = InferData<IdentityUserTransformer>\n          export namespace User {\n            export type Variants = InferVariants<IdentityUserTransformer>\n          }\n        }\n      }\n      \"\n    `)\n  })\n\n  test('generate frontend manifest file', async ({ assert, fs }) => {\n    const cliUi = Kernel.create().ui\n    cliUi.switchMode('raw')\n\n    await fs.create('config/app.ts', '') // ignored\n    await fs.create('config/hash.ts', '')\n    await fs.create('config/auth.ts', '')\n\n    const generator = new IndexGenerator(stringHelpers.toUnixSlash(fs.basePath), cliUi.logger)\n    const indexer = indexEntities({\n      transformers: {\n        enabled: true,\n      },\n    })\n\n    indexer.run({} as any, {} as any, generator)\n    await generator.generate()\n\n    await assert.fileExists('.adonisjs/client/manifest.d.ts')\n    assert.snapshot(await fs.contents('.adonisjs/client/manifest.d.ts')).matchInline(`\n      \"/**\n       * This file is automatically generated.\n       * DO NOT EDIT manually\n       */\n\n      /// <reference path=\\\\\"../../adonisrc.ts\\\\\" />\n      /// <reference path=\\\\\"../../config/auth.ts\\\\\" />\n      /// <reference path=\\\\\"../../config/hash.ts\\\\\" />\n      \"\n    `)\n  })\n\n  test('include all files', async ({ assert, fs }) => {\n    const cliUi = Kernel.create().ui\n    cliUi.switchMode('raw')\n\n    await fs.create('config/app.ts', '')\n    await fs.create('config/hash.ts', '')\n    await fs.create('config/auth.ts', '')\n\n    const generator = new IndexGenerator(stringHelpers.toUnixSlash(fs.basePath), cliUi.logger)\n    const indexer = indexEntities({\n      transformers: {\n        enabled: true,\n      },\n      manifest: {\n        enabled: true,\n        exclude: [],\n      },\n    })\n\n    indexer.run({} as any, {} as any, generator)\n    await generator.generate()\n\n    await assert.fileExists('.adonisjs/client/manifest.d.ts')\n    assert.snapshot(await fs.contents('.adonisjs/client/manifest.d.ts')).matchInline(`\n      \"/**\n       * This file is automatically generated.\n       * DO NOT EDIT manually\n       */\n\n      /// <reference path=\\\\\"../../adonisrc.ts\\\\\" />\n      /// <reference path=\\\\\"../../config/app.ts\\\\\" />\n      /// <reference path=\\\\\"../../config/auth.ts\\\\\" />\n      /// <reference path=\\\\\"../../config/hash.ts\\\\\" />\n      \"\n    `)\n  })\n\n  test('do not generate manifest file when explicitly disabled', async ({ assert, fs }) => {\n    const cliUi = Kernel.create().ui\n    cliUi.switchMode('raw')\n\n    await fs.create('config/app.ts', '')\n    await fs.create('config/hash.ts', '')\n    await fs.create('config/auth.ts', '')\n\n    const generator = new IndexGenerator(stringHelpers.toUnixSlash(fs.basePath), cliUi.logger)\n    const indexer = indexEntities({\n      transformers: {\n        enabled: true,\n      },\n      manifest: {\n        enabled: false,\n      },\n    })\n\n    indexer.run({} as any, {} as any, generator)\n    await generator.generate()\n\n    await assert.fileNotExists('.adonisjs/client/manifest.d.ts')\n  })\n\n  test('generate manifest file when explicitly enable without enabling transformers', async ({\n    assert,\n    fs,\n  }) => {\n    const cliUi = Kernel.create().ui\n    cliUi.switchMode('raw')\n\n    await fs.create('config/app.ts', '')\n    await fs.create('config/hash.ts', '')\n    await fs.create('config/auth.ts', '')\n\n    const generator = new IndexGenerator(stringHelpers.toUnixSlash(fs.basePath), cliUi.logger)\n    const indexer = indexEntities({\n      manifest: {\n        enabled: true,\n      },\n    })\n\n    indexer.run({} as any, {} as any, generator)\n    await generator.generate()\n\n    await assert.fileExists('.adonisjs/client/manifest.d.ts')\n    assert.snapshot(await fs.contents('.adonisjs/client/manifest.d.ts')).matchInline(`\n      \"/**\n       * This file is automatically generated.\n       * DO NOT EDIT manually\n       */\n\n      /// <reference path=\\\\\"../../adonisrc.ts\\\\\" />\n      /// <reference path=\\\\\"../../config/auth.ts\\\\\" />\n      /// <reference path=\\\\\"../../config/hash.ts\\\\\" />\n      \"\n    `)\n  })\n})\n"
  },
  {
    "path": "tests/pretty_print_error.spec.ts",
    "content": "/*\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 { test } from '@japa/runner'\nimport testConsole from 'test-console'\nimport { prettyPrintError } from '../index.ts'\n\ntest.group('Pretty print error', () => {\n  test('pretty print an error using youch', async ({ assert }) => {\n    const output = await testConsole.stderr.inspectAsync(async () => {\n      await prettyPrintError(new Error('Something went wrong'))\n    })\n\n    assert.match(output[0].trim(), /\\[31mℹ Error: Something went wrong/)\n  })\n})\n"
  },
  {
    "path": "tests/providers.spec.ts",
    "content": "/*\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 { test } from '@japa/runner'\nimport { fileURLToPath } from 'node:url'\nimport { setTimeout } from 'node:timers/promises'\nimport { defineConfig } from '@adonisjs/application'\n\nimport { Repl } from '../modules/repl.ts'\nimport { Config } from '../modules/config.ts'\nimport { Emitter } from '../modules/events.ts'\nimport { Kernel } from '../modules/ace/kernel.ts'\nimport { TestUtils } from '../src/test_utils/main.ts'\nimport { Router, Server } from '../modules/http/main.ts'\nimport { Hash, HashManager } from '../modules/hash/main.ts'\nimport { Logger, LoggerManager } from '../modules/logger.ts'\nimport { IgnitorFactory } from '../factories/core/ignitor.ts'\nimport { Encryption, EncryptionManager } from '../modules/encryption/main.ts'\nimport BodyParserMiddleware from '../modules/bodyparser/bodyparser_middleware.ts'\nimport { defineConfig as defineDumperConfig } from '../modules/dumper/define_config.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\nconst BASE_PATH = fileURLToPath(BASE_URL)\n\ntest.group('Providers', () => {\n  test('ensure all providers have been registered', async ({ assert }) => {\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../providers/app_provider.js'),\n            () => import('../providers/hash_provider.js'),\n            () => import('../providers/repl_provider.js'),\n          ],\n        },\n      })\n      .create(BASE_URL)\n\n    const app = ignitor.createApp('web')\n    await app.init()\n    await app.boot()\n\n    assert.isTrue(app.container.hasBinding('app'))\n    assert.isTrue(app.container.hasBinding('ace'))\n    assert.isTrue(app.container.hasBinding('logger'))\n    assert.isTrue(app.container.hasBinding('config'))\n    assert.isTrue(app.container.hasBinding('emitter'))\n    assert.isTrue(app.container.hasBinding('encryption'))\n    assert.isTrue(app.container.hasBinding('hash'))\n    assert.isTrue(app.container.hasBinding('dumper'))\n    assert.isTrue(app.container.hasBinding('server'))\n    assert.isTrue(app.container.hasBinding('router'))\n    assert.isTrue(app.container.hasBinding('testUtils'))\n    assert.isTrue(app.container.hasBinding('repl'))\n  })\n\n  test('ensure services can resolve bindings using container', async ({ assert }) => {\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../providers/app_provider.js'),\n            () => import('../providers/hash_provider.js'),\n            () => import('../providers/repl_provider.js'),\n          ],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    const app = ignitor.createApp('web')\n    await app.init()\n    await app.boot()\n\n    const { default: appService } = await import('../services/app.ts')\n    const { default: configService } = await import('../services/config.ts')\n    const { default: emitterService } = await import('../services/emitter.ts')\n    const { default: encryptionService } = await import('../services/encryption.ts')\n    const { default: hashService } = await import('../services/hash.ts')\n    const { default: loggerService } = await import('../services/logger.ts')\n    const { default: routerService } = await import('../services/router.ts')\n    const { default: serverService } = await import('../services/server.ts')\n    const { default: aceService } = await import('../services/ace.ts')\n    const { default: testUtils } = await import('../services/test_utils.ts')\n    const { default: repl } = await import('../services/repl.ts')\n    const { dd } = await import('../services/dumper.ts')\n    const { urlFor, signedUrlFor } = await import('../services/url_builder.ts')\n\n    assert.instanceOf(aceService, Kernel)\n    assert.strictEqual(app, appService)\n    assert.instanceOf(configService, Config)\n    assert.instanceOf(emitterService, Emitter)\n    assert.instanceOf(encryptionService, EncryptionManager)\n    assert.instanceOf(hashService, HashManager)\n    assert.instanceOf(loggerService, LoggerManager)\n    assert.instanceOf(routerService, Router)\n    assert.instanceOf(serverService, Server)\n    assert.instanceOf(testUtils, TestUtils)\n    assert.instanceOf(repl, Repl)\n    assert.isFunction(dd)\n    assert.strictEqual(urlFor, routerService.urlBuilder.urlFor)\n    assert.strictEqual(signedUrlFor, routerService.urlBuilder.signedUrlFor)\n    assert.throws(() => dd('d'), 'Dump and Die exception')\n  })\n\n  test('construct bodyparser middleware using the container', async ({ assert }) => {\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../providers/app_provider.js'),\n            () => import('../providers/hash_provider.js'),\n            () => import('../providers/repl_provider.js'),\n          ],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    const app = ignitor.createApp('web')\n    await app.init()\n    await app.boot()\n\n    const bodyparser = await app.container.make(BodyParserMiddleware)\n    assert.instanceOf(bodyparser, BodyParserMiddleware)\n  })\n\n  test('construct Hash class using the container', async ({ assert }) => {\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../providers/app_provider.js'),\n            () => import('../providers/hash_provider.js'),\n            () => import('../providers/repl_provider.js'),\n          ],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    const app = ignitor.createApp('web')\n    await app.init()\n    await app.boot()\n\n    const hashManger = await app.container.make('hash')\n\n    const hash = await app.container.make(Hash)\n    assert.instanceOf(hash, Hash)\n    assert.strictEqual(hash, hashManger.use())\n  })\n\n  test('construct Encryption class using the container', async ({ assert }) => {\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../providers/app_provider.js'),\n            () => import('../providers/hash_provider.js'),\n            () => import('../providers/repl_provider.js'),\n          ],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    const app = ignitor.createApp('web')\n    await app.init()\n    await app.boot()\n\n    const encryptionManager = await app.container.make('encryption')\n\n    const encryption = await app.container.make(Encryption)\n    assert.instanceOf(encryption, Encryption)\n    assert.strictEqual(encryption, encryptionManager.use())\n  })\n\n  test('construct Logger class using the container', async ({ assert }) => {\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../providers/app_provider.js'),\n            () => import('../providers/hash_provider.js'),\n            () => import('../providers/repl_provider.js'),\n          ],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    const app = ignitor.createApp('web')\n    await app.init()\n    await app.boot()\n\n    const loggerService = await app.container.make('logger')\n\n    const logger = await app.container.make(Logger)\n    assert.instanceOf(logger, Logger)\n    assert.strictEqual(logger, loggerService.use())\n  })\n\n  test('register repl methods when repl provider is imported', async ({ assert }) => {\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../providers/app_provider.js'),\n            () => import('../providers/hash_provider.js'),\n            () => import('../providers/repl_provider.js'),\n          ],\n        },\n      })\n      .create(BASE_URL)\n\n    const app = ignitor.createApp('repl')\n    await app.init()\n    await app.boot()\n\n    const repl = await app.container.make('repl')\n    assert.properties(repl.getMethods(), [\n      'importDefault',\n      'loadApp',\n      'loadConfig',\n      'loadEncryption',\n      'loadHash',\n      'loadHelpers',\n      'loadRouter',\n      'loadTestUtils',\n    ])\n  })\n\n  test('register providers with side-effects', async () => {\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: defineConfig({\n          providers: [\n            () => import('../providers/app_provider.js'),\n            () => import('../providers/hash_provider.js'),\n            () => import('../providers/repl_provider.js'),\n            () => import('../providers/vinejs_provider.js'),\n            () => import('../providers/edge_provider.js'),\n          ],\n        }),\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    const app = ignitor.createApp('repl')\n    await app.init()\n    await app.boot()\n  })\n\n  test('configure dumper using config/app file', async ({ assert }) => {\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../providers/app_provider.js'),\n            () => import('../providers/hash_provider.js'),\n            () => import('../providers/repl_provider.js'),\n          ],\n        },\n      })\n      .withCoreConfig()\n      .merge({\n        config: {\n          app: {\n            dumper: defineDumperConfig({\n              html: {\n                maxArrayLength: 1,\n              },\n              console: {\n                maxArrayLength: 1,\n              },\n            }),\n          },\n        },\n      })\n      .create(BASE_URL)\n\n    const app = ignitor.createApp('web')\n    await app.init()\n    await app.boot()\n\n    const dumper = await app.container.make('dumper')\n    assert.include(dumper.dumpToAnsi([1, 2, 3]), '[...2 more items]')\n    assert.include(dumper.dumpToHtml([1, 2, 3]), '[...2 more items]')\n  })\n\n  test('generate routes types file once app is ready', async ({ assert, fs }) => {\n    fs.baseUrl = BASE_URL\n    fs.basePath = BASE_PATH\n\n    const ignitor = new IgnitorFactory()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../providers/app_provider.js'),\n            () => import('../providers/hash_provider.js'),\n            () => import('../providers/repl_provider.js'),\n          ],\n        },\n      })\n      .withCoreConfig()\n      .create(BASE_URL)\n\n    const app = ignitor.createApp('web')\n    await app.init()\n    await app.boot()\n\n    const router = await app.container.make('router')\n    const PostsController = () => import('#controllers/posts_controller' as any)\n\n    router.get('/', () => {})\n    router.resource('users', '#controllers/users_controllers')\n    router.resource('posts', PostsController)\n    router.commit()\n\n    await app.start(() => {})\n    await setTimeout(3000)\n\n    assert.snapshot(await fs.contents('.adonisjs/server/routes.d.ts')).matchInline(`\n      \"import '@adonisjs/core/types/http'\n\n      type ParamValue = string | number | bigint | boolean\n\n      export type ScannedRoutes = {\n        ALL: {\n          'users.index': { paramsTuple?: []; params?: {} }\n          'users.create': { paramsTuple?: []; params?: {} }\n          'users.store': { paramsTuple?: []; params?: {} }\n          'users.show': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }\n          'users.edit': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }\n          'users.update': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }\n          'users.destroy': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }\n          'posts.index': { paramsTuple?: []; params?: {} }\n          'posts.create': { paramsTuple?: []; params?: {} }\n          'posts.store': { paramsTuple?: []; params?: {} }\n          'posts.show': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }\n          'posts.edit': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }\n          'posts.update': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }\n          'posts.destroy': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }\n        }\n        GET: {\n          'users.index': { paramsTuple?: []; params?: {} }\n          'users.create': { paramsTuple?: []; params?: {} }\n          'users.show': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }\n          'users.edit': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }\n          'posts.index': { paramsTuple?: []; params?: {} }\n          'posts.create': { paramsTuple?: []; params?: {} }\n          'posts.show': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }\n          'posts.edit': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }\n        }\n        HEAD: {\n          'users.index': { paramsTuple?: []; params?: {} }\n          'users.create': { paramsTuple?: []; params?: {} }\n          'users.show': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }\n          'users.edit': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }\n          'posts.index': { paramsTuple?: []; params?: {} }\n          'posts.create': { paramsTuple?: []; params?: {} }\n          'posts.show': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }\n          'posts.edit': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }\n        }\n        POST: {\n          'users.store': { paramsTuple?: []; params?: {} }\n          'posts.store': { paramsTuple?: []; params?: {} }\n        }\n        PUT: {\n          'users.update': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }\n          'posts.update': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }\n        }\n        PATCH: {\n          'users.update': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }\n          'posts.update': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }\n        }\n        DELETE: {\n          'users.destroy': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }\n          'posts.destroy': { paramsTuple: [ParamValue]; params: {'id': ParamValue} }\n        }\n      }\n      declare module '@adonisjs/core/types/http' {\n        export interface RoutesList extends ScannedRoutes {}\n      }\"\n    `)\n  }).timeout(5000)\n})\n"
  },
  {
    "path": "tests/request_validator.spec.ts",
    "content": "/*\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 { test } from '@japa/runner'\nimport { type FieldContext } from '@vinejs/vine/types'\nimport vine, { SimpleErrorReporter, SimpleMessagesProvider, ValidationError } from '@vinejs/vine'\n\nimport { RequestValidator } from '../modules/http/main.ts'\nimport { IgnitorFactory } from '../factories/core/ignitor.ts'\nimport { TestUtilsFactory } from '../factories/core/test_utils.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\n\ntest.group('Request validator', () => {\n  test('perform validation on request data using request validator', async ({ assert }) => {\n    assert.plan(1)\n\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../providers/app_provider.js'),\n            () => import('../providers/vinejs_provider.js'),\n          ],\n        },\n      })\n      .create(BASE_URL)\n\n    const testUtils = new TestUtilsFactory().create(ignitor)\n    await testUtils.app.init()\n    await testUtils.app.boot()\n    await testUtils.boot()\n\n    const ctx = await testUtils.createHttpContext()\n    const validator = vine.compile(\n      vine.object({\n        username: vine.string(),\n      })\n    )\n\n    ctx.request.__raw_files = {}\n\n    try {\n      await ctx.request.validateUsing(validator)\n    } catch (error) {\n      assert.deepEqual(error.messages, [\n        {\n          field: 'username',\n          message: 'The username field must be defined',\n          rule: 'required',\n        },\n      ])\n    }\n  })\n\n  test('pass validation when data is valid', async ({ assert, expectTypeOf }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../providers/app_provider.js'),\n            () => import('../providers/vinejs_provider.js'),\n          ],\n        },\n      })\n      .create(BASE_URL)\n\n    const testUtils = new TestUtilsFactory().create(ignitor)\n    await testUtils.app.init()\n    await testUtils.app.boot()\n    await testUtils.boot()\n\n    const ctx = await testUtils.createHttpContext()\n    const validator = vine.compile(\n      vine.object({\n        username: vine.string(),\n      })\n    )\n\n    ctx.request.__raw_files = {}\n    ctx.request.setInitialBody({ username: 'virk' })\n\n    const output = await ctx.request.validateUsing(validator)\n    assert.deepEqual(output, { username: 'virk' })\n    expectTypeOf(output).toEqualTypeOf<{ username: string }>()\n  })\n\n  test('define inline data', async ({ assert, expectTypeOf }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../providers/app_provider.js'),\n            () => import('../providers/vinejs_provider.js'),\n          ],\n        },\n      })\n      .create(BASE_URL)\n\n    const testUtils = new TestUtilsFactory().create(ignitor)\n    await testUtils.app.init()\n    await testUtils.app.boot()\n    await testUtils.boot()\n\n    const ctx = await testUtils.createHttpContext()\n    const validator = vine.compile(\n      vine.object({\n        username: vine.string(),\n      })\n    )\n\n    ctx.request.__raw_files = {}\n\n    const output = await ctx.request.validateUsing(validator, { data: { username: 'virk' } })\n    assert.deepEqual(output, { username: 'virk' })\n    expectTypeOf(output).toEqualTypeOf<{ username: string }>()\n  })\n\n  test('validate headers', async ({ assert, expectTypeOf }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../providers/app_provider.js'),\n            () => import('../providers/vinejs_provider.js'),\n          ],\n        },\n      })\n      .create(BASE_URL)\n\n    const testUtils = new TestUtilsFactory().create(ignitor)\n    await testUtils.app.init()\n    await testUtils.app.boot()\n    await testUtils.boot()\n\n    const ctx = await testUtils.createHttpContext()\n    const validator = vine.compile(\n      vine.object({\n        username: vine.string(),\n        headers: vine.object({\n          accept: vine.string(),\n        }),\n      })\n    )\n\n    ctx.request.request.headers['accept'] = 'json'\n    ctx.request.__raw_files = {}\n    ctx.request.setInitialBody({ username: 'virk' })\n\n    const output = await ctx.request.validateUsing(validator)\n    assert.deepEqual(output, { username: 'virk', headers: { accept: 'json' } })\n    expectTypeOf(output).toEqualTypeOf<{ username: string; headers: { accept: string } }>()\n  })\n\n  test('pass metadata to validator', async ({ assert }) => {\n    assert.plan(1)\n\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../providers/app_provider.js'),\n            () => import('../providers/vinejs_provider.js'),\n          ],\n        },\n      })\n      .create(BASE_URL)\n\n    const testUtils = new TestUtilsFactory().create(ignitor)\n    await testUtils.app.init()\n    await testUtils.app.boot()\n    await testUtils.boot()\n\n    const ctx = await testUtils.createHttpContext()\n    const validator = vine.withMetaData<{ disallowUserNames: string[] }>().compile(\n      vine.object({\n        username: vine.string().notIn((field) => {\n          return field.meta.disallowUserNames\n        }),\n      })\n    )\n\n    ctx.request.__raw_files = {}\n    ctx.request.setInitialBody({ username: 'virk' })\n\n    try {\n      await ctx.request.validateUsing(validator, {\n        meta: { disallowUserNames: ['virk'] },\n      })\n    } catch (error) {\n      assert.containsSubset(error.messages, [\n        {\n          field: 'username',\n          message: 'The selected username is invalid',\n          rule: 'notIn',\n        },\n      ])\n    }\n  })\n\n  test('use custom messages provider', async ({ assert, cleanup }) => {\n    assert.plan(1)\n\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../providers/app_provider.js'),\n            () => import('../providers/vinejs_provider.js'),\n          ],\n        },\n      })\n      .create(BASE_URL)\n\n    const testUtils = new TestUtilsFactory().create(ignitor)\n    await testUtils.app.init()\n    await testUtils.app.boot()\n    await testUtils.boot()\n\n    const ctx = await testUtils.createHttpContext()\n    const validator = vine.compile(\n      vine.object({\n        username: vine.string(),\n      })\n    )\n\n    ctx.request.__raw_files = {}\n    RequestValidator.messagesProvider = () =>\n      new SimpleMessagesProvider(\n        {\n          required: 'The value is missing',\n        },\n        {}\n      )\n    cleanup(() => {\n      RequestValidator.messagesProvider = undefined\n    })\n\n    try {\n      await ctx.request.validateUsing(validator)\n    } catch (error) {\n      assert.deepEqual(error.messages, [\n        {\n          field: 'username',\n          message: 'The value is missing',\n          rule: 'required',\n        },\n      ])\n    }\n  })\n\n  test('use custom error reporter', async ({ assert, cleanup }) => {\n    assert.plan(1)\n\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../providers/app_provider.js'),\n            () => import('../providers/vinejs_provider.js'),\n          ],\n        },\n      })\n      .create(BASE_URL)\n\n    const testUtils = new TestUtilsFactory().create(ignitor)\n    await testUtils.app.init()\n    await testUtils.app.boot()\n    await testUtils.boot()\n\n    const ctx = await testUtils.createHttpContext()\n    const validator = vine.compile(\n      vine.object({\n        username: vine.string(),\n      })\n    )\n\n    ctx.request.__raw_files = {}\n    class MyErrorReporter extends SimpleErrorReporter {\n      report(\n        message: string,\n        rule: string,\n        field: FieldContext,\n        meta?: Record<string, any> | undefined\n      ): void {\n        return super.report(message, `validations.${rule}`, field, meta)\n      }\n    }\n\n    RequestValidator.errorReporter = () => {\n      return new MyErrorReporter()\n    }\n    cleanup(() => {\n      RequestValidator.errorReporter = undefined\n    })\n\n    try {\n      await ctx.request.validateUsing(validator)\n    } catch (error) {\n      assert.deepEqual(error.messages, [\n        {\n          field: 'username',\n          message: 'The username field must be defined',\n          rule: 'validations.required',\n        },\n      ])\n    }\n  })\n\n  test('try validate using')\n    .with([\n      { expectValid: true, body: { username: 'virk' } },\n      { expectValid: false, body: { foo: true } },\n    ])\n    .run(async ({ assert }, { expectValid, body }) => {\n      assert.plan(2)\n\n      const ignitor = new IgnitorFactory()\n        .withCoreConfig()\n        .merge({\n          rcFileContents: {\n            providers: [\n              () => import('../providers/app_provider.js'),\n              () => import('../providers/vinejs_provider.js'),\n            ],\n          },\n        })\n        .create(BASE_URL)\n\n      const testUtils = new TestUtilsFactory().create(ignitor)\n      await testUtils.app.init()\n      await testUtils.app.boot()\n      await testUtils.boot()\n\n      const ctx = await testUtils.createHttpContext()\n      const validator = vine.compile(\n        vine.object({\n          username: vine.string(),\n        })\n      )\n\n      ctx.request.setInitialBody(body)\n\n      const [error, data] = await ctx.request.tryValidateUsing(validator)\n\n      if (expectValid) {\n        assert.isNull(error)\n        assert.deepEqual(data, body)\n      } else {\n        assert.instanceOf(error, ValidationError)\n        assert.isNull(data)\n      }\n    })\n\n  test('try validate using with custom messages provider', async ({ assert, cleanup }) => {\n    assert.plan(3)\n\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../providers/app_provider.js'),\n            () => import('../providers/vinejs_provider.js'),\n          ],\n        },\n      })\n      .create(BASE_URL)\n\n    const testUtils = new TestUtilsFactory().create(ignitor)\n    await testUtils.app.init()\n    await testUtils.app.boot()\n    await testUtils.boot()\n\n    const ctx = await testUtils.createHttpContext()\n    const validator = vine.compile(\n      vine.object({\n        username: vine.string(),\n      })\n    )\n\n    ctx.request.setInitialBody({ error: true })\n\n    RequestValidator.messagesProvider = () =>\n      new SimpleMessagesProvider(\n        {\n          required: 'The value is missing',\n        },\n        {}\n      )\n    cleanup(() => {\n      RequestValidator.messagesProvider = undefined\n    })\n\n    const [error, data] = await ctx.request.tryValidateUsing(validator)\n\n    assert.isNull(data)\n    assert.instanceOf(error, ValidationError)\n    assert.deepEqual(error!.messages, [\n      {\n        field: 'username',\n        message: 'The value is missing',\n        rule: 'required',\n      },\n    ])\n  })\n\n  test('try validate using with custom error reporter', async ({ assert, cleanup }) => {\n    assert.plan(3)\n\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [\n            () => import('../providers/app_provider.js'),\n            () => import('../providers/vinejs_provider.js'),\n          ],\n        },\n      })\n      .create(BASE_URL)\n\n    const testUtils = new TestUtilsFactory().create(ignitor)\n    await testUtils.app.init()\n    await testUtils.app.boot()\n    await testUtils.boot()\n\n    const ctx = await testUtils.createHttpContext()\n    const validator = vine.compile(\n      vine.object({\n        username: vine.string(),\n      })\n    )\n\n    ctx.request.setInitialBody({ error: true })\n\n    class MyErrorReporter extends SimpleErrorReporter {\n      report(\n        message: string,\n        rule: string,\n        field: FieldContext,\n        meta?: Record<string, any> | undefined\n      ): void {\n        return super.report(message, `validations.${rule}`, field, meta)\n      }\n    }\n\n    RequestValidator.errorReporter = () => {\n      return new MyErrorReporter()\n    }\n    cleanup(() => {\n      RequestValidator.errorReporter = undefined\n    })\n\n    const [error, data] = await ctx.request.tryValidateUsing(validator)\n\n    assert.isNull(data)\n    assert.instanceOf(error, ValidationError)\n    assert.deepEqual(error!.messages, [\n      {\n        field: 'username',\n        message: 'The username field must be defined',\n        rule: 'validations.required',\n      },\n    ])\n  })\n})\n"
  },
  {
    "path": "tests/stubs/make_command.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { fileURLToPath } from 'node:url'\nimport { AppFactory } from '@adonisjs/application/factories'\n\nimport { stubsRoot } from '../../stubs/main.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\nconst BASE_PATH = fileURLToPath(BASE_URL)\n\ntest.group('Make command', () => {\n  test('prepare command stub', async ({ assert }) => {\n    const app = new AppFactory().create(BASE_URL)\n    await app.init()\n\n    const stubs = await app.stubs.create()\n    const stub = await stubs.build('make/command/main.stub', {\n      source: stubsRoot,\n    })\n    const { contents, destination } = await stub.prepare({\n      entity: app.generators.createEntity('listRoutes'),\n    })\n\n    assert.equal(destination, join(BASE_PATH, 'commands/list_routes.ts'))\n    assert.match(contents, new RegExp('export default class ListRoutes extends BaseCommand {'))\n    assert.match(contents, new RegExp(\"import { BaseCommand } from '@adonisjs/core/ace'\"))\n    assert.match(contents, new RegExp(\"static commandName = 'list:routes'\"))\n  })\n})\n"
  },
  {
    "path": "tests/stubs/make_controller.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { fileURLToPath } from 'node:url'\nimport { AppFactory } from '@adonisjs/application/factories'\n\nimport { stubsRoot } from '../../stubs/main.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\nconst BASE_PATH = fileURLToPath(BASE_URL)\n\ntest.group('Make controller', () => {\n  test('prepare controller stub', async ({ assert }) => {\n    const app = new AppFactory().create(BASE_URL)\n    await app.init()\n\n    const stubs = await app.stubs.create()\n\n    const stub = await stubs.build('make/controller/main.stub', {\n      source: stubsRoot,\n    })\n    const { contents, destination } = await stub.prepare({\n      entity: app.generators.createEntity('user'),\n      singular: false,\n    })\n\n    assert.equal(destination, join(BASE_PATH, 'app/controllers/users_controller.ts'))\n    assert.match(contents, /export default class UsersController {/)\n    assert.match(contents, new RegExp(\"// import type { HttpContext } from '@adonisjs/core/http'\"))\n  })\n\n  test('prepare resourceful controller stub', async ({ assert }) => {\n    const app = new AppFactory().create(BASE_URL)\n    await app.init()\n\n    const stubs = await app.stubs.create()\n\n    const stub = await stubs.build('make/controller/resource.stub', {\n      source: stubsRoot,\n    })\n    const { contents, destination } = await stub.prepare({\n      entity: app.generators.createEntity('user'),\n      singular: false,\n    })\n\n    assert.equal(destination, join(BASE_PATH, 'app/controllers/users_controller.ts'))\n    assert.match(contents, /export default class UsersController {/)\n    assert.match(contents, new RegExp(\"import type { HttpContext } from '@adonisjs/core/http'\"))\n    assert.match(contents, new RegExp('async index\\\\({}: HttpContext\\\\) {}'))\n    assert.match(contents, new RegExp('async create\\\\({}: HttpContext\\\\) {}'))\n    assert.match(contents, new RegExp('async store\\\\({ request }: HttpContext\\\\) {}'))\n    assert.match(contents, new RegExp('async show\\\\({ params }: HttpContext\\\\) {}'))\n    assert.match(contents, new RegExp('async edit\\\\({ params }: HttpContext\\\\) {}'))\n    assert.match(contents, new RegExp('async update\\\\({ params, request }: HttpContext\\\\) {}'))\n    assert.match(contents, new RegExp('async destroy\\\\({ params }: HttpContext\\\\) {}'))\n  })\n\n  test('prepare resourceful api controller stub', async ({ assert }) => {\n    const app = new AppFactory().create(BASE_URL)\n    await app.init()\n\n    const stubs = await app.stubs.create()\n\n    const stub = await stubs.build('make/controller/api.stub', {\n      source: stubsRoot,\n    })\n    const { contents, destination } = await stub.prepare({\n      entity: app.generators.createEntity('user'),\n      singular: false,\n    })\n\n    assert.equal(destination, join(BASE_PATH, 'app/controllers/users_controller.ts'))\n    assert.match(contents, /export default class UsersController {/)\n    assert.match(contents, new RegExp(\"import type { HttpContext } from '@adonisjs/core/http'\"))\n    assert.match(contents, new RegExp('async index\\\\({}: HttpContext\\\\) {}'))\n    assert.notMatch(contents, new RegExp('async create\\\\({}: HttpContext\\\\) {}'))\n    assert.match(contents, new RegExp('async store\\\\({ request }: HttpContext\\\\) {}'))\n    assert.match(contents, new RegExp('async show\\\\({ params }: HttpContext\\\\) {}'))\n    assert.notMatch(contents, new RegExp('async edit\\\\({ params }: HttpContext\\\\) {}'))\n    assert.match(contents, new RegExp('async update\\\\({ params, request }: HttpContext\\\\) {}'))\n    assert.match(contents, new RegExp('async destroy\\\\({ params }: HttpContext\\\\) {}'))\n  })\n\n  test('prepare actions controller stub', async ({ assert }) => {\n    const app = new AppFactory().create(BASE_URL)\n    await app.init()\n\n    const stubs = await app.stubs.create()\n\n    const stub = await stubs.build('make/controller/actions.stub', {\n      source: stubsRoot,\n    })\n    const { contents, destination } = await stub.prepare({\n      entity: app.generators.createEntity('user'),\n      singular: false,\n      actions: ['index', 'show', 'deleteProfile'],\n    })\n\n    assert.equal(destination, join(BASE_PATH, 'app/controllers/users_controller.ts'))\n    assert.match(contents, /export default class UsersController {/)\n    assert.match(contents, new RegExp(\"import type { HttpContext } from '@adonisjs/core/http'\"))\n    assert.match(contents, new RegExp('async index\\\\({}: HttpContext\\\\) {}'))\n    assert.match(contents, new RegExp('async show\\\\({}: HttpContext\\\\) {}'))\n    assert.match(contents, new RegExp('async deleteProfile\\\\({}: HttpContext\\\\) {}'))\n  })\n})\n"
  },
  {
    "path": "tests/stubs/make_event.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { fileURLToPath } from 'node:url'\nimport { AppFactory } from '@adonisjs/application/factories'\n\nimport { stubsRoot } from '../../stubs/main.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\nconst BASE_PATH = fileURLToPath(BASE_URL)\n\ntest.group('Make event', () => {\n  test('prepare event stub', async ({ assert }) => {\n    const app = new AppFactory().create(BASE_URL)\n    await app.init()\n\n    const stubs = await app.stubs.create()\n    const stub = await stubs.build('make/event/main.stub', {\n      source: stubsRoot,\n    })\n    const { contents, destination } = await stub.prepare({\n      entity: app.generators.createEntity('userRegistered'),\n    })\n\n    assert.equal(destination, join(BASE_PATH, 'app/events/user_registered.ts'))\n    assert.match(contents, new RegExp('export default class UserRegistered extends BaseEvent {'))\n    assert.match(contents, new RegExp(\"import { BaseEvent } from '@adonisjs/core/events'\"))\n    assert.match(contents, new RegExp('constructor\\\\(\\\\) {'))\n  })\n})\n"
  },
  {
    "path": "tests/stubs/make_exception.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { fileURLToPath } from 'node:url'\nimport { AppFactory } from '@adonisjs/application/factories'\n\nimport { stubsRoot } from '../../stubs/main.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\nconst BASE_PATH = fileURLToPath(BASE_URL)\n\ntest.group('Make exception', () => {\n  test('prepare exception stub', async ({ assert }) => {\n    const app = new AppFactory().create(BASE_URL)\n    await app.init()\n\n    const stubs = await app.stubs.create()\n    const stub = await stubs.build('make/exception/main.stub', {\n      source: stubsRoot,\n    })\n    const { contents, destination } = await stub.prepare({\n      entity: app.generators.createEntity('Unauthorized'),\n    })\n\n    assert.equal(destination, join(BASE_PATH, 'app/exceptions/unauthorized_exception.ts'))\n    assert.match(\n      contents,\n      new RegExp('export default class UnauthorizedException extends Exception {')\n    )\n    assert.match(contents, new RegExp(\"import { Exception } from '@adonisjs/core/exceptions'\"))\n    assert.match(contents, new RegExp('static status = 500'))\n  })\n})\n"
  },
  {
    "path": "tests/stubs/make_listener.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { fileURLToPath } from 'node:url'\nimport { AppFactory } from '@adonisjs/application/factories'\n\nimport { stubsRoot } from '../../stubs/main.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\nconst BASE_PATH = fileURLToPath(BASE_URL)\n\ntest.group('Make listener', () => {\n  test('prepare listener stub', async ({ assert }) => {\n    const app = new AppFactory().create(BASE_URL)\n    await app.init()\n\n    const stubs = await app.stubs.create()\n    const stub = await stubs.build('make/listener/main.stub', {\n      source: stubsRoot,\n    })\n    const { contents, destination } = await stub.prepare({\n      entity: app.generators.createEntity('sendEmail'),\n    })\n\n    assert.equal(destination, join(BASE_PATH, 'app/listeners/send_email.ts'))\n    assert.match(contents, new RegExp('export default class SendEmail {'))\n  })\n\n  test('prepare listener stub for an event', async ({ assert }) => {\n    const app = new AppFactory().create(BASE_URL)\n    await app.init()\n\n    const stubs = await app.stubs.create()\n    const stub = await stubs.build('make/listener/for_event.stub', {\n      source: stubsRoot,\n    })\n    const { contents, destination } = await stub.prepare({\n      entity: app.generators.createEntity('sendEmail'),\n      event: app.generators.createEntity('users/user_registered'),\n    })\n\n    assert.equal(destination, join(BASE_PATH, 'app/listeners/send_email.ts'))\n    assert.match(contents, new RegExp('export default class SendEmail {'))\n    assert.match(\n      contents,\n      new RegExp(\"import type UserRegistered from '#events/users/user_registered.ts'\")\n    )\n    assert.match(contents, new RegExp('async handle\\\\(event: UserRegistered\\\\) {'))\n  })\n})\n"
  },
  {
    "path": "tests/stubs/make_middleware.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { fileURLToPath } from 'node:url'\nimport { AppFactory } from '@adonisjs/application/factories'\n\nimport { stubsRoot } from '../../stubs/main.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\nconst BASE_PATH = fileURLToPath(BASE_URL)\n\ntest.group('Make middleware', () => {\n  test('prepare middleware stub', async ({ assert }) => {\n    const app = new AppFactory().create(BASE_URL)\n    await app.init()\n\n    const stubs = await app.stubs.create()\n    const stub = await stubs.build('make/middleware/main.stub', {\n      source: stubsRoot,\n    })\n    const { contents, destination } = await stub.prepare({\n      entity: app.generators.createEntity('auth'),\n    })\n\n    assert.equal(destination, join(BASE_PATH, 'app/middleware/auth_middleware.ts'))\n    assert.match(contents, new RegExp('export default class AuthMiddleware {'))\n    assert.match(contents, new RegExp(\"import type { HttpContext } from '@adonisjs/core/http'\"))\n    assert.match(contents, new RegExp(\"import type { NextFn } from '@adonisjs/core/types/http'\"))\n    assert.match(contents, new RegExp('export default class AuthMiddleware {'))\n    assert.match(contents, new RegExp('async handle\\\\(ctx: HttpContext, next: NextFn\\\\) {'))\n  })\n})\n"
  },
  {
    "path": "tests/stubs/make_prldfile.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { fileURLToPath } from 'node:url'\nimport { AppFactory } from '@adonisjs/application/factories'\n\nimport { stubsRoot } from '../../stubs/main.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\nconst BASE_PATH = fileURLToPath(BASE_URL)\n\ntest.group('Make preload file', () => {\n  test('prepare preload file stub', async ({ assert }) => {\n    const app = new AppFactory().create(BASE_URL)\n    await app.init()\n\n    const stubs = await app.stubs.create()\n    const stub = await stubs.build('make/preload/main.stub', {\n      source: stubsRoot,\n    })\n    const { destination } = await stub.prepare({\n      entity: app.generators.createEntity('app'),\n    })\n\n    assert.equal(destination, join(BASE_PATH, 'start/app.ts'))\n  })\n})\n"
  },
  {
    "path": "tests/stubs/make_provider.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { fileURLToPath } from 'node:url'\nimport { AppFactory } from '@adonisjs/application/factories'\n\nimport { stubsRoot } from '../../stubs/main.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\nconst BASE_PATH = fileURLToPath(BASE_URL)\n\ntest.group('Make provider', () => {\n  test('prepare provider stub', async ({ assert }) => {\n    const app = new AppFactory().create(BASE_URL)\n    await app.init()\n\n    const stubs = await app.stubs.create()\n    const stub = await stubs.build('make/provider/main.stub', {\n      source: stubsRoot,\n    })\n    const { contents, destination } = await stub.prepare({\n      entity: app.generators.createEntity('app'),\n    })\n\n    assert.equal(destination, join(BASE_PATH, 'providers/app_provider.ts'))\n    assert.match(contents, new RegExp('export default class AppProvider {'))\n    assert.match(\n      contents,\n      new RegExp(\"import type { ApplicationService } from '@adonisjs/core/types'\")\n    )\n    assert.match(contents, new RegExp('constructor\\\\(protected app: ApplicationService\\\\) {}'))\n    assert.match(contents, new RegExp('register\\\\(\\\\)'))\n    assert.match(contents, new RegExp('async boot\\\\(\\\\)'))\n    assert.match(contents, new RegExp('async ready\\\\(\\\\)'))\n    assert.match(contents, new RegExp('async start\\\\(\\\\)'))\n    assert.match(contents, new RegExp('async shutdown\\\\(\\\\)'))\n  })\n})\n"
  },
  {
    "path": "tests/stubs/make_service.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { fileURLToPath } from 'node:url'\nimport { AppFactory } from '@adonisjs/application/factories'\n\nimport { stubsRoot } from '../../stubs/main.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\nconst BASE_PATH = fileURLToPath(BASE_URL)\n\ntest.group('Make Service', () => {\n  test('prepare service stub', async ({ assert }) => {\n    const app = new AppFactory().create(BASE_URL)\n    await app.init()\n\n    const stubs = await app.stubs.create()\n    const stub = await stubs.build('make/service/main.stub', {\n      source: stubsRoot,\n    })\n    const { contents, destination } = await stub.prepare({\n      entity: app.generators.createEntity('app'),\n    })\n\n    assert.equal(destination, join(BASE_PATH, 'app/services/app_service.ts'))\n    assert.match(contents.trim(), /export class AppService {/)\n  })\n})\n"
  },
  {
    "path": "tests/stubs/make_test.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { fileURLToPath } from 'node:url'\nimport { AppFactory } from '@adonisjs/application/factories'\n\nimport { stubsRoot } from '../../stubs/main.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\nconst BASE_PATH = fileURLToPath(BASE_URL)\n\ntest.group('Make test', () => {\n  test('prepare test stub', async ({ assert }) => {\n    const app = new AppFactory().create(BASE_URL)\n    await app.init()\n\n    const stubs = await app.stubs.create()\n    const stub = await stubs.build('make/test/main.stub', {\n      source: stubsRoot,\n    })\n    const { contents, destination } = await stub.prepare({\n      entity: app.generators.createEntity('users/send_email'),\n      suite: {\n        directory: 'tests/functional',\n      },\n    })\n\n    assert.equal(destination, join(BASE_PATH, 'tests/functional/users/send_email.spec.ts'))\n    assert.match(contents, new RegExp(`import { test } from '@japa/runner'`))\n    assert.match(contents, new RegExp(`test\\\\.group\\\\('Users send email'`))\n  })\n})\n"
  },
  {
    "path": "tests/stubs/make_validator.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { fileURLToPath } from 'node:url'\nimport { AppFactory } from '@adonisjs/application/factories'\n\nimport { stubsRoot } from '../../stubs/main.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\nconst BASE_PATH = fileURLToPath(BASE_URL)\n\ntest.group('Make validator', () => {\n  test('prepare validator stub', async ({ assert }) => {\n    const app = new AppFactory().create(BASE_URL)\n    await app.init()\n\n    const stubs = await app.stubs.create()\n    const stub = await stubs.build('make/validator/main.stub', {\n      source: stubsRoot,\n    })\n    const { contents, destination } = await stub.prepare({\n      entity: app.generators.createEntity('posts'),\n    })\n\n    assert.equal(destination, join(BASE_PATH, 'app/validators/post.ts'))\n    assert.match(contents, new RegExp(\"import vine from '@vinejs/vine'\"))\n  })\n\n  test('prepare validator stub for a resource', async ({ assert }) => {\n    const app = new AppFactory().create(BASE_URL)\n    await app.init()\n\n    const stubs = await app.stubs.create()\n    const stub = await stubs.build('make/validator/resource.stub', {\n      source: stubsRoot,\n    })\n    const { contents, destination } = await stub.prepare({\n      entity: app.generators.createEntity('posts'),\n    })\n\n    assert.equal(destination, join(BASE_PATH, 'app/validators/post.ts'))\n    assert.match(contents, new RegExp(\"import vine from '@vinejs/vine'\"))\n    assert.includeMembers(contents.split('\\n'), [\n      `export const createPostValidator = vine.compile(`,\n      `  vine.object({})`,\n      `)`,\n      `export const updatePostValidator = vine.compile(`,\n      `  vine.object({})`,\n      `)`,\n    ])\n  })\n})\n"
  },
  {
    "path": "tests/stubs/make_view.spec.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { test } from '@japa/runner'\nimport { fileURLToPath } from 'node:url'\nimport { AppFactory } from '@adonisjs/application/factories'\n\nimport { stubsRoot } from '../../stubs/main.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\nconst BASE_PATH = fileURLToPath(BASE_URL)\n\ntest.group('Make View', () => {\n  test('prepare view stub', async ({ assert }) => {\n    const app = new AppFactory().create(BASE_URL)\n    await app.init()\n\n    const stubs = await app.stubs.create()\n    const stub = await stubs.build('make/view/main.stub', {\n      source: stubsRoot,\n    })\n    const { contents, destination } = await stub.prepare({\n      entity: app.generators.createEntity('pages/posts/index'),\n    })\n\n    assert.equal(destination, join(BASE_PATH, 'resources/views/pages/posts/index.edge'))\n    assert.equal(contents.trim(), '')\n  })\n})\n"
  },
  {
    "path": "tests/test_utils/http.spec.ts",
    "content": "/*\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 getPort from 'get-port'\nimport { Socket } from 'node:net'\nimport { test } from '@japa/runner'\nimport { createServer, IncomingMessage, ServerResponse } from 'node:http'\n\nimport { HttpContext } from '../../modules/http/main.ts'\nimport { IgnitorFactory } from '../../factories/core/ignitor.ts'\nimport { TestUtilsFactory } from '../../factories/core/test_utils.ts'\n\nconst BASE_URL = new URL('./tmp/', import.meta.url)\n\ntest.group('Test utils | Http', () => {\n  test('start HTTP server using test utils', async ({ assert, cleanup }) => {\n    const server = createServer()\n    cleanup(() => {\n      server.close()\n    })\n\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(BASE_URL)\n\n    const testUtils = new TestUtilsFactory().create(ignitor)\n    await testUtils.app.init()\n    await testUtils.app.boot()\n    await testUtils.boot()\n\n    await testUtils.httpServer().start(() => server)\n    assert.isTrue(server.listening)\n  })\n\n  test('close HTTP server using the cleanup function', async ({ assert, cleanup }) => {\n    const server = createServer()\n    cleanup(() => {\n      server.close()\n    })\n\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(BASE_URL)\n\n    const testUtils = new TestUtilsFactory().create(ignitor)\n    await testUtils.app.init()\n    await testUtils.app.boot()\n    await testUtils.boot()\n\n    const closeServer = await testUtils.httpServer().start(() => server)\n    assert.isTrue(server.listening)\n\n    await closeServer()\n    assert.isFalse(server.listening)\n  })\n\n  test('share HTTP server instance with AdonisJS server class', async ({ assert }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(BASE_URL)\n\n    const testUtils = new TestUtilsFactory().create(ignitor)\n    await testUtils.app.init()\n    await testUtils.app.boot()\n    await testUtils.boot()\n\n    const closeServer = await testUtils.httpServer().start()\n    const adonisJsServer = await testUtils.app.container.make('server')\n    assert.isTrue(adonisJsServer.getNodeServer()!.listening)\n\n    await closeServer()\n    assert.isFalse(adonisJsServer.getNodeServer()!.listening)\n  })\n\n  test('throw error if port is already in use', async ({ assert, cleanup }) => {\n    const nodeServer = createServer(() => {})\n\n    cleanup(async () => {\n      delete process.env.HOST\n      delete process.env.PORT\n      nodeServer.close()\n    })\n\n    process.env.HOST = 'localhost'\n    process.env.PORT = String(await getPort())\n\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(BASE_URL)\n\n    const testUtils = new TestUtilsFactory().create(ignitor)\n    await testUtils.app.init()\n    await testUtils.app.boot()\n    await testUtils.boot()\n\n    await new Promise<void>((resolve) => {\n      nodeServer.listen(Number(process.env.PORT), process.env.HOST, () => {\n        resolve()\n      })\n    })\n\n    await assert.rejects(async () => {\n      await testUtils.httpServer().start()\n    }, /listen EADDRINUSE: address already in use/)\n  })\n\n  test('raise error when closing an already closed server', async ({ assert, cleanup }) => {\n    const server = createServer()\n    cleanup(() => {\n      server.close()\n    })\n\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(BASE_URL)\n\n    const testUtils = new TestUtilsFactory().create(ignitor)\n    await testUtils.app.init()\n    await testUtils.app.boot()\n    await testUtils.boot()\n\n    const closeServer = await testUtils.httpServer().start(() => server)\n    assert.isTrue(server.listening)\n\n    await closeServer()\n    await assert.rejects(() => closeServer(), 'Server is not running.')\n  })\n\n  test('create HTTP context', async ({ assert }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(BASE_URL)\n\n    const testUtils = new TestUtilsFactory().create(ignitor)\n    await testUtils.app.init()\n    await testUtils.app.boot()\n    await testUtils.boot()\n\n    const context = await testUtils.createHttpContext()\n    assert.instanceOf(context, HttpContext)\n  })\n\n  test('create HTTP context with custom req and res object', async ({ assert }) => {\n    const ignitor = new IgnitorFactory()\n      .withCoreConfig()\n      .merge({\n        rcFileContents: {\n          providers: [() => import('../../providers/app_provider.js')],\n        },\n      })\n      .create(BASE_URL)\n\n    const testUtils = new TestUtilsFactory().create(ignitor)\n    await testUtils.app.init()\n    await testUtils.app.boot()\n    await testUtils.boot()\n\n    const req = new IncomingMessage(new Socket())\n    const res = new ServerResponse(req)\n\n    req.url = '/users/1'\n\n    const context = await testUtils.createHttpContext({ req, res })\n    assert.instanceOf(context, HttpContext)\n    assert.equal(context.request.url(), '/users/1')\n  })\n})\n"
  },
  {
    "path": "tests/verification_token.spec.ts",
    "content": "/*\n * @adonisjs/persona\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 timekeeper from 'timekeeper'\nimport { Secret } from '@poppinss/utils'\nimport base64 from '@poppinss/utils/base64'\nimport { getActiveTest, test } from '@japa/runner'\n\nimport { VerificationToken } from '../src/helpers/verification_token.ts'\n\nfunction freezeTime() {\n  const t = getActiveTest()\n  if (!t) {\n    throw new Error('Cannot use \"freezeTime\" outside of a Japa test')\n  }\n\n  timekeeper.reset()\n\n  const date = new Date()\n  timekeeper.freeze(date)\n\n  t.cleanup(() => {\n    timekeeper.reset()\n  })\n}\n\nclass EmailVerificationToken extends VerificationToken {\n  constructor(props: {\n    identifier: number\n    tokenableId: number\n    hash: string\n    expiresAt: Date\n    secret?: Secret<string>\n  }) {\n    super()\n    this.identifier = props.identifier\n    this.tokenableId = props.tokenableId\n    this.hash = props.hash\n    this.expiresAt = props.expiresAt\n    if (props.secret) {\n      this.computeValue(props.secret)\n    }\n  }\n}\n\ntest.group('VerificationToken token | decode', () => {\n  test('decode \"{input}\" as token')\n    .with([\n      {\n        input: null,\n        output: null,\n      },\n      {\n        input: '',\n        output: null,\n      },\n      {\n        input: '..',\n        output: null,\n      },\n      {\n        input: 'foobar',\n        output: null,\n      },\n      {\n        input: 'foo.baz',\n        output: null,\n      },\n      {\n        input: `bar.${base64.urlEncode('baz')}`,\n        output: null,\n      },\n      {\n        input: `${base64.urlEncode('baz')}.bar`,\n        output: null,\n      },\n      {\n        input: `${base64.urlEncode('bar')}.${base64.urlEncode('baz')}`,\n        output: {\n          identifier: 'bar',\n          secret: 'baz',\n        },\n      },\n    ])\n    .run(({ assert }, { input, output }) => {\n      const decoded = VerificationToken.decode(input as string)\n      if (!decoded) {\n        assert.deepEqual(decoded, output)\n      } else {\n        assert.deepEqual(\n          { identifier: decoded.identifier, secret: decoded.secret.release() },\n          output\n        )\n      }\n    })\n})\n\ntest.group('VerificationToken token | create', () => {\n  test('create a transient token', ({ assert }) => {\n    freezeTime()\n    const date = new Date()\n    const expiresAt = new Date()\n    expiresAt.setSeconds(date.getSeconds() + 60 * 20)\n\n    const token = VerificationToken.createTransientToken(1, 40, '20 mins')\n    assert.equal(token.userId, 1)\n    assert.exists(token.hash)\n    assert.equal(token.expiresAt!.getTime(), expiresAt.getTime())\n    assert.instanceOf(token.secret, Secret)\n  })\n\n  test('create token from persisted information', ({ assert }) => {\n    const createdAt = new Date()\n    const expiresAt = new Date()\n    expiresAt.setSeconds(createdAt.getSeconds() + 60 * 20)\n\n    const token = new EmailVerificationToken({\n      identifier: 12,\n      tokenableId: 1,\n      hash: '1234',\n      expiresAt,\n    })\n\n    assert.equal(token.identifier, 12)\n    assert.equal(token.hash, '1234')\n    assert.equal(token.tokenableId, 1)\n    assert.equal(token.expiresAt!.getTime(), expiresAt.getTime())\n\n    assert.isUndefined(token.value)\n    assert.isFalse(token.isExpired())\n  })\n\n  test('create token with a secret', ({ assert }) => {\n    const createdAt = new Date()\n    const expiresAt = new Date()\n    expiresAt.setSeconds(createdAt.getSeconds() + 60 * 20)\n\n    const transientToken = EmailVerificationToken.createTransientToken(1, 40, '20 mins')\n\n    const token = new EmailVerificationToken({\n      identifier: 12,\n      tokenableId: 1,\n      hash: transientToken.hash,\n      expiresAt,\n      secret: transientToken.secret,\n    })\n\n    const decoded = EmailVerificationToken.decode(token.value!.release())\n\n    assert.equal(token.identifier, 12)\n    assert.equal(token.tokenableId, 1)\n    assert.equal(token.hash, transientToken.hash)\n    assert.instanceOf(token.value, Secret)\n    assert.isTrue(token.verify(transientToken.secret))\n    assert.isTrue(token.verify(decoded!.secret))\n    assert.equal(token.expiresAt!.getTime(), expiresAt.getTime())\n    assert.isFalse(token.isExpired())\n  })\n\n  test('verify token hash', ({ assert }) => {\n    const transientToken = EmailVerificationToken.createTransientToken(1, 40, '20 mins')\n\n    const token = new EmailVerificationToken({\n      identifier: 12,\n      tokenableId: 1,\n      hash: transientToken.hash,\n      expiresAt: new Date(),\n      secret: transientToken.secret,\n    })\n\n    assert.isTrue(token.verify(transientToken.secret))\n  })\n})\n"
  },
  {
    "path": "toolkit/commands/index_commands.ts",
    "content": "/*\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 { join } from 'node:path'\nimport { args, BaseCommand, IndexGenerator } from '@adonisjs/ace'\n\n/**\n * Generates index of commands with a loader. Must be called against\n * the TypeScript compiled output.\n */\nexport default class IndexCommand extends BaseCommand {\n  static commandName = 'index'\n  static description: string = 'Create an index of commands along with a lazy loader'\n\n  @args.string({ description: 'Relative path from cwd to the commands directory' })\n  declare commandsDir: string\n\n  async run(): Promise<any> {\n    await new IndexGenerator(join(process.cwd(), this.commandsDir)).generate()\n  }\n}\n"
  },
  {
    "path": "toolkit/main.ts",
    "content": "#!/usr/bin/env node\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 { Kernel, ListLoader, HelpCommand } from '@adonisjs/ace'\nimport IndexCommand from './commands/index_commands.ts'\n\nconst kernel = Kernel.create()\nkernel.addLoader(new ListLoader([IndexCommand]))\n\nkernel.defineFlag('help', {\n  type: 'boolean',\n  description: HelpCommand.description,\n})\n\n/**\n * Flag listener to display the help\n */\nkernel.on('help', async (command, $kernel, parsed) => {\n  parsed.args.unshift(command.commandName)\n  const help = new HelpCommand($kernel, parsed, kernel.ui, kernel.prompt)\n  await help.exec()\n  return $kernel.shortcircuit()\n})\n\nawait kernel.handle(process.argv.splice(2))\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"extends\": \"@adonisjs/tsconfig/tsconfig.package.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"./\",\n    \"allowImportingTsExtensions\": true,\n    \"rewriteRelativeImportExtensions\": true,\n    \"outDir\": \"./build\"\n  }\n}\n"
  },
  {
    "path": "typedoc.json",
    "content": "{\n  \"$schema\": \"https://typedoc.org/schema.json\",\n  \"name\": \"@adonisjs/core\",\n  \"includeVersion\": true,\n  \"excludeExternals\": true,\n  \"entryPoints\": [\n    \"./index.ts\",\n    \"./commands/**/*.ts\",\n    \"./factories/**/*.ts\",\n    \"./modules/**/*.ts\",\n    \"./providers/**/*.ts\",\n    \"./services/**/*.ts\",\n    \"./src/types.ts\",\n    \"./src/helpers/main.ts\",\n    \"./src/exceptions.ts\",\n    \"./src/test_utils/main.ts\",\n    \"./src/vine.ts\",\n    \"./stubs/main.ts\"\n  ],\n  \"excludePrivate\": true,\n  \"excludeProtected\": true,\n  \"excludeInternal\": true,\n  \"readme\": \"none\",\n  \"gitRevision\": \"main\",\n  \"sort\": [\"source-order\"]\n}\n"
  },
  {
    "path": "types/ace.ts",
    "content": "/*\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 { CommandOptions as BaseCommandOptions } from '@adonisjs/ace/types'\nexport type CommandOptions = BaseCommandOptions & {\n  startApp?: boolean\n}\n\nexport * from '@adonisjs/ace/types'\n"
  },
  {
    "path": "types/app.ts",
    "content": "/*\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\nexport * from '@adonisjs/application/types'\n"
  },
  {
    "path": "types/bodyparser.ts",
    "content": "/*\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\nexport * from '@adonisjs/bodyparser/types'\n"
  },
  {
    "path": "types/common.ts",
    "content": "/*\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\nexport * from '@poppinss/utils/types'\n"
  },
  {
    "path": "types/container.ts",
    "content": "/*\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\nexport * from '@adonisjs/fold/types'\n"
  },
  {
    "path": "types/encryption.ts",
    "content": "/*\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\n/**\n * Contract that all encryption drivers must implement.\n *\n * Defines the interface for encrypting and decrypting values, including\n * support for optional purpose binding and child key derivation.\n */\nexport type { EncryptionDriverContract, EncryptionConfig } from '@boringnode/encryption/types'\n\n/**\n * Factory function signature for creating encryption driver instances.\n *\n * The factory receives an encryption key and returns a configured\n * driver instance. This pattern allows the manager to create drivers\n * on-demand with different keys.\n */\nexport type { ManagerDriverFactory } from '@boringnode/encryption/types'\n\n/**\n * Configuration options for the AES-256-CBC encryption driver.\n *\n * Includes the driver identifier and a list of encryption keys.\n * The first key is used for encryption, while all keys are tried\n * for decryption (allowing for key rotation).\n */\nexport type { AES256CBCDriverConfig } from '@boringnode/encryption/drivers/aes_256_cbc'\n\n/**\n * Configuration options for the AES-256-GCM encryption driver.\n *\n * Includes the driver identifier and a list of encryption keys.\n * The first key is used for encryption, while all keys are tried\n * for decryption (allowing for key rotation).\n */\nexport type { AES256GCMDriverConfig } from '@boringnode/encryption/drivers/aes_256_gcm'\n\n/**\n * Configuration options for the AES-SIV encryption driver.\n *\n * Includes the driver identifier and a single encryption key.\n */\nexport type { AESSIVDriverConfig } from '@boringnode/encryption/drivers/aes_siv'\n\n/**\n * Configuration options for the ChaCha20-Poly1305 encryption driver.\n *\n * Includes the driver identifier and a list of encryption keys.\n * The first key is used for encryption, while all keys are tried\n * for decryption (allowing for key rotation).\n */\nexport type { ChaCha20Poly1305DriverConfig } from '@boringnode/encryption/drivers/chacha20_poly1305'\n\n/**\n * Configuration options for the Legacy encryption driver.\n *\n * The Legacy driver maintains compatibility with the old AdonisJS v6\n * encryption format. It does not require a driver identifier since\n * the legacy format doesn't include one.\n */\nexport type { LegacyDriverConfig } from '../modules/encryption/drivers/legacy.ts'\n"
  },
  {
    "path": "types/events.ts",
    "content": "/*\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\nexport * from '@adonisjs/events/types'\n"
  },
  {
    "path": "types/hash.ts",
    "content": "/*\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\nexport * from '@adonisjs/hash/types'\n"
  },
  {
    "path": "types/health.ts",
    "content": "/*\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\nexport * from '@adonisjs/health/types'\n"
  },
  {
    "path": "types/helpers.ts",
    "content": "/*\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\n/**\n * Helper types and utilities for AdonisJS applications.\n * Re-exports commonly used type utilities and file system operation types.\n *\n * @example\n * // Use Opaque type for branded primitives\n * import type { Opaque } from '@adonisjs/core/types/helpers'\n *\n * type UserId = Opaque<'UserId', number>\n * const userId: UserId = 123 as UserId\n *\n * @example\n * // Use file system option types\n * import type { ImportAllFilesOptions } from '@adonisjs/core/types/helpers'\n *\n * const options: ImportAllFilesOptions = {\n *   ignoreMissingExports: true,\n *   transformKeys: (key) => key.toLowerCase()\n * }\n */\nexport type { Opaque, NormalizeConstructor } from '@poppinss/utils/types'\nexport type { ImportAllFilesOptions, ReadAllFilesOptions } from '@poppinss/utils/fs'\n"
  },
  {
    "path": "types/http.ts",
    "content": "/*\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\nexport * from '@adonisjs/http-server/types'\nimport type { ValidationOptions } from '@vinejs/vine/types'\nexport type { InferRouteParams } from '@poppinss/utils/types'\n\n/**\n * Validation options accepted by the \"request.validateUsing\" method\n */\nexport type RequestValidationOptions<MetaData extends undefined | Record<string, any>> =\n  ValidationOptions<MetaData> & { data?: any }\n"
  },
  {
    "path": "types/logger.ts",
    "content": "/*\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\nexport * from '@adonisjs/logger/types'\n"
  },
  {
    "path": "types/repl.ts",
    "content": "/*\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\nexport * from '@adonisjs/repl/types'\n"
  },
  {
    "path": "types/transformers.ts",
    "content": "/*\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\nexport * from '@adonisjs/http-transformers/types'\n"
  }
]