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 41455eec9b00..42ff60c26495 100644 --- a/.github/actions/rsc_related_changes/rsc_related_changes.mjs +++ b/.github/actions/rsc_related_changes/rsc_related_changes.mjs @@ -29,6 +29,8 @@ async function main() { 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-rsc-from-fixture/README.md b/.github/actions/set-up-rsa-project/README.md similarity index 52% rename from .github/actions/set-up-rsc-from-fixture/README.md rename to .github/actions/set-up-rsa-project/README.md index 7691b892f570..0bf518131d44 100644 --- a/.github/actions/set-up-rsc-from-fixture/README.md +++ b/.github/actions/set-up-rsa-project/README.md @@ -12,17 +12,18 @@ Go into the github actions folder `cd .github/actions` Then run the following command to execute the action -`node set-up-rsc-from-fixture/setUpRscFixtureLocally.mjs` +`node set-up-rsa-project/setUpRsaProjectLocally.mjs` ## Design -The main logic of the action is in the `setUpRscFixture.mjs` file. To be able -to run that code both on GitHub and locally it uses dependency injection. The -injection is done by `setupRscFixtureLocally.mjs` for when you want to run -the action on your own machine and by `setupRscFixtureGitHib.mjs` when it's +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 -`setUpRscFixture.mjs` so that the same logic is used both locally and on -GitHub. +`../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-rsc-from-fixture/jsconfig.json b/.github/actions/set-up-rsa-project/jsconfig.json similarity index 100% rename from .github/actions/set-up-rsc-from-fixture/jsconfig.json rename to .github/actions/set-up-rsa-project/jsconfig.json diff --git a/.github/actions/set-up-rsc-from-fixture/package.json b/.github/actions/set-up-rsa-project/package.json similarity index 66% rename from .github/actions/set-up-rsc-from-fixture/package.json rename to .github/actions/set-up-rsa-project/package.json index 09285f37aa53..196dba219d44 100644 --- a/.github/actions/set-up-rsc-from-fixture/package.json +++ b/.github/actions/set-up-rsa-project/package.json @@ -1,5 +1,5 @@ { - "name": "set-up-rsc-fixture", + "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-rsc-from-fixture/setUpRscFromFixtureLocally.mjs b/.github/actions/set-up-rsa-project/setUpRsaProjectLocally.mjs similarity index 86% rename from .github/actions/set-up-rsc-from-fixture/setUpRscFromFixtureLocally.mjs rename to .github/actions/set-up-rsa-project/setUpRsaProjectLocally.mjs index 010b7e0a25ed..8e9baa044594 100644 --- a/.github/actions/set-up-rsc-from-fixture/setUpRscFromFixtureLocally.mjs +++ b/.github/actions/set-up-rsa-project/setUpRsaProjectLocally.mjs @@ -6,7 +6,7 @@ import path from 'node:path' import execa from 'execa' -import { main } from './setUpRscFromFixture.mjs' +import { setUpRscTestProject } from '../actionsLib.mjs' class ExecaError extends Error { stdout @@ -71,9 +71,12 @@ function getExecaOptions(cwd, env = {}) { } } -const rsaProjectPath = path.join( +const testProjectAndFixtureName = 'test-project-rsa' + +const testProjectPath = path.join( os.tmpdir(), - 'redwood-rsa-project', + 'redwood', + testProjectAndFixtureName, // ":" is problematic with paths new Date().toISOString().split(':').join('-') ) @@ -96,8 +99,13 @@ function execInProject(commandLine, options) { return exec( commandLine, undefined, - getExecaOptions(rsaProjectPath, options?.env) + getExecaOptions(testProjectPath, options?.env) ) } -main(rsaProjectPath, core, execInProject) +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-from-fixture/action.yaml b/.github/actions/set-up-rsc-from-fixture/action.yaml deleted file mode 100644 index f01ccfc00473..000000000000 --- a/.github/actions/set-up-rsc-from-fixture/action.yaml +++ /dev/null @@ -1,10 +0,0 @@ -name: Set up RSC test project from fixture -description: Sets up an RSC project for smoke-tests - -runs: - using: node20 - main: 'setUpRscFromFixtureGitHub.mjs' - -outputs: - test-project-path: - description: Path to the test project diff --git a/.github/actions/set-up-rsc-from-fixture/setUpRscFromFixture.mjs b/.github/actions/set-up-rsc-from-fixture/setUpRscFromFixture.mjs deleted file mode 100644 index 7a048b67118b..000000000000 --- a/.github/actions/set-up-rsc-from-fixture/setUpRscFromFixture.mjs +++ /dev/null @@ -1,130 +0,0 @@ -/* eslint-env node */ -// @ts-check - -import fs from 'node:fs' -import path from 'node:path' - -import { REDWOOD_FRAMEWORK_PATH, projectCopy, projectDeps } from '../actionsLib.mjs' - -/** - * @typedef {import('@actions/exec').ExecOptions} ExecOptions - */ - -/** - * @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} rsaProjectPath - * @param {Object} core - * @param {(key: string, value: string) => void} core.setOutput - * @param {ExecInProject} execInProject - * @returns {Promise} - */ -export async function main( - rsaProjectPath, - core, - execInProject -) { - core.setOutput('rsa-project-path', rsaProjectPath) - - console.log('rwPath', REDWOOD_FRAMEWORK_PATH) - console.log('rsaProjectPath', rsaProjectPath) - - await setUpRsaTestProject( - rsaProjectPath, - execInProject, - ) -} - -/** - * @param {string} rsaProjectPath - * @param {ExecInProject} execInProject - * @returns {Promise} - */ -async function setUpRsaTestProject(rsaProjectPath, execInProject) { - const fixturePath = path.join( - REDWOOD_FRAMEWORK_PATH, - '__fixtures__', - 'test-project-rsa' - ) - 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 ${rsaProjectPath}`) - console.log() - fs.cpSync(fixturePath, rsaProjectPath, { recursive: true }) - - console.log(`Adding framework dependencies to ${rsaProjectPath}`) - await projectDeps(rsaProjectPath) - console.log() - - console.log(`Installing node_modules in ${rsaProjectPath}`) - await execInProject('yarn install') - - console.log(`Building project in ${rsaProjectPath}`) - await execInProject(`node ${rwBinPath} build -v`) - console.log() - - console.log(`Copying over framework files to ${rsaProjectPath}`) - await execInProject(`node ${rwfwBinPath} project:copy`, { - env: { RWFW_PATH: REDWOOD_FRAMEWORK_PATH }, - }) - console.log() - - // await cache.saveCache([rsaProjectPath], dependenciesKey) - // console.log(`Cache saved with key: ${dependenciesKey}`) -} - -// async function setUpRsaFromFixture( -// rsaProjectPath, -// exec, -// execInProject, -// ) { -// 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 ${rsaProjectPath}`) -// console.log() -// await exec('npx', [ -// '-y', -// 'create-redwood-app@canary', -// '-y', -// '--no-git', -// rscProjectPath, -// ]) - -// console.log(`Setting up Streaming/SSR in ${rscProjectPath}`) -// const cmdSetupStreamingSSR = `node ${rwBinPath} experimental setup-streaming-ssr -f` -// await execInProject(cmdSetupStreamingSSR) -// console.log() - -// console.log(`Setting up RSC in ${rscProjectPath}`) -// await execInProject(`node ${rwBinPath} experimental setup-rsc`) -// console.log() - -// console.log(`Building project in ${rscProjectPath}`) -// await execInProject(`node ${rwBinPath} build -v`) -// console.log() - -// console.log(`Building project in ${rscProjectPath}`) -// await execInProject(`node ${rwfwBinPath} project:copy`, { -// env: { RWFW_PATH: REDWOOD_FRAMEWORK_PATH }, -// }) -// console.log() -// } diff --git a/.github/actions/set-up-rsc-from-fixture/setUpRscFromFixtureGitHub.mjs b/.github/actions/set-up-rsc-from-fixture/setUpRscFromFixtureGitHub.mjs deleted file mode 100644 index 167e24807fd5..000000000000 --- a/.github/actions/set-up-rsc-from-fixture/setUpRscFromFixtureGitHub.mjs +++ /dev/null @@ -1,16 +0,0 @@ -/* eslint-env node */ -// @ts-check - -import path from 'node:path' - -import core from '@actions/core' - -import { createExecWithEnvInCwd } from '../actionsLib.mjs' - -import { main } from './setUpRscFromFixture.mjs' - -const rsaProjectPath = path.join(path.dirname(process.cwd()), 'rsa-project') - -const execInProject = createExecWithEnvInCwd(rsaProjectPath) - -main(rsaProjectPath, core, execInProject) 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 fe66173ff0e6..e809bd381b3c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -532,9 +532,9 @@ jobs: REDWOOD_TEST_PROJECT_PATH: ${{ steps.set-up-rsc-project.outputs.rsc-project-path }} REDWOOD_DISABLE_TELEMETRY: 1 - - name: 🌲 Set up RSC from fixture - id: set-up-rsc-from-fixture - uses: ./.github/actions/set-up-rsc-from-fixture + - 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 @@ -543,7 +543,21 @@ jobs: working-directory: tasks/smoke-tests/rsa run: npx playwright test env: - REDWOOD_TEST_PROJECT_PATH: ${{ steps.set-up-rsc-from-fixture.outputs.rsa-project-path }} + 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: diff --git a/__fixtures__/test-project-rsa/web/src/chat.ts b/__fixtures__/test-project-rsa/web/src/chat.ts index 45602d2fd76c..b2095706ab95 100644 --- a/__fixtures__/test-project-rsa/web/src/chat.ts +++ b/__fixtures__/test-project-rsa/web/src/chat.ts @@ -3,7 +3,13 @@ import { randomWords } from './words' export async function onSend(formData: FormData) { - console.log('message', formData.get('message')) + const message = formData.get('message') + + console.log('message', message) + + if (typeof message !== 'string') { + throw new Error('message must be a string') + } // Locally you could do this: // const words = await fetch( @@ -12,5 +18,6 @@ export async function onSend(formData: FormData) { // But in CI we don't want to hit an external API, so we just do this instead: const words = await randomWords(5) - return { messages: [formData.get('message'), words.join(' ')] } + return { messages: [message, words.join(' ')] } } + diff --git a/__fixtures__/test-project-rsc-external-packages/.editorconfig b/__fixtures__/test-project-rsc-external-packages/.editorconfig new file mode 100644 index 000000000000..ae10a5cce3b2 --- /dev/null +++ b/__fixtures__/test-project-rsc-external-packages/.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-rsc-external-packages/.env.defaults b/__fixtures__/test-project-rsc-external-packages/.env.defaults new file mode 100644 index 000000000000..fb88fb33b334 --- /dev/null +++ b/__fixtures__/test-project-rsc-external-packages/.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-rsc-external-packages/.env.example b/__fixtures__/test-project-rsc-external-packages/.env.example new file mode 100644 index 000000000000..2a2de6c026ca --- /dev/null +++ b/__fixtures__/test-project-rsc-external-packages/.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-rsc-external-packages/.gitignore b/__fixtures__/test-project-rsc-external-packages/.gitignore new file mode 100644 index 000000000000..9b8149560d9b --- /dev/null +++ b/__fixtures__/test-project-rsc-external-packages/.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-rsc-external-packages/.gitpod.yml b/__fixtures__/test-project-rsc-external-packages/.gitpod.yml new file mode 100644 index 000000000000..a357a6e8c9a9 --- /dev/null +++ b/__fixtures__/test-project-rsc-external-packages/.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-rsc-external-packages/.nvmrc b/__fixtures__/test-project-rsc-external-packages/.nvmrc new file mode 100644 index 000000000000..b009dfb9d9f9 --- /dev/null +++ b/__fixtures__/test-project-rsc-external-packages/.nvmrc @@ -0,0 +1 @@ +lts/* diff --git a/__fixtures__/test-project-rsc-external-packages/.redwood/README.md b/__fixtures__/test-project-rsc-external-packages/.redwood/README.md new file mode 100644 index 000000000000..f22b586a47cc --- /dev/null +++ b/__fixtures__/test-project-rsc-external-packages/.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-rsc-external-packages/.vscode/extensions.json b/__fixtures__/test-project-rsc-external-packages/.vscode/extensions.json new file mode 100644 index 000000000000..7fc50a119fc6 --- /dev/null +++ b/__fixtures__/test-project-rsc-external-packages/.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-rsc-external-packages/.vscode/launch.json b/__fixtures__/test-project-rsc-external-packages/.vscode/launch.json new file mode 100644 index 000000000000..ea5956966fff --- /dev/null +++ b/__fixtures__/test-project-rsc-external-packages/.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-rsc-external-packages/.vscode/settings.json b/__fixtures__/test-project-rsc-external-packages/.vscode/settings.json new file mode 100644 index 000000000000..bb0578ddbbf8 --- /dev/null +++ b/__fixtures__/test-project-rsc-external-packages/.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-rsc-external-packages/.yarn/patches/vite-npm-4.4.9-e845c1bbf8.patch b/__fixtures__/test-project-rsc-external-packages/.yarn/patches/vite-npm-4.4.9-e845c1bbf8.patch new file mode 100644 index 000000000000..eb67d7906284 --- /dev/null +++ b/__fixtures__/test-project-rsc-external-packages/.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-rsc-external-packages/.yarn/releases/yarn-3.6.3.cjs b/__fixtures__/test-project-rsc-external-packages/.yarn/releases/yarn-3.6.3.cjs new file mode 100755 index 000000000000..9837c3028118 --- /dev/null +++ b/__fixtures__/test-project-rsc-external-packages/.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-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/api-server/src/plugins/withWebServer.ts b/packages/api-server/src/plugins/withWebServer.ts index f347e672c2b2..fa34797ce134 100644 --- a/packages/api-server/src/plugins/withWebServer.ts +++ b/packages/api-server/src/plugins/withWebServer.ts @@ -2,7 +2,7 @@ import fs from 'fs' import path from 'path' import fastifyStatic from '@fastify/static' -import type { FastifyInstance, FastifyReply } from 'fastify' +import type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify' import { getPaths } from '@redwoodjs/project-config' @@ -54,10 +54,21 @@ const withWebServer = async ( // For SPA routing fallback on unmatched routes // And let JS 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) + } + ) return fastify } diff --git a/packages/api/package.json b/packages/api/package.json index 062fc8b80580..a83ea83a240b 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -31,7 +31,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@prisma/client": "5.4.2", "@whatwg-node/fetch": "0.9.9", "core-js": "3.32.2", diff --git a/packages/auth-providers/auth0/api/package.json b/packages/auth-providers/auth0/api/package.json index ff0415f090ca..d90522ec0f17 100644 --- a/packages/auth-providers/auth0/api/package.json +++ b/packages/auth-providers/auth0/api/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "core-js": "3.32.2", "jsonwebtoken": "9.0.0", "jwks-rsa": "3.0.1" diff --git a/packages/auth-providers/auth0/setup/package.json b/packages/auth-providers/auth0/setup/package.json index ecd635ea5193..03852f494d48 100644 --- a/packages/auth-providers/auth0/setup/package.json +++ b/packages/auth-providers/auth0/setup/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@redwoodjs/cli-helpers": "6.0.7", "core-js": "3.32.2" }, diff --git a/packages/auth-providers/auth0/web/package.json b/packages/auth-providers/auth0/web/package.json index 0b418c877048..38784fb9c801 100644 --- a/packages/auth-providers/auth0/web/package.json +++ b/packages/auth-providers/auth0/web/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@redwoodjs/auth": "6.0.7", "core-js": "3.32.2" }, diff --git a/packages/auth-providers/azureActiveDirectory/api/package.json b/packages/auth-providers/azureActiveDirectory/api/package.json index a1f3bd4a44c4..f31dabfd7774 100644 --- a/packages/auth-providers/azureActiveDirectory/api/package.json +++ b/packages/auth-providers/azureActiveDirectory/api/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "core-js": "3.32.2", "jsonwebtoken": "9.0.0", "jwks-rsa": "3.0.1" diff --git a/packages/auth-providers/azureActiveDirectory/setup/package.json b/packages/auth-providers/azureActiveDirectory/setup/package.json index 371e9bd88a5f..778abb8b2fbf 100644 --- a/packages/auth-providers/azureActiveDirectory/setup/package.json +++ b/packages/auth-providers/azureActiveDirectory/setup/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@redwoodjs/cli-helpers": "6.0.7", "core-js": "3.32.2" }, diff --git a/packages/auth-providers/azureActiveDirectory/web/package.json b/packages/auth-providers/azureActiveDirectory/web/package.json index cea8b27ff002..ac088253a4c5 100644 --- a/packages/auth-providers/azureActiveDirectory/web/package.json +++ b/packages/auth-providers/azureActiveDirectory/web/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@redwoodjs/auth": "6.0.7", "core-js": "3.32.2" }, diff --git a/packages/auth-providers/clerk/api/package.json b/packages/auth-providers/clerk/api/package.json index f016867083d3..2ea43a496116 100644 --- a/packages/auth-providers/clerk/api/package.json +++ b/packages/auth-providers/clerk/api/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@clerk/clerk-sdk-node": "4.12.6", "core-js": "3.32.2" }, diff --git a/packages/auth-providers/clerk/setup/package.json b/packages/auth-providers/clerk/setup/package.json index 6bb396ae1dec..f6e58e2d705a 100644 --- a/packages/auth-providers/clerk/setup/package.json +++ b/packages/auth-providers/clerk/setup/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@redwoodjs/cli-helpers": "6.0.7", "core-js": "3.32.2" }, diff --git a/packages/auth-providers/clerk/web/package.json b/packages/auth-providers/clerk/web/package.json index 84b7b7fe511e..61d42d2c5465 100644 --- a/packages/auth-providers/clerk/web/package.json +++ b/packages/auth-providers/clerk/web/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@redwoodjs/auth": "6.0.7", "core-js": "3.32.2" }, diff --git a/packages/auth-providers/custom/setup/package.json b/packages/auth-providers/custom/setup/package.json index 9d4cc2a60140..485364ad9162 100644 --- a/packages/auth-providers/custom/setup/package.json +++ b/packages/auth-providers/custom/setup/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@redwoodjs/cli-helpers": "6.0.7", "core-js": "3.32.2" }, diff --git a/packages/auth-providers/dbAuth/api/package.json b/packages/auth-providers/dbAuth/api/package.json index b6e4006c5616..0e0033b5a22d 100644 --- a/packages/auth-providers/dbAuth/api/package.json +++ b/packages/auth-providers/dbAuth/api/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@redwoodjs/project-config": "6.0.7", "base64url": "3.0.1", "core-js": "3.32.2", diff --git a/packages/auth-providers/dbAuth/setup/package.json b/packages/auth-providers/dbAuth/setup/package.json index 0ca9421c4646..980069bb5957 100644 --- a/packages/auth-providers/dbAuth/setup/package.json +++ b/packages/auth-providers/dbAuth/setup/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@redwoodjs/cli-helpers": "6.0.7", "@simplewebauthn/browser": "7.2.0", "core-js": "3.32.2", diff --git a/packages/auth-providers/dbAuth/web/package.json b/packages/auth-providers/dbAuth/web/package.json index 134003b73888..a0a30c413800 100644 --- a/packages/auth-providers/dbAuth/web/package.json +++ b/packages/auth-providers/dbAuth/web/package.json @@ -23,7 +23,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@redwoodjs/auth": "6.0.7", "@simplewebauthn/browser": "7.2.0", "core-js": "3.32.2" diff --git a/packages/auth-providers/firebase/api/package.json b/packages/auth-providers/firebase/api/package.json index 11b4f57cb6ec..d2183a08e733 100644 --- a/packages/auth-providers/firebase/api/package.json +++ b/packages/auth-providers/firebase/api/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "core-js": "3.32.2", "firebase-admin": "11.10.1" }, diff --git a/packages/auth-providers/firebase/setup/package.json b/packages/auth-providers/firebase/setup/package.json index 193952db07a4..6bb7b56b3f38 100644 --- a/packages/auth-providers/firebase/setup/package.json +++ b/packages/auth-providers/firebase/setup/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@redwoodjs/cli-helpers": "6.0.7", "core-js": "3.32.2" }, diff --git a/packages/auth-providers/firebase/web/package.json b/packages/auth-providers/firebase/web/package.json index 46a1c2842220..69f0f00257e2 100644 --- a/packages/auth-providers/firebase/web/package.json +++ b/packages/auth-providers/firebase/web/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@redwoodjs/auth": "6.0.7", "core-js": "3.32.2" }, diff --git a/packages/auth-providers/netlify/api/package.json b/packages/auth-providers/netlify/api/package.json index 85c2d8baa5e4..c5e062cf4e42 100644 --- a/packages/auth-providers/netlify/api/package.json +++ b/packages/auth-providers/netlify/api/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "core-js": "3.32.2", "jsonwebtoken": "9.0.0" }, diff --git a/packages/auth-providers/netlify/setup/package.json b/packages/auth-providers/netlify/setup/package.json index ae4a336a1b7a..18637cfae482 100644 --- a/packages/auth-providers/netlify/setup/package.json +++ b/packages/auth-providers/netlify/setup/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@redwoodjs/cli-helpers": "6.0.7", "core-js": "3.32.2" }, diff --git a/packages/auth-providers/netlify/web/package.json b/packages/auth-providers/netlify/web/package.json index ce869ba54f13..9e75eb93c319 100644 --- a/packages/auth-providers/netlify/web/package.json +++ b/packages/auth-providers/netlify/web/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@redwoodjs/auth": "6.0.7", "core-js": "3.32.2" }, diff --git a/packages/auth-providers/supabase/api/package.json b/packages/auth-providers/supabase/api/package.json index 09b1aaf764b3..ba7dd5226698 100644 --- a/packages/auth-providers/supabase/api/package.json +++ b/packages/auth-providers/supabase/api/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "core-js": "3.32.2", "jsonwebtoken": "9.0.0" }, diff --git a/packages/auth-providers/supabase/setup/package.json b/packages/auth-providers/supabase/setup/package.json index 27c615bdcd3b..63ea03ae182b 100644 --- a/packages/auth-providers/supabase/setup/package.json +++ b/packages/auth-providers/supabase/setup/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@redwoodjs/cli-helpers": "6.0.7", "core-js": "3.32.2" }, diff --git a/packages/auth-providers/supabase/web/package.json b/packages/auth-providers/supabase/web/package.json index 8ce8aeef5dc5..3fce1a0bc8e5 100644 --- a/packages/auth-providers/supabase/web/package.json +++ b/packages/auth-providers/supabase/web/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "core-js": "3.32.2" }, "devDependencies": { diff --git a/packages/auth-providers/supertokens/api/package.json b/packages/auth-providers/supertokens/api/package.json index 47567cef438b..d553f4c4ac64 100644 --- a/packages/auth-providers/supertokens/api/package.json +++ b/packages/auth-providers/supertokens/api/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "core-js": "3.32.2", "jsonwebtoken": "9.0.0", "jwks-rsa": "3.0.1" diff --git a/packages/auth-providers/supertokens/setup/package.json b/packages/auth-providers/supertokens/setup/package.json index 3aaed6a29d7d..b15d23b20e4b 100644 --- a/packages/auth-providers/supertokens/setup/package.json +++ b/packages/auth-providers/supertokens/setup/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@redwoodjs/cli-helpers": "6.0.7", "core-js": "3.32.2" }, diff --git a/packages/auth-providers/supertokens/web/package.json b/packages/auth-providers/supertokens/web/package.json index 69d5915ef26f..f441c1c347bf 100644 --- a/packages/auth-providers/supertokens/web/package.json +++ b/packages/auth-providers/supertokens/web/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@redwoodjs/auth": "6.0.7", "core-js": "3.32.2" }, diff --git a/packages/auth/package.json b/packages/auth/package.json index e0fa2916f7cb..1b326a17c8c3 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "core-js": "3.32.2", "react": "0.0.0-experimental-e5205658f-20230913" }, diff --git a/packages/babel-config/package.json b/packages/babel-config/package.json index 95a0628d62a8..206d725adf8c 100644 --- a/packages/babel-config/package.json +++ b/packages/babel-config/package.json @@ -27,12 +27,12 @@ "@babel/plugin-transform-private-methods": "^7.22.5", "@babel/plugin-transform-private-property-in-object": "^7.22.11", "@babel/plugin-transform-react-jsx": "^7.22.15", - "@babel/plugin-transform-runtime": "7.22.15", + "@babel/plugin-transform-runtime": "7.23.2", "@babel/preset-env": "^7.22.20", "@babel/preset-react": "^7.22.15", "@babel/preset-typescript": "^7.22.15", "@babel/register": "^7.22.15", - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@babel/traverse": "^7.22.20", "@redwoodjs/project-config": "6.0.7", "babel-plugin-auto-import": "1.1.0", diff --git a/packages/babel-config/src/__tests__/api.test.ts b/packages/babel-config/src/__tests__/api.test.ts index d89811c185cb..5305f2411eac 100644 --- a/packages/babel-config/src/__tests__/api.test.ts +++ b/packages/babel-config/src/__tests__/api.test.ts @@ -174,7 +174,7 @@ describe('api', () => { proposals: true, version: 3, }, - version: '7.23.1', + version: '7.23.2', }, ]) diff --git a/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/directive-skipAuth/code.js b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/directive-skipAuth/code.js new file mode 100644 index 000000000000..e85b94ae8b89 --- /dev/null +++ b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/directive-skipAuth/code.js @@ -0,0 +1,16 @@ +import gql from 'graphql-tag' + +import { createValidatorDirective } from '@redwoodjs/graphql-server' + +export const schema = gql` + """ + Use to skip authentication checks and allow public access. + """ + directive @skipAuth on FIELD_DEFINITION +` + +const skipAuth = createValidatorDirective(schema, () => { + return +}) + +export default skipAuth diff --git a/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/directive-skipAuth/output.js b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/directive-skipAuth/output.js new file mode 100644 index 000000000000..40d4c728bfbd --- /dev/null +++ b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/directive-skipAuth/output.js @@ -0,0 +1,13 @@ +import { trace as RW_OTEL_WRAPPER_TRACE } from '@opentelemetry/api' +import gql from 'graphql-tag' +import { createValidatorDirective } from '@redwoodjs/graphql-server' +export const schema = gql` + """ + Use to skip authentication checks and allow public access. + """ + directive @skipAuth on FIELD_DEFINITION +` +const skipAuth = createValidatorDirective(schema, () => { + return +}) +export default skipAuth \ No newline at end of file diff --git a/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/function-auth/code.js b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/function-auth/code.js new file mode 100644 index 000000000000..b3494cb4d877 --- /dev/null +++ b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/function-auth/code.js @@ -0,0 +1,102 @@ +import { DbAuthHandler, DbAuthHandlerOptions } from '@redwoodjs/auth-dbauth-api' + +import { db } from 'src/lib/db' + +export const handler = async ( + event, + context +) => { + const forgotPasswordOptions = { + handler: (user) => { + return user + }, + + expires: 60 * 60 * 24, + + errors: { + usernameNotFound: 'Username not found', + usernameRequired: 'Username is required', + }, + } + + const loginOptions = { + handler: (user) => { + return user + }, + + errors: { + usernameOrPasswordMissing: 'Both username and password are required', + usernameNotFound: 'Username ${username} not found', + incorrectPassword: 'Incorrect password for ${username}', + }, + + expires: 60 * 60 * 24 * 365 * 10, + } + + const resetPasswordOptions = { + handler: (_user) => { + return true + }, + + allowReusedPassword: true, + + errors: { + resetTokenExpired: 'resetToken is expired', + resetTokenInvalid: 'resetToken is invalid', + resetTokenRequired: 'resetToken is required', + reusedPassword: 'Must choose a new password', + }, + } + + const signupOptions = { + handler: ({ username, hashedPassword, salt, userAttributes }) => { + return db.user.create({ + data: { + email: username, + hashedPassword: hashedPassword, + salt: salt, + fullName: userAttributes['full-name'], + }, + }) + }, + + passwordValidation: (_password) => { + return true + }, + + errors: { + fieldMissing: '${field} is required', + usernameTaken: 'Username `${username}` already in use', + }, + } + + const authHandler = new DbAuthHandler(event, context, { + db: db, + + authModelAccessor: 'user', + + authFields: { + id: 'id', + username: 'email', + hashedPassword: 'hashedPassword', + salt: 'salt', + resetToken: 'resetToken', + resetTokenExpiresAt: 'resetTokenExpiresAt', + }, + + cookie: { + HttpOnly: true, + Path: '/', + SameSite: 'Strict', + Secure: process.env.NODE_ENV !== 'development', + + }, + + forgotPassword: forgotPasswordOptions, + login: loginOptions, + resetPassword: resetPasswordOptions, + signup: signupOptions, + }) + + return await authHandler.invoke() +} diff --git a/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/function-auth/output.js b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/function-auth/output.js new file mode 100644 index 000000000000..c2e265b1563b --- /dev/null +++ b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/function-auth/output.js @@ -0,0 +1,105 @@ +import { trace as RW_OTEL_WRAPPER_TRACE } from '@opentelemetry/api' +import { DbAuthHandler, DbAuthHandlerOptions } from '@redwoodjs/auth-dbauth-api' +import { db } from 'src/lib/db' +export const handler = async (event, context) => { + const __handler = async (event, context) => { + const forgotPasswordOptions = { + handler: (user) => { + return user + }, + expires: 60 * 60 * 24, + errors: { + usernameNotFound: 'Username not found', + usernameRequired: 'Username is required', + }, + } + const loginOptions = { + handler: (user) => { + return user + }, + errors: { + usernameOrPasswordMissing: 'Both username and password are required', + usernameNotFound: 'Username ${username} not found', + incorrectPassword: 'Incorrect password for ${username}', + }, + expires: 60 * 60 * 24 * 365 * 10, + } + const resetPasswordOptions = { + handler: (_user) => { + return true + }, + allowReusedPassword: true, + errors: { + resetTokenExpired: 'resetToken is expired', + resetTokenInvalid: 'resetToken is invalid', + resetTokenRequired: 'resetToken is required', + reusedPassword: 'Must choose a new password', + }, + } + const signupOptions = { + handler: ({ username, hashedPassword, salt, userAttributes }) => { + return db.user.create({ + data: { + email: username, + hashedPassword: hashedPassword, + salt: salt, + fullName: userAttributes['full-name'], + }, + }) + }, + passwordValidation: (_password) => { + return true + }, + errors: { + fieldMissing: '${field} is required', + usernameTaken: 'Username `${username}` already in use', + }, + } + const authHandler = new DbAuthHandler(event, context, { + db: db, + authModelAccessor: 'user', + authFields: { + id: 'id', + username: 'email', + hashedPassword: 'hashedPassword', + salt: 'salt', + resetToken: 'resetToken', + resetTokenExpiresAt: 'resetTokenExpiresAt', + }, + cookie: { + HttpOnly: true, + Path: '/', + SameSite: 'Strict', + Secure: process.env.NODE_ENV !== 'development', + }, + forgotPassword: forgotPasswordOptions, + login: loginOptions, + resetPassword: resetPasswordOptions, + signup: signupOptions, + }) + return await authHandler.invoke() + } + const RW_OTEL_WRAPPER_TRACER = RW_OTEL_WRAPPER_TRACE.getTracer('redwoodjs') + const RW_OTEL_WRAPPER_RESULT = await RW_OTEL_WRAPPER_TRACER.startActiveSpan( + 'redwoodjs:api:__MOCKED_API_FOLDER__:handler', + async (span) => { + span.setAttribute('code.function', 'handler') + span.setAttribute('code.filepath', '__MOCKED_FILENAME__') + try { + const RW_OTEL_WRAPPER_INNER_RESULT = await __handler(event, context) + span.end() + return RW_OTEL_WRAPPER_INNER_RESULT + } catch (error) { + span.recordException(error) + span.setStatus({ + code: 2, + message: + error?.message?.split('\n')[0] ?? error?.toString()?.split('\n')[0], + }) + span.end() + throw error + } + } + ) + return RW_OTEL_WRAPPER_RESULT +} \ No newline at end of file diff --git a/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/function-graphql/code.js b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/function-graphql/code.js new file mode 100644 index 000000000000..5d8db6ab8f2a --- /dev/null +++ b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/function-graphql/code.js @@ -0,0 +1,23 @@ +import { authDecoder } from '@redwoodjs/auth-dbauth-api' +import { createGraphQLHandler } from '@redwoodjs/graphql-server' + +import directives from 'src/directives/**/*.{js,ts}' +import sdls from 'src/graphql/**/*.sdl.{js,ts}' +import services from 'src/services/**/*.{js,ts}' + +import { getCurrentUser } from 'src/lib/auth' +import { db } from 'src/lib/db' +import { logger } from 'src/lib/logger' + +export const handler = createGraphQLHandler({ + authDecoder, + getCurrentUser, + loggerConfig: { logger, options: {} }, + directives, + sdls, + services, + onException: () => { + // Disconnect from your database with an unhandled exception. + db.$disconnect() + }, +}) diff --git a/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/function-graphql/output.js b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/function-graphql/output.js new file mode 100644 index 000000000000..873ed281570b --- /dev/null +++ b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/function-graphql/output.js @@ -0,0 +1,24 @@ +import { trace as RW_OTEL_WRAPPER_TRACE } from '@opentelemetry/api' +import { authDecoder } from '@redwoodjs/auth-dbauth-api' +import { createGraphQLHandler } from '@redwoodjs/graphql-server' +import directives from 'src/directives/**/*.{js,ts}' +import sdls from 'src/graphql/**/*.sdl.{js,ts}' +import services from 'src/services/**/*.{js,ts}' +import { getCurrentUser } from 'src/lib/auth' +import { db } from 'src/lib/db' +import { logger } from 'src/lib/logger' +export const handler = createGraphQLHandler({ + authDecoder, + getCurrentUser, + loggerConfig: { + logger, + options: {}, + }, + directives, + sdls, + services, + onException: () => { + // Disconnect from your database with an unhandled exception. + db.$disconnect() + }, +}) \ No newline at end of file diff --git a/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/lib-auth/code.js b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/lib-auth/code.js new file mode 100644 index 000000000000..a268c008e449 --- /dev/null +++ b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/lib-auth/code.js @@ -0,0 +1,61 @@ +import { AuthenticationError, ForbiddenError } from '@redwoodjs/graphql-server' + +import { db } from './db' + +export const getCurrentUser = async (session) => { + if (!session || typeof session.id !== 'number') { + throw new Error('Invalid session') + } + + return await db.user.findUnique({ + where: { id: session.id }, + select: { id: true, roles: true, email: true }, + }) +} + +export const isAuthenticated = () => { + return !!context.currentUser +} + +export const hasRole = (roles) => { + if (!isAuthenticated()) { + return false + } + + const currentUserRoles = context.currentUser?.roles + + if (typeof roles === 'string') { + if (typeof currentUserRoles === 'string') { + // roles to check is a string, currentUser.roles is a string + return currentUserRoles === roles + } else if (Array.isArray(currentUserRoles)) { + // roles to check is a string, currentUser.roles is an array + return currentUserRoles?.some((allowedRole) => roles === allowedRole) + } + } + + if (Array.isArray(roles)) { + if (Array.isArray(currentUserRoles)) { + // roles to check is an array, currentUser.roles is an array + return currentUserRoles?.some((allowedRole) => + roles.includes(allowedRole) + ) + } else if (typeof currentUserRoles === 'string') { + // roles to check is an array, currentUser.roles is a string + return roles.some((allowedRole) => currentUserRoles === allowedRole) + } + } + + // roles not found + return false +} + +export const requireAuth = ({ roles } = {}) => { + if (!isAuthenticated()) { + throw new AuthenticationError("You don't have permission to do that.") + } + + if (roles && !hasRole(roles)) { + throw new ForbiddenError("You don't have access to do that.") + } +} diff --git a/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/lib-auth/output.js b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/lib-auth/output.js new file mode 100644 index 000000000000..893341755924 --- /dev/null +++ b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/lib-auth/output.js @@ -0,0 +1,160 @@ +import { trace as RW_OTEL_WRAPPER_TRACE } from '@opentelemetry/api' +import { AuthenticationError, ForbiddenError } from '@redwoodjs/graphql-server' +import { db } from './db' +export const getCurrentUser = async (session) => { + const __getCurrentUser = async (session) => { + if (!session || typeof session.id !== 'number') { + throw new Error('Invalid session') + } + return await db.user.findUnique({ + where: { + id: session.id, + }, + select: { + id: true, + roles: true, + email: true, + }, + }) + } + const RW_OTEL_WRAPPER_TRACER = RW_OTEL_WRAPPER_TRACE.getTracer('redwoodjs') + const RW_OTEL_WRAPPER_RESULT = await RW_OTEL_WRAPPER_TRACER.startActiveSpan( + 'redwoodjs:api:__MOCKED_API_FOLDER__:getCurrentUser', + async (span) => { + span.setAttribute('code.function', 'getCurrentUser') + span.setAttribute('code.filepath', '__MOCKED_FILENAME__') + try { + const RW_OTEL_WRAPPER_INNER_RESULT = await __getCurrentUser(session) + span.end() + return RW_OTEL_WRAPPER_INNER_RESULT + } catch (error) { + span.recordException(error) + span.setStatus({ + code: 2, + message: + error?.message?.split('\n')[0] ?? error?.toString()?.split('\n')[0], + }) + span.end() + throw error + } + } + ) + return RW_OTEL_WRAPPER_RESULT +} +export const isAuthenticated = () => { + const __isAuthenticated = () => { + return !!context.currentUser + } + const RW_OTEL_WRAPPER_TRACER = RW_OTEL_WRAPPER_TRACE.getTracer('redwoodjs') + const RW_OTEL_WRAPPER_RESULT = RW_OTEL_WRAPPER_TRACER.startActiveSpan( + 'redwoodjs:api:__MOCKED_API_FOLDER__:isAuthenticated', + (span) => { + span.setAttribute('code.function', 'isAuthenticated') + span.setAttribute('code.filepath', '__MOCKED_FILENAME__') + try { + const RW_OTEL_WRAPPER_INNER_RESULT = __isAuthenticated() + span.end() + return RW_OTEL_WRAPPER_INNER_RESULT + } catch (error) { + span.recordException(error) + span.setStatus({ + code: 2, + message: + error?.message?.split('\n')[0] ?? error?.toString()?.split('\n')[0], + }) + span.end() + throw error + } + } + ) + return RW_OTEL_WRAPPER_RESULT +} +export const hasRole = (roles) => { + const __hasRole = (roles) => { + if (!isAuthenticated()) { + return false + } + const currentUserRoles = context.currentUser?.roles + if (typeof roles === 'string') { + if (typeof currentUserRoles === 'string') { + // roles to check is a string, currentUser.roles is a string + return currentUserRoles === roles + } else if (Array.isArray(currentUserRoles)) { + // roles to check is a string, currentUser.roles is an array + return currentUserRoles?.some((allowedRole) => roles === allowedRole) + } + } + if (Array.isArray(roles)) { + if (Array.isArray(currentUserRoles)) { + // roles to check is an array, currentUser.roles is an array + return currentUserRoles?.some((allowedRole) => + roles.includes(allowedRole) + ) + } else if (typeof currentUserRoles === 'string') { + // roles to check is an array, currentUser.roles is a string + return roles.some((allowedRole) => currentUserRoles === allowedRole) + } + } + + // roles not found + return false + } + const RW_OTEL_WRAPPER_TRACER = RW_OTEL_WRAPPER_TRACE.getTracer('redwoodjs') + const RW_OTEL_WRAPPER_RESULT = RW_OTEL_WRAPPER_TRACER.startActiveSpan( + 'redwoodjs:api:__MOCKED_API_FOLDER__:hasRole', + (span) => { + span.setAttribute('code.function', 'hasRole') + span.setAttribute('code.filepath', '__MOCKED_FILENAME__') + try { + const RW_OTEL_WRAPPER_INNER_RESULT = __hasRole(roles) + span.end() + return RW_OTEL_WRAPPER_INNER_RESULT + } catch (error) { + span.recordException(error) + span.setStatus({ + code: 2, + message: + error?.message?.split('\n')[0] ?? error?.toString()?.split('\n')[0], + }) + span.end() + throw error + } + } + ) + return RW_OTEL_WRAPPER_RESULT +} +export const requireAuth = ({ roles } = {}) => { + const __requireAuth = ({ roles } = {}) => { + if (!isAuthenticated()) { + throw new AuthenticationError("You don't have permission to do that.") + } + if (roles && !hasRole(roles)) { + throw new ForbiddenError("You don't have access to do that.") + } + } + const RW_OTEL_WRAPPER_TRACER = RW_OTEL_WRAPPER_TRACE.getTracer('redwoodjs') + const RW_OTEL_WRAPPER_RESULT = RW_OTEL_WRAPPER_TRACER.startActiveSpan( + 'redwoodjs:api:__MOCKED_API_FOLDER__:requireAuth', + (span) => { + span.setAttribute('code.function', 'requireAuth') + span.setAttribute('code.filepath', '__MOCKED_FILENAME__') + try { + const RW_OTEL_WRAPPER_INNER_RESULT = __requireAuth({ + roles, + }) + span.end() + return RW_OTEL_WRAPPER_INNER_RESULT + } catch (error) { + span.recordException(error) + span.setStatus({ + code: 2, + message: + error?.message?.split('\n')[0] ?? error?.toString()?.split('\n')[0], + }) + span.end() + throw error + } + } + ) + return RW_OTEL_WRAPPER_RESULT +} \ No newline at end of file diff --git a/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/lib-db/code.js b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/lib-db/code.js new file mode 100644 index 000000000000..63a4c976ab1c --- /dev/null +++ b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/lib-db/code.js @@ -0,0 +1,18 @@ +import { PrismaClient } from '@prisma/client' + +import { emitLogLevels, handlePrismaLogging } from '@redwoodjs/api/logger' + +import { logger } from './logger' + +/* + * Instance of the Prisma Client + */ +export const db = new PrismaClient({ + log: emitLogLevels(['info', 'warn', 'error']), +}) + +handlePrismaLogging({ + db, + logger, + logLevels: ['info', 'warn', 'error'], +}) diff --git a/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/lib-db/output.js b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/lib-db/output.js new file mode 100644 index 000000000000..e70d8a743d2e --- /dev/null +++ b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/lib-db/output.js @@ -0,0 +1,16 @@ +import { trace as RW_OTEL_WRAPPER_TRACE } from '@opentelemetry/api' +import { PrismaClient } from '@prisma/client' +import { emitLogLevels, handlePrismaLogging } from '@redwoodjs/api/logger' +import { logger } from './logger' + +/* + * Instance of the Prisma Client + */ +export const db = new PrismaClient({ + log: emitLogLevels(['info', 'warn', 'error']), +}) +handlePrismaLogging({ + db, + logger, + logLevels: ['info', 'warn', 'error'], +}) \ No newline at end of file diff --git a/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/service-basic/code.js b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/service-basic/code.js new file mode 100644 index 000000000000..6bdecbe8123b --- /dev/null +++ b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/service-basic/code.js @@ -0,0 +1,35 @@ +import { db } from 'src/lib/db' + +export const contacts = () => { + return db.contact.findMany() +} + +export const contact = ({ id }) => { + return db.contact.findUnique({ + where: { id }, + }) +} + +export const createContact = ({ + input, +}) => { + return db.contact.create({ + data: input, + }) +} + +export const updateContact = ({ + id, + input, +}) => { + return db.contact.update({ + data: input, + where: { id }, + }) +} + +export const deleteContact = ({ id }) => { + return db.contact.delete({ + where: { id }, + }) +} diff --git a/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/service-basic/output.js b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/service-basic/output.js new file mode 100644 index 000000000000..bede484d4d4b --- /dev/null +++ b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/service-basic/output.js @@ -0,0 +1,166 @@ +import { trace as RW_OTEL_WRAPPER_TRACE } from '@opentelemetry/api' +import { db } from 'src/lib/db' +export const contacts = () => { + const __contacts = () => { + return db.contact.findMany() + } + const RW_OTEL_WRAPPER_TRACER = RW_OTEL_WRAPPER_TRACE.getTracer('redwoodjs') + const RW_OTEL_WRAPPER_RESULT = RW_OTEL_WRAPPER_TRACER.startActiveSpan( + 'redwoodjs:api:__MOCKED_API_FOLDER__:contacts', + (span) => { + span.setAttribute('code.function', 'contacts') + span.setAttribute('code.filepath', '__MOCKED_FILENAME__') + try { + const RW_OTEL_WRAPPER_INNER_RESULT = __contacts() + span.end() + return RW_OTEL_WRAPPER_INNER_RESULT + } catch (error) { + span.recordException(error) + span.setStatus({ + code: 2, + message: + error?.message?.split('\n')[0] ?? error?.toString()?.split('\n')[0], + }) + span.end() + throw error + } + } + ) + return RW_OTEL_WRAPPER_RESULT +} +export const contact = ({ id }) => { + const __contact = ({ id }) => { + return db.contact.findUnique({ + where: { + id, + }, + }) + } + const RW_OTEL_WRAPPER_TRACER = RW_OTEL_WRAPPER_TRACE.getTracer('redwoodjs') + const RW_OTEL_WRAPPER_RESULT = RW_OTEL_WRAPPER_TRACER.startActiveSpan( + 'redwoodjs:api:__MOCKED_API_FOLDER__:contact', + (span) => { + span.setAttribute('code.function', 'contact') + span.setAttribute('code.filepath', '__MOCKED_FILENAME__') + try { + const RW_OTEL_WRAPPER_INNER_RESULT = __contact({ + id, + }) + span.end() + return RW_OTEL_WRAPPER_INNER_RESULT + } catch (error) { + span.recordException(error) + span.setStatus({ + code: 2, + message: + error?.message?.split('\n')[0] ?? error?.toString()?.split('\n')[0], + }) + span.end() + throw error + } + } + ) + return RW_OTEL_WRAPPER_RESULT +} +export const createContact = ({ input }) => { + const __createContact = ({ input }) => { + return db.contact.create({ + data: input, + }) + } + const RW_OTEL_WRAPPER_TRACER = RW_OTEL_WRAPPER_TRACE.getTracer('redwoodjs') + const RW_OTEL_WRAPPER_RESULT = RW_OTEL_WRAPPER_TRACER.startActiveSpan( + 'redwoodjs:api:__MOCKED_API_FOLDER__:createContact', + (span) => { + span.setAttribute('code.function', 'createContact') + span.setAttribute('code.filepath', '__MOCKED_FILENAME__') + try { + const RW_OTEL_WRAPPER_INNER_RESULT = __createContact({ + input, + }) + span.end() + return RW_OTEL_WRAPPER_INNER_RESULT + } catch (error) { + span.recordException(error) + span.setStatus({ + code: 2, + message: + error?.message?.split('\n')[0] ?? error?.toString()?.split('\n')[0], + }) + span.end() + throw error + } + } + ) + return RW_OTEL_WRAPPER_RESULT +} +export const updateContact = ({ id, input }) => { + const __updateContact = ({ id, input }) => { + return db.contact.update({ + data: input, + where: { + id, + }, + }) + } + const RW_OTEL_WRAPPER_TRACER = RW_OTEL_WRAPPER_TRACE.getTracer('redwoodjs') + const RW_OTEL_WRAPPER_RESULT = RW_OTEL_WRAPPER_TRACER.startActiveSpan( + 'redwoodjs:api:__MOCKED_API_FOLDER__:updateContact', + (span) => { + span.setAttribute('code.function', 'updateContact') + span.setAttribute('code.filepath', '__MOCKED_FILENAME__') + try { + const RW_OTEL_WRAPPER_INNER_RESULT = __updateContact({ + id, + input, + }) + span.end() + return RW_OTEL_WRAPPER_INNER_RESULT + } catch (error) { + span.recordException(error) + span.setStatus({ + code: 2, + message: + error?.message?.split('\n')[0] ?? error?.toString()?.split('\n')[0], + }) + span.end() + throw error + } + } + ) + return RW_OTEL_WRAPPER_RESULT +} +export const deleteContact = ({ id }) => { + const __deleteContact = ({ id }) => { + return db.contact.delete({ + where: { + id, + }, + }) + } + const RW_OTEL_WRAPPER_TRACER = RW_OTEL_WRAPPER_TRACE.getTracer('redwoodjs') + const RW_OTEL_WRAPPER_RESULT = RW_OTEL_WRAPPER_TRACER.startActiveSpan( + 'redwoodjs:api:__MOCKED_API_FOLDER__:deleteContact', + (span) => { + span.setAttribute('code.function', 'deleteContact') + span.setAttribute('code.filepath', '__MOCKED_FILENAME__') + try { + const RW_OTEL_WRAPPER_INNER_RESULT = __deleteContact({ + id, + }) + span.end() + return RW_OTEL_WRAPPER_INNER_RESULT + } catch (error) { + span.recordException(error) + span.setStatus({ + code: 2, + message: + error?.message?.split('\n')[0] ?? error?.toString()?.split('\n')[0], + }) + span.end() + throw error + } + } + ) + return RW_OTEL_WRAPPER_RESULT +} \ No newline at end of file diff --git a/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/service-custom/code.js b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/service-custom/code.js new file mode 100644 index 000000000000..5d01ea5c350f --- /dev/null +++ b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/service-custom/code.js @@ -0,0 +1,25 @@ +// This example function has default values in the function signature +export const withDefaultValues = async ({ + id, + process = true, + output = [], + backup = () => ('backup'), +}) => { + if (process) { + output.push(backup()) + } + return `${id}: ${output.join('\t')}` +} + +// This example function has a different default value definition in the function signature +export const withDefaultValuesTwo = async (args = { + id, + process: true, + output: [], + backup: () => ('backup'), +}) => { + if (args.process) { + args.output.push(args.backup()) + } + return `${args.id}: ${args.output.join('\t')}` +} diff --git a/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/service-custom/output.js b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/service-custom/output.js new file mode 100644 index 000000000000..fdf834704bb9 --- /dev/null +++ b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/service-custom/output.js @@ -0,0 +1,95 @@ +import { trace as RW_OTEL_WRAPPER_TRACE } from '@opentelemetry/api' +// This example function has default values in the function signature +export const withDefaultValues = async ({ + id, + process = true, + output = [], + backup = () => 'backup', +}) => { + const __withDefaultValues = async ({ + id, + process = true, + output = [], + backup = () => 'backup', + }) => { + if (process) { + output.push(backup()) + } + return `${id}: ${output.join('\t')}` + } + const RW_OTEL_WRAPPER_TRACER = RW_OTEL_WRAPPER_TRACE.getTracer('redwoodjs') + const RW_OTEL_WRAPPER_RESULT = await RW_OTEL_WRAPPER_TRACER.startActiveSpan( + 'redwoodjs:api:__MOCKED_API_FOLDER__:withDefaultValues', + async (span) => { + span.setAttribute('code.function', 'withDefaultValues') + span.setAttribute('code.filepath', '__MOCKED_FILENAME__') + try { + const RW_OTEL_WRAPPER_INNER_RESULT = await __withDefaultValues({ + id, + process: process, + output: output, + backup: backup, + }) + span.end() + return RW_OTEL_WRAPPER_INNER_RESULT + } catch (error) { + span.recordException(error) + span.setStatus({ + code: 2, + message: + error?.message?.split('\n')[0] ?? error?.toString()?.split('\n')[0], + }) + span.end() + throw error + } + } + ) + return RW_OTEL_WRAPPER_RESULT +} + +// This example function has a different default value definition in the function signature +export const withDefaultValuesTwo = async ( + args = { + id, + process: true, + output: [], + backup: () => 'backup', + } +) => { + const __withDefaultValuesTwo = async ( + args = { + id, + process: true, + output: [], + backup: () => 'backup', + } + ) => { + if (args.process) { + args.output.push(args.backup()) + } + return `${args.id}: ${args.output.join('\t')}` + } + const RW_OTEL_WRAPPER_TRACER = RW_OTEL_WRAPPER_TRACE.getTracer('redwoodjs') + const RW_OTEL_WRAPPER_RESULT = await RW_OTEL_WRAPPER_TRACER.startActiveSpan( + 'redwoodjs:api:__MOCKED_API_FOLDER__:withDefaultValuesTwo', + async (span) => { + span.setAttribute('code.function', 'withDefaultValuesTwo') + span.setAttribute('code.filepath', '__MOCKED_FILENAME__') + try { + const RW_OTEL_WRAPPER_INNER_RESULT = await __withDefaultValuesTwo(args) + span.end() + return RW_OTEL_WRAPPER_INNER_RESULT + } catch (error) { + span.recordException(error) + span.setStatus({ + code: 2, + message: + error?.message?.split('\n')[0] ?? error?.toString()?.split('\n')[0], + }) + span.end() + throw error + } + } + ) + return RW_OTEL_WRAPPER_RESULT +} \ No newline at end of file diff --git a/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/service-instrumented/code.js b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/service-instrumented/code.js new file mode 100644 index 000000000000..210393e41988 --- /dev/null +++ b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/service-instrumented/code.js @@ -0,0 +1,22 @@ +import opentelemetry from '@opentelemetry/api' + +import { db } from 'src/lib/db' + +export const updateContact = ({ + id, + input, +} = { + id: 1, + input: { + name: 'R. Edwoods', + }, + }) => { + return opentelemetry.trace.getTracer('service').startActiveSpan('updateContact', async (span) => { + const data = await db.contact.update({ + data: input, + where: { id }, + }) + span.end() + return data + }) +} diff --git a/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/service-instrumented/output.js b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/service-instrumented/output.js new file mode 100644 index 000000000000..cf325a44c74b --- /dev/null +++ b/packages/babel-config/src/plugins/__tests__/__fixtures__/otel-wrapping/service-instrumented/output.js @@ -0,0 +1,59 @@ +import { trace as RW_OTEL_WRAPPER_TRACE } from '@opentelemetry/api' +import opentelemetry from '@opentelemetry/api' +import { db } from 'src/lib/db' +export const updateContact = ( + { id, input } = { + id: 1, + input: { + name: 'R. Edwoods', + }, + } +) => { + const __updateContact = ( + { id, input } = { + id: 1, + input: { + name: 'R. Edwoods', + }, + } + ) => { + return opentelemetry.trace + .getTracer('service') + .startActiveSpan('updateContact', async (span) => { + const data = await db.contact.update({ + data: input, + where: { + id, + }, + }) + span.end() + return data + }) + } + const RW_OTEL_WRAPPER_TRACER = RW_OTEL_WRAPPER_TRACE.getTracer('redwoodjs') + const RW_OTEL_WRAPPER_RESULT = RW_OTEL_WRAPPER_TRACER.startActiveSpan( + 'redwoodjs:api:__MOCKED_API_FOLDER__:updateContact', + (span) => { + span.setAttribute('code.function', 'updateContact') + span.setAttribute('code.filepath', '__MOCKED_FILENAME__') + try { + const RW_OTEL_WRAPPER_INNER_RESULT = __updateContact({ + id, + input, + }) + span.end() + return RW_OTEL_WRAPPER_INNER_RESULT + } catch (error) { + span.recordException(error) + span.setStatus({ + code: 2, + message: + error?.message?.split('\n')[0] ?? error?.toString()?.split('\n')[0], + }) + span.end() + throw error + } + } + ) + return RW_OTEL_WRAPPER_RESULT +} \ No newline at end of file diff --git a/packages/babel-config/src/plugins/__tests__/babel-plugin-redwood-otel-wrapping.test.ts b/packages/babel-config/src/plugins/__tests__/babel-plugin-redwood-otel-wrapping.test.ts new file mode 100644 index 000000000000..37ec1d2d5394 --- /dev/null +++ b/packages/babel-config/src/plugins/__tests__/babel-plugin-redwood-otel-wrapping.test.ts @@ -0,0 +1,19 @@ +import path from 'path' + +import pluginTester from 'babel-plugin-tester' + +import redwoodOtelWrappingPlugin from '../babel-plugin-redwood-otel-wrapping' + +jest.mock('@redwoodjs/project-config', () => { + return { + getBaseDirFromFile: () => { + return '' + }, + } +}) + +pluginTester({ + plugin: redwoodOtelWrappingPlugin, + pluginName: 'babel-plugin-redwood-otel-wrapping', + fixtures: path.join(__dirname, '__fixtures__/otel-wrapping'), +}) diff --git a/packages/babel-config/src/plugins/babel-plugin-redwood-otel-wrapping.ts b/packages/babel-config/src/plugins/babel-plugin-redwood-otel-wrapping.ts index 03befb374bfe..7b1ab73644aa 100644 --- a/packages/babel-config/src/plugins/babel-plugin-redwood-otel-wrapping.ts +++ b/packages/babel-config/src/plugins/babel-plugin-redwood-otel-wrapping.ts @@ -1,311 +1,362 @@ import * as nodejsPath from 'path' -import type { PluginObj, types } from '@babel/core' +import type { NodePath, PluginObj, PluginPass, types } from '@babel/core' import { getBaseDirFromFile } from '@redwoodjs/project-config' -// This wraps user code within opentelemetry spans to provide greater ease in trace analysis. +// This wraps user code within opentelemetry spans to provide automatic tracing in your redwood API. + +function addOpenTelemetryImport( + path: NodePath, + t: typeof types +) { + // We need to have access to the `trace` from `@opentelemetry/api` in order to add the + // automatic instrumentation. We will import it and alias it to something highly specific + // to avoid any potential naming conflicts with user code. + path.node.body.unshift( + t.importDeclaration( + [ + t.importSpecifier( + t.identifier('RW_OTEL_WRAPPER_TRACE'), + t.identifier('trace') + ), + ], + t.stringLiteral('@opentelemetry/api') + ) + ) +} + +function getRedwoodPaths(state: PluginPass): { + filename: string | null | undefined + apiFolder: string +} { + // NOTE: Unable to get 'babel-plugin-tester' to mock the filename so we have specific + // testing logic here. Not ideal but it works for now. + if (process.env.NODE_ENV === 'test') { + return { + filename: '__MOCKED_FILENAME__', + apiFolder: '__MOCKED_API_FOLDER__', + } + } + + const filename = state.file.opts.filename + const filenameOffset = filename + ? getBaseDirFromFile(filename).length + 9 // 9 is the length of '/api/src/' + : 0 + const apiFolder = filename + ? filename.substring( + filenameOffset, + filename.substring(filenameOffset).indexOf(nodejsPath.sep) + + filenameOffset + ) + : '?' -export default function ({ types: t }: { types: typeof types }): PluginObj { return { - name: 'babel-plugin-redwood-otel-wrapping', - visitor: { - Program(path) { - // Only import if it isn't already imported in the way we need it - // TODO: Check for ImportNamespaceSpecifier like "import * as opentelemetry from '@opentelemetry/api'" - // TODO: Consider just checking for the import name "opentelemetry" and don't consider the source - const importDeclarations = path.node.body.filter( - (node) => node.type === 'ImportDeclaration' - ) as types.ImportDeclaration[] - const requiredOpenTelemetryImportExists = importDeclarations.some( - (importDeclaration) => { - if (importDeclaration.source.value !== '@opentelemetry/api') { - return false - } - if ( - importDeclaration.specifiers[0].type !== 'ImportDefaultSpecifier' - ) { - return false - } - if ( - importDeclaration.specifiers[0].local.name === 'opentelemetry' - ) { - return true + filename, + apiFolder, + } +} + +function wrapExportNamedDeclaration( + path: NodePath, + state: PluginPass, + t: typeof types +) { + const declaration = path.node.declaration + const declarationIsSupported = + declaration != null && + declaration.type === 'VariableDeclaration' && + declaration.declarations[0].init?.type === 'ArrowFunctionExpression' + if (!declarationIsSupported) { + return + } + + const originalFunction = declaration.declarations[0] + .init as types.ArrowFunctionExpression + if (!originalFunction) { + return + } + + const originalFunctionName = + declaration.declarations[0].id.type === 'Identifier' + ? declaration.declarations[0].id.name + : '?' + const wrappedFunctionName = `__${ + originalFunctionName === '?' + ? 'RW_OTEL_WRAPPER_UNKNOWN_FUNCTION' + : originalFunctionName + }` + + const originalFunctionArgumentsWithoutDefaults: ( + | types.ArgumentPlaceholder + | types.JSXNamespacedName + | types.SpreadElement + | types.Expression + )[] = [] + for (const param of originalFunction.params) { + if (param.type === 'Identifier') { + originalFunctionArgumentsWithoutDefaults.push(param) + continue + } + + if (param.type === 'ObjectPattern') { + const objectProperties = param.properties.filter( + (p) => p.type === 'ObjectProperty' + ) as types.ObjectProperty[] + originalFunctionArgumentsWithoutDefaults.push( + t.objectExpression( + objectProperties.map((p) => { + if (p.value.type === 'AssignmentPattern') { + return t.objectProperty(p.key, p.value.left) } - return false - } + return p + }) ) - if (!requiredOpenTelemetryImportExists) { - path.node.body.unshift( - t.importDeclaration( - [t.importDefaultSpecifier(t.identifier('opentelemetry'))], - t.stringLiteral('@opentelemetry/api') - ) + ) + + continue + } + + if (param.type === 'AssignmentPattern') { + if (param.left.type === 'Identifier') { + originalFunctionArgumentsWithoutDefaults.push(param.left) + } else if (param.left.type === 'ObjectPattern') { + const objectProperties = param.left.properties.filter( + (p) => p.type === 'ObjectProperty' + ) as types.ObjectProperty[] + originalFunctionArgumentsWithoutDefaults.push( + t.objectExpression( + objectProperties.map((p) => { + if (p.value.type === 'AssignmentPattern') { + return t.objectProperty(p.key, p.value.left) + } + return p + }) ) - } - }, - ExportNamedDeclaration(path, state) { - if ( - path.node.declaration?.type === 'VariableDeclaration' && - path.node.declaration.declarations[0].init?.type === - 'ArrowFunctionExpression' - ) { - const originalFunc = path.node.declaration.declarations[0].init - const originalFuncId = - path.node.declaration.declarations[0].id.type === 'Identifier' - ? path.node.declaration.declarations[0].id.name - : '?' + ) + } else { + // TODO: Implement others, bail out for now + return + } + } - const originalFuncArguments: ( - | types.ArgumentPlaceholder - | types.JSXNamespacedName - | types.SpreadElement - | types.Expression - )[] = [] - for (const param of originalFunc.params) { - switch (param.type) { - case 'ArrayPattern': - // TODO: Implement me - break - case 'AssignmentPattern': - // TODO: Implement me - break - case 'Identifier': - originalFuncArguments.push(param) - // TODO: Implement me - break - case 'ObjectPattern': - // TODO: Is this correct? - originalFuncArguments.push( - t.objectExpression( - param.properties.filter( - (p) => p.type === 'ObjectProperty' - ) as types.ObjectProperty[] - ) - ) - break - case 'RestElement': - // TODO: Implement me - break - } - } + if (param.type === 'ArrayPattern' || param.type === 'RestElement') { + // TODO: Implement, bail out for now + return + } + } - const filename = state.file.opts.filename - const filenameOffset = filename - ? getBaseDirFromFile(filename).length + 9 // 9 is the length of '/api/src/' - : 0 - const apiFolder = filename - ? filename.substring( - filenameOffset, - filename.substring(filenameOffset).indexOf(nodejsPath.sep) + - filenameOffset - ) - : '?' + const { filename, apiFolder } = getRedwoodPaths(state) - const activeSpanBlock = t.callExpression( - t.memberExpression( - t.identifier('tracer'), - t.identifier('startActiveSpan') - ), - [ - t.stringLiteral(`redwoodjs:api:${apiFolder}:${originalFuncId}`), - t.arrowFunctionExpression( - [t.identifier('span')], - t.blockStatement([ - t.expressionStatement( - t.callExpression( - t.memberExpression( - t.identifier('span'), - t.identifier('setAttribute') - ), - [ - t.stringLiteral('code.function'), - t.stringLiteral(originalFuncId), - ] - ) - ), - t.expressionStatement( - t.callExpression( - t.memberExpression( - t.identifier('span'), - t.identifier('setAttribute') - ), - [ - t.stringLiteral('code.filepath'), - t.stringLiteral(state.file.opts.filename || '?'), - ] - ) - ), - t.tryStatement( - t.blockStatement([ - t.variableDeclaration('const', [ - t.variableDeclarator( - t.identifier('innerResult'), - originalFunc.async - ? t.awaitExpression( - t.callExpression( - t.identifier(`_${originalFuncId}`), - originalFuncArguments - ) - ) - : t.callExpression( - t.identifier(`_${originalFuncId}`), - originalFuncArguments - ) - ), - ]), - t.expressionStatement( + const activeSpanBlock = t.callExpression( + t.memberExpression( + t.identifier('RW_OTEL_WRAPPER_TRACER'), + t.identifier('startActiveSpan') + ), + [ + t.stringLiteral(`redwoodjs:api:${apiFolder}:${originalFunctionName}`), + t.arrowFunctionExpression( + [t.identifier('span')], + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('span'), + t.identifier('setAttribute') + ), + [ + t.stringLiteral('code.function'), + t.stringLiteral(originalFunctionName), + ] + ) + ), + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('span'), + t.identifier('setAttribute') + ), + [ + t.stringLiteral('code.filepath'), + t.stringLiteral(filename || '?'), + ] + ) + ), + t.tryStatement( + t.blockStatement([ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('RW_OTEL_WRAPPER_INNER_RESULT'), + originalFunction.async + ? t.awaitExpression( t.callExpression( - t.memberExpression( - t.identifier('span'), - t.identifier('end') - ), - [] + t.identifier(wrappedFunctionName), + originalFunctionArgumentsWithoutDefaults ) - ), - t.returnStatement(t.identifier('innerResult')), - ]), - t.catchClause( - t.identifier('error'), - t.blockStatement([ - t.expressionStatement( - t.callExpression( - t.memberExpression( - t.identifier('span'), - t.identifier('recordException') - ), - [t.identifier('error')] - ) + ) + : t.callExpression( + t.identifier(wrappedFunctionName), + originalFunctionArgumentsWithoutDefaults + ) + ), + ]), + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier('span'), t.identifier('end')), + [] + ) + ), + t.returnStatement(t.identifier('RW_OTEL_WRAPPER_INNER_RESULT')), + ]), + t.catchClause( + t.identifier('error'), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('span'), + t.identifier('recordException') + ), + [t.identifier('error')] + ) + ), + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('span'), + t.identifier('setStatus') + ), + [ + t.objectExpression([ + t.objectProperty( + t.identifier('code'), + t.numericLiteral(2) ), - t.expressionStatement( - t.callExpression( - t.memberExpression( - t.identifier('span'), - t.identifier('setStatus') - ), - [ - t.objectExpression([ - t.objectProperty( - t.identifier('code'), - t.numericLiteral(2) + t.objectProperty( + t.identifier('message'), + t.logicalExpression( + '??', + t.optionalMemberExpression( + t.optionalCallExpression( + t.optionalMemberExpression( + t.optionalMemberExpression( + t.identifier('error'), + t.identifier('message'), + false, + true + ), + t.identifier('split'), + false, + true ), - t.objectProperty( - t.identifier('message'), - t.logicalExpression( - '??', + [t.stringLiteral('\n')], + false + ), + t.numericLiteral(0), + true, + false + ), + t.optionalMemberExpression( + t.optionalCallExpression( + t.optionalMemberExpression( + t.optionalCallExpression( t.optionalMemberExpression( - t.optionalCallExpression( - t.optionalMemberExpression( - t.optionalMemberExpression( - t.identifier('error'), - t.identifier('message'), - false, - true - ), - t.identifier('split'), - false, - true - ), - [t.stringLiteral('\n')], - false - ), - t.numericLiteral(0), - true, - false + t.identifier('error'), + t.identifier('toString'), + false, + true ), - t.optionalMemberExpression( - t.optionalCallExpression( - t.optionalMemberExpression( - t.optionalCallExpression( - t.optionalMemberExpression( - t.identifier('error'), - t.identifier('toString'), - false, - true - ), - [], - false - ), - t.identifier('split'), - false, - true - ), - [t.stringLiteral('\n')], - false - ), - t.numericLiteral(0), - true, - false - ) - ) + [], + false + ), + t.identifier('split'), + false, + true ), - ]), - ] - ) - ), - t.expressionStatement( - t.callExpression( - t.memberExpression( - t.identifier('span'), - t.identifier('end') - ), - [] + [t.stringLiteral('\n')], + false + ), + t.numericLiteral(0), + true, + false + ) ) ), - t.throwStatement(t.identifier('error')), - ]) - ) - ), - ]), - originalFunc.async + ]), + ] + ) + ), + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier('span'), + t.identifier('end') + ), + [] + ) + ), + t.throwStatement(t.identifier('error')), + ]) + ) + ), + ]), + originalFunction.async + ), + ] + ) + + const wrapper = t.arrowFunctionExpression( + originalFunction.params, + t.blockStatement( + [ + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier(wrappedFunctionName), + originalFunction + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('RW_OTEL_WRAPPER_TRACER'), + t.callExpression( + t.memberExpression( + t.identifier('RW_OTEL_WRAPPER_TRACE'), + t.identifier('getTracer') ), - ] - ) + [t.stringLiteral('redwoodjs')] + ) + ), + ]), + t.variableDeclaration('const', [ + t.variableDeclarator( + t.identifier('RW_OTEL_WRAPPER_RESULT'), + originalFunction.async + ? t.awaitExpression(activeSpanBlock) + : activeSpanBlock + ), + ]), + t.returnStatement(t.identifier('RW_OTEL_WRAPPER_RESULT')), + ], + originalFunction.body.type === 'BlockStatement' + ? originalFunction.body.directives + : undefined + ), + originalFunction.async + ) - const wrapper = t.arrowFunctionExpression( - originalFunc.params, - t.blockStatement( - [ - t.variableDeclaration('const', [ - t.variableDeclarator( - t.identifier(`_${originalFuncId}`), - originalFunc - ), - ]), - t.variableDeclaration('const', [ - t.variableDeclarator( - t.identifier('tracer'), - t.callExpression( - t.memberExpression( - t.memberExpression( - t.identifier('opentelemetry'), - t.identifier('trace') - ), - t.identifier('getTracer') - ), - [t.stringLiteral('redwoodjs')] - ) - ), - ]), - t.variableDeclaration('const', [ - t.variableDeclarator( - t.identifier('result'), - originalFunc.async - ? t.awaitExpression(activeSpanBlock) - : activeSpanBlock - ), - ]), - t.returnStatement(t.identifier('result')), - ], - originalFunc.body.type === 'BlockStatement' - ? originalFunc.body.directives - : undefined - ), - originalFunc.async - ) + // Replace the original function with the wrapped version + declaration.declarations[0].init = wrapper +} - path.node.declaration.declarations[0].init = wrapper - } +export default function ({ types: t }: { types: typeof types }): PluginObj { + return { + name: 'babel-plugin-redwood-otel-wrapping', + visitor: { + Program(path) { + addOpenTelemetryImport(path, t) + }, + ExportNamedDeclaration(path, state) { + wrapExportNamedDeclaration(path, state, t) }, }, } diff --git a/packages/cli-helpers/package.json b/packages/cli-helpers/package.json index 8ebb15ecc338..bf0185c704c9 100644 --- a/packages/cli-helpers/package.json +++ b/packages/cli-helpers/package.json @@ -23,12 +23,14 @@ }, "dependencies": { "@babel/core": "^7.22.20", - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", + "@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/package.json b/packages/cli/package.json index b91d54d82695..c7f515923536 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -28,7 +28,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@iarna/toml": "2.2.5", "@opentelemetry/api": "1.4.1", "@opentelemetry/core": "1.15.2", @@ -50,7 +50,7 @@ "camelcase": "6.3.0", "chalk": "4.1.2", "ci-info": "3.8.0", - "concurrently": "8.2.1", + "concurrently": "8.2.2", "configstore": "3.1.5", "core-js": "3.32.2", "cross-env": "7.0.3", @@ -73,7 +73,7 @@ "prettier": "2.8.8", "prisma": "5.4.2", "prompts": "2.4.2", - "rimraf": "5.0.1", + "rimraf": "5.0.5", "secure-random-password": "0.2.3", "semver": "7.5.3", "string-env-interpolation": "1.0.1", diff --git a/packages/cli/src/commands/experimental/setupOpentelemetryHandler.js b/packages/cli/src/commands/experimental/setupOpentelemetryHandler.js index 7371888f4fbd..eef9373fd67d 100644 --- a/packages/cli/src/commands/experimental/setupOpentelemetryHandler.js +++ b/packages/cli/src/commands/experimental/setupOpentelemetryHandler.js @@ -69,7 +69,7 @@ export const handler = async ({ force, verbose }) => { writeFile( redwoodTomlPath, configContent.concat( - `\n[experimental.opentelemetry]\n\tenabled = true\n\tapiSdk = "${opentelemetryScriptPath}"` + `\n[experimental.opentelemetry]\n\tenabled = true\n\twrapApi = true\n\tapiSdk = "${opentelemetryScriptPath}"` ), { overwriteExisting: true, // redwood.toml always exists diff --git a/packages/cli/src/commands/experimental/setupRealtimeHandler.js b/packages/cli/src/commands/experimental/setupRealtimeHandler.js index 97216209653e..814929c15056 100644 --- a/packages/cli/src/commands/experimental/setupRealtimeHandler.js +++ b/packages/cli/src/commands/experimental/setupRealtimeHandler.js @@ -246,6 +246,126 @@ export async function handler({ force, includeExamples, verbose }) { ] }, }, + + { + title: 'Adding Defer example queries ...', + enabled: () => includeExamples, + task: () => { + // sdl + + const exampleSdlTemplateContent = fs.readFileSync( + path.resolve( + __dirname, + 'templates', + 'defer', + 'fastAndSlowFields', + `fastAndSlowFields.sdl.template` + ), + 'utf-8' + ) + + const sdlFile = path.join( + redwoodPaths.api.graphql, + `fastAndSlowFields.sdl.${isTypeScriptProject() ? 'ts' : 'js'}` + ) + + const sdlContent = ts + ? exampleSdlTemplateContent + : transformTSToJS(sdlFile, exampleSdlTemplateContent) + + // service + + const exampleServiceTemplateContent = fs.readFileSync( + path.resolve( + __dirname, + 'templates', + 'defer', + 'fastAndSlowFields', + `fastAndSlowFields.ts.template` + ), + 'utf-8' + ) + const serviceFile = path.join( + redwoodPaths.api.services, + 'fastAndSlowFields', + `fastAndSlowFields.${isTypeScriptProject() ? 'ts' : 'js'}` + ) + + const serviceContent = ts + ? exampleServiceTemplateContent + : transformTSToJS(serviceFile, exampleServiceTemplateContent) + + // write all files + return [ + writeFile(sdlFile, sdlContent, { + overwriteExisting: force, + }), + writeFile(serviceFile, serviceContent, { + overwriteExisting: force, + }), + ] + }, + }, + + { + title: 'Adding Stream example queries ...', + enabled: () => includeExamples, + task: () => { + // sdl + + const exampleSdlTemplateContent = fs.readFileSync( + path.resolve( + __dirname, + 'templates', + 'stream', + 'alphabet', + `alphabet.sdl.template` + ), + 'utf-8' + ) + + const sdlFile = path.join( + redwoodPaths.api.graphql, + `alphabet.sdl.${isTypeScriptProject() ? 'ts' : 'js'}` + ) + + const sdlContent = ts + ? exampleSdlTemplateContent + : transformTSToJS(sdlFile, exampleSdlTemplateContent) + + // service + + const exampleServiceTemplateContent = fs.readFileSync( + path.resolve( + __dirname, + 'templates', + 'stream', + 'alphabet', + `alphabet.ts.template` + ), + 'utf-8' + ) + const serviceFile = path.join( + redwoodPaths.api.services, + 'alphabet', + `alphabet.${isTypeScriptProject() ? 'ts' : 'js'}` + ) + + const serviceContent = ts + ? exampleServiceTemplateContent + : transformTSToJS(serviceFile, exampleServiceTemplateContent) + + // write all files + return [ + writeFile(sdlFile, sdlContent, { + overwriteExisting: force, + }), + writeFile(serviceFile, serviceContent, { + overwriteExisting: force, + }), + ] + }, + }, { title: 'Adding config to redwood.toml...', task: (_ctx, task) => { diff --git a/packages/cli/src/commands/experimental/templates/defer/fastAndSlowFields/fastAndSlowFields.sdl.template b/packages/cli/src/commands/experimental/templates/defer/fastAndSlowFields/fastAndSlowFields.sdl.template new file mode 100644 index 000000000000..67cedf7119a1 --- /dev/null +++ b/packages/cli/src/commands/experimental/templates/defer/fastAndSlowFields/fastAndSlowFields.sdl.template @@ -0,0 +1,14 @@ +export const schema = gql` + type Query { + """ + A field that resolves fast. + """ + fastField: String! @skipAuth + + """ + A field that resolves slowly. + Maybe you want to @defer this field ;) + """ + slowField(waitFor: Int! = 5000): String @skipAuth + } +` diff --git a/packages/cli/src/commands/experimental/templates/defer/fastAndSlowFields/fastAndSlowFields.ts.template b/packages/cli/src/commands/experimental/templates/defer/fastAndSlowFields/fastAndSlowFields.ts.template new file mode 100644 index 000000000000..d8e25c46de0c --- /dev/null +++ b/packages/cli/src/commands/experimental/templates/defer/fastAndSlowFields/fastAndSlowFields.ts.template @@ -0,0 +1,14 @@ +import { logger } from 'src/lib/logger' + +const wait = (time: number) => + new Promise((resolve) => setTimeout(resolve, time)) + +export const fastField = async () => { + return 'I am fast' +} + +export const slowField = async (_, { waitFor = 5000 }) => { + logger.debug('waiting on slowField') + await wait(waitFor) + return 'I am slow' +} diff --git a/packages/cli/src/commands/experimental/templates/realtime.ts.template b/packages/cli/src/commands/experimental/templates/realtime.ts.template index 33028f34177a..db55b686b6c6 100644 --- a/packages/cli/src/commands/experimental/templates/realtime.ts.template +++ b/packages/cli/src/commands/experimental/templates/realtime.ts.template @@ -21,6 +21,8 @@ import subscriptions from 'src/subscriptions/**/*.{js,ts}' * Redwood Realtime * - uses a publish/subscribe model to broadcast data to clients. * - uses a store to persist Live Query and Subscription data. + * - and enable defer and stream directives to improve latency + * for clients by sending data the most important data as soon as it's ready. * * Redwood Realtime supports in-memory and Redis stores: * - In-memory stores are useful for development and testing. @@ -39,4 +41,6 @@ export const realtime: RedwoodRealtimeOptions = { // if using a Redis store // store: { redis: { publishClient, subscribeClient } }, }, + // To enable defer and streaming, set to true. + // enableDeferStream: true, } diff --git a/packages/cli/src/commands/experimental/templates/stream/alphabet/alphabet.sdl.template b/packages/cli/src/commands/experimental/templates/stream/alphabet/alphabet.sdl.template new file mode 100644 index 000000000000..44e478cb8486 --- /dev/null +++ b/packages/cli/src/commands/experimental/templates/stream/alphabet/alphabet.sdl.template @@ -0,0 +1,9 @@ +export const schema = gql` + type Query { + """ + A field that spells out the letters of the alphabet + Maybe you want to @stream this field ;) + """ + alphabet: [String!]! @skipAuth + } +` diff --git a/packages/cli/src/commands/experimental/templates/stream/alphabet/alphabet.ts.template b/packages/cli/src/commands/experimental/templates/stream/alphabet/alphabet.ts.template new file mode 100644 index 000000000000..a3ffde7e1d05 --- /dev/null +++ b/packages/cli/src/commands/experimental/templates/stream/alphabet/alphabet.ts.template @@ -0,0 +1,31 @@ +import { Repeater } from '@redwoodjs/realtime' + +import { logger } from 'src/lib/logger' + +export const alphabet = async () => { + return new Repeater(async (push, stop) => { + const letters = 'abcdefghijklmnopqrstuvwxyz'.split('') + + const publish = () => { + const letter = letters.shift() + + if (letter) { + logger.debug({ letter }, 'publishing letter...') + push(letter) + } + + if (letters.length === 0) { + stop() + } + } + + const interval = setInterval(publish, 1000) + + stop.then(() => { + logger.debug('cancel') + clearInterval(interval) + }) + + publish() + }) +} diff --git a/packages/cli/src/commands/experimental/templates/subscriptions/countdown/countdown.ts.template b/packages/cli/src/commands/experimental/templates/subscriptions/countdown/countdown.ts.template index bf42145b1025..2c87356fcfdf 100644 --- a/packages/cli/src/commands/experimental/templates/subscriptions/countdown/countdown.ts.template +++ b/packages/cli/src/commands/experimental/templates/subscriptions/countdown/countdown.ts.template @@ -1,5 +1,9 @@ import gql from 'graphql-tag' +import { Repeater } from '@redwoodjs/realtime' + +import { logger } from 'src/lib/logger' + export const schema = gql` type Subscription { countdown(from: Int!, interval: Int!): Int! @requireAuth @@ -15,14 +19,39 @@ export const schema = gql` */ const countdown = { countdown: { - async *subscribe(_, { from = 100, interval = 10 }) { - while (from >= 0) { - yield { countdown: from } - // pause for 1/4 second - await new Promise((resolve) => setTimeout(resolve, 250)) - from -= interval + subscribe: ( + _, + { + from = 100, + interval = 10, + }: { + from: number + interval: number } - }, + ) => + new Repeater((push, stop) => { + function decrement() { + from -= interval + + if (from < 0) { + logger.debug({ from }, 'stopping as countdown is less than 0') + stop() + } + + logger.debug({ from }, 'pushing countdown value ...') + push(from) + } + + decrement() + + const delay = setInterval(decrement, 500) + + stop.then(() => { + clearInterval(delay) + logger.debug('stopping countdown') + }) + }), + resolve: (payload: number) => payload, }, } 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/mailer/mailer.js b/packages/cli/src/commands/setup/mailer/mailer.js new file mode 100644 index 000000000000..3838ec7f9500 --- /dev/null +++ b/packages/cli/src/commands/setup/mailer/mailer.js @@ -0,0 +1,31 @@ +import { recordTelemetryAttributes } from '@redwoodjs/cli-helpers' + +export const command = 'mailer' + +export const description = + 'Setup the redwood mailer. This will install the required packages and add the required initial configuration to your redwood app.' + +export const builder = (yargs) => { + yargs + .option('force', { + alias: 'f', + default: false, + description: 'Overwrite existing configuration', + type: 'boolean', + }) + .option('skip-examples', { + default: false, + description: 'Only include required files and exclude any examples', + type: 'boolean', + }) +} + +export const handler = async (options) => { + recordTelemetryAttributes({ + command: 'setup mailer', + force: options.force, + skipExamples: options.skipExamples, + }) + const { handler } = await import('./mailerHandler.js') + return handler(options) +} diff --git a/packages/cli/src/commands/setup/mailer/mailerHandler.js b/packages/cli/src/commands/setup/mailer/mailerHandler.js new file mode 100644 index 000000000000..a25ce2966c18 --- /dev/null +++ b/packages/cli/src/commands/setup/mailer/mailerHandler.js @@ -0,0 +1,119 @@ +import fs from 'fs' +import path from 'path' + +import { Listr } from 'listr2' + +import { addApiPackages } from '@redwoodjs/cli-helpers' +import { errorTelemetry } from '@redwoodjs/telemetry' + +import { getPaths, transformTSToJS, writeFile } from '../../../lib' +import c from '../../../lib/colors' +import { isTypeScriptProject } from '../../../lib/project' + +export const handler = async ({ force, skipExamples }) => { + const projectIsTypescript = isTypeScriptProject() + const redwoodVersion = + require(path.join(getPaths().base, 'package.json')).devDependencies[ + '@redwoodjs/core' + ] ?? 'latest' + + const tasks = new Listr( + [ + { + title: `Adding api/src/lib/mailer.${ + projectIsTypescript ? 'ts' : 'js' + }...`, + task: () => { + const templatePath = path.resolve( + __dirname, + 'templates', + 'mailer.ts.template' + ) + const templateContent = fs.readFileSync(templatePath, { + encoding: 'utf8', + flag: 'r', + }) + + const mailerPath = path.join( + getPaths().api.lib, + `mailer.${projectIsTypescript ? 'ts' : 'js'}` + ) + const mailerContent = projectIsTypescript + ? templateContent + : transformTSToJS(mailerPath, templateContent) + + return writeFile(mailerPath, mailerContent, { + overwriteExisting: force, + }) + }, + }, + { + title: 'Adding api/src/mail directory...', + task: () => { + const mailDir = path.join(getPaths().api.mail) + if (!fs.existsSync(mailDir)) { + fs.mkdirSync(mailDir) + } + }, + }, + { + title: `Adding example ReactEmail mail template`, + skip: () => skipExamples, + task: () => { + const templatePath = path.resolve( + __dirname, + 'templates', + 're-example.tsx.template' + ) + const templateContent = fs.readFileSync(templatePath, { + encoding: 'utf8', + flag: 'r', + }) + + const exampleTemplatePath = path.join( + getPaths().api.mail, + 'Example', + `Example.${projectIsTypescript ? 'tsx' : 'jsx'}` + ) + const exampleTemplateContent = projectIsTypescript + ? templateContent + : transformTSToJS(exampleTemplatePath, templateContent) + + return writeFile(exampleTemplatePath, exampleTemplateContent, { + overwriteExisting: force, + }) + }, + }, + { + // Add production dependencies + ...addApiPackages([ + `@redwoodjs/mailer-core@${redwoodVersion}`, + `@redwoodjs/mailer-handler-nodemailer@${redwoodVersion}`, + `@redwoodjs/mailer-renderer-react-email@${redwoodVersion}`, + `@react-email/components`, // NOTE: Unpinned dependency here + ]), + title: 'Adding production dependencies to your api side...', + }, + { + // Add development dependencies + ...addApiPackages([ + '-D', + `@redwoodjs/mailer-handler-in-memory@${redwoodVersion}`, + `@redwoodjs/mailer-handler-studio@${redwoodVersion}`, + ]), + title: 'Adding development dependencies to your api side...', + }, + ], + { + rendererOptions: { collapseSubtasks: false }, + } + ) + + try { + await tasks.run() + } catch (e) { + errorTelemetry(process.argv, e.message) + console.error(c.error(e.message)) + process.exit(e?.exitCode || 1) + } +} diff --git a/packages/cli/src/commands/setup/mailer/templates/mailer.ts.template b/packages/cli/src/commands/setup/mailer/templates/mailer.ts.template new file mode 100644 index 000000000000..eac5fed86efc --- /dev/null +++ b/packages/cli/src/commands/setup/mailer/templates/mailer.ts.template @@ -0,0 +1,30 @@ +import { Mailer } from '@redwoodjs/mailer-core' +import { NodemailerMailHandler } from '@redwoodjs/mailer-handler-nodemailer' +import { ReactEmailRenderer } from '@redwoodjs/mailer-renderer-react-email' + +import { logger } from 'src/lib/logger' + +export const mailer = new Mailer({ + handling: { + handlers: { + // TODO: Update this handler config or switch it out for a different handler completely + nodemailer: new NodemailerMailHandler({ + transport: { + host: 'localhost', + port: 4319, + secure: false, + }, + }), + }, + default: 'nodemailer', + }, + + rendering: { + renderers: { + reactEmail: new ReactEmailRenderer(), + }, + default: 'reactEmail', + }, + + logger, +}) diff --git a/packages/cli/src/commands/setup/mailer/templates/re-example.tsx.template b/packages/cli/src/commands/setup/mailer/templates/re-example.tsx.template new file mode 100644 index 000000000000..9a13cf19eb1f --- /dev/null +++ b/packages/cli/src/commands/setup/mailer/templates/re-example.tsx.template @@ -0,0 +1,40 @@ +import React from 'react' + +import { + Html, + Text, + Hr, + Body, + Head, + Tailwind, + Preview, + Container, + Heading, +} from '@react-email/components' + +export function ExampleEmail( + { when }: { when: string } = { when: new Date().toLocaleString() } +) { + return ( + + + An example email + + + + + Example Email + + + This is an example email which you can customise to your needs. + +
+ + Message was sent on {when} + +
+ +
+ + ) +} 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/codemods/package.json b/packages/codemods/package.json index 3383454401ba..fe4b5dda072b 100644 --- a/packages/codemods/package.json +++ b/packages/codemods/package.json @@ -26,7 +26,7 @@ "@babel/core": "^7.22.20", "@babel/parser": "^7.22.16", "@babel/plugin-transform-typescript": "^7.22.15", - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@babel/traverse": "^7.22.20", "@iarna/toml": "2.2.5", "@redwoodjs/project-config": "6.0.7", diff --git a/packages/core/package.json b/packages/core/package.json index ea90cce9b8a8..1935c35d4797 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -38,7 +38,7 @@ }, "dependencies": { "@babel/cli": "7.23.0", - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@pmmmwh/react-refresh-webpack-plugin": "0.5.10", "@redwoodjs/cli": "6.0.7", "@redwoodjs/eslint-config": "6.0.7", @@ -61,7 +61,7 @@ "null-loader": "4.0.1", "react-refresh": "0.14.0", "resolve-url-loader": "5.0.0", - "rimraf": "5.0.1", + "rimraf": "5.0.5", "style-loader": "3.3.3", "typescript": "5.2.2", "url-loader": "4.1.1", diff --git a/packages/forms/package.json b/packages/forms/package.json index 2358e44ec32c..8391e8ee8636 100644 --- a/packages/forms/package.json +++ b/packages/forms/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "core-js": "3.32.2", "pascalcase": "1.0.0", "react-hook-form": "7.46.1" diff --git a/packages/graphql-server/package.json b/packages/graphql-server/package.json index 39d779c0448c..3ddc6b407e57 100644 --- a/packages/graphql-server/package.json +++ b/packages/graphql-server/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@envelop/core": "4.0.0", "@envelop/depth-limit": "3.0.0", "@envelop/disable-introspection": "5.0.0", diff --git a/packages/graphql-server/src/plugins/useRedwoodError.ts b/packages/graphql-server/src/plugins/useRedwoodError.ts index 27dd054213fd..e57a558c0afa 100644 --- a/packages/graphql-server/src/plugins/useRedwoodError.ts +++ b/packages/graphql-server/src/plugins/useRedwoodError.ts @@ -52,8 +52,12 @@ export const useRedwoodError = ( } }) + // be certain to return the complete result + // and not just the data or the errors + // because defer, stream and AsyncIterator results + // need to be returned as is setResult({ - data: result.data, + ...result, errors, extensions: result.extensions || {}, }) diff --git a/packages/internal/package.json b/packages/internal/package.json index a893acaddc0f..171a47371fb5 100644 --- a/packages/internal/package.json +++ b/packages/internal/package.json @@ -31,7 +31,7 @@ "@babel/parser": "^7.22.16", "@babel/plugin-transform-react-jsx": "^7.22.15", "@babel/plugin-transform-typescript": "^7.22.15", - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@babel/traverse": "^7.22.20", "@graphql-codegen/add": "4.0.1", "@graphql-codegen/cli": "3.3.1", @@ -56,7 +56,7 @@ "graphql": "16.8.1", "kill-port": "1.6.1", "prettier": "2.8.8", - "rimraf": "5.0.1", + "rimraf": "5.0.5", "source-map": "0.7.4", "string-env-interpolation": "1.0.1", "systeminformation": "5.21.7", diff --git a/packages/internal/src/build/api.ts b/packages/internal/src/build/api.ts index e9f49c977838..bf015bacfa50 100644 --- a/packages/internal/src/build/api.ts +++ b/packages/internal/src/build/api.ts @@ -37,8 +37,11 @@ export const cleanApiBuild = () => { */ export const prebuildApiFiles = (srcFiles: string[]) => { const rwjsPaths = getPaths() + const rwjsConfig = getConfig() const plugins = getApiSideBabelPlugins({ - openTelemetry: getConfig().experimental.opentelemetry.enabled, + openTelemetry: + rwjsConfig.experimental.opentelemetry.enabled && + rwjsConfig.experimental.opentelemetry.wrapApi, }) return srcFiles.map((srcPath) => { 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/mailer/core/src/__tests__/mailer.test.ts b/packages/mailer/core/src/__tests__/mailer.test.ts index b7dd65541818..dc10c3d2f869 100644 --- a/packages/mailer/core/src/__tests__/mailer.test.ts +++ b/packages/mailer/core/src/__tests__/mailer.test.ts @@ -325,33 +325,45 @@ describe('Uses the correct modes', () => { expect(console.warn).toBeCalledWith( 'The test handler is null, this will prevent mail from being processed in test mode' ) + }) + + test('development', () => { console.warn.mockClear() - const _mailer2 = new Mailer({ + const _mailer1 = new Mailer({ ...baseConfig, - test: { + development: { when: true, - handler: undefined, + handler: null, }, }) expect(console.warn).toBeCalledWith( - 'The test handler is null, this will prevent mail from being processed in test mode' + 'The development handler is null, this will prevent mail from being processed in development mode' ) }) + }) - test('development', () => { + describe('attempts to use fallback handlers', () => { + beforeAll(() => { + jest.spyOn(console, 'warn').mockImplementation(() => {}) + }) + + test('test', () => { console.warn.mockClear() - const _mailer1 = new Mailer({ + const _mailer = new Mailer({ ...baseConfig, - development: { + test: { when: true, - handler: null, + handler: undefined, }, }) expect(console.warn).toBeCalledWith( - 'The development handler is null, this will prevent mail from being processed in development mode' + "Automatically loaded the '@redwoodjs/mailer-handler-in-memory' handler, this will be used to process mail in test mode" ) + }) + + test('development', () => { console.warn.mockClear() - const _mailer2 = new Mailer({ + const _mailer = new Mailer({ ...baseConfig, development: { when: true, @@ -359,7 +371,7 @@ describe('Uses the correct modes', () => { }, }) expect(console.warn).toBeCalledWith( - 'The development handler is null, this will prevent mail from being processed in development mode' + "Automatically loaded the '@redwoodjs/mailer-handler-studio' handler, this will be used to process mail in development mode" ) }) }) @@ -804,7 +816,7 @@ describe('Uses the correct modes', () => { expect(mailerExplicitlyNullTestHandler.getTestHandler()).toBeNull() const mailerNoTestHandlerDefined = new Mailer(baseConfig) - expect(mailerNoTestHandlerDefined.getTestHandler()).toBeNull() + expect(mailerNoTestHandlerDefined.getTestHandler()).not.toBeNull() }) test('getDevelopmentHandler', () => { @@ -835,7 +847,9 @@ describe('Uses the correct modes', () => { ).toBeNull() const mailerNoDevelopmentHandlerDefined = new Mailer(baseConfig) - expect(mailerNoDevelopmentHandlerDefined.getDevelopmentHandler()).toBeNull() + expect( + mailerNoDevelopmentHandlerDefined.getDevelopmentHandler() + ).not.toBeNull() }) test('getDefaultProductionHandler', () => { diff --git a/packages/mailer/core/src/mailer.ts b/packages/mailer/core/src/mailer.ts index 4b565fdf77e3..de689b2cc399 100644 --- a/packages/mailer/core/src/mailer.ts +++ b/packages/mailer/core/src/mailer.ts @@ -1,5 +1,6 @@ import type { Logger } from '@redwoodjs/api/logger' +import type { AbstractMailHandler } from './handler' import type { MailerConfig, MailSendWithoutRenderingOptions, @@ -27,6 +28,11 @@ export class Mailer< public handlers: THandlers public renderers: TRenderers + // TODO: These would be better typed as the specific InMemoryMailHandler and StudioMailHandler classes + // However, that would require a circular dependency between this file and those files + private fallbackTestHandler?: AbstractMailHandler + private fallbackDevelopmentHandler?: AbstractMailHandler + constructor( public config: MailerConfig< THandlers, @@ -59,15 +65,18 @@ export class Mailer< // Validate handlers for test and development modes const testHandlerKey = this.config.test?.handler if (testHandlerKey === undefined) { - // TODO: Attempt to use a default in-memory handler if the required package is installed - // otherwise default to null and log a warning - this.config.test = { - ...this.config.test, - handler: null, + // Attempt to use a default in-memory handler if the required package is installed + try { + this.fallbackTestHandler = + new (require('@redwoodjs/mailer-handler-in-memory').InMemoryMailHandler)() + this.logger.warn( + "Automatically loaded the '@redwoodjs/mailer-handler-in-memory' handler, this will be used to process mail in test mode" + ) + } catch (_error) { + this.logger.warn( + "No test handler specified and could not load the '@redwoodjs/mailer-handler-in-memory' handler automatically, this will prevent mail from being processed in test mode" + ) } - this.logger.warn( - 'The test handler is null, this will prevent mail from being processed in test mode' - ) } else if (testHandlerKey === null) { this.logger.warn( 'The test handler is null, this will prevent mail from being processed in test mode' @@ -81,15 +90,18 @@ export class Mailer< } const developmentHandlerKey = this.config.development?.handler if (developmentHandlerKey === undefined) { - // TODO: Attempt to use a default studio handler if the required package is installed - // otherwise default to null and log a warning - this.config.development = { - ...this.config.development, - handler: null, + // Attempt to use a default studio handler if the required package is installed + try { + this.fallbackDevelopmentHandler = + new (require('@redwoodjs/mailer-handler-studio').StudioMailHandler)() + this.logger.warn( + "Automatically loaded the '@redwoodjs/mailer-handler-studio' handler, this will be used to process mail in development mode" + ) + } catch (_error) { + this.logger.warn( + "No development handler specified and could not load the '@redwoodjs/mailer-handler-studio' handler automatically, this will prevent mail from being processed in development mode" + ) } - this.logger.warn( - 'The development handler is null, this will prevent mail from being processed in development mode' - ) } else if (developmentHandlerKey === null) { this.logger.warn( 'The development handler is null, this will prevent mail from being processed in development mode' @@ -171,13 +183,6 @@ export class Mailer< // Handler is null, which indicates a no-op return {} } - if (handlerKey === undefined) { - throw new Error('No handler specified and no default handler configured') - } - const handler = this.handlers[handlerKey] - if (handler === undefined) { - throw new Error(`No handler found to match '${handlerKey.toString()}'`) - } const completedSendOptions = constructCompleteSendOptions( sendOptions, @@ -210,10 +215,23 @@ export class Mailer< } ) - const defaultedHandlerOptions = { - ...this.config.handling.options?.[handlerKeyForProduction], - ...handlerOptions, + const defaultedHandlerOptions = + handlerKey === undefined + ? handlerOptions + : { + ...this.config.handling.options?.[handlerKey], + ...handlerOptions, + } + + const handler = + handlerKey === undefined + ? this.getDefaultHandler() + : this.handlers[handlerKey] + if (handler === null || handler === undefined) { + // Handler is null or missing, which indicates a no-op + return {} } + const result = await handler.send( renderedContent, completedSendOptions, @@ -260,23 +278,29 @@ export class Mailer< // Handler is null, which indicates a no-op return {} } - if (handlerKey === undefined) { - throw new Error('No handler specified and no default handler configured') - } - const handler = this.handlers[handlerKey] - if (handler === undefined) { - throw new Error(`No handler found to match '${handlerKey.toString()}'`) - } const completedSendOptions = constructCompleteSendOptions( sendOptions, this.defaults ) - const defaultedHandlerOptions = { - ...this.config.handling.options?.[handlerKeyForProduction], - ...handlerOptions, + const defaultedHandlerOptions = + handlerKey === undefined + ? handlerOptions + : { + ...this.config.handling.options?.[handlerKey], + ...handlerOptions, + } + + const handler = + handlerKey === undefined + ? this.getDefaultHandler() + : this.handlers[handlerKey] + if (handler === null || handler === undefined) { + // Handler is null or missing, which indicates a no-op + return {} } + const result = await handler.send( content, completedSendOptions, @@ -322,17 +346,23 @@ export class Mailer< getTestHandler() { const handlerKey = this.config.test?.handler - if (handlerKey === undefined || handlerKey === null) { + if (handlerKey === null) { return handlerKey } + if (handlerKey === undefined) { + return this.fallbackTestHandler + } return this.handlers[handlerKey] } getDevelopmentHandler() { const handlerKey = this.config.development?.handler - if (handlerKey === undefined || handlerKey === null) { + if (handlerKey === null) { return handlerKey } + if (handlerKey === undefined) { + return this.fallbackDevelopmentHandler + } return this.handlers[handlerKey] } diff --git a/packages/prerender/package.json b/packages/prerender/package.json index bde05da0b59e..35c20dbc0b32 100644 --- a/packages/prerender/package.json +++ b/packages/prerender/package.json @@ -24,7 +24,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@redwoodjs/auth": "6.0.7", "@redwoodjs/internal": "6.0.7", "@redwoodjs/project-config": "6.0.7", diff --git a/packages/project-config/package.json b/packages/project-config/package.json index c05b98f465f9..ee6c0f93661f 100644 --- a/packages/project-config/package.json +++ b/packages/project-config/package.json @@ -31,7 +31,7 @@ "devDependencies": { "esbuild": "0.19.3", "jest": "29.7.0", - "rimraf": "5.0.1", + "rimraf": "5.0.5", "typescript": "5.2.2" }, "gitHead": "3905ed045508b861b495f8d5630d76c7a157d8f1" diff --git a/packages/project-config/src/__tests__/config.test.ts b/packages/project-config/src/__tests__/config.test.ts index 05728ce72cc0..5e0b777bf9b6 100644 --- a/packages/project-config/src/__tests__/config.test.ts +++ b/packages/project-config/src/__tests__/config.test.ts @@ -57,6 +57,7 @@ describe('getConfig', () => { "opentelemetry": { "apiSdk": undefined, "enabled": false, + "wrapApi": true, }, "rsc": { "enabled": false, diff --git a/packages/project-config/src/config.ts b/packages/project-config/src/config.ts index d975215ff972..17f9ff66b7a5 100644 --- a/packages/project-config/src/config.ts +++ b/packages/project-config/src/config.ts @@ -96,6 +96,7 @@ export interface Config { experimental: { opentelemetry: { enabled: boolean + wrapApi: boolean apiSdk?: string } studio: StudioConfig @@ -158,6 +159,7 @@ const DEFAULT_CONFIG: Config = { experimental: { opentelemetry: { enabled: false, + wrapApi: true, apiSdk: undefined, }, studio: { diff --git a/packages/realtime/package.json b/packages/realtime/package.json index 92e425088a37..b5b19511399f 100644 --- a/packages/realtime/package.json +++ b/packages/realtime/package.json @@ -26,6 +26,7 @@ "@envelop/live-query": "6.0.0", "@graphql-tools/schema": "10.0.0", "@graphql-tools/utils": "10.0.1", + "@graphql-yoga/plugin-defer-stream": "2.0.4", "@graphql-yoga/plugin-graphql-sse": "2.0.4", "@graphql-yoga/redis-event-target": "2.0.0", "@graphql-yoga/subscription": "4.0.0", diff --git a/packages/realtime/src/graphql/index.ts b/packages/realtime/src/graphql/index.ts index b85e2ecee3cc..2c6835f0ee0f 100644 --- a/packages/realtime/src/graphql/index.ts +++ b/packages/realtime/src/graphql/index.ts @@ -6,6 +6,7 @@ export { RedisLiveQueryStore, liveQueryStore, pubSub, + Repeater, } from './plugins/useRedwoodRealtime' export type { diff --git a/packages/realtime/src/graphql/plugins/useRedwoodRealtime.ts b/packages/realtime/src/graphql/plugins/useRedwoodRealtime.ts index ac18352059ca..a75736b45b25 100644 --- a/packages/realtime/src/graphql/plugins/useRedwoodRealtime.ts +++ b/packages/realtime/src/graphql/plugins/useRedwoodRealtime.ts @@ -2,6 +2,7 @@ import type { Plugin } from '@envelop/core' import { useLiveQuery } from '@envelop/live-query' import { mergeSchemas } from '@graphql-tools/schema' import { astFromDirective } from '@graphql-tools/utils' +import { useDeferStream } from '@graphql-yoga/plugin-defer-stream' import { useGraphQLSSE } from '@graphql-yoga/plugin-graphql-sse' import { createRedisEventTarget } from '@graphql-yoga/redis-event-target' import type { CreateRedisEventTargetArgs } from '@graphql-yoga/redis-event-target' @@ -12,6 +13,8 @@ import { InMemoryLiveQueryStore } from '@n1ru4l/in-memory-live-query-store' import type { execute as defaultExecute } from 'graphql' import { print } from 'graphql' +export { Repeater } from 'graphql-yoga' + /** * We want SubscriptionsGlobs type to be an object with this shape: * @@ -60,6 +63,7 @@ export type SubscribeClientType = CreateRedisEventTargetArgs['subscribeClient'] * */ export type RedwoodRealtimeOptions = { + enableDeferStream?: boolean liveQueries?: { /** * @description Redwood Realtime supports in-memory and Redis stores. @@ -232,6 +236,9 @@ export const useRedwoodRealtime = (options: RedwoodRealtimeOptions): Plugin => { if (subscriptionsEnabled) { addPlugin(useGraphQLSSE() as Plugin) } + if (options.enableDeferStream) { + addPlugin(useDeferStream() as Plugin) + } }, onContextBuilding() { return ({ extendContext }) => { diff --git a/packages/realtime/src/index.ts b/packages/realtime/src/index.ts index 674f7c106beb..b2706a4958a5 100644 --- a/packages/realtime/src/index.ts +++ b/packages/realtime/src/index.ts @@ -6,6 +6,7 @@ export { RedisLiveQueryStore, liveQueryStore, pubSub, + Repeater, } from './graphql' export type { diff --git a/packages/record/package.json b/packages/record/package.json index b3b582b200db..ce2be4551100 100644 --- a/packages/record/package.json +++ b/packages/record/package.json @@ -27,7 +27,7 @@ ] }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@prisma/client": "5.4.2", "@redwoodjs/project-config": "6.0.7", "core-js": "3.32.2" diff --git a/packages/router/package.json b/packages/router/package.json index 59d11a7b0de5..a9ce2abbd533 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -22,7 +22,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@reach/skip-nav": "0.18.0", "@redwoodjs/auth": "6.0.7", "core-js": "3.32.2" diff --git a/packages/router/src/Set.tsx b/packages/router/src/Set.tsx index 13dce2254d0b..14fbb61a57b4 100644 --- a/packages/router/src/Set.tsx +++ b/packages/router/src/Set.tsx @@ -81,7 +81,9 @@ export const isSetNode = ( ): node is ReactElement> => { return ( React.isValidElement(node) && - (node.type === Set || node.type === PrivateSet || node.type === Private) + (node.type === Set || node.type === PrivateSet || node.type === Private) && + // Don't even bother including Sets without children. They're useless. + node.props.children ) } diff --git a/packages/router/src/__tests__/analyzeRoutes.test.tsx b/packages/router/src/__tests__/analyzeRoutes.test.tsx index 90b5d6c8e2fd..030b5bbe101b 100644 --- a/packages/router/src/__tests__/analyzeRoutes.test.tsx +++ b/packages/router/src/__tests__/analyzeRoutes.test.tsx @@ -166,7 +166,7 @@ describe('AnalyzeRoutes: with homePage and Children', () => { whileLoadingPage: undefined, sets: [ { - id: 1, + id: '1', wrappers: [WrapperX], isPrivate: false, props: { @@ -186,7 +186,7 @@ describe('AnalyzeRoutes: with homePage and Children', () => { whileLoadingPage: undefined, sets: [ { - id: 1, + id: '1', wrappers: [WrapperX], isPrivate: false, props: { @@ -195,7 +195,7 @@ describe('AnalyzeRoutes: with homePage and Children', () => { }, }, { - id: 2, + id: '1.1', isPrivate: false, wrappers: [WrapperY], props: { @@ -215,7 +215,7 @@ describe('AnalyzeRoutes: with homePage and Children', () => { whileLoadingPage: undefined, sets: [ { - id: 1, + id: '1', wrappers: [WrapperX], isPrivate: false, props: { @@ -224,7 +224,7 @@ describe('AnalyzeRoutes: with homePage and Children', () => { }, }, { - id: 2, + id: '1.1', wrappers: [WrapperY], isPrivate: false, props: { @@ -288,7 +288,7 @@ describe('AnalyzeRoutes: with homePage and Children', () => { whileLoadingPage: undefined, sets: [ { - id: 1, + id: '1', wrappers: [WrapperX], isPrivate: false, props: { @@ -308,7 +308,7 @@ describe('AnalyzeRoutes: with homePage and Children', () => { whileLoadingPage: undefined, sets: [ { - id: 1, + id: '1', wrappers: [WrapperX], isPrivate: false, props: { @@ -317,7 +317,7 @@ describe('AnalyzeRoutes: with homePage and Children', () => { }, }, { - id: 2, + id: '1.1', wrappers: [WrapperY], isPrivate: false, props: { @@ -335,10 +335,9 @@ describe('AnalyzeRoutes: with homePage and Children', () => { name: 'routeC', path: '/c', whileLoadingPage: undefined, - setId: 2, sets: [ { - id: 1, + id: '1', wrappers: [WrapperX], isPrivate: false, props: { @@ -347,7 +346,7 @@ describe('AnalyzeRoutes: with homePage and Children', () => { }, }, { - id: 2, + id: '1.1', wrappers: [WrapperY], isPrivate: false, props: { @@ -452,10 +451,9 @@ describe('AnalyzeRoutes: with homePage and Children', () => { path: '/private', whileLoadingPage: undefined, page: FakePage, - setId: 1, sets: [ { - id: 1, + id: '1', wrappers: [], isPrivate: true, props: { unauthenticated: 'home' }, @@ -484,10 +482,9 @@ describe('AnalyzeRoutes: with homePage and Children', () => { path: '/private', whileLoadingPage: undefined, page: FakePage, - setId: 1, sets: [ { - id: 1, + id: '1', wrappers: [], isPrivate: true, props: { unauthenticated: 'home' }, @@ -568,7 +565,7 @@ describe('AnalyzeRoutes: with homePage and Children', () => { const { pathRouteMap, namedRoutesMap } = analyzeRoutes( RedirectedRoutes.props.children, { - currentPathName: '/simple', + currentPathName: '/does-not-exist', } ) @@ -578,7 +575,7 @@ describe('AnalyzeRoutes: with homePage and Children', () => { redirect: null, sets: [ { - id: 1, + id: '1', isPrivate: true, props: { unauthenticated: 'home' }, }, @@ -594,13 +591,13 @@ describe('AnalyzeRoutes: with homePage and Children', () => { redirect: null, sets: [ { - id: 1, + id: '1', wrappers: [], isPrivate: true, props: { unauthenticated: 'home' }, }, { - id: 2, + id: '1.1', wrappers: [], isPrivate: true, props: expect.objectContaining({ @@ -609,7 +606,7 @@ describe('AnalyzeRoutes: with homePage and Children', () => { }), }, { - id: 3, + id: '1.1.1', wrappers: [], isPrivate: true, props: { @@ -628,14 +625,14 @@ describe('AnalyzeRoutes: with homePage and Children', () => { sets: [ // Should have the first one, but also.. { - id: 1, + id: '1', wrappers: [], isPrivate: true, props: { unauthenticated: 'home' }, }, // ...the second private set's props { - id: 2, + id: '1.1', wrappers: [], isPrivate: true, props: { @@ -645,7 +642,7 @@ describe('AnalyzeRoutes: with homePage and Children', () => { }, // ...and the third private set's props { - id: 4, + id: '1.1.2', wrappers: [], isPrivate: true, props: { @@ -658,3 +655,52 @@ describe('AnalyzeRoutes: with homePage and Children', () => { }) }) }) + +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__/nestedSets.test.tsx b/packages/router/src/__tests__/nestedSets.test.tsx index c51bdc1a36b2..a251513aefa1 100644 --- a/packages/router/src/__tests__/nestedSets.test.tsx +++ b/packages/router/src/__tests__/nestedSets.test.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import * as React from 'react' import type { ReactNode } from 'react' import '@testing-library/jest-dom/extend-expect' @@ -17,6 +17,10 @@ import { Private, Set } from '../Set' const HomePage = () =>

Home Page

const Page = () =>

Page

+interface LayoutProps { + children: ReactNode +} + beforeEach(() => { window.history.pushState({}, '', '/') }) @@ -34,7 +38,7 @@ afterAll(() => { }) test('Sets nested in Private should not error out if no authenticated prop provided', () => { - const Layout1 = ({ children }: { children: ReactNode }) => ( + const Layout1 = ({ children }: LayoutProps) => (

Layout1

{children} @@ -112,3 +116,119 @@ test('Sets nested in `` should not error out if no authenticated pr '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__/set.test.tsx b/packages/router/src/__tests__/set.test.tsx index a972bf38dbea..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 = ({ children }: { children: ReactNode }) => ( +const GlobalLayout = ({ children }: LayoutProps) => (

Global Layout

{children}
This is a footer
) -const CustomWrapper = ({ children }: { children: ReactNode }) => ( +const CustomWrapper = ({ children }: LayoutProps) => (

Custom Wrapper

{children}

Custom Wrapper End

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

Layout for B

{children}
) +beforeEach(() => { + window.history.pushState({}, '', '/') +}) + test('wraps components in other components', async () => { const TestSet = () => ( @@ -157,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 b9abba0bd0c7..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' @@ -80,28 +79,20 @@ test("Doesn't destroy when navigating inside, but does when navigating bet await waitFor(() => screen.getByText('Home Page')) - // @ts-expect-error - No type gen here for routes like there is in a real app - act(() => navigate(routes.ctx1())) + act(() => navigate('/ctx-1-page')) await waitFor(() => screen.getByText('1-updatedSetValue')) - // @ts-expect-error - No type gen here for routes like there is in a real app - act(() => navigate(routes.ctx2())) + act(() => navigate('/ctx-2-page')) await waitFor(() => screen.getByText('2-updatedSetValue')) - // @ts-expect-error - No type gen here for routes like there is in a real app - act(() => navigate(routes.ctx3())) + act(() => navigate('/ctx-3-page')) await waitFor(() => screen.getByText('3-initialSetValue')) - // @ts-expect-error - No type gen here for routes like there is in a real app - 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 74bddc3beae3..bfd17acf1f41 100644 --- a/packages/router/src/router.tsx +++ b/packages/router/src/router.tsx @@ -146,7 +146,7 @@ const LocationAwareRouter: React.FC = ({ return null } - const { path, page, name, redirect, whileLoadingPage, sets, setId } = + const { path, page, name, redirect, whileLoadingPage, sets } = pathRouteMap[activeRoutePath] if (!path) { @@ -171,7 +171,6 @@ const LocationAwareRouter: React.FC = ({ {redirect && } {!redirect && page && ( = ({ interface WrappedPageProps { routeLoaderElement: ReactNode sets: Array<{ - id: number + id: string wrappers: Wrappers isPrivate: boolean props: { @@ -231,8 +230,12 @@ const WrappedPage = memo(({ routeLoaderElement, sets }: WrappedPageProps) => { // 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) => { - return React.createElement(Wrapper, set.props, acc) + let wrapped = set.wrappers.reduceRight((acc, Wrapper, index) => { + return React.createElement( + Wrapper, + { ...set.props, key: set.id + '-' + index }, + acc + ) }, acc) // If set is private, wrap it in AuthenticatedRoute diff --git a/packages/router/src/util.ts b/packages/router/src/util.ts index db49aeb78958..1b42eb05ca51 100644 --- a/packages/router/src/util.ts +++ b/packages/router/src/util.ts @@ -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,16 +473,7 @@ interface AnalyzedRoute { whileLoadingPage?: WhileLoadingPage page: PageType | null redirect: string | null - sets: Array<{ - id: number - wrappers: Wrappers - isPrivate: boolean - props: { - private?: boolean - [key: string]: unknown - } - }> - setId: number + sets: Array } export function analyzeRoutes( @@ -488,41 +489,35 @@ export function analyzeRoutes( interface RecurseParams { nodes: ReturnType whileLoadingPageFromSet?: WhileLoadingPage - sets?: Array<{ - id: number - wrappers: Wrappers - isPrivate: boolean - props: { - private?: boolean - [key: string]: unknown - } - }> - 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, sets: previousSets = [], }: RecurseParams) => { + let nextSetId = 0 + nodes.forEach((node) => { if (isValidRoute(node)) { // Rename for readability @@ -564,7 +559,6 @@ export function analyzeRoutes( path, page: null, // Redirects don't need pages. We set this to null for consistency sets: previousSets, - setId, } if (name) { @@ -596,7 +590,6 @@ export function analyzeRoutes( route.props.whileLoadingPage || whileLoadingPageFromSet, page, sets: previousSets, - setId, } // e.g. namedRoutesMap.homePage = () => '/home' @@ -606,7 +599,6 @@ export function analyzeRoutes( // @NOTE: A is also a Set if (isSetNode(node)) { - setId = setId + 1 // increase the Set id for each Set found const { children, whileLoadingPage: whileLoadingPageFromCurrentSet, @@ -621,31 +613,30 @@ export function analyzeRoutes( : [wrapFromCurrentSet] } - 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, - sets: [ - ...previousSets, - { - id: setId, - 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, - }, - ], - }) - } + 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, + }, + ], + }) } }) } @@ -660,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/structure/package.json b/packages/structure/package.json index b02b27f35a94..e048d992e9c4 100644 --- a/packages/structure/package.json +++ b/packages/structure/package.json @@ -30,7 +30,7 @@ ] }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@iarna/toml": "2.2.5", "@prisma/internals": "5.4.2", "@redwoodjs/project-config": "6.0.7", diff --git a/packages/studio/package.json b/packages/studio/package.json index e055f7cb8bf5..a76ac633deef 100644 --- a/packages/studio/package.json +++ b/packages/studio/package.json @@ -21,7 +21,7 @@ "prepublishOnly": "NODE_ENV=production yarn build" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@fastify/http-proxy": "9.2.1", "@fastify/static": "6.11.2", "@fastify/url-data": "5.3.1", diff --git a/packages/telemetry/package.json b/packages/telemetry/package.json index 1a498803e980..a223426fb5ea 100644 --- a/packages/telemetry/package.json +++ b/packages/telemetry/package.json @@ -26,7 +26,7 @@ ] }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@redwoodjs/project-config": "6.0.7", "@redwoodjs/structure": "6.0.7", "@whatwg-node/fetch": "0.9.9", diff --git a/packages/testing/package.json b/packages/testing/package.json index a5afdb2f5009..1b8713ac5cc3 100644 --- a/packages/testing/package.json +++ b/packages/testing/package.json @@ -27,7 +27,7 @@ "test:watch": "yarn test --watch" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@redwoodjs/auth": "6.0.7", "@redwoodjs/babel-config": "6.0.7", "@redwoodjs/graphql-server": "6.0.7", diff --git a/packages/vite/package.json b/packages/vite/package.json index 59a30eeeb46c..30c01bf7d8bc 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -63,7 +63,7 @@ "test:watch": "glob './src/**/__tests__/*.test.mts' --cmd='node --loader tsx --no-warnings --test --watch'" }, "dependencies": { - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@redwoodjs/internal": "6.0.7", "@redwoodjs/project-config": "6.0.7", "@redwoodjs/web": "6.0.7", diff --git a/packages/vite/src/rsc/rscRequestHandler.ts b/packages/vite/src/rsc/rscRequestHandler.ts index 115f257848d5..33e5b03df7b2 100644 --- a/packages/vite/src/rsc/rscRequestHandler.ts +++ b/packages/vite/src/rsc/rscRequestHandler.ts @@ -3,7 +3,8 @@ import type { Request, Response } from 'express' import RSDWServer from 'react-server-dom-webpack/server.node.unbundled' import { hasStatusCode } from '../lib/StatusError' -import { renderRSC } from '../waku-lib/rsc-handler-worker' + +import { renderRsc } from './rscWorkerCommunication' const { decodeReply, decodeReplyFromBusboy } = RSDWServer @@ -46,6 +47,32 @@ export function createRscRequestHandler() { 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 = '' @@ -82,7 +109,7 @@ export function createRscRequestHandler() { } try { - const pipeable = await renderRSC({ rscId, props, rsfId, args }) + 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) 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 998d51523ebf..6ef02ae1f01e 100644 --- a/packages/vite/src/runRscFeServer.ts +++ b/packages/vite/src/runRscFeServer.ts @@ -15,8 +15,8 @@ import type { Manifest as ViteBuildManifest } from 'vite' import { getConfig, getPaths } from '@redwoodjs/project-config' import { createRscRequestHandler } from './rsc/rscRequestHandler' +import { setClientEntries } from './rsc/rscWorkerCommunication' import { registerFwGlobals } from './streaming/registerGlobals' -import { setClientEntries } from './waku-lib/rsc-handler-worker' /** * TODO (STREAMING) 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/packages/web/package.json b/packages/web/package.json index ea6bc47ed047..a7e30fec1377 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -36,7 +36,7 @@ }, "dependencies": { "@apollo/client": "3.8.5", - "@babel/runtime-corejs3": "7.23.1", + "@babel/runtime-corejs3": "7.23.2", "@redwoodjs/auth": "6.0.7", "core-js": "3.32.2", "graphql": "16.8.1", diff --git a/tasks/benchmark/README.md b/tasks/benchmark/README.md deleted file mode 100644 index e3f484d11c70..000000000000 --- a/tasks/benchmark/README.md +++ /dev/null @@ -1,64 +0,0 @@ -# Benchmark Task - -This task is used to benchmark the performance of the Redwood api locally. - -## Tests - -The `tests` folder contains the k6 tests which will be executed to benchmark the api. - -Please remember that these are run by the k6 program and so you can't treat them exactly like any old javascript file. - -The tests should in most cases be hitting the `http://localhost:8911` endpoint as the test runner is running `yarn rw serve api` to start the api. - -## Setups - -The `setups` folder contains the setup scripts which will be executed before the tests are run to setup the correct environment. - -These setup scripts should be in a named folder and contain a `setup.mts` file which will be executed to perform the setup. This file must export the following: -* A `setup` function which will be executed to perform the setup. -* A `validForTests` string array which contains the names of the tests which this setup is valid for. - -## Running - -To run the benchmark tests you can run the following command: - -```bash -yarn benchmark -``` - -This will need the k6 program to be installed on your machine. You can find information about it here: https://k6.io/docs/getting-started/installation - -Running the benchmarks will do the following: -* Create a temporary redwood test project within the `/tmp/redwood-benchmark` folder - or windows equivalent. -* Link the current state of your framework into the test project. -* Run each of the setup scripts in the `setups` folder and for each one: - * Run the `setup` function. - * Build the api side. - * Start the api server. - * Run each of the appropriate tests in the `tests` folder. - * Stop the api server. - * Reset the project to its original state. - - -**Filtering tests and setups** - -You can filter the tests and setups which are run by passing command line arguments to the benchmark command. - -To limit the setups which are run you can pass a list of setup names to the `--setup` argument. For example: - -```bash -yarn benchmark --setup setup1 setup2 -``` - -To limit the tests which are run you can pass a list of test names to the `--test` argument. For example: - -```bash -yarn benchmark --test test1 test2 -``` - -You can combine these like so: -```bash -yarn benchmark --setup setup1 setup2 --test test1 test2 -``` - -By default all setups and tests will be run. diff --git a/tasks/benchmark/run-benchmarks.mts b/tasks/benchmark/run-benchmarks.mts deleted file mode 100755 index f3f3940e15d3..000000000000 --- a/tasks/benchmark/run-benchmarks.mts +++ /dev/null @@ -1,212 +0,0 @@ -#!/usr/bin/env node -/* eslint-env node, es6*/ - -import os from 'node:os' -import path from 'node:path' -import url from "node:url" - -import execa from 'execa' -import fg from 'fast-glob' -import fs from 'fs-extra' -import { hideBin } from 'yargs/helpers' -import yargs from 'yargs/yargs' -import { $ } from 'zx' - -import { buildRedwoodFramework, addFrameworkDepsToProject, cleanUp, copyFrameworkPackages, createRedwoodJSApp, initGit, runYarnInstall } from "./util/util.mjs" - -// useful consts -const __dirname = url.fileURLToPath(new URL('.', import.meta.url)); - -// Parse input -const args = yargs(hideBin(process.argv)) - .positional('project-directory', { - type: 'string', - describe: 'The project directory to run the benchmarks in', - demandOption: false, - }) - .option('setup', { default: [], type: 'array', alias: 's' }) - .option('test', { default: [], type: 'array', alias: 't' }) - .option('clean-up', { default: true, type: 'boolean' }) - .scriptName('run-benchmarks') - .example('run-benchmarks', 'Run all the benchmarks') - .example( - 'run-benchmarks /tmp/redwood-app --setup someSetup --test somTest anotherTest', - "Run the benchmarks only for the setup 'someSetup' and the tests 'someTest' and 'anotherTest'" - ) - .help() - .parseSync() - -const REDWOODJS_FRAMEWORK_PATH = path.join(__dirname, '..', '..') -const REDWOOD_PROJECT_DIRECTORY = - args._?.[0]?.toString() ?? - path.join( - os.tmpdir(), - 'redwood-benchmark', - // ":" is problematic with paths - new Date().toISOString().split(':').join('-') - ) - -const SETUPS_DIR = path.join(__dirname, 'setups') -const TESTS_DIR = path.join(__dirname, 'tests') -let cleanUpExecuted = false - -async function main() { - const divider = '~'.repeat(process.stdout.columns) - - console.log(`${divider}\nBenchmark tests\n${divider}\n`) - console.log('Benchmark tests will be run in the following directory:') - console.log(`${REDWOOD_PROJECT_DIRECTORY}\n`) - - fs.mkdirSync(REDWOOD_PROJECT_DIRECTORY, { recursive: true }) - - // Register clean up - if (args.cleanUp) { - console.log('The directory will be deleted after the tests are run') - process.on('SIGINT', () => { - if(!cleanUpExecuted){ - cleanUp({ - projectPath: REDWOOD_PROJECT_DIRECTORY, - }) - cleanUpExecuted = true - } - }) - process.on('exit', () => { - if(!cleanUpExecuted){ - cleanUp({ - projectPath: REDWOOD_PROJECT_DIRECTORY, - }) - cleanUpExecuted = true - } - }) - } - - // Get all the setups - const setups = fg - .sync('*', { - onlyDirectories: true, - cwd: SETUPS_DIR, - }) - .filter((setupDir) => { - return ( - args.setup.length === 0 || - args.setup.some((setup) => setupDir.includes(setup.toString())) - ) - }) - - if (setups.length === 0) { - console.log('\nThere are no setups to run.') - process.exit(0) - } - - // Create a test project and sync the current framework state - console.log('\nCreating a fresh project:') - - buildRedwoodFramework({ - frameworkPath: REDWOODJS_FRAMEWORK_PATH, - }) - createRedwoodJSApp({ - frameworkPath: REDWOODJS_FRAMEWORK_PATH, - projectPath: REDWOOD_PROJECT_DIRECTORY, - typescript: true - }) - addFrameworkDepsToProject({ - frameworkPath: REDWOODJS_FRAMEWORK_PATH, - projectPath: REDWOOD_PROJECT_DIRECTORY, - }) - runYarnInstall({ - projectPath: REDWOOD_PROJECT_DIRECTORY, - }) - copyFrameworkPackages({ - frameworkPath: REDWOODJS_FRAMEWORK_PATH, - projectPath: REDWOOD_PROJECT_DIRECTORY, - }) - initGit({ - projectPath: REDWOOD_PROJECT_DIRECTORY, - }) - - // zx setup - $.verbose = false - $.cwd = REDWOOD_PROJECT_DIRECTORY - $.log = () => {} - - console.log('\nThe following setups will be run:') - for(let i = 0; i < setups.length; i++){ - console.log(`- ${setups[i]}`) - } - - for (const setup of setups) { - // import the setup - const setupFile = path.join(SETUPS_DIR, setup, 'setup.mjs') - const setupModule = await import(setupFile) - const runForTests = args.test.length === 0 ? - setupModule.validForTests : - args.test.filter((test) => setupModule.validForTests.includes(test)) - - if(runForTests.length === 0){ - console.log(`\nThere are no tests to run for setup ${setup}, skipping...`) - continue - } - - // Clean up the project state - console.log(`\nCleaning up the project state...`) - await $`git reset --hard` - await $`git clean -fd` - - // Run the setup - console.log(`\nRunning setup: ${setup}\n`) - await setupModule.setup({ - projectPath: REDWOOD_PROJECT_DIRECTORY, - }) - - // Build the app - console.log('- Building the api...') - await execa('yarn', ['rw', 'build', 'api'], { - cwd: REDWOOD_PROJECT_DIRECTORY, - stdio: 'inherit' - }) - - // Run the tests - for(let i = 0; i < runForTests.length; i++){ - console.log(`\nRunning test ${i+1}/${runForTests.length}: ${runForTests[i]}`) - - // Start the server - const serverSubprocess = $`yarn rw serve api` - - // Wait for the server to be ready - let ready = false - serverSubprocess.stdout?.on('data', (data) => { - const text = Buffer.from(data).toString() - if (text.includes('API listening on')) { - ready = true - } - }) - while (!ready) { - await new Promise((resolve) => setTimeout(resolve, 100)) - } - - // Run k6 test - try { - await execa('k6', ['run', path.join(TESTS_DIR, `${runForTests[i]}.js`)], { - cwd: REDWOOD_PROJECT_DIRECTORY, - stdio: 'inherit' - }) - - // TODO: Consider collecting the results into some summary output? - } catch (_error) { - console.warn('The k6 test failed') - } - - // Stop the server - serverSubprocess.kill("SIGINT") - try { - await serverSubprocess - } catch (_error) { - // ignore - } - } - } - - process.emit('SIGINT') -} - -main() 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/k6-test/README.md b/tasks/k6-test/README.md new file mode 100644 index 000000000000..81f30fc8e63b --- /dev/null +++ b/tasks/k6-test/README.md @@ -0,0 +1,8 @@ +# K6 Task + +## Usage +``` +yarn test:k6 [project-directory] +``` + +You can pass additional command line options if you need specific behaviour. These are documented in the `--help` output of the above command. The source code within `run-k6-tests.mts` will also be helpful in understanding the behaviour. diff --git a/tasks/k6-test/run-k6-tests.mts b/tasks/k6-test/run-k6-tests.mts new file mode 100755 index 000000000000..a6cf749849f9 --- /dev/null +++ b/tasks/k6-test/run-k6-tests.mts @@ -0,0 +1,272 @@ +#!/usr/bin/env node +/* eslint-env node, es6*/ + +import os from 'node:os' +import path from 'node:path' +import url from "node:url" + +import chalk from 'chalk' +import execa, { ExecaChildProcess } from 'execa' +import fg from 'fast-glob' +import fs from 'fs-extra' +import { hideBin } from 'yargs/helpers' +import yargs from 'yargs/yargs' + +import { buildRedwoodFramework, addFrameworkDepsToProject, cleanUp, copyFrameworkPackages, createRedwoodJSApp, initGit, runYarnInstall } from "./util/util.mjs" + +// useful consts +const __dirname = url.fileURLToPath(new URL('.', import.meta.url)); + +// Parse input +const args = yargs(hideBin(process.argv)) + .positional('project-directory', { + type: 'string', + describe: 'The project directory to run the k6 tests in', + demandOption: false, + }) + .option('setup', { default: [], type: 'array', alias: 's' }) + .option('test', { default: [], type: 'array', alias: 't' }) + .option('clean-up', { default: true, type: 'boolean' }) + .option('verbose', { default: false, type: 'boolean' }) + .help() + .parseSync() + +const REDWOODJS_FRAMEWORK_PATH = path.join(__dirname, '..', '..') +const REDWOOD_PROJECT_DIRECTORY = + args._?.[0]?.toString() ?? + path.join( + os.tmpdir(), + 'redwood-k6-test', + // ":" is problematic with paths + new Date().toISOString().split(':').join('-') + ) + +const SETUPS_DIR = path.join(__dirname, 'setups') +const TESTS_DIR = path.join(__dirname, 'tests') +const API_SERVER_COMMANDS = [ + { + cmd: `node ${path.resolve(REDWOOD_PROJECT_DIRECTORY, 'node_modules/@redwoodjs/cli/dist/index.js')} serve api`, + host: 'http://localhost:8911', + }, + { + cmd: `node ${path.resolve(REDWOOD_PROJECT_DIRECTORY, 'node_modules/@redwoodjs/api-server/dist/index.js')} api`, + host: 'http://localhost:8911' + }, +] +let cleanUpExecuted = false + +let serverSubprocess: ExecaChildProcess | undefined +const startServer = async (command: string, gracePeriod?: number) => { + serverSubprocess = execa.command(command, { + cwd: REDWOOD_PROJECT_DIRECTORY, + stdio: args.verbose ? 'inherit' : 'ignore', + }) + await new Promise((r) => setTimeout(r, gracePeriod ?? 4000)) +} +const stopServer = async () => { + if (!serverSubprocess) { + return + } + serverSubprocess.cancel() + try { + await serverSubprocess + } catch (_error) { + // ignore + } +} + +async function main() { + const divider = chalk.blue('~'.repeat(process.stdout.columns)) + + console.log(`${divider}\nK6 tests\n${divider}`) + console.log('Benchmark tests will be run in the following directory:') + console.log(`${REDWOOD_PROJECT_DIRECTORY}`) + + fs.mkdirSync(REDWOOD_PROJECT_DIRECTORY, { recursive: true }) + + // Register clean up + if (args.cleanUp) { + console.log('\nThe directory will be deleted after the tests are run') + process.on('SIGINT', () => { + if (!cleanUpExecuted) { + cleanUp({ + projectPath: REDWOOD_PROJECT_DIRECTORY, + }) + cleanUpExecuted = true + } + }) + process.on('exit', () => { + if (!cleanUpExecuted) { + cleanUp({ + projectPath: REDWOOD_PROJECT_DIRECTORY, + }) + cleanUpExecuted = true + } + }) + } + + // Get all the setups + const setups = fg + .sync('*', { + onlyDirectories: true, + cwd: SETUPS_DIR, + }) + .filter((setupDir) => { + return ( + args.setup.length === 0 || + args.setup.some((setup) => setupDir.includes(setup.toString())) + ) + }) + + if (setups.length === 0) { + console.log('There are no setups to run.') + process.exit(0) + } + + // Create a test project and sync the current framework state + console.log('\nCreating a fresh project:') + + console.log('- building the framework') + buildRedwoodFramework({ + frameworkPath: REDWOODJS_FRAMEWORK_PATH, + verbose: args.verbose, + }) + console.log('- creating a new project') + createRedwoodJSApp({ + frameworkPath: REDWOODJS_FRAMEWORK_PATH, + projectPath: REDWOOD_PROJECT_DIRECTORY, + typescript: true, + verbose: args.verbose, + }) + console.log('- syncing the framework dependencies') + addFrameworkDepsToProject({ + frameworkPath: REDWOODJS_FRAMEWORK_PATH, + projectPath: REDWOOD_PROJECT_DIRECTORY, + verbose: args.verbose, + }) + console.log('- installing dependencies') + runYarnInstall({ + projectPath: REDWOOD_PROJECT_DIRECTORY, + verbose: args.verbose, + }) + console.log('- copying framework packages') + copyFrameworkPackages({ + frameworkPath: REDWOODJS_FRAMEWORK_PATH, + projectPath: REDWOOD_PROJECT_DIRECTORY, + verbose: args.verbose, + }) + console.log('- initializing git') + initGit({ + projectPath: REDWOOD_PROJECT_DIRECTORY, + verbose: args.verbose, + }) + + // Results collection + const results = {} + + console.log('The following setups will be run:') + for (let i = 0; i < setups.length; i++) { + console.log(`- ${setups[i]}`) + } + + for (const setup of setups) { + // import the setup + const setupFile = path.join(SETUPS_DIR, setup, 'setup.mjs') + const setupModule = await import(setupFile) + const runForTests = args.test.length === 0 ? + setupModule.validForTests : + args.test.filter((test) => setupModule.validForTests.includes(test)) + + console.log(`\n${divider}\nPreparing setup: ${setup}\n${divider}`) + + if (runForTests.length === 0) { + console.log(`There are no tests to run for setup ${setup}, skipping...`) + continue + } + + // Clean up the project state + console.log(`Cleaning up the project state...`) + await execa('git', ['reset', '--hard'], { + cwd: REDWOOD_PROJECT_DIRECTORY, + stdio: args.verbose ? 'inherit' : 'ignore', + }) + await execa('git', ['clean', '-fd'], { + cwd: REDWOOD_PROJECT_DIRECTORY, + stdio: args.verbose ? 'inherit' : 'ignore', + }) + + // Run the setup + console.log(`Running setup: ${setup}`) + await setupModule.setup({ + projectPath: REDWOOD_PROJECT_DIRECTORY, + }) + + // Build the app + console.log('Building the project...') + await execa('yarn', ['rw', 'build'], { + cwd: REDWOOD_PROJECT_DIRECTORY, + stdio: args.verbose ? 'inherit' : 'ignore', + }) + + // Run the tests + for (let i = 0; i < runForTests.length; i++) { + // Run for different server commands + for (let j = 0; j < API_SERVER_COMMANDS.length; j++) { + console.log(`\n${divider}`) + console.log(`Running test ${i * API_SERVER_COMMANDS.length + j + 1}/${runForTests.length * API_SERVER_COMMANDS.length}: ${runForTests[i]}`) + console.log(chalk.dim(API_SERVER_COMMANDS[j].cmd)) + console.log(`${divider}`) + + // Start the server + await startServer(API_SERVER_COMMANDS[j].cmd, setupModule.startupGracePeriod) + + // Run k6 test + let passed = false + try { + await execa('k6', ['run', path.join(TESTS_DIR, `${runForTests[i]}.js`), '--env', `TEST_HOST=${API_SERVER_COMMANDS[j].host}`], { + cwd: REDWOOD_PROJECT_DIRECTORY, + stdio: 'inherit', + }) + passed = true + } catch (_error) { + // ignore + } + + results[setup] ??= {} + results[setup][runForTests[i]] ??= {} + results[setup][runForTests[i]][API_SERVER_COMMANDS[j].cmd] = fs.readJSONSync(path.join(REDWOOD_PROJECT_DIRECTORY, 'summary.json'), { + throws: false, + flag: 'r', + encoding: 'utf-8', + }) ?? {} + results[setup][runForTests[i]][API_SERVER_COMMANDS[j].cmd].passed = passed + + // Stop the server + await stopServer() + } + } + } + + // Print results + console.log(`\n${divider}\nResults:\n${divider}`) + for (const setup in results) { + console.log(chalk.bgBlue(`\nSetup: ${setup}`)) + for (const test in results[setup]) { + for (const serverCommand in results[setup][test]) { + const passed = results[setup][test][serverCommand].passed + const bgColor = passed ? chalk.bgGreen : chalk.bgRed + const bgPrefix = bgColor(' ') + console.log(passed ? bgColor(' PASS ') : bgColor(' FAIL ')) + console.log(`${bgPrefix} Test: ${test} [${serverCommand}]`) + console.log(`${bgPrefix} Requests: ${results[setup][test][serverCommand].metrics?.http_reqs.values.count}`) + console.log(`${bgPrefix} Duration (p90): ${results[setup][test][serverCommand].metrics?.http_req_duration.values['p(90)'].toFixed(3)}`) + console.log(`${bgPrefix} TTFB (p90): ${results[setup][test][serverCommand].metrics?.http_req_waiting.values['p(90)'].toFixed(3)}`) + console.log() + } + } + } + + process.emit('SIGINT') +} + +main() diff --git a/tasks/benchmark/setups/context_magic_number/setup.mts b/tasks/k6-test/setups/context_magic_number/setup.mts similarity index 100% rename from tasks/benchmark/setups/context_magic_number/setup.mts rename to tasks/k6-test/setups/context_magic_number/setup.mts diff --git a/tasks/benchmark/setups/context_magic_number/templates/benchmark.sdl.ts b/tasks/k6-test/setups/context_magic_number/templates/benchmark.sdl.ts similarity index 100% rename from tasks/benchmark/setups/context_magic_number/templates/benchmark.sdl.ts rename to tasks/k6-test/setups/context_magic_number/templates/benchmark.sdl.ts diff --git a/tasks/benchmark/setups/context_magic_number/templates/benchmarks.ts b/tasks/k6-test/setups/context_magic_number/templates/benchmarks.ts similarity index 63% rename from tasks/benchmark/setups/context_magic_number/templates/benchmarks.ts rename to tasks/k6-test/setups/context_magic_number/templates/benchmarks.ts index f638811bceb4..0d8be240ebad 100644 --- a/tasks/benchmark/setups/context_magic_number/templates/benchmarks.ts +++ b/tasks/k6-test/setups/context_magic_number/templates/benchmarks.ts @@ -2,25 +2,19 @@ import type { MutationResolvers } from 'types/graphql' import { setContext } from '@redwoodjs/graphql-server' -import { logger } from 'src/lib/logger' - export const magicNumber: MutationResolvers['magicNumber'] = async ({ value, }) => { setContext({ - // ...context, magicNumber: value, }) - // context.magicNumber = value const sleep = Math.random() * 200 - // logger.info(`Sleeping for ${sleep}ms`) await new Promise((resolve) => setTimeout(resolve, sleep)) const numberFromContext = (context.magicNumber ?? -1) as number if (value !== numberFromContext) { - logger.error(`Expected ${value} but got ${numberFromContext}`) - // throw new Error(`Expected ${value} but got ${numberFromContext}`) + throw new Error(`Expected ${value} but got ${numberFromContext}`) } return { value: numberFromContext } diff --git a/tasks/benchmark/setups/context_magic_number/templates/func.ts b/tasks/k6-test/setups/context_magic_number/templates/func.ts similarity index 84% rename from tasks/benchmark/setups/context_magic_number/templates/func.ts rename to tasks/k6-test/setups/context_magic_number/templates/func.ts index 5e4b957cd351..6132e50942ef 100644 --- a/tasks/benchmark/setups/context_magic_number/templates/func.ts +++ b/tasks/k6-test/setups/context_magic_number/templates/func.ts @@ -2,8 +2,6 @@ import type { APIGatewayProxyEvent, Context } from 'aws-lambda' import { setContext } from '@redwoodjs/graphql-server' -import { logger } from 'src/lib/logger' - export const handler = async ( event: APIGatewayProxyEvent, _context: Context @@ -19,7 +17,7 @@ export const handler = async ( const numberFromContext = (context.magicNumber ?? -1) as number if (magicNumber !== numberFromContext) { - logger.error(`Expected ${magicNumber} but got ${numberFromContext}`) + throw new Error(`Expected ${magicNumber} but got ${numberFromContext}`) } return { diff --git a/tasks/benchmark/setups/scalable_graphql_schema/setup.mts b/tasks/k6-test/setups/scalable_graphql_schema/setup.mts similarity index 98% rename from tasks/benchmark/setups/scalable_graphql_schema/setup.mts rename to tasks/k6-test/setups/scalable_graphql_schema/setup.mts index c72bd7e981ef..97fed5955577 100644 --- a/tasks/benchmark/setups/scalable_graphql_schema/setup.mts +++ b/tasks/k6-test/setups/scalable_graphql_schema/setup.mts @@ -12,6 +12,8 @@ export const validForTests = [ "scalable_graphql_schema", ] +export const startupGracePeriod = 8000 + export function setup({ projectPath }: { projectPath: string }) { const modelCount = 1024 diff --git a/tasks/benchmark/setups/scalable_graphql_schema/templates/definition.sdl.ts b/tasks/k6-test/setups/scalable_graphql_schema/templates/definition.sdl.ts similarity index 100% rename from tasks/benchmark/setups/scalable_graphql_schema/templates/definition.sdl.ts rename to tasks/k6-test/setups/scalable_graphql_schema/templates/definition.sdl.ts diff --git a/tasks/benchmark/setups/scalable_graphql_schema/templates/implementation.ts b/tasks/k6-test/setups/scalable_graphql_schema/templates/implementation.ts similarity index 100% rename from tasks/benchmark/setups/scalable_graphql_schema/templates/implementation.ts rename to tasks/k6-test/setups/scalable_graphql_schema/templates/implementation.ts diff --git a/tasks/benchmark/setups/scalable_graphql_schema/templates/relation.sdl.ts b/tasks/k6-test/setups/scalable_graphql_schema/templates/relation.sdl.ts similarity index 100% rename from tasks/benchmark/setups/scalable_graphql_schema/templates/relation.sdl.ts rename to tasks/k6-test/setups/scalable_graphql_schema/templates/relation.sdl.ts diff --git a/tasks/benchmark/tests/context_functions.js b/tasks/k6-test/tests/context_functions.js similarity index 51% rename from tasks/benchmark/tests/context_functions.js rename to tasks/k6-test/tests/context_functions.js index 5e7eb0ebfa1e..6c8f3b04da68 100644 --- a/tasks/benchmark/tests/context_functions.js +++ b/tasks/k6-test/tests/context_functions.js @@ -7,9 +7,9 @@ const contextErrorCounter = new Counter('Context_Errors') export const options = { stages: [ - { duration: '2s', target: 8 }, - { duration: '16s', target: 8 }, - { duration: '2s', target: 0 }, + { duration: '1s', target: 8 }, + { duration: '6s', target: 8 }, + { duration: '1s', target: 0 }, ], thresholds: { Request_Failures: ['count<1'], @@ -19,28 +19,7 @@ export const options = { export default function () { const magicNumber = Math.floor(Math.random() * 16000000) - - const payload = (value) => { - return JSON.stringify({ - query: `mutation MagicNumber($value: Int!) { - magicNumber(value: $value) { - value - } - }`, - variables: { - value, - }, - operationName: 'MagicNumber', - }) - } - - const url = 'http://localhost:8911/graphql' - const params = { - headers: { - 'Content-Type': 'application/json', - }, - } - const res = http.post(url, payload(magicNumber), params) + const res = http.get(`${__ENV.TEST_HOST}/func?magicNumber=${magicNumber}`) const requestPassed = check(res, { 'status was 200': (r) => r.status == 200, @@ -50,9 +29,16 @@ export default function () { } const contextPassed = check(res, { - 'correct magic number': (r) => r.body.includes(`"value":${magicNumber}}`), + 'correct magic number': (r) => + r.body != null && r.body.includes(`"value":"${magicNumber}"}`), }) if (!contextPassed) { contextErrorCounter.add(1) } } + +export function handleSummary(data) { + return { + 'summary.json': JSON.stringify(data), + } +} diff --git a/tasks/benchmark/tests/context_graphql.js b/tasks/k6-test/tests/context_graphql.js similarity index 76% rename from tasks/benchmark/tests/context_graphql.js rename to tasks/k6-test/tests/context_graphql.js index 5e7eb0ebfa1e..2415dff66172 100644 --- a/tasks/benchmark/tests/context_graphql.js +++ b/tasks/k6-test/tests/context_graphql.js @@ -7,9 +7,9 @@ const contextErrorCounter = new Counter('Context_Errors') export const options = { stages: [ - { duration: '2s', target: 8 }, - { duration: '16s', target: 8 }, - { duration: '2s', target: 0 }, + { duration: '1s', target: 8 }, + { duration: '6s', target: 8 }, + { duration: '1s', target: 0 }, ], thresholds: { Request_Failures: ['count<1'], @@ -34,7 +34,7 @@ export default function () { }) } - const url = 'http://localhost:8911/graphql' + const url = `${__ENV.TEST_HOST}/graphql` const params = { headers: { 'Content-Type': 'application/json', @@ -50,9 +50,16 @@ export default function () { } const contextPassed = check(res, { - 'correct magic number': (r) => r.body.includes(`"value":${magicNumber}}`), + 'correct magic number': (r) => + r.body != null && r.body.includes(`"value":${magicNumber}}`), }) if (!contextPassed) { contextErrorCounter.add(1) } } + +export function handleSummary(data) { + return { + 'summary.json': JSON.stringify(data), + } +} diff --git a/tasks/benchmark/tests/scalable_graphql_schema.js b/tasks/k6-test/tests/scalable_graphql_schema.js similarity index 75% rename from tasks/benchmark/tests/scalable_graphql_schema.js rename to tasks/k6-test/tests/scalable_graphql_schema.js index ae7e418349d6..bebb745e295e 100644 --- a/tasks/benchmark/tests/scalable_graphql_schema.js +++ b/tasks/k6-test/tests/scalable_graphql_schema.js @@ -6,9 +6,9 @@ const requestFailureCounter = new Counter('Request_Failures') export const options = { stages: [ - { duration: '2s', target: 8 }, - { duration: '16s', target: 8 }, - { duration: '2s', target: 0 }, + { duration: '1s', target: 8 }, + { duration: '6s', target: 8 }, + { duration: '1s', target: 0 }, ], thresholds: { Request_Failures: ['count<1'], @@ -41,7 +41,7 @@ export default function () { }) } - const url = 'http://localhost:8911/graphql' + const url = `${__ENV.TEST_HOST}/graphql` const params = { headers: { 'Content-Type': 'application/json', @@ -51,9 +51,16 @@ export default function () { const requestPassed = check(res, { 'status was 200': (r) => r.status == 200, - 'content matched': (r) => r.body.includes(`"typeName":"T${i}"`), + 'content matched': (r) => + r.body != null && r.body.includes(`"typeName":"T${i}"`), }) if (!requestPassed) { requestFailureCounter.add(1) } } + +export function handleSummary(data) { + return { + 'summary.json': JSON.stringify(data), + } +} diff --git a/tasks/benchmark/util/util.mts b/tasks/k6-test/util/util.mts similarity index 84% rename from tasks/benchmark/util/util.mts rename to tasks/k6-test/util/util.mts index 43057c5c0c97..e76f4df0c485 100644 --- a/tasks/benchmark/util/util.mts +++ b/tasks/k6-test/util/util.mts @@ -4,8 +4,9 @@ import fg from "fast-glob" import fs from "fs-extra" import execa from "execa" import { rimrafSync } from 'rimraf' +import chalk from "chalk" -export function buildRedwoodFramework({frameworkPath}: {frameworkPath: string}) { +export function buildRedwoodFramework({frameworkPath, verbose}: {frameworkPath: string, verbose: boolean}) { try { const files = fg.sync('packages/**/dist', { onlyDirectories: true, @@ -18,7 +19,7 @@ export function buildRedwoodFramework({frameworkPath}: {frameworkPath: string}) { cwd: frameworkPath, shell: true, - stdio: 'inherit', + stdio: verbose ? 'inherit': 'ignore', } ) } catch (e) { @@ -30,7 +31,7 @@ export function buildRedwoodFramework({frameworkPath}: {frameworkPath: string}) } } -export function createRedwoodJSApp({ frameworkPath, projectPath, typescript }: { frameworkPath: string, projectPath: string, typescript: boolean }) { +export function createRedwoodJSApp({ frameworkPath, projectPath, typescript, verbose }: { frameworkPath: string, projectPath: string, typescript: boolean, verbose: boolean }) { try { execa.sync( 'yarn node dist/create-redwood-app.js', @@ -45,7 +46,7 @@ export function createRedwoodJSApp({ frameworkPath, projectPath, typescript }: { cwd: path.join(frameworkPath, 'packages/create-redwood-app'), env: { REDWOOD_CI: '1' }, shell: true, - stdio: 'inherit', + stdio: verbose ? 'inherit' : 'ignore', } ) @@ -79,15 +80,17 @@ export function createRedwoodJSApp({ frameworkPath, projectPath, typescript }: { export function addFrameworkDepsToProject({ frameworkPath, projectPath, + verbose }: { frameworkPath: string projectPath: string + verbose: boolean }) { try { execa.sync('yarn project:deps', { cwd: frameworkPath, shell: true, - stdio: 'inherit', + stdio: verbose ? 'inherit' : 'ignore', env: { RWFW_PATH: frameworkPath, RWJS_CWD: projectPath, @@ -107,15 +110,17 @@ export function addFrameworkDepsToProject({ export function copyFrameworkPackages({ frameworkPath, projectPath, + verbose }: { frameworkPath: string projectPath: string + verbose: boolean }) { try { execa.sync('yarn project:copy', { cwd: frameworkPath, shell: true, - stdio: 'inherit', + stdio: verbose ? 'inherit' : 'ignore', env: { RWFW_PATH: frameworkPath, RWJS_CWD: projectPath, @@ -132,14 +137,16 @@ export function copyFrameworkPackages({ export function runYarnInstall({ projectPath, + verbose }: { projectPath: string + verbose: boolean }) { try { execa.sync('yarn install', { cwd: projectPath, shell: true, - stdio: 'inherit', + stdio: verbose ? 'inherit' : 'ignore', }) } catch (e) { if (e.signal !== 'SIGINT') { @@ -152,20 +159,22 @@ export function runYarnInstall({ export function initGit({ projectPath, + verbose }: { projectPath: string + verbose: boolean }) { try { console.log('Initializing Git') execa.sync('git init --initial-branch main && git add .', { cwd: projectPath, shell: true, - stdio: 'inherit', + stdio: verbose ? 'inherit' : 'ignore', }) execa.sync('git commit -a --message=init --no-gpg-sign', { cwd: projectPath, shell: true, - stdio: 'inherit', + stdio: verbose ? 'inherit' : 'ignore', }) } catch (e) { if (e.signal !== 'SIGINT') { @@ -183,7 +192,7 @@ export function cleanUp({ }: { projectPath: string }) { - const divider = '~'.repeat(process.stdout.columns) + const divider = chalk.blue('~'.repeat(process.stdout.columns)) console.log(`\n${divider}`) console.log('Cleaning up files (may take a few seconds)...') if (fs.existsSync(projectPath)) { 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/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 601bcc027e52..57418c80df2e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -407,33 +407,33 @@ __metadata: languageName: node linkType: hard -"@babel/compat-data@npm:^7.20.5, @babel/compat-data@npm:^7.22.20, @babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9": - version: 7.22.20 - resolution: "@babel/compat-data@npm:7.22.20" - checksum: 73c0f7cf4a1181a0a58bbee6a8b69dc4ba1beec1e764686a586db067e8160044d3a28da0a3542f044f3f31fa662ab22fd061dfe3fc9520dc1cee2252f460db30 +"@babel/compat-data@npm:^7.20.5, @babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9, @babel/compat-data@npm:^7.23.2": + version: 7.23.2 + resolution: "@babel/compat-data@npm:7.23.2" + checksum: 0397a08c3e491696cc1b12cf0879bf95fc550bfc6ef524d5a9452981aa0e192a958b2246debfb230fa22718fac473cc5a36616f89b1ad6e7e52055732cd374a1 languageName: node linkType: hard "@babel/core@npm:^7.11.1, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.12.9, @babel/core@npm:^7.13.16, @babel/core@npm:^7.14.0, @babel/core@npm:^7.21.3, @babel/core@npm:^7.22.20, @babel/core@npm:^7.22.9, @babel/core@npm:^7.7.5": - version: 7.23.0 - resolution: "@babel/core@npm:7.23.0" + version: 7.23.2 + resolution: "@babel/core@npm:7.23.2" dependencies: "@ampproject/remapping": ^2.2.0 "@babel/code-frame": ^7.22.13 "@babel/generator": ^7.23.0 "@babel/helper-compilation-targets": ^7.22.15 "@babel/helper-module-transforms": ^7.23.0 - "@babel/helpers": ^7.23.0 + "@babel/helpers": ^7.23.2 "@babel/parser": ^7.23.0 "@babel/template": ^7.22.15 - "@babel/traverse": ^7.23.0 + "@babel/traverse": ^7.23.2 "@babel/types": ^7.23.0 convert-source-map: ^2.0.0 debug: ^4.1.0 gensync: ^1.0.0-beta.2 json5: ^2.2.3 semver: ^6.3.1 - checksum: ba3604b28de28cdb07d7829f67127b03ad2e826c4e28a0560a037c8bbe16b8dc8cdb8baf344e916ad3c28c63aab88c1a1a38f5e3df6047ab79c910b41bb3a4e8 + checksum: 14ad6e0a3ac0085dc008e7fb0c8513f0a3e39f2ab883a964a89ef1311338d49cf085c94cb6165c07fdec0fdcc6e865ce4811253c479f9f45ac375226dfe3ad3b languageName: node linkType: hard @@ -538,9 +538,9 @@ __metadata: languageName: node linkType: hard -"@babel/helper-define-polyfill-provider@npm:^0.4.2": - version: 0.4.2 - resolution: "@babel/helper-define-polyfill-provider@npm:0.4.2" +"@babel/helper-define-polyfill-provider@npm:^0.4.3": + version: 0.4.3 + resolution: "@babel/helper-define-polyfill-provider@npm:0.4.3" dependencies: "@babel/helper-compilation-targets": ^7.22.6 "@babel/helper-plugin-utils": ^7.22.5 @@ -549,7 +549,7 @@ __metadata: resolve: ^1.14.2 peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: 2f4905e3dba478f53d41925a66711dfbdb63d759a59adfc4951eca3e132ac3a0bbcb39237f756fe243c2e8ee6e849afbe357e5520f55df210dcf26838357b9a1 + checksum: 0007035157e0d32ee9cb4ca319b89d6f3705523383efe52a59eb3d4dfa2ed08c5147e49c10a6e6d69c15221d89c76c8e5875475d6710fb44a5c37b8e69388e40 languageName: node linkType: hard @@ -597,7 +597,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.22.5, @babel/helper-module-transforms@npm:^7.22.9, @babel/helper-module-transforms@npm:^7.23.0": +"@babel/helper-module-transforms@npm:^7.22.5, @babel/helper-module-transforms@npm:^7.23.0": version: 7.23.0 resolution: "@babel/helper-module-transforms@npm:7.23.0" dependencies: @@ -628,16 +628,16 @@ __metadata: languageName: node linkType: hard -"@babel/helper-remap-async-to-generator@npm:^7.22.5, @babel/helper-remap-async-to-generator@npm:^7.22.9": - version: 7.22.9 - resolution: "@babel/helper-remap-async-to-generator@npm:7.22.9" +"@babel/helper-remap-async-to-generator@npm:^7.22.20, @babel/helper-remap-async-to-generator@npm:^7.22.5": + version: 7.22.20 + resolution: "@babel/helper-remap-async-to-generator@npm:7.22.20" dependencies: "@babel/helper-annotate-as-pure": ^7.22.5 - "@babel/helper-environment-visitor": ^7.22.5 - "@babel/helper-wrap-function": ^7.22.9 + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-wrap-function": ^7.22.20 peerDependencies: "@babel/core": ^7.0.0 - checksum: e753f19726846df26a13a304632aff2bc6e437201f27eecc7ba12db04b9175062da307e72512cf4761e659ec82cb71016352acd83fbe5e527f4b881ce1e633e8 + checksum: aa93aa74250b636d477e8d863fbe59d4071f8c2654841b7ac608909e480c1cf3ff7d7af5a4038568829ad09d810bb681668cbe497d9c89ba5c352793dc9edf1e languageName: node linkType: hard @@ -702,25 +702,25 @@ __metadata: languageName: node linkType: hard -"@babel/helper-wrap-function@npm:^7.22.9": - version: 7.22.10 - resolution: "@babel/helper-wrap-function@npm:7.22.10" +"@babel/helper-wrap-function@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-wrap-function@npm:7.22.20" dependencies: "@babel/helper-function-name": ^7.22.5 - "@babel/template": ^7.22.5 - "@babel/types": ^7.22.10 - checksum: 96d49c4dc825ea3a2532bbb8e748a6969c30de18c102124884d15b8038c48e07adf6e87d33f69deee0cdd71cd632a81ce63b8732918a67372629d18e903a7ba3 + "@babel/template": ^7.22.15 + "@babel/types": ^7.22.19 + checksum: 97b5f42ff4d305318ff2f99a5f59d3e97feff478333b2d893c4f85456d3c66372070f71d7bf9141f598c8cf2741c49a15918193633c427a88d170d98eb8c46eb languageName: node linkType: hard -"@babel/helpers@npm:^7.23.0": - version: 7.23.1 - resolution: "@babel/helpers@npm:7.23.1" +"@babel/helpers@npm:^7.23.2": + version: 7.23.2 + resolution: "@babel/helpers@npm:7.23.2" dependencies: "@babel/template": ^7.22.15 - "@babel/traverse": ^7.23.0 + "@babel/traverse": ^7.23.2 "@babel/types": ^7.23.0 - checksum: ae5a34bb60a0d8bbf9dc4273d90cd5b9499c048f11e2f0df1b033ba3ef3876b96a411374817a20bb24e69619853a04f9a4e7d01b3d1cef5e0c054b9bce9e3128 + checksum: 3a6a939c5277a27486e7c626812f0643b35d1c053ac2eb66911f5ae6c0a4e4bcdd40750eba36b766b0ee8a753484287f50ae56232a5f8f2947116723e44b9e35 languageName: node linkType: hard @@ -798,9 +798,9 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-proposal-decorators@npm:7.23.0": - version: 7.23.0 - resolution: "@babel/plugin-proposal-decorators@npm:7.23.0" +"@babel/plugin-proposal-decorators@npm:7.23.2": + version: 7.23.2 + resolution: "@babel/plugin-proposal-decorators@npm:7.23.2" dependencies: "@babel/helper-create-class-features-plugin": ^7.22.15 "@babel/helper-plugin-utils": ^7.22.5 @@ -809,7 +809,7 @@ __metadata: "@babel/plugin-syntax-decorators": ^7.22.10 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 983e7113f9ca3b2ae632869f71accec48cb652d68840697c3977071d44879657ca6b4427ed02e76e448e385d0feca9bd3d40edfaf1530c6c6c25fe8b97d46689 + checksum: 0936f1ca4d0ead4b0092987c9c99f9ea16fc7378dba09dc799dc8d86671ca15d16c41103064858882911221c51239efca1ef63149913b83a2f663036bb51dccf languageName: node linkType: hard @@ -1127,17 +1127,17 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-async-generator-functions@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/plugin-transform-async-generator-functions@npm:7.22.15" +"@babel/plugin-transform-async-generator-functions@npm:^7.23.2": + version: 7.23.2 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.23.2" dependencies: - "@babel/helper-environment-visitor": ^7.22.5 + "@babel/helper-environment-visitor": ^7.22.20 "@babel/helper-plugin-utils": ^7.22.5 - "@babel/helper-remap-async-to-generator": ^7.22.9 + "@babel/helper-remap-async-to-generator": ^7.22.20 "@babel/plugin-syntax-async-generators": ^7.8.4 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: e6fea97d765c57d1bf592a2bc15b1dd0ee6247b06d2fed5c468cc9a4f4ba790b407a061f6c42cc68cd3dc18481415c6d2ffe5abc7afb23993a79a9147a232195 + checksum: 16d7bd5dbd67991ab320a46ada19a9a0c8364725603c731f152afc98ee8764dc738c93f081a7560906d265b78c376bccabf3e31b9f99071c8982a6f9c8e2ac45 languageName: node linkType: hard @@ -1165,14 +1165,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-block-scoping@npm:^7.0.0, @babel/plugin-transform-block-scoping@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/plugin-transform-block-scoping@npm:7.22.15" +"@babel/plugin-transform-block-scoping@npm:^7.0.0, @babel/plugin-transform-block-scoping@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/plugin-transform-block-scoping@npm:7.23.0" dependencies: "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 8becbcd251c4d011ef12c6652c22528e352d4b7ca2d62d7ce8f87c23777aeb7bb760a512aed8b400b116324516ffb619501ece04f18747f7ce5618092d6a1c74 + checksum: f5d0822a4e2bb3a0b5172f01f8c107999b880f0e538a9c1bae3c7720e85d8d117a67167f5e8eba909e0ec3db67be3b30e7f5c83211dd4be5c7096222071571be languageName: node linkType: hard @@ -1232,14 +1232,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-destructuring@npm:^7.0.0, @babel/plugin-transform-destructuring@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/plugin-transform-destructuring@npm:7.22.15" +"@babel/plugin-transform-destructuring@npm:^7.0.0, @babel/plugin-transform-destructuring@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/plugin-transform-destructuring@npm:7.23.0" dependencies: "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: fbff08ea3fc5e89f3f6f0f305dc336a79e57c86111bfe224b83ed1a30ac8be97522196dc1a7fb1b18f400ac6e252eb4d2135b841f52628afe245c6d8437d2c14 + checksum: 038505eabdde2e1bb3bb904e50292b263d61d35e18660f751e7753b5723e2a5a5903a493290d772c8598da98c2c904b7cf45552ad1c11636fcb78f60754abd53 languageName: node linkType: hard @@ -1384,19 +1384,19 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-modules-amd@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-modules-amd@npm:7.22.5" +"@babel/plugin-transform-modules-amd@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/plugin-transform-modules-amd@npm:7.23.0" dependencies: - "@babel/helper-module-transforms": ^7.22.5 + "@babel/helper-module-transforms": ^7.23.0 "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 157ae3b58a50ca52e361860ecab2b608bc9228ea6c760112a35302990976f8936b8d75a2b21925797eed7b3bab4930a3f447193127afef9a21b7b6463ff0b422 + checksum: dda02864029ff66955e21d19c3d245aad69792b75e748de1391403bc86c8e9720b4f320b0db8413a29c11ba63b168146cf849180b5677bc6a74bfd085d20376d languageName: node linkType: hard -"@babel/plugin-transform-modules-commonjs@npm:^7.0.0, @babel/plugin-transform-modules-commonjs@npm:^7.13.8, @babel/plugin-transform-modules-commonjs@npm:^7.22.15, @babel/plugin-transform-modules-commonjs@npm:^7.23.0": +"@babel/plugin-transform-modules-commonjs@npm:^7.0.0, @babel/plugin-transform-modules-commonjs@npm:^7.13.8, @babel/plugin-transform-modules-commonjs@npm:^7.23.0": version: 7.23.0 resolution: "@babel/plugin-transform-modules-commonjs@npm:7.23.0" dependencies: @@ -1409,17 +1409,17 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-modules-systemjs@npm:^7.22.11": - version: 7.22.11 - resolution: "@babel/plugin-transform-modules-systemjs@npm:7.22.11" +"@babel/plugin-transform-modules-systemjs@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.23.0" dependencies: "@babel/helper-hoist-variables": ^7.22.5 - "@babel/helper-module-transforms": ^7.22.9 + "@babel/helper-module-transforms": ^7.23.0 "@babel/helper-plugin-utils": ^7.22.5 - "@babel/helper-validator-identifier": ^7.22.5 + "@babel/helper-validator-identifier": ^7.22.20 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: c484eedf57129a1f0c29b16da73dd77fc241faf14a9f96f4a84853372e9cd69a18555e2a2112ebfdd8f4d6ccd7943525c48cf06a07bc6ec0e473e4049e04fdd8 + checksum: 04c5cef7d6921bb9c9073cea389289099124e78cd1e3b7e020e3c085d486b48efadd9a42c0c0d963a9b1c3d5465c3151229092ea719997e53427f36935c84178 languageName: node linkType: hard @@ -1521,16 +1521,16 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-optional-chaining@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/plugin-transform-optional-chaining@npm:7.22.15" +"@babel/plugin-transform-optional-chaining@npm:^7.22.15, @babel/plugin-transform-optional-chaining@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.23.0" dependencies: "@babel/helper-plugin-utils": ^7.22.5 "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 "@babel/plugin-syntax-optional-chaining": ^7.8.3 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: d6437864209ef7884c36cd6122c7b3553b6ea48e4e2a7dc070741d20a96f94deac5b23360b0d953d358e6cb6c991c6831e6601fac68f1a206b487266d7a63807 + checksum: 2bf605b908c75f8d7616e8be52e4656983f2b027032260fbf5279f28297a67a1a28ec3ed60cd5760537dbd08a021246b8092ce06fb2418884390230b807142b3 languageName: node linkType: hard @@ -1676,19 +1676,19 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-runtime@npm:7.22.15": - version: 7.22.15 - resolution: "@babel/plugin-transform-runtime@npm:7.22.15" +"@babel/plugin-transform-runtime@npm:7.23.2": + version: 7.23.2 + resolution: "@babel/plugin-transform-runtime@npm:7.23.2" dependencies: "@babel/helper-module-imports": ^7.22.15 "@babel/helper-plugin-utils": ^7.22.5 - babel-plugin-polyfill-corejs2: ^0.4.5 - babel-plugin-polyfill-corejs3: ^0.8.3 - babel-plugin-polyfill-regenerator: ^0.5.2 + babel-plugin-polyfill-corejs2: ^0.4.6 + babel-plugin-polyfill-corejs3: ^0.8.5 + babel-plugin-polyfill-regenerator: ^0.5.3 semver: ^6.3.1 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: a01c4bc83c720e55367de978ab5c93ed6e27cd0f5e932c3628df6aed4331ee876868a3bf9a8c588aecf1ae2894dd5a6ffb21362af19b232d9fd2e836af431828 + checksum: 440291cd42e51c3f8789a0bd45cebbf597cf5d4ee4185050f1151f579465db016902054c50684e288342a03c9f1af8cec365fc02d85d14dc2b2a30ad5eb07c42 languageName: node linkType: hard @@ -1810,10 +1810,10 @@ __metadata: linkType: hard "@babel/preset-env@npm:^7.22.20, @babel/preset-env@npm:^7.22.9": - version: 7.22.20 - resolution: "@babel/preset-env@npm:7.22.20" + version: 7.23.2 + resolution: "@babel/preset-env@npm:7.23.2" dependencies: - "@babel/compat-data": ^7.22.20 + "@babel/compat-data": ^7.23.2 "@babel/helper-compilation-targets": ^7.22.15 "@babel/helper-plugin-utils": ^7.22.5 "@babel/helper-validator-option": ^7.22.15 @@ -1839,15 +1839,15 @@ __metadata: "@babel/plugin-syntax-top-level-await": ^7.14.5 "@babel/plugin-syntax-unicode-sets-regex": ^7.18.6 "@babel/plugin-transform-arrow-functions": ^7.22.5 - "@babel/plugin-transform-async-generator-functions": ^7.22.15 + "@babel/plugin-transform-async-generator-functions": ^7.23.2 "@babel/plugin-transform-async-to-generator": ^7.22.5 "@babel/plugin-transform-block-scoped-functions": ^7.22.5 - "@babel/plugin-transform-block-scoping": ^7.22.15 + "@babel/plugin-transform-block-scoping": ^7.23.0 "@babel/plugin-transform-class-properties": ^7.22.5 "@babel/plugin-transform-class-static-block": ^7.22.11 "@babel/plugin-transform-classes": ^7.22.15 "@babel/plugin-transform-computed-properties": ^7.22.5 - "@babel/plugin-transform-destructuring": ^7.22.15 + "@babel/plugin-transform-destructuring": ^7.23.0 "@babel/plugin-transform-dotall-regex": ^7.22.5 "@babel/plugin-transform-duplicate-keys": ^7.22.5 "@babel/plugin-transform-dynamic-import": ^7.22.11 @@ -1859,9 +1859,9 @@ __metadata: "@babel/plugin-transform-literals": ^7.22.5 "@babel/plugin-transform-logical-assignment-operators": ^7.22.11 "@babel/plugin-transform-member-expression-literals": ^7.22.5 - "@babel/plugin-transform-modules-amd": ^7.22.5 - "@babel/plugin-transform-modules-commonjs": ^7.22.15 - "@babel/plugin-transform-modules-systemjs": ^7.22.11 + "@babel/plugin-transform-modules-amd": ^7.23.0 + "@babel/plugin-transform-modules-commonjs": ^7.23.0 + "@babel/plugin-transform-modules-systemjs": ^7.23.0 "@babel/plugin-transform-modules-umd": ^7.22.5 "@babel/plugin-transform-named-capturing-groups-regex": ^7.22.5 "@babel/plugin-transform-new-target": ^7.22.5 @@ -1870,7 +1870,7 @@ __metadata: "@babel/plugin-transform-object-rest-spread": ^7.22.15 "@babel/plugin-transform-object-super": ^7.22.5 "@babel/plugin-transform-optional-catch-binding": ^7.22.11 - "@babel/plugin-transform-optional-chaining": ^7.22.15 + "@babel/plugin-transform-optional-chaining": ^7.23.0 "@babel/plugin-transform-parameters": ^7.22.15 "@babel/plugin-transform-private-methods": ^7.22.5 "@babel/plugin-transform-private-property-in-object": ^7.22.11 @@ -1887,15 +1887,15 @@ __metadata: "@babel/plugin-transform-unicode-regex": ^7.22.5 "@babel/plugin-transform-unicode-sets-regex": ^7.22.5 "@babel/preset-modules": 0.1.6-no-external-plugins - "@babel/types": ^7.22.19 - babel-plugin-polyfill-corejs2: ^0.4.5 - babel-plugin-polyfill-corejs3: ^0.8.3 - babel-plugin-polyfill-regenerator: ^0.5.2 + "@babel/types": ^7.23.0 + babel-plugin-polyfill-corejs2: ^0.4.6 + babel-plugin-polyfill-corejs3: ^0.8.5 + babel-plugin-polyfill-regenerator: ^0.5.3 core-js-compat: ^3.31.0 semver: ^6.3.1 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 3adf4209a785aec7bfc1a331845ca623acd115e01ff0f9c918b1bc67f69f9e06e6aad4c06940a5001c4c2189617d8c6f8b7fb4720ed7beb9b92d0bdf399692f7 + checksum: b5912f09dc92a8f6b93420f3274499e30255af6dbe5673075a30a5bfead1a651e5eb362c6b95e3ba48c6e6bd4e38b7a5aceebba99997ec7c83833e2e6af9abde languageName: node linkType: hard @@ -1942,8 +1942,8 @@ __metadata: linkType: hard "@babel/preset-typescript@npm:^7.13.0, @babel/preset-typescript@npm:^7.22.15": - version: 7.23.0 - resolution: "@babel/preset-typescript@npm:7.23.0" + version: 7.23.2 + resolution: "@babel/preset-typescript@npm:7.23.2" dependencies: "@babel/helper-plugin-utils": ^7.22.5 "@babel/helper-validator-option": ^7.22.15 @@ -1952,7 +1952,7 @@ __metadata: "@babel/plugin-transform-typescript": ^7.22.15 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 97e246bd14eefad1dd93144200e62aedfb8577fac4172c8da4760b1c2272680fe06780ad87fea1ab81b62e32a23fc9f8e9f10c31a1c22cabf879cb3025e2fed8 + checksum: 40eb71e9959d97a0c2e89fe5cf4c9db7edea5b103618d4c4b5cc7a41dd8c66ab1b1922c443607427000d7bb63e135e8c5f268f35426b2ba00ce53f75bf3b0f8b languageName: node linkType: hard @@ -1978,13 +1978,13 @@ __metadata: languageName: node linkType: hard -"@babel/runtime-corejs3@npm:7.23.1": - version: 7.23.1 - resolution: "@babel/runtime-corejs3@npm:7.23.1" +"@babel/runtime-corejs3@npm:7.23.2": + version: 7.23.2 + resolution: "@babel/runtime-corejs3@npm:7.23.2" dependencies: core-js-pure: ^3.30.2 regenerator-runtime: ^0.14.0 - checksum: 6e2c2b11779ff56c88b1f3a8742498640f7271ad4fcf9cfd24052bbb236a5e7c4c7c8d81cda751da3b4effa678736303deb78441c5752e63bfb90d6453fd870f + checksum: 1362f04cae16d99175961e4113618e5ae210e17053605d4cd2c7b93b3a0334fcfe6a689601d20c12f8946cd8a472430e25f0bf09b7dcd851f63fd82749fd7503 languageName: node linkType: hard @@ -2008,9 +2008,9 @@ __metadata: languageName: node 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" +"@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.2": + version: 7.23.2 + resolution: "@babel/traverse@npm:7.23.2" dependencies: "@babel/code-frame": ^7.22.13 "@babel/generator": ^7.23.0 @@ -2022,11 +2022,11 @@ __metadata: "@babel/types": ^7.23.0 debug: ^4.1.0 globals: ^11.1.0 - checksum: 84f93e64179965a0de6109a8b1ce92d66eb52a76e8ba325d27bdec6952cedd8fc98eabf09fe443ef667a051300dc7ed8924e7bf61a87ad456501d1da46657509 + checksum: d096c7c4bab9262a2f658298a3c630ae4a15a10755bb257ae91d5ab3e3b2877438934859c8d34018b7727379fe6b26c4fa2efc81cf4c462a7fe00caf79fa02ff languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.1.6, @babel/types@npm:^7.16.8, @babel/types@npm:^7.18.13, @babel/types@npm:^7.2.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.3, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.1.6, @babel/types@npm:^7.16.8, @babel/types@npm:^7.18.13, @babel/types@npm:^7.2.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.3, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": version: 7.23.0 resolution: "@babel/types@npm:7.23.0" dependencies: @@ -2921,6 +2921,13 @@ __metadata: languageName: node linkType: hard +"@fastify/busboy@npm:^2.0.0": + version: 2.0.0 + resolution: "@fastify/busboy@npm:2.0.0" + checksum: fdaedca865721769a3a8d788c9efd6af90e73b5f2ff0160dbf46a6160631bbe56e6e5770fafb9a6395111372c73fb2bfa8d4698edc98c6b1f7d97cc9b74e37ea + languageName: node + linkType: hard + "@fastify/deepmerge@npm:^1.0.0": version: 1.3.0 resolution: "@fastify/deepmerge@npm:1.3.0" @@ -4448,6 +4455,18 @@ __metadata: languageName: node linkType: hard +"@graphql-yoga/plugin-defer-stream@npm:2.0.4": + version: 2.0.4 + resolution: "@graphql-yoga/plugin-defer-stream@npm:2.0.4" + dependencies: + "@graphql-tools/utils": ^10.0.0 + peerDependencies: + graphql: ^15.2.0 || ^16.0.0 + graphql-yoga: ^4.0.4 + checksum: d402809bb5ef9bdb1aea3376bc18d756246852326a7d630930d0ea1630ebdca2e82d61bfa5123efaa69514ae37f3e02c20043a2512b82000262ffb3e33b17596 + languageName: node + linkType: hard + "@graphql-yoga/plugin-graphql-sse@npm:2.0.4": version: 2.0.4 resolution: "@graphql-yoga/plugin-graphql-sse@npm:2.0.4" @@ -7796,7 +7815,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@fastify/http-proxy": 9.2.1 "@fastify/static": 6.11.2 "@fastify/url-data": 5.3.1 @@ -7837,7 +7856,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@prisma/client": 5.4.2 "@types/aws-lambda": 8.10.119 "@types/jsonwebtoken": 9.0.2 @@ -7879,7 +7898,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/api": 6.0.7 "@types/jsonwebtoken": 9.0.2 core-js: 3.32.2 @@ -7896,7 +7915,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/cli-helpers": 6.0.7 "@types/yargs": 17.0.24 core-js: 3.32.2 @@ -7912,7 +7931,7 @@ __metadata: "@auth0/auth0-spa-js": 2.1.1 "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/auth": 6.0.7 "@types/react": 18.2.14 core-js: 3.32.2 @@ -7930,7 +7949,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/api": 6.0.7 "@types/aws-lambda": 8.10.119 "@types/jsonwebtoken": 9.0.2 @@ -7948,7 +7967,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/cli-helpers": 6.0.7 "@types/yargs": 17.0.24 core-js: 3.32.2 @@ -7964,7 +7983,7 @@ __metadata: "@azure/msal-browser": 2.38.1 "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/auth": 6.0.7 "@types/netlify-identity-widget": 1.9.3 "@types/react": 18.2.14 @@ -7983,7 +8002,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@clerk/clerk-sdk-node": 4.12.6 "@redwoodjs/api": 6.0.7 "@types/aws-lambda": 8.10.119 @@ -7999,7 +8018,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/cli-helpers": 6.0.7 "@types/yargs": 17.0.24 core-js: 3.32.2 @@ -8014,7 +8033,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@clerk/clerk-react": 4.25.1 "@clerk/types": 3.52.0 "@redwoodjs/auth": 6.0.7 @@ -8034,7 +8053,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/cli-helpers": 6.0.7 "@types/yargs": 17.0.24 core-js: 3.32.2 @@ -8049,7 +8068,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/api": 6.0.7 "@redwoodjs/project-config": 6.0.7 "@simplewebauthn/server": 7.3.1 @@ -8072,7 +8091,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/cli-helpers": 6.0.7 "@simplewebauthn/browser": 7.2.0 "@simplewebauthn/typescript-types": 7.0.0 @@ -8093,7 +8112,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/auth": 6.0.7 "@simplewebauthn/browser": 7.2.0 "@simplewebauthn/typescript-types": 7.0.0 @@ -8111,7 +8130,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/api": 6.0.7 "@types/aws-lambda": 8.10.119 core-js: 3.32.2 @@ -8127,7 +8146,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/cli-helpers": 6.0.7 "@types/yargs": 17.0.24 core-js: 3.32.2 @@ -8142,7 +8161,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/auth": 6.0.7 "@types/react": 18.2.14 core-js: 3.32.2 @@ -8161,7 +8180,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/api": 6.0.7 "@types/aws-lambda": 8.10.119 "@types/jsonwebtoken": 9.0.2 @@ -8178,7 +8197,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/cli-helpers": 6.0.7 "@types/yargs": 17.0.24 core-js: 3.32.2 @@ -8193,7 +8212,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/auth": 6.0.7 "@types/netlify-identity-widget": 1.9.3 "@types/react": 18.2.14 @@ -8212,7 +8231,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/api": 6.0.7 "@types/aws-lambda": 8.10.119 "@types/jsonwebtoken": 9.0.2 @@ -8229,7 +8248,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/cli-helpers": 6.0.7 "@types/yargs": 17.0.24 core-js: 3.32.2 @@ -8244,7 +8263,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@supabase/supabase-js": 2.26.0 "@types/react": 18.2.14 core-js: 3.32.2 @@ -8262,7 +8281,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/api": 6.0.7 "@types/jsonwebtoken": 9.0.2 core-js: 3.32.2 @@ -8281,7 +8300,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/cli-helpers": 6.0.7 "@types/yargs": 17.0.24 core-js: 3.32.2 @@ -8296,7 +8315,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/auth": 6.0.7 "@types/react": 18.2.14 core-js: 3.32.2 @@ -8315,7 +8334,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@testing-library/jest-dom": 5.16.5 "@testing-library/react": 14.0.0 core-js: 3.32.2 @@ -8336,12 +8355,12 @@ __metadata: "@babel/plugin-transform-private-methods": ^7.22.5 "@babel/plugin-transform-private-property-in-object": ^7.22.11 "@babel/plugin-transform-react-jsx": ^7.22.15 - "@babel/plugin-transform-runtime": 7.22.15 + "@babel/plugin-transform-runtime": 7.23.2 "@babel/preset-env": ^7.22.20 "@babel/preset-react": ^7.22.15 "@babel/preset-typescript": ^7.22.15 "@babel/register": ^7.22.15 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@babel/traverse": ^7.22.20 "@redwoodjs/project-config": 6.0.7 "@types/babel-plugin-tester": 9.0.7 @@ -8391,7 +8410,8 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 + "@iarna/toml": 2.2.5 "@opentelemetry/api": 1.4.1 "@redwoodjs/project-config": 6.0.7 "@redwoodjs/telemetry": 6.0.7 @@ -8400,6 +8420,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 @@ -8442,7 +8463,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@iarna/toml": 2.2.5 "@opentelemetry/api": 1.4.1 "@opentelemetry/core": 1.15.2 @@ -8465,7 +8486,7 @@ __metadata: camelcase: 6.3.0 chalk: 4.1.2 ci-info: 3.8.0 - concurrently: 8.2.1 + concurrently: 8.2.2 configstore: 3.1.5 core-js: 3.32.2 cross-env: 7.0.3 @@ -8489,7 +8510,7 @@ __metadata: prettier: 2.8.8 prisma: 5.4.2 prompts: 2.4.2 - rimraf: 5.0.1 + rimraf: 5.0.5 secure-random-password: 0.2.3 semver: 7.5.3 string-env-interpolation: 1.0.1 @@ -8514,7 +8535,7 @@ __metadata: "@babel/core": ^7.22.20 "@babel/parser": ^7.22.16 "@babel/plugin-transform-typescript": ^7.22.15 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@babel/traverse": ^7.22.20 "@iarna/toml": 2.2.5 "@redwoodjs/project-config": 6.0.7 @@ -8553,7 +8574,7 @@ __metadata: resolution: "@redwoodjs/core@workspace:packages/core" dependencies: "@babel/cli": 7.23.0 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@pmmmwh/react-refresh-webpack-plugin": 0.5.10 "@redwoodjs/cli": 6.0.7 "@redwoodjs/eslint-config": 6.0.7 @@ -8578,7 +8599,7 @@ __metadata: null-loader: 4.0.1 react-refresh: 0.14.0 resolve-url-loader: 5.0.0 - rimraf: 5.0.1 + rimraf: 5.0.5 style-loader: 3.3.3 typescript: 5.2.2 url-loader: 4.1.1 @@ -8682,7 +8703,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@testing-library/dom": 9.3.1 "@testing-library/jest-dom": 5.16.5 "@testing-library/react": 14.0.0 @@ -8712,7 +8733,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@envelop/core": 4.0.0 "@envelop/depth-limit": 3.0.0 "@envelop/disable-introspection": 5.0.0 @@ -8755,7 +8776,7 @@ __metadata: "@babel/parser": ^7.22.16 "@babel/plugin-transform-react-jsx": ^7.22.15 "@babel/plugin-transform-typescript": ^7.22.15 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@babel/traverse": ^7.22.20 "@graphql-codegen/add": 4.0.1 "@graphql-codegen/cli": 3.3.1 @@ -8783,7 +8804,7 @@ __metadata: jest: 29.7.0 kill-port: 1.6.1 prettier: 2.8.8 - rimraf: 5.0.1 + rimraf: 5.0.5 source-map: 0.7.4 string-env-interpolation: 1.0.1 systeminformation: 5.21.7 @@ -8890,7 +8911,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/auth": 6.0.7 "@redwoodjs/internal": 6.0.7 "@redwoodjs/project-config": 6.0.7 @@ -8922,7 +8943,7 @@ __metadata: esbuild: 0.19.3 fast-glob: 3.3.1 jest: 29.7.0 - rimraf: 5.0.1 + rimraf: 5.0.5 string-env-interpolation: 1.0.1 typescript: 5.2.2 languageName: unknown @@ -8938,6 +8959,7 @@ __metadata: "@envelop/types": 4.0.0 "@graphql-tools/schema": 10.0.0 "@graphql-tools/utils": 10.0.1 + "@graphql-yoga/plugin-defer-stream": 2.0.4 "@graphql-yoga/plugin-graphql-sse": 2.0.4 "@graphql-yoga/redis-event-target": 2.0.0 "@graphql-yoga/subscription": 4.0.0 @@ -8963,7 +8985,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@prisma/client": 5.4.2 "@prisma/internals": 5.4.2 "@redwoodjs/project-config": 6.0.7 @@ -8979,7 +9001,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@reach/skip-nav": 0.18.0 "@redwoodjs/auth": 6.0.7 "@types/react": 18.2.14 @@ -9001,7 +9023,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@iarna/toml": 2.2.5 "@prisma/internals": 5.4.2 "@redwoodjs/project-config": 6.0.7 @@ -9041,7 +9063,7 @@ __metadata: "@apollo/client": 3.8.5 "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@fastify/http-proxy": 9.2.1 "@fastify/static": 6.11.2 "@fastify/url-data": 5.3.1 @@ -9123,7 +9145,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/project-config": 6.0.7 "@redwoodjs/structure": 6.0.7 "@types/envinfo": 7.8.1 @@ -9146,7 +9168,7 @@ __metadata: dependencies: "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/auth": 6.0.7 "@redwoodjs/babel-config": 6.0.7 "@redwoodjs/graphql-server": 6.0.7 @@ -9196,7 +9218,7 @@ __metadata: resolution: "@redwoodjs/vite@workspace:packages/vite" dependencies: "@babel/cli": 7.23.0 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/internal": 6.0.7 "@redwoodjs/project-config": 6.0.7 "@redwoodjs/web": 6.0.7 @@ -9260,7 +9282,7 @@ __metadata: "@apollo/experimental-nextjs-app-support": 0.4.3 "@babel/cli": 7.23.0 "@babel/core": ^7.22.20 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@redwoodjs/auth": 6.0.7 "@testing-library/jest-dom": 5.16.5 "@testing-library/react": 14.0.0 @@ -14340,39 +14362,39 @@ __metadata: languageName: node linkType: hard -"babel-plugin-polyfill-corejs2@npm:^0.4.5": - version: 0.4.5 - resolution: "babel-plugin-polyfill-corejs2@npm:0.4.5" +"babel-plugin-polyfill-corejs2@npm:^0.4.6": + version: 0.4.6 + resolution: "babel-plugin-polyfill-corejs2@npm:0.4.6" dependencies: "@babel/compat-data": ^7.22.6 - "@babel/helper-define-polyfill-provider": ^0.4.2 + "@babel/helper-define-polyfill-provider": ^0.4.3 semver: ^6.3.1 peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: 89e12f24aac8bfae90001371cb3ed4d2e73b9acf723d8cce9bc7546424249d02163d883c9be436073210365abcbc0876ae3140b1f312839f37f824c8ba96ae03 + checksum: 64a98811f343492aa6970ab253760194e389c0417e5b830522f944009c1f0c78e1251975fd1b9869cd48cc4623111b20a3389cf6732a1d10ba0d19de6fa5114f languageName: node linkType: hard -"babel-plugin-polyfill-corejs3@npm:^0.8.3": - version: 0.8.3 - resolution: "babel-plugin-polyfill-corejs3@npm:0.8.3" +"babel-plugin-polyfill-corejs3@npm:^0.8.5": + version: 0.8.6 + resolution: "babel-plugin-polyfill-corejs3@npm:0.8.6" dependencies: - "@babel/helper-define-polyfill-provider": ^0.4.2 - core-js-compat: ^3.31.0 + "@babel/helper-define-polyfill-provider": ^0.4.3 + core-js-compat: ^3.33.1 peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: b5cbfad6d3695a1ea65ef62e34de7f9c6f717cd5cc6d64bde726528168ba1d0a81e09a385d9283a489aab9739fbe206f2192fd9f0f60a37a0577de6526553a8d + checksum: 97d974c1dfbefdf27866e21a1ac757f6ab1626379b544d6f8ddb05f7bfa02173f8347b6140295b0f770394549f9321775d3048e466a9a02b99b88ad5f0346858 languageName: node linkType: hard -"babel-plugin-polyfill-regenerator@npm:^0.5.2": - version: 0.5.2 - resolution: "babel-plugin-polyfill-regenerator@npm:0.5.2" +"babel-plugin-polyfill-regenerator@npm:^0.5.3": + version: 0.5.3 + resolution: "babel-plugin-polyfill-regenerator@npm:0.5.3" dependencies: - "@babel/helper-define-polyfill-provider": ^0.4.2 + "@babel/helper-define-polyfill-provider": ^0.4.3 peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: 31358bc030d99599fa1f7f0399b2cf7a5872495672bff779ecb49d6bbdb990378a1a5640789c247e248a481b6f298a2223d4396544ac79de4dc77fe3946bfe2c + checksum: cc32313b9ebbf1d7bedc33524a861136b9e5d3b6e9be317ac360a1c2a59ae5ed1b465a6c68b2715cdefb089780ddfb0c11f4a148e49827a947beee76e43da598 languageName: node linkType: hard @@ -14938,17 +14960,17 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.0.0, browserslist@npm:^4.14.5, browserslist@npm:^4.21.4, browserslist@npm:^4.21.5, browserslist@npm:^4.21.9": - version: 4.21.10 - resolution: "browserslist@npm:4.21.10" +"browserslist@npm:^4.0.0, browserslist@npm:^4.14.5, browserslist@npm:^4.21.4, browserslist@npm:^4.21.5, browserslist@npm:^4.21.9, browserslist@npm:^4.22.1": + version: 4.22.1 + resolution: "browserslist@npm:4.22.1" dependencies: - caniuse-lite: ^1.0.30001517 - electron-to-chromium: ^1.4.477 + caniuse-lite: ^1.0.30001541 + electron-to-chromium: ^1.4.535 node-releases: ^2.0.13 - update-browserslist-db: ^1.0.11 + update-browserslist-db: ^1.0.13 bin: browserslist: cli.js - checksum: e8c98496e5f2a5128d0e2f1f186dc0416bfc49c811e568b19c9e07a56cccc1f7f415fa4f532488e6a13dfacbe3332a9b55b152082ff125402696a11a158a0894 + checksum: 6810f2d63f171d0b7b8d38cf091708e00cb31525501810a507839607839320d66e657293b0aa3d7f051ecbc025cb07390a90c037682c1d05d12604991e41050b languageName: node linkType: hard @@ -15335,10 +15357,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001464, caniuse-lite@npm:^1.0.30001517": - version: 1.0.30001522 - resolution: "caniuse-lite@npm:1.0.30001522" - checksum: c0cff748458428b5ab502622861688c1d31bdc966ab0aadf0b8ccd6a7cd9e7b8567031ad667af2a4885cb1348c4c1856160ec1cb7376eb3f2f45f6dc1c4c641f +"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001464, caniuse-lite@npm:^1.0.30001541": + version: 1.0.30001554 + resolution: "caniuse-lite@npm:1.0.30001554" + checksum: 1ef7647d005ff4b6d2797dd3d4d47cf66733531999e40b50dcbe3c84f59f8ecac92ffba7ca35b932bd1ce5f8aedbf22f3bd464898be00874e3db99ef869bd726 languageName: node linkType: hard @@ -16243,9 +16265,9 @@ __metadata: languageName: node linkType: hard -"concurrently@npm:8.2.1": - version: 8.2.1 - resolution: "concurrently@npm:8.2.1" +"concurrently@npm:8.2.2": + version: 8.2.2 + resolution: "concurrently@npm:8.2.2" dependencies: chalk: ^4.1.2 date-fns: ^2.30.0 @@ -16259,7 +16281,7 @@ __metadata: bin: conc: dist/bin/concurrently.js concurrently: dist/bin/concurrently.js - checksum: cde6807839d41121c85f8a20064c9fc8a6c40737b42695db75a64ae1b840314cb63b3ba8c7462d33755b62d5ae5522120824015fcfa0714d773e0d839151f08a + checksum: 0e9683196fe9c071d944345d21d8f34aa6c0cc50c0dd897e95619f2f1c9eb4871dca851b2569da17888235b7335b4c821ca19deed35bebcd9a131ee5d247f34c languageName: node linkType: hard @@ -16536,12 +16558,12 @@ __metadata: languageName: node linkType: hard -"core-js-compat@npm:^3.31.0": - version: 3.31.1 - resolution: "core-js-compat@npm:3.31.1" +"core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.33.1": + version: 3.33.1 + resolution: "core-js-compat@npm:3.33.1" dependencies: - browserslist: ^4.21.9 - checksum: 2f05c5d5b04e8a69cf50f538ef3fb1932ab83bd7dc690c438c7b876049cb1515eb4ca9fa29400ed7cd5885f34c901bf6a26d9149dfff8665d8302cace7e96d72 + browserslist: ^4.22.1 + checksum: 9c7361b370eac30756e6ec52469988d62c6110759efa1c85edd15e6b30f05ace8319a9cc0671bf596a98e7e81c67ad693ceaab2691b85cb62c636da1afe8feb9 languageName: node linkType: hard @@ -18329,10 +18351,10 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.4.477": - version: 1.4.496 - resolution: "electron-to-chromium@npm:1.4.496" - checksum: 7c46af3c5da6cbdf97904b91f88f537b9bd8f3d60c9064431a4d871e7871301212218b61d622c353343aa0d30c446030327e8c26a81efd910bc93b0b6cf0391d +"electron-to-chromium@npm:^1.4.535": + version: 1.4.567 + resolution: "electron-to-chromium@npm:1.4.567" + checksum: 323206c97e6251c947dd4518465fa12f91696a9189e8d40efcaf7d0e608767eb29e894ec09bd30154633741ce0d4fb5d2b074262df1e0e108bf9dd2e8b7f958e languageName: node linkType: hard @@ -21088,18 +21110,18 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.0.0, glob@npm:^10.2.2, glob@npm:^10.2.5": - version: 10.3.3 - resolution: "glob@npm:10.3.3" +"glob@npm:^10.0.0, glob@npm:^10.2.2, glob@npm:^10.3.7": + version: 10.3.10 + resolution: "glob@npm:10.3.10" dependencies: foreground-child: ^3.1.0 - jackspeak: ^2.0.3 + jackspeak: ^2.3.5 minimatch: ^9.0.1 minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 path-scurry: ^1.10.1 bin: - glob: dist/cjs/src/bin.js - checksum: 50effa4208762e508def5688e4d88242db80b5913f65e9c5d5aefb707c59e66a27e845fbf18127157189f6ed0f055e2c94d7112c97a065b9cbfe002e1b26d330 + glob: dist/esm/bin.mjs + checksum: 13d8a1feb7eac7945f8c8480e11cd4a44b24d26503d99a8d8ac8d5aefbf3e9802a2b6087318a829fad04cb4e829f25c5f4f1110c68966c498720dd261c7e344d languageName: node linkType: hard @@ -23303,16 +23325,16 @@ __metadata: languageName: node linkType: hard -"jackspeak@npm:^2.0.3": - version: 2.2.1 - resolution: "jackspeak@npm:2.2.1" +"jackspeak@npm:^2.0.3, jackspeak@npm:^2.3.5": + version: 2.3.6 + resolution: "jackspeak@npm:2.3.6" dependencies: "@isaacs/cliui": ^8.0.2 "@pkgjs/parseargs": ^0.11.0 dependenciesMeta: "@pkgjs/parseargs": optional: true - checksum: 510860a5d1eaf12cba509a09a8f7d1696090bfa7c8ae75c6d9c836890d2897409f3b3dd91039cf0020627d6eba8c024f571ae4d78bd956162b07794ddfb9dd62 + checksum: f01d8f972d894cd7638bc338e9ef5ddb86f7b208ce177a36d718eac96ec86638a6efa17d0221b10073e64b45edc2ce15340db9380b1f5d5c5d000cbc517dc111 languageName: node linkType: hard @@ -31330,14 +31352,14 @@ __metadata: languageName: node linkType: hard -"rimraf@npm:5.0.1": - version: 5.0.1 - resolution: "rimraf@npm:5.0.1" +"rimraf@npm:5.0.5": + version: 5.0.5 + resolution: "rimraf@npm:5.0.5" dependencies: - glob: ^10.2.5 + glob: ^10.3.7 bin: - rimraf: dist/cjs/src/bin.js - checksum: 9e6062c0aea96f384dd937e6bb06b624c881de2eee79a83d3068193183d44eb9b1f3f68a27a54b9ca8cce56bf34c2951ff4239b093b970e0501a091907031f52 + rimraf: dist/esm/bin.mjs + checksum: d50dbe724f33835decd88395b25ed35995077c60a50ae78ded06e0185418914e555817aad1b4243edbff2254548c2f6ad6f70cc850040bebb4da9e8cc016f586 languageName: node linkType: hard @@ -31410,17 +31432,17 @@ __metadata: "@babel/core": ^7.22.20 "@babel/generator": 7.23.0 "@babel/node": 7.22.19 - "@babel/plugin-proposal-decorators": 7.23.0 + "@babel/plugin-proposal-decorators": 7.23.2 "@babel/plugin-transform-class-properties": ^7.22.5 "@babel/plugin-transform-nullish-coalescing-operator": 7.22.11 "@babel/plugin-transform-private-methods": ^7.22.5 "@babel/plugin-transform-private-property-in-object": ^7.22.11 "@babel/plugin-transform-react-jsx": ^7.22.15 - "@babel/plugin-transform-runtime": 7.22.15 + "@babel/plugin-transform-runtime": 7.23.2 "@babel/preset-env": ^7.22.20 "@babel/preset-react": ^7.22.15 "@babel/preset-typescript": ^7.22.15 - "@babel/runtime-corejs3": 7.23.1 + "@babel/runtime-corejs3": 7.23.2 "@faker-js/faker": 8.0.2 "@npmcli/arborist": 6.2.10 "@playwright/test": 1.37.1 @@ -31461,7 +31483,7 @@ __metadata: octokit: 2.1.0 ora: 6.3.1 prompts: 2.4.2 - rimraf: 5.0.1 + rimraf: 5.0.5 tsx: 3.12.7 typescript: 5.2.2 yargs: 17.7.2 @@ -34387,11 +34409,11 @@ __metadata: linkType: hard "undici@npm:^5.19.1": - version: 5.22.1 - resolution: "undici@npm:5.22.1" + version: 5.26.3 + resolution: "undici@npm:5.26.3" dependencies: - busboy: ^1.6.0 - checksum: 50479d28a9a5de4faae410cc73523823d339a7d016b77bfe89d3cdf78fe5441950f30958c9cfb6e2acd8fb4f914308597c75bd0c15e74143212f67e2ef020477 + "@fastify/busboy": ^2.0.0 + checksum: af418c4ea429fdd63640b780a21c4f790685f60aa3766663bbff1081c3d20a70da70cbb4d4955d5c0c78f06cd13527d171edf3a65db8476a6c02539f495e9f48 languageName: node linkType: hard @@ -34610,9 +34632,9 @@ __metadata: languageName: node linkType: hard -"update-browserslist-db@npm:^1.0.11": - version: 1.0.11 - resolution: "update-browserslist-db@npm:1.0.11" +"update-browserslist-db@npm:^1.0.13": + version: 1.0.13 + resolution: "update-browserslist-db@npm:1.0.13" dependencies: escalade: ^3.1.1 picocolors: ^1.0.0 @@ -34620,7 +34642,7 @@ __metadata: browserslist: ">= 4.21.0" bin: update-browserslist-db: cli.js - checksum: 280d5cf92e302d8de0c12ef840a6af26ec024a5158aa2020975cd01bf0ded09c709793a6f421e6d0f1a47557d6a1a10dc43af80f9c30b8fd0df9691eb98c1c69 + checksum: e52b8b521c78ce1e0c775f356cd16a9c22c70d25f3e01180839c407a5dc787fb05a13f67560cbaf316770d26fa99f78f1acd711b1b54a4f35d4820d4ea7136e6 languageName: node linkType: hard