diff --git a/.github/actions/actionsLib.mjs b/.github/actions/actionsLib.mjs index 8702ffde13d9..686beb1dc88d 100644 --- a/.github/actions/actionsLib.mjs +++ b/.github/actions/actionsLib.mjs @@ -1,6 +1,7 @@ /* eslint-env node */ // @ts-check +import fs from 'node:fs' import path from 'node:path' import { fileURLToPath } from 'node:url' @@ -98,3 +99,69 @@ export async function createCacheKeys({ baseKeyPrefix, distKeyPrefix }) { distKey } } + +/** + * @callback ExecInProject + * @param {string} commandLine command to execute (can include additional args). Must be correctly escaped. + * @param {Omit=} options exec options. See ExecOptions + * @returns {Promise} exit code + */ + +/** + * @param {string} testProjectPath + * @param {string} fixtureName + * @param {Object} core + * @param {(key: string, value: string) => void} core.setOutput + * @param {ExecInProject} execInProject + * @returns {Promise} + */ +export async function setUpRscTestProject( + testProjectPath, + fixtureName, + core, + execInProject +) { + core.setOutput('test-project-path', testProjectPath) + + console.log('rwPath', REDWOOD_FRAMEWORK_PATH) + console.log('testProjectPath', testProjectPath) + + const fixturePath = path.join( + REDWOOD_FRAMEWORK_PATH, + '__fixtures__', + fixtureName + ) + const rwBinPath = path.join( + REDWOOD_FRAMEWORK_PATH, + 'packages/cli/dist/index.js' + ) + const rwfwBinPath = path.join( + REDWOOD_FRAMEWORK_PATH, + 'packages/cli/dist/rwfw.js' + ) + + console.log(`Creating project at ${testProjectPath}`) + console.log() + fs.cpSync(fixturePath, testProjectPath, { recursive: true }) + + console.log(`Adding framework dependencies to ${testProjectPath}`) + await projectDeps(testProjectPath) + console.log() + + console.log(`Installing node_modules in ${testProjectPath}`) + await execInProject('yarn install') + + console.log(`Building project in ${testProjectPath}`) + await execInProject(`node ${rwBinPath} build -v`) + console.log() + + console.log(`Copying over framework files to ${testProjectPath}`) + await execInProject(`node ${rwfwBinPath} project:copy`, { + env: { RWFW_PATH: REDWOOD_FRAMEWORK_PATH }, + }) + console.log() + + // await cache.saveCache([testProjectPath], dependenciesKey) + // console.log(`Cache saved with key: ${dependenciesKey}`) +} + diff --git a/.github/actions/check_create_redwood_app/action.yml b/.github/actions/check_create_redwood_app/action.yml index dfef0c061eda..c3d123004953 100644 --- a/.github/actions/check_create_redwood_app/action.yml +++ b/.github/actions/check_create_redwood_app/action.yml @@ -1,8 +1,7 @@ name: Check create redwood app description: Determines if the create redwood app JS template should be rebuilt runs: - # `node18` isn't supported yet - using: node16 + using: node20 main: check_create_redwood_app.mjs inputs: labels: diff --git a/.github/actions/check_test_project_fixture/action.yml b/.github/actions/check_test_project_fixture/action.yml index e71e828528cc..43374e7ea0e7 100644 --- a/.github/actions/check_test_project_fixture/action.yml +++ b/.github/actions/check_test_project_fixture/action.yml @@ -1,8 +1,7 @@ name: Check test project fixture description: Determines if the test project fixture should be rebuilt runs: - # `node18` isn't supported yet - using: node16 + using: node20 main: check_test_project_fixture.mjs inputs: labels: diff --git a/.github/actions/only_doc_changes/action.yml b/.github/actions/only_doc_changes/action.yml index dc7e45989aba..d1c683f50219 100644 --- a/.github/actions/only_doc_changes/action.yml +++ b/.github/actions/only_doc_changes/action.yml @@ -4,6 +4,5 @@ outputs: only-doc-changes: description: If the PR only changes docs runs: - # `node18` isn't supported yet - using: node16 + using: node20 main: only_doc_changes.mjs diff --git a/.github/actions/require-milestone/action.yml b/.github/actions/require-milestone/action.yml index 7faafed88aef..3f89663494d9 100644 --- a/.github/actions/require-milestone/action.yml +++ b/.github/actions/require-milestone/action.yml @@ -2,6 +2,5 @@ name: Require milestone description: Ensures that a PR has a valid milestone runs: - # `node18` isn't supported yet - using: node16 + using: node20 main: requireMilestone.mjs diff --git a/.github/actions/rsc_related_changes/action.yml b/.github/actions/rsc_related_changes/action.yml index 43cba17a9774..6c1a8e1c293c 100644 --- a/.github/actions/rsc_related_changes/action.yml +++ b/.github/actions/rsc_related_changes/action.yml @@ -4,6 +4,5 @@ outputs: rsc-related-changes: description: If the PR makes any RSC related changes runs: - # `node18` isn't supported yet - using: node16 + using: node20 main: rsc_related_changes.mjs diff --git a/.github/actions/rsc_related_changes/rsc_related_changes.mjs b/.github/actions/rsc_related_changes/rsc_related_changes.mjs index 4077b1d9b98f..42ff60c26495 100644 --- a/.github/actions/rsc_related_changes/rsc_related_changes.mjs +++ b/.github/actions/rsc_related_changes/rsc_related_changes.mjs @@ -27,7 +27,10 @@ async function main() { // starting point. if ( changedFile.startsWith('tasks/smoke-tests/rsc/') || + changedFile.startsWith('tasks/smoke-tests/rsa/') || changedFile.startsWith('tasks/smoke-tests/basePlaywright.config.ts') || + changedFile.startsWith('.github/actions/set-up-rsa-project/') || + changedFile.startsWith('.github/actions/set-up-rsc-external-packages-project/') || changedFile.startsWith('.github/actions/set-up-rsc-project/') || changedFile.startsWith('github/actions/rsc_related_changes/') || changedFile.startsWith('packages/internal/') || diff --git a/.github/actions/set-up-rsa-project/README.md b/.github/actions/set-up-rsa-project/README.md new file mode 100644 index 000000000000..0bf518131d44 --- /dev/null +++ b/.github/actions/set-up-rsa-project/README.md @@ -0,0 +1,29 @@ +# GitHub action to copy a template RSA project to use for testing + +This action copies a RW project with Streaming SSR and RSC support already set +up. It's used for RSA smoke tests. + +It copies the `__fixtures__/test-project-rsa` project, runs `yarn install` and +`project:copy`. Finally it builds the rw app. + +## Testing/running locally + +Go into the github actions folder +`cd .github/actions` + +Then run the following command to execute the action +`node set-up-rsa-project/setUpRsaProjectLocally.mjs` + +## Design + +The main logic of the action is in the `../actionsLib.mjs` file. To be able to +run that code both on GitHub and locally it uses dependency injection. The +injection is done by `setupRsaProjectLocally.mjs` for when you want to run the +action on your own machine and by `setupRsaProjectGitHib.mjs` when it's +triggered by GitHub CI. + +When doing further changes to the code here it's very important to keep the +DI scripts as light on logic as possible. Ideally all logic is kept to +`../actionsLib.mjs` so that the same logic is used both locally and on GitHub. +Do note though that more actions share that code, so make sure not to break +the other actions when making changes there. diff --git a/.github/actions/set-up-rsa-project/action.yaml b/.github/actions/set-up-rsa-project/action.yaml new file mode 100644 index 000000000000..066eb600010a --- /dev/null +++ b/.github/actions/set-up-rsa-project/action.yaml @@ -0,0 +1,10 @@ +name: Set up RSA test project from fixture +description: Sets up an RSA project for smoke-tests + +runs: + using: node20 + main: 'setUpRsaProjectGitHub.mjs' + +outputs: + test-project-path: + description: Path to the test project diff --git a/.github/actions/set-up-rsa-project/jsconfig.json b/.github/actions/set-up-rsa-project/jsconfig.json new file mode 100644 index 000000000000..8effcfaa09ef --- /dev/null +++ b/.github/actions/set-up-rsa-project/jsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "noEmit": true, + "esModuleInterop": true, + "target": "esnext", + "module": "esnext", + "moduleResolution": "node", + "skipLibCheck": false, + "jsx": "react-jsx" + }, +} diff --git a/.github/actions/set-up-rsa-project/package.json b/.github/actions/set-up-rsa-project/package.json new file mode 100644 index 000000000000..196dba219d44 --- /dev/null +++ b/.github/actions/set-up-rsa-project/package.json @@ -0,0 +1,6 @@ +{ + "name": "set-up-rsa-project", + "version": "0.0.0", + "private": true, + "type": "module" +} diff --git a/.github/actions/set-up-rsa-project/setUpRsaProjectGitHub.mjs b/.github/actions/set-up-rsa-project/setUpRsaProjectGitHub.mjs new file mode 100644 index 000000000000..497d82e4c9bf --- /dev/null +++ b/.github/actions/set-up-rsa-project/setUpRsaProjectGitHub.mjs @@ -0,0 +1,22 @@ +/* eslint-env node */ +// @ts-check + +import path from 'node:path' + +import core from '@actions/core' + +import { createExecWithEnvInCwd, setUpRscTestProject } from '../actionsLib.mjs' + +const testProjectAndFixtureName = 'test-project-rsa' +const testProjectPath = path.join( + path.dirname(process.cwd()), + testProjectAndFixtureName +) +const execInProject = createExecWithEnvInCwd(testProjectPath) + +setUpRscTestProject( + testProjectPath, + testProjectAndFixtureName, + core, + execInProject +) diff --git a/.github/actions/set-up-rsa-project/setUpRsaProjectLocally.mjs b/.github/actions/set-up-rsa-project/setUpRsaProjectLocally.mjs new file mode 100644 index 000000000000..8e9baa044594 --- /dev/null +++ b/.github/actions/set-up-rsa-project/setUpRsaProjectLocally.mjs @@ -0,0 +1,111 @@ +/* eslint-env node */ +// @ts-check + +import os from 'node:os' +import path from 'node:path' + +import execa from 'execa' + +import { setUpRscTestProject } from '../actionsLib.mjs' + +class ExecaError extends Error { + stdout + stderr + exitCode + + constructor({ stdout, stderr, exitCode }) { + super(`execa failed with exit code ${exitCode}`) + this.stdout = stdout + this.stderr = stderr + this.exitCode = exitCode + } +} + +/** + * @template [EncodingType=string] + * @typedef {import('execa').Options} ExecaOptions + */ + +/** + * @typedef {{ + * env?: Record + * }} ExecOptions + */ + +/** + * @param {string} commandLine command to execute (can include additional args). Must be correctly escaped. + * @param {string[]=} args arguments for tool. Escaping is handled by the lib. + * @param {ExecOptions=} options exec options. See ExecOptions + */ +async function exec(commandLine, args, options) { + return execa(commandLine, args, options) + .then(({ stdout, stderr, exitCode }) => { + if (exitCode !== 0) { + throw new ExecaError({ stdout, stderr, exitCode }) + } + }) + .catch((error) => { + if (error instanceof ExecaError) { + // Rethrow ExecaError + throw error + } else { + const { stdout, stderr, exitCode } = error + console.log('error', error) + throw new ExecaError({ stdout, stderr, exitCode }) + } + }) +} + +/** + * @param {string} cwd + * @param {Record=} env + * @returns {ExecaOptions} + */ +function getExecaOptions(cwd, env = {}) { + return { + shell: true, + stdio: 'inherit', + cleanup: true, + cwd, + env, + } +} + +const testProjectAndFixtureName = 'test-project-rsa' + +const testProjectPath = path.join( + os.tmpdir(), + 'redwood', + testProjectAndFixtureName, + // ":" is problematic with paths + new Date().toISOString().split(':').join('-') +) + +// Mock for @actions/core +const core = { + setOutput: () => {}, +} + +/** + * Exec a command. + * Output will be streamed to the live console. + * Returns promise with return code + * + * @param {string} commandLine command to execute (can include additional args). Must be correctly escaped. + * @param {ExecOptions=} options exec options. See ExecOptions + * @returns {Promise} exit code + */ +function execInProject(commandLine, options) { + return exec( + commandLine, + undefined, + getExecaOptions(testProjectPath, options?.env) + ) +} + +setUpRscTestProject( + testProjectPath, + testProjectAndFixtureName, + core, + execInProject +) diff --git a/.github/actions/set-up-rsc-external-packages-project/README.md b/.github/actions/set-up-rsc-external-packages-project/README.md new file mode 100644 index 000000000000..8c47dc603dd5 --- /dev/null +++ b/.github/actions/set-up-rsc-external-packages-project/README.md @@ -0,0 +1,29 @@ +# GitHub action to copy a template RSC project to use for testing + +This action copies a RW project with Streaming SSR and RSC support already set +up. It's used for RSC smoke tests. + +It copies the `__fixtures__/test-project-rsc-external-packages` project, runs +`yarn install` and `project:copy`. Finally it builds the rw app. + +## Testing/running locally + +Go into the github actions folder +`cd .github/actions` + +Then run the following command to execute the action +`node set-up-rsc-external-packages-project/setUpRscExternalPackagesProjectLocally.mjs` + +## Design + +The main logic of the action is in the `../actionsLib.mjs` file. To be able to +run that code both on GitHub and locally it uses dependency injection. The +injection is done by `setupRscExternalPackagesProjectLocally.mjs` for when you +want to run the action on your own machine and by +`setupRscExternalPackagesProjectGitHib.mjs` when it's triggered by GitHub CI. + +When doing further changes to the code here it's very important to keep the +DI scripts as light on logic as possible. Ideally all logic is kept to +`../actionsLib.mjs` so that the same logic is used both locally and on GitHub. +Do note though that more actions share that code, so make sure not to break +the other actions when making changes there. diff --git a/.github/actions/set-up-rsc-external-packages-project/action.yaml b/.github/actions/set-up-rsc-external-packages-project/action.yaml new file mode 100644 index 000000000000..cdac1d7c9fbc --- /dev/null +++ b/.github/actions/set-up-rsc-external-packages-project/action.yaml @@ -0,0 +1,10 @@ +name: Set up RSC test project with external packages from fixture +description: Sets up an RSC project that imports external packages for smoke-tests + +runs: + using: node20 + main: 'setUpRscExternalPackagesProjectGitHub.mjs' + +outputs: + test-project-path: + description: Path to the test project diff --git a/.github/actions/set-up-rsc-external-packages-project/jsconfig.json b/.github/actions/set-up-rsc-external-packages-project/jsconfig.json new file mode 100644 index 000000000000..8effcfaa09ef --- /dev/null +++ b/.github/actions/set-up-rsc-external-packages-project/jsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "noEmit": true, + "esModuleInterop": true, + "target": "esnext", + "module": "esnext", + "moduleResolution": "node", + "skipLibCheck": false, + "jsx": "react-jsx" + }, +} diff --git a/.github/actions/set-up-rsc-external-packages-project/package.json b/.github/actions/set-up-rsc-external-packages-project/package.json new file mode 100644 index 000000000000..8dd1f5abbe06 --- /dev/null +++ b/.github/actions/set-up-rsc-external-packages-project/package.json @@ -0,0 +1,6 @@ +{ + "name": "set-up-rsc-external-packages-project", + "version": "0.0.0", + "private": true, + "type": "module" +} diff --git a/.github/actions/set-up-rsc-external-packages-project/setUpRscExternalPackagesProjectGitHub.mjs b/.github/actions/set-up-rsc-external-packages-project/setUpRscExternalPackagesProjectGitHub.mjs new file mode 100644 index 000000000000..e09f3f597d5f --- /dev/null +++ b/.github/actions/set-up-rsc-external-packages-project/setUpRscExternalPackagesProjectGitHub.mjs @@ -0,0 +1,22 @@ +/* eslint-env node */ +// @ts-check + +import path from 'node:path' + +import core from '@actions/core' + +import { createExecWithEnvInCwd, setUpRscTestProject } from '../actionsLib.mjs' + +const testProjectAndFixtureName = 'test-project-rsc-external-packages' +const testProjectPath = path.join( + path.dirname(process.cwd()), + testProjectAndFixtureName +) +const execInProject = createExecWithEnvInCwd(testProjectPath) + +setUpRscTestProject( + testProjectPath, + testProjectAndFixtureName, + core, + execInProject +) diff --git a/.github/actions/set-up-rsc-external-packages-project/setUpRscExternalPackagesProjectLocally.mjs b/.github/actions/set-up-rsc-external-packages-project/setUpRscExternalPackagesProjectLocally.mjs new file mode 100644 index 000000000000..2f2af2c87d85 --- /dev/null +++ b/.github/actions/set-up-rsc-external-packages-project/setUpRscExternalPackagesProjectLocally.mjs @@ -0,0 +1,111 @@ +/* eslint-env node */ +// @ts-check + +import os from 'node:os' +import path from 'node:path' + +import execa from 'execa' + +import { setUpRscTestProject } from '../actionsLib.mjs' + +class ExecaError extends Error { + stdout + stderr + exitCode + + constructor({ stdout, stderr, exitCode }) { + super(`execa failed with exit code ${exitCode}`) + this.stdout = stdout + this.stderr = stderr + this.exitCode = exitCode + } +} + +/** + * @template [EncodingType=string] + * @typedef {import('execa').Options} ExecaOptions + */ + +/** + * @typedef {{ + * env?: Record + * }} ExecOptions + */ + +/** + * @param {string} commandLine command to execute (can include additional args). Must be correctly escaped. + * @param {string[]=} args arguments for tool. Escaping is handled by the lib. + * @param {ExecOptions=} options exec options. See ExecOptions + */ +async function exec(commandLine, args, options) { + return execa(commandLine, args, options) + .then(({ stdout, stderr, exitCode }) => { + if (exitCode !== 0) { + throw new ExecaError({ stdout, stderr, exitCode }) + } + }) + .catch((error) => { + if (error instanceof ExecaError) { + // Rethrow ExecaError + throw error + } else { + const { stdout, stderr, exitCode } = error + console.log('error', error) + throw new ExecaError({ stdout, stderr, exitCode }) + } + }) +} + +/** + * @param {string} cwd + * @param {Record=} env + * @returns {ExecaOptions} + */ +function getExecaOptions(cwd, env = {}) { + return { + shell: true, + stdio: 'inherit', + cleanup: true, + cwd, + env, + } +} + +const testProjectAndFixtureName = 'test-project-rsc-external-packages' + +const testProjectPath = path.join( + os.tmpdir(), + 'redwood', + testProjectAndFixtureName, + // ":" is problematic with paths + new Date().toISOString().split(':').join('-') +) + +// Mock for @actions/core +const core = { + setOutput: () => {}, +} + +/** + * Exec a command. + * Output will be streamed to the live console. + * Returns promise with return code + * + * @param {string} commandLine command to execute (can include additional args). Must be correctly escaped. + * @param {ExecOptions=} options exec options. See ExecOptions + * @returns {Promise} exit code + */ +function execInProject(commandLine, options) { + return exec( + commandLine, + undefined, + getExecaOptions(testProjectPath, options?.env) + ) +} + +setUpRscTestProject( + testProjectPath, + testProjectAndFixtureName, + core, + execInProject +) diff --git a/.github/actions/set-up-rsc-project/setUpRscProject.mjs b/.github/actions/set-up-rsc-project/setUpRscProject.mjs index 625da3cc3ddb..adf51d038123 100644 --- a/.github/actions/set-up-rsc-project/setUpRscProject.mjs +++ b/.github/actions/set-up-rsc-project/setUpRscProject.mjs @@ -97,7 +97,7 @@ async function setUpRscProject( await execInProject(`node ${rwBinPath} build -v`) console.log() - console.log(`Building project in ${rscProjectPath}`) + console.log(`Copying over framework files to ${rscProjectPath}`) await execInProject(`node ${rwfwBinPath} project:copy`, { env: { RWFW_PATH: REDWOOD_FRAMEWORK_PATH }, }) diff --git a/.github/actions/set-up-rsc-project/setUpRscProjectLocally.mjs b/.github/actions/set-up-rsc-project/setUpRscProjectLocally.mjs index 5ab951f82775..c5c57ab2b31f 100644 --- a/.github/actions/set-up-rsc-project/setUpRscProjectLocally.mjs +++ b/.github/actions/set-up-rsc-project/setUpRscProjectLocally.mjs @@ -73,7 +73,7 @@ function getExecaOptions(cwd, env = {}) { const rscProjectPath = path.join( os.tmpdir(), - 'rsc-project', + 'redwood-rsc-project', // ":" is problematic with paths new Date().toISOString().split(':').join('-') ) diff --git a/.github/actions/set-up-test-project/action.yaml b/.github/actions/set-up-test-project/action.yaml index 0411c26bc66f..9866507ab1db 100644 --- a/.github/actions/set-up-test-project/action.yaml +++ b/.github/actions/set-up-test-project/action.yaml @@ -2,8 +2,7 @@ name: Set up test project description: Sets up the test project fixture in CI for smoke tests and CLI checks runs: - # `node18` isn't supported yet - using: node16 + using: node20 main: 'setUpTestProject.mjs' inputs: diff --git a/.github/actions/update_all_contributors/action.yml b/.github/actions/update_all_contributors/action.yml index 66a4b65f36e3..46dd2eb16cc1 100644 --- a/.github/actions/update_all_contributors/action.yml +++ b/.github/actions/update_all_contributors/action.yml @@ -1,6 +1,5 @@ name: Update all contributors description: Updates all contributors runs: - # `node18` isn't supported yet - using: node16 + using: node20 main: update_all_contributors.mjs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed7414923531..dfae09db3117 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -532,6 +532,34 @@ jobs: REDWOOD_TEST_PROJECT_PATH: ${{ steps.set-up-rsc-project.outputs.rsc-project-path }} REDWOOD_DISABLE_TELEMETRY: 1 + - name: ๐ŸŒฒ Set up RSA smoke test + id: set-up-rsa-project + uses: ./.github/actions/set-up-rsa-project + env: + REDWOOD_DISABLE_TELEMETRY: 1 + YARN_ENABLE_IMMUTABLE_INSTALLS: false + + - name: ๐Ÿ˜ Run RSA smoke tests + working-directory: tasks/smoke-tests/rsa + run: npx playwright test + env: + REDWOOD_TEST_PROJECT_PATH: ${{ steps.set-up-rsa-project.outputs.test-project-path }} + REDWOOD_DISABLE_TELEMETRY: 1 + + - name: ๐ŸŒฒ Set up RSC external packages smoke test + id: set-up-rsc-external-packages-project + uses: ./.github/actions/set-up-rsc-external-packages-project + env: + REDWOOD_DISABLE_TELEMETRY: 1 + YARN_ENABLE_IMMUTABLE_INSTALLS: false + + - name: ๐Ÿ˜ Run RSC external packages smoke tests + working-directory: tasks/smoke-tests/rsc-external-packages + run: npx playwright test + env: + REDWOOD_TEST_PROJECT_PATH: ${{ steps.set-up-rsc-external-packages-project.outputs.test-project-path }} + REDWOOD_DISABLE_TELEMETRY: 1 + rsc-smoke-tests-mock: needs: rsc-related-changes if: needs.rsc-related-changes.outputs.rsc-related-changes != 'true' @@ -545,3 +573,44 @@ jobs: steps: - run: echo "RSC smoke tests mock" + + server-tests: + needs: check + + name: ๐Ÿ“ก๐Ÿ” server tests / node 18 latest + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: โฌข Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: 18 + + - name: ๐Ÿˆ Set up yarn cache + uses: ./.github/actions/set-up-yarn-cache + + - name: ๐Ÿˆ Yarn install + run: yarn install --inline-builds + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: ๐Ÿ”จ Build + run: yarn build + + - name: ๐Ÿงช Test + run: yarn jest server.test.ts + working-directory: ./tasks/server-tests + env: + REDWOOD_DISABLE_TELEMETRY: 1 + + server-tests-docs: + needs: only-doc-changes + if: needs.only-doc-changes.outputs.only-doc-changes == 'true' + + name: ๐Ÿ“ก๐Ÿ” server tests / node 18 latest + runs-on: ubuntu-latest + + steps: + - run: echo "Only doc changes" diff --git a/__fixtures__/test-project-rsa/.editorconfig b/__fixtures__/test-project-rsa/.editorconfig new file mode 100644 index 000000000000..ae10a5cce3b2 --- /dev/null +++ b/__fixtures__/test-project-rsa/.editorconfig @@ -0,0 +1,10 @@ +# editorconfig.org +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/__fixtures__/test-project-rsa/.env.defaults b/__fixtures__/test-project-rsa/.env.defaults new file mode 100644 index 000000000000..fb88fb33b334 --- /dev/null +++ b/__fixtures__/test-project-rsa/.env.defaults @@ -0,0 +1,19 @@ +# These environment variables will be used by default if you do not create any +# yourself in .env. This file should be safe to check into your version control +# system. Any custom values should go in .env and .env should *not* be checked +# into version control. + +# schema.prisma defaults +DATABASE_URL=file:./dev.db + +# location of the test database for api service scenarios (defaults to ./.redwood/test.db if not set) +# TEST_DATABASE_URL=file:./.redwood/test.db + +# disables Prisma CLI update notifier +PRISMA_HIDE_UPDATE_MESSAGE=true + +# Option to override the current environment's default api-side log level +# See: https://redwoodjs.com/docs/logger for level options, defaults to "trace" otherwise. +# Most applications want "debug" or "info" during dev, "trace" when you have issues and "warn" in production. +# Ordered by how verbose they are: trace | debug | info | warn | error | silent +# LOG_LEVEL=debug diff --git a/__fixtures__/test-project-rsa/.env.example b/__fixtures__/test-project-rsa/.env.example new file mode 100644 index 000000000000..2a2de6c026ca --- /dev/null +++ b/__fixtures__/test-project-rsa/.env.example @@ -0,0 +1,4 @@ +# DATABASE_URL=file:./dev.db +# TEST_DATABASE_URL=file:./.redwood/test.db +# PRISMA_HIDE_UPDATE_MESSAGE=true +# LOG_LEVEL=trace diff --git a/__fixtures__/test-project-rsa/.gitignore b/__fixtures__/test-project-rsa/.gitignore new file mode 100644 index 000000000000..9b8149560d9b --- /dev/null +++ b/__fixtures__/test-project-rsa/.gitignore @@ -0,0 +1,22 @@ +.idea +.DS_Store +.env +.netlify +.redwood/* +!.redwood/README.md +dev.db* +dist +dist-babel +node_modules +yarn-error.log +web/public/mockServiceWorker.js +web/types/graphql.d.ts +api/types/graphql.d.ts +api/src/lib/generateGraphiQLHeader.* +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions diff --git a/__fixtures__/test-project-rsa/.gitpod.yml b/__fixtures__/test-project-rsa/.gitpod.yml new file mode 100644 index 000000000000..a357a6e8c9a9 --- /dev/null +++ b/__fixtures__/test-project-rsa/.gitpod.yml @@ -0,0 +1,25 @@ +# To learn about this file, please see https://www.gitpod.io/docs/references/gitpod-yml + +image: gitpod/workspace-node-lts + +tasks: + - init: | + # Cleanup terminal + printf "\033[3J\033c\033[3J" + + yarn install + + command: yarn rw build -v && yarn rw serve +ports: + - port: 8910 + name: RedwoodJS web application + onOpen: notify # because we already have [browser].open = true in redwood.toml + - port: 8911 + name: Serverless functions + onOpen: ignore + +vscode: + extensions: + - "dbaeumer.vscode-eslint" + - "mgmcdermott.vscode-language-babel" + - "editorconfig.editorconfig" diff --git a/__fixtures__/test-project-rsa/.nvmrc b/__fixtures__/test-project-rsa/.nvmrc new file mode 100644 index 000000000000..b009dfb9d9f9 --- /dev/null +++ b/__fixtures__/test-project-rsa/.nvmrc @@ -0,0 +1 @@ +lts/* diff --git a/__fixtures__/test-project-rsa/.redwood/README.md b/__fixtures__/test-project-rsa/.redwood/README.md new file mode 100644 index 000000000000..f22b586a47cc --- /dev/null +++ b/__fixtures__/test-project-rsa/.redwood/README.md @@ -0,0 +1,44 @@ +# .redwood + +## What is this directory? + +Redwood uses this `.redwood` directory to store transitory data that aids in the smooth and convenient operation of your Redwood project. + +## Do I need to do anything with this directory? + +No. You shouldn't have to create, edit or delete anything in this directory in your day-to-day work with Redwood. + +You don't need to commit any other contents of this directory to your version control system. It's ignored by default. + +## What's in this directory? + +### Files + +| Name | Description | +| :---------------- | :------- | +| commandCache.json | This file contains mappings to assist the Redwood CLI in efficiently executing commands. | +| schema.graphql | This is the GraphQL schema which has been automatically generated from your Redwood project. | +| studio.db | The sqlite database used by the experimental `rw exp studio` feature. | +| telemetry.txt | Contains a unique ID used for telemetry. This value is rotated every 24 hours to protect your project's anonymity. | +| test.db | The sqlite database used when running tests. | + +### Directories + +| Name | Description | +| :---------- | :------- | +| locks | Stores temporary files that Redwood uses to keep track of the execution of async/background tasks between processes. | +| logs | Stores log files for background tasks such as update checking. | +| prebuild | Stores transpiled JavaScript that is generated as part of Redwood's build process. | +| telemetry | Stores the recent telemetry that the Redwood CLI has generated. You may inspect these files to see everything Redwood is anonymously collecting. | +| types | Stores the results of type generation. | +| updateCheck | Stores a file which contains the results of checking for Redwood updates. | + +We try to keep this README up to date but you may, from time to time, find other files or directories in this `.redwood` directory that have not yet been documented here. This is likely nothing to worry about but feel free to let us know and we'll update this list. + +### Telemetry + +RedwoodJS collects completely anonymous telemetry data about general usage. For transparency, that data is viewable in the respective directories and files. To learn more and manage your project's settings, visit [telemetry.redwoodjs.com](https://telemetry.redwoodjs.com). + +### Have any questions? + +Feel free to reach out to us in the [RedwoodJS Community](https://community.redwoodjs.com/) forum if you have any questions. diff --git a/__fixtures__/test-project-rsa/.vscode/extensions.json b/__fixtures__/test-project-rsa/.vscode/extensions.json new file mode 100644 index 000000000000..7fc50a119fc6 --- /dev/null +++ b/__fixtures__/test-project-rsa/.vscode/extensions.json @@ -0,0 +1,14 @@ +{ + "recommendations": [ + "dbaeumer.vscode-eslint", + "eamodio.gitlens", + "ofhumanbondage.react-proptypes-intellisense", + "mgmcdermott.vscode-language-babel", + "wix.vscode-import-cost", + "pflannery.vscode-versionlens", + "editorconfig.editorconfig", + "prisma.prisma", + "graphql.vscode-graphql" + ], + "unwantedRecommendations": [] +} diff --git a/__fixtures__/test-project-rsa/.vscode/launch.json b/__fixtures__/test-project-rsa/.vscode/launch.json new file mode 100644 index 000000000000..ea5956966fff --- /dev/null +++ b/__fixtures__/test-project-rsa/.vscode/launch.json @@ -0,0 +1,36 @@ +{ + "version": "0.3.0", + "configurations": [ + { + "command": "yarn redwood dev --apiDebugPort 18911", + "name": "Run Dev Server", + "request": "launch", + "type": "node-terminal" + }, + { + "name": "Attach API debugger", + "port": 18911, // you can change this port, see https://redwoodjs.com/docs/project-configuration-dev-test-build#debugger-configuration + "request": "attach", + "skipFiles": [ + "/**" + ], + "type": "node", + "localRoot": "${workspaceFolder}/node_modules/@redwoodjs/api-server/dist", + "remoteRoot": "${workspaceFolder}/node_modules/@redwoodjs/api-server/dist", + "sourceMaps": true, + "restart": true + }, + { + "command": "yarn redwood test api", + "name": "Test api", + "request": "launch", + "type": "node-terminal" + }, + { + "command": "yarn redwood test web", + "name": "Test web", + "request": "launch", + "type": "node-terminal" + }, + ] +} diff --git a/__fixtures__/test-project-rsa/.vscode/settings.json b/__fixtures__/test-project-rsa/.vscode/settings.json new file mode 100644 index 000000000000..bb0578ddbbf8 --- /dev/null +++ b/__fixtures__/test-project-rsa/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "editor.tabSize": 2, + "files.trimTrailingWhitespace": true, + "editor.formatOnSave": false, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true + }, + "[prisma]": { + "editor.formatOnSave": true + } +} diff --git a/__fixtures__/test-project-rsa/.yarn/patches/vite-npm-4.4.9-e845c1bbf8.patch b/__fixtures__/test-project-rsa/.yarn/patches/vite-npm-4.4.9-e845c1bbf8.patch new file mode 100644 index 000000000000..eb67d7906284 --- /dev/null +++ b/__fixtures__/test-project-rsa/.yarn/patches/vite-npm-4.4.9-e845c1bbf8.patch @@ -0,0 +1,19 @@ +diff --git a/dist/node/chunks/dep-df561101.js b/dist/node/chunks/dep-df561101.js +index 1bc8674177fe73120171b22436e6104713c5d764..f0fee7b385868cb01c6d47b80d7f64a7368c0412 100644 +--- a/dist/node/chunks/dep-df561101.js ++++ b/dist/node/chunks/dep-df561101.js +@@ -55890,12 +55890,12 @@ async function instantiateModule(url, server, context = { global }, urlStack = [ + }; + urlStack = urlStack.concat(url); + const isCircular = (url) => urlStack.includes(url); +- const { isProduction, resolve: { dedupe, preserveSymlinks }, root, } = server.config; ++ const { isProduction, resolve: { dedupe, preserveSymlinks, conditions }, root, } = server.config; + const resolveOptions = { + mainFields: ['main'], + browserField: true, + conditions: [], +- overrideConditions: ['production', 'development'], ++ overrideConditions: [...conditions, 'production', 'development'], + extensions: ['.js', '.cjs', '.json'], + dedupe, + preserveSymlinks, diff --git a/__fixtures__/test-project-rsa/.yarn/releases/yarn-3.6.3.cjs b/__fixtures__/test-project-rsa/.yarn/releases/yarn-3.6.3.cjs new file mode 100755 index 000000000000..9837c3028118 --- /dev/null +++ b/__fixtures__/test-project-rsa/.yarn/releases/yarn-3.6.3.cjs @@ -0,0 +1,874 @@ +#!/usr/bin/env node +/* eslint-disable */ +//prettier-ignore +(()=>{var Dge=Object.create;var lS=Object.defineProperty;var kge=Object.getOwnPropertyDescriptor;var Rge=Object.getOwnPropertyNames;var Fge=Object.getPrototypeOf,Nge=Object.prototype.hasOwnProperty;var J=(r=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(r,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):r)(function(r){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+r+'" is not supported')});var Tge=(r,e)=>()=>(r&&(e=r(r=0)),e);var w=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),ut=(r,e)=>{for(var t in e)lS(r,t,{get:e[t],enumerable:!0})},Lge=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Rge(e))!Nge.call(r,n)&&n!==t&&lS(r,n,{get:()=>e[n],enumerable:!(i=kge(e,n))||i.enumerable});return r};var Pe=(r,e,t)=>(t=r!=null?Dge(Fge(r)):{},Lge(e||!r||!r.__esModule?lS(t,"default",{value:r,enumerable:!0}):t,r));var PK=w((z7e,xK)=>{xK.exports=vK;vK.sync=ife;var QK=J("fs");function rfe(r,e){var t=e.pathExt!==void 0?e.pathExt:process.env.PATHEXT;if(!t||(t=t.split(";"),t.indexOf("")!==-1))return!0;for(var i=0;i{FK.exports=kK;kK.sync=nfe;var DK=J("fs");function kK(r,e,t){DK.stat(r,function(i,n){t(i,i?!1:RK(n,e))})}function nfe(r,e){return RK(DK.statSync(r),e)}function RK(r,e){return r.isFile()&&sfe(r,e)}function sfe(r,e){var t=r.mode,i=r.uid,n=r.gid,s=e.uid!==void 0?e.uid:process.getuid&&process.getuid(),o=e.gid!==void 0?e.gid:process.getgid&&process.getgid(),a=parseInt("100",8),l=parseInt("010",8),c=parseInt("001",8),u=a|l,g=t&c||t&l&&n===o||t&a&&i===s||t&u&&s===0;return g}});var LK=w((Z7e,TK)=>{var X7e=J("fs"),lI;process.platform==="win32"||global.TESTING_WINDOWS?lI=PK():lI=NK();TK.exports=SS;SS.sync=ofe;function SS(r,e,t){if(typeof e=="function"&&(t=e,e={}),!t){if(typeof Promise!="function")throw new TypeError("callback not provided");return new Promise(function(i,n){SS(r,e||{},function(s,o){s?n(s):i(o)})})}lI(r,e||{},function(i,n){i&&(i.code==="EACCES"||e&&e.ignoreErrors)&&(i=null,n=!1),t(i,n)})}function ofe(r,e){try{return lI.sync(r,e||{})}catch(t){if(e&&e.ignoreErrors||t.code==="EACCES")return!1;throw t}}});var YK=w((_7e,GK)=>{var Dg=process.platform==="win32"||process.env.OSTYPE==="cygwin"||process.env.OSTYPE==="msys",MK=J("path"),afe=Dg?";":":",OK=LK(),KK=r=>Object.assign(new Error(`not found: ${r}`),{code:"ENOENT"}),UK=(r,e)=>{let t=e.colon||afe,i=r.match(/\//)||Dg&&r.match(/\\/)?[""]:[...Dg?[process.cwd()]:[],...(e.path||process.env.PATH||"").split(t)],n=Dg?e.pathExt||process.env.PATHEXT||".EXE;.CMD;.BAT;.COM":"",s=Dg?n.split(t):[""];return Dg&&r.indexOf(".")!==-1&&s[0]!==""&&s.unshift(""),{pathEnv:i,pathExt:s,pathExtExe:n}},HK=(r,e,t)=>{typeof e=="function"&&(t=e,e={}),e||(e={});let{pathEnv:i,pathExt:n,pathExtExe:s}=UK(r,e),o=[],a=c=>new Promise((u,g)=>{if(c===i.length)return e.all&&o.length?u(o):g(KK(r));let f=i[c],h=/^".*"$/.test(f)?f.slice(1,-1):f,p=MK.join(h,r),C=!h&&/^\.[\\\/]/.test(r)?r.slice(0,2)+p:p;u(l(C,c,0))}),l=(c,u,g)=>new Promise((f,h)=>{if(g===n.length)return f(a(u+1));let p=n[g];OK(c+p,{pathExt:s},(C,y)=>{if(!C&&y)if(e.all)o.push(c+p);else return f(c+p);return f(l(c,u,g+1))})});return t?a(0).then(c=>t(null,c),t):a(0)},Afe=(r,e)=>{e=e||{};let{pathEnv:t,pathExt:i,pathExtExe:n}=UK(r,e),s=[];for(let o=0;o{"use strict";var jK=(r={})=>{let e=r.env||process.env;return(r.platform||process.platform)!=="win32"?"PATH":Object.keys(e).reverse().find(i=>i.toUpperCase()==="PATH")||"Path"};vS.exports=jK;vS.exports.default=jK});var VK=w((eZe,zK)=>{"use strict";var JK=J("path"),lfe=YK(),cfe=qK();function WK(r,e){let t=r.options.env||process.env,i=process.cwd(),n=r.options.cwd!=null,s=n&&process.chdir!==void 0&&!process.chdir.disabled;if(s)try{process.chdir(r.options.cwd)}catch{}let o;try{o=lfe.sync(r.command,{path:t[cfe({env:t})],pathExt:e?JK.delimiter:void 0})}catch{}finally{s&&process.chdir(i)}return o&&(o=JK.resolve(n?r.options.cwd:"",o)),o}function ufe(r){return WK(r)||WK(r,!0)}zK.exports=ufe});var XK=w((tZe,PS)=>{"use strict";var xS=/([()\][%!^"`<>&|;, *?])/g;function gfe(r){return r=r.replace(xS,"^$1"),r}function ffe(r,e){return r=`${r}`,r=r.replace(/(\\*)"/g,'$1$1\\"'),r=r.replace(/(\\*)$/,"$1$1"),r=`"${r}"`,r=r.replace(xS,"^$1"),e&&(r=r.replace(xS,"^$1")),r}PS.exports.command=gfe;PS.exports.argument=ffe});var _K=w((rZe,ZK)=>{"use strict";ZK.exports=/^#!(.*)/});var eU=w((iZe,$K)=>{"use strict";var hfe=_K();$K.exports=(r="")=>{let e=r.match(hfe);if(!e)return null;let[t,i]=e[0].replace(/#! ?/,"").split(" "),n=t.split("/").pop();return n==="env"?i:i?`${n} ${i}`:n}});var rU=w((nZe,tU)=>{"use strict";var DS=J("fs"),pfe=eU();function dfe(r){let t=Buffer.alloc(150),i;try{i=DS.openSync(r,"r"),DS.readSync(i,t,0,150,0),DS.closeSync(i)}catch{}return pfe(t.toString())}tU.exports=dfe});var oU=w((sZe,sU)=>{"use strict";var Cfe=J("path"),iU=VK(),nU=XK(),mfe=rU(),Efe=process.platform==="win32",Ife=/\.(?:com|exe)$/i,yfe=/node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;function wfe(r){r.file=iU(r);let e=r.file&&mfe(r.file);return e?(r.args.unshift(r.file),r.command=e,iU(r)):r.file}function Bfe(r){if(!Efe)return r;let e=wfe(r),t=!Ife.test(e);if(r.options.forceShell||t){let i=yfe.test(e);r.command=Cfe.normalize(r.command),r.command=nU.command(r.command),r.args=r.args.map(s=>nU.argument(s,i));let n=[r.command].concat(r.args).join(" ");r.args=["/d","/s","/c",`"${n}"`],r.command=process.env.comspec||"cmd.exe",r.options.windowsVerbatimArguments=!0}return r}function bfe(r,e,t){e&&!Array.isArray(e)&&(t=e,e=null),e=e?e.slice(0):[],t=Object.assign({},t);let i={command:r,args:e,options:t,file:void 0,original:{command:r,args:e}};return t.shell?i:Bfe(i)}sU.exports=bfe});var lU=w((oZe,AU)=>{"use strict";var kS=process.platform==="win32";function RS(r,e){return Object.assign(new Error(`${e} ${r.command} ENOENT`),{code:"ENOENT",errno:"ENOENT",syscall:`${e} ${r.command}`,path:r.command,spawnargs:r.args})}function Qfe(r,e){if(!kS)return;let t=r.emit;r.emit=function(i,n){if(i==="exit"){let s=aU(n,e,"spawn");if(s)return t.call(r,"error",s)}return t.apply(r,arguments)}}function aU(r,e){return kS&&r===1&&!e.file?RS(e.original,"spawn"):null}function Sfe(r,e){return kS&&r===1&&!e.file?RS(e.original,"spawnSync"):null}AU.exports={hookChildProcess:Qfe,verifyENOENT:aU,verifyENOENTSync:Sfe,notFoundError:RS}});var TS=w((aZe,kg)=>{"use strict";var cU=J("child_process"),FS=oU(),NS=lU();function uU(r,e,t){let i=FS(r,e,t),n=cU.spawn(i.command,i.args,i.options);return NS.hookChildProcess(n,i),n}function vfe(r,e,t){let i=FS(r,e,t),n=cU.spawnSync(i.command,i.args,i.options);return n.error=n.error||NS.verifyENOENTSync(n.status,i),n}kg.exports=uU;kg.exports.spawn=uU;kg.exports.sync=vfe;kg.exports._parse=FS;kg.exports._enoent=NS});var fU=w((AZe,gU)=>{"use strict";function xfe(r,e){function t(){this.constructor=r}t.prototype=e.prototype,r.prototype=new t}function Zl(r,e,t,i){this.message=r,this.expected=e,this.found=t,this.location=i,this.name="SyntaxError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,Zl)}xfe(Zl,Error);Zl.buildMessage=function(r,e){var t={literal:function(c){return'"'+n(c.text)+'"'},class:function(c){var u="",g;for(g=0;g0){for(g=1,f=1;g>",ie=me(">>",!1),de=">&",_e=me(">&",!1),Pt=">",It=me(">",!1),Mr="<<<",ii=me("<<<",!1),gi="<&",hr=me("<&",!1),fi="<",ni=me("<",!1),Ks=function(m){return{type:"argument",segments:[].concat(...m)}},pr=function(m){return m},Ii="$'",rs=me("$'",!1),fa="'",dA=me("'",!1),cg=function(m){return[{type:"text",text:m}]},is='""',CA=me('""',!1),ha=function(){return{type:"text",text:""}},wp='"',mA=me('"',!1),EA=function(m){return m},wr=function(m){return{type:"arithmetic",arithmetic:m,quoted:!0}},Tl=function(m){return{type:"shell",shell:m,quoted:!0}},ug=function(m){return{type:"variable",...m,quoted:!0}},yo=function(m){return{type:"text",text:m}},gg=function(m){return{type:"arithmetic",arithmetic:m,quoted:!1}},Bp=function(m){return{type:"shell",shell:m,quoted:!1}},bp=function(m){return{type:"variable",...m,quoted:!1}},vr=function(m){return{type:"glob",pattern:m}},se=/^[^']/,wo=Je(["'"],!0,!1),Fn=function(m){return m.join("")},fg=/^[^$"]/,bt=Je(["$",'"'],!0,!1),Ll=`\\ +`,Nn=me(`\\ +`,!1),ns=function(){return""},ss="\\",gt=me("\\",!1),Bo=/^[\\$"`]/,At=Je(["\\","$",'"',"`"],!1,!1),ln=function(m){return m},S="\\a",Lt=me("\\a",!1),hg=function(){return"a"},Ml="\\b",Qp=me("\\b",!1),Sp=function(){return"\b"},vp=/^[Ee]/,xp=Je(["E","e"],!1,!1),Pp=function(){return"\x1B"},G="\\f",yt=me("\\f",!1),IA=function(){return"\f"},zi="\\n",Ol=me("\\n",!1),Xe=function(){return` +`},pa="\\r",pg=me("\\r",!1),ME=function(){return"\r"},Dp="\\t",OE=me("\\t",!1),ar=function(){return" "},Tn="\\v",Kl=me("\\v",!1),kp=function(){return"\v"},Us=/^[\\'"?]/,da=Je(["\\","'",'"',"?"],!1,!1),cn=function(m){return String.fromCharCode(parseInt(m,16))},Le="\\x",dg=me("\\x",!1),Ul="\\u",Hs=me("\\u",!1),Hl="\\U",yA=me("\\U",!1),Cg=function(m){return String.fromCodePoint(parseInt(m,16))},mg=/^[0-7]/,Ca=Je([["0","7"]],!1,!1),ma=/^[0-9a-fA-f]/,rt=Je([["0","9"],["a","f"],["A","f"]],!1,!1),bo=nt(),wA="-",Gl=me("-",!1),Gs="+",Yl=me("+",!1),KE=".",Rp=me(".",!1),Eg=function(m,Q,N){return{type:"number",value:(m==="-"?-1:1)*parseFloat(Q.join("")+"."+N.join(""))}},Fp=function(m,Q){return{type:"number",value:(m==="-"?-1:1)*parseInt(Q.join(""))}},UE=function(m){return{type:"variable",...m}},jl=function(m){return{type:"variable",name:m}},HE=function(m){return m},Ig="*",BA=me("*",!1),Rr="/",GE=me("/",!1),Ys=function(m,Q,N){return{type:Q==="*"?"multiplication":"division",right:N}},js=function(m,Q){return Q.reduce((N,U)=>({left:N,...U}),m)},yg=function(m,Q,N){return{type:Q==="+"?"addition":"subtraction",right:N}},bA="$((",R=me("$((",!1),q="))",Ce=me("))",!1),Ke=function(m){return m},Re="$(",ze=me("$(",!1),dt=function(m){return m},Ft="${",Ln=me("${",!1),JQ=":-",k1=me(":-",!1),R1=function(m,Q){return{name:m,defaultValue:Q}},WQ=":-}",F1=me(":-}",!1),N1=function(m){return{name:m,defaultValue:[]}},zQ=":+",T1=me(":+",!1),L1=function(m,Q){return{name:m,alternativeValue:Q}},VQ=":+}",M1=me(":+}",!1),O1=function(m){return{name:m,alternativeValue:[]}},XQ=function(m){return{name:m}},K1="$",U1=me("$",!1),H1=function(m){return e.isGlobPattern(m)},G1=function(m){return m},ZQ=/^[a-zA-Z0-9_]/,_Q=Je([["a","z"],["A","Z"],["0","9"],"_"],!1,!1),$Q=function(){return L()},eS=/^[$@*?#a-zA-Z0-9_\-]/,tS=Je(["$","@","*","?","#",["a","z"],["A","Z"],["0","9"],"_","-"],!1,!1),Y1=/^[(){}<>$|&; \t"']/,wg=Je(["(",")","{","}","<",">","$","|","&",";"," "," ",'"',"'"],!1,!1),rS=/^[<>&; \t"']/,iS=Je(["<",">","&",";"," "," ",'"',"'"],!1,!1),YE=/^[ \t]/,jE=Je([" "," "],!1,!1),b=0,Oe=0,QA=[{line:1,column:1}],d=0,E=[],I=0,k;if("startRule"in e){if(!(e.startRule in i))throw new Error(`Can't start parsing from rule "`+e.startRule+'".');n=i[e.startRule]}function L(){return r.substring(Oe,b)}function Z(){return Et(Oe,b)}function te(m,Q){throw Q=Q!==void 0?Q:Et(Oe,b),Ri([lt(m)],r.substring(Oe,b),Q)}function we(m,Q){throw Q=Q!==void 0?Q:Et(Oe,b),Mn(m,Q)}function me(m,Q){return{type:"literal",text:m,ignoreCase:Q}}function Je(m,Q,N){return{type:"class",parts:m,inverted:Q,ignoreCase:N}}function nt(){return{type:"any"}}function wt(){return{type:"end"}}function lt(m){return{type:"other",description:m}}function it(m){var Q=QA[m],N;if(Q)return Q;for(N=m-1;!QA[N];)N--;for(Q=QA[N],Q={line:Q.line,column:Q.column};Nd&&(d=b,E=[]),E.push(m))}function Mn(m,Q){return new Zl(m,null,null,Q)}function Ri(m,Q,N){return new Zl(Zl.buildMessage(m,Q),m,Q,N)}function SA(){var m,Q;return m=b,Q=Or(),Q===t&&(Q=null),Q!==t&&(Oe=m,Q=s(Q)),m=Q,m}function Or(){var m,Q,N,U,ce;if(m=b,Q=Kr(),Q!==t){for(N=[],U=He();U!==t;)N.push(U),U=He();N!==t?(U=Ea(),U!==t?(ce=os(),ce===t&&(ce=null),ce!==t?(Oe=m,Q=o(Q,U,ce),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t)}else b=m,m=t;if(m===t)if(m=b,Q=Kr(),Q!==t){for(N=[],U=He();U!==t;)N.push(U),U=He();N!==t?(U=Ea(),U===t&&(U=null),U!==t?(Oe=m,Q=a(Q,U),m=Q):(b=m,m=t)):(b=m,m=t)}else b=m,m=t;return m}function os(){var m,Q,N,U,ce;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t)if(N=Or(),N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();U!==t?(Oe=m,Q=l(N),m=Q):(b=m,m=t)}else b=m,m=t;else b=m,m=t;return m}function Ea(){var m;return r.charCodeAt(b)===59?(m=c,b++):(m=t,I===0&&be(u)),m===t&&(r.charCodeAt(b)===38?(m=g,b++):(m=t,I===0&&be(f))),m}function Kr(){var m,Q,N;return m=b,Q=j1(),Q!==t?(N=fge(),N===t&&(N=null),N!==t?(Oe=m,Q=h(Q,N),m=Q):(b=m,m=t)):(b=m,m=t),m}function fge(){var m,Q,N,U,ce,Se,ht;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t)if(N=hge(),N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();if(U!==t)if(ce=Kr(),ce!==t){for(Se=[],ht=He();ht!==t;)Se.push(ht),ht=He();Se!==t?(Oe=m,Q=p(N,ce),m=Q):(b=m,m=t)}else b=m,m=t;else b=m,m=t}else b=m,m=t;else b=m,m=t;return m}function hge(){var m;return r.substr(b,2)===C?(m=C,b+=2):(m=t,I===0&&be(y)),m===t&&(r.substr(b,2)===B?(m=B,b+=2):(m=t,I===0&&be(v))),m}function j1(){var m,Q,N;return m=b,Q=Cge(),Q!==t?(N=pge(),N===t&&(N=null),N!==t?(Oe=m,Q=D(Q,N),m=Q):(b=m,m=t)):(b=m,m=t),m}function pge(){var m,Q,N,U,ce,Se,ht;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t)if(N=dge(),N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();if(U!==t)if(ce=j1(),ce!==t){for(Se=[],ht=He();ht!==t;)Se.push(ht),ht=He();Se!==t?(Oe=m,Q=T(N,ce),m=Q):(b=m,m=t)}else b=m,m=t;else b=m,m=t}else b=m,m=t;else b=m,m=t;return m}function dge(){var m;return r.substr(b,2)===H?(m=H,b+=2):(m=t,I===0&&be(j)),m===t&&(r.charCodeAt(b)===124?(m=$,b++):(m=t,I===0&&be(V))),m}function qE(){var m,Q,N,U,ce,Se;if(m=b,Q=rK(),Q!==t)if(r.charCodeAt(b)===61?(N=W,b++):(N=t,I===0&&be(_)),N!==t)if(U=W1(),U!==t){for(ce=[],Se=He();Se!==t;)ce.push(Se),Se=He();ce!==t?(Oe=m,Q=A(Q,U),m=Q):(b=m,m=t)}else b=m,m=t;else b=m,m=t;else b=m,m=t;if(m===t)if(m=b,Q=rK(),Q!==t)if(r.charCodeAt(b)===61?(N=W,b++):(N=t,I===0&&be(_)),N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();U!==t?(Oe=m,Q=Ae(Q),m=Q):(b=m,m=t)}else b=m,m=t;else b=m,m=t;return m}function Cge(){var m,Q,N,U,ce,Se,ht,Bt,qr,hi,as;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t)if(r.charCodeAt(b)===40?(N=ge,b++):(N=t,I===0&&be(re)),N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();if(U!==t)if(ce=Or(),ce!==t){for(Se=[],ht=He();ht!==t;)Se.push(ht),ht=He();if(Se!==t)if(r.charCodeAt(b)===41?(ht=M,b++):(ht=t,I===0&&be(F)),ht!==t){for(Bt=[],qr=He();qr!==t;)Bt.push(qr),qr=He();if(Bt!==t){for(qr=[],hi=Np();hi!==t;)qr.push(hi),hi=Np();if(qr!==t){for(hi=[],as=He();as!==t;)hi.push(as),as=He();hi!==t?(Oe=m,Q=ue(ce,qr),m=Q):(b=m,m=t)}else b=m,m=t}else b=m,m=t}else b=m,m=t;else b=m,m=t}else b=m,m=t;else b=m,m=t}else b=m,m=t;else b=m,m=t;if(m===t){for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t)if(r.charCodeAt(b)===123?(N=pe,b++):(N=t,I===0&&be(ke)),N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();if(U!==t)if(ce=Or(),ce!==t){for(Se=[],ht=He();ht!==t;)Se.push(ht),ht=He();if(Se!==t)if(r.charCodeAt(b)===125?(ht=Fe,b++):(ht=t,I===0&&be(Ne)),ht!==t){for(Bt=[],qr=He();qr!==t;)Bt.push(qr),qr=He();if(Bt!==t){for(qr=[],hi=Np();hi!==t;)qr.push(hi),hi=Np();if(qr!==t){for(hi=[],as=He();as!==t;)hi.push(as),as=He();hi!==t?(Oe=m,Q=oe(ce,qr),m=Q):(b=m,m=t)}else b=m,m=t}else b=m,m=t}else b=m,m=t;else b=m,m=t}else b=m,m=t;else b=m,m=t}else b=m,m=t;else b=m,m=t;if(m===t){for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t){for(N=[],U=qE();U!==t;)N.push(U),U=qE();if(N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();if(U!==t){if(ce=[],Se=J1(),Se!==t)for(;Se!==t;)ce.push(Se),Se=J1();else ce=t;if(ce!==t){for(Se=[],ht=He();ht!==t;)Se.push(ht),ht=He();Se!==t?(Oe=m,Q=le(N,ce),m=Q):(b=m,m=t)}else b=m,m=t}else b=m,m=t}else b=m,m=t}else b=m,m=t;if(m===t){for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t){if(N=[],U=qE(),U!==t)for(;U!==t;)N.push(U),U=qE();else N=t;if(N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();U!==t?(Oe=m,Q=Be(N),m=Q):(b=m,m=t)}else b=m,m=t}else b=m,m=t}}}return m}function q1(){var m,Q,N,U,ce;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t){if(N=[],U=JE(),U!==t)for(;U!==t;)N.push(U),U=JE();else N=t;if(N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();U!==t?(Oe=m,Q=fe(N),m=Q):(b=m,m=t)}else b=m,m=t}else b=m,m=t;return m}function J1(){var m,Q,N;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t?(N=Np(),N!==t?(Oe=m,Q=ae(N),m=Q):(b=m,m=t)):(b=m,m=t),m===t){for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();Q!==t?(N=JE(),N!==t?(Oe=m,Q=ae(N),m=Q):(b=m,m=t)):(b=m,m=t)}return m}function Np(){var m,Q,N,U,ce;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();return Q!==t?(qe.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(ne)),N===t&&(N=null),N!==t?(U=mge(),U!==t?(ce=JE(),ce!==t?(Oe=m,Q=Y(N,U,ce),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m}function mge(){var m;return r.substr(b,2)===he?(m=he,b+=2):(m=t,I===0&&be(ie)),m===t&&(r.substr(b,2)===de?(m=de,b+=2):(m=t,I===0&&be(_e)),m===t&&(r.charCodeAt(b)===62?(m=Pt,b++):(m=t,I===0&&be(It)),m===t&&(r.substr(b,3)===Mr?(m=Mr,b+=3):(m=t,I===0&&be(ii)),m===t&&(r.substr(b,2)===gi?(m=gi,b+=2):(m=t,I===0&&be(hr)),m===t&&(r.charCodeAt(b)===60?(m=fi,b++):(m=t,I===0&&be(ni))))))),m}function JE(){var m,Q,N;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();return Q!==t?(N=W1(),N!==t?(Oe=m,Q=ae(N),m=Q):(b=m,m=t)):(b=m,m=t),m}function W1(){var m,Q,N;if(m=b,Q=[],N=z1(),N!==t)for(;N!==t;)Q.push(N),N=z1();else Q=t;return Q!==t&&(Oe=m,Q=Ks(Q)),m=Q,m}function z1(){var m,Q;return m=b,Q=Ege(),Q!==t&&(Oe=m,Q=pr(Q)),m=Q,m===t&&(m=b,Q=Ige(),Q!==t&&(Oe=m,Q=pr(Q)),m=Q,m===t&&(m=b,Q=yge(),Q!==t&&(Oe=m,Q=pr(Q)),m=Q,m===t&&(m=b,Q=wge(),Q!==t&&(Oe=m,Q=pr(Q)),m=Q))),m}function Ege(){var m,Q,N,U;return m=b,r.substr(b,2)===Ii?(Q=Ii,b+=2):(Q=t,I===0&&be(rs)),Q!==t?(N=Qge(),N!==t?(r.charCodeAt(b)===39?(U=fa,b++):(U=t,I===0&&be(dA)),U!==t?(Oe=m,Q=cg(N),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m}function Ige(){var m,Q,N,U;return m=b,r.charCodeAt(b)===39?(Q=fa,b++):(Q=t,I===0&&be(dA)),Q!==t?(N=Bge(),N!==t?(r.charCodeAt(b)===39?(U=fa,b++):(U=t,I===0&&be(dA)),U!==t?(Oe=m,Q=cg(N),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m}function yge(){var m,Q,N,U;if(m=b,r.substr(b,2)===is?(Q=is,b+=2):(Q=t,I===0&&be(CA)),Q!==t&&(Oe=m,Q=ha()),m=Q,m===t)if(m=b,r.charCodeAt(b)===34?(Q=wp,b++):(Q=t,I===0&&be(mA)),Q!==t){for(N=[],U=V1();U!==t;)N.push(U),U=V1();N!==t?(r.charCodeAt(b)===34?(U=wp,b++):(U=t,I===0&&be(mA)),U!==t?(Oe=m,Q=EA(N),m=Q):(b=m,m=t)):(b=m,m=t)}else b=m,m=t;return m}function wge(){var m,Q,N;if(m=b,Q=[],N=X1(),N!==t)for(;N!==t;)Q.push(N),N=X1();else Q=t;return Q!==t&&(Oe=m,Q=EA(Q)),m=Q,m}function V1(){var m,Q;return m=b,Q=eK(),Q!==t&&(Oe=m,Q=wr(Q)),m=Q,m===t&&(m=b,Q=tK(),Q!==t&&(Oe=m,Q=Tl(Q)),m=Q,m===t&&(m=b,Q=aS(),Q!==t&&(Oe=m,Q=ug(Q)),m=Q,m===t&&(m=b,Q=bge(),Q!==t&&(Oe=m,Q=yo(Q)),m=Q))),m}function X1(){var m,Q;return m=b,Q=eK(),Q!==t&&(Oe=m,Q=gg(Q)),m=Q,m===t&&(m=b,Q=tK(),Q!==t&&(Oe=m,Q=Bp(Q)),m=Q,m===t&&(m=b,Q=aS(),Q!==t&&(Oe=m,Q=bp(Q)),m=Q,m===t&&(m=b,Q=xge(),Q!==t&&(Oe=m,Q=vr(Q)),m=Q,m===t&&(m=b,Q=vge(),Q!==t&&(Oe=m,Q=yo(Q)),m=Q)))),m}function Bge(){var m,Q,N;for(m=b,Q=[],se.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(wo));N!==t;)Q.push(N),se.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(wo));return Q!==t&&(Oe=m,Q=Fn(Q)),m=Q,m}function bge(){var m,Q,N;if(m=b,Q=[],N=Z1(),N===t&&(fg.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(bt))),N!==t)for(;N!==t;)Q.push(N),N=Z1(),N===t&&(fg.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(bt)));else Q=t;return Q!==t&&(Oe=m,Q=Fn(Q)),m=Q,m}function Z1(){var m,Q,N;return m=b,r.substr(b,2)===Ll?(Q=Ll,b+=2):(Q=t,I===0&&be(Nn)),Q!==t&&(Oe=m,Q=ns()),m=Q,m===t&&(m=b,r.charCodeAt(b)===92?(Q=ss,b++):(Q=t,I===0&&be(gt)),Q!==t?(Bo.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(At)),N!==t?(Oe=m,Q=ln(N),m=Q):(b=m,m=t)):(b=m,m=t)),m}function Qge(){var m,Q,N;for(m=b,Q=[],N=_1(),N===t&&(se.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(wo)));N!==t;)Q.push(N),N=_1(),N===t&&(se.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(wo)));return Q!==t&&(Oe=m,Q=Fn(Q)),m=Q,m}function _1(){var m,Q,N;return m=b,r.substr(b,2)===S?(Q=S,b+=2):(Q=t,I===0&&be(Lt)),Q!==t&&(Oe=m,Q=hg()),m=Q,m===t&&(m=b,r.substr(b,2)===Ml?(Q=Ml,b+=2):(Q=t,I===0&&be(Qp)),Q!==t&&(Oe=m,Q=Sp()),m=Q,m===t&&(m=b,r.charCodeAt(b)===92?(Q=ss,b++):(Q=t,I===0&&be(gt)),Q!==t?(vp.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(xp)),N!==t?(Oe=m,Q=Pp(),m=Q):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===G?(Q=G,b+=2):(Q=t,I===0&&be(yt)),Q!==t&&(Oe=m,Q=IA()),m=Q,m===t&&(m=b,r.substr(b,2)===zi?(Q=zi,b+=2):(Q=t,I===0&&be(Ol)),Q!==t&&(Oe=m,Q=Xe()),m=Q,m===t&&(m=b,r.substr(b,2)===pa?(Q=pa,b+=2):(Q=t,I===0&&be(pg)),Q!==t&&(Oe=m,Q=ME()),m=Q,m===t&&(m=b,r.substr(b,2)===Dp?(Q=Dp,b+=2):(Q=t,I===0&&be(OE)),Q!==t&&(Oe=m,Q=ar()),m=Q,m===t&&(m=b,r.substr(b,2)===Tn?(Q=Tn,b+=2):(Q=t,I===0&&be(Kl)),Q!==t&&(Oe=m,Q=kp()),m=Q,m===t&&(m=b,r.charCodeAt(b)===92?(Q=ss,b++):(Q=t,I===0&&be(gt)),Q!==t?(Us.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(da)),N!==t?(Oe=m,Q=ln(N),m=Q):(b=m,m=t)):(b=m,m=t),m===t&&(m=Sge()))))))))),m}function Sge(){var m,Q,N,U,ce,Se,ht,Bt,qr,hi,as,AS;return m=b,r.charCodeAt(b)===92?(Q=ss,b++):(Q=t,I===0&&be(gt)),Q!==t?(N=nS(),N!==t?(Oe=m,Q=cn(N),m=Q):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===Le?(Q=Le,b+=2):(Q=t,I===0&&be(dg)),Q!==t?(N=b,U=b,ce=nS(),ce!==t?(Se=On(),Se!==t?(ce=[ce,Se],U=ce):(b=U,U=t)):(b=U,U=t),U===t&&(U=nS()),U!==t?N=r.substring(N,b):N=U,N!==t?(Oe=m,Q=cn(N),m=Q):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===Ul?(Q=Ul,b+=2):(Q=t,I===0&&be(Hs)),Q!==t?(N=b,U=b,ce=On(),ce!==t?(Se=On(),Se!==t?(ht=On(),ht!==t?(Bt=On(),Bt!==t?(ce=[ce,Se,ht,Bt],U=ce):(b=U,U=t)):(b=U,U=t)):(b=U,U=t)):(b=U,U=t),U!==t?N=r.substring(N,b):N=U,N!==t?(Oe=m,Q=cn(N),m=Q):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===Hl?(Q=Hl,b+=2):(Q=t,I===0&&be(yA)),Q!==t?(N=b,U=b,ce=On(),ce!==t?(Se=On(),Se!==t?(ht=On(),ht!==t?(Bt=On(),Bt!==t?(qr=On(),qr!==t?(hi=On(),hi!==t?(as=On(),as!==t?(AS=On(),AS!==t?(ce=[ce,Se,ht,Bt,qr,hi,as,AS],U=ce):(b=U,U=t)):(b=U,U=t)):(b=U,U=t)):(b=U,U=t)):(b=U,U=t)):(b=U,U=t)):(b=U,U=t)):(b=U,U=t),U!==t?N=r.substring(N,b):N=U,N!==t?(Oe=m,Q=Cg(N),m=Q):(b=m,m=t)):(b=m,m=t)))),m}function nS(){var m;return mg.test(r.charAt(b))?(m=r.charAt(b),b++):(m=t,I===0&&be(Ca)),m}function On(){var m;return ma.test(r.charAt(b))?(m=r.charAt(b),b++):(m=t,I===0&&be(rt)),m}function vge(){var m,Q,N,U,ce;if(m=b,Q=[],N=b,r.charCodeAt(b)===92?(U=ss,b++):(U=t,I===0&&be(gt)),U!==t?(r.length>b?(ce=r.charAt(b),b++):(ce=t,I===0&&be(bo)),ce!==t?(Oe=N,U=ln(ce),N=U):(b=N,N=t)):(b=N,N=t),N===t&&(N=b,U=b,I++,ce=iK(),I--,ce===t?U=void 0:(b=U,U=t),U!==t?(r.length>b?(ce=r.charAt(b),b++):(ce=t,I===0&&be(bo)),ce!==t?(Oe=N,U=ln(ce),N=U):(b=N,N=t)):(b=N,N=t)),N!==t)for(;N!==t;)Q.push(N),N=b,r.charCodeAt(b)===92?(U=ss,b++):(U=t,I===0&&be(gt)),U!==t?(r.length>b?(ce=r.charAt(b),b++):(ce=t,I===0&&be(bo)),ce!==t?(Oe=N,U=ln(ce),N=U):(b=N,N=t)):(b=N,N=t),N===t&&(N=b,U=b,I++,ce=iK(),I--,ce===t?U=void 0:(b=U,U=t),U!==t?(r.length>b?(ce=r.charAt(b),b++):(ce=t,I===0&&be(bo)),ce!==t?(Oe=N,U=ln(ce),N=U):(b=N,N=t)):(b=N,N=t));else Q=t;return Q!==t&&(Oe=m,Q=Fn(Q)),m=Q,m}function sS(){var m,Q,N,U,ce,Se;if(m=b,r.charCodeAt(b)===45?(Q=wA,b++):(Q=t,I===0&&be(Gl)),Q===t&&(r.charCodeAt(b)===43?(Q=Gs,b++):(Q=t,I===0&&be(Yl))),Q===t&&(Q=null),Q!==t){if(N=[],qe.test(r.charAt(b))?(U=r.charAt(b),b++):(U=t,I===0&&be(ne)),U!==t)for(;U!==t;)N.push(U),qe.test(r.charAt(b))?(U=r.charAt(b),b++):(U=t,I===0&&be(ne));else N=t;if(N!==t)if(r.charCodeAt(b)===46?(U=KE,b++):(U=t,I===0&&be(Rp)),U!==t){if(ce=[],qe.test(r.charAt(b))?(Se=r.charAt(b),b++):(Se=t,I===0&&be(ne)),Se!==t)for(;Se!==t;)ce.push(Se),qe.test(r.charAt(b))?(Se=r.charAt(b),b++):(Se=t,I===0&&be(ne));else ce=t;ce!==t?(Oe=m,Q=Eg(Q,N,ce),m=Q):(b=m,m=t)}else b=m,m=t;else b=m,m=t}else b=m,m=t;if(m===t){if(m=b,r.charCodeAt(b)===45?(Q=wA,b++):(Q=t,I===0&&be(Gl)),Q===t&&(r.charCodeAt(b)===43?(Q=Gs,b++):(Q=t,I===0&&be(Yl))),Q===t&&(Q=null),Q!==t){if(N=[],qe.test(r.charAt(b))?(U=r.charAt(b),b++):(U=t,I===0&&be(ne)),U!==t)for(;U!==t;)N.push(U),qe.test(r.charAt(b))?(U=r.charAt(b),b++):(U=t,I===0&&be(ne));else N=t;N!==t?(Oe=m,Q=Fp(Q,N),m=Q):(b=m,m=t)}else b=m,m=t;if(m===t&&(m=b,Q=aS(),Q!==t&&(Oe=m,Q=UE(Q)),m=Q,m===t&&(m=b,Q=ql(),Q!==t&&(Oe=m,Q=jl(Q)),m=Q,m===t)))if(m=b,r.charCodeAt(b)===40?(Q=ge,b++):(Q=t,I===0&&be(re)),Q!==t){for(N=[],U=He();U!==t;)N.push(U),U=He();if(N!==t)if(U=$1(),U!==t){for(ce=[],Se=He();Se!==t;)ce.push(Se),Se=He();ce!==t?(r.charCodeAt(b)===41?(Se=M,b++):(Se=t,I===0&&be(F)),Se!==t?(Oe=m,Q=HE(U),m=Q):(b=m,m=t)):(b=m,m=t)}else b=m,m=t;else b=m,m=t}else b=m,m=t}return m}function oS(){var m,Q,N,U,ce,Se,ht,Bt;if(m=b,Q=sS(),Q!==t){for(N=[],U=b,ce=[],Se=He();Se!==t;)ce.push(Se),Se=He();if(ce!==t)if(r.charCodeAt(b)===42?(Se=Ig,b++):(Se=t,I===0&&be(BA)),Se===t&&(r.charCodeAt(b)===47?(Se=Rr,b++):(Se=t,I===0&&be(GE))),Se!==t){for(ht=[],Bt=He();Bt!==t;)ht.push(Bt),Bt=He();ht!==t?(Bt=sS(),Bt!==t?(Oe=U,ce=Ys(Q,Se,Bt),U=ce):(b=U,U=t)):(b=U,U=t)}else b=U,U=t;else b=U,U=t;for(;U!==t;){for(N.push(U),U=b,ce=[],Se=He();Se!==t;)ce.push(Se),Se=He();if(ce!==t)if(r.charCodeAt(b)===42?(Se=Ig,b++):(Se=t,I===0&&be(BA)),Se===t&&(r.charCodeAt(b)===47?(Se=Rr,b++):(Se=t,I===0&&be(GE))),Se!==t){for(ht=[],Bt=He();Bt!==t;)ht.push(Bt),Bt=He();ht!==t?(Bt=sS(),Bt!==t?(Oe=U,ce=Ys(Q,Se,Bt),U=ce):(b=U,U=t)):(b=U,U=t)}else b=U,U=t;else b=U,U=t}N!==t?(Oe=m,Q=js(Q,N),m=Q):(b=m,m=t)}else b=m,m=t;return m}function $1(){var m,Q,N,U,ce,Se,ht,Bt;if(m=b,Q=oS(),Q!==t){for(N=[],U=b,ce=[],Se=He();Se!==t;)ce.push(Se),Se=He();if(ce!==t)if(r.charCodeAt(b)===43?(Se=Gs,b++):(Se=t,I===0&&be(Yl)),Se===t&&(r.charCodeAt(b)===45?(Se=wA,b++):(Se=t,I===0&&be(Gl))),Se!==t){for(ht=[],Bt=He();Bt!==t;)ht.push(Bt),Bt=He();ht!==t?(Bt=oS(),Bt!==t?(Oe=U,ce=yg(Q,Se,Bt),U=ce):(b=U,U=t)):(b=U,U=t)}else b=U,U=t;else b=U,U=t;for(;U!==t;){for(N.push(U),U=b,ce=[],Se=He();Se!==t;)ce.push(Se),Se=He();if(ce!==t)if(r.charCodeAt(b)===43?(Se=Gs,b++):(Se=t,I===0&&be(Yl)),Se===t&&(r.charCodeAt(b)===45?(Se=wA,b++):(Se=t,I===0&&be(Gl))),Se!==t){for(ht=[],Bt=He();Bt!==t;)ht.push(Bt),Bt=He();ht!==t?(Bt=oS(),Bt!==t?(Oe=U,ce=yg(Q,Se,Bt),U=ce):(b=U,U=t)):(b=U,U=t)}else b=U,U=t;else b=U,U=t}N!==t?(Oe=m,Q=js(Q,N),m=Q):(b=m,m=t)}else b=m,m=t;return m}function eK(){var m,Q,N,U,ce,Se;if(m=b,r.substr(b,3)===bA?(Q=bA,b+=3):(Q=t,I===0&&be(R)),Q!==t){for(N=[],U=He();U!==t;)N.push(U),U=He();if(N!==t)if(U=$1(),U!==t){for(ce=[],Se=He();Se!==t;)ce.push(Se),Se=He();ce!==t?(r.substr(b,2)===q?(Se=q,b+=2):(Se=t,I===0&&be(Ce)),Se!==t?(Oe=m,Q=Ke(U),m=Q):(b=m,m=t)):(b=m,m=t)}else b=m,m=t;else b=m,m=t}else b=m,m=t;return m}function tK(){var m,Q,N,U;return m=b,r.substr(b,2)===Re?(Q=Re,b+=2):(Q=t,I===0&&be(ze)),Q!==t?(N=Or(),N!==t?(r.charCodeAt(b)===41?(U=M,b++):(U=t,I===0&&be(F)),U!==t?(Oe=m,Q=dt(N),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m}function aS(){var m,Q,N,U,ce,Se;return m=b,r.substr(b,2)===Ft?(Q=Ft,b+=2):(Q=t,I===0&&be(Ln)),Q!==t?(N=ql(),N!==t?(r.substr(b,2)===JQ?(U=JQ,b+=2):(U=t,I===0&&be(k1)),U!==t?(ce=q1(),ce!==t?(r.charCodeAt(b)===125?(Se=Fe,b++):(Se=t,I===0&&be(Ne)),Se!==t?(Oe=m,Q=R1(N,ce),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===Ft?(Q=Ft,b+=2):(Q=t,I===0&&be(Ln)),Q!==t?(N=ql(),N!==t?(r.substr(b,3)===WQ?(U=WQ,b+=3):(U=t,I===0&&be(F1)),U!==t?(Oe=m,Q=N1(N),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===Ft?(Q=Ft,b+=2):(Q=t,I===0&&be(Ln)),Q!==t?(N=ql(),N!==t?(r.substr(b,2)===zQ?(U=zQ,b+=2):(U=t,I===0&&be(T1)),U!==t?(ce=q1(),ce!==t?(r.charCodeAt(b)===125?(Se=Fe,b++):(Se=t,I===0&&be(Ne)),Se!==t?(Oe=m,Q=L1(N,ce),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===Ft?(Q=Ft,b+=2):(Q=t,I===0&&be(Ln)),Q!==t?(N=ql(),N!==t?(r.substr(b,3)===VQ?(U=VQ,b+=3):(U=t,I===0&&be(M1)),U!==t?(Oe=m,Q=O1(N),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===Ft?(Q=Ft,b+=2):(Q=t,I===0&&be(Ln)),Q!==t?(N=ql(),N!==t?(r.charCodeAt(b)===125?(U=Fe,b++):(U=t,I===0&&be(Ne)),U!==t?(Oe=m,Q=XQ(N),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.charCodeAt(b)===36?(Q=K1,b++):(Q=t,I===0&&be(U1)),Q!==t?(N=ql(),N!==t?(Oe=m,Q=XQ(N),m=Q):(b=m,m=t)):(b=m,m=t)))))),m}function xge(){var m,Q,N;return m=b,Q=Pge(),Q!==t?(Oe=b,N=H1(Q),N?N=void 0:N=t,N!==t?(Oe=m,Q=G1(Q),m=Q):(b=m,m=t)):(b=m,m=t),m}function Pge(){var m,Q,N,U,ce;if(m=b,Q=[],N=b,U=b,I++,ce=nK(),I--,ce===t?U=void 0:(b=U,U=t),U!==t?(r.length>b?(ce=r.charAt(b),b++):(ce=t,I===0&&be(bo)),ce!==t?(Oe=N,U=ln(ce),N=U):(b=N,N=t)):(b=N,N=t),N!==t)for(;N!==t;)Q.push(N),N=b,U=b,I++,ce=nK(),I--,ce===t?U=void 0:(b=U,U=t),U!==t?(r.length>b?(ce=r.charAt(b),b++):(ce=t,I===0&&be(bo)),ce!==t?(Oe=N,U=ln(ce),N=U):(b=N,N=t)):(b=N,N=t);else Q=t;return Q!==t&&(Oe=m,Q=Fn(Q)),m=Q,m}function rK(){var m,Q,N;if(m=b,Q=[],ZQ.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(_Q)),N!==t)for(;N!==t;)Q.push(N),ZQ.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(_Q));else Q=t;return Q!==t&&(Oe=m,Q=$Q()),m=Q,m}function ql(){var m,Q,N;if(m=b,Q=[],eS.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(tS)),N!==t)for(;N!==t;)Q.push(N),eS.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(tS));else Q=t;return Q!==t&&(Oe=m,Q=$Q()),m=Q,m}function iK(){var m;return Y1.test(r.charAt(b))?(m=r.charAt(b),b++):(m=t,I===0&&be(wg)),m}function nK(){var m;return rS.test(r.charAt(b))?(m=r.charAt(b),b++):(m=t,I===0&&be(iS)),m}function He(){var m,Q;if(m=[],YE.test(r.charAt(b))?(Q=r.charAt(b),b++):(Q=t,I===0&&be(jE)),Q!==t)for(;Q!==t;)m.push(Q),YE.test(r.charAt(b))?(Q=r.charAt(b),b++):(Q=t,I===0&&be(jE));else m=t;return m}if(k=n(),k!==t&&b===r.length)return k;throw k!==t&&b{"use strict";function Dfe(r,e){function t(){this.constructor=r}t.prototype=e.prototype,r.prototype=new t}function $l(r,e,t,i){this.message=r,this.expected=e,this.found=t,this.location=i,this.name="SyntaxError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,$l)}Dfe($l,Error);$l.buildMessage=function(r,e){var t={literal:function(c){return'"'+n(c.text)+'"'},class:function(c){var u="",g;for(g=0;g0){for(g=1,f=1;gH&&(H=v,j=[]),j.push(ne))}function Ne(ne,Y){return new $l(ne,null,null,Y)}function oe(ne,Y,he){return new $l($l.buildMessage(ne,Y),ne,Y,he)}function le(){var ne,Y,he,ie;return ne=v,Y=Be(),Y!==t?(r.charCodeAt(v)===47?(he=s,v++):(he=t,$===0&&Fe(o)),he!==t?(ie=Be(),ie!==t?(D=ne,Y=a(Y,ie),ne=Y):(v=ne,ne=t)):(v=ne,ne=t)):(v=ne,ne=t),ne===t&&(ne=v,Y=Be(),Y!==t&&(D=ne,Y=l(Y)),ne=Y),ne}function Be(){var ne,Y,he,ie;return ne=v,Y=fe(),Y!==t?(r.charCodeAt(v)===64?(he=c,v++):(he=t,$===0&&Fe(u)),he!==t?(ie=qe(),ie!==t?(D=ne,Y=g(Y,ie),ne=Y):(v=ne,ne=t)):(v=ne,ne=t)):(v=ne,ne=t),ne===t&&(ne=v,Y=fe(),Y!==t&&(D=ne,Y=f(Y)),ne=Y),ne}function fe(){var ne,Y,he,ie,de;return ne=v,r.charCodeAt(v)===64?(Y=c,v++):(Y=t,$===0&&Fe(u)),Y!==t?(he=ae(),he!==t?(r.charCodeAt(v)===47?(ie=s,v++):(ie=t,$===0&&Fe(o)),ie!==t?(de=ae(),de!==t?(D=ne,Y=h(),ne=Y):(v=ne,ne=t)):(v=ne,ne=t)):(v=ne,ne=t)):(v=ne,ne=t),ne===t&&(ne=v,Y=ae(),Y!==t&&(D=ne,Y=h()),ne=Y),ne}function ae(){var ne,Y,he;if(ne=v,Y=[],p.test(r.charAt(v))?(he=r.charAt(v),v++):(he=t,$===0&&Fe(C)),he!==t)for(;he!==t;)Y.push(he),p.test(r.charAt(v))?(he=r.charAt(v),v++):(he=t,$===0&&Fe(C));else Y=t;return Y!==t&&(D=ne,Y=h()),ne=Y,ne}function qe(){var ne,Y,he;if(ne=v,Y=[],y.test(r.charAt(v))?(he=r.charAt(v),v++):(he=t,$===0&&Fe(B)),he!==t)for(;he!==t;)Y.push(he),y.test(r.charAt(v))?(he=r.charAt(v),v++):(he=t,$===0&&Fe(B));else Y=t;return Y!==t&&(D=ne,Y=h()),ne=Y,ne}if(V=n(),V!==t&&v===r.length)return V;throw V!==t&&v{"use strict";function mU(r){return typeof r>"u"||r===null}function Rfe(r){return typeof r=="object"&&r!==null}function Ffe(r){return Array.isArray(r)?r:mU(r)?[]:[r]}function Nfe(r,e){var t,i,n,s;if(e)for(s=Object.keys(e),t=0,i=s.length;t{"use strict";function Vp(r,e){Error.call(this),this.name="YAMLException",this.reason=r,this.mark=e,this.message=(this.reason||"(unknown reason)")+(this.mark?" "+this.mark.toString():""),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=new Error().stack||""}Vp.prototype=Object.create(Error.prototype);Vp.prototype.constructor=Vp;Vp.prototype.toString=function(e){var t=this.name+": ";return t+=this.reason||"(unknown reason)",!e&&this.mark&&(t+=" "+this.mark.toString()),t};EU.exports=Vp});var wU=w((SZe,yU)=>{"use strict";var IU=tc();function HS(r,e,t,i,n){this.name=r,this.buffer=e,this.position=t,this.line=i,this.column=n}HS.prototype.getSnippet=function(e,t){var i,n,s,o,a;if(!this.buffer)return null;for(e=e||4,t=t||75,i="",n=this.position;n>0&&`\0\r +\x85\u2028\u2029`.indexOf(this.buffer.charAt(n-1))===-1;)if(n-=1,this.position-n>t/2-1){i=" ... ",n+=5;break}for(s="",o=this.position;ot/2-1){s=" ... ",o-=5;break}return a=this.buffer.slice(n,o),IU.repeat(" ",e)+i+a+s+` +`+IU.repeat(" ",e+this.position-n+i.length)+"^"};HS.prototype.toString=function(e){var t,i="";return this.name&&(i+='in "'+this.name+'" '),i+="at line "+(this.line+1)+", column "+(this.column+1),e||(t=this.getSnippet(),t&&(i+=`: +`+t)),i};yU.exports=HS});var si=w((vZe,bU)=>{"use strict";var BU=Ng(),Mfe=["kind","resolve","construct","instanceOf","predicate","represent","defaultStyle","styleAliases"],Ofe=["scalar","sequence","mapping"];function Kfe(r){var e={};return r!==null&&Object.keys(r).forEach(function(t){r[t].forEach(function(i){e[String(i)]=t})}),e}function Ufe(r,e){if(e=e||{},Object.keys(e).forEach(function(t){if(Mfe.indexOf(t)===-1)throw new BU('Unknown option "'+t+'" is met in definition of "'+r+'" YAML type.')}),this.tag=r,this.kind=e.kind||null,this.resolve=e.resolve||function(){return!0},this.construct=e.construct||function(t){return t},this.instanceOf=e.instanceOf||null,this.predicate=e.predicate||null,this.represent=e.represent||null,this.defaultStyle=e.defaultStyle||null,this.styleAliases=Kfe(e.styleAliases||null),Ofe.indexOf(this.kind)===-1)throw new BU('Unknown kind "'+this.kind+'" is specified for "'+r+'" YAML type.')}bU.exports=Ufe});var rc=w((xZe,SU)=>{"use strict";var QU=tc(),dI=Ng(),Hfe=si();function GS(r,e,t){var i=[];return r.include.forEach(function(n){t=GS(n,e,t)}),r[e].forEach(function(n){t.forEach(function(s,o){s.tag===n.tag&&s.kind===n.kind&&i.push(o)}),t.push(n)}),t.filter(function(n,s){return i.indexOf(s)===-1})}function Gfe(){var r={scalar:{},sequence:{},mapping:{},fallback:{}},e,t;function i(n){r[n.kind][n.tag]=r.fallback[n.tag]=n}for(e=0,t=arguments.length;e{"use strict";var Yfe=si();vU.exports=new Yfe("tag:yaml.org,2002:str",{kind:"scalar",construct:function(r){return r!==null?r:""}})});var DU=w((DZe,PU)=>{"use strict";var jfe=si();PU.exports=new jfe("tag:yaml.org,2002:seq",{kind:"sequence",construct:function(r){return r!==null?r:[]}})});var RU=w((kZe,kU)=>{"use strict";var qfe=si();kU.exports=new qfe("tag:yaml.org,2002:map",{kind:"mapping",construct:function(r){return r!==null?r:{}}})});var CI=w((RZe,FU)=>{"use strict";var Jfe=rc();FU.exports=new Jfe({explicit:[xU(),DU(),RU()]})});var TU=w((FZe,NU)=>{"use strict";var Wfe=si();function zfe(r){if(r===null)return!0;var e=r.length;return e===1&&r==="~"||e===4&&(r==="null"||r==="Null"||r==="NULL")}function Vfe(){return null}function Xfe(r){return r===null}NU.exports=new Wfe("tag:yaml.org,2002:null",{kind:"scalar",resolve:zfe,construct:Vfe,predicate:Xfe,represent:{canonical:function(){return"~"},lowercase:function(){return"null"},uppercase:function(){return"NULL"},camelcase:function(){return"Null"}},defaultStyle:"lowercase"})});var MU=w((NZe,LU)=>{"use strict";var Zfe=si();function _fe(r){if(r===null)return!1;var e=r.length;return e===4&&(r==="true"||r==="True"||r==="TRUE")||e===5&&(r==="false"||r==="False"||r==="FALSE")}function $fe(r){return r==="true"||r==="True"||r==="TRUE"}function ehe(r){return Object.prototype.toString.call(r)==="[object Boolean]"}LU.exports=new Zfe("tag:yaml.org,2002:bool",{kind:"scalar",resolve:_fe,construct:$fe,predicate:ehe,represent:{lowercase:function(r){return r?"true":"false"},uppercase:function(r){return r?"TRUE":"FALSE"},camelcase:function(r){return r?"True":"False"}},defaultStyle:"lowercase"})});var KU=w((TZe,OU)=>{"use strict";var the=tc(),rhe=si();function ihe(r){return 48<=r&&r<=57||65<=r&&r<=70||97<=r&&r<=102}function nhe(r){return 48<=r&&r<=55}function she(r){return 48<=r&&r<=57}function ohe(r){if(r===null)return!1;var e=r.length,t=0,i=!1,n;if(!e)return!1;if(n=r[t],(n==="-"||n==="+")&&(n=r[++t]),n==="0"){if(t+1===e)return!0;if(n=r[++t],n==="b"){for(t++;t=0?"0b"+r.toString(2):"-0b"+r.toString(2).slice(1)},octal:function(r){return r>=0?"0"+r.toString(8):"-0"+r.toString(8).slice(1)},decimal:function(r){return r.toString(10)},hexadecimal:function(r){return r>=0?"0x"+r.toString(16).toUpperCase():"-0x"+r.toString(16).toUpperCase().slice(1)}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}})});var GU=w((LZe,HU)=>{"use strict";var UU=tc(),lhe=si(),che=new RegExp("^(?:[-+]?(?:0|[1-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");function uhe(r){return!(r===null||!che.test(r)||r[r.length-1]==="_")}function ghe(r){var e,t,i,n;return e=r.replace(/_/g,"").toLowerCase(),t=e[0]==="-"?-1:1,n=[],"+-".indexOf(e[0])>=0&&(e=e.slice(1)),e===".inf"?t===1?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:e===".nan"?NaN:e.indexOf(":")>=0?(e.split(":").forEach(function(s){n.unshift(parseFloat(s,10))}),e=0,i=1,n.forEach(function(s){e+=s*i,i*=60}),t*e):t*parseFloat(e,10)}var fhe=/^[-+]?[0-9]+e/;function hhe(r,e){var t;if(isNaN(r))switch(e){case"lowercase":return".nan";case"uppercase":return".NAN";case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===r)switch(e){case"lowercase":return".inf";case"uppercase":return".INF";case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===r)switch(e){case"lowercase":return"-.inf";case"uppercase":return"-.INF";case"camelcase":return"-.Inf"}else if(UU.isNegativeZero(r))return"-0.0";return t=r.toString(10),fhe.test(t)?t.replace("e",".e"):t}function phe(r){return Object.prototype.toString.call(r)==="[object Number]"&&(r%1!==0||UU.isNegativeZero(r))}HU.exports=new lhe("tag:yaml.org,2002:float",{kind:"scalar",resolve:uhe,construct:ghe,predicate:phe,represent:hhe,defaultStyle:"lowercase"})});var YS=w((MZe,YU)=>{"use strict";var dhe=rc();YU.exports=new dhe({include:[CI()],implicit:[TU(),MU(),KU(),GU()]})});var jS=w((OZe,jU)=>{"use strict";var Che=rc();jU.exports=new Che({include:[YS()]})});var zU=w((KZe,WU)=>{"use strict";var mhe=si(),qU=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),JU=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$");function Ehe(r){return r===null?!1:qU.exec(r)!==null||JU.exec(r)!==null}function Ihe(r){var e,t,i,n,s,o,a,l=0,c=null,u,g,f;if(e=qU.exec(r),e===null&&(e=JU.exec(r)),e===null)throw new Error("Date resolve error");if(t=+e[1],i=+e[2]-1,n=+e[3],!e[4])return new Date(Date.UTC(t,i,n));if(s=+e[4],o=+e[5],a=+e[6],e[7]){for(l=e[7].slice(0,3);l.length<3;)l+="0";l=+l}return e[9]&&(u=+e[10],g=+(e[11]||0),c=(u*60+g)*6e4,e[9]==="-"&&(c=-c)),f=new Date(Date.UTC(t,i,n,s,o,a,l)),c&&f.setTime(f.getTime()-c),f}function yhe(r){return r.toISOString()}WU.exports=new mhe("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:Ehe,construct:Ihe,instanceOf:Date,represent:yhe})});var XU=w((UZe,VU)=>{"use strict";var whe=si();function Bhe(r){return r==="<<"||r===null}VU.exports=new whe("tag:yaml.org,2002:merge",{kind:"scalar",resolve:Bhe})});var $U=w((HZe,_U)=>{"use strict";var ic;try{ZU=J,ic=ZU("buffer").Buffer}catch{}var ZU,bhe=si(),qS=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/= +\r`;function Qhe(r){if(r===null)return!1;var e,t,i=0,n=r.length,s=qS;for(t=0;t64)){if(e<0)return!1;i+=6}return i%8===0}function She(r){var e,t,i=r.replace(/[\r\n=]/g,""),n=i.length,s=qS,o=0,a=[];for(e=0;e>16&255),a.push(o>>8&255),a.push(o&255)),o=o<<6|s.indexOf(i.charAt(e));return t=n%4*6,t===0?(a.push(o>>16&255),a.push(o>>8&255),a.push(o&255)):t===18?(a.push(o>>10&255),a.push(o>>2&255)):t===12&&a.push(o>>4&255),ic?ic.from?ic.from(a):new ic(a):a}function vhe(r){var e="",t=0,i,n,s=r.length,o=qS;for(i=0;i>18&63],e+=o[t>>12&63],e+=o[t>>6&63],e+=o[t&63]),t=(t<<8)+r[i];return n=s%3,n===0?(e+=o[t>>18&63],e+=o[t>>12&63],e+=o[t>>6&63],e+=o[t&63]):n===2?(e+=o[t>>10&63],e+=o[t>>4&63],e+=o[t<<2&63],e+=o[64]):n===1&&(e+=o[t>>2&63],e+=o[t<<4&63],e+=o[64],e+=o[64]),e}function xhe(r){return ic&&ic.isBuffer(r)}_U.exports=new bhe("tag:yaml.org,2002:binary",{kind:"scalar",resolve:Qhe,construct:She,predicate:xhe,represent:vhe})});var t2=w((YZe,e2)=>{"use strict";var Phe=si(),Dhe=Object.prototype.hasOwnProperty,khe=Object.prototype.toString;function Rhe(r){if(r===null)return!0;var e=[],t,i,n,s,o,a=r;for(t=0,i=a.length;t{"use strict";var Nhe=si(),The=Object.prototype.toString;function Lhe(r){if(r===null)return!0;var e,t,i,n,s,o=r;for(s=new Array(o.length),e=0,t=o.length;e{"use strict";var Ohe=si(),Khe=Object.prototype.hasOwnProperty;function Uhe(r){if(r===null)return!0;var e,t=r;for(e in t)if(Khe.call(t,e)&&t[e]!==null)return!1;return!0}function Hhe(r){return r!==null?r:{}}n2.exports=new Ohe("tag:yaml.org,2002:set",{kind:"mapping",resolve:Uhe,construct:Hhe})});var Lg=w((JZe,o2)=>{"use strict";var Ghe=rc();o2.exports=new Ghe({include:[jS()],implicit:[zU(),XU()],explicit:[$U(),t2(),i2(),s2()]})});var A2=w((WZe,a2)=>{"use strict";var Yhe=si();function jhe(){return!0}function qhe(){}function Jhe(){return""}function Whe(r){return typeof r>"u"}a2.exports=new Yhe("tag:yaml.org,2002:js/undefined",{kind:"scalar",resolve:jhe,construct:qhe,predicate:Whe,represent:Jhe})});var c2=w((zZe,l2)=>{"use strict";var zhe=si();function Vhe(r){if(r===null||r.length===0)return!1;var e=r,t=/\/([gim]*)$/.exec(r),i="";return!(e[0]==="/"&&(t&&(i=t[1]),i.length>3||e[e.length-i.length-1]!=="/"))}function Xhe(r){var e=r,t=/\/([gim]*)$/.exec(r),i="";return e[0]==="/"&&(t&&(i=t[1]),e=e.slice(1,e.length-i.length-1)),new RegExp(e,i)}function Zhe(r){var e="/"+r.source+"/";return r.global&&(e+="g"),r.multiline&&(e+="m"),r.ignoreCase&&(e+="i"),e}function _he(r){return Object.prototype.toString.call(r)==="[object RegExp]"}l2.exports=new zhe("tag:yaml.org,2002:js/regexp",{kind:"scalar",resolve:Vhe,construct:Xhe,predicate:_he,represent:Zhe})});var f2=w((VZe,g2)=>{"use strict";var mI;try{u2=J,mI=u2("esprima")}catch{typeof window<"u"&&(mI=window.esprima)}var u2,$he=si();function epe(r){if(r===null)return!1;try{var e="("+r+")",t=mI.parse(e,{range:!0});return!(t.type!=="Program"||t.body.length!==1||t.body[0].type!=="ExpressionStatement"||t.body[0].expression.type!=="ArrowFunctionExpression"&&t.body[0].expression.type!=="FunctionExpression")}catch{return!1}}function tpe(r){var e="("+r+")",t=mI.parse(e,{range:!0}),i=[],n;if(t.type!=="Program"||t.body.length!==1||t.body[0].type!=="ExpressionStatement"||t.body[0].expression.type!=="ArrowFunctionExpression"&&t.body[0].expression.type!=="FunctionExpression")throw new Error("Failed to resolve function");return t.body[0].expression.params.forEach(function(s){i.push(s.name)}),n=t.body[0].expression.body.range,t.body[0].expression.body.type==="BlockStatement"?new Function(i,e.slice(n[0]+1,n[1]-1)):new Function(i,"return "+e.slice(n[0],n[1]))}function rpe(r){return r.toString()}function ipe(r){return Object.prototype.toString.call(r)==="[object Function]"}g2.exports=new $he("tag:yaml.org,2002:js/function",{kind:"scalar",resolve:epe,construct:tpe,predicate:ipe,represent:rpe})});var Xp=w((ZZe,p2)=>{"use strict";var h2=rc();p2.exports=h2.DEFAULT=new h2({include:[Lg()],explicit:[A2(),c2(),f2()]})});var N2=w((_Ze,Zp)=>{"use strict";var Ba=tc(),w2=Ng(),npe=wU(),B2=Lg(),spe=Xp(),kA=Object.prototype.hasOwnProperty,EI=1,b2=2,Q2=3,II=4,JS=1,ope=2,d2=3,ape=/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/,Ape=/[\x85\u2028\u2029]/,lpe=/[,\[\]\{\}]/,S2=/^(?:!|!!|![a-z\-]+!)$/i,v2=/^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i;function C2(r){return Object.prototype.toString.call(r)}function xo(r){return r===10||r===13}function sc(r){return r===9||r===32}function fn(r){return r===9||r===32||r===10||r===13}function Mg(r){return r===44||r===91||r===93||r===123||r===125}function cpe(r){var e;return 48<=r&&r<=57?r-48:(e=r|32,97<=e&&e<=102?e-97+10:-1)}function upe(r){return r===120?2:r===117?4:r===85?8:0}function gpe(r){return 48<=r&&r<=57?r-48:-1}function m2(r){return r===48?"\0":r===97?"\x07":r===98?"\b":r===116||r===9?" ":r===110?` +`:r===118?"\v":r===102?"\f":r===114?"\r":r===101?"\x1B":r===32?" ":r===34?'"':r===47?"/":r===92?"\\":r===78?"\x85":r===95?"\xA0":r===76?"\u2028":r===80?"\u2029":""}function fpe(r){return r<=65535?String.fromCharCode(r):String.fromCharCode((r-65536>>10)+55296,(r-65536&1023)+56320)}var x2=new Array(256),P2=new Array(256);for(nc=0;nc<256;nc++)x2[nc]=m2(nc)?1:0,P2[nc]=m2(nc);var nc;function hpe(r,e){this.input=r,this.filename=e.filename||null,this.schema=e.schema||spe,this.onWarning=e.onWarning||null,this.legacy=e.legacy||!1,this.json=e.json||!1,this.listener=e.listener||null,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=r.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.documents=[]}function D2(r,e){return new w2(e,new npe(r.filename,r.input,r.position,r.line,r.position-r.lineStart))}function ft(r,e){throw D2(r,e)}function yI(r,e){r.onWarning&&r.onWarning.call(null,D2(r,e))}var E2={YAML:function(e,t,i){var n,s,o;e.version!==null&&ft(e,"duplication of %YAML directive"),i.length!==1&&ft(e,"YAML directive accepts exactly one argument"),n=/^([0-9]+)\.([0-9]+)$/.exec(i[0]),n===null&&ft(e,"ill-formed argument of the YAML directive"),s=parseInt(n[1],10),o=parseInt(n[2],10),s!==1&&ft(e,"unacceptable YAML version of the document"),e.version=i[0],e.checkLineBreaks=o<2,o!==1&&o!==2&&yI(e,"unsupported YAML version of the document")},TAG:function(e,t,i){var n,s;i.length!==2&&ft(e,"TAG directive accepts exactly two arguments"),n=i[0],s=i[1],S2.test(n)||ft(e,"ill-formed tag handle (first argument) of the TAG directive"),kA.call(e.tagMap,n)&&ft(e,'there is a previously declared suffix for "'+n+'" tag handle'),v2.test(s)||ft(e,"ill-formed tag prefix (second argument) of the TAG directive"),e.tagMap[n]=s}};function DA(r,e,t,i){var n,s,o,a;if(e1&&(r.result+=Ba.repeat(` +`,e-1))}function ppe(r,e,t){var i,n,s,o,a,l,c,u,g=r.kind,f=r.result,h;if(h=r.input.charCodeAt(r.position),fn(h)||Mg(h)||h===35||h===38||h===42||h===33||h===124||h===62||h===39||h===34||h===37||h===64||h===96||(h===63||h===45)&&(n=r.input.charCodeAt(r.position+1),fn(n)||t&&Mg(n)))return!1;for(r.kind="scalar",r.result="",s=o=r.position,a=!1;h!==0;){if(h===58){if(n=r.input.charCodeAt(r.position+1),fn(n)||t&&Mg(n))break}else if(h===35){if(i=r.input.charCodeAt(r.position-1),fn(i))break}else{if(r.position===r.lineStart&&wI(r)||t&&Mg(h))break;if(xo(h))if(l=r.line,c=r.lineStart,u=r.lineIndent,zr(r,!1,-1),r.lineIndent>=e){a=!0,h=r.input.charCodeAt(r.position);continue}else{r.position=o,r.line=l,r.lineStart=c,r.lineIndent=u;break}}a&&(DA(r,s,o,!1),zS(r,r.line-l),s=o=r.position,a=!1),sc(h)||(o=r.position+1),h=r.input.charCodeAt(++r.position)}return DA(r,s,o,!1),r.result?!0:(r.kind=g,r.result=f,!1)}function dpe(r,e){var t,i,n;if(t=r.input.charCodeAt(r.position),t!==39)return!1;for(r.kind="scalar",r.result="",r.position++,i=n=r.position;(t=r.input.charCodeAt(r.position))!==0;)if(t===39)if(DA(r,i,r.position,!0),t=r.input.charCodeAt(++r.position),t===39)i=r.position,r.position++,n=r.position;else return!0;else xo(t)?(DA(r,i,n,!0),zS(r,zr(r,!1,e)),i=n=r.position):r.position===r.lineStart&&wI(r)?ft(r,"unexpected end of the document within a single quoted scalar"):(r.position++,n=r.position);ft(r,"unexpected end of the stream within a single quoted scalar")}function Cpe(r,e){var t,i,n,s,o,a;if(a=r.input.charCodeAt(r.position),a!==34)return!1;for(r.kind="scalar",r.result="",r.position++,t=i=r.position;(a=r.input.charCodeAt(r.position))!==0;){if(a===34)return DA(r,t,r.position,!0),r.position++,!0;if(a===92){if(DA(r,t,r.position,!0),a=r.input.charCodeAt(++r.position),xo(a))zr(r,!1,e);else if(a<256&&x2[a])r.result+=P2[a],r.position++;else if((o=upe(a))>0){for(n=o,s=0;n>0;n--)a=r.input.charCodeAt(++r.position),(o=cpe(a))>=0?s=(s<<4)+o:ft(r,"expected hexadecimal character");r.result+=fpe(s),r.position++}else ft(r,"unknown escape sequence");t=i=r.position}else xo(a)?(DA(r,t,i,!0),zS(r,zr(r,!1,e)),t=i=r.position):r.position===r.lineStart&&wI(r)?ft(r,"unexpected end of the document within a double quoted scalar"):(r.position++,i=r.position)}ft(r,"unexpected end of the stream within a double quoted scalar")}function mpe(r,e){var t=!0,i,n=r.tag,s,o=r.anchor,a,l,c,u,g,f={},h,p,C,y;if(y=r.input.charCodeAt(r.position),y===91)l=93,g=!1,s=[];else if(y===123)l=125,g=!0,s={};else return!1;for(r.anchor!==null&&(r.anchorMap[r.anchor]=s),y=r.input.charCodeAt(++r.position);y!==0;){if(zr(r,!0,e),y=r.input.charCodeAt(r.position),y===l)return r.position++,r.tag=n,r.anchor=o,r.kind=g?"mapping":"sequence",r.result=s,!0;t||ft(r,"missed comma between flow collection entries"),p=h=C=null,c=u=!1,y===63&&(a=r.input.charCodeAt(r.position+1),fn(a)&&(c=u=!0,r.position++,zr(r,!0,e))),i=r.line,Kg(r,e,EI,!1,!0),p=r.tag,h=r.result,zr(r,!0,e),y=r.input.charCodeAt(r.position),(u||r.line===i)&&y===58&&(c=!0,y=r.input.charCodeAt(++r.position),zr(r,!0,e),Kg(r,e,EI,!1,!0),C=r.result),g?Og(r,s,f,p,h,C):c?s.push(Og(r,null,f,p,h,C)):s.push(h),zr(r,!0,e),y=r.input.charCodeAt(r.position),y===44?(t=!0,y=r.input.charCodeAt(++r.position)):t=!1}ft(r,"unexpected end of the stream within a flow collection")}function Epe(r,e){var t,i,n=JS,s=!1,o=!1,a=e,l=0,c=!1,u,g;if(g=r.input.charCodeAt(r.position),g===124)i=!1;else if(g===62)i=!0;else return!1;for(r.kind="scalar",r.result="";g!==0;)if(g=r.input.charCodeAt(++r.position),g===43||g===45)JS===n?n=g===43?d2:ope:ft(r,"repeat of a chomping mode identifier");else if((u=gpe(g))>=0)u===0?ft(r,"bad explicit indentation width of a block scalar; it cannot be less than one"):o?ft(r,"repeat of an indentation width identifier"):(a=e+u-1,o=!0);else break;if(sc(g)){do g=r.input.charCodeAt(++r.position);while(sc(g));if(g===35)do g=r.input.charCodeAt(++r.position);while(!xo(g)&&g!==0)}for(;g!==0;){for(WS(r),r.lineIndent=0,g=r.input.charCodeAt(r.position);(!o||r.lineIndenta&&(a=r.lineIndent),xo(g)){l++;continue}if(r.lineIndente)&&l!==0)ft(r,"bad indentation of a sequence entry");else if(r.lineIndente)&&(Kg(r,e,II,!0,n)&&(p?f=r.result:h=r.result),p||(Og(r,c,u,g,f,h,s,o),g=f=h=null),zr(r,!0,-1),y=r.input.charCodeAt(r.position)),r.lineIndent>e&&y!==0)ft(r,"bad indentation of a mapping entry");else if(r.lineIndente?l=1:r.lineIndent===e?l=0:r.lineIndente?l=1:r.lineIndent===e?l=0:r.lineIndent tag; it should be "scalar", not "'+r.kind+'"'),g=0,f=r.implicitTypes.length;g tag; it should be "'+h.kind+'", not "'+r.kind+'"'),h.resolve(r.result)?(r.result=h.construct(r.result),r.anchor!==null&&(r.anchorMap[r.anchor]=r.result)):ft(r,"cannot resolve a node with !<"+r.tag+"> explicit tag")):ft(r,"unknown tag !<"+r.tag+">");return r.listener!==null&&r.listener("close",r),r.tag!==null||r.anchor!==null||u}function bpe(r){var e=r.position,t,i,n,s=!1,o;for(r.version=null,r.checkLineBreaks=r.legacy,r.tagMap={},r.anchorMap={};(o=r.input.charCodeAt(r.position))!==0&&(zr(r,!0,-1),o=r.input.charCodeAt(r.position),!(r.lineIndent>0||o!==37));){for(s=!0,o=r.input.charCodeAt(++r.position),t=r.position;o!==0&&!fn(o);)o=r.input.charCodeAt(++r.position);for(i=r.input.slice(t,r.position),n=[],i.length<1&&ft(r,"directive name must not be less than one character in length");o!==0;){for(;sc(o);)o=r.input.charCodeAt(++r.position);if(o===35){do o=r.input.charCodeAt(++r.position);while(o!==0&&!xo(o));break}if(xo(o))break;for(t=r.position;o!==0&&!fn(o);)o=r.input.charCodeAt(++r.position);n.push(r.input.slice(t,r.position))}o!==0&&WS(r),kA.call(E2,i)?E2[i](r,i,n):yI(r,'unknown document directive "'+i+'"')}if(zr(r,!0,-1),r.lineIndent===0&&r.input.charCodeAt(r.position)===45&&r.input.charCodeAt(r.position+1)===45&&r.input.charCodeAt(r.position+2)===45?(r.position+=3,zr(r,!0,-1)):s&&ft(r,"directives end mark is expected"),Kg(r,r.lineIndent-1,II,!1,!0),zr(r,!0,-1),r.checkLineBreaks&&Ape.test(r.input.slice(e,r.position))&&yI(r,"non-ASCII line breaks are interpreted as content"),r.documents.push(r.result),r.position===r.lineStart&&wI(r)){r.input.charCodeAt(r.position)===46&&(r.position+=3,zr(r,!0,-1));return}if(r.position"u"&&(t=e,e=null);var i=k2(r,t);if(typeof e!="function")return i;for(var n=0,s=i.length;n"u"&&(t=e,e=null),R2(r,e,Ba.extend({schema:B2},t))}function Spe(r,e){return F2(r,Ba.extend({schema:B2},e))}Zp.exports.loadAll=R2;Zp.exports.load=F2;Zp.exports.safeLoadAll=Qpe;Zp.exports.safeLoad=Spe});var iH=w(($Ze,_S)=>{"use strict";var $p=tc(),ed=Ng(),vpe=Xp(),xpe=Lg(),G2=Object.prototype.toString,Y2=Object.prototype.hasOwnProperty,Ppe=9,_p=10,Dpe=13,kpe=32,Rpe=33,Fpe=34,j2=35,Npe=37,Tpe=38,Lpe=39,Mpe=42,q2=44,Ope=45,J2=58,Kpe=61,Upe=62,Hpe=63,Gpe=64,W2=91,z2=93,Ype=96,V2=123,jpe=124,X2=125,Ni={};Ni[0]="\\0";Ni[7]="\\a";Ni[8]="\\b";Ni[9]="\\t";Ni[10]="\\n";Ni[11]="\\v";Ni[12]="\\f";Ni[13]="\\r";Ni[27]="\\e";Ni[34]='\\"';Ni[92]="\\\\";Ni[133]="\\N";Ni[160]="\\_";Ni[8232]="\\L";Ni[8233]="\\P";var qpe=["y","Y","yes","Yes","YES","on","On","ON","n","N","no","No","NO","off","Off","OFF"];function Jpe(r,e){var t,i,n,s,o,a,l;if(e===null)return{};for(t={},i=Object.keys(e),n=0,s=i.length;n0?r.charCodeAt(s-1):null,f=f&&M2(o,a)}else{for(s=0;si&&r[g+1]!==" ",g=s);else if(!Ug(o))return BI;a=s>0?r.charCodeAt(s-1):null,f=f&&M2(o,a)}c=c||u&&s-g-1>i&&r[g+1]!==" "}return!l&&!c?f&&!n(r)?_2:$2:t>9&&Z2(r)?BI:c?tH:eH}function _pe(r,e,t,i){r.dump=function(){if(e.length===0)return"''";if(!r.noCompatMode&&qpe.indexOf(e)!==-1)return"'"+e+"'";var n=r.indent*Math.max(1,t),s=r.lineWidth===-1?-1:Math.max(Math.min(r.lineWidth,40),r.lineWidth-n),o=i||r.flowLevel>-1&&t>=r.flowLevel;function a(l){return zpe(r,l)}switch(Zpe(e,o,r.indent,s,a)){case _2:return e;case $2:return"'"+e.replace(/'/g,"''")+"'";case eH:return"|"+O2(e,r.indent)+K2(L2(e,n));case tH:return">"+O2(e,r.indent)+K2(L2($pe(e,s),n));case BI:return'"'+ede(e,s)+'"';default:throw new ed("impossible error: invalid scalar style")}}()}function O2(r,e){var t=Z2(r)?String(e):"",i=r[r.length-1]===` +`,n=i&&(r[r.length-2]===` +`||r===` +`),s=n?"+":i?"":"-";return t+s+` +`}function K2(r){return r[r.length-1]===` +`?r.slice(0,-1):r}function $pe(r,e){for(var t=/(\n+)([^\n]*)/g,i=function(){var c=r.indexOf(` +`);return c=c!==-1?c:r.length,t.lastIndex=c,U2(r.slice(0,c),e)}(),n=r[0]===` +`||r[0]===" ",s,o;o=t.exec(r);){var a=o[1],l=o[2];s=l[0]===" ",i+=a+(!n&&!s&&l!==""?` +`:"")+U2(l,e),n=s}return i}function U2(r,e){if(r===""||r[0]===" ")return r;for(var t=/ [^ ]/g,i,n=0,s,o=0,a=0,l="";i=t.exec(r);)a=i.index,a-n>e&&(s=o>n?o:a,l+=` +`+r.slice(n,s),n=s+1),o=a;return l+=` +`,r.length-n>e&&o>n?l+=r.slice(n,o)+` +`+r.slice(o+1):l+=r.slice(n),l.slice(1)}function ede(r){for(var e="",t,i,n,s=0;s=55296&&t<=56319&&(i=r.charCodeAt(s+1),i>=56320&&i<=57343)){e+=T2((t-55296)*1024+i-56320+65536),s++;continue}n=Ni[t],e+=!n&&Ug(t)?r[s]:n||T2(t)}return e}function tde(r,e,t){var i="",n=r.tag,s,o;for(s=0,o=t.length;s1024&&(u+="? "),u+=r.dump+(r.condenseFlow?'"':"")+":"+(r.condenseFlow?"":" "),oc(r,e,c,!1,!1)&&(u+=r.dump,i+=u));r.tag=n,r.dump="{"+i+"}"}function nde(r,e,t,i){var n="",s=r.tag,o=Object.keys(t),a,l,c,u,g,f;if(r.sortKeys===!0)o.sort();else if(typeof r.sortKeys=="function")o.sort(r.sortKeys);else if(r.sortKeys)throw new ed("sortKeys must be a boolean or a function");for(a=0,l=o.length;a1024,g&&(r.dump&&_p===r.dump.charCodeAt(0)?f+="?":f+="? "),f+=r.dump,g&&(f+=VS(r,e)),oc(r,e+1,u,!0,g)&&(r.dump&&_p===r.dump.charCodeAt(0)?f+=":":f+=": ",f+=r.dump,n+=f));r.tag=s,r.dump=n||"{}"}function H2(r,e,t){var i,n,s,o,a,l;for(n=t?r.explicitTypes:r.implicitTypes,s=0,o=n.length;s tag resolver accepts not "'+l+'" style');r.dump=i}return!0}return!1}function oc(r,e,t,i,n,s){r.tag=null,r.dump=t,H2(r,t,!1)||H2(r,t,!0);var o=G2.call(r.dump);i&&(i=r.flowLevel<0||r.flowLevel>e);var a=o==="[object Object]"||o==="[object Array]",l,c;if(a&&(l=r.duplicates.indexOf(t),c=l!==-1),(r.tag!==null&&r.tag!=="?"||c||r.indent!==2&&e>0)&&(n=!1),c&&r.usedDuplicates[l])r.dump="*ref_"+l;else{if(a&&c&&!r.usedDuplicates[l]&&(r.usedDuplicates[l]=!0),o==="[object Object]")i&&Object.keys(r.dump).length!==0?(nde(r,e,r.dump,n),c&&(r.dump="&ref_"+l+r.dump)):(ide(r,e,r.dump),c&&(r.dump="&ref_"+l+" "+r.dump));else if(o==="[object Array]"){var u=r.noArrayIndent&&e>0?e-1:e;i&&r.dump.length!==0?(rde(r,u,r.dump,n),c&&(r.dump="&ref_"+l+r.dump)):(tde(r,u,r.dump),c&&(r.dump="&ref_"+l+" "+r.dump))}else if(o==="[object String]")r.tag!=="?"&&_pe(r,r.dump,e,s);else{if(r.skipInvalid)return!1;throw new ed("unacceptable kind of an object to dump "+o)}r.tag!==null&&r.tag!=="?"&&(r.dump="!<"+r.tag+"> "+r.dump)}return!0}function sde(r,e){var t=[],i=[],n,s;for(XS(r,t,i),n=0,s=i.length;n{"use strict";var bI=N2(),nH=iH();function QI(r){return function(){throw new Error("Function "+r+" is deprecated and cannot be used.")}}Fr.exports.Type=si();Fr.exports.Schema=rc();Fr.exports.FAILSAFE_SCHEMA=CI();Fr.exports.JSON_SCHEMA=YS();Fr.exports.CORE_SCHEMA=jS();Fr.exports.DEFAULT_SAFE_SCHEMA=Lg();Fr.exports.DEFAULT_FULL_SCHEMA=Xp();Fr.exports.load=bI.load;Fr.exports.loadAll=bI.loadAll;Fr.exports.safeLoad=bI.safeLoad;Fr.exports.safeLoadAll=bI.safeLoadAll;Fr.exports.dump=nH.dump;Fr.exports.safeDump=nH.safeDump;Fr.exports.YAMLException=Ng();Fr.exports.MINIMAL_SCHEMA=CI();Fr.exports.SAFE_SCHEMA=Lg();Fr.exports.DEFAULT_SCHEMA=Xp();Fr.exports.scan=QI("scan");Fr.exports.parse=QI("parse");Fr.exports.compose=QI("compose");Fr.exports.addConstructor=QI("addConstructor")});var aH=w((t_e,oH)=>{"use strict";var ade=sH();oH.exports=ade});var lH=w((r_e,AH)=>{"use strict";function Ade(r,e){function t(){this.constructor=r}t.prototype=e.prototype,r.prototype=new t}function ac(r,e,t,i){this.message=r,this.expected=e,this.found=t,this.location=i,this.name="SyntaxError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,ac)}Ade(ac,Error);ac.buildMessage=function(r,e){var t={literal:function(c){return'"'+n(c.text)+'"'},class:function(c){var u="",g;for(g=0;g0){for(g=1,f=1;g({[Ke]:Ce})))},H=function(R){return R},j=function(R){return R},$=Us("correct indentation"),V=" ",W=ar(" ",!1),_=function(R){return R.length===bA*yg},A=function(R){return R.length===(bA+1)*yg},Ae=function(){return bA++,!0},ge=function(){return bA--,!0},re=function(){return pg()},M=Us("pseudostring"),F=/^[^\r\n\t ?:,\][{}#&*!|>'"%@`\-]/,ue=Tn(["\r",` +`," "," ","?",":",",","]","[","{","}","#","&","*","!","|",">","'",'"',"%","@","`","-"],!0,!1),pe=/^[^\r\n\t ,\][{}:#"']/,ke=Tn(["\r",` +`," "," ",",","]","[","{","}",":","#",'"',"'"],!0,!1),Fe=function(){return pg().replace(/^ *| *$/g,"")},Ne="--",oe=ar("--",!1),le=/^[a-zA-Z\/0-9]/,Be=Tn([["a","z"],["A","Z"],"/",["0","9"]],!1,!1),fe=/^[^\r\n\t :,]/,ae=Tn(["\r",` +`," "," ",":",","],!0,!1),qe="null",ne=ar("null",!1),Y=function(){return null},he="true",ie=ar("true",!1),de=function(){return!0},_e="false",Pt=ar("false",!1),It=function(){return!1},Mr=Us("string"),ii='"',gi=ar('"',!1),hr=function(){return""},fi=function(R){return R},ni=function(R){return R.join("")},Ks=/^[^"\\\0-\x1F\x7F]/,pr=Tn(['"',"\\",["\0",""],"\x7F"],!0,!1),Ii='\\"',rs=ar('\\"',!1),fa=function(){return'"'},dA="\\\\",cg=ar("\\\\",!1),is=function(){return"\\"},CA="\\/",ha=ar("\\/",!1),wp=function(){return"/"},mA="\\b",EA=ar("\\b",!1),wr=function(){return"\b"},Tl="\\f",ug=ar("\\f",!1),yo=function(){return"\f"},gg="\\n",Bp=ar("\\n",!1),bp=function(){return` +`},vr="\\r",se=ar("\\r",!1),wo=function(){return"\r"},Fn="\\t",fg=ar("\\t",!1),bt=function(){return" "},Ll="\\u",Nn=ar("\\u",!1),ns=function(R,q,Ce,Ke){return String.fromCharCode(parseInt(`0x${R}${q}${Ce}${Ke}`))},ss=/^[0-9a-fA-F]/,gt=Tn([["0","9"],["a","f"],["A","F"]],!1,!1),Bo=Us("blank space"),At=/^[ \t]/,ln=Tn([" "," "],!1,!1),S=Us("white space"),Lt=/^[ \t\n\r]/,hg=Tn([" "," ",` +`,"\r"],!1,!1),Ml=`\r +`,Qp=ar(`\r +`,!1),Sp=` +`,vp=ar(` +`,!1),xp="\r",Pp=ar("\r",!1),G=0,yt=0,IA=[{line:1,column:1}],zi=0,Ol=[],Xe=0,pa;if("startRule"in e){if(!(e.startRule in i))throw new Error(`Can't start parsing from rule "`+e.startRule+'".');n=i[e.startRule]}function pg(){return r.substring(yt,G)}function ME(){return cn(yt,G)}function Dp(R,q){throw q=q!==void 0?q:cn(yt,G),Ul([Us(R)],r.substring(yt,G),q)}function OE(R,q){throw q=q!==void 0?q:cn(yt,G),dg(R,q)}function ar(R,q){return{type:"literal",text:R,ignoreCase:q}}function Tn(R,q,Ce){return{type:"class",parts:R,inverted:q,ignoreCase:Ce}}function Kl(){return{type:"any"}}function kp(){return{type:"end"}}function Us(R){return{type:"other",description:R}}function da(R){var q=IA[R],Ce;if(q)return q;for(Ce=R-1;!IA[Ce];)Ce--;for(q=IA[Ce],q={line:q.line,column:q.column};Cezi&&(zi=G,Ol=[]),Ol.push(R))}function dg(R,q){return new ac(R,null,null,q)}function Ul(R,q,Ce){return new ac(ac.buildMessage(R,q),R,q,Ce)}function Hs(){var R;return R=Cg(),R}function Hl(){var R,q,Ce;for(R=G,q=[],Ce=yA();Ce!==t;)q.push(Ce),Ce=yA();return q!==t&&(yt=R,q=s(q)),R=q,R}function yA(){var R,q,Ce,Ke,Re;return R=G,q=ma(),q!==t?(r.charCodeAt(G)===45?(Ce=o,G++):(Ce=t,Xe===0&&Le(a)),Ce!==t?(Ke=Rr(),Ke!==t?(Re=Ca(),Re!==t?(yt=R,q=l(Re),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t),R}function Cg(){var R,q,Ce;for(R=G,q=[],Ce=mg();Ce!==t;)q.push(Ce),Ce=mg();return q!==t&&(yt=R,q=c(q)),R=q,R}function mg(){var R,q,Ce,Ke,Re,ze,dt,Ft,Ln;if(R=G,q=Rr(),q===t&&(q=null),q!==t){if(Ce=G,r.charCodeAt(G)===35?(Ke=u,G++):(Ke=t,Xe===0&&Le(g)),Ke!==t){if(Re=[],ze=G,dt=G,Xe++,Ft=js(),Xe--,Ft===t?dt=void 0:(G=dt,dt=t),dt!==t?(r.length>G?(Ft=r.charAt(G),G++):(Ft=t,Xe===0&&Le(f)),Ft!==t?(dt=[dt,Ft],ze=dt):(G=ze,ze=t)):(G=ze,ze=t),ze!==t)for(;ze!==t;)Re.push(ze),ze=G,dt=G,Xe++,Ft=js(),Xe--,Ft===t?dt=void 0:(G=dt,dt=t),dt!==t?(r.length>G?(Ft=r.charAt(G),G++):(Ft=t,Xe===0&&Le(f)),Ft!==t?(dt=[dt,Ft],ze=dt):(G=ze,ze=t)):(G=ze,ze=t);else Re=t;Re!==t?(Ke=[Ke,Re],Ce=Ke):(G=Ce,Ce=t)}else G=Ce,Ce=t;if(Ce===t&&(Ce=null),Ce!==t){if(Ke=[],Re=Ys(),Re!==t)for(;Re!==t;)Ke.push(Re),Re=Ys();else Ke=t;Ke!==t?(yt=R,q=h(),R=q):(G=R,R=t)}else G=R,R=t}else G=R,R=t;if(R===t&&(R=G,q=ma(),q!==t?(Ce=Gl(),Ce!==t?(Ke=Rr(),Ke===t&&(Ke=null),Ke!==t?(r.charCodeAt(G)===58?(Re=p,G++):(Re=t,Xe===0&&Le(C)),Re!==t?(ze=Rr(),ze===t&&(ze=null),ze!==t?(dt=Ca(),dt!==t?(yt=R,q=y(Ce,dt),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t),R===t&&(R=G,q=ma(),q!==t?(Ce=Gs(),Ce!==t?(Ke=Rr(),Ke===t&&(Ke=null),Ke!==t?(r.charCodeAt(G)===58?(Re=p,G++):(Re=t,Xe===0&&Le(C)),Re!==t?(ze=Rr(),ze===t&&(ze=null),ze!==t?(dt=Ca(),dt!==t?(yt=R,q=y(Ce,dt),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t),R===t))){if(R=G,q=ma(),q!==t)if(Ce=Gs(),Ce!==t)if(Ke=Rr(),Ke!==t)if(Re=KE(),Re!==t){if(ze=[],dt=Ys(),dt!==t)for(;dt!==t;)ze.push(dt),dt=Ys();else ze=t;ze!==t?(yt=R,q=y(Ce,Re),R=q):(G=R,R=t)}else G=R,R=t;else G=R,R=t;else G=R,R=t;else G=R,R=t;if(R===t)if(R=G,q=ma(),q!==t)if(Ce=Gs(),Ce!==t){if(Ke=[],Re=G,ze=Rr(),ze===t&&(ze=null),ze!==t?(r.charCodeAt(G)===44?(dt=B,G++):(dt=t,Xe===0&&Le(v)),dt!==t?(Ft=Rr(),Ft===t&&(Ft=null),Ft!==t?(Ln=Gs(),Ln!==t?(yt=Re,ze=D(Ce,Ln),Re=ze):(G=Re,Re=t)):(G=Re,Re=t)):(G=Re,Re=t)):(G=Re,Re=t),Re!==t)for(;Re!==t;)Ke.push(Re),Re=G,ze=Rr(),ze===t&&(ze=null),ze!==t?(r.charCodeAt(G)===44?(dt=B,G++):(dt=t,Xe===0&&Le(v)),dt!==t?(Ft=Rr(),Ft===t&&(Ft=null),Ft!==t?(Ln=Gs(),Ln!==t?(yt=Re,ze=D(Ce,Ln),Re=ze):(G=Re,Re=t)):(G=Re,Re=t)):(G=Re,Re=t)):(G=Re,Re=t);else Ke=t;Ke!==t?(Re=Rr(),Re===t&&(Re=null),Re!==t?(r.charCodeAt(G)===58?(ze=p,G++):(ze=t,Xe===0&&Le(C)),ze!==t?(dt=Rr(),dt===t&&(dt=null),dt!==t?(Ft=Ca(),Ft!==t?(yt=R,q=T(Ce,Ke,Ft),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)}else G=R,R=t;else G=R,R=t}return R}function Ca(){var R,q,Ce,Ke,Re,ze,dt;if(R=G,q=G,Xe++,Ce=G,Ke=js(),Ke!==t?(Re=rt(),Re!==t?(r.charCodeAt(G)===45?(ze=o,G++):(ze=t,Xe===0&&Le(a)),ze!==t?(dt=Rr(),dt!==t?(Ke=[Ke,Re,ze,dt],Ce=Ke):(G=Ce,Ce=t)):(G=Ce,Ce=t)):(G=Ce,Ce=t)):(G=Ce,Ce=t),Xe--,Ce!==t?(G=q,q=void 0):q=t,q!==t?(Ce=Ys(),Ce!==t?(Ke=bo(),Ke!==t?(Re=Hl(),Re!==t?(ze=wA(),ze!==t?(yt=R,q=H(Re),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t),R===t&&(R=G,q=js(),q!==t?(Ce=bo(),Ce!==t?(Ke=Cg(),Ke!==t?(Re=wA(),Re!==t?(yt=R,q=H(Ke),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t),R===t))if(R=G,q=Yl(),q!==t){if(Ce=[],Ke=Ys(),Ke!==t)for(;Ke!==t;)Ce.push(Ke),Ke=Ys();else Ce=t;Ce!==t?(yt=R,q=j(q),R=q):(G=R,R=t)}else G=R,R=t;return R}function ma(){var R,q,Ce;for(Xe++,R=G,q=[],r.charCodeAt(G)===32?(Ce=V,G++):(Ce=t,Xe===0&&Le(W));Ce!==t;)q.push(Ce),r.charCodeAt(G)===32?(Ce=V,G++):(Ce=t,Xe===0&&Le(W));return q!==t?(yt=G,Ce=_(q),Ce?Ce=void 0:Ce=t,Ce!==t?(q=[q,Ce],R=q):(G=R,R=t)):(G=R,R=t),Xe--,R===t&&(q=t,Xe===0&&Le($)),R}function rt(){var R,q,Ce;for(R=G,q=[],r.charCodeAt(G)===32?(Ce=V,G++):(Ce=t,Xe===0&&Le(W));Ce!==t;)q.push(Ce),r.charCodeAt(G)===32?(Ce=V,G++):(Ce=t,Xe===0&&Le(W));return q!==t?(yt=G,Ce=A(q),Ce?Ce=void 0:Ce=t,Ce!==t?(q=[q,Ce],R=q):(G=R,R=t)):(G=R,R=t),R}function bo(){var R;return yt=G,R=Ae(),R?R=void 0:R=t,R}function wA(){var R;return yt=G,R=ge(),R?R=void 0:R=t,R}function Gl(){var R;return R=jl(),R===t&&(R=Rp()),R}function Gs(){var R,q,Ce;if(R=jl(),R===t){if(R=G,q=[],Ce=Eg(),Ce!==t)for(;Ce!==t;)q.push(Ce),Ce=Eg();else q=t;q!==t&&(yt=R,q=re()),R=q}return R}function Yl(){var R;return R=Fp(),R===t&&(R=UE(),R===t&&(R=jl(),R===t&&(R=Rp()))),R}function KE(){var R;return R=Fp(),R===t&&(R=jl(),R===t&&(R=Eg())),R}function Rp(){var R,q,Ce,Ke,Re,ze;if(Xe++,R=G,F.test(r.charAt(G))?(q=r.charAt(G),G++):(q=t,Xe===0&&Le(ue)),q!==t){for(Ce=[],Ke=G,Re=Rr(),Re===t&&(Re=null),Re!==t?(pe.test(r.charAt(G))?(ze=r.charAt(G),G++):(ze=t,Xe===0&&Le(ke)),ze!==t?(Re=[Re,ze],Ke=Re):(G=Ke,Ke=t)):(G=Ke,Ke=t);Ke!==t;)Ce.push(Ke),Ke=G,Re=Rr(),Re===t&&(Re=null),Re!==t?(pe.test(r.charAt(G))?(ze=r.charAt(G),G++):(ze=t,Xe===0&&Le(ke)),ze!==t?(Re=[Re,ze],Ke=Re):(G=Ke,Ke=t)):(G=Ke,Ke=t);Ce!==t?(yt=R,q=Fe(),R=q):(G=R,R=t)}else G=R,R=t;return Xe--,R===t&&(q=t,Xe===0&&Le(M)),R}function Eg(){var R,q,Ce,Ke,Re;if(R=G,r.substr(G,2)===Ne?(q=Ne,G+=2):(q=t,Xe===0&&Le(oe)),q===t&&(q=null),q!==t)if(le.test(r.charAt(G))?(Ce=r.charAt(G),G++):(Ce=t,Xe===0&&Le(Be)),Ce!==t){for(Ke=[],fe.test(r.charAt(G))?(Re=r.charAt(G),G++):(Re=t,Xe===0&&Le(ae));Re!==t;)Ke.push(Re),fe.test(r.charAt(G))?(Re=r.charAt(G),G++):(Re=t,Xe===0&&Le(ae));Ke!==t?(yt=R,q=Fe(),R=q):(G=R,R=t)}else G=R,R=t;else G=R,R=t;return R}function Fp(){var R,q;return R=G,r.substr(G,4)===qe?(q=qe,G+=4):(q=t,Xe===0&&Le(ne)),q!==t&&(yt=R,q=Y()),R=q,R}function UE(){var R,q;return R=G,r.substr(G,4)===he?(q=he,G+=4):(q=t,Xe===0&&Le(ie)),q!==t&&(yt=R,q=de()),R=q,R===t&&(R=G,r.substr(G,5)===_e?(q=_e,G+=5):(q=t,Xe===0&&Le(Pt)),q!==t&&(yt=R,q=It()),R=q),R}function jl(){var R,q,Ce,Ke;return Xe++,R=G,r.charCodeAt(G)===34?(q=ii,G++):(q=t,Xe===0&&Le(gi)),q!==t?(r.charCodeAt(G)===34?(Ce=ii,G++):(Ce=t,Xe===0&&Le(gi)),Ce!==t?(yt=R,q=hr(),R=q):(G=R,R=t)):(G=R,R=t),R===t&&(R=G,r.charCodeAt(G)===34?(q=ii,G++):(q=t,Xe===0&&Le(gi)),q!==t?(Ce=HE(),Ce!==t?(r.charCodeAt(G)===34?(Ke=ii,G++):(Ke=t,Xe===0&&Le(gi)),Ke!==t?(yt=R,q=fi(Ce),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)),Xe--,R===t&&(q=t,Xe===0&&Le(Mr)),R}function HE(){var R,q,Ce;if(R=G,q=[],Ce=Ig(),Ce!==t)for(;Ce!==t;)q.push(Ce),Ce=Ig();else q=t;return q!==t&&(yt=R,q=ni(q)),R=q,R}function Ig(){var R,q,Ce,Ke,Re,ze;return Ks.test(r.charAt(G))?(R=r.charAt(G),G++):(R=t,Xe===0&&Le(pr)),R===t&&(R=G,r.substr(G,2)===Ii?(q=Ii,G+=2):(q=t,Xe===0&&Le(rs)),q!==t&&(yt=R,q=fa()),R=q,R===t&&(R=G,r.substr(G,2)===dA?(q=dA,G+=2):(q=t,Xe===0&&Le(cg)),q!==t&&(yt=R,q=is()),R=q,R===t&&(R=G,r.substr(G,2)===CA?(q=CA,G+=2):(q=t,Xe===0&&Le(ha)),q!==t&&(yt=R,q=wp()),R=q,R===t&&(R=G,r.substr(G,2)===mA?(q=mA,G+=2):(q=t,Xe===0&&Le(EA)),q!==t&&(yt=R,q=wr()),R=q,R===t&&(R=G,r.substr(G,2)===Tl?(q=Tl,G+=2):(q=t,Xe===0&&Le(ug)),q!==t&&(yt=R,q=yo()),R=q,R===t&&(R=G,r.substr(G,2)===gg?(q=gg,G+=2):(q=t,Xe===0&&Le(Bp)),q!==t&&(yt=R,q=bp()),R=q,R===t&&(R=G,r.substr(G,2)===vr?(q=vr,G+=2):(q=t,Xe===0&&Le(se)),q!==t&&(yt=R,q=wo()),R=q,R===t&&(R=G,r.substr(G,2)===Fn?(q=Fn,G+=2):(q=t,Xe===0&&Le(fg)),q!==t&&(yt=R,q=bt()),R=q,R===t&&(R=G,r.substr(G,2)===Ll?(q=Ll,G+=2):(q=t,Xe===0&&Le(Nn)),q!==t?(Ce=BA(),Ce!==t?(Ke=BA(),Ke!==t?(Re=BA(),Re!==t?(ze=BA(),ze!==t?(yt=R,q=ns(Ce,Ke,Re,ze),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)))))))))),R}function BA(){var R;return ss.test(r.charAt(G))?(R=r.charAt(G),G++):(R=t,Xe===0&&Le(gt)),R}function Rr(){var R,q;if(Xe++,R=[],At.test(r.charAt(G))?(q=r.charAt(G),G++):(q=t,Xe===0&&Le(ln)),q!==t)for(;q!==t;)R.push(q),At.test(r.charAt(G))?(q=r.charAt(G),G++):(q=t,Xe===0&&Le(ln));else R=t;return Xe--,R===t&&(q=t,Xe===0&&Le(Bo)),R}function GE(){var R,q;if(Xe++,R=[],Lt.test(r.charAt(G))?(q=r.charAt(G),G++):(q=t,Xe===0&&Le(hg)),q!==t)for(;q!==t;)R.push(q),Lt.test(r.charAt(G))?(q=r.charAt(G),G++):(q=t,Xe===0&&Le(hg));else R=t;return Xe--,R===t&&(q=t,Xe===0&&Le(S)),R}function Ys(){var R,q,Ce,Ke,Re,ze;if(R=G,q=js(),q!==t){for(Ce=[],Ke=G,Re=Rr(),Re===t&&(Re=null),Re!==t?(ze=js(),ze!==t?(Re=[Re,ze],Ke=Re):(G=Ke,Ke=t)):(G=Ke,Ke=t);Ke!==t;)Ce.push(Ke),Ke=G,Re=Rr(),Re===t&&(Re=null),Re!==t?(ze=js(),ze!==t?(Re=[Re,ze],Ke=Re):(G=Ke,Ke=t)):(G=Ke,Ke=t);Ce!==t?(q=[q,Ce],R=q):(G=R,R=t)}else G=R,R=t;return R}function js(){var R;return r.substr(G,2)===Ml?(R=Ml,G+=2):(R=t,Xe===0&&Le(Qp)),R===t&&(r.charCodeAt(G)===10?(R=Sp,G++):(R=t,Xe===0&&Le(vp)),R===t&&(r.charCodeAt(G)===13?(R=xp,G++):(R=t,Xe===0&&Le(Pp)))),R}let yg=2,bA=0;if(pa=n(),pa!==t&&G===r.length)return pa;throw pa!==t&&G{"use strict";var hde=r=>{let e=!1,t=!1,i=!1;for(let n=0;n{if(!(typeof r=="string"||Array.isArray(r)))throw new TypeError("Expected the input to be `string | string[]`");e=Object.assign({pascalCase:!1},e);let t=n=>e.pascalCase?n.charAt(0).toUpperCase()+n.slice(1):n;return Array.isArray(r)?r=r.map(n=>n.trim()).filter(n=>n.length).join("-"):r=r.trim(),r.length===0?"":r.length===1?e.pascalCase?r.toUpperCase():r.toLowerCase():(r!==r.toLowerCase()&&(r=hde(r)),r=r.replace(/^[_.\- ]+/,"").toLowerCase().replace(/[_.\- ]+(\w|$)/g,(n,s)=>s.toUpperCase()).replace(/\d+(\w|$)/g,n=>n.toUpperCase()),t(r))};ev.exports=hH;ev.exports.default=hH});var dH=w((A_e,pde)=>{pde.exports=[{name:"AppVeyor",constant:"APPVEYOR",env:"APPVEYOR",pr:"APPVEYOR_PULL_REQUEST_NUMBER"},{name:"Azure Pipelines",constant:"AZURE_PIPELINES",env:"SYSTEM_TEAMFOUNDATIONCOLLECTIONURI",pr:"SYSTEM_PULLREQUEST_PULLREQUESTID"},{name:"Appcircle",constant:"APPCIRCLE",env:"AC_APPCIRCLE"},{name:"Bamboo",constant:"BAMBOO",env:"bamboo_planKey"},{name:"Bitbucket Pipelines",constant:"BITBUCKET",env:"BITBUCKET_COMMIT",pr:"BITBUCKET_PR_ID"},{name:"Bitrise",constant:"BITRISE",env:"BITRISE_IO",pr:"BITRISE_PULL_REQUEST"},{name:"Buddy",constant:"BUDDY",env:"BUDDY_WORKSPACE_ID",pr:"BUDDY_EXECUTION_PULL_REQUEST_ID"},{name:"Buildkite",constant:"BUILDKITE",env:"BUILDKITE",pr:{env:"BUILDKITE_PULL_REQUEST",ne:"false"}},{name:"CircleCI",constant:"CIRCLE",env:"CIRCLECI",pr:"CIRCLE_PULL_REQUEST"},{name:"Cirrus CI",constant:"CIRRUS",env:"CIRRUS_CI",pr:"CIRRUS_PR"},{name:"AWS CodeBuild",constant:"CODEBUILD",env:"CODEBUILD_BUILD_ARN"},{name:"Codefresh",constant:"CODEFRESH",env:"CF_BUILD_ID",pr:{any:["CF_PULL_REQUEST_NUMBER","CF_PULL_REQUEST_ID"]}},{name:"Codeship",constant:"CODESHIP",env:{CI_NAME:"codeship"}},{name:"Drone",constant:"DRONE",env:"DRONE",pr:{DRONE_BUILD_EVENT:"pull_request"}},{name:"dsari",constant:"DSARI",env:"DSARI"},{name:"GitHub Actions",constant:"GITHUB_ACTIONS",env:"GITHUB_ACTIONS",pr:{GITHUB_EVENT_NAME:"pull_request"}},{name:"GitLab CI",constant:"GITLAB",env:"GITLAB_CI",pr:"CI_MERGE_REQUEST_ID"},{name:"GoCD",constant:"GOCD",env:"GO_PIPELINE_LABEL"},{name:"LayerCI",constant:"LAYERCI",env:"LAYERCI",pr:"LAYERCI_PULL_REQUEST"},{name:"Hudson",constant:"HUDSON",env:"HUDSON_URL"},{name:"Jenkins",constant:"JENKINS",env:["JENKINS_URL","BUILD_ID"],pr:{any:["ghprbPullId","CHANGE_ID"]}},{name:"Magnum CI",constant:"MAGNUM",env:"MAGNUM"},{name:"Netlify CI",constant:"NETLIFY",env:"NETLIFY",pr:{env:"PULL_REQUEST",ne:"false"}},{name:"Nevercode",constant:"NEVERCODE",env:"NEVERCODE",pr:{env:"NEVERCODE_PULL_REQUEST",ne:"false"}},{name:"Render",constant:"RENDER",env:"RENDER",pr:{IS_PULL_REQUEST:"true"}},{name:"Sail CI",constant:"SAIL",env:"SAILCI",pr:"SAIL_PULL_REQUEST_NUMBER"},{name:"Semaphore",constant:"SEMAPHORE",env:"SEMAPHORE",pr:"PULL_REQUEST_NUMBER"},{name:"Screwdriver",constant:"SCREWDRIVER",env:"SCREWDRIVER",pr:{env:"SD_PULL_REQUEST",ne:"false"}},{name:"Shippable",constant:"SHIPPABLE",env:"SHIPPABLE",pr:{IS_PULL_REQUEST:"true"}},{name:"Solano CI",constant:"SOLANO",env:"TDDIUM",pr:"TDDIUM_PR_ID"},{name:"Strider CD",constant:"STRIDER",env:"STRIDER"},{name:"TaskCluster",constant:"TASKCLUSTER",env:["TASK_ID","RUN_ID"]},{name:"TeamCity",constant:"TEAMCITY",env:"TEAMCITY_VERSION"},{name:"Travis CI",constant:"TRAVIS",env:"TRAVIS",pr:{env:"TRAVIS_PULL_REQUEST",ne:"false"}},{name:"Vercel",constant:"VERCEL",env:"NOW_BUILDER"},{name:"Visual Studio App Center",constant:"APPCENTER",env:"APPCENTER_BUILD_ID"}]});var Ac=w(Un=>{"use strict";var mH=dH(),Po=process.env;Object.defineProperty(Un,"_vendors",{value:mH.map(function(r){return r.constant})});Un.name=null;Un.isPR=null;mH.forEach(function(r){let t=(Array.isArray(r.env)?r.env:[r.env]).every(function(i){return CH(i)});if(Un[r.constant]=t,t)switch(Un.name=r.name,typeof r.pr){case"string":Un.isPR=!!Po[r.pr];break;case"object":"env"in r.pr?Un.isPR=r.pr.env in Po&&Po[r.pr.env]!==r.pr.ne:"any"in r.pr?Un.isPR=r.pr.any.some(function(i){return!!Po[i]}):Un.isPR=CH(r.pr);break;default:Un.isPR=null}});Un.isCI=!!(Po.CI||Po.CONTINUOUS_INTEGRATION||Po.BUILD_NUMBER||Po.RUN_ID||Un.name);function CH(r){return typeof r=="string"?!!Po[r]:Object.keys(r).every(function(e){return Po[e]===r[e]})}});var hn={};ut(hn,{KeyRelationship:()=>lc,applyCascade:()=>od,base64RegExp:()=>BH,colorStringAlphaRegExp:()=>wH,colorStringRegExp:()=>yH,computeKey:()=>RA,getPrintable:()=>Vr,hasExactLength:()=>xH,hasForbiddenKeys:()=>Wde,hasKeyRelationship:()=>av,hasMaxLength:()=>Dde,hasMinLength:()=>Pde,hasMutuallyExclusiveKeys:()=>zde,hasRequiredKeys:()=>Jde,hasUniqueItems:()=>kde,isArray:()=>yde,isAtLeast:()=>Nde,isAtMost:()=>Tde,isBase64:()=>jde,isBoolean:()=>mde,isDate:()=>Ide,isDict:()=>Bde,isEnum:()=>Zi,isHexColor:()=>Yde,isISO8601:()=>Gde,isInExclusiveRange:()=>Mde,isInInclusiveRange:()=>Lde,isInstanceOf:()=>Qde,isInteger:()=>Ode,isJSON:()=>qde,isLiteral:()=>dde,isLowerCase:()=>Kde,isNegative:()=>Rde,isNullable:()=>xde,isNumber:()=>Ede,isObject:()=>bde,isOneOf:()=>Sde,isOptional:()=>vde,isPositive:()=>Fde,isString:()=>sd,isTuple:()=>wde,isUUID4:()=>Hde,isUnknown:()=>vH,isUpperCase:()=>Ude,iso8601RegExp:()=>ov,makeCoercionFn:()=>cc,makeSetter:()=>SH,makeTrait:()=>QH,makeValidator:()=>Qt,matchesRegExp:()=>ad,plural:()=>kI,pushError:()=>pt,simpleKeyRegExp:()=>IH,uuid4RegExp:()=>bH});function Qt({test:r}){return QH(r)()}function Vr(r){return r===null?"null":r===void 0?"undefined":r===""?"an empty string":JSON.stringify(r)}function RA(r,e){var t,i,n;return typeof e=="number"?`${(t=r==null?void 0:r.p)!==null&&t!==void 0?t:"."}[${e}]`:IH.test(e)?`${(i=r==null?void 0:r.p)!==null&&i!==void 0?i:""}.${e}`:`${(n=r==null?void 0:r.p)!==null&&n!==void 0?n:"."}[${JSON.stringify(e)}]`}function cc(r,e){return t=>{let i=r[e];return r[e]=t,cc(r,e).bind(null,i)}}function SH(r,e){return t=>{r[e]=t}}function kI(r,e,t){return r===1?e:t}function pt({errors:r,p:e}={},t){return r==null||r.push(`${e!=null?e:"."}: ${t}`),!1}function dde(r){return Qt({test:(e,t)=>e!==r?pt(t,`Expected a literal (got ${Vr(r)})`):!0})}function Zi(r){let e=Array.isArray(r)?r:Object.values(r),t=new Set(e);return Qt({test:(i,n)=>t.has(i)?!0:pt(n,`Expected a valid enumeration value (got ${Vr(i)})`)})}var IH,yH,wH,BH,bH,ov,QH,vH,sd,Cde,mde,Ede,Ide,yde,wde,Bde,bde,Qde,Sde,od,vde,xde,Pde,Dde,xH,kde,Rde,Fde,Nde,Tde,Lde,Mde,Ode,ad,Kde,Ude,Hde,Gde,Yde,jde,qde,Jde,Wde,zde,lc,Vde,av,ls=Tge(()=>{IH=/^[a-zA-Z_][a-zA-Z0-9_]*$/,yH=/^#[0-9a-f]{6}$/i,wH=/^#[0-9a-f]{6}([0-9a-f]{2})?$/i,BH=/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/,bH=/^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}$/i,ov=/^(?:[1-9]\d{3}(-?)(?:(?:0[1-9]|1[0-2])\1(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])\1(?:29|30)|(?:0[13578]|1[02])(?:\1)31|00[1-9]|0[1-9]\d|[12]\d{2}|3(?:[0-5]\d|6[0-5]))|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)(?:(-?)02(?:\2)29|-?366))T(?:[01]\d|2[0-3])(:?)[0-5]\d(?:\3[0-5]\d)?(?:Z|[+-][01]\d(?:\3[0-5]\d)?)$/,QH=r=>()=>r;vH=()=>Qt({test:(r,e)=>!0});sd=()=>Qt({test:(r,e)=>typeof r!="string"?pt(e,`Expected a string (got ${Vr(r)})`):!0});Cde=new Map([["true",!0],["True",!0],["1",!0],[1,!0],["false",!1],["False",!1],["0",!1],[0,!1]]),mde=()=>Qt({test:(r,e)=>{var t;if(typeof r!="boolean"){if(typeof(e==null?void 0:e.coercions)<"u"){if(typeof(e==null?void 0:e.coercion)>"u")return pt(e,"Unbound coercion result");let i=Cde.get(r);if(typeof i<"u")return e.coercions.push([(t=e.p)!==null&&t!==void 0?t:".",e.coercion.bind(null,i)]),!0}return pt(e,`Expected a boolean (got ${Vr(r)})`)}return!0}}),Ede=()=>Qt({test:(r,e)=>{var t;if(typeof r!="number"){if(typeof(e==null?void 0:e.coercions)<"u"){if(typeof(e==null?void 0:e.coercion)>"u")return pt(e,"Unbound coercion result");let i;if(typeof r=="string"){let n;try{n=JSON.parse(r)}catch{}if(typeof n=="number")if(JSON.stringify(n)===r)i=n;else return pt(e,`Received a number that can't be safely represented by the runtime (${r})`)}if(typeof i<"u")return e.coercions.push([(t=e.p)!==null&&t!==void 0?t:".",e.coercion.bind(null,i)]),!0}return pt(e,`Expected a number (got ${Vr(r)})`)}return!0}}),Ide=()=>Qt({test:(r,e)=>{var t;if(!(r instanceof Date)){if(typeof(e==null?void 0:e.coercions)<"u"){if(typeof(e==null?void 0:e.coercion)>"u")return pt(e,"Unbound coercion result");let i;if(typeof r=="string"&&ov.test(r))i=new Date(r);else{let n;if(typeof r=="string"){let s;try{s=JSON.parse(r)}catch{}typeof s=="number"&&(n=s)}else typeof r=="number"&&(n=r);if(typeof n<"u")if(Number.isSafeInteger(n)||!Number.isSafeInteger(n*1e3))i=new Date(n*1e3);else return pt(e,`Received a timestamp that can't be safely represented by the runtime (${r})`)}if(typeof i<"u")return e.coercions.push([(t=e.p)!==null&&t!==void 0?t:".",e.coercion.bind(null,i)]),!0}return pt(e,`Expected a date (got ${Vr(r)})`)}return!0}}),yde=(r,{delimiter:e}={})=>Qt({test:(t,i)=>{var n;if(typeof t=="string"&&typeof e<"u"&&typeof(i==null?void 0:i.coercions)<"u"){if(typeof(i==null?void 0:i.coercion)>"u")return pt(i,"Unbound coercion result");t=t.split(e),i.coercions.push([(n=i.p)!==null&&n!==void 0?n:".",i.coercion.bind(null,t)])}if(!Array.isArray(t))return pt(i,`Expected an array (got ${Vr(t)})`);let s=!0;for(let o=0,a=t.length;o{let t=xH(r.length);return Qt({test:(i,n)=>{var s;if(typeof i=="string"&&typeof e<"u"&&typeof(n==null?void 0:n.coercions)<"u"){if(typeof(n==null?void 0:n.coercion)>"u")return pt(n,"Unbound coercion result");i=i.split(e),n.coercions.push([(s=n.p)!==null&&s!==void 0?s:".",n.coercion.bind(null,i)])}if(!Array.isArray(i))return pt(n,`Expected a tuple (got ${Vr(i)})`);let o=t(i,Object.assign({},n));for(let a=0,l=i.length;aQt({test:(t,i)=>{if(typeof t!="object"||t===null)return pt(i,`Expected an object (got ${Vr(t)})`);let n=Object.keys(t),s=!0;for(let o=0,a=n.length;o{let t=Object.keys(r);return Qt({test:(i,n)=>{if(typeof i!="object"||i===null)return pt(n,`Expected an object (got ${Vr(i)})`);let s=new Set([...t,...Object.keys(i)]),o={},a=!0;for(let l of s){if(l==="constructor"||l==="__proto__")a=pt(Object.assign(Object.assign({},n),{p:RA(n,l)}),"Unsafe property name");else{let c=Object.prototype.hasOwnProperty.call(r,l)?r[l]:void 0,u=Object.prototype.hasOwnProperty.call(i,l)?i[l]:void 0;typeof c<"u"?a=c(u,Object.assign(Object.assign({},n),{p:RA(n,l),coercion:cc(i,l)}))&&a:e===null?a=pt(Object.assign(Object.assign({},n),{p:RA(n,l)}),`Extraneous property (got ${Vr(u)})`):Object.defineProperty(o,l,{enumerable:!0,get:()=>u,set:SH(i,l)})}if(!a&&(n==null?void 0:n.errors)==null)break}return e!==null&&(a||(n==null?void 0:n.errors)!=null)&&(a=e(o,n)&&a),a}})},Qde=r=>Qt({test:(e,t)=>e instanceof r?!0:pt(t,`Expected an instance of ${r.name} (got ${Vr(e)})`)}),Sde=(r,{exclusive:e=!1}={})=>Qt({test:(t,i)=>{var n,s,o;let a=[],l=typeof(i==null?void 0:i.errors)<"u"?[]:void 0;for(let c=0,u=r.length;c1?pt(i,`Expected to match exactly a single predicate (matched ${a.join(", ")})`):(o=i==null?void 0:i.errors)===null||o===void 0||o.push(...l),!1}}),od=(r,e)=>Qt({test:(t,i)=>{var n,s;let o={value:t},a=typeof(i==null?void 0:i.coercions)<"u"?cc(o,"value"):void 0,l=typeof(i==null?void 0:i.coercions)<"u"?[]:void 0;if(!r(t,Object.assign(Object.assign({},i),{coercion:a,coercions:l})))return!1;let c=[];if(typeof l<"u")for(let[,u]of l)c.push(u());try{if(typeof(i==null?void 0:i.coercions)<"u"){if(o.value!==t){if(typeof(i==null?void 0:i.coercion)>"u")return pt(i,"Unbound coercion result");i.coercions.push([(n=i.p)!==null&&n!==void 0?n:".",i.coercion.bind(null,o.value)])}(s=i==null?void 0:i.coercions)===null||s===void 0||s.push(...l)}return e.every(u=>u(o.value,i))}finally{for(let u of c)u()}}}),vde=r=>Qt({test:(e,t)=>typeof e>"u"?!0:r(e,t)}),xde=r=>Qt({test:(e,t)=>e===null?!0:r(e,t)}),Pde=r=>Qt({test:(e,t)=>e.length>=r?!0:pt(t,`Expected to have a length of at least ${r} elements (got ${e.length})`)}),Dde=r=>Qt({test:(e,t)=>e.length<=r?!0:pt(t,`Expected to have a length of at most ${r} elements (got ${e.length})`)}),xH=r=>Qt({test:(e,t)=>e.length!==r?pt(t,`Expected to have a length of exactly ${r} elements (got ${e.length})`):!0}),kde=({map:r}={})=>Qt({test:(e,t)=>{let i=new Set,n=new Set;for(let s=0,o=e.length;sQt({test:(r,e)=>r<=0?!0:pt(e,`Expected to be negative (got ${r})`)}),Fde=()=>Qt({test:(r,e)=>r>=0?!0:pt(e,`Expected to be positive (got ${r})`)}),Nde=r=>Qt({test:(e,t)=>e>=r?!0:pt(t,`Expected to be at least ${r} (got ${e})`)}),Tde=r=>Qt({test:(e,t)=>e<=r?!0:pt(t,`Expected to be at most ${r} (got ${e})`)}),Lde=(r,e)=>Qt({test:(t,i)=>t>=r&&t<=e?!0:pt(i,`Expected to be in the [${r}; ${e}] range (got ${t})`)}),Mde=(r,e)=>Qt({test:(t,i)=>t>=r&&tQt({test:(e,t)=>e!==Math.round(e)?pt(t,`Expected to be an integer (got ${e})`):Number.isSafeInteger(e)?!0:pt(t,`Expected to be a safe integer (got ${e})`)}),ad=r=>Qt({test:(e,t)=>r.test(e)?!0:pt(t,`Expected to match the pattern ${r.toString()} (got ${Vr(e)})`)}),Kde=()=>Qt({test:(r,e)=>r!==r.toLowerCase()?pt(e,`Expected to be all-lowercase (got ${r})`):!0}),Ude=()=>Qt({test:(r,e)=>r!==r.toUpperCase()?pt(e,`Expected to be all-uppercase (got ${r})`):!0}),Hde=()=>Qt({test:(r,e)=>bH.test(r)?!0:pt(e,`Expected to be a valid UUID v4 (got ${Vr(r)})`)}),Gde=()=>Qt({test:(r,e)=>ov.test(r)?!1:pt(e,`Expected to be a valid ISO 8601 date string (got ${Vr(r)})`)}),Yde=({alpha:r=!1})=>Qt({test:(e,t)=>(r?yH.test(e):wH.test(e))?!0:pt(t,`Expected to be a valid hexadecimal color string (got ${Vr(e)})`)}),jde=()=>Qt({test:(r,e)=>BH.test(r)?!0:pt(e,`Expected to be a valid base 64 string (got ${Vr(r)})`)}),qde=(r=vH())=>Qt({test:(e,t)=>{let i;try{i=JSON.parse(e)}catch{return pt(t,`Expected to be a valid JSON string (got ${Vr(e)})`)}return r(i,t)}}),Jde=r=>{let e=new Set(r);return Qt({test:(t,i)=>{let n=new Set(Object.keys(t)),s=[];for(let o of e)n.has(o)||s.push(o);return s.length>0?pt(i,`Missing required ${kI(s.length,"property","properties")} ${s.map(o=>`"${o}"`).join(", ")}`):!0}})},Wde=r=>{let e=new Set(r);return Qt({test:(t,i)=>{let n=new Set(Object.keys(t)),s=[];for(let o of e)n.has(o)&&s.push(o);return s.length>0?pt(i,`Forbidden ${kI(s.length,"property","properties")} ${s.map(o=>`"${o}"`).join(", ")}`):!0}})},zde=r=>{let e=new Set(r);return Qt({test:(t,i)=>{let n=new Set(Object.keys(t)),s=[];for(let o of e)n.has(o)&&s.push(o);return s.length>1?pt(i,`Mutually exclusive properties ${s.map(o=>`"${o}"`).join(", ")}`):!0}})};(function(r){r.Forbids="Forbids",r.Requires="Requires"})(lc||(lc={}));Vde={[lc.Forbids]:{expect:!1,message:"forbids using"},[lc.Requires]:{expect:!0,message:"requires using"}},av=(r,e,t,{ignore:i=[]}={})=>{let n=new Set(i),s=new Set(t),o=Vde[e];return Qt({test:(a,l)=>{let c=new Set(Object.keys(a));if(!c.has(r)||n.has(a[r]))return!0;let u=[];for(let g of s)(c.has(g)&&!n.has(a[g]))!==o.expect&&u.push(g);return u.length>=1?pt(l,`Property "${r}" ${o.message} ${kI(u.length,"property","properties")} ${u.map(g=>`"${g}"`).join(", ")}`):!0}})}});var qH=w((A$e,jH)=>{"use strict";jH.exports=(r,...e)=>new Promise(t=>{t(r(...e))})});var Jg=w((l$e,pv)=>{"use strict";var gCe=qH(),JH=r=>{if(r<1)throw new TypeError("Expected `concurrency` to be a number from 1 and up");let e=[],t=0,i=()=>{t--,e.length>0&&e.shift()()},n=(a,l,...c)=>{t++;let u=gCe(a,...c);l(u),u.then(i,i)},s=(a,l,...c)=>{tnew Promise(c=>s(a,c,...l));return Object.defineProperties(o,{activeCount:{get:()=>t},pendingCount:{get:()=>e.length}}),o};pv.exports=JH;pv.exports.default=JH});var gd=w((u$e,WH)=>{var fCe="2.0.0",hCe=Number.MAX_SAFE_INTEGER||9007199254740991,pCe=16;WH.exports={SEMVER_SPEC_VERSION:fCe,MAX_LENGTH:256,MAX_SAFE_INTEGER:hCe,MAX_SAFE_COMPONENT_LENGTH:pCe}});var fd=w((g$e,zH)=>{var dCe=typeof process=="object"&&process.env&&process.env.NODE_DEBUG&&/\bsemver\b/i.test(process.env.NODE_DEBUG)?(...r)=>console.error("SEMVER",...r):()=>{};zH.exports=dCe});var uc=w((NA,VH)=>{var{MAX_SAFE_COMPONENT_LENGTH:dv}=gd(),CCe=fd();NA=VH.exports={};var mCe=NA.re=[],et=NA.src=[],tt=NA.t={},ECe=0,St=(r,e,t)=>{let i=ECe++;CCe(i,e),tt[r]=i,et[i]=e,mCe[i]=new RegExp(e,t?"g":void 0)};St("NUMERICIDENTIFIER","0|[1-9]\\d*");St("NUMERICIDENTIFIERLOOSE","[0-9]+");St("NONNUMERICIDENTIFIER","\\d*[a-zA-Z-][a-zA-Z0-9-]*");St("MAINVERSION",`(${et[tt.NUMERICIDENTIFIER]})\\.(${et[tt.NUMERICIDENTIFIER]})\\.(${et[tt.NUMERICIDENTIFIER]})`);St("MAINVERSIONLOOSE",`(${et[tt.NUMERICIDENTIFIERLOOSE]})\\.(${et[tt.NUMERICIDENTIFIERLOOSE]})\\.(${et[tt.NUMERICIDENTIFIERLOOSE]})`);St("PRERELEASEIDENTIFIER",`(?:${et[tt.NUMERICIDENTIFIER]}|${et[tt.NONNUMERICIDENTIFIER]})`);St("PRERELEASEIDENTIFIERLOOSE",`(?:${et[tt.NUMERICIDENTIFIERLOOSE]}|${et[tt.NONNUMERICIDENTIFIER]})`);St("PRERELEASE",`(?:-(${et[tt.PRERELEASEIDENTIFIER]}(?:\\.${et[tt.PRERELEASEIDENTIFIER]})*))`);St("PRERELEASELOOSE",`(?:-?(${et[tt.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${et[tt.PRERELEASEIDENTIFIERLOOSE]})*))`);St("BUILDIDENTIFIER","[0-9A-Za-z-]+");St("BUILD",`(?:\\+(${et[tt.BUILDIDENTIFIER]}(?:\\.${et[tt.BUILDIDENTIFIER]})*))`);St("FULLPLAIN",`v?${et[tt.MAINVERSION]}${et[tt.PRERELEASE]}?${et[tt.BUILD]}?`);St("FULL",`^${et[tt.FULLPLAIN]}$`);St("LOOSEPLAIN",`[v=\\s]*${et[tt.MAINVERSIONLOOSE]}${et[tt.PRERELEASELOOSE]}?${et[tt.BUILD]}?`);St("LOOSE",`^${et[tt.LOOSEPLAIN]}$`);St("GTLT","((?:<|>)?=?)");St("XRANGEIDENTIFIERLOOSE",`${et[tt.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`);St("XRANGEIDENTIFIER",`${et[tt.NUMERICIDENTIFIER]}|x|X|\\*`);St("XRANGEPLAIN",`[v=\\s]*(${et[tt.XRANGEIDENTIFIER]})(?:\\.(${et[tt.XRANGEIDENTIFIER]})(?:\\.(${et[tt.XRANGEIDENTIFIER]})(?:${et[tt.PRERELEASE]})?${et[tt.BUILD]}?)?)?`);St("XRANGEPLAINLOOSE",`[v=\\s]*(${et[tt.XRANGEIDENTIFIERLOOSE]})(?:\\.(${et[tt.XRANGEIDENTIFIERLOOSE]})(?:\\.(${et[tt.XRANGEIDENTIFIERLOOSE]})(?:${et[tt.PRERELEASELOOSE]})?${et[tt.BUILD]}?)?)?`);St("XRANGE",`^${et[tt.GTLT]}\\s*${et[tt.XRANGEPLAIN]}$`);St("XRANGELOOSE",`^${et[tt.GTLT]}\\s*${et[tt.XRANGEPLAINLOOSE]}$`);St("COERCE",`(^|[^\\d])(\\d{1,${dv}})(?:\\.(\\d{1,${dv}}))?(?:\\.(\\d{1,${dv}}))?(?:$|[^\\d])`);St("COERCERTL",et[tt.COERCE],!0);St("LONETILDE","(?:~>?)");St("TILDETRIM",`(\\s*)${et[tt.LONETILDE]}\\s+`,!0);NA.tildeTrimReplace="$1~";St("TILDE",`^${et[tt.LONETILDE]}${et[tt.XRANGEPLAIN]}$`);St("TILDELOOSE",`^${et[tt.LONETILDE]}${et[tt.XRANGEPLAINLOOSE]}$`);St("LONECARET","(?:\\^)");St("CARETTRIM",`(\\s*)${et[tt.LONECARET]}\\s+`,!0);NA.caretTrimReplace="$1^";St("CARET",`^${et[tt.LONECARET]}${et[tt.XRANGEPLAIN]}$`);St("CARETLOOSE",`^${et[tt.LONECARET]}${et[tt.XRANGEPLAINLOOSE]}$`);St("COMPARATORLOOSE",`^${et[tt.GTLT]}\\s*(${et[tt.LOOSEPLAIN]})$|^$`);St("COMPARATOR",`^${et[tt.GTLT]}\\s*(${et[tt.FULLPLAIN]})$|^$`);St("COMPARATORTRIM",`(\\s*)${et[tt.GTLT]}\\s*(${et[tt.LOOSEPLAIN]}|${et[tt.XRANGEPLAIN]})`,!0);NA.comparatorTrimReplace="$1$2$3";St("HYPHENRANGE",`^\\s*(${et[tt.XRANGEPLAIN]})\\s+-\\s+(${et[tt.XRANGEPLAIN]})\\s*$`);St("HYPHENRANGELOOSE",`^\\s*(${et[tt.XRANGEPLAINLOOSE]})\\s+-\\s+(${et[tt.XRANGEPLAINLOOSE]})\\s*$`);St("STAR","(<|>)?=?\\s*\\*");St("GTE0","^\\s*>=\\s*0.0.0\\s*$");St("GTE0PRE","^\\s*>=\\s*0.0.0-0\\s*$")});var hd=w((f$e,XH)=>{var ICe=["includePrerelease","loose","rtl"],yCe=r=>r?typeof r!="object"?{loose:!0}:ICe.filter(e=>r[e]).reduce((e,t)=>(e[t]=!0,e),{}):{};XH.exports=yCe});var MI=w((h$e,$H)=>{var ZH=/^[0-9]+$/,_H=(r,e)=>{let t=ZH.test(r),i=ZH.test(e);return t&&i&&(r=+r,e=+e),r===e?0:t&&!i?-1:i&&!t?1:r_H(e,r);$H.exports={compareIdentifiers:_H,rcompareIdentifiers:wCe}});var Li=w((p$e,iG)=>{var OI=fd(),{MAX_LENGTH:eG,MAX_SAFE_INTEGER:KI}=gd(),{re:tG,t:rG}=uc(),BCe=hd(),{compareIdentifiers:pd}=MI(),Yn=class{constructor(e,t){if(t=BCe(t),e instanceof Yn){if(e.loose===!!t.loose&&e.includePrerelease===!!t.includePrerelease)return e;e=e.version}else if(typeof e!="string")throw new TypeError(`Invalid Version: ${e}`);if(e.length>eG)throw new TypeError(`version is longer than ${eG} characters`);OI("SemVer",e,t),this.options=t,this.loose=!!t.loose,this.includePrerelease=!!t.includePrerelease;let i=e.trim().match(t.loose?tG[rG.LOOSE]:tG[rG.FULL]);if(!i)throw new TypeError(`Invalid Version: ${e}`);if(this.raw=e,this.major=+i[1],this.minor=+i[2],this.patch=+i[3],this.major>KI||this.major<0)throw new TypeError("Invalid major version");if(this.minor>KI||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>KI||this.patch<0)throw new TypeError("Invalid patch version");i[4]?this.prerelease=i[4].split(".").map(n=>{if(/^[0-9]+$/.test(n)){let s=+n;if(s>=0&&s=0;)typeof this.prerelease[i]=="number"&&(this.prerelease[i]++,i=-2);i===-1&&this.prerelease.push(0)}t&&(this.prerelease[0]===t?isNaN(this.prerelease[1])&&(this.prerelease=[t,0]):this.prerelease=[t,0]);break;default:throw new Error(`invalid increment argument: ${e}`)}return this.format(),this.raw=this.version,this}};iG.exports=Yn});var gc=w((d$e,aG)=>{var{MAX_LENGTH:bCe}=gd(),{re:nG,t:sG}=uc(),oG=Li(),QCe=hd(),SCe=(r,e)=>{if(e=QCe(e),r instanceof oG)return r;if(typeof r!="string"||r.length>bCe||!(e.loose?nG[sG.LOOSE]:nG[sG.FULL]).test(r))return null;try{return new oG(r,e)}catch{return null}};aG.exports=SCe});var lG=w((C$e,AG)=>{var vCe=gc(),xCe=(r,e)=>{let t=vCe(r,e);return t?t.version:null};AG.exports=xCe});var uG=w((m$e,cG)=>{var PCe=gc(),DCe=(r,e)=>{let t=PCe(r.trim().replace(/^[=v]+/,""),e);return t?t.version:null};cG.exports=DCe});var fG=w((E$e,gG)=>{var kCe=Li(),RCe=(r,e,t,i)=>{typeof t=="string"&&(i=t,t=void 0);try{return new kCe(r,t).inc(e,i).version}catch{return null}};gG.exports=RCe});var cs=w((I$e,pG)=>{var hG=Li(),FCe=(r,e,t)=>new hG(r,t).compare(new hG(e,t));pG.exports=FCe});var UI=w((y$e,dG)=>{var NCe=cs(),TCe=(r,e,t)=>NCe(r,e,t)===0;dG.exports=TCe});var EG=w((w$e,mG)=>{var CG=gc(),LCe=UI(),MCe=(r,e)=>{if(LCe(r,e))return null;{let t=CG(r),i=CG(e),n=t.prerelease.length||i.prerelease.length,s=n?"pre":"",o=n?"prerelease":"";for(let a in t)if((a==="major"||a==="minor"||a==="patch")&&t[a]!==i[a])return s+a;return o}};mG.exports=MCe});var yG=w((B$e,IG)=>{var OCe=Li(),KCe=(r,e)=>new OCe(r,e).major;IG.exports=KCe});var BG=w((b$e,wG)=>{var UCe=Li(),HCe=(r,e)=>new UCe(r,e).minor;wG.exports=HCe});var QG=w((Q$e,bG)=>{var GCe=Li(),YCe=(r,e)=>new GCe(r,e).patch;bG.exports=YCe});var vG=w((S$e,SG)=>{var jCe=gc(),qCe=(r,e)=>{let t=jCe(r,e);return t&&t.prerelease.length?t.prerelease:null};SG.exports=qCe});var PG=w((v$e,xG)=>{var JCe=cs(),WCe=(r,e,t)=>JCe(e,r,t);xG.exports=WCe});var kG=w((x$e,DG)=>{var zCe=cs(),VCe=(r,e)=>zCe(r,e,!0);DG.exports=VCe});var HI=w((P$e,FG)=>{var RG=Li(),XCe=(r,e,t)=>{let i=new RG(r,t),n=new RG(e,t);return i.compare(n)||i.compareBuild(n)};FG.exports=XCe});var TG=w((D$e,NG)=>{var ZCe=HI(),_Ce=(r,e)=>r.sort((t,i)=>ZCe(t,i,e));NG.exports=_Ce});var MG=w((k$e,LG)=>{var $Ce=HI(),eme=(r,e)=>r.sort((t,i)=>$Ce(i,t,e));LG.exports=eme});var dd=w((R$e,OG)=>{var tme=cs(),rme=(r,e,t)=>tme(r,e,t)>0;OG.exports=rme});var GI=w((F$e,KG)=>{var ime=cs(),nme=(r,e,t)=>ime(r,e,t)<0;KG.exports=nme});var Cv=w((N$e,UG)=>{var sme=cs(),ome=(r,e,t)=>sme(r,e,t)!==0;UG.exports=ome});var YI=w((T$e,HG)=>{var ame=cs(),Ame=(r,e,t)=>ame(r,e,t)>=0;HG.exports=Ame});var jI=w((L$e,GG)=>{var lme=cs(),cme=(r,e,t)=>lme(r,e,t)<=0;GG.exports=cme});var mv=w((M$e,YG)=>{var ume=UI(),gme=Cv(),fme=dd(),hme=YI(),pme=GI(),dme=jI(),Cme=(r,e,t,i)=>{switch(e){case"===":return typeof r=="object"&&(r=r.version),typeof t=="object"&&(t=t.version),r===t;case"!==":return typeof r=="object"&&(r=r.version),typeof t=="object"&&(t=t.version),r!==t;case"":case"=":case"==":return ume(r,t,i);case"!=":return gme(r,t,i);case">":return fme(r,t,i);case">=":return hme(r,t,i);case"<":return pme(r,t,i);case"<=":return dme(r,t,i);default:throw new TypeError(`Invalid operator: ${e}`)}};YG.exports=Cme});var qG=w((O$e,jG)=>{var mme=Li(),Eme=gc(),{re:qI,t:JI}=uc(),Ime=(r,e)=>{if(r instanceof mme)return r;if(typeof r=="number"&&(r=String(r)),typeof r!="string")return null;e=e||{};let t=null;if(!e.rtl)t=r.match(qI[JI.COERCE]);else{let i;for(;(i=qI[JI.COERCERTL].exec(r))&&(!t||t.index+t[0].length!==r.length);)(!t||i.index+i[0].length!==t.index+t[0].length)&&(t=i),qI[JI.COERCERTL].lastIndex=i.index+i[1].length+i[2].length;qI[JI.COERCERTL].lastIndex=-1}return t===null?null:Eme(`${t[2]}.${t[3]||"0"}.${t[4]||"0"}`,e)};jG.exports=Ime});var WG=w((K$e,JG)=>{"use strict";JG.exports=function(r){r.prototype[Symbol.iterator]=function*(){for(let e=this.head;e;e=e.next)yield e.value}}});var WI=w((U$e,zG)=>{"use strict";zG.exports=Ht;Ht.Node=fc;Ht.create=Ht;function Ht(r){var e=this;if(e instanceof Ht||(e=new Ht),e.tail=null,e.head=null,e.length=0,r&&typeof r.forEach=="function")r.forEach(function(n){e.push(n)});else if(arguments.length>0)for(var t=0,i=arguments.length;t1)t=e;else if(this.head)i=this.head.next,t=this.head.value;else throw new TypeError("Reduce of empty list with no initial value");for(var n=0;i!==null;n++)t=r(t,i.value,n),i=i.next;return t};Ht.prototype.reduceReverse=function(r,e){var t,i=this.tail;if(arguments.length>1)t=e;else if(this.tail)i=this.tail.prev,t=this.tail.value;else throw new TypeError("Reduce of empty list with no initial value");for(var n=this.length-1;i!==null;n--)t=r(t,i.value,n),i=i.prev;return t};Ht.prototype.toArray=function(){for(var r=new Array(this.length),e=0,t=this.head;t!==null;e++)r[e]=t.value,t=t.next;return r};Ht.prototype.toArrayReverse=function(){for(var r=new Array(this.length),e=0,t=this.tail;t!==null;e++)r[e]=t.value,t=t.prev;return r};Ht.prototype.slice=function(r,e){e=e||this.length,e<0&&(e+=this.length),r=r||0,r<0&&(r+=this.length);var t=new Ht;if(ethis.length&&(e=this.length);for(var i=0,n=this.head;n!==null&&ithis.length&&(e=this.length);for(var i=this.length,n=this.tail;n!==null&&i>e;i--)n=n.prev;for(;n!==null&&i>r;i--,n=n.prev)t.push(n.value);return t};Ht.prototype.splice=function(r,e,...t){r>this.length&&(r=this.length-1),r<0&&(r=this.length+r);for(var i=0,n=this.head;n!==null&&i{"use strict";var bme=WI(),hc=Symbol("max"),va=Symbol("length"),Wg=Symbol("lengthCalculator"),md=Symbol("allowStale"),pc=Symbol("maxAge"),Sa=Symbol("dispose"),VG=Symbol("noDisposeOnSet"),di=Symbol("lruList"),Zs=Symbol("cache"),ZG=Symbol("updateAgeOnGet"),Ev=()=>1,yv=class{constructor(e){if(typeof e=="number"&&(e={max:e}),e||(e={}),e.max&&(typeof e.max!="number"||e.max<0))throw new TypeError("max must be a non-negative number");let t=this[hc]=e.max||1/0,i=e.length||Ev;if(this[Wg]=typeof i!="function"?Ev:i,this[md]=e.stale||!1,e.maxAge&&typeof e.maxAge!="number")throw new TypeError("maxAge must be a number");this[pc]=e.maxAge||0,this[Sa]=e.dispose,this[VG]=e.noDisposeOnSet||!1,this[ZG]=e.updateAgeOnGet||!1,this.reset()}set max(e){if(typeof e!="number"||e<0)throw new TypeError("max must be a non-negative number");this[hc]=e||1/0,Cd(this)}get max(){return this[hc]}set allowStale(e){this[md]=!!e}get allowStale(){return this[md]}set maxAge(e){if(typeof e!="number")throw new TypeError("maxAge must be a non-negative number");this[pc]=e,Cd(this)}get maxAge(){return this[pc]}set lengthCalculator(e){typeof e!="function"&&(e=Ev),e!==this[Wg]&&(this[Wg]=e,this[va]=0,this[di].forEach(t=>{t.length=this[Wg](t.value,t.key),this[va]+=t.length})),Cd(this)}get lengthCalculator(){return this[Wg]}get length(){return this[va]}get itemCount(){return this[di].length}rforEach(e,t){t=t||this;for(let i=this[di].tail;i!==null;){let n=i.prev;XG(this,e,i,t),i=n}}forEach(e,t){t=t||this;for(let i=this[di].head;i!==null;){let n=i.next;XG(this,e,i,t),i=n}}keys(){return this[di].toArray().map(e=>e.key)}values(){return this[di].toArray().map(e=>e.value)}reset(){this[Sa]&&this[di]&&this[di].length&&this[di].forEach(e=>this[Sa](e.key,e.value)),this[Zs]=new Map,this[di]=new bme,this[va]=0}dump(){return this[di].map(e=>zI(this,e)?!1:{k:e.key,v:e.value,e:e.now+(e.maxAge||0)}).toArray().filter(e=>e)}dumpLru(){return this[di]}set(e,t,i){if(i=i||this[pc],i&&typeof i!="number")throw new TypeError("maxAge must be a number");let n=i?Date.now():0,s=this[Wg](t,e);if(this[Zs].has(e)){if(s>this[hc])return zg(this,this[Zs].get(e)),!1;let l=this[Zs].get(e).value;return this[Sa]&&(this[VG]||this[Sa](e,l.value)),l.now=n,l.maxAge=i,l.value=t,this[va]+=s-l.length,l.length=s,this.get(e),Cd(this),!0}let o=new wv(e,t,s,n,i);return o.length>this[hc]?(this[Sa]&&this[Sa](e,t),!1):(this[va]+=o.length,this[di].unshift(o),this[Zs].set(e,this[di].head),Cd(this),!0)}has(e){if(!this[Zs].has(e))return!1;let t=this[Zs].get(e).value;return!zI(this,t)}get(e){return Iv(this,e,!0)}peek(e){return Iv(this,e,!1)}pop(){let e=this[di].tail;return e?(zg(this,e),e.value):null}del(e){zg(this,this[Zs].get(e))}load(e){this.reset();let t=Date.now();for(let i=e.length-1;i>=0;i--){let n=e[i],s=n.e||0;if(s===0)this.set(n.k,n.v);else{let o=s-t;o>0&&this.set(n.k,n.v,o)}}}prune(){this[Zs].forEach((e,t)=>Iv(this,t,!1))}},Iv=(r,e,t)=>{let i=r[Zs].get(e);if(i){let n=i.value;if(zI(r,n)){if(zg(r,i),!r[md])return}else t&&(r[ZG]&&(i.value.now=Date.now()),r[di].unshiftNode(i));return n.value}},zI=(r,e)=>{if(!e||!e.maxAge&&!r[pc])return!1;let t=Date.now()-e.now;return e.maxAge?t>e.maxAge:r[pc]&&t>r[pc]},Cd=r=>{if(r[va]>r[hc])for(let e=r[di].tail;r[va]>r[hc]&&e!==null;){let t=e.prev;zg(r,e),e=t}},zg=(r,e)=>{if(e){let t=e.value;r[Sa]&&r[Sa](t.key,t.value),r[va]-=t.length,r[Zs].delete(t.key),r[di].removeNode(e)}},wv=class{constructor(e,t,i,n,s){this.key=e,this.value=t,this.length=i,this.now=n,this.maxAge=s||0}},XG=(r,e,t,i)=>{let n=t.value;zI(r,n)&&(zg(r,t),r[md]||(n=void 0)),n&&e.call(i,n.value,n.key,r)};_G.exports=yv});var us=w((G$e,iY)=>{var dc=class{constructor(e,t){if(t=Sme(t),e instanceof dc)return e.loose===!!t.loose&&e.includePrerelease===!!t.includePrerelease?e:new dc(e.raw,t);if(e instanceof Bv)return this.raw=e.value,this.set=[[e]],this.format(),this;if(this.options=t,this.loose=!!t.loose,this.includePrerelease=!!t.includePrerelease,this.raw=e,this.set=e.split(/\s*\|\|\s*/).map(i=>this.parseRange(i.trim())).filter(i=>i.length),!this.set.length)throw new TypeError(`Invalid SemVer Range: ${e}`);if(this.set.length>1){let i=this.set[0];if(this.set=this.set.filter(n=>!tY(n[0])),this.set.length===0)this.set=[i];else if(this.set.length>1){for(let n of this.set)if(n.length===1&&kme(n[0])){this.set=[n];break}}}this.format()}format(){return this.range=this.set.map(e=>e.join(" ").trim()).join("||").trim(),this.range}toString(){return this.range}parseRange(e){e=e.trim();let i=`parseRange:${Object.keys(this.options).join(",")}:${e}`,n=eY.get(i);if(n)return n;let s=this.options.loose,o=s?Mi[bi.HYPHENRANGELOOSE]:Mi[bi.HYPHENRANGE];e=e.replace(o,Hme(this.options.includePrerelease)),Hr("hyphen replace",e),e=e.replace(Mi[bi.COMPARATORTRIM],xme),Hr("comparator trim",e,Mi[bi.COMPARATORTRIM]),e=e.replace(Mi[bi.TILDETRIM],Pme),e=e.replace(Mi[bi.CARETTRIM],Dme),e=e.split(/\s+/).join(" ");let a=s?Mi[bi.COMPARATORLOOSE]:Mi[bi.COMPARATOR],l=e.split(" ").map(f=>Rme(f,this.options)).join(" ").split(/\s+/).map(f=>Ume(f,this.options)).filter(this.options.loose?f=>!!f.match(a):()=>!0).map(f=>new Bv(f,this.options)),c=l.length,u=new Map;for(let f of l){if(tY(f))return[f];u.set(f.value,f)}u.size>1&&u.has("")&&u.delete("");let g=[...u.values()];return eY.set(i,g),g}intersects(e,t){if(!(e instanceof dc))throw new TypeError("a Range is required");return this.set.some(i=>rY(i,t)&&e.set.some(n=>rY(n,t)&&i.every(s=>n.every(o=>s.intersects(o,t)))))}test(e){if(!e)return!1;if(typeof e=="string")try{e=new vme(e,this.options)}catch{return!1}for(let t=0;tr.value==="<0.0.0-0",kme=r=>r.value==="",rY=(r,e)=>{let t=!0,i=r.slice(),n=i.pop();for(;t&&i.length;)t=i.every(s=>n.intersects(s,e)),n=i.pop();return t},Rme=(r,e)=>(Hr("comp",r,e),r=Tme(r,e),Hr("caret",r),r=Fme(r,e),Hr("tildes",r),r=Mme(r,e),Hr("xrange",r),r=Kme(r,e),Hr("stars",r),r),$i=r=>!r||r.toLowerCase()==="x"||r==="*",Fme=(r,e)=>r.trim().split(/\s+/).map(t=>Nme(t,e)).join(" "),Nme=(r,e)=>{let t=e.loose?Mi[bi.TILDELOOSE]:Mi[bi.TILDE];return r.replace(t,(i,n,s,o,a)=>{Hr("tilde",r,i,n,s,o,a);let l;return $i(n)?l="":$i(s)?l=`>=${n}.0.0 <${+n+1}.0.0-0`:$i(o)?l=`>=${n}.${s}.0 <${n}.${+s+1}.0-0`:a?(Hr("replaceTilde pr",a),l=`>=${n}.${s}.${o}-${a} <${n}.${+s+1}.0-0`):l=`>=${n}.${s}.${o} <${n}.${+s+1}.0-0`,Hr("tilde return",l),l})},Tme=(r,e)=>r.trim().split(/\s+/).map(t=>Lme(t,e)).join(" "),Lme=(r,e)=>{Hr("caret",r,e);let t=e.loose?Mi[bi.CARETLOOSE]:Mi[bi.CARET],i=e.includePrerelease?"-0":"";return r.replace(t,(n,s,o,a,l)=>{Hr("caret",r,n,s,o,a,l);let c;return $i(s)?c="":$i(o)?c=`>=${s}.0.0${i} <${+s+1}.0.0-0`:$i(a)?s==="0"?c=`>=${s}.${o}.0${i} <${s}.${+o+1}.0-0`:c=`>=${s}.${o}.0${i} <${+s+1}.0.0-0`:l?(Hr("replaceCaret pr",l),s==="0"?o==="0"?c=`>=${s}.${o}.${a}-${l} <${s}.${o}.${+a+1}-0`:c=`>=${s}.${o}.${a}-${l} <${s}.${+o+1}.0-0`:c=`>=${s}.${o}.${a}-${l} <${+s+1}.0.0-0`):(Hr("no pr"),s==="0"?o==="0"?c=`>=${s}.${o}.${a}${i} <${s}.${o}.${+a+1}-0`:c=`>=${s}.${o}.${a}${i} <${s}.${+o+1}.0-0`:c=`>=${s}.${o}.${a} <${+s+1}.0.0-0`),Hr("caret return",c),c})},Mme=(r,e)=>(Hr("replaceXRanges",r,e),r.split(/\s+/).map(t=>Ome(t,e)).join(" ")),Ome=(r,e)=>{r=r.trim();let t=e.loose?Mi[bi.XRANGELOOSE]:Mi[bi.XRANGE];return r.replace(t,(i,n,s,o,a,l)=>{Hr("xRange",r,i,n,s,o,a,l);let c=$i(s),u=c||$i(o),g=u||$i(a),f=g;return n==="="&&f&&(n=""),l=e.includePrerelease?"-0":"",c?n===">"||n==="<"?i="<0.0.0-0":i="*":n&&f?(u&&(o=0),a=0,n===">"?(n=">=",u?(s=+s+1,o=0,a=0):(o=+o+1,a=0)):n==="<="&&(n="<",u?s=+s+1:o=+o+1),n==="<"&&(l="-0"),i=`${n+s}.${o}.${a}${l}`):u?i=`>=${s}.0.0${l} <${+s+1}.0.0-0`:g&&(i=`>=${s}.${o}.0${l} <${s}.${+o+1}.0-0`),Hr("xRange return",i),i})},Kme=(r,e)=>(Hr("replaceStars",r,e),r.trim().replace(Mi[bi.STAR],"")),Ume=(r,e)=>(Hr("replaceGTE0",r,e),r.trim().replace(Mi[e.includePrerelease?bi.GTE0PRE:bi.GTE0],"")),Hme=r=>(e,t,i,n,s,o,a,l,c,u,g,f,h)=>($i(i)?t="":$i(n)?t=`>=${i}.0.0${r?"-0":""}`:$i(s)?t=`>=${i}.${n}.0${r?"-0":""}`:o?t=`>=${t}`:t=`>=${t}${r?"-0":""}`,$i(c)?l="":$i(u)?l=`<${+c+1}.0.0-0`:$i(g)?l=`<${c}.${+u+1}.0-0`:f?l=`<=${c}.${u}.${g}-${f}`:r?l=`<${c}.${u}.${+g+1}-0`:l=`<=${l}`,`${t} ${l}`.trim()),Gme=(r,e,t)=>{for(let i=0;i0){let n=r[i].semver;if(n.major===e.major&&n.minor===e.minor&&n.patch===e.patch)return!0}return!1}return!0}});var Ed=w((Y$e,AY)=>{var Id=Symbol("SemVer ANY"),Vg=class{static get ANY(){return Id}constructor(e,t){if(t=Yme(t),e instanceof Vg){if(e.loose===!!t.loose)return e;e=e.value}Qv("comparator",e,t),this.options=t,this.loose=!!t.loose,this.parse(e),this.semver===Id?this.value="":this.value=this.operator+this.semver.version,Qv("comp",this)}parse(e){let t=this.options.loose?nY[sY.COMPARATORLOOSE]:nY[sY.COMPARATOR],i=e.match(t);if(!i)throw new TypeError(`Invalid comparator: ${e}`);this.operator=i[1]!==void 0?i[1]:"",this.operator==="="&&(this.operator=""),i[2]?this.semver=new oY(i[2],this.options.loose):this.semver=Id}toString(){return this.value}test(e){if(Qv("Comparator.test",e,this.options.loose),this.semver===Id||e===Id)return!0;if(typeof e=="string")try{e=new oY(e,this.options)}catch{return!1}return bv(e,this.operator,this.semver,this.options)}intersects(e,t){if(!(e instanceof Vg))throw new TypeError("a Comparator is required");if((!t||typeof t!="object")&&(t={loose:!!t,includePrerelease:!1}),this.operator==="")return this.value===""?!0:new aY(e.value,t).test(this.value);if(e.operator==="")return e.value===""?!0:new aY(this.value,t).test(e.semver);let i=(this.operator===">="||this.operator===">")&&(e.operator===">="||e.operator===">"),n=(this.operator==="<="||this.operator==="<")&&(e.operator==="<="||e.operator==="<"),s=this.semver.version===e.semver.version,o=(this.operator===">="||this.operator==="<=")&&(e.operator===">="||e.operator==="<="),a=bv(this.semver,"<",e.semver,t)&&(this.operator===">="||this.operator===">")&&(e.operator==="<="||e.operator==="<"),l=bv(this.semver,">",e.semver,t)&&(this.operator==="<="||this.operator==="<")&&(e.operator===">="||e.operator===">");return i||n||s&&o||a||l}};AY.exports=Vg;var Yme=hd(),{re:nY,t:sY}=uc(),bv=mv(),Qv=fd(),oY=Li(),aY=us()});var yd=w((j$e,lY)=>{var jme=us(),qme=(r,e,t)=>{try{e=new jme(e,t)}catch{return!1}return e.test(r)};lY.exports=qme});var uY=w((q$e,cY)=>{var Jme=us(),Wme=(r,e)=>new Jme(r,e).set.map(t=>t.map(i=>i.value).join(" ").trim().split(" "));cY.exports=Wme});var fY=w((J$e,gY)=>{var zme=Li(),Vme=us(),Xme=(r,e,t)=>{let i=null,n=null,s=null;try{s=new Vme(e,t)}catch{return null}return r.forEach(o=>{s.test(o)&&(!i||n.compare(o)===-1)&&(i=o,n=new zme(i,t))}),i};gY.exports=Xme});var pY=w((W$e,hY)=>{var Zme=Li(),_me=us(),$me=(r,e,t)=>{let i=null,n=null,s=null;try{s=new _me(e,t)}catch{return null}return r.forEach(o=>{s.test(o)&&(!i||n.compare(o)===1)&&(i=o,n=new Zme(i,t))}),i};hY.exports=$me});var mY=w((z$e,CY)=>{var Sv=Li(),eEe=us(),dY=dd(),tEe=(r,e)=>{r=new eEe(r,e);let t=new Sv("0.0.0");if(r.test(t)||(t=new Sv("0.0.0-0"),r.test(t)))return t;t=null;for(let i=0;i{let a=new Sv(o.semver.version);switch(o.operator){case">":a.prerelease.length===0?a.patch++:a.prerelease.push(0),a.raw=a.format();case"":case">=":(!s||dY(a,s))&&(s=a);break;case"<":case"<=":break;default:throw new Error(`Unexpected operation: ${o.operator}`)}}),s&&(!t||dY(t,s))&&(t=s)}return t&&r.test(t)?t:null};CY.exports=tEe});var IY=w((V$e,EY)=>{var rEe=us(),iEe=(r,e)=>{try{return new rEe(r,e).range||"*"}catch{return null}};EY.exports=iEe});var VI=w((X$e,bY)=>{var nEe=Li(),BY=Ed(),{ANY:sEe}=BY,oEe=us(),aEe=yd(),yY=dd(),wY=GI(),AEe=jI(),lEe=YI(),cEe=(r,e,t,i)=>{r=new nEe(r,i),e=new oEe(e,i);let n,s,o,a,l;switch(t){case">":n=yY,s=AEe,o=wY,a=">",l=">=";break;case"<":n=wY,s=lEe,o=yY,a="<",l="<=";break;default:throw new TypeError('Must provide a hilo val of "<" or ">"')}if(aEe(r,e,i))return!1;for(let c=0;c{h.semver===sEe&&(h=new BY(">=0.0.0")),g=g||h,f=f||h,n(h.semver,g.semver,i)?g=h:o(h.semver,f.semver,i)&&(f=h)}),g.operator===a||g.operator===l||(!f.operator||f.operator===a)&&s(r,f.semver))return!1;if(f.operator===l&&o(r,f.semver))return!1}return!0};bY.exports=cEe});var SY=w((Z$e,QY)=>{var uEe=VI(),gEe=(r,e,t)=>uEe(r,e,">",t);QY.exports=gEe});var xY=w((_$e,vY)=>{var fEe=VI(),hEe=(r,e,t)=>fEe(r,e,"<",t);vY.exports=hEe});var kY=w(($$e,DY)=>{var PY=us(),pEe=(r,e,t)=>(r=new PY(r,t),e=new PY(e,t),r.intersects(e));DY.exports=pEe});var FY=w((eet,RY)=>{var dEe=yd(),CEe=cs();RY.exports=(r,e,t)=>{let i=[],n=null,s=null,o=r.sort((u,g)=>CEe(u,g,t));for(let u of o)dEe(u,e,t)?(s=u,n||(n=u)):(s&&i.push([n,s]),s=null,n=null);n&&i.push([n,null]);let a=[];for(let[u,g]of i)u===g?a.push(u):!g&&u===o[0]?a.push("*"):g?u===o[0]?a.push(`<=${g}`):a.push(`${u} - ${g}`):a.push(`>=${u}`);let l=a.join(" || "),c=typeof e.raw=="string"?e.raw:String(e);return l.length{var NY=us(),XI=Ed(),{ANY:vv}=XI,wd=yd(),xv=cs(),mEe=(r,e,t={})=>{if(r===e)return!0;r=new NY(r,t),e=new NY(e,t);let i=!1;e:for(let n of r.set){for(let s of e.set){let o=EEe(n,s,t);if(i=i||o!==null,o)continue e}if(i)return!1}return!0},EEe=(r,e,t)=>{if(r===e)return!0;if(r.length===1&&r[0].semver===vv){if(e.length===1&&e[0].semver===vv)return!0;t.includePrerelease?r=[new XI(">=0.0.0-0")]:r=[new XI(">=0.0.0")]}if(e.length===1&&e[0].semver===vv){if(t.includePrerelease)return!0;e=[new XI(">=0.0.0")]}let i=new Set,n,s;for(let h of r)h.operator===">"||h.operator===">="?n=TY(n,h,t):h.operator==="<"||h.operator==="<="?s=LY(s,h,t):i.add(h.semver);if(i.size>1)return null;let o;if(n&&s){if(o=xv(n.semver,s.semver,t),o>0)return null;if(o===0&&(n.operator!==">="||s.operator!=="<="))return null}for(let h of i){if(n&&!wd(h,String(n),t)||s&&!wd(h,String(s),t))return null;for(let p of e)if(!wd(h,String(p),t))return!1;return!0}let a,l,c,u,g=s&&!t.includePrerelease&&s.semver.prerelease.length?s.semver:!1,f=n&&!t.includePrerelease&&n.semver.prerelease.length?n.semver:!1;g&&g.prerelease.length===1&&s.operator==="<"&&g.prerelease[0]===0&&(g=!1);for(let h of e){if(u=u||h.operator===">"||h.operator===">=",c=c||h.operator==="<"||h.operator==="<=",n){if(f&&h.semver.prerelease&&h.semver.prerelease.length&&h.semver.major===f.major&&h.semver.minor===f.minor&&h.semver.patch===f.patch&&(f=!1),h.operator===">"||h.operator===">="){if(a=TY(n,h,t),a===h&&a!==n)return!1}else if(n.operator===">="&&!wd(n.semver,String(h),t))return!1}if(s){if(g&&h.semver.prerelease&&h.semver.prerelease.length&&h.semver.major===g.major&&h.semver.minor===g.minor&&h.semver.patch===g.patch&&(g=!1),h.operator==="<"||h.operator==="<="){if(l=LY(s,h,t),l===h&&l!==s)return!1}else if(s.operator==="<="&&!wd(s.semver,String(h),t))return!1}if(!h.operator&&(s||n)&&o!==0)return!1}return!(n&&c&&!s&&o!==0||s&&u&&!n&&o!==0||f||g)},TY=(r,e,t)=>{if(!r)return e;let i=xv(r.semver,e.semver,t);return i>0?r:i<0||e.operator===">"&&r.operator===">="?e:r},LY=(r,e,t)=>{if(!r)return e;let i=xv(r.semver,e.semver,t);return i<0?r:i>0||e.operator==="<"&&r.operator==="<="?e:r};MY.exports=mEe});var Xr=w((ret,KY)=>{var Pv=uc();KY.exports={re:Pv.re,src:Pv.src,tokens:Pv.t,SEMVER_SPEC_VERSION:gd().SEMVER_SPEC_VERSION,SemVer:Li(),compareIdentifiers:MI().compareIdentifiers,rcompareIdentifiers:MI().rcompareIdentifiers,parse:gc(),valid:lG(),clean:uG(),inc:fG(),diff:EG(),major:yG(),minor:BG(),patch:QG(),prerelease:vG(),compare:cs(),rcompare:PG(),compareLoose:kG(),compareBuild:HI(),sort:TG(),rsort:MG(),gt:dd(),lt:GI(),eq:UI(),neq:Cv(),gte:YI(),lte:jI(),cmp:mv(),coerce:qG(),Comparator:Ed(),Range:us(),satisfies:yd(),toComparators:uY(),maxSatisfying:fY(),minSatisfying:pY(),minVersion:mY(),validRange:IY(),outside:VI(),gtr:SY(),ltr:xY(),intersects:kY(),simplifyRange:FY(),subset:OY()}});var Dv=w(ZI=>{"use strict";Object.defineProperty(ZI,"__esModule",{value:!0});ZI.VERSION=void 0;ZI.VERSION="9.1.0"});var Gt=w((exports,module)=>{"use strict";var __spreadArray=exports&&exports.__spreadArray||function(r,e,t){if(t||arguments.length===2)for(var i=0,n=e.length,s;i{(function(r,e){typeof define=="function"&&define.amd?define([],e):typeof _I=="object"&&_I.exports?_I.exports=e():r.regexpToAst=e()})(typeof self<"u"?self:UY,function(){function r(){}r.prototype.saveState=function(){return{idx:this.idx,input:this.input,groupIdx:this.groupIdx}},r.prototype.restoreState=function(p){this.idx=p.idx,this.input=p.input,this.groupIdx=p.groupIdx},r.prototype.pattern=function(p){this.idx=0,this.input=p,this.groupIdx=0,this.consumeChar("/");var C=this.disjunction();this.consumeChar("/");for(var y={type:"Flags",loc:{begin:this.idx,end:p.length},global:!1,ignoreCase:!1,multiLine:!1,unicode:!1,sticky:!1};this.isRegExpFlag();)switch(this.popChar()){case"g":o(y,"global");break;case"i":o(y,"ignoreCase");break;case"m":o(y,"multiLine");break;case"u":o(y,"unicode");break;case"y":o(y,"sticky");break}if(this.idx!==this.input.length)throw Error("Redundant input: "+this.input.substring(this.idx));return{type:"Pattern",flags:y,value:C,loc:this.loc(0)}},r.prototype.disjunction=function(){var p=[],C=this.idx;for(p.push(this.alternative());this.peekChar()==="|";)this.consumeChar("|"),p.push(this.alternative());return{type:"Disjunction",value:p,loc:this.loc(C)}},r.prototype.alternative=function(){for(var p=[],C=this.idx;this.isTerm();)p.push(this.term());return{type:"Alternative",value:p,loc:this.loc(C)}},r.prototype.term=function(){return this.isAssertion()?this.assertion():this.atom()},r.prototype.assertion=function(){var p=this.idx;switch(this.popChar()){case"^":return{type:"StartAnchor",loc:this.loc(p)};case"$":return{type:"EndAnchor",loc:this.loc(p)};case"\\":switch(this.popChar()){case"b":return{type:"WordBoundary",loc:this.loc(p)};case"B":return{type:"NonWordBoundary",loc:this.loc(p)}}throw Error("Invalid Assertion Escape");case"(":this.consumeChar("?");var C;switch(this.popChar()){case"=":C="Lookahead";break;case"!":C="NegativeLookahead";break}a(C);var y=this.disjunction();return this.consumeChar(")"),{type:C,value:y,loc:this.loc(p)}}l()},r.prototype.quantifier=function(p){var C,y=this.idx;switch(this.popChar()){case"*":C={atLeast:0,atMost:1/0};break;case"+":C={atLeast:1,atMost:1/0};break;case"?":C={atLeast:0,atMost:1};break;case"{":var B=this.integerIncludingZero();switch(this.popChar()){case"}":C={atLeast:B,atMost:B};break;case",":var v;this.isDigit()?(v=this.integerIncludingZero(),C={atLeast:B,atMost:v}):C={atLeast:B,atMost:1/0},this.consumeChar("}");break}if(p===!0&&C===void 0)return;a(C);break}if(!(p===!0&&C===void 0))return a(C),this.peekChar(0)==="?"?(this.consumeChar("?"),C.greedy=!1):C.greedy=!0,C.type="Quantifier",C.loc=this.loc(y),C},r.prototype.atom=function(){var p,C=this.idx;switch(this.peekChar()){case".":p=this.dotAll();break;case"\\":p=this.atomEscape();break;case"[":p=this.characterClass();break;case"(":p=this.group();break}return p===void 0&&this.isPatternCharacter()&&(p=this.patternCharacter()),a(p),p.loc=this.loc(C),this.isQuantifier()&&(p.quantifier=this.quantifier()),p},r.prototype.dotAll=function(){return this.consumeChar("."),{type:"Set",complement:!0,value:[n(` +`),n("\r"),n("\u2028"),n("\u2029")]}},r.prototype.atomEscape=function(){switch(this.consumeChar("\\"),this.peekChar()){case"1":case"2":case"3":case"4":case"5":case"6":case"7":case"8":case"9":return this.decimalEscapeAtom();case"d":case"D":case"s":case"S":case"w":case"W":return this.characterClassEscape();case"f":case"n":case"r":case"t":case"v":return this.controlEscapeAtom();case"c":return this.controlLetterEscapeAtom();case"0":return this.nulCharacterAtom();case"x":return this.hexEscapeSequenceAtom();case"u":return this.regExpUnicodeEscapeSequenceAtom();default:return this.identityEscapeAtom()}},r.prototype.decimalEscapeAtom=function(){var p=this.positiveInteger();return{type:"GroupBackReference",value:p}},r.prototype.characterClassEscape=function(){var p,C=!1;switch(this.popChar()){case"d":p=u;break;case"D":p=u,C=!0;break;case"s":p=f;break;case"S":p=f,C=!0;break;case"w":p=g;break;case"W":p=g,C=!0;break}return a(p),{type:"Set",value:p,complement:C}},r.prototype.controlEscapeAtom=function(){var p;switch(this.popChar()){case"f":p=n("\f");break;case"n":p=n(` +`);break;case"r":p=n("\r");break;case"t":p=n(" ");break;case"v":p=n("\v");break}return a(p),{type:"Character",value:p}},r.prototype.controlLetterEscapeAtom=function(){this.consumeChar("c");var p=this.popChar();if(/[a-zA-Z]/.test(p)===!1)throw Error("Invalid ");var C=p.toUpperCase().charCodeAt(0)-64;return{type:"Character",value:C}},r.prototype.nulCharacterAtom=function(){return this.consumeChar("0"),{type:"Character",value:n("\0")}},r.prototype.hexEscapeSequenceAtom=function(){return this.consumeChar("x"),this.parseHexDigits(2)},r.prototype.regExpUnicodeEscapeSequenceAtom=function(){return this.consumeChar("u"),this.parseHexDigits(4)},r.prototype.identityEscapeAtom=function(){var p=this.popChar();return{type:"Character",value:n(p)}},r.prototype.classPatternCharacterAtom=function(){switch(this.peekChar()){case` +`:case"\r":case"\u2028":case"\u2029":case"\\":case"]":throw Error("TBD");default:var p=this.popChar();return{type:"Character",value:n(p)}}},r.prototype.characterClass=function(){var p=[],C=!1;for(this.consumeChar("["),this.peekChar(0)==="^"&&(this.consumeChar("^"),C=!0);this.isClassAtom();){var y=this.classAtom(),B=y.type==="Character";if(B&&this.isRangeDash()){this.consumeChar("-");var v=this.classAtom(),D=v.type==="Character";if(D){if(v.value=this.input.length)throw Error("Unexpected end of input");this.idx++},r.prototype.loc=function(p){return{begin:p,end:this.idx}};var e=/[0-9a-fA-F]/,t=/[0-9]/,i=/[1-9]/;function n(p){return p.charCodeAt(0)}function s(p,C){p.length!==void 0?p.forEach(function(y){C.push(y)}):C.push(p)}function o(p,C){if(p[C]===!0)throw"duplicate flag "+C;p[C]=!0}function a(p){if(p===void 0)throw Error("Internal Error - Should never get here!")}function l(){throw Error("Internal Error - Should never get here!")}var c,u=[];for(c=n("0");c<=n("9");c++)u.push(c);var g=[n("_")].concat(u);for(c=n("a");c<=n("z");c++)g.push(c);for(c=n("A");c<=n("Z");c++)g.push(c);var f=[n(" "),n("\f"),n(` +`),n("\r"),n(" "),n("\v"),n(" "),n("\xA0"),n("\u1680"),n("\u2000"),n("\u2001"),n("\u2002"),n("\u2003"),n("\u2004"),n("\u2005"),n("\u2006"),n("\u2007"),n("\u2008"),n("\u2009"),n("\u200A"),n("\u2028"),n("\u2029"),n("\u202F"),n("\u205F"),n("\u3000"),n("\uFEFF")];function h(){}return h.prototype.visitChildren=function(p){for(var C in p){var y=p[C];p.hasOwnProperty(C)&&(y.type!==void 0?this.visit(y):Array.isArray(y)&&y.forEach(function(B){this.visit(B)},this))}},h.prototype.visit=function(p){switch(p.type){case"Pattern":this.visitPattern(p);break;case"Flags":this.visitFlags(p);break;case"Disjunction":this.visitDisjunction(p);break;case"Alternative":this.visitAlternative(p);break;case"StartAnchor":this.visitStartAnchor(p);break;case"EndAnchor":this.visitEndAnchor(p);break;case"WordBoundary":this.visitWordBoundary(p);break;case"NonWordBoundary":this.visitNonWordBoundary(p);break;case"Lookahead":this.visitLookahead(p);break;case"NegativeLookahead":this.visitNegativeLookahead(p);break;case"Character":this.visitCharacter(p);break;case"Set":this.visitSet(p);break;case"Group":this.visitGroup(p);break;case"GroupBackReference":this.visitGroupBackReference(p);break;case"Quantifier":this.visitQuantifier(p);break}this.visitChildren(p)},h.prototype.visitPattern=function(p){},h.prototype.visitFlags=function(p){},h.prototype.visitDisjunction=function(p){},h.prototype.visitAlternative=function(p){},h.prototype.visitStartAnchor=function(p){},h.prototype.visitEndAnchor=function(p){},h.prototype.visitWordBoundary=function(p){},h.prototype.visitNonWordBoundary=function(p){},h.prototype.visitLookahead=function(p){},h.prototype.visitNegativeLookahead=function(p){},h.prototype.visitCharacter=function(p){},h.prototype.visitSet=function(p){},h.prototype.visitGroup=function(p){},h.prototype.visitGroupBackReference=function(p){},h.prototype.visitQuantifier=function(p){},{RegExpParser:r,BaseRegExpVisitor:h,VERSION:"0.5.0"}})});var ty=w(Xg=>{"use strict";Object.defineProperty(Xg,"__esModule",{value:!0});Xg.clearRegExpParserCache=Xg.getRegExpAst=void 0;var IEe=$I(),ey={},yEe=new IEe.RegExpParser;function wEe(r){var e=r.toString();if(ey.hasOwnProperty(e))return ey[e];var t=yEe.pattern(e);return ey[e]=t,t}Xg.getRegExpAst=wEe;function BEe(){ey={}}Xg.clearRegExpParserCache=BEe});var qY=w(Cn=>{"use strict";var bEe=Cn&&Cn.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(Cn,"__esModule",{value:!0});Cn.canMatchCharCode=Cn.firstCharOptimizedIndices=Cn.getOptimizedStartCodesIndices=Cn.failedOptimizationPrefixMsg=void 0;var GY=$I(),gs=Gt(),YY=ty(),xa=Rv(),jY="Complement Sets are not supported for first char optimization";Cn.failedOptimizationPrefixMsg=`Unable to use "first char" lexer optimizations: +`;function QEe(r,e){e===void 0&&(e=!1);try{var t=(0,YY.getRegExpAst)(r),i=iy(t.value,{},t.flags.ignoreCase);return i}catch(s){if(s.message===jY)e&&(0,gs.PRINT_WARNING)(""+Cn.failedOptimizationPrefixMsg+(" Unable to optimize: < "+r.toString()+` > +`)+` Complement Sets cannot be automatically optimized. + This will disable the lexer's first char optimizations. + See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#COMPLEMENT for details.`);else{var n="";e&&(n=` + This will disable the lexer's first char optimizations. + See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#REGEXP_PARSING for details.`),(0,gs.PRINT_ERROR)(Cn.failedOptimizationPrefixMsg+` +`+(" Failed parsing: < "+r.toString()+` > +`)+(" Using the regexp-to-ast library version: "+GY.VERSION+` +`)+" Please open an issue at: https://github.com/bd82/regexp-to-ast/issues"+n)}}return[]}Cn.getOptimizedStartCodesIndices=QEe;function iy(r,e,t){switch(r.type){case"Disjunction":for(var i=0;i=xa.minOptimizationVal)for(var f=u.from>=xa.minOptimizationVal?u.from:xa.minOptimizationVal,h=u.to,p=(0,xa.charCodeToOptimizedIndex)(f),C=(0,xa.charCodeToOptimizedIndex)(h),y=p;y<=C;y++)e[y]=y}}});break;case"Group":iy(o.value,e,t);break;default:throw Error("Non Exhaustive Match")}var a=o.quantifier!==void 0&&o.quantifier.atLeast===0;if(o.type==="Group"&&kv(o)===!1||o.type!=="Group"&&a===!1)break}break;default:throw Error("non exhaustive match!")}return(0,gs.values)(e)}Cn.firstCharOptimizedIndices=iy;function ry(r,e,t){var i=(0,xa.charCodeToOptimizedIndex)(r);e[i]=i,t===!0&&SEe(r,e)}function SEe(r,e){var t=String.fromCharCode(r),i=t.toUpperCase();if(i!==t){var n=(0,xa.charCodeToOptimizedIndex)(i.charCodeAt(0));e[n]=n}else{var s=t.toLowerCase();if(s!==t){var n=(0,xa.charCodeToOptimizedIndex)(s.charCodeAt(0));e[n]=n}}}function HY(r,e){return(0,gs.find)(r.value,function(t){if(typeof t=="number")return(0,gs.contains)(e,t);var i=t;return(0,gs.find)(e,function(n){return i.from<=n&&n<=i.to})!==void 0})}function kv(r){return r.quantifier&&r.quantifier.atLeast===0?!0:r.value?(0,gs.isArray)(r.value)?(0,gs.every)(r.value,kv):kv(r.value):!1}var vEe=function(r){bEe(e,r);function e(t){var i=r.call(this)||this;return i.targetCharCodes=t,i.found=!1,i}return e.prototype.visitChildren=function(t){if(this.found!==!0){switch(t.type){case"Lookahead":this.visitLookahead(t);return;case"NegativeLookahead":this.visitNegativeLookahead(t);return}r.prototype.visitChildren.call(this,t)}},e.prototype.visitCharacter=function(t){(0,gs.contains)(this.targetCharCodes,t.value)&&(this.found=!0)},e.prototype.visitSet=function(t){t.complement?HY(t,this.targetCharCodes)===void 0&&(this.found=!0):HY(t,this.targetCharCodes)!==void 0&&(this.found=!0)},e}(GY.BaseRegExpVisitor);function xEe(r,e){if(e instanceof RegExp){var t=(0,YY.getRegExpAst)(e),i=new vEe(r);return i.visit(t),i.found}else return(0,gs.find)(e,function(n){return(0,gs.contains)(r,n.charCodeAt(0))})!==void 0}Cn.canMatchCharCode=xEe});var Rv=w(Ve=>{"use strict";var JY=Ve&&Ve.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(Ve,"__esModule",{value:!0});Ve.charCodeToOptimizedIndex=Ve.minOptimizationVal=Ve.buildLineBreakIssueMessage=Ve.LineTerminatorOptimizedTester=Ve.isShortPattern=Ve.isCustomPattern=Ve.cloneEmptyGroups=Ve.performWarningRuntimeChecks=Ve.performRuntimeChecks=Ve.addStickyFlag=Ve.addStartOfInput=Ve.findUnreachablePatterns=Ve.findModesThatDoNotExist=Ve.findInvalidGroupType=Ve.findDuplicatePatterns=Ve.findUnsupportedFlags=Ve.findStartOfInputAnchor=Ve.findEmptyMatchRegExps=Ve.findEndOfInputAnchor=Ve.findInvalidPatterns=Ve.findMissingPatterns=Ve.validatePatterns=Ve.analyzeTokenTypes=Ve.enableSticky=Ve.disableSticky=Ve.SUPPORT_STICKY=Ve.MODES=Ve.DEFAULT_MODE=void 0;var WY=$I(),ir=Bd(),xe=Gt(),Zg=qY(),zY=ty(),ko="PATTERN";Ve.DEFAULT_MODE="defaultMode";Ve.MODES="modes";Ve.SUPPORT_STICKY=typeof new RegExp("(?:)").sticky=="boolean";function PEe(){Ve.SUPPORT_STICKY=!1}Ve.disableSticky=PEe;function DEe(){Ve.SUPPORT_STICKY=!0}Ve.enableSticky=DEe;function kEe(r,e){e=(0,xe.defaults)(e,{useSticky:Ve.SUPPORT_STICKY,debug:!1,safeMode:!1,positionTracking:"full",lineTerminatorCharacters:["\r",` +`],tracer:function(v,D){return D()}});var t=e.tracer;t("initCharCodeToOptimizedIndexMap",function(){HEe()});var i;t("Reject Lexer.NA",function(){i=(0,xe.reject)(r,function(v){return v[ko]===ir.Lexer.NA})});var n=!1,s;t("Transform Patterns",function(){n=!1,s=(0,xe.map)(i,function(v){var D=v[ko];if((0,xe.isRegExp)(D)){var T=D.source;return T.length===1&&T!=="^"&&T!=="$"&&T!=="."&&!D.ignoreCase?T:T.length===2&&T[0]==="\\"&&!(0,xe.contains)(["d","D","s","S","t","r","n","t","0","c","b","B","f","v","w","W"],T[1])?T[1]:e.useSticky?Tv(D):Nv(D)}else{if((0,xe.isFunction)(D))return n=!0,{exec:D};if((0,xe.has)(D,"exec"))return n=!0,D;if(typeof D=="string"){if(D.length===1)return D;var H=D.replace(/[\\^$.*+?()[\]{}|]/g,"\\$&"),j=new RegExp(H);return e.useSticky?Tv(j):Nv(j)}else throw Error("non exhaustive match")}})});var o,a,l,c,u;t("misc mapping",function(){o=(0,xe.map)(i,function(v){return v.tokenTypeIdx}),a=(0,xe.map)(i,function(v){var D=v.GROUP;if(D!==ir.Lexer.SKIPPED){if((0,xe.isString)(D))return D;if((0,xe.isUndefined)(D))return!1;throw Error("non exhaustive match")}}),l=(0,xe.map)(i,function(v){var D=v.LONGER_ALT;if(D){var T=(0,xe.isArray)(D)?(0,xe.map)(D,function(H){return(0,xe.indexOf)(i,H)}):[(0,xe.indexOf)(i,D)];return T}}),c=(0,xe.map)(i,function(v){return v.PUSH_MODE}),u=(0,xe.map)(i,function(v){return(0,xe.has)(v,"POP_MODE")})});var g;t("Line Terminator Handling",function(){var v=Aj(e.lineTerminatorCharacters);g=(0,xe.map)(i,function(D){return!1}),e.positionTracking!=="onlyOffset"&&(g=(0,xe.map)(i,function(D){if((0,xe.has)(D,"LINE_BREAKS"))return D.LINE_BREAKS;if(oj(D,v)===!1)return(0,Zg.canMatchCharCode)(v,D.PATTERN)}))});var f,h,p,C;t("Misc Mapping #2",function(){f=(0,xe.map)(i,Mv),h=(0,xe.map)(s,sj),p=(0,xe.reduce)(i,function(v,D){var T=D.GROUP;return(0,xe.isString)(T)&&T!==ir.Lexer.SKIPPED&&(v[T]=[]),v},{}),C=(0,xe.map)(s,function(v,D){return{pattern:s[D],longerAlt:l[D],canLineTerminator:g[D],isCustom:f[D],short:h[D],group:a[D],push:c[D],pop:u[D],tokenTypeIdx:o[D],tokenType:i[D]}})});var y=!0,B=[];return e.safeMode||t("First Char Optimization",function(){B=(0,xe.reduce)(i,function(v,D,T){if(typeof D.PATTERN=="string"){var H=D.PATTERN.charCodeAt(0),j=Lv(H);Fv(v,j,C[T])}else if((0,xe.isArray)(D.START_CHARS_HINT)){var $;(0,xe.forEach)(D.START_CHARS_HINT,function(W){var _=typeof W=="string"?W.charCodeAt(0):W,A=Lv(_);$!==A&&($=A,Fv(v,A,C[T]))})}else if((0,xe.isRegExp)(D.PATTERN))if(D.PATTERN.unicode)y=!1,e.ensureOptimizations&&(0,xe.PRINT_ERROR)(""+Zg.failedOptimizationPrefixMsg+(" Unable to analyze < "+D.PATTERN.toString()+` > pattern. +`)+` The regexp unicode flag is not currently supported by the regexp-to-ast library. + This will disable the lexer's first char optimizations. + For details See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#UNICODE_OPTIMIZE`);else{var V=(0,Zg.getOptimizedStartCodesIndices)(D.PATTERN,e.ensureOptimizations);(0,xe.isEmpty)(V)&&(y=!1),(0,xe.forEach)(V,function(W){Fv(v,W,C[T])})}else e.ensureOptimizations&&(0,xe.PRINT_ERROR)(""+Zg.failedOptimizationPrefixMsg+(" TokenType: <"+D.name+`> is using a custom token pattern without providing parameter. +`)+` This will disable the lexer's first char optimizations. + For details See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#CUSTOM_OPTIMIZE`),y=!1;return v},[])}),t("ArrayPacking",function(){B=(0,xe.packArray)(B)}),{emptyGroups:p,patternIdxToConfig:C,charCodeToPatternIdxToConfig:B,hasCustom:n,canBeOptimized:y}}Ve.analyzeTokenTypes=kEe;function REe(r,e){var t=[],i=VY(r);t=t.concat(i.errors);var n=XY(i.valid),s=n.valid;return t=t.concat(n.errors),t=t.concat(FEe(s)),t=t.concat(rj(s)),t=t.concat(ij(s,e)),t=t.concat(nj(s)),t}Ve.validatePatterns=REe;function FEe(r){var e=[],t=(0,xe.filter)(r,function(i){return(0,xe.isRegExp)(i[ko])});return e=e.concat(ZY(t)),e=e.concat($Y(t)),e=e.concat(ej(t)),e=e.concat(tj(t)),e=e.concat(_Y(t)),e}function VY(r){var e=(0,xe.filter)(r,function(n){return!(0,xe.has)(n,ko)}),t=(0,xe.map)(e,function(n){return{message:"Token Type: ->"+n.name+"<- missing static 'PATTERN' property",type:ir.LexerDefinitionErrorType.MISSING_PATTERN,tokenTypes:[n]}}),i=(0,xe.difference)(r,e);return{errors:t,valid:i}}Ve.findMissingPatterns=VY;function XY(r){var e=(0,xe.filter)(r,function(n){var s=n[ko];return!(0,xe.isRegExp)(s)&&!(0,xe.isFunction)(s)&&!(0,xe.has)(s,"exec")&&!(0,xe.isString)(s)}),t=(0,xe.map)(e,function(n){return{message:"Token Type: ->"+n.name+"<- static 'PATTERN' can only be a RegExp, a Function matching the {CustomPatternMatcherFunc} type or an Object matching the {ICustomPattern} interface.",type:ir.LexerDefinitionErrorType.INVALID_PATTERN,tokenTypes:[n]}}),i=(0,xe.difference)(r,e);return{errors:t,valid:i}}Ve.findInvalidPatterns=XY;var NEe=/[^\\][\$]/;function ZY(r){var e=function(n){JY(s,n);function s(){var o=n!==null&&n.apply(this,arguments)||this;return o.found=!1,o}return s.prototype.visitEndAnchor=function(o){this.found=!0},s}(WY.BaseRegExpVisitor),t=(0,xe.filter)(r,function(n){var s=n[ko];try{var o=(0,zY.getRegExpAst)(s),a=new e;return a.visit(o),a.found}catch{return NEe.test(s.source)}}),i=(0,xe.map)(t,function(n){return{message:`Unexpected RegExp Anchor Error: + Token Type: ->`+n.name+`<- static 'PATTERN' cannot contain end of input anchor '$' + See chevrotain.io/docs/guide/resolving_lexer_errors.html#ANCHORS for details.`,type:ir.LexerDefinitionErrorType.EOI_ANCHOR_FOUND,tokenTypes:[n]}});return i}Ve.findEndOfInputAnchor=ZY;function _Y(r){var e=(0,xe.filter)(r,function(i){var n=i[ko];return n.test("")}),t=(0,xe.map)(e,function(i){return{message:"Token Type: ->"+i.name+"<- static 'PATTERN' must not match an empty string",type:ir.LexerDefinitionErrorType.EMPTY_MATCH_PATTERN,tokenTypes:[i]}});return t}Ve.findEmptyMatchRegExps=_Y;var TEe=/[^\\[][\^]|^\^/;function $Y(r){var e=function(n){JY(s,n);function s(){var o=n!==null&&n.apply(this,arguments)||this;return o.found=!1,o}return s.prototype.visitStartAnchor=function(o){this.found=!0},s}(WY.BaseRegExpVisitor),t=(0,xe.filter)(r,function(n){var s=n[ko];try{var o=(0,zY.getRegExpAst)(s),a=new e;return a.visit(o),a.found}catch{return TEe.test(s.source)}}),i=(0,xe.map)(t,function(n){return{message:`Unexpected RegExp Anchor Error: + Token Type: ->`+n.name+`<- static 'PATTERN' cannot contain start of input anchor '^' + See https://chevrotain.io/docs/guide/resolving_lexer_errors.html#ANCHORS for details.`,type:ir.LexerDefinitionErrorType.SOI_ANCHOR_FOUND,tokenTypes:[n]}});return i}Ve.findStartOfInputAnchor=$Y;function ej(r){var e=(0,xe.filter)(r,function(i){var n=i[ko];return n instanceof RegExp&&(n.multiline||n.global)}),t=(0,xe.map)(e,function(i){return{message:"Token Type: ->"+i.name+"<- static 'PATTERN' may NOT contain global('g') or multiline('m')",type:ir.LexerDefinitionErrorType.UNSUPPORTED_FLAGS_FOUND,tokenTypes:[i]}});return t}Ve.findUnsupportedFlags=ej;function tj(r){var e=[],t=(0,xe.map)(r,function(s){return(0,xe.reduce)(r,function(o,a){return s.PATTERN.source===a.PATTERN.source&&!(0,xe.contains)(e,a)&&a.PATTERN!==ir.Lexer.NA&&(e.push(a),o.push(a)),o},[])});t=(0,xe.compact)(t);var i=(0,xe.filter)(t,function(s){return s.length>1}),n=(0,xe.map)(i,function(s){var o=(0,xe.map)(s,function(l){return l.name}),a=(0,xe.first)(s).PATTERN;return{message:"The same RegExp pattern ->"+a+"<-"+("has been used in all of the following Token Types: "+o.join(", ")+" <-"),type:ir.LexerDefinitionErrorType.DUPLICATE_PATTERNS_FOUND,tokenTypes:s}});return n}Ve.findDuplicatePatterns=tj;function rj(r){var e=(0,xe.filter)(r,function(i){if(!(0,xe.has)(i,"GROUP"))return!1;var n=i.GROUP;return n!==ir.Lexer.SKIPPED&&n!==ir.Lexer.NA&&!(0,xe.isString)(n)}),t=(0,xe.map)(e,function(i){return{message:"Token Type: ->"+i.name+"<- static 'GROUP' can only be Lexer.SKIPPED/Lexer.NA/A String",type:ir.LexerDefinitionErrorType.INVALID_GROUP_TYPE_FOUND,tokenTypes:[i]}});return t}Ve.findInvalidGroupType=rj;function ij(r,e){var t=(0,xe.filter)(r,function(n){return n.PUSH_MODE!==void 0&&!(0,xe.contains)(e,n.PUSH_MODE)}),i=(0,xe.map)(t,function(n){var s="Token Type: ->"+n.name+"<- static 'PUSH_MODE' value cannot refer to a Lexer Mode ->"+n.PUSH_MODE+"<-which does not exist";return{message:s,type:ir.LexerDefinitionErrorType.PUSH_MODE_DOES_NOT_EXIST,tokenTypes:[n]}});return i}Ve.findModesThatDoNotExist=ij;function nj(r){var e=[],t=(0,xe.reduce)(r,function(i,n,s){var o=n.PATTERN;return o===ir.Lexer.NA||((0,xe.isString)(o)?i.push({str:o,idx:s,tokenType:n}):(0,xe.isRegExp)(o)&&MEe(o)&&i.push({str:o.source,idx:s,tokenType:n})),i},[]);return(0,xe.forEach)(r,function(i,n){(0,xe.forEach)(t,function(s){var o=s.str,a=s.idx,l=s.tokenType;if(n"+i.name+"<-")+`in the lexer's definition. +See https://chevrotain.io/docs/guide/resolving_lexer_errors.html#UNREACHABLE`;e.push({message:c,type:ir.LexerDefinitionErrorType.UNREACHABLE_PATTERN,tokenTypes:[i,l]})}})}),e}Ve.findUnreachablePatterns=nj;function LEe(r,e){if((0,xe.isRegExp)(e)){var t=e.exec(r);return t!==null&&t.index===0}else{if((0,xe.isFunction)(e))return e(r,0,[],{});if((0,xe.has)(e,"exec"))return e.exec(r,0,[],{});if(typeof e=="string")return e===r;throw Error("non exhaustive match")}}function MEe(r){var e=[".","\\","[","]","|","^","$","(",")","?","*","+","{"];return(0,xe.find)(e,function(t){return r.source.indexOf(t)!==-1})===void 0}function Nv(r){var e=r.ignoreCase?"i":"";return new RegExp("^(?:"+r.source+")",e)}Ve.addStartOfInput=Nv;function Tv(r){var e=r.ignoreCase?"iy":"y";return new RegExp(""+r.source,e)}Ve.addStickyFlag=Tv;function OEe(r,e,t){var i=[];return(0,xe.has)(r,Ve.DEFAULT_MODE)||i.push({message:"A MultiMode Lexer cannot be initialized without a <"+Ve.DEFAULT_MODE+`> property in its definition +`,type:ir.LexerDefinitionErrorType.MULTI_MODE_LEXER_WITHOUT_DEFAULT_MODE}),(0,xe.has)(r,Ve.MODES)||i.push({message:"A MultiMode Lexer cannot be initialized without a <"+Ve.MODES+`> property in its definition +`,type:ir.LexerDefinitionErrorType.MULTI_MODE_LEXER_WITHOUT_MODES_PROPERTY}),(0,xe.has)(r,Ve.MODES)&&(0,xe.has)(r,Ve.DEFAULT_MODE)&&!(0,xe.has)(r.modes,r.defaultMode)&&i.push({message:"A MultiMode Lexer cannot be initialized with a "+Ve.DEFAULT_MODE+": <"+r.defaultMode+`>which does not exist +`,type:ir.LexerDefinitionErrorType.MULTI_MODE_LEXER_DEFAULT_MODE_VALUE_DOES_NOT_EXIST}),(0,xe.has)(r,Ve.MODES)&&(0,xe.forEach)(r.modes,function(n,s){(0,xe.forEach)(n,function(o,a){(0,xe.isUndefined)(o)&&i.push({message:"A Lexer cannot be initialized using an undefined Token Type. Mode:"+("<"+s+"> at index: <"+a+`> +`),type:ir.LexerDefinitionErrorType.LEXER_DEFINITION_CANNOT_CONTAIN_UNDEFINED})})}),i}Ve.performRuntimeChecks=OEe;function KEe(r,e,t){var i=[],n=!1,s=(0,xe.compact)((0,xe.flatten)((0,xe.mapValues)(r.modes,function(l){return l}))),o=(0,xe.reject)(s,function(l){return l[ko]===ir.Lexer.NA}),a=Aj(t);return e&&(0,xe.forEach)(o,function(l){var c=oj(l,a);if(c!==!1){var u=aj(l,c),g={message:u,type:c.issue,tokenType:l};i.push(g)}else(0,xe.has)(l,"LINE_BREAKS")?l.LINE_BREAKS===!0&&(n=!0):(0,Zg.canMatchCharCode)(a,l.PATTERN)&&(n=!0)}),e&&!n&&i.push({message:`Warning: No LINE_BREAKS Found. + This Lexer has been defined to track line and column information, + But none of the Token Types can be identified as matching a line terminator. + See https://chevrotain.io/docs/guide/resolving_lexer_errors.html#LINE_BREAKS + for details.`,type:ir.LexerDefinitionErrorType.NO_LINE_BREAKS_FLAGS}),i}Ve.performWarningRuntimeChecks=KEe;function UEe(r){var e={},t=(0,xe.keys)(r);return(0,xe.forEach)(t,function(i){var n=r[i];if((0,xe.isArray)(n))e[i]=[];else throw Error("non exhaustive match")}),e}Ve.cloneEmptyGroups=UEe;function Mv(r){var e=r.PATTERN;if((0,xe.isRegExp)(e))return!1;if((0,xe.isFunction)(e))return!0;if((0,xe.has)(e,"exec"))return!0;if((0,xe.isString)(e))return!1;throw Error("non exhaustive match")}Ve.isCustomPattern=Mv;function sj(r){return(0,xe.isString)(r)&&r.length===1?r.charCodeAt(0):!1}Ve.isShortPattern=sj;Ve.LineTerminatorOptimizedTester={test:function(r){for(var e=r.length,t=this.lastIndex;t Token Type +`)+(" Root cause: "+e.errMsg+`. +`)+" For details See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#IDENTIFY_TERMINATOR";if(e.issue===ir.LexerDefinitionErrorType.CUSTOM_LINE_BREAK)return`Warning: A Custom Token Pattern should specify the option. +`+(" The problem is in the <"+r.name+`> Token Type +`)+" For details See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#CUSTOM_LINE_BREAK";throw Error("non exhaustive match")}Ve.buildLineBreakIssueMessage=aj;function Aj(r){var e=(0,xe.map)(r,function(t){return(0,xe.isString)(t)&&t.length>0?t.charCodeAt(0):t});return e}function Fv(r,e,t){r[e]===void 0?r[e]=[t]:r[e].push(t)}Ve.minOptimizationVal=256;var ny=[];function Lv(r){return r255?255+~~(r/255):r}}});var _g=w(Nt=>{"use strict";Object.defineProperty(Nt,"__esModule",{value:!0});Nt.isTokenType=Nt.hasExtendingTokensTypesMapProperty=Nt.hasExtendingTokensTypesProperty=Nt.hasCategoriesProperty=Nt.hasShortKeyProperty=Nt.singleAssignCategoriesToksMap=Nt.assignCategoriesMapProp=Nt.assignCategoriesTokensProp=Nt.assignTokenDefaultProps=Nt.expandCategories=Nt.augmentTokenTypes=Nt.tokenIdxToClass=Nt.tokenShortNameIdx=Nt.tokenStructuredMatcherNoCategories=Nt.tokenStructuredMatcher=void 0;var Zr=Gt();function GEe(r,e){var t=r.tokenTypeIdx;return t===e.tokenTypeIdx?!0:e.isParent===!0&&e.categoryMatchesMap[t]===!0}Nt.tokenStructuredMatcher=GEe;function YEe(r,e){return r.tokenTypeIdx===e.tokenTypeIdx}Nt.tokenStructuredMatcherNoCategories=YEe;Nt.tokenShortNameIdx=1;Nt.tokenIdxToClass={};function jEe(r){var e=lj(r);cj(e),gj(e),uj(e),(0,Zr.forEach)(e,function(t){t.isParent=t.categoryMatches.length>0})}Nt.augmentTokenTypes=jEe;function lj(r){for(var e=(0,Zr.cloneArr)(r),t=r,i=!0;i;){t=(0,Zr.compact)((0,Zr.flatten)((0,Zr.map)(t,function(s){return s.CATEGORIES})));var n=(0,Zr.difference)(t,e);e=e.concat(n),(0,Zr.isEmpty)(n)?i=!1:t=n}return e}Nt.expandCategories=lj;function cj(r){(0,Zr.forEach)(r,function(e){fj(e)||(Nt.tokenIdxToClass[Nt.tokenShortNameIdx]=e,e.tokenTypeIdx=Nt.tokenShortNameIdx++),Ov(e)&&!(0,Zr.isArray)(e.CATEGORIES)&&(e.CATEGORIES=[e.CATEGORIES]),Ov(e)||(e.CATEGORIES=[]),hj(e)||(e.categoryMatches=[]),pj(e)||(e.categoryMatchesMap={})})}Nt.assignTokenDefaultProps=cj;function uj(r){(0,Zr.forEach)(r,function(e){e.categoryMatches=[],(0,Zr.forEach)(e.categoryMatchesMap,function(t,i){e.categoryMatches.push(Nt.tokenIdxToClass[i].tokenTypeIdx)})})}Nt.assignCategoriesTokensProp=uj;function gj(r){(0,Zr.forEach)(r,function(e){Kv([],e)})}Nt.assignCategoriesMapProp=gj;function Kv(r,e){(0,Zr.forEach)(r,function(t){e.categoryMatchesMap[t.tokenTypeIdx]=!0}),(0,Zr.forEach)(e.CATEGORIES,function(t){var i=r.concat(e);(0,Zr.contains)(i,t)||Kv(i,t)})}Nt.singleAssignCategoriesToksMap=Kv;function fj(r){return(0,Zr.has)(r,"tokenTypeIdx")}Nt.hasShortKeyProperty=fj;function Ov(r){return(0,Zr.has)(r,"CATEGORIES")}Nt.hasCategoriesProperty=Ov;function hj(r){return(0,Zr.has)(r,"categoryMatches")}Nt.hasExtendingTokensTypesProperty=hj;function pj(r){return(0,Zr.has)(r,"categoryMatchesMap")}Nt.hasExtendingTokensTypesMapProperty=pj;function qEe(r){return(0,Zr.has)(r,"tokenTypeIdx")}Nt.isTokenType=qEe});var Uv=w(sy=>{"use strict";Object.defineProperty(sy,"__esModule",{value:!0});sy.defaultLexerErrorProvider=void 0;sy.defaultLexerErrorProvider={buildUnableToPopLexerModeMessage:function(r){return"Unable to pop Lexer Mode after encountering Token ->"+r.image+"<- The Mode Stack is empty"},buildUnexpectedCharactersMessage:function(r,e,t,i,n){return"unexpected character: ->"+r.charAt(e)+"<- at offset: "+e+","+(" skipped "+t+" characters.")}}});var Bd=w(Cc=>{"use strict";Object.defineProperty(Cc,"__esModule",{value:!0});Cc.Lexer=Cc.LexerDefinitionErrorType=void 0;var _s=Rv(),nr=Gt(),JEe=_g(),WEe=Uv(),zEe=ty(),VEe;(function(r){r[r.MISSING_PATTERN=0]="MISSING_PATTERN",r[r.INVALID_PATTERN=1]="INVALID_PATTERN",r[r.EOI_ANCHOR_FOUND=2]="EOI_ANCHOR_FOUND",r[r.UNSUPPORTED_FLAGS_FOUND=3]="UNSUPPORTED_FLAGS_FOUND",r[r.DUPLICATE_PATTERNS_FOUND=4]="DUPLICATE_PATTERNS_FOUND",r[r.INVALID_GROUP_TYPE_FOUND=5]="INVALID_GROUP_TYPE_FOUND",r[r.PUSH_MODE_DOES_NOT_EXIST=6]="PUSH_MODE_DOES_NOT_EXIST",r[r.MULTI_MODE_LEXER_WITHOUT_DEFAULT_MODE=7]="MULTI_MODE_LEXER_WITHOUT_DEFAULT_MODE",r[r.MULTI_MODE_LEXER_WITHOUT_MODES_PROPERTY=8]="MULTI_MODE_LEXER_WITHOUT_MODES_PROPERTY",r[r.MULTI_MODE_LEXER_DEFAULT_MODE_VALUE_DOES_NOT_EXIST=9]="MULTI_MODE_LEXER_DEFAULT_MODE_VALUE_DOES_NOT_EXIST",r[r.LEXER_DEFINITION_CANNOT_CONTAIN_UNDEFINED=10]="LEXER_DEFINITION_CANNOT_CONTAIN_UNDEFINED",r[r.SOI_ANCHOR_FOUND=11]="SOI_ANCHOR_FOUND",r[r.EMPTY_MATCH_PATTERN=12]="EMPTY_MATCH_PATTERN",r[r.NO_LINE_BREAKS_FLAGS=13]="NO_LINE_BREAKS_FLAGS",r[r.UNREACHABLE_PATTERN=14]="UNREACHABLE_PATTERN",r[r.IDENTIFY_TERMINATOR=15]="IDENTIFY_TERMINATOR",r[r.CUSTOM_LINE_BREAK=16]="CUSTOM_LINE_BREAK"})(VEe=Cc.LexerDefinitionErrorType||(Cc.LexerDefinitionErrorType={}));var bd={deferDefinitionErrorsHandling:!1,positionTracking:"full",lineTerminatorsPattern:/\n|\r\n?/g,lineTerminatorCharacters:[` +`,"\r"],ensureOptimizations:!1,safeMode:!1,errorMessageProvider:WEe.defaultLexerErrorProvider,traceInitPerf:!1,skipValidations:!1};Object.freeze(bd);var XEe=function(){function r(e,t){var i=this;if(t===void 0&&(t=bd),this.lexerDefinition=e,this.lexerDefinitionErrors=[],this.lexerDefinitionWarning=[],this.patternIdxToConfig={},this.charCodeToPatternIdxToConfig={},this.modes=[],this.emptyGroups={},this.config=void 0,this.trackStartLines=!0,this.trackEndLines=!0,this.hasCustom=!1,this.canModeBeOptimized={},typeof t=="boolean")throw Error(`The second argument to the Lexer constructor is now an ILexerConfig Object. +a boolean 2nd argument is no longer supported`);this.config=(0,nr.merge)(bd,t);var n=this.config.traceInitPerf;n===!0?(this.traceInitMaxIdent=1/0,this.traceInitPerf=!0):typeof n=="number"&&(this.traceInitMaxIdent=n,this.traceInitPerf=!0),this.traceInitIndent=-1,this.TRACE_INIT("Lexer Constructor",function(){var s,o=!0;i.TRACE_INIT("Lexer Config handling",function(){if(i.config.lineTerminatorsPattern===bd.lineTerminatorsPattern)i.config.lineTerminatorsPattern=_s.LineTerminatorOptimizedTester;else if(i.config.lineTerminatorCharacters===bd.lineTerminatorCharacters)throw Error(`Error: Missing property on the Lexer config. + For details See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#MISSING_LINE_TERM_CHARS`);if(t.safeMode&&t.ensureOptimizations)throw Error('"safeMode" and "ensureOptimizations" flags are mutually exclusive.');i.trackStartLines=/full|onlyStart/i.test(i.config.positionTracking),i.trackEndLines=/full/i.test(i.config.positionTracking),(0,nr.isArray)(e)?(s={modes:{}},s.modes[_s.DEFAULT_MODE]=(0,nr.cloneArr)(e),s[_s.DEFAULT_MODE]=_s.DEFAULT_MODE):(o=!1,s=(0,nr.cloneObj)(e))}),i.config.skipValidations===!1&&(i.TRACE_INIT("performRuntimeChecks",function(){i.lexerDefinitionErrors=i.lexerDefinitionErrors.concat((0,_s.performRuntimeChecks)(s,i.trackStartLines,i.config.lineTerminatorCharacters))}),i.TRACE_INIT("performWarningRuntimeChecks",function(){i.lexerDefinitionWarning=i.lexerDefinitionWarning.concat((0,_s.performWarningRuntimeChecks)(s,i.trackStartLines,i.config.lineTerminatorCharacters))})),s.modes=s.modes?s.modes:{},(0,nr.forEach)(s.modes,function(u,g){s.modes[g]=(0,nr.reject)(u,function(f){return(0,nr.isUndefined)(f)})});var a=(0,nr.keys)(s.modes);if((0,nr.forEach)(s.modes,function(u,g){i.TRACE_INIT("Mode: <"+g+"> processing",function(){if(i.modes.push(g),i.config.skipValidations===!1&&i.TRACE_INIT("validatePatterns",function(){i.lexerDefinitionErrors=i.lexerDefinitionErrors.concat((0,_s.validatePatterns)(u,a))}),(0,nr.isEmpty)(i.lexerDefinitionErrors)){(0,JEe.augmentTokenTypes)(u);var f;i.TRACE_INIT("analyzeTokenTypes",function(){f=(0,_s.analyzeTokenTypes)(u,{lineTerminatorCharacters:i.config.lineTerminatorCharacters,positionTracking:t.positionTracking,ensureOptimizations:t.ensureOptimizations,safeMode:t.safeMode,tracer:i.TRACE_INIT.bind(i)})}),i.patternIdxToConfig[g]=f.patternIdxToConfig,i.charCodeToPatternIdxToConfig[g]=f.charCodeToPatternIdxToConfig,i.emptyGroups=(0,nr.merge)(i.emptyGroups,f.emptyGroups),i.hasCustom=f.hasCustom||i.hasCustom,i.canModeBeOptimized[g]=f.canBeOptimized}})}),i.defaultMode=s.defaultMode,!(0,nr.isEmpty)(i.lexerDefinitionErrors)&&!i.config.deferDefinitionErrorsHandling){var l=(0,nr.map)(i.lexerDefinitionErrors,function(u){return u.message}),c=l.join(`----------------------- +`);throw new Error(`Errors detected in definition of Lexer: +`+c)}(0,nr.forEach)(i.lexerDefinitionWarning,function(u){(0,nr.PRINT_WARNING)(u.message)}),i.TRACE_INIT("Choosing sub-methods implementations",function(){if(_s.SUPPORT_STICKY?(i.chopInput=nr.IDENTITY,i.match=i.matchWithTest):(i.updateLastIndex=nr.NOOP,i.match=i.matchWithExec),o&&(i.handleModes=nr.NOOP),i.trackStartLines===!1&&(i.computeNewColumn=nr.IDENTITY),i.trackEndLines===!1&&(i.updateTokenEndLineColumnLocation=nr.NOOP),/full/i.test(i.config.positionTracking))i.createTokenInstance=i.createFullToken;else if(/onlyStart/i.test(i.config.positionTracking))i.createTokenInstance=i.createStartOnlyToken;else if(/onlyOffset/i.test(i.config.positionTracking))i.createTokenInstance=i.createOffsetOnlyToken;else throw Error('Invalid config option: "'+i.config.positionTracking+'"');i.hasCustom?(i.addToken=i.addTokenUsingPush,i.handlePayload=i.handlePayloadWithCustom):(i.addToken=i.addTokenUsingMemberAccess,i.handlePayload=i.handlePayloadNoCustom)}),i.TRACE_INIT("Failed Optimization Warnings",function(){var u=(0,nr.reduce)(i.canModeBeOptimized,function(g,f,h){return f===!1&&g.push(h),g},[]);if(t.ensureOptimizations&&!(0,nr.isEmpty)(u))throw Error("Lexer Modes: < "+u.join(", ")+` > cannot be optimized. + Disable the "ensureOptimizations" lexer config flag to silently ignore this and run the lexer in an un-optimized mode. + Or inspect the console log for details on how to resolve these issues.`)}),i.TRACE_INIT("clearRegExpParserCache",function(){(0,zEe.clearRegExpParserCache)()}),i.TRACE_INIT("toFastProperties",function(){(0,nr.toFastProperties)(i)})})}return r.prototype.tokenize=function(e,t){if(t===void 0&&(t=this.defaultMode),!(0,nr.isEmpty)(this.lexerDefinitionErrors)){var i=(0,nr.map)(this.lexerDefinitionErrors,function(o){return o.message}),n=i.join(`----------------------- +`);throw new Error(`Unable to Tokenize because Errors detected in definition of Lexer: +`+n)}var s=this.tokenizeInternal(e,t);return s},r.prototype.tokenizeInternal=function(e,t){var i=this,n,s,o,a,l,c,u,g,f,h,p,C,y,B,v,D,T=e,H=T.length,j=0,$=0,V=this.hasCustom?0:Math.floor(e.length/10),W=new Array(V),_=[],A=this.trackStartLines?1:void 0,Ae=this.trackStartLines?1:void 0,ge=(0,_s.cloneEmptyGroups)(this.emptyGroups),re=this.trackStartLines,M=this.config.lineTerminatorsPattern,F=0,ue=[],pe=[],ke=[],Fe=[];Object.freeze(Fe);var Ne=void 0;function oe(){return ue}function le(pr){var Ii=(0,_s.charCodeToOptimizedIndex)(pr),rs=pe[Ii];return rs===void 0?Fe:rs}var Be=function(pr){if(ke.length===1&&pr.tokenType.PUSH_MODE===void 0){var Ii=i.config.errorMessageProvider.buildUnableToPopLexerModeMessage(pr);_.push({offset:pr.startOffset,line:pr.startLine!==void 0?pr.startLine:void 0,column:pr.startColumn!==void 0?pr.startColumn:void 0,length:pr.image.length,message:Ii})}else{ke.pop();var rs=(0,nr.last)(ke);ue=i.patternIdxToConfig[rs],pe=i.charCodeToPatternIdxToConfig[rs],F=ue.length;var fa=i.canModeBeOptimized[rs]&&i.config.safeMode===!1;pe&&fa?Ne=le:Ne=oe}};function fe(pr){ke.push(pr),pe=this.charCodeToPatternIdxToConfig[pr],ue=this.patternIdxToConfig[pr],F=ue.length,F=ue.length;var Ii=this.canModeBeOptimized[pr]&&this.config.safeMode===!1;pe&&Ii?Ne=le:Ne=oe}fe.call(this,t);for(var ae;jc.length){c=a,u=g,ae=_e;break}}}break}}if(c!==null){if(f=c.length,h=ae.group,h!==void 0&&(p=ae.tokenTypeIdx,C=this.createTokenInstance(c,j,p,ae.tokenType,A,Ae,f),this.handlePayload(C,u),h===!1?$=this.addToken(W,$,C):ge[h].push(C)),e=this.chopInput(e,f),j=j+f,Ae=this.computeNewColumn(Ae,f),re===!0&&ae.canLineTerminator===!0){var It=0,Mr=void 0,ii=void 0;M.lastIndex=0;do Mr=M.test(c),Mr===!0&&(ii=M.lastIndex-1,It++);while(Mr===!0);It!==0&&(A=A+It,Ae=f-ii,this.updateTokenEndLineColumnLocation(C,h,ii,It,A,Ae,f))}this.handleModes(ae,Be,fe,C)}else{for(var gi=j,hr=A,fi=Ae,ni=!1;!ni&&j <"+e+">");var n=(0,nr.timer)(t),s=n.time,o=n.value,a=s>10?console.warn:console.log;return this.traceInitIndent time: "+s+"ms"),this.traceInitIndent--,o}else return t()},r.SKIPPED="This marks a skipped Token pattern, this means each token identified by it willbe consumed and then thrown into oblivion, this can be used to for example to completely ignore whitespace.",r.NA=/NOT_APPLICABLE/,r}();Cc.Lexer=XEe});var TA=w(Qi=>{"use strict";Object.defineProperty(Qi,"__esModule",{value:!0});Qi.tokenMatcher=Qi.createTokenInstance=Qi.EOF=Qi.createToken=Qi.hasTokenLabel=Qi.tokenName=Qi.tokenLabel=void 0;var $s=Gt(),ZEe=Bd(),Hv=_g();function _Ee(r){return bj(r)?r.LABEL:r.name}Qi.tokenLabel=_Ee;function $Ee(r){return r.name}Qi.tokenName=$Ee;function bj(r){return(0,$s.isString)(r.LABEL)&&r.LABEL!==""}Qi.hasTokenLabel=bj;var eIe="parent",dj="categories",Cj="label",mj="group",Ej="push_mode",Ij="pop_mode",yj="longer_alt",wj="line_breaks",Bj="start_chars_hint";function Qj(r){return tIe(r)}Qi.createToken=Qj;function tIe(r){var e=r.pattern,t={};if(t.name=r.name,(0,$s.isUndefined)(e)||(t.PATTERN=e),(0,$s.has)(r,eIe))throw`The parent property is no longer supported. +See: https://github.com/chevrotain/chevrotain/issues/564#issuecomment-349062346 for details.`;return(0,$s.has)(r,dj)&&(t.CATEGORIES=r[dj]),(0,Hv.augmentTokenTypes)([t]),(0,$s.has)(r,Cj)&&(t.LABEL=r[Cj]),(0,$s.has)(r,mj)&&(t.GROUP=r[mj]),(0,$s.has)(r,Ij)&&(t.POP_MODE=r[Ij]),(0,$s.has)(r,Ej)&&(t.PUSH_MODE=r[Ej]),(0,$s.has)(r,yj)&&(t.LONGER_ALT=r[yj]),(0,$s.has)(r,wj)&&(t.LINE_BREAKS=r[wj]),(0,$s.has)(r,Bj)&&(t.START_CHARS_HINT=r[Bj]),t}Qi.EOF=Qj({name:"EOF",pattern:ZEe.Lexer.NA});(0,Hv.augmentTokenTypes)([Qi.EOF]);function rIe(r,e,t,i,n,s,o,a){return{image:e,startOffset:t,endOffset:i,startLine:n,endLine:s,startColumn:o,endColumn:a,tokenTypeIdx:r.tokenTypeIdx,tokenType:r}}Qi.createTokenInstance=rIe;function iIe(r,e){return(0,Hv.tokenStructuredMatcher)(r,e)}Qi.tokenMatcher=iIe});var mn=w(zt=>{"use strict";var Pa=zt&&zt.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(zt,"__esModule",{value:!0});zt.serializeProduction=zt.serializeGrammar=zt.Terminal=zt.Alternation=zt.RepetitionWithSeparator=zt.Repetition=zt.RepetitionMandatoryWithSeparator=zt.RepetitionMandatory=zt.Option=zt.Alternative=zt.Rule=zt.NonTerminal=zt.AbstractProduction=void 0;var Ar=Gt(),nIe=TA(),Ro=function(){function r(e){this._definition=e}return Object.defineProperty(r.prototype,"definition",{get:function(){return this._definition},set:function(e){this._definition=e},enumerable:!1,configurable:!0}),r.prototype.accept=function(e){e.visit(this),(0,Ar.forEach)(this.definition,function(t){t.accept(e)})},r}();zt.AbstractProduction=Ro;var Sj=function(r){Pa(e,r);function e(t){var i=r.call(this,[])||this;return i.idx=1,(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return Object.defineProperty(e.prototype,"definition",{get:function(){return this.referencedRule!==void 0?this.referencedRule.definition:[]},set:function(t){},enumerable:!1,configurable:!0}),e.prototype.accept=function(t){t.visit(this)},e}(Ro);zt.NonTerminal=Sj;var vj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.orgText="",(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return e}(Ro);zt.Rule=vj;var xj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.ignoreAmbiguities=!1,(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return e}(Ro);zt.Alternative=xj;var Pj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return e}(Ro);zt.Option=Pj;var Dj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return e}(Ro);zt.RepetitionMandatory=Dj;var kj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return e}(Ro);zt.RepetitionMandatoryWithSeparator=kj;var Rj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return e}(Ro);zt.Repetition=Rj;var Fj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return e}(Ro);zt.RepetitionWithSeparator=Fj;var Nj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,i.ignoreAmbiguities=!1,i.hasPredicates=!1,(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return Object.defineProperty(e.prototype,"definition",{get:function(){return this._definition},set:function(t){this._definition=t},enumerable:!1,configurable:!0}),e}(Ro);zt.Alternation=Nj;var oy=function(){function r(e){this.idx=1,(0,Ar.assign)(this,(0,Ar.pick)(e,function(t){return t!==void 0}))}return r.prototype.accept=function(e){e.visit(this)},r}();zt.Terminal=oy;function sIe(r){return(0,Ar.map)(r,Qd)}zt.serializeGrammar=sIe;function Qd(r){function e(s){return(0,Ar.map)(s,Qd)}if(r instanceof Sj){var t={type:"NonTerminal",name:r.nonTerminalName,idx:r.idx};return(0,Ar.isString)(r.label)&&(t.label=r.label),t}else{if(r instanceof xj)return{type:"Alternative",definition:e(r.definition)};if(r instanceof Pj)return{type:"Option",idx:r.idx,definition:e(r.definition)};if(r instanceof Dj)return{type:"RepetitionMandatory",idx:r.idx,definition:e(r.definition)};if(r instanceof kj)return{type:"RepetitionMandatoryWithSeparator",idx:r.idx,separator:Qd(new oy({terminalType:r.separator})),definition:e(r.definition)};if(r instanceof Fj)return{type:"RepetitionWithSeparator",idx:r.idx,separator:Qd(new oy({terminalType:r.separator})),definition:e(r.definition)};if(r instanceof Rj)return{type:"Repetition",idx:r.idx,definition:e(r.definition)};if(r instanceof Nj)return{type:"Alternation",idx:r.idx,definition:e(r.definition)};if(r instanceof oy){var i={type:"Terminal",name:r.terminalType.name,label:(0,nIe.tokenLabel)(r.terminalType),idx:r.idx};(0,Ar.isString)(r.label)&&(i.terminalLabel=r.label);var n=r.terminalType.PATTERN;return r.terminalType.PATTERN&&(i.pattern=(0,Ar.isRegExp)(n)?n.source:n),i}else{if(r instanceof vj)return{type:"Rule",name:r.name,orgText:r.orgText,definition:e(r.definition)};throw Error("non exhaustive match")}}}zt.serializeProduction=Qd});var Ay=w(ay=>{"use strict";Object.defineProperty(ay,"__esModule",{value:!0});ay.RestWalker=void 0;var Gv=Gt(),En=mn(),oIe=function(){function r(){}return r.prototype.walk=function(e,t){var i=this;t===void 0&&(t=[]),(0,Gv.forEach)(e.definition,function(n,s){var o=(0,Gv.drop)(e.definition,s+1);if(n instanceof En.NonTerminal)i.walkProdRef(n,o,t);else if(n instanceof En.Terminal)i.walkTerminal(n,o,t);else if(n instanceof En.Alternative)i.walkFlat(n,o,t);else if(n instanceof En.Option)i.walkOption(n,o,t);else if(n instanceof En.RepetitionMandatory)i.walkAtLeastOne(n,o,t);else if(n instanceof En.RepetitionMandatoryWithSeparator)i.walkAtLeastOneSep(n,o,t);else if(n instanceof En.RepetitionWithSeparator)i.walkManySep(n,o,t);else if(n instanceof En.Repetition)i.walkMany(n,o,t);else if(n instanceof En.Alternation)i.walkOr(n,o,t);else throw Error("non exhaustive match")})},r.prototype.walkTerminal=function(e,t,i){},r.prototype.walkProdRef=function(e,t,i){},r.prototype.walkFlat=function(e,t,i){var n=t.concat(i);this.walk(e,n)},r.prototype.walkOption=function(e,t,i){var n=t.concat(i);this.walk(e,n)},r.prototype.walkAtLeastOne=function(e,t,i){var n=[new En.Option({definition:e.definition})].concat(t,i);this.walk(e,n)},r.prototype.walkAtLeastOneSep=function(e,t,i){var n=Tj(e,t,i);this.walk(e,n)},r.prototype.walkMany=function(e,t,i){var n=[new En.Option({definition:e.definition})].concat(t,i);this.walk(e,n)},r.prototype.walkManySep=function(e,t,i){var n=Tj(e,t,i);this.walk(e,n)},r.prototype.walkOr=function(e,t,i){var n=this,s=t.concat(i);(0,Gv.forEach)(e.definition,function(o){var a=new En.Alternative({definition:[o]});n.walk(a,s)})},r}();ay.RestWalker=oIe;function Tj(r,e,t){var i=[new En.Option({definition:[new En.Terminal({terminalType:r.separator})].concat(r.definition)})],n=i.concat(e,t);return n}});var $g=w(ly=>{"use strict";Object.defineProperty(ly,"__esModule",{value:!0});ly.GAstVisitor=void 0;var Fo=mn(),aIe=function(){function r(){}return r.prototype.visit=function(e){var t=e;switch(t.constructor){case Fo.NonTerminal:return this.visitNonTerminal(t);case Fo.Alternative:return this.visitAlternative(t);case Fo.Option:return this.visitOption(t);case Fo.RepetitionMandatory:return this.visitRepetitionMandatory(t);case Fo.RepetitionMandatoryWithSeparator:return this.visitRepetitionMandatoryWithSeparator(t);case Fo.RepetitionWithSeparator:return this.visitRepetitionWithSeparator(t);case Fo.Repetition:return this.visitRepetition(t);case Fo.Alternation:return this.visitAlternation(t);case Fo.Terminal:return this.visitTerminal(t);case Fo.Rule:return this.visitRule(t);default:throw Error("non exhaustive match")}},r.prototype.visitNonTerminal=function(e){},r.prototype.visitAlternative=function(e){},r.prototype.visitOption=function(e){},r.prototype.visitRepetition=function(e){},r.prototype.visitRepetitionMandatory=function(e){},r.prototype.visitRepetitionMandatoryWithSeparator=function(e){},r.prototype.visitRepetitionWithSeparator=function(e){},r.prototype.visitAlternation=function(e){},r.prototype.visitTerminal=function(e){},r.prototype.visitRule=function(e){},r}();ly.GAstVisitor=aIe});var vd=w(Oi=>{"use strict";var AIe=Oi&&Oi.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(Oi,"__esModule",{value:!0});Oi.collectMethods=Oi.DslMethodsCollectorVisitor=Oi.getProductionDslName=Oi.isBranchingProd=Oi.isOptionalProd=Oi.isSequenceProd=void 0;var Sd=Gt(),br=mn(),lIe=$g();function cIe(r){return r instanceof br.Alternative||r instanceof br.Option||r instanceof br.Repetition||r instanceof br.RepetitionMandatory||r instanceof br.RepetitionMandatoryWithSeparator||r instanceof br.RepetitionWithSeparator||r instanceof br.Terminal||r instanceof br.Rule}Oi.isSequenceProd=cIe;function Yv(r,e){e===void 0&&(e=[]);var t=r instanceof br.Option||r instanceof br.Repetition||r instanceof br.RepetitionWithSeparator;return t?!0:r instanceof br.Alternation?(0,Sd.some)(r.definition,function(i){return Yv(i,e)}):r instanceof br.NonTerminal&&(0,Sd.contains)(e,r)?!1:r instanceof br.AbstractProduction?(r instanceof br.NonTerminal&&e.push(r),(0,Sd.every)(r.definition,function(i){return Yv(i,e)})):!1}Oi.isOptionalProd=Yv;function uIe(r){return r instanceof br.Alternation}Oi.isBranchingProd=uIe;function gIe(r){if(r instanceof br.NonTerminal)return"SUBRULE";if(r instanceof br.Option)return"OPTION";if(r instanceof br.Alternation)return"OR";if(r instanceof br.RepetitionMandatory)return"AT_LEAST_ONE";if(r instanceof br.RepetitionMandatoryWithSeparator)return"AT_LEAST_ONE_SEP";if(r instanceof br.RepetitionWithSeparator)return"MANY_SEP";if(r instanceof br.Repetition)return"MANY";if(r instanceof br.Terminal)return"CONSUME";throw Error("non exhaustive match")}Oi.getProductionDslName=gIe;var Lj=function(r){AIe(e,r);function e(){var t=r!==null&&r.apply(this,arguments)||this;return t.separator="-",t.dslMethods={option:[],alternation:[],repetition:[],repetitionWithSeparator:[],repetitionMandatory:[],repetitionMandatoryWithSeparator:[]},t}return e.prototype.reset=function(){this.dslMethods={option:[],alternation:[],repetition:[],repetitionWithSeparator:[],repetitionMandatory:[],repetitionMandatoryWithSeparator:[]}},e.prototype.visitTerminal=function(t){var i=t.terminalType.name+this.separator+"Terminal";(0,Sd.has)(this.dslMethods,i)||(this.dslMethods[i]=[]),this.dslMethods[i].push(t)},e.prototype.visitNonTerminal=function(t){var i=t.nonTerminalName+this.separator+"Terminal";(0,Sd.has)(this.dslMethods,i)||(this.dslMethods[i]=[]),this.dslMethods[i].push(t)},e.prototype.visitOption=function(t){this.dslMethods.option.push(t)},e.prototype.visitRepetitionWithSeparator=function(t){this.dslMethods.repetitionWithSeparator.push(t)},e.prototype.visitRepetitionMandatory=function(t){this.dslMethods.repetitionMandatory.push(t)},e.prototype.visitRepetitionMandatoryWithSeparator=function(t){this.dslMethods.repetitionMandatoryWithSeparator.push(t)},e.prototype.visitRepetition=function(t){this.dslMethods.repetition.push(t)},e.prototype.visitAlternation=function(t){this.dslMethods.alternation.push(t)},e}(lIe.GAstVisitor);Oi.DslMethodsCollectorVisitor=Lj;var cy=new Lj;function fIe(r){cy.reset(),r.accept(cy);var e=cy.dslMethods;return cy.reset(),e}Oi.collectMethods=fIe});var qv=w(No=>{"use strict";Object.defineProperty(No,"__esModule",{value:!0});No.firstForTerminal=No.firstForBranching=No.firstForSequence=No.first=void 0;var uy=Gt(),Mj=mn(),jv=vd();function gy(r){if(r instanceof Mj.NonTerminal)return gy(r.referencedRule);if(r instanceof Mj.Terminal)return Uj(r);if((0,jv.isSequenceProd)(r))return Oj(r);if((0,jv.isBranchingProd)(r))return Kj(r);throw Error("non exhaustive match")}No.first=gy;function Oj(r){for(var e=[],t=r.definition,i=0,n=t.length>i,s,o=!0;n&&o;)s=t[i],o=(0,jv.isOptionalProd)(s),e=e.concat(gy(s)),i=i+1,n=t.length>i;return(0,uy.uniq)(e)}No.firstForSequence=Oj;function Kj(r){var e=(0,uy.map)(r.definition,function(t){return gy(t)});return(0,uy.uniq)((0,uy.flatten)(e))}No.firstForBranching=Kj;function Uj(r){return[r.terminalType]}No.firstForTerminal=Uj});var Jv=w(fy=>{"use strict";Object.defineProperty(fy,"__esModule",{value:!0});fy.IN=void 0;fy.IN="_~IN~_"});var qj=w(fs=>{"use strict";var hIe=fs&&fs.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(fs,"__esModule",{value:!0});fs.buildInProdFollowPrefix=fs.buildBetweenProdsFollowPrefix=fs.computeAllProdsFollows=fs.ResyncFollowsWalker=void 0;var pIe=Ay(),dIe=qv(),Hj=Gt(),Gj=Jv(),CIe=mn(),Yj=function(r){hIe(e,r);function e(t){var i=r.call(this)||this;return i.topProd=t,i.follows={},i}return e.prototype.startWalking=function(){return this.walk(this.topProd),this.follows},e.prototype.walkTerminal=function(t,i,n){},e.prototype.walkProdRef=function(t,i,n){var s=jj(t.referencedRule,t.idx)+this.topProd.name,o=i.concat(n),a=new CIe.Alternative({definition:o}),l=(0,dIe.first)(a);this.follows[s]=l},e}(pIe.RestWalker);fs.ResyncFollowsWalker=Yj;function mIe(r){var e={};return(0,Hj.forEach)(r,function(t){var i=new Yj(t).startWalking();(0,Hj.assign)(e,i)}),e}fs.computeAllProdsFollows=mIe;function jj(r,e){return r.name+e+Gj.IN}fs.buildBetweenProdsFollowPrefix=jj;function EIe(r){var e=r.terminalType.name;return e+r.idx+Gj.IN}fs.buildInProdFollowPrefix=EIe});var xd=w(Da=>{"use strict";Object.defineProperty(Da,"__esModule",{value:!0});Da.defaultGrammarValidatorErrorProvider=Da.defaultGrammarResolverErrorProvider=Da.defaultParserErrorProvider=void 0;var ef=TA(),IIe=Gt(),eo=Gt(),Wv=mn(),Jj=vd();Da.defaultParserErrorProvider={buildMismatchTokenMessage:function(r){var e=r.expected,t=r.actual,i=r.previous,n=r.ruleName,s=(0,ef.hasTokenLabel)(e),o=s?"--> "+(0,ef.tokenLabel)(e)+" <--":"token of type --> "+e.name+" <--",a="Expecting "+o+" but found --> '"+t.image+"' <--";return a},buildNotAllInputParsedMessage:function(r){var e=r.firstRedundant,t=r.ruleName;return"Redundant input, expecting EOF but found: "+e.image},buildNoViableAltMessage:function(r){var e=r.expectedPathsPerAlt,t=r.actual,i=r.previous,n=r.customUserDescription,s=r.ruleName,o="Expecting: ",a=(0,eo.first)(t).image,l=` +but found: '`+a+"'";if(n)return o+n+l;var c=(0,eo.reduce)(e,function(h,p){return h.concat(p)},[]),u=(0,eo.map)(c,function(h){return"["+(0,eo.map)(h,function(p){return(0,ef.tokenLabel)(p)}).join(", ")+"]"}),g=(0,eo.map)(u,function(h,p){return" "+(p+1)+". "+h}),f=`one of these possible Token sequences: +`+g.join(` +`);return o+f+l},buildEarlyExitMessage:function(r){var e=r.expectedIterationPaths,t=r.actual,i=r.customUserDescription,n=r.ruleName,s="Expecting: ",o=(0,eo.first)(t).image,a=` +but found: '`+o+"'";if(i)return s+i+a;var l=(0,eo.map)(e,function(u){return"["+(0,eo.map)(u,function(g){return(0,ef.tokenLabel)(g)}).join(",")+"]"}),c=`expecting at least one iteration which starts with one of these possible Token sequences:: + `+("<"+l.join(" ,")+">");return s+c+a}};Object.freeze(Da.defaultParserErrorProvider);Da.defaultGrammarResolverErrorProvider={buildRuleNotFoundError:function(r,e){var t="Invalid grammar, reference to a rule which is not defined: ->"+e.nonTerminalName+`<- +inside top level rule: ->`+r.name+"<-";return t}};Da.defaultGrammarValidatorErrorProvider={buildDuplicateFoundError:function(r,e){function t(u){return u instanceof Wv.Terminal?u.terminalType.name:u instanceof Wv.NonTerminal?u.nonTerminalName:""}var i=r.name,n=(0,eo.first)(e),s=n.idx,o=(0,Jj.getProductionDslName)(n),a=t(n),l=s>0,c="->"+o+(l?s:"")+"<- "+(a?"with argument: ->"+a+"<-":"")+` + appears more than once (`+e.length+" times) in the top level rule: ->"+i+`<-. + For further details see: https://chevrotain.io/docs/FAQ.html#NUMERICAL_SUFFIXES + `;return c=c.replace(/[ \t]+/g," "),c=c.replace(/\s\s+/g,` +`),c},buildNamespaceConflictError:function(r){var e=`Namespace conflict found in grammar. +`+("The grammar has both a Terminal(Token) and a Non-Terminal(Rule) named: <"+r.name+`>. +`)+`To resolve this make sure each Terminal and Non-Terminal names are unique +This is easy to accomplish by using the convention that Terminal names start with an uppercase letter +and Non-Terminal names start with a lower case letter.`;return e},buildAlternationPrefixAmbiguityError:function(r){var e=(0,eo.map)(r.prefixPath,function(n){return(0,ef.tokenLabel)(n)}).join(", "),t=r.alternation.idx===0?"":r.alternation.idx,i="Ambiguous alternatives: <"+r.ambiguityIndices.join(" ,")+`> due to common lookahead prefix +`+("in inside <"+r.topLevelRule.name+`> Rule, +`)+("<"+e+`> may appears as a prefix path in all these alternatives. +`)+`See: https://chevrotain.io/docs/guide/resolving_grammar_errors.html#COMMON_PREFIX +For Further details.`;return i},buildAlternationAmbiguityError:function(r){var e=(0,eo.map)(r.prefixPath,function(n){return(0,ef.tokenLabel)(n)}).join(", "),t=r.alternation.idx===0?"":r.alternation.idx,i="Ambiguous Alternatives Detected: <"+r.ambiguityIndices.join(" ,")+"> in "+(" inside <"+r.topLevelRule.name+`> Rule, +`)+("<"+e+`> may appears as a prefix path in all these alternatives. +`);return i=i+`See: https://chevrotain.io/docs/guide/resolving_grammar_errors.html#AMBIGUOUS_ALTERNATIVES +For Further details.`,i},buildEmptyRepetitionError:function(r){var e=(0,Jj.getProductionDslName)(r.repetition);r.repetition.idx!==0&&(e+=r.repetition.idx);var t="The repetition <"+e+"> within Rule <"+r.topLevelRule.name+`> can never consume any tokens. +This could lead to an infinite loop.`;return t},buildTokenNameError:function(r){return"deprecated"},buildEmptyAlternationError:function(r){var e="Ambiguous empty alternative: <"+(r.emptyChoiceIdx+1)+">"+(" in inside <"+r.topLevelRule.name+`> Rule. +`)+"Only the last alternative may be an empty alternative.";return e},buildTooManyAlternativesError:function(r){var e=`An Alternation cannot have more than 256 alternatives: +`+(" inside <"+r.topLevelRule.name+`> Rule. + has `+(r.alternation.definition.length+1)+" alternatives.");return e},buildLeftRecursionError:function(r){var e=r.topLevelRule.name,t=IIe.map(r.leftRecursionPath,function(s){return s.name}),i=e+" --> "+t.concat([e]).join(" --> "),n=`Left Recursion found in grammar. +`+("rule: <"+e+`> can be invoked from itself (directly or indirectly) +`)+(`without consuming any Tokens. The grammar path that causes this is: + `+i+` +`)+` To fix this refactor your grammar to remove the left recursion. +see: https://en.wikipedia.org/wiki/LL_parser#Left_Factoring.`;return n},buildInvalidRuleNameError:function(r){return"deprecated"},buildDuplicateRuleNameError:function(r){var e;r.topLevelRule instanceof Wv.Rule?e=r.topLevelRule.name:e=r.topLevelRule;var t="Duplicate definition, rule: ->"+e+"<- is already defined in the grammar: ->"+r.grammarName+"<-";return t}}});var Vj=w(LA=>{"use strict";var yIe=LA&&LA.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(LA,"__esModule",{value:!0});LA.GastRefResolverVisitor=LA.resolveGrammar=void 0;var wIe=jn(),Wj=Gt(),BIe=$g();function bIe(r,e){var t=new zj(r,e);return t.resolveRefs(),t.errors}LA.resolveGrammar=bIe;var zj=function(r){yIe(e,r);function e(t,i){var n=r.call(this)||this;return n.nameToTopRule=t,n.errMsgProvider=i,n.errors=[],n}return e.prototype.resolveRefs=function(){var t=this;(0,Wj.forEach)((0,Wj.values)(this.nameToTopRule),function(i){t.currTopLevel=i,i.accept(t)})},e.prototype.visitNonTerminal=function(t){var i=this.nameToTopRule[t.nonTerminalName];if(i)t.referencedRule=i;else{var n=this.errMsgProvider.buildRuleNotFoundError(this.currTopLevel,t);this.errors.push({message:n,type:wIe.ParserDefinitionErrorType.UNRESOLVED_SUBRULE_REF,ruleName:this.currTopLevel.name,unresolvedRefName:t.nonTerminalName})}},e}(BIe.GAstVisitor);LA.GastRefResolverVisitor=zj});var Dd=w(Nr=>{"use strict";var mc=Nr&&Nr.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(Nr,"__esModule",{value:!0});Nr.nextPossibleTokensAfter=Nr.possiblePathsFrom=Nr.NextTerminalAfterAtLeastOneSepWalker=Nr.NextTerminalAfterAtLeastOneWalker=Nr.NextTerminalAfterManySepWalker=Nr.NextTerminalAfterManyWalker=Nr.AbstractNextTerminalAfterProductionWalker=Nr.NextAfterTokenWalker=Nr.AbstractNextPossibleTokensWalker=void 0;var Xj=Ay(),Kt=Gt(),QIe=qv(),kt=mn(),Zj=function(r){mc(e,r);function e(t,i){var n=r.call(this)||this;return n.topProd=t,n.path=i,n.possibleTokTypes=[],n.nextProductionName="",n.nextProductionOccurrence=0,n.found=!1,n.isAtEndOfPath=!1,n}return e.prototype.startWalking=function(){if(this.found=!1,this.path.ruleStack[0]!==this.topProd.name)throw Error("The path does not start with the walker's top Rule!");return this.ruleStack=(0,Kt.cloneArr)(this.path.ruleStack).reverse(),this.occurrenceStack=(0,Kt.cloneArr)(this.path.occurrenceStack).reverse(),this.ruleStack.pop(),this.occurrenceStack.pop(),this.updateExpectedNext(),this.walk(this.topProd),this.possibleTokTypes},e.prototype.walk=function(t,i){i===void 0&&(i=[]),this.found||r.prototype.walk.call(this,t,i)},e.prototype.walkProdRef=function(t,i,n){if(t.referencedRule.name===this.nextProductionName&&t.idx===this.nextProductionOccurrence){var s=i.concat(n);this.updateExpectedNext(),this.walk(t.referencedRule,s)}},e.prototype.updateExpectedNext=function(){(0,Kt.isEmpty)(this.ruleStack)?(this.nextProductionName="",this.nextProductionOccurrence=0,this.isAtEndOfPath=!0):(this.nextProductionName=this.ruleStack.pop(),this.nextProductionOccurrence=this.occurrenceStack.pop())},e}(Xj.RestWalker);Nr.AbstractNextPossibleTokensWalker=Zj;var SIe=function(r){mc(e,r);function e(t,i){var n=r.call(this,t,i)||this;return n.path=i,n.nextTerminalName="",n.nextTerminalOccurrence=0,n.nextTerminalName=n.path.lastTok.name,n.nextTerminalOccurrence=n.path.lastTokOccurrence,n}return e.prototype.walkTerminal=function(t,i,n){if(this.isAtEndOfPath&&t.terminalType.name===this.nextTerminalName&&t.idx===this.nextTerminalOccurrence&&!this.found){var s=i.concat(n),o=new kt.Alternative({definition:s});this.possibleTokTypes=(0,QIe.first)(o),this.found=!0}},e}(Zj);Nr.NextAfterTokenWalker=SIe;var Pd=function(r){mc(e,r);function e(t,i){var n=r.call(this)||this;return n.topRule=t,n.occurrence=i,n.result={token:void 0,occurrence:void 0,isEndOfRule:void 0},n}return e.prototype.startWalking=function(){return this.walk(this.topRule),this.result},e}(Xj.RestWalker);Nr.AbstractNextTerminalAfterProductionWalker=Pd;var vIe=function(r){mc(e,r);function e(){return r!==null&&r.apply(this,arguments)||this}return e.prototype.walkMany=function(t,i,n){if(t.idx===this.occurrence){var s=(0,Kt.first)(i.concat(n));this.result.isEndOfRule=s===void 0,s instanceof kt.Terminal&&(this.result.token=s.terminalType,this.result.occurrence=s.idx)}else r.prototype.walkMany.call(this,t,i,n)},e}(Pd);Nr.NextTerminalAfterManyWalker=vIe;var xIe=function(r){mc(e,r);function e(){return r!==null&&r.apply(this,arguments)||this}return e.prototype.walkManySep=function(t,i,n){if(t.idx===this.occurrence){var s=(0,Kt.first)(i.concat(n));this.result.isEndOfRule=s===void 0,s instanceof kt.Terminal&&(this.result.token=s.terminalType,this.result.occurrence=s.idx)}else r.prototype.walkManySep.call(this,t,i,n)},e}(Pd);Nr.NextTerminalAfterManySepWalker=xIe;var PIe=function(r){mc(e,r);function e(){return r!==null&&r.apply(this,arguments)||this}return e.prototype.walkAtLeastOne=function(t,i,n){if(t.idx===this.occurrence){var s=(0,Kt.first)(i.concat(n));this.result.isEndOfRule=s===void 0,s instanceof kt.Terminal&&(this.result.token=s.terminalType,this.result.occurrence=s.idx)}else r.prototype.walkAtLeastOne.call(this,t,i,n)},e}(Pd);Nr.NextTerminalAfterAtLeastOneWalker=PIe;var DIe=function(r){mc(e,r);function e(){return r!==null&&r.apply(this,arguments)||this}return e.prototype.walkAtLeastOneSep=function(t,i,n){if(t.idx===this.occurrence){var s=(0,Kt.first)(i.concat(n));this.result.isEndOfRule=s===void 0,s instanceof kt.Terminal&&(this.result.token=s.terminalType,this.result.occurrence=s.idx)}else r.prototype.walkAtLeastOneSep.call(this,t,i,n)},e}(Pd);Nr.NextTerminalAfterAtLeastOneSepWalker=DIe;function _j(r,e,t){t===void 0&&(t=[]),t=(0,Kt.cloneArr)(t);var i=[],n=0;function s(c){return c.concat((0,Kt.drop)(r,n+1))}function o(c){var u=_j(s(c),e,t);return i.concat(u)}for(;t.length=0;ge--){var re=B.definition[ge],M={idx:p,def:re.definition.concat((0,Kt.drop)(h)),ruleStack:C,occurrenceStack:y};g.push(M),g.push(o)}else if(B instanceof kt.Alternative)g.push({idx:p,def:B.definition.concat((0,Kt.drop)(h)),ruleStack:C,occurrenceStack:y});else if(B instanceof kt.Rule)g.push(RIe(B,p,C,y));else throw Error("non exhaustive match")}}return u}Nr.nextPossibleTokensAfter=kIe;function RIe(r,e,t,i){var n=(0,Kt.cloneArr)(t);n.push(r.name);var s=(0,Kt.cloneArr)(i);return s.push(1),{idx:e,def:r.definition,ruleStack:n,occurrenceStack:s}}});var kd=w(Zt=>{"use strict";var tq=Zt&&Zt.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(Zt,"__esModule",{value:!0});Zt.areTokenCategoriesNotUsed=Zt.isStrictPrefixOfPath=Zt.containsPath=Zt.getLookaheadPathsForOptionalProd=Zt.getLookaheadPathsForOr=Zt.lookAheadSequenceFromAlternatives=Zt.buildSingleAlternativeLookaheadFunction=Zt.buildAlternativesLookAheadFunc=Zt.buildLookaheadFuncForOptionalProd=Zt.buildLookaheadFuncForOr=Zt.getProdType=Zt.PROD_TYPE=void 0;var sr=Gt(),$j=Dd(),FIe=Ay(),hy=_g(),MA=mn(),NIe=$g(),oi;(function(r){r[r.OPTION=0]="OPTION",r[r.REPETITION=1]="REPETITION",r[r.REPETITION_MANDATORY=2]="REPETITION_MANDATORY",r[r.REPETITION_MANDATORY_WITH_SEPARATOR=3]="REPETITION_MANDATORY_WITH_SEPARATOR",r[r.REPETITION_WITH_SEPARATOR=4]="REPETITION_WITH_SEPARATOR",r[r.ALTERNATION=5]="ALTERNATION"})(oi=Zt.PROD_TYPE||(Zt.PROD_TYPE={}));function TIe(r){if(r instanceof MA.Option)return oi.OPTION;if(r instanceof MA.Repetition)return oi.REPETITION;if(r instanceof MA.RepetitionMandatory)return oi.REPETITION_MANDATORY;if(r instanceof MA.RepetitionMandatoryWithSeparator)return oi.REPETITION_MANDATORY_WITH_SEPARATOR;if(r instanceof MA.RepetitionWithSeparator)return oi.REPETITION_WITH_SEPARATOR;if(r instanceof MA.Alternation)return oi.ALTERNATION;throw Error("non exhaustive match")}Zt.getProdType=TIe;function LIe(r,e,t,i,n,s){var o=iq(r,e,t),a=Xv(o)?hy.tokenStructuredMatcherNoCategories:hy.tokenStructuredMatcher;return s(o,i,a,n)}Zt.buildLookaheadFuncForOr=LIe;function MIe(r,e,t,i,n,s){var o=nq(r,e,n,t),a=Xv(o)?hy.tokenStructuredMatcherNoCategories:hy.tokenStructuredMatcher;return s(o[0],a,i)}Zt.buildLookaheadFuncForOptionalProd=MIe;function OIe(r,e,t,i){var n=r.length,s=(0,sr.every)(r,function(l){return(0,sr.every)(l,function(c){return c.length===1})});if(e)return function(l){for(var c=(0,sr.map)(l,function(D){return D.GATE}),u=0;u{"use strict";var Zv=Vt&&Vt.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(Vt,"__esModule",{value:!0});Vt.checkPrefixAlternativesAmbiguities=Vt.validateSomeNonEmptyLookaheadPath=Vt.validateTooManyAlts=Vt.RepetionCollector=Vt.validateAmbiguousAlternationAlternatives=Vt.validateEmptyOrAlternative=Vt.getFirstNoneTerminal=Vt.validateNoLeftRecursion=Vt.validateRuleIsOverridden=Vt.validateRuleDoesNotAlreadyExist=Vt.OccurrenceValidationCollector=Vt.identifyProductionForDuplicates=Vt.validateGrammar=void 0;var er=Gt(),Qr=Gt(),To=jn(),_v=vd(),tf=kd(),YIe=Dd(),to=mn(),$v=$g();function jIe(r,e,t,i,n){var s=er.map(r,function(h){return qIe(h,i)}),o=er.map(r,function(h){return ex(h,h,i)}),a=[],l=[],c=[];(0,Qr.every)(o,Qr.isEmpty)&&(a=(0,Qr.map)(r,function(h){return cq(h,i)}),l=(0,Qr.map)(r,function(h){return uq(h,e,i)}),c=hq(r,e,i));var u=zIe(r,t,i),g=(0,Qr.map)(r,function(h){return fq(h,i)}),f=(0,Qr.map)(r,function(h){return lq(h,r,n,i)});return er.flatten(s.concat(c,o,a,l,u,g,f))}Vt.validateGrammar=jIe;function qIe(r,e){var t=new Aq;r.accept(t);var i=t.allProductions,n=er.groupBy(i,oq),s=er.pick(n,function(a){return a.length>1}),o=er.map(er.values(s),function(a){var l=er.first(a),c=e.buildDuplicateFoundError(r,a),u=(0,_v.getProductionDslName)(l),g={message:c,type:To.ParserDefinitionErrorType.DUPLICATE_PRODUCTIONS,ruleName:r.name,dslName:u,occurrence:l.idx},f=aq(l);return f&&(g.parameter=f),g});return o}function oq(r){return(0,_v.getProductionDslName)(r)+"_#_"+r.idx+"_#_"+aq(r)}Vt.identifyProductionForDuplicates=oq;function aq(r){return r instanceof to.Terminal?r.terminalType.name:r instanceof to.NonTerminal?r.nonTerminalName:""}var Aq=function(r){Zv(e,r);function e(){var t=r!==null&&r.apply(this,arguments)||this;return t.allProductions=[],t}return e.prototype.visitNonTerminal=function(t){this.allProductions.push(t)},e.prototype.visitOption=function(t){this.allProductions.push(t)},e.prototype.visitRepetitionWithSeparator=function(t){this.allProductions.push(t)},e.prototype.visitRepetitionMandatory=function(t){this.allProductions.push(t)},e.prototype.visitRepetitionMandatoryWithSeparator=function(t){this.allProductions.push(t)},e.prototype.visitRepetition=function(t){this.allProductions.push(t)},e.prototype.visitAlternation=function(t){this.allProductions.push(t)},e.prototype.visitTerminal=function(t){this.allProductions.push(t)},e}($v.GAstVisitor);Vt.OccurrenceValidationCollector=Aq;function lq(r,e,t,i){var n=[],s=(0,Qr.reduce)(e,function(a,l){return l.name===r.name?a+1:a},0);if(s>1){var o=i.buildDuplicateRuleNameError({topLevelRule:r,grammarName:t});n.push({message:o,type:To.ParserDefinitionErrorType.DUPLICATE_RULE_NAME,ruleName:r.name})}return n}Vt.validateRuleDoesNotAlreadyExist=lq;function JIe(r,e,t){var i=[],n;return er.contains(e,r)||(n="Invalid rule override, rule: ->"+r+"<- cannot be overridden in the grammar: ->"+t+"<-as it is not defined in any of the super grammars ",i.push({message:n,type:To.ParserDefinitionErrorType.INVALID_RULE_OVERRIDE,ruleName:r})),i}Vt.validateRuleIsOverridden=JIe;function ex(r,e,t,i){i===void 0&&(i=[]);var n=[],s=Rd(e.definition);if(er.isEmpty(s))return[];var o=r.name,a=er.contains(s,r);a&&n.push({message:t.buildLeftRecursionError({topLevelRule:r,leftRecursionPath:i}),type:To.ParserDefinitionErrorType.LEFT_RECURSION,ruleName:o});var l=er.difference(s,i.concat([r])),c=er.map(l,function(u){var g=er.cloneArr(i);return g.push(u),ex(r,u,t,g)});return n.concat(er.flatten(c))}Vt.validateNoLeftRecursion=ex;function Rd(r){var e=[];if(er.isEmpty(r))return e;var t=er.first(r);if(t instanceof to.NonTerminal)e.push(t.referencedRule);else if(t instanceof to.Alternative||t instanceof to.Option||t instanceof to.RepetitionMandatory||t instanceof to.RepetitionMandatoryWithSeparator||t instanceof to.RepetitionWithSeparator||t instanceof to.Repetition)e=e.concat(Rd(t.definition));else if(t instanceof to.Alternation)e=er.flatten(er.map(t.definition,function(o){return Rd(o.definition)}));else if(!(t instanceof to.Terminal))throw Error("non exhaustive match");var i=(0,_v.isOptionalProd)(t),n=r.length>1;if(i&&n){var s=er.drop(r);return e.concat(Rd(s))}else return e}Vt.getFirstNoneTerminal=Rd;var tx=function(r){Zv(e,r);function e(){var t=r!==null&&r.apply(this,arguments)||this;return t.alternations=[],t}return e.prototype.visitAlternation=function(t){this.alternations.push(t)},e}($v.GAstVisitor);function cq(r,e){var t=new tx;r.accept(t);var i=t.alternations,n=er.reduce(i,function(s,o){var a=er.dropRight(o.definition),l=er.map(a,function(c,u){var g=(0,YIe.nextPossibleTokensAfter)([c],[],null,1);return er.isEmpty(g)?{message:e.buildEmptyAlternationError({topLevelRule:r,alternation:o,emptyChoiceIdx:u}),type:To.ParserDefinitionErrorType.NONE_LAST_EMPTY_ALT,ruleName:r.name,occurrence:o.idx,alternative:u+1}:null});return s.concat(er.compact(l))},[]);return n}Vt.validateEmptyOrAlternative=cq;function uq(r,e,t){var i=new tx;r.accept(i);var n=i.alternations;n=(0,Qr.reject)(n,function(o){return o.ignoreAmbiguities===!0});var s=er.reduce(n,function(o,a){var l=a.idx,c=a.maxLookahead||e,u=(0,tf.getLookaheadPathsForOr)(l,r,c,a),g=WIe(u,a,r,t),f=pq(u,a,r,t);return o.concat(g,f)},[]);return s}Vt.validateAmbiguousAlternationAlternatives=uq;var gq=function(r){Zv(e,r);function e(){var t=r!==null&&r.apply(this,arguments)||this;return t.allProductions=[],t}return e.prototype.visitRepetitionWithSeparator=function(t){this.allProductions.push(t)},e.prototype.visitRepetitionMandatory=function(t){this.allProductions.push(t)},e.prototype.visitRepetitionMandatoryWithSeparator=function(t){this.allProductions.push(t)},e.prototype.visitRepetition=function(t){this.allProductions.push(t)},e}($v.GAstVisitor);Vt.RepetionCollector=gq;function fq(r,e){var t=new tx;r.accept(t);var i=t.alternations,n=er.reduce(i,function(s,o){return o.definition.length>255&&s.push({message:e.buildTooManyAlternativesError({topLevelRule:r,alternation:o}),type:To.ParserDefinitionErrorType.TOO_MANY_ALTS,ruleName:r.name,occurrence:o.idx}),s},[]);return n}Vt.validateTooManyAlts=fq;function hq(r,e,t){var i=[];return(0,Qr.forEach)(r,function(n){var s=new gq;n.accept(s);var o=s.allProductions;(0,Qr.forEach)(o,function(a){var l=(0,tf.getProdType)(a),c=a.maxLookahead||e,u=a.idx,g=(0,tf.getLookaheadPathsForOptionalProd)(u,n,l,c),f=g[0];if((0,Qr.isEmpty)((0,Qr.flatten)(f))){var h=t.buildEmptyRepetitionError({topLevelRule:n,repetition:a});i.push({message:h,type:To.ParserDefinitionErrorType.NO_NON_EMPTY_LOOKAHEAD,ruleName:n.name})}})}),i}Vt.validateSomeNonEmptyLookaheadPath=hq;function WIe(r,e,t,i){var n=[],s=(0,Qr.reduce)(r,function(a,l,c){return e.definition[c].ignoreAmbiguities===!0||(0,Qr.forEach)(l,function(u){var g=[c];(0,Qr.forEach)(r,function(f,h){c!==h&&(0,tf.containsPath)(f,u)&&e.definition[h].ignoreAmbiguities!==!0&&g.push(h)}),g.length>1&&!(0,tf.containsPath)(n,u)&&(n.push(u),a.push({alts:g,path:u}))}),a},[]),o=er.map(s,function(a){var l=(0,Qr.map)(a.alts,function(u){return u+1}),c=i.buildAlternationAmbiguityError({topLevelRule:t,alternation:e,ambiguityIndices:l,prefixPath:a.path});return{message:c,type:To.ParserDefinitionErrorType.AMBIGUOUS_ALTS,ruleName:t.name,occurrence:e.idx,alternatives:[a.alts]}});return o}function pq(r,e,t,i){var n=[],s=(0,Qr.reduce)(r,function(o,a,l){var c=(0,Qr.map)(a,function(u){return{idx:l,path:u}});return o.concat(c)},[]);return(0,Qr.forEach)(s,function(o){var a=e.definition[o.idx];if(a.ignoreAmbiguities!==!0){var l=o.idx,c=o.path,u=(0,Qr.findAll)(s,function(f){return e.definition[f.idx].ignoreAmbiguities!==!0&&f.idx{"use strict";Object.defineProperty(rf,"__esModule",{value:!0});rf.validateGrammar=rf.resolveGrammar=void 0;var ix=Gt(),VIe=Vj(),XIe=rx(),dq=xd();function ZIe(r){r=(0,ix.defaults)(r,{errMsgProvider:dq.defaultGrammarResolverErrorProvider});var e={};return(0,ix.forEach)(r.rules,function(t){e[t.name]=t}),(0,VIe.resolveGrammar)(e,r.errMsgProvider)}rf.resolveGrammar=ZIe;function _Ie(r){return r=(0,ix.defaults)(r,{errMsgProvider:dq.defaultGrammarValidatorErrorProvider}),(0,XIe.validateGrammar)(r.rules,r.maxLookahead,r.tokenTypes,r.errMsgProvider,r.grammarName)}rf.validateGrammar=_Ie});var nf=w(In=>{"use strict";var Fd=In&&In.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(In,"__esModule",{value:!0});In.EarlyExitException=In.NotAllInputParsedException=In.NoViableAltException=In.MismatchedTokenException=In.isRecognitionException=void 0;var $Ie=Gt(),mq="MismatchedTokenException",Eq="NoViableAltException",Iq="EarlyExitException",yq="NotAllInputParsedException",wq=[mq,Eq,Iq,yq];Object.freeze(wq);function eye(r){return(0,$Ie.contains)(wq,r.name)}In.isRecognitionException=eye;var py=function(r){Fd(e,r);function e(t,i){var n=this.constructor,s=r.call(this,t)||this;return s.token=i,s.resyncedTokens=[],Object.setPrototypeOf(s,n.prototype),Error.captureStackTrace&&Error.captureStackTrace(s,s.constructor),s}return e}(Error),tye=function(r){Fd(e,r);function e(t,i,n){var s=r.call(this,t,i)||this;return s.previousToken=n,s.name=mq,s}return e}(py);In.MismatchedTokenException=tye;var rye=function(r){Fd(e,r);function e(t,i,n){var s=r.call(this,t,i)||this;return s.previousToken=n,s.name=Eq,s}return e}(py);In.NoViableAltException=rye;var iye=function(r){Fd(e,r);function e(t,i){var n=r.call(this,t,i)||this;return n.name=yq,n}return e}(py);In.NotAllInputParsedException=iye;var nye=function(r){Fd(e,r);function e(t,i,n){var s=r.call(this,t,i)||this;return s.previousToken=n,s.name=Iq,s}return e}(py);In.EarlyExitException=nye});var sx=w(Ki=>{"use strict";Object.defineProperty(Ki,"__esModule",{value:!0});Ki.attemptInRepetitionRecovery=Ki.Recoverable=Ki.InRuleRecoveryException=Ki.IN_RULE_RECOVERY_EXCEPTION=Ki.EOF_FOLLOW_KEY=void 0;var dy=TA(),hs=Gt(),sye=nf(),oye=Jv(),aye=jn();Ki.EOF_FOLLOW_KEY={};Ki.IN_RULE_RECOVERY_EXCEPTION="InRuleRecoveryException";function nx(r){this.name=Ki.IN_RULE_RECOVERY_EXCEPTION,this.message=r}Ki.InRuleRecoveryException=nx;nx.prototype=Error.prototype;var Aye=function(){function r(){}return r.prototype.initRecoverable=function(e){this.firstAfterRepMap={},this.resyncFollows={},this.recoveryEnabled=(0,hs.has)(e,"recoveryEnabled")?e.recoveryEnabled:aye.DEFAULT_PARSER_CONFIG.recoveryEnabled,this.recoveryEnabled&&(this.attemptInRepetitionRecovery=Bq)},r.prototype.getTokenToInsert=function(e){var t=(0,dy.createTokenInstance)(e,"",NaN,NaN,NaN,NaN,NaN,NaN);return t.isInsertedInRecovery=!0,t},r.prototype.canTokenTypeBeInsertedInRecovery=function(e){return!0},r.prototype.tryInRepetitionRecovery=function(e,t,i,n){for(var s=this,o=this.findReSyncTokenType(),a=this.exportLexerState(),l=[],c=!1,u=this.LA(1),g=this.LA(1),f=function(){var h=s.LA(0),p=s.errorMessageProvider.buildMismatchTokenMessage({expected:n,actual:u,previous:h,ruleName:s.getCurrRuleFullName()}),C=new sye.MismatchedTokenException(p,u,s.LA(0));C.resyncedTokens=(0,hs.dropRight)(l),s.SAVE_ERROR(C)};!c;)if(this.tokenMatcher(g,n)){f();return}else if(i.call(this)){f(),e.apply(this,t);return}else this.tokenMatcher(g,o)?c=!0:(g=this.SKIP_TOKEN(),this.addToResyncTokens(g,l));this.importLexerState(a)},r.prototype.shouldInRepetitionRecoveryBeTried=function(e,t,i){return!(i===!1||e===void 0||t===void 0||this.tokenMatcher(this.LA(1),e)||this.isBackTracking()||this.canPerformInRuleRecovery(e,this.getFollowsForInRuleRecovery(e,t)))},r.prototype.getFollowsForInRuleRecovery=function(e,t){var i=this.getCurrentGrammarPath(e,t),n=this.getNextPossibleTokenTypes(i);return n},r.prototype.tryInRuleRecovery=function(e,t){if(this.canRecoverWithSingleTokenInsertion(e,t)){var i=this.getTokenToInsert(e);return i}if(this.canRecoverWithSingleTokenDeletion(e)){var n=this.SKIP_TOKEN();return this.consumeToken(),n}throw new nx("sad sad panda")},r.prototype.canPerformInRuleRecovery=function(e,t){return this.canRecoverWithSingleTokenInsertion(e,t)||this.canRecoverWithSingleTokenDeletion(e)},r.prototype.canRecoverWithSingleTokenInsertion=function(e,t){var i=this;if(!this.canTokenTypeBeInsertedInRecovery(e)||(0,hs.isEmpty)(t))return!1;var n=this.LA(1),s=(0,hs.find)(t,function(o){return i.tokenMatcher(n,o)})!==void 0;return s},r.prototype.canRecoverWithSingleTokenDeletion=function(e){var t=this.tokenMatcher(this.LA(2),e);return t},r.prototype.isInCurrentRuleReSyncSet=function(e){var t=this.getCurrFollowKey(),i=this.getFollowSetFromFollowKey(t);return(0,hs.contains)(i,e)},r.prototype.findReSyncTokenType=function(){for(var e=this.flattenFollowSet(),t=this.LA(1),i=2;;){var n=t.tokenType;if((0,hs.contains)(e,n))return n;t=this.LA(i),i++}},r.prototype.getCurrFollowKey=function(){if(this.RULE_STACK.length===1)return Ki.EOF_FOLLOW_KEY;var e=this.getLastExplicitRuleShortName(),t=this.getLastExplicitRuleOccurrenceIndex(),i=this.getPreviousExplicitRuleShortName();return{ruleName:this.shortRuleNameToFullName(e),idxInCallingRule:t,inRule:this.shortRuleNameToFullName(i)}},r.prototype.buildFullFollowKeyStack=function(){var e=this,t=this.RULE_STACK,i=this.RULE_OCCURRENCE_STACK;return(0,hs.map)(t,function(n,s){return s===0?Ki.EOF_FOLLOW_KEY:{ruleName:e.shortRuleNameToFullName(n),idxInCallingRule:i[s],inRule:e.shortRuleNameToFullName(t[s-1])}})},r.prototype.flattenFollowSet=function(){var e=this,t=(0,hs.map)(this.buildFullFollowKeyStack(),function(i){return e.getFollowSetFromFollowKey(i)});return(0,hs.flatten)(t)},r.prototype.getFollowSetFromFollowKey=function(e){if(e===Ki.EOF_FOLLOW_KEY)return[dy.EOF];var t=e.ruleName+e.idxInCallingRule+oye.IN+e.inRule;return this.resyncFollows[t]},r.prototype.addToResyncTokens=function(e,t){return this.tokenMatcher(e,dy.EOF)||t.push(e),t},r.prototype.reSyncTo=function(e){for(var t=[],i=this.LA(1);this.tokenMatcher(i,e)===!1;)i=this.SKIP_TOKEN(),this.addToResyncTokens(i,t);return(0,hs.dropRight)(t)},r.prototype.attemptInRepetitionRecovery=function(e,t,i,n,s,o,a){},r.prototype.getCurrentGrammarPath=function(e,t){var i=this.getHumanReadableRuleStack(),n=(0,hs.cloneArr)(this.RULE_OCCURRENCE_STACK),s={ruleStack:i,occurrenceStack:n,lastTok:e,lastTokOccurrence:t};return s},r.prototype.getHumanReadableRuleStack=function(){var e=this;return(0,hs.map)(this.RULE_STACK,function(t){return e.shortRuleNameToFullName(t)})},r}();Ki.Recoverable=Aye;function Bq(r,e,t,i,n,s,o){var a=this.getKeyForAutomaticLookahead(i,n),l=this.firstAfterRepMap[a];if(l===void 0){var c=this.getCurrRuleFullName(),u=this.getGAstProductions()[c],g=new s(u,n);l=g.startWalking(),this.firstAfterRepMap[a]=l}var f=l.token,h=l.occurrence,p=l.isEndOfRule;this.RULE_STACK.length===1&&p&&f===void 0&&(f=dy.EOF,h=1),this.shouldInRepetitionRecoveryBeTried(f,h,o)&&this.tryInRepetitionRecovery(r,e,t,f)}Ki.attemptInRepetitionRecovery=Bq});var Cy=w(Jt=>{"use strict";Object.defineProperty(Jt,"__esModule",{value:!0});Jt.getKeyForAutomaticLookahead=Jt.AT_LEAST_ONE_SEP_IDX=Jt.MANY_SEP_IDX=Jt.AT_LEAST_ONE_IDX=Jt.MANY_IDX=Jt.OPTION_IDX=Jt.OR_IDX=Jt.BITS_FOR_ALT_IDX=Jt.BITS_FOR_RULE_IDX=Jt.BITS_FOR_OCCURRENCE_IDX=Jt.BITS_FOR_METHOD_TYPE=void 0;Jt.BITS_FOR_METHOD_TYPE=4;Jt.BITS_FOR_OCCURRENCE_IDX=8;Jt.BITS_FOR_RULE_IDX=12;Jt.BITS_FOR_ALT_IDX=8;Jt.OR_IDX=1<{"use strict";Object.defineProperty(my,"__esModule",{value:!0});my.LooksAhead=void 0;var ka=kd(),ro=Gt(),bq=jn(),Ra=Cy(),Ec=vd(),cye=function(){function r(){}return r.prototype.initLooksAhead=function(e){this.dynamicTokensEnabled=(0,ro.has)(e,"dynamicTokensEnabled")?e.dynamicTokensEnabled:bq.DEFAULT_PARSER_CONFIG.dynamicTokensEnabled,this.maxLookahead=(0,ro.has)(e,"maxLookahead")?e.maxLookahead:bq.DEFAULT_PARSER_CONFIG.maxLookahead,this.lookAheadFuncsCache=(0,ro.isES2015MapSupported)()?new Map:[],(0,ro.isES2015MapSupported)()?(this.getLaFuncFromCache=this.getLaFuncFromMap,this.setLaFuncCache=this.setLaFuncCacheUsingMap):(this.getLaFuncFromCache=this.getLaFuncFromObj,this.setLaFuncCache=this.setLaFuncUsingObj)},r.prototype.preComputeLookaheadFunctions=function(e){var t=this;(0,ro.forEach)(e,function(i){t.TRACE_INIT(i.name+" Rule Lookahead",function(){var n=(0,Ec.collectMethods)(i),s=n.alternation,o=n.repetition,a=n.option,l=n.repetitionMandatory,c=n.repetitionMandatoryWithSeparator,u=n.repetitionWithSeparator;(0,ro.forEach)(s,function(g){var f=g.idx===0?"":g.idx;t.TRACE_INIT(""+(0,Ec.getProductionDslName)(g)+f,function(){var h=(0,ka.buildLookaheadFuncForOr)(g.idx,i,g.maxLookahead||t.maxLookahead,g.hasPredicates,t.dynamicTokensEnabled,t.lookAheadBuilderForAlternatives),p=(0,Ra.getKeyForAutomaticLookahead)(t.fullRuleNameToShort[i.name],Ra.OR_IDX,g.idx);t.setLaFuncCache(p,h)})}),(0,ro.forEach)(o,function(g){t.computeLookaheadFunc(i,g.idx,Ra.MANY_IDX,ka.PROD_TYPE.REPETITION,g.maxLookahead,(0,Ec.getProductionDslName)(g))}),(0,ro.forEach)(a,function(g){t.computeLookaheadFunc(i,g.idx,Ra.OPTION_IDX,ka.PROD_TYPE.OPTION,g.maxLookahead,(0,Ec.getProductionDslName)(g))}),(0,ro.forEach)(l,function(g){t.computeLookaheadFunc(i,g.idx,Ra.AT_LEAST_ONE_IDX,ka.PROD_TYPE.REPETITION_MANDATORY,g.maxLookahead,(0,Ec.getProductionDslName)(g))}),(0,ro.forEach)(c,function(g){t.computeLookaheadFunc(i,g.idx,Ra.AT_LEAST_ONE_SEP_IDX,ka.PROD_TYPE.REPETITION_MANDATORY_WITH_SEPARATOR,g.maxLookahead,(0,Ec.getProductionDslName)(g))}),(0,ro.forEach)(u,function(g){t.computeLookaheadFunc(i,g.idx,Ra.MANY_SEP_IDX,ka.PROD_TYPE.REPETITION_WITH_SEPARATOR,g.maxLookahead,(0,Ec.getProductionDslName)(g))})})})},r.prototype.computeLookaheadFunc=function(e,t,i,n,s,o){var a=this;this.TRACE_INIT(""+o+(t===0?"":t),function(){var l=(0,ka.buildLookaheadFuncForOptionalProd)(t,e,s||a.maxLookahead,a.dynamicTokensEnabled,n,a.lookAheadBuilderForOptional),c=(0,Ra.getKeyForAutomaticLookahead)(a.fullRuleNameToShort[e.name],i,t);a.setLaFuncCache(c,l)})},r.prototype.lookAheadBuilderForOptional=function(e,t,i){return(0,ka.buildSingleAlternativeLookaheadFunction)(e,t,i)},r.prototype.lookAheadBuilderForAlternatives=function(e,t,i,n){return(0,ka.buildAlternativesLookAheadFunc)(e,t,i,n)},r.prototype.getKeyForAutomaticLookahead=function(e,t){var i=this.getLastExplicitRuleShortName();return(0,Ra.getKeyForAutomaticLookahead)(i,e,t)},r.prototype.getLaFuncFromCache=function(e){},r.prototype.getLaFuncFromMap=function(e){return this.lookAheadFuncsCache.get(e)},r.prototype.getLaFuncFromObj=function(e){return this.lookAheadFuncsCache[e]},r.prototype.setLaFuncCache=function(e,t){},r.prototype.setLaFuncCacheUsingMap=function(e,t){this.lookAheadFuncsCache.set(e,t)},r.prototype.setLaFuncUsingObj=function(e,t){this.lookAheadFuncsCache[e]=t},r}();my.LooksAhead=cye});var Sq=w(Lo=>{"use strict";Object.defineProperty(Lo,"__esModule",{value:!0});Lo.addNoneTerminalToCst=Lo.addTerminalToCst=Lo.setNodeLocationFull=Lo.setNodeLocationOnlyOffset=void 0;function uye(r,e){isNaN(r.startOffset)===!0?(r.startOffset=e.startOffset,r.endOffset=e.endOffset):r.endOffset{"use strict";Object.defineProperty(OA,"__esModule",{value:!0});OA.defineNameProp=OA.functionName=OA.classNameFromInstance=void 0;var pye=Gt();function dye(r){return xq(r.constructor)}OA.classNameFromInstance=dye;var vq="name";function xq(r){var e=r.name;return e||"anonymous"}OA.functionName=xq;function Cye(r,e){var t=Object.getOwnPropertyDescriptor(r,vq);return(0,pye.isUndefined)(t)||t.configurable?(Object.defineProperty(r,vq,{enumerable:!1,configurable:!0,writable:!1,value:e}),!0):!1}OA.defineNameProp=Cye});var Fq=w(Si=>{"use strict";Object.defineProperty(Si,"__esModule",{value:!0});Si.validateRedundantMethods=Si.validateMissingCstMethods=Si.validateVisitor=Si.CstVisitorDefinitionError=Si.createBaseVisitorConstructorWithDefaults=Si.createBaseSemanticVisitorConstructor=Si.defaultVisit=void 0;var ps=Gt(),Nd=ox();function Pq(r,e){for(var t=(0,ps.keys)(r),i=t.length,n=0;n: + `+(""+s.join(` + +`).replace(/\n/g,` + `)))}}};return t.prototype=i,t.prototype.constructor=t,t._RULE_NAMES=e,t}Si.createBaseSemanticVisitorConstructor=mye;function Eye(r,e,t){var i=function(){};(0,Nd.defineNameProp)(i,r+"BaseSemanticsWithDefaults");var n=Object.create(t.prototype);return(0,ps.forEach)(e,function(s){n[s]=Pq}),i.prototype=n,i.prototype.constructor=i,i}Si.createBaseVisitorConstructorWithDefaults=Eye;var ax;(function(r){r[r.REDUNDANT_METHOD=0]="REDUNDANT_METHOD",r[r.MISSING_METHOD=1]="MISSING_METHOD"})(ax=Si.CstVisitorDefinitionError||(Si.CstVisitorDefinitionError={}));function Dq(r,e){var t=kq(r,e),i=Rq(r,e);return t.concat(i)}Si.validateVisitor=Dq;function kq(r,e){var t=(0,ps.map)(e,function(i){if(!(0,ps.isFunction)(r[i]))return{msg:"Missing visitor method: <"+i+"> on "+(0,Nd.functionName)(r.constructor)+" CST Visitor.",type:ax.MISSING_METHOD,methodName:i}});return(0,ps.compact)(t)}Si.validateMissingCstMethods=kq;var Iye=["constructor","visit","validateVisitor"];function Rq(r,e){var t=[];for(var i in r)(0,ps.isFunction)(r[i])&&!(0,ps.contains)(Iye,i)&&!(0,ps.contains)(e,i)&&t.push({msg:"Redundant visitor method: <"+i+"> on "+(0,Nd.functionName)(r.constructor)+` CST Visitor +There is no Grammar Rule corresponding to this method's name. +`,type:ax.REDUNDANT_METHOD,methodName:i});return t}Si.validateRedundantMethods=Rq});var Tq=w(Ey=>{"use strict";Object.defineProperty(Ey,"__esModule",{value:!0});Ey.TreeBuilder=void 0;var sf=Sq(),_r=Gt(),Nq=Fq(),yye=jn(),wye=function(){function r(){}return r.prototype.initTreeBuilder=function(e){if(this.CST_STACK=[],this.outputCst=e.outputCst,this.nodeLocationTracking=(0,_r.has)(e,"nodeLocationTracking")?e.nodeLocationTracking:yye.DEFAULT_PARSER_CONFIG.nodeLocationTracking,!this.outputCst)this.cstInvocationStateUpdate=_r.NOOP,this.cstFinallyStateUpdate=_r.NOOP,this.cstPostTerminal=_r.NOOP,this.cstPostNonTerminal=_r.NOOP,this.cstPostRule=_r.NOOP;else if(/full/i.test(this.nodeLocationTracking))this.recoveryEnabled?(this.setNodeLocationFromToken=sf.setNodeLocationFull,this.setNodeLocationFromNode=sf.setNodeLocationFull,this.cstPostRule=_r.NOOP,this.setInitialNodeLocation=this.setInitialNodeLocationFullRecovery):(this.setNodeLocationFromToken=_r.NOOP,this.setNodeLocationFromNode=_r.NOOP,this.cstPostRule=this.cstPostRuleFull,this.setInitialNodeLocation=this.setInitialNodeLocationFullRegular);else if(/onlyOffset/i.test(this.nodeLocationTracking))this.recoveryEnabled?(this.setNodeLocationFromToken=sf.setNodeLocationOnlyOffset,this.setNodeLocationFromNode=sf.setNodeLocationOnlyOffset,this.cstPostRule=_r.NOOP,this.setInitialNodeLocation=this.setInitialNodeLocationOnlyOffsetRecovery):(this.setNodeLocationFromToken=_r.NOOP,this.setNodeLocationFromNode=_r.NOOP,this.cstPostRule=this.cstPostRuleOnlyOffset,this.setInitialNodeLocation=this.setInitialNodeLocationOnlyOffsetRegular);else if(/none/i.test(this.nodeLocationTracking))this.setNodeLocationFromToken=_r.NOOP,this.setNodeLocationFromNode=_r.NOOP,this.cstPostRule=_r.NOOP,this.setInitialNodeLocation=_r.NOOP;else throw Error('Invalid config option: "'+e.nodeLocationTracking+'"')},r.prototype.setInitialNodeLocationOnlyOffsetRecovery=function(e){e.location={startOffset:NaN,endOffset:NaN}},r.prototype.setInitialNodeLocationOnlyOffsetRegular=function(e){e.location={startOffset:this.LA(1).startOffset,endOffset:NaN}},r.prototype.setInitialNodeLocationFullRecovery=function(e){e.location={startOffset:NaN,startLine:NaN,startColumn:NaN,endOffset:NaN,endLine:NaN,endColumn:NaN}},r.prototype.setInitialNodeLocationFullRegular=function(e){var t=this.LA(1);e.location={startOffset:t.startOffset,startLine:t.startLine,startColumn:t.startColumn,endOffset:NaN,endLine:NaN,endColumn:NaN}},r.prototype.cstInvocationStateUpdate=function(e,t){var i={name:e,children:{}};this.setInitialNodeLocation(i),this.CST_STACK.push(i)},r.prototype.cstFinallyStateUpdate=function(){this.CST_STACK.pop()},r.prototype.cstPostRuleFull=function(e){var t=this.LA(0),i=e.location;i.startOffset<=t.startOffset?(i.endOffset=t.endOffset,i.endLine=t.endLine,i.endColumn=t.endColumn):(i.startOffset=NaN,i.startLine=NaN,i.startColumn=NaN)},r.prototype.cstPostRuleOnlyOffset=function(e){var t=this.LA(0),i=e.location;i.startOffset<=t.startOffset?i.endOffset=t.endOffset:i.startOffset=NaN},r.prototype.cstPostTerminal=function(e,t){var i=this.CST_STACK[this.CST_STACK.length-1];(0,sf.addTerminalToCst)(i,t,e),this.setNodeLocationFromToken(i.location,t)},r.prototype.cstPostNonTerminal=function(e,t){var i=this.CST_STACK[this.CST_STACK.length-1];(0,sf.addNoneTerminalToCst)(i,t,e),this.setNodeLocationFromNode(i.location,e.location)},r.prototype.getBaseCstVisitorConstructor=function(){if((0,_r.isUndefined)(this.baseCstVisitorConstructor)){var e=(0,Nq.createBaseSemanticVisitorConstructor)(this.className,(0,_r.keys)(this.gastProductionsCache));return this.baseCstVisitorConstructor=e,e}return this.baseCstVisitorConstructor},r.prototype.getBaseCstVisitorConstructorWithDefaults=function(){if((0,_r.isUndefined)(this.baseCstVisitorWithDefaultsConstructor)){var e=(0,Nq.createBaseVisitorConstructorWithDefaults)(this.className,(0,_r.keys)(this.gastProductionsCache),this.getBaseCstVisitorConstructor());return this.baseCstVisitorWithDefaultsConstructor=e,e}return this.baseCstVisitorWithDefaultsConstructor},r.prototype.getLastExplicitRuleShortName=function(){var e=this.RULE_STACK;return e[e.length-1]},r.prototype.getPreviousExplicitRuleShortName=function(){var e=this.RULE_STACK;return e[e.length-2]},r.prototype.getLastExplicitRuleOccurrenceIndex=function(){var e=this.RULE_OCCURRENCE_STACK;return e[e.length-1]},r}();Ey.TreeBuilder=wye});var Mq=w(Iy=>{"use strict";Object.defineProperty(Iy,"__esModule",{value:!0});Iy.LexerAdapter=void 0;var Lq=jn(),Bye=function(){function r(){}return r.prototype.initLexerAdapter=function(){this.tokVector=[],this.tokVectorLength=0,this.currIdx=-1},Object.defineProperty(r.prototype,"input",{get:function(){return this.tokVector},set:function(e){if(this.selfAnalysisDone!==!0)throw Error("Missing invocation at the end of the Parser's constructor.");this.reset(),this.tokVector=e,this.tokVectorLength=e.length},enumerable:!1,configurable:!0}),r.prototype.SKIP_TOKEN=function(){return this.currIdx<=this.tokVector.length-2?(this.consumeToken(),this.LA(1)):Lq.END_OF_FILE},r.prototype.LA=function(e){var t=this.currIdx+e;return t<0||this.tokVectorLength<=t?Lq.END_OF_FILE:this.tokVector[t]},r.prototype.consumeToken=function(){this.currIdx++},r.prototype.exportLexerState=function(){return this.currIdx},r.prototype.importLexerState=function(e){this.currIdx=e},r.prototype.resetLexerState=function(){this.currIdx=-1},r.prototype.moveToTerminatedState=function(){this.currIdx=this.tokVector.length-1},r.prototype.getLexerPosition=function(){return this.exportLexerState()},r}();Iy.LexerAdapter=Bye});var Kq=w(yy=>{"use strict";Object.defineProperty(yy,"__esModule",{value:!0});yy.RecognizerApi=void 0;var Oq=Gt(),bye=nf(),Ax=jn(),Qye=xd(),Sye=rx(),vye=mn(),xye=function(){function r(){}return r.prototype.ACTION=function(e){return e.call(this)},r.prototype.consume=function(e,t,i){return this.consumeInternal(t,e,i)},r.prototype.subrule=function(e,t,i){return this.subruleInternal(t,e,i)},r.prototype.option=function(e,t){return this.optionInternal(t,e)},r.prototype.or=function(e,t){return this.orInternal(t,e)},r.prototype.many=function(e,t){return this.manyInternal(e,t)},r.prototype.atLeastOne=function(e,t){return this.atLeastOneInternal(e,t)},r.prototype.CONSUME=function(e,t){return this.consumeInternal(e,0,t)},r.prototype.CONSUME1=function(e,t){return this.consumeInternal(e,1,t)},r.prototype.CONSUME2=function(e,t){return this.consumeInternal(e,2,t)},r.prototype.CONSUME3=function(e,t){return this.consumeInternal(e,3,t)},r.prototype.CONSUME4=function(e,t){return this.consumeInternal(e,4,t)},r.prototype.CONSUME5=function(e,t){return this.consumeInternal(e,5,t)},r.prototype.CONSUME6=function(e,t){return this.consumeInternal(e,6,t)},r.prototype.CONSUME7=function(e,t){return this.consumeInternal(e,7,t)},r.prototype.CONSUME8=function(e,t){return this.consumeInternal(e,8,t)},r.prototype.CONSUME9=function(e,t){return this.consumeInternal(e,9,t)},r.prototype.SUBRULE=function(e,t){return this.subruleInternal(e,0,t)},r.prototype.SUBRULE1=function(e,t){return this.subruleInternal(e,1,t)},r.prototype.SUBRULE2=function(e,t){return this.subruleInternal(e,2,t)},r.prototype.SUBRULE3=function(e,t){return this.subruleInternal(e,3,t)},r.prototype.SUBRULE4=function(e,t){return this.subruleInternal(e,4,t)},r.prototype.SUBRULE5=function(e,t){return this.subruleInternal(e,5,t)},r.prototype.SUBRULE6=function(e,t){return this.subruleInternal(e,6,t)},r.prototype.SUBRULE7=function(e,t){return this.subruleInternal(e,7,t)},r.prototype.SUBRULE8=function(e,t){return this.subruleInternal(e,8,t)},r.prototype.SUBRULE9=function(e,t){return this.subruleInternal(e,9,t)},r.prototype.OPTION=function(e){return this.optionInternal(e,0)},r.prototype.OPTION1=function(e){return this.optionInternal(e,1)},r.prototype.OPTION2=function(e){return this.optionInternal(e,2)},r.prototype.OPTION3=function(e){return this.optionInternal(e,3)},r.prototype.OPTION4=function(e){return this.optionInternal(e,4)},r.prototype.OPTION5=function(e){return this.optionInternal(e,5)},r.prototype.OPTION6=function(e){return this.optionInternal(e,6)},r.prototype.OPTION7=function(e){return this.optionInternal(e,7)},r.prototype.OPTION8=function(e){return this.optionInternal(e,8)},r.prototype.OPTION9=function(e){return this.optionInternal(e,9)},r.prototype.OR=function(e){return this.orInternal(e,0)},r.prototype.OR1=function(e){return this.orInternal(e,1)},r.prototype.OR2=function(e){return this.orInternal(e,2)},r.prototype.OR3=function(e){return this.orInternal(e,3)},r.prototype.OR4=function(e){return this.orInternal(e,4)},r.prototype.OR5=function(e){return this.orInternal(e,5)},r.prototype.OR6=function(e){return this.orInternal(e,6)},r.prototype.OR7=function(e){return this.orInternal(e,7)},r.prototype.OR8=function(e){return this.orInternal(e,8)},r.prototype.OR9=function(e){return this.orInternal(e,9)},r.prototype.MANY=function(e){this.manyInternal(0,e)},r.prototype.MANY1=function(e){this.manyInternal(1,e)},r.prototype.MANY2=function(e){this.manyInternal(2,e)},r.prototype.MANY3=function(e){this.manyInternal(3,e)},r.prototype.MANY4=function(e){this.manyInternal(4,e)},r.prototype.MANY5=function(e){this.manyInternal(5,e)},r.prototype.MANY6=function(e){this.manyInternal(6,e)},r.prototype.MANY7=function(e){this.manyInternal(7,e)},r.prototype.MANY8=function(e){this.manyInternal(8,e)},r.prototype.MANY9=function(e){this.manyInternal(9,e)},r.prototype.MANY_SEP=function(e){this.manySepFirstInternal(0,e)},r.prototype.MANY_SEP1=function(e){this.manySepFirstInternal(1,e)},r.prototype.MANY_SEP2=function(e){this.manySepFirstInternal(2,e)},r.prototype.MANY_SEP3=function(e){this.manySepFirstInternal(3,e)},r.prototype.MANY_SEP4=function(e){this.manySepFirstInternal(4,e)},r.prototype.MANY_SEP5=function(e){this.manySepFirstInternal(5,e)},r.prototype.MANY_SEP6=function(e){this.manySepFirstInternal(6,e)},r.prototype.MANY_SEP7=function(e){this.manySepFirstInternal(7,e)},r.prototype.MANY_SEP8=function(e){this.manySepFirstInternal(8,e)},r.prototype.MANY_SEP9=function(e){this.manySepFirstInternal(9,e)},r.prototype.AT_LEAST_ONE=function(e){this.atLeastOneInternal(0,e)},r.prototype.AT_LEAST_ONE1=function(e){return this.atLeastOneInternal(1,e)},r.prototype.AT_LEAST_ONE2=function(e){this.atLeastOneInternal(2,e)},r.prototype.AT_LEAST_ONE3=function(e){this.atLeastOneInternal(3,e)},r.prototype.AT_LEAST_ONE4=function(e){this.atLeastOneInternal(4,e)},r.prototype.AT_LEAST_ONE5=function(e){this.atLeastOneInternal(5,e)},r.prototype.AT_LEAST_ONE6=function(e){this.atLeastOneInternal(6,e)},r.prototype.AT_LEAST_ONE7=function(e){this.atLeastOneInternal(7,e)},r.prototype.AT_LEAST_ONE8=function(e){this.atLeastOneInternal(8,e)},r.prototype.AT_LEAST_ONE9=function(e){this.atLeastOneInternal(9,e)},r.prototype.AT_LEAST_ONE_SEP=function(e){this.atLeastOneSepFirstInternal(0,e)},r.prototype.AT_LEAST_ONE_SEP1=function(e){this.atLeastOneSepFirstInternal(1,e)},r.prototype.AT_LEAST_ONE_SEP2=function(e){this.atLeastOneSepFirstInternal(2,e)},r.prototype.AT_LEAST_ONE_SEP3=function(e){this.atLeastOneSepFirstInternal(3,e)},r.prototype.AT_LEAST_ONE_SEP4=function(e){this.atLeastOneSepFirstInternal(4,e)},r.prototype.AT_LEAST_ONE_SEP5=function(e){this.atLeastOneSepFirstInternal(5,e)},r.prototype.AT_LEAST_ONE_SEP6=function(e){this.atLeastOneSepFirstInternal(6,e)},r.prototype.AT_LEAST_ONE_SEP7=function(e){this.atLeastOneSepFirstInternal(7,e)},r.prototype.AT_LEAST_ONE_SEP8=function(e){this.atLeastOneSepFirstInternal(8,e)},r.prototype.AT_LEAST_ONE_SEP9=function(e){this.atLeastOneSepFirstInternal(9,e)},r.prototype.RULE=function(e,t,i){if(i===void 0&&(i=Ax.DEFAULT_RULE_CONFIG),(0,Oq.contains)(this.definedRulesNames,e)){var n=Qye.defaultGrammarValidatorErrorProvider.buildDuplicateRuleNameError({topLevelRule:e,grammarName:this.className}),s={message:n,type:Ax.ParserDefinitionErrorType.DUPLICATE_RULE_NAME,ruleName:e};this.definitionErrors.push(s)}this.definedRulesNames.push(e);var o=this.defineRule(e,t,i);return this[e]=o,o},r.prototype.OVERRIDE_RULE=function(e,t,i){i===void 0&&(i=Ax.DEFAULT_RULE_CONFIG);var n=[];n=n.concat((0,Sye.validateRuleIsOverridden)(e,this.definedRulesNames,this.className)),this.definitionErrors=this.definitionErrors.concat(n);var s=this.defineRule(e,t,i);return this[e]=s,s},r.prototype.BACKTRACK=function(e,t){return function(){this.isBackTrackingStack.push(1);var i=this.saveRecogState();try{return e.apply(this,t),!0}catch(n){if((0,bye.isRecognitionException)(n))return!1;throw n}finally{this.reloadRecogState(i),this.isBackTrackingStack.pop()}}},r.prototype.getGAstProductions=function(){return this.gastProductionsCache},r.prototype.getSerializedGastProductions=function(){return(0,vye.serializeGrammar)((0,Oq.values)(this.gastProductionsCache))},r}();yy.RecognizerApi=xye});var Yq=w(By=>{"use strict";Object.defineProperty(By,"__esModule",{value:!0});By.RecognizerEngine=void 0;var Pr=Gt(),qn=Cy(),wy=nf(),Uq=kd(),of=Dd(),Hq=jn(),Pye=sx(),Gq=TA(),Td=_g(),Dye=ox(),kye=function(){function r(){}return r.prototype.initRecognizerEngine=function(e,t){if(this.className=(0,Dye.classNameFromInstance)(this),this.shortRuleNameToFull={},this.fullRuleNameToShort={},this.ruleShortNameIdx=256,this.tokenMatcher=Td.tokenStructuredMatcherNoCategories,this.definedRulesNames=[],this.tokensMap={},this.isBackTrackingStack=[],this.RULE_STACK=[],this.RULE_OCCURRENCE_STACK=[],this.gastProductionsCache={},(0,Pr.has)(t,"serializedGrammar"))throw Error(`The Parser's configuration can no longer contain a property. + See: https://chevrotain.io/docs/changes/BREAKING_CHANGES.html#_6-0-0 + For Further details.`);if((0,Pr.isArray)(e)){if((0,Pr.isEmpty)(e))throw Error(`A Token Vocabulary cannot be empty. + Note that the first argument for the parser constructor + is no longer a Token vector (since v4.0).`);if(typeof e[0].startOffset=="number")throw Error(`The Parser constructor no longer accepts a token vector as the first argument. + See: https://chevrotain.io/docs/changes/BREAKING_CHANGES.html#_4-0-0 + For Further details.`)}if((0,Pr.isArray)(e))this.tokensMap=(0,Pr.reduce)(e,function(o,a){return o[a.name]=a,o},{});else if((0,Pr.has)(e,"modes")&&(0,Pr.every)((0,Pr.flatten)((0,Pr.values)(e.modes)),Td.isTokenType)){var i=(0,Pr.flatten)((0,Pr.values)(e.modes)),n=(0,Pr.uniq)(i);this.tokensMap=(0,Pr.reduce)(n,function(o,a){return o[a.name]=a,o},{})}else if((0,Pr.isObject)(e))this.tokensMap=(0,Pr.cloneObj)(e);else throw new Error(" argument must be An Array of Token constructors, A dictionary of Token constructors or an IMultiModeLexerDefinition");this.tokensMap.EOF=Gq.EOF;var s=(0,Pr.every)((0,Pr.values)(e),function(o){return(0,Pr.isEmpty)(o.categoryMatches)});this.tokenMatcher=s?Td.tokenStructuredMatcherNoCategories:Td.tokenStructuredMatcher,(0,Td.augmentTokenTypes)((0,Pr.values)(this.tokensMap))},r.prototype.defineRule=function(e,t,i){if(this.selfAnalysisDone)throw Error("Grammar rule <"+e+`> may not be defined after the 'performSelfAnalysis' method has been called' +Make sure that all grammar rule definitions are done before 'performSelfAnalysis' is called.`);var n=(0,Pr.has)(i,"resyncEnabled")?i.resyncEnabled:Hq.DEFAULT_RULE_CONFIG.resyncEnabled,s=(0,Pr.has)(i,"recoveryValueFunc")?i.recoveryValueFunc:Hq.DEFAULT_RULE_CONFIG.recoveryValueFunc,o=this.ruleShortNameIdx<t},r.prototype.orInternal=function(e,t){var i=this.getKeyForAutomaticLookahead(qn.OR_IDX,t),n=(0,Pr.isArray)(e)?e:e.DEF,s=this.getLaFuncFromCache(i),o=s.call(this,n);if(o!==void 0){var a=n[o];return a.ALT.call(this)}this.raiseNoAltException(t,e.ERR_MSG)},r.prototype.ruleFinallyStateUpdate=function(){if(this.RULE_STACK.pop(),this.RULE_OCCURRENCE_STACK.pop(),this.cstFinallyStateUpdate(),this.RULE_STACK.length===0&&this.isAtEndOfInput()===!1){var e=this.LA(1),t=this.errorMessageProvider.buildNotAllInputParsedMessage({firstRedundant:e,ruleName:this.getCurrRuleFullName()});this.SAVE_ERROR(new wy.NotAllInputParsedException(t,e))}},r.prototype.subruleInternal=function(e,t,i){var n;try{var s=i!==void 0?i.ARGS:void 0;return n=e.call(this,t,s),this.cstPostNonTerminal(n,i!==void 0&&i.LABEL!==void 0?i.LABEL:e.ruleName),n}catch(o){this.subruleInternalError(o,i,e.ruleName)}},r.prototype.subruleInternalError=function(e,t,i){throw(0,wy.isRecognitionException)(e)&&e.partialCstResult!==void 0&&(this.cstPostNonTerminal(e.partialCstResult,t!==void 0&&t.LABEL!==void 0?t.LABEL:i),delete e.partialCstResult),e},r.prototype.consumeInternal=function(e,t,i){var n;try{var s=this.LA(1);this.tokenMatcher(s,e)===!0?(this.consumeToken(),n=s):this.consumeInternalError(e,s,i)}catch(o){n=this.consumeInternalRecovery(e,t,o)}return this.cstPostTerminal(i!==void 0&&i.LABEL!==void 0?i.LABEL:e.name,n),n},r.prototype.consumeInternalError=function(e,t,i){var n,s=this.LA(0);throw i!==void 0&&i.ERR_MSG?n=i.ERR_MSG:n=this.errorMessageProvider.buildMismatchTokenMessage({expected:e,actual:t,previous:s,ruleName:this.getCurrRuleFullName()}),this.SAVE_ERROR(new wy.MismatchedTokenException(n,t,s))},r.prototype.consumeInternalRecovery=function(e,t,i){if(this.recoveryEnabled&&i.name==="MismatchedTokenException"&&!this.isBackTracking()){var n=this.getFollowsForInRuleRecovery(e,t);try{return this.tryInRuleRecovery(e,n)}catch(s){throw s.name===Pye.IN_RULE_RECOVERY_EXCEPTION?i:s}}else throw i},r.prototype.saveRecogState=function(){var e=this.errors,t=(0,Pr.cloneArr)(this.RULE_STACK);return{errors:e,lexerState:this.exportLexerState(),RULE_STACK:t,CST_STACK:this.CST_STACK}},r.prototype.reloadRecogState=function(e){this.errors=e.errors,this.importLexerState(e.lexerState),this.RULE_STACK=e.RULE_STACK},r.prototype.ruleInvocationStateUpdate=function(e,t,i){this.RULE_OCCURRENCE_STACK.push(i),this.RULE_STACK.push(e),this.cstInvocationStateUpdate(t,e)},r.prototype.isBackTracking=function(){return this.isBackTrackingStack.length!==0},r.prototype.getCurrRuleFullName=function(){var e=this.getLastExplicitRuleShortName();return this.shortRuleNameToFull[e]},r.prototype.shortRuleNameToFullName=function(e){return this.shortRuleNameToFull[e]},r.prototype.isAtEndOfInput=function(){return this.tokenMatcher(this.LA(1),Gq.EOF)},r.prototype.reset=function(){this.resetLexerState(),this.isBackTrackingStack=[],this.errors=[],this.RULE_STACK=[],this.CST_STACK=[],this.RULE_OCCURRENCE_STACK=[]},r}();By.RecognizerEngine=kye});var qq=w(by=>{"use strict";Object.defineProperty(by,"__esModule",{value:!0});by.ErrorHandler=void 0;var lx=nf(),cx=Gt(),jq=kd(),Rye=jn(),Fye=function(){function r(){}return r.prototype.initErrorHandler=function(e){this._errors=[],this.errorMessageProvider=(0,cx.has)(e,"errorMessageProvider")?e.errorMessageProvider:Rye.DEFAULT_PARSER_CONFIG.errorMessageProvider},r.prototype.SAVE_ERROR=function(e){if((0,lx.isRecognitionException)(e))return e.context={ruleStack:this.getHumanReadableRuleStack(),ruleOccurrenceStack:(0,cx.cloneArr)(this.RULE_OCCURRENCE_STACK)},this._errors.push(e),e;throw Error("Trying to save an Error which is not a RecognitionException")},Object.defineProperty(r.prototype,"errors",{get:function(){return(0,cx.cloneArr)(this._errors)},set:function(e){this._errors=e},enumerable:!1,configurable:!0}),r.prototype.raiseEarlyExitException=function(e,t,i){for(var n=this.getCurrRuleFullName(),s=this.getGAstProductions()[n],o=(0,jq.getLookaheadPathsForOptionalProd)(e,s,t,this.maxLookahead),a=o[0],l=[],c=1;c<=this.maxLookahead;c++)l.push(this.LA(c));var u=this.errorMessageProvider.buildEarlyExitMessage({expectedIterationPaths:a,actual:l,previous:this.LA(0),customUserDescription:i,ruleName:n});throw this.SAVE_ERROR(new lx.EarlyExitException(u,this.LA(1),this.LA(0)))},r.prototype.raiseNoAltException=function(e,t){for(var i=this.getCurrRuleFullName(),n=this.getGAstProductions()[i],s=(0,jq.getLookaheadPathsForOr)(e,n,this.maxLookahead),o=[],a=1;a<=this.maxLookahead;a++)o.push(this.LA(a));var l=this.LA(0),c=this.errorMessageProvider.buildNoViableAltMessage({expectedPathsPerAlt:s,actual:o,previous:l,customUserDescription:t,ruleName:this.getCurrRuleFullName()});throw this.SAVE_ERROR(new lx.NoViableAltException(c,this.LA(1),l))},r}();by.ErrorHandler=Fye});var zq=w(Qy=>{"use strict";Object.defineProperty(Qy,"__esModule",{value:!0});Qy.ContentAssist=void 0;var Jq=Dd(),Wq=Gt(),Nye=function(){function r(){}return r.prototype.initContentAssist=function(){},r.prototype.computeContentAssist=function(e,t){var i=this.gastProductionsCache[e];if((0,Wq.isUndefined)(i))throw Error("Rule ->"+e+"<- does not exist in this grammar.");return(0,Jq.nextPossibleTokensAfter)([i],t,this.tokenMatcher,this.maxLookahead)},r.prototype.getNextPossibleTokenTypes=function(e){var t=(0,Wq.first)(e.ruleStack),i=this.getGAstProductions(),n=i[t],s=new Jq.NextAfterTokenWalker(n,e).startWalking();return s},r}();Qy.ContentAssist=Nye});var rJ=w(xy=>{"use strict";Object.defineProperty(xy,"__esModule",{value:!0});xy.GastRecorder=void 0;var yn=Gt(),Mo=mn(),Tye=Bd(),_q=_g(),$q=TA(),Lye=jn(),Mye=Cy(),vy={description:"This Object indicates the Parser is during Recording Phase"};Object.freeze(vy);var Vq=!0,Xq=Math.pow(2,Mye.BITS_FOR_OCCURRENCE_IDX)-1,eJ=(0,$q.createToken)({name:"RECORDING_PHASE_TOKEN",pattern:Tye.Lexer.NA});(0,_q.augmentTokenTypes)([eJ]);var tJ=(0,$q.createTokenInstance)(eJ,`This IToken indicates the Parser is in Recording Phase + See: https://chevrotain.io/docs/guide/internals.html#grammar-recording for details`,-1,-1,-1,-1,-1,-1);Object.freeze(tJ);var Oye={name:`This CSTNode indicates the Parser is in Recording Phase + See: https://chevrotain.io/docs/guide/internals.html#grammar-recording for details`,children:{}},Kye=function(){function r(){}return r.prototype.initGastRecorder=function(e){this.recordingProdStack=[],this.RECORDING_PHASE=!1},r.prototype.enableRecording=function(){var e=this;this.RECORDING_PHASE=!0,this.TRACE_INIT("Enable Recording",function(){for(var t=function(n){var s=n>0?n:"";e["CONSUME"+s]=function(o,a){return this.consumeInternalRecord(o,n,a)},e["SUBRULE"+s]=function(o,a){return this.subruleInternalRecord(o,n,a)},e["OPTION"+s]=function(o){return this.optionInternalRecord(o,n)},e["OR"+s]=function(o){return this.orInternalRecord(o,n)},e["MANY"+s]=function(o){this.manyInternalRecord(n,o)},e["MANY_SEP"+s]=function(o){this.manySepFirstInternalRecord(n,o)},e["AT_LEAST_ONE"+s]=function(o){this.atLeastOneInternalRecord(n,o)},e["AT_LEAST_ONE_SEP"+s]=function(o){this.atLeastOneSepFirstInternalRecord(n,o)}},i=0;i<10;i++)t(i);e.consume=function(n,s,o){return this.consumeInternalRecord(s,n,o)},e.subrule=function(n,s,o){return this.subruleInternalRecord(s,n,o)},e.option=function(n,s){return this.optionInternalRecord(s,n)},e.or=function(n,s){return this.orInternalRecord(s,n)},e.many=function(n,s){this.manyInternalRecord(n,s)},e.atLeastOne=function(n,s){this.atLeastOneInternalRecord(n,s)},e.ACTION=e.ACTION_RECORD,e.BACKTRACK=e.BACKTRACK_RECORD,e.LA=e.LA_RECORD})},r.prototype.disableRecording=function(){var e=this;this.RECORDING_PHASE=!1,this.TRACE_INIT("Deleting Recording methods",function(){for(var t=0;t<10;t++){var i=t>0?t:"";delete e["CONSUME"+i],delete e["SUBRULE"+i],delete e["OPTION"+i],delete e["OR"+i],delete e["MANY"+i],delete e["MANY_SEP"+i],delete e["AT_LEAST_ONE"+i],delete e["AT_LEAST_ONE_SEP"+i]}delete e.consume,delete e.subrule,delete e.option,delete e.or,delete e.many,delete e.atLeastOne,delete e.ACTION,delete e.BACKTRACK,delete e.LA})},r.prototype.ACTION_RECORD=function(e){},r.prototype.BACKTRACK_RECORD=function(e,t){return function(){return!0}},r.prototype.LA_RECORD=function(e){return Lye.END_OF_FILE},r.prototype.topLevelRuleRecord=function(e,t){try{var i=new Mo.Rule({definition:[],name:e});return i.name=e,this.recordingProdStack.push(i),t.call(this),this.recordingProdStack.pop(),i}catch(n){if(n.KNOWN_RECORDER_ERROR!==!0)try{n.message=n.message+` + This error was thrown during the "grammar recording phase" For more info see: + https://chevrotain.io/docs/guide/internals.html#grammar-recording`}catch{throw n}throw n}},r.prototype.optionInternalRecord=function(e,t){return Ld.call(this,Mo.Option,e,t)},r.prototype.atLeastOneInternalRecord=function(e,t){Ld.call(this,Mo.RepetitionMandatory,t,e)},r.prototype.atLeastOneSepFirstInternalRecord=function(e,t){Ld.call(this,Mo.RepetitionMandatoryWithSeparator,t,e,Vq)},r.prototype.manyInternalRecord=function(e,t){Ld.call(this,Mo.Repetition,t,e)},r.prototype.manySepFirstInternalRecord=function(e,t){Ld.call(this,Mo.RepetitionWithSeparator,t,e,Vq)},r.prototype.orInternalRecord=function(e,t){return Uye.call(this,e,t)},r.prototype.subruleInternalRecord=function(e,t,i){if(Sy(t),!e||(0,yn.has)(e,"ruleName")===!1){var n=new Error(" argument is invalid"+(" expecting a Parser method reference but got: <"+JSON.stringify(e)+">")+(` + inside top level rule: <`+this.recordingProdStack[0].name+">"));throw n.KNOWN_RECORDER_ERROR=!0,n}var s=(0,yn.peek)(this.recordingProdStack),o=e.ruleName,a=new Mo.NonTerminal({idx:t,nonTerminalName:o,label:i==null?void 0:i.LABEL,referencedRule:void 0});return s.definition.push(a),this.outputCst?Oye:vy},r.prototype.consumeInternalRecord=function(e,t,i){if(Sy(t),!(0,_q.hasShortKeyProperty)(e)){var n=new Error(" argument is invalid"+(" expecting a TokenType reference but got: <"+JSON.stringify(e)+">")+(` + inside top level rule: <`+this.recordingProdStack[0].name+">"));throw n.KNOWN_RECORDER_ERROR=!0,n}var s=(0,yn.peek)(this.recordingProdStack),o=new Mo.Terminal({idx:t,terminalType:e,label:i==null?void 0:i.LABEL});return s.definition.push(o),tJ},r}();xy.GastRecorder=Kye;function Ld(r,e,t,i){i===void 0&&(i=!1),Sy(t);var n=(0,yn.peek)(this.recordingProdStack),s=(0,yn.isFunction)(e)?e:e.DEF,o=new r({definition:[],idx:t});return i&&(o.separator=e.SEP),(0,yn.has)(e,"MAX_LOOKAHEAD")&&(o.maxLookahead=e.MAX_LOOKAHEAD),this.recordingProdStack.push(o),s.call(this),n.definition.push(o),this.recordingProdStack.pop(),vy}function Uye(r,e){var t=this;Sy(e);var i=(0,yn.peek)(this.recordingProdStack),n=(0,yn.isArray)(r)===!1,s=n===!1?r:r.DEF,o=new Mo.Alternation({definition:[],idx:e,ignoreAmbiguities:n&&r.IGNORE_AMBIGUITIES===!0});(0,yn.has)(r,"MAX_LOOKAHEAD")&&(o.maxLookahead=r.MAX_LOOKAHEAD);var a=(0,yn.some)(s,function(l){return(0,yn.isFunction)(l.GATE)});return o.hasPredicates=a,i.definition.push(o),(0,yn.forEach)(s,function(l){var c=new Mo.Alternative({definition:[]});o.definition.push(c),(0,yn.has)(l,"IGNORE_AMBIGUITIES")?c.ignoreAmbiguities=l.IGNORE_AMBIGUITIES:(0,yn.has)(l,"GATE")&&(c.ignoreAmbiguities=!0),t.recordingProdStack.push(c),l.ALT.call(t),t.recordingProdStack.pop()}),vy}function Zq(r){return r===0?"":""+r}function Sy(r){if(r<0||r>Xq){var e=new Error("Invalid DSL Method idx value: <"+r+`> + `+("Idx value must be a none negative value smaller than "+(Xq+1)));throw e.KNOWN_RECORDER_ERROR=!0,e}}});var nJ=w(Py=>{"use strict";Object.defineProperty(Py,"__esModule",{value:!0});Py.PerformanceTracer=void 0;var iJ=Gt(),Hye=jn(),Gye=function(){function r(){}return r.prototype.initPerformanceTracer=function(e){if((0,iJ.has)(e,"traceInitPerf")){var t=e.traceInitPerf,i=typeof t=="number";this.traceInitMaxIdent=i?t:1/0,this.traceInitPerf=i?t>0:t}else this.traceInitMaxIdent=0,this.traceInitPerf=Hye.DEFAULT_PARSER_CONFIG.traceInitPerf;this.traceInitIndent=-1},r.prototype.TRACE_INIT=function(e,t){if(this.traceInitPerf===!0){this.traceInitIndent++;var i=new Array(this.traceInitIndent+1).join(" ");this.traceInitIndent <"+e+">");var n=(0,iJ.timer)(t),s=n.time,o=n.value,a=s>10?console.warn:console.log;return this.traceInitIndent time: "+s+"ms"),this.traceInitIndent--,o}else return t()},r}();Py.PerformanceTracer=Gye});var sJ=w(Dy=>{"use strict";Object.defineProperty(Dy,"__esModule",{value:!0});Dy.applyMixins=void 0;function Yye(r,e){e.forEach(function(t){var i=t.prototype;Object.getOwnPropertyNames(i).forEach(function(n){if(n!=="constructor"){var s=Object.getOwnPropertyDescriptor(i,n);s&&(s.get||s.set)?Object.defineProperty(r.prototype,n,s):r.prototype[n]=t.prototype[n]}})})}Dy.applyMixins=Yye});var jn=w(dr=>{"use strict";var AJ=dr&&dr.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(dr,"__esModule",{value:!0});dr.EmbeddedActionsParser=dr.CstParser=dr.Parser=dr.EMPTY_ALT=dr.ParserDefinitionErrorType=dr.DEFAULT_RULE_CONFIG=dr.DEFAULT_PARSER_CONFIG=dr.END_OF_FILE=void 0;var en=Gt(),jye=qj(),oJ=TA(),lJ=xd(),aJ=Cq(),qye=sx(),Jye=Qq(),Wye=Tq(),zye=Mq(),Vye=Kq(),Xye=Yq(),Zye=qq(),_ye=zq(),$ye=rJ(),ewe=nJ(),twe=sJ();dr.END_OF_FILE=(0,oJ.createTokenInstance)(oJ.EOF,"",NaN,NaN,NaN,NaN,NaN,NaN);Object.freeze(dr.END_OF_FILE);dr.DEFAULT_PARSER_CONFIG=Object.freeze({recoveryEnabled:!1,maxLookahead:3,dynamicTokensEnabled:!1,outputCst:!0,errorMessageProvider:lJ.defaultParserErrorProvider,nodeLocationTracking:"none",traceInitPerf:!1,skipValidations:!1});dr.DEFAULT_RULE_CONFIG=Object.freeze({recoveryValueFunc:function(){},resyncEnabled:!0});var rwe;(function(r){r[r.INVALID_RULE_NAME=0]="INVALID_RULE_NAME",r[r.DUPLICATE_RULE_NAME=1]="DUPLICATE_RULE_NAME",r[r.INVALID_RULE_OVERRIDE=2]="INVALID_RULE_OVERRIDE",r[r.DUPLICATE_PRODUCTIONS=3]="DUPLICATE_PRODUCTIONS",r[r.UNRESOLVED_SUBRULE_REF=4]="UNRESOLVED_SUBRULE_REF",r[r.LEFT_RECURSION=5]="LEFT_RECURSION",r[r.NONE_LAST_EMPTY_ALT=6]="NONE_LAST_EMPTY_ALT",r[r.AMBIGUOUS_ALTS=7]="AMBIGUOUS_ALTS",r[r.CONFLICT_TOKENS_RULES_NAMESPACE=8]="CONFLICT_TOKENS_RULES_NAMESPACE",r[r.INVALID_TOKEN_NAME=9]="INVALID_TOKEN_NAME",r[r.NO_NON_EMPTY_LOOKAHEAD=10]="NO_NON_EMPTY_LOOKAHEAD",r[r.AMBIGUOUS_PREFIX_ALTS=11]="AMBIGUOUS_PREFIX_ALTS",r[r.TOO_MANY_ALTS=12]="TOO_MANY_ALTS"})(rwe=dr.ParserDefinitionErrorType||(dr.ParserDefinitionErrorType={}));function iwe(r){return r===void 0&&(r=void 0),function(){return r}}dr.EMPTY_ALT=iwe;var ky=function(){function r(e,t){this.definitionErrors=[],this.selfAnalysisDone=!1;var i=this;if(i.initErrorHandler(t),i.initLexerAdapter(),i.initLooksAhead(t),i.initRecognizerEngine(e,t),i.initRecoverable(t),i.initTreeBuilder(t),i.initContentAssist(),i.initGastRecorder(t),i.initPerformanceTracer(t),(0,en.has)(t,"ignoredIssues"))throw new Error(`The IParserConfig property has been deprecated. + Please use the flag on the relevant DSL method instead. + See: https://chevrotain.io/docs/guide/resolving_grammar_errors.html#IGNORING_AMBIGUITIES + For further details.`);this.skipValidations=(0,en.has)(t,"skipValidations")?t.skipValidations:dr.DEFAULT_PARSER_CONFIG.skipValidations}return r.performSelfAnalysis=function(e){throw Error("The **static** `performSelfAnalysis` method has been deprecated. \nUse the **instance** method with the same name instead.")},r.prototype.performSelfAnalysis=function(){var e=this;this.TRACE_INIT("performSelfAnalysis",function(){var t;e.selfAnalysisDone=!0;var i=e.className;e.TRACE_INIT("toFastProps",function(){(0,en.toFastProperties)(e)}),e.TRACE_INIT("Grammar Recording",function(){try{e.enableRecording(),(0,en.forEach)(e.definedRulesNames,function(s){var o=e[s],a=o.originalGrammarAction,l=void 0;e.TRACE_INIT(s+" Rule",function(){l=e.topLevelRuleRecord(s,a)}),e.gastProductionsCache[s]=l})}finally{e.disableRecording()}});var n=[];if(e.TRACE_INIT("Grammar Resolving",function(){n=(0,aJ.resolveGrammar)({rules:(0,en.values)(e.gastProductionsCache)}),e.definitionErrors=e.definitionErrors.concat(n)}),e.TRACE_INIT("Grammar Validations",function(){if((0,en.isEmpty)(n)&&e.skipValidations===!1){var s=(0,aJ.validateGrammar)({rules:(0,en.values)(e.gastProductionsCache),maxLookahead:e.maxLookahead,tokenTypes:(0,en.values)(e.tokensMap),errMsgProvider:lJ.defaultGrammarValidatorErrorProvider,grammarName:i});e.definitionErrors=e.definitionErrors.concat(s)}}),(0,en.isEmpty)(e.definitionErrors)&&(e.recoveryEnabled&&e.TRACE_INIT("computeAllProdsFollows",function(){var s=(0,jye.computeAllProdsFollows)((0,en.values)(e.gastProductionsCache));e.resyncFollows=s}),e.TRACE_INIT("ComputeLookaheadFunctions",function(){e.preComputeLookaheadFunctions((0,en.values)(e.gastProductionsCache))})),!r.DEFER_DEFINITION_ERRORS_HANDLING&&!(0,en.isEmpty)(e.definitionErrors))throw t=(0,en.map)(e.definitionErrors,function(s){return s.message}),new Error(`Parser Definition Errors detected: + `+t.join(` +------------------------------- +`))})},r.DEFER_DEFINITION_ERRORS_HANDLING=!1,r}();dr.Parser=ky;(0,twe.applyMixins)(ky,[qye.Recoverable,Jye.LooksAhead,Wye.TreeBuilder,zye.LexerAdapter,Xye.RecognizerEngine,Vye.RecognizerApi,Zye.ErrorHandler,_ye.ContentAssist,$ye.GastRecorder,ewe.PerformanceTracer]);var nwe=function(r){AJ(e,r);function e(t,i){i===void 0&&(i=dr.DEFAULT_PARSER_CONFIG);var n=this,s=(0,en.cloneObj)(i);return s.outputCst=!0,n=r.call(this,t,s)||this,n}return e}(ky);dr.CstParser=nwe;var swe=function(r){AJ(e,r);function e(t,i){i===void 0&&(i=dr.DEFAULT_PARSER_CONFIG);var n=this,s=(0,en.cloneObj)(i);return s.outputCst=!1,n=r.call(this,t,s)||this,n}return e}(ky);dr.EmbeddedActionsParser=swe});var uJ=w(Ry=>{"use strict";Object.defineProperty(Ry,"__esModule",{value:!0});Ry.createSyntaxDiagramsCode=void 0;var cJ=Dv();function owe(r,e){var t=e===void 0?{}:e,i=t.resourceBase,n=i===void 0?"https://unpkg.com/chevrotain@"+cJ.VERSION+"/diagrams/":i,s=t.css,o=s===void 0?"https://unpkg.com/chevrotain@"+cJ.VERSION+"/diagrams/diagrams.css":s,a=` + + + + + +`,l=` + +`,c=` + + + + + +
+ + + diff --git a/__fixtures__/test-project-rsa/web/src/layouts/.keep b/__fixtures__/test-project-rsa/web/src/layouts/.keep new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/__fixtures__/test-project-rsa/web/src/pages/FatalErrorPage/FatalErrorPage.tsx b/__fixtures__/test-project-rsa/web/src/pages/FatalErrorPage/FatalErrorPage.tsx new file mode 100644 index 000000000000..b2bb436f8ed0 --- /dev/null +++ b/__fixtures__/test-project-rsa/web/src/pages/FatalErrorPage/FatalErrorPage.tsx @@ -0,0 +1,57 @@ +// This page will be rendered when an error makes it all the way to the top of the +// application without being handled by a Javascript catch statement or React error +// boundary. +// +// You can modify this page as you wish, but it is important to keep things simple to +// avoid the possibility that it will cause its own error. If it does, Redwood will +// still render a generic error page, but your users will prefer something a bit more +// thoughtful :) + +// This import will be automatically removed when building for production +import { DevFatalErrorPage } from '@redwoodjs/web/dist/components/DevFatalErrorPage' + +export default DevFatalErrorPage || + (() => ( +
+ + +`,l=` + +`,c=` + + + + + +
+ + + diff --git a/__fixtures__/test-project-rsc-external-packages/web/src/layouts/.keep b/__fixtures__/test-project-rsc-external-packages/web/src/layouts/.keep new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/__fixtures__/test-project-rsc-external-packages/web/src/pages/FatalErrorPage/FatalErrorPage.tsx b/__fixtures__/test-project-rsc-external-packages/web/src/pages/FatalErrorPage/FatalErrorPage.tsx new file mode 100644 index 000000000000..b2bb436f8ed0 --- /dev/null +++ b/__fixtures__/test-project-rsc-external-packages/web/src/pages/FatalErrorPage/FatalErrorPage.tsx @@ -0,0 +1,57 @@ +// This page will be rendered when an error makes it all the way to the top of the +// application without being handled by a Javascript catch statement or React error +// boundary. +// +// You can modify this page as you wish, but it is important to keep things simple to +// avoid the possibility that it will cause its own error. If it does, Redwood will +// still render a generic error page, but your users will prefer something a bit more +// thoughtful :) + +// This import will be automatically removed when building for production +import { DevFatalErrorPage } from '@redwoodjs/web/dist/components/DevFatalErrorPage' + +export default DevFatalErrorPage || + (() => ( +
+ +
+

404 Page Not Found

+
+
+ + + + + diff --git a/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/README.md b/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/README.md new file mode 100644 index 000000000000..345ab0cd5acf --- /dev/null +++ b/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/README.md @@ -0,0 +1,54 @@ +# Static Assets + +Use this folder to add static files directly to your app. All included files and +folders will be copied directly into the `/dist` folder (created when Vite +builds for production). They will also be available during development when you +run `yarn rw dev`. >Note: files will _not_ hot reload while the development +server is running. You'll need to manually stop/start to access file changes. + +### Example Use + +A file like `favicon.png` will be copied to `/dist/favicon.png`. A folder +containing a file such as `static-files/my-logo.jpg` will be copied to +`/dist/static-files/my-logo.jpg`. These can be referenced in your code directly +without any special handling, e.g. + +``` + +``` + +and + +``` + alt="Logo" /> +``` + +## Best Practices + +Because assets in this folder are bypassing the javascript module system, **this +folder should be used sparingly** for assets such as favicons, robots.txt, +manifests, libraries incompatible with Vite, etc. + +In general, it's best to import files directly into a template, page, or +component. This allows Vite to include that file in the bundle when small +enough, or to copy it over to the `dist` folder with a hash. + +### Example Asset Import with Vite + +Instead of handling our logo image as a static file per the example above, we +can do the following: + +``` +import React from "react" +import logo from "./my-logo.jpg" + + +function Header() { + return Logo +} + +export default Header +``` + +See Vite's docs for +[static asset handling](https://vitejs.dev/guide/assets.html) diff --git a/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/about.html b/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/about.html new file mode 100644 index 000000000000..9daca9e2fa83 --- /dev/null +++ b/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/about.html @@ -0,0 +1,40 @@ + + + + + + Redwood App | Redwood App + + + + + + + + + + +
+
+

Redwood Blog

+ +
+
+

This site was created to demonstrate my mastery of Redwood: Look on my works, ye mighty, and + despair!

+ +
+
+ + + diff --git a/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/assets/AboutPage-7ec0f8df.js b/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/assets/AboutPage-7ec0f8df.js new file mode 100644 index 000000000000..a679b2cfce14 --- /dev/null +++ b/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/assets/AboutPage-7ec0f8df.js @@ -0,0 +1,3 @@ +import{j as t}from"./index-ff057e8f.js";const o=()=>t.jsx("p",{className:"font-light",children:"This site was created to demonstrate my mastery of Redwood: Look on my works, ye mighty, and despair!"});export{o as default}; +globalThis.__REDWOOD__PRERENDER_PAGES = globalThis.__REDWOOD__PRERENDER_PAGES || {}; +globalThis.__REDWOOD__PRERENDER_PAGES.AboutPage=o; diff --git a/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/assets/index-613d397d.css b/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/assets/index-613d397d.css new file mode 100644 index 000000000000..a46c81a539ee --- /dev/null +++ b/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/assets/index-613d397d.css @@ -0,0 +1,2 @@ +.rw-scaffold{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity))}.rw-scaffold h1,.rw-scaffold h2{margin:0}.rw-scaffold a{background-color:transparent}.rw-scaffold ul{margin:0;padding:0}.rw-scaffold input::-moz-placeholder{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity))}.rw-scaffold input::placeholder{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity))}.rw-header{display:flex;justify-content:space-between;padding:1rem 2rem}.rw-main{margin-left:1rem;margin-right:1rem;padding-bottom:1rem}.rw-segment{width:100%;overflow:hidden;border-radius:.5rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity));scrollbar-color:#a1a1aa transparent}.rw-segment::-webkit-scrollbar{height:initial}.rw-segment::-webkit-scrollbar-track{border-radius:0 0 10px 10px/0px 0px 10px 10px;border-width:0px;border-top-width:1px;border-style:solid;--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity));background-color:transparent;padding:2px}.rw-segment::-webkit-scrollbar-thumb{border-radius:9999px;border-width:3px;border-style:solid;border-color:transparent;--tw-bg-opacity: 1;background-color:rgb(161 161 170 / var(--tw-bg-opacity));background-clip:content-box}.rw-segment-header{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity));padding:.75rem 1rem;--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity))}.rw-segment-main{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity));padding:1rem}.rw-link{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity));text-decoration-line:underline}.rw-link:hover{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity))}.rw-forgot-link{margin-top:.25rem;text-align:right;font-size:.75rem;line-height:1rem;--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity));text-decoration-line:underline}.rw-forgot-link:hover{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity))}.rw-heading{font-weight:600}.rw-heading.rw-heading-primary{font-size:1.25rem;line-height:1.75rem}.rw-heading.rw-heading-secondary{font-size:.875rem;line-height:1.25rem}.rw-heading .rw-link{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity));text-decoration-line:none}.rw-heading .rw-link:hover{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity));text-decoration-line:underline}.rw-cell-error{font-size:.875rem;line-height:1.25rem;font-weight:600}.rw-form-wrapper{margin-top:-1rem;font-size:.875rem;line-height:1.25rem}.rw-cell-error,.rw-form-error-wrapper{margin-top:1rem;margin-bottom:1rem;border-radius:.25rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(254 226 226 / var(--tw-border-opacity));--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity));padding:1rem;--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity))}.rw-form-error-title{margin:0;font-weight:600}.rw-form-error-list{margin-top:.5rem;list-style-position:inside;list-style-type:disc}.rw-button{display:flex;cursor:pointer;justify-content:center;border-radius:.25rem;border-width:0px;--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity));padding:.25rem 1rem;font-size:.75rem;line-height:1rem;font-weight:600;text-transform:uppercase;line-height:2;letter-spacing:.025em;--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity));text-decoration-line:none;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.1s}.rw-button:hover{--tw-bg-opacity: 1;background-color:rgb(107 114 128 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.rw-button.rw-button-small{border-radius:.125rem;padding:.25rem .5rem;font-size:.75rem;line-height:1rem}.rw-button.rw-button-green{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.rw-button.rw-button-green:hover{--tw-bg-opacity: 1;background-color:rgb(21 128 61 / var(--tw-bg-opacity))}.rw-button.rw-button-blue{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.rw-button.rw-button-blue:hover{--tw-bg-opacity: 1;background-color:rgb(29 78 216 / var(--tw-bg-opacity))}.rw-button.rw-button-red{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.rw-button.rw-button-red:hover{--tw-bg-opacity: 1;background-color:rgb(185 28 28 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.rw-button-icon{margin-right:.25rem;font-size:1.25rem;line-height:1.25rem}.rw-button-group{margin:.75rem .5rem;display:flex;justify-content:center}.rw-button-group .rw-button{margin-left:.25rem;margin-right:.25rem}.rw-form-wrapper .rw-button-group{margin-top:2rem}.rw-label{margin-top:1.5rem;display:block;text-align:left;font-weight:600;--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity))}.rw-label.rw-label-error{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity))}.rw-input{margin-top:.5rem;display:block;width:100%;border-radius:.25rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity));--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity));padding:.5rem;outline:2px solid transparent;outline-offset:2px}.rw-check-radio-items{display:flex;justify-items:center}.rw-check-radio-item-none{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity))}.rw-input[type=checkbox],.rw-input[type=radio]{margin-left:0;margin-right:.25rem;margin-top:.25rem;display:inline;width:1rem}.rw-input:focus{--tw-border-opacity: 1;border-color:rgb(156 163 175 / var(--tw-border-opacity))}.rw-input-error{--tw-border-opacity: 1;border-color:rgb(220 38 38 / var(--tw-border-opacity));--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity))}.rw-input-error:focus{--tw-border-opacity: 1;border-color:rgb(220 38 38 / var(--tw-border-opacity));outline:2px solid transparent;outline-offset:2px;box-shadow:0 0 5px #c53030}.rw-field-error{margin-top:.25rem;display:block;font-size:.75rem;line-height:1rem;font-weight:600;text-transform:uppercase;--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity))}.rw-table-wrapper-responsive{overflow-x:auto}.rw-table-wrapper-responsive .rw-table{min-width:48rem}.rw-table{width:100%;font-size:.875rem;line-height:1.25rem}.rw-table th,.rw-table td{padding:.75rem}.rw-table td{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity))}.rw-table tr:nth-child(odd) td,.rw-table tr:nth-child(odd) th{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity))}.rw-table thead tr{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity))}.rw-table th{text-align:left;font-weight:600}.rw-table thead th{text-align:left}.rw-table tbody th{text-align:right}@media (min-width: 768px){.rw-table tbody th{width:20%}}.rw-table tbody tr{border-top-width:1px;--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity))}.rw-table input{margin-left:0}.rw-table-actions{display:flex;height:1rem;align-items:center;justify-content:flex-end;padding-right:.25rem}.rw-table-actions .rw-button{background-color:transparent}.rw-table-actions .rw-button:hover{--tw-bg-opacity: 1;background-color:rgb(107 114 128 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.rw-table-actions .rw-button-blue{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity))}.rw-table-actions .rw-button-blue:hover{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.rw-table-actions .rw-button-red{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity))}.rw-table-actions .rw-button-red:hover{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.rw-text-center{text-align:center}.rw-login-container{margin-left:auto;margin-right:auto;margin-top:4rem;margin-bottom:4rem;display:flex;width:24rem;flex-wrap:wrap;align-items:center;justify-content:center}.rw-login-container .rw-form-wrapper{width:100%;text-align:center}.rw-login-link{margin-top:1rem;width:100%;text-align:center;font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity))}.rw-webauthn-wrapper{margin-left:1rem;margin-right:1rem;margin-top:1.5rem;line-height:1.5rem}.rw-webauthn-wrapper h2{margin-bottom:1rem;font-size:1.25rem;line-height:1.75rem;font-weight:700}/*! tailwindcss v3.3.3 | MIT License | https://tailwindcss.com + */*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.relative{position:relative}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-4{margin-bottom:1rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-8{margin-top:2rem}.block{display:block}.flex{display:flex}.table{display:table}.max-w-4xl{max-width:56rem}.items-center{align-items:center}.justify-between{justify-content:space-between}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rounded{border-radius:.25rem}.rounded-sm{border-radius:.125rem}.rounded-b{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.border{border-width:1px}.border-red-700{--tw-border-opacity: 1;border-color:rgb(185 28 28 / var(--tw-border-opacity))}.bg-blue-700{--tw-bg-opacity: 1;background-color:rgb(29 78 216 / var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.p-12{padding:3rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.px-8{padding-left:2rem;padding-right:2rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.text-left{text-align:left}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.font-light{font-weight:300}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.tracking-tight{letter-spacing:-.025em}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity))}.text-blue-600{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.underline{text-decoration-line:underline}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-100{transition-duration:.1s}.visited\:text-purple-600:visited{color:#9333ea}.hover\:bg-blue-600:hover{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity))}.hover\:text-blue-100:hover{--tw-text-opacity: 1;color:rgb(219 234 254 / var(--tw-text-opacity))}.hover\:text-blue-600:hover{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity))}.hover\:text-blue-800:hover{--tw-text-opacity: 1;color:rgb(30 64 175 / var(--tw-text-opacity))} diff --git a/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/build-manifest.json b/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/build-manifest.json new file mode 100644 index 000000000000..ac9125cd9908 --- /dev/null +++ b/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/build-manifest.json @@ -0,0 +1,230 @@ +{ + "_ContactForm-d76f67ab.js": { + "file": "assets/ContactForm-d76f67ab.js", + "imports": [ + "index.html", + "_index-77bc0912.js" + ] + }, + "_PostForm-4b7853da.js": { + "file": "assets/PostForm-4b7853da.js", + "imports": [ + "index.html", + "_index-77bc0912.js" + ] + }, + "_formatters-2fce1756.js": { + "file": "assets/formatters-2fce1756.js", + "imports": [ + "index.html" + ] + }, + "_index-77bc0912.js": { + "file": "assets/index-77bc0912.js", + "imports": [ + "index.html" + ] + }, + "index.css": { + "file": "assets/index-613d397d.css", + "src": "index.css" + }, + "index.html": { + "css": [ + "assets/index-613d397d.css" + ], + "dynamicImports": [ + "pages/AboutPage/AboutPage.tsx", + "pages/BlogPostPage/BlogPostPage.tsx", + "pages/ContactUsPage/ContactUsPage.tsx", + "pages/DoublePage/DoublePage.tsx", + "pages/ForgotPasswordPage/ForgotPasswordPage.tsx", + "pages/LoginPage/LoginPage.tsx", + "pages/NotFoundPage/NotFoundPage.tsx", + "pages/ProfilePage/ProfilePage.tsx", + "pages/ResetPasswordPage/ResetPasswordPage.tsx", + "pages/SignupPage/SignupPage.tsx", + "pages/WaterfallPage/WaterfallPage.tsx", + "pages/Contact/ContactPage/ContactPage.tsx", + "pages/Contact/ContactsPage/ContactsPage.tsx", + "pages/Contact/EditContactPage/EditContactPage.tsx", + "pages/Contact/NewContactPage/NewContactPage.tsx", + "pages/Post/EditPostPage/EditPostPage.tsx", + "pages/Post/NewPostPage/NewPostPage.tsx", + "pages/Post/PostPage/PostPage.tsx", + "pages/Post/PostsPage/PostsPage.tsx" + ], + "file": "assets/index-ff057e8f.js", + "isEntry": true, + "src": "index.html" + }, + "pages/AboutPage/AboutPage.tsx": { + "file": "assets/AboutPage-7ec0f8df.js", + "imports": [ + "index.html" + ], + "isDynamicEntry": true, + "src": "pages/AboutPage/AboutPage.tsx" + }, + "pages/BlogPostPage/BlogPostPage.tsx": { + "file": "assets/BlogPostPage-526c7060.js", + "imports": [ + "index.html" + ], + "isDynamicEntry": true, + "src": "pages/BlogPostPage/BlogPostPage.tsx" + }, + "pages/Contact/ContactPage/ContactPage.tsx": { + "file": "assets/ContactPage-4a851c42.js", + "imports": [ + "index.html", + "_formatters-2fce1756.js" + ], + "isDynamicEntry": true, + "src": "pages/Contact/ContactPage/ContactPage.tsx" + }, + "pages/Contact/ContactsPage/ContactsPage.tsx": { + "file": "assets/ContactsPage-1fcf6187.js", + "imports": [ + "index.html", + "_formatters-2fce1756.js" + ], + "isDynamicEntry": true, + "src": "pages/Contact/ContactsPage/ContactsPage.tsx" + }, + "pages/Contact/EditContactPage/EditContactPage.tsx": { + "file": "assets/EditContactPage-1622b085.js", + "imports": [ + "index.html", + "_ContactForm-d76f67ab.js", + "_index-77bc0912.js" + ], + "isDynamicEntry": true, + "src": "pages/Contact/EditContactPage/EditContactPage.tsx" + }, + "pages/Contact/NewContactPage/NewContactPage.tsx": { + "file": "assets/NewContactPage-5935f0db.js", + "imports": [ + "index.html", + "_ContactForm-d76f67ab.js", + "_index-77bc0912.js" + ], + "isDynamicEntry": true, + "src": "pages/Contact/NewContactPage/NewContactPage.tsx" + }, + "pages/ContactUsPage/ContactUsPage.tsx": { + "file": "assets/ContactUsPage-71f00589.js", + "imports": [ + "index.html", + "_index-77bc0912.js" + ], + "isDynamicEntry": true, + "src": "pages/ContactUsPage/ContactUsPage.tsx" + }, + "pages/DoublePage/DoublePage.tsx": { + "file": "assets/DoublePage-0bee4876.js", + "imports": [ + "index.html" + ], + "isDynamicEntry": true, + "src": "pages/DoublePage/DoublePage.tsx" + }, + "pages/ForgotPasswordPage/ForgotPasswordPage.tsx": { + "file": "assets/ForgotPasswordPage-15d7cf2f.js", + "imports": [ + "index.html", + "_index-77bc0912.js" + ], + "isDynamicEntry": true, + "src": "pages/ForgotPasswordPage/ForgotPasswordPage.tsx" + }, + "pages/LoginPage/LoginPage.tsx": { + "file": "assets/LoginPage-5f6d498c.js", + "imports": [ + "index.html", + "_index-77bc0912.js" + ], + "isDynamicEntry": true, + "src": "pages/LoginPage/LoginPage.tsx" + }, + "pages/NotFoundPage/NotFoundPage.tsx": { + "file": "assets/NotFoundPage-0903a03f.js", + "imports": [ + "index.html" + ], + "isDynamicEntry": true, + "src": "pages/NotFoundPage/NotFoundPage.tsx" + }, + "pages/Post/EditPostPage/EditPostPage.tsx": { + "file": "assets/EditPostPage-abe727e6.js", + "imports": [ + "index.html", + "_PostForm-4b7853da.js", + "_index-77bc0912.js" + ], + "isDynamicEntry": true, + "src": "pages/Post/EditPostPage/EditPostPage.tsx" + }, + "pages/Post/NewPostPage/NewPostPage.tsx": { + "file": "assets/NewPostPage-dcbeffd5.js", + "imports": [ + "index.html", + "_PostForm-4b7853da.js", + "_index-77bc0912.js" + ], + "isDynamicEntry": true, + "src": "pages/Post/NewPostPage/NewPostPage.tsx" + }, + "pages/Post/PostPage/PostPage.tsx": { + "file": "assets/PostPage-292888c6.js", + "imports": [ + "index.html", + "_formatters-2fce1756.js" + ], + "isDynamicEntry": true, + "src": "pages/Post/PostPage/PostPage.tsx" + }, + "pages/Post/PostsPage/PostsPage.tsx": { + "file": "assets/PostsPage-cacd5a1e.js", + "imports": [ + "index.html", + "_formatters-2fce1756.js" + ], + "isDynamicEntry": true, + "src": "pages/Post/PostsPage/PostsPage.tsx" + }, + "pages/ProfilePage/ProfilePage.tsx": { + "file": "assets/ProfilePage-133e6e05.js", + "imports": [ + "index.html" + ], + "isDynamicEntry": true, + "src": "pages/ProfilePage/ProfilePage.tsx" + }, + "pages/ResetPasswordPage/ResetPasswordPage.tsx": { + "file": "assets/ResetPasswordPage-a3399e1b.js", + "imports": [ + "index.html", + "_index-77bc0912.js" + ], + "isDynamicEntry": true, + "src": "pages/ResetPasswordPage/ResetPasswordPage.tsx" + }, + "pages/SignupPage/SignupPage.tsx": { + "file": "assets/SignupPage-44411fe1.js", + "imports": [ + "index.html", + "_index-77bc0912.js" + ], + "isDynamicEntry": true, + "src": "pages/SignupPage/SignupPage.tsx" + }, + "pages/WaterfallPage/WaterfallPage.tsx": { + "file": "assets/WaterfallPage-46b80a6f.js", + "imports": [ + "index.html" + ], + "isDynamicEntry": true, + "src": "pages/WaterfallPage/WaterfallPage.tsx" + } +} diff --git a/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/contacts/new.html b/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/contacts/new.html new file mode 100644 index 000000000000..a3d4460288bb --- /dev/null +++ b/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/contacts/new.html @@ -0,0 +1,50 @@ + + + + + + Redwood App | Redwood App + + + + + + + + + + +
+
+
+
+

Contacts

+
+
New Contact +
+
+
+
+
+

New Contact

+
+
+
+
+
+
+
+
+
+ +
+
+
+ + + diff --git a/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/favicon.png b/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/favicon.png new file mode 100644 index 000000000000..47414294173c Binary files /dev/null and b/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/favicon.png differ diff --git a/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/index.html b/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/index.html new file mode 100644 index 000000000000..0e54fa2690c7 --- /dev/null +++ b/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/index.html @@ -0,0 +1,79 @@ + + + + + Redwood App | Redwood App + + + + + + + + + + +
+
+

Redwood Blog

+ +
+
+
+
+
+

October 13, 2023 - By: User One + (user.one@example.com)

+

Welcome to the + blog!

+
+
I'm baby single- origin coffee kickstarter lo - fi paleo + skateboard.Tumblr hashtag austin whatever DIY plaid knausgaard fanny pack messenger bag blog next level + woke.Ethical bitters fixie freegan,helvetica pitchfork 90's tbh chillwave mustache godard subway tile ramps + art party. Hammock sustainable twee yr bushwick disrupt unicorn, before they sold out direct trade + chicharrones etsy polaroid hoodie. Gentrify offal hoodie fingerstache.
+
+
+
+

October 13, 2023 - By: User Two + (user.two@example.com)

+

What is the + meaning of life?

+
+
Meh waistcoat succulents umami asymmetrical, hoodie + post-ironic paleo chillwave tote bag. Trust fund kitsch waistcoat vape, cray offal gochujang food truck + cloud bread enamel pin forage. Roof party chambray ugh occupy fam stumptown. Dreamcatcher tousled snackwave, + typewriter lyft unicorn pabst portland blue bottle locavore squid PBR&B tattooed.
+
+
+
+

October 13, 2023 - By: User One + (user.one@example.com)

+

A little more + about me

+
+
Raclette shoreditch before they sold out lyft. Ethical bicycle + rights meh prism twee. Tote bag ennui vice, slow-carb taiyaki crucifix whatever you probably haven't heard + of them jianbing raw denim DIY hot chicken. Chillwave blog succulents freegan synth af ramps poutine + wayfarers yr seitan roof party squid. Jianbing flexitarian gentrify hexagon portland single-origin coffee + raclette gluten-free. Coloring book cloud bread street art kitsch lumbersexual af distillery ethical ugh + thundercats roof party poke chillwave. 90's palo santo green juice subway tile, prism viral butcher selvage + etsy pitchfork sriracha tumeric bushwick.
+
+
+ +
+
+ + + diff --git a/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/nested/index.html b/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/nested/index.html new file mode 100644 index 000000000000..355801d52690 --- /dev/null +++ b/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/nested/index.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + + +
+ + + diff --git a/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/robots.txt b/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/robots.txt new file mode 100644 index 000000000000..eb0536286f30 --- /dev/null +++ b/packages/api-server/src/__tests__/fixtures/redwood-app/web/dist/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: diff --git a/packages/api-server/src/__tests__/lambdaLoader.test.ts b/packages/api-server/src/__tests__/lambdaLoader.test.ts new file mode 100644 index 000000000000..3228ff0d68fe --- /dev/null +++ b/packages/api-server/src/__tests__/lambdaLoader.test.ts @@ -0,0 +1,75 @@ +import path from 'path' + +import { + LAMBDA_FUNCTIONS, + loadFunctionsFromDist, +} from '../plugins/lambdaLoader' + +// Suppress terminal logging. +console.log = jest.fn() +console.warn = jest.fn() + +// Set up RWJS_CWD. +let original_RWJS_CWD + +beforeAll(() => { + original_RWJS_CWD = process.env.RWJS_CWD + process.env.RWJS_CWD = path.resolve(__dirname, 'fixtures/redwood-app') +}) + +afterAll(() => { + process.env.RWJS_CWD = original_RWJS_CWD +}) + +// Reset the LAMBDA_FUNCTIONS object after each test. +afterEach(() => { + for (const key in LAMBDA_FUNCTIONS) { + delete LAMBDA_FUNCTIONS[key] + } +}) + +describe('loadFunctionsFromDist', () => { + it('loads functions from the api/dist directory', async () => { + expect(LAMBDA_FUNCTIONS).toEqual({}) + + await loadFunctionsFromDist() + + expect(LAMBDA_FUNCTIONS).toEqual({ + env: expect.any(Function), + graphql: expect.any(Function), + health: expect.any(Function), + hello: expect.any(Function), + nested: expect.any(Function), + }) + }) + + // We have logic that specifically puts the graphql function at the front. + // Though it's not clear why or if this is actually respected by how JS objects work. + // See the complementary lambdaLoaderNumberFunctions test. + it('puts the graphql function first', async () => { + expect(LAMBDA_FUNCTIONS).toEqual({}) + + await loadFunctionsFromDist() + + expect(Object.keys(LAMBDA_FUNCTIONS)[0]).toEqual('graphql') + }) + + // `loadFunctionsFromDist` loads files that don't export a handler into the object as `undefined`. + // This is probably harmless, but we could also probably go without it. + it("warns if a function doesn't have a handler and sets it to `undefined`", async () => { + expect(LAMBDA_FUNCTIONS).toEqual({}) + + await loadFunctionsFromDist() + + expect(LAMBDA_FUNCTIONS).toMatchObject({ + noHandler: undefined, + }) + + expect(console.warn).toHaveBeenCalledWith( + 'noHandler', + 'at', + expect.any(String), + 'does not have a function called handler defined.' + ) + }) +}) diff --git a/packages/api-server/src/__tests__/lambdaLoaderNumberFunctions.test.ts b/packages/api-server/src/__tests__/lambdaLoaderNumberFunctions.test.ts new file mode 100644 index 000000000000..ddeaba9bc151 --- /dev/null +++ b/packages/api-server/src/__tests__/lambdaLoaderNumberFunctions.test.ts @@ -0,0 +1,32 @@ +import path from 'path' + +import { + LAMBDA_FUNCTIONS, + loadFunctionsFromDist, +} from '../plugins/lambdaLoader' + +// Suppress terminal logging. +console.log = jest.fn() + +// Set up RWJS_CWD. +let original_RWJS_CWD + +beforeAll(() => { + original_RWJS_CWD = process.env.RWJS_CWD + process.env.RWJS_CWD = path.resolve( + __dirname, + 'fixtures/redwood-app-number-functions' + ) +}) + +afterAll(() => { + process.env.RWJS_CWD = original_RWJS_CWD +}) + +test('loadFunctionsFromDist puts functions named with numbers before the graphql function', async () => { + expect(LAMBDA_FUNCTIONS).toEqual({}) + + await loadFunctionsFromDist() + + expect(Object.keys(LAMBDA_FUNCTIONS)[0]).toEqual('1') +}) diff --git a/packages/api-server/src/__tests__/withApiProxy.test.ts b/packages/api-server/src/__tests__/withApiProxy.test.ts index 71f6733fe3af..593bba043d99 100644 --- a/packages/api-server/src/__tests__/withApiProxy.test.ts +++ b/packages/api-server/src/__tests__/withApiProxy.test.ts @@ -1,65 +1,23 @@ -import path from 'path' - +import httpProxy from '@fastify/http-proxy' import type { FastifyInstance } from 'fastify' import withApiProxy from '../plugins/withApiProxy' -const FIXTURE_PATH = path.resolve( - __dirname, - '../../../../__fixtures__/example-todo-main' -) - -// Mock the dist folder from fixtures, -// because its gitignored -jest.mock('@redwoodjs/internal', () => { - return { - ...jest.requireActual('@redwoodjs/internal'), - } -}) - -jest.mock('../fastify', () => { - return { - ...jest.requireActual('../fastify'), - loadFastifyConfig: jest.fn().mockReturnValue({ - config: {}, - configureFastify: jest.fn((fastify) => fastify), - }), +test('withApiProxy registers `@fastify/http-proxy`', async () => { + const mockedFastifyInstance = { + register: jest.fn(), } -}) -describe('Configures the ApiProxy', () => { - beforeAll(() => { - process.env.RWJS_CWD = FIXTURE_PATH + // `apiUrl` is unfortunately named. It isn't a URL, it's just a prefix. Meanwhile, `apiHost` _is_ a URL. + // See https://github.com/fastify/fastify-http-proxy and https://github.com/fastify/fastify-reply-from. + await withApiProxy(mockedFastifyInstance as unknown as FastifyInstance, { + apiUrl: 'my-api-host', + apiHost: 'http://localhost:8910', }) - afterAll(() => { - delete process.env.RWJS_CWD - }) - - beforeEach(() => { - jest.clearAllMocks() - }) - - test('Checks that the fastify http-proxy plugin is configured correctly', async () => { - const mockedFastifyInstance = { - register: jest.fn(), - get: jest.fn(), - all: jest.fn(), - addContentTypeParser: jest.fn(), - log: console, - } - - await withApiProxy(mockedFastifyInstance as unknown as FastifyInstance, { - apiUrl: 'http://localhost', - apiHost: 'my-api-host', - }) - - const mockedFastifyInstanceOptions = - mockedFastifyInstance.register.mock.calls[0][1] - expect(mockedFastifyInstanceOptions).toEqual({ - disableCache: true, - prefix: 'http://localhost', - upstream: 'my-api-host', - }) + expect(mockedFastifyInstance.register).toHaveBeenCalledWith(httpProxy, { + disableCache: true, + prefix: 'my-api-host', + upstream: 'http://localhost:8910', }) }) diff --git a/packages/api-server/src/__tests__/withFunctions.test.ts b/packages/api-server/src/__tests__/withFunctions.test.ts index 3bc3e3471cc3..45cd602f5d67 100644 --- a/packages/api-server/src/__tests__/withFunctions.test.ts +++ b/packages/api-server/src/__tests__/withFunctions.test.ts @@ -1,141 +1,151 @@ import path from 'path' -import type { FastifyInstance, FastifyPluginCallback } from 'fastify' - -import { loadFastifyConfig } from '../fastify' +import createFastifyInstance from '../fastify' import withFunctions from '../plugins/withFunctions' -const FIXTURE_PATH = path.resolve( - __dirname, - '../../../../__fixtures__/example-todo-main' -) - -// Mock the dist folder from fixtures, -// because its gitignored -jest.mock('@redwoodjs/internal', () => { - return { - ...jest.requireActual('@redwoodjs/internal'), - } -}) +// Suppress terminal logging. +console.log = jest.fn() +console.warn = jest.fn() -jest.mock('../fastify', () => { - return { - ...jest.requireActual('../fastify'), - loadFastifyConfig: jest.fn(), - } +// Set up RWJS_CWD. +let original_RWJS_CWD + +beforeAll(() => { + original_RWJS_CWD = process.env.RWJS_CWD + process.env.RWJS_CWD = path.resolve(__dirname, 'fixtures/redwood-app') }) -jest.mock('../plugins/lambdaLoader', () => { - return { - loadFunctionsFromDist: jest.fn(), - lambdaRequestHandler: jest.fn(), - } +afterAll(() => { + process.env.RWJS_CWD = original_RWJS_CWD }) -describe('Checks that configureFastify is called for the api side', () => { - beforeAll(() => { - process.env.RWJS_CWD = FIXTURE_PATH +// Set up and teardown the fastify instance for each test. +let fastifyInstance +let returnedFastifyInstance + +beforeAll(async () => { + fastifyInstance = createFastifyInstance() + + returnedFastifyInstance = await withFunctions(fastifyInstance, { + port: 8911, + apiRootPath: '/', }) - afterAll(() => { - delete process.env.RWJS_CWD + + await fastifyInstance.ready() +}) + +afterAll(async () => { + await fastifyInstance.close() +}) + +describe('withFunctions', () => { + // Deliberately using `toBe` here to check for referential equality. + it('returns the same fastify instance', async () => { + expect(returnedFastifyInstance).toBe(fastifyInstance) }) - beforeEach(() => { - jest.clearAllMocks() + it('configures the `@fastify/url-data` and `fastify-raw-body` plugins', async () => { + const plugins = fastifyInstance.printPlugins() + + expect(plugins.includes('@fastify/url-data')).toEqual(true) + expect(plugins.includes('fastify-raw-body')).toEqual(true) }) - const mockedFastifyInstance = { - register: jest.fn(), - get: jest.fn((routeName) => routeName), - all: jest.fn(), - addContentTypeParser: jest.fn(), - setNotFoundHandler: jest.fn(), - log: jest.fn(), - } as unknown as FastifyInstance - - // We're mocking a fake plugin, so don't worry about the type - const registerCustomPlugin = - 'I was registered by the custom configureFastify function' as unknown as FastifyPluginCallback - - // Mock the load fastify config function - ;(loadFastifyConfig as jest.Mock).mockReturnValue({ - config: {}, - configureFastify: jest.fn((fastify) => { - fastify.register(registerCustomPlugin) - - fastify.get( - `/rest/v1/users/get/:userId`, - async function (request, reply) { - const { userId } = request.params as any - - return reply.send(`Get User ${userId}!`) - } - ) - fastify.version = 'bazinga' - return fastify - }), + it('configures two additional content type parsers, `application/x-www-form-urlencoded` and `multipart/form-data`', async () => { + expect( + fastifyInstance.hasContentTypeParser('application/x-www-form-urlencoded') + ).toEqual(true) + expect(fastifyInstance.hasContentTypeParser('multipart/form-data')).toEqual( + true + ) }) - it('Verify that configureFastify is called with the expected side and options', async () => { - const { configureFastify } = loadFastifyConfig() - await withFunctions(mockedFastifyInstance, { - apiRootPath: '/kittens', - port: 5555, + it('can be configured by the user', async () => { + const res = await fastifyInstance.inject({ + method: 'GET', + url: '/rest/v1/users/get/1', }) - expect(configureFastify).toHaveBeenCalledTimes(1) + expect(res.body).toEqual(JSON.stringify({ id: 1 })) + }) - expect(configureFastify).toHaveBeenCalledWith(expect.anything(), { - side: 'api', - apiRootPath: '/kittens', - port: 5555, - }) + // We use `fastify.all` to register functions, which means they're invoked for all HTTP verbs. + // Only testing GET and POST here at the moment. + // + // We can use `printRoutes` with a method for debugging, but not without one. + // See https://fastify.dev/docs/latest/Reference/Server#printroutes + it('builds a tree of routes for GET and POST', async () => { + expect(fastifyInstance.printRoutes({ method: 'GET' })) + .toMatchInlineSnapshot(` + "โ””โ”€โ”€ / + โ”œโ”€โ”€ rest/v1/users/get/ + โ”‚ โ””โ”€โ”€ :userId (GET) + โ””โ”€โ”€ :routeName (GET) + โ””โ”€โ”€ / + โ””โ”€โ”€ * (GET) + " + `) + + expect(fastifyInstance.printRoutes({ method: 'POST' })) + .toMatchInlineSnapshot(` + "โ””โ”€โ”€ / + โ””โ”€โ”€ :routeName (POST) + โ””โ”€โ”€ / + โ””โ”€โ”€ * (POST) + " + `) }) - it('Check that configureFastify registers a plugin', async () => { - await withFunctions(mockedFastifyInstance, { - apiRootPath: '/kittens', - port: 5555, + describe('serves functions', () => { + it('serves hello.js', async () => { + const res = await fastifyInstance.inject({ + method: 'GET', + url: '/hello', + }) + + expect(res.statusCode).toEqual(200) + expect(res.json()).toEqual({ data: 'hello function' }) }) - expect(mockedFastifyInstance.register).toHaveBeenCalledWith( - 'I was registered by the custom configureFastify function' - ) - }) + it('it serves graphql.js', async () => { + const res = await fastifyInstance.inject({ + method: 'POST', + url: '/graphql?query={redwood{version}}', + }) - // Note: This tests an undocumented use of configureFastify to register a route - it('Check that configureFastify registers a route', async () => { - await withFunctions(mockedFastifyInstance, { - apiRootPath: '/boots', - port: 5554, + expect(res.statusCode).toEqual(200) + expect(res.json()).toEqual({ data: { version: 42 } }) }) - expect(mockedFastifyInstance.get).toHaveBeenCalledWith( - `/rest/v1/users/get/:userId`, - expect.any(Function) - ) - }) + it('serves health.js', async () => { + const res = await fastifyInstance.inject({ + method: 'GET', + url: '/health', + }) - it('Check that withFunctions returns the same Fastify instance, and not a new one', async () => { - await withFunctions(mockedFastifyInstance, { - apiRootPath: '/bazinga', - port: 5556, + expect(res.statusCode).toEqual(200) }) - expect(mockedFastifyInstance.version).toBe('bazinga') - }) + it('serves a nested function, nested.js', async () => { + const res = await fastifyInstance.inject({ + method: 'GET', + url: '/nested/nested', + }) - it('Does not throw when configureFastify is missing from server config', () => { - ;(loadFastifyConfig as jest.Mock).mockReturnValue({ - config: {}, - configureFastify: null, + expect(res.statusCode).toEqual(200) + expect(res.json()).toEqual({ data: 'nested function' }) }) - expect( - withFunctions(mockedFastifyInstance, { - apiRootPath: '/bazinga', - port: 5556, + it("doesn't serve deeply-nested functions", async () => { + const res = await fastifyInstance.inject({ + method: 'GET', + url: '/deeplyNested/nestedDir/deeplyNested', }) - ).resolves.not.toThrowError() + + expect(res.statusCode).toEqual(404) + expect(res.body).toEqual( + 'Function "deeplyNested" was not found.' + ) + }) }) }) diff --git a/packages/api-server/src/__tests__/withWebServer.test.ts b/packages/api-server/src/__tests__/withWebServer.test.ts index 0fd33f395f1e..ecd7c0f6508d 100644 --- a/packages/api-server/src/__tests__/withWebServer.test.ts +++ b/packages/api-server/src/__tests__/withWebServer.test.ts @@ -1,142 +1,283 @@ +import fs from 'fs' import path from 'path' -import type { FastifyInstance, FastifyPluginCallback } from 'fastify' +import { getPaths } from '@redwoodjs/project-config' -import { loadFastifyConfig } from '../fastify' +import { createFastifyInstance } from '../fastify' import withWebServer from '../plugins/withWebServer' -const FIXTURE_PATH = path.resolve( - __dirname, - '../../../../__fixtures__/example-todo-main' -) - -// Mock the dist folder from fixtures, -// because its gitignored -jest.mock('../plugins/findPrerenderedHtml', () => { - return { - findPrerenderedHtml: () => { - return ['about.html', 'mocked.html', 'posts/new.html', 'index.html'] - }, - } -}) +// Suppress terminal logging. +console.log = jest.fn() -jest.mock('../fastify', () => { - return { - ...jest.requireActual('../fastify'), - loadFastifyConfig: jest.fn(), - } -}) +// Set up RWJS_CWD. +let original_RWJS_CWD beforeAll(() => { - process.env.RWJS_CWD = FIXTURE_PATH + original_RWJS_CWD = process.env.RWJS_CWD + process.env.RWJS_CWD = path.join(__dirname, 'fixtures/redwood-app') }) + afterAll(() => { - delete process.env.RWJS_CWD + process.env.RWJS_CWD = original_RWJS_CWD }) -test('Attach handlers for prerendered files', async () => { - const mockedFastifyInstance = { - register: jest.fn(), - get: jest.fn(), - setNotFoundHandler: jest.fn(), - log: console, - } as unknown as FastifyInstance - - await withWebServer(mockedFastifyInstance, { port: 3000 }) - - expect(mockedFastifyInstance.get).toHaveBeenCalledWith( - '/about', - expect.anything() - ) - expect(mockedFastifyInstance.get).toHaveBeenCalledWith( - '/mocked', - expect.anything() - ) - expect(mockedFastifyInstance.get).toHaveBeenCalledWith( - '/posts/new', - expect.anything() - ) - - // Ignore index.html - expect(mockedFastifyInstance.get).not.toHaveBeenCalledWith( - '/index', - expect.anything() - ) -}) +// Set up and teardown the fastify instance with options. +let fastifyInstance +let returnedFastifyInstance -test('Adds SPA fallback', async () => { - const mockedFastifyInstance = { - register: jest.fn(), - get: jest.fn(), - setNotFoundHandler: jest.fn(), - log: console, - } as unknown as FastifyInstance +const port = 8910 +const message = 'hello from server.config.js' - await withWebServer(mockedFastifyInstance, { port: 3000 }) +beforeAll(async () => { + fastifyInstance = createFastifyInstance() - expect(mockedFastifyInstance.setNotFoundHandler).toHaveBeenCalled() + returnedFastifyInstance = await withWebServer(fastifyInstance, { + port, + // @ts-expect-error just testing that options can be passed through + message, + }) + + await fastifyInstance.ready() }) -describe('Checks that configureFastify is called for the web side', () => { - beforeEach(() => { - jest.clearAllMocks() +afterAll(async () => { + await fastifyInstance.close() +}) + +describe('withWebServer', () => { + // Deliberately using `toBe` here to check for referential equality. + it('returns the same fastify instance', async () => { + expect(returnedFastifyInstance).toBe(fastifyInstance) }) - const mockedFastifyInstance = { - register: jest.fn(), - get: jest.fn(), - setNotFoundHandler: jest.fn(), - log: jest.fn(), - } as unknown as FastifyInstance - - // We're mocking a fake plugin, so don't worry about the type - const fakeFastifyPlugin = - 'Fake bazinga plugin' as unknown as FastifyPluginCallback - - // Mock the load fastify config function - ;(loadFastifyConfig as jest.Mock).mockReturnValue({ - config: {}, - configureFastify: jest.fn((fastify) => { - fastify.register(fakeFastifyPlugin) - fastify.version = 'bazinga' - return fastify - }), + it('can be configured by the user', async () => { + const res = await fastifyInstance.inject({ + method: 'GET', + url: '/test-route', + }) + + expect(res.body).toBe(JSON.stringify({ message })) }) - it('Check that configureFastify is called with the expected side and options', async () => { - await withWebServer(mockedFastifyInstance, { port: 3001 }) + // We can use `printRoutes` with a method for debugging, but not without one. + // See https://fastify.dev/docs/latest/Reference/Server#printroutes + it('builds a tree of routes for GET', async () => { + expect(fastifyInstance.printRoutes({ method: 'GET' })) + .toMatchInlineSnapshot(` + "โ””โ”€โ”€ / + โ”œโ”€โ”€ about (GET) + โ”œโ”€โ”€ contacts/new (GET) + โ”œโ”€โ”€ nested/index (GET) + โ”œโ”€โ”€ test-route (GET) + โ””โ”€โ”€ * (GET) + " + `) + }) - const { configureFastify } = loadFastifyConfig() + describe('serves prerendered files', () => { + it('serves the prerendered about page', async () => { + const url = '/about' - expect(configureFastify).toHaveBeenCalledTimes(1) + const res = await fastifyInstance.inject({ + method: 'GET', + url, + }) - // We don't care about the first argument - expect(configureFastify).toHaveBeenCalledWith(expect.anything(), { - side: 'web', - port: 3001, + expect(res.statusCode).toBe(200) + expect(res.headers['content-type']).toBe('text/html; charset=UTF-8') + expect(res.body).toBe( + fs.readFileSync(path.join(getPaths().web.dist, `${url}.html`), 'utf-8') + ) }) - }) - it('Check that configureFastify will register in Fastify a plugin', async () => { - await withWebServer(mockedFastifyInstance, { port: 3001 }) - expect(mockedFastifyInstance.register).toHaveBeenCalledWith( - 'Fake bazinga plugin' - ) - }) + it('serves the prerendered new contact page', async () => { + const url = '/contacts/new' + + const res = await fastifyInstance.inject({ + method: 'GET', + url, + }) + + expect(res.statusCode).toBe(200) + expect(res.headers['content-type']).toBe('text/html; charset=UTF-8') + expect(res.body).toBe( + fs.readFileSync(path.join(getPaths().web.dist, `${url}.html`), 'utf-8') + ) + }) + + // We don't serve files named index.js at the root level. + // This logic ensures nested files aren't affected. + it('serves the prerendered nested index page', async () => { + const url = '/nested/index' + + const res = await fastifyInstance.inject({ + method: 'GET', + url, + }) + + expect(res.statusCode).toBe(200) + expect(res.headers['content-type']).toBe('text/html; charset=UTF-8') + expect(res.body).toBe( + fs.readFileSync(path.join(getPaths().web.dist, `${url}.html`), 'utf-8') + ) + }) + + it('serves prerendered files with certain headers', async () => { + await fastifyInstance.listen({ port }) + + const res = await fetch(`http://localhost:${port}/about`) + const headers = [...res.headers.keys()] + + expect(headers).toMatchInlineSnapshot(` + [ + "accept-ranges", + "cache-control", + "connection", + "content-length", + "content-type", + "date", + "etag", + "keep-alive", + "last-modified", + ] + `) + }) + + // I'm not sure if this was intentional, but we support it. + // We may want to use the `@fastify/static` plugin's `allowedPath` option. + // See https://github.com/fastify/fastify-static?tab=readme-ov-file#allowedpath. + it('serves prerendered files at `${routeName}.html`', async () => { + const url = '/about.html' - it('Check that withWebServer returns the same Fastify instance, and not a new one', async () => { - await withWebServer(mockedFastifyInstance, { port: 3001 }) - expect(mockedFastifyInstance.version).toBe('bazinga') + const res = await fastifyInstance.inject({ + method: 'GET', + url, + }) + + expect(res.statusCode).toBe(200) + expect(res.headers['content-type']).toBe('text/html; charset=UTF-8') + expect(res.body).toBe( + fs.readFileSync(path.join(getPaths().web.dist, url), 'utf-8') + ) + }) + + it('handles not found by serving a fallback', async () => { + const res = await fastifyInstance.inject({ + method: 'GET', + url: '/absent.html', + }) + + expect(res.statusCode).toBe(200) + expect(res.headers['content-type']).toBe('text/html; charset=UTF-8') + expect(res.body).toBe( + fs.readFileSync(path.join(getPaths().web.dist, '200.html'), 'utf-8') + ) + }) }) - it('When configureFastify is missing from server config, it does not throw', () => { - ;(loadFastifyConfig as jest.Mock).mockReturnValue({ - config: {}, - configureFastify: null, + describe('serves pretty much anything in web dist', () => { + it('serves the built AboutPage.js', async () => { + const relativeFilePath = '/assets/AboutPage-7ec0f8df.js' + + const res = await fastifyInstance.inject({ + method: 'GET', + url: relativeFilePath, + }) + + expect(res.statusCode).toBe(200) + expect(res.headers['content-type']).toBe( + 'application/javascript; charset=UTF-8' + ) + expect(res.body).toBe( + fs.readFileSync( + path.join(getPaths().web.dist, relativeFilePath), + 'utf-8' + ) + ) }) - expect( - withWebServer(mockedFastifyInstance, { port: 3001 }) - ).resolves.not.toThrowError() + it('serves the built index.css', async () => { + const relativeFilePath = '/assets/index-613d397d.css' + + const res = await fastifyInstance.inject({ + method: 'GET', + url: relativeFilePath, + }) + + expect(res.statusCode).toBe(200) + expect(res.headers['content-type']).toBe('text/css; charset=UTF-8') + expect(res.body).toBe( + fs.readFileSync( + path.join(getPaths().web.dist, relativeFilePath), + 'utf-8' + ) + ) + }) + + it('serves build-manifest.json', async () => { + const relativeFilePath = '/build-manifest.json' + + const res = await fastifyInstance.inject({ + method: 'GET', + url: relativeFilePath, + }) + + expect(res.statusCode).toBe(200) + expect(res.headers['content-type']).toBe( + 'application/json; charset=UTF-8' + ) + expect(res.body).toBe( + fs.readFileSync( + path.join(getPaths().web.dist, relativeFilePath), + 'utf-8' + ) + ) + }) + + it('serves favicon.png', async () => { + const res = await fastifyInstance.inject({ + method: 'GET', + url: '/favicon.png', + }) + + expect(res.statusCode).toBe(200) + expect(res.headers['content-type']).toBe('image/png') + }) + + it('serves README.md', async () => { + const relativeFilePath = '/README.md' + + const res = await fastifyInstance.inject({ + method: 'GET', + url: relativeFilePath, + }) + + expect(res.statusCode).toBe(200) + expect(res.headers['content-type']).toBe('text/markdown; charset=UTF-8') + expect(res.body).toBe( + fs.readFileSync( + path.join(getPaths().web.dist, relativeFilePath), + 'utf-8' + ) + ) + }) + + it('serves robots.txt', async () => { + const relativeFilePath = '/robots.txt' + + const res = await fastifyInstance.inject({ + method: 'GET', + url: relativeFilePath, + }) + + expect(res.statusCode).toBe(200) + expect(res.headers['content-type']).toBe('text/plain; charset=UTF-8') + expect(res.body).toBe( + fs.readFileSync( + path.join(getPaths().web.dist, relativeFilePath), + 'utf-8' + ) + ) + }) }) }) diff --git a/packages/api-server/src/__tests__/withWebServerFallback.test.ts b/packages/api-server/src/__tests__/withWebServerFallback.test.ts new file mode 100644 index 000000000000..d962b26bcf5b --- /dev/null +++ b/packages/api-server/src/__tests__/withWebServerFallback.test.ts @@ -0,0 +1,43 @@ +import fs from 'fs' +import path from 'path' + +import { getPaths } from '@redwoodjs/project-config' + +import { createFastifyInstance } from '../fastify' +import withWebServer from '../plugins/withWebServer' + +// Set up RWJS_CWD. +let original_RWJS_CWD + +beforeAll(() => { + original_RWJS_CWD = process.env.RWJS_CWD + process.env.RWJS_CWD = path.join(__dirname, 'fixtures/redwood-app-fallback') +}) + +afterAll(() => { + process.env.RWJS_CWD = original_RWJS_CWD +}) + +test("handles not found by serving index.html if 200.html doesn't exist", async () => { + const fastifyInstance = await withWebServer( + createFastifyInstance({ logger: false }), + { + port: 8910, + } + ) + + const url = '/index.html' + + const res = await fastifyInstance.inject({ + method: 'GET', + url, + }) + + expect(res.statusCode).toBe(200) + expect(res.headers['content-type']).toBe('text/html; charset=UTF-8') + expect(res.body).toBe( + fs.readFileSync(path.join(getPaths().web.dist, url), 'utf-8') + ) + + await fastifyInstance.close() +}) diff --git a/packages/api-server/src/__tests__/withWebServerLoadFastifyConfig.test.ts b/packages/api-server/src/__tests__/withWebServerLoadFastifyConfig.test.ts new file mode 100644 index 000000000000..33ca81da8192 --- /dev/null +++ b/packages/api-server/src/__tests__/withWebServerLoadFastifyConfig.test.ts @@ -0,0 +1,92 @@ +import { vol } from 'memfs' + +import { createFastifyInstance } from '../fastify' +import withWebServer from '../plugins/withWebServer' + +// Suppress terminal logging. +console.log = jest.fn() + +// Set up RWJS_CWD. +let original_RWJS_CWD +const FIXTURE_PATH = '/redwood-app' + +beforeAll(() => { + original_RWJS_CWD = process.env.RWJS_CWD + process.env.RWJS_CWD = FIXTURE_PATH +}) + +afterAll(() => { + process.env.RWJS_CWD = original_RWJS_CWD +}) + +// Mock server.config.js. +jest.mock('fs', () => require('memfs').fs) + +jest.mock( + '/redwood-app/api/server.config.js', + () => { + return { + config: {}, + configureFastify: async (fastify, options) => { + if (options.side === 'web') { + fastify.get('/about.html', async (_request, _reply) => { + return { virtualAboutHtml: true } + }) + } + + return fastify + }, + } + }, + { virtual: true } +) + +jest.mock( + '\\redwood-app\\api\\server.config.js', + () => { + return { + config: {}, + configureFastify: async (fastify, options) => { + if (options.side === 'web') { + fastify.get('/about.html', async (_request, _reply) => { + return { virtualAboutHtml: true } + }) + } + + return fastify + }, + } + }, + { virtual: true } +) + +test("the user can overwrite static files that weren't set specifically ", async () => { + vol.fromNestedJSON( + { + 'redwood.toml': '', + api: { + 'server.config.js': '', + }, + web: { + dist: { + 'about.html': '

About

', + }, + }, + }, + FIXTURE_PATH + ) + + const fastifyInstance = await withWebServer(createFastifyInstance(), { + port: 8910, + }) + + const res = await fastifyInstance.inject({ + method: 'GET', + url: '/about.html', + }) + + expect(res.statusCode).toBe(200) + expect(res.body).toBe(JSON.stringify({ virtualAboutHtml: true })) + + await fastifyInstance.close() +}) diff --git a/packages/api-server/src/__tests__/withWebServerLoadFastifyConfigError.test.ts b/packages/api-server/src/__tests__/withWebServerLoadFastifyConfigError.test.ts new file mode 100644 index 000000000000..115e927bec2c --- /dev/null +++ b/packages/api-server/src/__tests__/withWebServerLoadFastifyConfigError.test.ts @@ -0,0 +1,88 @@ +import { vol } from 'memfs' + +import { createFastifyInstance } from '../fastify' +import withWebServer from '../plugins/withWebServer' + +// Suppress terminal logging. +console.log = jest.fn() + +// Set up RWJS_CWD. +let original_RWJS_CWD +const FIXTURE_PATH = '/redwood-app' + +beforeAll(() => { + original_RWJS_CWD = process.env.RWJS_CWD + process.env.RWJS_CWD = FIXTURE_PATH +}) + +afterAll(() => { + process.env.RWJS_CWD = original_RWJS_CWD +}) + +// Mock server.config.js. +jest.mock('fs', () => require('memfs').fs) + +const aboutHTML = '

About

' + +jest.mock( + '/redwood-app/api/server.config.js', + () => { + return { + config: {}, + configureFastify: async (fastify, options) => { + if (options.side === 'web') { + fastify.get('/about', async (_request, _reply) => { + return { virtualAboutHtml: true } + }) + } + + return fastify + }, + } + }, + { virtual: true } +) + +jest.mock( + '\\redwood-app\\api\\server.config.js', + () => { + return { + config: {}, + configureFastify: async (fastify, options) => { + if (options.side === 'web') { + fastify.get('/about', async (_request, _reply) => { + return { virtualAboutHtml: true } + }) + } + + return fastify + }, + } + }, + { virtual: true } +) + +test("the user can't overwrite prerendered files", async () => { + vol.fromNestedJSON( + { + 'redwood.toml': '', + api: { + 'server.config.js': '', + }, + web: { + dist: { + 'about.html': aboutHTML, + }, + }, + }, + FIXTURE_PATH + ) + + try { + await withWebServer(createFastifyInstance(), { + port: 8910, + }) + } catch (e) { + expect(e.code).toBe('FST_ERR_DUPLICATED_ROUTE') + } +}) diff --git a/packages/api-server/src/fastify.ts b/packages/api-server/src/fastify.ts index 36c95c7147b2..5b73d2c45204 100644 --- a/packages/api-server/src/fastify.ts +++ b/packages/api-server/src/fastify.ts @@ -8,7 +8,8 @@ import { getPaths, getConfig } from '@redwoodjs/project-config' import type { FastifySideConfigFn } from './types' -const DEFAULT_OPTIONS = { +// Exported for testing. +export const DEFAULT_OPTIONS = { logger: { level: process.env.NODE_ENV === 'development' ? 'debug' : 'info', }, diff --git a/packages/babel-config/src/plugins/__tests__/__fixtures__/route-auto-loader/failure/redwood.toml b/packages/babel-config/src/plugins/__tests__/__fixtures__/route-auto-loader/failure/redwood.toml new file mode 100644 index 000000000000..286d9315b1ba --- /dev/null +++ b/packages/babel-config/src/plugins/__tests__/__fixtures__/route-auto-loader/failure/redwood.toml @@ -0,0 +1,10 @@ +[web] + port = 8910 + apiProxyPath = "/api/functions" + +[api] + port = 8911 + [api.paths] + functions = './api/src/functions' + graphql = './api/src/graphql' + generated = './api/generated' diff --git a/packages/babel-config/src/plugins/__tests__/__fixtures__/route-auto-loader/failure/web/src/Routes.tsx b/packages/babel-config/src/plugins/__tests__/__fixtures__/route-auto-loader/failure/web/src/Routes.tsx new file mode 100644 index 000000000000..6e95d14b53c8 --- /dev/null +++ b/packages/babel-config/src/plugins/__tests__/__fixtures__/route-auto-loader/failure/web/src/Routes.tsx @@ -0,0 +1,11 @@ +import { Router, Route } from '@redwoodjs/router' + +const Routes = () => { + return ( + + + + ) +} + +export default Routes diff --git a/packages/babel-config/src/plugins/__tests__/__fixtures__/route-auto-loader/failure/web/src/pages/HomePage/HomePage.tsx b/packages/babel-config/src/plugins/__tests__/__fixtures__/route-auto-loader/failure/web/src/pages/HomePage/HomePage.tsx new file mode 100644 index 000000000000..c184a81e8e9b --- /dev/null +++ b/packages/babel-config/src/plugins/__tests__/__fixtures__/route-auto-loader/failure/web/src/pages/HomePage/HomePage.tsx @@ -0,0 +1,9 @@ +const HomePage = () => { + return ( +
+

HomePage

+
+ ) +} + +export default HomePage diff --git a/packages/babel-config/src/plugins/__tests__/__fixtures__/route-auto-loader/failure/web/src/pages/HomePage/useHomePage.tsx b/packages/babel-config/src/plugins/__tests__/__fixtures__/route-auto-loader/failure/web/src/pages/HomePage/useHomePage.tsx new file mode 100644 index 000000000000..e93ada786af0 --- /dev/null +++ b/packages/babel-config/src/plugins/__tests__/__fixtures__/route-auto-loader/failure/web/src/pages/HomePage/useHomePage.tsx @@ -0,0 +1,5 @@ +const useHomePage = () => { + return 'useHomePage' +} + +export default useHomePage diff --git a/packages/babel-config/src/plugins/__tests__/babel-plugin-redwood-routes-auto-loader.test.ts b/packages/babel-config/src/plugins/__tests__/babel-plugin-redwood-routes-auto-loader.test.ts index 9c3e63601dc2..9c27d7c93800 100644 --- a/packages/babel-config/src/plugins/__tests__/babel-plugin-redwood-routes-auto-loader.test.ts +++ b/packages/babel-config/src/plugins/__tests__/babel-plugin-redwood-routes-auto-loader.test.ts @@ -7,11 +7,6 @@ import { getPaths } from '@redwoodjs/project-config' import babelRoutesAutoLoader from '../babel-plugin-redwood-routes-auto-loader' -const FIXTURE_PATH = path.resolve( - __dirname, - '../../../../../__fixtures__/example-todo-main/' -) - const transform = (filename: string) => { const code = fs.readFileSync(filename, 'utf-8') return babel.transform(code, { @@ -21,7 +16,35 @@ const transform = (filename: string) => { }) } +describe('mulitiple files ending in Page.{js,jsx,ts,tsx}', () => { + const FAILURE_FIXTURE_PATH = path.resolve( + __dirname, + './__fixtures__/route-auto-loader/failure' + ) + + beforeAll(() => { + process.env.RWJS_CWD = FAILURE_FIXTURE_PATH + }) + + afterAll(() => { + delete process.env.RWJS_CWD + }) + + test('Fails with appropriate message', () => { + expect(() => { + transform(getPaths().web.routes) + }).toThrowError( + "Unable to find only a single file ending in 'Page.{js,jsx,ts,tsx}' in the follow page directories: 'HomePage" + ) + }) +}) + describe('page auto loader correctly imports pages', () => { + const FIXTURE_PATH = path.resolve( + __dirname, + '../../../../../__fixtures__/example-todo-main/' + ) + let result: babel.BabelFileResult | null beforeAll(() => { diff --git a/packages/babel-config/src/plugins/babel-plugin-redwood-routes-auto-loader.ts b/packages/babel-config/src/plugins/babel-plugin-redwood-routes-auto-loader.ts index 03ce0e6d3460..7457db2babcc 100644 --- a/packages/babel-config/src/plugins/babel-plugin-redwood-routes-auto-loader.ts +++ b/packages/babel-config/src/plugins/babel-plugin-redwood-routes-auto-loader.ts @@ -43,6 +43,26 @@ export default function ( // @NOTE: This var gets mutated inside the visitors let pages = processPagesDir().map(withRelativeImports) + // Currently processPagesDir() can return duplicate entries when there are multiple files + // ending in Page in the individual page directories. This will cause an error upstream. + // Here we check for duplicates and throw a more helpful error message. + const duplicatePageImportNames = new Set() + const sortedPageImportNames = pages.map((page) => page.importName).sort() + for (let i = 0; i < sortedPageImportNames.length - 1; i++) { + if (sortedPageImportNames[i + 1] === sortedPageImportNames[i]) { + duplicatePageImportNames.add(sortedPageImportNames[i]) + } + } + if (duplicatePageImportNames.size > 0) { + throw new Error( + `Unable to find only a single file ending in 'Page.{js,jsx,ts,tsx}' in the follow page directories: ${Array.from( + duplicatePageImportNames + ) + .map((name) => `'${name}'`) + .join(', ')}` + ) + } + return { name: 'babel-plugin-redwood-routes-auto-loader', visitor: { diff --git a/packages/cli-helpers/package.json b/packages/cli-helpers/package.json index 8ebb15ecc338..f48fec629930 100644 --- a/packages/cli-helpers/package.json +++ b/packages/cli-helpers/package.json @@ -24,11 +24,13 @@ "dependencies": { "@babel/core": "^7.22.20", "@babel/runtime-corejs3": "7.23.1", + "@iarna/toml": "2.2.5", "@opentelemetry/api": "1.4.1", "@redwoodjs/project-config": "6.0.7", "@redwoodjs/telemetry": "6.0.7", "chalk": "4.1.2", "core-js": "3.32.2", + "dotenv": "16.3.1", "execa": "5.1.1", "listr2": "6.6.1", "lodash": "4.17.21", diff --git a/packages/cli-helpers/src/lib/__tests__/__snapshots__/project.test.ts.snap b/packages/cli-helpers/src/lib/__tests__/__snapshots__/project.test.ts.snap new file mode 100644 index 000000000000..6da535eaf61e --- /dev/null +++ b/packages/cli-helpers/src/lib/__tests__/__snapshots__/project.test.ts.snap @@ -0,0 +1,149 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`addEnvVar addEnvVar adds environment variables as part of a setup task should add a comment that the existing environment variable value was not changed, but include its new value as a comment 1`] = ` +"EXISTING_VAR=value +# CommentedVar=123 + +# Note: The existing environment variable EXISTING_VAR was not overwritten. Uncomment to use its new value. +# Updated existing variable Comment +# EXISTING_VAR = new_value +" +`; + +exports[`addEnvVar addEnvVar adds environment variables as part of a setup task should add a new environment variable when it does not exist 1`] = ` +"EXISTING_VAR = value +# CommentedVar = 123 + +# New Variable Comment +NEW_VAR = new_value +" +`; + +exports[`addEnvVar addEnvVar adds environment variables as part of a setup task should add a new environment variable when it does not exist when existing envars have no spacing 1`] = ` +"EXISTING_VAR=value +# CommentedVar = 123 + +# New Variable Comment +NEW_VAR = new_value +" +`; + +exports[`addEnvVar addEnvVar adds environment variables as part of a setup task should handle existing environment variables and new value with quoted values by not updating the original value 1`] = ` +"EXISTING_VAR = "value" +# CommentedVar = 123 + +# Note: The existing environment variable EXISTING_VAR was not overwritten. Uncomment to use its new value. +# New Variable Comment +# EXISTING_VAR = new_value +" +`; + +exports[`addEnvVar addEnvVar adds environment variables as part of a setup task should handle existing environment variables with quoted values 1`] = ` +"EXISTING_VAR = "value" +# CommentedVar = 123 +" +`; + +exports[`addEnvVar addEnvVar adds environment variables as part of a setup task should handle existing environment variables with quoted values and no spacing 1`] = ` +"EXISTING_VAR="value" +# CommentedVar=123 +" +`; + +exports[`updateTomlConfig updateTomlConfig configures a new CLI plugin adds package but keeps autoInstall false 1`] = ` +"[web] +title = "Redwood App" +port = 8_910 +apiUrl = "/.redwood/functions" +includeEnvironmentVariables = [ ] + +[api] +port = 8_911 + +[experimental.cli] +autoInstall = false + +[[experimental.cli.plugins]] +package = "@example/test-package-when-autoInstall-false" +enabled = true +" +`; + +exports[`updateTomlConfig updateTomlConfig configures a new CLI plugin adds when experimental cli has some plugins configured 1`] = ` +"[web] +title = "Redwood App" +port = 8_910 +apiUrl = "/.redwood/functions" +includeEnvironmentVariables = [ ] + +[api] +port = 8_911 + +[experimental.cli] +autoInstall = true + + [[experimental.cli.plugins]] + package = "@existing-example/some-package-when-cli-has-some-packages-configured" + +[[experimental.cli.plugins]] +package = "@example/test-package-name" +enabled = true +" +`; + +exports[`updateTomlConfig updateTomlConfig configures a new CLI plugin adds when experimental cli is not configured 1`] = ` +"[web] +title = "Redwood App" +port = 8_910 +apiUrl = "/.redwood/functions" +includeEnvironmentVariables = [ ] + +[api] +port = 8_911 + +[experimental.cli] +autoInstall = true + + [[experimental.cli.plugins]] + package = "@example/test-package-when-cli-not-configured" + enabled = true +" +`; + +exports[`updateTomlConfig updateTomlConfig configures a new CLI plugin adds when experimental cli is setup but has no plugins configured 1`] = ` +"[web] +title = "Redwood App" +port = 8_910 +apiUrl = "/.redwood/functions" +includeEnvironmentVariables = [ ] + +[api] +port = 8_911 + +[experimental.cli] +autoInstall = true + +[[experimental.cli.plugins]] +package = "@example/test-package-when-no-plugins-configured" +enabled = true +" +`; + +exports[`updateTomlConfig updateTomlConfig configures a new CLI plugin does not add duplicate place when experimental cli has that plugin configured 1`] = ` +"[web] +title = "Redwood App" +port = 8_910 +apiUrl = "/.redwood/functions" +includeEnvironmentVariables = [ ] + +[api] +port = 8_911 + +[experimental.cli] +autoInstall = true + + [[experimental.cli.plugins]] + package = "@existing-example/some-package-name-already-exists" + +" +`; diff --git a/packages/cli-helpers/src/lib/__tests__/project.test.ts b/packages/cli-helpers/src/lib/__tests__/project.test.ts new file mode 100644 index 000000000000..3aef810bc9bc --- /dev/null +++ b/packages/cli-helpers/src/lib/__tests__/project.test.ts @@ -0,0 +1,214 @@ +import fs from 'fs' + +import toml from '@iarna/toml' + +import { updateTomlConfig, addEnvVar } from '../project' // Replace with the correct path to your module + +jest.mock('fs') + +const defaultRedwoodToml = { + web: { + title: 'Redwood App', + port: 8910, + apiUrl: '/.redwood/functions', + includeEnvironmentVariables: [], + }, + api: { + port: 8911, + }, +} + +const getRedwoodToml = () => { + return defaultRedwoodToml +} + +jest.mock('@redwoodjs/project-config', () => { + return { + getPaths: () => { + return { + generated: { + base: '.redwood', + }, + base: '', + } + }, + getConfigPath: () => { + return '.redwood.toml' + }, + getConfig: () => { + return getRedwoodToml() + }, + } +}) + +describe('addEnvVar', () => { + let envFileContent = '' + + describe('addEnvVar adds environment variables as part of a setup task', () => { + beforeEach(() => { + jest.spyOn(fs, 'existsSync').mockImplementation(() => { + return true + }) + + jest.spyOn(fs, 'readFileSync').mockImplementation(() => { + return envFileContent + }) + + jest.spyOn(fs, 'writeFileSync').mockImplementation((envPath, envFile) => { + expect(envPath).toContain('.env') + return envFile + }) + }) + + afterEach(() => { + jest.restoreAllMocks() + envFileContent = '' + }) + + it('should add a new environment variable when it does not exist', () => { + envFileContent = 'EXISTING_VAR = value\n# CommentedVar = 123\n' + const file = addEnvVar('NEW_VAR', 'new_value', 'New Variable Comment') + + expect(file).toMatchSnapshot() + }) + + it('should add a new environment variable when it does not exist when existing envars have no spacing', () => { + envFileContent = 'EXISTING_VAR=value\n# CommentedVar = 123\n' + const file = addEnvVar('NEW_VAR', 'new_value', 'New Variable Comment') + + expect(file).toMatchSnapshot() + }) + + it('should add a comment that the existing environment variable value was not changed, but include its new value as a comment', () => { + envFileContent = 'EXISTING_VAR=value\n# CommentedVar=123\n' + const file = addEnvVar( + 'EXISTING_VAR', + 'new_value', + 'Updated existing variable Comment' + ) + + expect(file).toMatchSnapshot() + }) + + it('should handle existing environment variables with quoted values', () => { + envFileContent = `EXISTING_VAR = "value"\n# CommentedVar = 123\n` + const file = addEnvVar('EXISTING_VAR', 'value', 'New Variable Comment') + + expect(file).toMatchSnapshot() + }) + + it('should handle existing environment variables with quoted values and no spacing', () => { + envFileContent = `EXISTING_VAR="value"\n# CommentedVar=123\n` + const file = addEnvVar('EXISTING_VAR', 'value', 'New Variable Comment') + + expect(file).toMatchSnapshot() + }) + + it('should handle existing environment variables and new value with quoted values by not updating the original value', () => { + envFileContent = `EXISTING_VAR = "value"\n# CommentedVar = 123\n` + const file = addEnvVar( + 'EXISTING_VAR', + 'new_value', + 'New Variable Comment' + ) + + expect(file).toMatchSnapshot() + }) + }) +}) + +describe('updateTomlConfig', () => { + describe('updateTomlConfig configures a new CLI plugin', () => { + beforeEach(() => { + jest.spyOn(fs, 'existsSync').mockImplementation(() => { + return true + }) + + jest.spyOn(fs, 'readFileSync').mockImplementation(() => { + return toml.stringify(defaultRedwoodToml) + }) + + jest + .spyOn(fs, 'writeFileSync') + .mockImplementation((tomlPath, tomlFile) => { + expect(tomlPath).toContain('redwood.toml') + return tomlFile + }) + }) + + afterEach(() => { + jest.restoreAllMocks() + }) + + it('adds when experimental cli is not configured', () => { + const file = updateTomlConfig( + '@example/test-package-when-cli-not-configured' + ) + expect(file).toMatchSnapshot() + }) + + it('adds when experimental cli has some plugins configured', () => { + defaultRedwoodToml['experimental'] = { + cli: { + autoInstall: true, + plugins: [ + { + package: + '@existing-example/some-package-when-cli-has-some-packages-configured', + }, + ], + }, + } + + const file = updateTomlConfig('@example/test-package-name') + expect(file).toMatchSnapshot() + }) + + it('adds when experimental cli is setup but has no plugins configured', () => { + defaultRedwoodToml['experimental'] = { + cli: { + autoInstall: true, + }, + } + + const file = updateTomlConfig( + '@example/test-package-when-no-plugins-configured' + ) + + expect(file).toMatchSnapshot() + }) + + it('adds package but keeps autoInstall false', () => { + defaultRedwoodToml['experimental'] = { + cli: { + autoInstall: false, + }, + } + + const file = updateTomlConfig( + '@example/test-package-when-autoInstall-false' + ) + + expect(file).toMatchSnapshot() + }) + + it('does not add duplicate place when experimental cli has that plugin configured', () => { + defaultRedwoodToml['experimental'] = { + cli: { + autoInstall: true, + plugins: [ + { + package: '@existing-example/some-package-name-already-exists', + }, + ], + }, + } + + const file = updateTomlConfig( + '@existing-example/some-package-name-already-exists' + ) + + expect(file).toMatchSnapshot() + }) + }) +}) diff --git a/packages/cli-helpers/src/lib/project.ts b/packages/cli-helpers/src/lib/project.ts index 1e0c6fe618dd..7755671f2aad 100644 --- a/packages/cli-helpers/src/lib/project.ts +++ b/packages/cli-helpers/src/lib/project.ts @@ -1,7 +1,16 @@ import fs from 'fs' import path from 'path' -import { resolveFile, findUp } from '@redwoodjs/project-config' +import type { JsonMap } from '@iarna/toml' +import toml from '@iarna/toml' +import dotenv from 'dotenv' + +import { + findUp, + getConfigPath, + getConfig, + resolveFile, +} from '@redwoodjs/project-config' import { colors } from './colors' import { getPaths } from './paths' @@ -33,21 +42,117 @@ export const getInstalledRedwoodVersion = () => { } } +/** + * Updates the project's redwood.toml file to include the specified packages plugin + * + * Uses toml parsing to determine if the plugin is already included in the file and + * only adds it if it is not. + * + * Writes the updated config to the file system by appending strings, not stringify-ing the toml. + */ +export const updateTomlConfig = (packageName: string) => { + const redwoodTomlPath = getConfigPath() + const originalTomlContent = fs.readFileSync(redwoodTomlPath, 'utf-8') + + let tomlToAppend = {} as JsonMap + + const config = getConfig(redwoodTomlPath) + + const cliSection = config.experimental?.cli + + if (!cliSection) { + tomlToAppend = { + experimental: { + cli: { + autoInstall: true, + plugins: [{ package: packageName, enabled: true }], + }, + }, + } + } else if (cliSection.plugins) { + const packageExists = cliSection.plugins.some( + (plugin) => plugin.package === packageName + ) + + if (!packageExists) { + tomlToAppend = { + experimental: { + cli: { + plugins: [{ package: packageName, enabled: true }], + }, + }, + } + } + } else { + tomlToAppend = { + experimental: { + cli: { + plugins: [{ package: packageName, enabled: true }], + }, + }, + } + } + + const newConfig = originalTomlContent + '\n' + toml.stringify(tomlToAppend) + + return fs.writeFileSync(redwoodTomlPath, newConfig, 'utf-8') +} + +export const updateTomlConfigTask = (packageName: string) => { + return { + title: `Updating redwood.toml to configure ${packageName} ...`, + task: () => { + updateTomlConfig(packageName) + }, + } +} + export const addEnvVarTask = (name: string, value: string, comment: string) => { return { title: `Adding ${name} var to .env...`, task: () => { - const envPath = path.join(getPaths().base, '.env') - const content = [comment && `# ${comment}`, `${name}=${value}`, ''].flat() - let envFile = '' + addEnvVar(name, value, comment) + }, + } +} - if (fs.existsSync(envPath)) { - envFile = fs.readFileSync(envPath).toString() + '\n' - } +export const addEnvVar = (name: string, value: string, comment: string) => { + const envPath = path.join(getPaths().base, '.env') + let envFile = '' + const newEnvironmentVariable = [ + comment && `# ${comment}`, + `${name} = ${value}`, + '', + ] + .flat() + .join('\n') - fs.writeFileSync(envPath, envFile + content.join('\n')) - }, + if (fs.existsSync(envPath)) { + envFile = fs.readFileSync(envPath).toString() + const existingEnvVars = dotenv.parse(envFile) + + if (existingEnvVars[name] && existingEnvVars[name] === value) { + return envFile + } + + if (existingEnvVars[name]) { + const p = [ + `# Note: The existing environment variable ${name} was not overwritten. Uncomment to use its new value.`, + comment && `# ${comment}`, + `# ${name} = ${value}`, + '', + ] + .flat() + .join('\n') + envFile += '\n' + p + } else { + envFile += '\n' + newEnvironmentVariable + } + } else { + envFile = newEnvironmentVariable } + + return fs.writeFileSync(envPath, envFile) } /** diff --git a/packages/cli/src/commands/generate.js b/packages/cli/src/commands/generate.js index 8e6ee986ea6f..d42c8a5f6f4d 100644 --- a/packages/cli/src/commands/generate.js +++ b/packages/cli/src/commands/generate.js @@ -13,7 +13,13 @@ export const builder = (yargs) => recordTelemetryAttributes({ command: 'generate types', }) - execa.sync('yarn rw-gen', { shell: true, stdio: 'inherit' }) + try { + execa.sync('yarn rw-gen', { shell: true, stdio: 'inherit' }) + } catch (error) { + // rw-gen is responsible for logging its own errors but we need to + // make sure we exit with a non-zero exit code + process.exitCode = error.exitCode ?? 1 + } }) .commandDir('./generate', { recurse: true, diff --git a/packages/cli/src/commands/serveBothHandler.js b/packages/cli/src/commands/serveBothHandler.js index 28ace745bbcf..349c4563f900 100644 --- a/packages/cli/src/commands/serveBothHandler.js +++ b/packages/cli/src/commands/serveBothHandler.js @@ -19,10 +19,7 @@ export const bothExperimentalServerFileHandler = async () => { await execa( 'node', - [ - '--conditions react-server', - './node_modules/@redwoodjs/vite/dist/runRscFeServer.js', - ], + ['./node_modules/@redwoodjs/vite/dist/runRscFeServer.js'], { cwd: getPaths().base, stdio: 'inherit', @@ -64,9 +61,9 @@ export const bothRscServerHandler = async (argv) => { const fePromise = execa( 'node', [ + // TODO (RSC): Do we need these on the worker thread? '--experimental-loader @redwoodjs/vite/node-loader', '--experimental-loader @redwoodjs/vite/react-node-loader', - '--conditions react-server', './node_modules/@redwoodjs/vite/dist/runRscFeServer.js', ], { diff --git a/packages/cli/src/commands/setup/ui/libraries/tailwindcss.js b/packages/cli/src/commands/setup/ui/libraries/tailwindcss.js index d7b1ce953817..40ed1a6273d7 100644 --- a/packages/cli/src/commands/setup/ui/libraries/tailwindcss.js +++ b/packages/cli/src/commands/setup/ui/libraries/tailwindcss.js @@ -242,6 +242,44 @@ export const handler = async ({ force, install }) => { } }, }, + { + title: "Updating tailwind 'scaffold.css'...", + skip: () => { + // Skip this step if the 'scaffold.css' file does not exist + return !fs.existsSync(path.join(rwPaths.web.src, 'scaffold.css')) + }, + task: async (_ctx, task) => { + const overrideScaffoldCss = + force || + (await task.prompt({ + type: 'Confirm', + message: + "Do you want to override your 'scaffold.css' to use tailwind too?", + })) + + if (overrideScaffoldCss) { + const tailwindScaffoldTemplate = fs.readFileSync( + path.join( + __dirname, + '..', + '..', + '..', + 'generate', + 'scaffold', + 'templates', + 'assets', + 'scaffold.tailwind.css.template' + ) + ) + fs.writeFileSync( + path.join(rwPaths.web.src, 'scaffold.css'), + tailwindScaffoldTemplate + ) + } else { + task.skip('Skipping scaffold.css override') + } + }, + }, { title: 'Adding recommended VS Code extensions to project settings...', task: (_ctx, task) => { diff --git a/packages/eslint-plugin/src/unsupported-route-components.ts b/packages/eslint-plugin/src/unsupported-route-components.ts index 0f4b433a3153..3bcc8be2ab23 100644 --- a/packages/eslint-plugin/src/unsupported-route-components.ts +++ b/packages/eslint-plugin/src/unsupported-route-components.ts @@ -3,7 +3,7 @@ import { ESLintUtils } from '@typescript-eslint/utils' const createRule = ESLintUtils.RuleCreator.withoutDocs function isAllowedElement(name: string) { - const allowedElements = ['Router', 'Route', 'Set', 'Private'] + const allowedElements = ['Router', 'Route', 'Set', 'PrivateSet', 'Private'] return allowedElements.includes(name) } @@ -16,7 +16,7 @@ export const unsupportedRouteComponents = createRule({ }, messages: { unexpected: - 'Unexpected JSX element <{{name}}>. Only , , and are allowed in the Routes file.', + 'Unexpected JSX element <{{name}}>. Only , , , and are allowed in the Routes file.', }, schema: [], // No additional configuration needed }, diff --git a/packages/fastify/src/web.ts b/packages/fastify/src/web.ts index 46116ab4754a..8814ee604fff 100644 --- a/packages/fastify/src/web.ts +++ b/packages/fastify/src/web.ts @@ -6,6 +6,7 @@ import fg from 'fast-glob' import type { FastifyInstance, FastifyReply, + FastifyRequest, HookHandlerDoneFunction, } from 'fastify' @@ -47,10 +48,21 @@ export async function redwoodFastifyWeb( const indexPath = getFallbackIndexPath() // For SPA routing, fallback on unmatched routes and let client-side routing take over. - fastify.setNotFoundHandler({}, function (_, reply: FastifyReply) { - reply.header('Content-Type', 'text/html; charset=UTF-8') - reply.sendFile(indexPath) - }) + fastify.setNotFoundHandler( + {}, + function (req: FastifyRequest, reply: FastifyReply) { + const requestedExtension = path.extname(req.url) + // If it's requesting some sort of asset, e.g. .js or .jpg files + // Html files should fallback to the index.html + if (requestedExtension !== '' && requestedExtension !== '.html') { + reply.code(404) + return reply.send('Not Found') + } + + reply.header('Content-Type', 'text/html; charset=UTF-8') + return reply.sendFile(indexPath) + } + ) done() } diff --git a/packages/internal/src/generate/generate.ts b/packages/internal/src/generate/generate.ts index f24bca684de4..44bb33db50e5 100644 --- a/packages/internal/src/generate/generate.ts +++ b/packages/internal/src/generate/generate.ts @@ -51,6 +51,7 @@ export const run = async () => { console.log() return } + process.exitCode ||= 1 console.log('... done with errors.') console.log() diff --git a/packages/router/src/AuthenticatedRoute.tsx b/packages/router/src/AuthenticatedRoute.tsx index a3bdba1726d5..79091ab03260 100644 --- a/packages/router/src/AuthenticatedRoute.tsx +++ b/packages/router/src/AuthenticatedRoute.tsx @@ -8,20 +8,16 @@ import type { GeneratedRoutesMap } from './util' interface AuthenticatedRouteProps { children: React.ReactNode roles?: string | string[] - unauthenticated?: keyof GeneratedRoutesMap + unauthenticated: keyof GeneratedRoutesMap whileLoadingAuth?: () => React.ReactElement | null - private?: boolean } -export const AuthenticatedRoute: React.FC = ( - props -) => { - const { - private: isPrivate, - unauthenticated, - roles, - whileLoadingAuth, - children, - } = props + +export const AuthenticatedRoute: React.FC = ({ + unauthenticated, + roles, + whileLoadingAuth, + children, +}) => { const routerState = useRouterState() const { loading: authLoading, @@ -34,14 +30,7 @@ export const AuthenticatedRoute: React.FC = ( }, [isAuthenticated, roles, hasRole]) // Make sure `wrappers` is always an array with at least one wrapper component - if (isPrivate && unauthorized()) { - if (!unauthenticated) { - throw new Error( - 'Private Sets need to specify what route to redirect unauthorized ' + - 'users to by setting the `unauthenticated` prop' - ) - } - + if (unauthorized()) { if (authLoading) { return whileLoadingAuth?.() || null } else { diff --git a/packages/router/src/Set.tsx b/packages/router/src/Set.tsx index abebebc2d8e6..14fbb61a57b4 100644 --- a/packages/router/src/Set.tsx +++ b/packages/router/src/Set.tsx @@ -2,25 +2,35 @@ import type { ReactElement, ReactNode } from 'react' import React from 'react' export type WrapperType = ( - props: WTProps & { children: ReactNode } + props: Omit & { + children: ReactNode + } ) => ReactElement | null type SetProps

= P & { - // P is the interface for the props that are forwarded to the wrapper - // components. TypeScript will most likely infer this for you, but if you - // need to you can specify it yourself in your JSX like so: - // wrap={ThemeableLayout} theme="dark"> + /** + * P is the interface for the props that are forwarded to the wrapper + * components. TypeScript will most likely infer this for you, but if you + * need to you can specify it yourself in your JSX like so: + * wrap={ThemableLayout} theme="dark"> + */ wrap?: WrapperType

| WrapperType

[] /** - * `Routes` nested in a `` with `private` specified require + *`Routes` nested in a `` with `private` specified require * authentication. When a user is not authenticated and attempts to visit * the wrapped route they will be redirected to `unauthenticated` route. + * + * @deprecated Please use `` instead */ private?: boolean - /** The page name where a user will be redirected when not authenticated */ + /** + * The page name where a user will be redirected when not authenticated + * + * @deprecated Please use `` instead and specify this prop there + */ unauthenticated?: string /** - * Route is permitted when authenticated and use has any of the provided + * Route is permitted when authenticated and user has any of the provided * roles such as "admin" or ["admin", "editor"] */ roles?: string | string[] @@ -28,8 +38,8 @@ type SetProps

= P & { prerender?: boolean children: ReactNode /** Loading state for auth to distinguish with whileLoading */ - whileLoadingAuth?: () => React.ReactElement | null - whileLoadingPage?: () => React.ReactElement | null + whileLoadingAuth?: () => ReactElement | null + whileLoadingPage?: () => ReactElement | null } /** @@ -38,14 +48,13 @@ type SetProps

= P & { * JSX like so: * wrap={ThemeableLayout} theme="dark"> */ -export function Set(_props: SetProps) { +export function Set(props: SetProps) { // @MARK: Virtual Component, this is actually never rendered // See analyzeRoutes in utils.tsx, inside the isSetNode block - - return null + return <>{props.children} } -type PrivateProps

= Omit< +type PrivateSetProps

= Omit< SetProps

, 'private' | 'unauthenticated' | 'wrap' > & { @@ -54,20 +63,36 @@ type PrivateProps

= Omit< wrap?: WrapperType

| WrapperType

[] } -export function Private(_props: PrivateProps) { +/** @deprecated Please use `` instead */ +export function Private(props: PrivateSetProps) { // @MARK Virtual Component, this is actually never rendered // See analyzeRoutes in utils.tsx, inside the isSetNode block - return null + return <>{props.children} +} + +export function PrivateSet(props: PrivateSetProps) { + // @MARK Virtual Component, this is actually never rendered + // See analyzeRoutes in utils.tsx, inside the isSetNode block + return <>{props.children} } export const isSetNode = ( node: ReactNode ): node is ReactElement> => { return ( - React.isValidElement(node) && (node.type === Set || node.type === Private) + React.isValidElement(node) && + (node.type === Set || node.type === PrivateSet || node.type === Private) && + // Don't even bother including Sets without children. They're useless. + node.props.children ) } +export const isPrivateSetNode = ( + node: ReactNode +): node is ReactElement> => { + return React.isValidElement(node) && node.type === PrivateSet +} + // Only identifies nodes, not nodes export const isPrivateNode = ( node: ReactNode diff --git a/packages/router/src/__tests__/analyzeRoutes.test.tsx b/packages/router/src/__tests__/analyzeRoutes.test.tsx index fcac36f1603e..030b5bbe101b 100644 --- a/packages/router/src/__tests__/analyzeRoutes.test.tsx +++ b/packages/router/src/__tests__/analyzeRoutes.test.tsx @@ -1,14 +1,24 @@ import React, { isValidElement } from 'react' import { Route, Router } from '../router' -import { Private, Set } from '../Set' +import { Private, PrivateSet, Set } from '../Set' import { analyzeRoutes } from '../util' const FakePage = () =>

Fake Page

-const FakeLayout1 = ({ children }) =>
{children}
-const FakeLayout2 = ({ children }) =>
{children}
-const FakeLayout3 = ({ children }) =>
{children}
+interface LayoutProps { + children: React.ReactNode +} + +const FakeLayout1 = ({ children }: LayoutProps) => ( +
{children}
+) +const FakeLayout2 = ({ children }: LayoutProps) => ( +
{children}
+) +const FakeLayout3 = ({ children }: LayoutProps) => ( +
{children}
+) describe('AnalyzeRoutes: with homePage and Children', () => { const CheckRoutes = ( @@ -106,14 +116,26 @@ describe('AnalyzeRoutes: with homePage and Children', () => { }) test('Creates setWrapper map', () => { - const WrapperX = ({ children }) => ( + interface WrapperXProps { + children: React.ReactNode + id: string + passThruProp: string + } + + const WrapperX = ({ children }: WrapperXProps) => ( <>

WrapperA

{children} ) - const WrapperY = ({ children }) => ( + interface WrapperYProps { + children: React.ReactNode + id: string + theme: string + } + + const WrapperY = ({ children }: WrapperYProps) => ( <>

WrapperY

{children} @@ -142,12 +164,15 @@ describe('AnalyzeRoutes: with homePage and Children', () => { name: 'routeA', path: '/a', whileLoadingPage: undefined, - wrappers: [WrapperX], - // Props passed through from set - setProps: [ + sets: [ { - id: 'set-one', - passThruProp: 'bazinga', + id: '1', + wrappers: [WrapperX], + isPrivate: false, + props: { + id: 'set-one', + passThruProp: 'bazinga', + }, }, ], }) @@ -159,15 +184,24 @@ describe('AnalyzeRoutes: with homePage and Children', () => { name: 'routeB', path: '/b', whileLoadingPage: undefined, - wrappers: [WrapperX, WrapperY], // both wrappers - setProps: [ + sets: [ { - id: 'set-one', - passThruProp: 'bazinga', + id: '1', + wrappers: [WrapperX], + isPrivate: false, + props: { + id: 'set-one', + passThruProp: 'bazinga', + }, }, { - id: 'set-two', - theme: 'blue', + id: '1.1', + isPrivate: false, + wrappers: [WrapperY], + props: { + id: 'set-two', + theme: 'blue', + }, }, ], }) @@ -179,15 +213,146 @@ describe('AnalyzeRoutes: with homePage and Children', () => { name: 'routeC', path: '/c', whileLoadingPage: undefined, - wrappers: [WrapperX, WrapperY], // both wrappers - setProps: [ + sets: [ { - id: 'set-one', - passThruProp: 'bazinga', + id: '1', + wrappers: [WrapperX], + isPrivate: false, + props: { + id: 'set-one', + passThruProp: 'bazinga', + }, }, { - id: 'set-two', - theme: 'blue', + id: '1.1', + wrappers: [WrapperY], + isPrivate: false, + props: { + id: 'set-two', + theme: 'blue', + }, + }, + ], + }) + ) + }) + + test('Connects Set wrapper props with correct Set', () => { + interface WrapperXProps { + children: React.ReactNode + id: string + passThruProp: string + } + + const WrapperX = ({ children }: WrapperXProps) => ( + <> +

WrapperA

+ {children} + + ) + + interface WrapperYProps { + children: React.ReactNode + id: string + theme: string + } + + const WrapperY = ({ children }: WrapperYProps) => ( + <> +

WrapperY

+ {children} + + ) + + const Simple = ( + + + + + + + + + + ) + + const { pathRouteMap } = analyzeRoutes(Simple.props.children, { + currentPathName: '/', + }) + + expect(pathRouteMap['/a']).toEqual( + expect.objectContaining({ + redirect: null, + name: 'routeA', + path: '/a', + whileLoadingPage: undefined, + sets: [ + { + id: '1', + wrappers: [WrapperX], + isPrivate: false, + props: { + id: 'set-one', + passThruProp: 'bazinga', + }, + }, + ], + }) + ) + + expect(pathRouteMap['/b']).toEqual( + expect.objectContaining({ + redirect: null, + name: 'routeB', + path: '/b', + whileLoadingPage: undefined, + sets: [ + { + id: '1', + wrappers: [WrapperX], + isPrivate: false, + props: { + id: 'set-one', + passThruProp: 'bazinga', + }, + }, + { + id: '1.1', + wrappers: [WrapperY], + isPrivate: false, + props: { + id: 'set-two', + theme: 'blue', + }, + }, + ], + }) + ) + + expect(pathRouteMap['/c']).toEqual( + expect.objectContaining({ + redirect: null, + name: 'routeC', + path: '/c', + whileLoadingPage: undefined, + sets: [ + { + id: '1', + wrappers: [WrapperX], + isPrivate: false, + props: { + id: 'set-one', + passThruProp: 'bazinga', + }, + }, + { + id: '1.1', + wrappers: [WrapperY], + isPrivate: false, + props: { + id: 'set-two', + theme: 'blue', + }, }, ], }) @@ -196,7 +361,7 @@ describe('AnalyzeRoutes: with homePage and Children', () => { test('Creates setWrapper map with nested sets', () => { const KrismasTree = ( - + { />
-
+ ) const { pathRouteMap } = analyzeRoutes(KrismasTree.props.children, { @@ -286,12 +451,43 @@ describe('AnalyzeRoutes: with homePage and Children', () => { path: '/private', whileLoadingPage: undefined, page: FakePage, - wrappers: [], - setId: 1, - setProps: [ + sets: [ { - private: true, - unauthenticated: 'home', + id: '1', + wrappers: [], + isPrivate: true, + props: { unauthenticated: 'home' }, + }, + ], + }) + }) + + test('Handles PrivateSet', () => { + const Routes = ( + + + + + + + ) + + const { pathRouteMap } = analyzeRoutes(Routes.props.children, { + currentPathName: '/', + }) + + expect(pathRouteMap['/private']).toStrictEqual({ + redirect: null, + name: 'privateRoute', + path: '/private', + whileLoadingPage: undefined, + page: FakePage, + sets: [ + { + id: '1', + wrappers: [], + isPrivate: true, + props: { unauthenticated: 'home' }, }, ], }) @@ -334,7 +530,7 @@ describe('AnalyzeRoutes: with homePage and Children', () => { const RedirectedRoutes = ( - + { roles={['ADMIN', 'EMPLOYEE']} someProp="propFromNoRolesSet" > - + - + - + - +
- +
) const { pathRouteMap, namedRoutesMap } = analyzeRoutes( RedirectedRoutes.props.children, { - currentPathName: '/simple', + currentPathName: '/does-not-exist', } ) @@ -377,12 +573,13 @@ describe('AnalyzeRoutes: with homePage and Children', () => { expect(pathRouteMap).toMatchObject({ '/no-roles-assigned': { redirect: null, - setProps: expect.arrayContaining([ - expect.objectContaining({ - unauthenticated: 'home', - private: true, - }), - ]), + sets: [ + { + id: '1', + isPrivate: true, + props: { unauthenticated: 'home' }, + }, + ], }, }) @@ -392,19 +589,32 @@ describe('AnalyzeRoutes: with homePage and Children', () => { expect(pathRouteMap).toMatchObject({ '/employee': { redirect: null, - setProps: expect.arrayContaining([ - // Should have the first one, but also.. - expect.objectContaining({ - unauthenticated: 'home', - private: true, - }), - // ...the second private set's props - expect.objectContaining({ - private: true, - unauthenticated: 'noRolesAssigned', - roles: ['ADMIN', 'EMPLOYEE'], - }), - ]), + sets: [ + { + id: '1', + wrappers: [], + isPrivate: true, + props: { unauthenticated: 'home' }, + }, + { + id: '1.1', + wrappers: [], + isPrivate: true, + props: expect.objectContaining({ + unauthenticated: 'noRolesAssigned', + roles: ['ADMIN', 'EMPLOYEE'], + }), + }, + { + id: '1.1.1', + wrappers: [], + isPrivate: true, + props: { + unauthenticated: 'admin', + roles: 'EMPLOYEE', + }, + }, + ], }, }) @@ -412,27 +622,85 @@ describe('AnalyzeRoutes: with homePage and Children', () => { expect(pathRouteMap).toMatchObject({ '/admin': { redirect: null, - setProps: expect.arrayContaining([ + sets: [ // Should have the first one, but also.. - expect.objectContaining({ - unauthenticated: 'home', - private: true, - }), + { + id: '1', + wrappers: [], + isPrivate: true, + props: { unauthenticated: 'home' }, + }, // ...the second private set's props - expect.objectContaining({ - private: true, - unauthenticated: 'noRolesAssigned', - roles: ['ADMIN', 'EMPLOYEE'], - }), - + { + id: '1.1', + wrappers: [], + isPrivate: true, + props: { + unauthenticated: 'noRolesAssigned', + roles: ['ADMIN', 'EMPLOYEE'], + }, + }, // ...and the third private set's props - expect.objectContaining({ - unauthenticated: 'employee', - roles: 'ADMIN', - private: true, - }), - ]), + { + id: '1.1.2', + wrappers: [], + isPrivate: true, + props: { + unauthenticated: 'employee', + roles: 'ADMIN', + }, + }, + ], }, }) }) }) + +test('Give correct ids to root sets', () => { + const HomePage = () =>

Home Page

+ const Page = () =>

Page

+ const Layout = ({ children }: LayoutProps) => <>{children} + + const Routes = ( + + + + + + + + + + ) + + const { pathRouteMap } = analyzeRoutes(Routes.props.children, { + currentPathName: '/', + }) + + expect(pathRouteMap).toMatchObject({ + '/': { + redirect: null, + sets: [], + }, + '/one': { + redirect: null, + sets: [ + { + id: '1', + wrappers: [Layout], + isPrivate: false, + }, + ], + }, + '/two': { + redirect: null, + sets: [ + { + id: '2', + wrappers: [Layout], + isPrivate: false, + }, + ], + }, + }) +}) diff --git a/packages/router/src/__tests__/links.test.tsx b/packages/router/src/__tests__/links.test.tsx index 780745414f60..85dbbfeebb2a 100644 --- a/packages/router/src/__tests__/links.test.tsx +++ b/packages/router/src/__tests__/links.test.tsx @@ -2,7 +2,9 @@ import React from 'react' import { toHaveClass, toHaveStyle } from '@testing-library/jest-dom/matchers' import { render } from '@testing-library/react' + // TODO: Remove when jest configs are in place +// @ts-expect-error - Issue with TS and jest-dom expect.extend({ toHaveClass, toHaveStyle }) import { NavLink, useMatch, Link } from '../links' @@ -284,7 +286,10 @@ describe('', () => { }) describe('useMatch', () => { - const MyLink = ({ to, ...rest }) => { + const MyLink = ({ + to, + ...rest + }: React.ComponentPropsWithoutRef) => { const [pathname, queryString] = to.split('?') const matchInfo = useMatch(pathname, { searchParams: flattenSearchParams(queryString), diff --git a/packages/router/src/__tests__/nestedSets.test.tsx b/packages/router/src/__tests__/nestedSets.test.tsx new file mode 100644 index 000000000000..a251513aefa1 --- /dev/null +++ b/packages/router/src/__tests__/nestedSets.test.tsx @@ -0,0 +1,234 @@ +import * as React from 'react' +import type { ReactNode } from 'react' + +import '@testing-library/jest-dom/extend-expect' +import { act, render } from '@testing-library/react' + +import { navigate, Route, Router } from '../' +import { Private, Set } from '../Set' + +// Heads-up, in this test we're not mocking LazyComponent because all the tests +// explicitly define the pages in the router. +// +// If you add tests with dynamic imports, i.e. all the pages aren't explicitly +// supplied to the router, then you'll need to mock LazyComponent (see +// router.test.tsx) + +const HomePage = () =>

Home Page

+const Page = () =>

Page

+ +interface LayoutProps { + children: ReactNode +} + +beforeEach(() => { + window.history.pushState({}, '', '/') +}) + +let err: typeof console.error + +beforeAll(() => { + // Hide thrown exceptions. We're expecting them, and they clutter the output + err = console.error + console.error = jest.fn() +}) + +afterAll(() => { + console.error = err +}) + +test('Sets nested in Private should not error out if no authenticated prop provided', () => { + const Layout1 = ({ children }: LayoutProps) => ( +
+

Layout1

+ {children} +
+ ) + + const SetInsidePrivate = () => ( + + + 'Regular Auth'} name="auth" /> + 'Admin Auth'} name="adminAuth" /> + + + {/* The Set below is private implicitly (nested under private), but + should not need an unauthenticated prop */} + + + + + + + + + + + ) + + render() + + expect(() => { + act(() => navigate('/three')) + }).not.toThrowError() + + // But still throws if you try to navigate to a private route without an unauthenticated prop + expect(() => { + act(() => navigate('/four')) + }).toThrowError('You must specify an `unauthenticated` route') +}) + +test('Sets nested in `` should not error out if no authenticated prop provided', () => { + const Layout1 = ({ children }: { children: ReactNode }) => ( +
+

Layout1

+ {children} +
+ ) + + const SetInsideSetPrivate = () => ( + + + 'Regular Auth'} name="auth" /> + 'Admin Auth'} name="adminAuth" /> + + + {/* The Set below is private implicitly (nested under private), but + should not need an unauthenticated prop */} + + + + + + + + + + + ) + + render() + + expect(() => act(() => navigate('/three'))).not.toThrowError() + + // But still throws if you try to navigate to a private route without an unauthenticated prop + expect(() => act(() => navigate('/four'))).toThrowError( + 'You must specify an `unauthenticated` route' + ) +}) + +test('Nested sets should not cause a re-mount of parent wrap components', async () => { + const layoutOneMount = jest.fn() + const layoutOneUnmount = jest.fn() + const layoutTwoMount = jest.fn() + const layoutTwoUnmount = jest.fn() + + const Layout1 = ({ children }: LayoutProps) => { + React.useEffect(() => { + // Called on mount and re-mount of this layout + layoutOneMount() + + return () => { + layoutOneUnmount() + } + }, []) + + return ( + <> +

ONE

+ {children} + + ) + } + + const Layout2 = ({ children }: LayoutProps) => { + React.useEffect(() => { + // Called on mount and re-mount of this layout + layoutTwoMount() + + return () => { + layoutTwoUnmount() + } + }, []) + + return ( + <> +

TWO

+ {children} + + ) + } + + const NestedSetsWithWrap = () => ( + + + + + + + + + + + + ) + + render() + + // Layout 1 is mounted on initial render because we start out on / + // Layout 2 is not mounted at all + expect(layoutOneMount).toHaveBeenCalledTimes(1) + expect(layoutOneUnmount).toHaveBeenCalledTimes(0) + expect(layoutTwoMount).toHaveBeenCalledTimes(0) + expect(layoutTwoUnmount).toHaveBeenCalledTimes(0) + + act(() => navigate('/')) + + // Haven't navigated anywhere, so nothing should have changed + expect(layoutOneMount).toHaveBeenCalledTimes(1) + expect(layoutOneUnmount).toHaveBeenCalledTimes(0) + expect(layoutTwoMount).toHaveBeenCalledTimes(0) + expect(layoutTwoUnmount).toHaveBeenCalledTimes(0) + + act(() => navigate('/posts')) + + // Layout 2 should now have been mounted + // We're still within Layout 1, so it should not have been unmounted + expect(layoutOneMount).toHaveBeenCalledTimes(1) + expect(layoutOneUnmount).toHaveBeenCalledTimes(0) + expect(layoutTwoMount).toHaveBeenCalledTimes(1) + expect(layoutTwoUnmount).toHaveBeenCalledTimes(0) + + act(() => navigate('/')) + + // Navigating back up to / should unmount Layout 2 but crucially not remount + // Layout 1 + expect(layoutOneMount).toHaveBeenCalledTimes(1) + expect(layoutOneUnmount).toHaveBeenCalledTimes(0) + expect(layoutTwoMount).toHaveBeenCalledTimes(1) + expect(layoutTwoUnmount).toHaveBeenCalledTimes(1) + + act(() => navigate('/posts')) + + // Going back to /posts should remount Layout 2 but not Layout 1 + expect(layoutOneMount).toHaveBeenCalledTimes(1) + expect(layoutOneUnmount).toHaveBeenCalledTimes(0) + expect(layoutTwoMount).toHaveBeenCalledTimes(2) + expect(layoutTwoUnmount).toHaveBeenCalledTimes(1) + + act(() => navigate('/posts')) + + // Navigating within Layout 2 should not remount any of the layouts + expect(layoutOneMount).toHaveBeenCalledTimes(1) + expect(layoutOneUnmount).toHaveBeenCalledTimes(0) + expect(layoutTwoMount).toHaveBeenCalledTimes(2) + expect(layoutTwoUnmount).toHaveBeenCalledTimes(1) + + act(() => navigate('/')) + + // Back up to / again and we should see Layout 2 unmount + expect(layoutOneMount).toHaveBeenCalledTimes(1) + expect(layoutOneUnmount).toHaveBeenCalledTimes(0) + expect(layoutTwoMount).toHaveBeenCalledTimes(2) + expect(layoutTwoUnmount).toHaveBeenCalledTimes(2) +}) diff --git a/packages/router/src/__tests__/route-announcer.test.tsx b/packages/router/src/__tests__/route-announcer.test.tsx index e34c5c595c7c..606dd45a2bbf 100644 --- a/packages/router/src/__tests__/route-announcer.test.tsx +++ b/packages/router/src/__tests__/route-announcer.test.tsx @@ -51,6 +51,7 @@ const EmptyH1Page = () => ( beforeEach(() => { window.history.pushState({}, '', '/') + // @ts-expect-error - No type gen here for routes like there is in a real app Object.keys(routes).forEach((key) => delete routes[key]) }) @@ -94,6 +95,7 @@ test('gets the announcement in the correct order of priority', async () => { // navigate to h1 // since there's no RouteAnnouncement, it should announce the h1. + // @ts-expect-error - No type gen here for routes like there is in a real app act(() => navigate(routes.h1())) await waitFor(() => { screen.getByText(/H1 Page/i) @@ -102,6 +104,7 @@ test('gets the announcement in the correct order of priority', async () => { // navigate to noH1. // since there's no h1, it should announce the title. + // @ts-expect-error - No type gen here for routes like there is in a real app act(() => navigate(routes.noH1())) await waitFor(() => { screen.getByText(/NoH1 Page/i) @@ -113,6 +116,7 @@ test('gets the announcement in the correct order of priority', async () => { // navigate to noH1OrTitle. // since there's no h1 or title, // it should announce the location. + // @ts-expect-error - No type gen here for routes like there is in a real app act(() => navigate(routes.noH1OrTitle())) await waitFor(() => { screen.getByText(/NoH1OrTitle Page/i) diff --git a/packages/router/src/__tests__/route-focus.test.tsx b/packages/router/src/__tests__/route-focus.test.tsx index 04c517b23896..59cecad3e3a2 100644 --- a/packages/router/src/__tests__/route-focus.test.tsx +++ b/packages/router/src/__tests__/route-focus.test.tsx @@ -20,6 +20,7 @@ const NoRouteFocusPage = () =>

No Route Focus Page

const RouteFocusNoChildren = () => ( <> + {/* @ts-expect-error - Testing a JS scenario */}

Route Focus No Children Page

@@ -45,7 +46,8 @@ const RouteFocusNegativeTabIndexPage = () => ( ) beforeEach(() => { - window.history.pushState({}, null, '/') + window.history.pushState({}, '', '/') + // @ts-expect-error - No type gen here for routes like there is in a real app Object.keys(routes).forEach((key) => delete routes[key]) }) diff --git a/packages/router/src/__tests__/router.test.tsx b/packages/router/src/__tests__/router.test.tsx index a44c738f99cb..47c93faaf1ba 100644 --- a/packages/router/src/__tests__/router.test.tsx +++ b/packages/router/src/__tests__/router.test.tsx @@ -29,7 +29,7 @@ import { waitFor, } from '@testing-library/react' -import type { AuthContextInterface } from '@redwoodjs/auth' +import type { AuthContextInterface, UseAuth } from '@redwoodjs/auth' import { back, @@ -37,6 +37,7 @@ import { Link, navigate, Private, + PrivateSet, Redirect, Route, Router, @@ -142,6 +143,10 @@ const mockUseAuth = }) } +interface LayoutProps { + children: React.ReactNode +} + const HomePage = () =>

Home Page

const LoginPage = () =>

Login Page

const AboutPage = () =>

About Page

@@ -187,7 +192,7 @@ describe('slow imports', () => { ) } - const PageLoadingContextLayout = ({ children }) => { + const PageLoadingContextLayout = ({ children }: LayoutProps) => { const { loading } = usePageLoadingContext() return ( @@ -248,22 +253,24 @@ describe('slow imports', () => { name="login" whileLoadingPage={LoginPagePlaceholder} /> - + - - + + - + + {/* Keeping this one around for now, so we don't accidentally break + Private until we're ready to remove it */} { test( 'path params should never be empty', async () => { - const PathParamPage = ({ value }) => { + const PathParamPage = ({ value }: { value: string }) => { expect(value).not.toBeFalsy() return

{value}

} @@ -551,9 +558,9 @@ describe('inits routes and navigates as expected', () => { - + - + @@ -762,9 +769,9 @@ test('unauthenticated user is redirected away from private page', async () => { - + - + ) const screen = render() @@ -789,9 +796,9 @@ test('unauthenticated user is redirected including search params', async () => { - + - + ) const screen = render() @@ -817,9 +824,9 @@ test('authenticated user can access private page', async () => { const TestRouter = () => ( - + - + ) const screen = render() @@ -840,12 +847,12 @@ test('can display a loading screen whilst waiting for auth', async () => { const TestRouter = () => ( - <>Authenticating...} > - + ) const screen = render() @@ -883,9 +890,9 @@ test('can display a loading screen with a hook', async () => { })} > - + - + ) const screen = render() @@ -914,14 +921,14 @@ test('inits routes two private routes with a space in between and loads as expec - + {' '} - +
param {value}
} + page={({ value }: { value: string }) =>
param {value}
} name="params" /> @@ -933,7 +940,7 @@ test('inits routes two private routes with a space in between and loads as expec }) test('supports ', async () => { - const GlobalLayout = ({ children }) => ( + const GlobalLayout = ({ children }: LayoutProps) => (

Global Layout

{children} @@ -946,14 +953,14 @@ test('supports ', async () => { - + - + ) @@ -964,7 +971,7 @@ test('supports ', async () => { }) test('can use named routes for navigating', async () => { - const MainLayout = ({ children }) => { + const MainLayout = ({ children }: LayoutProps) => { return (

Main Layout

@@ -996,7 +1003,7 @@ test('can use named routes for navigating', async () => { }) test('renders only active path', async () => { - const AboutLayout = ({ children }) => { + const AboutLayout = ({ children }: LayoutProps) => { return (

About Layout

@@ -1006,7 +1013,7 @@ test('renders only active path', async () => { ) } - const LoginLayout = ({ children }) => { + const LoginLayout = ({ children }: LayoutProps) => { return (

Login Layout

@@ -1097,7 +1104,7 @@ test('renders first matching route only, even if multiple routes have the same n expect(screen.queryByText('About Two Page')).not.toBeInTheDocument() }) -test('renders first matching route only, also with Private', async () => { +test('renders first matching route only, also with PrivateSet', async () => { const ParamPage = ({ param }: { param: string }) =>
param {param}
const TestRouter = () => ( @@ -1105,9 +1112,9 @@ test('renders first matching route only, also with Private', async () => { - + - + ) @@ -1121,15 +1128,15 @@ test('renders first matching route only, also with Private', async () => { expect(screen.queryByText(/param/)).not.toBeInTheDocument() }) -test('renders first matching route only, also with param path outside Private', async () => { +test('renders first matching route only, also with param path outside PrivateSet', async () => { const ParamPage = ({ param }: { param: string }) =>
param {param}
const TestRouter = () => ( - + - + ) @@ -1166,10 +1173,10 @@ test('params should never be an empty object in Set', async () => { return
Param Page
} - const SetWithUseParams = ({ children }) => { + const SetWithUseParams = ({ children }: LayoutProps) => { const params = useParams() expect(params).not.toEqual({}) - return children + return <>{children} } const TestRouter = () => ( @@ -1191,12 +1198,12 @@ test('params should never be an empty object in Set with waitFor (I)', async () return <>documentId: {documentId} } - const SetWithUseParams = ({ children }) => { + const SetWithUseParams = ({ children }: LayoutProps) => { const params = useParams() // 1st run: { documentId: '1' } // 2nd run: { documentId: '2' } expect(params).not.toEqual({}) - return children + return <>{children} } const TestRouter = () => ( @@ -1221,12 +1228,12 @@ test('params should never be an empty object in Set without waitFor (II)', async return <>documentId: {documentId} } - const SetWithUseParams = ({ children }) => { + const SetWithUseParams = ({ children }: LayoutProps) => { const params = useParams() // 1st run: { documentId: '1' } // 2nd run: { documentId: '2' } expect(params).not.toEqual({}) - return children + return <>{children} } const TestRouter = () => ( @@ -1251,17 +1258,17 @@ test('Set is not rendered for unauthenticated user.', async () => { return null } - const SetWithUseParams = ({ children }) => { + const SetWithUseParams = ({ children }: LayoutProps) => { // This should never be called. We should be redirected to login instead. expect(false).toBe(true) - return children + return <>{children} } const TestRouter = () => ( - + - +
auth thyself
} name="login" />
@@ -1284,14 +1291,16 @@ test('Set is not rendered for unauthenticated user on direct navigation', async return null } - const SetWithUseParams = ({ children }) => { + const SetWithUseParams = ({ children }: LayoutProps) => { // This should never be called. We should be redirected to login instead. expect(false).toBe(true) - return children + return <>{children} } const TestRouter = () => ( + {/* Keeping this around so we don't accidentally break the `private` prop + on Set until we're ready to remove it */} @@ -1305,8 +1314,14 @@ test('Set is not rendered for unauthenticated user on direct navigation', async await waitFor(() => screen.getByText(/auth thyself/)) }) +// TODO: Remove this entire test once we remove the `` component test('Private is an alias for Set private', async () => { - const PrivateLayout = ({ children, theme }) => ( + interface PrivateLayoutProps { + children: React.ReactNode + theme: string + } + + const PrivateLayout = ({ children, theme }: PrivateLayoutProps) => (

Private Layout ({theme})

{children} @@ -1316,7 +1331,11 @@ test('Private is an alias for Set private', async () => { const TestRouter = () => ( - + + wrap={PrivateLayout} + unauthenticated="home" + theme="dark" + > @@ -1335,9 +1354,9 @@ test('redirect to last page', async () => { - + - + ) @@ -1403,7 +1422,7 @@ test('jump to new route, then go back', async () => { }) test('redirect replacing route', async () => { - const ListWithDefaultParamsPage = (props) => { + const ListWithDefaultParamsPage = (props: { _limit: string }) => { if (props['_limit']) { return

List Page

} @@ -1548,7 +1567,7 @@ test('should handle ref and key as search params', async () => { }) describe('Unauthorized redirect error messages', () => { - let err + let err: typeof console.error beforeAll(() => { err = console.error @@ -1559,13 +1578,13 @@ describe('Unauthorized redirect error messages', () => { console.error = err }) - test('Private set with unauthenticated prop with nonexisting page', async () => { + test('PrivateSet with unauthenticated prop with nonexisting page', async () => { const TestRouter = ({ authenticated }: { authenticated?: boolean }) => ( - + - + ) @@ -1575,14 +1594,14 @@ describe('Unauthorized redirect error messages', () => { ) }) - test('Private set redirecting to page that needs parameters', async () => { + test('PrivateSet redirecting to page that needs parameters', async () => { const TestRouter = ({ authenticated }: { authenticated?: boolean }) => ( - + - + ) @@ -1600,51 +1619,48 @@ describe('Multiple nested private sets', () => { const PrivateEmployeePage = () =>

Private Employee Page

const PrivateAdminPage = () =>

Private Admin Page

- const LevelLayout = ({ children, level }) => ( + interface LevelLayoutProps { + children: React.ReactNode + level: string + } + + const LevelLayout = ({ children, level }: LevelLayoutProps) => (
Level: {level} {children}
) - const TestRouter = ({ useAuthMock }) => ( + const TestRouter = ({ useAuthMock }: { useAuthMock: UseAuth }) => ( - + + unauthenticated="home" + level="1" + wrap={LevelLayout} + > - - + - + - + - - - + + + ) @@ -1699,7 +1715,6 @@ describe('Multiple nested private sets', () => { act(() => navigate('/admin')) await waitFor(() => { expect(screen.queryByText(`Private Admin Page`)).toBeInTheDocument() - expect(screen.queryByText(`Level: 3`)).toBeInTheDocument() }) }) @@ -1719,16 +1734,22 @@ describe('Multiple nested private sets', () => { await waitFor(() => { expect(screen.queryByText(`Private Admin Page`)).toBeInTheDocument() - expect(screen.queryByText(`Level: 3`)).toBeInTheDocument() }) }) }) -describe('Multiple nested private sets', () => { +describe('Multiple nested sets', () => { const HomePage = () =>

Home Page

const Page = () =>

Page

- const DebugLayout = (props) => { + interface DebugLayoutProps { + children: React.ReactNode + theme: string + otherProp?: string + level: string + } + + const DebugLayout = (props: DebugLayoutProps) => { return (

Theme: {props.theme}

@@ -1742,7 +1763,7 @@ describe('Multiple nested private sets', () => { const TestRouter = () => ( - + level="1" theme="blue" wrap={DebugLayout}> @@ -1755,25 +1776,27 @@ describe('Multiple nested private sets', () => { ) test('level 1, matches expected props', async () => { - const screen = render() - act(() => navigate('/level1')) + const screen = render() + await waitFor(() => { - expect(screen.queryByText(`Theme: blue`)).toBeInTheDocument() - expect(screen.queryByText(`Page Level: 1`)).toBeInTheDocument() + expect(screen.queryByText('Theme: blue')).toBeInTheDocument() + expect(screen.queryByText('Other Prop:')).toBeInTheDocument() + expect(screen.queryByText('Page Level: 1')).toBeInTheDocument() }) }) - test('level 2, should override level 1', async () => { - const screen = render() - + test('level 2, should not affect level 1 set props', async () => { act(() => navigate('/level2')) + const screen = render() + await waitFor(() => { - expect(screen.queryByText(`Theme: red`)).toBeInTheDocument() - expect(screen.queryByText(`Other Prop: bazinga`)).toBeInTheDocument() - expect(screen.queryByText(`Page Level: 2`)).toBeInTheDocument() + expect(screen.queryByText('Page')).toBeInTheDocument() + expect(screen.queryByText('Theme: blue')).toBeInTheDocument() + expect(screen.queryByText('Other Prop:')).toBeInTheDocument() + expect(screen.queryByText('Page Level: 1')).toBeInTheDocument() }) }) @@ -1783,9 +1806,9 @@ describe('Multiple nested private sets', () => { act(() => navigate('/level3')) await waitFor(() => { - expect(screen.queryByText(`Theme: green`)).toBeInTheDocument() - expect(screen.queryByText(`Other Prop: bazinga`)).toBeInTheDocument() - expect(screen.queryByText(`Page Level: 3`)).toBeInTheDocument() + expect(screen.queryByText('Theme: blue')).toBeInTheDocument() + expect(screen.queryByText('Other Prop:')).toBeInTheDocument() + expect(screen.queryByText('Page Level: 1')).toBeInTheDocument() }) }) }) diff --git a/packages/router/src/__tests__/set.test.tsx b/packages/router/src/__tests__/set.test.tsx index 791ed34a95c0..5e5fe6a24680 100644 --- a/packages/router/src/__tests__/set.test.tsx +++ b/packages/router/src/__tests__/set.test.tsx @@ -1,36 +1,46 @@ -import React, { type ReactNode } from 'react' +import * as React from 'react' +import type { ReactNode } from 'react' -import { render, waitFor } from '@testing-library/react' +import { act, render, waitFor } from '@testing-library/react' import '@testing-library/jest-dom/extend-expect' +import { navigate } from '../history' import { Route, Router } from '../router' import { Set } from '../Set' // SETUP +interface LayoutProps { + children: ReactNode +} + const ChildA = () =>

ChildA

const ChildB = () =>

ChildB

const ChildC = () =>

ChildC

-const GlobalLayout: React.FC<{ children?: ReactNode }> = ({ children }) => ( +const GlobalLayout = ({ children }: LayoutProps) => (

Global Layout

{children}
This is a footer
) -const CustomWrapper: React.FC<{ children?: ReactNode }> = ({ children }) => ( +const CustomWrapper = ({ children }: LayoutProps) => (

Custom Wrapper

{children}

Custom Wrapper End

) -const BLayout = ({ children }) => ( +const BLayout = ({ children }: LayoutProps) => (

Layout for B

{children}
) +beforeEach(() => { + window.history.pushState({}, '', '/') +}) + test('wraps components in other components', async () => { const TestSet = () => ( @@ -89,10 +99,10 @@ test('passes props to wrappers', async () => { interface Props { propOne: string propTwo: string - children?: ReactNode + children: ReactNode } - const PropWrapper: React.FC = ({ children, propOne, propTwo }) => ( + const PropWrapper = ({ children, propOne, propTwo }: Props) => (

Prop Wrapper

1:{propOne}

@@ -100,9 +110,18 @@ test('passes props to wrappers', async () => { {children}
) + + const PropWrapperTwo = ({ children }: Props) => ( +
+

Prop Wrapper Two

+ {children} +
This is a footer
+
+ ) + const TestSet = () => ( - + @@ -128,7 +147,7 @@ test('passes props to wrappers', async () => {

- Global Layout + Prop Wrapper Two

ChildA @@ -148,3 +167,127 @@ test('passes props to wrappers', async () => {

`) }) + +describe('Navigating Sets', () => { + const HomePage = () =>

Home Page

+ const Page = () =>

Page

+ + test('Sets should not cause a re-mount of wrap components when navigating within the set', async () => { + const layoutOneMount = jest.fn() + const layoutOneUnmount = jest.fn() + + const Layout1 = ({ children }: LayoutProps) => { + React.useEffect(() => { + // Called on mount and re-mount of this layout + layoutOneMount() + + return () => { + layoutOneUnmount() + } + }, []) + + return ( + <> +

ONE

+ {children} + + ) + } + + const Routes = () => ( + + + + + + + + + + ) + + render() + + act(() => navigate('/')) + act(() => navigate('/posts')) + act(() => navigate('/posts/new')) + act(() => navigate('/posts')) + act(() => navigate('/posts/1')) + act(() => navigate('/posts/new')) + act(() => navigate('/posts')) + + // Navigating into, and then within Layout1 should not cause a re-mount + expect(layoutOneMount).toHaveBeenCalledTimes(1) + expect(layoutOneUnmount).toHaveBeenCalledTimes(0) + }) + + test('Sets should make wrap components remount when navigating between separate sets with the same wrap component', async () => { + const layoutOneMount = jest.fn() + const layoutOneUnmount = jest.fn() + + const Layout1 = ({ children }: LayoutProps) => { + React.useEffect(() => { + // Called on mount and re-mount of this layout + layoutOneMount() + + return () => { + layoutOneUnmount() + } + }, []) + + return ( + <> +

ONE

+ {children} + + ) + } + + const Routes = () => ( + + + + + + + + + + ) + + render() + + act(() => navigate('/')) + + expect(layoutOneMount).toHaveBeenCalledTimes(0) + expect(layoutOneUnmount).toHaveBeenCalledTimes(0) + + act(() => navigate('/posts')) + + expect(layoutOneMount).toHaveBeenCalledTimes(1) + expect(layoutOneUnmount).toHaveBeenCalledTimes(0) + + act(() => navigate('/')) + + expect(layoutOneMount).toHaveBeenCalledTimes(1) + expect(layoutOneUnmount).toHaveBeenCalledTimes(1) + + act(() => navigate('/posts')) + + expect(layoutOneMount).toHaveBeenCalledTimes(2) + expect(layoutOneUnmount).toHaveBeenCalledTimes(1) + + // This is the real test. Navigating between /posts and /comments should + // remount the wrap component because even though it's the same component, + // it's in different sets. + act(() => navigate('/comments')) + + expect(layoutOneMount).toHaveBeenCalledTimes(3) + expect(layoutOneUnmount).toHaveBeenCalledTimes(2) + + act(() => navigate('/')) + + expect(layoutOneMount).toHaveBeenCalledTimes(3) + expect(layoutOneUnmount).toHaveBeenCalledTimes(3) + }) +}) diff --git a/packages/router/src/__tests__/setContextReuse.test.tsx b/packages/router/src/__tests__/setContextReuse.test.tsx index b572562538ba..920f466d263e 100644 --- a/packages/router/src/__tests__/setContextReuse.test.tsx +++ b/packages/router/src/__tests__/setContextReuse.test.tsx @@ -2,9 +2,8 @@ import React from 'react' import { act, render, waitFor } from '@testing-library/react' -import { Route, Router, navigate, routes } from '../' +import { Route, Router, navigate } from '../' import { Set } from '../Set' -import { analyzeRoutes } from '../util' import '@testing-library/jest-dom/extend-expect' @@ -19,7 +18,7 @@ interface ContextState { const SetContext = React.createContext(undefined) -const SetContextProvider = ({ children }) => { +const SetContextProvider = ({ children }: { children: React.ReactNode }) => { const [contextValue, setContextValue] = React.useState('initialSetValue') return ( @@ -80,24 +79,20 @@ test("Doesn't destroy when navigating inside, but does when navigating bet await waitFor(() => screen.getByText('Home Page')) - act(() => navigate(routes.ctx1())) + act(() => navigate('/ctx-1-page')) await waitFor(() => screen.getByText('1-updatedSetValue')) - act(() => navigate(routes.ctx2())) + act(() => navigate('/ctx-2-page')) await waitFor(() => screen.getByText('2-updatedSetValue')) - act(() => navigate(routes.ctx3())) + act(() => navigate('/ctx-3-page')) await waitFor(() => screen.getByText('3-initialSetValue')) - act(() => navigate(routes.ctx4())) + act(() => navigate('/ctx-4-page')) + await waitFor(() => screen.getByText('4-initialSetValue')) + act(() => navigate('/ctx-2-page')) + await waitFor(() => screen.getByText('2-initialSetValue')) + act(() => navigate('/ctx-1-page')) + await waitFor(() => screen.getByText('1-updatedSetValue')) + act(() => navigate('/ctx-2-page')) + await waitFor(() => screen.getByText('2-updatedSetValue')) + act(() => navigate('/ctx-4-page')) await waitFor(() => screen.getByText('4-initialSetValue')) -}) - -test('Pages are correctly given a setId if they are nested in', () => { - const { pathRouteMap } = analyzeRoutes(TestRouter().props.children, { - currentPathName: '/', - }) - - expect(pathRouteMap['/'].setId).toBe(0) - expect(pathRouteMap['/ctx-1-page'].setId).toBe(1) - expect(pathRouteMap['/ctx-2-page'].setId).toBe(1) - expect(pathRouteMap['/ctx-3-page'].setId).toBe(2) - expect(pathRouteMap['/ctx-4-page'].setId).toBe(3) }) diff --git a/packages/router/src/router.tsx b/packages/router/src/router.tsx index 4e6c71c7183b..bfd17acf1f41 100644 --- a/packages/router/src/router.tsx +++ b/packages/router/src/router.tsx @@ -44,10 +44,9 @@ export interface RouteProps { } /** - * * Route is now a "virtual" component * it is actually never rendered. All the page loading logic happens in active-route-loader - * and all the validation happens within utlity functions called from the Router + * and all the validation happens within utility functions called from the Router */ function Route(props: RouteProps): JSX.Element function Route(props: RedirectRouteProps): JSX.Element @@ -147,16 +146,8 @@ const LocationAwareRouter: React.FC = ({ return null } - const { - path, - page, - name, - redirect, - whileLoadingPage, - wrappers = [], - setProps, - setId, - } = pathRouteMap[activeRoutePath] + const { path, page, name, redirect, whileLoadingPage, sets } = + pathRouteMap[activeRoutePath] if (!path) { throw new Error(`Route "${name}" needs to specify a path`) @@ -180,8 +171,7 @@ const LocationAwareRouter: React.FC = ({ {redirect && } {!redirect && page && ( = ({ whileLoadingPage={whileLoadingPage as any} /> } - setProps={setProps} /> )} @@ -200,77 +189,76 @@ const LocationAwareRouter: React.FC = ({ } interface WrappedPageProps { - wrappers: Wrappers routeLoaderElement: ReactNode - setProps: Record[] + sets: Array<{ + id: string + wrappers: Wrappers + isPrivate: boolean + props: { + private?: boolean + [key: string]: unknown + } + }> } /** * This is effectively a Set (without auth-related code) * - * This means that the and components become "virtual" + * This means that the and components become "virtual" * i.e. they are never actually Rendered, but their props are extracted by the * analyze routes function. * * This is so that we can have all the information up front in the routes-manifest * for SSR, but also so that we only do one loop of all the Routes. */ -const WrappedPage = memo( - ({ wrappers, routeLoaderElement, setProps }: WrappedPageProps) => { - // @NOTE: don't mutate the wrappers array, it causes full page re-renders - // Instead just create a new array with the AuthenticatedRoute wrapper +const WrappedPage = memo(({ routeLoaderElement, sets }: WrappedPageProps) => { + // @NOTE: don't mutate the wrappers array, it causes full page re-renders + // Instead just create a new array with the AuthenticatedRoute wrapper - // we need to pass the setProps from each set to each wrapper - let wrappersWithAuthMaybe = wrappers - const reveresedSetProps = [...setProps].reverse() - - reveresedSetProps - // @MARK note the reverse() here, because we spread wrappersWithAuthMaybe - .forEach((propsFromSet) => { - if (propsFromSet.private) { - if (!propsFromSet.unauthenticated) { - throw new Error( - 'You must specify an `unauthenticated` route when marking a Route as private' - ) - } - - // @MARK: this component intentionally removes all props except children - // because the .reduce below will apply props inside out - const AuthComponent: React.FC<{ children: ReactNode }> = ({ - children, - }) => { - return ( - - {children} - - ) - } + if (!sets || sets.length === 0) { + return routeLoaderElement + } - wrappersWithAuthMaybe = [AuthComponent, ...wrappersWithAuthMaybe] - } - }) + return sets.reduceRight((acc, set) => { + // For each set in `sets`, if you have `` then + // this will return + // + // If you have `` instead it will return + // + // + // - if (wrappersWithAuthMaybe.length > 0) { - // If wrappers exist e.g. [a,b,c] -> and returns a single ReactNode - // Wrap AuthenticatedRoute this way, because if we mutate the wrappers array itself - // it causes full rerenders of the page - return wrappersWithAuthMaybe.reduceRight((acc, wrapper) => { - // Merge props from set, the lowest set props will override the higher ones - const mergedSetProps = setProps.reduce((acc, props) => { - return { ...acc, ...props } - }, {}) + // Bundle up all the wrappers into a single element with each wrapper as a + // child of the previous (that's why we do reduceRight) + let wrapped = set.wrappers.reduceRight((acc, Wrapper, index) => { + return React.createElement( + Wrapper, + { ...set.props, key: set.id + '-' + index }, + acc + ) + }, acc) - return React.createElement( - wrapper as any, - mergedSetProps, - acc ? acc : routeLoaderElement + // If set is private, wrap it in AuthenticatedRoute + if (set.isPrivate) { + const unauthenticated = set.props.unauthenticated + if (!unauthenticated || typeof unauthenticated !== 'string') { + throw new Error( + 'You must specify an `unauthenticated` route when using PrivateSet' ) - }, undefined as ReactNode) + } + + // We do this last, to make sure that none of the wrapper elements are + // rendered if the user isn't authenticated + wrapped = ( + + {wrapped} + + ) } - return routeLoaderElement - } -) + return wrapped + }, routeLoaderElement) +}) export { Router, diff --git a/packages/router/src/util.ts b/packages/router/src/util.ts index 6d330262d3d6..1b42eb05ca51 100644 --- a/packages/router/src/util.ts +++ b/packages/router/src/util.ts @@ -8,7 +8,7 @@ import { isValidRoute, } from './route-validators' import type { PageType } from './router' -import { isPrivateNode, isSetNode } from './Set' +import { isPrivateNode, isPrivateSetNode, isSetNode } from './Set' /** Create a React Context with the given name. */ export function createNamedContext(name: string, defaultValue?: T) { @@ -455,6 +455,16 @@ export type GeneratedRoutesMap = { ) => string } +interface Set { + id: string + wrappers: Wrappers + isPrivate: boolean + props: { + private?: boolean + [key: string]: unknown + } +} + type RoutePath = string export type Wrappers = Array<(props: any) => ReactNode> interface AnalyzedRoute { @@ -463,9 +473,7 @@ interface AnalyzedRoute { whileLoadingPage?: WhileLoadingPage page: PageType | null redirect: string | null - wrappers: Wrappers - setProps: Record[] - setId: number + sets: Array } export function analyzeRoutes( @@ -481,36 +489,35 @@ export function analyzeRoutes( interface RecurseParams { nodes: ReturnType whileLoadingPageFromSet?: WhileLoadingPage - wrappersFromSet?: Wrappers - // we don't know, or care about, what props users are passing down - propsFromSet?: Record[] - setId?: number + sets?: Array } - // Track the number of sets found. - // Because Sets are virtually rendered we can use this setId as a key to + // Assign ids to all sets found. + // Because Sets are virtually rendered we can use this id as a key to // properly manage re-rendering when using the same wrapper Component for // different Sets // // Example: // - // + // // id: '1' // // - // + // // id: '1.1' + // + // // - // + // // id: '2' // // // - let setId = 0 const recurseThroughRouter = ({ nodes, whileLoadingPageFromSet, - wrappersFromSet = [], - propsFromSet: previousSetProps = [], + sets: previousSets = [], }: RecurseParams) => { + let nextSetId = 0 + nodes.forEach((node) => { if (isValidRoute(node)) { // Rename for readability @@ -551,9 +558,7 @@ export function analyzeRoutes( name: name || null, path, page: null, // Redirects don't need pages. We set this to null for consistency - wrappers: wrappersFromSet, - setProps: previousSetProps, - setId, + sets: previousSets, } if (name) { @@ -583,10 +588,8 @@ export function analyzeRoutes( path, whileLoadingPage: route.props.whileLoadingPage || whileLoadingPageFromSet, - page: page, - wrappers: wrappersFromSet, - setProps: previousSetProps, - setId, + page, + sets: previousSets, } // e.g. namedRoutesMap.homePage = () => '/home' @@ -594,9 +597,8 @@ export function analyzeRoutes( } } - // @NOTE: A is also a Set + // @NOTE: A is also a Set if (isSetNode(node)) { - setId = setId + 1 // increase the Set id for each Set found const { children, whileLoadingPage: whileLoadingPageFromCurrentSet, @@ -611,34 +613,30 @@ export function analyzeRoutes( : [wrapFromCurrentSet] } - // You cannot make a nested set public if the parent is private - // i.e. the private prop cannot be overridden by a child Set - const privateProps = - isPrivateNode(node) || previousSetProps.some((props) => props.private) - ? { private: true } - : {} - - if (children) { - recurseThroughRouter({ - nodes: Children.toArray(children), - // When there's a whileLoadingPage prop on a Set, we pass it down to all its children - // If the parent node was also a Set with whileLoadingPage, we pass it down. The child's whileLoadingPage - // will always take precedence over the parent's - whileLoadingPageFromSet: - whileLoadingPageFromCurrentSet || whileLoadingPageFromSet, - setId, - wrappersFromSet: [...wrappersFromSet, ...wrapperComponentsArray], - propsFromSet: [ - ...previousSetProps, - { - // Current one takes precedence - ...otherPropsFromCurrentSet, - // See comment at definition, intentionally at the end - ...privateProps, - }, - ], - }) - } + nextSetId = nextSetId + 1 + + recurseThroughRouter({ + nodes: Children.toArray(children), + // When there's a whileLoadingPage prop on a Set, we pass it down to all its children + // If the parent node was also a Set with whileLoadingPage, we pass it down. The child's whileLoadingPage + // will always take precedence over the parent's + whileLoadingPageFromSet: + whileLoadingPageFromCurrentSet || whileLoadingPageFromSet, + sets: [ + ...previousSets, + { + id: createSetId(nextSetId, previousSets), + wrappers: wrapperComponentsArray, + isPrivate: + isPrivateSetNode(node) || + // The following two conditions can be removed when we remove + // the deprecated private prop + isPrivateNode(node) || + !!otherPropsFromCurrentSet.private, + props: otherPropsFromCurrentSet, + }, + ], + }) } }) } @@ -653,3 +651,15 @@ export function analyzeRoutes( activeRoutePath, } } + +function createSetId(nextSetId: number, previousSets: Array) { + const firstLevel = previousSets.length === 0 + + if (firstLevel) { + // For the first level we don't want to add any dots ('.') to the id like + // we do for all other levels + return nextSetId.toString() + } + + return previousSets.at(-1)?.id + '.' + nextSetId +} diff --git a/packages/router/tsconfig.json b/packages/router/tsconfig.json index a3b71d69ff3a..db9449de1641 100644 --- a/packages/router/tsconfig.json +++ b/packages/router/tsconfig.json @@ -10,6 +10,11 @@ } }, "include": ["src", "./ambient.d.ts"], + "exclude": [ + "dist", + "node_modules", + "**/__mocks__", + ], "references": [ { "path": "../auth" }, ] diff --git a/packages/studio/package.json b/packages/studio/package.json index 71a791ab44b8..e055f7cb8bf5 100644 --- a/packages/studio/package.json +++ b/packages/studio/package.json @@ -101,7 +101,7 @@ "tailwindcss": "3.3.2", "typescript": "5.2.2", "use-url-search-params": "2.5.1", - "vite": "4.4.11" + "vite": "4.5.0" }, "gitHead": "3905ed045508b861b495f8d5630d76c7a157d8f1" } diff --git a/packages/vite/package.json b/packages/vite/package.json index 232798cb6b4a..59a30eeeb46c 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -80,7 +80,7 @@ "isbot": "3.6.8", "react": "0.0.0-experimental-e5205658f-20230913", "react-server-dom-webpack": "0.0.0-experimental-e5205658f-20230913", - "vite": "4.4.11", + "vite": "4.5.0", "yargs-parser": "21.1.1" }, "devDependencies": { diff --git a/packages/vite/src/buildFeServer.ts b/packages/vite/src/buildFeServer.ts index d3de9a8653d2..3755346e1414 100644 --- a/packages/vite/src/buildFeServer.ts +++ b/packages/vite/src/buildFeServer.ts @@ -4,6 +4,7 @@ import path from 'path' import type { PluginBuild } from 'esbuild' import { build as esbuildBuild } from 'esbuild' import type { Manifest as ViteBuildManifest } from 'vite' +import { build as viteBuild } from 'vite' import { getRouteHookBabelPlugins, @@ -65,18 +66,18 @@ export const buildFeServer = async ({ verbose, webDir }: BuildOptions = {}) => { // Step 1A: Generate the client bundle await buildWeb({ verbose }) - // TODO (STREAMING) When Streaming is released Vite will be the only bundler, - // so we can switch to a regular import - // @NOTE: Using dynamic import, because vite is still opt-in - const { build: viteBuild } = await import('vite') - // Step 1B: Generate the server output await viteBuild({ configFile: viteConfigPath, build: { - // Because we configure the root to be web/src, we need to go up one level outDir: rwPaths.web.distServer, - ssr: rwPaths.web.entryServer, + ssr: true, // use boolean, and supply the inputs in rollup options (see Documentation) + rollupOptions: { + input: { + 'entry.server': rwPaths.web.entryServer, + Document: rwPaths.web.document, // We need the document for React's fallback + }, + }, }, envFile: false, logLevel: verbose ? 'info' : 'warn', diff --git a/packages/vite/src/rsc/rscRequestHandler.ts b/packages/vite/src/rsc/rscRequestHandler.ts new file mode 100644 index 000000000000..33e5b03df7b2 --- /dev/null +++ b/packages/vite/src/rsc/rscRequestHandler.ts @@ -0,0 +1,121 @@ +import busboy from 'busboy' +import type { Request, Response } from 'express' +import RSDWServer from 'react-server-dom-webpack/server.node.unbundled' + +import { hasStatusCode } from '../lib/StatusError' + +import { renderRsc } from './rscWorkerCommunication' + +const { decodeReply, decodeReplyFromBusboy } = RSDWServer + +export function createRscRequestHandler() { + // This is mounted at /RSC, so will have /RSC stripped from req.url + return async (req: Request, res: Response) => { + const basePath = '/RSC/' + console.log('basePath', basePath) + console.log('req.originalUrl', req.originalUrl, 'req.url', req.url) + console.log('req.headers.host', req.headers.host) + + const url = new URL(req.originalUrl || '', 'http://' + req.headers.host) + let rscId: string | undefined + let props = {} + let rsfId: string | undefined + let args: unknown[] = [] + + console.log('url.pathname', url.pathname) + + if (url.pathname.startsWith(basePath)) { + const index = url.pathname.lastIndexOf('/') + const params = new URLSearchParams(url.pathname.slice(index + 1)) + rscId = url.pathname.slice(basePath.length, index) + rsfId = params.get('action_id') || undefined + + console.log('rscId', rscId) + console.log('rsfId', rsfId) + + if (rscId && rscId !== '_') { + res.setHeader('Content-Type', 'text/x-component') + props = JSON.parse(params.get('props') || '{}') + } else { + rscId = undefined + } + + if (rsfId) { + if (req.headers['content-type']?.startsWith('multipart/form-data')) { + const bb = busboy({ headers: req.headers }) + const reply = decodeReplyFromBusboy(bb) + + req.pipe(bb) + args = await reply + + // TODO (RSC): Loop over args (to not only look at args[0]) + // TODO (RSC): Verify that this works with node16 (MDN says FormData is + // only supported in node18 and up) + if (args[0] instanceof FormData) { + const serializedFormData: Record = {} + + for (const [key, value] of args[0]) { + // Several form fields can share the same name. This should be + // represented as an array of the values of all those fields + if (serializedFormData[key] !== undefined) { + if (!Array.isArray(serializedFormData[key])) { + serializedFormData[key] = [serializedFormData[key]] + } + + serializedFormData[key].push(value) + } else { + serializedFormData[key] = value + } + } + + args[0] = { + __formData__: true, + state: serializedFormData, + } + } + } else { + let body = '' + + for await (const chunk of req) { + body += chunk + } + + if (body) { + args = await decodeReply(body) + } + } + } + } + + if (rscId || rsfId) { + const handleError = (err: unknown) => { + if (hasStatusCode(err)) { + res.statusCode = err.statusCode + } else { + console.info('Cannot render RSC', err) + res.statusCode = 500 + } + + // Getting a warning on GitHub about this + // https://github.com/redwoodjs/redwood/security/code-scanning/211 + // Handle according to TODO below + res.end(String(err)) + // TODO (RSC): When we have `yarn rw dev` support we should do this: + // if (options.command === 'dev') { + // res.end(String(err)) + // } else { + // res.end() + // } + } + + try { + const pipeable = await renderRsc({ rscId, props, rsfId, args }) + // TODO (RSC): See if we can/need to do more error handling here + // pipeable.on(handleError) + pipeable.pipe(res) + } catch (e) { + handleError(e) + } + } + } +} diff --git a/packages/vite/src/waku-lib/rsc-handler-worker.ts b/packages/vite/src/rsc/rscWorker.ts similarity index 71% rename from packages/vite/src/waku-lib/rsc-handler-worker.ts rename to packages/vite/src/rsc/rscWorker.ts index aefa68ab11bd..56bda94a8906 100644 --- a/packages/vite/src/waku-lib/rsc-handler-worker.ts +++ b/packages/vite/src/rsc/rscWorker.ts @@ -1,7 +1,10 @@ -// TODO (RSC) Take ownership of this file and move it out ouf the waku-lib folder -// import fs from 'node:fs' +// This is a dedicated worker for RSCs. +// It's needed because the main process can't be loaded with +// `--condition react-server`. If we did try to do that the main process +// couldn't do SSR because it would be missing client-side React functions +// like `useState` and `createContext`. import path from 'node:path' -import type { Writable } from 'node:stream' +import { Writable } from 'node:stream' import { parentPort } from 'node:worker_threads' import { createElement } from 'react' @@ -13,89 +16,98 @@ import { getPaths } from '@redwoodjs/project-config' import type { defineEntries } from '../entries' import { StatusError } from '../lib/StatusError' -// import type { unstable_GetCustomModules } from '../waku-server' +import { configFileConfig, resolveConfig } from '../waku-lib/config' +import { transformRsfId } from '../waku-lib/rsc-utils' +import { + rscTransformPlugin, + rscReloadPlugin, +} from '../waku-lib/vite-plugin-rsc' -import { configFileConfig, resolveConfig } from './config' +// import type { unstable_GetCustomModules } from '../waku-server' +import type { + RenderInput, + MessageRes, + MessageReq, +} from './rscWorkerCommunication' // import type { RenderInput, MessageReq, MessageRes } from './rsc-handler' -import type { RenderInput, MessageRes } from './rsc-handler' // import { transformRsfId, generatePrefetchCode } from './rsc-utils' -import { transformRsfId } from './rsc-utils' -import { rscTransformPlugin, rscReloadPlugin } from './vite-plugin-rsc' const { renderToPipeableStream } = RSDWServer type Entries = { default: ReturnType } type PipeableStream = { pipe(destination: T): T } -// const handleSetClientEntries = async ( -// mesg: MessageReq & { type: 'setClientEntries' } -// ) => { -// const { id, value } = mesg -// try { -// await setClientEntries(value) +const handleSetClientEntries = async ({ + id, + value, +}: MessageReq & { type: 'setClientEntries' }) => { + try { + await setClientEntries(value) -// if (!parentPort) { -// throw new Error('parentPort is undefined') -// } + if (!parentPort) { + throw new Error('parentPort is undefined') + } -// const message: MessageRes = { id, type: 'end' } -// parentPort.postMessage(message) -// } catch (err) { -// if (!parentPort) { -// throw new Error('parentPort is undefined') -// } + const message: MessageRes = { id, type: 'end' } + parentPort.postMessage(message) + } catch (err) { + if (!parentPort) { + throw new Error('parentPort is undefined') + } -// const message: MessageRes = { id, type: 'err', err } -// parentPort.postMessage(message) -// } -// } + const message: MessageRes = { id, type: 'err', err } + parentPort.postMessage(message) + } +} -// const handleRender = async (message: MessageReq & { type: 'render' }) => { -// const { id, input } = message +const handleRender = async ({ id, input }: MessageReq & { type: 'render' }) => { + console.log('handleRender', id, input) + + try { + const pipeable = await renderRsc(input) + + const writable = new Writable({ + write(chunk, encoding, callback) { + if (encoding !== ('buffer' as any)) { + throw new Error('Unknown encoding') + } + + if (!parentPort) { + throw new Error('parentPort is undefined') + } + + const buffer: Buffer = chunk + const message: MessageRes = { + id, + type: 'buf', + buf: buffer.buffer, + offset: buffer.byteOffset, + len: buffer.length, + } + parentPort.postMessage(message, [message.buf]) + callback() + }, + final(callback) { + if (!parentPort) { + throw new Error('parentPort is undefined') + } + + const message: MessageRes = { id, type: 'end' } + parentPort.postMessage(message) + callback() + }, + }) -// try { -// const pipeable = await renderRSC(input) -// const writable = new Writable({ -// write(chunk, encoding, callback) { -// if (encoding !== ('buffer' as any)) { -// throw new Error('Unknown encoding') -// } - -// if (!parentPort) { -// throw new Error('parentPort is undefined') -// } - -// const buffer: Buffer = chunk -// const msg: MessageRes = { -// id, -// type: 'buf', -// buf: buffer.buffer, -// offset: buffer.byteOffset, -// len: buffer.length, -// } -// parentPort.postMessage(msg, [msg.buf]) -// callback() -// }, -// final(callback) { -// if (!parentPort) { -// throw new Error('parentPort is undefined') -// } - -// const mesg: MessageRes = { id, type: 'end' } -// parentPort.postMessage(mesg) -// callback() -// }, -// }) -// pipeable.pipe(writable) -// } catch (err) { -// if (!parentPort) { -// throw new Error('parentPort is undefined') -// } + pipeable.pipe(writable) + } catch (err) { + if (!parentPort) { + throw new Error('parentPort is undefined') + } -// const mesg: MessageRes = { id, type: 'err', err } -// parentPort.postMessage(mesg) -// } -// } + const message: MessageRes = { id, type: 'err', err } + parentPort.postMessage(message) + } +} // const handleGetCustomModules = async ( // mesg: MessageReq & { type: 'getCustomModules' } @@ -149,48 +161,52 @@ const vitePromise = createServer({ throw new Error('parentPort is undefined') } - const mesg: MessageRes = { type } - parentPort.postMessage(mesg) + const message: MessageRes = { type } + parentPort.postMessage(message) }), ], - resolve: { - conditions: ['react-server'], + ssr: { + resolve: { + externalConditions: ['react-server'], + }, }, appType: 'custom', }) -// const shutdown = async () => { -// const vite = await vitePromise -// await vite.close() -// if (!parentPort) { -// throw new Error('parentPort is undefined') -// } +const shutdown = async () => { + const vite = await vitePromise + await vite.close() + if (!parentPort) { + throw new Error('parentPort is undefined') + } -// parentPort.close() -// } + parentPort.close() +} const loadServerFile = async (fname: string) => { const vite = await vitePromise return vite.ssrLoadModule(fname) } -// if (!parentPort) { -// throw new Error('parentPort is undefined') -// } +if (!parentPort) { + throw new Error('parentPort is undefined') +} -// parentPort.on('message', (mesg: MessageReq) => { -// if (mesg.type === 'shutdown') { -// shutdown() -// } else if (mesg.type === 'setClientEntries') { -// handleSetClientEntries(mesg) -// } else if (mesg.type === 'render') { -// handleRender(mesg) -// } else if (mesg.type === 'getCustomModules') { -// handleGetCustomModules(mesg) -// } else if (mesg.type === 'build') { -// handleBuild(mesg) -// } -// }) +parentPort.on('message', (message: MessageReq) => { + console.log('message', message) + + if (message.type === 'shutdown') { + shutdown() + } else if (message.type === 'setClientEntries') { + handleSetClientEntries(message) + } else if (message.type === 'render') { + handleRender(message) + // } else if (message.type === 'getCustomModules') { + // handleGetCustomModules(message) + // } else if (message.type === 'build') { + // handleBuild(message) + } +}) const configPromise = resolveConfig('serve') @@ -250,7 +266,7 @@ const resolveClientEntry = ( return clientEntry } -export async function setClientEntries( +async function setClientEntries( value: 'load' | Record ): Promise { if (value !== 'load') { @@ -283,7 +299,16 @@ export async function setClientEntries( ) } -export async function renderRSC(input: RenderInput): Promise { +interface SerializedFormData { + __formData__: boolean + state: Record +} + +function isSerializedFormData(data?: unknown): data is SerializedFormData { + return !!data && (data as SerializedFormData)?.__formData__ +} + +async function renderRsc(input: RenderInput): Promise { const config = await configPromise const bundlerConfig = new Proxy( {}, @@ -300,13 +325,31 @@ export async function renderRSC(input: RenderInput): Promise { } ) - console.log('renderRSC input', input) + console.log('renderRsc input', input) if (input.rsfId && input.args) { const [fileId, name] = input.rsfId.split('#') const fname = path.join(config.root, fileId) - const mod = await loadServerFile(fname) - const data = await (mod[name] || mod)(...input.args) + console.log('Server Action, fileId', fileId, 'name', name, 'fname', fname) + const module = await loadServerFile(fname) + + if (isSerializedFormData(input.args[0])) { + const formData = new FormData() + + Object.entries(input.args[0].state).forEach(([key, value]) => { + if (Array.isArray(value)) { + value.forEach((v) => { + formData.append(key, v) + }) + } else { + formData.append(key, value) + } + }) + + input.args[0] = formData + } + + const data = await (module[name] || module)(...input.args) if (!input.rscId) { return renderToPipeableStream(data, bundlerConfig) } diff --git a/packages/vite/src/waku-lib/rsc-handler.ts b/packages/vite/src/rsc/rscWorkerCommunication.ts similarity index 53% rename from packages/vite/src/waku-lib/rsc-handler.ts rename to packages/vite/src/rsc/rscWorkerCommunication.ts index d40c0c42e490..6570c0125c51 100644 --- a/packages/vite/src/waku-lib/rsc-handler.ts +++ b/packages/vite/src/rsc/rscWorkerCommunication.ts @@ -1,9 +1,9 @@ -// TODO (RSC) Take ownership of this file and move it out ouf the waku-lib folder +import path from 'node:path' import { PassThrough } from 'node:stream' import type { Readable } from 'node:stream' import { Worker } from 'node:worker_threads' -const worker = new Worker(new URL('rsc-handler-worker.js', import.meta.url), { +const worker = new Worker(path.join(__dirname, 'rscWorker.js'), { execArgv: ['--conditions', 'react-server'], }) @@ -48,29 +48,32 @@ export type MessageRes = | { id: number; type: 'err'; err: unknown } | { id: number; type: 'customModules'; modules: CustomModules } -const messageCallbacks = new Map void>() +const messageCallbacks = new Map void>() -worker.on('message', (mesg: MessageRes) => { - if ('id' in mesg) { - messageCallbacks.get(mesg.id)?.(mesg) +worker.on('message', (message: MessageRes) => { + if ('id' in message) { + messageCallbacks.get(message.id)?.(message) } }) export function registerReloadCallback(fn: (type: 'full-reload') => void) { - const listener = (mesg: MessageRes) => { - if (mesg.type === 'full-reload') { - fn(mesg.type) + const listener = (message: MessageRes) => { + if (message.type === 'full-reload') { + fn(message.type) } } + worker.on('message', listener) + return () => worker.off('message', listener) } export function shutdown() { return new Promise((resolve) => { worker.on('close', resolve) - const mesg: MessageReq = { type: 'shutdown' } - worker.postMessage(mesg) + + const message: MessageReq = { type: 'shutdown' } + worker.postMessage(message) }) } @@ -79,73 +82,83 @@ let nextId = 1 export function setClientEntries( value: 'load' | Record ): Promise { - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { const id = nextId++ - messageCallbacks.set(id, (mesg) => { - if (mesg.type === 'end') { + + messageCallbacks.set(id, (message) => { + if (message.type === 'end') { resolve() messageCallbacks.delete(id) - } else if (mesg.type === 'err') { - reject(mesg.err) + } else if (message.type === 'err') { + reject(message.err) messageCallbacks.delete(id) } }) - const mesg: MessageReq = { id, type: 'setClientEntries', value } - worker.postMessage(mesg) + + const message: MessageReq = { id, type: 'setClientEntries', value } + worker.postMessage(message) }) } -export function renderRSC(input: RenderInput): Readable { +export function renderRsc(input: RenderInput): Readable { + // TODO (RSC): What's the biggest number JS handles here? What happens when + // it overflows? Will it just start over at 0? If so, we should be fine. If + // not, we need to figure out a more robust way to handle this. const id = nextId++ const passthrough = new PassThrough() - messageCallbacks.set(id, (mesg) => { - if (mesg.type === 'buf') { - passthrough.write(Buffer.from(mesg.buf, mesg.offset, mesg.len)) - } else if (mesg.type === 'end') { + + messageCallbacks.set(id, (message) => { + if (message.type === 'buf') { + passthrough.write(Buffer.from(message.buf, message.offset, message.len)) + } else if (message.type === 'end') { passthrough.end() messageCallbacks.delete(id) - } else if (mesg.type === 'err') { + } else if (message.type === 'err') { passthrough.destroy( - mesg.err instanceof Error ? mesg.err : new Error(String(mesg.err)) + message.err instanceof Error + ? message.err + : new Error(String(message.err)) ) messageCallbacks.delete(id) } }) - const mesg: MessageReq = { id, type: 'render', input } - worker.postMessage(mesg) + + const message: MessageReq = { id, type: 'render', input } + worker.postMessage(message) + return passthrough } export function getCustomModulesRSC(): Promise { return new Promise((resolve, reject) => { const id = nextId++ - messageCallbacks.set(id, (mesg) => { - if (mesg.type === 'customModules') { - resolve(mesg.modules) + messageCallbacks.set(id, (message) => { + if (message.type === 'customModules') { + resolve(message.modules) messageCallbacks.delete(id) - } else if (mesg.type === 'err') { - reject(mesg.err) + } else if (message.type === 'err') { + reject(message.err) messageCallbacks.delete(id) } }) - const mesg: MessageReq = { id, type: 'getCustomModules' } - worker.postMessage(mesg) + const message: MessageReq = { id, type: 'getCustomModules' } + worker.postMessage(message) }) } export function buildRSC(): Promise { return new Promise((resolve, reject) => { const id = nextId++ - messageCallbacks.set(id, (mesg) => { - if (mesg.type === 'end') { + messageCallbacks.set(id, (message) => { + if (message.type === 'end') { resolve() messageCallbacks.delete(id) - } else if (mesg.type === 'err') { - reject(mesg.err) + } else if (message.type === 'err') { + reject(message.err) messageCallbacks.delete(id) } }) - const mesg: MessageReq = { id, type: 'build' } - worker.postMessage(mesg) + const message: MessageReq = { id, type: 'build' } + worker.postMessage(message) }) } diff --git a/packages/vite/src/rscBuild.ts b/packages/vite/src/rscBuild.ts index 75725ef1c333..070b929a9ab0 100644 --- a/packages/vite/src/rscBuild.ts +++ b/packages/vite/src/rscBuild.ts @@ -43,9 +43,9 @@ export async function rscBuild(viteConfigPath: string) { // TODO (RSC): Figure out what the `external` list should be. Right // now it's just copied from waku external: ['react', 'minimatch'], - }, - resolve: { - conditions: ['react-server'], + resolve: { + externalConditions: ['react-server'], + }, }, build: { manifest: 'rsc-build-manifest.json', diff --git a/packages/vite/src/runRscFeServer.ts b/packages/vite/src/runRscFeServer.ts index cd6106d05aea..6ef02ae1f01e 100644 --- a/packages/vite/src/runRscFeServer.ts +++ b/packages/vite/src/runRscFeServer.ts @@ -6,22 +6,17 @@ import fs from 'fs/promises' import path from 'path' -import busboy from 'busboy' // @ts-expect-error We will remove dotenv-defaults from this package anyway import { config as loadDotEnv } from 'dotenv-defaults' import express from 'express' import { createProxyMiddleware } from 'http-proxy-middleware' -import isbot from 'isbot' -import RSDWServer from 'react-server-dom-webpack/server.node.unbundled' import type { Manifest as ViteBuildManifest } from 'vite' import { getConfig, getPaths } from '@redwoodjs/project-config' -import { hasStatusCode } from './lib/StatusError' +import { createRscRequestHandler } from './rsc/rscRequestHandler' +import { setClientEntries } from './rsc/rscWorkerCommunication' import { registerFwGlobals } from './streaming/registerGlobals' -import { renderRSC, setClientEntries } from './waku-lib/rsc-handler-worker' - -const { decodeReply, decodeReplyFromBusboy } = RSDWServer /** * TODO (STREAMING) @@ -39,10 +34,7 @@ loadDotEnv({ defaults: path.join(getPaths().base, '.env.defaults'), multiline: true, }) -//------------------------------------------------ - -const checkUaForSeoCrawler = isbot.spawn() -checkUaForSeoCrawler.exclude(['chrome-lighthouse']) +// ------------------------------------------------ export async function runFeServer() { const app = express() @@ -72,10 +64,7 @@ export async function runFeServer() { // const routeManifest: RWRouteManifest = JSON.parse(routeManifestStr) // TODO See above about using `import { with: { type: 'json' } }` instead - const manifestPath = path.join( - getPaths().web.dist, - 'client-build-manifest.json' - ) + const manifestPath = path.join(rwPaths.web.dist, 'client-build-manifest.json') const buildManifestStr = await fs.readFile(manifestPath, 'utf-8') const buildManifest: ViteBuildManifest = JSON.parse(buildManifestStr) @@ -91,11 +80,11 @@ export async function runFeServer() { throw new Error('Could not find index.html in build manifest') } - // ๐Ÿ‘‰ 1. Use static handler for assets + // 1. Use static handler for assets // For CF workers, we'd need an equivalent of this app.use('/assets', express.static(rwPaths.web.dist + '/assets')) - // ๐Ÿ‘‰ 2. Proxy the api server + // 2. Proxy the api server // TODO (STREAMING) we need to be able to specify whether proxying is required or not // e.g. deploying to Netlify, we don't need to proxy but configure it in Netlify // Also be careful of differences between v2 and v3 of the server @@ -114,91 +103,8 @@ export async function runFeServer() { }) ) - app.use((req, _res, next) => { - console.log('req.url', req.url) - next() - }) - // Mounting middleware at /RSC will strip /RSC from req.url - app.use('/RSC', async (req, res) => { - const basePath = '/RSC/' - console.log('basePath', basePath) - console.log('req.originalUrl', req.originalUrl, 'req.url', req.url) - console.log('req.headers.host', req.headers.host) - - const url = new URL(req.originalUrl || '', 'http://' + req.headers.host) - let rscId: string | undefined - let props = {} - let rsfId: string | undefined - let args: unknown[] = [] - - console.log('url.pathname', url.pathname) - - if (url.pathname.startsWith(basePath)) { - const index = url.pathname.lastIndexOf('/') - const params = new URLSearchParams(url.pathname.slice(index + 1)) - rscId = url.pathname.slice(basePath.length, index) - rsfId = params.get('action_id') || undefined - - console.log('rscId', rscId) - console.log('rsfId', rsfId) - - if (rscId && rscId !== '_') { - res.setHeader('Content-Type', 'text/x-component') - props = JSON.parse(params.get('props') || '{}') - } else { - rscId = undefined - } - - if (rsfId) { - if (req.headers['content-type']?.startsWith('multipart/form-data')) { - const bb = busboy({ headers: req.headers }) - const reply = decodeReplyFromBusboy(bb) - - req.pipe(bb) - args = await reply - } else { - let body = '' - - for await (const chunk of req) { - body += chunk - } - - if (body) { - args = await decodeReply(body) - } - } - } - } - - if (rscId || rsfId) { - const handleError = (err: unknown) => { - if (hasStatusCode(err)) { - res.statusCode = err.statusCode - } else { - console.info('Cannot render RSC', err) - res.statusCode = 500 - } - - res.end(String(err)) - // TODO (RSC): When we have `yarn rw dev` support we should do this: - // if (options.command === 'dev') { - // res.end(String(err)) - // } else { - // res.end() - // } - } - - try { - const pipeable = await renderRSC({ rscId, props, rsfId, args }) - // TODO (RSC): See if we can/need to do more error handling here - // pipeable.on(handleError) - pipeable.pipe(res) - } catch (e) { - handleError(e) - } - } - }) + app.use('/RSC', createRscRequestHandler()) app.use(express.static(rwPaths.web.dist)) diff --git a/packages/vite/src/streaming/createReactStreamingHandler.ts b/packages/vite/src/streaming/createReactStreamingHandler.ts index a958e0487bc4..63de73f4a261 100644 --- a/packages/vite/src/streaming/createReactStreamingHandler.ts +++ b/packages/vite/src/streaming/createReactStreamingHandler.ts @@ -115,6 +115,13 @@ export const createReactStreamingHandler = async ( }, { waitForAllReady: isSeoCrawler, + onError: (err) => { + if (!isProd && viteDevServer) { + viteDevServer.ssrFixStacktrace(err) + } + + console.error(err) + }, } ) diff --git a/packages/vite/src/streaming/streamHelpers.ts b/packages/vite/src/streaming/streamHelpers.ts index efcd01f3de9e..e92e9038c624 100644 --- a/packages/vite/src/streaming/streamHelpers.ts +++ b/packages/vite/src/streaming/streamHelpers.ts @@ -2,6 +2,11 @@ import path from 'node:path' import React from 'react' +import type { + RenderToReadableStreamOptions, + ReactDOMServerReadableStream, +} from 'react-dom/server' + import type { TagDescriptor } from '@redwoodjs/web' // @TODO (ESM), use exports field. Cannot import from web because of index exports import { @@ -10,6 +15,7 @@ import { } from '@redwoodjs/web/dist/components/ServerInject' import { createBufferedTransformStream } from './transforms/bufferedTransform' +import { createTimeoutTransform } from './transforms/cancelTimeoutTransform' import { createServerInjectionTransform } from './transforms/serverInjectionTransform' interface RenderToStreamArgs { @@ -24,6 +30,7 @@ interface RenderToStreamArgs { interface StreamOptions { waitForAllReady?: boolean + onError?: (err: Error) => void } export async function reactRenderToStreamResponse( @@ -55,13 +62,22 @@ export async function reactRenderToStreamResponse( const { injectionState, injectToPage } = createInjector() // This makes it safe for us to inject at any point in the stream - const bufferedTransformStream = createBufferedTransformStream() + const bufferTransform = createBufferedTransformStream() // This is a transformer stream, that will inject all things called with useServerInsertedHtml - const serverInjectionTransformer = createServerInjectionTransform({ + const serverInjectionTransform = createServerInjectionTransform({ injectionState, }) + // Timeout after 10 seconds + // @TODO make this configurable + const controller = new AbortController() + const timeoutHandle = setTimeout(() => { + controller.abort() + }, 10000) + + const timeoutTransform = createTimeoutTransform(timeoutHandle) + // @ts-expect-error Something in React's packages mean types dont come through // Possible that we need to upgrade the @types/* packages const { renderToReadableStream } = await import('react-dom/server.edge') @@ -96,29 +112,27 @@ export async function reactRenderToStreamResponse( // This gets set if there are errors inside Suspense boundaries let didErrorOutsideShell = false - // Timeout after 10 seconds - // @TODO make this configurable - const controller = new AbortController() - setTimeout(() => { - controller.abort() - }, 10000) + // Assign here so we get types, the dynamic import messes types + const renderToStreamOptions: RenderToReadableStreamOptions = { + ...bootstrapOptions, + signal: controller.signal, + onError: (err: any) => { + didErrorOutsideShell = true + console.error('๐Ÿ”ป Caught error outside shell') + streamOptions.onError?.(err) + }, + } - const reactStream = await renderToReadableStream( - renderRoot(currentPathName), - { - ...bootstrapOptions, - signal: controller.signal, - onError: (err: any) => { - didErrorOutsideShell = true - console.error('๐Ÿ”ป Caught error outside shell') - console.error(err) - }, - } - ) + const reactStream: ReactDOMServerReadableStream = + await renderToReadableStream( + renderRoot(currentPathName), + renderToStreamOptions + ) const output = reactStream - .pipeThrough(bufferedTransformStream) - .pipeThrough(serverInjectionTransformer) + .pipeThrough(bufferTransform) + .pipeThrough(serverInjectionTransform) + .pipeThrough(timeoutTransform) if (waitForAllReady) { await reactStream.allReady @@ -130,7 +144,7 @@ export async function reactRenderToStreamResponse( }) } catch (e) { console.error('๐Ÿ”ป Failed to render shell') - console.error(e) + streamOptions.onError?.(e as Error) // @TODO Asking for clarification from React team. Their documentation on this is incomplete I think. // Having the Document (and bootstrap scripts) here allows client to recover from errors in the shell diff --git a/packages/vite/src/streaming/transforms/cancelTimeoutTransform.ts b/packages/vite/src/streaming/transforms/cancelTimeoutTransform.ts new file mode 100644 index 000000000000..f157ab7ca793 --- /dev/null +++ b/packages/vite/src/streaming/transforms/cancelTimeoutTransform.ts @@ -0,0 +1,7 @@ +export function createTimeoutTransform(timeoutHandle: NodeJS.Timeout) { + return new TransformStream({ + flush() { + clearTimeout(timeoutHandle) + }, + }) +} diff --git a/packages/vite/src/waku-lib/build-server.ts b/packages/vite/src/waku-lib/build-server.ts index 2ff6dfe70201..2003621f6c0e 100644 --- a/packages/vite/src/waku-lib/build-server.ts +++ b/packages/vite/src/waku-lib/build-server.ts @@ -8,6 +8,7 @@ import { getPaths } from '@redwoodjs/project-config' import { onWarn } from '../lib/onWarn' +// This is part of step 3. It's invoked from ./buildRscFeServer export async function serverBuild( entriesFile: string, clientEntryFiles: Record, @@ -43,7 +44,7 @@ export async function serverBuild( ) const splitPath = relativePath.split('/') - // TODO (RSC): Verify this is correct. Need to find a scoped packages + // TODO (RSC): Verify this is correct. Need to find a scoped package // that uses 'use client' // Handle scoped packages if (relativePath.startsWith('@')) { @@ -53,11 +54,11 @@ export async function serverBuild( // Packages without scope return splitPath[0] }), + resolve: { + externalConditions: ['react-server'], + }, }, plugins: [react()], - resolve: { - conditions: ['react-server'], - }, build: { ssr: true, ssrEmitAssets: true, diff --git a/packages/vite/src/waku-lib/builder.ts b/packages/vite/src/waku-lib/builder.ts index 95acfac199d7..1ab154b604ae 100644 --- a/packages/vite/src/waku-lib/builder.ts +++ b/packages/vite/src/waku-lib/builder.ts @@ -7,14 +7,14 @@ import react from '@vitejs/plugin-react' import { build as viteBuild } from 'vite' import { onWarn } from '../lib/onWarn' - -import { configFileConfig, resolveConfig } from './config' import { shutdown, setClientEntries, getCustomModulesRSC, buildRSC, -} from './rsc-handler' +} from '../rsc/rscWorkerCommunication' + +import { configFileConfig, resolveConfig } from './config' import { rscIndexPlugin, rscAnalyzePlugin } from './vite-plugin-rsc' export async function build() { diff --git a/tasks/check/action.yml b/tasks/check/action.yml index c511c1fe3e9d..913458202a20 100644 --- a/tasks/check/action.yml +++ b/tasks/check/action.yml @@ -1,6 +1,5 @@ name: 'Check' description: "Check constraints, dependencies, and package.json's" runs: - # `node18` isn't supported yet - using: node16 + using: node20 main: 'check.mjs' diff --git a/tasks/clean.mjs b/tasks/clean.mjs new file mode 100644 index 000000000000..9264c3e0651e --- /dev/null +++ b/tasks/clean.mjs @@ -0,0 +1,13 @@ +#!/usr/bin/env node +/* eslint-env node */ + +import { rimraf } from 'rimraf' +import { $ } from 'zx' + +await $`yarn clean:prisma` + +await rimraf('packages/**/dist', { + glob: { + ignore: 'packages/**/{fixtures,__fixtures__}/**/dist', + }, +}) diff --git a/tasks/server-tests/.gitignore b/tasks/server-tests/.gitignore new file mode 100644 index 000000000000..42290cbb0ccd --- /dev/null +++ b/tasks/server-tests/.gitignore @@ -0,0 +1,2 @@ +!fixtures/**/dist +fixtures/**/.redwood diff --git a/tasks/server-tests/fixtures/redwood-app/.env.defaults b/tasks/server-tests/fixtures/redwood-app/.env.defaults new file mode 100644 index 000000000000..f644ff583db7 --- /dev/null +++ b/tasks/server-tests/fixtures/redwood-app/.env.defaults @@ -0,0 +1 @@ +LOAD_ENV_DEFAULTS_TEST=42 diff --git a/tasks/server-tests/fixtures/redwood-app/api/dist/functions/deeplyNested/nestedDir/deeplyNested.js b/tasks/server-tests/fixtures/redwood-app/api/dist/functions/deeplyNested/nestedDir/deeplyNested.js new file mode 100644 index 000000000000..8f3f42e5b4da --- /dev/null +++ b/tasks/server-tests/fixtures/redwood-app/api/dist/functions/deeplyNested/nestedDir/deeplyNested.js @@ -0,0 +1,19 @@ +/** + * @typedef { import('aws-lambda').APIGatewayEvent } APIGatewayEvent + * @typedef { import('aws-lambda').Context } Context + * @param { APIGatewayEvent } event + * @param { Context } context + */ +const handler = async (event, _context) => { + return { + statusCode: 200, + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + data: 'deeply nested function', + }), + } +} + +module.exports = { handler } diff --git a/tasks/server-tests/fixtures/redwood-app/api/dist/functions/env.js b/tasks/server-tests/fixtures/redwood-app/api/dist/functions/env.js new file mode 100644 index 000000000000..93df345b952a --- /dev/null +++ b/tasks/server-tests/fixtures/redwood-app/api/dist/functions/env.js @@ -0,0 +1,19 @@ +/** + * @typedef { import('aws-lambda').APIGatewayEvent } APIGatewayEvent + * @typedef { import('aws-lambda').Context } Context + * @param { APIGatewayEvent } event + * @param { Context } context + */ +const handler = async (event, _context) => { + return { + statusCode: 200, + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + data: process.env.LOAD_ENV_DEFAULTS_TEST, + }), + } +} + +module.exports = { handler } diff --git a/tasks/server-tests/fixtures/redwood-app/api/dist/functions/graphql.js b/tasks/server-tests/fixtures/redwood-app/api/dist/functions/graphql.js new file mode 100644 index 000000000000..9fb67748eb5d --- /dev/null +++ b/tasks/server-tests/fixtures/redwood-app/api/dist/functions/graphql.js @@ -0,0 +1,29 @@ +/** + * @typedef { import('aws-lambda').APIGatewayEvent } APIGatewayEvent + * @typedef { import('aws-lambda').Context } Context + * @param { APIGatewayEvent } event + * @param { Context } context + */ +const handler = async (event, _context) => { + const { query } = event.queryStringParameters + + if (query.trim() !== "{redwood{version}}") { + return { + statusCode: 400 + } + } + + return { + statusCode: 200, + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + data: { + version: 42 + }, + }), + } +} + +module.exports = { handler } diff --git a/tasks/server-tests/fixtures/redwood-app/api/dist/functions/health.js b/tasks/server-tests/fixtures/redwood-app/api/dist/functions/health.js new file mode 100644 index 000000000000..3be65e235cbd --- /dev/null +++ b/tasks/server-tests/fixtures/redwood-app/api/dist/functions/health.js @@ -0,0 +1,7 @@ +const handler = async () => { + return { + statusCode: 200, + } +} + +module.exports = { handler } diff --git a/tasks/server-tests/fixtures/redwood-app/api/dist/functions/hello.js b/tasks/server-tests/fixtures/redwood-app/api/dist/functions/hello.js new file mode 100644 index 000000000000..62a749d44e8b --- /dev/null +++ b/tasks/server-tests/fixtures/redwood-app/api/dist/functions/hello.js @@ -0,0 +1,19 @@ +/** + * @typedef { import('aws-lambda').APIGatewayEvent } APIGatewayEvent + * @typedef { import('aws-lambda').Context } Context + * @param { APIGatewayEvent } event + * @param { Context } context + */ +const handler = async (event, _context) => { + return { + statusCode: 200, + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + data: 'hello function', + }), + } +} + +module.exports = { handler } diff --git a/tasks/server-tests/fixtures/redwood-app/api/dist/functions/nested/nested.js b/tasks/server-tests/fixtures/redwood-app/api/dist/functions/nested/nested.js new file mode 100644 index 000000000000..11e3048bc928 --- /dev/null +++ b/tasks/server-tests/fixtures/redwood-app/api/dist/functions/nested/nested.js @@ -0,0 +1,19 @@ +/** + * @typedef { import('aws-lambda').APIGatewayEvent } APIGatewayEvent + * @typedef { import('aws-lambda').Context } Context + * @param { APIGatewayEvent } event + * @param { Context } context + */ +const handler = async (event, _context) => { + return { + statusCode: 200, + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + data: 'nested function', + }), + } +} + +module.exports = { handler } diff --git a/tasks/server-tests/fixtures/redwood-app/api/dist/functions/noHandler.js b/tasks/server-tests/fixtures/redwood-app/api/dist/functions/noHandler.js new file mode 100644 index 000000000000..3d4b958aa487 --- /dev/null +++ b/tasks/server-tests/fixtures/redwood-app/api/dist/functions/noHandler.js @@ -0,0 +1,3 @@ +const version = '42' + +module.exports = { version } diff --git a/tasks/server-tests/fixtures/redwood-app/api/server.config.js b/tasks/server-tests/fixtures/redwood-app/api/server.config.js new file mode 100644 index 000000000000..2d56f961257d --- /dev/null +++ b/tasks/server-tests/fixtures/redwood-app/api/server.config.js @@ -0,0 +1,64 @@ +/** + * This file allows you to configure the Fastify Server settings + * used by the RedwoodJS dev server. + * + * It also applies when running RedwoodJS with `yarn rw serve`. + * + * For the Fastify server options that you can set, see: + * https://www.fastify.io/docs/latest/Reference/Server/#factory + * + * Examples include: logger settings, timeouts, maximum payload limits, and more. + * + * Note: This configuration does not apply in a serverless deploy. + */ + +/** @type {import('fastify').FastifyServerOptions} */ +const config = { + requestTimeout: 15_000, + logger: false, +} + +/** + * You can also register Fastify plugins and additional routes for the API and Web sides + * in the configureFastify function. + * + * This function has access to the Fastify instance and options, such as the side + * (web, api, or proxy) that is being configured and other settings like the apiRootPath + * of the functions endpoint. + * + * Note: This configuration does not apply in a serverless deploy. + */ + +/** @type {import('@redwoodjs/api-server/dist/types').FastifySideConfigFn} */ +const configureFastify = async (fastify, options) => { + if (options.side === 'api') { + fastify.log.trace({ custom: { options } }, 'Configuring api side') + + fastify.get( + `/rest/v1/users/get/:userId`, + async function (request, reply) { + const { userId } = request.params + + return reply.send({ + id: 1 + }) + } + ) + } + + if (options.side === 'web') { + fastify.log.trace({ custom: { options } }, 'Configuring web side') + + fastify.get('/test-route', async (_request, _reply) => { + return { message: options.message } + }) + } + + return fastify +} + +module.exports = { + config, + configureFastify, +} + diff --git a/tasks/server-tests/fixtures/redwood-app/redwood.toml b/tasks/server-tests/fixtures/redwood-app/redwood.toml new file mode 100644 index 000000000000..147631de6159 --- /dev/null +++ b/tasks/server-tests/fixtures/redwood-app/redwood.toml @@ -0,0 +1,21 @@ +# This file contains the configuration settings for your Redwood app. +# This file is also what makes your Redwood app a Redwood app. +# If you remove it and try to run `yarn rw dev`, you'll get an error. +# +# For the full list of options, see the "App Configuration: redwood.toml" doc: +# https://redwoodjs.com/docs/app-configuration-redwood-toml + +[web] + title = "Redwood App" + port = 8910 + apiUrl = "/.redwood/functions" # You can customize graphql and dbauth urls individually too: see https://redwoodjs.com/docs/app-configuration-redwood-toml#api-paths + includeEnvironmentVariables = [ + # Add any ENV vars that should be available to the web side to this array + # See https://redwoodjs.com/docs/environment-variables#web + ] +[api] + port = 8911 +[browser] + open = true +[notifications] + versionUpdates = ["latest"] diff --git a/tasks/server-tests/fixtures/redwood-app/web/dist/200.html b/tasks/server-tests/fixtures/redwood-app/web/dist/200.html new file mode 100644 index 000000000000..355801d52690 --- /dev/null +++ b/tasks/server-tests/fixtures/redwood-app/web/dist/200.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + + +
+ + + diff --git a/tasks/server-tests/fixtures/redwood-app/web/dist/404.html b/tasks/server-tests/fixtures/redwood-app/web/dist/404.html new file mode 100644 index 000000000000..f6d55df34ba6 --- /dev/null +++ b/tasks/server-tests/fixtures/redwood-app/web/dist/404.html @@ -0,0 +1,65 @@ + + + + + + Redwood App | Redwood App + + + + + + + + + + +
+
+ +
+

404 Page Not Found

+
+
+ +
+ + + diff --git a/tasks/server-tests/fixtures/redwood-app/web/dist/README.md b/tasks/server-tests/fixtures/redwood-app/web/dist/README.md new file mode 100644 index 000000000000..345ab0cd5acf --- /dev/null +++ b/tasks/server-tests/fixtures/redwood-app/web/dist/README.md @@ -0,0 +1,54 @@ +# Static Assets + +Use this folder to add static files directly to your app. All included files and +folders will be copied directly into the `/dist` folder (created when Vite +builds for production). They will also be available during development when you +run `yarn rw dev`. >Note: files will _not_ hot reload while the development +server is running. You'll need to manually stop/start to access file changes. + +### Example Use + +A file like `favicon.png` will be copied to `/dist/favicon.png`. A folder +containing a file such as `static-files/my-logo.jpg` will be copied to +`/dist/static-files/my-logo.jpg`. These can be referenced in your code directly +without any special handling, e.g. + +``` + +``` + +and + +``` + alt="Logo" /> +``` + +## Best Practices + +Because assets in this folder are bypassing the javascript module system, **this +folder should be used sparingly** for assets such as favicons, robots.txt, +manifests, libraries incompatible with Vite, etc. + +In general, it's best to import files directly into a template, page, or +component. This allows Vite to include that file in the bundle when small +enough, or to copy it over to the `dist` folder with a hash. + +### Example Asset Import with Vite + +Instead of handling our logo image as a static file per the example above, we +can do the following: + +``` +import React from "react" +import logo from "./my-logo.jpg" + + +function Header() { + return Logo +} + +export default Header +``` + +See Vite's docs for +[static asset handling](https://vitejs.dev/guide/assets.html) diff --git a/tasks/server-tests/fixtures/redwood-app/web/dist/about.html b/tasks/server-tests/fixtures/redwood-app/web/dist/about.html new file mode 100644 index 000000000000..9daca9e2fa83 --- /dev/null +++ b/tasks/server-tests/fixtures/redwood-app/web/dist/about.html @@ -0,0 +1,40 @@ + + + + + + Redwood App | Redwood App + + + + + + + + + + +
+
+

Redwood Blog

+ +
+
+

This site was created to demonstrate my mastery of Redwood: Look on my works, ye mighty, and + despair!

+ +
+
+ + + diff --git a/tasks/server-tests/fixtures/redwood-app/web/dist/assets/AboutPage-7ec0f8df.js b/tasks/server-tests/fixtures/redwood-app/web/dist/assets/AboutPage-7ec0f8df.js new file mode 100644 index 000000000000..a679b2cfce14 --- /dev/null +++ b/tasks/server-tests/fixtures/redwood-app/web/dist/assets/AboutPage-7ec0f8df.js @@ -0,0 +1,3 @@ +import{j as t}from"./index-ff057e8f.js";const o=()=>t.jsx("p",{className:"font-light",children:"This site was created to demonstrate my mastery of Redwood: Look on my works, ye mighty, and despair!"});export{o as default}; +globalThis.__REDWOOD__PRERENDER_PAGES = globalThis.__REDWOOD__PRERENDER_PAGES || {}; +globalThis.__REDWOOD__PRERENDER_PAGES.AboutPage=o; diff --git a/tasks/server-tests/fixtures/redwood-app/web/dist/assets/index-613d397d.css b/tasks/server-tests/fixtures/redwood-app/web/dist/assets/index-613d397d.css new file mode 100644 index 000000000000..a46c81a539ee --- /dev/null +++ b/tasks/server-tests/fixtures/redwood-app/web/dist/assets/index-613d397d.css @@ -0,0 +1,2 @@ +.rw-scaffold{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity))}.rw-scaffold h1,.rw-scaffold h2{margin:0}.rw-scaffold a{background-color:transparent}.rw-scaffold ul{margin:0;padding:0}.rw-scaffold input::-moz-placeholder{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity))}.rw-scaffold input::placeholder{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity))}.rw-header{display:flex;justify-content:space-between;padding:1rem 2rem}.rw-main{margin-left:1rem;margin-right:1rem;padding-bottom:1rem}.rw-segment{width:100%;overflow:hidden;border-radius:.5rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity));scrollbar-color:#a1a1aa transparent}.rw-segment::-webkit-scrollbar{height:initial}.rw-segment::-webkit-scrollbar-track{border-radius:0 0 10px 10px/0px 0px 10px 10px;border-width:0px;border-top-width:1px;border-style:solid;--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity));background-color:transparent;padding:2px}.rw-segment::-webkit-scrollbar-thumb{border-radius:9999px;border-width:3px;border-style:solid;border-color:transparent;--tw-bg-opacity: 1;background-color:rgb(161 161 170 / var(--tw-bg-opacity));background-clip:content-box}.rw-segment-header{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity));padding:.75rem 1rem;--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity))}.rw-segment-main{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity));padding:1rem}.rw-link{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity));text-decoration-line:underline}.rw-link:hover{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity))}.rw-forgot-link{margin-top:.25rem;text-align:right;font-size:.75rem;line-height:1rem;--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity));text-decoration-line:underline}.rw-forgot-link:hover{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity))}.rw-heading{font-weight:600}.rw-heading.rw-heading-primary{font-size:1.25rem;line-height:1.75rem}.rw-heading.rw-heading-secondary{font-size:.875rem;line-height:1.25rem}.rw-heading .rw-link{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity));text-decoration-line:none}.rw-heading .rw-link:hover{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity));text-decoration-line:underline}.rw-cell-error{font-size:.875rem;line-height:1.25rem;font-weight:600}.rw-form-wrapper{margin-top:-1rem;font-size:.875rem;line-height:1.25rem}.rw-cell-error,.rw-form-error-wrapper{margin-top:1rem;margin-bottom:1rem;border-radius:.25rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(254 226 226 / var(--tw-border-opacity));--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity));padding:1rem;--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity))}.rw-form-error-title{margin:0;font-weight:600}.rw-form-error-list{margin-top:.5rem;list-style-position:inside;list-style-type:disc}.rw-button{display:flex;cursor:pointer;justify-content:center;border-radius:.25rem;border-width:0px;--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity));padding:.25rem 1rem;font-size:.75rem;line-height:1rem;font-weight:600;text-transform:uppercase;line-height:2;letter-spacing:.025em;--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity));text-decoration-line:none;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.1s}.rw-button:hover{--tw-bg-opacity: 1;background-color:rgb(107 114 128 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.rw-button.rw-button-small{border-radius:.125rem;padding:.25rem .5rem;font-size:.75rem;line-height:1rem}.rw-button.rw-button-green{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.rw-button.rw-button-green:hover{--tw-bg-opacity: 1;background-color:rgb(21 128 61 / var(--tw-bg-opacity))}.rw-button.rw-button-blue{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.rw-button.rw-button-blue:hover{--tw-bg-opacity: 1;background-color:rgb(29 78 216 / var(--tw-bg-opacity))}.rw-button.rw-button-red{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.rw-button.rw-button-red:hover{--tw-bg-opacity: 1;background-color:rgb(185 28 28 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.rw-button-icon{margin-right:.25rem;font-size:1.25rem;line-height:1.25rem}.rw-button-group{margin:.75rem .5rem;display:flex;justify-content:center}.rw-button-group .rw-button{margin-left:.25rem;margin-right:.25rem}.rw-form-wrapper .rw-button-group{margin-top:2rem}.rw-label{margin-top:1.5rem;display:block;text-align:left;font-weight:600;--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity))}.rw-label.rw-label-error{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity))}.rw-input{margin-top:.5rem;display:block;width:100%;border-radius:.25rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity));--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity));padding:.5rem;outline:2px solid transparent;outline-offset:2px}.rw-check-radio-items{display:flex;justify-items:center}.rw-check-radio-item-none{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity))}.rw-input[type=checkbox],.rw-input[type=radio]{margin-left:0;margin-right:.25rem;margin-top:.25rem;display:inline;width:1rem}.rw-input:focus{--tw-border-opacity: 1;border-color:rgb(156 163 175 / var(--tw-border-opacity))}.rw-input-error{--tw-border-opacity: 1;border-color:rgb(220 38 38 / var(--tw-border-opacity));--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity))}.rw-input-error:focus{--tw-border-opacity: 1;border-color:rgb(220 38 38 / var(--tw-border-opacity));outline:2px solid transparent;outline-offset:2px;box-shadow:0 0 5px #c53030}.rw-field-error{margin-top:.25rem;display:block;font-size:.75rem;line-height:1rem;font-weight:600;text-transform:uppercase;--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity))}.rw-table-wrapper-responsive{overflow-x:auto}.rw-table-wrapper-responsive .rw-table{min-width:48rem}.rw-table{width:100%;font-size:.875rem;line-height:1.25rem}.rw-table th,.rw-table td{padding:.75rem}.rw-table td{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity))}.rw-table tr:nth-child(odd) td,.rw-table tr:nth-child(odd) th{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity))}.rw-table thead tr{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity))}.rw-table th{text-align:left;font-weight:600}.rw-table thead th{text-align:left}.rw-table tbody th{text-align:right}@media (min-width: 768px){.rw-table tbody th{width:20%}}.rw-table tbody tr{border-top-width:1px;--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity))}.rw-table input{margin-left:0}.rw-table-actions{display:flex;height:1rem;align-items:center;justify-content:flex-end;padding-right:.25rem}.rw-table-actions .rw-button{background-color:transparent}.rw-table-actions .rw-button:hover{--tw-bg-opacity: 1;background-color:rgb(107 114 128 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.rw-table-actions .rw-button-blue{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity))}.rw-table-actions .rw-button-blue:hover{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.rw-table-actions .rw-button-red{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity))}.rw-table-actions .rw-button-red:hover{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.rw-text-center{text-align:center}.rw-login-container{margin-left:auto;margin-right:auto;margin-top:4rem;margin-bottom:4rem;display:flex;width:24rem;flex-wrap:wrap;align-items:center;justify-content:center}.rw-login-container .rw-form-wrapper{width:100%;text-align:center}.rw-login-link{margin-top:1rem;width:100%;text-align:center;font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity))}.rw-webauthn-wrapper{margin-left:1rem;margin-right:1rem;margin-top:1.5rem;line-height:1.5rem}.rw-webauthn-wrapper h2{margin-bottom:1rem;font-size:1.25rem;line-height:1.75rem;font-weight:700}/*! tailwindcss v3.3.3 | MIT License | https://tailwindcss.com + */*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.relative{position:relative}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-4{margin-bottom:1rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-8{margin-top:2rem}.block{display:block}.flex{display:flex}.table{display:table}.max-w-4xl{max-width:56rem}.items-center{align-items:center}.justify-between{justify-content:space-between}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rounded{border-radius:.25rem}.rounded-sm{border-radius:.125rem}.rounded-b{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.border{border-width:1px}.border-red-700{--tw-border-opacity: 1;border-color:rgb(185 28 28 / var(--tw-border-opacity))}.bg-blue-700{--tw-bg-opacity: 1;background-color:rgb(29 78 216 / var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.p-12{padding:3rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.px-8{padding-left:2rem;padding-right:2rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.text-left{text-align:left}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.font-light{font-weight:300}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.tracking-tight{letter-spacing:-.025em}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity))}.text-blue-600{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.underline{text-decoration-line:underline}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-100{transition-duration:.1s}.visited\:text-purple-600:visited{color:#9333ea}.hover\:bg-blue-600:hover{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity))}.hover\:text-blue-100:hover{--tw-text-opacity: 1;color:rgb(219 234 254 / var(--tw-text-opacity))}.hover\:text-blue-600:hover{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity))}.hover\:text-blue-800:hover{--tw-text-opacity: 1;color:rgb(30 64 175 / var(--tw-text-opacity))} diff --git a/tasks/server-tests/fixtures/redwood-app/web/dist/build-manifest.json b/tasks/server-tests/fixtures/redwood-app/web/dist/build-manifest.json new file mode 100644 index 000000000000..ac9125cd9908 --- /dev/null +++ b/tasks/server-tests/fixtures/redwood-app/web/dist/build-manifest.json @@ -0,0 +1,230 @@ +{ + "_ContactForm-d76f67ab.js": { + "file": "assets/ContactForm-d76f67ab.js", + "imports": [ + "index.html", + "_index-77bc0912.js" + ] + }, + "_PostForm-4b7853da.js": { + "file": "assets/PostForm-4b7853da.js", + "imports": [ + "index.html", + "_index-77bc0912.js" + ] + }, + "_formatters-2fce1756.js": { + "file": "assets/formatters-2fce1756.js", + "imports": [ + "index.html" + ] + }, + "_index-77bc0912.js": { + "file": "assets/index-77bc0912.js", + "imports": [ + "index.html" + ] + }, + "index.css": { + "file": "assets/index-613d397d.css", + "src": "index.css" + }, + "index.html": { + "css": [ + "assets/index-613d397d.css" + ], + "dynamicImports": [ + "pages/AboutPage/AboutPage.tsx", + "pages/BlogPostPage/BlogPostPage.tsx", + "pages/ContactUsPage/ContactUsPage.tsx", + "pages/DoublePage/DoublePage.tsx", + "pages/ForgotPasswordPage/ForgotPasswordPage.tsx", + "pages/LoginPage/LoginPage.tsx", + "pages/NotFoundPage/NotFoundPage.tsx", + "pages/ProfilePage/ProfilePage.tsx", + "pages/ResetPasswordPage/ResetPasswordPage.tsx", + "pages/SignupPage/SignupPage.tsx", + "pages/WaterfallPage/WaterfallPage.tsx", + "pages/Contact/ContactPage/ContactPage.tsx", + "pages/Contact/ContactsPage/ContactsPage.tsx", + "pages/Contact/EditContactPage/EditContactPage.tsx", + "pages/Contact/NewContactPage/NewContactPage.tsx", + "pages/Post/EditPostPage/EditPostPage.tsx", + "pages/Post/NewPostPage/NewPostPage.tsx", + "pages/Post/PostPage/PostPage.tsx", + "pages/Post/PostsPage/PostsPage.tsx" + ], + "file": "assets/index-ff057e8f.js", + "isEntry": true, + "src": "index.html" + }, + "pages/AboutPage/AboutPage.tsx": { + "file": "assets/AboutPage-7ec0f8df.js", + "imports": [ + "index.html" + ], + "isDynamicEntry": true, + "src": "pages/AboutPage/AboutPage.tsx" + }, + "pages/BlogPostPage/BlogPostPage.tsx": { + "file": "assets/BlogPostPage-526c7060.js", + "imports": [ + "index.html" + ], + "isDynamicEntry": true, + "src": "pages/BlogPostPage/BlogPostPage.tsx" + }, + "pages/Contact/ContactPage/ContactPage.tsx": { + "file": "assets/ContactPage-4a851c42.js", + "imports": [ + "index.html", + "_formatters-2fce1756.js" + ], + "isDynamicEntry": true, + "src": "pages/Contact/ContactPage/ContactPage.tsx" + }, + "pages/Contact/ContactsPage/ContactsPage.tsx": { + "file": "assets/ContactsPage-1fcf6187.js", + "imports": [ + "index.html", + "_formatters-2fce1756.js" + ], + "isDynamicEntry": true, + "src": "pages/Contact/ContactsPage/ContactsPage.tsx" + }, + "pages/Contact/EditContactPage/EditContactPage.tsx": { + "file": "assets/EditContactPage-1622b085.js", + "imports": [ + "index.html", + "_ContactForm-d76f67ab.js", + "_index-77bc0912.js" + ], + "isDynamicEntry": true, + "src": "pages/Contact/EditContactPage/EditContactPage.tsx" + }, + "pages/Contact/NewContactPage/NewContactPage.tsx": { + "file": "assets/NewContactPage-5935f0db.js", + "imports": [ + "index.html", + "_ContactForm-d76f67ab.js", + "_index-77bc0912.js" + ], + "isDynamicEntry": true, + "src": "pages/Contact/NewContactPage/NewContactPage.tsx" + }, + "pages/ContactUsPage/ContactUsPage.tsx": { + "file": "assets/ContactUsPage-71f00589.js", + "imports": [ + "index.html", + "_index-77bc0912.js" + ], + "isDynamicEntry": true, + "src": "pages/ContactUsPage/ContactUsPage.tsx" + }, + "pages/DoublePage/DoublePage.tsx": { + "file": "assets/DoublePage-0bee4876.js", + "imports": [ + "index.html" + ], + "isDynamicEntry": true, + "src": "pages/DoublePage/DoublePage.tsx" + }, + "pages/ForgotPasswordPage/ForgotPasswordPage.tsx": { + "file": "assets/ForgotPasswordPage-15d7cf2f.js", + "imports": [ + "index.html", + "_index-77bc0912.js" + ], + "isDynamicEntry": true, + "src": "pages/ForgotPasswordPage/ForgotPasswordPage.tsx" + }, + "pages/LoginPage/LoginPage.tsx": { + "file": "assets/LoginPage-5f6d498c.js", + "imports": [ + "index.html", + "_index-77bc0912.js" + ], + "isDynamicEntry": true, + "src": "pages/LoginPage/LoginPage.tsx" + }, + "pages/NotFoundPage/NotFoundPage.tsx": { + "file": "assets/NotFoundPage-0903a03f.js", + "imports": [ + "index.html" + ], + "isDynamicEntry": true, + "src": "pages/NotFoundPage/NotFoundPage.tsx" + }, + "pages/Post/EditPostPage/EditPostPage.tsx": { + "file": "assets/EditPostPage-abe727e6.js", + "imports": [ + "index.html", + "_PostForm-4b7853da.js", + "_index-77bc0912.js" + ], + "isDynamicEntry": true, + "src": "pages/Post/EditPostPage/EditPostPage.tsx" + }, + "pages/Post/NewPostPage/NewPostPage.tsx": { + "file": "assets/NewPostPage-dcbeffd5.js", + "imports": [ + "index.html", + "_PostForm-4b7853da.js", + "_index-77bc0912.js" + ], + "isDynamicEntry": true, + "src": "pages/Post/NewPostPage/NewPostPage.tsx" + }, + "pages/Post/PostPage/PostPage.tsx": { + "file": "assets/PostPage-292888c6.js", + "imports": [ + "index.html", + "_formatters-2fce1756.js" + ], + "isDynamicEntry": true, + "src": "pages/Post/PostPage/PostPage.tsx" + }, + "pages/Post/PostsPage/PostsPage.tsx": { + "file": "assets/PostsPage-cacd5a1e.js", + "imports": [ + "index.html", + "_formatters-2fce1756.js" + ], + "isDynamicEntry": true, + "src": "pages/Post/PostsPage/PostsPage.tsx" + }, + "pages/ProfilePage/ProfilePage.tsx": { + "file": "assets/ProfilePage-133e6e05.js", + "imports": [ + "index.html" + ], + "isDynamicEntry": true, + "src": "pages/ProfilePage/ProfilePage.tsx" + }, + "pages/ResetPasswordPage/ResetPasswordPage.tsx": { + "file": "assets/ResetPasswordPage-a3399e1b.js", + "imports": [ + "index.html", + "_index-77bc0912.js" + ], + "isDynamicEntry": true, + "src": "pages/ResetPasswordPage/ResetPasswordPage.tsx" + }, + "pages/SignupPage/SignupPage.tsx": { + "file": "assets/SignupPage-44411fe1.js", + "imports": [ + "index.html", + "_index-77bc0912.js" + ], + "isDynamicEntry": true, + "src": "pages/SignupPage/SignupPage.tsx" + }, + "pages/WaterfallPage/WaterfallPage.tsx": { + "file": "assets/WaterfallPage-46b80a6f.js", + "imports": [ + "index.html" + ], + "isDynamicEntry": true, + "src": "pages/WaterfallPage/WaterfallPage.tsx" + } +} diff --git a/tasks/server-tests/fixtures/redwood-app/web/dist/contacts/new.html b/tasks/server-tests/fixtures/redwood-app/web/dist/contacts/new.html new file mode 100644 index 000000000000..a3d4460288bb --- /dev/null +++ b/tasks/server-tests/fixtures/redwood-app/web/dist/contacts/new.html @@ -0,0 +1,50 @@ + + + + + + Redwood App | Redwood App + + + + + + + + + + +
+
+
+
+

Contacts

+
+
New Contact +
+
+
+
+
+

New Contact

+
+
+
+
+
+
+
+
+
+ +
+
+
+ + + diff --git a/tasks/server-tests/fixtures/redwood-app/web/dist/favicon.png b/tasks/server-tests/fixtures/redwood-app/web/dist/favicon.png new file mode 100644 index 000000000000..47414294173c Binary files /dev/null and b/tasks/server-tests/fixtures/redwood-app/web/dist/favicon.png differ diff --git a/tasks/server-tests/fixtures/redwood-app/web/dist/index.html b/tasks/server-tests/fixtures/redwood-app/web/dist/index.html new file mode 100644 index 000000000000..0e54fa2690c7 --- /dev/null +++ b/tasks/server-tests/fixtures/redwood-app/web/dist/index.html @@ -0,0 +1,79 @@ + + + + + Redwood App | Redwood App + + + + + + + + + + +
+
+

Redwood Blog

+ +
+
+
+
+
+

October 13, 2023 - By: User One + (user.one@example.com)

+

Welcome to the + blog!

+
+
I'm baby single- origin coffee kickstarter lo - fi paleo + skateboard.Tumblr hashtag austin whatever DIY plaid knausgaard fanny pack messenger bag blog next level + woke.Ethical bitters fixie freegan,helvetica pitchfork 90's tbh chillwave mustache godard subway tile ramps + art party. Hammock sustainable twee yr bushwick disrupt unicorn, before they sold out direct trade + chicharrones etsy polaroid hoodie. Gentrify offal hoodie fingerstache.
+
+
+
+

October 13, 2023 - By: User Two + (user.two@example.com)

+

What is the + meaning of life?

+
+
Meh waistcoat succulents umami asymmetrical, hoodie + post-ironic paleo chillwave tote bag. Trust fund kitsch waistcoat vape, cray offal gochujang food truck + cloud bread enamel pin forage. Roof party chambray ugh occupy fam stumptown. Dreamcatcher tousled snackwave, + typewriter lyft unicorn pabst portland blue bottle locavore squid PBR&B tattooed.
+
+
+
+

October 13, 2023 - By: User One + (user.one@example.com)

+

A little more + about me

+
+
Raclette shoreditch before they sold out lyft. Ethical bicycle + rights meh prism twee. Tote bag ennui vice, slow-carb taiyaki crucifix whatever you probably haven't heard + of them jianbing raw denim DIY hot chicken. Chillwave blog succulents freegan synth af ramps poutine + wayfarers yr seitan roof party squid. Jianbing flexitarian gentrify hexagon portland single-origin coffee + raclette gluten-free. Coloring book cloud bread street art kitsch lumbersexual af distillery ethical ugh + thundercats roof party poke chillwave. 90's palo santo green juice subway tile, prism viral butcher selvage + etsy pitchfork sriracha tumeric bushwick.
+
+
+ +
+
+ + + diff --git a/tasks/server-tests/fixtures/redwood-app/web/dist/nested/index.html b/tasks/server-tests/fixtures/redwood-app/web/dist/nested/index.html new file mode 100644 index 000000000000..355801d52690 --- /dev/null +++ b/tasks/server-tests/fixtures/redwood-app/web/dist/nested/index.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + + +
+ + + diff --git a/tasks/server-tests/fixtures/redwood-app/web/dist/robots.txt b/tasks/server-tests/fixtures/redwood-app/web/dist/robots.txt new file mode 100644 index 000000000000..eb0536286f30 --- /dev/null +++ b/tasks/server-tests/fixtures/redwood-app/web/dist/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: diff --git a/tasks/server-tests/jest.config.js b/tasks/server-tests/jest.config.js new file mode 100644 index 000000000000..6d446413e90f --- /dev/null +++ b/tasks/server-tests/jest.config.js @@ -0,0 +1,7 @@ +/** @type {import('jest').Config} */ +const config = { + rootDir: '.', + testTimeout: 5_000 * 2, +} + +module.exports = config diff --git a/tasks/server-tests/server.test.ts b/tasks/server-tests/server.test.ts new file mode 100644 index 000000000000..a7e34f9af9e5 --- /dev/null +++ b/tasks/server-tests/server.test.ts @@ -0,0 +1,668 @@ +const fs = require('fs') +const http = require('http') +const path = require('path') + +const execa = require('execa') + +// Set up RWJS_CWD. +let original_RWJS_CWD + +beforeAll(() => { + original_RWJS_CWD = process.env.RWJS_CWD + process.env.RWJS_CWD = path.join(__dirname, './fixtures/redwood-app') +}) + +afterAll(() => { + process.env.RWJS_CWD = original_RWJS_CWD +}) + +// Clean up the child process after each test. +let child + +afterEach(async () => { + if (!child) { + return + } + + child.cancel() + + // Wait for child process to terminate. + try { + await child + } catch (e) { + // Ignore the error. + } +}) + +const TIMEOUT = 1_000 * 2 + +const commandStrings = { + '@redwoodjs/cli': `node ${path.resolve( + __dirname, + '../../packages/cli/dist/index.js' + )} serve`, + '@redwoodjs/api-server': `node ${path.resolve( + __dirname, + '../../packages/api-server/dist/index.js' + )}`, + '@redwoodjs/web-server': `node ${path.resolve( + __dirname, + '../../packages/web-server/dist/server.js' + )}`, +} + +const redwoodToml = fs.readFileSync( + path.join(__dirname, './fixtures/redwood-app/redwood.toml'), + 'utf-8' +) + +const { + groups: { apiUrl }, +} = redwoodToml.match(/apiUrl = "(?[^"]*)/) + +describe.each([ + [`${commandStrings['@redwoodjs/cli']}`], + [`${commandStrings['@redwoodjs/api-server']}`], +])('serve both (%s)', (commandString) => { + it('serves both sides, using the apiRootPath in redwood.toml', async () => { + child = execa.command(commandString) + await new Promise((r) => setTimeout(r, TIMEOUT)) + + const webRes = await fetch('http://localhost:8910/about') + const webBody = await webRes.text() + + expect(webRes.status).toEqual(200) + expect(webBody).toEqual( + fs.readFileSync( + path.join(__dirname, './fixtures/redwood-app/web/dist/about.html'), + 'utf-8' + ) + ) + + const apiRes = await fetch(`http://localhost:8910${apiUrl}/hello`) + const apiBody = await apiRes.json() + + expect(apiRes.status).toEqual(200) + expect(apiBody).toEqual({ data: 'hello function' }) + }) + + it('--port changes the port', async () => { + const port = 8920 + + child = execa.command(`${commandString} --port ${port}`) + await new Promise((r) => setTimeout(r, TIMEOUT)) + + const webRes = await fetch(`http://localhost:${port}/about`) + const webBody = await webRes.text() + + expect(webRes.status).toEqual(200) + expect(webBody).toEqual( + fs.readFileSync( + path.join(__dirname, './fixtures/redwood-app/web/dist/about.html'), + 'utf-8' + ) + ) + + const apiRes = await fetch(`http://localhost:${port}${apiUrl}/hello`) + const apiBody = await apiRes.json() + + expect(apiRes.status).toEqual(200) + expect(apiBody).toEqual({ data: 'hello function' }) + }) +}) + +describe.each([ + [`${commandStrings['@redwoodjs/cli']} api`], + [`${commandStrings['@redwoodjs/api-server']} api`], +])('serve api (%s)', (commandString) => { + it('serves the api side', async () => { + child = execa.command(commandString) + await new Promise((r) => setTimeout(r, TIMEOUT)) + + const res = await fetch('http://localhost:8911/hello') + const body = await res.json() + + expect(res.status).toEqual(200) + expect(body).toEqual({ data: 'hello function' }) + }) + + it('--port changes the port', async () => { + const port = 3000 + + child = execa.command(`${commandString} --port ${port}`) + await new Promise((r) => setTimeout(r, TIMEOUT)) + + const res = await fetch(`http://localhost:${port}/hello`) + const body = await res.json() + + expect(res.status).toEqual(200) + expect(body).toEqual({ data: 'hello function' }) + }) + + it('--apiRootPath changes the prefix', async () => { + const apiRootPath = '/api' + + child = execa.command(`${commandString} --apiRootPath ${apiRootPath}`) + await new Promise((r) => setTimeout(r, TIMEOUT)) + + const res = await fetch(`http://localhost:8911${apiRootPath}/hello`) + const body = await res.json() + + expect(res.status).toEqual(200) + expect(body).toEqual({ data: 'hello function' }) + }) +}) + +// We can't test @redwoodjs/cli here because it depends on node_modules. +describe.each([ + [`${commandStrings['@redwoodjs/api-server']} web`], + [commandStrings['@redwoodjs/web-server']], +])('serve web (%s)', (commandString) => { + it('serves the web side', async () => { + child = execa.command(commandString) + await new Promise((r) => setTimeout(r, TIMEOUT)) + + const res = await fetch('http://localhost:8910/about') + const body = await res.text() + + expect(res.status).toEqual(200) + expect(body).toEqual( + fs.readFileSync( + path.join(__dirname, './fixtures/redwood-app/web/dist/about.html'), + 'utf-8' + ) + ) + }) + + it('--port changes the port', async () => { + const port = 8912 + + child = execa.command(`${commandString} --port ${port}`) + await new Promise((r) => setTimeout(r, TIMEOUT)) + + const res = await fetch(`http://localhost:${port}/about`) + const body = await res.text() + + expect(res.status).toEqual(200) + expect(body).toEqual( + fs.readFileSync( + path.join(__dirname, './fixtures/redwood-app/web/dist/about.html'), + 'utf-8' + ) + ) + }) + + it('--apiHost changes the upstream api url', async () => { + const apiPort = 8916 + const apiHost = 'localhost' + + const helloData = { data: 'hello from mock server' } + + const server = http.createServer((req, res) => { + if (req.url === '/hello') { + res.end(JSON.stringify(helloData)) + } + }) + + server.listen(apiPort, apiHost) + + child = execa.command( + `${commandString} --apiHost http://${apiHost}:${apiPort}` + ) + await new Promise((r) => setTimeout(r, TIMEOUT)) + + const res = await fetch('http://localhost:8910/.redwood/functions/hello') + const body = await res.json() + + expect(res.status).toEqual(200) + expect(body).toEqual(helloData) + + server.close() + }) + + it("doesn't error out on unknown args", async () => { + child = execa.command(`${commandString} --foo --bar --baz`) + await new Promise((r) => setTimeout(r, TIMEOUT)) + + const res = await fetch('http://localhost:8910/about') + const body = await res.text() + + expect(res.status).toEqual(200) + expect(body).toEqual( + fs.readFileSync( + path.join(__dirname, './fixtures/redwood-app/web/dist/about.html'), + 'utf-8' + ) + ) + }) +}) + +describe('@redwoodjs/cli', () => { + describe('both server CLI', () => { + const commandString = commandStrings['@redwoodjs/cli'] + + it.todo('handles --socket differently') + + it('has help configured', () => { + const { stdout } = execa.commandSync(`${commandString} --help`) + + expect(stdout).toMatchInlineSnapshot(` + "usage: rw + + Commands: + rw serve Run both api and web servers [default] + rw serve api Start server for serving only the api + rw serve web Start server for serving only the web side + + Options: + --help Show help [boolean] + --version Show version number [boolean] + --cwd Working directory to use (where \`redwood.toml\` is located) + --telemetry Whether to send anonymous usage telemetry to RedwoodJS + [boolean] + -p, --port [number] [default: 8910] + --socket [string] + + Also see the Redwood CLI Reference + (โ€‹https://redwoodjs.com/docs/cli-commands#serveโ€‹)" + `) + }) + + it('errors out on unknown args', async () => { + const { stdout } = execa.commandSync(`${commandString} --foo --bar --baz`) + + expect(stdout).toMatchInlineSnapshot(` + "usage: rw + + Commands: + rw serve Run both api and web servers [default] + rw serve api Start server for serving only the api + rw serve web Start server for serving only the web side + + Options: + --help Show help [boolean] + --version Show version number [boolean] + --cwd Working directory to use (where \`redwood.toml\` is located) + --telemetry Whether to send anonymous usage telemetry to RedwoodJS + [boolean] + -p, --port [number] [default: 8910] + --socket [string] + + Also see the Redwood CLI Reference + (โ€‹https://redwoodjs.com/docs/cli-commands#serveโ€‹) + + Unknown arguments: foo, bar, baz" + `) + }) + }) + + describe('api server CLI', () => { + const commandString = `${commandStrings['@redwoodjs/cli']} api` + + it.todo('handles --socket differently') + + it('loads dotenv files', async () => { + child = execa.command(`${commandString}`) + await new Promise((r) => setTimeout(r, TIMEOUT)) + + const res = await fetch(`http://localhost:8911/env`) + const body = await res.json() + + expect(res.status).toEqual(200) + expect(body).toEqual({ data: '42' }) + }) + + it('has help configured', () => { + const { stdout } = execa.commandSync(`${commandString} --help`) + + expect(stdout).toMatchInlineSnapshot(` + "rw serve api + + Start server for serving only the api + + Options: + --help Show help [boolean] + --version Show version number [boolean] + --cwd Working directory to use (where + \`redwood.toml\` is located) + --telemetry Whether to send anonymous usage + telemetry to RedwoodJS [boolean] + -p, --port [number] [default: 8911] + --socket [string] + --apiRootPath, --api-root-path, Root path where your api functions + --rootPath, --root-path are served [string] [default: "/"]" + `) + }) + + it('errors out on unknown args', async () => { + const { stdout } = execa.commandSync(`${commandString} --foo --bar --baz`) + + expect(stdout).toMatchInlineSnapshot(` + "rw serve api + + Start server for serving only the api + + Options: + --help Show help [boolean] + --version Show version number [boolean] + --cwd Working directory to use (where + \`redwood.toml\` is located) + --telemetry Whether to send anonymous usage + telemetry to RedwoodJS [boolean] + -p, --port [number] [default: 8911] + --socket [string] + --apiRootPath, --api-root-path, Root path where your api functions + --rootPath, --root-path are served [string] [default: "/"] + + Unknown arguments: foo, bar, baz" + `) + }) + }) + + describe('web server CLI', () => { + const commandString = `${commandStrings['@redwoodjs/cli']} web` + + it.todo('handles --socket differently') + + it('has help configured', () => { + const { stdout } = execa.commandSync(`${commandString} --help`) + + expect(stdout).toMatchInlineSnapshot(` + "rw serve web + + Start server for serving only the web side + + Options: + --help Show help [boolean] + --version Show version number [boolean] + --cwd Working directory to use (where \`redwood.toml\` is + located) + --telemetry Whether to send anonymous usage telemetry to + RedwoodJS [boolean] + -p, --port [number] [default: 8910] + --socket [string] + --apiHost, --api-host Forward requests from the apiUrl, defined in + redwood.toml to this host [string]" + `) + }) + + it('errors out on unknown args', async () => { + const { stdout } = execa.commandSync(`${commandString} --foo --bar --baz`) + + expect(stdout).toMatchInlineSnapshot(` + "rw serve web + + Start server for serving only the web side + + Options: + --help Show help [boolean] + --version Show version number [boolean] + --cwd Working directory to use (where \`redwood.toml\` is + located) + --telemetry Whether to send anonymous usage telemetry to + RedwoodJS [boolean] + -p, --port [number] [default: 8910] + --socket [string] + --apiHost, --api-host Forward requests from the apiUrl, defined in + redwood.toml to this host [string] + + Unknown arguments: foo, bar, baz" + `) + }) + }) +}) + +describe('@redwoodjs/api-server', () => { + describe('both server CLI', () => { + const commandString = commandStrings['@redwoodjs/api-server'] + + it('--socket changes the port', async () => { + const socket = 8921 + + child = execa.command(`${commandString} --socket ${socket}`) + await new Promise((r) => setTimeout(r, TIMEOUT)) + + const webRes = await fetch(`http://localhost:${socket}/about`) + const webBody = await webRes.text() + + expect(webRes.status).toEqual(200) + expect(webBody).toEqual( + fs.readFileSync( + path.join(__dirname, './fixtures/redwood-app/web/dist/about.html'), + 'utf-8' + ) + ) + + const apiRes = await fetch( + `http://localhost:${socket}/.redwood/functions/hello` + ) + const apiBody = await apiRes.json() + + expect(apiRes.status).toEqual(200) + expect(apiBody).toEqual({ data: 'hello function' }) + }) + + it('--socket wins out over --port', async () => { + const socket = 8922 + const port = 8923 + + child = execa.command( + `${commandString} --socket ${socket} --port ${port}` + ) + await new Promise((r) => setTimeout(r, TIMEOUT)) + + const webRes = await fetch(`http://localhost:${socket}/about`) + const webBody = await webRes.text() + + expect(webRes.status).toEqual(200) + expect(webBody).toEqual( + fs.readFileSync( + path.join(__dirname, './fixtures/redwood-app/web/dist/about.html'), + 'utf-8' + ) + ) + + const apiRes = await fetch( + `http://localhost:${socket}/.redwood/functions/hello` + ) + const apiBody = await apiRes.json() + + expect(apiRes.status).toEqual(200) + expect(apiBody).toEqual({ data: 'hello function' }) + }) + + it("doesn't have help configured", () => { + const { stdout } = execa.commandSync(`${commandString} --help`) + + expect(stdout).toMatchInlineSnapshot(` + "Options: + --help Show help [boolean] + --version Show version number [boolean]" + `) + }) + + it("doesn't error out on unknown args", async () => { + child = execa.command(`${commandString} --foo --bar --baz`) + await new Promise((r) => setTimeout(r, TIMEOUT)) + + const webRes = await fetch('http://localhost:8910/about') + const webBody = await webRes.text() + + expect(webRes.status).toEqual(200) + expect(webBody).toEqual( + fs.readFileSync( + path.join(__dirname, './fixtures/redwood-app/web/dist/about.html'), + 'utf-8' + ) + ) + + const apiRes = await fetch( + 'http://localhost:8910/.redwood/functions/hello' + ) + const apiBody = await apiRes.json() + + expect(apiRes.status).toEqual(200) + expect(apiBody).toEqual({ data: 'hello function' }) + }) + }) + + describe('api server CLI', () => { + const commandString = `${commandStrings['@redwoodjs/api-server']} api` + + it('--socket changes the port', async () => { + const socket = 3001 + + child = execa.command(`${commandString} --socket ${socket}`) + await new Promise((r) => setTimeout(r, TIMEOUT)) + + const res = await fetch(`http://localhost:${socket}/hello`) + const body = await res.json() + + expect(res.status).toEqual(200) + expect(body).toEqual({ data: 'hello function' }) + }) + + it('--socket wins out over --port', async () => { + const socket = 3002 + const port = 3003 + + child = execa.command( + `${commandString} --socket ${socket} --port ${port}` + ) + await new Promise((r) => setTimeout(r, TIMEOUT)) + + const res = await fetch(`http://localhost:${socket}/hello`) + const body = await res.json() + + expect(res.status).toEqual(200) + expect(body).toEqual({ data: 'hello function' }) + }) + + it('--loadEnvFiles loads dotenv files', async () => { + child = execa.command(`${commandString} --loadEnvFiles`) + await new Promise((r) => setTimeout(r, TIMEOUT)) + + const res = await fetch(`http://localhost:8911/env`) + const body = await res.json() + + expect(res.status).toEqual(200) + expect(body).toEqual({ data: '42' }) + }) + + it("doesn't have help configured", () => { + const { stdout } = execa.commandSync(`${commandString} --help`) + + expect(stdout).toMatchInlineSnapshot(` + "Options: + --help Show help [boolean] + --version Show version number [boolean]" + `) + }) + + it("doesn't error out on unknown args", async () => { + child = execa.command(`${commandString} --foo --bar --baz`) + await new Promise((r) => setTimeout(r, TIMEOUT)) + + const res = await fetch('http://localhost:8911/hello') + const body = await res.json() + + expect(res.status).toEqual(200) + expect(body).toEqual({ data: 'hello function' }) + }) + }) + + describe('web server CLI', () => { + const commandString = `${commandStrings['@redwoodjs/api-server']} web` + + it('--socket changes the port', async () => { + const socket = 8913 + + child = execa.command(`${commandString} --socket ${socket}`) + await new Promise((r) => setTimeout(r, TIMEOUT)) + + const res = await fetch(`http://localhost:${socket}/about`) + const body = await res.text() + + expect(res.status).toEqual(200) + expect(body).toEqual( + fs.readFileSync( + path.join(__dirname, './fixtures/redwood-app/web/dist/about.html'), + 'utf-8' + ) + ) + }) + + it('--socket wins out over --port', async () => { + const socket = 8914 + const port = 8915 + + child = execa.command( + `${commandString} --socket ${socket} --port ${port}` + ) + await new Promise((r) => setTimeout(r, TIMEOUT)) + + const res = await fetch(`http://localhost:${socket}/about`) + const body = await res.text() + + expect(res.status).toEqual(200) + expect(body).toEqual( + fs.readFileSync( + path.join(__dirname, './fixtures/redwood-app/web/dist/about.html'), + 'utf-8' + ) + ) + }) + + it("doesn't have help configured", () => { + const { stdout } = execa.commandSync(`${commandString} --help`) + + expect(stdout).toMatchInlineSnapshot(` + "Options: + --help Show help [boolean] + --version Show version number [boolean]" + `) + }) + + it("doesn't error out on unknown args", async () => { + child = execa.command(`${commandString} --foo --bar --baz`, { + stdio: 'inherit', + }) + await new Promise((r) => setTimeout(r, TIMEOUT)) + + const res = await fetch('http://localhost:8910/about') + const body = await res.text() + + expect(res.status).toEqual(200) + expect(body).toEqual( + fs.readFileSync( + path.join(__dirname, './fixtures/redwood-app/web/dist/about.html'), + 'utf-8' + ) + ) + }) + }) +}) + +describe('@redwoodjs/web-server', () => { + const commandString = commandStrings['@redwoodjs/web-server'] + + it.todo('handles --socket differently') + + // @redwoodjs/web-server doesn't have help configured in a different way than the others. + // The others output help, it's just empty. This doesn't even do that. It just runs. + it("doesn't have help configured", async () => { + child = execa.command(`${commandString} --help`) + await new Promise((r) => setTimeout(r, TIMEOUT)) + + const res = await fetch('http://localhost:8910/about') + const body = await res.text() + + expect(res.status).toEqual(200) + expect(body).toEqual( + fs.readFileSync( + path.join(__dirname, './fixtures/redwood-app/web/dist/about.html'), + 'utf-8' + ) + ) + }) +}) diff --git a/tasks/smoke-tests/rsa/playwright.config.ts b/tasks/smoke-tests/rsa/playwright.config.ts new file mode 100644 index 000000000000..f3323ded09d4 --- /dev/null +++ b/tasks/smoke-tests/rsa/playwright.config.ts @@ -0,0 +1,21 @@ +import { defineConfig } from '@playwright/test' + +import { basePlaywrightConfig } from '../basePlaywright.config' + +// See https://playwright.dev/docs/test-configuration#global-configuration +export default defineConfig({ + ...basePlaywrightConfig, + + use: { + baseURL: 'http://localhost:8910', + }, + + // Run your local dev server before starting the tests + webServer: { + command: 'yarn redwood serve', + cwd: process.env.REDWOOD_TEST_PROJECT_PATH, + url: 'http://localhost:8910', + reuseExistingServer: !process.env.CI, + stdout: 'pipe', + }, +}) diff --git a/tasks/smoke-tests/rsa/tests/rsa.spec.ts b/tasks/smoke-tests/rsa/tests/rsa.spec.ts new file mode 100644 index 000000000000..0a12cf4c3211 --- /dev/null +++ b/tasks/smoke-tests/rsa/tests/rsa.spec.ts @@ -0,0 +1,29 @@ +import { test, expect } from '@playwright/test' + +test('Submitting the form should return a response', async ({ page }) => { + await page.goto('/') + + const h3 = await page.locator('h1').innerHTML() + expect(h3).toMatch(/Hello Redwood RSAs!!/) + + const pageText = await page.locator('#redwood-app > div').innerText() + expect(pageText).toMatch('The form has been submitted 0 times.') + + await page.getByRole('textbox').fill('Hello World') + await page.getByRole('button').click() + + const submittedPageText = page.locator('#redwood-app > div') + await expect(submittedPageText).toHaveText( + /The form has been submitted 1 times./ + ) + + // Expect an echo of our message back from the server + const echo = await page.locator('p').first().innerText() + expect(echo).toMatch('Hello World') + + // Expect to get five (random) words back from the server + const words = await page.locator('p').nth(1).innerText() + expect(words.split(' ')).toHaveLength(5) + + page.close() +}) diff --git a/tasks/smoke-tests/rsc-external-packages/playwright.config.ts b/tasks/smoke-tests/rsc-external-packages/playwright.config.ts new file mode 100644 index 000000000000..f3323ded09d4 --- /dev/null +++ b/tasks/smoke-tests/rsc-external-packages/playwright.config.ts @@ -0,0 +1,21 @@ +import { defineConfig } from '@playwright/test' + +import { basePlaywrightConfig } from '../basePlaywright.config' + +// See https://playwright.dev/docs/test-configuration#global-configuration +export default defineConfig({ + ...basePlaywrightConfig, + + use: { + baseURL: 'http://localhost:8910', + }, + + // Run your local dev server before starting the tests + webServer: { + command: 'yarn redwood serve', + cwd: process.env.REDWOOD_TEST_PROJECT_PATH, + url: 'http://localhost:8910', + reuseExistingServer: !process.env.CI, + stdout: 'pipe', + }, +}) diff --git a/tasks/smoke-tests/rsc-external-packages/tests/rsc-external-packages.spec.ts b/tasks/smoke-tests/rsc-external-packages/tests/rsc-external-packages.spec.ts new file mode 100644 index 000000000000..9d1016c4f926 --- /dev/null +++ b/tasks/smoke-tests/rsc-external-packages/tests/rsc-external-packages.spec.ts @@ -0,0 +1,44 @@ +import { test, expect } from '@playwright/test' + +test('Client components should work', async ({ page }) => { + await page.goto('/') + + const h3 = await page.locator('h3').first().innerHTML() + expect(h3).toMatch(/This is a client component/) + await page.locator('p').filter({ hasText: 'Count: 0' }).first().isVisible() + + await page.locator('button').filter({ hasText: 'Increment' }).click() + + const count = await page.locator('p').first().innerText() + expect(count).toMatch('Count: 1') + + page.close() +}) + +test('Submitting the form should return a response', async ({ page }) => { + await page.goto('/') + + const h3 = await page.locator('h1').innerHTML() + expect(h3).toMatch(/Hello Redwood RSAs!!/) + + const pageText = await page.locator('#redwood-app > div').innerText() + expect(pageText).toMatch('The form has been submitted 0 times.') + + await page.getByRole('textbox').fill('Hello World') + await page.getByRole('button').getByText('Send').click() + + const submittedPageText = page.locator('#redwood-app > div') + await expect(submittedPageText).toHaveText( + /The form has been submitted 1 times./ + ) + + // Expect an echo of our message back from the server + const echo = await page.locator('p').first().innerText() + expect(echo).toMatch('Hello World') + + // Expect to get five (random) words back from the server + const words = await page.locator('p').nth(1).innerText() + expect(words.split(' ')).toHaveLength(5) + + page.close() +}) diff --git a/yarn.lock b/yarn.lock index 602a68b35811..ecd7e7d7085a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2009,8 +2009,8 @@ __metadata: linkType: hard "@babel/traverse@npm:^7.1.6, @babel/traverse@npm:^7.14.0, @babel/traverse@npm:^7.16.8, @babel/traverse@npm:^7.22.20, @babel/traverse@npm:^7.22.8, @babel/traverse@npm:^7.23.0": - version: 7.23.0 - resolution: "@babel/traverse@npm:7.23.0" + version: 7.23.2 + resolution: "@babel/traverse@npm:7.23.2" dependencies: "@babel/code-frame": ^7.22.13 "@babel/generator": ^7.23.0 @@ -2022,7 +2022,7 @@ __metadata: "@babel/types": ^7.23.0 debug: ^4.1.0 globals: ^11.1.0 - checksum: 84f93e64179965a0de6109a8b1ce92d66eb52a76e8ba325d27bdec6952cedd8fc98eabf09fe443ef667a051300dc7ed8924e7bf61a87ad456501d1da46657509 + checksum: d096c7c4bab9262a2f658298a3c630ae4a15a10755bb257ae91d5ab3e3b2877438934859c8d34018b7727379fe6b26c4fa2efc81cf4c462a7fe00caf79fa02ff languageName: node linkType: hard @@ -8399,6 +8399,7 @@ __metadata: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 "@babel/runtime-corejs3": 7.23.1 + "@iarna/toml": 2.2.5 "@opentelemetry/api": 1.4.1 "@redwoodjs/project-config": 6.0.7 "@redwoodjs/telemetry": 6.0.7 @@ -8407,6 +8408,7 @@ __metadata: "@types/yargs": 17.0.24 chalk: 4.1.2 core-js: 3.32.2 + dotenv: 16.3.1 execa: 5.1.1 jest: 29.7.0 listr2: 6.6.1 @@ -9119,7 +9121,7 @@ __metadata: typescript: 5.2.2 use-url-search-params: 2.5.1 uuid: 9.0.0 - vite: 4.4.11 + vite: 4.5.0 yargs: 17.7.2 languageName: unknown linkType: soft @@ -9228,7 +9230,7 @@ __metadata: react-server-dom-webpack: 0.0.0-experimental-e5205658f-20230913 rollup: 3.27.2 typescript: 5.2.2 - vite: 4.4.11 + vite: 4.5.0 yargs-parser: 21.1.1 bin: rw-dev-fe: ./dist/devFeServer.js @@ -35024,9 +35026,9 @@ __metadata: languageName: node linkType: hard -"vite@npm:4.4.11": - version: 4.4.11 - resolution: "vite@npm:4.4.11" +"vite@npm:4.5.0": + version: 4.5.0 + resolution: "vite@npm:4.5.0" dependencies: esbuild: ^0.18.10 fsevents: ~2.3.2 @@ -35060,7 +35062,7 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 550af0f67b600f603d0c129b74ac18dfa674d19e2b7dba28f4214d5edeba217a91fb7b8f4f47037aa0297f142d22360780a0a4533b27dbaacd2894030f61e5f4 + checksum: 7e21e9e4b80656ae5ee61e8c5edb5e8f589139c2b22c43e89d054c65a0194f1c1ef066fbc770204173c7eb244c798265042f988adda5880ad74337a053b28b7f languageName: node linkType: hard