diff --git a/.github/workflows/ci-jobs.yml b/.github/workflows/ci-jobs.yml index c7b81878dc6..de5b6856e8b 100644 --- a/.github/workflows/ci-jobs.yml +++ b/.github/workflows/ci-jobs.yml @@ -220,6 +220,8 @@ jobs: perf-check: name: Perf script still works runs-on: ubuntu-latest + timeout-minutes: 10 + if: ${{ !startsWith(github.ref, 'refs/tags/') }} # Don't run on tags steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index 2ef53403460..afb8b104cac 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -21,7 +21,7 @@ jobs: matrix: branch: [main, beta, release] steps: - - uses: kategengler/ci-cron@d54b69bfd9147fb125899da4a2891f7fdf35f786 # v1.0.2 + - uses: kategengler/ci-cron@181db7e5bac13d0b55b6f5c4a8567fd20154576b # v1.0.3 with: branch: ${{ matrix.branch }} # This must use a personal access token because of a Github Actions diff --git a/.github/workflows/glimmer-syntax-prettier-smoke-test.yml b/.github/workflows/glimmer-syntax-prettier-smoke-test.yml new file mode 100644 index 00000000000..3b87973841f --- /dev/null +++ b/.github/workflows/glimmer-syntax-prettier-smoke-test.yml @@ -0,0 +1,68 @@ +# aka: our primary CLI-land consumer of @glimmer/syntax +name: "Prettier Smoke Test" + +on: + push: + branches: + - main + - beta + - release + - release* + - lts* + paths: + - ".github/workflows/glimmer-syntax-prettier-smoke-test.yml" + - ".github/actions/setup/**" + - "rollup.config.mjs" + - "packages/@glimmer/syntax/**" + - "packages/@glimmer/interfaces/**" + - "packages/@glimmer/util/**" + - "packages/@glimmer/wire-format/**" + - "packages/@handlebars/parser/**" + pull_request: + paths: + - ".github/workflows/glimmer-syntax-prettier-smoke-test.yml" + - ".github/actions/setup/**" + - "rollup.config.mjs" + - "packages/@glimmer/syntax/**" + - "packages/@glimmer/interfaces/**" + - "packages/@glimmer/util/**" + - "packages/@glimmer/wire-format/**" + - "packages/@handlebars/parser/**" + workflow_dispatch: + +permissions: + contents: read + +jobs: + prettier-smoke-test: + name: Prettier handlebars smoke test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - uses: ./.github/actions/setup + - run: pnpm build + + - name: Pack @glimmer/syntax + working-directory: packages/@glimmer/syntax + run: pnpm pack --out ${{ github.workspace }}/glimmer-syntax.tgz + + - name: Checkout prettier/prettier + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + repository: prettier/prettier + path: prettier-repo + + - name: Install prettier dependencies + working-directory: prettier-repo + run: yarn install + + - name: Install local @glimmer/syntax into prettier + working-directory: prettier-repo + run: yarn add "@glimmer/syntax@file:${{ github.workspace }}/glimmer-syntax.tgz" + + - name: Run prettier handlebars tests + working-directory: prettier-repo + run: yarn jest tests/format/handlebars diff --git a/.github/workflows/pr-title-lint.yml b/.github/workflows/pr-title-lint.yml index 8a05789535b..7bdc129946f 100644 --- a/.github/workflows/pr-title-lint.yml +++ b/.github/workflows/pr-title-lint.yml @@ -1,7 +1,7 @@ name: PR Title Lint on: - pull_request: + pull_request_target: # This workflow has permissions on the repo, do NOT run code from PRs in this workflow. See https://securitylab.github.com/research/github-actions-preventing-pwn-requests/ # zizmor: ignore[dangerous-triggers] we know what we are doing here types: [opened, edited, reopened, synchronize] permissions: diff --git a/CHANGELOG.md b/CHANGELOG.md index 61b42db7a62..3a554090b6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Ember Changelog +## v6.12.0-beta.2 (March 9, 2026) + +- [#21144](https://github.com/emberjs/ember.js/pull/21144) [BUGFIX] Fix crash *during* destroy in fastboot + +## v6.12.0-beta.1 (February 17, 2026) - [#20908](https://github.com/emberjs/ember.js/pull/20908) / [#21020](https://github.com/emberjs/ember.js/pull/21020) Merge [glimmerjs/glimmer-vm](https://github.com/glimmerjs/glimmer-vm) into the `emberjs/ember.js` monorepo. - All `@glimmer/*` packages that were formerly dependencies of `ember-source` are now included in the monorepo. This enables us to more easily iterate on the Glimmer VM and related packages, avoid an integration step with `ember.js` and to more easily share code between them and `ember-source`. diff --git a/bin/benchmark/run.mjs b/bin/benchmark/run.mjs index a31d121e975..04c7c8b929d 100644 --- a/bin/benchmark/run.mjs +++ b/bin/benchmark/run.mjs @@ -171,24 +171,6 @@ async function bootAndRun({ headless = true } = {}) { '--debug', '--browserArgs', [ - '--no-sandbox', - '--crash-dumps-dir=./tmp', - // Disable task throttling (also in TracerBench defaults, but explicit here for clarity) - '--disable-background-timer-throttling', - '--disable-backgrounding-occluded-windows', - '--disable-renderer-backgrounding', - // Disable caching and unnecessary subsystems - '--disable-dev-shm-usage', - '--disable-cache', - '--disable-v8-idle-tasks', - '--disable-breakpad', - '--disable-component-update', - '--disable-background-networking', - '--disable-notifications', - '--disable-hang-monitor', - '--safebrowsing-disable-auto-update', - '--ignore-certificate-errors', - '--v8-cache-options=none', // Use the new headless mode to support multiple targets ...(headless ? ['--headless=new'] : []), // GPU: use software rendering via SwiftShader, but do NOT @@ -196,11 +178,6 @@ async function bootAndRun({ headless = true } = {}) { // as the contradictory flags cause use-after-free crashes on macOS '--disable-gpu', '--disable-gpu-compositing', - // Disable Chrome ML/TFLite features (suppresses XNNPACK/TFLite init) - '--disable-features=TranslateUI', - '--disable-features=UseChromiumML', - '--disable-features=UseTfLite', - '--disable-features=TensorFlowLite', ].join(','), ]; diff --git a/eslint.config.mjs b/eslint.config.mjs index 2915043fe27..160c3340173 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -154,6 +154,11 @@ export default [ Symbol: true, WeakMap: true, Event: true, + MouseEvent: true, + KeyboardEvent: true, + DOMRect: true, + DOMRectList: true, + globalThis: true, }, ecmaVersion: 2017, diff --git a/node-tests/blueprints/component-test-test.js b/node-tests/blueprints/component-test-test.js index 99c4a9273b6..5494e76f997 100644 --- a/node-tests/blueprints/component-test-test.js +++ b/node-tests/blueprints/component-test-test.js @@ -20,11 +20,12 @@ describe('Blueprint: component-test', function () { it('component-test foo', function () { return emberGenerateDestroy(['component-test', 'foo'], (_file) => { - expect(_file('tests/integration/components/foo-test.js')).to.equal( - fixture('component-test/app.js', { + expect(_file('tests/integration/components/foo-test.gjs')).to.equal( + fixture('component-test/app.gjs', { replace: { component: 'foo', componentInvocation: 'Foo', + testDescription: 'Integration | Component | foo', }, }) ); @@ -34,7 +35,13 @@ describe('Blueprint: component-test', function () { it('component-test foo --strict', function () { return emberGenerateDestroy(['component-test', 'foo', '--strict'], (_file) => { expect(_file('tests/integration/components/foo-test.gjs')).to.equal( - fixture('component-test/app.gjs') + fixture('component-test/app.gjs', { + replace: { + component: 'foo', + componentInvocation: 'Foo', + testDescription: 'Integration | Component | foo', + }, + }) ); }); }); @@ -50,8 +57,35 @@ describe('Blueprint: component-test', function () { ); }); + it('component-test foo --loose', function () { + return emberGenerateDestroy(['component-test', 'foo', '--loose'], (_file) => { + expect(_file('tests/integration/components/foo-test.js')).to.equal( + fixture('component-test/app.js', { + replace: { + component: 'foo', + componentInvocation: 'Foo', + }, + }) + ); + }); + }); + it('component-test x-foo --unit', function () { return emberGenerateDestroy(['component-test', 'x-foo', '--unit'], (_file) => { + expect(_file('tests/unit/components/x-foo-test.gjs')).to.equal( + fixture('component-test/app.gjs', { + replace: { + component: 'x-foo', + componentInvocation: 'XFoo', + testDescription: 'Unit | Component | x-foo', + }, + }) + ); + }); + }); + + it('component-test x-foo --unit --loose', function () { + return emberGenerateDestroy(['component-test', 'x-foo', '--unit', '--loose'], (_file) => { expect(_file('tests/unit/components/x-foo-test.js')).to.equal( fixture('component-test/unit.js') ); @@ -66,11 +100,12 @@ describe('Blueprint: component-test', function () { it('component-test foo', function () { return emberGenerateDestroy(['component-test', 'foo'], (_file) => { - expect(_file('tests/integration/components/foo-test.js')).to.equal( - fixture('component-test/addon.js', { + expect(_file('tests/integration/components/foo-test.gjs')).to.equal( + fixture('component-test/addon.gjs', { replace: { component: 'foo', componentInvocation: 'Foo', + testDescription: 'Integration | Component | foo', }, }) ); @@ -79,8 +114,14 @@ describe('Blueprint: component-test', function () { it('component-test foo --unit', function () { return emberGenerateDestroy(['component-test', 'foo', '--unit'], (_file) => { - expect(_file('tests/unit/components/foo-test.js')).to.equal( - fixture('component-test/addon-unit.js') + expect(_file('tests/unit/components/foo-test.gjs')).to.equal( + fixture('component-test/addon.gjs', { + replace: { + component: 'foo', + componentInvocation: 'Foo', + testDescription: 'Unit | Component | foo', + }, + }) ); }); }); @@ -88,7 +129,13 @@ describe('Blueprint: component-test', function () { it('component-test foo --strict', function () { return emberGenerateDestroy(['component-test', 'foo', '--strict'], (_file) => { expect(_file('tests/integration/components/foo-test.gjs')).to.equal( - fixture('component-test/addon.gjs') + fixture('component-test/addon.gjs', { + replace: { + component: 'foo', + componentInvocation: 'Foo', + testDescription: 'Integration | Component | foo', + }, + }) ); }); }); @@ -103,6 +150,27 @@ describe('Blueprint: component-test', function () { } ); }); + + it('component-test foo --loose', function () { + return emberGenerateDestroy(['component-test', 'foo', '--loose'], (_file) => { + expect(_file('tests/integration/components/foo-test.js')).to.equal( + fixture('component-test/addon.js', { + replace: { + component: 'foo', + componentInvocation: 'Foo', + }, + }) + ); + }); + }); + + it('component-test foo --unit --loose', function () { + return emberGenerateDestroy(['component-test', 'foo', '--unit', '--loose'], (_file) => { + expect(_file('tests/unit/components/foo-test.js')).to.equal( + fixture('component-test/addon-unit.js') + ); + }); + }); }); describe('in in-repo-addon', function () { @@ -114,11 +182,12 @@ describe('Blueprint: component-test', function () { return emberGenerateDestroy( ['component-test', 'foo', '--in-repo-addon=my-addon'], (_file) => { - expect(_file('tests/integration/components/foo-test.js')).to.equal( - fixture('component-test/app.js', { + expect(_file('tests/integration/components/foo-test.gjs')).to.equal( + fixture('component-test/app.gjs', { replace: { component: 'foo', componentInvocation: 'Foo', + testDescription: 'Integration | Component | foo', }, }) ); @@ -129,6 +198,39 @@ describe('Blueprint: component-test', function () { it('component-test x-foo --in-repo-addon=my-addon --unit', function () { return emberGenerateDestroy( ['component-test', 'x-foo', '--in-repo-addon=my-addon', '--unit'], + (_file) => { + expect(_file('tests/unit/components/x-foo-test.gjs')).to.equal( + fixture('component-test/app.gjs', { + replace: { + component: 'x-foo', + componentInvocation: 'XFoo', + testDescription: 'Unit | Component | x-foo', + }, + }) + ); + } + ); + }); + + it('component-test foo --in-repo-addon=my-addon --loose', function () { + return emberGenerateDestroy( + ['component-test', 'foo', '--in-repo-addon=my-addon', '--loose'], + (_file) => { + expect(_file('tests/integration/components/foo-test.js')).to.equal( + fixture('component-test/app.js', { + replace: { + component: 'foo', + componentInvocation: 'Foo', + }, + }) + ); + } + ); + }); + + it('component-test x-foo --in-repo-addon=my-addon --unit --loose', function () { + return emberGenerateDestroy( + ['component-test', 'x-foo', '--in-repo-addon=my-addon', '--unit', '--loose'], (_file) => { expect(_file('tests/unit/components/x-foo-test.js')).to.equal( fixture('component-test/unit.js') diff --git a/node-tests/blueprints/component-test.js b/node-tests/blueprints/component-test.js index 6faf3d9b4d5..db01ff0db12 100644 --- a/node-tests/blueprints/component-test.js +++ b/node-tests/blueprints/component-test.js @@ -11,21 +11,11 @@ const expect = chai.expect; const fixture = require('../helpers/fixture'); -const glimmerComponentContents = `import Component from '@glimmer/component'; - -export default class Foo extends Component {} -`; - const emberComponentContents = `import Component from '@ember/component'; export default class extends Component {} `; -const templateOnlyContents = `import templateOnly from '@ember/component/template-only'; - -export default templateOnly(); -`; - describe('Blueprint: component', function () { setupTestHooks(this); @@ -37,13 +27,16 @@ describe('Blueprint: component', function () { it('component foo', function () { return emberGenerateDestroy(['component', 'foo'], (_file) => { expect(_file('app/components/foo.js')).to.not.exist; - expect(_file('app/components/foo.hbs')).to.equal('{{yield}}'); + expect(_file('app/components/foo.gjs')).to.equal( + fixture('component/template-only-component.gjs') + ); - expect(_file('tests/integration/components/foo-test.js')).to.equal( - fixture('component-test/app.js', { + expect(_file('tests/integration/components/foo-test.gjs')).to.equal( + fixture('component-test/app.gjs', { replace: { component: 'foo', componentInvocation: 'Foo', + testDescription: 'Integration | Component | foo', }, }) ); @@ -61,15 +54,18 @@ describe('Blueprint: component', function () { 'foo', ], (_file) => { - expect(_file('app/components/foo.js')).to.equal(glimmerComponentContents); - - expect(_file('app/components/foo.hbs')).to.equal('{{yield}}'); + expect(_file('app/components/foo.js')).to.not.exist; + expect(_file('app/components/foo.hbs')).to.not.exist; + expect(_file('app/components/foo.gjs')).to.equal( + fixture('component/glimmer-component.gjs') + ); - expect(_file('tests/integration/components/foo-test.js')).to.equal( - fixture('component-test/app.js', { + expect(_file('tests/integration/components/foo-test.gjs')).to.equal( + fixture('component-test/app.gjs', { replace: { component: 'foo', componentInvocation: 'Foo', + testDescription: 'Integration | Component | foo', }, }) ); @@ -81,13 +77,16 @@ describe('Blueprint: component', function () { return emberGenerateDestroy( ['component', '--component-structure', 'flat', 'foo'], (_file) => { - expect(_file('app/components/foo.hbs')).to.equal('{{yield}}'); + expect(_file('app/components/foo.gjs')).to.equal( + fixture('component/template-only-component.gjs') + ); - expect(_file('tests/integration/components/foo-test.js')).to.equal( - fixture('component-test/app.js', { + expect(_file('tests/integration/components/foo-test.gjs')).to.equal( + fixture('component-test/app.gjs', { replace: { component: 'foo', componentInvocation: 'Foo', + testDescription: 'Integration | Component | foo', }, }) ); @@ -99,13 +98,16 @@ describe('Blueprint: component', function () { return emberGenerateDestroy( ['component', '--component-structure', 'nested', 'foo'], (_file) => { - expect(_file('app/components/foo/index.hbs')).to.equal('{{yield}}'); + expect(_file('app/components/foo/index.gjs')).to.equal( + fixture('component/template-only-component.gjs') + ); - expect(_file('tests/integration/components/foo-test.js')).to.equal( - fixture('component-test/app.js', { + expect(_file('tests/integration/components/foo-test.gjs')).to.equal( + fixture('component-test/app.gjs', { replace: { component: 'foo', componentInvocation: 'Foo', + testDescription: 'Integration | Component | foo', }, }) ); @@ -115,7 +117,7 @@ describe('Blueprint: component', function () { it('component foo --component-class=@ember/component', function () { return emberGenerateDestroy( - ['component', '--component-class', '@ember/component', 'foo'], + ['component', '--component-class', '@ember/component', '--loose', 'foo'], (_file) => { expect(_file('app/components/foo.js')).to.equal(emberComponentContents); @@ -137,15 +139,18 @@ describe('Blueprint: component', function () { return emberGenerateDestroy( ['component', '--component-class', '@glimmer/component', 'foo'], (_file) => { - expect(_file('app/components/foo.js')).to.equal(glimmerComponentContents); - - expect(_file('app/components/foo.hbs')).to.equal('{{yield}}'); + expect(_file('app/components/foo.js')).to.not.exist; + expect(_file('app/components/foo.hbs')).to.not.exist; + expect(_file('app/components/foo.gjs')).to.equal( + fixture('component/glimmer-component.gjs') + ); - expect(_file('tests/integration/components/foo-test.js')).to.equal( - fixture('component-test/app.js', { + expect(_file('tests/integration/components/foo-test.gjs')).to.equal( + fixture('component-test/app.gjs', { replace: { component: 'foo', componentInvocation: 'Foo', + testDescription: 'Integration | Component | foo', }, }) ); @@ -157,15 +162,18 @@ describe('Blueprint: component', function () { return emberGenerateDestroy( ['component', '--component-class', '@ember/component/template-only', 'foo'], (_file) => { - expect(_file('app/components/foo.js')).to.equal(templateOnlyContents); - - expect(_file('app/components/foo.hbs')).to.equal('{{yield}}'); + expect(_file('app/components/foo.js')).to.not.exist; + expect(_file('app/components/foo.hbs')).to.not.exist; + expect(_file('app/components/foo.gjs')).to.equal( + fixture('component/template-only-component.gjs') + ); - expect(_file('tests/integration/components/foo-test.js')).to.equal( - fixture('component-test/app.js', { + expect(_file('tests/integration/components/foo-test.gjs')).to.equal( + fixture('component-test/app.gjs', { replace: { component: 'foo', componentInvocation: 'Foo', + testDescription: 'Integration | Component | foo', }, }) ); @@ -177,13 +185,16 @@ describe('Blueprint: component', function () { return emberGenerateDestroy(['component', '--no-component-class', 'foo'], (_file) => { expect(_file('app/components/foo.js')).to.not.exist; - expect(_file('app/components/foo.hbs')).to.equal('{{yield}}'); + expect(_file('app/components/foo.gjs')).to.equal( + fixture('component/template-only-component.gjs') + ); - expect(_file('tests/integration/components/foo-test.js')).to.equal( - fixture('component-test/app.js', { + expect(_file('tests/integration/components/foo-test.gjs')).to.equal( + fixture('component-test/app.gjs', { replace: { component: 'foo', componentInvocation: 'Foo', + testDescription: 'Integration | Component | foo', }, }) ); @@ -193,13 +204,16 @@ describe('Blueprint: component', function () { it('component x-foo', function () { return emberGenerateDestroy(['component', 'x-foo'], (_file) => { expect(_file('app/components/x-foo.js')).to.not.exist; - expect(_file('app/components/x-foo.hbs')).to.equal('{{yield}}'); + expect(_file('app/components/x-foo.gjs')).to.equal( + fixture('component/template-only-component.gjs') + ); - expect(_file('tests/integration/components/x-foo-test.js')).to.equal( - fixture('component-test/app.js', { + expect(_file('tests/integration/components/x-foo-test.gjs')).to.equal( + fixture('component-test/app.gjs', { replace: { component: 'x-foo', componentInvocation: 'XFoo', + testDescription: 'Integration | Component | x-foo', }, }) ); @@ -213,13 +227,16 @@ describe('Blueprint: component', function () { expect(_file('app/templates/components/x-foo.js.hbs')).to.not.exist; expect(_file('tests/integration/components/x-foo-test.js.js')).to.not.exist; - expect(_file('app/components/x-foo.hbs')).to.equal('{{yield}}'); + expect(_file('app/components/x-foo.gjs')).to.equal( + fixture('component/template-only-component.gjs') + ); - expect(_file('tests/integration/components/x-foo-test.js')).to.equal( - fixture('component-test/app.js', { + expect(_file('tests/integration/components/x-foo-test.gjs')).to.equal( + fixture('component-test/app.gjs', { replace: { component: 'x-foo', componentInvocation: 'XFoo', + testDescription: 'Integration | Component | x-foo', }, }) ); @@ -229,13 +246,16 @@ describe('Blueprint: component', function () { it('component foo/x-foo', function () { return emberGenerateDestroy(['component', 'foo/x-foo'], (_file) => { expect(_file('app/components/foo/x-foo.js')).to.not.exist; - expect(_file('app/components/foo/x-foo.hbs')).to.equal('{{yield}}'); + expect(_file('app/components/foo/x-foo.gjs')).to.equal( + fixture('component/template-only-component.gjs') + ); - expect(_file('tests/integration/components/foo/x-foo-test.js')).to.equal( - fixture('component-test/app.js', { + expect(_file('tests/integration/components/foo/x-foo-test.gjs')).to.equal( + fixture('component-test/app.gjs', { replace: { component: 'foo/x-foo', - componentInvocation: 'Foo::XFoo', + componentInvocation: 'XFoo', + testDescription: 'Integration | Component | foo/x-foo', }, }) ); @@ -246,16 +266,18 @@ describe('Blueprint: component', function () { return emberGenerateDestroy( ['component', 'foo/x-foo', '--component-class', '@glimmer/component'], (_file) => { - expect(_file('app/components/foo/x-foo.js')).to.equal( - glimmerComponentContents.replace('Foo', 'FooXFoo') + expect(_file('app/components/foo/x-foo.js')).to.not.exist; + expect(_file('app/components/foo/x-foo.hbs')).to.not.exist; + expect(_file('app/components/foo/x-foo.gjs')).to.equal( + fixture('component/glimmer-component.gjs', {}).replace('Foo', 'FooXFoo') ); - expect(_file('app/components/foo/x-foo.hbs')).to.equal('{{yield}}'); - expect(_file('tests/integration/components/foo/x-foo-test.js')).to.equal( - fixture('component-test/app.js', { + expect(_file('tests/integration/components/foo/x-foo-test.gjs')).to.equal( + fixture('component-test/app.gjs', { replace: { component: 'foo/x-foo', - componentInvocation: 'Foo::XFoo', + componentInvocation: 'XFoo', + testDescription: 'Integration | Component | foo/x-foo', }, }) ); @@ -270,7 +292,13 @@ describe('Blueprint: component', function () { ); expect(_file('tests/integration/components/foo-test.gjs')).to.equal( - fixture('component-test/app.gjs') + fixture('component-test/app.gjs', { + replace: { + component: 'foo', + componentInvocation: 'Foo', + testDescription: 'Integration | Component | foo', + }, + }) ); }); }); @@ -284,7 +312,13 @@ describe('Blueprint: component', function () { ); expect(_file('tests/integration/components/foo-test.gjs')).to.equal( - fixture('component-test/app.gjs') + fixture('component-test/app.gjs', { + replace: { + component: 'foo', + componentInvocation: 'Foo', + testDescription: 'Integration | Component | foo', + }, + }) ); } ); @@ -335,7 +369,9 @@ describe('Blueprint: component', function () { return emberGenerateDestroy(['component', 'foo'], (_file) => { expect(_file('addon/components/foo.js')).to.not.exist; - expect(_file('addon/components/foo.hbs')).to.equal('{{yield}}'); + expect(_file('addon/components/foo.gjs')).to.equal( + fixture('component/template-only-component.gjs') + ); expect(_file('app/components/foo.js')).to.contain( "export { default } from 'my-addon/components/foo';" @@ -343,11 +379,12 @@ describe('Blueprint: component', function () { expect(_file('app/templates/components/foo.js')).to.not.exist; - expect(_file('tests/integration/components/foo-test.js')).to.equal( - fixture('component-test/addon.js', { + expect(_file('tests/integration/components/foo-test.gjs')).to.equal( + fixture('component-test/addon.gjs', { replace: { component: 'foo', componentInvocation: 'Foo', + testDescription: 'Integration | Component | foo', }, }) ); @@ -358,7 +395,9 @@ describe('Blueprint: component', function () { return emberGenerateDestroy(['component', 'x-foo'], (_file) => { expect(_file('addon/components/x-foo.js')).to.not.exist; - expect(_file('addon/components/x-foo.hbs')).to.equal('{{yield}}'); + expect(_file('addon/components/x-foo.gjs')).to.equal( + fixture('component/template-only-component.gjs') + ); expect(_file('app/components/x-foo.js')).to.contain( "export { default } from 'my-addon/components/x-foo';" @@ -367,11 +406,12 @@ describe('Blueprint: component', function () { expect(_file('app/templates/components/x-foo.js')).to.not.exist; expect(_file('app/components/x-foo.hbs')).to.not.exist; - expect(_file('tests/integration/components/x-foo-test.js')).to.equal( - fixture('component-test/addon.js', { + expect(_file('tests/integration/components/x-foo-test.gjs')).to.equal( + fixture('component-test/addon.gjs', { replace: { component: 'x-foo', componentInvocation: 'XFoo', + testDescription: 'Integration | Component | x-foo', }, }) ); @@ -439,7 +479,9 @@ describe('Blueprint: component', function () { return emberGenerateDestroy(['component', 'foo/x-foo'], (_file) => { expect(_file('addon/components/foo/x-foo.js')).to.not.exist; - expect(_file('addon/components/foo/x-foo.hbs')).to.equal('{{yield}}'); + expect(_file('addon/components/foo/x-foo.gjs')).to.equal( + fixture('component/template-only-component.gjs') + ); expect(_file('app/components/foo/x-foo.js')).to.contain( "export { default } from 'my-addon/components/foo/x-foo';" @@ -447,11 +489,12 @@ describe('Blueprint: component', function () { expect(_file('app/templates/components/foo/x-foo.js')).to.not.exist; - expect(_file('tests/integration/components/foo/x-foo-test.js')).to.equal( - fixture('component-test/addon.js', { + expect(_file('tests/integration/components/foo/x-foo-test.gjs')).to.equal( + fixture('component-test/addon.gjs', { replace: { component: 'foo/x-foo', - componentInvocation: 'Foo::XFoo', + componentInvocation: 'XFoo', + testDescription: 'Integration | Component | foo/x-foo', }, }) ); @@ -462,7 +505,9 @@ describe('Blueprint: component', function () { return emberGenerateDestroy(['component', 'x-foo', '--dummy'], (_file) => { expect(_file('tests/dummy/app/components/x-foo.js')).to.not.exist; - expect(_file('tests/dummy/app/components/x-foo.hbs')).to.equal('{{yield}}'); + expect(_file('tests/dummy/app/components/x-foo.gjs')).to.equal( + fixture('component/template-only-component.gjs') + ); expect(_file('app/components/x-foo.js')).to.not.exist; expect(_file('app/components/x-foo.hbs')).to.not.exist; @@ -476,7 +521,9 @@ describe('Blueprint: component', function () { return emberGenerateDestroy(['component', 'foo/x-foo', '--dummy'], (_file) => { expect(_file('tests/dummy/app/components/foo/x-foo.js')).to.not.exist; - expect(_file('tests/dummy/app/components/foo/x-foo.hbs')).to.equal('{{yield}}'); + expect(_file('tests/dummy/app/components/foo/x-foo.gjs')).to.equal( + fixture('component/template-only-component.gjs') + ); expect(_file('tests/dummy/app/templates/components/foo/x-foo.hbs')).to.not.exist; expect(_file('app/components/foo/x-foo.js')).to.not.exist; @@ -496,7 +543,9 @@ describe('Blueprint: component', function () { it('component foo --in-repo-addon=my-addon', function () { return emberGenerateDestroy(['component', 'foo', '--in-repo-addon=my-addon'], (_file) => { expect(_file('lib/my-addon/addon/components/foo.js')).to.not.exist; - expect(_file('lib/my-addon/addon/components/foo.hbs')).to.equal('{{yield}}'); + expect(_file('lib/my-addon/addon/components/foo.gjs')).to.equal( + fixture('component/template-only-component.gjs') + ); expect(_file('lib/my-addon/addon/templates/components/foo.hbs')).to.not.exist; expect(_file('lib/my-addon/app/components/foo.js')).to.contain( @@ -506,11 +555,12 @@ describe('Blueprint: component', function () { expect(_file('lib/my-addon/app/templates/components/foo.js')).to.not.exist; expect(_file('lib/my-addon/app/components/foo.hbs')).to.not.exist; - expect(_file('tests/integration/components/foo-test.js')).to.equal( - fixture('component-test/app.js', { + expect(_file('tests/integration/components/foo-test.gjs')).to.equal( + fixture('component-test/app.gjs', { replace: { component: 'foo', componentInvocation: 'Foo', + testDescription: 'Integration | Component | foo', }, }) ); @@ -520,7 +570,9 @@ describe('Blueprint: component', function () { it('component x-foo --in-repo-addon=my-addon', function () { return emberGenerateDestroy(['component', 'x-foo', '--in-repo-addon=my-addon'], (_file) => { expect(_file('lib/my-addon/addon/components/x-foo.js')).to.not.exist; - expect(_file('lib/my-addon/addon/components/x-foo.hbs')).to.equal('{{yield}}'); + expect(_file('lib/my-addon/addon/components/x-foo.gjs')).to.equal( + fixture('component/template-only-component.gjs') + ); expect(_file('lib/my-addon/addon/templates/components/x-foo.hbs')).to.not.exist; expect(_file('lib/my-addon/app/components/x-foo.js')).to.contain( @@ -530,11 +582,12 @@ describe('Blueprint: component', function () { expect(_file('lib/my-addon/app/templates/components/x-foo.js')).to.not.exist; expect(_file('lib/my-addon/app/components/x-foo.hbs')).to.not.exist; - expect(_file('tests/integration/components/x-foo-test.js')).to.equal( - fixture('component-test/app.js', { + expect(_file('tests/integration/components/x-foo-test.gjs')).to.equal( + fixture('component-test/app.gjs', { replace: { component: 'x-foo', componentInvocation: 'XFoo', + testDescription: 'Integration | Component | x-foo', }, }) ); diff --git a/node-tests/blueprints/route-test.js b/node-tests/blueprints/route-test.js index c018165bf66..47dcd142156 100644 --- a/node-tests/blueprints/route-test.js +++ b/node-tests/blueprints/route-test.js @@ -16,6 +16,13 @@ const fs = require('fs-extra'); const fixture = require('../helpers/fixture'); +function strictRouteTemplate(routeName, { addTitle = true } = {}) { + if (addTitle) { + return `import { pageTitle } from 'ember-page-title';\n\n\n`; + } + return '\n'; +} + describe('Blueprint: route', function () { setupTestHooks(this); @@ -28,7 +35,7 @@ describe('Blueprint: route', function () { return emberGenerateDestroy(['route', 'foo'], (_file) => { expect(_file('app/routes/foo.js')).to.equal(fixture('route/route.js')); - expect(_file('app/templates/foo.hbs')).to.equal('{{page-title "Foo"}}\n{{outlet}}'); + expect(_file('app/templates/foo.gjs')).to.equal(strictRouteTemplate('Foo')); expect(_file('tests/unit/routes/foo-test.js')).to.equal(fixture('route-test/app.js')); @@ -46,7 +53,7 @@ describe('Blueprint: route', function () { expect(_file('app/routes/foo.js')).to.equal(fixture('route/route.js')); - expect(_file('app/templates/foo.hbs')).to.equal('{{page-title "Foo"}}\n{{outlet}}'); + expect(_file('app/templates/foo.gjs')).to.equal(strictRouteTemplate('Foo')); expect(_file('tests/unit/routes/foo-test.js')).to.equal(fixture('route-test/app.js')); @@ -60,7 +67,7 @@ describe('Blueprint: route', function () { it('route foo --skip-router', function () { return emberGenerateDestroy(['route', 'foo', '--skip-router'], (_file) => { expect(_file('app/routes/foo.js')).to.exist; - expect(_file('app/templates/foo.hbs')).to.exist; + expect(_file('app/templates/foo.gjs')).to.exist; expect(_file('tests/unit/routes/foo-test.js')).to.exist; expect(file('app/router.js')).to.not.contain("this.route('foo')"); }).then(() => { @@ -72,7 +79,7 @@ describe('Blueprint: route', function () { return emberGenerateDestroy(['route', 'foo', '--path=:foo_id/show'], (_file) => { expect(_file('app/routes/foo.js')).to.equal(fixture('route/route-with-dynamic-segment.js')); - expect(_file('app/templates/foo.hbs')).to.equal('{{page-title "Foo"}}\n{{outlet}}'); + expect(_file('app/templates/foo.gjs')).to.equal(strictRouteTemplate('Foo')); expect(_file('tests/unit/routes/foo-test.js')).to.equal(fixture('route-test/app.js')); @@ -91,7 +98,7 @@ describe('Blueprint: route', function () { return emberGenerateDestroy(['route', 'parent/child', '--reset-namespace'], (_file) => { expect(_file('app/routes/child.js')).to.equal(fixture('route/route-child.js')); - expect(_file('app/templates/child.hbs')).to.equal('{{page-title "Child"}}\n{{outlet}}'); + expect(_file('app/templates/child.gjs')).to.equal(strictRouteTemplate('Child')); expect(_file('tests/unit/routes/child-test.js')).to.equal(fixture('route-test/child.js')); @@ -109,7 +116,7 @@ describe('Blueprint: route', function () { (_file) => { expect(_file('app/child/route.js')).to.equal(fixture('route/route-child.js')); - expect(_file('app/child/template.hbs')).to.equal('{{page-title "Child"}}\n{{outlet}}'); + expect(_file('app/child/template.gjs')).to.equal(strictRouteTemplate('Child')); expect(_file('tests/unit/child/route-test.js')).to.equal(fixture('route-test/child.js')); @@ -125,7 +132,7 @@ describe('Blueprint: route', function () { it('route index', function () { return emberGenerateDestroy(['route', 'index'], (_file) => { expect(_file('app/routes/index.js')).to.exist; - expect(_file('app/templates/index.hbs')).to.exist; + expect(_file('app/templates/index.gjs')).to.exist; expect(_file('tests/unit/routes/index-test.js')).to.exist; expect(file('app/router.js')).to.not.contain("this.route('index')"); }).then(() => { @@ -134,7 +141,7 @@ describe('Blueprint: route', function () { }); it('route application', function () { - fs.removeSync('app/templates/application.hbs'); + fs.removeSync('app/templates/application.gjs'); return emberGenerate(['route', 'application']).then(() => { expect(file('app/router.js')).to.not.contain("this.route('application')"); }); @@ -228,7 +235,7 @@ describe('Blueprint: route', function () { expect(_file('app/foo/route.js')).to.equal(fixture('route/route.js')); - expect(_file('app/foo/template.hbs')).to.equal('{{page-title "Foo"}}\n{{outlet}}'); + expect(_file('app/foo/template.gjs')).to.equal(strictRouteTemplate('Foo')); expect(_file('tests/unit/foo/route-test.js')).to.equal(fixture('route-test/app.js')); @@ -246,7 +253,7 @@ describe('Blueprint: route', function () { expect(_file('app/foo/route.js')).to.equal(fixture('route/route.js')); - expect(_file('app/foo/template.hbs')).to.equal('{{page-title "Foo"}}\n{{outlet}}'); + expect(_file('app/foo/template.gjs')).to.equal(strictRouteTemplate('Foo')); expect(_file('tests/unit/foo/route-test.js')).to.equal(fixture('route-test/app.js')); @@ -283,7 +290,7 @@ describe('Blueprint: route', function () { it('route application --pod', function () { return emberGenerate(['route', 'application', '--pod']) .then(() => expect(file('app/application/route.js')).to.exist) - .then(() => expect(file('app/application/template.hbs')).to.exist) + .then(() => expect(file('app/application/template.gjs')).to.exist) .then(() => expect(file('app/router.js')).to.not.contain("this.route('application')")); }); @@ -303,7 +310,7 @@ describe('Blueprint: route', function () { return emberGenerateDestroy(['route', 'foo', '--pod'], (_file) => { expect(_file('app/pods/foo/route.js')).to.equal(fixture('route/route.js')); - expect(_file('app/pods/foo/template.hbs')).to.equal('{{page-title "Foo"}}\n{{outlet}}'); + expect(_file('app/pods/foo/template.gjs')).to.equal(strictRouteTemplate('Foo')); expect(_file('tests/unit/pods/foo/route-test.js')).to.equal(fixture('route-test/app.js')); @@ -321,7 +328,7 @@ describe('Blueprint: route', function () { expect(_file('app/pods/foo/route.js')).to.equal(fixture('route/route.js')); - expect(_file('app/pods/foo/template.hbs')).to.equal('{{page-title "Foo"}}\n{{outlet}}'); + expect(_file('app/pods/foo/template.gjs')).to.equal(strictRouteTemplate('Foo')); expect(_file('tests/unit/pods/foo/route-test.js')).to.equal(fixture('route-test/app.js')); @@ -339,13 +346,17 @@ describe('Blueprint: route', function () { it('route foo', function () { return emberGenerateDestroy(['route', 'foo'], (_file) => { - expect(_file('app/templates/foo.hbs')).to.equal('{{outlet}}'); + expect(_file('app/templates/foo.gjs')).to.equal( + strictRouteTemplate('Foo', { addTitle: false }) + ); }); }); it('route foo/bar', function () { return emberGenerateDestroy(['route', 'foo/bar'], (_file) => { - expect(_file('app/templates/foo/bar.hbs')).to.equal('{{outlet}}'); + expect(_file('app/templates/foo/bar.gjs')).to.equal( + strictRouteTemplate('Bar', { addTitle: false }) + ); }); }); }); @@ -387,7 +398,7 @@ describe('Blueprint: route', function () { return emberGenerateDestroy(['route', 'foo'], (_file) => { expect(_file('addon/routes/foo.js')).to.equal(fixture('route/route.js')); - expect(_file('addon/templates/foo.hbs')).to.equal('{{page-title "Foo"}}\n{{outlet}}'); + expect(_file('addon/templates/foo.gjs')).to.equal(strictRouteTemplate('Foo')); expect(_file('app/routes/foo.js')).to.contain( "export { default } from 'my-addon/routes/foo';" @@ -415,7 +426,7 @@ describe('Blueprint: route', function () { expect(_file('addon/routes/foo.js')).to.equal(fixture('route/route.js')); - expect(_file('addon/templates/foo.hbs')).to.equal('{{page-title "Foo"}}\n{{outlet}}'); + expect(_file('addon/templates/foo.gjs')).to.equal(strictRouteTemplate('Foo')); expect(_file('app/routes/foo.js')).to.contain( "export { default } from 'my-addon/routes/foo';" @@ -438,7 +449,7 @@ describe('Blueprint: route', function () { return emberGenerateDestroy(['route', 'foo/bar'], (_file) => { expect(_file('addon/routes/foo/bar.js')).to.equal(fixture('route/route-nested.js')); - expect(_file('addon/templates/foo/bar.hbs')).to.equal('{{page-title "Bar"}}\n{{outlet}}'); + expect(_file('addon/templates/foo/bar.gjs')).to.equal(strictRouteTemplate('Bar')); expect(_file('app/routes/foo/bar.js')).to.contain( "export { default } from 'my-addon/routes/foo/bar';" @@ -462,9 +473,7 @@ describe('Blueprint: route', function () { return emberGenerateDestroy(['route', 'foo', '--dummy'], (_file) => { expect(_file('tests/dummy/app/routes/foo.js')).to.equal(fixture('route/route.js')); - expect(_file('tests/dummy/app/templates/foo.hbs')).to.equal( - '{{page-title "Foo"}}\n{{outlet}}' - ); + expect(_file('tests/dummy/app/templates/foo.gjs')).to.equal(strictRouteTemplate('Foo')); expect(_file('app/routes/foo.js')).to.not.exist; expect(_file('app/templates/foo.hbs')).to.not.exist; @@ -483,9 +492,7 @@ describe('Blueprint: route', function () { expect(_file('tests/dummy/app/routes/foo.js')).to.equal(fixture('route/route.js')); - expect(_file('tests/dummy/app/templates/foo.hbs')).to.equal( - '{{page-title "Foo"}}\n{{outlet}}' - ); + expect(_file('tests/dummy/app/templates/foo.gjs')).to.equal(strictRouteTemplate('Foo')); expect(_file('app/routes/foo.js')).to.not.exist; expect(_file('app/templates/foo.hbs')).to.not.exist; @@ -504,9 +511,7 @@ describe('Blueprint: route', function () { fixture('route/route-nested.js') ); - expect(_file('tests/dummy/app/templates/foo/bar.hbs')).to.equal( - '{{page-title "Bar"}}\n{{outlet}}' - ); + expect(_file('tests/dummy/app/templates/foo/bar.gjs')).to.equal(strictRouteTemplate('Bar')); expect(_file('app/routes/foo/bar.js')).to.not.exist; expect(_file('app/templates/foo/bar.hbs')).to.not.exist; @@ -524,7 +529,7 @@ describe('Blueprint: route', function () { return emberGenerateDestroy(['route', 'foo', '--pod'], (_file) => { expect(_file('addon/foo/route.js')).to.equal(fixture('route/route.js')); - expect(_file('addon/foo/template.hbs')).to.equal('{{page-title "Foo"}}\n{{outlet}}'); + expect(_file('addon/foo/template.gjs')).to.equal(strictRouteTemplate('Foo')); expect(_file('app/foo/route.js')).to.contain( "export { default } from 'my-addon/foo/route';" @@ -548,7 +553,7 @@ describe('Blueprint: route', function () { expect(_file('addon/foo/route.js')).to.equal(fixture('route/route.js')); - expect(_file('addon/foo/template.hbs')).to.equal('{{page-title "Foo"}}\n{{outlet}}'); + expect(_file('addon/foo/template.gjs')).to.equal(strictRouteTemplate('Foo')); expect(_file('app/foo/route.js')).to.contain( "export { default } from 'my-addon/foo/route';" @@ -569,13 +574,17 @@ describe('Blueprint: route', function () { it('route foo', function () { return emberGenerateDestroy(['route', 'foo'], (_file) => { - expect(_file('addon/templates/foo.hbs')).to.equal('{{outlet}}'); + expect(_file('addon/templates/foo.gjs')).to.equal( + strictRouteTemplate('Foo', { addTitle: false }) + ); }); }); it('route foo/bar', function () { return emberGenerateDestroy(['route', 'foo/bar'], (_file) => { - expect(_file('addon/templates/foo/bar.hbs')).to.equal('{{outlet}}'); + expect(_file('addon/templates/foo/bar.gjs')).to.equal( + strictRouteTemplate('Bar', { addTitle: false }) + ); }); }); }); @@ -616,9 +625,7 @@ describe('Blueprint: route', function () { return emberGenerateDestroy(['route', 'foo', '--in-repo-addon=my-addon'], (_file) => { expect(_file('lib/my-addon/addon/routes/foo.js')).to.equal(fixture('route/route.js')); - expect(_file('lib/my-addon/addon/templates/foo.hbs')).to.equal( - '{{page-title "Foo"}}\n{{outlet}}' - ); + expect(_file('lib/my-addon/addon/templates/foo.gjs')).to.equal(strictRouteTemplate('Foo')); expect(_file('lib/my-addon/app/routes/foo.js')).to.contain( "export { default } from 'my-addon/routes/foo';" @@ -642,9 +649,7 @@ describe('Blueprint: route', function () { expect(_file('lib/my-addon/addon/routes/foo.js')).to.equal(fixture('route/route.js')); - expect(_file('lib/my-addon/addon/templates/foo.hbs')).to.equal( - '{{page-title "Foo"}}\n{{outlet}}' - ); + expect(_file('lib/my-addon/addon/templates/foo.gjs')).to.equal(strictRouteTemplate('Foo')); expect(_file('lib/my-addon/app/routes/foo.js')).to.contain( "export { default } from 'my-addon/routes/foo';" @@ -664,8 +669,8 @@ describe('Blueprint: route', function () { fixture('route/route-nested.js') ); - expect(_file('lib/my-addon/addon/templates/foo/bar.hbs')).to.equal( - '{{page-title "Bar"}}\n{{outlet}}' + expect(_file('lib/my-addon/addon/templates/foo/bar.gjs')).to.equal( + strictRouteTemplate('Bar') ); expect(_file('lib/my-addon/app/routes/foo/bar.js')).to.contain( @@ -689,13 +694,17 @@ describe('Blueprint: route', function () { it('route foo', function () { return emberGenerateDestroy(['route', 'foo', '--in-repo-addon=my-addon'], (_file) => { - expect(_file('lib/my-addon/addon/templates/foo.hbs')).to.equal('{{outlet}}'); + expect(_file('lib/my-addon/addon/templates/foo.gjs')).to.equal( + strictRouteTemplate('Foo', { addTitle: false }) + ); }); }); it('route foo/bar', function () { return emberGenerateDestroy(['route', 'foo/bar', '--in-repo-addon=my-addon'], (_file) => { - expect(_file('lib/my-addon/addon/templates/foo/bar.hbs')).to.equal('{{outlet}}'); + expect(_file('lib/my-addon/addon/templates/foo/bar.gjs')).to.equal( + strictRouteTemplate('Bar', { addTitle: false }) + ); }); }); }); diff --git a/node-tests/fixtures/component-test/addon.gjs b/node-tests/fixtures/component-test/addon.gjs index f68723e10ca..79a65697eb1 100644 --- a/node-tests/fixtures/component-test/addon.gjs +++ b/node-tests/fixtures/component-test/addon.gjs @@ -1,9 +1,9 @@ import { module, test } from 'qunit'; import { setupRenderingTest } from 'dummy/tests/helpers'; import { render } from '@ember/test-helpers'; -import Foo from 'my-addon/components/foo'; +import <%= componentInvocation =%> from 'my-addon/components/<%= component =%>'; -module('Integration | Component | foo', function (hooks) { +module('<%= testDescription =%>', function (hooks) { setupRenderingTest(hooks); test('it renders', async function (assert) { @@ -12,15 +12,15 @@ module('Integration | Component | foo', function (hooks) { // and update using state.myProperty = 1; await rerender(); // Handle any actions with function myAction(val) { ... }; - await render(); + await render(); assert.dom().hasText(''); // Template block usage: await render(); assert.dom().hasText('template block text'); diff --git a/node-tests/fixtures/component-test/app.gjs b/node-tests/fixtures/component-test/app.gjs index 889ab8807a5..ca3015a52e2 100644 --- a/node-tests/fixtures/component-test/app.gjs +++ b/node-tests/fixtures/component-test/app.gjs @@ -1,9 +1,9 @@ import { module, test } from 'qunit'; import { setupRenderingTest } from 'my-app/tests/helpers'; import { render } from '@ember/test-helpers'; -import Foo from 'my-app/components/foo'; +import <%= componentInvocation =%> from 'my-app/components/<%= component =%>'; -module('Integration | Component | foo', function (hooks) { +module('<%= testDescription =%>', function (hooks) { setupRenderingTest(hooks); test('it renders', async function (assert) { @@ -12,15 +12,15 @@ module('Integration | Component | foo', function (hooks) { // and update using state.myProperty = 1; await rerender(); // Handle any actions with function myAction(val) { ... }; - await render(); + await render(); assert.dom().hasText(''); // Template block usage: await render(); assert.dom().hasText('template block text'); diff --git a/package.json b/package.json index e7f45dbf34f..02c2e2d0c6f 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,6 @@ }, "dependencies": { "@babel/core": "^7.24.4", - "@ember/edition-utils": "^1.2.0", "@embroider/addon-shim": "^1.10.2", "@simple-dom/interface": "^1.4.0", "backburner.js": "^2.8.0", @@ -77,16 +76,13 @@ "chalk": "^4.0.0", "ember-cli-babel": "^8.2.0", "ember-cli-get-component-path-option": "^1.0.0", - "ember-cli-is-package-missing": "^1.0.0", "ember-cli-normalize-entity-name": "^1.0.0", "ember-cli-path-utils": "^1.0.0", "ember-cli-string-utils": "^1.1.0", "ember-cli-typescript-blueprint-polyfill": "^0.1.0", - "ember-cli-version-checker": "^5.1.2", "ember-router-generator": "^2.0.0", "inflection": "^2.0.1", "route-recognizer": "^0.3.4", - "router_js": "^8.0.5", "semver": "^7.5.2", "silent-error": "^1.1.1", "simple-html-tokenizer": "^0.5.11" @@ -112,7 +108,6 @@ "auto-dist-tag": "^2.1.1", "babel-plugin-debug-macros": "1.0.0", "babel-plugin-ember-template-compilation": "3.0.0-alpha.4", - "brotli": "^1.3.3", "dag-map": "^2.0.2", "decorator-transforms": "2.0.0", "ember-cli": "^6.3.0", @@ -129,7 +124,6 @@ "eslint-plugin-qunit": "^8.1.2", "execa": "^5.1.1", "expect-type": "^0.15.0", - "filesize": "^10.1.6", "fs-extra": "^11.1.1", "git-repo-info": "^2.1.1", "github": "^0.2.3", @@ -137,15 +131,14 @@ "globals": "^16.0.0", "kill-port-process": "^3.2.1", "mocha": "^10.2.0", - "node-gzip": "^1.1.2", - "npm-run-all2": "^6.0.6", + "npm-run-all2": "^8.0.0", "prettier": "^3.5.3", "qunit": "^2.19.4", "recast": "^0.22.0", "resolve.exports": "^2.0.3", "rollup": "^4.57.1", + "router_js": "workspace:*", "rsvp": "^4.8.5", - "table": "^6.9.0", "terser": "^5.42.0", "testem": "^3.10.1", "testem-failure-only-reporter": "^1.0.0", @@ -295,6 +288,7 @@ "@ember/template-compiler/lib/-internal/primitives.js": "ember-source/@ember/template-compiler/lib/-internal/primitives.js", "@ember/template-compiler/lib/compile-options.js": "ember-source/@ember/template-compiler/lib/compile-options.js", "@ember/template-compiler/lib/dasherize-component-name.js": "ember-source/@ember/template-compiler/lib/dasherize-component-name.js", + "@ember/template-compiler/lib/plugins/allowed-globals.js": "ember-source/@ember/template-compiler/lib/plugins/allowed-globals.js", "@ember/template-compiler/lib/plugins/assert-against-attrs.js": "ember-source/@ember/template-compiler/lib/plugins/assert-against-attrs.js", "@ember/template-compiler/lib/plugins/assert-against-named-outlets.js": "ember-source/@ember/template-compiler/lib/plugins/assert-against-named-outlets.js", "@ember/template-compiler/lib/plugins/assert-input-helper-without-block.js": "ember-source/@ember/template-compiler/lib/plugins/assert-input-helper-without-block.js", diff --git a/packages/@ember/-internals/environment/index.ts b/packages/@ember/-internals/environment/index.ts index bd0f49e5b0a..27e1530a895 100644 --- a/packages/@ember/-internals/environment/index.ts +++ b/packages/@ember/-internals/environment/index.ts @@ -1,3 +1,2 @@ export * from './lib/context'; export * from './lib/env'; -export { default as global } from './lib/global'; diff --git a/packages/@ember/-internals/environment/lib/context.ts b/packages/@ember/-internals/environment/lib/context.ts index a6e38c12103..d6d7267f624 100644 --- a/packages/@ember/-internals/environment/lib/context.ts +++ b/packages/@ember/-internals/environment/lib/context.ts @@ -1,17 +1,15 @@ -import global from './global'; - export interface GlobalContext { imports: object; exports: object; lookup: Record; } +const global = globalThis as Record; +const Ember = global['Ember'] as Partial | undefined; + // legacy imports/exports/lookup stuff (should we keep this??) -export const context = (function ( - global: Record, - Ember: Partial | undefined -): GlobalContext { - return Ember === undefined +export const context: GlobalContext = + Ember === undefined ? { imports: global, exports: global, lookup: global } : { // import jQuery @@ -21,7 +19,6 @@ export const context = (function ( // search for Namespaces lookup: Ember.lookup || global, }; -})(global, global.Ember); export function getLookup(): Record { return context.lookup; diff --git a/packages/@ember/-internals/environment/lib/env.ts b/packages/@ember/-internals/environment/lib/env.ts index b71f02d9702..8bf539aef25 100644 --- a/packages/@ember/-internals/environment/lib/env.ts +++ b/packages/@ember/-internals/environment/lib/env.ts @@ -1,5 +1,4 @@ import { DEBUG } from '@glimmer/env'; -import global from './global'; /** The hash of environment variables used to control various configuration @@ -154,15 +153,15 @@ export const ENV = { }, }; -(( - EmberENV: Record & { - EXTEND_PROTOTYPES?: boolean; - EMBER_LOAD_HOOKS?: Record; - FEATURES?: Record; - } -) => { - if (typeof EmberENV !== 'object' || EmberENV === null) return; +interface EmberENVConfig extends Record { + EXTEND_PROTOTYPES?: boolean; + EMBER_LOAD_HOOKS?: Record; + FEATURES?: Record; +} +const EmberENV = (globalThis as { EmberENV?: EmberENVConfig }).EmberENV; + +if (typeof EmberENV === 'object' && EmberENV !== null) { for (let flag in EmberENV) { if ( !Object.prototype.hasOwnProperty.call(EmberENV, flag) || @@ -203,7 +202,7 @@ export const ENV = { if (DEBUG) { ENV._DEBUG_RENDER_TREE = true; } -})(global.EmberENV); +} export function getENV(): object { return ENV; diff --git a/packages/@ember/-internals/environment/lib/global.ts b/packages/@ember/-internals/environment/lib/global.ts deleted file mode 100644 index 9744e80da21..00000000000 --- a/packages/@ember/-internals/environment/lib/global.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* globals window, self */ -declare const mainContext: object | undefined; - -// from lodash to catch fake globals -function checkGlobal(value: any | null | undefined): object | undefined { - return value && value.Object === Object ? value : undefined; -} - -// element ids can ruin global miss checks -function checkElementIdShadowing(value: any | null | undefined) { - return value && value.nodeType === undefined ? value : undefined; -} - -declare const global: unknown; - -// export real global -export default checkGlobal(checkElementIdShadowing(typeof global === 'object' && global)) || - checkGlobal(typeof self === 'object' && self) || - checkGlobal(typeof window === 'object' && window) || - (typeof mainContext !== 'undefined' && mainContext) || // set before strict mode in Ember loader/wrapper - new Function('return this')(); // eval outside of strict mode diff --git a/packages/@ember/-internals/glimmer/lib/component-managers/curly.ts b/packages/@ember/-internals/glimmer/lib/component-managers/curly.ts index 3dff5f3bace..44b4cdc5c61 100644 --- a/packages/@ember/-internals/glimmer/lib/component-managers/curly.ts +++ b/packages/@ember/-internals/glimmer/lib/component-managers/curly.ts @@ -531,11 +531,11 @@ export function initialRenderInstrumentDetails(component: any): any { return component.instrumentDetails({ initialRender: true }); } -export function rerenderInstrumentDetails(component: any): any { +function rerenderInstrumentDetails(component: any): any { return component.instrumentDetails({ initialRender: false }); } -export const CURLY_CAPABILITIES: InternalComponentCapabilities = { +const CURLY_CAPABILITIES: InternalComponentCapabilities = { dynamicLayout: true, dynamicTag: true, prepareArgs: true, diff --git a/packages/@ember/-internals/glimmer/lib/component-managers/root.ts b/packages/@ember/-internals/glimmer/lib/component-managers/root.ts index 00aca8f633c..a0488f74488 100644 --- a/packages/@ember/-internals/glimmer/lib/component-managers/root.ts +++ b/packages/@ember/-internals/glimmer/lib/component-managers/root.ts @@ -78,7 +78,7 @@ class RootComponentManager extends CurlyComponentManager { // ROOT is the top-level template it has nothing but one yield. // it is supposed to have a dummy element -export const ROOT_CAPABILITIES: InternalComponentCapabilities = { +const ROOT_CAPABILITIES: InternalComponentCapabilities = { dynamicLayout: true, dynamicTag: true, prepareArgs: false, diff --git a/packages/@ember/-internals/glimmer/lib/components/link-to.ts b/packages/@ember/-internals/glimmer/lib/components/link-to.ts index 1102525721e..a8c55b759e0 100644 --- a/packages/@ember/-internals/glimmer/lib/components/link-to.ts +++ b/packages/@ember/-internals/glimmer/lib/components/link-to.ts @@ -554,12 +554,12 @@ class _LinkTo extends InternalComponent { if (typeof currentWhen === 'boolean') { return currentWhen; } else if (typeof currentWhen === 'string') { - let { models, routing } = this; + let { routing } = this; return currentWhen .split(' ') .some((route) => - routing.isActiveForRoute(models, undefined, this.namespaceRoute(route), state) + routing.isActiveForRoute([], undefined, this.namespaceRoute(route), state) ); } else { let { route, models, query, routing } = this; diff --git a/packages/@ember/-internals/glimmer/lib/helper.ts b/packages/@ember/-internals/glimmer/lib/helper.ts index 5105852957e..a538c33aeed 100644 --- a/packages/@ember/-internals/glimmer/lib/helper.ts +++ b/packages/@ember/-internals/glimmer/lib/helper.ts @@ -14,7 +14,7 @@ import { getInternalHelperManager, helperCapabilities, setHelperManager } from ' import type { DirtyableTag } from '@glimmer/validator'; import { consumeTag, createTag, dirtyTag } from '@glimmer/validator'; -export const RECOMPUTE_TAG = Symbol('RECOMPUTE_TAG'); +const RECOMPUTE_TAG = Symbol('RECOMPUTE_TAG'); // Signature type utilities type GetOr = K extends keyof T ? T[K] : Else; @@ -293,7 +293,7 @@ class SimpleClassicHelperManager implements HelperManager<() => unknown> { } } -export const SIMPLE_CLASSIC_HELPER_MANAGER = new SimpleClassicHelperManager(); +const SIMPLE_CLASSIC_HELPER_MANAGER = new SimpleClassicHelperManager(); setHelperManager(() => SIMPLE_CLASSIC_HELPER_MANAGER, Wrapper.prototype); diff --git a/packages/@ember/-internals/glimmer/lib/modifiers/internal.ts b/packages/@ember/-internals/glimmer/lib/modifiers/internal.ts deleted file mode 100644 index d62959ceb67..00000000000 --- a/packages/@ember/-internals/glimmer/lib/modifiers/internal.ts +++ /dev/null @@ -1,103 +0,0 @@ -import type { InternalOwner } from '@ember/-internals/owner'; -import { setOwner } from '@ember/-internals/owner'; -import { guidFor } from '@ember/-internals/utils'; -import { assert } from '@ember/debug'; -import { registerDestructor } from '@glimmer/destroyable'; -import type { - CapturedArguments, - Destroyable, - InternalModifierManager as ModifierManager, -} from '@glimmer/interfaces'; -import { valueForRef } from '@glimmer/reference'; -import type { SimpleElement } from '@simple-dom/interface'; - -export default class InternalModifier { - // Override this - static toString(): string { - return 'internal modifier'; - } - - constructor( - protected owner: InternalOwner, - protected readonly element: Element, - protected readonly args: CapturedArguments - ) { - setOwner(this, owner); - } - - install(): void {} - - remove(): void {} - - protected positional(index: number): unknown { - let ref = this.args.positional[index]; - return ref ? valueForRef(ref) : undefined; - } - - protected named(key: string): unknown { - let ref = this.args.named[key]; - return ref ? valueForRef(ref) : undefined; - } - - toString(): string { - return `<${this.constructor.toString()}:${guidFor(this)}>`; - } -} - -function destructor(modifier: InternalModifier): void { - modifier.remove(); -} - -class InternalModifierState implements Destroyable { - constructor(readonly instance: InternalModifier) {} -} - -export abstract class InternalModifierManager implements ModifierManager< - InternalModifierState, - typeof InternalModifier -> { - constructor( - private ModifierClass: typeof InternalModifier, - private name: string - ) {} - - create( - owner: InternalOwner, - element: SimpleElement, - _definition: unknown, - args: CapturedArguments - ): InternalModifierState { - assert('element must be an HTMLElement', element instanceof HTMLElement); - - let { ModifierClass } = this; - let instance = new ModifierClass(owner, element, args); - - registerDestructor(instance, destructor); - - return new InternalModifierState(instance); - } - - // not needed for now, but feel free to implement this - getTag(): null { - return null; - } - - abstract getDebugInstance(state: InternalModifierState): unknown; - - getDebugName(): string { - return this.name; - } - - install({ instance }: InternalModifierState): void { - return instance.install(); - } - - // not needed for now, but feel free to implement this - update(): void { - assert('update should never be called on an internal modifier'); - } - - getDestroyable({ instance }: InternalModifierState): Destroyable { - return instance; - } -} diff --git a/packages/@ember/-internals/glimmer/lib/renderer.ts b/packages/@ember/-internals/glimmer/lib/renderer.ts index e2b8d23e74e..cfc74e0e423 100644 --- a/packages/@ember/-internals/glimmer/lib/renderer.ts +++ b/packages/@ember/-internals/glimmer/lib/renderer.ts @@ -363,7 +363,7 @@ interface RendererData { builder: IBuilder; } -export class RendererState { +class RendererState { static create(data: RendererData, renderer: BaseRenderer): RendererState { const state = new RendererState(data, renderer); associateDestroyableChild(renderer, state); @@ -717,7 +717,7 @@ export function renderComponent( const RENDER_CACHE = new WeakMap(); const RENDERER_CACHE = new WeakMap(); -export class BaseRenderer { +class BaseRenderer { static strict( owner: object, document: SimpleDocument | Document, diff --git a/packages/@ember/-internals/glimmer/lib/resolver.ts b/packages/@ember/-internals/glimmer/lib/resolver.ts index e6517bc3e88..af51ab9865d 100644 --- a/packages/@ember/-internals/glimmer/lib/resolver.ts +++ b/packages/@ember/-internals/glimmer/lib/resolver.ts @@ -87,7 +87,7 @@ function lookupComponentPair(owner: InternalOwner, name: string): Nullable = { +const BUILTIN_KEYWORD_HELPERS: Record = { mut, readonly, unbound, @@ -101,7 +101,7 @@ export const BUILTIN_KEYWORD_HELPERS: Record = { '-in-el-null': inElementNullCheckHelper, }; -export const BUILTIN_HELPERS: Record = { +const BUILTIN_HELPERS: Record = { ...BUILTIN_KEYWORD_HELPERS, array, concat, diff --git a/packages/@ember/-internals/glimmer/lib/syntax/utils.ts b/packages/@ember/-internals/glimmer/lib/syntax/utils.ts deleted file mode 100644 index c4ee2eb856b..00000000000 --- a/packages/@ember/-internals/glimmer/lib/syntax/utils.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { Core, PresentArray } from '@glimmer/interfaces'; -import type { Nullable } from '@ember/-internals/utility-types'; - -export function hashToArgs(hash: Nullable): Nullable { - if (hash === null) return null; - let names = hash[0].map((key) => `@${key}`); - return [names as PresentArray, hash[1]]; -} diff --git a/packages/@ember/-internals/glimmer/lib/templates/empty.ts b/packages/@ember/-internals/glimmer/lib/templates/empty.ts deleted file mode 100644 index f5665d5f8b0..00000000000 --- a/packages/@ember/-internals/glimmer/lib/templates/empty.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { precompileTemplate } from '@ember/template-compilation'; -export default precompileTemplate('', { - moduleName: 'packages/@ember/-internals/glimmer/lib/templates/empty.hbs', - strictMode: true, -}); diff --git a/packages/@ember/-internals/glimmer/lib/utils/bindings.ts b/packages/@ember/-internals/glimmer/lib/utils/bindings.ts index bf112ddacee..405c44d390b 100644 --- a/packages/@ember/-internals/glimmer/lib/utils/bindings.ts +++ b/packages/@ember/-internals/glimmer/lib/utils/bindings.ts @@ -131,7 +131,7 @@ export function createSimpleClassNameBindingRef(inner: Reference, path?: string) }); } -export function createColonClassNameBindingRef( +function createColonClassNameBindingRef( inner: Reference, truthy: string, falsy: string | undefined diff --git a/packages/@ember/-internals/glimmer/lib/utils/debug-render-message.ts b/packages/@ember/-internals/glimmer/lib/utils/debug-render-message.ts deleted file mode 100644 index 9ef9c7f4bb2..00000000000 --- a/packages/@ember/-internals/glimmer/lib/utils/debug-render-message.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { DEBUG } from '@glimmer/env'; - -let debugRenderMessage: undefined | ((renderingStack: string) => string); - -if (DEBUG) { - debugRenderMessage = (renderingStack: string) => { - return `While rendering:\n----------------\n${renderingStack.replace(/^/gm, ' ')}`; - }; -} - -export default debugRenderMessage; diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/input-angle-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/input-angle-test.js index 4fcd2bb4771..428ffb8c855 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/input-angle-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/input-angle-test.js @@ -61,8 +61,7 @@ class InputRenderingTest extends RenderingTestCase { } triggerEvent(type, options, selector) { - let event = document.createEvent('Events'); - event.initEvent(type, true, true); + let event = new Event(type, { bubbles: true, cancelable: true }); Object.assign(event, options); let element = this.$(selector || 'input')[0]; diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/input-curly-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/input-curly-test.js index 42448fc0c9e..97f4732c6a6 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/input-curly-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/input-curly-test.js @@ -62,8 +62,7 @@ class InputRenderingTest extends RenderingTestCase { } triggerEvent(type, options) { - let event = document.createEvent('Events'); - event.initEvent(type, true, true); + let event = new Event(type, { bubbles: true, cancelable: true }); Object.assign(event, options); let element = this.$input()[0]; diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-angle-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-angle-test.js index 8062450e0ef..3ce04285b2f 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-angle-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-angle-test.js @@ -15,11 +15,6 @@ import Engine from '@ember/engine'; import { DEBUG } from '@glimmer/env'; import { compile } from '../../../utils/helpers'; -// IE includes the host name -function normalizeUrl(url) { - return url.replace(/https?:\/\/[^/]+/, ''); -} - function shouldNotBeActive(assert, element) { checkActive(assert, element, false); } @@ -152,9 +147,7 @@ moduleFor( // SVGAElement does not have a .click() method like HTMLElement, // so we dispatch a click event manually. let svgLink = document.querySelector('#svg-about-link'); - let clickEvent = document.createEvent('MouseEvents'); - clickEvent.initMouseEvent('click', true, true); - svgLink.dispatchEvent(clickEvent); + svgLink.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true })); await runLoopSettled(); assert.equal(this.$('h3.about').length, 1, 'The about template was rendered'); @@ -870,7 +863,7 @@ moduleFor( await this.visit('/about/item'); - assert.equal(normalizeUrl(this.$('#item a').attr('href')), '/about'); + assert.equal(this.$('#item a').attr('href'), '/about'); } async [`@test it supports custom, nested, current-when`](assert) { @@ -925,6 +918,37 @@ moduleFor( ); } + async [`@test it supports custom, nested, current-when with route params`](assert) { + assert.expect(2); + this.router.map(function () { + this.route('index', { path: '/' }); + this.route('foo', { path: '/foo/:fooId' }, function () { + this.route('bar', { path: '/bar/:barId' }); + }); + }); + + this.addTemplate('index', `{{outlet}}`); + this.addTemplate( + 'foo', + `Foo Index {{outlet}}` + ); + this.addTemplate( + 'foo.bar', + `Foo Bar` + ); + + await this.visit('/foo/1/bar/2'); + + assert.ok( + this.$('a[href="/foo/1"]').is('.active'), + 'The link to foo.index should be active when on foo.bar' + ); + assert.ok( + this.$('a[href="/foo/1/bar/2"]').is('.active'), + 'The link to foo.bar should be active when on foo.bar' + ); + } + async ['@test it does not disregard current-when when it is set via a bound param'](assert) { this.router.map(function () { this.route('index', { path: '/' }, function () { @@ -1195,11 +1219,7 @@ moduleFor( await this.visit('/about'); assert.equal(this.$('h3.list').length, 1, 'The home template was rendered'); - assert.equal( - normalizeUrl(this.$('#home-link').attr('href')), - '/', - 'The home link points back at /' - ); + assert.equal(this.$('#home-link').attr('href'), '/', 'The home link points back at /'); await this.click('#yehuda'); @@ -1210,9 +1230,9 @@ moduleFor( await this.click('#about-link'); - assert.equal(normalizeUrl(this.$('li a#yehuda').attr('href')), '/item/yehuda'); - assert.equal(normalizeUrl(this.$('li a#tom').attr('href')), '/item/tom'); - assert.equal(normalizeUrl(this.$('li a#erik').attr('href')), '/item/erik'); + assert.equal(this.$('li a#yehuda').attr('href'), '/item/yehuda'); + assert.equal(this.$('li a#tom').attr('href'), '/item/tom'); + assert.equal(this.$('li a#erik').attr('href'), '/item/erik'); await this.click('#erik'); @@ -1391,11 +1411,11 @@ moduleFor( await this.visit('/filters/popular'); - assert.equal(normalizeUrl(this.$('#link').attr('href')), '/filters/unpopular'); - assert.equal(normalizeUrl(this.$('#path-link').attr('href')), '/filters/unpopular'); - assert.equal(normalizeUrl(this.$('#post-path-link').attr('href')), '/post/123'); - assert.equal(normalizeUrl(this.$('#post-number-link').attr('href')), '/post/123'); - assert.equal(normalizeUrl(this.$('#repo-object-link').attr('href')), '/repo/ember/ember.js'); + assert.equal(this.$('#link').attr('href'), '/filters/unpopular'); + assert.equal(this.$('#path-link').attr('href'), '/filters/unpopular'); + assert.equal(this.$('#post-path-link').attr('href'), '/post/123'); + assert.equal(this.$('#post-number-link').attr('href'), '/post/123'); + assert.equal(this.$('#repo-object-link').attr('href'), '/repo/ember/ember.js'); } async [`@test [GH#4201] Shorthand for route.index shouldn't throw errors about context arguments`]( @@ -1463,8 +1483,8 @@ moduleFor( ); let assertEquality = (href) => { - assert.equal(normalizeUrl(this.$('#string-link').attr('href')), '/'); - assert.equal(normalizeUrl(this.$('#path-link').attr('href')), href); + assert.equal(this.$('#string-link').attr('href'), '/'); + assert.equal(this.$('#path-link').attr('href'), href); }; await this.visit('/'); @@ -1506,7 +1526,7 @@ moduleFor( runTask(() => controller.set('post', post)); assert.equal( - normalizeUrl(this.$('#post').attr('href')), + this.$('#post').attr('href'), '/posts/1', 'precond - Link has rendered href attr properly' ); @@ -1600,9 +1620,8 @@ moduleFor( let idx; for (idx = 0; idx < links.length; idx++) { let href = this.$(links[idx]).attr('href'); - // Old IE includes the whole hostname as well assert.equal( - href.slice(-expected[idx].length), + href, expected[idx], `Expected link to be '${expected[idx]}', but was '${href}'` ); @@ -1910,10 +1929,10 @@ moduleFor( function assertLinkStatus(link, url) { if (url) { - assert.equal(normalizeUrl(link.attr('href')), url, 'loaded link-to has expected href'); + assert.equal(link.attr('href'), url, 'loaded link-to has expected href'); assert.ok(!link.hasClass('i-am-loading'), 'loaded linkComponent has no loadingClass'); } else { - assert.equal(normalizeUrl(link.attr('href')), '#', "unloaded link-to has href='#'"); + assert.equal(link.attr('href'), '#', "unloaded link-to has href='#'"); assert.ok(link.hasClass('i-am-loading'), 'loading linkComponent has loadingClass'); } } diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-curly-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-curly-test.js index 76e42f53e53..601713290c9 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-curly-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/link-to/routing-curly-test.js @@ -14,11 +14,6 @@ import Engine from '@ember/engine'; import { DEBUG } from '@glimmer/env'; import { compile } from '../../../utils/helpers'; -// IE includes the host name -function normalizeUrl(url) { - return url.replace(/https?:\/\/[^/]+/, ''); -} - function shouldNotBeActive(assert, element) { checkActive(assert, element, false); } @@ -911,7 +906,7 @@ moduleFor( await this.visit('/about/item'); - assert.equal(normalizeUrl(this.$('#item a').attr('href')), '/about'); + assert.equal(this.$('#item a').attr('href'), '/about'); } async [`@test it supports custom, nested, current-when`](assert) { @@ -966,6 +961,37 @@ moduleFor( ); } + async [`@test it supports custom, nested, current-when with route params`](assert) { + assert.expect(2); + this.router.map(function () { + this.route('index', { path: '/' }); + this.route('foo', { path: '/foo/:fooId' }, function () { + this.route('bar', { path: '/bar/:barId' }); + }); + }); + + this.addTemplate('index', `{{outlet}}`); + this.addTemplate( + 'foo', + `{{#link-to route='foo.index' model=1 current-when='foo.index foo.bar'}}Foo Index{{/link-to}} {{outlet}}` + ); + this.addTemplate( + 'foo.bar', + `{{#link-to route='foo.bar' models=(array 1 2)}}Foo Bar{{/link-to}}` + ); + + await this.visit('/foo/1/bar/2'); + + assert.ok( + this.$('a[href="/foo/1"]').is('.active'), + 'The link to foo.index should be active when on foo.bar' + ); + assert.ok( + this.$('a[href="/foo/1/bar/2"]').is('.active'), + 'The link to foo.bar should be active when on foo.bar' + ); + } + async ['@test it does not disregard current-when when it is set via a bound param'](assert) { this.router.map(function () { this.route('index', { path: '/' }, function () { @@ -1191,11 +1217,7 @@ moduleFor( await this.visit('/about'); assert.equal(this.$('h3.list').length, 1, 'The home template was rendered'); - assert.equal( - normalizeUrl(this.$('#home-link > a').attr('href')), - '/', - 'The home link points back at /' - ); + assert.equal(this.$('#home-link > a').attr('href'), '/', 'The home link points back at /'); await this.click('#yehuda > a'); @@ -1206,9 +1228,9 @@ moduleFor( await this.click('#about-link > a'); - assert.equal(normalizeUrl(this.$('li#yehuda > a').attr('href')), '/item/yehuda'); - assert.equal(normalizeUrl(this.$('li#tom > a').attr('href')), '/item/tom'); - assert.equal(normalizeUrl(this.$('li#erik > a').attr('href')), '/item/erik'); + assert.equal(this.$('li#yehuda > a').attr('href'), '/item/yehuda'); + assert.equal(this.$('li#tom > a').attr('href'), '/item/tom'); + assert.equal(this.$('li#erik > a').attr('href'), '/item/erik'); await this.click('#erik > a'); @@ -1261,14 +1283,11 @@ moduleFor( await this.visit('/filters/popular'); - assert.equal(normalizeUrl(this.$('#link > a').attr('href')), '/filters/unpopular'); - assert.equal(normalizeUrl(this.$('#path-link > a').attr('href')), '/filters/unpopular'); - assert.equal(normalizeUrl(this.$('#post-path-link > a').attr('href')), '/post/123'); - assert.equal(normalizeUrl(this.$('#post-number-link > a').attr('href')), '/post/123'); - assert.equal( - normalizeUrl(this.$('#repo-object-link > a').attr('href')), - '/repo/ember/ember.js' - ); + assert.equal(this.$('#link > a').attr('href'), '/filters/unpopular'); + assert.equal(this.$('#path-link > a').attr('href'), '/filters/unpopular'); + assert.equal(this.$('#post-path-link > a').attr('href'), '/post/123'); + assert.equal(this.$('#post-number-link > a').attr('href'), '/post/123'); + assert.equal(this.$('#repo-object-link > a').attr('href'), '/repo/ember/ember.js'); } async [`@test [GH#4201] Shorthand for route.index shouldn't throw errors about context arguments`]( @@ -1336,8 +1355,8 @@ moduleFor( ); let assertEquality = (href) => { - assert.equal(normalizeUrl(this.$('#string-link > a').attr('href')), '/'); - assert.equal(normalizeUrl(this.$('#path-link > a').attr('href')), href); + assert.equal(this.$('#string-link > a').attr('href'), '/'); + assert.equal(this.$('#path-link > a').attr('href'), href); }; await this.visit('/'); @@ -1379,7 +1398,7 @@ moduleFor( runTask(() => controller.set('post', post)); assert.equal( - normalizeUrl(this.$('#post > a').attr('href')), + this.$('#post > a').attr('href'), '/posts/1', 'precond - Link has rendered href attr properly' ); @@ -1473,9 +1492,8 @@ moduleFor( let idx; for (idx = 0; idx < links.length; idx++) { let href = this.$(links[idx]).attr('href'); - // Old IE includes the whole hostname as well assert.equal( - href.slice(-expected[idx].length), + href, expected[idx], `Expected link to be '${expected[idx]}', but was '${href}'` ); @@ -1797,10 +1815,10 @@ moduleFor( function assertLinkStatus(link, url) { if (url) { - assert.equal(normalizeUrl(link.attr('href')), url, 'loaded link-to has expected href'); + assert.equal(link.attr('href'), url, 'loaded link-to has expected href'); assert.ok(!link.hasClass('i-am-loading'), 'loaded linkComponent has no loadingClass'); } else { - assert.equal(normalizeUrl(link.attr('href')), '#', "unloaded link-to has href='#'"); + assert.equal(link.attr('href'), '#', "unloaded link-to has href='#'"); assert.ok(link.hasClass('i-am-loading'), 'loading linkComponent has loadingClass'); } } diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/runtime-template-compiler-explicit-test.ts b/packages/@ember/-internals/glimmer/tests/integration/components/runtime-template-compiler-explicit-test.ts index 0c78ad86ea9..1bed33f5d01 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/runtime-template-compiler-explicit-test.ts +++ b/packages/@ember/-internals/glimmer/tests/integration/components/runtime-template-compiler-explicit-test.ts @@ -72,6 +72,19 @@ moduleFor( this.assertStableRerender(); } + async '@test Can use `this` from explicit scope'() { + await this.renderComponentModule(() => { + let state = { cls: 'Hello, world!' }; + + return template('
{{this.cls}}
', { + scope: () => ({ this: state }), + }); + }); + + this.assertHTML('
Hello, world!
'); + this.assertStableRerender(); + } + async '@test Can use inline if and unless in strict mode templates'() { await this.renderComponentModule(() => { return template('{{if true "foo" "bar"}}{{unless true "foo" "bar"}}'); diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/textarea-angle-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/textarea-angle-test.js index 9be9d9d23e7..7bac8040007 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/textarea-angle-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/textarea-angle-test.js @@ -16,8 +16,7 @@ class TextAreaRenderingTest extends RenderingTestCase { } triggerEvent(type, options = {}) { - let event = document.createEvent('Events'); - event.initEvent(type, true, true); + let event = new Event(type, { bubbles: true, cancelable: true }); Object.assign(event, options); this.firstChild.dispatchEvent(event); diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/textarea-curly-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/textarea-curly-test.js index adfbf2497cb..87ae3986bac 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/textarea-curly-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/textarea-curly-test.js @@ -16,8 +16,7 @@ class TextAreaRenderingTest extends RenderingTestCase { } triggerEvent(type, options = {}) { - let event = document.createEvent('Events'); - event.initEvent(type, true, true); + let event = new Event(type, { bubbles: true, cancelable: true }); Object.assign(event, options); this.firstChild.dispatchEvent(event); diff --git a/packages/@ember/-internals/glimmer/tests/integration/components/utils-test.js b/packages/@ember/-internals/glimmer/tests/integration/components/utils-test.js index e9cbd211101..877a8d6e467 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/components/utils-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/components/utils-test.js @@ -259,27 +259,6 @@ moduleFor( } ); -let hasGetClientRects, hasGetBoundingClientRect; -let ClientRectListCtor, ClientRectCtor; - -(function () { - if (document.createRange) { - let range = document.createRange(); - - if (range.getClientRects) { - let clientRectsList = range.getClientRects(); - hasGetClientRects = true; - ClientRectListCtor = clientRectsList && clientRectsList.constructor; - } - - if (range.getBoundingClientRect) { - let clientRect = range.getBoundingClientRect(); - hasGetBoundingClientRect = true; - ClientRectCtor = clientRect && clientRect.constructor; - } - } -})(); - moduleFor( 'Bounds tests', class extends RenderingTestCase { @@ -352,14 +331,6 @@ moduleFor( } ['@test getViewClientRects'](assert) { - if (!hasGetClientRects || !ClientRectListCtor) { - assert.ok( - true, - 'The test environment does not support the DOM API required to run this test.' - ); - return; - } - let component; this.registerComponent('hi-mom', { ComponentClass: class extends Component { @@ -373,18 +344,10 @@ moduleFor( this.render(`{{hi-mom}}`); - assert.ok(getViewClientRects(component) instanceof ClientRectListCtor); + assert.ok(getViewClientRects(component) instanceof DOMRectList); } ['@test getViewBoundingClientRect'](assert) { - if (!hasGetBoundingClientRect || !ClientRectCtor) { - assert.ok( - true, - 'The test environment does not support the DOM API required to run this test.' - ); - return; - } - let component; this.registerComponent('hi-mom', { ComponentClass: class extends Component { @@ -398,7 +361,7 @@ moduleFor( this.render(`{{hi-mom}}`); - assert.ok(getViewBoundingClientRect(component) instanceof ClientRectCtor); + assert.ok(getViewBoundingClientRect(component) instanceof DOMRect); } } ); diff --git a/packages/@ember/-internals/glimmer/tests/integration/event-dispatcher-test.js b/packages/@ember/-internals/glimmer/tests/integration/event-dispatcher-test.js index 60c37711e7d..f5890b8168c 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/event-dispatcher-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/event-dispatcher-test.js @@ -3,11 +3,8 @@ import { moduleFor, RenderingTestCase, runTask } from 'internal-test-helpers'; import { Component } from '../utils/helpers'; import { _getCurrentRunLoop } from '@ember/runloop'; -let canDataTransfer = Boolean(document.createEvent('HTMLEvents').dataTransfer); - function fireNativeWithDataTransfer(node, type, dataTransfer) { - let event = document.createEvent('HTMLEvents'); - event.initEvent(type, true, true); + let event = new Event(type, { bubbles: true, cancelable: true }); event.dataTransfer = dataTransfer; node.dispatchEvent(event); } @@ -408,25 +405,23 @@ moduleFor( } ); -if (canDataTransfer) { - moduleFor( - 'EventDispatcher - Event Properties', - class extends RenderingTestCase { - ['@test dataTransfer property is added to drop event'](assert) { - let receivedEvent; - this.registerComponent('x-foo', { - ComponentClass: class extends Component { - drop(event) { - receivedEvent = event; - } - }, - }); - - this.render(`{{x-foo}}`); - - fireNativeWithDataTransfer(this.$('div')[0], 'drop', 'success'); - assert.equal(receivedEvent.dataTransfer, 'success'); - } +moduleFor( + 'EventDispatcher - Event Properties', + class extends RenderingTestCase { + ['@test dataTransfer property is added to drop event'](assert) { + let receivedEvent; + this.registerComponent('x-foo', { + ComponentClass: class extends Component { + drop(event) { + receivedEvent = event; + } + }, + }); + + this.render(`{{x-foo}}`); + + fireNativeWithDataTransfer(this.$('div')[0], 'drop', 'success'); + assert.equal(receivedEvent.dataTransfer, 'success'); } - ); -} + } +); diff --git a/packages/@ember/-internals/glimmer/tests/integration/syntax/each-test.js b/packages/@ember/-internals/glimmer/tests/integration/syntax/each-test.js index e4ed8e69213..2c3fdcf2f1f 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/syntax/each-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/syntax/each-test.js @@ -96,21 +96,6 @@ class ArrayDelegate { } } -const makeSet = (() => { - // IE11 does not support `new Set(items);` - let set = new Set([1, 2, 3]); - - if (set.size === 3) { - return (items) => new Set(items); - } else { - return (items) => { - let s = new Set(); - items.forEach((value) => s.add(value)); - return s; - }; - } -})(); - class SetDelegate extends ArrayDelegate { constructor(set) { let array = []; @@ -158,7 +143,7 @@ class BasicEachTest extends TogglingEachTest {} const TRUTHY_CASES = [ ['hello'], emberA(['hello']), - makeSet(['hello']), + new Set(['hello']), new ForEachable(['hello']), ArrayProxy.create({ content: ['hello'] }), ArrayProxy.create({ content: emberA(['hello']) }), @@ -173,7 +158,7 @@ const FALSY_CASES = [ 0, [], emberA([]), - makeSet([]), + new Set([]), new ForEachable([]), ArrayProxy.create({ content: [] }), ArrayProxy.create({ content: emberA([]) }), @@ -1039,7 +1024,7 @@ moduleFor( 'Syntax test: {{#each}} with native Set', class extends EachTest { createList(items) { - let set = makeSet(items); + let set = new Set(items); return { list: set, delegate: new SetDelegate(set) }; } diff --git a/packages/@ember/-internals/metal/lib/alias.ts b/packages/@ember/-internals/metal/lib/alias.ts index af955f3cb12..66ebf468f31 100644 --- a/packages/@ember/-internals/metal/lib/alias.ts +++ b/packages/@ember/-internals/metal/lib/alias.ts @@ -58,7 +58,7 @@ class AliasDecoratorImpl extends Function { } } -export class AliasedProperty extends ComputedDescriptor { +class AliasedProperty extends ComputedDescriptor { readonly altKey: string; constructor(altKey: string) { diff --git a/packages/@ember/-internals/metal/lib/decorator.ts b/packages/@ember/-internals/metal/lib/decorator.ts index 8e749b87a70..5c71ad98338 100644 --- a/packages/@ember/-internals/metal/lib/decorator.ts +++ b/packages/@ember/-internals/metal/lib/decorator.ts @@ -76,7 +76,7 @@ export abstract class ComputedDescriptor { abstract set(obj: object, keyName: string, value: any | null | undefined): any | null | undefined; } -export let COMPUTED_GETTERS: WeakSet<() => unknown>; +let COMPUTED_GETTERS: WeakSet<() => unknown>; if (DEBUG) { COMPUTED_GETTERS = new WeakSet(); diff --git a/packages/@ember/-internals/metal/lib/dependent_keys.ts b/packages/@ember/-internals/metal/lib/dependent_keys.ts deleted file mode 100644 index cb0ff5c3b54..00000000000 --- a/packages/@ember/-internals/metal/lib/dependent_keys.ts +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/packages/@ember/-internals/metal/lib/each_proxy_events.ts b/packages/@ember/-internals/metal/lib/each_proxy_events.ts index 3e53f179782..df4873496b8 100644 --- a/packages/@ember/-internals/metal/lib/each_proxy_events.ts +++ b/packages/@ember/-internals/metal/lib/each_proxy_events.ts @@ -1,4 +1,4 @@ -export const EACH_PROXIES = new WeakMap(); +const EACH_PROXIES = new WeakMap(); export function eachProxyArrayWillChange( array: any, diff --git a/packages/@ember/-internals/metal/lib/observer.ts b/packages/@ember/-internals/metal/lib/observer.ts index f1f8035fdbe..4154e3441a8 100644 --- a/packages/@ember/-internals/metal/lib/observer.ts +++ b/packages/@ember/-internals/metal/lib/observer.ts @@ -113,7 +113,7 @@ export function activateObserver(target: object, eventName: string, sync = false let DEACTIVATE_SUSPENDED = false; let SCHEDULED_DEACTIVATE: [object, string, boolean][] = []; -export function deactivateObserver(target: object, eventName: string, sync = false) { +function deactivateObserver(target: object, eventName: string, sync = false) { if (DEACTIVATE_SUSPENDED === true) { SCHEDULED_DEACTIVATE.push([target, eventName, sync]); return; @@ -265,7 +265,7 @@ export function setObserverSuspended(target: object, property: string, suspended } } -export function destroyObservers(target: object) { +function destroyObservers(target: object) { if (SYNC_OBSERVERS.size > 0) SYNC_OBSERVERS.delete(target); if (ASYNC_OBSERVERS.size > 0) ASYNC_OBSERVERS.delete(target); } diff --git a/packages/@ember/-internals/metal/lib/property_get.ts b/packages/@ember/-internals/metal/lib/property_get.ts index b7fb86eabf1..c797bc38589 100644 --- a/packages/@ember/-internals/metal/lib/property_get.ts +++ b/packages/@ember/-internals/metal/lib/property_get.ts @@ -58,15 +58,9 @@ interface MaybeHasIsDestroyed { get(obj, "name"); ``` - If you plan to run on IE8 and older browsers then you should use this - method anytime you want to retrieve a property on an object that you don't - know for sure is private. (Properties beginning with an underscore '_' - are considered private.) - - On all newer browsers, you only need to use this method to retrieve - properties if the property might not be defined on the object and you want - to respect the `unknownProperty` handler. Otherwise you can ignore this - method. + You only need to use this method to retrieve properties if the property + might not be defined on the object and you want to respect the + `unknownProperty` handler. Otherwise you can access the property directly. Note that if the object itself is `undefined`, this method will throw an error. diff --git a/packages/@ember/-internals/package.json b/packages/@ember/-internals/package.json index 873441b41ab..cc947bbb6b5 100644 --- a/packages/@ember/-internals/package.json +++ b/packages/@ember/-internals/package.json @@ -69,7 +69,7 @@ "ember-template-compiler": "workspace:*", "expect-type": "^0.15.0", "internal-test-helpers": "workspace:*", - "router_js": "^8.0.5", + "router_js": "workspace:*", "rsvp": "^4.8.5" }, "devDependencies": { diff --git a/packages/@ember/-internals/views/lib/system/utils.ts b/packages/@ember/-internals/views/lib/system/utils.ts index f949a7cfa5a..05d81d7611c 100644 --- a/packages/@ember/-internals/views/lib/system/utils.ts +++ b/packages/@ember/-internals/views/lib/system/utils.ts @@ -16,7 +16,7 @@ export function isSimpleClick(event: Event): boolean { return false; } let modifier = event.shiftKey || event.metaKey || event.altKey || event.ctrlKey; - let secondaryClick = event.which > 1; // IE9 may return undefined + let secondaryClick = event.button !== 0; return !modifier && !secondaryClick; } @@ -120,7 +120,7 @@ export function getChildViews(view: View): View[] { return collectChildViews(view, registry); } -export function initChildViews(view: View): Set { +function initChildViews(view: View): Set { let childViews: Set = new Set(); CHILD_VIEW_IDS.set(view, childViews); return childViews; @@ -135,7 +135,7 @@ export function addChildView(parent: View, child: View): void { childViews.add(getViewId(child)); } -export function collectChildViews(view: View, registry: Dict): View[] { +function collectChildViews(view: View, registry: Dict): View[] { let views: View[] = []; let childViews = CHILD_VIEW_IDS.get(view); @@ -165,7 +165,7 @@ export function getViewBounds(view: View) { @method getViewRange @param {Ember.View} view */ -export function getViewRange(view: View): Range { +function getViewRange(view: View): Range { let bounds = getViewBounds(view); let range = document.createRange(); @@ -179,8 +179,7 @@ export function getViewRange(view: View): Range { `getViewClientRects` provides information about the position of the border box edges of a view relative to the viewport. - It is only intended to be used by development tools like the Ember Inspector - and may not work on older browsers. + It is only intended to be used by development tools like the Ember Inspector. @private @method getViewClientRects @@ -195,29 +194,13 @@ export function getViewClientRects(view: View): DOMRectList { `getViewBoundingClientRect` provides information about the position of the bounding border box edges of a view relative to the viewport. - It is only intended to be used by development tools like the Ember Inspector - and may not work on older browsers. + It is only intended to be used by development tools like the Ember Inspector. @private @method getViewBoundingClientRect @param {Ember.View} view */ -export function getViewBoundingClientRect(view: View): ClientRect | DOMRect { +export function getViewBoundingClientRect(view: View): DOMRect { let range = getViewRange(view); return range.getBoundingClientRect(); } - -export function contains(a: Node, b: Node): boolean { - if (a.contains !== undefined) { - return a.contains(b); - } - - let current: Nullable = b.parentNode; - - while (current && (current = current.parentNode)) { - if (current === a) { - return true; - } - } - return false; -} diff --git a/packages/@ember/application/index.ts b/packages/@ember/application/index.ts index 5f3231bbd29..ef73494e0f8 100644 --- a/packages/@ember/application/index.ts +++ b/packages/@ember/application/index.ts @@ -341,55 +341,6 @@ class Application extends Engine { */ declare autoboot: boolean; - /** - Whether the application should be configured for the legacy "globals mode". - Under this mode, the Application object serves as a global namespace for all - classes. - - ```javascript - import Application from '@ember/application'; - import Component from '@ember/component'; - - let App = Application.create({ - ... - }); - - App.Router.reopen({ - location: 'none' - }); - - App.Router.map({ - ... - }); - - App.MyComponent = Component.extend({ - ... - }); - ``` - - This flag also exposes other internal APIs that assumes the existence of - a special "default instance", like `App.__container__.lookup(...)`. - - This option is currently not configurable, its value is derived from - the `autoboot` flag – disabling `autoboot` also implies opting-out of - globals mode support, although they are ultimately orthogonal concerns. - - Some of the global modes features are already deprecated in 1.x. The - existence of this flag is to untangle the globals mode code paths from - the autoboot code paths, so that these legacy features can be reviewed - for deprecation/removal separately. - - Forcing the (autoboot=true, _globalsMode=false) here and running the tests - would reveal all the places where we are still relying on these legacy - behavior internally (mostly just tests). - - @property _globalsMode - @type Boolean - @default true - @private - */ - declare _globalsMode: boolean; - /** An array of application instances created by `buildInstance()`. Used internally to ensure that all instances get destroyed. @@ -413,7 +364,6 @@ class Application extends Engine { this.customEvents ??= null; this.autoboot ??= true; this._document ??= hasDOM ? window.document : null; - this._globalsMode ??= true; if (DEBUG) { if (ENV.LOG_VERSION) { @@ -429,13 +379,15 @@ class Application extends Engine { this._booted = false; this._applicationInstances = new Set(); - this.autoboot = this._globalsMode = Boolean(this.autoboot); - - if (this._globalsMode) { - this._prepareForGlobalsMode(); - } + this.autoboot = Boolean(this.autoboot); if (this.autoboot) { + // Create subclass of Router for this Application instance. + // This is to ensure that someone reopening `App.Router` does not + // tamper with the default `Router`. + this.Router = (this.Router || Router).extend() as typeof Router; + + this._buildDeprecatedInstance(); this.waitForDOMReady(); } } @@ -489,26 +441,6 @@ class Application extends Engine { Router?: typeof Router; - /** - Enable the legacy globals mode by allowing this application to act - as a global namespace. See the docs on the `_globalsMode` property - for details. - - Most of these features are already deprecated in 1.x, so we can - stop using them internally and try to remove them. - - @private - @method _prepareForGlobalsMode - */ - _prepareForGlobalsMode(): void { - // Create subclass of Router for this Application instance. - // This is to ensure that someone reopening `App.Router` does not - // tamper with the default `Router`. - this.Router = (this.Router || Router).extend() as typeof Router; - - this._buildDeprecatedInstance(); - } - __deprecatedInstance__?: ApplicationInstance; __container__?: Container; @@ -590,7 +522,7 @@ class Application extends Engine { ```javascript _autoBoot() { this.boot().then(() => { - let instance = (this._globalsMode) ? this.__deprecatedInstance__ : this.buildInstance(); + let instance = this.__deprecatedInstance__; return instance.boot(); }).then((instance) => { App.ready(); @@ -872,10 +804,10 @@ class Application extends Engine { assert( `Calling reset() on instances of \`Application\` is not - supported when globals mode is disabled; call \`visit()\` to + supported when autoboot is disabled; call \`visit()\` to create new \`ApplicationInstance\`s and dispose them via their \`destroy()\` method instead.`, - this._globalsMode && this.autoboot + this.autoboot ); let instance = this.__deprecatedInstance__; @@ -907,24 +839,12 @@ class Application extends Engine { assert('expected _bootResolver', this._bootResolver); try { - // TODO: Is this still needed for _globalsMode = false? - // See documentation on `_autoboot()` for details if (this.autoboot) { - let instance; - - if (this._globalsMode) { - // If we already have the __deprecatedInstance__ lying around, boot it to - // avoid unnecessary work - instance = this.__deprecatedInstance__; - assert('expected instance', instance); - } else { - // Otherwise, build an instance and boot it. This is currently unreachable, - // because we forced _globalsMode to === autoboot; but having this branch - // allows us to locally toggle that flag for weeding out legacy globals mode - // dependencies independently - instance = this.buildInstance(); - } + // If we already have the __deprecatedInstance__ lying around, boot it to + // avoid unnecessary work + let instance = this.__deprecatedInstance__; + assert('expected instance', instance); instance._bootSync(); diff --git a/packages/@ember/application/instance.ts b/packages/@ember/application/instance.ts index 53f39d321d0..47ecb342bd4 100644 --- a/packages/@ember/application/instance.ts +++ b/packages/@ember/application/instance.ts @@ -263,11 +263,6 @@ class ApplicationInstance extends EngineInstance { let handleTransitionReject = (error: any): unknown => { if (error.error && error.error instanceof Error) { throw error.error; - } else if (error.name === 'TransitionAborted' && router._routerMicrolib.activeTransition) { - return router._routerMicrolib.activeTransition.then( - handleTransitionResolve, - handleTransitionReject - ); } else if (error.name === 'TransitionAborted') { throw new Error(error.message); } else { @@ -284,6 +279,7 @@ class ApplicationInstance extends EngineInstance { // getURL returns the set url with the rootURL stripped off return router .handleURL(location.getURL()) + .followRedirects() .then(handleTransitionResolve, handleTransitionReject); } diff --git a/packages/@ember/application/package.json b/packages/@ember/application/package.json index 0aa1de249e7..074819001a0 100644 --- a/packages/@ember/application/package.json +++ b/packages/@ember/application/package.json @@ -30,6 +30,6 @@ "ember-template-compiler": "workspace:*", "expect-type": "^0.15.0", "internal-test-helpers": "workspace:*", - "router_js": "^8.0.5" + "router_js": "workspace:*" } } diff --git a/packages/@ember/debug/index.ts b/packages/@ember/debug/index.ts index a466026cccc..b5ae304b05a 100644 --- a/packages/@ember/debug/index.ts +++ b/packages/@ember/debug/index.ts @@ -265,13 +265,7 @@ if (DEBUG) { }); setDebugFunction('debugFreeze', function debugFreeze(obj) { - // re-freezing an already frozen object introduces a significant - // performance penalty on Chrome (tested through 59). - // - // See: https://bugs.chromium.org/p/v8/issues/detail?id=6450 - if (!Object.isFrozen(obj)) { - Object.freeze(obj); - } + Object.freeze(obj); }); setDebugFunction('warn', _warn); diff --git a/packages/@ember/engine/package.json b/packages/@ember/engine/package.json index 75ace0b4a22..b08914eb32f 100644 --- a/packages/@ember/engine/package.json +++ b/packages/@ember/engine/package.json @@ -27,6 +27,6 @@ "dag-map": "^2.0.2", "expect-type": "^0.15.0", "internal-test-helpers": "workspace:*", - "router_js": "^8.0.5" + "router_js": "workspace:*" } } diff --git a/packages/@ember/instrumentation/index.ts b/packages/@ember/instrumentation/index.ts index 3d34e94af45..00938f3a9c7 100644 --- a/packages/@ember/instrumentation/index.ts +++ b/packages/@ember/instrumentation/index.ts @@ -23,14 +23,6 @@ export interface StructuredProfilePayload { object: string | object; } -interface MaybePerf { - now?: () => number; - mozNow?: () => number; - webkitNow?: () => number; - msNow?: () => number; - oNow?: () => number; -} - /** @module @ember/instrumentation @private @@ -102,12 +94,7 @@ function populateListeners(name: string) { return listeners; } -const time = ((): (() => number) => { - let perf: MaybePerf = 'undefined' !== typeof window ? window.performance || {} : {}; - let fn = perf.now || perf.mozNow || perf.webkitNow || perf.msNow || perf.oNow; - - return fn ? fn.bind(perf) : Date.now; -})(); +const time = (): number => performance.now(); type InstrumentCallback = (this: Binding) => Result; diff --git a/packages/@ember/object/mixin.ts b/packages/@ember/object/mixin.ts index 32b550c2cf9..65119179d00 100644 --- a/packages/@ember/object/mixin.ts +++ b/packages/@ember/object/mixin.ts @@ -4,7 +4,7 @@ import { INIT_FACTORY } from '@ember/-internals/container'; import type { Meta } from '@ember/-internals/meta'; import { meta as metaFor, peekMeta } from '@ember/-internals/meta'; -import { guidFor, observerListenerMetaFor, ROOT, wrap } from '@ember/-internals/utils'; +import { observerListenerMetaFor, ROOT, wrap } from '@ember/-internals/utils'; import { assert } from '@ember/debug'; import { DEBUG } from '@glimmer/env'; import { @@ -562,14 +562,6 @@ export default class Mixin { if (DEBUG) { // Eagerly add INIT_FACTORY to avoid issues in DEBUG as a result of Object.seal(mixin) this[INIT_FACTORY] = null; - /* - In debug builds, we seal mixins to help avoid performance pitfalls. - - In IE11 there is a quirk that prevents sealed objects from being added - to a WeakMap. Unfortunately, the mixin system currently relies on - weak maps in `guidFor`, so we need to prime the guid cache weak map. - */ - guidFor(this); if (Mixin._disableDebugSeal !== true) { Object.seal(this); diff --git a/packages/@ember/routing/history-location.ts b/packages/@ember/routing/history-location.ts index 709c344a03f..42019c63b54 100644 --- a/packages/@ember/routing/history-location.ts +++ b/packages/@ember/routing/history-location.ts @@ -7,8 +7,6 @@ import { getHash } from './lib/location-utils'; @module @ember/routing/history-location */ -let popstateFired = false; - function _uuid() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { let r, v; @@ -65,7 +63,6 @@ export default class HistoryLocation extends EmberObject implements EmberLocatio history?: Window['history']; - _previousURL?: string; _popstateHandler?: EventListener; /** @@ -115,11 +112,7 @@ export default class HistoryLocation extends EmberObject implements EmberLocatio let { state } = history; let path = this.formatURL(this.getURL()); - if (state && state.path === path) { - // preserve existing state - // used for webkit workaround, since there will be no initial popstate event - this._previousURL = this.getURL(); - } else { + if (!state || state.path !== path) { this.replaceState(path); } } @@ -198,9 +191,6 @@ export default class HistoryLocation extends EmberObject implements EmberLocatio assert('HistoryLocation.history is unexpectedly missing', this.history); this.history.pushState(state, '', path); - - // used for webkit workaround - this._previousURL = this.getURL(); } /** @@ -215,9 +205,6 @@ export default class HistoryLocation extends EmberObject implements EmberLocatio assert('HistoryLocation.history is unexpectedly missing', this.history); this.history.replaceState(state, '', path); - - // used for webkit workaround - this._previousURL = this.getURL(); } /** @@ -232,13 +219,6 @@ export default class HistoryLocation extends EmberObject implements EmberLocatio this._removeEventListener(); this._popstateHandler = () => { - // Ignore initial page load popstate event in Chrome - if (!popstateFired) { - popstateFired = true; - if (this.getURL() === this._previousURL) { - return; - } - } callback(this.getURL()); }; diff --git a/packages/@ember/routing/lib/location-utils.ts b/packages/@ember/routing/lib/location-utils.ts index 64dd6e3a705..0fe26430886 100644 --- a/packages/@ember/routing/lib/location-utils.ts +++ b/packages/@ember/routing/lib/location-utils.ts @@ -1,11 +1,10 @@ /** @private - Returns the current `location.pathname`, normalized for IE inconsistencies. + Returns the current `location.pathname`, ensuring it has a leading slash. */ export function getPath(location: Location): string { let pathname = location.pathname; - // Various versions of IE/Opera don't always return a leading slash if (pathname[0] !== '/') { pathname = `/${pathname}`; } @@ -39,21 +38,6 @@ export function getFullPath(location: Location): string { return getPath(location) + getQuery(location) + getHash(location); } -export function getOrigin(location: Location): string { - let origin = location.origin; - - // Older browsers, especially IE, don't have origin - if (!origin) { - origin = `${location.protocol}//${location.hostname}`; - - if (location.port) { - origin += `:${location.port}`; - } - } - - return origin; -} - /** Replaces the current location, making sure we explicitly include the origin to prevent redirecting to a different origin. @@ -61,5 +45,5 @@ export function getOrigin(location: Location): string { @private */ export function replacePath(location: Location, path: string): void { - location.replace(getOrigin(location) + path); + location.replace(location.origin + path); } diff --git a/packages/@ember/routing/package.json b/packages/@ember/routing/package.json index c7eca12260a..b75af126221 100644 --- a/packages/@ember/routing/package.json +++ b/packages/@ember/routing/package.json @@ -37,6 +37,6 @@ "dag-map": "^2.0.2", "expect-type": "^0.15.0", "internal-test-helpers": "workspace:*", - "router_js": "^8.0.5" + "router_js": "workspace:*" } } diff --git a/packages/@ember/routing/tests/location/hash_location_test.js b/packages/@ember/routing/tests/location/hash_location_test.js index 7a873adbfcf..3e7d9368ec0 100644 --- a/packages/@ember/routing/tests/location/hash_location_test.js +++ b/packages/@ember/routing/tests/location/hash_location_test.js @@ -46,9 +46,7 @@ function mockBrowserLocation(path) { } function triggerHashchange() { - let event = document.createEvent('HTMLEvents'); - event.initEvent('hashchange', true, false); - window.dispatchEvent(event); + window.dispatchEvent(new Event('hashchange', { bubbles: true, cancelable: false })); } moduleFor( diff --git a/packages/@ember/routing/tests/location/history_location_test.js b/packages/@ember/routing/tests/location/history_location_test.js index 6bf7a81b356..984dad9c778 100644 --- a/packages/@ember/routing/tests/location/history_location_test.js +++ b/packages/@ember/routing/tests/location/history_location_test.js @@ -81,22 +81,6 @@ moduleFor( createLocation(); } - ["@test webkit doesn't fire popstate on page load"](assert) { - assert.expect(1); - - HistoryTestLocation.reopen({ - initState() { - this._super(...arguments); - // these two should be equal to be able - // to successfully detect webkit initial popstate - assert.equal(this._previousURL, this.getURL()); - }, - }); - - createLocation(); - location.initState(); - } - ['@test with href sets `baseURL`'](assert) { assert.expect(1); diff --git a/packages/@ember/routing/tests/location/util_test.js b/packages/@ember/routing/tests/location/util_test.js index 8f5ef8eeff4..f32de9d24b2 100644 --- a/packages/@ember/routing/tests/location/util_test.js +++ b/packages/@ember/routing/tests/location/util_test.js @@ -25,9 +25,7 @@ moduleFor( let expectedURL; let location = { - protocol: 'http:', - hostname: 'emberjs.com', - port: '1337', + origin: 'http://emberjs.com:1337', replace(url) { assert.equal(url, expectedURL); diff --git a/packages/@ember/runloop/tests/later_test.js b/packages/@ember/runloop/tests/later_test.js index f8ec7251d28..357b3fe0735 100644 --- a/packages/@ember/runloop/tests/later_test.js +++ b/packages/@ember/runloop/tests/later_test.js @@ -220,10 +220,8 @@ moduleFor( let done = assert.async(); // Rationale: The old run loop code was susceptible to an occasional // bug where invokeLaterTimers would be scheduled with a setTimeout - // with a negative wait. Modern browsers normalize this to 0, but - // older browsers (IE <= 8) break with a negative wait, which - // happens when an expired timer callback takes a while to run, - // which is what we simulate here. + // with a negative wait. Browsers normalize this to 0, but we verify + // that the wait is always a non-negative number. let newSetTimeoutUsed; _backburner._platform = Object.assign({}, originalPlatform, { setTimeout() { diff --git a/packages/@ember/template-compiler/lib/public-types.ts b/packages/@ember/template-compiler/lib/public-types.ts deleted file mode 100644 index af810b77a3d..00000000000 --- a/packages/@ember/template-compiler/lib/public-types.ts +++ /dev/null @@ -1,9 +0,0 @@ -export type { - BaseClassTemplateOptions, - ExplicitClassOptions, - BaseTemplateOptions, - ExplicitTemplateOnlyOptions, - ImplicitClassOptions, - ImplicitEvalOption, - ImplicitTemplateOnlyOptions, -} from './template'; diff --git a/packages/@ember/template-compiler/lib/template.ts b/packages/@ember/template-compiler/lib/template.ts index ca83645457e..bd2247eb386 100644 --- a/packages/@ember/template-compiler/lib/template.ts +++ b/packages/@ember/template-compiler/lib/template.ts @@ -270,10 +270,24 @@ function buildEvaluator(options: Partial | undefined) { } return (source: string) => { - const argNames = Object.keys(scope); - const argValues = Object.values(scope); + let hasThis = Object.prototype.hasOwnProperty.call(scope, 'this'); + let thisValue = hasThis ? (scope as { this?: unknown }).this : undefined; - return new Function(...argNames, `return (${source})`)(...argValues); + let argNames: string[] = []; + let argValues: unknown[] = []; + + for (let [name, value] of Object.entries(scope)) { + if (name === 'this') { + continue; + } + + argNames.push(name); + argValues.push(value); + } + + let fn = new Function(...argNames, `return (${source})`); + + return hasThis ? fn.call(thisValue, ...argValues) : fn(...argValues); }; } } diff --git a/packages/@ember/template-compiler/type-tests/template.test.ts b/packages/@ember/template-compiler/type-tests/template.test.ts index d26d36564a7..9fe4478c765 100644 --- a/packages/@ember/template-compiler/type-tests/template.test.ts +++ b/packages/@ember/template-compiler/type-tests/template.test.ts @@ -1,4 +1,4 @@ -import { template, type EmberPrecompileOptions } from '@ember/template-compiler'; +import { template } from '@ember/template-compiler'; import type { TemplateOnlyComponent } from '@ember/component/template-only'; import { expectTypeOf } from 'expect-type'; diff --git a/packages/@glimmer-workspace/integration-tests/lib/compile.ts b/packages/@glimmer-workspace/integration-tests/lib/compile.ts index 012278e8765..ace69285e2c 100644 --- a/packages/@glimmer-workspace/integration-tests/lib/compile.ts +++ b/packages/@glimmer-workspace/integration-tests/lib/compile.ts @@ -24,7 +24,10 @@ export function createTemplate( ): TemplateFactory { options.locals = options.locals ?? Object.keys(scopeValues ?? {}); let [block, usedLocals] = precompileJSON(templateSource, options); - let reifiedScopeValues = usedLocals.map((key) => scopeValues[key]); + let reifiedScope: Record = {}; + for (let key of usedLocals) { + reifiedScope[key] = scopeValues[key]; + } if ('emit' in options && options.emit?.debugSymbols) { block.push(usedLocals); @@ -34,7 +37,7 @@ export function createTemplate( id: String(templateId++), block: JSON.stringify(block), moduleName: options.meta?.moduleName ?? '(unknown template module)', - scope: reifiedScopeValues.length > 0 ? () => reifiedScopeValues : null, + scope: usedLocals.length > 0 ? () => reifiedScope : null, isStrictMode: options.strictMode ?? false, }; diff --git a/packages/@glimmer-workspace/integration-tests/test/compiler/compile-options-test.ts b/packages/@glimmer-workspace/integration-tests/test/compiler/compile-options-test.ts index c166e06c1d0..7d2c5d2505e 100644 --- a/packages/@glimmer-workspace/integration-tests/test/compiler/compile-options-test.ts +++ b/packages/@glimmer-workspace/integration-tests/test/compiler/compile-options-test.ts @@ -57,7 +57,7 @@ module('[glimmer-compiler] precompile', ({ test }) => { ...WireFormat.Statement[], ]; - assert.deepEqual(wire.scope?.(), [hello]); + assert.deepEqual(wire.scope?.(), { hello }); assert.deepEqual( componentNameExpr, @@ -84,7 +84,7 @@ module('[glimmer-compiler] precompile', ({ test }) => { ...WireFormat.Statement[], ]; - assert.deepEqual(wire.scope?.(), [f]); + assert.deepEqual(wire.scope?.(), { f }); assert.deepEqual( componentNameExpr, [SexpOpcodes.GetLexicalSymbol, 0, ['hello']], @@ -218,7 +218,7 @@ module('[glimmer-compiler] precompile', ({ test }) => { _wire = compile(`{{this.message}}`, ['this'], (source) => eval(source)); }).call(target); let wire = _wire!; - assert.deepEqual(wire.scope?.(), [target]); + assert.deepEqual(wire.scope?.(), { this: target }); assert.deepEqual(wire.block[0], [ [SexpOpcodes.Append, [SexpOpcodes.GetLexicalSymbol, 0, ['message']]], ]); diff --git a/packages/@glimmer-workspace/integration-tests/test/debug-render-tree-test.ts b/packages/@glimmer-workspace/integration-tests/test/debug-render-tree-test.ts index 5cecd7d0852..81a594e7d49 100644 --- a/packages/@glimmer-workspace/integration-tests/test/debug-render-tree-test.ts +++ b/packages/@glimmer-workspace/integration-tests/test/debug-render-tree-test.ts @@ -11,6 +11,7 @@ import type { import type { TemplateOnlyComponent } from '@glimmer/runtime'; import type { EmberishCurlyComponent } from '@glimmer-workspace/integration-tests'; import { expect } from '@glimmer/debug-util'; +import { DEBUG } from '@glimmer/env'; import { modifierCapabilities, setComponentTemplate, setModifierManager } from '@glimmer/manager'; import { EMPTY_ARGS, templateOnlyComponent, TemplateOnlyComponentManager } from '@glimmer/runtime'; import { assign } from '@glimmer/util'; @@ -110,6 +111,88 @@ class DebugRenderTreeTest extends RenderTest { ]); } + @test 'strict-mode components without debug symbols preserve names from scope'() { + const HelloWorld = defComponent('{{@arg}}'); + const Root = defComponent(``, { + scope: { HelloWorld }, + emit: { moduleName: 'root.hbs', debugSymbols: false }, + }); + + this.renderComponent(Root); + + this.assertRenderTree([ + { + type: 'component', + name: '{ROOT}', + args: { positional: [], named: {} }, + instance: null, + template: 'root.hbs', + bounds: this.elementBounds(this.delegate.getInitialElement()), + children: [ + { + type: 'component', + name: 'HelloWorld', + args: { positional: [], named: { arg: 'first' } }, + instance: null, + template: '(unknown template module)', + bounds: this.nodeBounds(this.delegate.getInitialElement().firstChild), + children: [], + }, + ], + }, + ]); + } + + @test({ skip: !DEBUG }) 'dynamic component via '() { + const HelloWorld = defComponent('{{@arg}}'); + + class Root extends GlimmerishComponent { + HelloWorld = HelloWorld; + } + + const RootDef = defComponent(``, { + component: Root, + emit: { moduleName: 'root.hbs' }, + }); + + this.renderComponent(RootDef); + + const rootChildren = this.delegate.getCapturedRenderTree()[0]?.children ?? []; + const componentNode = rootChildren.find( + (n: CapturedRenderNode) => n.type === 'component' && n.name !== '{ROOT}' + ); + + this.assert.ok(componentNode, 'found a component child node'); + + this.assert.strictEqual( + componentNode?.name, + 'this.HelloWorld', + `dynamic component name (got "${componentNode?.name}")` + ); + } + + @test({ skip: !DEBUG }) 'dynamic component via <@argComponent>'() { + const HelloWorld = defComponent('{{@arg}}'); + const Root = defComponent(`<@Greeting @arg="first"/>`, { + emit: { moduleName: 'root.hbs' }, + }); + + this.renderComponent(Root, { Greeting: HelloWorld }); + + const rootChildren = this.delegate.getCapturedRenderTree()[0]?.children ?? []; + const componentNode = rootChildren.find( + (n: CapturedRenderNode) => n.type === 'component' && n.name !== '{ROOT}' + ); + + this.assert.ok(componentNode, 'found a component child node'); + + this.assert.strictEqual( + componentNode?.name, + '@Greeting', + `dynamic <@X> component name (got "${componentNode?.name}")` + ); + } + @test 'strict-mode modifiers'() { const state = trackedObj({ showSecond: false }); diff --git a/packages/@glimmer/compiler/lib/compiler.ts b/packages/@glimmer/compiler/lib/compiler.ts index 089608f65f5..a712196610a 100644 --- a/packages/@glimmer/compiler/lib/compiler.ts +++ b/packages/@glimmer/compiler/lib/compiler.ts @@ -148,7 +148,14 @@ export function precompile( let stringified = JSON.stringify(templateJSONObject); if (usedLocals.length > 0) { - const scopeFn = `()=>[${usedLocals.join(',')}]`; + const scopeEntries = usedLocals.map((name) => { + // Reserved words like "this" can't use shorthand property syntax + if (name === 'this') { + return `"this":this`; + } + return name; + }); + const scopeFn = `()=>({${scopeEntries.join(',')}})`; stringified = stringified.replace(`"${SCOPE_PLACEHOLDER}"`, scopeFn); } diff --git a/packages/@glimmer/debug/lib/debug.ts b/packages/@glimmer/debug/lib/debug.ts index cef99d0e87a..2956a721990 100644 --- a/packages/@glimmer/debug/lib/debug.ts +++ b/packages/@glimmer/debug/lib/debug.ts @@ -5,20 +5,11 @@ import type { Nullable, Optional, Program, - ProgramConstants, RuntimeOp, } from '@glimmer/interfaces'; -import { - CURRIED_COMPONENT, - CURRIED_HELPER, - CURRIED_MODIFIER, - decodeHandle, - decodeImmediate, -} from '@glimmer/constants'; import { exhausted, expect, unreachable } from '@glimmer/debug-util'; import { LOCAL_DEBUG, LOCAL_SUBTLE_LOGGING, LOCAL_TRACE_LOGGING } from '@glimmer/local-debug-flags'; import { enumerate, LOCAL_LOGGER } from '@glimmer/util'; -import { $fp, $pc, $ra, $s0, $s1, $sp, $t0, $t1, $v0 } from '@glimmer/vm'; import type { Primitive, RegisterName } from './dism/dism'; import type { NormalizedOperand, OperandType, ShorthandOperand } from './dism/operand-types'; diff --git a/packages/@glimmer/destroyable/index.ts b/packages/@glimmer/destroyable/index.ts index a92775d88c6..f09e8ba7475 100644 --- a/packages/@glimmer/destroyable/index.ts +++ b/packages/@glimmer/destroyable/index.ts @@ -189,7 +189,7 @@ export function destroy(destroyable: Destroyable) { function removeChildFromParent(child: Destroyable, parent: Destroyable) { let parentMeta = getDestroyableMeta(parent); - if (parentMeta.state === LIVE_STATE) { + if (parentMeta.state !== DESTROYED_STATE) { parentMeta.children = remove( parentMeta.children, child, diff --git a/packages/@glimmer/destroyable/test/destroyables-test.ts b/packages/@glimmer/destroyable/test/destroyables-test.ts index 3d0f75f4fc5..8c2aa3c4e5c 100644 --- a/packages/@glimmer/destroyable/test/destroyables-test.ts +++ b/packages/@glimmer/destroyable/test/destroyables-test.ts @@ -1,7 +1,7 @@ import { DEBUG } from '@glimmer/env'; -import type { GlobalContext } from '@glimmer/global-context'; import { unwrap } from '@glimmer/debug-util'; import { + _hasDestroyableChildren, assertDestroyablesDestroyed, associateDestroyableChild, destroy, @@ -384,6 +384,23 @@ module('Destroyables', (hooks) => { assert.verifySteps(['child destructor', 'parent destructor'], 'destructors run bottom up'); }); + test('parent no longer references child after cascaded destruction', (assert) => { + const parent = {}; + const child = {}; + + associateDestroyableChild(parent, child); + + assert.true(_hasDestroyableChildren(parent), 'parent has children before destruction'); + + destroy(parent); + flush(); + + assert.false( + _hasDestroyableChildren(parent), + 'parent metadata releases child reference during cascaded destruction, allowing GC to reclaim the tree' + ); + }); + if (DEBUG) { test('attempting to unregister a destructor that was not registered throws an error', (assert) => { assert.throws(() => { diff --git a/packages/@glimmer/interfaces/lib/compile/wire-format/api.d.ts b/packages/@glimmer/interfaces/lib/compile/wire-format/api.d.ts index 6db2138eb87..9032916b8d1 100644 --- a/packages/@glimmer/interfaces/lib/compile/wire-format/api.d.ts +++ b/packages/@glimmer/interfaces/lib/compile/wire-format/api.d.ts @@ -397,7 +397,7 @@ export interface SerializedTemplateWithLazyBlock { id?: Nullable; block: SerializedTemplateBlockJSON; moduleName: string; - scope?: (() => unknown[]) | undefined | null; + scope?: (() => Record) | undefined | null; isStrictMode: boolean; } diff --git a/packages/@glimmer/interfaces/lib/template.d.ts b/packages/@glimmer/interfaces/lib/template.d.ts index 5e008c8039c..2990176844a 100644 --- a/packages/@glimmer/interfaces/lib/template.d.ts +++ b/packages/@glimmer/interfaces/lib/template.d.ts @@ -18,7 +18,7 @@ export interface LayoutWithContext { readonly block: SerializedTemplateBlock; readonly moduleName: string; readonly owner: Owner | null; - readonly scope: (() => unknown[]) | undefined | null; + readonly scope: (() => Record) | undefined | null; readonly isStrictMode: boolean; } diff --git a/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/shared.ts b/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/shared.ts index 640b63494b7..634fd603510 100644 --- a/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/shared.ts +++ b/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/shared.ts @@ -107,14 +107,15 @@ export function CompilePositional( export function meta(layout: LayoutWithContext): BlockMetadata { let [, locals, upvars, lexicalSymbols] = layout.block; + let scopeRecord = layout.scope?.() ?? null; return { symbols: { locals, upvars, - lexical: lexicalSymbols, + lexical: scopeRecord ? Object.keys(scopeRecord) : lexicalSymbols, }, - scopeValues: layout.scope?.() ?? null, + scopeValues: scopeRecord ? Object.values(scopeRecord) : null, isStrictMode: layout.isStrictMode, moduleName: layout.moduleName, owner: layout.owner, diff --git a/packages/@glimmer/program/lib/program.ts b/packages/@glimmer/program/lib/program.ts index 9a3c714393e..672d5be15aa 100644 --- a/packages/@glimmer/program/lib/program.ts +++ b/packages/@glimmer/program/lib/program.ts @@ -43,7 +43,6 @@ export class ProgramHeapImpl implements ProgramHeap { private heap: Int32Array; private handleTable: number[]; private handleState: TableSlotState[]; - private handle = 0; constructor() { this.heap = new Int32Array(PAGE_SIZE); diff --git a/packages/@glimmer/reference/test/iterable-test.ts b/packages/@glimmer/reference/test/iterable-test.ts index 80bc1a1bcc8..5e97c466029 100644 --- a/packages/@glimmer/reference/test/iterable-test.ts +++ b/packages/@glimmer/reference/test/iterable-test.ts @@ -1,7 +1,4 @@ -import type { GlobalContext } from '@glimmer/global-context'; import type { OpaqueIterationItem, Reference } from '@glimmer/reference'; -import { unwrap } from '@glimmer/debug-util'; -import { testOverrideGlobalContext } from '@glimmer/global-context'; import { createComputeRef, createIteratorRef, valueForRef } from '@glimmer/reference'; import { consumeTag, VOLATILE_TAG } from '@glimmer/validator'; diff --git a/packages/@glimmer/runtime/lib/compiled/opcodes/component.ts b/packages/@glimmer/runtime/lib/compiled/opcodes/component.ts index a8091130ec7..55baed8453a 100644 --- a/packages/@glimmer/runtime/lib/compiled/opcodes/component.ts +++ b/packages/@glimmer/runtime/lib/compiled/opcodes/component.ts @@ -154,10 +154,8 @@ APPEND_OPCODES.add(VM_PUSH_COMPONENT_DEFINITION_OP, (vm, { op1: handle }) => { APPEND_OPCODES.add(VM_RESOLVE_DYNAMIC_COMPONENT_OP, (vm, { op1: _isStrict }) => { let stack = vm.stack; - let component = check( - valueForRef(check(stack.pop(), CheckReference)), - CheckOr(CheckString, CheckCurriedComponentDefinition) - ); + let ref = check(stack.pop(), CheckReference); + let component = check(valueForRef(ref), CheckOr(CheckString, CheckCurriedComponentDefinition)); let constants = vm.constants; let owner = vm.getOwner(); let isStrict = constants.getValue(_isStrict); @@ -182,6 +180,13 @@ APPEND_OPCODES.add(VM_RESOLVE_DYNAMIC_COMPONENT_OP, (vm, { op1: _isStrict }) => definition = constants.component(component, owner); } + if (DEBUG && !isCurriedValue(definition) && !definition.resolvedName && !definition.debugName) { + let debugLabel = ref.debugLabel; + if (debugLabel) { + definition.debugName = debugLabel; + } + } + stack.push(definition); }); @@ -217,6 +222,19 @@ APPEND_OPCODES.add(VM_RESOLVE_CURRIED_COMPONENT_OP, (vm) => { } } + if ( + DEBUG && + definition && + !isCurriedValue(definition) && + !definition.resolvedName && + !definition.debugName + ) { + let debugLabel = ref.debugLabel; + if (debugLabel) { + definition.debugName = debugLabel; + } + } + stack.push(definition); }); diff --git a/packages/@glimmer/runtime/lib/dom/props.ts b/packages/@glimmer/runtime/lib/dom/props.ts index 685bedccf9e..dd82cf56137 100644 --- a/packages/@glimmer/runtime/lib/dom/props.ts +++ b/packages/@glimmer/runtime/lib/dom/props.ts @@ -41,23 +41,28 @@ export function normalizePropertyValue(value: unknown): unknown { return value; } -// properties that MUST be set as attributes, due to: -// * browser bug -// * strange spec outlier +// Properties that MUST be set as attributes because the DOM properties +// are read-only or have type mismatches with the HTML attributes. +// +// element.form is a read-only DOM property on all form-associated elements +// that returns the owning HTMLFormElement (or null). The HTML `form` attribute +// (set via setAttribute) associates the element with a form by ID. +// See: https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/form +// https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/form const ATTR_OVERRIDES: Dict = { INPUT: { form: true, - // Chrome 46.0.2464.0: 'autocorrect' in document.createElement('input') === false - // Safari 8.0.7: 'autocorrect' in document.createElement('input') === false - // Mobile Safari (iOS 8.4 simulator): 'autocorrect' in document.createElement('input') === true + // HTMLElement.autocorrect is a boolean DOM property, but the HTML attribute + // uses "on"/"off" strings. Setting `element.autocorrect = "off"` coerces to + // `true` (truthy string). Must use setAttribute for correct "on"/"off" behavior. + // See: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/autocorrect autocorrect: true, - // Chrome 54.0.2840.98: 'list' in document.createElement('input') === true - // Safari 9.1.3: 'list' in document.createElement('input') === false + // HTMLInputElement.list is a read-only DOM property that returns the associated + // HTMLDataListElement (or null). Must use setAttribute to set the datalist ID. + // See: https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/list list: true, }, - // element.form is actually a legitimate readOnly property, that is to be - // mutated, but must be mutated by setAttribute... SELECT: { form: true }, OPTION: { form: true }, TEXTAREA: { form: true }, diff --git a/packages/@glimmer/syntax/package.json b/packages/@glimmer/syntax/package.json index b3961651653..886a9b99963 100644 --- a/packages/@glimmer/syntax/package.json +++ b/packages/@glimmer/syntax/package.json @@ -16,17 +16,11 @@ "access": "public", "exports": { ".": { - "development": { - "types": "./dist/dev/index.d.ts", - "default": "./dist/dev/index.js" + "node": { + "require": "./dist/cjs/index.cjs", + "import": "./dist/es/index.js" }, - "require": { - "default": "./dist/dev/index.cjs" - }, - "default": { - "types": "./dist/prod/index.d.ts", - "default": "./dist/prod/index.js" - } + "default": "./dist/es/index.js" } }, "types": "dist/dev/index.d.ts" @@ -35,7 +29,6 @@ "dist" ], "scripts": { - "prepack": "rollup -c rollup.config.mjs", "test:publint": "publint" }, "dependencies": { diff --git a/packages/@handlebars/parser/package.json b/packages/@handlebars/parser/package.json index d4529cd44e2..d1180ec0a2b 100644 --- a/packages/@handlebars/parser/package.json +++ b/packages/@handlebars/parser/package.json @@ -34,6 +34,6 @@ "combine-files": "^1.1.8", "jison": "^0.4.18", "mocha": "^10.7.3", - "npm-run-all": "^4.1.5" + "npm-run-all2": "^5.0.0" } } diff --git a/packages/ember-testing/package.json b/packages/ember-testing/package.json index b7c9e9e0112..d2ceb6b5435 100644 --- a/packages/ember-testing/package.json +++ b/packages/ember-testing/package.json @@ -27,6 +27,6 @@ "backburner.js": "^2.7.0", "ember": "workspace:*", "internal-test-helpers": "workspace:*", - "router_js": "^8.0.5" + "router_js": "workspace:*" } } diff --git a/packages/ember/package.json b/packages/ember/package.json index ed48f2646eb..5fd19c1e9c5 100644 --- a/packages/ember/package.json +++ b/packages/ember/package.json @@ -46,7 +46,7 @@ "ember-testing": "workspace:*", "expect-type": "^0.15.0", "internal-test-helpers": "workspace:*", - "router_js": "^8.0.5", + "router_js": "workspace:*", "rsvp": "^4.8.5" } } diff --git a/packages/ember/tests/routing/decoupled_basic_test.js b/packages/ember/tests/routing/decoupled_basic_test.js index a71b245d919..a66a6ddd72a 100644 --- a/packages/ember/tests/routing/decoupled_basic_test.js +++ b/packages/ember/tests/routing/decoupled_basic_test.js @@ -698,7 +698,11 @@ moduleFor( // if we transition in this test we will receive failures // if the tests are run from a static file _doURLTransition() { - return RSVP.resolve(''); + return { + followRedirects() { + return RSVP.resolve(''); + }, + }; }, }); diff --git a/packages/internal-test-helpers/index.ts b/packages/internal-test-helpers/index.ts index 33c768572fa..cfb0d5c2910 100644 --- a/packages/internal-test-helpers/index.ts +++ b/packages/internal-test-helpers/index.ts @@ -57,5 +57,4 @@ export { ModuleBasedResolver as ModuleBasedTestResolver, } from './lib/test-resolver'; -export { isEdge } from './lib/browser-detect'; export { verifyRegistration } from './lib/registry-check'; diff --git a/packages/internal-test-helpers/lib/browser-detect.ts b/packages/internal-test-helpers/lib/browser-detect.ts deleted file mode 100644 index cf352934c41..00000000000 --- a/packages/internal-test-helpers/lib/browser-detect.ts +++ /dev/null @@ -1 +0,0 @@ -export const isEdge = /Edge/.test(navigator.userAgent); diff --git a/packages/internal-test-helpers/lib/compile.ts b/packages/internal-test-helpers/lib/compile.ts index 7fd317a7fe8..2266b47457e 100644 --- a/packages/internal-test-helpers/lib/compile.ts +++ b/packages/internal-test-helpers/lib/compile.ts @@ -24,12 +24,15 @@ export default function compile( ): TemplateFactory { options.locals = options.locals ?? Object.keys(scopeValues ?? {}); let [block, usedLocals] = precompileJSON(templateSource, compileOptions(options)); - let reifiedScopeValues = usedLocals.map((key) => scopeValues[key]); + let reifiedScope: Record = {}; + for (let key of usedLocals) { + reifiedScope[key] = scopeValues[key]; + } let templateBlock: SerializedTemplateWithLazyBlock = { block: JSON.stringify(block), moduleName: options.moduleName ?? options.meta?.moduleName ?? '(unknown template module)', - scope: reifiedScopeValues.length > 0 ? () => reifiedScopeValues : null, + scope: usedLocals.length > 0 ? () => reifiedScope : null, isStrictMode: options.strictMode ?? false, }; diff --git a/packages/internal-test-helpers/lib/ember-dev/assertion.ts b/packages/internal-test-helpers/lib/ember-dev/assertion.ts index 928d038e048..7a0b4dfb1f5 100644 --- a/packages/internal-test-helpers/lib/ember-dev/assertion.ts +++ b/packages/internal-test-helpers/lib/ember-dev/assertion.ts @@ -73,8 +73,6 @@ export function setupAssertionHelpers(hooks: NestedHooks, env: DebugEnv): void { }); hooks.afterEach(function () { - // Edge will occasionally not run finally blocks, so we have to be extra - // sure we restore the original assert function env.setDebugFunction('assert', originalAssertFunc); let w = window as ExtendedWindow; diff --git a/packages/internal-test-helpers/lib/equal-inner-html.ts b/packages/internal-test-helpers/lib/equal-inner-html.ts index dee3f81aadb..0f20badccf8 100644 --- a/packages/internal-test-helpers/lib/equal-inner-html.ts +++ b/packages/internal-test-helpers/lib/equal-inner-html.ts @@ -1,37 +1,9 @@ -// detect side-effects of cloning svg elements in IE9-11 -let ieSVGInnerHTML = (() => { - if (!document.createElementNS) { - return false; - } - let div = document.createElement('div'); - let node = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); - div.appendChild(node); - let clone = div.cloneNode(true) as HTMLDivElement; - return clone.innerHTML === ''; -})(); - -function normalizeInnerHTML(actualHTML: string) { - if (ieSVGInnerHTML) { - // Replace `` with ``, etc. - // drop namespace attribute - // replace self-closing elements - actualHTML = actualHTML - .replace(/ xmlns="[^"]+"/, '') - .replace( - /<([^ >]+) [^/>]*\/>/gi, - (tag, tagName) => `${tag.slice(0, tag.length - 3)}>` - ); - } - - return actualHTML; -} - export default function equalInnerHTML( assert: QUnit['assert'], fragment: HTMLElement, html: string ) { - let actualHTML = normalizeInnerHTML(fragment.innerHTML); + let actualHTML = fragment.innerHTML; assert.pushResult({ result: actualHTML === html, diff --git a/packages/internal-test-helpers/lib/matchers.ts b/packages/internal-test-helpers/lib/matchers.ts index 3faa71aa20e..8ea4b6fdf5b 100644 --- a/packages/internal-test-helpers/lib/matchers.ts +++ b/packages/internal-test-helpers/lib/matchers.ts @@ -75,8 +75,6 @@ export function styles(expected: string) { [MATCHER_BRAND]: true, match(actual: string) { - // coerce `null` or `undefined` to an empty string - // needed for matching empty styles on IE9 - IE11 actual = actual || ''; actual = actual.trim(); diff --git a/packages/internal-test-helpers/lib/system/synthetic-events.ts b/packages/internal-test-helpers/lib/system/synthetic-events.ts index 032f2b17c28..d012c411038 100644 --- a/packages/internal-test-helpers/lib/system/synthetic-events.ts +++ b/packages/internal-test-helpers/lib/system/synthetic-events.ts @@ -43,7 +43,7 @@ export function focus(el: Element | null | undefined) { } if (isFocusable(el)) { run(null, function () { - let browserIsNotFocused = document.hasFocus && !document.hasFocus(); + let browserIsNotFocused = !document.hasFocus(); // Firefox does not trigger the `focusin` event if the window // does not have focus. If the document doesn't have focus just @@ -66,7 +66,7 @@ export function focus(el: Element | null | undefined) { export function blur(el: Element) { if (isFocusable(el)) { run(null, function () { - let browserIsNotFocused = document.hasFocus && !document.hasFocus(); + let browserIsNotFocused = !document.hasFocus(); fireEvent(el, 'focusout'); @@ -134,21 +134,9 @@ function buildBasicEvent(type: string, options: EventInit = {}) { } function buildMouseEvent(type: string, options: MouseEventInit = {}) { - let event; - try { - event = new MouseEvent(type, { ...DEFAULT_EVENT_OPTIONS, ...options }); - } catch (_e) { - event = buildBasicEvent(type, options); - } - return event; + return new MouseEvent(type, { ...DEFAULT_EVENT_OPTIONS, ...options }); } function buildKeyboardEvent(type: string, options: KeyboardEventInit = {}) { - let event; - try { - event = new KeyboardEvent(type, { ...DEFAULT_EVENT_OPTIONS, ...options }); - } catch (_e) { - event = buildBasicEvent(type, options); - } - return event; + return new KeyboardEvent(type, { ...DEFAULT_EVENT_OPTIONS, ...options }); } diff --git a/packages/internal-test-helpers/package.json b/packages/internal-test-helpers/package.json index a37a820bd6a..d09f8ef17c0 100644 --- a/packages/internal-test-helpers/package.json +++ b/packages/internal-test-helpers/package.json @@ -39,7 +39,7 @@ "dag-map": "^2.0.2", "ember": "workspace:*", "ember-template-compiler": "workspace:*", - "router_js": "^8.0.5", + "router_js": "workspace:*", "rsvp": "^4.8.5", "simple-html-tokenizer": "^0.5.11" } diff --git a/packages/loader/lib/index.js b/packages/loader/lib/index.js index 875c7ffe566..15e6a1dec8d 100644 --- a/packages/loader/lib/index.js +++ b/packages/loader/lib/index.js @@ -1,27 +1,11 @@ /* eslint-disable no-var */ -/* globals global globalThis self */ /* eslint-disable-next-line no-unused-vars */ var define, require; (function () { - var globalObj = - typeof globalThis !== 'undefined' - ? globalThis - : typeof self !== 'undefined' - ? self - : typeof window !== 'undefined' - ? window - : typeof global !== 'undefined' - ? global - : null; - - if (globalObj === null) { - throw new Error('unable to locate global object'); - } - - if (typeof globalObj.define === 'function' && typeof globalObj.require === 'function') { - define = globalObj.define; - require = globalObj.require; + if (typeof globalThis.define === 'function' && typeof globalThis.require === 'function') { + define = globalThis.define; + require = globalThis.require; return; } diff --git a/packages/router_js/.eslintignore b/packages/router_js/.eslintignore new file mode 100644 index 00000000000..849ddff3b7e --- /dev/null +++ b/packages/router_js/.eslintignore @@ -0,0 +1 @@ +dist/ diff --git a/packages/router_js/.gitignore b/packages/router_js/.gitignore new file mode 100644 index 00000000000..bf5d524735e --- /dev/null +++ b/packages/router_js/.gitignore @@ -0,0 +1,7 @@ +/.bundle +/dist +/tmp +/node_modules + +dist/tests +.eslintcache diff --git a/packages/router_js/ARCHITECTURE.md b/packages/router_js/ARCHITECTURE.md new file mode 100644 index 00000000000..a1e6391d45e --- /dev/null +++ b/packages/router_js/ARCHITECTURE.md @@ -0,0 +1,186 @@ +# [router.js](https://github.com/tildeio/router.js) Architecture + +This is a guide to `router.js`'s internals. + +`router.js` is a stand-alone microlibrary for client-side routing in JavaScript +applications. It's notably used by the [Ember.js Router][Ember Router]. + +## Scope of `router.js` and its Dependencies + +Ember.js's router consumes `router.js`, which in turn consumes +[route-recognizer](https://github.com/tildeio/route-recognizer). + +The division of responsibilities of these three libs is as follows: + +### `route-recognizer` + +`route-recognizer` is an engine for both parsing/generating URLs into/from +parameters. + +It can take a URL like `articles/123/comments` and parse out the parameter +`{ article_id: "123" }`. + +It can take `{ article_id: "123" }` and a route descriptor like +`articles/:article_id/comments` and generate `articles/123/comments`. + +### `router.js` + +`router.js` adds the concept of transitions to `route-recognizer`'s +URL parsing engine. + +Transitions can be URL-initiated (via browser navigation) or can be +directly initiated via route name +(e.g. `transitionTo('articles', articleObject)`). + +`router.js` resolves all of the model objects that needed to be loaded +in order to enter a route. + +e.g. to navigate to `articles/123/comments/2`, a promise for both the +`article` and `comments` routes need to be fulfilled. + +### Ember Router + +The [Ember Router][] adds a DSL for declaring your app's routes on top of +`router.js`. It defines the API for the `Ember.Route` class that handles +intelligent defaults, rendering templates, and loading data into controllers. + +## History + +`router.js` has gone through a few iterations between 2013 and 2014: + +- July of 2013 – `router.js` adds promise-awareness. +- Jan 2014 – refactored `router.js`'s primitives to handle corner cases. + +### Corner Cases + +1. Avoid running `model` hooks (responsible for fetching data needed to enter a + route) for shared parent routes. + +2. Avoid running model hooks when redirecting in the middle of another transition. + e.g. during a transition to `articles/123/comments/2` you redirect to + `articles/123/comments/3` after resolving Article 123 and you want to + avoid re-running the hooks to load Article 123 again. + +3. Handle two different approaches to transitions: + - URL based (where a URL is parsed into route parameters that are used to + load all the data needed to enter a route (e.g. `{ article_id: 123 }`). + + - direct named transition-based, where a route name and any context objects + are provided (e.g. `transitionTo('article', articleObject)`), and the + provided context object(s) might be promises that can't be serialized + into URL params until they've fulfilled. + +## Classes + +### `HandlerInfo` + +A `HandlerInfo` is an object that describes the state of a route handler. + +For example, the `foo/bar` URL likely breaks down into a hierarchy of two +handlers: the `foo` handler and the `bar` handler. A "handler" is just an +object that defines hooks that `router.js` will call in the course of a +transition (e.g. `model`, `beforeModel`, `setup`, etc.). + +In Ember.js, handlers are instances of `Ember.Route`. + +A `HandlerInfo` instance contains that handler's model (e.g. `articleObject`), +or the URL parameters associated with the current state of that handler +(e.g. `{ article_id: '123' }`). + +Because `router.js` allows you to reuse handlers between different routes and +route hierarchies, we need `HandlerInfo`s to describe the state of each route +hierarchy. + +`HandlerInfo` is a top-level class with 3 subclasses: + +#### `UnresolvedHandlerInfoByParam` + +`UnresolvedHandlerInfoByParam` has the URL params stored on it which it can use +to resolve itself (by calling the handler's `beforeModel`/`model`/`afterModel` +hooks). + +#### `UnresolvedHandlerInfoByObject` + +`UnresolvedHandlerInfoByObject` has a context object, but no URL params. +It can use the context to resolve itself and serialize into URL params once +the context object is fulfilled. + +#### `ResolvedHandlerInfo` + +`ResolvedHandlerInfo` has calculated its URL params and resolved context/model +object. + +#### Public API + +`HandlerInfo` has just a `resolve` method which fires all `model` hooks and +ultimately resolves to a `ResolvedHandlerInfo` object. + +The `ResolvedHandlerInfo`'s `resolve` method just returns a promise that +fulfills with itself. + +### `TransitionState` + +The `TransitionState` object consists of an array of `HandlerInfo`s +(though more might be added to it; not sure yet). + +#### Public API + +It too has a public API consisting only of a `resolve` method that +will loop through all of its `HandlerInfo`s, swapping unresolved +`HandlerInfo`s with `ResolvedHandlerInfo`s as it goes. + +Instances of `Router` and `Transition` contain `TransitionState` +properties, which is useful since, depending on whether or not there is +a currently active transition, the "starting point" of a transition +might be the router's current hierarchy of `ResolvedHandlerInfo`s, or it +might be a transition's hierarchy of `ResolvedHandlerInfo`s mixed with +unresolved HandlerInfos. + +### `TransitionIntent` + +A `TransitionIntent` describes an attempt to transition. + +via URL +or by named transition (via its subclasses `URLTransitionIntent` and +`NamedTransitionIntent`). + +#### `URLTransitionIntent` + +A `URLTransitionIntent` has a `url` property. + +#### `NamedTransitionIntent` + +A `NamedTransitionIntent` has a target route `name` and `contexts` array +property. + +This class defines only one method `applyToState` which takes an instance of +`TransitionState` and plays this `TransitionIntent` on top of it to generate +and return a new instance of `TransitionState` that contains a combination of +resolved and unresolved `HandlerInfo`s. + +`TransitionIntent`s don't care whether the provided state comes from a router +or a currently active transition; whatever you provide it, both subclasses of +`TransitionIntent`s are smart enough to spit out a `TransitionState` +containing `HandlerInfo`s that still need to be resolved in order to complete +a transition. + +Much of the messy logic that used to live in `paramsForHandler`/`getMatchPoint` +now live way less messily in the `applyToState` methods. + +This makes it easy to detect corner cases like no-op transitions – if the +returned `TransitionState` consists entirely of `ResolvedHandlerInfo`s, there's +no need to fire off a transition. It simplifies things like redirecting into a +child route without winding up in some infinite loop on the parent route hook +that's doing the redirecting. + +This simplifies `Transition#retry`; to retry a transition, provide its `intent` +property to the transitioning function used by `transitionTo`, `handleURL`. +`handle` function will make the right choice as to the correct `TransitionState` +to pass to the intent's `applyToState` method. + +This approach is used to implement `Router#isActive`. You can determine if a +destination route is active by constructing a `TransitionIntent`, applying it +to the router's current state, and returning `true` if all of the +`HandlerInfo`s are already resolved. + +[Ember Router]: http://emberjs.com/guides/routing/ diff --git a/packages/router_js/CHANGELOG.md b/packages/router_js/CHANGELOG.md new file mode 100644 index 00000000000..35c514e5a56 --- /dev/null +++ b/packages/router_js/CHANGELOG.md @@ -0,0 +1,121 @@ +## v8.0.6 (2024-08-02) + +- [#335] Fix followRedirects when source is async and destination is sync ([@davidtaylorhq](https://github.com/davidtaylorhq)) + + +## v8.0.5 (2024-03-19) + +- [#339] Fix a type error when exactOptionalPropertyTypes is enabled ([@boris-petrov](https://github.com/boris-petrov)) + + +## v8.0.4 (2024-03-06) + +- [#336] Calling recognize should not affect the transition.from query params for subsequent transitions ([@chbonser](https://github.com/chbonser)) + + +## v8.0.3 (2022-08-27) + +- [#334] Fix undefined routeInfo in routeInfo's `find` callback ([@sly7-7](https://github.com/sly7-7)) + + +## v8.0.2 (2022-02-09) + +- [#332] Correct more incorrect TypeScript types + +## v8.0.1 (2022-02-03) + +- [#331] Correct some incorrect TypeScript types + +## v8.0.0 (2022-02-02) + +#### :boom: Breaking Change + +- [#329](https://github.com/tildeio/router.js/pull/329) Better Types ([@wagenet](https://github.com/wagenet)) + +#### Committers: 1 + +- Peter Wagenet ([@wagenet](https://github.com/wagenet)) + +## v7.3.0 (2021-03-07) + +#### :rocket: Enhancement + +- [#321](https://github.com/tildeio/router.js/pull/321) Add `isIntermediate` flag to Transition ([@sly7-7](https://github.com/sly7-7)) + +#### :house: Internal + +- [#320](https://github.com/tildeio/router.js/pull/320) Remove testing for multiple platforms. ([@rwjblue](https://github.com/rwjblue)) + +#### Committers: 2 + +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) +- Sylvain MINA ([@sly7-7](https://github.com/sly7-7)) + +## v7.2.0 (2021-03-07) + +#### :bug: Bug Fix + +- [#319](https://github.com/tildeio/router.js/pull/319) Ensure query params are preserved through an intermediate loading state transition ([@sly7-7](https://github.com/sly7-7)) + +#### :memo: Documentation + +- [#316](https://github.com/tildeio/router.js/pull/316) Publish type declaration ([@xg-wang](https://github.com/xg-wang)) + +#### :house: Internal + +- [#318](https://github.com/tildeio/router.js/pull/318) add livereload so tests reload when i make changes ([@stefanpenner](https://github.com/stefanpenner)) +- [#309](https://github.com/tildeio/router.js/pull/309) Refactor TransitionAbort to builder interface ([@rwjblue](https://github.com/rwjblue)) +- [#306](https://github.com/tildeio/router.js/pull/306) Simplify TransitionState resolution system. ([@rwjblue](https://github.com/rwjblue)) +- [#314](https://github.com/tildeio/router.js/pull/314) [Closes [#313](https://github.com/tildeio/router.js/issues/313)] Fix Typo shouldSupercede -> shouldSupersede ([@stefanpenner](https://github.com/stefanpenner)) +- [#315](https://github.com/tildeio/router.js/pull/315) Fix other typo’s ([@stefanpenner](https://github.com/stefanpenner)) +- [#312](https://github.com/tildeio/router.js/pull/312) Upgrade `devDependencies` ([@stefanpenner](https://github.com/stefanpenner)) +- [#311](https://github.com/tildeio/router.js/pull/311) Upgrade CI ([@stefanpenner](https://github.com/stefanpenner)) + +#### Committers: 4 + +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) +- Stefan Penner ([@stefanpenner](https://github.com/stefanpenner)) +- Sylvain MINA ([@sly7-7](https://github.com/sly7-7)) +- Thomas Wang ([@xg-wang](https://github.com/xg-wang)) + +## v7.1.1 (2020-11-06) + +#### :bug: Bug Fix + +- [#308](https://github.com/tildeio/router.js/pull/308) Provide transition to `setupContext` for internal transition ([@rreckonerr](https://github.com/rreckonerr)) + +#### Committers: 1 + +- Volodymyr Radchenko ([@rreckonerr](https://github.com/rreckonerr)) + +## v7.1.0 (2020-09-09) + +#### :rocket: Enhancement + +- [#305](https://github.com/tildeio/router.js/pull/305) Add better Transition debugging information. ([@rwjblue](https://github.com/rwjblue)) + +#### Committers: 1 + +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) + +## v7.0.0 (2020-07-21) + +#### :boom: Breaking Change + +- [#297](https://github.com/tildeio/router.js/pull/297) Update TypeScript to 3.9 ([@xg-wang](https://github.com/xg-wang)) +- [#294](https://github.com/tildeio/router.js/pull/294) Drop Node < 10. ([@rwjblue](https://github.com/rwjblue)) +- [#289](https://github.com/tildeio/router.js/pull/289) Upgrade TypeScript to 3.5 ([@xg-wang](https://github.com/xg-wang)) + +#### :house: Internal + +- [#301](https://github.com/tildeio/router.js/pull/301) Add automated release setup. ([@rwjblue](https://github.com/rwjblue)) +- [#300](https://github.com/tildeio/router.js/pull/300) Update Babel to latest. ([@rwjblue](https://github.com/rwjblue)) +- [#299](https://github.com/tildeio/router.js/pull/299) Update remaining dependencies/devDependencies to latest. ([@rwjblue](https://github.com/rwjblue)) +- [#298](https://github.com/tildeio/router.js/pull/298) Update prettier to 2.0.5. ([@rwjblue](https://github.com/rwjblue)) +- [#296](https://github.com/tildeio/router.js/pull/296) Migrate from TSLint to ESLint ([@rwjblue](https://github.com/rwjblue)) +- [#295](https://github.com/tildeio/router.js/pull/295) Add GitHub Actions CI setup ([@rwjblue](https://github.com/rwjblue)) + +#### Committers: 2 + +- Robert Jackson ([@rwjblue](https://github.com/rwjblue)) +- Thomas Wang ([@xg-wang](https://github.com/xg-wang)) diff --git a/packages/router_js/LICENSE b/packages/router_js/LICENSE new file mode 100644 index 00000000000..13883e15041 --- /dev/null +++ b/packages/router_js/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014 Yehuda Katz, Tom Dale, and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE diff --git a/packages/router_js/README.md b/packages/router_js/README.md new file mode 100644 index 00000000000..82c360744a5 --- /dev/null +++ b/packages/router_js/README.md @@ -0,0 +1,5 @@ +# router.js + +This package was a dependency of Ember.js and was migrated into the monorepo from https://github.com/emberjs/router.js + +`router.js` was always bundled in the ember-source package and was never consumed directly as a package. This has been merged into the monorepo to prepare for the upcoming [Route Manager RFC](https://github.com/emberjs/rfcs/pull/1169) to make it easier to move things around during the implementation phase. diff --git a/packages/router_js/index.ts b/packages/router_js/index.ts new file mode 100644 index 00000000000..11f8f8bb438 --- /dev/null +++ b/packages/router_js/index.ts @@ -0,0 +1,19 @@ +export { default } from './lib/router'; +export { + default as InternalTransition, + logAbort, + STATE_SYMBOL, + PARAMS_SYMBOL, + QUERY_PARAMS_SYMBOL, +} from './lib/transition'; + +export type { PublicTransition as Transition } from './lib/transition'; + +export { default as TransitionState, TransitionError } from './lib/transition-state'; +export { + default as InternalRouteInfo, + type Route, + type RouteInfo, + type RouteInfoWithAttributes, + type ModelFor, +} from './lib/route-info'; diff --git a/packages/router_js/lib/core.ts b/packages/router_js/lib/core.ts new file mode 100644 index 00000000000..cc35265994a --- /dev/null +++ b/packages/router_js/lib/core.ts @@ -0,0 +1,7 @@ +export type Present = object | void; +export type Option = T | null; +export type Maybe = Option | undefined | void; +export type Recast = (T & U) | U; +export interface Dict { + [key: string]: T; +} diff --git a/packages/router_js/lib/route-info.ts b/packages/router_js/lib/route-info.ts new file mode 100644 index 00000000000..ecd4875b1a8 --- /dev/null +++ b/packages/router_js/lib/route-info.ts @@ -0,0 +1,603 @@ +/* eslint-disable no-prototype-builtins */ +import { Promise } from 'rsvp'; +import type { Dict, Option } from './core'; +import type { SerializerFunc } from './router'; +import type Router from './router'; +import type { PublicTransition as Transition } from './transition'; +import type InternalTransition from './transition'; +import { isTransition, PARAMS_SYMBOL, prepareResult, QUERY_PARAMS_SYMBOL } from './transition'; +import { isParam, isPromise, merge } from './utils'; +import { throwIfAborted } from './transition-aborted-error'; + +export type IModel = {} & { + id?: string | number; +}; + +export type ModelFor = T extends Route ? V : never; + +export interface Route { + inaccessibleByURL?: boolean; + routeName: string; + _internalName: string; + context: T | undefined; + events?: Dict<(...args: unknown[]) => unknown>; + model?(params: Dict, transition: Transition): PromiseLike | undefined | T; + deserialize?(params: Dict, transition: Transition): T | PromiseLike | undefined; + serialize?(model: T | undefined, params: string[]): Dict | undefined; + beforeModel?(transition: Transition): PromiseLike | any; + afterModel?(resolvedModel: T | undefined, transition: Transition): PromiseLike | any; + setup?(context: T | undefined, transition: Transition): void; + enter?(transition: Transition): void; + exit?(transition?: Transition): void; + _internalReset?(wasReset: boolean, transition?: Transition): void; + contextDidChange?(): void; + redirect?(context: T | undefined, transition: Transition): void; + buildRouteInfoMetadata?(): unknown; +} + +export interface RouteInfo { + readonly name: string; + readonly parent: RouteInfo | RouteInfoWithAttributes | null; + readonly child: RouteInfo | RouteInfoWithAttributes | null; + readonly localName: string; + readonly params: Dict | undefined; + readonly paramNames: string[]; + readonly queryParams: Dict; + readonly metadata: unknown; + find( + predicate: (this: any, routeInfo: RouteInfo, i: number) => boolean, + thisArg?: any + ): RouteInfo | undefined; +} + +export interface RouteInfoWithAttributes extends RouteInfo { + attributes: any; +} + +type RouteInfosKey = InternalRouteInfo; + +let ROUTE_INFOS = new WeakMap(); + +export function toReadOnlyRouteInfo( + routeInfos: InternalRouteInfo[], + queryParams: Dict = {}, + options: { + includeAttributes?: boolean; + localizeMapUpdates?: boolean; + } = { includeAttributes: false, localizeMapUpdates: false } +): RouteInfoWithAttributes[] | RouteInfo[] { + const LOCAL_ROUTE_INFOS = new WeakMap(); + + return routeInfos.map((info, i) => { + let { name, params, paramNames, context, route } = info; + // SAFETY: This should be safe since it is just for use as a key + let key = info as unknown as RouteInfosKey; + if (ROUTE_INFOS.has(key) && options.includeAttributes) { + let routeInfo = ROUTE_INFOS.get(key)!; + routeInfo = attachMetadata(route!, routeInfo); + let routeInfoWithAttribute = createRouteInfoWithAttributes(routeInfo, context); + LOCAL_ROUTE_INFOS.set(key, routeInfo); + if (!options.localizeMapUpdates) { + ROUTE_INFOS.set(key, routeInfoWithAttribute); + } + return routeInfoWithAttribute as RouteInfoWithAttributes; + } + + const routeInfosRef = options.localizeMapUpdates ? LOCAL_ROUTE_INFOS : ROUTE_INFOS; + + let routeInfo: RouteInfo = { + find( + predicate: (this: any, routeInfo: RouteInfo, i: number, arr?: RouteInfo[]) => boolean, + thisArg: any + ) { + let publicInfo; + let arr: RouteInfo[] = []; + + if (predicate.length === 3) { + arr = routeInfos.map( + // SAFETY: This should be safe since it is just for use as a key + (info) => routeInfosRef.get(info as unknown as RouteInfosKey)! + ); + } + + for (let i = 0; routeInfos.length > i; i++) { + // SAFETY: This should be safe since it is just for use as a key + publicInfo = routeInfosRef.get(routeInfos[i] as unknown as RouteInfosKey)!; + if (predicate.call(thisArg, publicInfo, i, arr)) { + return publicInfo; + } + } + + return undefined; + }, + + get name() { + return name; + }, + + get paramNames() { + return paramNames; + }, + + get metadata() { + return buildRouteInfoMetadata(info.route); + }, + + get parent() { + let parent = routeInfos[i - 1]; + + if (parent === undefined) { + return null; + } + + // SAFETY: This should be safe since it is just for use as a key + return routeInfosRef.get(parent as unknown as RouteInfosKey)!; + }, + + get child() { + let child = routeInfos[i + 1]; + + if (child === undefined) { + return null; + } + + // SAFETY: This should be safe since it is just for use as a key + return routeInfosRef.get(child as unknown as RouteInfosKey)!; + }, + + get localName() { + let parts = this.name.split('.'); + return parts[parts.length - 1]!; + }, + + get params() { + return params; + }, + + get queryParams() { + return queryParams; + }, + }; + + if (options.includeAttributes) { + routeInfo = createRouteInfoWithAttributes(routeInfo, context); + } + + // SAFETY: This should be safe since it is just for use as a key + LOCAL_ROUTE_INFOS.set(info as unknown as RouteInfosKey, routeInfo); + + if (!options.localizeMapUpdates) { + // SAFETY: This should be safe since it is just for use as a key + ROUTE_INFOS.set(info as unknown as RouteInfosKey, routeInfo); + } + + return routeInfo; + }); +} + +function createRouteInfoWithAttributes( + routeInfo: RouteInfo, + context: any +): RouteInfoWithAttributes { + let attributes = { + get attributes() { + return context; + }, + }; + + if (!Object.isExtensible(routeInfo) || routeInfo.hasOwnProperty('attributes')) { + return Object.freeze(Object.assign({}, routeInfo, attributes)); + } + + return Object.assign(routeInfo, attributes); +} + +function buildRouteInfoMetadata(route?: Route) { + if (route !== undefined && route !== null && route.buildRouteInfoMetadata !== undefined) { + return route.buildRouteInfoMetadata(); + } + + return null; +} + +function attachMetadata(route: Route, routeInfo: RouteInfo) { + let metadata = { + get metadata() { + return buildRouteInfoMetadata(route); + }, + }; + + if (!Object.isExtensible(routeInfo) || routeInfo.hasOwnProperty('metadata')) { + return Object.freeze(Object.assign({}, routeInfo, metadata)); + } + + return Object.assign(routeInfo, metadata); +} + +export default class InternalRouteInfo { + private _routePromise?: Promise = undefined; + private _route?: Option = null; + protected router: Router; + declare paramNames: string[]; + declare name: string; + params: Dict | undefined = {}; + declare queryParams?: Dict; + declare context?: ModelFor | PromiseLike> | undefined; + isResolved = false; + + constructor(router: Router, name: string, paramNames: string[], route?: R) { + this.name = name; + this.paramNames = paramNames; + this.router = router; + if (route) { + this._processRoute(route); + } + } + + getModel(_transition: InternalTransition) { + return Promise.resolve(this.context); + } + + serialize(_context?: ModelFor | null): Dict | undefined { + return this.params || {}; + } + + resolve(transition: InternalTransition): Promise> { + return Promise.resolve(this.routePromise) + .then((route: Route) => { + throwIfAborted(transition); + return route; + }) + .then(() => this.runBeforeModelHook(transition)) + .then(() => throwIfAborted(transition)) + .then(() => this.getModel(transition)) + .then((resolvedModel) => { + throwIfAborted(transition); + return resolvedModel; + }) + .then((resolvedModel) => this.runAfterModelHook(transition, resolvedModel)) + .then((resolvedModel) => this.becomeResolved(transition, resolvedModel)); + } + + becomeResolved( + transition: InternalTransition | null, + resolvedContext: ModelFor | undefined + ): ResolvedRouteInfo { + let params = this.serialize(resolvedContext); + + if (transition) { + this.stashResolvedModel(transition, resolvedContext); + transition[PARAMS_SYMBOL] = transition[PARAMS_SYMBOL] || {}; + transition[PARAMS_SYMBOL][this.name] = params; + } + + let context; + let contextsMatch = resolvedContext === this.context; + + if ('context' in this || !contextsMatch) { + context = resolvedContext; + } + + // SAFETY: Since this is just for lookup, it should be safe + let cached = ROUTE_INFOS.get(this as unknown as InternalRouteInfo); + let resolved = new ResolvedRouteInfo( + this.router, + this.name, + this.paramNames, + params, + this.route!, + context + ); + + if (cached !== undefined) { + // SAFETY: This is potentially a bit risker, but for what we're doing, it should be ok. + ROUTE_INFOS.set(resolved as unknown as InternalRouteInfo, cached); + } + + return resolved; + } + + shouldSupersede(routeInfo?: InternalRouteInfo) { + // Prefer this newer routeInfo over `other` if: + // 1) The other one doesn't exist + // 2) The names don't match + // 3) This route has a context that doesn't match + // the other one (or the other one doesn't have one). + // 4) This route has parameters that don't match the other. + if (!routeInfo) { + return true; + } + + let contextsMatch = routeInfo.context === this.context; + return ( + routeInfo.name !== this.name || + ('context' in this && !contextsMatch) || + (this.hasOwnProperty('params') && !paramsMatch(this.params, routeInfo.params)) + ); + } + + get route(): R | undefined { + // _route could be set to either a route object or undefined, so we + // compare against null to know when it's been set + if (this._route !== null) { + return this._route; + } + + return this.fetchRoute(); + } + + set route(route: R | undefined) { + this._route = route; + } + + get routePromise(): Promise { + if (this._routePromise) { + return this._routePromise; + } + + this.fetchRoute(); + + return this._routePromise!; + } + + set routePromise(routePromise: Promise) { + this._routePromise = routePromise; + } + + protected log(transition: InternalTransition, message: string) { + if (transition.log) { + transition.log(this.name + ': ' + message); + } + } + + private updateRoute(route: R) { + route._internalName = this.name; + return (this.route = route); + } + + private runBeforeModelHook(transition: InternalTransition) { + if (transition.trigger) { + transition.trigger(true, 'willResolveModel', transition, this.route); + } + + let result; + if (this.route) { + if (this.route.beforeModel !== undefined) { + result = this.route.beforeModel(transition); + } + } + + if (isTransition(result)) { + result = null; + } + + return Promise.resolve(result); + } + + private runAfterModelHook( + transition: InternalTransition, + resolvedModel?: ModelFor | null + ): Promise> { + // Stash the resolved model on the payload. + // This makes it possible for users to swap out + // the resolved model in afterModel. + let name = this.name; + this.stashResolvedModel(transition, resolvedModel!); + + let result; + if (this.route !== undefined) { + if (this.route.afterModel !== undefined) { + result = this.route.afterModel(resolvedModel!, transition); + } + } + + result = prepareResult(result); + + return Promise.resolve(result).then(() => { + // Ignore the fulfilled value returned from afterModel. + // Return the value stashed in resolvedModels, which + // might have been swapped out in afterModel. + // SAFTEY: We expect this to be of type T, though typing it as such is challenging. + return transition.resolvedModels[name]! as unknown as ModelFor; + }); + } + + private stashResolvedModel( + transition: InternalTransition, + resolvedModel: ModelFor | undefined + ) { + transition.resolvedModels = transition.resolvedModels || {}; + // SAFETY: It's unfortunate that we have to do this cast. It should be safe though. + transition.resolvedModels[this.name] = resolvedModel; + } + + private fetchRoute() { + let route = this.router.getRoute(this.name); + return this._processRoute(route); + } + + private _processRoute(route: R | Promise) { + // Setup a routePromise so that we can wait for asynchronously loaded routes + this.routePromise = Promise.resolve(route); + + // Wait until the 'route' property has been updated when chaining to a route + // that is a promise + if (isPromise(route)) { + this.routePromise = this.routePromise.then((r) => { + return this.updateRoute(r); + }); + // set to undefined to avoid recursive loop in the route getter + return (this.route = undefined); + } else if (route) { + return this.updateRoute(route); + } + + return undefined; + } +} + +export class ResolvedRouteInfo extends InternalRouteInfo { + isResolved: boolean; + context: ModelFor | undefined; + constructor( + router: Router, + name: string, + paramNames: string[], + params: Dict | undefined, + route: R, + context?: ModelFor + ) { + super(router, name, paramNames, route); + this.params = params; + this.isResolved = true; + this.context = context; + } + + resolve(transition: InternalTransition): Promise { + // A ResolvedRouteInfo just resolved with itself. + if (transition && transition.resolvedModels) { + transition.resolvedModels[this.name] = this.context; + } + return Promise.resolve(this); + } +} + +export class UnresolvedRouteInfoByParam extends InternalRouteInfo { + params: Dict = {}; + constructor( + router: Router, + name: string, + paramNames: string[], + params: Dict | undefined, + route?: R + ) { + super(router, name, paramNames, route); + if (params) { + this.params = params; + } + } + + getModel(transition: InternalTransition): Promise> { + let fullParams = this.params; + if (transition && transition[QUERY_PARAMS_SYMBOL]) { + fullParams = {}; + merge(fullParams, this.params); + fullParams['queryParams'] = transition[QUERY_PARAMS_SYMBOL]; + } + + let route = this.route!; + + let result: ModelFor | PromiseLike> | undefined; + + // FIXME: Review these casts + if (route.deserialize) { + result = route.deserialize(fullParams, transition) as + | ModelFor + | PromiseLike> + | undefined; + } else if (route.model) { + result = route.model(fullParams, transition) as + | ModelFor + | PromiseLike> + | undefined; + } + + if (result && isTransition(result)) { + result = undefined; + } + + return Promise.resolve(result); + } +} + +export class UnresolvedRouteInfoByObject extends InternalRouteInfo { + serializer?: SerializerFunc>; + constructor( + router: Router, + name: string, + paramNames: string[], + context: ModelFor | PromiseLike> | undefined + ) { + super(router, name, paramNames); + this.context = context; + this.serializer = this.router.getSerializer(name); + } + + getModel(transition: InternalTransition) { + if (this.router.log !== undefined) { + this.router.log(this.name + ': resolving provided model'); + } + return super.getModel(transition); + } + + /** + @private + + Serializes a route using its custom `serialize` method or + by a default that looks up the expected property name from + the dynamic segment. + + @param {Object} model the model to be serialized for this route + */ + serialize(model?: ModelFor): Dict | undefined { + let { paramNames, context } = this; + + if (!model) { + // SAFETY: By the time we serialize, we expect to be resolved. + // This may not be an entirely safe assumption though no tests fail. + model = context as ModelFor; + } + + let object: Dict = {}; + if (isParam(model)) { + object[paramNames[0]!] = model; + return object; + } + + // Use custom serialize if it exists. + if (this.serializer) { + // invoke this.serializer unbound (getSerializer returns a stateless function) + return this.serializer.call(null, model, paramNames); + } else if (this.route !== undefined) { + if (this.route.serialize) { + return this.route.serialize(model, paramNames); + } + } + + if (paramNames.length !== 1) { + return; + } + + let name = paramNames[0]!; + + if (/_id$/.test(name)) { + // SAFETY: Model is supposed to extend IModel already + object[name] = (model as IModel).id; + } else { + object[name] = model; + } + return object; + } +} + +function paramsMatch(a: Dict | undefined, b: Dict | undefined) { + if (a === b) { + // Both are identical, may both be undefined + return true; + } + + if (!a || !b) { + // Only one is undefined, already checked they aren't identical + return false; + } + + // Note: this assumes that both params have the same + // number of keys, but since we're comparing the + // same routes, they should. + for (let k in a) { + if (a.hasOwnProperty(k) && a[k] !== b[k]) { + return false; + } + } + return true; +} diff --git a/packages/router_js/lib/router.ts b/packages/router_js/lib/router.ts new file mode 100644 index 00000000000..0dd1300ae8c --- /dev/null +++ b/packages/router_js/lib/router.ts @@ -0,0 +1,1106 @@ +/* eslint-disable no-prototype-builtins */ +import type { MatchCallback, Params, QueryParams } from 'route-recognizer'; +import RouteRecognizer from 'route-recognizer'; +import { Promise } from 'rsvp'; +import type { Dict, Maybe, Option } from './core'; +import type { ModelFor, Route, RouteInfo, RouteInfoWithAttributes } from './route-info'; +import type InternalRouteInfo from './route-info'; +import { toReadOnlyRouteInfo } from './route-info'; +import type { OpaqueTransition, PublicTransition as Transition } from './transition'; +import InternalTransition, { logAbort, QUERY_PARAMS_SYMBOL, STATE_SYMBOL } from './transition'; +import { throwIfAborted, isTransitionAborted } from './transition-aborted-error'; +import type { TransitionIntent } from './transition-intent'; +import NamedTransitionIntent from './transition-intent/named-transition-intent'; +import URLTransitionIntent from './transition-intent/url-transition-intent'; +import type { TransitionError } from './transition-state'; +import TransitionState from './transition-state'; +import type { ChangeList, ModelsAndQueryParams } from './utils'; +import { extractQueryParams, forEach, getChangelist, log, merge, promiseLabel } from './utils'; + +export interface SerializerFunc { + (model: T, params: string[]): Dict; +} + +export interface ParsedHandler { + handler: string; + names: string[]; +} + +export default abstract class Router { + private _lastQueryParams = {}; + log?: (message: string) => void; + state?: TransitionState = undefined; + oldState: Maybe> = undefined; + activeTransition?: InternalTransition = undefined; + currentRouteInfos?: InternalRouteInfo[] = undefined; + _changedQueryParams?: Dict = undefined; + currentSequence = 0; + recognizer: RouteRecognizer; + + constructor(logger?: (message: string) => void) { + this.log = logger; + this.recognizer = new RouteRecognizer(); + this.reset(); + } + + abstract getRoute(name: string): R | Promise; + abstract getSerializer(name: string): SerializerFunc> | undefined; + abstract updateURL(url: string): void; + abstract replaceURL(url: string): void; + abstract willTransition( + oldRouteInfos: InternalRouteInfo[], + newRouteInfos: InternalRouteInfo[], + transition: Transition + ): void; + abstract didTransition(routeInfos: InternalRouteInfo[]): void; + abstract triggerEvent( + routeInfos: InternalRouteInfo[], + ignoreFailure: boolean, + name: string, + args: unknown[] + ): void; + + abstract routeWillChange(transition: Transition): void; + abstract routeDidChange(transition: Transition): void; + abstract transitionDidError(error: TransitionError, transition: Transition): Transition | Error; + + /** + The main entry point into the router. The API is essentially + the same as the `map` method in `route-recognizer`. + + This method extracts the String handler at the last `.to()` + call and uses it as the name of the whole route. + + @param {Function} callback + */ + map(callback: MatchCallback) { + this.recognizer.map(callback, function (recognizer, routes) { + for (let i = routes.length - 1, proceed = true; i >= 0 && proceed; --i) { + let route = routes[i]!; + let handler = route.handler as string; + recognizer.add(routes, { as: handler }); + proceed = route.path === '/' || route.path === '' || handler.slice(-6) === '.index'; + } + }); + } + + hasRoute(route: string) { + return this.recognizer.hasRoute(route); + } + + queryParamsTransition( + changelist: ChangeList, + wasTransitioning: boolean, + oldState: TransitionState, + newState: TransitionState + ): OpaqueTransition { + this.fireQueryParamDidChange(newState, changelist); + + if (!wasTransitioning && this.activeTransition) { + // One of the routes in queryParamsDidChange + // caused a transition. Just return that transition. + return this.activeTransition; + } else { + // Running queryParamsDidChange didn't change anything. + // Just update query params and be on our way. + + // We have to return a noop transition that will + // perform a URL update at the end. This gives + // the user the ability to set the url update + // method (default is replaceState). + let newTransition = new InternalTransition(this, undefined, undefined); + newTransition.queryParamsOnly = true; + + oldState.queryParams = this.finalizeQueryParamChange( + newState.routeInfos, + newState.queryParams, + newTransition + ); + + newTransition[QUERY_PARAMS_SYMBOL] = newState.queryParams; + + this.toReadOnlyInfos(newTransition, newState); + + this.routeWillChange(newTransition); + + newTransition.promise = newTransition.promise!.then( + (result: TransitionState | Route | Error | undefined) => { + if (!newTransition.isAborted) { + this._updateURL(newTransition, oldState); + this.didTransition(this.currentRouteInfos!); + this.toInfos(newTransition, newState.routeInfos, true); + this.routeDidChange(newTransition); + } + return result; + }, + null, + promiseLabel('Transition complete') + ); + + return newTransition; + } + } + + transitionByIntent(intent: TransitionIntent, isIntermediate: boolean): InternalTransition { + try { + return this.getTransitionByIntent(intent, isIntermediate); + } catch (e) { + return new InternalTransition(this, intent, undefined, e, undefined); + } + } + + recognize(url: string): Option { + let intent = new URLTransitionIntent(this, url); + let newState = this.generateNewState(intent); + + if (newState === null) { + return newState; + } + + let readonlyInfos = toReadOnlyRouteInfo(newState.routeInfos, newState.queryParams, { + includeAttributes: false, + localizeMapUpdates: true, + }); + return readonlyInfos[readonlyInfos.length - 1] as RouteInfo; + } + + recognizeAndLoad(url: string): Promise { + let intent = new URLTransitionIntent(this, url); + let newState = this.generateNewState(intent); + + if (newState === null) { + return Promise.reject(`URL ${url} was not recognized`); + } + + let newTransition: OpaqueTransition = new InternalTransition(this, intent, newState, undefined); + return newTransition.then(() => { + let routeInfosWithAttributes = toReadOnlyRouteInfo( + newState!.routeInfos, + newTransition[QUERY_PARAMS_SYMBOL], + { + includeAttributes: true, + localizeMapUpdates: false, + } + ) as RouteInfoWithAttributes[]; + return routeInfosWithAttributes[routeInfosWithAttributes.length - 1]!; + }); + } + + private generateNewState(intent: TransitionIntent): Option> { + try { + return intent.applyToState(this.state!, false); + } catch (_e) { + return null; + } + } + + private getTransitionByIntent( + intent: TransitionIntent, + isIntermediate: boolean + ): InternalTransition { + let wasTransitioning = Boolean(this.activeTransition); + let oldState = wasTransitioning ? this.activeTransition![STATE_SYMBOL] : this.state; + let newTransition: InternalTransition; + + let newState = intent.applyToState(oldState!, isIntermediate); + let queryParamChangelist = getChangelist(oldState!.queryParams, newState.queryParams); + + if (routeInfosEqual(newState.routeInfos, oldState!.routeInfos)) { + // This is a no-op transition. See if query params changed. + if (queryParamChangelist) { + let newTransition = this.queryParamsTransition( + queryParamChangelist, + wasTransitioning, + oldState!, + newState + ); + newTransition.queryParamsOnly = true; + // SAFETY: The returned OpaqueTransition should actually be this. + return newTransition as InternalTransition; + } + + // No-op. No need to create a new transition. + return this.activeTransition || new InternalTransition(this, undefined, undefined); + } + + if (isIntermediate) { + let transition = new InternalTransition(this, undefined, newState); + transition.isIntermediate = true; + this.toReadOnlyInfos(transition, newState); + this.setupContexts(newState, transition); + + this.routeWillChange(transition); + return this.activeTransition!; + } + + // Create a new transition to the destination route. + newTransition = new InternalTransition( + this, + intent, + newState, + undefined, + this.activeTransition + ); + + // transition is to same route with same params, only query params differ. + // not caught above probably because refresh() has been used + if (routeInfosSameExceptQueryParams(newState.routeInfos, oldState!.routeInfos)) { + newTransition.queryParamsOnly = true; + } + + this.toReadOnlyInfos(newTransition, newState); + // Abort and usurp any previously active transition. + if (this.activeTransition) { + this.activeTransition.redirect(newTransition); + } + this.activeTransition = newTransition; + + // Transition promises by default resolve with resolved state. + // For our purposes, swap out the promise to resolve + // after the transition has been finalized. + newTransition.promise = newTransition.promise!.then( + (result: TransitionState) => { + return this.finalizeTransition(newTransition, result); + }, + null, + promiseLabel('Settle transition promise when transition is finalized') + ); + + if (!wasTransitioning) { + this.notifyExistingHandlers(newState, newTransition); + } + + this.fireQueryParamDidChange(newState, queryParamChangelist!); + + return newTransition; + } + + /** + @private + + Begins and returns a Transition based on the provided + arguments. Accepts arguments in the form of both URL + transitions and named transitions. + + @param {Router} router + @param {Array[Object]} args arguments passed to transitionTo, + replaceWith, or handleURL +*/ + private doTransition( + name?: string, + modelsArray: [...ModelFor[]] | [...ModelFor[], { queryParams: QueryParams }] = [], + isIntermediate = false + ): InternalTransition { + let lastArg = modelsArray[modelsArray.length - 1]; + let queryParams: Dict = {}; + + if (lastArg && Object.prototype.hasOwnProperty.call(lastArg, 'queryParams')) { + // We just checked this. + // TODO: Use an assertion? + queryParams = (modelsArray.pop() as { queryParams: QueryParams }) + .queryParams as Dict; + } + + let intent; + if (name === undefined) { + log(this, 'Updating query params'); + + // A query param update is really just a transition + // into the route you're already on. + let { routeInfos } = this.state!; + intent = new NamedTransitionIntent( + this, + routeInfos[routeInfos.length - 1]!.name, + undefined, + [], + queryParams + ); + } else if (name.charAt(0) === '/') { + log(this, 'Attempting URL transition to ' + name); + intent = new URLTransitionIntent(this, name); + } else { + log(this, 'Attempting transition to ' + name); + intent = new NamedTransitionIntent( + this, + name, + undefined, + // SAFETY: We know this to be the case since we removed the last item if it was QPs + modelsArray as ModelFor[], + queryParams + ); + } + + return this.transitionByIntent(intent, isIntermediate); + } + + /** + @private + + Updates the URL (if necessary) and calls `setupContexts` + to update the router's array of `currentRouteInfos`. + */ + private finalizeTransition( + transition: InternalTransition, + newState: TransitionState + ): R | Promise { + try { + log( + transition.router, + transition.sequence, + 'Resolved all models on destination route; finalizing transition.' + ); + + let routeInfos = newState.routeInfos; + + // Run all the necessary enter/setup/exit hooks + this.setupContexts(newState, transition); + + // Check if a redirect occurred in enter/setup + if (transition.isAborted) { + // TODO: cleaner way? distinguish b/w targetRouteInfos? + this.state!.routeInfos = this.currentRouteInfos!; + return Promise.reject(logAbort(transition)); + } + + this._updateURL(transition, newState); + + transition.isActive = false; + this.activeTransition = undefined; + + this.triggerEvent(this.currentRouteInfos!, true, 'didTransition', []); + this.didTransition(this.currentRouteInfos!); + this.toInfos(transition, newState.routeInfos, true); + this.routeDidChange(transition); + + log(this, transition.sequence, 'TRANSITION COMPLETE.'); + + // Resolve with the final route. + return routeInfos[routeInfos.length - 1]!.route!; + } catch (e) { + if (!isTransitionAborted(e)) { + let infos = transition[STATE_SYMBOL]!.routeInfos; + transition.trigger(true, 'error', e, transition, infos[infos.length - 1]!.route); + transition.abort(); + } + + throw e; + } + } + + /** + @private + + Takes an Array of `RouteInfo`s, figures out which ones are + exiting, entering, or changing contexts, and calls the + proper route hooks. + + For example, consider the following tree of routes. Each route is + followed by the URL segment it handles. + + ``` + |~index ("/") + | |~posts ("/posts") + | | |-showPost ("/:id") + | | |-newPost ("/new") + | | |-editPost ("/edit") + | |~about ("/about/:id") + ``` + + Consider the following transitions: + + 1. A URL transition to `/posts/1`. + 1. Triggers the `*model` callbacks on the + `index`, `posts`, and `showPost` routes + 2. Triggers the `enter` callback on the same + 3. Triggers the `setup` callback on the same + 2. A direct transition to `newPost` + 1. Triggers the `exit` callback on `showPost` + 2. Triggers the `enter` callback on `newPost` + 3. Triggers the `setup` callback on `newPost` + 3. A direct transition to `about` with a specified + context object + 1. Triggers the `exit` callback on `newPost` + and `posts` + 2. Triggers the `serialize` callback on `about` + 3. Triggers the `enter` callback on `about` + 4. Triggers the `setup` callback on `about` + + @param {Router} transition + @param {TransitionState} newState +*/ + private setupContexts(newState: TransitionState, transition?: InternalTransition) { + let partition = this.partitionRoutes(this.state!, newState); + let i, l, route; + + for (i = 0, l = partition.exited.length; i < l; i++) { + route = partition.exited[i]!.route; + delete route!.context; + + if (route !== undefined) { + if (route._internalReset !== undefined) { + route._internalReset(true, transition); + } + + if (route.exit !== undefined) { + route.exit(transition); + } + } + } + + let oldState = (this.oldState = this.state); + this.state = newState; + let currentRouteInfos = (this.currentRouteInfos = partition.unchanged.slice()); + + try { + for (i = 0, l = partition.reset.length; i < l; i++) { + route = partition.reset[i]!.route; + if (route !== undefined) { + if (route._internalReset !== undefined) { + route._internalReset(false, transition); + } + } + } + + for (i = 0, l = partition.updatedContext.length; i < l; i++) { + this.routeEnteredOrUpdated( + currentRouteInfos, + partition.updatedContext[i]!, + false, + transition! + ); + } + + for (i = 0, l = partition.entered.length; i < l; i++) { + this.routeEnteredOrUpdated(currentRouteInfos, partition.entered[i]!, true, transition!); + } + } catch (e) { + this.state = oldState; + this.currentRouteInfos = oldState!.routeInfos; + throw e; + } + + this.state.queryParams = this.finalizeQueryParamChange( + currentRouteInfos, + newState.queryParams, + transition! + ); + } + + /** + @private + + Fires queryParamsDidChange event +*/ + private fireQueryParamDidChange(newState: TransitionState, queryParamChangelist: ChangeList) { + // If queryParams changed trigger event + if (queryParamChangelist) { + // This is a little hacky but we need some way of storing + // changed query params given that no activeTransition + // is guaranteed to have occurred. + this._changedQueryParams = queryParamChangelist.all; + this.triggerEvent(newState.routeInfos, true, 'queryParamsDidChange', [ + queryParamChangelist.changed, + queryParamChangelist.all, + queryParamChangelist.removed, + ]); + this._changedQueryParams = undefined; + } + } + + /** + @private + + Helper method used by setupContexts. Handles errors or redirects + that may happen in enter/setup. +*/ + private routeEnteredOrUpdated( + currentRouteInfos: InternalRouteInfo[], + routeInfo: InternalRouteInfo, + enter: boolean, + transition?: InternalTransition + ) { + let route = routeInfo.route, + context = routeInfo.context; + + function _routeEnteredOrUpdated(route: R) { + if (enter) { + if (route.enter !== undefined) { + route.enter(transition!); + } + } + + throwIfAborted(transition); + + route.context = context as Awaited; + + if (route.contextDidChange !== undefined) { + route.contextDidChange(); + } + + if (route.setup !== undefined) { + route.setup(context!, transition!); + } + + throwIfAborted(transition); + + currentRouteInfos.push(routeInfo); + return route; + } + + // If the route doesn't exist, it means we haven't resolved the route promise yet + if (route === undefined) { + routeInfo.routePromise = routeInfo.routePromise.then(_routeEnteredOrUpdated); + } else { + _routeEnteredOrUpdated(route); + } + + return true; + } + + /** + @private + + This function is called when transitioning from one URL to + another to determine which routes are no longer active, + which routes are newly active, and which routes remain + active but have their context changed. + + Take a list of old routes and new routes and partition + them into four buckets: + + * unchanged: the route was active in both the old and + new URL, and its context remains the same + * updated context: the route was active in both the + old and new URL, but its context changed. The route's + `setup` method, if any, will be called with the new + context. + * exited: the route was active in the old URL, but is + no longer active. + * entered: the route was not active in the old URL, but + is now active. + + The PartitionedRoutes structure has four fields: + + * `updatedContext`: a list of `RouteInfo` objects that + represent routes that remain active but have a changed + context + * `entered`: a list of `RouteInfo` objects that represent + routes that are newly active + * `exited`: a list of `RouteInfo` objects that are no + longer active. + * `unchanged`: a list of `RouteInfo` objects that remain active. + + @param {Array[InternalRouteInfo]} oldRoutes a list of the route + information for the previous URL (or `[]` if this is the + first handled transition) + @param {Array[InternalRouteInfo]} newRoutes a list of the route + information for the new URL + + @return {Partition} +*/ + private partitionRoutes(oldState: TransitionState, newState: TransitionState) { + let oldRouteInfos = oldState.routeInfos; + let newRouteInfos = newState.routeInfos; + + let routes: RoutePartition = { + updatedContext: [], + exited: [], + entered: [], + unchanged: [], + reset: [], + }; + + let routeChanged, + contextChanged = false, + i, + l; + + for (i = 0, l = newRouteInfos.length; i < l; i++) { + let oldRouteInfo = oldRouteInfos[i]!, + newRouteInfo = newRouteInfos[i]!; + + if (!oldRouteInfo || oldRouteInfo.route !== newRouteInfo.route) { + routeChanged = true; + } + + if (routeChanged) { + routes.entered.push(newRouteInfo); + if (oldRouteInfo) { + routes.exited.unshift(oldRouteInfo); + } + } else if (contextChanged || oldRouteInfo.context !== newRouteInfo.context) { + contextChanged = true; + routes.updatedContext.push(newRouteInfo); + } else { + routes.unchanged.push(oldRouteInfo); + } + } + + for (i = newRouteInfos.length, l = oldRouteInfos.length; i < l; i++) { + routes.exited.unshift(oldRouteInfos[i]!); + } + + routes.reset = routes.updatedContext.slice(); + routes.reset.reverse(); + + return routes; + } + + private _updateURL(transition: OpaqueTransition, state: TransitionState) { + let urlMethod: string | null = transition.urlMethod; + + if (!urlMethod) { + return; + } + + let { routeInfos } = state; + let { name: routeName } = routeInfos[routeInfos.length - 1]!; + let params: Dict = {}; + + for (let i = routeInfos.length - 1; i >= 0; --i) { + let routeInfo = routeInfos[i]!; + merge(params, routeInfo.params); + if (routeInfo.route!.inaccessibleByURL) { + urlMethod = null; + } + } + + if (urlMethod) { + params['queryParams'] = transition._visibleQueryParams || state.queryParams; + let url = this.recognizer.generate(routeName, params as Params); + + // transitions during the initial transition must always use replaceURL. + // When the app boots, you are at a url, e.g. /foo. If some route + // redirects to bar as part of the initial transition, you don't want to + // add a history entry for /foo. If you do, pressing back will immediately + // hit the redirect again and take you back to /bar, thus killing the back + // button + let initial = transition.isCausedByInitialTransition; + + // say you are at / and you click a link to route /foo. In /foo's + // route, the transition is aborted using replaceWith('/bar'). + // Because the current url is still /, the history entry for / is + // removed from the history. Clicking back will take you to the page + // you were on before /, which is often not even the app, thus killing + // the back button. That's why updateURL is always correct for an + // aborting transition that's not the initial transition + let replaceAndNotAborting = + urlMethod === 'replace' && !transition.isCausedByAbortingTransition; + + // because calling refresh causes an aborted transition, this needs to be + // special cased - if the initial transition is a replace transition, the + // urlMethod should be honored here. + let isQueryParamsRefreshTransition = transition.queryParamsOnly && urlMethod === 'replace'; + + // say you are at / and you a `replaceWith(/foo)` is called. Then, that + // transition is aborted with `replaceWith(/bar)`. At the end, we should + // end up with /bar replacing /. We are replacing the replace. We only + // will replace the initial route if all subsequent aborts are also + // replaces. However, there is some ambiguity around the correct behavior + // here. + let replacingReplace = + urlMethod === 'replace' && transition.isCausedByAbortingReplaceTransition; + + if (initial || replaceAndNotAborting || isQueryParamsRefreshTransition || replacingReplace) { + this.replaceURL!(url); + } else { + this.updateURL(url); + } + } + } + + private finalizeQueryParamChange( + resolvedHandlers: InternalRouteInfo[], + newQueryParams: Dict, + transition: OpaqueTransition + ) { + // We fire a finalizeQueryParamChange event which + // gives the new route hierarchy a chance to tell + // us which query params it's consuming and what + // their final values are. If a query param is + // no longer consumed in the final route hierarchy, + // its serialized segment will be removed + // from the URL. + + for (let k in newQueryParams) { + if (newQueryParams.hasOwnProperty(k) && newQueryParams[k] === null) { + delete newQueryParams[k]; + } + } + + let finalQueryParamsArray: { + key: string; + value: string; + visible: boolean; + }[] = []; + + this.triggerEvent(resolvedHandlers, true, 'finalizeQueryParamChange', [ + newQueryParams, + finalQueryParamsArray, + transition, + ]); + + if (transition) { + transition._visibleQueryParams = {}; + } + + let finalQueryParams: Dict = {}; + for (let i = 0, len = finalQueryParamsArray.length; i < len; ++i) { + let qp = finalQueryParamsArray[i]!; + finalQueryParams[qp.key] = qp.value; + if (transition && qp.visible !== false) { + transition._visibleQueryParams[qp.key] = qp.value; + } + } + return finalQueryParams; + } + + private toReadOnlyInfos(newTransition: OpaqueTransition, newState: TransitionState) { + let oldRouteInfos = this.state!.routeInfos; + this.fromInfos(newTransition, oldRouteInfos); + this.toInfos(newTransition, newState.routeInfos); + this._lastQueryParams = newState.queryParams; + } + + private fromInfos(newTransition: OpaqueTransition, oldRouteInfos: InternalRouteInfo[]) { + if (newTransition !== undefined && oldRouteInfos.length > 0) { + let fromInfos = toReadOnlyRouteInfo(oldRouteInfos, Object.assign({}, this._lastQueryParams), { + includeAttributes: true, + localizeMapUpdates: false, + }) as RouteInfoWithAttributes[]; + newTransition!.from = fromInfos[fromInfos.length - 1] || null; + } + } + + public toInfos( + newTransition: OpaqueTransition, + newRouteInfos: InternalRouteInfo[], + includeAttributes = false + ) { + if (newTransition !== undefined && newRouteInfos.length > 0) { + let toInfos = toReadOnlyRouteInfo( + newRouteInfos, + Object.assign({}, newTransition[QUERY_PARAMS_SYMBOL]), + { includeAttributes, localizeMapUpdates: false } + ); + newTransition!.to = toInfos[toInfos.length - 1]! || null; + } + } + + private notifyExistingHandlers( + newState: TransitionState, + newTransition: InternalTransition + ) { + let oldRouteInfos = this.state!.routeInfos, + changing = [], + i, + oldRouteInfoLen, + oldHandler, + newRouteInfo; + + oldRouteInfoLen = oldRouteInfos.length; + for (i = 0; i < oldRouteInfoLen; i++) { + oldHandler = oldRouteInfos[i]!; + newRouteInfo = newState.routeInfos[i]; + + if (!newRouteInfo || oldHandler.name !== newRouteInfo.name) { + break; + } + + if (!newRouteInfo.isResolved) { + changing.push(oldHandler); + } + } + + this.triggerEvent(oldRouteInfos, true, 'willTransition', [newTransition]); + this.routeWillChange(newTransition); + this.willTransition(oldRouteInfos, newState.routeInfos, newTransition); + } + + /** + Clears the current and target route routes and triggers exit + on each of them starting at the leaf and traversing up through + its ancestors. + */ + reset() { + if (this.state) { + forEach>(this.state.routeInfos.slice().reverse(), function (routeInfo) { + let route = routeInfo.route; + if (route !== undefined) { + if (route.exit !== undefined) { + route.exit(); + } + } + return true; + }); + } + + this.oldState = undefined; + this.state = new TransitionState(); + this.currentRouteInfos = undefined; + } + + /** + let handler = routeInfo.handler; + The entry point for handling a change to the URL (usually + via the back and forward button). + + Returns an Array of handlers and the parameters associated + with those parameters. + + @param {String} url a URL to process + + @return {Array} an Array of `[handler, parameter]` tuples + */ + handleURL(url: string) { + // Perform a URL-based transition, but don't change + // the URL afterward, since it already happened. + if (url.charAt(0) !== '/') { + url = '/' + url; + } + + return this.doTransition(url)!.method(null); + } + + /** + Transition into the specified named route. + + If necessary, trigger the exit callback on any routes + that are no longer represented by the target route. + + @param {String} name the name of the route + */ + transitionTo(name: string | { queryParams: Dict }, ...contexts: any[]) { + if (typeof name === 'object') { + contexts.push(name); + return this.doTransition(undefined, contexts, false); + } + + return this.doTransition(name, contexts); + } + + intermediateTransitionTo(name: string, ...args: any[]) { + return this.doTransition(name, args, true); + } + + refresh(pivotRoute?: R) { + let previousTransition = this.activeTransition; + let state = previousTransition ? previousTransition[STATE_SYMBOL] : this.state; + let routeInfos = state!.routeInfos; + + if (pivotRoute === undefined) { + pivotRoute = routeInfos[0]!.route; + } + + log(this, 'Starting a refresh transition'); + let name = routeInfos[routeInfos.length - 1]!.name; + let intent = new NamedTransitionIntent( + this, + name, + pivotRoute, + [], + this._changedQueryParams || state!.queryParams + ); + + let newTransition = this.transitionByIntent(intent, false); + + // if the previous transition is a replace transition, that needs to be preserved + if (previousTransition && previousTransition.urlMethod === 'replace') { + newTransition.method(previousTransition.urlMethod); + } + + return newTransition; + } + + /** + Identical to `transitionTo` except that the current URL will be replaced + if possible. + + This method is intended primarily for use with `replaceState`. + + @param {String} name the name of the route + */ + replaceWith(name: string) { + return this.doTransition(name).method('replace'); + } + + /** + Take a named route and context objects and generate a + URL. + + @param {String} name the name of the route to generate + a URL for + @param {...Object} objects a list of objects to serialize + + @return {String} a URL + */ + generate(routeName: string, ...args: ModelsAndQueryParams>) { + let partitionedArgs = extractQueryParams(args), + suppliedParams = partitionedArgs[0], + queryParams = partitionedArgs[1]; + + // Construct a TransitionIntent with the provided params + // and apply it to the present state of the router. + let intent = new NamedTransitionIntent(this, routeName, undefined, suppliedParams); + let state = intent.applyToState(this.state!, false); + + let params: Params = {}; + for (let i = 0, len = state.routeInfos.length; i < len; ++i) { + let routeInfo = state.routeInfos[i]!; + let routeParams = routeInfo.serialize(); + merge(params, routeParams); + } + params.queryParams = queryParams; + + return this.recognizer.generate(routeName, params); + } + + applyIntent(routeName: string, contexts: ModelFor[]): TransitionState { + let intent = new NamedTransitionIntent(this, routeName, undefined, contexts); + + let state = (this.activeTransition && this.activeTransition[STATE_SYMBOL]) || this.state!; + + return intent.applyToState(state, false); + } + + isActiveIntent( + routeName: string, + contexts: ModelFor[], + queryParams?: Dict | null, + _state?: TransitionState + ) { + let state = _state || this.state!, + targetRouteInfos = state.routeInfos, + routeInfo, + len; + + if (!targetRouteInfos.length) { + return false; + } + + let targetHandler = targetRouteInfos[targetRouteInfos.length - 1]!.name; + let recognizerHandlers: ParsedHandler[] = this.recognizer.handlersFor(targetHandler); + + let index = 0; + for (len = recognizerHandlers.length; index < len; ++index) { + routeInfo = targetRouteInfos[index]!; + if (routeInfo.name === routeName) { + break; + } + } + + if (index === recognizerHandlers.length) { + // The provided route name isn't even in the route hierarchy. + return false; + } + + let testState = new TransitionState(); + testState.routeInfos = targetRouteInfos.slice(0, index + 1); + recognizerHandlers = recognizerHandlers.slice(0, index + 1); + + let intent = new NamedTransitionIntent(this, targetHandler, undefined, contexts); + + let newState = intent.applyToHandlers(testState, recognizerHandlers, targetHandler, true, true); + + let routesEqual = routeInfosEqual(newState.routeInfos, testState.routeInfos); + if (!queryParams || !routesEqual) { + return routesEqual; + } + + // Get a hash of QPs that will still be active on new route + let activeQPsOnNewHandler: Dict = {}; + merge(activeQPsOnNewHandler, queryParams); + + let activeQueryParams = state.queryParams; + for (let key in activeQueryParams) { + if (activeQueryParams.hasOwnProperty(key) && activeQPsOnNewHandler.hasOwnProperty(key)) { + activeQPsOnNewHandler[key] = activeQueryParams[key]; + } + } + + return routesEqual && !getChangelist(activeQPsOnNewHandler, queryParams); + } + + isActive(routeName: string, ...args: ModelsAndQueryParams>) { + let [contexts, queryParams] = extractQueryParams(args); + return this.isActiveIntent(routeName, contexts, queryParams); + } + + trigger(name: string, ...args: any[]) { + this.triggerEvent(this.currentRouteInfos!, false, name, args); + } +} + +function routeInfosEqual( + routeInfos: InternalRouteInfo[], + otherRouteInfos: InternalRouteInfo[] +) { + if (routeInfos.length !== otherRouteInfos.length) { + return false; + } + + for (let i = 0, len = routeInfos.length; i < len; ++i) { + // SAFETY: Just casting for comparison + if (routeInfos[i] !== (otherRouteInfos[i] as unknown as InternalRouteInfo)) { + return false; + } + } + return true; +} + +function routeInfosSameExceptQueryParams( + routeInfos: InternalRouteInfo[], + otherRouteInfos: InternalRouteInfo[] +) { + if (routeInfos.length !== otherRouteInfos.length) { + return false; + } + + for (let i = 0, len = routeInfos.length; i < len; ++i) { + if (routeInfos[i]!.name !== otherRouteInfos[i]!.name) { + return false; + } + + if (!paramsEqual(routeInfos[i]!.params, otherRouteInfos[i]!.params)) { + return false; + } + } + return true; +} + +function paramsEqual(params: Dict | undefined, otherParams: Dict | undefined) { + if (params === otherParams) { + // Both identical or both undefined + return true; + } + + if (!params || !otherParams) { + // One is falsy but other is not + return false; + } + + let keys = Object.keys(params); + let otherKeys = Object.keys(otherParams); + + if (keys.length !== otherKeys.length) { + return false; + } + + for (let i = 0, len = keys.length; i < len; ++i) { + let key = keys[i]!; + + if (params[key] !== otherParams[key]) { + return false; + } + } + + return true; +} + +export interface RoutePartition { + updatedContext: InternalRouteInfo[]; + exited: InternalRouteInfo[]; + entered: InternalRouteInfo[]; + unchanged: InternalRouteInfo[]; + reset: InternalRouteInfo[]; +} diff --git a/packages/router_js/lib/transition-aborted-error.ts b/packages/router_js/lib/transition-aborted-error.ts new file mode 100644 index 00000000000..54b0049e15c --- /dev/null +++ b/packages/router_js/lib/transition-aborted-error.ts @@ -0,0 +1,40 @@ +export interface TransitionAbortedError extends Error { + name: 'TransitionAborted'; + code: 'TRANSITION_ABORTED'; +} + +export function buildTransitionAborted() { + let error = new Error('TransitionAborted') as TransitionAbortedError; + error.name = 'TransitionAborted'; + error.code = 'TRANSITION_ABORTED'; + return error; +} + +export function isTransitionAborted(maybeError: unknown): maybeError is TransitionAbortedError { + return ( + typeof maybeError === 'object' && + maybeError !== null && + (maybeError as TransitionAbortedError).code === 'TRANSITION_ABORTED' + ); +} + +interface Abortable { + isAborted: T; + [key: string]: unknown; +} + +function isAbortable(maybeAbortable: unknown): maybeAbortable is Abortable { + return ( + typeof maybeAbortable === 'object' && + maybeAbortable !== null && + typeof (maybeAbortable as Abortable).isAborted === 'boolean' + ); +} + +export function throwIfAborted(maybe: Abortable): never; +export function throwIfAborted(maybe: unknown): void; +export function throwIfAborted(maybe: unknown | Abortable): never | void { + if (isAbortable(maybe) && maybe.isAborted) { + throw buildTransitionAborted(); + } +} diff --git a/packages/router_js/lib/transition-intent.ts b/packages/router_js/lib/transition-intent.ts new file mode 100644 index 00000000000..d3c2595fdf2 --- /dev/null +++ b/packages/router_js/lib/transition-intent.ts @@ -0,0 +1,16 @@ +import type { Route } from './route-info'; +import type Router from './router'; +import type TransitionState from './transition-state'; + +export type OpaqueIntent = TransitionIntent; + +export abstract class TransitionIntent { + data: object; + router: Router; + constructor(router: Router, data: object = {}) { + this.router = router; + this.data = data; + } + preTransitionState?: TransitionState; + abstract applyToState(oldState: TransitionState, isIntermediate: boolean): TransitionState; +} diff --git a/packages/router_js/lib/transition-intent/named-transition-intent.ts b/packages/router_js/lib/transition-intent/named-transition-intent.ts new file mode 100644 index 00000000000..c99cf319797 --- /dev/null +++ b/packages/router_js/lib/transition-intent/named-transition-intent.ts @@ -0,0 +1,257 @@ +/* eslint-disable no-prototype-builtins */ +import type { Dict } from '../core'; +import type { ModelFor, ResolvedRouteInfo, Route } from '../route-info'; +import type InternalRouteInfo from '../route-info'; +import { UnresolvedRouteInfoByObject, UnresolvedRouteInfoByParam } from '../route-info'; +import type { ParsedHandler } from '../router'; +import type Router from '../router'; +import { TransitionIntent } from '../transition-intent'; +import TransitionState from '../transition-state'; +import { isParam, merge } from '../utils'; + +export default class NamedTransitionIntent extends TransitionIntent { + name: string; + pivotHandler?: Route; + contexts: ModelFor[]; + queryParams: Dict; + preTransitionState?: TransitionState = undefined; + + constructor( + router: Router, + name: string, + pivotHandler: Route | undefined, + contexts: ModelFor[] = [], + queryParams: Dict = {}, + data?: object + ) { + super(router, data); + this.name = name; + this.pivotHandler = pivotHandler; + this.contexts = contexts; + this.queryParams = queryParams; + } + + applyToState(oldState: TransitionState, isIntermediate: boolean): TransitionState { + let handlers: ParsedHandler[] = this.router.recognizer.handlersFor(this.name); + + let targetRouteName = handlers[handlers.length - 1]!.handler; + + return this.applyToHandlers(oldState, handlers, targetRouteName, isIntermediate, false); + } + + applyToHandlers( + oldState: TransitionState, + parsedHandlers: ParsedHandler[], + targetRouteName: string, + isIntermediate: boolean, + checkingIfActive: boolean + ) { + let i, len; + let newState = new TransitionState(); + let objects = this.contexts.slice(0); + + let invalidateIndex = parsedHandlers.length; + + // Pivot handlers are provided for refresh transitions + if (this.pivotHandler) { + for (i = 0, len = parsedHandlers.length; i < len; ++i) { + if (parsedHandlers[i]!.handler === this.pivotHandler._internalName) { + invalidateIndex = i; + break; + } + } + } + + for (i = parsedHandlers.length - 1; i >= 0; --i) { + let result = parsedHandlers[i]!; + let name = result.handler; + + let oldHandlerInfo = oldState.routeInfos[i]!; + let newHandlerInfo: + | InternalRouteInfo + | UnresolvedRouteInfoByObject + | ResolvedRouteInfo + | null = null; + + if (result.names.length > 0) { + if (i >= invalidateIndex) { + newHandlerInfo = this.createParamHandlerInfo(name, result.names, objects, oldHandlerInfo); + } else { + newHandlerInfo = this.getHandlerInfoForDynamicSegment( + name, + result.names, + objects, + oldHandlerInfo, + targetRouteName, + i + ); + } + } else { + // This route has no dynamic segment. + // Therefore treat as a param-based handlerInfo + // with empty params. This will cause the `model` + // hook to be called with empty params, which is desirable. + newHandlerInfo = this.createParamHandlerInfo(name, result.names, objects, oldHandlerInfo); + } + + if (checkingIfActive) { + // If we're performing an isActive check, we want to + // serialize URL params with the provided context, but + // ignore mismatches between old and new context. + newHandlerInfo = newHandlerInfo.becomeResolved( + null, + // SAFETY: This seems to imply that it would be resolved, but it's unclear if that's actually the case. + newHandlerInfo.context as Awaited + ); + let oldContext = oldHandlerInfo && oldHandlerInfo.context; + if ( + result.names.length > 0 && + oldHandlerInfo.context !== undefined && + newHandlerInfo.context === oldContext + ) { + // If contexts match in isActive test, assume params also match. + // This allows for flexibility in not requiring that every last + // handler provide a `serialize` method + newHandlerInfo.params = oldHandlerInfo && oldHandlerInfo.params; + } + newHandlerInfo.context = oldContext as Awaited; + } + + let handlerToUse: + | InternalRouteInfo + | UnresolvedRouteInfoByObject + | ResolvedRouteInfo = oldHandlerInfo; + + if (i >= invalidateIndex || newHandlerInfo.shouldSupersede(oldHandlerInfo)) { + invalidateIndex = Math.min(i, invalidateIndex); + handlerToUse = newHandlerInfo; + } + + if (isIntermediate && !checkingIfActive) { + handlerToUse = handlerToUse.becomeResolved( + null, + // SAFETY: This seems to imply that it would be resolved, but it's unclear if that's actually the case. + handlerToUse.context as ModelFor + ); + } + + newState.routeInfos.unshift(handlerToUse); + } + + if (objects.length > 0) { + throw new Error( + 'More context objects were passed than there are dynamic segments for the route: ' + + targetRouteName + ); + } + + if (!isIntermediate) { + this.invalidateChildren(newState.routeInfos, invalidateIndex); + } + + merge(newState.queryParams, this.queryParams || {}); + if (isIntermediate && oldState.queryParams) { + merge(newState.queryParams, oldState.queryParams); + } + + return newState; + } + + invalidateChildren(handlerInfos: InternalRouteInfo[], invalidateIndex: number) { + for (let i = invalidateIndex, l = handlerInfos.length; i < l; ++i) { + let handlerInfo = handlerInfos[i]!; + if (handlerInfo.isResolved) { + let { name, params, route, paramNames } = handlerInfos[i]!; + handlerInfos[i] = new UnresolvedRouteInfoByParam( + this.router, + name, + paramNames, + params, + route + ); + } + } + } + + getHandlerInfoForDynamicSegment( + name: string, + names: string[], + objects: ModelFor[], + oldHandlerInfo: InternalRouteInfo, + _targetRouteName: string, + i: number + ): UnresolvedRouteInfoByObject { + let objectToUse: ModelFor | PromiseLike> | undefined; + if (objects.length > 0) { + // Use the objects provided for this transition. + objectToUse = objects[objects.length - 1]; + if (isParam(objectToUse)) { + return this.createParamHandlerInfo(name, names, objects, oldHandlerInfo); + } else { + objects.pop(); + } + } else if (oldHandlerInfo && oldHandlerInfo.name === name) { + // Reuse the matching oldHandlerInfo + return oldHandlerInfo; + } else { + if (this.preTransitionState) { + let preTransitionHandlerInfo = this.preTransitionState.routeInfos[i] as + | ResolvedRouteInfo + | undefined; + objectToUse = preTransitionHandlerInfo?.context; + } else { + // Ideally we should throw this error to provide maximal + // information to the user that not enough context objects + // were provided, but this proves too cumbersome in Ember + // in cases where inner template helpers are evaluated + // before parent helpers un-render, in which cases this + // error somewhat prematurely fires. + //throw new Error("Not enough context objects were provided to complete a transition to " + targetRouteName + ". Specifically, the " + name + " route needs an object that can be serialized into its dynamic URL segments [" + names.join(', ') + "]"); + return oldHandlerInfo; + } + } + + return new UnresolvedRouteInfoByObject(this.router, name, names, objectToUse); + } + + createParamHandlerInfo( + name: string, + names: string[], + objects: unknown[], + oldHandlerInfo: InternalRouteInfo + ) { + let params: Dict = {}; + + // Soak up all the provided string/numbers + let numNames = names.length; + let missingParams = []; + while (numNames--) { + // Only use old params if the names match with the new handler + let oldParams = + (oldHandlerInfo && name === oldHandlerInfo.name && oldHandlerInfo.params) || {}; + + let peek = objects[objects.length - 1]; + let paramName = names[numNames]!; + if (isParam(peek)) { + params[paramName] = String(objects.pop()); + } else { + // If we're here, this means only some of the params + // were string/number params, so try and use a param + // value from a previous handler. + if (oldParams.hasOwnProperty(paramName)) { + params[paramName] = oldParams[paramName]; + } else { + missingParams.push(paramName); + } + } + } + if (missingParams.length > 0) { + throw new Error( + `You didn't provide enough string/numeric parameters to satisfy all of the dynamic segments for route ${name}.` + + ` Missing params: ${missingParams}` + ); + } + + return new UnresolvedRouteInfoByParam(this.router, name, names, params); + } +} diff --git a/packages/router_js/lib/transition-intent/url-transition-intent.ts b/packages/router_js/lib/transition-intent/url-transition-intent.ts new file mode 100644 index 00000000000..ff5cfde36f7 --- /dev/null +++ b/packages/router_js/lib/transition-intent/url-transition-intent.ts @@ -0,0 +1,81 @@ +import type { Route } from '../route-info'; +import { UnresolvedRouteInfoByParam } from '../route-info'; +import type Router from '../router'; +import { TransitionIntent } from '../transition-intent'; +import TransitionState from '../transition-state'; +import UnrecognizedURLError from '../unrecognized-url-error'; +import { merge } from '../utils'; + +export default class URLTransitionIntent extends TransitionIntent { + preTransitionState?: TransitionState; + url: string; + constructor(router: Router, url: string, data?: object) { + super(router, data); + this.url = url; + this.preTransitionState = undefined; + } + + applyToState(oldState: TransitionState) { + let newState = new TransitionState(); + let results = this.router.recognizer.recognize(this.url), + i, + len; + + if (!results) { + throw new UnrecognizedURLError(this.url); + } + + let statesDiffer = false; + let _url = this.url; + + // Checks if a handler is accessible by URL. If it is not, an error is thrown. + // For the case where the handler is loaded asynchronously, the error will be + // thrown once it is loaded. + function checkHandlerAccessibility(handler: R) { + if (handler && handler.inaccessibleByURL) { + throw new UnrecognizedURLError(_url); + } + + return handler; + } + + for (i = 0, len = results.length; i < len; ++i) { + let result = results[i]!; + let name = result.handler as string; + let paramNames: string[] = []; + + if (this.router.recognizer.hasRoute(name)) { + paramNames = this.router.recognizer.handlersFor(name)[i].names; + } + + let newRouteInfo = new UnresolvedRouteInfoByParam( + this.router, + name, + paramNames, + result.params + ); + + let route = newRouteInfo.route; + + if (route) { + checkHandlerAccessibility(route); + } else { + // If the handler is being loaded asynchronously, check if we can + // access it after it has resolved + newRouteInfo.routePromise = newRouteInfo.routePromise.then(checkHandlerAccessibility); + } + + let oldRouteInfo = oldState.routeInfos[i]!; + if (statesDiffer || newRouteInfo.shouldSupersede(oldRouteInfo)) { + statesDiffer = true; + newState.routeInfos[i] = newRouteInfo; + } else { + newState.routeInfos[i] = oldRouteInfo; + } + } + + merge(newState.queryParams, results.queryParams); + + return newState; + } +} diff --git a/packages/router_js/lib/transition-state.ts b/packages/router_js/lib/transition-state.ts new file mode 100644 index 00000000000..e10c7c7361c --- /dev/null +++ b/packages/router_js/lib/transition-state.ts @@ -0,0 +1,130 @@ +import { Promise } from 'rsvp'; +import type { Dict } from './core'; +import type { Route, ResolvedRouteInfo } from './route-info'; +import type InternalRouteInfo from './route-info'; +import type Transition from './transition'; +import { forEach, promiseLabel } from './utils'; +import { throwIfAborted } from './transition-aborted-error'; + +interface IParams { + [key: string]: unknown; +} + +function handleError( + currentState: TransitionState, + transition: Transition, + error: Error +): never { + // This is the only possible + // reject value of TransitionState#resolve + let routeInfos = currentState.routeInfos; + let errorHandlerIndex = + transition.resolveIndex >= routeInfos.length ? routeInfos.length - 1 : transition.resolveIndex; + + let wasAborted = transition.isAborted; + + throw new TransitionError( + error, + currentState.routeInfos[errorHandlerIndex]!.route!, + wasAborted, + currentState + ); +} + +function resolveOneRouteInfo( + currentState: TransitionState, + transition: Transition +): void | Promise { + if (transition.resolveIndex === currentState.routeInfos.length) { + // This is is the only possible + // fulfill value of TransitionState#resolve + return; + } + + let routeInfo = currentState.routeInfos[transition.resolveIndex]!; + + let callback = proceed.bind(null, currentState, transition) as ( + resolvedRouteInfo: ResolvedRouteInfo + ) => void | Promise; + + return routeInfo.resolve(transition).then(callback, null, currentState.promiseLabel('Proceed')); +} + +function proceed( + currentState: TransitionState, + transition: Transition, + resolvedRouteInfo: ResolvedRouteInfo +): void | Promise { + let wasAlreadyResolved = currentState.routeInfos[transition.resolveIndex]!.isResolved; + + // Swap the previously unresolved routeInfo with + // the resolved routeInfo + currentState.routeInfos[transition.resolveIndex++] = resolvedRouteInfo; + + if (!wasAlreadyResolved) { + // Call the redirect hook. The reason we call it here + // vs. afterModel is so that redirects into child + // routes don't re-run the model hooks for this + // already-resolved route. + let { route } = resolvedRouteInfo; + if (route !== undefined) { + if (route.redirect) { + route.redirect(resolvedRouteInfo.context, transition); + } + } + } + + // Proceed after ensuring that the redirect hook + // didn't abort this transition by transitioning elsewhere. + throwIfAborted(transition); + + return resolveOneRouteInfo(currentState, transition); +} + +export default class TransitionState { + routeInfos: InternalRouteInfo[] = []; + queryParams: Dict = {}; + params: IParams = {}; + + promiseLabel(label: string) { + let targetName = ''; + forEach(this.routeInfos, function (routeInfo) { + if (targetName !== '') { + targetName += '.'; + } + targetName += routeInfo.name; + return true; + }); + return promiseLabel("'" + targetName + "': " + label); + } + + resolve(transition: Transition): Promise> { + // First, calculate params for this state. This is useful + // information to provide to the various route hooks. + let params = this.params; + forEach(this.routeInfos, (routeInfo) => { + params[routeInfo.name] = routeInfo.params || {}; + return true; + }); + + transition.resolveIndex = 0; + + let callback = resolveOneRouteInfo.bind(null, this, transition); + let errorHandler = handleError.bind(null, this, transition); + + // The prelude RSVP.resolve() async moves us into the promise land. + return Promise.resolve(null, this.promiseLabel('Start transition')) + .then(callback, null, this.promiseLabel('Resolve route')) + .catch(errorHandler, this.promiseLabel('Handle error')) + .then(() => this); + } +} + +export class TransitionError { + constructor( + public error: Error, + public route: Route, + public wasAborted: boolean, + public state: TransitionState + ) {} +} diff --git a/packages/router_js/lib/transition.ts b/packages/router_js/lib/transition.ts new file mode 100644 index 00000000000..b4c0e26634c --- /dev/null +++ b/packages/router_js/lib/transition.ts @@ -0,0 +1,465 @@ +import { Promise } from 'rsvp'; +import type { Dict, Maybe, Option } from './core'; +import type { ModelFor, Route, RouteInfo, RouteInfoWithAttributes } from './route-info'; +import type InternalRouteInfo from './route-info'; +import type Router from './router'; +import type { TransitionAbortedError } from './transition-aborted-error'; +import { buildTransitionAborted } from './transition-aborted-error'; +import type { OpaqueIntent } from './transition-intent'; +import type { TransitionError } from './transition-state'; +import type TransitionState from './transition-state'; +import { log, promiseLabel } from './utils'; +import { DEBUG } from '@glimmer/env'; + +export type OnFulfilled = + | ((value: T) => TResult1 | PromiseLike) + | undefined + | null; +export type OnRejected = + | ((reason: T) => TResult2 | PromiseLike) + | undefined + | null; + +export type PublicTransition = Transition; +export type OpaqueTransition = PublicTransition; + +export const STATE_SYMBOL = `__STATE__-2619860001345920-3322w3`; +export const PARAMS_SYMBOL = `__PARAMS__-261986232992830203-23323`; +export const QUERY_PARAMS_SYMBOL = `__QPS__-2619863929824844-32323`; +export const REDIRECT_DESTINATION_SYMBOL = `__RDS__-2619863929824844-32323`; + +/** + A Transition is a thenable (a promise-like object) that represents + an attempt to transition to another route. It can be aborted, either + explicitly via `abort` or by attempting another transition while a + previous one is still underway. An aborted transition can also + be `retry()`d later. + + @class Transition + @constructor + @param {Object} router + @param {Object} intent + @param {Object} state + @param {Object} error + @private + */ +export default class Transition implements Partial> { + [STATE_SYMBOL]: TransitionState; + from: Maybe = null; + to?: RouteInfo | RouteInfoWithAttributes = undefined; + router: Router; + data: Dict; + intent: Maybe; + resolvedModels: Dict | undefined>; + [QUERY_PARAMS_SYMBOL]: Dict; + promise?: Promise; // Todo: Fix this shit its actually TransitionState | IHandler | undefined | Error + error: Maybe; + [PARAMS_SYMBOL]: Dict; + routeInfos: InternalRouteInfo[]; + targetName: Maybe; + pivotHandler: Maybe; + sequence: number; + isAborted = false; + isActive = true; + urlMethod: Option = 'update'; + resolveIndex = 0; + queryParamsOnly = false; + isTransition = true; + isCausedByAbortingTransition = false; + isCausedByInitialTransition = false; + isCausedByAbortingReplaceTransition = false; + _visibleQueryParams: Dict = {}; + isIntermediate = false; + [REDIRECT_DESTINATION_SYMBOL]?: Transition; + + /** + In non-production builds, this function will return the stack that this Transition was + created within. In production builds, this function will not be present. + + @method debugCreationStack + @return string + */ + declare debugCreationStack?: () => string | undefined; + + /** + In non-production builds, this function will return the stack that this Transition was + aborted within (or `undefined` if the Transition has not been aborted yet). In production + builds, this function will not be present. + + @method debugAbortStack + @return string + */ + declare debugAbortStack?: () => string | undefined; + + /** + In non-production builds, this property references the Transition that _this_ Transition + was derived from or `undefined` if this transition did not derive from another. In + production builds, this property will not be present. + + @property debugPreviousTransition + @type {Transition | undefined} + */ + declare debugPreviousTransition: Maybe>; + + constructor( + router: Router, + intent: Maybe, + state: TransitionState | undefined, + error: Maybe = undefined, + previousTransition: Maybe> = undefined + ) { + this[STATE_SYMBOL] = state! || router.state!; + this.intent = intent; + this.router = router; + this.data = (intent && intent.data) || {}; + this.resolvedModels = {}; + this[QUERY_PARAMS_SYMBOL] = {}; + this.promise = undefined; + this.error = undefined; + this[PARAMS_SYMBOL] = {}; + this.routeInfos = []; + this.targetName = undefined; + this.pivotHandler = undefined; + this.sequence = -1; + + if (DEBUG) { + let error = new Error(`Transition creation stack`); + + this.debugCreationStack = () => error.stack; + + // not aborted yet, will be replaced when `this.isAborted` is set + this.debugAbortStack = () => undefined; + + this.debugPreviousTransition = previousTransition; + } + + if (error) { + this.promise = Promise.reject(error); + this.error = error; + return; + } + + // if you're doing multiple redirects, need the new transition to know if it + // is actually part of the first transition or not. Any further redirects + // in the initial transition also need to know if they are part of the + // initial transition + this.isCausedByAbortingTransition = Boolean(previousTransition); + this.isCausedByInitialTransition = + Boolean(previousTransition) && + (previousTransition!.isCausedByInitialTransition || previousTransition!.sequence === 0); + // Every transition in the chain is a replace + this.isCausedByAbortingReplaceTransition = + Boolean(previousTransition) && + previousTransition!.urlMethod === 'replace' && + (!previousTransition!.isCausedByAbortingTransition || + previousTransition!.isCausedByAbortingReplaceTransition); + + if (state) { + this[PARAMS_SYMBOL] = state.params; + this[QUERY_PARAMS_SYMBOL] = state.queryParams; + this.routeInfos = state.routeInfos; + + let len = state.routeInfos.length; + if (len) { + this.targetName = state.routeInfos[len - 1]!.name; + } + + for (let i = 0; i < len; ++i) { + let handlerInfo = state.routeInfos[i]!; + + // TODO: this all seems hacky + if (!handlerInfo.isResolved) { + break; + } + this.pivotHandler = handlerInfo.route; + } + + this.sequence = router.currentSequence++; + this.promise = state.resolve(this).catch((result: TransitionError) => { + let error = this.router.transitionDidError(result, this); + + throw error; + }, promiseLabel('Handle Abort')); + } else { + this.promise = Promise.resolve(this[STATE_SYMBOL]!); + this[PARAMS_SYMBOL] = {}; + } + } + + /** + The Transition's internal promise. Calling `.then` on this property + is that same as calling `.then` on the Transition object itself, but + this property is exposed for when you want to pass around a + Transition's promise, but not the Transition object itself, since + Transition object can be externally `abort`ed, while the promise + cannot. + + @property promise + @type {Object} + @public + */ + + /** + Custom state can be stored on a Transition's `data` object. + This can be useful for decorating a Transition within an earlier + hook and shared with a later hook. Properties set on `data` will + be copied to new transitions generated by calling `retry` on this + transition. + + @property data + @type {Object} + @public + */ + + /** + A standard promise hook that resolves if the transition + succeeds and rejects if it fails/redirects/aborts. + + Forwards to the internal `promise` property which you can + use in situations where you want to pass around a thenable, + but not the Transition itself. + + @method then + @param {Function} onFulfilled + @param {Function} onRejected + @param {String} label optional string for labeling the promise. + Useful for tooling. + @return {Promise} + @public + */ + then( + onFulfilled?: ((value: R) => TResult1 | PromiseLike) | undefined | null, + onRejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null, + label?: string + ): Promise { + return this.promise!.then(onFulfilled, onRejected, label); + } + + /** + + Forwards to the internal `promise` property which you can + use in situations where you want to pass around a thennable, + but not the Transition itself. + + @method catch + @param {Function} onRejection + @param {String} label optional string for labeling the promise. + Useful for tooling. + @return {Promise} + @public + */ + catch(onRejection?: OnRejected, T>, label?: string) { + return this.promise!.catch(onRejection, label); + } + + /** + + Forwards to the internal `promise` property which you can + use in situations where you want to pass around a thenable, + but not the Transition itself. + + @method finally + @param {Function} callback + @param {String} label optional string for labeling the promise. + Useful for tooling. + @return {Promise} + @public + */ + finally(callback?: T | undefined, label?: string) { + // @ts-expect-error @types/rsvp doesn't have the correct signiture for RSVP.Promise.finally + return this.promise!.finally(callback, label); + } + + /** + Aborts the Transition. Note you can also implicitly abort a transition + by initiating another transition while a previous one is underway. + + @method abort + @return {Transition} this transition + @public + */ + abort() { + this.rollback(); + let transition = new Transition(this.router, undefined, undefined, undefined); + transition.to = this.from as RouteInfoWithAttributes; + transition.from = this.from; + transition.isAborted = true; + this.router.routeWillChange(transition); + this.router.routeDidChange(transition); + return this; + } + + rollback() { + if (!this.isAborted) { + log(this.router, this.sequence, this.targetName + ': transition was aborted'); + + if (DEBUG) { + let error = new Error(`Transition aborted stack`); + + this.debugAbortStack = () => error.stack; + } + + if (this.intent !== undefined && this.intent !== null) { + this.intent.preTransitionState = this.router.state; + } + + this.isAborted = true; + this.isActive = false; + this.router.activeTransition = undefined; + } + } + + redirect(newTransition: Transition) { + this[REDIRECT_DESTINATION_SYMBOL] = newTransition; + this.rollback(); + this.router.routeWillChange(newTransition); + } + + /** + + Retries a previously-aborted transition (making sure to abort the + transition if it's still active). Returns a new transition that + represents the new attempt to transition. + + @method retry + @return {Transition} new transition + @public + */ + retry() { + // TODO: add tests for merged state retry()s + this.abort(); + let newTransition = this.router.transitionByIntent(this.intent as OpaqueIntent, false); + + // inheriting a `null` urlMethod is not valid + // the urlMethod is only set to `null` when + // the transition is initiated *after* the url + // has been updated (i.e. `router.handleURL`) + // + // in that scenario, the url method cannot be + // inherited for a new transition because then + // the url would not update even though it should + if (this.urlMethod !== null) { + newTransition.method(this.urlMethod); + } + return newTransition; + } + + /** + + Sets the URL-changing method to be employed at the end of a + successful transition. By default, a new Transition will just + use `updateURL`, but passing 'replace' to this method will + cause the URL to update using 'replaceWith' instead. Omitting + a parameter will disable the URL change, allowing for transitions + that don't update the URL at completion (this is also used for + handleURL, since the URL has already changed before the + transition took place). + + @method method + @param {String} method the type of URL-changing method to use + at the end of a transition. Accepted values are 'replace', + falsy values, or any other non-falsy value (which is + interpreted as an updateURL transition). + + @return {Transition} this transition + @public + */ + method(method: Option) { + this.urlMethod = method; + return this; + } + + // Alias 'trigger' as 'send' + send( + ignoreFailure = false, + _name: string, + err?: Error, + transition?: Transition, + handler?: Route + ) { + this.trigger(ignoreFailure, _name, err, transition, handler); + } + + /** + + Fires an event on the current list of resolved/resolving + handlers within this transition. Useful for firing events + on route hierarchies that haven't fully been entered yet. + + Note: This method is also aliased as `send` + + @method trigger + @param {Boolean} [ignoreFailure=false] a boolean specifying whether unhandled events throw an error + @param {String} name the name of the event to fire + @public + */ + trigger(ignoreFailure = false, name: string, ...args: any[]) { + // TODO: Deprecate the current signature + if (typeof ignoreFailure === 'string') { + name = ignoreFailure; + ignoreFailure = false; + } + + this.router.triggerEvent( + this[STATE_SYMBOL]!.routeInfos.slice(0, this.resolveIndex + 1), + ignoreFailure, + name, + args + ); + } + + /** + Transitions are aborted and their promises rejected + when redirects occur; this method returns a promise + that will follow any redirects that occur and fulfill + with the value fulfilled by any redirecting transitions + that occur. + + @method followRedirects + @return {Promise} a promise that fulfills with the same + value that the final redirecting transition fulfills with + @public + */ + followRedirects(): Promise { + return this.promise!.catch((reason) => { + if (this[REDIRECT_DESTINATION_SYMBOL]) { + return this[REDIRECT_DESTINATION_SYMBOL]!.followRedirects(); + } + return Promise.reject(reason); + }); + } + + toString() { + return 'Transition (sequence ' + this.sequence + ')'; + } + + /** + @private + */ + log(message: string) { + log(this.router, this.sequence, message); + } +} + +/** + @private + + Logs and returns an instance of TransitionAborted. + */ +export function logAbort(transition: Transition): TransitionAbortedError { + log(transition.router, transition.sequence, 'detected abort.'); + + return buildTransitionAborted(); +} + +export function isTransition(obj: unknown): obj is typeof Transition { + return typeof obj === 'object' && obj instanceof Transition && obj.isTransition; +} + +export function prepareResult(obj: Dict | undefined) { + if (isTransition(obj)) { + return null; + } + + return obj; +} diff --git a/packages/router_js/lib/unrecognized-url-error.ts b/packages/router_js/lib/unrecognized-url-error.ts new file mode 100644 index 00000000000..b64b6514fd5 --- /dev/null +++ b/packages/router_js/lib/unrecognized-url-error.ts @@ -0,0 +1,31 @@ +export interface UnrecognizedURLConstructor { + new (message?: string): UnrecognizedURLError; + readonly prototype: UnrecognizedURLError; +} + +export interface UnrecognizedURLError extends Error { + constructor: UnrecognizedURLConstructor; +} + +const UnrecognizedURLError: UnrecognizedURLConstructor = (function () { + UnrecognizedURLError.prototype = Object.create(Error.prototype); + UnrecognizedURLError.prototype.constructor = UnrecognizedURLError; + + function UnrecognizedURLError(this: UnrecognizedURLError, message?: string) { + let error = Error.call(this, message); + this.name = 'UnrecognizedURLError'; + this.message = message || 'UnrecognizedURL'; + + // @ts-expect-error I don't know why this is failing + if (Error.captureStackTrace) { + // @ts-expect-error I don't know why this is failing + Error.captureStackTrace(this, UnrecognizedURLError); + } else { + this.stack = error.stack; + } + } + + return UnrecognizedURLError as any; +})(); + +export default UnrecognizedURLError; diff --git a/packages/router_js/lib/utils.ts b/packages/router_js/lib/utils.ts new file mode 100644 index 00000000000..38912f6c240 --- /dev/null +++ b/packages/router_js/lib/utils.ts @@ -0,0 +1,177 @@ +import type { QueryParams } from 'route-recognizer'; +import type { Promise } from 'rsvp'; +import type { Dict } from './core'; +import type Router from './router'; + +export const slice = Array.prototype.slice; +const hasOwnProperty = Object.prototype.hasOwnProperty; + +/** + Determines if an object is Promise by checking if it is "thenable". +**/ +export function isPromise(p: any): p is Promise { + return p !== null && typeof p === 'object' && typeof p.then === 'function'; +} + +export function merge(hash: Dict, other?: Dict) { + for (let prop in other) { + if (hasOwnProperty.call(other, prop)) { + hash[prop] = other[prop]; + } + } +} + +export type ModelsAndQueryParams = T[] | [...T[], QueryParamsContainer]; + +/** + @private + + Extracts query params from the end of an array +**/ +export function extractQueryParams(array: ModelsAndQueryParams): [T[], QueryParams | null] { + let len = array && array.length, + head, + queryParams; + + if (len && len > 0) { + let obj = array[len - 1]; + if (isQueryParamsContainer(obj)) { + queryParams = obj.queryParams; + head = slice.call(array, 0, len - 1); + return [head, queryParams]; + } + } + + // SAFETY: We confirmed that the last item isn't a QP container + return [array as T[], null]; +} + +export type QueryParamsContainer = { queryParams: QueryParams }; + +// TODO: Actually check that Dict is QueryParams +function isQueryParamsContainer(obj: unknown): obj is QueryParamsContainer { + if (obj && typeof obj === 'object') { + let cast = obj as QueryParamsContainer; + return ( + 'queryParams' in cast && Object.keys(cast.queryParams).every((k) => typeof k === 'string') + ); + } + return false; +} + +/** + @private + + Coerces query param properties and array elements into strings. +**/ +export function coerceQueryParamsToString(queryParams: Dict) { + for (let key in queryParams) { + let val = queryParams[key]; + if (typeof val === 'number') { + queryParams[key] = String(val); + } else if (Array.isArray(val)) { + for (let i = 0, l = val.length; i < l; i++) { + val[i] = String(val[i]); + } + } + } +} +/** + @private + */ +export function log(router: Router, ...args: (string | number)[]): void { + if (!router.log) { + return; + } + + if (args.length === 2) { + let [sequence, msg] = args; + router.log('Transition #' + sequence + ': ' + msg); + } else { + let [msg] = args; + router.log(msg as string); + } +} + +export function isParam(object: any): object is string | number { + return ( + typeof object === 'string' || + object instanceof String || + typeof object === 'number' || + object instanceof Number + ); +} + +export function forEach(array: T[], callback: (item: T) => boolean) { + for (let i = 0, l = array.length; i < l && callback(array[i]!) !== false; i++) { + // empty intentionally + } +} + +export interface ChangeList { + all: Dict; + changed: Dict; + removed: Dict; +} + +export function getChangelist( + oldObject: Dict, + newObject: Dict +): ChangeList | undefined { + let key; + let results: ChangeList = { + all: {}, + changed: {}, + removed: {}, + }; + + merge(results.all, newObject); + + let didChange = false; + coerceQueryParamsToString(oldObject); + coerceQueryParamsToString(newObject); + + // Calculate removals + for (key in oldObject) { + if (hasOwnProperty.call(oldObject, key)) { + if (!hasOwnProperty.call(newObject, key)) { + didChange = true; + results.removed[key] = oldObject[key]; + } + } + } + + // Calculate changes + for (key in newObject) { + if (hasOwnProperty.call(newObject, key)) { + let oldElement = oldObject[key]; + let newElement = newObject[key]; + if (isArray(oldElement) && isArray(newElement)) { + if (oldElement.length !== newElement.length) { + results.changed[key] = newObject[key]; + didChange = true; + } else { + for (let i = 0, l = oldElement.length; i < l; i++) { + if (oldElement[i] !== newElement[i]) { + results.changed[key] = newObject[key]; + didChange = true; + } + } + } + } else if (oldObject[key] !== newObject[key]) { + results.changed[key] = newObject[key]; + didChange = true; + } + } + } + + return didChange ? results : undefined; +} + +function isArray(obj: unknown): obj is ArrayLike { + return Array.isArray(obj); +} + +export function promiseLabel(label: string) { + return 'Router: ' + label; +} diff --git a/packages/router_js/package.json b/packages/router_js/package.json new file mode 100644 index 00000000000..68628f0ac24 --- /dev/null +++ b/packages/router_js/package.json @@ -0,0 +1,33 @@ +{ + "name": "router_js", + "version": "8.0.6", + "description": "A lightweight JavaScript library is built on top of route-recognizer and rsvp.js to provide an API for handling routes", + "license": "MIT", + "author": "Tilde, Inc.", + "private": true, + "exports": { + ".": "./index.ts" + }, + "scripts": { + }, + "dependencies": { + "@glimmer/env": "workspace:*" + }, + "devDependencies": { + "@types/qunit": "^2.9.6", + "@types/rsvp": "^4.0.4", + "backburner.js": "^2.6.0", + "loader.js": "^4.7.0", + "qunit": "^2.11.3", + "route-recognizer": "^0.3.4", + "rsvp": "^4.8.5" + }, + "peerDependencies": { + "route-recognizer": "^0.3.4", + "rsvp": "^4.8.5" + }, + "publishConfig": { + "registry": "https://registry.npmjs.org" + }, + "namespace": "Router" +} diff --git a/packages/router_js/tests/async_get_handler_test.ts b/packages/router_js/tests/async_get_handler_test.ts new file mode 100644 index 00000000000..92835f5e6f9 --- /dev/null +++ b/packages/router_js/tests/async_get_handler_test.ts @@ -0,0 +1,118 @@ +import type { Route } from '../index'; +import type { Dict } from '../lib/core'; +import { Promise } from 'rsvp'; +import { createHandler, TestRouter } from './test_helpers'; + +function map(router: TestRouter) { + router.map(function (match) { + match('/index').to('index'); + match('/foo').to('foo', function (match) { + match('/').to('fooIndex'); + match('/bar').to('fooBar'); + }); + }); +} + +// Intentionally use QUnit.module instead of module from test_helpers +// so that we avoid using Backburner to handle the async portions of +// the test suite +let routes: Dict; +let router: TestRouter; +QUnit.module('Async Get Handler', { + beforeEach: function () { + QUnit.config.testTimeout = 60000; + routes = {}; + }, + + afterEach: function () { + QUnit.config.testTimeout = 1000; + }, +}); + +QUnit.test('can transition to lazily-resolved routes', function (assert) { + let done = assert.async(); + + class LazyRouter extends TestRouter { + getRoute(name: string) { + return new Promise(function (resolve) { + setTimeout(function () { + resolve(routes[name] || (routes[name] = createHandler('empty'))); + }, 1); + }); + } + } + + router = new LazyRouter(); + map(router); + + let fooCalled = false; + let fooBarCalled = false; + + routes['foo'] = createHandler('foo', { + model() { + fooCalled = true; + }, + }); + routes['fooBar'] = createHandler('fooBar', { + model: function () { + fooBarCalled = true; + }, + }); + + router.transitionTo('/foo/bar').then(function () { + assert.ok(fooCalled, 'foo is called before transition ends'); + assert.ok(fooBarCalled, 'fooBar is called before transition ends'); + done(); + }); + + assert.notOk(fooCalled, 'foo is not called synchronously'); + assert.notOk(fooBarCalled, 'fooBar is not called synchronously'); +}); + +QUnit.test('calls hooks of lazily-resolved routes in order', function (assert) { + let done = assert.async(); + let operations: string[] = []; + + class LazyRouter extends TestRouter { + getRoute(name: string) { + operations.push('get handler ' + name); + return new Promise(function (resolve) { + let timeoutLength = name === 'foo' ? 100 : 1; + setTimeout(function () { + operations.push('resolved ' + name); + resolve(routes[name] || (routes[name] = createHandler('empty'))); + }, timeoutLength); + }); + } + } + + router = new LazyRouter(); + map(router); + + routes['foo'] = createHandler('foo', { + model: function () { + operations.push('model foo'); + }, + }); + routes['fooBar'] = createHandler('fooBar', { + model: function () { + operations.push('model fooBar'); + }, + }); + + router.transitionTo('/foo/bar').then(function () { + assert.deepEqual( + operations, + [ + 'get handler foo', + 'get handler fooBar', + 'resolved fooBar', + 'resolved foo', + 'model foo', + 'model fooBar', + ], + 'order of operations is correct' + ); + done(); + }, null); +}); diff --git a/packages/router_js/tests/query_params_test.ts b/packages/router_js/tests/query_params_test.ts new file mode 100644 index 00000000000..d816289fa9a --- /dev/null +++ b/packages/router_js/tests/query_params_test.ts @@ -0,0 +1,637 @@ +/* eslint-disable qunit/no-conditional-assertions */ +import type { MatchCallback } from 'route-recognizer'; +import type { Route, Transition } from '../index'; +import type Router from '../index'; +import type { Dict, Maybe } from '../lib/core'; +import type RouteInfo from '../lib/route-info'; +import { Promise } from 'rsvp'; +import { createHandler, TestRouter, trigger, ignoreTransitionError } from './test_helpers'; + +let router: Router, handlers: Dict, expectedUrl: Maybe; +let scenarios = [ + { + name: 'Sync Get Handler', + getHandler: function (name: string) { + return handlers[name] || (handlers[name] = createHandler('empty')); + }, + }, + { + name: 'Async Get Handler', + getHandler: function (name: string) { + return Promise.resolve(handlers[name] || (handlers[name] = createHandler('empty'))); + }, + }, +]; + +scenarios.forEach(function (scenario) { + QUnit.module('Query Params (' + scenario.name + ')', { + beforeEach: function (assert: Assert) { + handlers = {}; + expectedUrl = undefined; + + map(assert, function (match) { + match('/index').to('index'); + match('/parent').to('parent', function (match) { + match('/').to('parentIndex'); + match('/child').to('parentChild'); + }); + }); + }, + }); + + function map(assert: Assert, fn: MatchCallback) { + class QPRouter extends TestRouter { + routeDidChange() {} + routeWillChange() {} + didTransition() {} + willTransition() {} + triggerEvent( + handlerInfos: RouteInfo[], + ignoreFailure: boolean, + name: string, + args: any[] + ) { + trigger(handlerInfos, ignoreFailure, name, ...args); + } + replaceURL(name: string) { + this.updateURL(name); + } + getRoute(name: string) { + return scenario.getHandler(name); + } + getSerializer(): never { + throw new Error('never'); + } + updateURL(newUrl: string) { + if (expectedUrl) { + assert.equal(newUrl, expectedUrl, 'The url is ' + newUrl + ' as expected'); + } + } + } + router = new QPRouter(); + router.map(fn); + } + + function consumeAllFinalQueryParams(params: Dict, finalParams: Dict[]) { + for (let key in params) { + let value = params[key]; + delete params[key]; + finalParams.push({ key: key, value: value }); + } + return true; + } + + QUnit.test( + 'a change in query params fires a queryParamsDidChange event', + async function (assert) { + assert.expect(7); + + let count = 0; + handlers['index'] = createHandler('index', { + setup: function () { + assert.equal( + count, + 0, + "setup should be called exactly once since we're only changing query params after the first transition" + ); + }, + events: { + finalizeQueryParamChange: consumeAllFinalQueryParams, + + queryParamsDidChange: function (changed: Dict, all: Dict) { + switch (count) { + case 0: + assert.ok(false, "shouldn't fire on first trans"); + break; + case 1: + assert.deepEqual(changed, { foo: '5' }); + assert.deepEqual(all, { foo: '5' }); + break; + case 2: + assert.deepEqual(changed, { bar: '6' }); + assert.deepEqual(all, { foo: '5', bar: '6' }); + break; + case 3: + assert.deepEqual(changed, { foo: '8', bar: '9' }); + assert.deepEqual(all, { foo: '8', bar: '9' }); + break; + } + }, + }, + }); + + await router.transitionTo('/index'); + count = 1; + await router.transitionTo('/index?foo=5'); + count = 2; + await router.transitionTo('/index?foo=5&bar=6'); + count = 3; + await router.transitionTo('/index?foo=8&bar=9'); + } + ); + + QUnit.test( + 'transitioning between routes fires a queryParamsDidChange event', + async function (assert) { + assert.expect(8); + let count = 0; + handlers['parent'] = createHandler('parent', { + events: { + finalizeQueryParamChange: consumeAllFinalQueryParams, + queryParamsDidChange: function (changed: Dict, all: Dict) { + switch (count) { + case 0: + assert.ok(false, "shouldn't fire on first trans"); + break; + case 1: + assert.deepEqual(changed, { foo: '5' }); + assert.deepEqual(all, { foo: '5' }); + break; + case 2: + assert.deepEqual(changed, { bar: '6' }); + assert.deepEqual(all, { foo: '5', bar: '6' }); + break; + case 3: + assert.deepEqual(changed, { foo: '8', bar: '9' }); + assert.deepEqual(all, { foo: '8', bar: '9' }); + break; + case 4: + assert.deepEqual(changed, { foo: '10', bar: '11' }); + assert.deepEqual(all, { foo: '10', bar: '11' }); + } + }, + }, + }); + + handlers['parentChild'] = createHandler('parentChild', { + events: { + finalizeQueryParamChange: function () { + // Do nothing since this handler isn't consuming the QPs + return true; + }, + + queryParamsDidChange: function () { + return true; + }, + }, + }); + await router.transitionTo('/parent/child'); + count = 1; + await router.transitionTo('/parent/child?foo=5'); + count = 2; + await router.transitionTo('/parent/child?foo=5&bar=6'); + count = 3; + await router.transitionTo('/parent/child?foo=8&bar=9'); + count = 4; + await router.transitionTo('/parent?foo=10&bar=11'); + } + ); + + QUnit.test( + 'Refreshing the route when changing only query params should correctly set queryParamsOnly', + async function (assert) { + assert.expect(16); + + let initialTransition = true; + + let expectReplace: boolean; + + router.updateURL = function () { + assert.notOk(expectReplace, 'Expected replace but update was called'); + }; + + router.replaceURL = function () { + assert.ok(expectReplace, 'Replace was called but update was expected'); + }; + + handlers['index'] = createHandler('index', { + events: { + finalizeQueryParamChange: function ( + _params: Dict, + _finalParams: Dict[], + transition: Transition + ) { + if (initialTransition) { + assert.notOk( + transition.queryParamsOnly, + 'should not be query params only transition' + ); + initialTransition = false; + } else { + assert.ok(transition.queryParamsOnly, 'should be query params only transition'); + } + }, + + queryParamsDidChange: function () { + router.refresh(); + }, + }, + }); + + handlers['child'] = createHandler('child', { + events: { + finalizeQueryParamChange: function ( + _params: Dict, + _finalParams: Dict, + transition: Transition + ) { + assert.notOk(transition.queryParamsOnly, 'should be normal transition'); + return true; + }, + }, + }); + + expectReplace = false; + + let transition = router.transitionTo('/index'); + assert.notOk( + transition.queryParamsOnly, + 'Initial transition is not query params only transition' + ); + await transition; + + transition = router.transitionTo('/index?foo=123'); + + assert.ok( + transition.queryParamsOnly, + 'Second transition with updateURL intent is query params only' + ); + await ignoreTransitionError(transition); + + expectReplace = true; + transition = router.replaceWith('/index?foo=456'); + assert.ok( + transition.queryParamsOnly, + 'Third transition with replaceURL intent is query params only' + ); + await ignoreTransitionError(transition); + + expectReplace = false; + + transition = router.transitionTo('/parent/child?foo=789'); + assert.notOk( + transition.queryParamsOnly, + 'Fourth transition with transitionTo intent is not query params only' + ); + await transition; + + transition = router.transitionTo('/parent/child?foo=901'); + assert.ok( + transition.queryParamsOnly, + 'Firth transition with transitionTo intent is query params only' + ); + await transition; + + transition = router.transitionTo('/index?foo=123'); + assert.notOk( + transition.queryParamsOnly, + 'Firth transition with transitionTo intent is not query params only' + ); + + return ignoreTransitionError(transition); + } + ); + + QUnit.test( + 'a handler can opt into a full-on transition by calling refresh', + async function (assert) { + assert.expect(3); + + let count = 0; + handlers['index'] = createHandler('index', { + model: function () { + switch (count) { + case 0: + assert.ok(true, 'model called in initial transition'); + break; + case 1: + assert.ok(true, 'model called during refresh'); + break; + case 2: + assert.ok(true, 'model called during refresh w 2 QPs'); + break; + default: + assert.ok(false, "shouldn't have been called for " + count); + } + }, + events: { + queryParamsDidChange: function () { + if (count === 0) { + assert.ok(false, "shouldn't fire on first trans"); + } else { + router.refresh(this as Route); + } + }, + finalizeQueryParamChange: consumeAllFinalQueryParams, + }, + }); + + await router.transitionTo('/index'); + count = 1; + await ignoreTransitionError(router.transitionTo('/index?foo=5')); + count = 2; + return ignoreTransitionError(router.transitionTo('/index?foo=5&wat=lol')); + } + ); + + QUnit.test( + 'at the end of a query param change a finalizeQueryParamChange event is fired', + async function (assert) { + assert.expect(5); + + let eventHandled = false; + let count = 0; + handlers['index'] = createHandler('index', { + setup: function () { + assert.notOk(eventHandled, 'setup should happen before eventHandled'); + }, + events: { + finalizeQueryParamChange: function (all: Dict) { + eventHandled = true; + switch (count) { + case 0: + assert.deepEqual(all, {}); + break; + case 1: + assert.deepEqual(all, { foo: '5' }); + break; + case 2: + assert.deepEqual(all, { foo: '5', bar: '6' }); + break; + case 3: + assert.deepEqual(all, { foo: '8', bar: '9' }); + break; + } + }, + }, + }); + + await router.transitionTo('/index'); + count = 1; + await router.transitionTo('/index?foo=5'); + count = 2; + await router.transitionTo('/index?foo=5&bar=6'); + count = 3; + await router.transitionTo('/index?foo=8&bar=9'); + } + ); + + QUnit.test( + 'failing to consume QPs in finalize event tells the router it no longer has those params', + async function (assert) { + assert.expect(2); + + handlers['index'] = createHandler('index', { + setup: function () { + assert.ok(true, 'setup was entered'); + }, + }); + + await router.transitionTo('/index?foo=8&bar=9'); + + assert.deepEqual(router.state!.queryParams, {}); + } + ); + + QUnit.test( + 'consuming QPs in finalize event tells the router those params are active', + async function (assert) { + assert.expect(1); + + handlers['index'] = createHandler('index', { + events: { + finalizeQueryParamChange: function (params: Dict, finalParams: Dict[]) { + finalParams.push({ key: 'foo', value: params['foo'] }); + }, + }, + }); + + await router.transitionTo('/index?foo=8&bar=9'); + assert.deepEqual(router.state!.queryParams, { foo: '8' }); + } + ); + + QUnit.test( + "can hide query params from URL if they're marked as visible=false in finalizeQueryParamChange", + async function (assert) { + assert.expect(2); + + handlers['index'] = createHandler('index', { + events: { + finalizeQueryParamChange: function (params: Dict, finalParams: Dict[]) { + finalParams.push({ key: 'foo', value: params['foo'], visible: false }); + finalParams.push({ key: 'bar', value: params['bar'] }); + }, + }, + }); + + expectedUrl = '/index?bar=9'; + await router.transitionTo('/index?foo=8&bar=9'); + assert.deepEqual(router.state!.queryParams, { foo: '8', bar: '9' }); + } + ); + + QUnit.test('transitionTo() works with single query param arg', async function (assert) { + assert.expect(2); + + handlers['index'] = createHandler('index', { + events: { + finalizeQueryParamChange: function (params: Dict, finalParams: Dict[]) { + finalParams.push({ key: 'foo', value: params['foo'] }); + finalParams.push({ key: 'bar', value: params['bar'] }); + }, + }, + }); + + await router.transitionTo('/index?bar=9&foo=8'); + assert.deepEqual(router.state!.queryParams, { foo: '8', bar: '9' }); + + expectedUrl = '/index?foo=123'; + await router.transitionTo({ queryParams: { foo: '123' } }); + }); + + QUnit.test( + 'handleURL will NOT follow up with a replace URL if query params are already in sync', + function (assert) { + assert.expect(0); + + router.replaceURL = function (url) { + assert.ok(false, "query params are in sync, this replaceURL shouldn't happen: " + url); + }; + + router.handleURL('/index'); + } + ); + + QUnit.test('model hook receives queryParams', async function (assert) { + assert.expect(1); + + handlers['index'] = createHandler('index', { + model: function (params: Dict) { + assert.deepEqual(params, { queryParams: { foo: '5' } }); + }, + }); + + await router.transitionTo('/index?foo=5'); + }); + + QUnit.test( + 'can cause full transition by calling refresh within queryParamsDidChange', + async function (assert) { + assert.expect(5); + + let modelCount = 0; + handlers['index'] = createHandler('index', { + model: function (params: Dict) { + ++modelCount; + if (modelCount === 1) { + assert.deepEqual(params, { queryParams: { foo: '5' } }); + } else if (modelCount === 2) { + assert.deepEqual(params, { queryParams: { foo: '6' } }); + } + }, + events: { + queryParamsDidChange: function () { + router.refresh(this as Route); + }, + }, + }); + + assert.equal(modelCount, 0); + await ignoreTransitionError(router.transitionTo('/index?foo=5')); + assert.equal(modelCount, 1); + await ignoreTransitionError(router.transitionTo('/index?foo=6')); + assert.equal(modelCount, 2); + } + ); + + QUnit.test('can retry a query-params refresh', async function (assert) { + let causeRedirect = false; + + map(assert, function (match) { + match('/index').to('index'); + match('/login').to('login'); + }); + + assert.expect(11); + + let redirect = false; + let indexTransition: Transition; + handlers['index'] = createHandler('index', { + model: function (_params: Dict, transition: Transition) { + if (redirect) { + indexTransition = transition; + router.transitionTo('login'); + } + }, + setup: function () { + assert.ok(true, 'index#setup'); + }, + events: { + queryParamsDidChange: function () { + assert.ok(true, 'index#queryParamsDidChange'); + redirect = causeRedirect; + router.refresh(this as Route); + }, + finalizeQueryParamChange: function (params: Dict, finalParams: Dict[]) { + (finalParams as any).foo = params['foo']; // TODO wat + finalParams.push({ key: 'foo', value: params['foo'] }); + }, + }, + }); + + handlers['login'] = createHandler('login', { + setup: function () { + assert.ok(true, 'login#setup'); + }, + }); + + expectedUrl = '/index?foo=abc'; + await ignoreTransitionError(router.transitionTo('/index?foo=abc')); + causeRedirect = true; + expectedUrl = '/login'; + await ignoreTransitionError(router.transitionTo('/index?foo=def')); + causeRedirect = false; + redirect = false; + assert.ok(indexTransition!, 'index transition was saved'); + expectedUrl = '/index?foo=def'; + return ignoreTransitionError(indexTransition!.retry()); + }); + + QUnit.test( + 'tests whether query params to transitionTo are considered active', + async function (assert) { + assert.expect(6); + + handlers['index'] = createHandler('index', { + events: { + finalizeQueryParamChange: function (params: Dict, finalParams: Dict[]) { + finalParams.push({ key: 'foo', value: params['foo'] }); + finalParams.push({ key: 'bar', value: params['bar'] }); + }, + }, + }); + + await router.transitionTo('/index?foo=8&bar=9'); + assert.deepEqual(router.state!.queryParams, { foo: '8', bar: '9' }); + assert.ok( + router.isActive('index', { queryParams: { foo: '8', bar: '9' } }), + 'The index handler is active' + ); + assert.ok( + router.isActive('index', { queryParams: { foo: 8, bar: 9 } }), + 'Works when property is number' + ); + assert.notOk( + router.isActive('index', { queryParams: { foo: '9' } }), + 'Only supply one changed query param' + ); + assert.notOk( + router.isActive('index', { + queryParams: { foo: '8', bar: '10', baz: '11' }, + }), + 'A new query param was added' + ); + assert.notOk( + router.isActive('index', { queryParams: { foo: '8', bar: '11' } }), + 'A query param changed' + ); + } + ); + + QUnit.test( + 'tests whether array query params to transitionTo are considered active', + async function (assert) { + assert.expect(7); + + handlers['index'] = createHandler('index', { + events: { + finalizeQueryParamChange: function (params: Dict, finalParams: Dict[]) { + finalParams.push({ key: 'foo', value: params['foo'] }); + }, + }, + }); + + await router.transitionTo('/index?foo[]=1&foo[]=2'); + assert.deepEqual(router.state!.queryParams, { foo: ['1', '2'] }); + assert.ok( + router.isActive('index', { queryParams: { foo: ['1', '2'] } }), + 'The index handler is active' + ); + assert.ok( + router.isActive('index', { queryParams: { foo: [1, 2] } }), + 'Works when array has numeric elements' + ); + assert.notOk(router.isActive('index', { queryParams: { foo: ['2', '1'] } }), 'Change order'); + assert.notOk( + router.isActive('index', { queryParams: { foo: ['1', '2', '3'] } }), + 'Change Length' + ); + assert.notOk( + router.isActive('index', { queryParams: { foo: ['3', '4'] } }), + 'Change Content' + ); + assert.notOk(router.isActive('index', { queryParams: { foo: [] } }), 'Empty Array'); + } + ); +}); diff --git a/packages/router_js/tests/route_info_test.ts b/packages/router_js/tests/route_info_test.ts new file mode 100644 index 00000000000..31ba500e7b7 --- /dev/null +++ b/packages/router_js/tests/route_info_test.ts @@ -0,0 +1,236 @@ +import type { Transition } from '../index'; +import type { Dict } from '../lib/core'; +import type { IModel, Route } from '../lib/route-info'; +import { + ResolvedRouteInfo, + toReadOnlyRouteInfo, + UnresolvedRouteInfoByObject, + UnresolvedRouteInfoByParam, +} from '../lib/route-info'; +import InternalTransition from '../lib/transition'; +import URLTransitionIntent from '../lib/transition-intent/url-transition-intent'; +import { resolve } from 'rsvp'; +import { createHandler, createHandlerInfo, TestRouter } from './test_helpers'; + +QUnit.module('RouteInfo'); + +QUnit.test('ResolvedRouteInfo resolve to themselves', function (assert) { + assert.expect(1); + let router = new TestRouter(); + let routeInfo = new ResolvedRouteInfo(router, 'foo', [], {}, createHandler('empty')); + let intent = new URLTransitionIntent(router, 'foo'); + + let transition = new InternalTransition(router, intent, undefined); + + routeInfo.resolve(transition).then((resolvedRouteInfo) => { + assert.equal(routeInfo, resolvedRouteInfo); + }); +}); + +QUnit.test('UnresolvedRouteInfoByParam defaults params to {}', function (assert) { + let router = new TestRouter(); + let routeInfo = new UnresolvedRouteInfoByParam(router, 'empty', [], {}); + assert.deepEqual(routeInfo.params, {}); + + let routeInfo2 = new UnresolvedRouteInfoByParam(router, 'empty', [], { foo: 5 }); + assert.deepEqual(routeInfo2.params, { foo: 5 }); +}); + +QUnit.test('RouteInfo can be aborted mid-resolve', function (assert) { + assert.expect(1); + + let routeInfo = createHandlerInfo('stub'); + + let transition = {} as Transition; + transition.isAborted = true; + + routeInfo + .resolve(transition) + .then(() => { + assert.ok(false, 'unreachable'); + }) + .catch((e) => { + assert.equal(e.message, 'TransitionAborted'); + }); +}); + +QUnit.test('RouteInfo#resolve resolves with a ResolvedRouteInfo', function (assert) { + assert.expect(1); + + let routeInfo = createHandlerInfo('stub'); + routeInfo.resolve({} as Transition).then((resolvedRouteInfo) => { + assert.ok(resolvedRouteInfo instanceof ResolvedRouteInfo); + }); +}); + +QUnit.test('RouteInfo#resolve runs beforeModel hook on handler', function (assert) { + assert.expect(1); + + let transition = {} as Transition; + + let routeInfo = createHandlerInfo('stub', { + route: createHandler('stub', { + beforeModel: function (currentTransition: Transition) { + assert.equal( + transition, + currentTransition, + 'beforeModel was called with the payload we passed to resolve()' + ); + }, + }), + }); + + routeInfo.resolve(transition).then(() => { + assert.ok(true, 'routeInfo resolved successfully'); + }); +}); + +QUnit.test('RouteInfo#resolve runs getModel hook', async function (assert) { + assert.expect(2); + + let transition = {} as Transition; + + let routeInfo = createHandlerInfo('stub', { + getModel(payload: Dict) { + assert.equal(payload, transition); + }, + }); + + routeInfo.resolve(transition).then(() => { + assert.ok(true, 'routeInfo resolved successfully'); + }); +}); + +/** + * This test file was not being run before it was integrated from upstream and a number of these + * tests were failing as soon as we started running it again. + * + * This test has some strange timing issues with the strange backburner wrapper it's doing in the + * test-helpers. We could not figure this out and really the solution should be to remove the strange + * wrapper. + * + * TODO: unskip this test + */ +QUnit.skip('RouteInfo#resolve runs afterModel hook on handler', function (assert) { + assert.expect(3); + + let transition = {} as Transition; + let model = {}; + + let routeInfo = createHandlerInfo('foo', { + route: createHandler('foo', { + afterModel(resolvedModel: Dict, payload: Dict) { + assert.equal(resolvedModel, model, 'afterModel receives the value resolved by model'); + assert.equal(payload, transition); + return resolve(123); // 123 should get ignored + }, + }), + getModel() { + return resolve(model); + }, + }); + + routeInfo.resolve(transition).then((resolvedRouteInfo) => { + assert.equal(resolvedRouteInfo.context, model, 'RouteInfo resolved with correct model'); + }); +}); + +QUnit.test('UnresolvedRouteInfoByParam gets its model hook called', function (assert) { + assert.expect(2); + let router = new TestRouter(); + + let transition = {} as Transition; + + let routeInfo = new UnresolvedRouteInfoByParam( + router, + 'empty', + [], + { first_name: 'Alex', last_name: 'Matchnerd' }, + createHandler('h', { + model(params: Dict, payload: Dict) { + assert.equal(payload, transition); + assert.deepEqual(params, { + first_name: 'Alex', + last_name: 'Matchnerd', + }); + }, + }) + ); + + routeInfo.resolve(transition); +}); + +QUnit.test('UnresolvedRouteInfoByObject does NOT get its model hook called', function (assert) { + type Dorkleton = { name: string } & IModel; + + assert.expect(1); + + class TestRouteInfo extends UnresolvedRouteInfoByObject> { + __routeHandler?: Route; + get route(): Route { + if (this.__routeHandler) { + return this.__routeHandler; + } + return (this.__routeHandler = createHandler('unresolved', { + model: function () { + assert.ok(false, "I shouldn't be called because I already have a context/model"); + }, + })); + } + set route(_value) { + // TODO: this stub is here because something is setting this and it breaks if there isn't a setter + } + } + + let routeInfo = new TestRouteInfo( + new TestRouter(), + 'unresolved', + ['wat'], + resolve({ name: 'dorkletons' }) + ); + + routeInfo.resolve({} as Transition).then((resolvedRouteInfo) => { + assert.equal(resolvedRouteInfo.context!.name, 'dorkletons'); + }); +}); + +QUnit.test('RouteInfo.find', function (assert) { + assert.expect(3); + let router = new TestRouter(); + let parent = new ResolvedRouteInfo(router, 'parent', [], {}, createHandler('parent')); + let child = new ResolvedRouteInfo(router, 'child', [], {}, createHandler('child')); + let grandChild = new ResolvedRouteInfo(router, 'grandChild', [], {}, createHandler('grandChild')); + let [root] = toReadOnlyRouteInfo([parent, child, grandChild]); + + enum RouteInfoNames { + parent, + child, + grandChild, + } + + root!.find((routInfo, i) => { + assert.equal(RouteInfoNames[i], routInfo.name); + return false; + }); +}); + +QUnit.test('RouteInfo.find returns matched', function (assert) { + assert.expect(3); + let router = new TestRouter(); + let parent = new ResolvedRouteInfo(router, 'parent', [], {}, createHandler('parent')); + let child = new ResolvedRouteInfo(router, 'child', [], {}, createHandler('child')); + let grandChild = new ResolvedRouteInfo(router, 'grandChild', [], {}, createHandler('grandChild')); + let [root] = toReadOnlyRouteInfo([parent, child, grandChild]); + + enum RouteInfoNames { + parent, + child, + grandChild, + } + + let childInfo = root!.find((routInfo, i) => { + assert.equal(RouteInfoNames[i], routInfo.name); + return routInfo.name === 'child'; + }); + assert.equal(childInfo!.name, 'child'); +}); diff --git a/packages/router_js/tests/router_test.ts b/packages/router_js/tests/router_test.ts new file mode 100644 index 00000000000..2f8d320a751 --- /dev/null +++ b/packages/router_js/tests/router_test.ts @@ -0,0 +1,6629 @@ +/* eslint-disable qunit/no-conditional-assertions, qunit/no-assert-logical-expression, qunit/no-early-return, no-console, no-throw-literal */ +import type { MatchCallback } from 'route-recognizer'; +import type { Route, Transition } from '../index'; +import type Router from '../index'; +import type { Dict, Maybe } from '../lib/core'; +import type { + IModel, + RouteInfo as PublicRouteInfo, + RouteInfoWithAttributes, +} from '../lib/route-info'; +import type RouteInfo from '../lib/route-info'; +import type { SerializerFunc } from '../lib/router'; +import { logAbort, PARAMS_SYMBOL, QUERY_PARAMS_SYMBOL, STATE_SYMBOL } from '../lib/transition'; +import type { TransitionError } from '../lib/transition-state'; +import { Promise, reject } from 'rsvp'; +import { + assertAbort, + createHandler, + isExiting, + replaceWith, + shouldNotHappen, + TestRouter, + transitionToWithAbort, + trigger, + ignoreTransitionError, +} from './test_helpers'; + +let router: Router; +let url: string | undefined; +let routes: Dict; + +function isPresent(maybe: Maybe): maybe is PublicRouteInfo { + return maybe !== undefined && maybe !== null; +} + +let serializers: Dict>, expectedUrl: Maybe; +let scenarios = [ + { + name: 'Sync Get Handler', + async: false, + getRoute: function (name: string) { + return routes[name] || (routes[name] = createHandler('empty')); + }, + getSerializer: function (_name: string) { + return undefined; + }, + }, + { + name: 'Async Get Handler', + async: true, + getRoute: function (name: string) { + // Treat 'loading' route transitions are synchronous + let handler = routes[name] || (routes[name] = createHandler('empty')); + return name === 'loading' ? handler : Promise.resolve(handler); + }, + getSerializer: function (name: string) { + return serializers && serializers[name]; + }, + }, +]; + +scenarios.forEach(function (scenario) { + QUnit.module('The router (' + scenario.name + ')', { + beforeEach: function (assert: Assert) { + routes = {}; + expectedUrl = undefined; + url = undefined; + + map(assert, function (match) { + match('/index').to('index'); + match('/about').to('about'); + match('/faq').to('faq'); + match('/nested').to('nestedParent', function (match) { + match('/').to('nestedChild'); + }); + match('/posts', function (match) { + match('/:id').to('showPost'); + match('/:postId/:commentId').to('showComment'); + match('/on/:date').to('showPostsForDate'); + match('/admin/:id').to('admin', function (match) { + match('/posts').to('adminPosts'); + match('/posts/:post_id').to('adminPost'); + }); + match('/').to('postIndex', function (match) { + match('/all').to('showAllPosts'); + + // TODO: Support canonical: true + match('/').to('showAllPosts'); + match('/popular').to('showPopularPosts'); + match('/filter/:filter_id').to('showFilteredPosts'); + }); + }); + }); + }, + }); + + function map(assert: Assert, fn: MatchCallback) { + class Router extends TestRouter { + routeDidChange() {} + routeWillChange() {} + didTransition() {} + willTransition() {} + replaceURL(name: string) { + this.updateURL(name); + } + triggerEvent( + handlerInfos: RouteInfo[], + ignoreFailure: boolean, + name: string, + args: any[] + ) { + trigger(handlerInfos, ignoreFailure, name, ...args); + } + + getRoute(name: string) { + return scenario.getRoute(name); + } + + getSerializer(name: string) { + return scenario.getSerializer(name); + } + + updateURL(newUrl: string) { + if (expectedUrl) { + assert.equal(newUrl, expectedUrl, 'The url is ' + newUrl + ' as expected'); + } + + url = newUrl; + } + } + + router = new Router(); + + router.map(fn); + } + + QUnit.test('Mapping adds named routes to the end', function (assert) { + url = router.recognizer.generate('showPost', { id: 1 }); + assert.equal(url, '/posts/1'); + + url = router.recognizer.generate('showAllPosts'); + assert.equal(url, '/posts'); + + url = router.recognizer.generate('showComment', { + postId: 1, + commentId: 2, + }); + assert.equal(url, '/posts/1/2'); + + url = router.generate('showComment', 1, 2); + assert.equal(url, '/posts/1/2'); + }); + + QUnit.test('Handling an invalid URL returns a rejecting promise', function (assert) { + router.handleURL('/unknown').then(shouldNotHappen(assert), function (e: Error) { + assert.equal(e.name, 'UnrecognizedURLError', 'error.name is UnrecognizedURLError'); + }); + }); + + function routePath(infos: RouteInfo[]) { + let path = []; + + for (let i = 0, l = infos.length; i < l; i++) { + path.push(infos[i]!.name); + } + + return path.join('.'); + } + + QUnit.test( + 'Handling a URL triggers model on the handler and passes the result into the setup method', + function (assert) { + assert.expect(4); + + let post = { post: true }; + + routes = { + showPost: createHandler('showPost', { + model: function (params: Dict) { + assert.deepEqual( + params, + { id: '1', queryParams: {} }, + 'showPost#model called with id 1' + ); + return post; + }, + + setup: function (object: Dict) { + assert.strictEqual(object, post, 'setup was called with expected model'); + assert.equal( + routes['showPost']!.context, + post, + 'context was properly set on showPost handler' + ); + }, + }), + }; + + router.didTransition = function (infos) { + assert.equal(routePath(infos), 'showPost'); + }; + + router.handleURL('/posts/1'); + } + ); + + QUnit.test('isActive should not break on initial intermediate route', function (assert) { + assert.expect(1); + router.intermediateTransitionTo('/posts/admin/1/posts'); + assert.ok(router.isActive('admin', '1')); + }); + + QUnit.test('Handling a URL passes in query params', async function (assert) { + assert.expect(3); + + routes = { + index: createHandler('index', { + model: function (_params: string[], transition: Transition) { + assert.deepEqual(transition[QUERY_PARAMS_SYMBOL], { + sort: 'date', + filter: 'true', + }); + }, + events: { + finalizeQueryParamChange: function (params: string[], finalParams: Dict[]) { + assert.ok(true, 'finalizeQueryParamChange'); + // need to consume the params so that the router + // knows that they're active + finalParams.push({ key: 'sort', value: params['sort'] }); + finalParams.push({ key: 'filter', value: params['filter'] }); + }, + }, + }), + }; + + await router.handleURL('/index?sort=date&filter'); + assert.deepEqual(router.state!.queryParams, { + sort: 'date', + filter: 'true', + }); + }); + + QUnit.test('handleURL accepts slash-less URLs', function (assert) { + assert.expect(1); + + routes = { + showAllPosts: createHandler('showAllPosts', { + setup: function () { + assert.ok(true, "showAllPosts' setup called"); + }, + }), + }; + + router.handleURL('posts/all'); + }); + + QUnit.test('handleURL accepts query params', function (assert) { + assert.expect(1); + + routes = { + showAllPosts: createHandler('showAllPosts', { + setup: function () { + assert.ok(true, "showAllPosts' setup called"); + }, + }), + }; + + router.handleURL('/posts/all?sort=name&sortDirection=descending'); + }); + + QUnit.test("redirect hook shouldn't get called on parent routes", async function (assert) { + map(assert, function (match) { + match('/').to('app', function (match) { + match('/').to('index'); + match('/other').to('other'); + }); + }); + + let appRedirects = 0; + routes = { + app: createHandler('app', { + redirect: function () { + appRedirects++; + }, + }), + }; + + await router.transitionTo('/'); + assert.equal(appRedirects, 1); + await router.transitionTo('other'); + assert.equal(appRedirects, 1); + }); + + QUnit.test( + 'when transitioning with the same context, setup should only be called once', + async function (assert) { + let parentSetupCount = 0, + childSetupCount = 0; + + let context = { id: 1 }; + + map(assert, function (match) { + match('/').to('index'); + match('/posts/:id').to('post', function (match) { + match('/details').to('postDetails'); + }); + }); + + routes = { + post: createHandler('post', { + setup: function () { + parentSetupCount++; + }, + }), + + postDetails: createHandler('postDetails', { + setup: function () { + childSetupCount++; + }, + }), + }; + + await router.transitionTo('/'); + + assert.equal(parentSetupCount, 0, 'precondition - parent not setup'); + assert.equal(childSetupCount, 0, 'precondition - child not setup'); + + await router.transitionTo('postDetails', context); + + assert.equal(parentSetupCount, 1, 'after initial transition parent is setup once'); + assert.equal(childSetupCount, 1, 'after initial transition child is setup once'); + + await router.transitionTo('postDetails', context); + + assert.equal(parentSetupCount, 1, 'after duplicate transition, parent is still setup once'); + assert.equal(childSetupCount, 1, 'after duplicate transition, child is still setup once'); + } + ); + + QUnit.test('basic route change events', function (assert) { + assert.expect(11); + map(assert, function (match) { + match('/').to('index'); + match('/posts/:id').to('post', function (match) { + match('/details').to('postDetails'); + }); + }); + + let enteredWillChange = 0; + let enteredDidChange = 0; + routes = { + post: createHandler('post', { + model() { + return { title: 'The Title' }; + }, + }), + postDetails: createHandler('postDetails', { + model() { + return { body: 'The Content' }; + }, + }), + }; + + router.routeWillChange = (transition: Transition) => { + enteredWillChange++; + + if (isPresent(transition.to)) { + assert.equal(transition.to.localName, 'postDetails'); + assert.equal(transition.from, null); + assert.equal(transition.to.parent!.localName, 'post'); + assert.equal((transition.to as any).attributes, undefined); + } + }; + + router.routeDidChange = (transition: Transition) => { + enteredDidChange++; + let to = transition.to! as RouteInfoWithAttributes; + if (isPresent(transition.to)) { + assert.equal(to.localName, 'postDetails'); + assert.equal(transition.from!, null); + assert.equal(to.parent!.localName, 'post'); + assert.deepEqual(to.attributes, { body: 'The Content' }); + assert.deepEqual((to.parent! as RouteInfoWithAttributes).attributes, { + title: 'The Title', + }); + } + }; + + router.transitionTo('/posts/1/details').then(() => { + assert.equal(enteredWillChange, 1); + assert.equal(enteredDidChange, 1); + }); + }); + + QUnit.test('basic events with route metadata', function (assert) { + assert.expect(10); + map(assert, function (match) { + match('/').to('index'); + match('/profile').to('profile'); + match('/posts/:id').to('post', function (match) { + match('/details').to('postDetails'); + }); + }); + + routes = { + post: createHandler('post', { + buildRouteInfoMetadata() { + return 'post-page'; + }, + model() { + return { title: 'The Title' }; + }, + }), + profile: createHandler('profile', { + buildRouteInfoMetadata() { + return 'profile-page'; + }, + }), + postDetails: createHandler('postDetails', { + buildRouteInfoMetadata() { + return 'post-details-page'; + }, + model() { + return { body: 'The Content' }; + }, + }), + }; + + router.routeWillChange = (transition: Transition) => { + if (!isPresent(transition.from) && isPresent(transition.to)) { + if (scenario.async) { + assert.equal(transition.to.metadata, null, 'initial to leaf'); + assert.equal(transition.to.parent!.metadata, null, 'initial to leaf'); + } else { + assert.equal(transition.to.metadata, 'post-details-page'); + assert.equal(transition.to.parent!.metadata, 'post-page'); + } + } + + if (isPresent(transition.from) && isPresent(transition.to)) { + if (scenario.async) { + assert.equal(transition.from.metadata, 'post-details-page', 'from leaf'); + assert.equal(transition.from.parent!.metadata, 'post-page', 'from parent'); + assert.equal(transition.to.metadata, null, 'to leaf'); + } else { + assert.equal(transition.from.metadata, 'post-details-page'); + assert.equal(transition.from.parent!.metadata, 'post-page'); + assert.equal(transition.to.metadata, 'profile-page'); + } + } + }; + + router.routeDidChange = (transition: Transition) => { + if (!isPresent(transition.from) && isPresent(transition.to)) { + assert.equal(transition.to.metadata, 'post-details-page', 'initial to leaf'); + assert.equal(transition.to.parent!.metadata, 'post-page', 'initial to parent'); + } + + if (isPresent(transition.from) && isPresent(transition.to)) { + assert.equal(transition.from.metadata, 'post-details-page', 'from: /profile visited'); + assert.equal( + transition.from.parent!.metadata, + 'post-page', + 'from: /profile visited parent' + ); + assert.equal(transition.to.metadata, 'profile-page', 'to: /profile'); + } + }; + + router.transitionTo('/posts/1/details').then(() => { + return router.transitionTo('/profile'); + }); + }); + + QUnit.test('basic route change events with replacement', function (assert) { + assert.expect(14); + map(assert, function (match) { + match('/').to('index'); + match('/posts/:id').to('post', function (match) { + match('/details').to('postDetails'); + }); + match('/post-details/:id').to('canonicalPostDetails'); + }); + + let enteredWillChange = 0; + let enteredDidChange = 0; + routes = { + post: createHandler('post'), + postDetails: createHandler('postDetails'), + canonicalPostDetails: createHandler('canonicalPostDetails'), + }; + + let replacement = false; + + router.routeWillChange = (transition: Transition) => { + enteredWillChange++; + if (isPresent(transition.to)) { + if (replacement) { + assert.equal(transition.to.localName, 'canonicalPostDetails'); + assert.equal(isPresent(transition.from) && transition.from.localName, 'postDetails'); + assert.equal(transition.to!.parent!, null); + } else { + assert.equal(transition.to!.localName, 'postDetails'); + assert.equal(transition.from!, null); + assert.equal(transition.to!.parent!.localName, 'post'); + } + } + }; + + router.routeDidChange = (transition: Transition) => { + enteredDidChange++; + if (isPresent(transition.to)) { + if (replacement) { + assert.equal(transition.to!.localName, 'canonicalPostDetails'); + assert.equal(isPresent(transition.from) && transition.from.localName, 'postDetails'); + assert.equal(transition.to!.parent, null); + } else { + assert.equal(transition.to!.localName, 'postDetails'); + assert.equal(transition.from!, null); + assert.equal(transition.to!.parent!.localName, 'post'); + } + } + }; + + router + .transitionTo('/posts/1/details') + .then(() => { + replacement = true; + return router.replaceWith('/post-details/1'); + }) + .then(() => { + assert.equal(enteredWillChange, 2); + assert.equal(enteredDidChange, 2); + }); + }); + + QUnit.test('basic route change events with nested replacement', function (assert) { + assert.expect(12); + map(assert, function (match) { + match('/').to('index'); + match('/posts/:id').to('post', function (match) { + match('/details').to('postDetails'); + }); + match('/post-details/:id').to('canonicalPostDetails'); + }); + + let enteredWillChange = 0; + let enteredDidChange = 0; + routes = { + post: createHandler('post'), + postDetails: createHandler('postDetails', { + model() { + router.replaceWith('/post-details/1'); + replacement = true; + }, + }), + canonicalPostDetails: createHandler('canonicalPostDetails'), + }; + + let replacement = false; + + router.routeWillChange = (transition: Transition) => { + enteredWillChange++; + if (isPresent(transition.to)) { + if (replacement) { + assert.equal(transition.to.localName, 'canonicalPostDetails'); + assert.equal(transition.from!, null); + assert.equal(transition.to.parent!, null); + } else { + assert.equal(transition.to.localName, 'postDetails'); + assert.equal(transition.from!, null); + assert.equal(transition.to.parent!.localName, 'post'); + replacement = true; + } + } + }; + + router.routeDidChange = (transition: Transition) => { + enteredDidChange++; + assert.equal(transition.to!.localName, 'canonicalPostDetails'); + assert.equal(transition.from!, null); + assert.equal(transition.to!.parent, null); + }; + + router + .transitionTo('/posts/1/details') + .catch((err: any) => { + assert.equal(err.name, 'TransitionAborted'); + return router.activeTransition as any; + }) + .then(() => { + assert.equal(enteredWillChange, 2); + assert.equal(enteredDidChange, 1); + }); + }); + + QUnit.test('basic route change events with params', function (assert) { + assert.expect(26); + map(assert, function (match) { + match('/').to('index'); + match('/posts/:id').to('post'); + }); + + let enteredWillChange = 0; + let enteredDidChange = 0; + routes = { + index: createHandler('index', { + model() { + return Promise.resolve('Index'); + }, + }), + post: createHandler('post', { + model(params: Dict) { + return Promise.resolve(params['id']); + }, + }), + }; + + let newParam = false; + + router.routeWillChange = (transition: Transition) => { + enteredWillChange++; + assert.deepEqual(transition.to!.paramNames, ['id']); + if (newParam) { + assert.equal(transition.to!.localName, 'post'); + assert.equal(isPresent(transition.from) && transition.from.localName, 'post'); + assert.deepEqual(isPresent(transition.from) && transition.from.attributes, '1'); + assert.deepEqual(transition.to!.params, { id: '2' }); + assert.equal(url, '/posts/1'); + } else { + assert.equal(transition.to!.localName, 'post'); + assert.equal(transition.from, null); + assert.notOk(url); + assert.deepEqual(transition.to!.params, { id: '1' }); + } + }; + + router.routeDidChange = (transition: Transition) => { + enteredDidChange++; + let to = transition.to! as RouteInfoWithAttributes; + assert.deepEqual(transition.to!.paramNames, ['id']); + if (newParam) { + assert.equal(to.localName, 'post'); + assert.equal(isPresent(transition.from) && transition.from.localName, 'post'); + assert.deepEqual(to.params, { id: '2' }); + assert.deepEqual(to.attributes, '2'); + assert.deepEqual(isPresent(transition.from) && transition.from.attributes, '1'); + assert.equal(url, '/posts/2'); + } else { + assert.equal(to.localName, 'post'); + assert.equal(transition.from, null); + assert.equal(url, '/posts/1'); + assert.deepEqual(to.params, { id: '1' }); + assert.deepEqual(to.attributes, '1'); + } + }; + + router + .transitionTo('/posts/1') + .then(() => { + newParam = true; + return router.transitionTo('/posts/2'); + }) + .then(() => { + assert.equal(enteredWillChange, 2); + assert.equal(enteredDidChange, 2); + }); + }); + + QUnit.test('top-level recognizeAndLoad url', function (assert) { + map(assert, function (match) { + match('/').to('index'); + }); + + routes = { + index: createHandler('index', { + model() { + return { name: 'index', data: 1 }; + }, + }), + }; + assert.notOk(router.activeTransition, 'Does not start with an active transition'); + + router.replaceURL = () => { + assert.ok(false, 'Should not replace the URL'); + }; + + router.updateURL = () => { + assert.ok(false, 'Should not update the URL'); + }; + + router.recognizeAndLoad('/').then((routeInfoWithAttributes: RouteInfoWithAttributes) => { + assert.notOk(router.activeTransition, 'Does not create an active transition'); + if (routeInfoWithAttributes === null) { + assert.ok(false); + return; + } + assert.equal(routeInfoWithAttributes.name, 'index'); + assert.equal(routeInfoWithAttributes.localName, 'index'); + assert.equal(routeInfoWithAttributes.parent, null); + assert.equal(routeInfoWithAttributes.child, null); + assert.deepEqual(routeInfoWithAttributes.attributes, { name: 'index', data: 1 }); + assert.deepEqual(routeInfoWithAttributes.queryParams, {}); + assert.deepEqual(routeInfoWithAttributes.params, {}); + assert.deepEqual(routeInfoWithAttributes.paramNames, []); + }); + }); + + QUnit.test('top-level parameterized recognizeAndLoad', function (assert) { + map(assert, function (match) { + match('/posts/:id').to('posts'); + }); + + routes = { + posts: createHandler('posts', { + model(params: { id: string }) { + return { name: 'posts', data: params['id'] }; + }, + }), + }; + assert.notOk(router.activeTransition, 'Does not start with an active transition'); + + router.replaceURL = () => { + assert.ok(false, 'Should not replace the URL'); + }; + + router.updateURL = () => { + assert.ok(false, 'Should not update the URL'); + }; + + router + .recognizeAndLoad('/posts/123') + .then((routeInfoWithAttributes: RouteInfoWithAttributes) => { + assert.notOk(router.activeTransition, 'Does not create an active transition'); + if (routeInfoWithAttributes === null) { + assert.ok(false); + return; + } + assert.equal(routeInfoWithAttributes.name, 'posts'); + assert.equal(routeInfoWithAttributes.localName, 'posts'); + assert.equal(routeInfoWithAttributes.parent, null); + assert.equal(routeInfoWithAttributes.child, null); + assert.deepEqual(routeInfoWithAttributes.attributes, { name: 'posts', data: '123' }); + assert.deepEqual(routeInfoWithAttributes.queryParams, {}); + assert.deepEqual(routeInfoWithAttributes.params, { id: '123' }); + assert.deepEqual(routeInfoWithAttributes.paramNames, ['id']); + }); + }); + + QUnit.test('nested recognizeAndLoad', function (assert) { + routes = { + postIndex: createHandler('postIndex'), + showPopularPosts: createHandler('showPopularPosts', { + model() { + return { name: 'showPopularPosts', data: 123 }; + }, + }), + }; + assert.notOk(router.activeTransition, 'Does not start with an active transition'); + + router.replaceURL = () => { + assert.ok(false, 'Should not replace the URL'); + }; + + router.updateURL = () => { + assert.ok(false, 'Should not update the URL'); + }; + + router + .recognizeAndLoad('/posts/popular') + .then((routeInfoWithAttributes: RouteInfoWithAttributes) => { + assert.notOk(router.activeTransition, 'Does not create an active transition'); + if (routeInfoWithAttributes === null) { + assert.ok(false); + return; + } + assert.equal(routeInfoWithAttributes.name, 'showPopularPosts'); + assert.equal(routeInfoWithAttributes.localName, 'showPopularPosts'); + assert.equal(routeInfoWithAttributes.parent!.name, 'postIndex'); + assert.equal(routeInfoWithAttributes.child, null); + assert.deepEqual(routeInfoWithAttributes.attributes, { + name: 'showPopularPosts', + data: 123, + }); + assert.deepEqual(routeInfoWithAttributes.queryParams, {}); + assert.deepEqual(routeInfoWithAttributes.params, {}); + assert.deepEqual(routeInfoWithAttributes.paramNames, []); + }); + }); + + QUnit.test('nested params recognizeAndLoad', function (assert) { + routes = { + postIndex: createHandler('postIndex'), + showFilteredPosts: createHandler('showFilteredPosts', { + model(params: { filter_id: string }) { + return { name: 'showFilteredPosts', data: params['filter_id'] }; + }, + }), + }; + assert.notOk(router.activeTransition, 'Does not start with an active transition'); + + router.replaceURL = () => { + assert.ok(false, 'Should not replace the URL'); + }; + + router.updateURL = () => { + assert.ok(false, 'Should not update the URL'); + }; + + router + .recognizeAndLoad('/posts/filter/1') + .then((routeInfoWithAttributes: RouteInfoWithAttributes) => { + assert.notOk(router.activeTransition, 'Does not create an active transition'); + if (routeInfoWithAttributes === null) { + assert.ok(false); + return; + } + assert.equal(routeInfoWithAttributes.name, 'showFilteredPosts'); + assert.equal(routeInfoWithAttributes.localName, 'showFilteredPosts'); + assert.equal(routeInfoWithAttributes.parent!.name, 'postIndex'); + assert.equal(routeInfoWithAttributes.child, null); + assert.deepEqual(routeInfoWithAttributes.attributes, { + name: 'showFilteredPosts', + data: '1', + }); + assert.deepEqual(routeInfoWithAttributes.queryParams, {}); + assert.deepEqual(routeInfoWithAttributes.params, { filter_id: '1' }); + assert.deepEqual(routeInfoWithAttributes.paramNames, ['filter_id']); + }); + }); + + QUnit.test('top-level QPs recognizeAndLoad', function (assert) { + routes = { + showAllPosts: createHandler('showAllPosts', { + model() { + return { name: 'showAllPosts', data: 'qp' }; + }, + }), + }; + assert.notOk(router.activeTransition, 'Does not start with an active transition'); + + router.replaceURL = () => { + assert.ok(false, 'Should not replace the URL'); + }; + + router.updateURL = () => { + assert.ok(false, 'Should not update the URL'); + }; + + router + .recognizeAndLoad('/posts/?a=b') + .then((routeInfoWithAttributes: RouteInfoWithAttributes) => { + assert.notOk(router.activeTransition, 'Does not create an active transition'); + if (routeInfoWithAttributes === null) { + assert.ok(false); + return; + } + assert.equal(routeInfoWithAttributes.name, 'showAllPosts'); + assert.equal(routeInfoWithAttributes.localName, 'showAllPosts'); + assert.equal(routeInfoWithAttributes.parent!.name, 'postIndex'); + assert.equal(routeInfoWithAttributes.child, null); + assert.deepEqual(routeInfoWithAttributes.attributes, { + name: 'showAllPosts', + data: 'qp', + }); + assert.deepEqual(routeInfoWithAttributes.queryParams, { a: 'b' }); + assert.deepEqual(routeInfoWithAttributes.params, {}); + assert.deepEqual(routeInfoWithAttributes.paramNames, []); + }); + }); + + QUnit.test('top-level params and QPs recognizeAndLoad', function (assert) { + routes = { + postsIndex: createHandler('postsIndex'), + showFilteredPosts: createHandler('showFilteredPosts', { + model(params: { filter_id: string }) { + return { name: 'showFilteredPosts', data: params['filter_id'] }; + }, + }), + }; + assert.notOk(router.activeTransition, 'Does not start with an active transition'); + + router.replaceURL = () => { + assert.ok(false, 'Should not replace the URL'); + }; + + router.updateURL = () => { + assert.ok(false, 'Should not update the URL'); + }; + + router + .recognizeAndLoad('/posts/filter/123?a=b') + .then((routeInfoWithAttributes: RouteInfoWithAttributes) => { + assert.notOk(router.activeTransition, 'Does not create an active transition'); + if (routeInfoWithAttributes === null) { + assert.ok(false); + return; + } + assert.equal(routeInfoWithAttributes.name, 'showFilteredPosts'); + assert.equal(routeInfoWithAttributes.localName, 'showFilteredPosts'); + assert.equal(routeInfoWithAttributes.parent!.name, 'postIndex'); + assert.equal(routeInfoWithAttributes.child, null); + assert.deepEqual(routeInfoWithAttributes.attributes, { + name: 'showFilteredPosts', + data: '123', + }); + assert.deepEqual(routeInfoWithAttributes.queryParams, { a: 'b' }); + assert.deepEqual(routeInfoWithAttributes.params, { filter_id: '123' }); + assert.deepEqual(routeInfoWithAttributes.paramNames, ['filter_id']); + }); + }); + + QUnit.test('unrecognized url rejects', function (assert) { + router.recognizeAndLoad('/fixzzz').then( + () => { + assert.ok(false, 'never here'); + }, + (reason: string) => { + assert.equal(reason, `URL /fixzzz was not recognized`); + } + ); + }); + + QUnit.test('top-level recognize url', function (assert) { + map(assert, function (match) { + match('/').to('index'); + }); + + routes = { + post: createHandler('post'), + }; + assert.notOk(router.activeTransition, 'Does not start with an active transition'); + let routeInfo = router.recognize('/'); + + assert.notOk(router.activeTransition, 'Does not create an active transition'); + + if (routeInfo === null) { + assert.ok(false); + return; + } + + router.replaceURL = () => { + assert.ok(false, 'Should not replace the URL'); + }; + + router.updateURL = () => { + assert.ok(false, 'Should not update the URL'); + }; + + assert.equal(routeInfo.name, 'index'); + assert.equal(routeInfo.localName, 'index'); + assert.equal(routeInfo.parent, null); + assert.equal(routeInfo.child, null); + assert.deepEqual(routeInfo.queryParams, {}); + assert.deepEqual(routeInfo.params, {}); + assert.deepEqual(routeInfo.paramNames, []); + }); + + QUnit.test('top-level recognize url with params', function (assert) { + map(assert, function (match) { + match('/posts/:id').to('post'); + }); + + routes = { + post: createHandler('post'), + }; + + assert.notOk(router.activeTransition, 'Does not start with an active transition'); + + let routeInfo = router.recognize('/posts/123'); + + assert.notOk(router.activeTransition, 'Does not create an active transition'); + + if (routeInfo === null) { + assert.ok(false); + return; + } + + router.replaceURL = () => { + assert.ok(false, 'Should not replace the URL'); + }; + + router.updateURL = () => { + assert.ok(false, 'Should not update the URL'); + }; + + assert.equal(routeInfo.name, 'post'); + assert.equal(routeInfo.localName, 'post'); + assert.equal(routeInfo.parent, null); + assert.equal(routeInfo.child, null); + assert.deepEqual(routeInfo.queryParams, {}); + assert.deepEqual(routeInfo.params, { id: '123' }); + assert.deepEqual(routeInfo.paramNames, ['id']); + }); + + QUnit.test('nested recognize url', function (assert) { + routes = { + postIndex: createHandler('postIndex'), + showPopularPosts: createHandler('showPopularPosts'), + }; + assert.notOk(router.activeTransition, 'Does not start with an active transition'); + + let routeInfo = router.recognize('/posts/popular'); + + assert.notOk(router.activeTransition, 'Does not create an active transition'); + + if (routeInfo === null) { + assert.ok(false); + return; + } + + router.replaceURL = () => { + assert.ok(false, 'Should not replace the URL'); + }; + + router.updateURL = () => { + assert.ok(false, 'Should not update the URL'); + }; + + assert.equal(routeInfo.name, 'showPopularPosts'); + assert.equal(routeInfo.localName, 'showPopularPosts'); + assert.equal(routeInfo.parent!.name, 'postIndex'); + assert.equal(routeInfo.child, null); + assert.deepEqual(routeInfo.queryParams, {}); + assert.deepEqual(routeInfo.params, {}); + assert.deepEqual(routeInfo.paramNames, []); + }); + + QUnit.test('nested recognize url with params', function (assert) { + routes = { + postIndex: createHandler('postIndex'), + showFilteredPosts: createHandler('showFilteredPosts'), + }; + assert.notOk(router.activeTransition, 'Does not start with an active transition'); + + let routeInfo = router.recognize('/posts/filter/123'); + + assert.notOk(router.activeTransition, 'Does not create an active transition'); + + if (routeInfo === null) { + assert.ok(false); + return; + } + + router.replaceURL = () => { + assert.ok(false, 'Should not replace the URL'); + }; + + router.updateURL = () => { + assert.ok(false, 'Should not update the URL'); + }; + + assert.equal(routeInfo.name, 'showFilteredPosts'); + assert.equal(routeInfo.localName, 'showFilteredPosts'); + assert.equal(routeInfo.parent!.name, 'postIndex'); + assert.equal(routeInfo.child, null); + assert.deepEqual(routeInfo.queryParams, {}); + assert.deepEqual(routeInfo.params, { filter_id: '123' }); + assert.deepEqual(routeInfo.paramNames, ['filter_id']); + }); + + QUnit.test('top-level recognize url with QPs', function (assert) { + map(assert, function (match) { + match('/').to('index'); + }); + + routes = { + index: createHandler('index'), + }; + + assert.notOk(router.activeTransition, 'Does not start with an active transition'); + + let routeInfo = router.recognize('/?a=123'); + + assert.notOk(router.activeTransition, 'Does not create an active transition'); + + if (routeInfo === null) { + assert.ok(false); + return; + } + + router.replaceURL = () => { + assert.ok(false, 'Should not replace the URL'); + }; + + router.updateURL = () => { + assert.ok(false, 'Should not update the URL'); + }; + + assert.equal(routeInfo.name, 'index'); + assert.equal(routeInfo.localName, 'index'); + assert.equal(routeInfo.parent, null); + assert.equal(routeInfo.child, null); + assert.deepEqual(routeInfo.queryParams, { a: '123' }); + assert.deepEqual(routeInfo.params, {}); + assert.deepEqual(routeInfo.paramNames, []); + }); + + QUnit.test('nested recognize url with QPs', function (assert) { + routes = { + postIndex: createHandler('postIndex'), + showPopularPosts: createHandler('showPopularPosts'), + }; + + assert.notOk(router.activeTransition, 'Does not start with an active transition'); + + let routeInfo = router.recognize('/posts/popular?fizz=bar'); + + assert.notOk(router.activeTransition, 'Does not create an active transition'); + + if (routeInfo === null) { + assert.ok(false); + return; + } + + router.replaceURL = () => { + assert.ok(false, 'Should not replace the URL'); + }; + + router.updateURL = () => { + assert.ok(false, 'Should not update the URL'); + }; + + assert.equal(routeInfo.name, 'showPopularPosts'); + assert.equal(routeInfo.localName, 'showPopularPosts'); + assert.equal(routeInfo.parent!.name, 'postIndex'); + assert.equal(routeInfo.child, null); + assert.deepEqual(routeInfo.queryParams, { fizz: 'bar' }); + assert.deepEqual(routeInfo.params, {}); + assert.deepEqual(routeInfo.paramNames, []); + }); + + QUnit.test('nested recognize url with QPs and params', function (assert) { + routes = { + postIndex: createHandler('postIndex'), + showFilteredPosts: createHandler('showFilteredPosts'), + }; + + assert.notOk(router.activeTransition, 'Does not start with an active transition'); + + let routeInfo = router.recognize('/posts/filter/123?fizz=bar'); + + assert.notOk(router.activeTransition, 'Does not create an active transition'); + + if (routeInfo === null) { + assert.ok(false); + return; + } + + router.replaceURL = () => { + assert.ok(false, 'Should not replace the URL'); + }; + + router.updateURL = () => { + assert.ok(false, 'Should not update the URL'); + }; + + assert.equal(routeInfo.name, 'showFilteredPosts'); + assert.equal(routeInfo.localName, 'showFilteredPosts'); + assert.equal(routeInfo.parent!.name, 'postIndex'); + assert.equal(routeInfo.child, null); + assert.deepEqual(routeInfo.queryParams, { fizz: 'bar' }); + assert.deepEqual(routeInfo.params, { filter_id: '123' }); + assert.deepEqual(routeInfo.paramNames, ['filter_id']); + }); + + QUnit.test('unrecognized url returns null', function (assert) { + map(assert, function (match) { + match('/').to('index'); + match('/posts/:id').to('post'); + }); + + routes = { + post: createHandler('post'), + }; + let routeInfo = router.recognize('/fixzzz'); + assert.equal(routeInfo, null, 'Unrecognized url'); + }); + + QUnit.test('basic route change events with nested params', function (assert) { + assert.expect(14); + map(assert, function (match) { + match('/').to('index'); + match('/posts/:id/foo').to('post'); + }); + + let enteredWillChange = 0; + let enteredDidChange = 0; + routes = { + post: createHandler('post'), + }; + + let newParam = false; + + router.routeWillChange = (transition: Transition) => { + enteredWillChange++; + if (newParam) { + assert.equal(transition.to!.localName, 'post'); + assert.equal(isPresent(transition.from) && transition.from.localName, 'post'); + assert.deepEqual(transition.to!.params, { id: '2' }); + } else { + assert.equal(transition.to!.localName, 'post'); + assert.equal(transition.from, null); + assert.deepEqual(transition.to!.params, { id: '1' }); + } + }; + + router.routeDidChange = (transition: Transition) => { + enteredDidChange++; + if (newParam) { + assert.equal(transition.to!.localName, 'post'); + assert.equal(isPresent(transition.from) && transition.from.localName, 'post'); + assert.deepEqual(transition.to!.params, { id: '2' }); + } else { + assert.equal(transition.to!.localName, 'post'); + assert.equal(transition.from, null); + assert.deepEqual(transition.to!.params, { id: '1' }); + } + }; + + router + .transitionTo('/posts/1/foo') + .then(() => { + newParam = true; + return router.transitionTo('/posts/2/foo'); + }) + .then(() => { + assert.equal(enteredWillChange, 2); + assert.equal(enteredDidChange, 2); + }); + }); + + QUnit.test('basic route change events with query params', function (assert) { + assert.expect(20); + map(assert, function (match) { + match('/').to('index'); + match('/posts/:id').to('post'); + }); + + let enteredWillChange = 0; + let enteredDidChange = 0; + routes = { + post: createHandler('post'), + }; + + let newParam = false; + + router.routeWillChange = (transition: Transition) => { + enteredWillChange++; + if (newParam) { + assert.equal(transition.to!.localName, 'post'); + assert.equal(isPresent(transition.from) && transition.from.localName, 'post'); + assert.deepEqual(transition.to!.queryParams, { trk: 'b' }); + assert.deepEqual(isPresent(transition.from) && transition.from!.queryParams, { trk: 'a' }); + } else { + assert.equal(transition.to!.localName, 'post'); + assert.equal(transition.from, null); + assert.deepEqual(transition.to!.queryParams, { trk: 'a' }); + } + + assert.deepEqual(transition.to!.params, { id: '1' }); + }; + + router.routeDidChange = (transition: Transition) => { + enteredDidChange++; + if (newParam) { + assert.equal(transition.to!.localName, 'post'); + assert.equal(isPresent(transition.from) && transition.from.localName, 'post'); + assert.deepEqual(transition.to!.queryParams, { trk: 'b' }); + assert.deepEqual(isPresent(transition.from) && transition.from!.queryParams, { trk: 'a' }); + } else { + assert.equal(transition.to!.localName, 'post'); + assert.equal(transition.from, null); + assert.deepEqual(transition.to!.queryParams, { trk: 'a' }); + } + + assert.deepEqual(transition.to!.params, { id: '1' }); + }; + + router + .transitionTo('/posts/1?trk=a') + .then(() => { + newParam = true; + return router.transitionTo('/posts/1?trk=b'); + }) + .then(() => { + assert.equal(enteredWillChange, 2); + assert.equal(enteredDidChange, 2); + }); + }); + + QUnit.test('basic route to one with query params', function (assert) { + assert.expect(8); + map(assert, function (match) { + match('/').to('index'); + match('/search').to('search'); + }); + + routes = { + search: createHandler('search'), + }; + + let newParam = false; + + router.routeWillChange = (transition: Transition) => { + if (newParam) { + assert.deepEqual(transition.to!.queryParams, { term: 'b' }, 'going to page with qps'); + assert.deepEqual( + isPresent(transition.from) && transition.from!.queryParams, + {}, + 'from never has qps' + ); + } else { + assert.equal(transition.from, null); + assert.deepEqual(transition.to!.queryParams, {}); + } + }; + + router.routeDidChange = (transition: Transition) => { + if (newParam) { + assert.deepEqual(transition.to!.queryParams, { term: 'b' }); + assert.deepEqual(isPresent(transition.from) && transition.from!.queryParams, {}); + } else { + assert.equal(transition.from, null); + assert.deepEqual(transition.to!.queryParams, {}); + } + }; + + router.transitionTo('/').then(() => { + newParam = true; + return router.transitionTo('search', { queryParams: { term: 'b' } }); + }); + }); + + QUnit.test( + 'calling recognize should not affect the transition.from query params for subsequent transitions', + function (assert) { + assert.expect(12); + map(assert, function (match) { + match('/').to('index'); + match('/search').to('search'); + }); + + routes = { + search: createHandler('search'), + }; + + let firstParam = false; + let secondParam = false; + + router.routeWillChange = (transition: Transition) => { + if (secondParam) { + assert.deepEqual( + transition.to!.queryParams, + { term: 'c' }, + 'going to next page with qps' + ); + assert.deepEqual( + isPresent(transition.from) && transition.from!.queryParams, + { term: 'b' }, + 'has previous qps' + ); + } else if (firstParam) { + assert.deepEqual(transition.to!.queryParams, { term: 'b' }, 'going to page with qps'); + assert.deepEqual( + isPresent(transition.from) && transition.from!.queryParams, + {}, + 'from never has qps' + ); + } else { + assert.equal(transition.from, null); + assert.deepEqual(transition.to!.queryParams, {}); + } + }; + + router.routeDidChange = (transition: Transition) => { + if (secondParam) { + assert.deepEqual(transition.to!.queryParams, { term: 'c' }); + assert.deepEqual(isPresent(transition.from) && transition.from!.queryParams, { + term: 'b', + }); + } else if (firstParam) { + assert.deepEqual(transition.to!.queryParams, { term: 'b' }); + assert.deepEqual(isPresent(transition.from) && transition.from!.queryParams, {}); + } else { + assert.equal(transition.from, null); + assert.deepEqual(transition.to!.queryParams, {}); + } + }; + + router + .transitionTo('/') + .then(() => { + firstParam = true; + return router.transitionTo('search', { queryParams: { term: 'b' } }); + }) + .then(() => { + secondParam = true; + router.recognize('/search?wat=foo'); + return router.transitionTo({ queryParams: { term: 'c' } }); + }); + } + ); + + QUnit.test('redirects route events', function (assert) { + assert.expect(19); + map(assert, function (match) { + match('/').to('index'); + match('/posts', function (match) { + match('/:id').to('post'); + match('/details').to('postDetails'); + }); + match('/foo', function (match) { + match('/').to('foo', function (match) { + match('/bar').to('bar'); + }); + }); + match('/ok').to('ok'); + }); + + let redirected1 = false; + let redirected2 = false; + let initial = true; + let enteredWillChange = 0; + let enteredDidChange = 0; + + routes = { + post: createHandler('post', { + model() { + redirected1 = true; + router.transitionTo('/foo/bar'); + }, + }), + foo: createHandler('foo', { + model() { + redirected1 = false; + redirected2 = true; + router.transitionTo('/ok'); + }, + }), + ok: createHandler('ok'), + bar: createHandler('bar'), + postDetails: createHandler('postDetails'), + }; + + router.routeWillChange = (transition: Transition) => { + enteredWillChange++; + if (initial) { + assert.equal(transition.to!.localName, 'index'); + assert.equal(transition.from!, null); + assert.equal(transition.to!.parent, null); + } else if (redirected1) { + assert.equal(transition.to!.localName, 'bar'); + assert.equal(isPresent(transition.from) && transition.from.localName, 'index'); + assert.equal(transition.to!.parent!.localName, 'foo'); + } else if (redirected2) { + assert.equal(transition.to!.localName, 'ok'); + assert.equal(isPresent(transition.from) && transition.from.localName, 'index'); + assert.equal(transition.to!.parent!, null); + } else { + assert.equal(transition.to!.localName, 'post'); + assert.equal(isPresent(transition.from) && transition.from.localName, 'index'); + assert.equal(transition.to!.parent, null); + } + }; + + router.routeDidChange = (transition: Transition) => { + enteredDidChange++; + if (initial) { + assert.equal(transition.to!.localName, 'index'); + assert.equal(transition.from!, null); + initial = false; + } else { + assert.equal(transition.to!.localName, 'ok'); + assert.equal(isPresent(transition.from) && transition.from.localName, 'index'); + } + }; + + router + .transitionTo('/') + .then(() => { + return router.transitionTo('/posts/1'); + }) + .catch((err: any) => { + console.log(err); + assert.equal(err.name, 'TransitionAborted'); + return router.activeTransition as any; + }) + .then(() => { + assert.equal(enteredWillChange, 4); + assert.equal(enteredDidChange, 2); + }); + }); + + QUnit.test('abort route events', function (assert) { + assert.expect(19); + map(assert, function (match) { + match('/').to('index'); + match('/posts', function (match) { + match('/:id').to('post'); + match('/details').to('postDetails'); + }); + match('/foo', function (match) { + match('/').to('foo', function (match) { + match('/bar').to('bar'); + }); + }); + }); + + let redirected = false; + let initial = true; + let aborted = false; + let enteredWillChange = 0; + let enteredDidChange = 0; + + routes = { + post: createHandler('post', { + model() { + redirected = true; + router.transitionTo('/foo/bar'); + }, + }), + foo: createHandler('foo', { + model(_model: any, transition: Transition) { + aborted = true; + redirected = false; + transition.abort(); + }, + }), + bar: createHandler('bar'), + postDetails: createHandler('postDetails'), + }; + + router.routeWillChange = (transition: Transition) => { + enteredWillChange++; + if (initial) { + assert.equal(transition.to!.localName, 'index'); + assert.equal(transition.from!, null); + assert.equal(transition.to!.parent, null); + } else if (redirected) { + assert.equal(transition.to!.localName, 'bar'); + assert.equal(isPresent(transition.from) && transition.from.localName, 'index'); + assert.equal(transition.to!.parent!.localName, 'foo'); + } else if (aborted) { + assert.true(transition.isAborted); + assert.equal(transition.to, transition.from); + assert.equal(transition.to!.localName, 'index'); + } else { + assert.equal(transition.to!.localName, 'post'); + assert.equal(isPresent(transition.from) && transition.from.localName, 'index'); + assert.equal(transition.to!.parent, null); + } + }; + + router.routeDidChange = (transition: Transition) => { + enteredDidChange++; + if (initial) { + assert.equal(transition.to!.localName, 'index'); + assert.equal(transition.from!, null); + initial = false; + } else { + assert.equal(transition.to!.localName, 'index'); + assert.equal(isPresent(transition.from) && transition.from.localName, 'index'); + } + }; + + router + .transitionTo('/') + .then(() => { + return router.transitionTo('/posts/1'); + }) + .catch((err: any) => { + assert.equal(err.name, 'TransitionAborted'); + return router.activeTransition as any; + }) + .then(() => { + assert.equal(enteredWillChange, 4); + assert.equal(enteredDidChange, 2); + }); + }); + + QUnit.test('abort query param only', function (assert) { + assert.expect(6); + map(assert, function (match) { + match('/').to('index'); + }); + + routes = { + search: createHandler('search'), + }; + + let newParam = false; + let initial = true; + + router.updateURL = function (updateUrl) { + url = updateUrl; + if (!initial) { + assert.ok(false, 'updateURL should not be called'); + } + }; + + router.routeWillChange = (transition: Transition) => { + if (!transition.isAborted) { + if (newParam) { + assert.deepEqual(transition.to!.queryParams, { term: 'b' }, 'going to page with qps'); + assert.deepEqual( + isPresent(transition.from) && transition.from!.queryParams, + {}, + 'from never has qps' + ); + } else { + assert.strictEqual(transition.from, null, 'null transition from'); + assert.deepEqual(transition.to!.queryParams, {}, 'empty transition queryParams'); + } + } + if (!initial) { + if (!transition.isAborted) { + newParam = false; + transition.abort(); + } + } + }; + + router.routeDidChange = (transition: Transition) => { + if (!transition.isAborted) { + assert.strictEqual(transition.from, null, 'routeDidChange null from transition'); + assert.deepEqual(transition.to!.queryParams, {}, 'routeDidChange empty queryParams'); + } + }; + + router.transitionTo('/').then(() => { + newParam = true; + initial = false; + return router.transitionTo({ queryParams: { term: 'b' } }); + }); + }); + + QUnit.test('always has a transition through the substates', function (assert) { + map(assert, function (match) { + match('/').to('index'); + match('/posts', function (match) { + match('/:id').to('post'); + match('/details').to('postDetails'); + }); + match('/foo', function (match) { + match('/').to('foo', function (match) { + match('/bar').to('bar'); + }); + }); + match('/err').to('fooError'); + }); + + let enterSubstate = false; + let initial = true; + let isAborted = false; + let errorHandled = false; + let enteredWillChange = 0; + let enteredDidChange = 0; + + routes = { + post: createHandler('post', { + beforeModel(transition: Transition) { + isAborted = true; + transition.abort(); + enterSubstate = true; + router.intermediateTransitionTo('fooError'); + }, + }), + foo: createHandler('foo'), + }; + + router.transitionDidError = (error: TransitionError, transition: Transition) => { + if (error.wasAborted || transition.isAborted) { + return logAbort(transition); + } else { + transition.trigger(false, 'error', error.error, transition, error.route); + if (errorHandled) { + transition.rollback(); + router.routeDidChange(transition); + return transition; + } else { + transition.abort(); + return error.error; + } + } + }; + + router.routeWillChange = (transition: Transition) => { + enteredWillChange++; + if (initial) { + assert.equal(transition.to!.localName, 'index', 'initial'); + assert.equal(transition.from!, null, 'initial'); + assert.equal(transition.to!.parent, null, 'initial'); + } else if (isAborted) { + assert.equal(transition.to!.localName, 'index', 'aborted'); + assert.equal(isPresent(transition.from) && transition.from!.localName, 'index', 'aborted'); + } else if (enterSubstate) { + assert.equal(transition.to!.localName, 'fooError', 'substate'); + assert.equal(isPresent(transition.from) && transition.from!.localName, 'index', 'substate'); + if (transition.to?.parent) { + assert.equal(transition.to.parent.localName, 'foo', 'substate'); + } + } else { + assert.equal(transition.to!.localName, 'post', 'to post'); + assert.equal(isPresent(transition.from) && transition.from!.localName, 'index', 'to post'); + assert.equal(transition.to!.parent, null, 'to post'); + } + }; + + router.routeDidChange = (transition: Transition) => { + enteredDidChange++; + if (initial) { + assert.equal(transition.to!.localName, 'index', 'initial'); + assert.equal(transition.from!, null, 'initial'); + initial = false; + } else if (isAborted) { + assert.equal(transition.to!.localName, 'index', 'aborted'); + assert.equal(isPresent(transition.from) && transition.from!.localName, 'index', 'aborted'); + isAborted = false; + } else { + assert.equal(transition.to!.localName, 'bar'); + assert.equal(isPresent(transition.from) && transition.from!.localName, 'index'); + } + }; + + router + .transitionTo('/') + .then(() => { + return router.transitionTo('/posts/1'); + }) + .catch((err: any) => { + assert.equal(err.name, 'TransitionAborted'); + return router.activeTransition as any; + }) + .finally(() => { + assert.equal(enteredWillChange, 4); + assert.equal(enteredDidChange, 2); + }); + }); + + QUnit.test('error route events', function (assert) { + map(assert, function (match) { + match('/').to('index'); + match('/posts', function (match) { + match('/:id').to('post'); + match('/details').to('postDetails'); + }); + match('/foo', function (match) { + match('/').to('foo', function (match) { + match('/bar').to('bar'); + }); + }); + match('/err').to('fooError'); + }); + + let redirected = false; + let initial = true; + let errored = false; + let errorHandled = false; + let enteredWillChange = 0; + let enteredDidChange = 0; + + routes = { + post: createHandler('post', { + model() { + redirected = true; + router.transitionTo('/foo/bar'); + }, + }), + foo: createHandler('foo', { + model() { + errored = true; + redirected = false; + throw new Error('boom'); + }, + events: { + error() { + errorHandled = true; + router.intermediateTransitionTo('fooError'); + }, + }, + }), + fooError: createHandler('fooError'), + bar: createHandler('bar'), + postDetails: createHandler('postDetails'), + }; + + router.transitionDidError = (error: TransitionError, transition: Transition) => { + if (error.wasAborted || transition.isAborted) { + return logAbort(transition); + } else { + transition.trigger(false, 'error', error.error, transition, error.route); + if (errorHandled) { + transition.rollback(); + router.toInfos(transition, router.state!.routeInfos, true); + router.routeDidChange(transition); + return transition; + } else { + transition.abort(); + return error.error; + } + } + }; + + router.routeWillChange = (transition: Transition) => { + enteredWillChange++; + if (initial) { + assert.equal(transition.to!.localName, 'index'); + assert.equal(transition.from!, null); + assert.equal(transition.to!.parent, null); + } else if (redirected) { + assert.equal(transition.to!.localName, 'bar'); + assert.equal(isPresent(transition.from) && transition.from!.localName, 'index'); + assert.equal(transition.to!.parent!.localName, 'foo'); + } else if (errored) { + assert.false(transition.isAborted); + assert.equal(isPresent(transition.from) && transition.from!.localName, 'index'); + assert.equal(transition.to!.localName, 'fooError'); + } else { + assert.equal(transition.to!.localName, 'post'); + assert.equal(isPresent(transition.from) && transition.from!.localName, 'index'); + assert.equal(transition.to!.parent, null); + } + }; + + router.routeDidChange = (transition: Transition) => { + enteredDidChange++; + if (initial) { + assert.equal(transition.to!.localName, 'index'); + assert.equal(transition.from!, null); + initial = false; + } else { + assert.equal(transition.to!.localName, 'fooError'); + assert.equal(isPresent(transition.from) && transition.from!.localName, 'index'); + } + }; + + const transition = router + .transitionTo('/') + .then(() => { + return router.transitionTo('/posts/1'); + }) + .catch((err: any) => { + assert.equal(err.name, 'TransitionAborted'); + return router.activeTransition as any; + }) + .finally(() => { + assert.equal(enteredWillChange, 4); + assert.equal(enteredDidChange, 2); + }); + + assert.rejects(transition); + }); + + QUnit.test( + "when transitioning to a new parent and child state, the parent's context should be available to the child's model", + function (assert) { + type Post = IModel; + + assert.expect(1); + let contexts: Array = []; + + map(assert, function (match) { + match('/').to('index'); + match('/posts/:id').to('post', function (match) { + match('/details').to('postDetails'); + }); + }); + + routes = { + post: createHandler('post', { + model: function () { + return contexts; + }, + }), + + postDetails: createHandler('postDetails', { + name: 'postDetails', + afterModel: function (_model: Post, transition: Transition) { + contexts.push(transition.resolvedModels['post'] as Post | undefined); + }, + }), + }; + + router + .handleURL('/') + .then(function () { + // This is a crucial part of the test + // In some cases, calling `generate` was preventing `model` from being called + router.generate('postDetails', { id: 1 }); + + return router.transitionTo('postDetails', { id: 1 }); + }, shouldNotHappen(assert)) + .then(function (value) { + assert.deepEqual(contexts, [{ id: 1 }], 'parent context is available'); + return value; + }, shouldNotHappen(assert)); + } + ); + + QUnit.test('handleURL: Handling a nested URL triggers each handler', function (assert) { + assert.expect(37); + + let posts: Dict[] = []; + let allPosts = { all: true }; + let popularPosts = { popular: true }; + let amazingPosts = { id: 'amazing' }; + let sadPosts = { id: 'sad' }; + + let counter = 0; + + let postIndexHandler = createHandler('postIndex', { + model: function (params: Dict, transition: Transition) { + assert.equal(transition.from, null, 'initial transition'); + assert.equal(transition.to && transition.to.localName, 'showAllPosts', 'going to leaf'); + // this will always get called, since it's at the root + // of all of the routes tested here + assert.deepEqual( + params, + { queryParams: {} }, + 'params should be empty in postIndexHandler#model' + ); + return posts; + }, + + setup: function (context: unknown) { + if (counter === 0) { + assert.equal( + postIndexHandler.context, + posts, + 'postIndexHandler context should be set up in postIndexHandler#setup' + ); + assert.strictEqual( + context, + posts, + 'The object passed in to postIndexHandler#setup should be posts' + ); + } else { + assert.ok(false, 'Should not get here'); + } + }, + }); + + let showAllPostsHandler = createHandler('showAllPosts', { + model(params: Dict, transition: Transition) { + if (counter > 0 && counter < 4) { + assert.equal( + postIndexHandler.context, + posts, + 'postIndexHandler context should be set up in showAllPostsHandler#model' + ); + } + + if (counter < 4) { + assert.equal(transition.from, null, 'initial transition'); + assert.equal(transition.to && transition.to.localName, 'showAllPosts', 'at leaf'); + assert.deepEqual( + params, + { queryParams: {} }, + 'params should be empty in showAllPostsHandler#model' + ); + return allPosts; + } else { + assert.ok(false, 'Should not get here'); + } + + return; + }, + + setup(context: Dict) { + if (counter === 0) { + assert.equal( + postIndexHandler.context, + posts, + 'postIndexHandler context should be set up in showAllPostsHandler#setup' + ); + assert.equal( + showAllPostsHandler.context, + allPosts, + 'showAllPostsHandler context should be set up in showAllPostsHandler#setup' + ); + assert.strictEqual( + context, + allPosts, + 'The object passed in should be allPosts in showAllPostsHandler#setup' + ); + } else { + assert.ok(false, 'Should not get here'); + } + }, + }); + + let showPopularPostsHandler = createHandler('showPopularPosts', { + model: function (params: Dict) { + if (counter < 3) { + assert.ok(false, 'Should not get here'); + } else if (counter === 3) { + assert.equal( + postIndexHandler.context, + posts, + 'postIndexHandler context should be set up in showPopularPostsHandler#model' + ); + assert.deepEqual( + params, + { queryParams: {} }, + 'params should be empty in showPopularPostsHandler#serialize' + ); + return popularPosts; + } else { + assert.ok(false, 'Should not get here'); + } + + return; + }, + + setup: function (context: Dict) { + if (counter === 3) { + assert.equal( + postIndexHandler.context, + posts, + 'postIndexHandler context should be set up in showPopularPostsHandler#setup' + ); + assert.equal( + showPopularPostsHandler.context, + popularPosts, + 'showPopularPostsHandler context should be set up in showPopularPostsHandler#setup' + ); + assert.strictEqual( + context, + popularPosts, + 'The object passed to showPopularPostsHandler#setup should be popular posts' + ); + } else { + assert.ok(false, 'Should not get here'); + } + }, + }); + + let showFilteredPostsHandler = createHandler('showFilteredPosts', { + model: function (params: Dict, transition: Transition) { + if (counter < 4) { + assert.ok(false, 'Should not get here'); + } else if (counter === 4) { + assert.equal(transition.from && transition.from.localName, 'showPopularPosts'); + assert.equal( + postIndexHandler.context, + posts, + 'postIndexHandler context should be set up in showFilteredPostsHandler#model' + ); + assert.deepEqual( + params, + { filter_id: 'amazing', queryParams: {} }, + "params should be { filter_id: 'amazing' } in showFilteredPostsHandler#model" + ); + return amazingPosts; + } else if (counter === 5) { + assert.equal( + transition.from && transition.from.localName, + 'showFilteredPosts', + 'came from same route' + ); + assert.equal( + transition.to && transition.to.localName, + 'showFilteredPosts', + 'going to same route' + ); + assert.equal(transition.from?.params?.['filter_id'], 'amazing', 'old params'); + assert.equal(transition.to?.params?.['filter_id'], 'sad', 'new params'); + assert.equal( + postIndexHandler.context, + posts, + 'postIndexHandler context should be posts in showFilteredPostsHandler#model' + ); + assert.deepEqual( + params, + { filter_id: 'sad', queryParams: {} }, + "params should be { filter_id: 'sad' } in showFilteredPostsHandler#model" + ); + return sadPosts; + } else { + assert.ok(false, 'Should not get here'); + } + + return; + }, + + setup: function (context: Dict) { + if (counter === 4) { + assert.equal(postIndexHandler.context, posts); + assert.equal(showFilteredPostsHandler.context, amazingPosts); + assert.strictEqual(context, amazingPosts); + } else if (counter === 5) { + assert.equal(postIndexHandler.context, posts); + assert.equal(showFilteredPostsHandler.context, sadPosts); + assert.strictEqual(context, sadPosts); + } else { + assert.ok(false, 'Should not get here'); + } + }, + }); + + routes = { + postIndex: postIndexHandler, + showAllPosts: showAllPostsHandler, + showPopularPosts: showPopularPostsHandler, + showFilteredPosts: showFilteredPostsHandler, + }; + + router + .transitionTo('/posts') + .then(function () { + assert.ok(true, '1: Finished, trying /posts/all'); + counter++; + return router.transitionTo('/posts/all'); + }, shouldNotHappen(assert)) + .then(function () { + assert.ok(true, '2: Finished, trying /posts'); + counter++; + return router.transitionTo('/posts'); + }, shouldNotHappen(assert)) + .then(function () { + assert.ok(true, '3: Finished, trying /posts/popular'); + counter++; + return router.transitionTo('/posts/popular'); + }, shouldNotHappen(assert)) + .then(function () { + assert.ok(true, '4: Finished, trying /posts/filter/amazing'); + counter++; + return router.transitionTo('/posts/filter/amazing'); + }, shouldNotHappen(assert)) + .then(function () { + assert.ok(true, '5: Finished, trying /posts/filter/sad'); + counter++; + return router.transitionTo('/posts/filter/sad'); + }, shouldNotHappen(assert)) + .then(function () { + assert.ok(true, '6: Finished!'); + }, shouldNotHappen(assert)); + }); + + QUnit.test('it can handle direct transitions to named routes', function (assert) { + let allPosts = { all: true }; + let popularPosts = { popular: true }; + let amazingPosts = { filter: 'amazing' }; + let sadPosts = { filter: 'sad' }; + + let postIndexHandler = createHandler('postIndex', { + model: function () { + return allPosts; + }, + + serialize: function () { + return {}; + }, + }); + + let showAllPostsHandler = createHandler('showAllPosts', { + model: function () { + //assert.ok(!params, 'params is falsy for non dynamic routes'); + return allPosts; + }, + + serialize: function () { + return {}; + }, + + setup: function (context: Dict) { + assert.strictEqual(context, allPosts, 'showAllPosts should get correct setup'); + }, + }); + + let showPopularPostsHandler = createHandler('showPopularPosts', { + model: function () { + return popularPosts; + }, + + serialize: function () { + return {}; + }, + + setup: function (context: Dict) { + assert.strictEqual( + context, + popularPosts, + 'showPopularPosts#setup should be called with the deserialized value' + ); + }, + }); + + let showFilteredPostsHandler = createHandler('showFilteredPosts', { + model: function (params: Dict) { + if (!params) { + return; + } + if (params['filter_id'] === 'amazing') { + return amazingPosts; + } else if (params['filter_id'] === 'sad') { + return sadPosts; + } + return; + }, + + serialize: function (context: Dict, params: string[]) { + assert.deepEqual(params, ['filter_id'], 'showFilteredPosts should get correct serialize'); + return { filter_id: context['filter'] }; + }, + + setup: function (context: Dict) { + if (counter === 2) { + assert.strictEqual( + context, + amazingPosts, + 'showFilteredPosts should get setup with amazingPosts' + ); + } else if (counter === 3) { + assert.strictEqual( + context, + sadPosts, + 'showFilteredPosts should get setup setup with sadPosts' + ); + } + }, + }); + + routes = { + postIndex: postIndexHandler, + showAllPosts: showAllPostsHandler, + showPopularPosts: showPopularPostsHandler, + showFilteredPosts: showFilteredPostsHandler, + }; + + router.updateURL = function (url) { + let expected: Dict = { + 0: '/posts', + 1: '/posts/popular', + 2: '/posts/filter/amazing', + 3: '/posts/filter/sad', + 4: '/posts', + }; + + assert.equal(url, expected[counter], 'updateURL should be called with correct url'); + }; + + let counter = 0; + + router + .handleURL('/posts') + .then(function () { + return router.transitionTo('showAllPosts'); + }, shouldNotHappen(assert)) + .then(function () { + counter++; + return router.transitionTo('showPopularPosts'); + }, shouldNotHappen(assert)) + .then(function () { + counter++; + return router.transitionTo('showFilteredPosts', amazingPosts); + }, shouldNotHappen(assert)) + .then(function () { + counter++; + return router.transitionTo('showFilteredPosts', sadPosts); + }, shouldNotHappen(assert)) + .then(function () { + counter++; + return router.transitionTo('showAllPosts'); + }, shouldNotHappen(assert)); + }); + + QUnit.test('replaceWith calls replaceURL', function (assert) { + let updateCount = 0, + replaceCount = 0; + + router.updateURL = function () { + updateCount++; + }; + + router.replaceURL = function () { + replaceCount++; + }; + + router + .handleURL('/posts') + .then(function () { + return router.replaceWith('about'); + }) + .then(function () { + assert.equal(updateCount, 0, 'should not call updateURL'); + assert.equal(replaceCount, 1, 'should call replaceURL once'); + }); + }); + + QUnit.test( + 'applyIntent returns a tentative state based on a named transition', + async function (assert) { + await router.transitionTo('/posts'); + let state = router.applyIntent('faq', []); + assert.ok(state.routeInfos.length); + } + ); + + QUnit.test('Moving to a new top-level route triggers exit callbacks', function (assert) { + assert.expect(6); + + let allPosts = { posts: 'all' }; + let postsStore: Dict = { 1: { id: 1 }, 2: { id: 2 } }; + let currentId: number; + let currentPath: string; + + routes = { + showAllPosts: createHandler('showAllPosts', { + model: function () { + return allPosts; + }, + + setup: function (posts: Dict, transition: Transition) { + assert.notOk(isExiting(this as unknown as Route, transition.routeInfos)); + assert.equal( + posts, + allPosts, + 'The correct context was passed into showAllPostsHandler#setup' + ); + currentPath = 'postIndex.showAllPosts'; + }, + + exit: function (transition: Transition) { + assert.ok(isExiting(this as unknown as Route, transition.routeInfos)); + }, + }), + + showPost: createHandler('showPost', { + model: function (params: Dict) { + let id = parseInt(params['id'] as string, 10); + return postsStore[id]; + }, + + serialize: function (post: Dict) { + return { id: post['id'] }; + }, + + setup: function (post: Dict) { + currentPath = 'showPost'; + assert.equal(post['id'], currentId, 'The post id is ' + currentId); + }, + }), + }; + + router + .handleURL('/posts') + .then(function () { + expectedUrl = '/posts/1'; + currentId = 1; + return router.transitionTo('showPost', postsStore[1]); + }, shouldNotHappen(assert)) + .then(function () { + assert.equal(routePath(router.currentRouteInfos!), currentPath); + }, shouldNotHappen(assert)); + }); + + QUnit.test('pivotHandler is exposed on Transition object', function (assert) { + assert.expect(3); + + routes = { + showAllPosts: createHandler('showAllPosts', { + beforeModel: function (transition: Transition) { + assert.notOk(transition.pivotHandler, 'First route transition has no pivot route'); + }, + }), + + showPopularPosts: createHandler('showPopularPosts', { + beforeModel: function (transition: Transition) { + assert.equal( + transition.pivotHandler, + routes['postIndex'], + 'showAllPosts -> showPopularPosts pivotHandler is postIndex' + ); + }, + }), + + postIndex: createHandler('postIndex'), + + about: createHandler('about', { + beforeModel: function (transition: Transition) { + assert.notOk(transition.pivotHandler, 'top-level transition has no pivotHandler'); + }, + }), + }; + + router + .handleURL('/posts') + .then(function () { + return router.transitionTo('showPopularPosts'); + }) + .then(function () { + return router.transitionTo('about'); + }); + }); + + QUnit.test('transition.resolvedModels after redirects b/w routes', async function (assert) { + type Application = { app: boolean } & IModel; + + assert.expect(3); + + map(assert, function (match) { + match('/').to('application', function (match) { + match('/peter').to('peter'); + match('/wagenet').to('wagenet'); + }); + }); + + let app = { app: true }; + + routes = { + application: createHandler('application', { + model: function () { + assert.ok(true, 'application#model'); + return app; + }, + }), + + peter: createHandler('peter', { + model: function (_params: Dict, transition: Transition) { + assert.deepEqual( + transition.resolvedModels['application'] as Application, + app, + 'peter: resolvedModel correctly stored in resolvedModels for parent route' + ); + router.transitionTo('wagenet'); + }, + }), + wagenet: createHandler('wagenet', { + model: function (_params: Dict, transition: Transition) { + assert.deepEqual( + transition.resolvedModels['application'] as Application | undefined, + app, + 'wagenet: resolvedModel correctly stored in resolvedModels for parent route' + ); + }, + }), + }; + + return ignoreTransitionError(router.transitionTo('/peter')); + }); + + QUnit.test( + 'transition.resolvedModels after redirects within the same route', + async function (assert) { + type Admin = IModel & { admin: boolean }; + + let admin = { admin: true }, + redirect = true; + + routes = { + admin: createHandler('admin', { + model: function () { + assert.ok(true, 'admin#model'); + return admin; + }, + }), + + adminPosts: createHandler('adminPosts', { + model: function (_params: Dict, transition: Transition) { + assert.deepEqual( + transition.resolvedModels['admin'] as Admin | undefined, + admin, + 'resolvedModel correctly stored in resolvedModels for parent route' + ); + if (redirect) { + redirect = false; + router.transitionTo('adminPosts'); + } + }, + }), + }; + + await router.transitionTo('/posts/admin/1/posts'); + } + ); + + QUnit.test( + `transition.to.find's callback is always called with defined routeInfo`, + async function (assert) { + type Application = { app: boolean } & IModel; + + assert.expect(3); + + map(assert, function (match) { + match('/').to('application', function (match) { + match('/peter').to('peter', function (match) { + match('/wagenet').to('wagenet'); + }); + }); + }); + + routes = { + application: createHandler('application'), + peter: createHandler('peter'), + wagenet: createHandler('wagenet', { + model: function (_params: Dict, transition: Transition) { + transition.to!.find((routeInfo) => { + assert.ok(routeInfo, 'routeInfo is defined'); + return false; + }); + }, + }), + }; + + await router.transitionTo('/peter/wagenet'); + } + ); + + QUnit.test( + 'Moving to the same route with a different parent dynamic segment re-runs model', + async function (assert) { + let admins: Dict = { 1: { id: 1 }, 2: { id: 2 } }, + adminPosts: Dict = { 1: { id: 1 }, 2: { id: 2 } }; + + routes = { + admin: createHandler('admin', { + currentModel: -1, + model: function (params: Dict) { + return (this['currentModel'] = admins[params['id'] as string]); + }, + }), + + adminPosts: createHandler('adminPosts', { + model: function () { + return adminPosts[(routes['admin'] as any).currentModel.id]; + }, + }), + }; + + await router.transitionTo('/posts/admin/1/posts'); + assert.equal(routes['admin']!.context, admins[1]); + assert.equal(routes['adminPosts']!.context, adminPosts[1]); + + await router.transitionTo('/posts/admin/2/posts'); + assert.equal(routes['admin']!.context, admins[2]); + assert.equal(routes['adminPosts']!.context, adminPosts[2]); + } + ); + + QUnit.test( + 'Moving to a sibling route only triggers exit callbacks on the current route (when transitioned internally)', + async function (assert) { + assert.expect(8); + + let allPosts = { posts: 'all' }; + + let showAllPostsHandler = createHandler('showAllPosts', { + model: function () { + return allPosts; + }, + + setup: function (posts: Dict) { + assert.equal( + posts, + allPosts, + 'The correct context was passed into showAllPostsHandler#setup' + ); + }, + + enter: function () { + assert.ok(true, 'The sibling handler should be entered'); + }, + + exit: function () { + assert.ok(true, 'The sibling handler should be exited'); + }, + }); + + let filters: Dict = {}; + + let showFilteredPostsHandler = createHandler('showFilteredPosts', { + enter: function () { + assert.ok(true, 'The new handler was entered'); + }, + + exit: function () { + assert.ok(false, 'The new handler should not be exited'); + }, + + model: function (params: Dict) { + let id = params['filter_id'] as string; + if (!filters[id]) { + filters[id] = { id: id }; + } + + return filters[id]; + }, + + serialize: function (filter: Dict) { + assert.equal(filter['id'], 'favorite', "The filter should be 'favorite'"); + return { filter_id: filter['id'] }; + }, + + setup: function (filter: Dict) { + assert.equal( + filter['id'], + 'favorite', + 'showFilteredPostsHandler#setup was called with the favorite filter' + ); + }, + }); + + let postIndexHandler = createHandler('postIndex', { + enter: function () { + assert.ok(true, 'The outer handler was entered only once'); + }, + + exit: function () { + assert.ok(false, 'The outer handler was not exited'); + }, + }); + + routes = { + postIndex: postIndexHandler, + showAllPosts: showAllPostsHandler, + showFilteredPosts: showFilteredPostsHandler, + }; + + await router.handleURL('/posts').then(function () { + expectedUrl = '/posts/filter/favorite'; + return router.transitionTo('showFilteredPosts', { id: 'favorite' }); + }); + } + ); + + QUnit.test( + 'Moving to a sibling route only triggers exit callbacks on the current route (when transitioned via a URL change)', + async function (assert) { + assert.expect(7); + + let allPosts = { posts: 'all' }; + + let showAllPostsHandler = createHandler('showAllPostsHandler', { + model: function () { + return allPosts; + }, + + setup: function (posts: Dict) { + assert.equal( + posts, + allPosts, + 'The correct context was passed into showAllPostsHandler#setup' + ); + }, + + enter: function () { + assert.ok(true, 'The sibling handler should be entered'); + }, + + exit: function () { + assert.ok(true, 'The sibling handler should be exited'); + }, + }); + + let filters: Dict = {}; + + let showFilteredPostsHandler = createHandler('showFilteredPosts', { + enter: function () { + assert.ok(true, 'The new handler was entered'); + }, + + exit: function () { + assert.ok(false, 'The new handler should not be exited'); + }, + + model: function (params: Dict) { + assert.equal(params['filter_id'], 'favorite', "The filter should be 'favorite'"); + + let id = params['filter_id'] as string; + if (!filters[id]) { + filters[id] = { id: id }; + } + + return filters[id]; + }, + + serialize: function (filter: Dict) { + return { filter_id: filter['id'] }; + }, + + setup: function (filter: Dict) { + assert.equal( + filter['id'], + 'favorite', + 'showFilteredPostsHandler#setup was called with the favorite filter' + ); + }, + }); + + let postIndexHandler = createHandler('postIndex', { + enter: function () { + assert.ok(true, 'The outer handler was entered only once'); + }, + + exit: function () { + assert.ok(false, 'The outer handler was not exited'); + }, + }); + + routes = { + postIndex: postIndexHandler, + showAllPosts: showAllPostsHandler, + showFilteredPosts: showFilteredPostsHandler, + }; + + await router.handleURL('/posts'); + + expectedUrl = '/posts/filter/favorite'; + await router.handleURL(expectedUrl); + } + ); + + QUnit.test('events can be targeted at the current handler', async function (assert) { + assert.expect(2); + + routes = { + showPost: createHandler('showPost', { + enter: function () { + assert.ok(true, 'The show post handler was entered'); + }, + + events: { + expand: function () { + assert.equal(this, routes['showPost'], 'The handler is the `this` for the event'); + }, + }, + }), + }; + + await router.transitionTo('/posts/1'); + + router.trigger('expand'); + }); + + QUnit.test('event triggering is pluggable', function (assert) { + routes = { + showPost: createHandler('showPost', { + enter: function () { + assert.ok(true, 'The show post handler was entered'); + }, + + actions: { + expand: function () { + assert.equal(this, routes['showPost'], 'The handler is the `this` for the event'); + }, + }, + }), + }; + router.triggerEvent = function ( + handlerInfos: RouteInfo[], + ignoreFailure: boolean, + name: string, + args: any[] + ) { + if (!handlerInfos) { + if (ignoreFailure) { + return; + } + throw new Error("Could not trigger event '" + name + "'. There are no active handlers"); + } + + for (let i = handlerInfos.length - 1; i >= 0; i--) { + let handlerInfo = handlerInfos[i], + handler = handlerInfo!.route as any; + + if (handler.actions && handler.actions[name]) { + if (handler.actions[name].apply(handler, args) !== true) { + return; + } + } + } + }; + router.handleURL('/posts/1').then(function () { + router.trigger('expand'); + }); + }); + + QUnit.test('Unhandled events raise an exception', function (assert) { + router.handleURL('/posts/1'); + + assert.throws(function () { + router.trigger('doesnotexist'); + }, /doesnotexist/); + }); + + QUnit.test('events can be targeted at a parent handler', async function (assert) { + assert.expect(3); + + routes = { + postIndex: createHandler('postIndex', { + enter: function () { + assert.ok(true, 'The post index handler was entered'); + }, + + events: { + expand: function () { + assert.equal(this, routes['postIndex'], 'The handler is the `this` in events'); + }, + }, + }), + showAllPosts: createHandler('showAllPosts', { + enter: function () { + assert.ok(true, 'The show all posts handler was entered'); + }, + }), + }; + + await router.transitionTo('/posts'); + router.trigger('expand'); + }); + + QUnit.test('events can bubble up to a parent handler via `return true`', function (assert) { + assert.expect(4); + + routes = { + postIndex: createHandler('postIndex', { + enter: function () { + assert.ok(true, 'The post index handler was entered'); + }, + + events: { + expand: function () { + assert.equal(this, routes['postIndex'], 'The handler is the `this` in events'); + }, + }, + }), + showAllPosts: createHandler('showAllPosts', { + enter: function () { + assert.ok(true, 'The show all posts handler was entered'); + }, + events: { + expand: function () { + assert.equal(this, routes['showAllPosts'], 'The handler is the `this` in events'); + return true; + }, + }, + }), + }; + + router.handleURL('/posts').then(function () { + router.trigger('expand'); + }); + }); + + QUnit.test( + "handled-then-bubbled events don't throw an exception if uncaught by parent route", + async function (assert) { + assert.expect(3); + + routes = { + postIndex: createHandler('postIndex', { + enter: function () { + assert.ok(true, 'The post index handler was entered'); + }, + }), + + showAllPosts: createHandler('showAllPosts', { + enter: function () { + assert.ok(true, 'The show all posts handler was entered'); + }, + events: { + expand: function () { + assert.equal(this, routes['showAllPosts'], 'The handler is the `this` in events'); + return true; + }, + }, + }), + }; + + await router.transitionTo('/posts'); + router.trigger('expand'); + } + ); + + QUnit.test('events only fire on the closest handler', function (assert) { + assert.expect(5); + + routes = { + postIndex: createHandler('postIndex', { + enter: function () { + assert.ok(true, 'The post index handler was entered'); + }, + + events: { + expand: function () { + assert.ok(false, 'Should not get to the parent handler'); + }, + }, + }), + + showAllPosts: createHandler('showAllPosts', { + enter: function () { + assert.ok(true, 'The show all posts handler was entered'); + }, + + events: { + expand: function (passedContext1: Dict, passedContext2: Dict) { + assert.equal(context1, passedContext1, 'A context is passed along'); + assert.equal(context2, passedContext2, 'A second context is passed along'); + assert.equal( + this, + routes['showAllPosts'], + 'The handler is passed into events as `this`' + ); + }, + }, + }), + }; + + let context1: Dict = {}, + context2: Dict = {}; + router.handleURL('/posts').then(function () { + router.trigger('expand', context1, context2); + }); + }); + + QUnit.test("Date params aren't treated as string/number params", function (assert) { + assert.expect(1); + + routes = { + showPostsForDate: createHandler('showPostsForDate', { + serialize: function (date: Date) { + return { + date: date.getFullYear() + '-' + date.getMonth() + '-' + date.getDate(), + }; + }, + + model: function () { + assert.ok(false, "model shouldn't be called; the date is the provided model"); + }, + }), + }; + + if (scenario.async) { + serializers = { + showPostsForDate: function (date: any) { + return { + date: date.getFullYear() + '-' + date.getMonth() + '-' + date.getDate(), + }; + }, + }; + } + + let result = router.generate('showPostsForDate', new Date(1815, 5, 18)); + assert.equal(result, '/posts/on/1815-5-18'); + }); + + QUnit.test('getSerializer takes precedence over handler.serialize', function (assert) { + assert.expect(2); + + router.getSerializer = function () { + return function (date: any) { + assert.ok(true, 'getSerializer called'); + return { + date: date.getFullYear() + '-' + date.getMonth() + '-' + date.getDate(), + }; + }; + }; + + routes = { + showPostsForDate: createHandler('showPostsForDate', { + serialize: function () { + assert.ok(false, "serialize method shouldn't be called"); + return {}; + }, + + model: function () { + assert.ok(false, "model shouldn't be called; the date is the provided model"); + }, + }), + }; + + assert.equal(router.generate('showPostsForDate', new Date(1815, 5, 18)), '/posts/on/1815-5-18'); + }); + + QUnit.test('the serializer method is unbound', function (assert) { + assert.expect(1); + + router.getSerializer = function () { + return function (this: void, date: any) { + assert.equal(this, undefined); + return { + date: date.getFullYear() + '-' + date.getMonth() + '-' + date.getDate(), + }; + }; + }; + + router.generate('showPostsForDate', new Date(1815, 5, 18)); + }); + + QUnit.test('params are known by a transition up front', async function (assert) { + assert.expect(2); + + routes = { + postIndex: createHandler('postIndex', { + model: function (_params: Dict, transition: Transition) { + assert.deepEqual(transition[PARAMS_SYMBOL], { + postIndex: {}, + showFilteredPosts: { filter_id: 'sad' }, + }); + }, + }), + showFilteredPosts: createHandler('showFilteredPosts', { + model: function (_params: Dict, transition: Transition) { + assert.deepEqual(transition[PARAMS_SYMBOL], { + postIndex: {}, + showFilteredPosts: { filter_id: 'sad' }, + }); + }, + }), + }; + + await router.transitionTo('/posts/filter/sad', 'blorg'); + }); + + QUnit.test( + 'transitionTo uses the current context if you are already in a handler with a context that is not changing', + async function (assert) { + let admin = { id: 47 }, + adminPost = { id: 74 }; + + routes = { + admin: createHandler('admin', { + serialize: function (object: Dict) { + assert.equal(object['id'], 47, 'The object passed to serialize is correct'); + return { id: 47 }; + }, + + model: function (params: Dict) { + assert.equal(params['id'], 47, 'The object passed to serialize is correct'); + return admin; + }, + }), + + adminPost: createHandler('adminPost', { + serialize: function (object: Dict) { + return { post_id: object['id'] }; + }, + + model: function (params: Dict) { + assert.equal(params['id'], 74, 'The object passed to serialize is correct'); + return adminPost; + }, + }), + }; + + expectedUrl = '/posts/admin/47/posts/74'; + await router.transitionTo('adminPost', admin, adminPost); + + expectedUrl = '/posts/admin/47/posts/75'; + await router.transitionTo('adminPost', { id: 75 }); + } + ); + + QUnit.test('check for mid-transition correctness', async function (assert) { + let posts: Dict = { + 1: { id: 1 }, + 2: { id: 2 }, + 3: { id: 3 }, + }; + + let showPostHandler = createHandler('showPost', { + serialize: function (object: Dict) { + return (object && { id: object['id'] }) || null; + }, + + model: function (params: Dict) { + let id = params['id'] as string; + return posts[id]; + }, + }); + + routes = { + showPost: showPostHandler, + }; + + // Get a reference to the transition, mid-transition. + router.willTransition = function () { + let midTransitionState = router.activeTransition![STATE_SYMBOL]; + + // Make sure that the activeIntent doesn't match post 300. + let isPost300Targeted = router.isActiveIntent( + 'showPost', + [300], + undefined, + midTransitionState + ); + assert.notOk(isPost300Targeted, 'Post 300 should not match post 3.'); + }; + + // Go to post 3. This triggers our test. + await router.transitionTo('/posts/3'); + }); + + QUnit.test( + 'tests whether arguments to transitionTo are considered active', + async function (assert) { + let admin = { id: 47 }, + adminPost = { id: 74 }, + posts: Dict = { + 1: { id: 1 }, + 2: { id: 2 }, + 3: { id: 3 }, + }; + + let adminHandler = createHandler('admin', { + serialize: function () { + return { id: 47 }; + }, + + model: function () { + return admin; + }, + }); + + let adminPostHandler = createHandler('adminPost', { + serialize: function (object: Dict) { + return { post_id: object['id'] }; + }, + + model: function () { + return adminPost; + }, + }); + + let showPostHandler = createHandler('showPost', { + serialize: function (object: Dict) { + return (object && { id: object['id'] }) || null; + }, + + model: function (params: Dict) { + return posts[params['id'] as string]; + }, + }); + + routes = { + admin: adminHandler, + adminPost: adminPostHandler, + showPost: showPostHandler, + }; + + await router.transitionTo('/posts/1'); + assert.ok(router.isActive('showPost'), 'The showPost handler is active'); + assert.ok( + router.isActive('showPost', posts[1]), + 'The showPost handler is active with the appropriate context' + ); + assert.notOk( + router.isActive('showPost', posts[2]), + 'The showPost handler is inactive when the context is different' + ); + assert.notOk(router.isActive('adminPost'), 'The adminPost handler is inactive'); + assert.notOk( + router.isActive('showPost', null), + 'The showPost handler is inactive with a null context' + ); + + await router.transitionTo('adminPost', admin, adminPost); + assert.ok(router.isActive('adminPost'), 'The adminPost handler is active'); + assert.ok( + router.isActive('adminPost', adminPost), + 'The adminPost handler is active with the current context' + ); + assert.ok( + router.isActive('adminPost', admin, adminPost), + 'The adminPost handler is active with the current and parent context' + ); + assert.ok(router.isActive('admin'), 'The admin handler is active'); + assert.ok(router.isActive('admin', admin), 'The admin handler is active with its context'); + } + ); + + QUnit.test( + 'calling generate on a non-dynamic route does not blow away parent contexts', + function (assert) { + map(assert, function (match) { + match('/projects').to('projects', function (match) { + match('/').to('projectsIndex'); + match('/project').to('project', function (match) { + match('/').to('projectIndex'); + }); + }); + }); + + let projects = {}; + + routes = { + projects: createHandler('projects', { + model: function () { + return projects; + }, + }), + }; + + router.handleURL('/projects').then(function () { + assert.equal(routes['projects']!.context, projects, 'projects handler has correct context'); + router.generate('projectIndex'); + assert.equal( + routes['projects']!.context, + projects, + 'projects handler retains correct context' + ); + }); + } + ); + + QUnit.test( + 'calling transitionTo on a dynamic parent route causes non-dynamic child context to be updated', + async function (assert) { + type Project = { project_id: string } & IModel; + + map(assert, function (match) { + match('/project/:project_id').to('project', function (match) { + match('/').to('projectIndex'); + }); + }); + + let projectHandler = createHandler('project', { + model: function (params: Dict) { + delete params['queryParams']; + return params; + }, + }); + + let projectIndexHandler = createHandler('projectIndex', { + model: function (_params: Dict, transition: Transition) { + return transition.resolvedModels['project']; + }, + }); + + routes = { + project: projectHandler, + projectIndex: projectIndexHandler, + }; + + await router.transitionTo('/project/1'); + assert.deepEqual( + projectHandler.context, + { project_id: '1' }, + 'project handler retains correct context' + ); + assert.deepEqual( + projectIndexHandler.context, + { project_id: '1' }, + 'project index handler has correct context' + ); + + router.generate('projectIndex', { project_id: '2' }); + + assert.deepEqual( + projectHandler.context, + { project_id: '1' }, + 'project handler retains correct context' + ); + assert.deepEqual( + projectIndexHandler.context, + { project_id: '1' }, + 'project index handler retains correct context' + ); + + await router.transitionTo('projectIndex', { project_id: '2' }); + assert.deepEqual( + projectHandler.context, + { project_id: '2' }, + 'project handler has updated context' + ); + assert.deepEqual( + projectIndexHandler.context, + { project_id: '2' }, + 'project index handler has updated context' + ); + } + ); + + QUnit.test( + 'reset exits and clears the current and target route handlers', + async function (assert) { + let postIndexExited = false; + let showAllPostsExited = false; + let steps = 0; + + assert.equal(++steps, 1); + let postIndexHandler = createHandler('postIndex', { + exit: function () { + postIndexExited = true; + assert.equal(++steps, 4); + }, + }); + let showAllPostsHandler = createHandler('showAllPosts', { + exit: function () { + showAllPostsExited = true; + assert.equal(++steps, 3); + }, + }); + routes = { + postIndex: postIndexHandler, + showAllPosts: showAllPostsHandler, + }; + + await router.transitionTo('/posts/all'); + + assert.equal(++steps, 2); + router.reset(); + + assert.ok(postIndexExited, 'Post index handler did not exit'); + assert.ok(showAllPostsExited, 'Show all posts handler did not exit'); + assert.equal(router.currentRouteInfos, null, 'currentHandlerInfos should be null'); + } + ); + + QUnit.test( + 'any of the model hooks can redirect with or without promise', + async function (assert) { + assert.expect(26); + let setupShouldBeEntered = false; + let returnPromise = false; + let redirectTo: string; + + function redirectToAbout() { + if (returnPromise) { + return reject().then(null, function () { + router.transitionTo(redirectTo); + }); + } else { + router.transitionTo(redirectTo); + } + return; + } + + routes = { + index: createHandler('index', { + beforeModel: redirectToAbout, + model: redirectToAbout, + afterModel: redirectToAbout, + + setup: function () { + assert.ok(setupShouldBeEntered, 'setup should be entered at this time'); + }, + }), + + about: createHandler('about', { + setup: function () { + assert.ok(true, "about handler's setup function was called"); + }, + }), + + borf: createHandler('borf', { + setup: function () { + assert.ok(true, 'borf setup entered'); + }, + }), + }; + + async function testStartup(assert: Assert, firstExpectedURL?: string) { + map(assert, function (match) { + match('/').to('index'); + match('/about').to('about'); + match('/foo').to('foo'); + match('/borf').to('borf'); + }); + + redirectTo = 'about'; + + // Perform a redirect on startup. + expectedUrl = firstExpectedURL || '/about'; + await ignoreTransitionError(router.transitionTo('/')); + + expectedUrl = '/borf'; + redirectTo = 'borf'; + + await ignoreTransitionError(router.transitionTo('index')); + } + + await testStartup(assert); + + returnPromise = true; + await testStartup(assert); + + delete routes['index']!.beforeModel; + returnPromise = false; + await testStartup(assert); + + returnPromise = true; + await testStartup(assert); + + delete routes['index']!.model; + returnPromise = false; + await testStartup(assert); + + returnPromise = true; + await testStartup(assert); + + delete routes['index']!.afterModel; + setupShouldBeEntered = true; + await testStartup(assert, '/'); + } + ); + + QUnit.test( + 'transitionTo with a promise pauses the transition until resolve, passes resolved context to setup', + async function (assert) { + routes = { + index: createHandler('index'), + showPost: createHandler('showPost', { + setup: function (context: Dict) { + assert.deepEqual(context, { id: 1 }, 'setup receives a resolved context'); + }, + }), + }; + + await router.transitionTo('/index'); + + await router.transitionTo( + 'showPost', + new Promise(function (resolve) { + resolve({ id: 1 }); + }) + ); + } + ); + + QUnit.test('error handler gets called for errors in validation hooks', function (assert) { + assert.expect(25); + let setupShouldBeEntered = false; + let expectedReason = { reason: 'No funciona, mon frere.' }; + + function throwAnError() { + return reject(expectedReason); + } + + routes = { + index: createHandler('index', { + beforeModel: throwAnError, + model: throwAnError, + afterModel: throwAnError, + + events: { + error: function (reason: string) { + assert.equal( + reason, + expectedReason, + "the value passed to the error handler is what was 'thrown' from the hook" + ); + }, + }, + + setup: function () { + assert.ok(setupShouldBeEntered, 'setup should be entered at this time'); + }, + }), + + about: createHandler('about', { + setup: function () { + assert.ok(true, "about handler's setup function was called"); + }, + }), + }; + + function testStartup(assert: Assert) { + map(assert, function (match) { + match('/').to('index'); + match('/about').to('about'); + }); + + // Perform a redirect on startup. + return router.handleURL('/').then(null, function (reason: string) { + assert.equal( + reason, + expectedReason, + 'handleURL error reason is what was originally thrown' + ); + + return router + .transitionTo('index') + .then(shouldNotHappen(assert), function (newReason: string) { + assert.equal( + newReason, + expectedReason, + 'transitionTo error reason is what was originally thrown' + ); + }); + }); + } + + testStartup(assert) + .then(function () { + return testStartup(assert); + }) + .then(function () { + delete routes['index']!.beforeModel; + return testStartup(assert); + }) + .then(function () { + return testStartup(assert); + }) + .then(function () { + delete routes['index']!.model; + return testStartup(assert); + }) + .then(function () { + return testStartup(assert); + }) + .then(function () { + delete routes['index']!.afterModel; + setupShouldBeEntered = true; + return testStartup(assert); + }); + }); + + QUnit.test( + "Errors shouldn't be handled after proceeding to next child route", + async function (assert) { + assert.expect(3); + + map(assert, function (match) { + match('/parent').to('parent', function (match) { + match('/articles').to('articles'); + match('/login').to('login'); + }); + }); + + routes = { + articles: createHandler('articles', { + beforeModel: function () { + assert.ok(true, 'articles beforeModel was entered'); + return Promise.reject('blorg in beforeModel in articles'); + }, + events: { + error: function () { + assert.ok(true, 'error handled in articles'); + router.transitionTo('login'); + }, + }, + }), + + login: createHandler('login', { + setup: function () { + assert.ok(true, 'login#setup'); + }, + }), + + parent: createHandler('parent', { + events: { + error: function () { + assert.ok(false, "handled error shouldn't bubble up to parent route"); + }, + }, + }), + }; + + ignoreTransitionError(router.handleURL('/parent/articles')); + } + ); + + QUnit.test( + "Error handling shouldn't trigger for transitions that are already aborted", + function (assert) { + assert.expect(1); + + map(assert, function (match) { + match('/slow_failure').to('slow_failure'); + match('/good').to('good'); + }); + + routes = { + slow_failure: createHandler('showFailure', { + model: function () { + return new Promise(function (_res, rej) { + router.transitionTo('good'); + rej(); + }); + }, + events: { + error: function () { + assert.ok(false, "error handling shouldn't fire"); + }, + }, + }), + + good: createHandler('good', { + setup: function () { + assert.ok(true, 'good#setup'); + }, + }), + }; + + return ignoreTransitionError(router.handleURL('/slow_failure')); + } + ); + + QUnit.test( + 'Transitions to the same destination as the active transition just return the active transition', + function (assert) { + assert.expect(1); + + let transition0 = router.handleURL('/index'); + let transition1 = router.handleURL('/index'); + assert.equal(transition0, transition1); + } + ); + + QUnit.test('can redirect from error handler', function (assert) { + assert.expect(4); + + let errorCount = 0; + + routes = { + index: createHandler('index'), + + showPost: createHandler('showPost', { + model: function () { + return reject('borf!'); + }, + events: { + error: function (e: Error) { + errorCount++; + + assert.equal(e, 'borf!', 'received error thrown from model'); + + // Redirect to index. + router.transitionTo('index').then(function () { + if (errorCount === 1) { + // transition back here to test transitionTo error handling. + return router + .transitionTo('showPost', reject('borf!')) + .then(shouldNotHappen(assert), function (e: Error) { + assert.equal(e, 'borf!', 'got thing'); + }); + } + return; + }, shouldNotHappen(assert)); + }, + }, + + setup: function () { + assert.ok(false, 'should not get here'); + }, + }), + }; + + router.handleURL('/posts/123').then(shouldNotHappen(assert), function (reason: string) { + assert.equal(reason, 'borf!', 'expected reason received from first failed transition'); + }); + }); + + QUnit.test('can redirect from setup/enter', function (assert) { + assert.expect(5); + + routes = { + index: createHandler('index', { + enter: function () { + assert.ok(true, 'index#enter called'); + router.transitionTo('about').then(secondAttempt, shouldNotHappen(assert)); + }, + setup: function () { + assert.ok(true, 'index#setup called'); + router.transitionTo('/about').then(thirdAttempt, shouldNotHappen(assert)); + }, + events: { + error: function () { + assert.ok(false, 'redirects should not call error hook'); + }, + }, + }), + about: createHandler('about', { + setup: function () { + assert.ok(true, 'about#setup was entered'); + }, + }), + }; + + router.handleURL('/index').then(shouldNotHappen(assert), assertAbort(assert)); + + function secondAttempt() { + delete routes['index']!.enter; + router.transitionTo('index').then(shouldNotHappen(assert), assertAbort(assert)); + } + + function thirdAttempt() { + delete routes['index']!.setup; + router.transitionTo('index').then(null, shouldNotHappen(assert)); + } + }); + + QUnit.test( + 'redirecting to self from validation hooks should no-op (and not infinite loop)', + function (assert) { + assert.expect(2); + + let count = 0; + + routes = { + index: createHandler('index', { + afterModel: function () { + if (count++ > 10) { + assert.ok(false, 'infinite loop occurring'); + } else { + assert.ok(count <= 2, 'running index no more than twice'); + router.transitionTo('index'); + } + }, + setup: function () { + assert.ok(true, 'setup was called'); + }, + }), + }; + + router.handleURL('/index'); + } + ); + + QUnit.test('Transition#method(null) prevents URLs from updating', async function (assert) { + assert.expect(1); + + routes = { + about: createHandler('about', { + setup: function () { + assert.ok(true, 'about#setup was called'); + }, + }), + }; + + router.updateURL = function () { + assert.ok(false, "updateURL shouldn't have been called"); + }; + + // Test multiple calls to method in a row. + router.handleURL('/index').method(null); + await router.handleURL('/index').method(null); + + await router.transitionTo('about').method(null); + }); + + QUnit.test( + 'redirecting to self from enter hooks should no-op (and not infinite loop)', + function (assert) { + assert.expect(1); + + let count = 0; + + routes = { + index: createHandler('index', { + setup: function () { + if (count++ > 10) { + assert.ok(false, 'infinite loop occurring'); + } else { + assert.ok(true, 'setup was called'); + router.transitionTo('index'); + } + }, + }), + }; + + router.handleURL('/index'); + } + ); + + QUnit.test( + 'redirecting to child handler from validation hooks should no-op (and not infinite loop)', + function (assert) { + assert.expect(4); + + routes = { + postIndex: createHandler('postIndex', { + beforeModel: function () { + assert.ok(true, 'postIndex beforeModel called'); + router.transitionTo('showAllPosts'); + }, + }), + + showAllPosts: createHandler('showAllPosts', { + beforeModel: function () { + assert.ok(true, 'showAllPosts beforeModel called'); + }, + }), + + showPopularPosts: createHandler('showPopularPosts', { + beforeModel: function () { + assert.ok(true, 'showPopularPosts beforeModel called'); + }, + }), + }; + + router.handleURL('/posts/popular').then( + function () { + assert.ok(false, 'redirected handleURL should not succeed'); + }, + function () { + assert.ok(true, 'redirected handleURL should fail'); + } + ); + } + ); + + function startUpSetup(assert: Assert) { + routes = { + index: createHandler('index', { + setup: function () { + assert.ok(true, 'index setup called'); + }, + }), + about: createHandler('about', { + setup: function () { + assert.ok(true, 'about setup called'); + }, + }), + faq: createHandler('faq', { + setup: function () { + assert.ok(true, 'faq setup called'); + }, + }), + }; + } + + QUnit.test('transitionTo with named transition can be called at startup', function (assert) { + assert.expect(2); + + startUpSetup(assert); + + router.transitionTo('index').then( + function () { + assert.ok(true, 'success handler called'); + }, + function () { + assert.ok(false, 'failure handle should not be called'); + } + ); + }); + + QUnit.test('transitionTo with URL transition can be called at startup', function (assert) { + assert.expect(2); + + startUpSetup(assert); + + router.transitionTo('/index').then( + function () { + assert.ok(true, 'success handler called'); + }, + function () { + assert.ok(false, 'failure handle should not be called'); + } + ); + }); + + QUnit.test('transitions fire a didTransition event on the destination route', function (assert) { + assert.expect(1); + + routes = { + about: createHandler('about', { + events: { + didTransition: function () { + assert.ok(true, "index's didTransition was called"); + }, + }, + }), + }; + + router.handleURL('/index').then(function () { + router.transitionTo('about'); + }, shouldNotHappen(assert)); + }); + + QUnit.test('willTransition function fired before route change', function (assert) { + assert.expect(1); + + let beforeModelNotCalled = true; + + routes = { + about: createHandler('about', { + beforeModel: function () { + beforeModelNotCalled = false; + }, + }), + }; + + router.willTransition = function () { + assert.ok(beforeModelNotCalled, 'about beforeModel hook should not be called at this time'); + }; + + router.handleURL('/about'); + }); + + QUnit.test('willTransition function fired with handler infos passed in', function (assert) { + assert.expect(2); + + router.handleURL('/about').then(function () { + router.willTransition = function (fromInfos, toInfos) { + assert.equal( + routePath(fromInfos), + 'about', + 'first argument should be the old handler infos' + ); + assert.equal( + routePath(toInfos), + 'postIndex.showPopularPosts', + 'second argument should be the new handler infos' + ); + }; + + router.handleURL('/posts/popular'); + }); + }); + + QUnit.test( + 'willTransition function fired with cancellable transition passed in', + function (assert) { + assert.expect(2); + + router.handleURL('/index').then(function () { + router.willTransition = function (_fromInfos, _toInfos, transition) { + assert.ok(true, "index's transitionTo was called"); + transition.abort(); + }; + + return router.transitionTo('about').then(shouldNotHappen(assert), assertAbort(assert)); + }); + } + ); + + QUnit.test('transitions can be aborted in the willTransition event', function (assert) { + assert.expect(3); + + routes = { + index: createHandler('index', { + setup: function () { + assert.ok(true, 'index setup called'); + }, + events: { + willTransition: function (transition: Transition) { + assert.ok(true, "index's transitionTo was called"); + transition.abort(); + }, + }, + }), + about: createHandler('about', { + setup: function () { + assert.ok(true, 'about setup called'); + }, + }), + }; + + router.handleURL('/index').then(function () { + return router.transitionTo('about').then(shouldNotHappen(assert), assertAbort(assert)); + }); + }); + + QUnit.test('transitions can redirected in the willTransition event', function (assert) { + assert.expect(2); + + let destFlag = true; + + routes = { + index: createHandler('index', { + setup: function () { + assert.ok(true, 'index setup called'); + }, + events: { + willTransition: function () { + // Router code must be careful here not to refire + // `willTransition` when a transition is already + // underway, else infinite loop. + let dest = destFlag ? 'about' : 'faq'; + destFlag = !destFlag; + router.transitionTo(dest); + }, + }, + }), + about: createHandler('about', { + setup: function () { + assert.ok(true, 'about setup called'); + }, + }), + faq: createHandler('faq', { + setup: function () { + assert.ok(false, 'faq setup should not be called'); + }, + }), + }; + + router.handleURL('/index').then(function () { + router.transitionTo('faq'); + }); + }); + + QUnit.test('transitions that abort and enter into a substate', function (assert) { + assert.expect(3); + + routes = { + index: createHandler('index'), + about: createHandler('about', { + setup: function () { + assert.ok(true, 'about setup called'); + }, + events: { + willTransition: function (transition: Transition) { + assert.ok(true, 'willTransition'); + transition.abort(); + router.intermediateTransitionTo('faq'); + }, + }, + }), + faq: createHandler('faq', { + setup: function () { + assert.ok(true, 'faq setup called'); + }, + }), + }; + + router.handleURL('/about').then(() => { + return router.transitionTo('index'); + }); + }); + + QUnit.test('aborted transitions can be saved and later retried', function (assert) { + assert.expect(9); + + let shouldPrevent = true, + transitionToAbout, + lastTransition: Transition, + retryTransition: Transition; + + routes = { + index: createHandler('index', { + setup: function () { + assert.ok(true, 'index setup called'); + }, + events: { + willTransition: function (transition: Transition) { + assert.ok(true, "index's willTransition was called"); + if (shouldPrevent) { + transition.data['foo'] = 'hello'; + (transition as any).foo = 'hello'; + transition.abort(); + lastTransition = transition; + } else { + assert.notOk((transition as any).foo, 'no foo property exists on new transition'); + assert.equal( + transition.data['foo'], + 'hello', + 'values stored in data hash of old transition persist when retried' + ); + } + }, + }, + }), + about: createHandler('about', { + setup: function () { + assert.ok(true, 'about setup called'); + }, + }), + }; + + router.handleURL('/index').then(function () { + router + .transitionTo('about') + .then(shouldNotHappen(assert), function () { + assert.ok(true, 'transition was blocked'); + shouldPrevent = false; + transitionToAbout = lastTransition; + retryTransition = transitionToAbout.retry(); + assert.equal(retryTransition.urlMethod, 'update'); + return retryTransition; + }) + .then(function () { + assert.ok(true, 'transition succeeded via .retry()'); + }, shouldNotHappen(assert)); + }); + }); + + QUnit.test( + 'aborted transitions can be saved and later retried asynchronously', + function (assert) { + assert.expect(2); + + let abortedTransition: Transition; + let shouldPrevent = true; + routes = { + index: createHandler('index', { + events: { + willTransition: function (transition: Transition) { + if (shouldPrevent) { + abortedTransition = transition.abort(); + + const t = router.intermediateTransitionTo('loading'); + assert.rejects(t as unknown as Promise); + } + }, + }, + }), + about: createHandler('about', { + setup: function () { + assert.ok(true, 'about setup called'); + }, + }), + loading: createHandler('loading', { + setup: function () { + assert.ok(true, 'loading setup called'); + }, + }), + }; + + router.handleURL('/index').then(function () { + return router + .transitionTo('about') + .then(shouldNotHappen(assert), function () { + shouldPrevent = false; + return new Promise((resolve) => { + let transition = abortedTransition.retry(); + resolve(transition); + }); + }) + .then(function () { + assert.ok(true, 'transition succeeded via .retry()'); + }, shouldNotHappen(assert)) + .catch(shouldNotHappen(assert)); + }); + } + ); + + QUnit.test( + 'if an aborted transition is retried, it preserves the urlMethod of the original one', + function (assert) { + assert.expect(9); + + let shouldPrevent = true, + transitionToAbout, + lastTransition: Transition, + retryTransition: Transition; + + routes = { + index: createHandler('index', { + setup: function () { + assert.ok(true, 'index setup called'); + }, + events: { + willTransition: function (transition: Transition) { + assert.ok(true, "index's willTransition was called"); + if (shouldPrevent) { + transition.data['foo'] = 'hello'; + (transition as any).foo = 'hello'; + transition.abort(); + lastTransition = transition; + } else { + assert.notOk((transition as any).foo, 'no foo property exists on new transition'); + assert.equal( + transition.data['foo'], + 'hello', + 'values stored in data hash of old transition persist when retried' + ); + } + }, + }, + }), + about: createHandler('about', { + setup: function () { + assert.ok(true, 'about setup called'); + }, + }), + }; + + router.handleURL('/index').then(function () { + router + .replaceWith('about') + .then(shouldNotHappen(assert), function () { + assert.ok(true, 'transition was blocked'); + shouldPrevent = false; + transitionToAbout = lastTransition; + retryTransition = transitionToAbout.retry(); + assert.equal(retryTransition.urlMethod, 'replace'); + return transitionToAbout.retry(); + }) + .then(function () { + assert.ok(true, 'transition succeeded via .retry()'); + }, shouldNotHappen(assert)); + }); + } + ); + + QUnit.test( + 'if an initial transition is aborted during validation phase and later retried', + async function (assert) { + assert.expect(7); + + let shouldRedirectToLogin = true; + let currentURL = '/login'; + let urlStack: string[][] = []; + let lastTransition: Transition; + + map(assert, function (match) { + match('/').to('index'); + match('/login').to('login'); + }); + + router.updateURL = function (url) { + urlStack.push(['updateURL', url]); + currentURL = url; + }; + + router.replaceURL = function (url) { + urlStack.push(['replaceURL', url]); + currentURL = url; + }; + + routes = { + index: createHandler('index', { + beforeModel: function (transition: Transition) { + assert.ok(true, 'index model called'); + if (shouldRedirectToLogin) { + lastTransition = transition; + return router.transitionTo('/login'); + } + return; + }, + }), + login: createHandler('login', { + setup: function () { + assert.ok('login setup called'); + }, + }), + }; + + // use `handleURL` to emulate initial transition properly + try { + await router.handleURL('/'); + shouldNotHappen(assert, 'initial transition aborted'); + } catch { + assert.equal(currentURL, '/login', 'currentURL matches on initial transition aborted'); + assert.deepEqual(urlStack, [['replaceURL', '/login']]); + + shouldRedirectToLogin = false; + await lastTransition!.retry(); + assert.equal(currentURL, '/', 'after retry currentURL is updated'); + assert.deepEqual(urlStack, [ + ['replaceURL', '/login'], + ['updateURL', '/'], + ]); + } + } + ); + + QUnit.test('completed transitions can be saved and later retried', function (assert) { + assert.expect(8); + + let post = { id: '123' }, + savedTransition: Transition; + + routes = { + showPost: createHandler('showPost', { + afterModel: function (model: Dict, transition: Transition) { + if (savedTransition === undefined) { + assert.equal(transition.from && transition.from.localName, 'index', 'starting point'); + } else { + assert.equal( + transition.from && transition.from.localName, + 'about', + 'new starting point' + ); + } + + assert.equal(transition.to && transition.to.localName, 'showPost', 'to points at leaf'); + assert.equal(model, post, "showPost's afterModel got the expected post model"); + savedTransition = transition; + }, + }), + index: createHandler('index', { + model(_params: Dict, transition: Transition) { + assert.equal(transition.from, null); + }, + }), + about: createHandler('about', { + setup: function () { + assert.ok(true, 'setup was entered'); + }, + }), + }; + + router + .handleURL('/index') + .then(function () { + return router.transitionTo('showPost', post); + }) + .then(function () { + return router.transitionTo('about'); + }) + .then(function () { + return savedTransition.retry(); + }); + }); + + function setupAuthenticatedExample(assert: Assert) { + map(assert, function (match) { + match('/index').to('index'); + match('/login').to('login'); + + match('/admin').to('admin', function (match) { + match('/about').to('about'); + match('/posts/:post_id').to('adminPost'); + }); + }); + + let isLoggedIn = false, + lastRedirectedTransition: Transition; + + routes = { + index: createHandler('index'), + login: createHandler('login', { + events: { + logUserIn: function () { + isLoggedIn = true; + lastRedirectedTransition.retry(); + }, + }, + }), + admin: createHandler('admin', { + beforeModel: function (transition: Transition) { + lastRedirectedTransition = transition; + assert.ok(true, 'beforeModel redirect was called'); + if (!isLoggedIn) { + router.transitionTo('login'); + } + }, + }), + about: createHandler('about', { + setup: function () { + assert.ok(isLoggedIn, 'about was entered only after user logged in'); + }, + }), + adminPost: createHandler('adminPost', { + model: function (params: Dict) { + assert.deepEqual( + params, + { post_id: '5', queryParams: {} }, + 'adminPost received params previous transition attempt' + ); + return 'adminPost'; + }, + setup: function (model: Dict) { + assert.equal(model, 'adminPost', 'adminPost was entered with correct model'); + }, + }), + }; + } + + QUnit.test('authenticated routes: starting on non-auth route', async function (assert) { + assert.expect(8); + + setupAuthenticatedExample(assert); + + await router.transitionTo('/index'); + await transitionToWithAbort(assert, router, 'about'); + await transitionToWithAbort(assert, router, 'about'); + await transitionToWithAbort(assert, router, '/admin/about'); + + // Log in. This will retry the last failed transition to 'about'. + router.trigger('logUserIn'); + }); + + QUnit.test('authenticated routes: starting on auth route', async function (assert) { + assert.expect(8); + + setupAuthenticatedExample(assert); + + await transitionToWithAbort(assert, router, '/admin/about'); + await transitionToWithAbort(assert, router, '/admin/about'); + await transitionToWithAbort(assert, router, 'about'); + + // Log in. This will retry the last failed transition to 'about'. + router.trigger('logUserIn'); + }); + + QUnit.test('authenticated routes: starting on parameterized auth route', async function (assert) { + assert.expect(5); + + setupAuthenticatedExample(assert); + + await transitionToWithAbort(assert, router, '/admin/posts/5'); + + // Log in. This will retry the last failed transition to '/posts/5'. + router.trigger('logUserIn'); + }); + + QUnit.test('An instantly aborted transition fires no hooks', function (assert) { + assert.expect(8); + + let hooksShouldBeCalled = false; + + routes = { + index: createHandler('index', { + beforeModel: function (transition: Transition) { + assert.equal( + transition.from, + null, + 'from is "null" on initial transitions even with aborts' + ); + assert.ok(hooksShouldBeCalled, 'index beforeModel hook should be called at this time'); + }, + }), + about: createHandler('about', { + beforeModel: function () { + assert.ok(hooksShouldBeCalled, 'about beforeModel hook should be called at this time'); + }, + }), + }; + + router + .transitionTo('index') + .abort() + .then(shouldNotHappen(assert), function () { + assert.ok(true, 'Failure handler called for index'); + return router.transitionTo('/index').abort(); + }) + .then(shouldNotHappen(assert), function () { + assert.ok(true, 'Failure handler called for /index'); + hooksShouldBeCalled = true; + return router.transitionTo('index'); + }) + .then(function () { + assert.ok(true, 'Success handler called for index'); + hooksShouldBeCalled = false; + return router.transitionTo('about').abort(); + }, shouldNotHappen(assert)) + .then(shouldNotHappen(assert), function () { + assert.ok(true, 'failure handler called for about'); + return router.transitionTo('/about').abort(); + }) + .then(shouldNotHappen(assert), function () { + assert.ok(true, 'failure handler called for /about'); + hooksShouldBeCalled = true; + return router.transitionTo('/about'); + }); + }); + + QUnit.test('a successful transition resolves with the target handler', function (assert) { + assert.expect(2); + + // Note: this is extra convenient for Ember where you can all + // .transitionTo right on the route. + + routes = { + index: createHandler('index', { borfIndex: true }), + about: createHandler('about', { borfAbout: true }), + }; + + router + .handleURL('/index') + .then(function (route: Route) { + assert.ok((route as any)['borfIndex'], 'resolved to index handler'); + return router.transitionTo('about'); + }, shouldNotHappen(assert)) + .then(function (result: Dict) { + assert.ok(result['borfAbout'], 'resolved to about handler'); + }); + }); + + QUnit.test('transitions have a .promise property', function (assert) { + assert.expect(2); + + router + .handleURL('/index') + .promise!.then(function () { + let promise = router.transitionTo('about').abort().promise; + assert.ok(promise, 'promise exists on aborted transitions'); + return promise; + }, shouldNotHappen(assert)) + .then(shouldNotHappen(assert), function () { + assert.ok(true, 'failure handler called'); + }); + }); + + QUnit.test( + 'the serialize function is bound to the correct object when called', + function (assert) { + assert.expect(scenario.async ? 0 : 1); + + routes = { + showPostsForDate: createHandler('showPostsForDate', { + serialize: function (date: any) { + assert.equal(this, routes['showPostsForDate']); + return { + date: date.getFullYear() + '-' + date.getMonth() + '-' + date.getDate(), + }; + }, + }), + }; + + router.generate('showPostsForDate', new Date(1815, 5, 18)); + } + ); + + QUnit.test( + 'transitionTo will soak up resolved parent models of active transition', + function (assert) { + assert.expect(5); + + let admin = { id: 47 }, + adminPost = { id: 74 }, + adminSetupShouldBeEntered = false; + + function adminPromise() { + return new Promise(function (res) { + res(admin); + }); + } + + let adminHandler = createHandler('admin', { + serialize: function (object: Dict) { + assert.equal(object['id'], 47, 'The object passed to serialize is correct'); + return { id: 47 }; + }, + + model: function (params: Dict) { + assert.equal(params['id'], 47, 'The object passed to serialize is correct'); + return admin; + }, + + setup: function () { + assert.ok( + adminSetupShouldBeEntered, + "adminHandler's setup should be called at this time" + ); + }, + }); + + let adminPostHandler = createHandler('adminPost', { + serialize: function (object: Dict) { + return { post_id: object['id'] }; + }, + + setup: function () { + assert.equal( + adminHandler.context, + admin, + 'adminPostHandler receives resolved soaked promise from previous transition' + ); + }, + + model: function () { + return adminPost; + }, + }); + + let adminPostsHandler = createHandler('adminPosts', { + beforeModel: function () { + adminSetupShouldBeEntered = true; + router.transitionTo('adminPost', adminPost); + }, + }); + + let indexHandler = createHandler('index', { + setup: function () { + assert.ok(true, 'index entered'); + }, + }); + + routes = { + index: indexHandler, + admin: adminHandler, + adminPost: adminPostHandler, + adminPosts: adminPostsHandler, + }; + + router.transitionTo('index').then(function () { + router + .transitionTo('adminPosts', adminPromise()) + .then(shouldNotHappen(assert), assertAbort(assert)); + }); + } + ); + + QUnit.test( + "transitionTo will soak up resolved all models of active transition, including present route's resolved model", + function (assert) { + assert.expect(2); + + let modelCalled = 0, + hasRedirected = false; + + map(assert, function (match) { + match('/post').to('post', function (match) { + match('/').to('postIndex'); + match('/new').to('postNew'); + }); + }); + + let postHandler = createHandler('post', { + model: function () { + assert.equal(modelCalled++, 0, "postHandler's model should only be called once"); + return { title: 'Hello world' }; + }, + + redirect: function () { + if (!hasRedirected) { + hasRedirected = true; + router.transitionTo('postNew'); + } + }, + }); + + routes = { + post: postHandler, + postIndex: createHandler('postIndex'), + postNew: createHandler('postNew'), + }; + + router.transitionTo('postIndex').then(shouldNotHappen(assert), assertAbort(assert)); + } + ); + + QUnit.test("can reference leaf '/' route by leaf or parent name", async function (assert) { + map(assert, function (match) { + match('/').to('app', function (match) { + match('/').to('index'); + match('/nest').to('nest', function (match) { + match('/').to('nest.index'); + }); + }); + }); + + function assertOnRoute(name: string) { + let last = router.currentRouteInfos![router.currentRouteInfos!.length - 1]; + assert.equal(last!.name, name); + } + + await router.transitionTo('app'); + assertOnRoute('index'); + await router.transitionTo('nest'); + assertOnRoute('nest.index'); + await router.transitionTo('app'); + assertOnRoute('index'); + }); + + QUnit.test('resolved models can be swapped out within afterModel', function (assert) { + assert.expect(3); + + let modelPre = {}, + modelPost = {}; + + routes = { + index: createHandler('index', { + model: function () { + return modelPre; + }, + afterModel: function (resolvedModel: Dict, transition: Transition) { + assert.equal( + resolvedModel, + transition.resolvedModels['index'], + "passed-in resolved model equals model in transition's hash" + ); + assert.equal( + resolvedModel, + modelPre, + 'passed-in resolved model equals model returned from `model`' + ); + transition.resolvedModels['index'] = modelPost; + }, + setup: function (model: Dict) { + assert.equal( + model, + modelPost, + 'the model passed to `setup` is the one substituted in afterModel' + ); + }, + }), + }; + + router.transitionTo('index'); + }); + + QUnit.test('String/number args in transitionTo are treated as url params', function (assert) { + assert.expect(11); + + let adminParams = { id: '1' }, + adminModel = { id: '1' }, + adminPostModel = { id: '2' }; + + routes = { + admin: createHandler('admin', { + model: function (params: Dict) { + delete params['queryParams']; + assert.deepEqual( + params, + adminParams, + 'admin handler gets the number passed in via transitionTo, converts to string' + ); + return adminModel; + }, + }), + adminPost: createHandler('adminPost', { + model: function (params: Dict) { + delete params['queryParams']; + assert.deepEqual( + params, + { post_id: '2' }, + 'adminPost handler gets the string passed in via transitionTo' + ); + return adminPostModel; + }, + setup: function () { + assert.ok(true, 'adminPost setup was entered'); + }, + }), + }; + + router + .handleURL('/index') + .then(function () { + expectedUrl = '/posts/admin/1/posts/2'; + return router.transitionTo('adminPost', 1, '2'); + }) + .then(function () { + assert.ok(router.isActive('adminPost', 1, '2'), 'adminPost is active via params'); + assert.ok( + router.isActive('adminPost', 1, adminPostModel), + 'adminPost is active via contexts' + ); + + adminParams = { id: '0' }; + expectedUrl = '/posts/admin/0/posts/2'; + return router.transitionTo('adminPost', 0, '2'); + }) + .then(function () { + assert.ok(router.isActive('adminPost', 0, '2'), 'adminPost is active via params'); + assert.ok( + router.isActive('adminPost', 0, adminPostModel), + 'adminPost is active via contexts' + ); + }, shouldNotHappen(assert)); + }); + + QUnit.test( + "Transitions returned from beforeModel/model/afterModel hooks aren't treated as pausing promises", + function (assert) { + assert.expect(6); + + routes = { + index: createHandler('index', { + beforeModel: function () { + assert.ok(true, 'index beforeModel called'); + return router.transitionTo('index'); + }, + model: function () { + assert.ok(true, 'index model called'); + return router.transitionTo('index'); + }, + afterModel: function () { + assert.ok(true, 'index afterModel called'); + return router.transitionTo('index'); + }, + }), + }; + + function testStartup(assert: Assert) { + map(assert, function (match) { + match('/index').to('index'); + }); + + return router.handleURL('/index'); + } + + testStartup(assert) + .then(function () { + delete routes['index']!.beforeModel; + return testStartup(assert); + }) + .then(function () { + delete routes['index']!.model; + return testStartup(assert); + }) + .then(function () { + delete routes['index']!.afterModel; + return testStartup(assert); + }); + } + ); + + /* TODO: revisit this idea + QUnit.test("exceptions thrown from model hooks aren't swallowed", function(assert) { + assert.expect(7); + + enableErrorHandlingDeferredActionQueue(); + + let anError = {}; + function throwAnError() { + throw anError; + } + + let routeWasEntered = false; + + handlers = { + index: { + beforeModel: throwAnError, + model: throwAnError, + afterModel: throwAnError, + setup: function(model) { + routeWasEntered = true; + } + } + }; + + let hooks = ['beforeModel', 'model', 'afterModel']; + + while(hooks.length) { + let transition = router.transitionTo('index'); + flush(anError); + transition.abort(); + assert.ok(!routeWasEntered, "route hasn't been entered yet"); + delete handlers.index[hooks.shift()]; + } + + router.transitionTo('index'); + flush(anError); + + assert.ok(routeWasEntered, "route was finally entered"); + }); + */ + + QUnit.test( + 'Transition#followRedirects() returns a promise that fulfills when any redirecting transitions complete', + function (assert) { + assert.expect(3); + + routes['about'] = createHandler('about', { + redirect: function () { + router.transitionTo('faq').then(null, shouldNotHappen(assert)); + }, + }); + + router + .transitionTo('/index') + .followRedirects() + .then(function (handler: Route) { + assert.equal( + handler, + routes['index'], + 'followRedirects works with non-redirecting transitions' + ); + + return router.transitionTo('about').followRedirects(); + }) + .then(function (handler: Route) { + assert.equal( + handler, + routes['faq'], + 'followRedirects promise resolved with redirected faq handler' + ); + + (routes['about'] as Route).beforeModel = function (transition: Transition) { + transition.abort(); + return undefined; + }; + + // followRedirects should just reject for non-redirecting transitions. + return router + .transitionTo('about') + .followRedirects() + .then(shouldNotHappen(assert), assertAbort(assert)); + }); + } + ); + + QUnit.test( + 'Transition#followRedirects() works correctly when redirecting from an async model hook', + function (assert) { + assert.expect(2); + + routes['index'] = createHandler('index', { + beforeModel: function () { + return Promise.resolve(true).then(() => { + return router.transitionTo('about'); + }); + }, + }); + + routes['about'] = createHandler('about', { + setup: function () { + assert.ok(true, 'about#setup was called'); + }, + }); + + router + .transitionTo('/index') + .followRedirects() + .then(function (handler: Route) { + assert.equal( + handler, + routes['about'], + 'followRedirects works with redirect from async hook transitions' + ); + }); + } + ); + + QUnit.test( + "Returning a redirecting Transition from a model hook doesn't cause things to explode", + function (assert) { + assert.expect(2); + + routes['index'] = createHandler('index', { + beforeModel: function () { + return router.transitionTo('about'); + }, + }); + + routes['about'] = createHandler('about', { + setup: function () { + assert.ok(true, 'about#setup was called'); + }, + }); + + router.transitionTo('/index').then(null, assertAbort(assert)); + } + ); + + QUnit.test('Generate works w queryparams', function (assert) { + assert.equal(router.generate('index'), '/index', 'just index'); + assert.equal( + router.generate('index', { queryParams: { foo: '123' } }), + '/index?foo=123', + 'just index' + ); + assert.equal( + router.generate('index', { queryParams: { foo: '123', bar: '456' } }), + '/index?bar=456&foo=123', + 'just index' + ); + }); + + if (scenario.async) { + QUnit.test('Generate does not invoke getHandler', function (assert) { + let originalGetHandler = router.getRoute; + router.getRoute = function () { + assert.ok(false, 'getHandler should not be called'); + return createHandler('empty'); + }; + + assert.equal(router.generate('index'), '/index', 'just index'); + assert.equal( + router.generate('index', { queryParams: { foo: '123' } }), + '/index?foo=123', + 'just index' + ); + assert.equal( + router.generate('index', { queryParams: { foo: '123', bar: '456' } }), + '/index?bar=456&foo=123', + 'just index' + ); + + router.getRoute = originalGetHandler; + }); + } + + QUnit.test('errors in enter/setup hooks fire `error`', function (assert) { + assert.expect(4); + + let count = 0; + + routes = { + index: createHandler('index', { + enter: function () { + throw 'OMG ENTER'; + }, + setup: function () { + throw 'OMG SETUP'; + }, + events: { + error: function (e: Error) { + if (count === 0) { + assert.equal(e, 'OMG ENTER', "enter's throw value passed to error hook"); + } else if (count === 1) { + assert.equal(e, 'OMG SETUP', "setup's throw value passed to error hook"); + } else { + assert.ok(false, 'should not happen'); + } + }, + }, + }), + }; + + router + .handleURL('/index') + .then(shouldNotHappen(assert), function (reason: string) { + assert.equal(reason, 'OMG ENTER', "enters's error was propagated"); + count++; + delete routes['index']!.enter; + return router.handleURL('/index'); + }) + .then(shouldNotHappen(assert), function (reason: string) { + assert.equal(reason, 'OMG SETUP', "setup's error was propagated"); + delete routes['index']!.setup; + }); + }); + + QUnit.test( + 'invalidating parent model with different string/numeric parameters invalidates children', + async function (assert) { + map(assert, function (match) { + match('/:p').to('parent', function (match) { + match('/:c').to('child'); + }); + }); + + assert.expect(8); + + let count = 0; + routes = { + parent: createHandler('parent', { + model: function (params: Dict) { + assert.ok(true, 'parent model called'); + return { id: params['p'] }; + }, + setup: function (model: Dict) { + if (count === 0) { + assert.deepEqual(model, { id: '1' }); + } else { + assert.deepEqual(model, { id: '2' }); + } + }, + }), + child: createHandler('child', { + model: function (params: Dict) { + assert.ok(true, 'child model called'); + return { id: params['c'] }; + }, + setup: function (model: Dict) { + if (count === 0) { + assert.deepEqual(model, { id: '1' }); + } else { + assert.deepEqual(model, { id: '1' }); + } + }, + }), + }; + + await router.transitionTo('child', '1', '1'); + count = 1; + await router.transitionTo('child', '2', '1'); + } + ); + + QUnit.test( + 'intents make use of previous transition state in case not enough contexts are provided to retry a transition', + async function (assert) { + assert.expect(3); + + map(assert, function (match) { + match('/').to('application', function (match) { + match('/users/:user').to('user', function (match) { + match('/index').to('userIndex'); + match('/auth').to('auth'); + }); + match('/login').to('login'); + }); + }); + + let hasAuthed = false, + savedTransition: Transition, + didFinish = false; + routes = { + auth: createHandler('auth', { + beforeModel: function (transition: Transition) { + if (!hasAuthed) { + savedTransition = transition; + router.transitionTo('login'); + } + }, + setup: function () { + didFinish = true; + }, + }), + }; + + await router.transitionTo('userIndex', { user: 'machty' }); + + // Then attempt to transition into auth; this will redirect. + await ignoreTransitionError(router.transitionTo('auth')); + + assert.ok(savedTransition!, 'transition was saved'); + + hasAuthed = true; + await savedTransition!.retry(); + + assert.ok(didFinish, 'did enter auth route'); + assert.equal( + (routes['user']!.context as any).user, + 'machty', + 'User was remembered upon retry' + ); + } + ); + + QUnit.test('A failed transition calls the catch and finally callbacks', function (assert) { + assert.expect(2); + + map(assert, function (match) { + match('/').to('application', function (match) { + match('/bad').to('badRoute'); + }); + }); + + routes = { + badRoute: createHandler('badRoute', { + beforeModel: function () { + return new Promise(function (_resolve, reject) { + reject('example reason'); + }); + }, + }), + }; + + return router + .handleURL('/bad') + .catch(function () { + assert.ok(true, 'catch callback was called'); + }) + .finally(function () { + assert.ok(true, 'finally callback was called'); + }); + }); + + QUnit.test('A successful transition calls the finally callback', function (assert) { + assert.expect(1); + + map(assert, function (match) { + match('/').to('application', function (match) { + match('/example').to('exampleRoute'); + }); + }); + + router.handleURL('/example').finally(function () { + assert.ok(true, 'finally callback was called'); + }); + }); + + QUnit.test('transition sets isActive by default', function (assert) { + assert.expect(2); + + map(assert, function (match) { + match('/').to('application', function (match) { + match('/example').to('exampleRoute'); + }); + }); + + let transition = router.handleURL('/example'); + + assert.true(transition.isActive); + assert.false(transition.isAborted); + }); + + QUnit.test('transition sets isActive to false when aborted', function (assert) { + assert.expect(4); + + map(assert, function (match) { + match('/').to('application', function (match) { + match('/example').to('exampleRoute'); + }); + }); + + let transition = router.handleURL('/example'); + + assert.true(transition.isActive, 'precond'); + assert.false(transition.isAborted, 'precond'); + + transition.abort(); + + assert.false(transition.isActive, 'isActive should be false after abort'); + assert.true(transition.isAborted, 'isAborted is set to true after abort'); + }); + + if (scenario.async) { + QUnit.test('getHandler is invoked synchronously when returning Promises', function (assert) { + assert.expect(2); + + let count = 0; + let handlerCount = 2; + + routes = { + postIndex: createHandler('postIndex'), + showAllPosts: createHandler('showAllPosts'), + }; + + router.getRoute = function (name) { + count++; + + return Promise.resolve(scenario.getRoute.call(null, name)).then(function (handler: Route) { + assert.equal(count, handlerCount); + return handler; + }); + }; + + router.transitionTo('/posts/all'); + }); + } + + QUnit.module('Multiple dynamic segments per route (' + scenario.name + ')'); + + QUnit.test('Multiple string/number params are soaked up', async function (assert) { + assert.expect(3); + + map(assert, function (match) { + match('/:foo_id/:bar_id').to('bar'); + }); + + routes = { + bar: createHandler('bar', { + model: function () { + return {}; + }, + }), + }; + + expectedUrl = '/omg/lol'; + await router.transitionTo('bar', 'omg', 'lol'); + + expectedUrl = '/omg/heehee'; + await router.transitionTo('bar', 'heehee'); + + expectedUrl = '/lol/no'; + await router.transitionTo('bar', 'lol', 'no'); + }); + + QUnit.module('isActive (' + scenario.name + ')', { + beforeEach: async function (assert: Assert) { + routes = { + parent: createHandler('parent', { + serialize: function (obj: Dict) { + return { + one: obj['one'], + two: obj['two'], + }; + }, + }), + child: createHandler('child', { + serialize: function (obj: Dict) { + return { + three: obj['three'], + four: obj['four'], + }; + }, + }), + }; + + // When using an async getHandler serializers need to be loaded separately + if (scenario.async) { + serializers = { + parent: function (obj) { + let castObj = obj as Dict; + // TODO: Review this + return { + one: castObj['one'], + two: castObj['two'], + }; + }, + child: function (obj) { + let castObj = obj as Dict; + return { + three: castObj['three'], + four: castObj['four'], + }; + }, + }; + } + + map(assert, function (match) { + match('/:one/:two').to('parent', function (match) { + match('/:three/:four').to('child'); + }); + }); + + expectedUrl = null; + + await router.transitionTo('child', 'a', 'b', 'c', 'd'); + }, + }); + + QUnit.test( + 'isActive supports multiple soaked up string/number params (via params)', + function (assert) { + assert.ok(router.isActive('child'), 'child'); + assert.ok(router.isActive('parent'), 'parent'); + + assert.ok(router.isActive('child', 'd'), 'child d'); + assert.ok(router.isActive('child', 'c', 'd'), 'child c d'); + assert.ok(router.isActive('child', 'b', 'c', 'd'), 'child b c d'); + assert.ok(router.isActive('child', 'a', 'b', 'c', 'd'), 'child a b c d'); + + assert.notOk(router.isActive('child', 'e'), '!child e'); + assert.notOk(router.isActive('child', 'c', 'e'), '!child c e'); + assert.notOk(router.isActive('child', 'e', 'd'), '!child e d'); + assert.notOk(router.isActive('child', 'x', 'x'), '!child x x'); + assert.notOk(router.isActive('child', 'b', 'c', 'e'), '!child b c e'); + assert.notOk(router.isActive('child', 'b', 'e', 'd'), 'child b e d'); + assert.notOk(router.isActive('child', 'e', 'c', 'd'), 'child e c d'); + assert.notOk(router.isActive('child', 'a', 'b', 'c', 'e'), 'child a b c e'); + assert.notOk(router.isActive('child', 'a', 'b', 'e', 'd'), 'child a b e d'); + assert.notOk(router.isActive('child', 'a', 'e', 'c', 'd'), 'child a e c d'); + assert.notOk(router.isActive('child', 'e', 'b', 'c', 'd'), 'child e b c d'); + + assert.ok(router.isActive('parent', 'b'), 'parent b'); + assert.ok(router.isActive('parent', 'a', 'b'), 'parent a b'); + + assert.notOk(router.isActive('parent', 'c'), '!parent c'); + assert.notOk(router.isActive('parent', 'a', 'c'), '!parent a c'); + assert.notOk(router.isActive('parent', 'c', 'b'), '!parent c b'); + assert.notOk(router.isActive('parent', 'c', 't'), '!parent c t'); + } + ); + + QUnit.test( + 'isActive supports multiple soaked up string/number params (via serialized objects)', + function (assert) { + assert.ok(router.isActive('child', { three: 'c', four: 'd' }), 'child(3:c, 4:d)'); + assert.notOk(router.isActive('child', { three: 'e', four: 'd' }), '!child(3:e, 4:d)'); + assert.notOk(router.isActive('child', { three: 'c', four: 'e' }), '!child(3:c, 4:e)'); + assert.notOk(router.isActive('child', { three: 'c' }), '!child(3:c)'); + assert.notOk(router.isActive('child', { four: 'd' }), '!child(4:d)'); + assert.notOk(router.isActive('child', {}), '!child({})'); + + assert.ok(router.isActive('parent', { one: 'a', two: 'b' }), 'parent(1:a, 2:b)'); + assert.notOk(router.isActive('parent', { one: 'e', two: 'b' }), '!parent(1:e, 2:b)'); + assert.notOk(router.isActive('parent', { one: 'a', two: 'e' }), '!parent(1:a, 2:e)'); + assert.notOk(router.isActive('parent', { one: 'a' }), '!parent(1:a)'); + assert.notOk(router.isActive('parent', { two: 'b' }), '!parent(2:b)'); + + assert.ok( + router.isActive('child', { one: 'a', two: 'b' }, { three: 'c', four: 'd' }), + 'child(1:a, 2:b, 3:c, 4:d)' + ); + assert.notOk( + router.isActive('child', { one: 'e', two: 'b' }, { three: 'c', four: 'd' }), + '!child(1:e, 2:b, 3:c, 4:d)' + ); + assert.notOk( + router.isActive('child', { one: 'a', two: 'b' }, { three: 'c', four: 'e' }), + '!child(1:a, 2:b, 3:c, 4:e)' + ); + } + ); + + QUnit.test( + 'isActive supports multiple soaked up string/number params (mixed)', + function (assert) { + assert.ok(router.isActive('child', 'a', 'b', { three: 'c', four: 'd' })); + assert.ok(router.isActive('child', 'b', { three: 'c', four: 'd' })); + assert.notOk(router.isActive('child', 'a', { three: 'c', four: 'd' })); + assert.ok(router.isActive('child', { one: 'a', two: 'b' }, 'c', 'd')); + assert.ok(router.isActive('child', { one: 'a', two: 'b' }, 'd')); + assert.notOk(router.isActive('child', { one: 'a', two: 'b' }, 'c')); + + assert.notOk(router.isActive('child', 'a', 'b', { three: 'e', four: 'd' })); + assert.notOk(router.isActive('child', 'b', { three: 'e', four: 'd' })); + assert.notOk(router.isActive('child', { one: 'e', two: 'b' }, 'c', 'd')); + assert.notOk(router.isActive('child', { one: 'e', two: 'b' }, 'd')); + } + ); + + QUnit.module('Preservation of params between redirects (' + scenario.name + ')', { + beforeEach: function (assert: Assert) { + expectedUrl = null; + + map(assert, function (match) { + match('/').to('index'); + match('/:foo_id').to('foo', function (match) { + match('/').to('fooIndex'); + match('/:bar_id').to('bar', function (match) { + match('/').to('barIndex'); + }); + }); + }); + + routes = { + foo: createHandler('foo', { + modelCount: undefined, + model: function (params: Dict) { + this['modelCount'] = this['modelCount'] ? (this as any).modelCount + 1 : 1; + return { id: params['foo_id'] }; + }, + afterModel: function () { + router.transitionTo('barIndex', '789'); + }, + }), + + bar: createHandler('bar', { + model: function (params: Dict) { + this['modelCount'] = this['modelCount'] ? (this as any).modelCount + 1 : 1; + return { id: params['bar_id'] }; + }, + }), + }; + }, + }); + + QUnit.test("Starting on '/' root index", async function (assert) { + await router.transitionTo('/'); + + // Should call model for foo and bar + expectedUrl = '/123/789'; + await ignoreTransitionError(router.transitionTo('barIndex', '123', '456')); + + assert.equal( + (routes['foo'] as any).modelCount, + 2, + 'redirect in foo#afterModel should run foo#model twice (since validation failed)' + ); + + assert.deepEqual(routes['foo']!.context, { id: '123' }); + assert.deepEqual( + routes['bar']!.context, + { id: '789' }, + 'bar should have redirected to bar 789' + ); + + // Try setting foo's context to 200; this should redirect + // bar to '789' but preserve the new foo 200. + expectedUrl = '/200/789'; + await ignoreTransitionError(router.transitionTo('fooIndex', '200')); + + assert.equal( + (routes['foo'] as any).modelCount, + 4, + 'redirect in foo#afterModel should re-run foo#model' + ); + + assert.deepEqual(routes['foo']!.context, { id: '200' }); + assert.deepEqual( + routes['bar']!.context, + { id: '789' }, + 'bar should have redirected to bar 789' + ); + }); + + QUnit.test("Starting on '/' root index, using redirect", async function (assert) { + (routes['foo']!.redirect as any) = routes['foo']!.afterModel; + delete routes['foo']!.afterModel; + + await router.transitionTo('/'); + + // Should call model for foo and bar + expectedUrl = '/123/789'; + await ignoreTransitionError(router.transitionTo('barIndex', '123', '456')); + + assert.equal( + (routes['foo'] as any).modelCount, + 1, + 'redirect in foo#redirect should NOT run foo#model (since validation succeeded)' + ); + + assert.deepEqual(routes['foo']!.context, { id: '123' }); + assert.deepEqual( + routes['bar']!.context, + { id: '789' }, + 'bar should have redirected to bar 789' + ); + + // Try setting foo's context to 200; this should redirect + // bar to '789' but preserve the new foo 200. + expectedUrl = '/200/789'; + await ignoreTransitionError(router.transitionTo('fooIndex', '200')); + + assert.equal( + (routes['foo'] as any).modelCount, + 2, + 'redirect in foo#redirect should NOT foo#model' + ); + + assert.deepEqual(routes['foo']!.context, { id: '200' }); + assert.deepEqual( + routes['bar']!.context, + { id: '789' }, + 'bar should have redirected to bar 789' + ); + }); + + QUnit.test('Starting on non root index', async function (assert) { + await ignoreTransitionError(router.transitionTo('/123/456')); + assert.deepEqual(routes['foo']!.context, { id: '123' }); + assert.deepEqual( + routes['bar']!.context, + { id: '789' }, + 'bar should have redirected to bar 789' + ); + + // Try setting foo's context to 200; this should redirect + // bar to '789' but preserve the new foo 200. + expectedUrl = '/200/789'; + + await ignoreTransitionError(router.transitionTo('fooIndex', '200')); + + assert.deepEqual(routes['foo']!.context, { id: '200' }); + assert.deepEqual( + routes['bar']!.context, + { id: '789' }, + 'bar should have redirected to bar 789' + ); + }); + + /* TODO revisit + QUnit.test("A failed handler's setup shouldn't prevent future transitions", function(assert) { + assert.expect(2); + + enableErrorHandlingDeferredActionQueue(); + + map(assert, function(match) { + match("/parent").to('parent', function(match) { + match("/articles").to('articles'); + match("/login").to('login'); + }); + }); + + let error = new Error("blorg"); + + handlers = { + articles: { + setup: function() { + assert.ok(true, "articles setup was entered"); + throw error; + }, + events: { + error: function() { + assert.ok(true, "error handled in articles"); + router.transitionTo('login'); + } + } + }, + + login: { + setup: function() { + start(); + } + } + }; + + router.handleURL('/parent/articles'); + flush(error); + }); + */ + + QUnit.test( + "beforeModel shouldn't be refired with incorrect params during redirect", + async function (assert) { + // Source: https://github.com/emberjs/ember.js/issues/3407 + + assert.expect(3); + + map(assert, function (match) { + match('/').to('index'); + match('/people/:id').to('people', function (match) { + match('/').to('peopleIndex'); + match('/home').to('peopleHome'); + }); + }); + + let peopleModels: any[] = [null, {}, {}]; + let peopleBeforeModelCalled = false; + + routes = { + people: createHandler('people', { + beforeModel: function () { + assert.notOk(peopleBeforeModelCalled, 'people#beforeModel should only be called once'); + peopleBeforeModelCalled = true; + }, + model: function (params: Dict) { + assert.ok(params['id'], 'people#model called'); + return peopleModels[params['id'] as number]; + }, + }), + peopleIndex: createHandler('peopleIndex', { + afterModel: function () { + router.transitionTo('peopleHome'); + }, + }), + peopleHome: createHandler('peopleHome', { + setup: function () { + assert.ok(true, 'I was entered'); + }, + }), + }; + + await router.transitionTo('/'); + await ignoreTransitionError(router.transitionTo('peopleIndex', '1')); + } + ); + + QUnit.module('URL-less routes (' + scenario.name + ')', { + beforeEach: function (assert: Assert) { + routes = {}; + expectedUrl = null; + + map(assert, function (match) { + match('/index').to('index'); + match('/admin').to('admin', function (match) { + match('/posts').to('adminPosts'); + match('/articles').to('adminArticles'); + }); + }); + }, + }); + + QUnit.test( + "Transitioning into a route marked as inaccessibleByURL doesn't update the URL", + function (assert) { + assert.expect(1); + + routes = { + adminPosts: createHandler('adminPosts', { + inaccessibleByURL: true, + }), + }; + + router + .handleURL('/index') + .then(function () { + url = '/index'; + return router.transitionTo('adminPosts'); + }) + .then(function () { + assert.equal(url, '/index'); + }); + } + ); + + QUnit.test( + "Transitioning into a route with a parent route marked as inaccessibleByURL doesn't update the URL", + async function (assert) { + assert.expect(2); + + routes = { + admin: createHandler('admin', { + inaccessibleByURL: true, + }), + }; + + await router.transitionTo('/index'); + url = '/index'; + await router.transitionTo('adminPosts'); + assert.equal(url, '/index'); + await router.transitionTo('adminArticles'); + assert.equal(url, '/index'); + } + ); + + QUnit.test( + 'Handling a URL on a route marked as inaccessible behaves like a failed url match', + function (assert) { + assert.expect(1); + + routes = { + admin: createHandler('admin', { + inaccessibleByURL: true, + }), + }; + + router + .handleURL('/index') + .then(function () { + return router.handleURL('/admin/posts'); + }) + .then(shouldNotHappen(assert), function (e: Error) { + assert.equal(e.name, 'UnrecognizedURLError', 'error.name is UnrecognizedURLError'); + }); + } + ); + + QUnit.module('Intermediate transitions (' + scenario.name + ')', { + beforeEach: function (assert: Assert) { + routes = {}; + expectedUrl = null; + + map(assert, function (match) { + match('/').to('application', function (match) { + //match("/").to("index"); + match('/foo').to('foo'); + match('/loading').to('loading'); + }); + }); + }, + }); + + QUnit.test( + 'intermediateTransitionTo() has the correct RouteInfo objects', + async function (assert) { + assert.expect(9); + routes = { + application: createHandler('application'), + foo: createHandler('foo', { + model: function () { + router.intermediateTransitionTo('loading'); + return new Promise(function (resolve) { + resolve(); + }); + }, + }), + loading: createHandler('loading'), + }; + + let enteredCount = 0; + router.routeWillChange = (transition: Transition) => { + if (enteredCount === 0) { + assert.equal(transition.to!.name, 'foo', 'going to'); + assert.equal(transition.to!.queryParams['qux'], '42', 'going to with query params'); + } else if (enteredCount === 1) { + assert.equal(transition.to!.name, 'loading', 'entering'); + assert.equal( + transition.to!.queryParams['qux'], + '42', + 'intermediate also has query params' + ); + // https://github.com/emberjs/ember.js/issues/14438 + assert.equal(transition[STATE_SYMBOL].routeInfos.length, 2, 'with routeInfos present'); + } + enteredCount++; + assert.equal(transition.from, null); + }; + + router.routeDidChange = (transition: Transition) => { + assert.equal(transition.to!.name, 'foo', 'landed at'); + assert.equal(enteredCount, 2); + }; + + await router.transitionTo('/foo?qux=42'); + } + ); + + QUnit.test( + "intermediateTransitionTo() forces an immediate intermediate transition that doesn't cancel currently active async transitions", + async function (assert) { + assert.expect(11); + + let counter = 1, + willResolves: Route[], + appModel = {}, + fooModel = {}; + + function counterAt(expectedValue: number, description: string) { + assert.equal(counter, expectedValue, 'Step ' + expectedValue + ': ' + description); + counter++; + } + + routes = { + application: createHandler('application', { + model: function () { + return appModel; + }, + setup: function (obj: Dict) { + counterAt(1, 'application#setup'); + assert.equal(obj, appModel, 'application#setup is passed the return value from model'); + }, + events: { + willResolveModel: function (_transition: Transition, handler: Route) { + assert.equal( + willResolves.shift(), + handler, + 'willResolveModel event fired and passed expanded handler' + ); + }, + }, + }), + foo: createHandler('foo', { + model: function () { + router.intermediateTransitionTo('loading'); + counterAt(3, 'intermediate transition finished within foo#model'); + + return new Promise(function (resolve) { + counterAt(4, "foo's model promise resolves"); + resolve(fooModel); + }); + }, + setup: function (obj: Dict) { + counterAt(6, 'foo#setup'); + assert.equal(obj, fooModel, 'foo#setup is passed the resolve model promise'); + }, + }), + loading: createHandler('loading', { + model: function () { + assert.ok(false, "intermediate transitions don't call model hooks"); + }, + setup: function () { + counterAt(2, 'loading#setup'); + }, + exit: function () { + counterAt(5, 'loading state exited'); + }, + }), + }; + + willResolves = [routes['application']!, routes['foo']!]; + + await router.transitionTo('/foo'); + + counterAt(7, 'original transition promise resolves'); + } + ); + + QUnit.test( + 'Calling transitionTo during initial transition in validation hook should use replaceURL', + async function (assert) { + assert.expect(4); + map(assert, function (match) { + match('/foo').to('foo'); + match('/bar').to('bar'); + }); + + let fooModelCount = 0, + barModelCount = 0; + + router.updateURL = function (updateUrl) { + url = updateUrl; + assert.ok(false, 'The url was not correctly replaced on initial transition'); + }; + + router.replaceURL = function (replaceURL) { + url = replaceURL; + assert.ok(true, 'The url was replaced correctly on initial transition'); + }; + + let fooHandler = createHandler('foo', { + model: function () { + fooModelCount++; + router.transitionTo('/bar'); + }, + }); + + let barHandler = createHandler('bar', { + model: function () { + barModelCount++; + }, + }); + + routes = { + foo: fooHandler, + bar: barHandler, + }; + + await ignoreTransitionError(router.transitionTo('/foo')); + + assert.equal(url, '/bar'); + assert.equal(fooModelCount, 1); + assert.equal(barModelCount, 1); + } + ); + + QUnit.test( + 'Calling transitionTo during initial transition in validation hook with multiple redirects should use replaceURL', + async function (assert) { + assert.expect(5); + map(assert, function (match) { + match('/foo').to('foo'); + match('/bar').to('bar'); + match('/baz').to('baz'); + }); + + let fooModelCount = 0, + barModelCount = 0, + bazModelCount = 0; + + router.updateURL = function (updateUrl) { + url = updateUrl; + assert.ok(false, 'The url was not correctly replaced on initial transition'); + }; + + router.replaceURL = function (replaceURL) { + url = replaceURL; + assert.ok(true, 'The url was replaced correctly on initial transition'); + }; + + let fooHandler = createHandler('foo', { + model: function () { + fooModelCount++; + router.transitionTo('/bar'); + }, + }); + + let barHandler = createHandler('bar', { + model: function () { + barModelCount++; + router.transitionTo('/baz'); + }, + }); + + let bazHandler = createHandler('baz', { + model: function () { + bazModelCount++; + }, + }); + + routes = { + foo: fooHandler, + bar: barHandler, + baz: bazHandler, + }; + + await ignoreTransitionError(router.transitionTo('/foo')); + + assert.equal(url, '/baz'); + assert.equal(fooModelCount, 1); + assert.equal(barModelCount, 1); + assert.equal(bazModelCount, 1); + } + ); + + QUnit.test( + 'Calling transitionTo after initial transition in validation hook should use updateUrl', + async function (assert) { + assert.expect(8); + + map(assert, function (match) { + match('/foo').to('foo'); + match('/bar').to('bar'); + }); + + let fooModelCount = 0, + barModelCount = 0; + + router.updateURL = function (updateUrl) { + url = updateUrl; + assert.ok(true, 'updateURL should be used'); + }; + + router.replaceURL = function (replaceURL) { + url = replaceURL; + assert.ok(false, 'replaceURL should not be used'); + }; + + let fooHandler = createHandler('foo', { + model: function () { + fooModelCount++; + router.transitionTo('/bar'); + }, + }); + + let barHandler = createHandler('bar', { + model: function () { + barModelCount++; + }, + }); + + routes = { + foo: fooHandler, + bar: barHandler, + }; + + await router.transitionTo('/bar'); + + assert.equal(url, '/bar'); + assert.equal(barModelCount, 1, 'Bar model should be called once'); + assert.equal(fooModelCount, 0, 'Foo model should not be called'); + + await ignoreTransitionError(router.transitionTo('/foo')); + + assert.equal(url, '/bar'); + assert.equal(barModelCount, 2, 'Bar model should be called twice'); + assert.equal(fooModelCount, 1, 'Foo model should be called once'); + } + ); + + QUnit.test( + 'Calling transitionTo after initial transition in validation hook with multiple redirects should use updateUrl', + async function (assert) { + assert.expect(10); + + map(assert, function (match) { + match('/foo').to('foo'); + match('/bar').to('bar'); + match('/baz').to('baz'); + }); + + let fooModelCount = 0, + barModelCount = 0, + bazModelCount = 0; + + router.updateURL = function (updateUrl) { + url = updateUrl; + assert.ok(true, 'updateURL should be used'); + }; + + router.replaceURL = function (replaceURL) { + url = replaceURL; + assert.ok(false, 'replaceURL should not be used'); + }; + + let fooHandler = createHandler('foo', { + model: function () { + fooModelCount++; + router.transitionTo('/bar'); + }, + }); + + let barHandler = createHandler('bar', { + model: function () { + barModelCount++; + router.transitionTo('/baz'); + }, + }); + + let bazHandler = createHandler('baz', { + model: function () { + bazModelCount++; + }, + }); + + routes = { + foo: fooHandler, + bar: barHandler, + baz: bazHandler, + }; + + await router.transitionTo('/baz'); + + assert.equal(url, '/baz'); + assert.equal(bazModelCount, 1, 'Baz model should be called once'); + assert.equal(fooModelCount, 0, 'Foo model should not be called'); + assert.equal(barModelCount, 0, 'Bar model should not be called'); + + await ignoreTransitionError(router.transitionTo('/foo')); + + assert.equal(url, '/baz'); + assert.equal(bazModelCount, 2, 'Baz model should be called twice'); + assert.equal(fooModelCount, 1, 'Foo model should be called once'); + assert.equal(barModelCount, 1, 'Bar model should be called once'); + } + ); + + QUnit.test( + 'Calling replaceWith during initial transition in validation hook should use replaceURL', + async function (assert) { + assert.expect(4); + map(assert, function (match) { + match('/foo').to('foo'); + match('/bar').to('bar'); + }); + + let fooModelCount = 0, + barModelCount = 0; + + router.updateURL = function (updateUrl) { + url = updateUrl; + assert.ok(false, 'The url was not correctly replaced on initial transition'); + }; + + router.replaceURL = function (replaceURL) { + url = replaceURL; + assert.ok(true, 'The url was replaced correctly on initial transition'); + }; + + let fooHandler = createHandler('foo', { + model: function () { + fooModelCount++; + router.replaceWith('/bar'); + }, + }); + + let barHandler = createHandler('bar', { + model: function () { + barModelCount++; + }, + }); + + routes = { + foo: fooHandler, + bar: barHandler, + }; + + await ignoreTransitionError(router.transitionTo('/foo')); + + assert.equal(url, '/bar'); + assert.equal(fooModelCount, 1); + assert.equal(barModelCount, 1); + } + ); + + QUnit.test( + 'Calling replaceWith during initial transition in validation hook with multiple redirects should use replaceURL', + async function (assert) { + assert.expect(5); + map(assert, function (match) { + match('/foo').to('foo'); + match('/bar').to('bar'); + match('/baz').to('baz'); + }); + + let fooModelCount = 0, + barModelCount = 0, + bazModelCount = 0; + + router.updateURL = function (updateUrl) { + url = updateUrl; + assert.ok(false, 'The url was not correctly replaced on initial transition'); + }; + + router.replaceURL = function (replaceURL) { + url = replaceURL; + assert.ok(true, 'The url was replaced correctly on initial transition'); + }; + + let fooHandler = createHandler('foo', { + model: function () { + fooModelCount++; + router.replaceWith('/bar'); + }, + }); + + let barHandler = createHandler('bar', { + model: function () { + barModelCount++; + router.replaceWith('/baz'); + }, + }); + + let bazHandler = createHandler('baz', { + model: function () { + bazModelCount++; + }, + }); + + routes = { + foo: fooHandler, + bar: barHandler, + baz: bazHandler, + }; + + await ignoreTransitionError(router.transitionTo('/foo')); + + assert.equal(url, '/baz'); + assert.equal(fooModelCount, 1, 'should call foo model once'); + assert.equal(barModelCount, 1, 'should call bar model once'); + assert.equal(bazModelCount, 1, 'should call baz model once'); + } + ); + + QUnit.test( + 'Calling replaceWith after initial transition in validation hook should use updateUrl', + async function (assert) { + assert.expect(8); + + map(assert, function (match) { + match('/foo').to('foo'); + match('/bar').to('bar'); + }); + + let fooModelCount = 0, + barModelCount = 0; + + router.updateURL = function (updateUrl) { + url = updateUrl; + assert.ok(true, 'updateURL should be used'); + }; + + router.replaceURL = function (replaceURL) { + url = replaceURL; + assert.ok(false, 'replaceURL should not be used'); + }; + + let fooHandler = createHandler('foo', { + model: function () { + fooModelCount++; + router.replaceWith('/bar'); + }, + }); + let barHandler = createHandler('bar', { + model: function () { + barModelCount++; + }, + }); + + routes = { + foo: fooHandler, + bar: barHandler, + }; + + await router.transitionTo('/bar'); + + assert.equal(url, '/bar'); + assert.equal(barModelCount, 1, 'Bar model should be called once'); + assert.equal(fooModelCount, 0, 'Foo model should not be called'); + + await ignoreTransitionError(router.transitionTo('/foo')); + + assert.equal(url, '/bar'); + assert.equal(barModelCount, 2, 'Bar model should be called twice'); + assert.equal(fooModelCount, 1, 'Foo model should be called once'); + } + ); + + QUnit.test( + 'Calling replaceWith after initial transition in validation hook with multiple redirects should use updateUrl', + async function (assert) { + assert.expect(10); + + map(assert, function (match) { + match('/foo').to('foo'); + match('/bar').to('bar'); + match('/baz').to('baz'); + }); + + let fooModelCount = 0, + barModelCount = 0, + bazModelCount = 0; + + router.updateURL = function (updateUrl) { + url = updateUrl; + assert.ok(true, 'updateURL should be used'); + }; + + router.replaceURL = function (replaceURL) { + url = replaceURL; + assert.ok(false, 'replaceURL should not be used'); + }; + + let fooHandler = createHandler('foo', { + model: function () { + fooModelCount++; + router.replaceWith('/bar'); + }, + }); + + let barHandler = createHandler('bar', { + model: function () { + barModelCount++; + router.replaceWith('/baz'); + }, + }); + + let bazHandler = createHandler('baz', { + model: function () { + bazModelCount++; + }, + }); + + routes = { + foo: fooHandler, + bar: barHandler, + baz: bazHandler, + }; + + await router.transitionTo('/baz'); + + assert.equal(url, '/baz'); + assert.equal(bazModelCount, 1, 'Bar model should be called once'); + assert.equal(fooModelCount, 0, 'Foo model should not be called'); + assert.equal(barModelCount, 0, 'Baz model should not be called'); + + await ignoreTransitionError(router.transitionTo('/foo')); + + assert.equal(url, '/baz'); + assert.equal(bazModelCount, 2, 'Baz model should be called twice'); + assert.equal(fooModelCount, 1, 'Foo model should be called once'); + assert.equal(barModelCount, 1, 'Bar model should be called once'); + } + ); + + QUnit.test( + 'Calling replaceWith after initial replace in validation hook with multiple redirects should use replaceUrl', + async function (assert) { + map(assert, function (match) { + match('/foo').to('foo'); + match('/bar').to('bar'); + match('/baz').to('baz'); + match('/qux').to('qux'); + }); + + let fooModelCount = 0, + barModelCount = 0, + bazModelCount = 0, + history: string[] = []; + + router.updateURL = function (updateUrl) { + url = updateUrl; + history.push(url); + }; + + router.replaceURL = function (replaceURL) { + url = replaceURL; + if (history.length === 0) { + assert.ok(false, 'should not replace on initial'); + } + history[history.length - 1] = url; + }; + + let fooHandler = createHandler('foo', { + model: function () { + fooModelCount++; + router.replaceWith('/bar'); + }, + }); + + let barHandler = createHandler('bar', { + model: function () { + barModelCount++; + router.replaceWith('/baz'); + }, + }); + + let bazHandler = createHandler('baz', { + model: function () { + bazModelCount++; + }, + }); + + let quxHandler = createHandler('qux', { + model: function () {}, + }); + + routes = { + foo: fooHandler, + bar: barHandler, + baz: bazHandler, + qux: quxHandler, + }; + + await router.transitionTo('/qux'); + + assert.equal(history.length, 1, 'only one history item'); + assert.equal(history[0], '/qux', 'history item is /qux'); + + await ignoreTransitionError(replaceWith(router, '/foo')); + + assert.equal(history.length, 1, 'still only one history item, replaced the previous'); + assert.equal(history[0], '/baz', 'history item is /foo'); + assert.equal(fooModelCount, 1, 'Foo model should be called once'); + assert.equal(barModelCount, 1, 'Bar model should be called once'); + assert.equal(bazModelCount, 1, 'Baz model should be called once'); + } + ); + + QUnit.test( + 'Mixing multiple types of redirect during initial transition should work', + async function (assert) { + assert.expect(10); + + map(assert, function (match) { + match('/foo').to('foo'); + match('/bar').to('bar'); + match('/baz').to('baz'); + }); + + let fooModelCount = 0, + barModelCount = 0, + bazModelCount = 0; + + router.updateURL = function (updateUrl) { + url = updateUrl; + assert.ok(true, 'updateURL should be used'); + }; + + router.replaceURL = function (replaceURL) { + url = replaceURL; + assert.ok(false, 'replaceURL should not be used'); + }; + + let fooHandler = createHandler('foo', { + model: function () { + fooModelCount++; + router.replaceWith('/bar'); + }, + }); + + let barHandler = createHandler('bar', { + model: function () { + barModelCount++; + router.transitionTo('/baz'); + }, + }); + + let bazHandler = createHandler('baz', { + model: function () { + bazModelCount++; + }, + }); + + routes = { + foo: fooHandler, + bar: barHandler, + baz: bazHandler, + }; + + await router.transitionTo('/baz'); + + assert.equal(url, '/baz'); + assert.equal(bazModelCount, 1, 'Bar model should be called once'); + assert.equal(fooModelCount, 0, 'Foo model should not be called'); + assert.equal(barModelCount, 0, 'Baz model should not be called'); + + await ignoreTransitionError(router.transitionTo('/foo')); + + assert.equal(url, '/baz'); + assert.equal(bazModelCount, 2, 'Baz model should be called twice'); + assert.equal(fooModelCount, 1, 'Foo model should be called once'); + assert.equal(barModelCount, 1, 'Bar model should be called once'); + } + ); + + QUnit.test( + 'Mixing multiple types of redirects after initial transition should work', + async function (assert) { + assert.expect(12); + + map(assert, function (match) { + match('/foo').to('foo'); + match('/bar').to('bar'); + match('/baz').to('baz'); + }); + + let fooModelCount = 0, + barModelCount = 0, + bazModelCount = 0, + updateUrlCount = 0, + replaceUrlCount = 0; + + router.updateURL = function (updateUrl) { + url = updateUrl; + updateUrlCount++; + }; + + router.replaceURL = function (replaceURL) { + url = replaceURL; + replaceUrlCount++; + }; + + let fooHandler = createHandler('foo', { + model: function () { + fooModelCount++; + router.replaceWith('/bar'); + }, + }); + + let barHandler = createHandler('bar', { + model: function () { + barModelCount++; + router.transitionTo('/baz'); + }, + }); + + let bazHandler = createHandler('baz', { + model: function () { + bazModelCount++; + }, + }); + + routes = { + foo: fooHandler, + bar: barHandler, + baz: bazHandler, + }; + + await router.transitionTo('/baz'); + // actually replaceURL probably makes more sense here, but it's an initial + // transition to a route that the page loaded on, so it's a no-op and doesn't + // cause a problem + assert.equal(replaceUrlCount, 0, 'replaceURL should not be used'); + assert.equal(updateUrlCount, 1, 'updateURL should be used for initial transition'); + assert.equal(url, '/baz'); + assert.equal(bazModelCount, 1, 'Baz model should be called once'); + assert.equal(fooModelCount, 0, 'Foo model should not be called'); + assert.equal(barModelCount, 0, 'Bar model should not be called'); + + await ignoreTransitionError(router.transitionTo('/foo')); + + assert.equal(replaceUrlCount, 0, 'replaceURL should not be used'); + assert.equal(updateUrlCount, 2, 'updateURL should be used for subsequent transition'); + assert.equal(url, '/baz'); + assert.equal(bazModelCount, 2, 'Baz model should be called twice'); + assert.equal(fooModelCount, 1, 'Foo model should be called once'); + assert.equal(barModelCount, 1, 'Bar model should be called once'); + } + ); + + QUnit.test( + 'Calling replaceWith after initial transition outside validation hook should use replaceURL', + async function (assert) { + assert.expect(7); + + map(assert, function (match) { + match('/foo').to('foo'); + match('/bar').to('bar'); + }); + + let fooModelCount = 0, + barModelCount = 0; + + router.updateURL = function (updateUrl) { + url = updateUrl; + assert.equal(updateUrl, '/foo', 'incorrect url for updateURL'); + }; + + router.replaceURL = function (replaceUrl) { + url = replaceUrl; + assert.equal(replaceUrl, '/bar', 'incorrect url for replaceURL'); + }; + + let fooHandler = createHandler('foo', { + model: function () { + fooModelCount++; + }, + }); + let barHandler = createHandler('bar', { + model: function () { + barModelCount++; + }, + }); + + routes = { + foo: fooHandler, + bar: barHandler, + }; + + await router.transitionTo('/foo'); + + assert.equal(url, '/foo', 'failed initial transition'); + assert.equal(fooModelCount, 1, 'Foo model should be called once'); + assert.equal(barModelCount, 0, 'Bar model should not be called'); + + await router.replaceWith('/bar'); + + assert.equal(fooModelCount, 1, 'Foo model should be called once'); + assert.equal(barModelCount, 1, 'Bar model should be called once'); + } + ); + + QUnit.test( + 'Calling transitionTo after initial transition outside validation hook should use updateUrl', + async function (assert) { + assert.expect(7); + + map(assert, function (match) { + match('/foo').to('foo'); + match('/bar').to('bar'); + }); + + let fooModelCount = 0, + barModelCount = 0; + + router.updateURL = function (updateUrl) { + url = updateUrl; + assert.ok(true, 'updateURL is used'); + }; + + router.replaceURL = function (replaceURL) { + url = replaceURL; + assert.ok(false, 'replaceURL should not be used'); + }; + + let fooHandler = createHandler('foo', { + model: function () { + fooModelCount++; + }, + }); + let barHandler = createHandler('bar', { + model: function () { + barModelCount++; + }, + }); + + routes = { + foo: fooHandler, + bar: barHandler, + }; + + await router.transitionTo('/foo'); + + assert.equal(url, '/foo', 'failed initial transition'); + assert.equal(fooModelCount, 1, 'Foo model should be called once'); + assert.equal(barModelCount, 0, 'Bar model should not be called'); + + await router.transitionTo('/bar'); + + assert.equal(fooModelCount, 1, 'Foo model should be called once'); + assert.equal(barModelCount, 1, 'Bar model should be called once'); + } + ); + + QUnit.test( + 'transitioning to the same route with different context should not reenter the route', + async function (assert) { + map(assert, function (match) { + match('/project/:project_id').to('project'); + }); + + let projectEnterCount = 0; + let projectSetupCount = 0; + let projectHandler = createHandler('project', { + model: function (params: Dict) { + delete params['queryParams']; + return params; + }, + enter: function () { + projectEnterCount++; + }, + setup: function () { + projectSetupCount++; + }, + }); + + routes = { + project: projectHandler, + }; + + await router.transitionTo('/project/1'); + assert.equal(projectEnterCount, 1, 'project handler should have been entered once'); + assert.equal(projectSetupCount, 1, 'project handler should have been setup once'); + + await router.transitionTo('/project/2'); + assert.equal( + projectEnterCount, + 1, + 'project handler should still have been entered only once' + ); + assert.equal(projectSetupCount, 2, 'project handler should have been setup twice'); + } + ); + + QUnit.test( + 'synchronous transition errors can be detected synchronously', + async function (assert) { + map(assert, function (match) { + match('/').to('root'); + }); + + router.getRoute = function () { + throw new Error('boom!'); + }; + + const transition = router.transitionTo('/'); + + assert.rejects(transition as unknown as Promise); + assert.equal((transition.error as Error).message, 'boom!'); + } + ); +}); diff --git a/packages/router_js/tests/test_helpers.ts b/packages/router_js/tests/test_helpers.ts new file mode 100644 index 00000000000..dcba75cd40e --- /dev/null +++ b/packages/router_js/tests/test_helpers.ts @@ -0,0 +1,174 @@ +import type { Route, Transition } from '../index'; +import Router from '../index'; +import type { Dict } from '../lib/core'; +import type { IModel } from '../lib/route-info'; +import RouteInfo, { UnresolvedRouteInfoByParam } from '../lib/route-info'; +import type { PublicTransition } from '../lib/transition'; +import { logAbort } from '../lib/transition'; +import type { TransitionError } from '../lib/transition-state'; +import type { UnrecognizedURLError } from '../lib/unrecognized-url-error'; +import { isTransitionAborted } from '../lib/transition-aborted-error'; + +QUnit.config.testTimeout = 1000; + +// A useful function to allow you to ignore transition errors in a testing context +export async function ignoreTransitionError(transition: Transition) { + try { + await transition; + } catch { + // if it errors we don't do anything + } +} + +function assertAbort(assert: Assert) { + return function _assertAbort(e: Error) { + assert.ok(isTransitionAborted(e), 'transition was redirected/aborted'); + }; +} + +function transitionToWithAbort(assert: Assert, router: Router, path: string) { + return router.transitionTo(path).then(shouldNotHappen(assert), assertAbort(assert)); +} + +function replaceWith(router: Router, path: string) { + return router.transitionTo.apply(router, [path]).method('replace'); +} + +function shouldNotHappen(assert: Assert, _message?: string) { + let message = _message || 'this .then handler should not be called'; + return function _shouldNotHappen(error: any) { + console.error(error.stack); // eslint-disable-line + assert.ok(false, message); + return error; + }; +} + +export function isExiting(route: Route | string, routeInfos: RouteInfo[]) { + for (let i = 0, len = routeInfos.length; i < len; ++i) { + let routeInfo = routeInfos[i]; + if (routeInfo!.name === route || routeInfo!.route === route) { + return false; + } + } + return true; +} + +function stubbedHandlerInfoFactory(name: string, props: Dict) { + let obj = Object.create(props); + obj._handlerInfoType = name; + return obj; +} + +export { + transitionToWithAbort, + replaceWith, + shouldNotHappen, + stubbedHandlerInfoFactory, + assertAbort, +}; + +export function createHandler(name: string, options?: Dict): Route { + return Object.assign( + { name, routeName: name, context: {}, names: [], handler: name, _internalName: name }, + options + ) as unknown as Route; +} + +export class TestRouter extends Router { + didTransition() {} + willTransition() {} + updateURL(_url: string): void {} + replaceURL(_url: string): void {} + triggerEvent( + _handlerInfos: RouteInfo[], + _ignoreFailure: boolean, + _name: string, + _args: any[] + ) {} + routeDidChange() {} + routeWillChange() {} + transitionDidError(error: TransitionError, transition: PublicTransition) { + if (error.wasAborted || transition.isAborted) { + return logAbort(transition); + } else { + transition.trigger(false, 'error', error.error, this, error.route); + transition.abort(); + return error.error; + } + } + getRoute(_name: string): any { + return {}; + } + getSerializer(_name: string): any { + return () => {}; + } +} + +export function createHandlerInfo(name: string, options: Dict = {}): RouteInfo { + class Stub extends RouteInfo { + constructor(name: string, router: Router, handler?: Route) { + super(router, name, [], handler); + } + getModel(_transition: Transition) { + return {} as any; + } + getUnresolved() { + return new UnresolvedRouteInfoByParam(this.router, 'empty', [], {}); + } + } + + let handler = (options['handler'] as Route) || createHandler('foo'); + delete options['handler']; + + Object.assign(Stub.prototype, options); + let stub = new Stub(name, new TestRouter(), handler); + return stub; +} + +export function trigger( + handlerInfos: RouteInfo[], + ignoreFailure: boolean, + name: string, + ...args: any[] +) { + if (!handlerInfos) { + if (ignoreFailure) { + return; + } + throw new Error("Could not trigger event '" + name + "'. There are no active handlers"); + } + + let eventWasHandled = false; + + for (let i = handlerInfos.length - 1; i >= 0; i--) { + let currentHandlerInfo = handlerInfos[i]!, + currentHandler = currentHandlerInfo.route; + + // If there is no handler, it means the handler hasn't resolved yet which + // means that we should trigger the event later when the handler is available + if (!currentHandler) { + currentHandlerInfo.routePromise!.then(function (resolvedHandler) { + if (resolvedHandler.events?.[name]) { + resolvedHandler.events[name].apply(resolvedHandler, args); + } + }); + continue; + } + + if (currentHandler.events && currentHandler.events[name]) { + if (currentHandler.events[name].apply(currentHandler, args) === true) { + eventWasHandled = true; + } else { + return; + } + } + } + + // In the case that we got an UnrecognizedURLError as an event with no handler, + // let it bubble up + if (name === 'error' && (args[0] as UnrecognizedURLError)!.name === 'UnrecognizedURLError') { + throw args[0]; + } else if (!eventWasHandled && !ignoreFailure) { + throw new Error("Nothing handled the event '" + name + "'."); + } +} diff --git a/packages/router_js/tests/transition-aborted-error_test.ts b/packages/router_js/tests/transition-aborted-error_test.ts new file mode 100644 index 00000000000..14267e5456c --- /dev/null +++ b/packages/router_js/tests/transition-aborted-error_test.ts @@ -0,0 +1,38 @@ +import { + throwIfAborted, + isTransitionAborted, + buildTransitionAborted, +} from '../lib/transition-aborted-error'; + +QUnit.module('transition-aborted-error'); + +QUnit.test('correct inheritance and name', function (assert) { + let error; + + try { + throw buildTransitionAborted(); + } catch (e) { + error = e; + } + + // it would be more correct with TransitionAbortedError, but other libraries may rely on this name + assert.equal( + (error as Error).name, + 'TransitionAborted', + "TransitionAbortedError has the name 'TransitionAborted'" + ); + + assert.ok(isTransitionAborted(error)); + assert.ok(error instanceof Error); +}); + +QUnit.test('throwIfAborted', function (assert) { + throwIfAborted(undefined); + throwIfAborted(null); + throwIfAborted({}); + throwIfAborted({ apple: false }); + throwIfAborted({ isAborted: false }); + throwIfAborted({ isAborted: false, other: 'key' }); + assert.throws(() => throwIfAborted({ isAborted: true }), /TransitionAborted/); + assert.throws(() => throwIfAborted({ isAborted: true, other: 'key' }), /TransitionAborted/); +}); diff --git a/packages/router_js/tests/transition_intent_test.ts b/packages/router_js/tests/transition_intent_test.ts new file mode 100644 index 00000000000..028c1e70001 --- /dev/null +++ b/packages/router_js/tests/transition_intent_test.ts @@ -0,0 +1,306 @@ +import NamedTransitionIntent from '../lib/transition-intent/named-transition-intent'; +import URLTransitionIntent from '../lib/transition-intent/url-transition-intent'; +import TransitionState from '../lib/transition-state'; +import { createHandler, TestRouter } from './test_helpers'; + +import type { default as Router, Route } from '../index'; +import type { Dict } from '../lib/core'; +import { + type default as InternalRouteInfo, + ResolvedRouteInfo, + UnresolvedRouteInfoByObject, + UnresolvedRouteInfoByParam, +} from '../lib/route-info'; +import { Promise } from 'rsvp'; + +let handlers: Dict, recognizer: any; + +let scenarios = [ + { + name: 'Sync Get Handler', + async: false, + getHandler: function (name: string) { + return handlers[name] || (handlers[name] = createHandler(name)); + }, + }, + { + name: 'Async Get Handler', + async: true, + getHandler: function (name: string) { + return Promise.resolve(handlers[name] || (handlers[name] = createHandler(name))); + }, + }, +]; + +scenarios.forEach(function (scenario) { + class TransitionRouter extends TestRouter { + getRoute(name: string) { + return scenario.getHandler(name); + } + } + + let router: Router; + + // Asserts that a handler from a handlerInfo equals an expected valued. + // Returns a promise during async scenarios to wait until the handler is ready. + function assertHandlerEquals( + assert: Assert, + handlerInfo: InternalRouteInfo, + expected: Route + ) { + if (!scenario.async) { + return assert.equal(handlerInfo.route, expected); + } else { + assert.equal(handlerInfo.route, undefined); + return handlerInfo.routePromise.then(function (handler) { + assert.equal(handler, expected); + }); + } + } + + // TODO: remove repetition, DRY in to test_helpers. + QUnit.module('TransitionIntent (' + scenario.name + ')', { + beforeEach: function () { + handlers = {}; + + handlers['foo'] = createHandler('foo'); + handlers['bar'] = createHandler('bar'); + handlers['articles'] = createHandler('articles'); + handlers['comments'] = createHandler('comments'); + + recognizer = { + handlersFor: function (name: string) { + if (name === 'comments') { + return [ + { + handler: 'articles', + names: ['article_id'], + }, + { + handler: 'comments', + names: ['comment_id'], + }, + ]; + } + return; + }, + hasRoute: function (name: string) { + return name === 'comments'; + }, + recognize: function (url: string) { + if (url === '/foo/bar') { + return [ + { + handler: 'foo', + isDynamic: false, + params: {}, + }, + { + handler: 'bar', + isDynamic: false, + params: {}, + }, + ]; + } else if (url === '/articles/123/comments/456') { + return [ + { + handler: 'articles', + isDynamic: true, + params: { article_id: '123' }, + }, + { + handler: 'comments', + isDynamic: true, + params: { comment_id: '456' }, + }, + ]; + } + + return; + }, + }; + + router = new TransitionRouter(); + router.recognizer = recognizer; + }, + }); + + QUnit.test('URLTransitionIntent can be applied to an empty state', function (assert) { + let state = new TransitionState(); + let intent = new URLTransitionIntent(router, '/foo/bar'); + let newState = intent.applyToState(state); + let handlerInfos = newState.routeInfos; + + assert.equal(handlerInfos.length, 2); + assert.notOk( + handlerInfos[0]!.isResolved, + 'generated state consists of unresolved handler info, 1' + ); + assert.notOk( + handlerInfos[1]!.isResolved, + 'generated state consists of unresolved handler info, 2' + ); + Promise.all([ + assertHandlerEquals(assert, handlerInfos[0]!, handlers['foo']!), + assertHandlerEquals(assert, handlerInfos[1]!, handlers['bar']!), + ]); + }); + + QUnit.test('URLTransitionIntent applied to single unresolved URL handlerInfo', function (assert) { + let state = new TransitionState(); + + let startingHandlerInfo = new UnresolvedRouteInfoByParam( + router, + 'foo', + [], + {}, + handlers['foo'] + ); + + // This single unresolved handler info will be preserved + // in the new array of handlerInfos. + // Reason: if it were resolved, we wouldn't want to replace it. + // So we only want to replace if it's actually known to be + // different. + state.routeInfos = [startingHandlerInfo]; + + let intent = new URLTransitionIntent(router, '/foo/bar'); + let newState = intent.applyToState(state); + let handlerInfos = newState.routeInfos; + + assert.equal(handlerInfos.length, 2); + assert.equal( + handlerInfos[0], + startingHandlerInfo, + "The starting foo handlerInfo wasn't overridden because the new one wasn't any different" + ); + assert.ok( + handlerInfos[1] instanceof UnresolvedRouteInfoByParam, + 'generated state consists of UnresolvedHandlerInfoByParam, 2' + ); + assertHandlerEquals(assert, handlerInfos[1]!, handlers['bar']!); + }); + + QUnit.test('URLTransitionIntent applied to an already-resolved handlerInfo', function (assert) { + let state = new TransitionState(); + + let startingHandlerInfo = new ResolvedRouteInfo(router, 'foo', [], {}, handlers['foo']!); + + state.routeInfos = [startingHandlerInfo]; + + let intent = new URLTransitionIntent(router, '/foo/bar'); + let newState = intent.applyToState(state); + let handlerInfos = newState.routeInfos; + + assert.equal(handlerInfos.length, 2); + assert.equal( + handlerInfos[0], + startingHandlerInfo, + "The starting foo resolved handlerInfo wasn't overridden because the new one wasn't any different" + ); + assert.ok( + handlerInfos[1] instanceof UnresolvedRouteInfoByParam, + 'generated state consists of UnresolvedHandlerInfoByParam, 2' + ); + assertHandlerEquals(assert, handlerInfos[1]!, handlers['bar']!); + }); + + QUnit.test( + 'URLTransitionIntent applied to an already-resolved handlerInfo (non-empty params)', + function (assert) { + let state = new TransitionState(); + let article = {}; + + let startingHandlerInfo = new ResolvedRouteInfo( + router, + 'articles', + [], + { article_id: 'some-other-id' }, + createHandler('articles'), + article + ); + + state.routeInfos = [startingHandlerInfo]; + + let intent = new URLTransitionIntent(router, '/articles/123/comments/456'); + let newState = intent.applyToState(state); + let handlerInfos = newState.routeInfos; + + assert.equal(handlerInfos.length, 2); + assert.notStrictEqual( + handlerInfos[0], + startingHandlerInfo, + 'The starting foo resolved handlerInfo was overridden because the new had different params' + ); + assert.ok( + handlerInfos[1] instanceof UnresolvedRouteInfoByParam, + 'generated state consists of UnresolvedHandlerInfoByParam, 2' + ); + + assertHandlerEquals(assert, handlerInfos[1]!, handlers['comments']!); + } + ); + + QUnit.test( + 'URLTransitionIntent applied to an already-resolved handlerInfo of different route', + function (assert) { + let state = new TransitionState(); + + let startingHandlerInfo = new ResolvedRouteInfo(router, 'alex', [], {}, handlers['foo']!); + + state.routeInfos = [startingHandlerInfo]; + + let intent = new URLTransitionIntent(router, '/foo/bar'); + let newState = intent.applyToState(state); + let handlerInfos = newState.routeInfos; + + assert.equal(handlerInfos.length, 2); + assert.notStrictEqual( + handlerInfos[0], + startingHandlerInfo, + 'The starting foo resolved handlerInfo gets overridden because the new one has a different name' + ); + assert.ok( + handlerInfos[1] instanceof UnresolvedRouteInfoByParam, + 'generated state consists of UnresolvedHandlerInfoByParam, 2' + ); + assertHandlerEquals(assert, handlerInfos[1]!, handlers['bar']!); + } + ); + + QUnit.test( + 'NamedTransitionIntent applied to an already-resolved handlerInfo (non-empty params)', + function (assert) { + let state = new TransitionState(); + + let article = {}; + let comment = {}; + + let startingHandlerInfo = new ResolvedRouteInfo( + router, + 'articles', + [], + { article_id: 'some-other-id' }, + createHandler('articles'), + article + ); + + state.routeInfos = [startingHandlerInfo]; + + let intent = new NamedTransitionIntent(router, 'comments', undefined, [article, comment]); + + let newState = intent.applyToState(state, false); + let handlerInfos = newState.routeInfos; + + assert.equal(handlerInfos.length, 2); + assert.equal(handlerInfos[0], startingHandlerInfo); + assert.equal(handlerInfos[0]!.context, article); + assert.ok( + handlerInfos[1] instanceof UnresolvedRouteInfoByObject, + 'generated state consists of UnresolvedHandlerInfoByObject, 2' + ); + assert.equal(handlerInfos[1]!.context, comment); + assertHandlerEquals(assert, handlerInfos[1]!, handlers['comments']!); + } + ); +}); diff --git a/packages/router_js/tests/transition_state_test.ts b/packages/router_js/tests/transition_state_test.ts new file mode 100644 index 00000000000..099d3e0f40a --- /dev/null +++ b/packages/router_js/tests/transition_state_test.ts @@ -0,0 +1,115 @@ +import type { Transition } from '../index'; +import type { Dict } from '../lib/core'; +import { + type Route, + UnresolvedRouteInfoByObject, + UnresolvedRouteInfoByParam, +} from '../lib/route-info'; +import TransitionState, { type TransitionError } from '../lib/transition-state'; +import { Promise, resolve } from 'rsvp'; +import { createHandler, createHandlerInfo, TestRouter } from './test_helpers'; + +QUnit.module('TransitionState'); + +QUnit.test('it starts off with default state', function (assert) { + let state = new TransitionState(); + assert.deepEqual(state.routeInfos, [], 'it has an array of handlerInfos'); +}); + +QUnit.test("#resolve delegates to handleInfo objects' resolve()", function (assert) { + assert.expect(3); + + let state = new TransitionState(); + + let counter = 0; + + let resolvedHandlerInfos: any[] = [{}, {}]; + + state.routeInfos = [ + createHandlerInfo('one', { + resolve: function () { + ++counter; + assert.equal(counter, 1); + return resolve(resolvedHandlerInfos[0]); + }, + }), + createHandlerInfo('two', { + resolve: function () { + ++counter; + assert.equal(counter, 2); + return resolve(resolvedHandlerInfos[1]); + }, + }), + ]; + + state.resolve({} as Transition).then(function (result: TransitionState) { + assert.deepEqual(result.routeInfos, resolvedHandlerInfos); + }); +}); + +QUnit.test('State resolution can be halted', async function (assert) { + assert.expect(1); + + let state = new TransitionState(); + + state.routeInfos = [ + createHandlerInfo('one', { + resolve: function () {}, + }), + createHandlerInfo('two', { + resolve: function () { + assert.ok(false, 'I should not be entered because we threw an error in shouldContinue'); + }, + }), + ]; + + let fakeTransition = {} as Transition; + fakeTransition.isAborted = true; + + await state.resolve(fakeTransition).catch(function (reason: TransitionError) { + assert.ok(reason.wasAborted, 'state resolution was correctly marked as aborted'); + }); +}); + +QUnit.test('Integration w/ HandlerInfos', function (assert) { + assert.expect(4); + + let state = new TransitionState(); + let router = new TestRouter(); + let fooModel = {}; + let barModel = {}; + let transition = {}; + + state.routeInfos = [ + new UnresolvedRouteInfoByParam( + router, + 'foo', + ['foo_id'], + { foo_id: '123' }, + createHandler('foo', { + model: function (params: Dict, payload: Dict) { + assert.equal(payload, transition); + assert.equal(params['foo_id'], '123', 'foo#model received expected params'); + return resolve(fooModel); + }, + }) + ), + new UnresolvedRouteInfoByObject(router, 'bar', ['bar_id'], resolve(barModel)), + ]; + + state + .resolve(transition as Transition) + .then(function (result: TransitionState) { + let models = []; + for (let i = 0; i < result.routeInfos.length; i++) { + models.push(result.routeInfos[i]!.context); + } + + assert.equal(models[0], fooModel); + assert.equal(models[1], barModel); + return Promise.resolve(new TransitionState()); + }) + .catch(function (error: Error) { + assert.ok(false, 'Caught error: ' + error); + }); +}); diff --git a/packages/router_js/tests/unrecognized-url-error_test.ts b/packages/router_js/tests/unrecognized-url-error_test.ts new file mode 100644 index 00000000000..5730e6b5108 --- /dev/null +++ b/packages/router_js/tests/unrecognized-url-error_test.ts @@ -0,0 +1,16 @@ +import UnrecognizedURLError from '../lib/unrecognized-url-error'; + +QUnit.module('unrecognized-url-error'); + +QUnit.test('correct inheritance', function (assert) { + let error; + + try { + throw new UnrecognizedURLError('Message'); + } catch (e) { + error = e; + } + + assert.ok(error instanceof UnrecognizedURLError); + assert.ok(error instanceof Error); +}); diff --git a/packages/router_js/tests/utils_test.ts b/packages/router_js/tests/utils_test.ts new file mode 100644 index 00000000000..06ba8270b7a --- /dev/null +++ b/packages/router_js/tests/utils_test.ts @@ -0,0 +1,32 @@ +import { getChangelist } from '../lib/utils'; + +QUnit.module('utils'); + +QUnit.test('getChangelist', function (assert) { + let result = getChangelist({}, { foo: '123' }); + assert.deepEqual(result, { + all: { foo: '123' }, + changed: { foo: '123' }, + removed: {}, + }); + + result = getChangelist({ foo: '123' }, { foo: '123' }); + assert.notOk(result); + + result = getChangelist({ foo: '123' }, {}); + assert.deepEqual(result, { all: {}, changed: {}, removed: { foo: '123' } }); + + result = getChangelist({ foo: '123', bar: '456' }, { foo: '123' }); + assert.deepEqual(result, { + all: { foo: '123' }, + changed: {}, + removed: { bar: '456' }, + }); + + result = getChangelist({ foo: '123', bar: '456' }, { foo: '456' }); + assert.deepEqual(result, { + all: { foo: '456' }, + changed: { foo: '456' }, + removed: { bar: '456' }, + }); +}); diff --git a/patches/@tracerbench__core@8.0.1.patch b/patches/@tracerbench__core@8.0.1.patch index fa9b0967701..1a551f68662 100644 --- a/patches/@tracerbench__core@8.0.1.patch +++ b/patches/@tracerbench__core@8.0.1.patch @@ -1,15 +1,60 @@ diff --git a/dist/create-trace-benchmark.js b/dist/create-trace-benchmark.js -index 5918e8f7665b3e796ef88283fc40c2b3286a564f..e1a8768964de8b3c16d38bfb6280d836b45aba0b 100644 +index 5918e8f7665b3e796ef88283fc40c2b3286a564f..b9927ba8f639c0a9ecc70144362da439468f1b3a 100644 --- a/dist/create-trace-benchmark.js +++ b/dist/create-trace-benchmark.js -@@ -45,9 +45,8 @@ function createTraceBenchmark(group, sampleTrace, options = {}) { +@@ -45,35 +45,27 @@ function createTraceBenchmark(group, sampleTrace, options = {}) { } exports.default = createTraceBenchmark; function getCategories(isTrial, options) { - const categories = ['-*', ...defaultCategories]; -+ const categories = [...defaultCategories]; - if (isTrial) { +- if (isTrial) { - categories.push(...captureAllDevtoolsTimelineCategories, ...captureCpuProfileCategories, captureCpuProfilesHiresCategory, captureFilmStripCategory, ...capturePaintProfileCategories); - if (options.additionalTrialCategories) { - categories.push(...options.additionalTrialCategories); - } +- if (options.additionalTrialCategories) { +- categories.push(...options.additionalTrialCategories); +- } ++ const categories = [...defaultCategories]; ++ // include the basic disabled by default devtools categories ++ if (options.captureDevtoolsTimeline) { ++ categories.push(...captureDevtoolsTimelineCategories); + } +- else { +- // include the basic disabled by default devtools categories +- if (options.captureDevtoolsTimeline) { +- categories.push(...captureDevtoolsTimelineCategories); +- } +- if (options.captureV8RuntimeStats) { +- // this breaks devtools display of CPU profile in dev tools +- categories.push(...captureV8RuntimeStatsCategories); +- } +- if (options.captureCpuProfile) { +- // includes runtime samples +- categories.push(...captureCpuProfileCategories); +- } +- if (options.captureFilmStrip) { +- categories.push(captureFilmStripCategory); +- } +- if (options.capturePaintProfile) { +- categories.push(...capturePaintProfileCategories); +- } +- if (options.additionalCategories) { +- categories.push(...options.additionalCategories); +- } ++ if (options.captureV8RuntimeStats) { ++ // this breaks devtools display of CPU profile in dev tools ++ categories.push(...captureV8RuntimeStatsCategories); ++ } ++ if (options.captureCpuProfile) { ++ // includes runtime samples ++ categories.push(...captureCpuProfileCategories); ++ } ++ if (options.captureFilmStrip) { ++ categories.push(captureFilmStripCategory); ++ } ++ if (options.capturePaintProfile) { ++ categories.push(...capturePaintProfileCategories); ++ } ++ if (options.additionalCategories) { ++ categories.push(...options.additionalCategories); + } + return categories; + } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a3b1752250d..25f4eb99114 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,7 +11,7 @@ overrides: patchedDependencies: '@tracerbench/core@8.0.1': - hash: 94ed69d4e124c0c94f1c1e3332668ae5d3265509b12cc97dd634feee8ed7e846 + hash: ee5cfa4adb0f65df07ef51d9be56c31150b4330d7ac7e1fbbb0a87329938af0a path: patches/@tracerbench__core@8.0.1.patch importers: @@ -21,9 +21,6 @@ importers: '@babel/core': specifier: ^7.24.4 version: 7.29.0 - '@ember/edition-utils': - specifier: ^1.2.0 - version: 1.2.0 '@embroider/addon-shim': specifier: ^1.10.2 version: 1.10.2 @@ -51,9 +48,6 @@ importers: ember-cli-get-component-path-option: specifier: ^1.0.0 version: 1.0.0 - ember-cli-is-package-missing: - specifier: ^1.0.0 - version: 1.0.0 ember-cli-normalize-entity-name: specifier: ^1.0.0 version: 1.0.0 @@ -66,9 +60,6 @@ importers: ember-cli-typescript-blueprint-polyfill: specifier: ^0.1.0 version: 0.1.0 - ember-cli-version-checker: - specifier: ^5.1.2 - version: 5.1.2 ember-router-generator: specifier: ^2.0.0 version: 2.0.0 @@ -78,9 +69,6 @@ importers: route-recognizer: specifier: ^0.3.4 version: 0.3.4 - router_js: - specifier: ^8.0.5 - version: 8.0.6(route-recognizer@0.3.4)(rsvp@4.8.5) semver: specifier: ^7.5.2 version: 7.7.4 @@ -93,7 +81,7 @@ importers: devDependencies: '@aws-sdk/client-s3': specifier: ^3.731.0 - version: 3.986.0 + version: 3.1003.0 '@babel/plugin-transform-typescript': specifier: ^7.22.9 version: 7.28.6(@babel/core@7.29.0) @@ -105,16 +93,16 @@ importers: version: 7.29.0 '@embroider/macros': specifier: ^1.19.7 - version: 1.19.7(@babel/core@7.29.0) + version: 1.20.1(@babel/core@7.29.0) '@embroider/shared-internals': specifier: ^2.9.2 version: 2.9.2(supports-color@8.1.1) '@embroider/vite': specifier: ^1.5.2 - version: 1.5.2(@embroider/core@4.4.3)(rollup@4.59.0)(vite@5.4.21(@types/node@22.19.11)(terser@5.46.0)) + version: 1.6.1(@embroider/core@4.4.5)(vite@5.4.21(@types/node@22.19.15)(terser@5.46.0)) '@eslint/js': specifier: ^9.21.0 - version: 9.39.2 + version: 9.39.3 '@glimmer/component': specifier: workspace:* version: link:packages/@glimmer/component @@ -126,10 +114,10 @@ importers: version: 1.4.0 '@swc-node/register': specifier: ^1.6.8 - version: 1.11.1(@swc/core@1.15.11)(@swc/types@0.1.25)(typescript@5.9.3) + version: 1.11.1(@swc/core@1.15.18)(@swc/types@0.1.25)(typescript@5.9.3) '@swc/core': specifier: ^1.3.100 - version: 1.15.11 + version: 1.15.18 '@tsconfig/ember': specifier: 3.0.8 version: 3.0.8 @@ -151,9 +139,6 @@ importers: babel-plugin-ember-template-compilation: specifier: 3.0.0-alpha.4 version: 3.0.0-alpha.4 - brotli: - specifier: ^1.3.3 - version: 1.3.3 dag-map: specifier: ^2.0.2 version: 2.0.2 @@ -162,7 +147,7 @@ importers: version: 2.0.0(@babel/core@7.29.0) ember-cli: specifier: ^6.3.0 - version: 6.5.0(@types/node@22.19.11)(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.7) + version: 6.11.0(@types/node@22.19.15)(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.8) ember-cli-blueprint-test-helpers: specifier: ^0.19.2 version: 0.19.2 @@ -171,13 +156,13 @@ importers: version: 2.1.0 ember-cli-dependency-checker: specifier: ^3.3.1 - version: 3.3.3(ember-cli@6.5.0(@types/node@22.19.11)(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.7)) + version: 3.3.3(ember-cli@6.11.0(@types/node@22.19.15)(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.8)) ember-cli-yuidoc: specifier: ^0.9.1 version: 0.9.1 eslint: specifier: ^9.21.0 - version: 9.39.2 + version: 9.39.3 eslint-import-resolver-node: specifier: ^0.3.7 version: 0.3.9 @@ -186,28 +171,25 @@ importers: version: 0.1.3 eslint-plugin-ember-internal: specifier: ^3.0.0 - version: 3.0.0(eslint@9.39.2) + version: 3.0.0(eslint@9.39.3) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(eslint@9.39.2) + version: 2.32.0(eslint@9.39.3) eslint-plugin-n: specifier: ^17.16.2 - version: 17.23.2(eslint@9.39.2)(typescript@5.9.3) + version: 17.24.0(eslint@9.39.3)(typescript@5.9.3) eslint-plugin-qunit: specifier: ^8.1.2 - version: 8.2.6(eslint@9.39.2) + version: 8.2.6(eslint@9.39.3) execa: specifier: ^5.1.1 version: 5.1.1 expect-type: specifier: ^0.15.0 version: 0.15.0 - filesize: - specifier: ^10.1.6 - version: 10.1.6 fs-extra: specifier: ^11.1.1 - version: 11.3.3 + version: 11.3.4 git-repo-info: specifier: ^2.1.1 version: 2.1.1 @@ -226,12 +208,9 @@ importers: mocha: specifier: ^10.2.0 version: 10.8.2 - node-gzip: - specifier: ^1.1.2 - version: 1.1.2 npm-run-all2: - specifier: ^6.0.6 - version: 6.2.6 + specifier: ^8.0.0 + version: 8.0.4 prettier: specifier: ^3.5.3 version: 3.8.1 @@ -247,33 +226,33 @@ importers: rollup: specifier: ^4.2.0 version: 4.59.0 + router_js: + specifier: workspace:* + version: link:packages/router_js rsvp: specifier: ^4.8.5 version: 4.8.5 - table: - specifier: ^6.9.0 - version: 6.9.0 terser: specifier: ^5.42.0 version: 5.46.0 testem: specifier: ^3.10.1 - version: 3.17.0(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.7) + version: 3.17.0(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.8) testem-failure-only-reporter: specifier: ^1.0.0 - version: 1.0.0(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.7) + version: 1.0.0(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.8) tracerbench: specifier: ^8.0.1 - version: 8.0.1(@swc/core@1.15.11)(@types/node@22.19.11)(typescript@5.9.3) + version: 8.0.1(@swc/core@1.15.18)(@types/node@22.19.15)(typescript@5.9.3) typescript: specifier: ^5.7.3 version: 5.9.3 typescript-eslint: specifier: ^8.26.0 - version: 8.55.0(eslint@9.39.2)(typescript@5.9.3) + version: 8.56.1(eslint@9.39.3)(typescript@5.9.3) vite: specifier: ^5.4.12 - version: 5.4.21(@types/node@22.19.11)(terser@5.46.0) + version: 5.4.21(@types/node@22.19.15)(terser@5.46.0) packages/@ember/-internals: dependencies: @@ -416,8 +395,8 @@ importers: specifier: workspace:* version: link:../../internal-test-helpers router_js: - specifier: ^8.0.5 - version: 8.0.6(route-recognizer@0.3.4)(rsvp@4.8.5) + specifier: workspace:* + version: link:../../router_js rsvp: specifier: ^4.8.5 version: 4.8.5 @@ -498,8 +477,8 @@ importers: specifier: workspace:* version: link:../../internal-test-helpers router_js: - specifier: ^8.0.5 - version: 8.0.6(route-recognizer@0.3.4)(rsvp@4.8.5) + specifier: workspace:* + version: link:../../router_js packages/@ember/array: dependencies: @@ -763,8 +742,8 @@ importers: specifier: workspace:* version: link:../../internal-test-helpers router_js: - specifier: ^8.0.5 - version: 8.0.6(route-recognizer@0.3.4)(rsvp@4.8.5) + specifier: workspace:* + version: link:../../router_js packages/@ember/enumerable: dependencies: @@ -1046,8 +1025,8 @@ importers: specifier: workspace:* version: link:../../internal-test-helpers router_js: - specifier: ^8.0.5 - version: 8.0.6(route-recognizer@0.3.4)(rsvp@4.8.5) + specifier: workspace:* + version: link:../../router_js packages/@ember/runloop: dependencies: @@ -1494,7 +1473,7 @@ importers: version: link:../../@glimmer/debug-util eslint: specifier: ^9.20.1 - version: 9.39.2 + version: 9.39.3 packages/@glimmer/compiler: dependencies: @@ -1525,13 +1504,13 @@ importers: version: link:../local-debug-flags '@types/node': specifier: ^22.13.4 - version: 22.19.11 + version: 22.19.15 eslint: specifier: ^9.20.1 - version: 9.39.2 + version: 9.39.3 publint: specifier: ^0.3.2 - version: 0.3.17 + version: 0.3.18 rollup: specifier: ^4.2.0 version: 4.59.0 @@ -1600,10 +1579,10 @@ importers: version: link:../local-debug-flags eslint: specifier: ^9.20.1 - version: 9.39.2 + version: 9.39.3 publint: specifier: ^0.3.2 - version: 0.3.17 + version: 0.3.18 typescript: specifier: ^5.7.3 version: 5.9.3 @@ -1650,7 +1629,7 @@ importers: version: link:../local-debug-flags eslint: specifier: ^9.20.1 - version: 9.39.2 + version: 9.39.3 typescript: specifier: ^5.7.3 version: 5.9.3 @@ -1669,7 +1648,7 @@ importers: version: link:../local-debug-flags eslint: specifier: ^9.20.1 - version: 9.39.2 + version: 9.39.3 typescript: specifier: ^5.7.3 version: 5.9.3 @@ -1713,10 +1692,10 @@ importers: version: link:../env eslint: specifier: ^9.20.1 - version: 9.39.2 + version: 9.39.3 publint: specifier: ^0.3.2 - version: 0.3.17 + version: 0.3.18 rollup: specifier: ^4.2.0 version: 4.59.0 @@ -1754,10 +1733,10 @@ importers: version: link:../env eslint: specifier: ^9.20.1 - version: 9.39.2 + version: 9.39.3 publint: specifier: ^0.3.2 - version: 0.3.17 + version: 0.3.18 rollup: specifier: ^4.2.0 version: 4.59.0 @@ -1774,10 +1753,10 @@ importers: version: link:../env eslint: specifier: ^9.20.1 - version: 9.39.2 + version: 9.39.3 publint: specifier: ^0.3.2 - version: 0.3.17 + version: 0.3.18 rollup: specifier: ^4.2.0 version: 4.59.0 @@ -1796,10 +1775,10 @@ importers: devDependencies: eslint: specifier: ^9.20.1 - version: 9.39.2 + version: 9.39.3 publint: specifier: ^0.3.2 - version: 0.3.17 + version: 0.3.18 typescript: specifier: ^5.7.3 version: 5.9.3 @@ -1810,7 +1789,7 @@ importers: devDependencies: eslint: specifier: ^9.20.1 - version: 9.39.2 + version: 9.39.3 packages/@glimmer/manager: dependencies: @@ -1847,10 +1826,10 @@ importers: version: link:../env eslint: specifier: ^9.20.1 - version: 9.39.2 + version: 9.39.3 publint: specifier: ^0.3.2 - version: 0.3.17 + version: 0.3.18 rollup: specifier: ^4.2.0 version: 4.59.0 @@ -1899,10 +1878,10 @@ importers: version: 2.19.13 eslint: specifier: ^9.20.1 - version: 9.39.2 + version: 9.39.3 publint: specifier: ^0.3.2 - version: 0.3.17 + version: 0.3.18 rollup: specifier: ^4.2.0 version: 4.59.0 @@ -1948,10 +1927,10 @@ importers: version: link:../local-debug-flags eslint: specifier: ^9.20.1 - version: 9.39.2 + version: 9.39.3 publint: specifier: ^0.3.2 - version: 0.3.17 + version: 0.3.18 rollup: specifier: ^4.2.0 version: 4.59.0 @@ -1966,10 +1945,10 @@ importers: devDependencies: eslint: specifier: ^9.20.1 - version: 9.39.2 + version: 9.39.3 publint: specifier: ^0.3.2 - version: 0.3.17 + version: 0.3.18 rollup: specifier: ^4.2.0 version: 4.59.0 @@ -2015,10 +1994,10 @@ importers: version: link:../local-debug-flags eslint: specifier: ^9.20.1 - version: 9.39.2 + version: 9.39.3 publint: specifier: ^0.3.2 - version: 0.3.17 + version: 0.3.18 rollup: specifier: ^4.2.0 version: 4.59.0 @@ -2058,10 +2037,10 @@ importers: version: link:../tracking eslint: specifier: ^9.20.1 - version: 9.39.2 + version: 9.39.3 publint: specifier: ^0.3.2 - version: 0.3.17 + version: 0.3.18 rollup: specifier: ^4.2.0 version: 4.59.0 @@ -2138,10 +2117,10 @@ importers: version: link:../local-debug-flags eslint: specifier: ^9.20.1 - version: 9.39.2 + version: 9.39.3 publint: specifier: ^0.3.2 - version: 0.3.17 + version: 0.3.18 rollup: specifier: ^4.2.0 version: 4.59.0 @@ -2178,10 +2157,10 @@ importers: version: link:../local-debug-flags eslint: specifier: ^9.20.1 - version: 9.39.2 + version: 9.39.3 publint: specifier: ^0.3.2 - version: 0.3.17 + version: 0.3.18 rollup: specifier: ^4.2.0 version: 4.59.0 @@ -2234,10 +2213,10 @@ importers: version: 2.19.13 eslint: specifier: ^9.20.1 - version: 9.39.2 + version: 9.39.3 publint: specifier: ^0.3.2 - version: 0.3.17 + version: 0.3.18 rollup: specifier: ^4.2.0 version: 4.59.0 @@ -2268,13 +2247,13 @@ importers: version: link:../env eslint: specifier: ^9.20.1 - version: 9.39.2 + version: 9.39.3 expect-type: specifier: ^1.1.0 version: 1.3.0 publint: specifier: ^0.3.2 - version: 0.3.17 + version: 0.3.18 rollup: specifier: ^4.2.0 version: 4.59.0 @@ -2305,10 +2284,10 @@ importers: devDependencies: eslint: specifier: ^9.20.1 - version: 9.39.2 + version: 9.39.3 publint: specifier: ^0.3.2 - version: 0.3.17 + version: 0.3.18 rollup: specifier: ^4.2.0 version: 4.59.0 @@ -2324,10 +2303,10 @@ importers: devDependencies: eslint: specifier: ^9.20.1 - version: 9.39.2 + version: 9.39.3 publint: specifier: ^0.3.2 - version: 0.3.17 + version: 0.3.18 rollup: specifier: ^4.2.0 version: 4.59.0 @@ -2346,9 +2325,9 @@ importers: mocha: specifier: ^10.7.3 version: 10.8.2 - npm-run-all: - specifier: ^4.1.5 - version: 4.1.5 + npm-run-all2: + specifier: ^5.0.0 + version: 5.0.2 packages/@types/js-reporters: {} @@ -2472,8 +2451,8 @@ importers: specifier: workspace:* version: link:../internal-test-helpers router_js: - specifier: ^8.0.5 - version: 8.0.6(route-recognizer@0.3.4)(rsvp@4.8.5) + specifier: workspace:* + version: link:../router_js rsvp: specifier: ^4.8.5 version: 4.8.5 @@ -2631,8 +2610,8 @@ importers: specifier: workspace:* version: link:../internal-test-helpers router_js: - specifier: ^8.0.5 - version: 8.0.6(route-recognizer@0.3.4)(rsvp@4.8.5) + specifier: workspace:* + version: link:../router_js packages/internal-test-helpers: dependencies: @@ -2733,8 +2712,8 @@ importers: specifier: workspace:* version: link:../ember-template-compiler router_js: - specifier: ^8.0.5 - version: 8.0.6(route-recognizer@0.3.4)(rsvp@4.8.5) + specifier: workspace:* + version: link:../router_js rsvp: specifier: ^4.8.5 version: 4.8.5 @@ -2744,26 +2723,57 @@ importers: packages/loader: {} + packages/router_js: + dependencies: + '@glimmer/env': + specifier: workspace:* + version: link:../@glimmer/env + devDependencies: + '@types/qunit': + specifier: ^2.9.6 + version: 2.19.13 + '@types/rsvp': + specifier: ^4.0.4 + version: 4.0.9 + backburner.js: + specifier: ^2.6.0 + version: 2.8.0 + loader.js: + specifier: ^4.7.0 + version: 4.7.0 + qunit: + specifier: ^2.11.3 + version: 2.25.0 + route-recognizer: + specifier: ^0.3.4 + version: 0.3.4 + rsvp: + specifier: ^4.8.5 + version: 4.8.5 + smoke-tests/app-template: devDependencies: '@babel/core': - specifier: ^7.24.4 + specifier: ^7.29.0 version: 7.29.0 + '@babel/eslint-parser': + specifier: ^7.28.6 + version: 7.28.6(@babel/core@7.29.0)(eslint@9.39.3) + '@babel/plugin-proposal-decorators': + specifier: ^7.29.0 + version: 7.29.0(@babel/core@7.29.0) '@ember/optional-features': specifier: ^2.3.0 version: 2.3.0 - '@ember/string': - specifier: ^3.0.1 - version: 3.1.1 '@ember/test-helpers': - specifier: ^3.3.0 - version: 3.3.1(@babel/core@7.29.0)(ember-source@)(webpack@5.105.1) - '@ember/test-waiters': - specifier: ^3.1.0 - version: 3.1.0 - '@embroider/test-setup': - specifier: ^4.0.0 - version: 4.0.0(@embroider/compat@3.9.3(@embroider/core@3.5.9))(@embroider/core@3.5.9)(@embroider/webpack@4.1.2(@embroider/core@3.5.9)(webpack@5.105.1)) + specifier: ^5.4.1 + version: 5.4.1(@babel/core@7.29.0) + '@embroider/macros': + specifier: ^1.19.7 + version: 1.20.1(@babel/core@7.29.0) + '@eslint/js': + specifier: ^9.39.2 + version: 9.39.3 '@glimmer/component': specifier: workspace:^ version: link:../../packages/@glimmer/component @@ -2773,18 +2783,30 @@ importers: broccoli-asset-rev: specifier: ^3.0.0 version: 3.0.0 + concurrently: + specifier: ^9.2.1 + version: 9.2.1 ember-auto-import: - specifier: ^2.12.0 - version: 2.12.1(webpack@5.105.1) + specifier: ^2.13.0 + version: 2.13.0(webpack@5.105.4) ember-cli: - specifier: ~5.7.0 - version: 5.7.0(@types/node@22.19.11) + specifier: ~6.11.0 + version: 6.11.0(@types/node@22.19.15)(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.8) + ember-cli-app-version: + specifier: ^7.0.0 + version: 7.0.0(ember-source@) ember-cli-babel: - specifier: ^8.2.0 + specifier: ^8.3.1 version: 8.3.1(@babel/core@7.29.0) + ember-cli-clean-css: + specifier: ^3.0.0 + version: 3.0.0 ember-cli-dependency-checker: - specifier: ^3.3.1 - version: 3.3.3(ember-cli@5.7.0(@types/node@22.19.11)) + specifier: ^3.3.3 + version: 3.3.3(ember-cli@6.11.0(@types/node@22.19.15)(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.8)) + ember-cli-deprecation-workflow: + specifier: ^3.4.0 + version: 3.4.0(ember-source@) ember-cli-htmlbars: specifier: ^7.0.0 version: 7.0.0(@babel/core@7.29.0)(ember-source@) @@ -2797,72 +2819,75 @@ importers: ember-cli-terser: specifier: ^4.0.2 version: 4.0.2 - ember-data: - specifier: ~5.8.1 - version: 5.8.1(@babel/core@7.29.0)(@ember/test-helpers@3.3.1(@babel/core@7.29.0)(ember-source@)(webpack@5.105.1))(@ember/test-waiters@3.1.0)(qunit@2.25.0) ember-load-initializers: - specifier: ^2.1.2 - version: 2.1.2(@babel/core@7.29.0) + specifier: ^3.0.1 + version: 3.0.1(ember-source@) + ember-modifier: + specifier: ^4.3.0 + version: 4.3.0(@babel/core@7.29.0) ember-page-title: - specifier: ^8.2.3 - version: 8.2.4(ember-source@) + specifier: ^9.0.3 + version: 9.0.3 ember-qunit: - specifier: ^8.0.2 - version: 8.1.1(@babel/core@7.29.0)(@ember/test-helpers@3.3.1(@babel/core@7.29.0)(ember-source@)(webpack@5.105.1))(ember-source@)(qunit@2.25.0) + specifier: ^9.0.4 + version: 9.0.4(@babel/core@7.29.0)(@ember/test-helpers@5.4.1(@babel/core@7.29.0))(qunit@2.25.0) ember-resolver: - specifier: ^11.0.1 - version: 11.0.1(ember-source@) + specifier: ^13.1.1 + version: 13.2.0 ember-source: specifier: workspace:* version: link:../.. ember-template-imports: - specifier: ^4.1.2 + specifier: ^4.4.0 version: 4.4.0 ember-template-lint: - specifier: ^6.0.0 + specifier: ^6.1.0 version: 6.1.0 - ember-welcome-page: - specifier: ^7.0.2 - version: 7.0.2 eslint: - specifier: ^8.0.0 - version: 8.57.1 + specifier: ^9.39.2 + version: 9.39.3 eslint-config-prettier: - specifier: ^9.1.0 - version: 9.1.2(eslint@8.57.1) + specifier: ^9.1.2 + version: 9.1.2(eslint@9.39.3) eslint-plugin-ember: - specifier: ^12.0.2 - version: 12.7.5(@babel/core@7.29.0)(@typescript-eslint/parser@8.55.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3) - eslint-plugin-node: - specifier: ^11.1.0 - version: 11.1.0(eslint@8.57.1) - eslint-plugin-prettier: - specifier: ^5.1.3 - version: 5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@9.1.2(eslint@8.57.1))(eslint@8.57.1)(prettier@3.8.1) + specifier: ^12.7.5 + version: 12.7.5(@babel/core@7.29.0)(@typescript-eslint/parser@8.56.1(eslint@9.39.3)(typescript@5.9.3))(eslint@9.39.3)(typescript@5.9.3) + eslint-plugin-n: + specifier: ^17.24.0 + version: 17.24.0(eslint@9.39.3)(typescript@5.9.3) eslint-plugin-qunit: - specifier: ^8.1.1 - version: 8.2.6(eslint@8.57.1) + specifier: ^8.2.6 + version: 8.2.6(eslint@9.39.3) + globals: + specifier: ^15.15.0 + version: 15.15.0 loader.js: specifier: ^4.7.0 version: 4.7.0 - npm-run-all: - specifier: ^4.1.5 - version: 4.1.5 prettier: - specifier: ^3.2.5 + specifier: ^3.8.1 version: 3.8.1 + prettier-plugin-ember-template-tag: + specifier: ^2.1.3 + version: 2.1.3(prettier@3.8.1) qunit: - specifier: ^2.19.2 + specifier: ^2.25.0 version: 2.25.0 qunit-dom: - specifier: ^3.1.1 + specifier: ^3.5.0 version: 3.5.0 + stylelint: + specifier: ^16.26.1 + version: 16.26.1(typescript@5.9.3) + stylelint-config-standard: + specifier: ^36.0.1 + version: 36.0.1(stylelint@16.26.1(typescript@5.9.3)) tracked-built-ins: - specifier: ^4.1.0 - version: 4.1.0(@babel/core@7.29.0)(ember-source@) + specifier: ^4.1.2 + version: 4.1.2(@babel/core@7.29.0) webpack: - specifier: ^5.74.0 - version: 5.105.1 + specifier: ^5.105.2 + version: 5.105.4 smoke-tests/benchmark-app: devDependencies: @@ -2877,16 +2902,16 @@ importers: version: 7.28.6 '@embroider/core': specifier: ^4.4.3 - version: 4.4.3 + version: 4.4.5 '@embroider/macros': specifier: ^1.19.7 - version: 1.19.7(@babel/core@7.29.0) + version: 1.20.1(@babel/core@7.29.0) '@embroider/router': specifier: ^3.0.6 - version: 3.0.6(@babel/core@7.29.0)(@embroider/core@4.4.3) + version: 3.0.6(@babel/core@7.29.0)(@embroider/core@4.4.5) '@embroider/vite': specifier: ^1.5.2 - version: 1.5.2(@embroider/core@4.4.3)(rollup@4.59.0)(vite@7.3.1(@types/node@22.19.11)(terser@5.46.0)) + version: 1.6.1(@embroider/core@4.4.5)(vite@7.3.1(@types/node@22.19.15)(terser@5.46.0)) '@glimmer/component': specifier: workspace:* version: link:../../packages/@glimmer/component @@ -2907,22 +2932,16 @@ importers: version: 0.1.1(@babel/core@7.29.0) vite: specifier: ^7.3.0 - version: 7.3.1(@types/node@22.19.11)(terser@5.46.0) + version: 7.3.1(@types/node@22.19.15)(terser@5.46.0) smoke-tests/node-template: dependencies: - git-repo-info: - specifier: ^2.1.1 - version: 2.1.1 html-differ: specifier: ^1.4.0 version: 1.4.0 qunit: specifier: ^2.20.1 version: 2.25.0 - semver: - specifier: ^7.6.0 - version: 7.7.4 simple-dom: specifier: ^1.4.0 version: 1.4.0 @@ -2937,19 +2956,19 @@ importers: version: 3.5.9 '@embroider/webpack': specifier: ^4.1.2 - version: 4.1.2(@embroider/core@3.5.9)(webpack@5.105.1(@swc/core@1.15.11)) + version: 4.1.2(@embroider/core@3.5.9)(webpack@5.105.4(@swc/core@1.15.18)) '@swc-node/register': specifier: ^1.6.8 - version: 1.11.1(@swc/core@1.15.11)(@swc/types@0.1.25)(typescript@5.1.6) + version: 1.11.1(@swc/core@1.15.18)(@swc/types@0.1.25)(typescript@5.1.6) '@swc/core': specifier: ^1.4.17 - version: 1.15.11 + version: 1.15.18 '@swc/types': specifier: ^0.1.6 version: 0.1.25 '@types/node': specifier: ^20.12.7 - version: 20.19.33 + version: 20.19.37 ember-cli-htmlbars-6: specifier: npm:ember-cli-htmlbars@^6.0.0 version: ember-cli-htmlbars@6.3.0 @@ -2964,7 +2983,7 @@ importers: version: 5.1.6 webpack: specifier: ^5.91.0 - version: 5.105.1(@swc/core@1.15.11) + version: 5.105.4(@swc/core@1.15.18) smoke-tests/v2-app-template: devDependencies: @@ -2973,7 +2992,7 @@ importers: version: 7.29.0 '@babel/eslint-parser': specifier: ^7.28.6 - version: 7.28.6(@babel/core@7.29.0)(eslint@9.39.2) + version: 7.28.6(@babel/core@7.29.0)(eslint@9.39.3) '@babel/plugin-transform-runtime': specifier: ^7.29.0 version: 7.29.0(@babel/core@7.29.0) @@ -2994,28 +3013,28 @@ importers: version: 4.1.1(@babel/core@7.29.0) '@embroider/compat': specifier: ^4.1.13 - version: 4.1.13(@embroider/core@4.4.3) + version: 4.1.15(@embroider/core@4.4.5) '@embroider/config-meta-loader': specifier: ^1.0.0 version: 1.0.0 '@embroider/core': specifier: ^4.4.3 - version: 4.4.3 + version: 4.4.5 '@embroider/legacy-inspector-support': specifier: ^0.1.3 version: 0.1.3 '@embroider/macros': specifier: ^1.19.7 - version: 1.19.7(@babel/core@7.29.0) + version: 1.20.1(@babel/core@7.29.0) '@embroider/router': specifier: ^3.0.6 - version: 3.0.6(@babel/core@7.29.0)(@embroider/core@4.4.3) + version: 3.0.6(@babel/core@7.29.0)(@embroider/core@4.4.5) '@embroider/vite': specifier: ^1.5.2 - version: 1.5.2(@embroider/core@4.4.3)(rollup@4.59.0)(vite@7.3.1(@types/node@22.19.11)(terser@5.46.0)) + version: 1.6.1(@embroider/core@4.4.5)(vite@7.3.1(@types/node@22.19.15)(terser@5.46.0)) '@eslint/js': specifier: ^9.39.2 - version: 9.39.2 + version: 9.39.3 '@glimmer/component': specifier: workspace:^ version: link:../../packages/@glimmer/component @@ -3032,14 +3051,14 @@ importers: specifier: ^2.3.1 version: 2.3.1(@babel/core@7.29.0) ember-cli: - specifier: ~6.10.2 - version: 6.10.2(@types/node@22.19.11)(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.7) + specifier: ~6.11.0 + version: 6.11.0(@types/node@22.19.15)(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.8) ember-cli-babel: specifier: ^8.3.1 version: 8.3.1(@babel/core@7.29.0) ember-cli-deprecation-workflow: - specifier: ^3.4.0 - version: 3.4.0(ember-source@) + specifier: ^4.0.0 + version: 4.0.1(@babel/core@7.29.0) ember-load-initializers: specifier: ^3.0.1 version: 3.0.1(ember-source@) @@ -3054,7 +3073,7 @@ importers: version: 9.0.4(@babel/core@7.29.0)(@ember/test-helpers@5.4.1(@babel/core@7.29.0))(qunit@2.25.0) ember-resolver: specifier: ^13.1.1 - version: 13.1.1 + version: 13.2.0 ember-source: specifier: workspace:* version: link:../.. @@ -3063,19 +3082,19 @@ importers: version: 7.9.3 eslint: specifier: ^9.39.2 - version: 9.39.2 + version: 9.39.3 eslint-config-prettier: specifier: ^10.1.8 - version: 10.1.8(eslint@9.39.2) + version: 10.1.8(eslint@9.39.3) eslint-plugin-ember: specifier: ^12.7.5 - version: 12.7.5(@babel/core@7.29.0)(@typescript-eslint/parser@8.55.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) + version: 12.7.5(@babel/core@7.29.0)(@typescript-eslint/parser@8.56.1(eslint@9.39.3)(typescript@5.9.3))(eslint@9.39.3)(typescript@5.9.3) eslint-plugin-n: specifier: ^17.24.0 - version: 17.24.0(eslint@9.39.2)(typescript@5.9.3) + version: 17.24.0(eslint@9.39.3)(typescript@5.9.3) eslint-plugin-qunit: specifier: ^8.2.6 - version: 8.2.6(eslint@9.39.2) + version: 8.2.6(eslint@9.39.3) globals: specifier: ^16.5.0 version: 16.5.0 @@ -3099,13 +3118,13 @@ importers: version: 38.0.0(stylelint@16.26.1(typescript@5.9.3)) testem: specifier: ^3.17.0 - version: 3.17.0(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.7) + version: 3.17.0(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.8) tracked-built-ins: specifier: ^4.1.0 version: 4.1.0(@babel/core@7.29.0)(ember-source@) vite: specifier: ^7.3.1 - version: 7.3.1(@types/node@22.19.11)(terser@5.46.0) + version: 7.3.1(@types/node@22.19.15)(terser@5.46.0) packages: @@ -3135,135 +3154,127 @@ packages: '@aws-crypto/util@5.2.0': resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} - '@aws-sdk/client-s3@3.986.0': - resolution: {integrity: sha512-IcDJ8shVVvbxgMe8+dLWcv6uhSwmX65PHTVGX81BhWAElPnp3CL8w/5uzOPRo4n4/bqIk9eskGVEIicw2o+SrA==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/client-sso@3.985.0': - resolution: {integrity: sha512-81J8iE8MuXhdbMfIz4sWFj64Pe41bFi/uqqmqOC5SlGv+kwoyLsyKS/rH2tW2t5buih4vTUxskRjxlqikTD4oQ==} + '@aws-sdk/client-s3@3.1003.0': + resolution: {integrity: sha512-on8GvIWeH1pD0l53NuKbPO84bEC1mk/9zskgU+dVKcVoGxOZI94fVddCJb+IwIUN6rfBHCfXPCVbgVyzsHTAVg==} engines: {node: '>=20.0.0'} - '@aws-sdk/core@3.973.7': - resolution: {integrity: sha512-wNZZQQNlJ+hzD49cKdo+PY6rsTDElO8yDImnrI69p2PLBa7QomeUKAJWYp9xnaR38nlHqWhMHZuYLCQ3oSX+xg==} + '@aws-sdk/core@3.973.18': + resolution: {integrity: sha512-GUIlegfcK2LO1J2Y98sCJy63rQSiLiDOgVw7HiHPRqfI2vb3XozTVqemwO0VSGXp54ngCnAQz0Lf0YPCBINNxA==} engines: {node: '>=20.0.0'} - '@aws-sdk/crc64-nvme@3.972.0': - resolution: {integrity: sha512-ThlLhTqX68jvoIVv+pryOdb5coP1cX1/MaTbB9xkGDCbWbsqQcLqzPxuSoW1DCnAAIacmXCWpzUNOB9pv+xXQw==} + '@aws-sdk/crc64-nvme@3.972.4': + resolution: {integrity: sha512-HKZIZLbRyvzo/bXZU7Zmk6XqU+1C9DjI56xd02vwuDIxedxBEqP17t9ExhbP9QFeNq/a3l9GOcyirFXxmbDhmw==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-env@3.972.5': - resolution: {integrity: sha512-LxJ9PEO4gKPXzkufvIESUysykPIdrV7+Ocb9yAhbhJLE4TiAYqbCVUE+VuKP1leGR1bBfjWjYgSV5MxprlX3mQ==} + '@aws-sdk/credential-provider-env@3.972.16': + resolution: {integrity: sha512-HrdtnadvTGAQUr18sPzGlE5El3ICphnH6SU7UQOMOWFgRKbTRNN8msTxM4emzguUso9CzaHU2xy5ctSrmK5YNA==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-http@3.972.7': - resolution: {integrity: sha512-L2uOGtvp2x3bTcxFTpSM+GkwFIPd8pHfGWO1764icMbo7e5xJh0nfhx1UwkXLnwvocTNEf8A7jISZLYjUSNaTg==} + '@aws-sdk/credential-provider-http@3.972.18': + resolution: {integrity: sha512-NyB6smuZAixND5jZumkpkunQ0voc4Mwgkd+SZ6cvAzIB7gK8HV8Zd4rS8Kn5MmoGgusyNfVGG+RLoYc4yFiw+A==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-ini@3.972.5': - resolution: {integrity: sha512-SdDTYE6jkARzOeL7+kudMIM4DaFnP5dZVeatzw849k4bSXDdErDS188bgeNzc/RA2WGrlEpsqHUKP6G7sVXhZg==} + '@aws-sdk/credential-provider-ini@3.972.16': + resolution: {integrity: sha512-hzAnzNXKV0A4knFRWGu2NCt72P4WWxpEGnOc6H3DptUjC4oX3hGw846oN76M1rTHAOwDdbhjU0GAOWR4OUfTZg==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-login@3.972.5': - resolution: {integrity: sha512-uYq1ILyTSI6ZDCMY5+vUsRM0SOCVI7kaW4wBrehVVkhAxC6y+e9rvGtnoZqCOWL1gKjTMouvsf4Ilhc5NCg1Aw==} + '@aws-sdk/credential-provider-login@3.972.16': + resolution: {integrity: sha512-VI0kXTlr0o1FTay+Jvx6AKqx5ECBgp7X4VevGBEbuXdCXnNp7SPU0KvjsOLVhIz3OoPK4/lTXphk43t0IVk65w==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-node@3.972.6': - resolution: {integrity: sha512-DZ3CnAAtSVtVz+G+ogqecaErMLgzph4JH5nYbHoBMgBkwTUV+SUcjsjOJwdBJTHu3Dm6l5LBYekZoU2nDqQk2A==} + '@aws-sdk/credential-provider-node@3.972.17': + resolution: {integrity: sha512-98MAcQ2Dk7zkvgwZ5f6fLX2lTyptC3gTSDx4EpvTdJWET8qs9lBPYggoYx7GmKp/5uk0OwVl0hxIDZsDNS/Y9g==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-process@3.972.5': - resolution: {integrity: sha512-HDKF3mVbLnuqGg6dMnzBf1VUOywE12/N286msI9YaK9mEIzdsGCtLTvrDhe3Up0R9/hGFbB+9l21/TwF5L1C6g==} + '@aws-sdk/credential-provider-process@3.972.16': + resolution: {integrity: sha512-n89ibATwnLEg0ZdZmUds5bq8AfBAdoYEDpqP3uzPLaRuGelsKlIvCYSNNvfgGLi8NaHPNNhs1HjJZYbqkW9b+g==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-sso@3.972.5': - resolution: {integrity: sha512-8urj3AoeNeQisjMmMBhFeiY2gxt6/7wQQbEGun0YV/OaOOiXrIudTIEYF8ZfD+NQI6X1FY5AkRsx6O/CaGiybA==} + '@aws-sdk/credential-provider-sso@3.972.16': + resolution: {integrity: sha512-b9of7tQgERxgcEcwAFWvRe84ivw+Kw6b3jVuz/6LQzonkomiY5UoWfprkbjc8FSCQ2VjDqKTvIRA9F0KSQ025w==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-web-identity@3.972.5': - resolution: {integrity: sha512-OK3cULuJl6c+RcDZfPpaK5o3deTOnKZbxm7pzhFNGA3fI2hF9yDih17fGRazJzGGWaDVlR9ejZrpDef4DJCEsw==} + '@aws-sdk/credential-provider-web-identity@3.972.16': + resolution: {integrity: sha512-PaOH5jFoPQX4WkqpKzKh9cM7rieKtbgEGqrZ+ybGmotJhcvhI/xl69yCwMbHGnpQJJmHZIX9q2zaPB7HTBn/4w==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-bucket-endpoint@3.972.3': - resolution: {integrity: sha512-fmbgWYirF67YF1GfD7cg5N6HHQ96EyRNx/rDIrTF277/zTWVuPI2qS/ZHgofwR1NZPe/NWvoppflQY01LrbVLg==} + '@aws-sdk/middleware-bucket-endpoint@3.972.7': + resolution: {integrity: sha512-goX+axlJ6PQlRnzE2bQisZ8wVrlm6dXJfBzMJhd8LhAIBan/w1Kl73fJnalM/S+18VnpzIHumyV6DtgmvqG5IA==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-expect-continue@3.972.3': - resolution: {integrity: sha512-4msC33RZsXQpUKR5QR4HnvBSNCPLGHmB55oDiROqqgyOc+TOfVu2xgi5goA7ms6MdZLeEh2905UfWMnMMF4mRg==} + '@aws-sdk/middleware-expect-continue@3.972.7': + resolution: {integrity: sha512-mvWqvm61bmZUKmmrtl2uWbokqpenY3Mc3Jf4nXB/Hse6gWxLPaCQThmhPBDzsPSV8/Odn8V6ovWt3pZ7vy4BFQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-flexible-checksums@3.972.5': - resolution: {integrity: sha512-SF/1MYWx67OyCrLA4icIpWUfCkdlOi8Y1KecQ9xYxkL10GMjVdPTGPnYhAg0dw5U43Y9PVUWhAV2ezOaG+0BLg==} + '@aws-sdk/middleware-flexible-checksums@3.973.4': + resolution: {integrity: sha512-7CH2jcGmkvkHc5Buz9IGbdjq1729AAlgYJiAvGq7qhCHqYleCsriWdSnmsqWTwdAfXHMT+pkxX3w6v5tJNcSug==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-host-header@3.972.3': - resolution: {integrity: sha512-aknPTb2M+G3s+0qLCx4Li/qGZH8IIYjugHMv15JTYMe6mgZO8VBpYgeGYsNMGCqCZOcWzuf900jFBG5bopfzmA==} + '@aws-sdk/middleware-host-header@3.972.7': + resolution: {integrity: sha512-aHQZgztBFEpDU1BB00VWCIIm85JjGjQW1OG9+98BdmaOpguJvzmXBGbnAiYcciCd+IS4e9BEq664lhzGnWJHgQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-location-constraint@3.972.3': - resolution: {integrity: sha512-nIg64CVrsXp67vbK0U1/Is8rik3huS3QkRHn2DRDx4NldrEFMgdkZGI/+cZMKD9k4YOS110Dfu21KZLHrFA/1g==} + '@aws-sdk/middleware-location-constraint@3.972.7': + resolution: {integrity: sha512-vdK1LJfffBp87Lj0Bw3WdK1rJk9OLDYdQpqoKgmpIZPe+4+HawZ6THTbvjhJt4C4MNnRrHTKHQjkwBiIpDBoig==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-logger@3.972.3': - resolution: {integrity: sha512-Ftg09xNNRqaz9QNzlfdQWfpqMCJbsQdnZVJP55jfhbKi1+FTWxGuvfPoBhDHIovqWKjqbuiew3HuhxbJ0+OjgA==} + '@aws-sdk/middleware-logger@3.972.7': + resolution: {integrity: sha512-LXhiWlWb26txCU1vcI9PneESSeRp/RYY/McuM4SpdrimQR5NgwaPb4VJCadVeuGWgh6QmqZ6rAKSoL1ob16W6w==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-recursion-detection@3.972.3': - resolution: {integrity: sha512-PY57QhzNuXHnwbJgbWYTrqIDHYSeOlhfYERTAuc16LKZpTZRJUjzBFokp9hF7u1fuGeE3D70ERXzdbMBOqQz7Q==} + '@aws-sdk/middleware-recursion-detection@3.972.7': + resolution: {integrity: sha512-l2VQdcBcYLzIzykCHtXlbpiVCZ94/xniLIkAj0jpnpjY4xlgZx7f56Ypn+uV1y3gG0tNVytJqo3K9bfMFee7SQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-sdk-s3@3.972.7': - resolution: {integrity: sha512-VtZ7tMIw18VzjG+I6D6rh2eLkJfTtByiFoCIauGDtTTPBEUMQUiGaJ/zZrPlCY6BsvLLeFKz3+E5mntgiOWmIg==} + '@aws-sdk/middleware-sdk-s3@3.972.18': + resolution: {integrity: sha512-5E3XxaElrdyk6ZJ0TjH7Qm6ios4b/qQCiLr6oQ8NK7e4Kn6JBTJCaYioQCQ65BpZ1+l1mK5wTAac2+pEz0Smpw==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-ssec@3.972.3': - resolution: {integrity: sha512-dU6kDuULN3o3jEHcjm0c4zWJlY1zWVkjG9NPe9qxYLLpcbdj5kRYBS2DdWYD+1B9f910DezRuws7xDEqKkHQIg==} + '@aws-sdk/middleware-ssec@3.972.7': + resolution: {integrity: sha512-G9clGVuAml7d8DYzY6DnRi7TIIDRvZ3YpqJPz/8wnWS5fYx/FNWNmkO6iJVlVkQg9BfeMzd+bVPtPJOvC4B+nQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-user-agent@3.972.7': - resolution: {integrity: sha512-HUD+geASjXSCyL/DHPQc/Ua7JhldTcIglVAoCV8kiVm99IaFSlAbTvEnyhZwdE6bdFyTL+uIaWLaCFSRsglZBQ==} + '@aws-sdk/middleware-user-agent@3.972.18': + resolution: {integrity: sha512-KcqQDs/7WtoEnp52+879f8/i1XAJkgka5i4arOtOCPR10o4wWo3VRecDI9Gxoh6oghmLCnIiOSKyRcXI/50E+w==} engines: {node: '>=20.0.0'} - '@aws-sdk/nested-clients@3.985.0': - resolution: {integrity: sha512-TsWwKzb/2WHafAY0CE7uXgLj0FmnkBTgfioG9HO+7z/zCPcl1+YU+i7dW4o0y+aFxFgxTMG+ExBQpqT/k2ao8g==} + '@aws-sdk/nested-clients@3.996.6': + resolution: {integrity: sha512-blNJ3ugn4gCQ9ZSZi/firzKCvVl5LvPFVxv24LprENeWI4R8UApG006UQkF4SkmLygKq2BQXRad2/anQ13Te4Q==} engines: {node: '>=20.0.0'} - '@aws-sdk/region-config-resolver@3.972.3': - resolution: {integrity: sha512-v4J8qYAWfOMcZ4MJUyatntOicTzEMaU7j3OpkRCGGFSL2NgXQ5VbxauIyORA+pxdKZ0qQG2tCQjQjZDlXEC3Ow==} + '@aws-sdk/region-config-resolver@3.972.7': + resolution: {integrity: sha512-/Ev/6AI8bvt4HAAptzSjThGUMjcWaX3GX8oERkB0F0F9x2dLSBdgFDiyrRz3i0u0ZFZFQ1b28is4QhyqXTUsVA==} engines: {node: '>=20.0.0'} - '@aws-sdk/signature-v4-multi-region@3.986.0': - resolution: {integrity: sha512-Upw+rw7wCH93E6QWxqpAqJLrUmJYVUAWrk4tCOBnkeuwzGERZvJFL5UQ6TAJFj9T18Ih+vNFaACh8J5aP4oTBw==} + '@aws-sdk/signature-v4-multi-region@3.996.6': + resolution: {integrity: sha512-NnsOQsVmJXy4+IdPFUjRCWPn9qNH1TzS/f7MiWgXeoHs903tJpAWQWQtoFvLccyPoBgomKP9L89RRr2YsT/L0g==} engines: {node: '>=20.0.0'} - '@aws-sdk/token-providers@3.985.0': - resolution: {integrity: sha512-+hwpHZyEq8k+9JL2PkE60V93v2kNhUIv7STFt+EAez1UJsJOQDhc5LpzEX66pNjclI5OTwBROs/DhJjC/BtMjQ==} + '@aws-sdk/token-providers@3.1003.0': + resolution: {integrity: sha512-SOyyWNdT7njKRwtZ1JhwHlH1csv6Pkgf305X96/OIfnhq1pU/EjmT6W6por57rVrjrKuHBuEIXgpWv8OgoMHpg==} engines: {node: '>=20.0.0'} - '@aws-sdk/types@3.973.1': - resolution: {integrity: sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg==} + '@aws-sdk/types@3.973.5': + resolution: {integrity: sha512-hl7BGwDCWsjH8NkZfx+HgS7H2LyM2lTMAI7ba9c8O0KqdBLTdNJivsHpqjg9rNlAlPyREb6DeDRXUl0s8uFdmQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/util-arn-parser@3.972.2': - resolution: {integrity: sha512-VkykWbqMjlSgBFDyrY3nOSqupMc6ivXuGmvci6Q3NnLq5kC+mKQe2QBZ4nrWRE/jqOxeFP2uYzLtwncYYcvQDg==} + '@aws-sdk/util-arn-parser@3.972.3': + resolution: {integrity: sha512-HzSD8PMFrvgi2Kserxuff5VitNq2sgf3w9qxmskKDiDTThWfVteJxuCS9JXiPIPtmCrp+7N9asfIaVhBFORllA==} engines: {node: '>=20.0.0'} - '@aws-sdk/util-endpoints@3.985.0': - resolution: {integrity: sha512-vth7UfGSUR3ljvaq8V4Rc62FsM7GUTH/myxPWkaEgOrprz1/Pc72EgTXxj+cPPPDAfHFIpjhkB7T7Td0RJx+BA==} + '@aws-sdk/util-endpoints@3.996.4': + resolution: {integrity: sha512-Hek90FBmd4joCFj+Vc98KLJh73Zqj3s2W56gjAcTkrNLMDI5nIFkG9YpfcJiVI1YlE2Ne1uOQNe+IgQ/Vz2XRA==} engines: {node: '>=20.0.0'} - '@aws-sdk/util-endpoints@3.986.0': - resolution: {integrity: sha512-Mqi79L38qi1gCG3adlVdbNrSxvcm1IPDLiJPA3OBypY5ewxUyWbaA3DD4goG+EwET6LSFgZJcRSIh6KBNpP5pA==} + '@aws-sdk/util-locate-window@3.965.5': + resolution: {integrity: sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/util-locate-window@3.965.4': - resolution: {integrity: sha512-H1onv5SkgPBK2P6JR2MjGgbOnttoNzSPIRoeZTNPZYyaplwGg50zS3amXvXqF0/qfXpWEC9rLWU564QTB9bSog==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/util-user-agent-browser@3.972.3': - resolution: {integrity: sha512-JurOwkRUcXD/5MTDBcqdyQ9eVedtAsZgw5rBwktsPTN7QtPiS2Ld1jkJepNgYoCufz1Wcut9iup7GJDoIHp8Fw==} + '@aws-sdk/util-user-agent-browser@3.972.7': + resolution: {integrity: sha512-7SJVuvhKhMF/BkNS1n0QAJYgvEwYbK2QLKBrzDiwQGiTRU6Yf1f3nehTzm/l21xdAOtWSfp2uWSddPnP2ZtsVw==} - '@aws-sdk/util-user-agent-node@3.972.5': - resolution: {integrity: sha512-GsUDF+rXyxDZkkJxUsDxnA67FG+kc5W1dnloCFLl6fWzceevsCYzJpASBzT+BPjwUgREE6FngfJYYYMQUY5fZQ==} + '@aws-sdk/util-user-agent-node@3.973.3': + resolution: {integrity: sha512-8s2cQmTUOwcBlIJyI9PAZNnnnF+cGtdhHc1yzMMsSD/GR/Hxj7m0IGUE92CslXXb8/p5Q76iqOCjN1GFwyf+1A==} engines: {node: '>=20.0.0'} peerDependencies: aws-crt: '>=1.0.0' @@ -3271,8 +3282,8 @@ packages: aws-crt: optional: true - '@aws-sdk/xml-builder@3.972.4': - resolution: {integrity: sha512-0zJ05ANfYqI6+rGqj8samZBFod0dPPousBjLEqg8WdxSgbMAkRgLyn81lP215Do0rFJ/17LIXwr7q0yK24mP6Q==} + '@aws-sdk/xml-builder@3.972.10': + resolution: {integrity: sha512-OnejAIVD+CxzyAUrVic7lG+3QRltyja9LoNqCE/1YVs8ichoTbJlVSaZ9iSMcnHLyzrSNtvaOGjSDRP+d/ouFA==} engines: {node: '>=20.0.0'} '@aws/lambda-invoke-store@0.2.3': @@ -3298,10 +3309,6 @@ packages: '@babel/core': ^7.11.0 eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 - '@babel/generator@7.23.6': - resolution: {integrity: sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==} - engines: {node: '>=6.9.0'} - '@babel/generator@7.29.1': resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} engines: {node: '>=6.9.0'} @@ -3331,22 +3338,10 @@ packages: peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - '@babel/helper-environment-visitor@7.24.7': - resolution: {integrity: sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-function-name@7.24.7': - resolution: {integrity: sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==} - engines: {node: '>=6.9.0'} - '@babel/helper-globals@7.28.0': resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} engines: {node: '>=6.9.0'} - '@babel/helper-hoist-variables@7.24.7': - resolution: {integrity: sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==} - engines: {node: '>=6.9.0'} - '@babel/helper-member-expression-to-functions@7.28.5': resolution: {integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==} engines: {node: '>=6.9.0'} @@ -3385,10 +3380,6 @@ packages: resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==} engines: {node: '>=6.9.0'} - '@babel/helper-split-export-declaration@7.24.7': - resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==} - engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.27.1': resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} @@ -3812,11 +3803,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-typescript@7.4.5': - resolution: {integrity: sha512-RPB/YeGr4ZrFKNwfuQRlMf2lxoCUaU01MTw39/OFE/RiL8HDjtn68BwEPft1P7JN4akyEmjGWAMNldOV7o9V2g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-escapes@7.27.1': resolution: {integrity: sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==} engines: {node: '>=6.9.0'} @@ -3867,27 +3853,19 @@ packages: resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.23.9': - resolution: {integrity: sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==} - engines: {node: '>=6.9.0'} - '@babel/traverse@7.29.0': resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} engines: {node: '>=6.9.0'} - '@babel/types@7.23.0': - resolution: {integrity: sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==} - engines: {node: '>=6.9.0'} - '@babel/types@7.29.0': resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} - '@cacheable/memory@2.0.7': - resolution: {integrity: sha512-RbxnxAMf89Tp1dLhXMS7ceft/PGsDl1Ip7T20z5nZ+pwIAsQ1p2izPjVG69oCLv/jfQ7HDPHTWK0c9rcAWXN3A==} + '@cacheable/memory@2.0.8': + resolution: {integrity: sha512-FvEb29x5wVwu/Kf93IWwsOOEuhHh6dYCJF3vcKLzXc0KXIW181AOzv6ceT4ZpBHDvAfG60eqb+ekmrnLHIy+jw==} - '@cacheable/utils@2.3.4': - resolution: {integrity: sha512-knwKUJEYgIfwShABS1BX6JyJJTglAFcEU7EXqzTdiGCXur4voqkiJkdgZIQtWNFhynzDWERcTYv/sETMu3uJWA==} + '@cacheable/utils@2.4.0': + resolution: {integrity: sha512-PeMMsqjVq+bF0WBsxFBxr/WozBJiZKY0rUojuaCoIaKnEl3Ju1wfEwS+SV1DU/cSe8fqHIPiYJFif8T3MVt4cQ==} '@cnakazawa/watch@1.0.4': resolution: {integrity: sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==} @@ -3926,8 +3904,8 @@ packages: peerDependencies: '@csstools/css-tokenizer': ^3.0.4 - '@csstools/css-syntax-patches-for-csstree@1.0.27': - resolution: {integrity: sha512-sxP33Jwg1bviSUXAV43cVYdmjt2TLnLXNqCWl9xmxHawWVjGz/kEbdkr7F9pxJNBN2Mh+dq0crgItbW6tQvyow==} + '@csstools/css-syntax-patches-for-csstree@1.1.0': + resolution: {integrity: sha512-H4tuz2nhWgNKLt1inYpoVCfbJbMwX/lQKp3g69rrrIMIYlFD9+zTykOKhNR8uGrAmbS/kT9n6hTFkmDkxLgeTA==} '@csstools/css-tokenizer@3.0.4': resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} @@ -3949,72 +3927,23 @@ packages: '@dual-bundle/import-meta-resolve@4.2.1': resolution: {integrity: sha512-id+7YRUgoUX6CgV0DtuhirQWodeeA7Lf4i2x71JS/vtA5pRb/hIGWlw+G6MeXvsM+MXrz0VAydTGElX1rAfgPg==} - '@ember-data/adapter@5.8.1': - resolution: {integrity: sha512-LWKrP/z50XxVMl2jjPrgyDZUjCyUstp3DDsHqM+aShJipec+Afi4Mu9mAaEsMFyTr4xpq21tG82GnAkDfFf0ig==} - - '@ember-data/debug@5.8.1': - resolution: {integrity: sha512-Jn7F0+stvn6QVkFhROXDXGLKn4iaCbG9uYVeEyqHSayTZikfSeXu0RqbPQxL+3rOyAcLf8QAfR9GlNV6EmETGQ==} - - '@ember-data/graph@5.8.1': - resolution: {integrity: sha512-uqbjISLWFOcT9+tloz3Kl+1ZI1VUPRSB6eQXh/i1Od7KSC5D5buu5J4JqtluxrC7MbsK2MaE0vI2T1Li5iVGbw==} - - '@ember-data/json-api@5.8.1': - resolution: {integrity: sha512-DzHIVXAwbKtf6i6sIIlu4Y7EBgPEPc3naaRvEJ8stQB/1JwKoJPvAe3IEkHAMwe1/Ay1Fzm7DJXS/roEj4TlnQ==} - - '@ember-data/legacy-compat@5.8.1': - resolution: {integrity: sha512-FaGE4j8BAEMVo3OixEvst/2a2DNq8oHtx6thA9jbDiVAD7jzrvqQpPTGlsYVyRWJFGpEFxABLIUwVbaZubpqMg==} - - '@ember-data/model@5.8.1': - resolution: {integrity: sha512-4sJO/5sbl6ArpKPV1Va5Uibeyyi4y2CDBH76tn9nAuLf5ba/q1FxynD18mpR3VkHAxUdqBZYimINKN08hCYhEQ==} - - '@ember-data/request-utils@5.8.1': - resolution: {integrity: sha512-xKSbQLFyq95EHePShtMJM0Cu3SibGyB8Eo0XuO74fTopMWD/xW29uY/bqBonQdaZnIonJwOKs36ztf7oSiRaZQ==} - peerDependencies: - ember-inflector: ^4.0.2 || ^5.0.0 || ^6.0.0 - peerDependenciesMeta: - ember-inflector: - optional: true - - '@ember-data/request@5.8.1': - resolution: {integrity: sha512-ZyvBr/JQNoPmBkBVhAW0hKPi5WTagEMqQuzH9JmyzduuFXPHLGqdxL/8bBVwm1k6TqjaUM6y0y1/24o/Y5XGgA==} - '@ember-data/rfc395-data@0.0.4': resolution: {integrity: sha512-tGRdvgC9/QMQSuSuJV45xoyhI0Pzjm7A9o/MVVA3HakXIImJbbzx/k/6dO9CUEQXIyS2y0fW6C1XaYOG7rY0FQ==} - '@ember-data/serializer@5.8.1': - resolution: {integrity: sha512-SGnzZWrBT2TDJAJkNKQQqvtXxoAF9o1+M0puS7AZ0uuUVdo35Rwscrb1SrbCzXDM0MaZ5mE++Cz2yBhZuwZB/g==} - - '@ember-data/store@5.8.1': - resolution: {integrity: sha512-8OqAL6aqDpbv3jCH70qQhA0HJtbTM0oFl2gRuJ2gXq0tx7WhOU7f3IwQEHX646O2x43RdtsPKhbc27rXxQdFGw==} - peerDependencies: - '@ember-data/tracking': 5.8.1 - '@ember/test-waiters': ^3.1.0 || ^4.0.0 - peerDependenciesMeta: - '@ember-data/tracking': - optional: true - '@ember/test-waiters': - optional: true - - '@ember-data/tracking@5.8.1': - resolution: {integrity: sha512-ytaExT9HoRH9yUbAe/iOe5cv9I2rmTxwqHPMzTHBkuJvIyAAFXnCHX4RI+p+jud11stquV6Z6IgiUsT3E9RL8A==} - deprecated: Use @warp-drive/ember - peerDependencies: - '@ember/test-waiters': ^3.1.0 || ^4.0.0 - '@ember-tooling/blueprint-blueprint@0.2.1': resolution: {integrity: sha512-eZ5qicL3gfFFbmzLaSiEWPSmoRUJGnqg+dQmU0R81vv+0Ni7W/cS7MXx1l4HpN9B7Yg4M9GgdQTkeJnb6abQug==} '@ember-tooling/blueprint-model@0.5.0': resolution: {integrity: sha512-2zAebSmmzpUO2wt6EyfX5TlcmvB9cTkteuZ3QhPmXLMthUpU5nUifcz3hlYcXPK7WM0HdO9qL4GdGQCoxhzaGg==} - '@ember-tooling/classic-build-addon-blueprint@6.10.0': - resolution: {integrity: sha512-pxXtpcU2VAHNow6L3x7Fqz8XShB6MyvivFl87meDQmHIKNQVUTOH1KltyQekfDTwnEzM8pmtoAU/FqOe0TkFVw==} + '@ember-tooling/classic-build-addon-blueprint@6.11.0': + resolution: {integrity: sha512-YDZlXLg+nzp2wDGEA7eJKTxF7d9d6WEjgALQkoOnardWQCS0Trr3Ce2itVySsadB8CX1Sqrze4qCQjw1XMAjqg==} - '@ember-tooling/classic-build-app-blueprint@6.10.0': - resolution: {integrity: sha512-lTyYGTnsq4FFeTAJ7ZxGwmwF0T6fuiZeqdMp34IHoiUC2lMV0yFLFpSChiaxiWgz1yTaagz8pJ9Kv+XbUZZVmA==} + '@ember-tooling/classic-build-app-blueprint@6.11.0': + resolution: {integrity: sha512-ZqwAC+3X3HFcBcmbyyBRh0KXkQSuW+L6Rry9Q7vmGFoQ+wQQnDQ9MS+TXz72VqP47+MGfZRJXWfCeqEUTpuSRg==} - '@ember/app-blueprint@6.10.4': - resolution: {integrity: sha512-9MrxcopYDau1s7icCoQJxPGYg+x0g86PPMqr4YzKKyzLYl33PbyH2zFwZahGOiUNVfc9itdB1TfXdIU64fBnqQ==} + '@ember/app-blueprint@6.11.1': + resolution: {integrity: sha512-Bq9+s/EQYPYVFNU3ZXgwxLuF9WbPtyEcv0sSi5f29WIvt7vxVbeF+IADLlLimT+GYTBYfqjdFCsUlkhyM1pI8A==} '@ember/edition-utils@1.2.0': resolution: {integrity: sha512-VmVq/8saCaPdesQmftPqbFtxJWrzxNGSQ+e8x8LLe3Hjm36pJ04Q8LeORGZkAeOhldoUX9seLGmSaHeXkIqoog==} @@ -4023,26 +3952,12 @@ packages: resolution: {integrity: sha512-+M8CkPledQEaDbfIlwlq6Phgpm5jdT3a6WVDJk7b/zadw5xAJkuQKVK7DgR0SFgHGiWlyn6a8AU5p2mCA706RA==} engines: {node: 10.* || 12.* || >= 14} - '@ember/string@3.1.1': - resolution: {integrity: sha512-UbXJ+k3QOrYN4SRPHgXCqYIJ+yWWUg1+vr0H4DhdQPTy8LJfyqwZ2tc5uqpSSnEXE+/1KopHBE5J8GDagAg5cg==} - engines: {node: 12.* || 14.* || >= 16} - '@ember/string@4.0.1': resolution: {integrity: sha512-VWeng8BSWrIsdPfffOQt/bKwNKJL7+37gPFh/6iZZ9bke+S83kKqkS30poo4bTGfRcMnvAE0ie7txom+iDu81Q==} - '@ember/test-helpers@3.3.1': - resolution: {integrity: sha512-h4uFBy4pquBtHsHI+tx9S0wtMmn1L+8dkXiDiyoqG1+3e0Awk6GBujiFM9s4ANq6wC8uIhC3wEFyts10h2OAoQ==} - engines: {node: 16.* || >= 18} - peerDependencies: - ember-source: ^4.0.0 || ^5.0.0 - '@ember/test-helpers@5.4.1': resolution: {integrity: sha512-BUdT91ra+QibEWAUwtZmvTGFoDHJCxDU+fkQENA8Zs0FR3pZiICxxP/fgdlNExCjjdm1letut7ENoueBuDdixQ==} - '@ember/test-waiters@3.1.0': - resolution: {integrity: sha512-bb9h95ktG2wKY9+ja1sdsFBdOms2lB19VWs8wmNpzgHv1NCetonBoV5jHBV4DHt0uS1tg9z66cZqhUVlYs96KQ==} - engines: {node: 10.* || 12.* || >= 14.*} - '@ember/test-waiters@4.1.1': resolution: {integrity: sha512-HbK70JYCDJcGI0CrwcbjeL2QHAn0HLwa3oGep7mr6l/yO95U7JYA8VN+/9VTsWJTmKueLtWayUqEmGS3a3mVOg==} @@ -4063,11 +3978,11 @@ packages: peerDependencies: '@embroider/core': ^3.5.9 - '@embroider/compat@4.1.13': - resolution: {integrity: sha512-TUvc1bv95deXBdhbgnuNAISbgky5Muo+2x38H4qaw56B//9ppmwqnqw0LIVTXlezY40qgwrW8/ztLW6qIbsPeg==} + '@embroider/compat@4.1.15': + resolution: {integrity: sha512-Z0tDSliXSsMZtvCHUYHIF2oJnjhgf9EE7D75519DBh8UG/xb4jNZrq6ykDEIC2sGByjt8e+ZAczWqAapMBAJZg==} engines: {node: '>= 20.19.*'} peerDependencies: - '@embroider/core': ^4.4.3 + '@embroider/core': ^4.4.5 '@embroider/config-meta-loader@1.0.0': resolution: {integrity: sha512-qznkdjgEGPe6NM94hZNXvOm/WhrJwBh8FtSQZ+nGjh9TOjY42tOiTEevFuM0onNXUn6bpdGzmjwKo2xY2jxQxQ==} @@ -4077,8 +3992,8 @@ packages: resolution: {integrity: sha512-e6ChqCI2I4/UMnnGRS6be2pY3ssJDXfjrF1dtLt2e6l4EM2IIlT1ndtPAYUGSYSO9JB5WxNpO8Wirj88mVh97Q==} engines: {node: 12.* || 14.* || >= 16} - '@embroider/core@4.4.3': - resolution: {integrity: sha512-kj651cfYIRf4V8OUnMhuPy1mo7lF1CpCCXyw7kD77qkeBXdvAzCSQFGKANxwuOVkcTW0kU74l3Dv9gGp2NrHxA==} + '@embroider/core@4.4.5': + resolution: {integrity: sha512-WNcKSO7AY2QS35uPksfYi/APCWqPyHduJYXJrs/MX39FDbrZCqxu+dHBAXtQw3ZaVcXzHUeOMrAdt37qlmu/mw==} engines: {node: 12.* || 14.* || >= 16} '@embroider/hbs-loader@3.0.5': @@ -4091,15 +4006,6 @@ packages: '@embroider/legacy-inspector-support@0.1.3': resolution: {integrity: sha512-0VzD1xExkT78a1CUiW8wZ5VZDL4bVyMSc3t8E/RiAW1X6TlyKIA/m6zoQgsQtQIiiTPPxH0/1Tdd0F7b5//etw==} - '@embroider/macros@1.19.7': - resolution: {integrity: sha512-KOdoJ2QwNpWFwRP8q4CutMjs4QAgZ0rjNJAO+hYZkWFxM3DOQFyqvImNDx0m/Z/sXEnE1XwUN8NpMCNYyq801A==} - engines: {node: 12.* || 14.* || >= 16} - peerDependencies: - '@glint/template': ^1.0.0 - peerDependenciesMeta: - '@glint/template': - optional: true - '@embroider/macros@1.20.1': resolution: {integrity: sha512-Ia3uPg4kgunvI3XySzHqKpC/niyxKSjjI8b6OIDf1KL9gtfztbC8x1dthHvX2823KnHcOhdHMudGWAhVuj2BKg==} engines: {node: 12.* || 14.* || >= 16} @@ -4129,25 +4035,10 @@ packages: resolution: {integrity: sha512-/SusdG+zgosc3t+9sPFVKSFOYyiSgLfXOT6lYNWoG1YtnhWDxlK4S8leZ0jhcVjemdaHln5rTyxCnq8oFLxqpQ==} engines: {node: 12.* || 14.* || >= 16} - '@embroider/test-setup@4.0.0': - resolution: {integrity: sha512-1S3Ebk0CEh3XDqD93AWSwQZBCk+oGv03gtkaGgdgyXGIR7jrVyDgEnEuslN/hJ0cuU8TqhiXrzHMw7bJwIGhWw==} - engines: {node: 12.* || 14.* || >= 16} - peerDependencies: - '@embroider/compat': ^3.4.8 - '@embroider/core': ^3.4.8 - '@embroider/webpack': ^4.0.0 - peerDependenciesMeta: - '@embroider/compat': - optional: true - '@embroider/core': - optional: true - '@embroider/webpack': - optional: true - - '@embroider/vite@1.5.2': - resolution: {integrity: sha512-vaD2rSugRGAsBgoF6a098JqyL8grPAoPTx627wvxfUhE5uW19hGi7ybpTD3Zlkn4pKNKR9k9tPW3sP1Cnvbm4A==} + '@embroider/vite@1.6.1': + resolution: {integrity: sha512-82xk4ODS31yJTPk9LntJarkmEDvbbZIw3dM95O+k67qXt0NHrcF7AJR2Wg/yn4cgUw0PDQptFE40TeJl6igymQ==} peerDependencies: - '@embroider/core': ^4.4.3 + '@embroider/core': ^4.4.5 vite: '>= 5.2.0' '@embroider/webpack@4.1.2': @@ -4482,20 +4373,12 @@ packages: resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/eslintrc@2.1.4': - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - '@eslint/eslintrc@3.3.3': - resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} + '@eslint/eslintrc@3.3.4': + resolution: {integrity: sha512-4h4MVF8pmBsncB60r0wSJiIeUKTSD4m7FmTFThG8RHlsg9ajqckLm9OraguFGZE4vVdpiI1Q4+hFnisopmG6gQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@8.57.1': - resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - '@eslint/js@9.39.2': - resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==} + '@eslint/js@9.39.3': + resolution: {integrity: sha512-1B1VkCq6FuUNlQvlBYb+1jDu/gV297TIs/OeiaSR9l1H27SVW55ONE1e1Vp16NqP683+xEGzxYtv4XCiDPaQiw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.7': @@ -4524,9 +4407,6 @@ packages: '@glimmer/interfaces@0.84.3': resolution: {integrity: sha512-dk32ykoNojt0mvEaIW6Vli5MGTbQo58uy3Epj7ahCgTHmWOKuw/0G83f2UmFprRwFx689YTXG38I/vbpltEjzg==} - '@glimmer/interfaces@0.88.1': - resolution: {integrity: sha512-BOcN8xFNX/eppGxwS9Rm1+PlQaFX+tK91cuQLHj2sRwB+qVbL/WeutIa3AUQYr0VVEzMm2S6bYCLvG6p0a8v9A==} - '@glimmer/interfaces@0.94.6': resolution: {integrity: sha512-sp/1WePvB/8O+jrcUHwjboNPTKrdGicuHKA9T/lh0vkYK2qM5Xz4i25lQMQ38tEMiw7KixrjHiTUiaXRld+IwA==} @@ -4545,9 +4425,6 @@ packages: '@glimmer/syntax@0.84.3': resolution: {integrity: sha512-ioVbTic6ZisLxqTgRBL2PCjYZTFIwobifCustrozRU2xGDiYvVIL0vt25h2c1ioDsX59UgVlDkIK4YTAQQSd2A==} - '@glimmer/syntax@0.88.1': - resolution: {integrity: sha512-tucexG0j5SSbk3d4ayCOnvjg5FldvWyrZbzxukZOBhDgAYhGWUnGFAqdoXjpr3w6FkD4xIVliVD9GFrH4lI8DA==} - '@glimmer/syntax@0.95.0': resolution: {integrity: sha512-W/PHdODnpONsXjbbdY9nedgIHpglMfOzncf/moLVrKIcCfeQhw2vG07Rs/YW8KeJCgJRCLkQsi+Ix7XvrurGAg==} @@ -4557,9 +4434,6 @@ packages: '@glimmer/util@0.84.3': resolution: {integrity: sha512-qFkh6s16ZSRuu2rfz3T4Wp0fylFj3HBsONGXQcrAdZjdUaIS6v3pNj6mecJ71qRgcym9Hbaq/7/fefIwECUiKw==} - '@glimmer/util@0.88.1': - resolution: {integrity: sha512-PV/24+vBmsReR78UQXJlEHDblU6QBAeIJa8MwKhQoxSD6WgvQHP4KmX23rvlCz11GxApTwyPm/2qyp/SwVvX2A==} - '@glimmer/util@0.94.8': resolution: {integrity: sha512-HfCKeZ74clF9BsPDBOqK/yRNa/ke6niXFPM6zRn9OVYw+ZAidLs7V8He/xljUHlLRL322kaZZY8XxRW7ALEwyg==} @@ -4575,9 +4449,6 @@ packages: '@glimmer/vm@0.94.8': resolution: {integrity: sha512-0E8BVNRE/1qlK9OQRUmGlQXwWmoco7vL3yIyLZpTWhbv22C1zEcM826wQT3ioaoUQSlvRsKKH6IEEUal2d3wxQ==} - '@glimmer/wire-format@0.88.1': - resolution: {integrity: sha512-DPM2UiYRNzcWdOUrSa8/IFbWKovH+c2JPnbvtk04DpfQapU7+hteBj34coEN/pW3FJiP3WMvx/EuPfWROkeDsg==} - '@glimmer/wire-format@0.94.8': resolution: {integrity: sha512-A+Cp5m6vZMAEu0Kg/YwU2dJZXyYxVJs2zI57d3CP6NctmX7FsT8WjViiRUmt5abVmMmRH5b8BUovqY6GSMAdrw==} @@ -4600,19 +4471,10 @@ packages: resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} engines: {node: '>=18.18.0'} - '@humanwhocodes/config-array@0.13.0': - resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} - engines: {node: '>=10.10.0'} - deprecated: Use @eslint/config-array instead - '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - '@humanwhocodes/object-schema@2.0.3': - resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} - deprecated: Use @eslint/object-schema instead - '@humanwhocodes/retry@0.4.3': resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} @@ -4666,15 +4528,6 @@ packages: '@types/node': optional: true - '@inquirer/external-editor@1.0.3': - resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} - engines: {node: '>=18'} - peerDependencies: - '@types/node': '>=18' - peerDependenciesMeta: - '@types/node': - optional: true - '@inquirer/external-editor@2.0.3': resolution: {integrity: sha512-LgyI7Agbda74/cL5MvA88iDpvdXI2KuMBCGRkbCl2Dg1vzHeOgs+s0SDcXV7b+WZJrv2+ERpWSM65Fpi9VfY3w==} engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} @@ -4684,10 +4537,6 @@ packages: '@types/node': optional: true - '@inquirer/figures@1.0.15': - resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==} - engines: {node: '>=18'} - '@inquirer/figures@2.0.3': resolution: {integrity: sha512-y09iGt3JKoOCBQ3w4YrSJdokcD8ciSlMIWsD+auPu+OZpfxLuyz+gICAQ6GCBOmJJt4KEQGHuZSVff2jiNOy7g==} engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} @@ -4764,14 +4613,6 @@ packages: '@types/node': optional: true - '@isaacs/balanced-match@4.0.1': - resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} - engines: {node: 20 || >=22} - - '@isaacs/brace-expansion@5.0.1': - resolution: {integrity: sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==} - engines: {node: 20 || >=22} - '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -4874,111 +4715,111 @@ packages: resolution: {integrity: sha512-y7eSzT6R5bmTIJbiMMXgOlbBpcWXGlVhNeQJBLBCCy1+90Wbjyqf6uvY0i2WcO4sh/THTJ20qCW80j3XUlgDTA==} engines: {node: '>=12.0.0'} - '@oxc-resolver/binding-android-arm-eabi@11.17.1': - resolution: {integrity: sha512-+VuZyMYYaap5uDAU1xDU3Kul0FekLqpBS8kI5JozlWfYQKnc/HsZg2gHPkQrj0SC9lt74WMNCfOzZZJlYXSdEQ==} + '@oxc-resolver/binding-android-arm-eabi@11.19.1': + resolution: {integrity: sha512-aUs47y+xyXHUKlbhqHUjBABjvycq6YSD7bpxSW7vplUmdzAlJ93yXY6ZR0c1o1x5A/QKbENCvs3+NlY8IpIVzg==} cpu: [arm] os: [android] - '@oxc-resolver/binding-android-arm64@11.17.1': - resolution: {integrity: sha512-YlDDTjvOEKhom/cRSVsXsMVeXVIAM9PJ/x2mfe08rfuS0iIEfJd8PngKbEIhG72WPxleUa+vkEZj9ncmC14z3Q==} + '@oxc-resolver/binding-android-arm64@11.19.1': + resolution: {integrity: sha512-oolbkRX+m7Pq2LNjr/kKgYeC7bRDMVTWPgxBGMjSpZi/+UskVo4jsMU3MLheZV55jL6c3rNelPl4oD60ggYmqA==} cpu: [arm64] os: [android] - '@oxc-resolver/binding-darwin-arm64@11.17.1': - resolution: {integrity: sha512-HOYYLSY4JDk14YkXaz/ApgJYhgDP4KsG8EZpgpOxdszGW9HmIMMY/vXqVKYW74dSH+GQkIXYxBrEh3nv+XODVg==} + '@oxc-resolver/binding-darwin-arm64@11.19.1': + resolution: {integrity: sha512-nUC6d2i3R5B12sUW4O646qD5cnMXf2oBGPLIIeaRfU9doJRORAbE2SGv4eW6rMqhD+G7nf2Y8TTJTLiiO3Q/dQ==} cpu: [arm64] os: [darwin] - '@oxc-resolver/binding-darwin-x64@11.17.1': - resolution: {integrity: sha512-JHPJbsa5HvPq2/RIdtGlqfaG9zV2WmgvHrKTYmlW0L5esqtKCBuetFudXTBzkNcyD69kSZLzH92AzTr6vFHMFg==} + '@oxc-resolver/binding-darwin-x64@11.19.1': + resolution: {integrity: sha512-cV50vE5+uAgNcFa3QY1JOeKDSkM/9ReIcc/9wn4TavhW/itkDGrXhw9jaKnkQnGbjJ198Yh5nbX/Gr2mr4Z5jQ==} cpu: [x64] os: [darwin] - '@oxc-resolver/binding-freebsd-x64@11.17.1': - resolution: {integrity: sha512-UD1FRC8j8xZstFXYsXwQkNmmg7vUbee006IqxokwDUUA+xEgKZDpLhBEiVKM08Urb+bn7Q0gn6M1pyNR0ng5mg==} + '@oxc-resolver/binding-freebsd-x64@11.19.1': + resolution: {integrity: sha512-xZOQiYGFxtk48PBKff+Zwoym7ScPAIVp4c14lfLxizO2LTTTJe5sx9vQNGrBymrf/vatSPNMD4FgsaaRigPkqw==} cpu: [x64] os: [freebsd] - '@oxc-resolver/binding-linux-arm-gnueabihf@11.17.1': - resolution: {integrity: sha512-wFWC1wyf2ROFWTxK5x0Enm++DSof3EBQ/ypyAesMDLiYxOOASDoMOZG1ylWUnlKaCt5W7eNOWOzABpdfFf/ssA==} + '@oxc-resolver/binding-linux-arm-gnueabihf@11.19.1': + resolution: {integrity: sha512-lXZYWAC6kaGe/ky2su94e9jN9t6M0/6c+GrSlCqL//XO1cxi5lpAhnJYdyrKfm0ZEr/c7RNyAx3P7FSBcBd5+A==} cpu: [arm] os: [linux] - '@oxc-resolver/binding-linux-arm-musleabihf@11.17.1': - resolution: {integrity: sha512-k/hUif0GEBk/csSqCfTPXb8AAVs1NNWCa/skBghvNbTtORcWfOVqJ3mM+2pE189+enRm4UnryLREu5ysI0kXEQ==} + '@oxc-resolver/binding-linux-arm-musleabihf@11.19.1': + resolution: {integrity: sha512-veG1kKsuK5+t2IsO9q0DErYVSw2azvCVvWHnfTOS73WE0STdLLB7Q1bB9WR+yHPQM76ASkFyRbogWo1GR1+WbQ==} cpu: [arm] os: [linux] - '@oxc-resolver/binding-linux-arm64-gnu@11.17.1': - resolution: {integrity: sha512-Cwm6A071ww60QouJ9LoHAwBgEoZzHQ0Qaqk2E7WLfBdiQN9mLXIDhnrpn04hlRElRPhLiu/dtg+o5PPLvaINXQ==} + '@oxc-resolver/binding-linux-arm64-gnu@11.19.1': + resolution: {integrity: sha512-heV2+jmXyYnUrpUXSPugqWDRpnsQcDm2AX4wzTuvgdlZfoNYO0O3W2AVpJYaDn9AG4JdM6Kxom8+foE7/BcSig==} cpu: [arm64] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-arm64-musl@11.17.1': - resolution: {integrity: sha512-+hwlE2v3m0r3sk93SchJL1uyaKcPjf+NGO/TD2DZUDo+chXx7FfaEj0nUMewigSt7oZ2sQN9Z4NJOtUa75HE5Q==} + '@oxc-resolver/binding-linux-arm64-musl@11.19.1': + resolution: {integrity: sha512-jvo2Pjs1c9KPxMuMPIeQsgu0mOJF9rEb3y3TdpsrqwxRM+AN6/nDDwv45n5ZrUnQMsdBy5gIabioMKnQfWo9ew==} cpu: [arm64] os: [linux] libc: [musl] - '@oxc-resolver/binding-linux-ppc64-gnu@11.17.1': - resolution: {integrity: sha512-bO+rsaE5Ox8cFyeL5Ct5tzot1TnQpFa/Wmu5k+hqBYSH2dNVDGoi0NizBN5QV8kOIC6O5MZr81UG4yW/2FyDTA==} + '@oxc-resolver/binding-linux-ppc64-gnu@11.19.1': + resolution: {integrity: sha512-vLmdNxWCdN7Uo5suays6A/+ywBby2PWBBPXctWPg5V0+eVuzsJxgAn6MMB4mPlshskYbppjpN2Zg83ArHze9gQ==} cpu: [ppc64] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-riscv64-gnu@11.17.1': - resolution: {integrity: sha512-B/P+hxKQ1oX4YstI9Lyh4PGzqB87Ddqj/A4iyRBbPdXTcxa+WW3oRLx1CsJKLmHPdDk461Hmbghq1Bm3pl+8Aw==} + '@oxc-resolver/binding-linux-riscv64-gnu@11.19.1': + resolution: {integrity: sha512-/b+WgR+VTSBxzgOhDO7TlMXC1ufPIMR6Vj1zN+/x+MnyXGW7prTLzU9eW85Aj7Th7CCEG9ArCbTeqxCzFWdg2w==} cpu: [riscv64] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-riscv64-musl@11.17.1': - resolution: {integrity: sha512-ulp2H3bFXzd/th2maH+QNKj5qgOhJ3v9Yspdf1svTw3CDOuuTl6sRKsWQ7MUw0vnkSNvQndtflBwVXgzZvURsQ==} + '@oxc-resolver/binding-linux-riscv64-musl@11.19.1': + resolution: {integrity: sha512-YlRdeWb9j42p29ROh+h4eg/OQ3dTJlpHSa+84pUM9+p6i3djtPz1q55yLJhgW9XfDch7FN1pQ/Vd6YP+xfRIuw==} cpu: [riscv64] os: [linux] libc: [musl] - '@oxc-resolver/binding-linux-s390x-gnu@11.17.1': - resolution: {integrity: sha512-LAXYVe3rKk09Zo9YKF2ZLBcH8sz8Oj+JIyiUxiHtq0hiYLMsN6dOpCf2hzQEjPAmsSEA/hdC1PVKeXo+oma8mQ==} + '@oxc-resolver/binding-linux-s390x-gnu@11.19.1': + resolution: {integrity: sha512-EDpafVOQWF8/MJynsjOGFThcqhRHy417sRyLfQmeiamJ8qVhSKAn2Dn2VVKUGCjVB9C46VGjhNo7nOPUi1x6uA==} cpu: [s390x] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-x64-gnu@11.17.1': - resolution: {integrity: sha512-3RAhxipMKE8RCSPn7O//sj440i+cYTgYbapLeOoDvQEt6R1QcJjTsFgI4iz99FhVj3YbPxlZmcLB5VW+ipyRTA==} + '@oxc-resolver/binding-linux-x64-gnu@11.19.1': + resolution: {integrity: sha512-NxjZe+rqWhr+RT8/Ik+5ptA3oz7tUw361Wa5RWQXKnfqwSSHdHyrw6IdcTfYuml9dM856AlKWZIUXDmA9kkiBQ==} cpu: [x64] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-x64-musl@11.17.1': - resolution: {integrity: sha512-wpjMEubGU8r9VjZTLdZR3aPHaBqTl8Jl8F4DBbgNoZ+yhkhQD1/MGvY70v2TLnAI6kAHSvcqgfvaqKDa2iWsPQ==} + '@oxc-resolver/binding-linux-x64-musl@11.19.1': + resolution: {integrity: sha512-cM/hQwsO3ReJg5kR+SpI69DMfvNCp+A/eVR4b4YClE5bVZwz8rh2Nh05InhwI5HR/9cArbEkzMjcKgTHS6UaNw==} cpu: [x64] os: [linux] libc: [musl] - '@oxc-resolver/binding-openharmony-arm64@11.17.1': - resolution: {integrity: sha512-XIE4w17RYAVIgx+9Gs3deTREq5tsmalbatYOOBGNdH7n0DfTE600c7wYXsp7ANc3BPDXsInnOzXDEPCvO1F6cg==} + '@oxc-resolver/binding-openharmony-arm64@11.19.1': + resolution: {integrity: sha512-QF080IowFB0+9Rh6RcD19bdgh49BpQHUW5TajG1qvWHvmrQznTZZjYlgE2ltLXyKY+qs4F/v5xuX1XS7Is+3qA==} cpu: [arm64] os: [openharmony] - '@oxc-resolver/binding-wasm32-wasi@11.17.1': - resolution: {integrity: sha512-Lqi5BlHX3zS4bpSOkIbOKVf7DIk6Gvmdifr2OuOI58eUUyP944M8/OyaB09cNpPy9Vukj7nmmhOzj8pwLgAkIg==} + '@oxc-resolver/binding-wasm32-wasi@11.19.1': + resolution: {integrity: sha512-w8UCKhX826cP/ZLokXDS6+milN8y4X7zidsAttEdWlVoamTNf6lhBJldaWr3ukTDiye7s4HRcuPEPOXNC432Vg==} engines: {node: '>=14.0.0'} cpu: [wasm32] - '@oxc-resolver/binding-win32-arm64-msvc@11.17.1': - resolution: {integrity: sha512-l6lTcLBQVj1HNquFpXSsrkCIM8X5Hlng5YNQJrg00z/KyovvDV5l3OFhoRyZ+aLBQ74zUnMRaJZC7xcBnHyeNg==} + '@oxc-resolver/binding-win32-arm64-msvc@11.19.1': + resolution: {integrity: sha512-nJ4AsUVZrVKwnU/QRdzPCCrO0TrabBqgJ8pJhXITdZGYOV28TIYystV1VFLbQ7DtAcaBHpocT5/ZJnF78YJPtQ==} cpu: [arm64] os: [win32] - '@oxc-resolver/binding-win32-ia32-msvc@11.17.1': - resolution: {integrity: sha512-VTzVtfnCCsU/6GgvursWoyZrhe3Gj/RyXzDWmh4/U1Y3IW0u1FZbp+hCIlBL16pRPbDc5YvXVtCOnA41QOrOoQ==} + '@oxc-resolver/binding-win32-ia32-msvc@11.19.1': + resolution: {integrity: sha512-EW+ND5q2Tl+a3pH81l1QbfgbF3HmqgwLfDfVithRFheac8OTcnbXt/JxqD2GbDkb7xYEqy1zNaVFRr3oeG8npA==} cpu: [ia32] os: [win32] - '@oxc-resolver/binding-win32-x64-msvc@11.17.1': - resolution: {integrity: sha512-jRPVU+6/12baj87q2+UGRh30FBVBzqKdJ7rP/mSqiL1kpNQB9yZ1j0+m3sru1m+C8hiFK7lBFwjUtYUBI7+UpQ==} + '@oxc-resolver/binding-win32-x64-msvc@11.19.1': + resolution: {integrity: sha512-6hIU3RQu45B+VNTY4Ru8ppFwjVS/S5qwYyGhBotmjxfEKk41I2DlGtRfGJndZ5+6lneE2pwloqunlOyZuX/XAw==} cpu: [x64] os: [win32] @@ -4986,10 +4827,6 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@pkgr/core@0.2.9': - resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@pnpm/cli-meta@6.0.1': resolution: {integrity: sha512-r1mAyn8wCD5Ow89sF/5IfdwaXyzWI0bI2SVHA8/dR/+ykylCA7L05PKkvV6LSEQ28eKEawNq/0OwnxRSjVx9BQ==} engines: {node: '>=18.12'} @@ -5020,10 +4857,6 @@ packages: resolution: {integrity: sha512-2hf0s4pVrVEH8RvdJJ7YRKjQdiG8m0iAT26TTqXnCbK30kKwJW69VLmP5tED5zstmDRXcOeH5eRcrpkdwczQ9g==} engines: {node: '>=18.12'} - '@pnpm/constants@7.1.1': - resolution: {integrity: sha512-31pZqMtjwV+Vaq7MaPrT1EoDFSYwye3dp6BiHIGRJmVThCQwySRKM7hCvqqI94epNkqFAAYoWrNynWoRYosGdw==} - engines: {node: '>=16.14'} - '@pnpm/constants@8.0.0': resolution: {integrity: sha512-yQosGUvYPpAjb1jOFcdbwekRjZRVxN6C0hHzfRCZrMKbxGjt/E0g0RcFlEDNVZ95tm4oMMcr7nEPa7H7LX3emw==} engines: {node: '>=18.12'} @@ -5056,10 +4889,6 @@ packages: resolution: {integrity: sha512-GjH0TPjbVNrPnl/BAGoFuBLJ2sFfXNKbS33lll/Ehe9yw0fyc8Kdw7kO9if37yQqn6vaa4dAHKkPllum7f/IPQ==} engines: {node: '>=18.12'} - '@pnpm/error@5.0.3': - resolution: {integrity: sha512-ONJU5cUeoeJSy50qOYsMZQHTA/9QKmGgh1ATfEpCLgtbdwqUiwD9MxHNeXUYYI/pocBCz6r1ZCFqiQvO+8SUKA==} - engines: {node: '>=16.14'} - '@pnpm/error@6.0.1': resolution: {integrity: sha512-7yjO0RgmWYb4OKgcWC33yD4Z2CxE7Tm7vXX1SmS7GDifDT/bgZZhHeS2xq/+W6y9yhwIrRSA+7AlQL1NM2wIvw==} engines: {node: '>=18.12'} @@ -5076,10 +4905,6 @@ packages: resolution: {integrity: sha512-5dGA5kZEPplKpbN8JthaOLTkx78ZGZfxB0HtbIyfSezls6Q37T3QxggS6V/ziRs0ZI3ajPhpHsv+t4vwSBZ8WQ==} engines: {node: '>=18.12'} - '@pnpm/find-workspace-dir@6.0.3': - resolution: {integrity: sha512-0iJnNkS4T8lJE4ldOhRERgER1o59iHA1nMlvpUI5lxNC9SUruH6peRUOlP4/rNcDg+UQ9u0rt5loYOnWKCojtw==} - engines: {node: '>=16.14'} - '@pnpm/find-workspace-dir@7.0.3': resolution: {integrity: sha512-eGjkyHSufkHyZ66WpygWnslcRePB0U1lJg1dF3rgWqTChpregYoDyNGDzK7l9Gk+CHVgGZZS5aWp7uKKVmAAEg==} engines: {node: '>=18.12'} @@ -5402,220 +5227,220 @@ packages: resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} engines: {node: '>=18'} - '@smithy/abort-controller@4.2.8': - resolution: {integrity: sha512-peuVfkYHAmS5ybKxWcfraK7WBBP0J+rkfUcbHJJKQ4ir3UAUNQI+Y4Vt/PqSzGqgloJ5O1dk7+WzNL8wcCSXbw==} + '@smithy/abort-controller@4.2.11': + resolution: {integrity: sha512-Hj4WoYWMJnSpM6/kchsm4bUNTL9XiSyhvoMb2KIq4VJzyDt7JpGHUZHkVNPZVC7YE1tf8tPeVauxpFBKGW4/KQ==} engines: {node: '>=18.0.0'} - '@smithy/chunked-blob-reader-native@4.2.1': - resolution: {integrity: sha512-lX9Ay+6LisTfpLid2zZtIhSEjHMZoAR5hHCR4H7tBz/Zkfr5ea8RcQ7Tk4mi0P76p4cN+Btz16Ffno7YHpKXnQ==} + '@smithy/chunked-blob-reader-native@4.2.3': + resolution: {integrity: sha512-jA5k5Udn7Y5717L86h4EIv06wIr3xn8GM1qHRi/Nf31annXcXHJjBKvgztnbn2TxH3xWrPBfgwHsOwZf0UmQWw==} engines: {node: '>=18.0.0'} - '@smithy/chunked-blob-reader@5.2.0': - resolution: {integrity: sha512-WmU0TnhEAJLWvfSeMxBNe5xtbselEO8+4wG0NtZeL8oR21WgH1xiO37El+/Y+H/Ie4SCwBy3MxYWmOYaGgZueA==} + '@smithy/chunked-blob-reader@5.2.2': + resolution: {integrity: sha512-St+kVicSyayWQca+I1rGitaOEH6uKgE8IUWoYnnEX26SWdWQcL6LvMSD19Lg+vYHKdT9B2Zuu7rd3i6Wnyb/iw==} engines: {node: '>=18.0.0'} - '@smithy/config-resolver@4.4.6': - resolution: {integrity: sha512-qJpzYC64kaj3S0fueiu3kXm8xPrR3PcXDPEgnaNMRn0EjNSZFoFjvbUp0YUDsRhN1CB90EnHJtbxWKevnH99UQ==} + '@smithy/config-resolver@4.4.10': + resolution: {integrity: sha512-IRTkd6ps0ru+lTWnfnsbXzW80A8Od8p3pYiZnW98K2Hb20rqfsX7VTlfUwhrcOeSSy68Gn9WBofwPuw3e5CCsg==} engines: {node: '>=18.0.0'} - '@smithy/core@3.23.0': - resolution: {integrity: sha512-Yq4UPVoQICM9zHnByLmG8632t2M0+yap4T7ANVw482J0W7HW0pOuxwVmeOwzJqX2Q89fkXz0Vybz55Wj2Xzrsg==} + '@smithy/core@3.23.8': + resolution: {integrity: sha512-f7uPeBi7ehmLT4YF2u9j3qx6lSnurG1DLXOsTtJrIRNDF7VXio4BGHQ+SQteN/BrUVudbkuL4v7oOsRCzq4BqA==} engines: {node: '>=18.0.0'} - '@smithy/credential-provider-imds@4.2.8': - resolution: {integrity: sha512-FNT0xHS1c/CPN8upqbMFP83+ul5YgdisfCfkZ86Jh2NSmnqw/AJ6x5pEogVCTVvSm7j9MopRU89bmDelxuDMYw==} + '@smithy/credential-provider-imds@4.2.11': + resolution: {integrity: sha512-lBXrS6ku0kTj3xLmsJW0WwqWbGQ6ueooYyp/1L9lkyT0M02C+DWwYwc5aTyXFbRaK38ojALxNixg+LxKSHZc0g==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-codec@4.2.8': - resolution: {integrity: sha512-jS/O5Q14UsufqoGhov7dHLOPCzkYJl9QDzusI2Psh4wyYx/izhzvX9P4D69aTxcdfVhEPhjK+wYyn/PzLjKbbw==} + '@smithy/eventstream-codec@4.2.11': + resolution: {integrity: sha512-Sf39Ml0iVX+ba/bgMPxaXWAAFmHqYLTmbjAPfLPLY8CrYkRDEqZdUsKC1OwVMCdJXfAt0v4j49GIJ8DoSYAe6w==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-serde-browser@4.2.8': - resolution: {integrity: sha512-MTfQT/CRQz5g24ayXdjg53V0mhucZth4PESoA5IhvaWVDTOQLfo8qI9vzqHcPsdd2v6sqfTYqF5L/l+pea5Uyw==} + '@smithy/eventstream-serde-browser@4.2.11': + resolution: {integrity: sha512-3rEpo3G6f/nRS7fQDsZmxw/ius6rnlIpz4UX6FlALEzz8JoSxFmdBt0SZnthis+km7sQo6q5/3e+UJcuQivoXA==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-serde-config-resolver@4.3.8': - resolution: {integrity: sha512-ah12+luBiDGzBruhu3efNy1IlbwSEdNiw8fOZksoKoWW1ZHvO/04MQsdnws/9Aj+5b0YXSSN2JXKy/ClIsW8MQ==} + '@smithy/eventstream-serde-config-resolver@4.3.11': + resolution: {integrity: sha512-XeNIA8tcP/GDWnnKkO7qEm/bg0B/bP9lvIXZBXcGZwZ+VYM8h8k9wuDvUODtdQ2Wcp2RcBkPTCSMmaniVHrMlA==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-serde-node@4.2.8': - resolution: {integrity: sha512-cYpCpp29z6EJHa5T9WL0KAlq3SOKUQkcgSoeRfRVwjGgSFl7Uh32eYGt7IDYCX20skiEdRffyDpvF2efEZPC0A==} + '@smithy/eventstream-serde-node@4.2.11': + resolution: {integrity: sha512-fzbCh18rscBDTQSCrsp1fGcclLNF//nJyhjldsEl/5wCYmgpHblv5JSppQAyQI24lClsFT0wV06N1Porn0IsEw==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-serde-universal@4.2.8': - resolution: {integrity: sha512-iJ6YNJd0bntJYnX6s52NC4WFYcZeKrPUr1Kmmr5AwZcwCSzVpS7oavAmxMR7pMq7V+D1G4s9F5NJK0xwOsKAlQ==} + '@smithy/eventstream-serde-universal@4.2.11': + resolution: {integrity: sha512-MJ7HcI+jEkqoWT5vp+uoVaAjBrmxBtKhZTeynDRG/seEjJfqyg3SiqMMqyPnAMzmIfLaeJ/uiuSDP/l9AnMy/Q==} engines: {node: '>=18.0.0'} - '@smithy/fetch-http-handler@5.3.9': - resolution: {integrity: sha512-I4UhmcTYXBrct03rwzQX1Y/iqQlzVQaPxWjCjula++5EmWq9YGBrx6bbGqluGc1f0XEfhSkiY4jhLgbsJUMKRA==} + '@smithy/fetch-http-handler@5.3.13': + resolution: {integrity: sha512-U2Hcfl2s3XaYjikN9cT4mPu8ybDbImV3baXR0PkVlC0TTx808bRP3FaPGAzPtB8OByI+JqJ1kyS+7GEgae7+qQ==} engines: {node: '>=18.0.0'} - '@smithy/hash-blob-browser@4.2.9': - resolution: {integrity: sha512-m80d/iicI7DlBDxyQP6Th7BW/ejDGiF0bgI754+tiwK0lgMkcaIBgvwwVc7OFbY4eUzpGtnig52MhPAEJ7iNYg==} + '@smithy/hash-blob-browser@4.2.12': + resolution: {integrity: sha512-1wQE33DsxkM/waftAhCH9VtJbUGyt1PJ9YRDpOu+q9FUi73LLFUZ2fD8A61g2mT1UY9k7b99+V1xZ41Rz4SHRQ==} engines: {node: '>=18.0.0'} - '@smithy/hash-node@4.2.8': - resolution: {integrity: sha512-7ZIlPbmaDGxVoxErDZnuFG18WekhbA/g2/i97wGj+wUBeS6pcUeAym8u4BXh/75RXWhgIJhyC11hBzig6MljwA==} + '@smithy/hash-node@4.2.11': + resolution: {integrity: sha512-T+p1pNynRkydpdL015ruIoyPSRw9e/SQOWmSAMmmprfswMrd5Ow5igOWNVlvyVFZlxXqGmyH3NQwfwy8r5Jx0A==} engines: {node: '>=18.0.0'} - '@smithy/hash-stream-node@4.2.8': - resolution: {integrity: sha512-v0FLTXgHrTeheYZFGhR+ehX5qUm4IQsjAiL9qehad2cyjMWcN2QG6/4mSwbSgEQzI7jwfoXj7z4fxZUx/Mhj2w==} + '@smithy/hash-stream-node@4.2.11': + resolution: {integrity: sha512-hQsTjwPCRY8w9GK07w1RqJi3e+myh0UaOWBBhZ1UMSDgofH/Q1fEYzU1teaX6HkpX/eWDdm7tAGR0jBPlz9QEQ==} engines: {node: '>=18.0.0'} - '@smithy/invalid-dependency@4.2.8': - resolution: {integrity: sha512-N9iozRybwAQ2dn9Fot9kI6/w9vos2oTXLhtK7ovGqwZjlOcxu6XhPlpLpC+INsxktqHinn5gS2DXDjDF2kG5sQ==} + '@smithy/invalid-dependency@4.2.11': + resolution: {integrity: sha512-cGNMrgykRmddrNhYy1yBdrp5GwIgEkniS7k9O1VLB38yxQtlvrxpZtUVvo6T4cKpeZsriukBuuxfJcdZQc/f/g==} engines: {node: '>=18.0.0'} '@smithy/is-array-buffer@2.2.0': resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} engines: {node: '>=14.0.0'} - '@smithy/is-array-buffer@4.2.0': - resolution: {integrity: sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==} + '@smithy/is-array-buffer@4.2.2': + resolution: {integrity: sha512-n6rQ4N8Jj4YTQO3YFrlgZuwKodf4zUFs7EJIWH86pSCWBaAtAGBFfCM7Wx6D2bBJ2xqFNxGBSrUWswT3M0VJow==} engines: {node: '>=18.0.0'} - '@smithy/md5-js@4.2.8': - resolution: {integrity: sha512-oGMaLj4tVZzLi3itBa9TCswgMBr7k9b+qKYowQ6x1rTyTuO1IU2YHdHUa+891OsOH+wCsH7aTPRsTJO3RMQmjQ==} + '@smithy/md5-js@4.2.11': + resolution: {integrity: sha512-350X4kGIrty0Snx2OWv7rPM6p6vM7RzryvFs6B/56Cux3w3sChOb3bymo5oidXJlPcP9fIRxGUCk7GqpiSOtng==} engines: {node: '>=18.0.0'} - '@smithy/middleware-content-length@4.2.8': - resolution: {integrity: sha512-RO0jeoaYAB1qBRhfVyq0pMgBoUK34YEJxVxyjOWYZiOKOq2yMZ4MnVXMZCUDenpozHue207+9P5ilTV1zeda0A==} + '@smithy/middleware-content-length@4.2.11': + resolution: {integrity: sha512-UvIfKYAKhCzr4p6jFevPlKhQwyQwlJ6IeKLDhmV1PlYfcW3RL4ROjNEDtSik4NYMi9kDkH7eSwyTP3vNJ/u/Dw==} engines: {node: '>=18.0.0'} - '@smithy/middleware-endpoint@4.4.14': - resolution: {integrity: sha512-FUFNE5KVeaY6U/GL0nzAAHkaCHzXLZcY1EhtQnsAqhD8Du13oPKtMB9/0WK4/LK6a/T5OZ24wPoSShff5iI6Ag==} + '@smithy/middleware-endpoint@4.4.22': + resolution: {integrity: sha512-sc81w1o4Jy+/MAQlY3sQ8C7CmSpcvIi3TAzXblUv2hjG11BBSJi/Cw8vDx5BxMxapuH2I+Gc+45vWsgU07WZRQ==} engines: {node: '>=18.0.0'} - '@smithy/middleware-retry@4.4.31': - resolution: {integrity: sha512-RXBzLpMkIrxBPe4C8OmEOHvS8aH9RUuCOH++Acb5jZDEblxDjyg6un72X9IcbrGTJoiUwmI7hLypNfuDACypbg==} + '@smithy/middleware-retry@4.4.39': + resolution: {integrity: sha512-MCVCxaCzuZgiHtHGV2Ke44nh6t4+8/tO+rTYOzrr2+G4nMLU/qbzNCWKBX54lyEaVcGQrfOJiG2f8imtiw+nIQ==} engines: {node: '>=18.0.0'} - '@smithy/middleware-serde@4.2.9': - resolution: {integrity: sha512-eMNiej0u/snzDvlqRGSN3Vl0ESn3838+nKyVfF2FKNXFbi4SERYT6PR392D39iczngbqqGG0Jl1DlCnp7tBbXQ==} + '@smithy/middleware-serde@4.2.12': + resolution: {integrity: sha512-W9g1bOLui7Xn5FABRVS0o3rXL0gfN37d/8I/W7i0N7oxjx9QecUmXEMSUMADTODwdtka9cN43t5BI2CodLJpng==} engines: {node: '>=18.0.0'} - '@smithy/middleware-stack@4.2.8': - resolution: {integrity: sha512-w6LCfOviTYQjBctOKSwy6A8FIkQy7ICvglrZFl6Bw4FmcQ1Z420fUtIhxaUZZshRe0VCq4kvDiPiXrPZAe8oRA==} + '@smithy/middleware-stack@4.2.11': + resolution: {integrity: sha512-s+eenEPW6RgliDk2IhjD2hWOxIx1NKrOHxEwNUaUXxYBxIyCcDfNULZ2Mu15E3kwcJWBedTET/kEASPV1A1Akg==} engines: {node: '>=18.0.0'} - '@smithy/node-config-provider@4.3.8': - resolution: {integrity: sha512-aFP1ai4lrbVlWjfpAfRSL8KFcnJQYfTl5QxLJXY32vghJrDuFyPZ6LtUL+JEGYiFRG1PfPLHLoxj107ulncLIg==} + '@smithy/node-config-provider@4.3.11': + resolution: {integrity: sha512-xD17eE7kaLgBBGf5CZQ58hh2YmwK1Z0O8YhffwB/De2jsL0U3JklmhVYJ9Uf37OtUDLF2gsW40Xwwag9U869Gg==} engines: {node: '>=18.0.0'} - '@smithy/node-http-handler@4.4.10': - resolution: {integrity: sha512-u4YeUwOWRZaHbWaebvrs3UhwQwj+2VNmcVCwXcYTvPIuVyM7Ex1ftAj+fdbG/P4AkBwLq/+SKn+ydOI4ZJE9PA==} + '@smithy/node-http-handler@4.4.14': + resolution: {integrity: sha512-DamSqaU8nuk0xTJDrYnRzZndHwwRnyj/n/+RqGGCcBKB4qrQem0mSDiWdupaNWdwxzyMU91qxDmHOCazfhtO3A==} engines: {node: '>=18.0.0'} - '@smithy/property-provider@4.2.8': - resolution: {integrity: sha512-EtCTbyIveCKeOXDSWSdze3k612yCPq1YbXsbqX3UHhkOSW8zKsM9NOJG5gTIya0vbY2DIaieG8pKo1rITHYL0w==} + '@smithy/property-provider@4.2.11': + resolution: {integrity: sha512-14T1V64o6/ndyrnl1ze1ZhyLzIeYNN47oF/QU6P5m82AEtyOkMJTb0gO1dPubYjyyKuPD6OSVMPDKe+zioOnCg==} engines: {node: '>=18.0.0'} - '@smithy/protocol-http@5.3.8': - resolution: {integrity: sha512-QNINVDhxpZ5QnP3aviNHQFlRogQZDfYlCkQT+7tJnErPQbDhysondEjhikuANxgMsZrkGeiAxXy4jguEGsDrWQ==} + '@smithy/protocol-http@5.3.11': + resolution: {integrity: sha512-hI+barOVDJBkNt4y0L2mu3Ugc0w7+BpJ2CZuLwXtSltGAAwCb3IvnalGlbDV/UCS6a9ZuT3+exd1WxNdLb5IlQ==} engines: {node: '>=18.0.0'} - '@smithy/querystring-builder@4.2.8': - resolution: {integrity: sha512-Xr83r31+DrE8CP3MqPgMJl+pQlLLmOfiEUnoyAlGzzJIrEsbKsPy1hqH0qySaQm4oWrCBlUqRt+idEgunKB+iw==} + '@smithy/querystring-builder@4.2.11': + resolution: {integrity: sha512-7spdikrYiljpket6u0up2Ck2mxhy7dZ0+TDd+S53Dg2DHd6wg+YNJrTCHiLdgZmEXZKI7LJZcwL3721ZRDFiqA==} engines: {node: '>=18.0.0'} - '@smithy/querystring-parser@4.2.8': - resolution: {integrity: sha512-vUurovluVy50CUlazOiXkPq40KGvGWSdmusa3130MwrR1UNnNgKAlj58wlOe61XSHRpUfIIh6cE0zZ8mzKaDPA==} + '@smithy/querystring-parser@4.2.11': + resolution: {integrity: sha512-nE3IRNjDltvGcoThD2abTozI1dkSy8aX+a2N1Rs55en5UsdyyIXgGEmevUL3okZFoJC77JgRGe99xYohhsjivQ==} engines: {node: '>=18.0.0'} - '@smithy/service-error-classification@4.2.8': - resolution: {integrity: sha512-mZ5xddodpJhEt3RkCjbmUQuXUOaPNTkbMGR0bcS8FE0bJDLMZlhmpgrvPNCYglVw5rsYTpSnv19womw9WWXKQQ==} + '@smithy/service-error-classification@4.2.11': + resolution: {integrity: sha512-HkMFJZJUhzU3HvND1+Yw/kYWXp4RPDLBWLcK1n+Vqw8xn4y2YiBhdww8IxhkQjP/QlZun5bwm3vcHc8AqIU3zw==} engines: {node: '>=18.0.0'} - '@smithy/shared-ini-file-loader@4.4.3': - resolution: {integrity: sha512-DfQjxXQnzC5UbCUPeC3Ie8u+rIWZTvuDPAGU/BxzrOGhRvgUanaP68kDZA+jaT3ZI+djOf+4dERGlm9mWfFDrg==} + '@smithy/shared-ini-file-loader@4.4.6': + resolution: {integrity: sha512-IB/M5I8G0EeXZTHsAxpx51tMQ5R719F3aq+fjEB6VtNcCHDc0ajFDIGDZw+FW9GxtEkgTduiPpjveJdA/CX7sw==} engines: {node: '>=18.0.0'} - '@smithy/signature-v4@5.3.8': - resolution: {integrity: sha512-6A4vdGj7qKNRF16UIcO8HhHjKW27thsxYci+5r/uVRkdcBEkOEiY8OMPuydLX4QHSrJqGHPJzPRwwVTqbLZJhg==} + '@smithy/signature-v4@5.3.11': + resolution: {integrity: sha512-V1L6N9aKOBAN4wEHLyqjLBnAz13mtILU0SeDrjOaIZEeN6IFa6DxwRt1NNpOdmSpQUfkBj0qeD3m6P77uzMhgQ==} engines: {node: '>=18.0.0'} - '@smithy/smithy-client@4.11.3': - resolution: {integrity: sha512-Q7kY5sDau8OoE6Y9zJoRGgje8P4/UY0WzH8R2ok0PDh+iJ+ZnEKowhjEqYafVcubkbYxQVaqwm3iufktzhprGg==} + '@smithy/smithy-client@4.12.2': + resolution: {integrity: sha512-HezY3UuG0k4T+4xhFKctLXCA5N2oN+Rtv+mmL8Gt7YmsUY2yhmcLyW75qrSzldfj75IsCW/4UhY3s20KcFnZqA==} engines: {node: '>=18.0.0'} - '@smithy/types@4.12.0': - resolution: {integrity: sha512-9YcuJVTOBDjg9LWo23Qp0lTQ3D7fQsQtwle0jVfpbUHy9qBwCEgKuVH4FqFB3VYu0nwdHKiEMA+oXz7oV8X1kw==} + '@smithy/types@4.13.0': + resolution: {integrity: sha512-COuLsZILbbQsdrwKQpkkpyep7lCsByxwj7m0Mg5v66/ZTyenlfBc40/QFQ5chO0YN/PNEH1Bi3fGtfXPnYNeDw==} engines: {node: '>=18.0.0'} - '@smithy/url-parser@4.2.8': - resolution: {integrity: sha512-NQho9U68TGMEU639YkXnVMV3GEFFULmmaWdlu1E9qzyIePOHsoSnagTGSDv1Zi8DCNN6btxOSdgmy5E/hsZwhA==} + '@smithy/url-parser@4.2.11': + resolution: {integrity: sha512-oTAGGHo8ZYc5VZsBREzuf5lf2pAurJQsccMusVZ85wDkX66ojEc/XauiGjzCj50A61ObFTPe6d7Pyt6UBYaing==} engines: {node: '>=18.0.0'} - '@smithy/util-base64@4.3.0': - resolution: {integrity: sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==} + '@smithy/util-base64@4.3.2': + resolution: {integrity: sha512-XRH6b0H/5A3SgblmMa5ErXQ2XKhfbQB+Fm/oyLZ2O2kCUrwgg55bU0RekmzAhuwOjA9qdN5VU2BprOvGGUkOOQ==} engines: {node: '>=18.0.0'} - '@smithy/util-body-length-browser@4.2.0': - resolution: {integrity: sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==} + '@smithy/util-body-length-browser@4.2.2': + resolution: {integrity: sha512-JKCrLNOup3OOgmzeaKQwi4ZCTWlYR5H4Gm1r2uTMVBXoemo1UEghk5vtMi1xSu2ymgKVGW631e2fp9/R610ZjQ==} engines: {node: '>=18.0.0'} - '@smithy/util-body-length-node@4.2.1': - resolution: {integrity: sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==} + '@smithy/util-body-length-node@4.2.3': + resolution: {integrity: sha512-ZkJGvqBzMHVHE7r/hcuCxlTY8pQr1kMtdsVPs7ex4mMU+EAbcXppfo5NmyxMYi2XU49eqaz56j2gsk4dHHPG/g==} engines: {node: '>=18.0.0'} '@smithy/util-buffer-from@2.2.0': resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} engines: {node: '>=14.0.0'} - '@smithy/util-buffer-from@4.2.0': - resolution: {integrity: sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==} + '@smithy/util-buffer-from@4.2.2': + resolution: {integrity: sha512-FDXD7cvUoFWwN6vtQfEta540Y/YBe5JneK3SoZg9bThSoOAC/eGeYEua6RkBgKjGa/sz6Y+DuBZj3+YEY21y4Q==} engines: {node: '>=18.0.0'} - '@smithy/util-config-provider@4.2.0': - resolution: {integrity: sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==} + '@smithy/util-config-provider@4.2.2': + resolution: {integrity: sha512-dWU03V3XUprJwaUIFVv4iOnS1FC9HnMHDfUrlNDSh4315v0cWyaIErP8KiqGVbf5z+JupoVpNM7ZB3jFiTejvQ==} engines: {node: '>=18.0.0'} - '@smithy/util-defaults-mode-browser@4.3.30': - resolution: {integrity: sha512-cMni0uVU27zxOiU8TuC8pQLC1pYeZ/xEMxvchSK/ILwleRd1ugobOcIRr5vXtcRqKd4aBLWlpeBoDPJJ91LQng==} + '@smithy/util-defaults-mode-browser@4.3.38': + resolution: {integrity: sha512-c8P1mFLNxcsdAMabB8/VUQUbWzFmgujWi4bAXSggcqLYPc8V4U5abqFqOyn+dK4YT+q8UyCVkTO8807t4t2syA==} engines: {node: '>=18.0.0'} - '@smithy/util-defaults-mode-node@4.2.33': - resolution: {integrity: sha512-LEb2aq5F4oZUSzWBG7S53d4UytZSkOEJPXcBq/xbG2/TmK9EW5naUZ8lKu1BEyWMzdHIzEVN16M3k8oxDq+DJA==} + '@smithy/util-defaults-mode-node@4.2.41': + resolution: {integrity: sha512-/UG+9MT3UZAR0fLzOtMJMfWGcjjHvgggq924x/CRy8vRbL+yFf3Z6vETlvq8vDH92+31P/1gSOFoo7303wN8WQ==} engines: {node: '>=18.0.0'} - '@smithy/util-endpoints@3.2.8': - resolution: {integrity: sha512-8JaVTn3pBDkhZgHQ8R0epwWt+BqPSLCjdjXXusK1onwJlRuN69fbvSK66aIKKO7SwVFM6x2J2ox5X8pOaWcUEw==} + '@smithy/util-endpoints@3.3.2': + resolution: {integrity: sha512-+4HFLpE5u29AbFlTdlKIT7jfOzZ8PDYZKTb3e+AgLz986OYwqTourQ5H+jg79/66DB69Un1+qKecLnkZdAsYcA==} engines: {node: '>=18.0.0'} - '@smithy/util-hex-encoding@4.2.0': - resolution: {integrity: sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==} + '@smithy/util-hex-encoding@4.2.2': + resolution: {integrity: sha512-Qcz3W5vuHK4sLQdyT93k/rfrUwdJ8/HZ+nMUOyGdpeGA1Wxt65zYwi3oEl9kOM+RswvYq90fzkNDahPS8K0OIg==} engines: {node: '>=18.0.0'} - '@smithy/util-middleware@4.2.8': - resolution: {integrity: sha512-PMqfeJxLcNPMDgvPbbLl/2Vpin+luxqTGPpW3NAQVLbRrFRzTa4rNAASYeIGjRV9Ytuhzny39SpyU04EQreF+A==} + '@smithy/util-middleware@4.2.11': + resolution: {integrity: sha512-r3dtF9F+TpSZUxpOVVtPfk09Rlo4lT6ORBqEvX3IBT6SkQAdDSVKR5GcfmZbtl7WKhKnmb3wbDTQ6ibR2XHClw==} engines: {node: '>=18.0.0'} - '@smithy/util-retry@4.2.8': - resolution: {integrity: sha512-CfJqwvoRY0kTGe5AkQokpURNCT1u/MkRzMTASWMPPo2hNSnKtF1D45dQl3DE2LKLr4m+PW9mCeBMJr5mCAVThg==} + '@smithy/util-retry@4.2.11': + resolution: {integrity: sha512-XSZULmL5x6aCTTii59wJqKsY1l3eMIAomRAccW7Tzh9r8s7T/7rdo03oektuH5jeYRlJMPcNP92EuRDvk9aXbw==} engines: {node: '>=18.0.0'} - '@smithy/util-stream@4.5.12': - resolution: {integrity: sha512-D8tgkrmhAX/UNeCZbqbEO3uqyghUnEmmoO9YEvRuwxjlkKKUE7FOgCJnqpTlQPe9MApdWPky58mNQQHbnCzoNg==} + '@smithy/util-stream@4.5.17': + resolution: {integrity: sha512-793BYZ4h2JAQkNHcEnyFxDTcZbm9bVybD0UV/LEWmZ5bkTms7JqjfrLMi2Qy0E5WFcCzLwCAPgcvcvxoeALbAQ==} engines: {node: '>=18.0.0'} - '@smithy/util-uri-escape@4.2.0': - resolution: {integrity: sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==} + '@smithy/util-uri-escape@4.2.2': + resolution: {integrity: sha512-2kAStBlvq+lTXHyAZYfJRb/DfS3rsinLiwb+69SstC9Vb0s9vNWkRwpnj918Pfi85mzi42sOqdV72OLxWAISnw==} engines: {node: '>=18.0.0'} '@smithy/util-utf8@2.3.0': resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} engines: {node: '>=14.0.0'} - '@smithy/util-utf8@4.2.0': - resolution: {integrity: sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==} + '@smithy/util-utf8@4.2.2': + resolution: {integrity: sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw==} engines: {node: '>=18.0.0'} - '@smithy/util-waiter@4.2.8': - resolution: {integrity: sha512-n+lahlMWk+aejGuax7DPWtqav8HYnWxQwR+LCG2BgCUmaGcTe9qZCFsmw8TMg9iG75HOwhrJCX9TCJRLH+Yzqg==} + '@smithy/util-waiter@4.2.11': + resolution: {integrity: sha512-x7Rh2azQPs3XxbvCzcttRErKKvLnbZfqRf/gOjw2pb+ZscX88e5UkRPCB67bVnsFHxayvMvmePfKTqsRb+is1A==} engines: {node: '>=18.0.0'} - '@smithy/uuid@1.1.0': - resolution: {integrity: sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==} + '@smithy/uuid@1.1.2': + resolution: {integrity: sha512-O/IEdcCUKkubz60tFbGA7ceITTAJsty+lBjNoorP4Z6XRqaFb/OjQjZODophEcuq68nKm6/0r+6/lLQ+XVpk8g==} engines: {node: '>=18.0.0'} '@socket.io/component-emitter@3.1.2': @@ -5637,72 +5462,72 @@ packages: '@swc-node/sourcemap-support@0.6.1': resolution: {integrity: sha512-ovltDVH5QpdHXZkW138vG4+dgcNsxfwxHVoV6BtmTbz2KKl1A8ZSlbdtxzzfNjCjbpayda8Us9eMtcHobm38dA==} - '@swc/core-darwin-arm64@1.15.11': - resolution: {integrity: sha512-QoIupRWVH8AF1TgxYyeA5nS18dtqMuxNwchjBIwJo3RdwLEFiJq6onOx9JAxHtuPwUkIVuU2Xbp+jCJ7Vzmgtg==} + '@swc/core-darwin-arm64@1.15.18': + resolution: {integrity: sha512-+mIv7uBuSaywN3C9LNuWaX1jJJ3SKfiJuE6Lr3bd+/1Iv8oMU7oLBjYMluX1UrEPzwN2qCdY6Io0yVicABoCwQ==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] - '@swc/core-darwin-x64@1.15.11': - resolution: {integrity: sha512-S52Gu1QtPSfBYDiejlcfp9GlN+NjTZBRRNsz8PNwBgSE626/FUf2PcllVUix7jqkoMC+t0rS8t+2/aSWlMuQtA==} + '@swc/core-darwin-x64@1.15.18': + resolution: {integrity: sha512-wZle0eaQhnzxWX5V/2kEOI6Z9vl/lTFEC6V4EWcn+5pDjhemCpQv9e/TDJ0GIoiClX8EDWRvuZwh+Z3dhL1NAg==} engines: {node: '>=10'} cpu: [x64] os: [darwin] - '@swc/core-linux-arm-gnueabihf@1.15.11': - resolution: {integrity: sha512-lXJs8oXo6Z4yCpimpQ8vPeCjkgoHu5NoMvmJZ8qxDyU99KVdg6KwU9H79vzrmB+HfH+dCZ7JGMqMF//f8Cfvdg==} + '@swc/core-linux-arm-gnueabihf@1.15.18': + resolution: {integrity: sha512-ao61HGXVqrJFHAcPtF4/DegmwEkVCo4HApnotLU8ognfmU8x589z7+tcf3hU+qBiU1WOXV5fQX6W9Nzs6hjxDw==} engines: {node: '>=10'} cpu: [arm] os: [linux] - '@swc/core-linux-arm64-gnu@1.15.11': - resolution: {integrity: sha512-chRsz1K52/vj8Mfq/QOugVphlKPWlMh10V99qfH41hbGvwAU6xSPd681upO4bKiOr9+mRIZZW+EfJqY42ZzRyA==} + '@swc/core-linux-arm64-gnu@1.15.18': + resolution: {integrity: sha512-3xnctOBLIq3kj8PxOCgPrGjBLP/kNOddr6f5gukYt/1IZxsITQaU9TDyjeX6jG+FiCIHjCuWuffsyQDL5Ew1bg==} engines: {node: '>=10'} cpu: [arm64] os: [linux] libc: [glibc] - '@swc/core-linux-arm64-musl@1.15.11': - resolution: {integrity: sha512-PYftgsTaGnfDK4m6/dty9ryK1FbLk+LosDJ/RJR2nkXGc8rd+WenXIlvHjWULiBVnS1RsjHHOXmTS4nDhe0v0w==} + '@swc/core-linux-arm64-musl@1.15.18': + resolution: {integrity: sha512-0a+Lix+FSSHBSBOA0XznCcHo5/1nA6oLLjcnocvzXeqtdjnPb+SvchItHI+lfeiuj1sClYPDvPMLSLyXFaiIKw==} engines: {node: '>=10'} cpu: [arm64] os: [linux] libc: [musl] - '@swc/core-linux-x64-gnu@1.15.11': - resolution: {integrity: sha512-DKtnJKIHiZdARyTKiX7zdRjiDS1KihkQWatQiCHMv+zc2sfwb4Glrodx2VLOX4rsa92NLR0Sw8WLcPEMFY1szQ==} + '@swc/core-linux-x64-gnu@1.15.18': + resolution: {integrity: sha512-wG9J8vReUlpaHz4KOD/5UE1AUgirimU4UFT9oZmupUDEofxJKYb1mTA/DrMj0s78bkBiNI+7Fo2EgPuvOJfuAA==} engines: {node: '>=10'} cpu: [x64] os: [linux] libc: [glibc] - '@swc/core-linux-x64-musl@1.15.11': - resolution: {integrity: sha512-mUjjntHj4+8WBaiDe5UwRNHuEzLjIWBTSGTw0JT9+C9/Yyuh4KQqlcEQ3ro6GkHmBGXBFpGIj/o5VMyRWfVfWw==} + '@swc/core-linux-x64-musl@1.15.18': + resolution: {integrity: sha512-4nwbVvCphKzicwNWRmvD5iBaZj8JYsRGa4xOxJmOyHlMDpsvvJ2OR2cODlvWyGFH6BYL1MfIAK3qph3hp0Az6g==} engines: {node: '>=10'} cpu: [x64] os: [linux] libc: [musl] - '@swc/core-win32-arm64-msvc@1.15.11': - resolution: {integrity: sha512-ZkNNG5zL49YpaFzfl6fskNOSxtcZ5uOYmWBkY4wVAvgbSAQzLRVBp+xArGWh2oXlY/WgL99zQSGTv7RI5E6nzA==} + '@swc/core-win32-arm64-msvc@1.15.18': + resolution: {integrity: sha512-zk0RYO+LjiBCat2RTMHzAWaMky0cra9loH4oRrLKLLNuL+jarxKLFDA8xTZWEkCPLjUTwlRN7d28eDLLMgtUcQ==} engines: {node: '>=10'} cpu: [arm64] os: [win32] - '@swc/core-win32-ia32-msvc@1.15.11': - resolution: {integrity: sha512-6XnzORkZCQzvTQ6cPrU7iaT9+i145oLwnin8JrfsLG41wl26+5cNQ2XV3zcbrnFEV6esjOceom9YO1w9mGJByw==} + '@swc/core-win32-ia32-msvc@1.15.18': + resolution: {integrity: sha512-yVuTrZ0RccD5+PEkpcLOBAuPbYBXS6rslENvIXfvJGXSdX5QGi1ehC4BjAMl5FkKLiam4kJECUI0l7Hq7T1vwg==} engines: {node: '>=10'} cpu: [ia32] os: [win32] - '@swc/core-win32-x64-msvc@1.15.11': - resolution: {integrity: sha512-IQ2n6af7XKLL6P1gIeZACskSxK8jWtoKpJWLZmdXTDj1MGzktUy4i+FvpdtxFmJWNavRWH1VmTr6kAubRDHeKw==} + '@swc/core-win32-x64-msvc@1.15.18': + resolution: {integrity: sha512-7NRmE4hmUQNCbYU3Hn9Tz57mK9Qq4c97ZS+YlamlK6qG9Fb5g/BB3gPDe0iLlJkns/sYv2VWSkm8c3NmbEGjbg==} engines: {node: '>=10'} cpu: [x64] os: [win32] - '@swc/core@1.15.11': - resolution: {integrity: sha512-iLmLTodbYxU39HhMPaMUooPwO/zqJWvsqkrXv1ZI38rMb048p6N7qtAtTp37sw9NzSrvH6oli8EdDygo09IZ/w==} + '@swc/core@1.15.18': + resolution: {integrity: sha512-z87aF9GphWp//fnkRsqvtY+inMVPgYW3zSlXH1kJFvRT5H/wiAn+G32qW5l3oEk63KSF1x3Ov0BfHCObAmT8RA==} engines: {node: '>=10'} peerDependencies: '@swc/helpers': '>=0.5.17' @@ -5822,15 +5647,9 @@ packages: '@types/fs-extra@5.1.0': resolution: {integrity: sha512-AInn5+UBFIK9FK5xc9yP5e3TQSPNNgjHByqYcj9g5elVBnDQcQL7PlO1CIRy2gWlbwK7UPYqi7vRvFA44dCmYQ==} - '@types/fs-extra@8.1.5': - resolution: {integrity: sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==} - '@types/fs-extra@9.0.13': resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==} - '@types/glob@7.2.0': - resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} - '@types/glob@9.0.0': resolution: {integrity: sha512-00UxlRaIUvYm4R4W9WYkN8/J+kV8fmOQ7okeH6YFtGWFMt3odD45tpG5yA5wnL7HE6lLgjaTW5n14ju2hl2NNA==} deprecated: This is a stub types definition. glob provides its own type definitions, so you do not need this installed. @@ -5856,24 +5675,20 @@ packages: '@types/minimatch@5.1.2': resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} - '@types/minimatch@6.0.0': - resolution: {integrity: sha512-zmPitbQ8+6zNutpwgcQuLcsEpn/Cj54Kbn7L5pX0Os5kdWplB7xPgEh/g+SWOB/qmows2gpuCaPyduq8ZZRnxA==} - deprecated: This is a stub types definition. minimatch provides its own type definitions, so you do not need this installed. - '@types/minimist@1.2.5': resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} - '@types/node@20.19.33': - resolution: {integrity: sha512-Rs1bVAIdBs5gbTIKza/tgpMuG1k3U/UMJLWecIMxNdJFDMzcM5LOiLVRYh3PilWEYDIeUDv7bpiHPLPsbydGcw==} + '@types/node@20.19.37': + resolution: {integrity: sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==} - '@types/node@22.19.11': - resolution: {integrity: sha512-BH7YwL6rA93ReqeQS1c4bsPpcfOmJasG+Fkr6Y59q83f9M1WcBRHR2vM+P9eOisYRcN3ujQoiZY8uk5W+1WL8w==} + '@types/node@22.19.15': + resolution: {integrity: sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - '@types/qs@6.14.0': - resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} + '@types/qs@6.15.0': + resolution: {integrity: sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow==} '@types/qunit@2.19.13': resolution: {integrity: sha512-N4xp3v4s7f0jb2Oij6+6xw5QhH7/IgHCoGIFLCWtbEWoPkGYp8Te4mIwIP21qaurr6ed5JiPMiy2/ZoiGPkLIw==} @@ -5917,102 +5732,65 @@ packages: '@types/yargs@17.0.35': resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} - '@typescript-eslint/eslint-plugin@8.55.0': - resolution: {integrity: sha512-1y/MVSz0NglV1ijHC8OT49mPJ4qhPYjiK08YUQVbIOyu+5k862LKUHFkpKHWu//zmr7hDR2rhwUm6gnCGNmGBQ==} + '@typescript-eslint/eslint-plugin@8.56.1': + resolution: {integrity: sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.55.0 - eslint: ^8.57.0 || ^9.0.0 + '@typescript-eslint/parser': ^8.56.1 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.55.0': - resolution: {integrity: sha512-4z2nCSBfVIMnbuu8uinj+f0o4qOeggYJLbjpPHka3KH1om7e+H9yLKTYgksTaHcGco+NClhhY2vyO3HsMH1RGw==} + '@typescript-eslint/parser@8.56.1': + resolution: {integrity: sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.55.0': - resolution: {integrity: sha512-zRcVVPFUYWa3kNnjaZGXSu3xkKV1zXy8M4nO/pElzQhFweb7PPtluDLQtKArEOGmjXoRjnUZ29NjOiF0eCDkcQ==} + '@typescript-eslint/project-service@8.56.1': + resolution: {integrity: sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.55.0': - resolution: {integrity: sha512-fVu5Omrd3jeqeQLiB9f1YsuK/iHFOwb04bCtY4BSCLgjNbOD33ZdV6KyEqplHr+IlpgT0QTZ/iJ+wT7hvTx49Q==} + '@typescript-eslint/scope-manager@8.56.1': + resolution: {integrity: sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.55.0': - resolution: {integrity: sha512-1R9cXqY7RQd7WuqSN47PK9EDpgFUK3VqdmbYrvWJZYDd0cavROGn+74ktWBlmJ13NXUQKlZ/iAEQHI/V0kKe0Q==} + '@typescript-eslint/tsconfig-utils@8.56.1': + resolution: {integrity: sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.55.0': - resolution: {integrity: sha512-x1iH2unH4qAt6I37I2CGlsNs+B9WGxurP2uyZLRz6UJoZWDBx9cJL1xVN/FiOmHEONEg6RIufdvyT0TEYIgC5g==} + '@typescript-eslint/type-utils@8.56.1': + resolution: {integrity: sha512-yB/7dxi7MgTtGhZdaHCemf7PuwrHMenHjmzgUW1aJpO+bBU43OycnM3Wn+DdvDO/8zzA9HlhaJ0AUGuvri4oGg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.55.0': - resolution: {integrity: sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w==} + '@typescript-eslint/types@8.56.1': + resolution: {integrity: sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.55.0': - resolution: {integrity: sha512-EwrH67bSWdx/3aRQhCoxDaHM+CrZjotc2UCCpEDVqfCE+7OjKAGWNY2HsCSTEVvWH2clYQK8pdeLp42EVs+xQw==} + '@typescript-eslint/typescript-estree@8.56.1': + resolution: {integrity: sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.55.0': - resolution: {integrity: sha512-BqZEsnPGdYpgyEIkDC1BadNY8oMwckftxBT+C8W0g1iKPdeqKZBtTfnvcq0nf60u7MkjFO8RBvpRGZBPw4L2ow==} + '@typescript-eslint/utils@8.56.1': + resolution: {integrity: sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.55.0': - resolution: {integrity: sha512-AxNRwEie8Nn4eFS1FzDMJWIISMGoXMb037sgCBJ3UR6o0fQTzr2tqN9WT+DkWJPhIdQCfV7T6D387566VtnCJA==} + '@typescript-eslint/visitor-keys@8.56.1': + resolution: {integrity: sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@ungap/structured-clone@1.3.0': - resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} - - '@warp-drive/build-config@5.8.1': - resolution: {integrity: sha512-uT0zdNf7vdHEYYdYJ/1+coE0MwRiV6dg/dTwAaYtlsTFd57NrxE+s+1qd5aAjuwdB/GVlBP/D/IlUwWggbxXbg==} - - '@warp-drive/core-types@5.8.1': - resolution: {integrity: sha512-y1NZMQZWajLcf6RafpEBnqI8S6wJi81fpNxUintt3JwRGVLlJ5Py9eGKGwPARCjNsQM+cQVk4Um1HrDUdtsvuQ==} - - '@warp-drive/core@5.8.1': - resolution: {integrity: sha512-7Id5mvUjqRqlG2Tgz8Y/k1M5gmcUExfSWW3XBDbMDotF63YcmgukDLO145cFJtqiO3q8nZXC8PoftYCmoTwhuA==} - - '@warp-drive/ember@5.8.1': - resolution: {integrity: sha512-HcT8U+g3/p0xrc7tk2mLFAt1eX51IoNFlj9XwjqLIVCdBJ/VSlAbnUtvOOJPmTCgdBOgxs+f2xv/61d4l+VybQ==} - peerDependencies: - '@ember/test-waiters': ^3.1.0 || ^4.0.0 - ember-provide-consume-context: ^0.8.0 - peerDependenciesMeta: - ember-provide-consume-context: - optional: true - - '@warp-drive/json-api@5.8.1': - resolution: {integrity: sha512-JnxNUGUIwfvqBJkO9HRSighpE0HSyyrE1dmgK1KljDJm45U7frx3PtWykB4AoRDWx9+HSEVS1Dj4QRlXGK0IZQ==} - peerDependencies: - '@warp-drive/core': 5.8.1 - - '@warp-drive/legacy@5.8.1': - resolution: {integrity: sha512-i2+LhOQ+RO4AKeI4mSMWGNsiIY/sVB9CoslPDqCVc9BofcQE7uvAZinIjjPgPU5bbzqEThqdlHiEeoOdd19Tfw==} - peerDependencies: - '@warp-drive/core': 5.8.1 - '@warp-drive/utilities': 5.8.1 - - '@warp-drive/utilities@5.8.1': - resolution: {integrity: sha512-55cJjxIj0lQwLmhflQH3GqQs3oGGytlYjrpT/7mcvA7/zEnvfjlJH5z9r6WnMQXh4BN6scvKaFBw/lqeDGlIig==} - peerDependencies: - '@warp-drive/core': 5.8.1 - '@webassemblyjs/ast@1.14.1': resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} @@ -6102,12 +5880,12 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn-walk@8.3.4: - resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} + acorn-walk@8.3.5: + resolution: {integrity: sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==} engines: {node: '>=0.4.0'} - acorn@8.15.0: - resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} engines: {node: '>=0.4.0'} hasBin: true @@ -6136,14 +5914,11 @@ packages: peerDependencies: ajv: ^8.8.2 - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - ajv@6.14.0: resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} - ajv@8.17.1: - resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + ajv@8.18.0: + resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} amd-name-resolver@1.3.1: resolution: {integrity: sha512-26qTEWqZQ+cxSYygZ4Cf8tsjDBLceJahhtewxtKZA3SRa4PluuqYCuheemDQD+7Mf5B7sr+zhTDWAHDh02a1Dw==} @@ -6220,15 +5995,14 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + ansi-styles@6.2.3: resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} - ansi-to-html@0.6.15: - resolution: {integrity: sha512-28ijx2aHJGdzbs+O5SNQF65r6rrKYnkuwTYm8lZlChuoJ9P1vVzIpWO20sQTqTPDXYp6NFwk326vApTtLVFXpQ==} - engines: {node: '>=8.0.0'} - hasBin: true - ansicolors@0.2.1: resolution: {integrity: sha512-tOIuy1/SK/dr94ZA0ckDohKXNeBNqZ4us6PjMVLs5h1w2GBB6uPtOknp2+VF4F/zcy9LI70W+Z+pE2Soajky1w==} @@ -6576,8 +6350,9 @@ packages: resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} engines: {node: '>=0.10.0'} - baseline-browser-mapping@2.9.19: - resolution: {integrity: sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==} + baseline-browser-mapping@2.10.0: + resolution: {integrity: sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==} + engines: {node: '>=6.0.0'} hasBin: true basic-auth@2.0.1: @@ -6626,8 +6401,8 @@ packages: body@5.1.0: resolution: {integrity: sha512-chUsBxGRtuElD6fmw1gHLpvnKdVLK302peeFa9ZqAEk8TyzZ3fygLyUEDDPTJvL9+Bor0dIwn6ePOsRM2y0zQQ==} - bole@5.0.27: - resolution: {integrity: sha512-Hv/NnQSWwgo0yZ1tSi8B8fd2qk9LFRNqtpms7P6dZI67A7HTCy7MP1fwfmZgCbMNURf9+tdHHbbsORp/r0NjJA==} + bole@5.0.28: + resolution: {integrity: sha512-l+yybyZLV7zTD6EuGxoXsilpER1ctMCpdOqjSYNigJJma39ha85fzCtYccPx06oR1u7uCQLOcUAFFzvfXVBmuQ==} boom@0.4.2: resolution: {integrity: sha512-OvfN8y1oAxxphzkl2SnCS+ztV/uVKTATtgLjWYg/7KwcNyf3rzpHxNQJZCKtsZd4+MteKczhWbSjtEX4bGgU9g==} @@ -6675,10 +6450,6 @@ packages: peerDependencies: '@babel/core': ^7.17.9 - broccoli-builder@0.18.14: - resolution: {integrity: sha512-YoUHeKnPi4xIGZ2XDVN9oHNA9k3xF5f5vlA+1wvrxIIDXqQU97gp2FxVAF503Zxdtt0C5CRB5n+47k2hlkaBzA==} - engines: {node: '>= 0.10.0'} - broccoli-caching-writer@2.0.4: resolution: {integrity: sha512-+68OQpkriDc3b6tNgZmCCgE1UpfSKhMktXHrRYyJFcEc+g4T5dJe0N2vNUx96HwHo4FKmpReSanXoaXOgjQ/fA==} @@ -6688,15 +6459,15 @@ packages: broccoli-caching-writer@3.1.0: resolution: {integrity: sha512-3TWi92ogzUhLmCF5V4DjhN7v4t6OjXYO21p9GkuOZQ1SiVmM1sYio364y64dREHUzjFEcH8mdVCiRDdrwUGVTw==} - broccoli-concat@4.2.5: - resolution: {integrity: sha512-dFB5ATPwOyV8S2I7a07HxCoutoq23oY//LhM6Mou86cWUTB174rND5aQLR7Fu8FjFFLxoTbkk7y0VPITJ1IQrw==} + broccoli-concat@4.2.7: + resolution: {integrity: sha512-JePfBFwHtZ2FR33PBZQA99/hQ4idIbZ205rH84Jw6vgkuKDRVXWVzZP2gvR2WXugXaQ1fj3+yO04b0QsstNHzQ==} engines: {node: 10.* || >= 12.*} broccoli-config-loader@1.0.1: resolution: {integrity: sha512-MDKYQ50rxhn+g17DYdfzfEM9DjTuSGu42Db37A8TQHQe8geYEcUZ4SQqZRgzdAI3aRQNlA1yBHJfOeGmOjhLIg==} - broccoli-config-replace@1.1.2: - resolution: {integrity: sha512-qLlEY3V7p3ZWJNRPdPgwIM77iau1qR03S9BupMMFngjzBr7S6RSzcg96HbCYXmW9gfTbjRm9FC4CQT81SBusZg==} + broccoli-config-replace@1.1.3: + resolution: {integrity: sha512-gWGS2h/2VyJnD9tI1/HzRsXLOptnt7tu+KLpfPuxd+DBcdswn/i0kyVrTxQpFy+C5eo2hBn672QAEZzf/7LlAA==} broccoli-debug@0.6.5: resolution: {integrity: sha512-RIVjHvNar9EMCLDW/FggxFRXqpjhncM/3qq87bn/y+/zR9tqEkHvTqbyOc4QnB97NO2m6342w4wGkemkaeOuWg==} @@ -6743,10 +6514,6 @@ packages: broccoli-node-api@1.7.0: resolution: {integrity: sha512-QIqLSVJWJUVOhclmkmypJJH9u9s/aWH4+FH6Q6Ju5l+Io4dtwqdPUNmDfw40o6sxhbZHhqGujDJuHTML1wG8Yw==} - broccoli-node-info@1.1.0: - resolution: {integrity: sha512-DUohSZCdfXli/3iN6SmxPbck1OVG8xCkrLx47R25his06xVc1ZmmrOsrThiM8BsCWirwyocODiYJqNP5W2Hg1A==} - engines: {node: '>= 0.10.0'} - broccoli-node-info@2.2.0: resolution: {integrity: sha512-VabSGRpKIzpmC+r+tJueCE5h8k6vON7EIMMWu6d/FyPdtijwLQ7QvzShEw+m3mHoDzUaj/kiZsDYrS8X2adsBg==} engines: {node: 8.* || >= 10.*} @@ -6810,9 +6577,6 @@ packages: resolution: {integrity: sha512-p5el5/ig0QeRGFPkLMPdm7KblkTm44eicEWfwnRTz6hncghVuRZ0+XDAtCi7ynxobeE/mey5Q7lAulFkgNzxVA==} engines: {node: '>= 20.19.*'} - brotli@1.3.3: - resolution: {integrity: sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==} - browser-stdout@1.3.1: resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} @@ -6828,8 +6592,8 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true - browserstack-local@1.5.9: - resolution: {integrity: sha512-p8H3alMqUK9lq8JHhsDdZ4tpnSgbHyRyKnZu9U+9p7XzR/SpvTm/zkfsSJsnUZBoiYFe+B1VaGZ4cL5f2ya6mw==} + browserstack-local@1.5.12: + resolution: {integrity: sha512-xrdpG4rw6Ktxa/gM8x0esnohFlw0V33bQiUX08rrHWKbnJAG57KTHGvJ4mvgc9eRL63pEKal+WuNDg3vEUz4hA==} browserstack@1.6.1: resolution: {integrity: sha512-GxtFjpIaKdbAyzHfFDKixKO8IBT7wR3NjbzrGc78nNs/Ciys9wU3/nBtsqsWv5nDSrdI5tz0peKuzCPuNXNUiw==} @@ -6864,8 +6628,8 @@ packages: resolution: {integrity: sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==} engines: {node: '>=8'} - cacheable@2.3.2: - resolution: {integrity: sha512-w+ZuRNmex9c1TR9RcsxbfTKCjSL0rh1WA5SABbrWprIHeNBdmyQLSYonlDy9gpD+63XT8DgZ/wNh1Smvc9WnJA==} + cacheable@2.3.3: + resolution: {integrity: sha512-iffYMX4zxKp54evOH27fm92hs+DeC1DhXmNVN8Tr94M/iZIV42dqTHSR2Ik4TOSPyOAwKr7Yu3rN9ALoLkbWyQ==} calculate-cache-key-for-tree@2.0.0: resolution: {integrity: sha512-Quw8a6y8CPmRd6eU+mwypktYCwUcf8yVFIRbNZ6tPQEckX9yd+EBVEPC/GSZZrMWH9e7Vz4pT7XhpmyApRByLQ==} @@ -6910,8 +6674,8 @@ packages: resolution: {integrity: sha512-eOgiEWqjppB+3DN/5E82EQ8dTINus8d9GXMCbEsUnp2hcUIcXmBvzWmD3tXMk3CuBK0v+ddK9qw0EAF+JVRMjQ==} engines: {node: '>=10.13'} - caniuse-lite@1.0.30001769: - resolution: {integrity: sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==} + caniuse-lite@1.0.30001776: + resolution: {integrity: sha512-sg01JDPzZ9jGshqKSckOQthXnYwOEP50jeVFhaSFbZcOy05TiuuaffDOfcwtCisJ9kNQuLBFibYywv2Bgm9osw==} capture-exit@2.0.0: resolution: {integrity: sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==} @@ -7004,10 +6768,6 @@ packages: resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} engines: {node: '>=6.0'} - ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} - engines: {node: '>=8'} - ci-info@4.4.0: resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} engines: {node: '>=8'} @@ -7115,10 +6875,6 @@ packages: resolution: {integrity: sha512-rGWmDcp/wV2gZZ40pbN8Jo9OHuDUYPF45X5pfPgIiGmfp4xCKCyb+7/iamd764XkDbf5nQBj3zboOCdOf1T5Ww==} engines: {node: '>= 0.6.0'} - code-error-fragment@0.0.230: - resolution: {integrity: sha512-cadkfKp6932H8UkhzE/gcUqhRMNf8jHzkAN7+5Myabswaghu4xABTgPHDCjW+dBAJxj/SpkTYokpzDqY4pCzQw==} - engines: {node: '>= 4'} - code-point-at@1.1.0: resolution: {integrity: sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==} engines: {node: '>=0.10.0'} @@ -7236,10 +6992,6 @@ packages: config-chain@1.1.13: resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} - configstore@5.0.1: - resolution: {integrity: sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==} - engines: {node: '>=8'} - configstore@7.1.0: resolution: {integrity: sha512-N4oog6YJWbR9kGyXvS7jEykLDXIE2C0ILYqNBZBp9iwiJpoCBWYsuAdW6PPFn6w06jjnC+3JstVvWHO4cZqvRg==} engines: {node: '>=18'} @@ -7484,8 +7236,8 @@ packages: resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} engines: {node: '>= 0.10'} - cosmiconfig@9.0.0: - resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + cosmiconfig@9.0.1: + resolution: {integrity: sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==} engines: {node: '>=14'} peerDependencies: typescript: '>=4.9.5' @@ -7539,8 +7291,8 @@ packages: resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} engines: {node: '>=8.0.0'} - css-tree@3.1.0: - resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==} + css-tree@3.2.1: + resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} cssesc@3.0.0: @@ -7742,10 +7494,6 @@ packages: resolution: {integrity: sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==} engines: {node: '>=0.10.0'} - detect-indent@6.1.0: - resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} - engines: {node: '>=8'} - detect-indent@7.0.2: resolution: {integrity: sha512-y+8xyqdGLL+6sh0tVeHcfP/QDd8gUgbasolJJpY7NgeQGSZ739bDtSiaiDgtoicy+mtYB81dKLxO9xRhCyIB3A==} engines: {node: '>=12.20'} @@ -7754,10 +7502,6 @@ packages: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} - detect-newline@3.1.0: - resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} - engines: {node: '>=8'} - detect-newline@4.0.1: resolution: {integrity: sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -7793,10 +7537,6 @@ packages: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} - doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dom-element-descriptors@0.5.1: resolution: {integrity: sha512-DLayMRQ+yJaziF4JJX1FMjwjdr7wdTr1y9XvZ+NfHELfOMcYDnCHneAYXAS4FT1gLILh4V0juMZohhH1N5FsoQ==} @@ -7806,10 +7546,6 @@ packages: dot-case@3.0.4: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} - dot-prop@5.3.0: - resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} - engines: {node: '>=8'} - dot-prop@9.0.0: resolution: {integrity: sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ==} engines: {node: '>=18'} @@ -7821,9 +7557,6 @@ packages: duplexer3@0.1.5: resolution: {integrity: sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==} - duplexer@0.1.2: - resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} - eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -7846,17 +7579,23 @@ packages: engines: {node: '>=0.10.0'} hasBin: true - electron-to-chromium@1.5.286: - resolution: {integrity: sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==} + electron-to-chromium@1.5.307: + resolution: {integrity: sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==} elegant-spinner@1.0.1: resolution: {integrity: sha512-B+ZM+RXvRqQaAmkMlO/oSe5nMUOaUnyfGYCEHoR8wrXsZR2mA0XVibsxV1bvTwxdRWah1PkQqso2EzhILGHtEQ==} engines: {node: '>=0.10.0'} - ember-auto-import@2.12.1: - resolution: {integrity: sha512-wyvl+aJJKOKbRSLqq6CyMsNrvurmX4SIWHHqZdC5giZ7P8ECGmcn9W9HFoVLpwXkFJoXhNV4L7mqqcU6881t0w==} + ember-auto-import@2.13.0: + resolution: {integrity: sha512-P6COSWDDC6qpgNdc33PyAubhTHUkKc1gUfP2oR4BZoHhUVoEMHiSOECHISd5a2J8DaNrcpFcZmjgb1vJ2ydkjw==} engines: {node: 12.* || 14.* || >= 16} + ember-cli-app-version@7.0.0: + resolution: {integrity: sha512-zWIkxvlRrW7w1/vp+bGkmS27QsVum7NKp8N9DgAjhFMWuKewVqGyl/jeYaujMS/I4WSKBzSG9WHwBy2rjbUWxA==} + engines: {node: '>= 18'} + peerDependencies: + ember-source: ^3.28.0 || >= 4.0.0 + ember-cli-babel-plugin-helpers@1.1.1: resolution: {integrity: sha512-sKvOiPNHr5F/60NLd7SFzMpYPte/nnGkq/tMIfXejfKHIhaiIkYFqX8Z9UFTKWLLn+V7NOaby6niNPZUdvKCRw==} engines: {node: 6.* || 8.* || >= 10.*} @@ -7880,6 +7619,10 @@ packages: engines: {node: 10.* || >= 12} hasBin: true + ember-cli-clean-css@3.0.0: + resolution: {integrity: sha512-BbveJCyRvzzkaTH1llLW+MpHe/yzA5zpHOpMIg2vp/3JD9mban9zUm7lphaB0TSpPuMuby9rAhTI8pgXq0ifIA==} + engines: {node: 16.* || >= 18} + ember-cli-dependency-checker@3.3.3: resolution: {integrity: sha512-mvp+HrE0M5Zhc2oW8cqs8wdhtqq0CfQXAYzaIstOzHJJn/U01NZEGu3hz7J7zl/+jxZkyygylzcS57QqmPXMuQ==} engines: {node: '>= 6'} @@ -7892,6 +7635,9 @@ packages: peerDependencies: ember-source: '>= 3.28.0' + ember-cli-deprecation-workflow@4.0.1: + resolution: {integrity: sha512-XJzUZVXyb6/nFKU7GzGRlHlcAl4KtkioBTjfuIHp1aysbRZ6XxYLSPtP090EbOxQBtYwAPsH2kPAtPS86tL2RA==} + ember-cli-get-component-path-option@1.0.0: resolution: {integrity: sha512-k47TDwcJ2zPideBCZE8sCiShSxQSpebY2BHcX2DdipMmBox5gsfyVrbKJWIHeSTTKyEUgmBIvQkqTOozEziCZA==} @@ -7916,10 +7662,6 @@ packages: ember-cli-is-package-missing@1.0.0: resolution: {integrity: sha512-9hEoZj6Au5onlSDdcoBqYEPT8ehlYntZPxH8pBKV0GO7LNel88otSAQsCfXvbi2eKE+MaSeLG/gNaCI5UdWm9g==} - ember-cli-lodash-subset@2.0.1: - resolution: {integrity: sha512-QkLGcYv1WRK35g4MWu/uIeJ5Suk2eJXKtZ+8s+qE7C9INmpCPyPxzaqZABquYzcWNzIdw6kYwz3NWAFdKYFxwg==} - engines: {node: ^4.5 || 6.* || >= 7.*} - ember-cli-normalize-entity-name@1.0.0: resolution: {integrity: sha512-rF4P1rW2P1gVX1ynZYPmuIf7TnAFDiJmIUFI1Xz16VYykUAyiOCme0Y22LeZq8rTzwBMiwBwoE3RO4GYWehXZA==} @@ -7941,20 +7683,9 @@ packages: resolution: {integrity: sha512-Ej77K+YhCZImotoi/CU2cfsoZaswoPlGaM5TB3LvjvPDlVPRhxUHO2RsaUVC5lsGeRLRiHCOxVtoJ6GyqexzFA==} engines: {node: 10.* || 12.* || >= 14} - ember-cli-test-info@1.0.0: - resolution: {integrity: sha512-dEVTIpmUfCzweC97NGf6p7L6XKBwV2GmSM4elmzKvkttEp5P7AvGA9uGyN4GqFq+RwhW+2b0I2qlX00w+skm+A==} - - ember-cli-test-loader@3.1.0: - resolution: {integrity: sha512-0aocZV9SIoOHiU3hrH3IuLR6busWhTX6UVXgd490hmJkIymmOXNH2+jJoC7Ebkeo3PiOfAdjqhb765QDlHSJOw==} - engines: {node: 10.* || >= 12} - ember-cli-typescript-blueprint-polyfill@0.1.0: resolution: {integrity: sha512-g0weUTOnHmPGqVZzkQTl3Nbk9fzEdFkEXydCs5mT1qBjXh8eQ6VlmjjGD5/998UXKuA0pLSCVVMbSp/linLzGA==} - ember-cli-typescript@2.0.2: - resolution: {integrity: sha512-7I5azCTxOgRDN8aSSnJZIKSqr+MGnT+jLTUbBYqF8wu6ojs2DUnTePxUcQMcvNh3Q3B1ySv7Q/uZFSjdU9gSjA==} - engines: {node: 6.* || 8.* || >= 10.*} - ember-cli-version-checker@3.1.3: resolution: {integrity: sha512-PZNSvpzwWgv68hcXxyjREpj3WWb81A7rtYNQq1lLEgrWIchF8ApKJjWP3NBpHjaatwILkZAV8klair5WFlXAKg==} engines: {node: 6.* || 8.* || >= 10.*} @@ -7971,33 +7702,11 @@ packages: resolution: {integrity: sha512-4pb3OKXhHCeUux6a7SDKziLDWdDciJwzmUld3Fumt60RLcH/nIk5lPdI0o+UXJ9NfP+WcSvvpWWroFmWqWAWWA==} engines: {node: '>= 4.0.0'} - ember-cli@5.7.0: - resolution: {integrity: sha512-MKHVcRpDk1ENUCCRGGqZ8yfkCsszvSUbwO09h14vqcfaqcJkOWI+p0oynmdZQMM8OkZp484oLe3+CZCsXO9LfA==} - engines: {node: '>= 18'} - hasBin: true - - ember-cli@6.10.2: - resolution: {integrity: sha512-NsVKAphIjU2chk/rskIjnIqU5ZN9mbDsczDrn7Mu5RZYa60cULjt2XMWQAcMMak6XO8ve8KDf7UyYe6IyKoTXQ==} + ember-cli@6.11.0: + resolution: {integrity: sha512-c+5m4KgPr1hi7+64+SAfphIeCFZMuKTR+QSM0PPmEJhXibtCJd+8Ag5IrBMJ5urhX4jUtZ3skc0/Zln67CiGjQ==} engines: {node: '>= 20.19.0'} hasBin: true - ember-cli@6.5.0: - resolution: {integrity: sha512-2qNqaD3iIFeFcYiKsgrsP0qdEilvT820+vX2Fz1x32XIgcsmy79ufc0rHrsHmEiazSQLC9XKUskwEzFBWjy54g==} - engines: {node: '>= 18'} - hasBin: true - - ember-data@5.8.1: - resolution: {integrity: sha512-bxCNErbs5vr+cXg/A1gz3dfoJqGdfUZ1JkOQUn5FE2y6qRsQG3S8OShHb2QolKpbKUTY+UHqRhaspdL5NXJjKA==} - peerDependencies: - '@ember/test-helpers': ^3.3.0 || ^4.0.4 || ^5.1.0 - '@ember/test-waiters': ^3.1.0 || ^4.0.0 - qunit: ^2.18.0 - peerDependenciesMeta: - '@ember/test-helpers': - optional: true - qunit: - optional: true - ember-eslint-parser@0.5.13: resolution: {integrity: sha512-b6ALDaxs9Bb4v0uagWud/5lECb78qpXHFv7M340dUHFW4Y0RuhlsfA4Rb+765X1+6KHp8G7TaAs0UgggWUqD3g==} engines: {node: '>=16.0.0'} @@ -8008,10 +7717,6 @@ packages: '@typescript-eslint/parser': optional: true - ember-load-initializers@2.1.2: - resolution: {integrity: sha512-CYR+U/wRxLbrfYN3dh+0Tb6mFaxJKfdyz+wNql6cqTrA0BBi9k6J3AaKXj273TqvEpyyXegQFFkZEiuZdYtgJw==} - engines: {node: 6.* || 8.* || >= 10.*} - ember-load-initializers@3.0.1: resolution: {integrity: sha512-qV3vxJKw5+7TVDdtdLPy8PhVsh58MlK8jwzqh5xeOwJPNP7o0+BlhvwoIlLYTPzGaHdfjEIFCgVSyMRGd74E1g==} engines: {node: '>= 18.*'} @@ -8021,41 +7726,18 @@ packages: ember-modifier@4.3.0: resolution: {integrity: sha512-O0rirSLQbGg0VJ/NqoQ4uN1bh2iAekZC/Ykma+FkjCM2ofrO38u+d8n3+AK6uVWeMJmogGX2KL+Is5fofoInJg==} - ember-page-title@8.2.4: - resolution: {integrity: sha512-ZZ912IRItIEfD5+35w65DT9TmqppK+suXJeaJenD5OSuvujUnYl6KxBpyAbfjw4mYtURwJO/TmSe+4GGJbsJ0w==} - engines: {node: 16.* || >= 18} - peerDependencies: - ember-source: '>= 3.28.0' - ember-page-title@9.0.3: resolution: {integrity: sha512-fedRHUsvq8tIZgOii8jTrfAyeq+la/9H5eAzhNNwEyzo7nDMmqK2SxsyBUGXprd8fOacsPabLlzlucMi/4mUpA==} engines: {node: 16.* || >= 18} - ember-qunit@8.1.1: - resolution: {integrity: sha512-nT+6s74j3BKNn+QQY/hINC3Xw3kn0NF0cU9zlgVQmCBWoyis1J24xWrY2LFOMThPmF6lHqcrUb5JwvBD4BXEXg==} - peerDependencies: - '@ember/test-helpers': '>=3.0.3' - ember-source: '>=4.0.0' - qunit: ^2.13.0 - ember-qunit@9.0.4: resolution: {integrity: sha512-rv6gKvrdXdPBTdSZC5co82eIcDWWVR7RjafU/c+5TTz290oXhIHPoVuZbcO2F5RiAqkTW0jKzwkCP8y+2tCjFw==} peerDependencies: '@ember/test-helpers': '>=3.0.3' qunit: ^2.13.0 - ember-resolver@11.0.1: - resolution: {integrity: sha512-ucBk3oM+PR+AfYoSUXeQh8cDQS1sSiEKp4Pcgbew5cFMSqPxJfqd1zyZsfQKNTuyubeGmWxBOyMVSTvX2LeCyg==} - engines: {node: 14.* || 16.* || >= 18} - peerDependencies: - ember-source: ^4.8.3 || >= 5.0.0 - peerDependenciesMeta: - ember-source: - optional: true - - ember-resolver@13.1.1: - resolution: {integrity: sha512-rA4RDuTm/F9AzYX2+g7EY3QWU48kyF9+Ck8IE8VQipnlwv2Q42kdRWiw7hfeQbRxx6XoSZCak6nzAG9ePd/+Ug==} - engines: {node: 14.* || 16.* || >= 18} + ember-resolver@13.2.0: + resolution: {integrity: sha512-A+BffoSKC0ngiczbgaz/IOY66ovZVRRHHIDDi+d7so5i0By8xuB4nXgZZ6Dv3u/3WwoUyixgUvb0xTUO+MtupA==} ember-rfc176-data@0.3.18: resolution: {integrity: sha512-JtuLoYGSjay1W3MQAxt3eINWXNYYQliK90tLwtb8aeCuQK8zKGCRbBodVIrkcTqshULMnRuTOS6t1P7oQk3g6Q==} @@ -8090,17 +7772,10 @@ packages: engines: {node: 12.* || 14.* || >= 16.*} hasBin: true - ember-template-tag@2.3.16: - resolution: {integrity: sha512-G6bIBcT4VnLlBUogkXxEXIzVvdYXhmLe+Io2yJzRYYZeHrdxKa6u2ZHXF4qII298grgqnqGo6tNqqgtD4AAS5g==} - ember-tracked-storage-polyfill@1.0.0: resolution: {integrity: sha512-eL7lZat68E6P/D7b9UoTB5bB5Oh/0aju0Z7PCMi3aTwhaydRaxloE7TGrTRYU+NdJuyNVZXeGyxFxn2frvd3TA==} engines: {node: 12.* || >= 14} - ember-welcome-page@7.0.2: - resolution: {integrity: sha512-TyaKxFIRXhODW5BTbqD/by0Gu8Z9B9AA1ki3Bzzm6fOj2b30Qlprtt+XUG52kS0zVNmxYj/WWoT0TsKiU61VOw==} - engines: {node: 14.* || 16.* || >= 18} - emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -8130,8 +7805,8 @@ packages: resolution: {integrity: sha512-2RZdgEbXmp5+dVbRm0P7HQUImZpICccJy7rN7Tv+SFa55pH+lxnuw6/K1ZxxBfHoYpSkHLAO92oa8O4SwFXA2A==} engines: {node: '>=10.2.0'} - enhanced-resolve@5.19.0: - resolution: {integrity: sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==} + enhanced-resolve@5.20.0: + resolution: {integrity: sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==} engines: {node: '>=10.13.0'} ensure-posix-path@1.1.1: @@ -8140,13 +7815,6 @@ packages: entities@1.1.2: resolution: {integrity: sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==} - entities@2.2.0: - resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} - - entities@3.0.1: - resolution: {integrity: sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==} - engines: {node: '>=0.12'} - entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} @@ -8307,12 +7975,6 @@ packages: peerDependencies: eslint: '>=8' - eslint-plugin-es@3.0.1: - resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==} - engines: {node: '>=8.10.0'} - peerDependencies: - eslint: '>=4.19.1' - eslint-plugin-import@2.32.0: resolution: {integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==} engines: {node: '>=4'} @@ -8323,38 +7985,12 @@ packages: '@typescript-eslint/parser': optional: true - eslint-plugin-n@17.23.2: - resolution: {integrity: sha512-RhWBeb7YVPmNa2eggvJooiuehdL76/bbfj/OJewyoGT80qn5PXdz8zMOTO6YHOsI7byPt7+Ighh/i/4a5/v7hw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: '>=8.23.0' - eslint-plugin-n@17.24.0: resolution: {integrity: sha512-/gC7/KAYmfNnPNOb3eu8vw+TdVnV0zhdQwexsw6FLXbhzroVj20vRn2qL8lDWDGnAQ2J8DhdfvXxX9EoxvERvw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: '>=8.23.0' - eslint-plugin-node@11.1.0: - resolution: {integrity: sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==} - engines: {node: '>=8.10.0'} - peerDependencies: - eslint: '>=5.16.0' - - eslint-plugin-prettier@5.5.5: - resolution: {integrity: sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - '@types/eslint': '>=8.0.0' - eslint: '>=8.0.0' - eslint-config-prettier: '>= 7.0.0 <10.0.0 || >=10.1.0' - prettier: '>=3.0.0' - peerDependenciesMeta: - '@types/eslint': - optional: true - eslint-config-prettier: - optional: true - eslint-plugin-qunit@8.2.6: resolution: {integrity: sha512-S1jC/DIW9J8VtNX4uG1vlf5FZVrfQFlcuiYmvTHR2IICUhubHqpWA5o+qS1tujh+81Gs39omKV2D4OXfbSJE5g==} engines: {node: ^16.0.0 || ^18.0.0 || >=20.0.0} @@ -8373,20 +8009,12 @@ packages: resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint-utils@2.1.0: - resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} - engines: {node: '>=6'} - eslint-utils@3.0.0: resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} peerDependencies: eslint: '>=5' - eslint-visitor-keys@1.3.0: - resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} - engines: {node: '>=4'} - eslint-visitor-keys@2.1.0: resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} engines: {node: '>=10'} @@ -8399,14 +8027,12 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@8.57.1: - resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. - hasBin: true + eslint-visitor-keys@5.0.1: + resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} - eslint@9.39.2: - resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==} + eslint@9.39.3: + resolution: {integrity: sha512-VmQ+sifHUbI/IcSopBCF/HO3YiHQx/AVd3UVyYL6weuwW+HvON9VYn5l6Zl1WZzPWXPNZrSQpxwkkZ/VuvJZzg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -8423,10 +8049,6 @@ packages: resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - esprima@1.1.1: resolution: {integrity: sha512-qxxB994/7NtERxgXdFgLHIs9M6bhLXc6qtUmWZ3L8+gTQ9qaoyki2887P2IqAYsoENyr8SUbTutStDniOHSDHg==} engines: {node: '>=0.4.0'} @@ -8477,9 +8099,6 @@ packages: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} - event-stream@3.3.4: - resolution: {integrity: sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==} - eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} @@ -8571,9 +8190,6 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-diff@1.3.0: - resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} - fast-glob@3.3.3: resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} @@ -8606,8 +8222,11 @@ packages: fast-wrap-ansi@0.2.0: resolution: {integrity: sha512-rLV8JHxTyhVmFYhBJuMujcrHqOT2cnO5Zxj37qROj23CP39GXubJRBUFF0z8KFK77Uc0SukZUf7JZhsVEQ6n8w==} - fast-xml-parser@5.3.4: - resolution: {integrity: sha512-EFd6afGmXlCx8H8WTZHhAoDaWaGyuIBoZJ2mknrNxug+aZKjkp0a0dlars9Izl+jF+7Gu1/5f/2h68cQpe0IiA==} + fast-xml-builder@1.0.0: + resolution: {integrity: sha512-fpZuDogrAgnyt9oDDz+5DBz0zgPdPZz6D4IR7iESxRXElrlGTRkHJ9eEt+SACRJwT0FNFrt71DFQIUFBJfX/uQ==} + + fast-xml-parser@5.4.1: + resolution: {integrity: sha512-BQ30U1mKkvXQXXkAGcuyUA/GA26oEB7NzOtsxCDtyu62sjGw5QraKFhx2Em3WQNjPw9PG6MQ9yuIIgkSDfGu5A==} hasBin: true fastest-levenshtein@1.0.16: @@ -8652,16 +8271,12 @@ packages: file-entry-cache@11.1.2: resolution: {integrity: sha512-N2WFfK12gmrK1c1GXOqiAJ1tc5YE+R53zvQ+t5P8S5XhnmKYVB5eZEiLNZKDSmoG8wqqbF9EXYBBW/nef19log==} - file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} - file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} - filelist@1.0.4: - resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + filelist@1.0.6: + resolution: {integrity: sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==} filesize@10.1.6: resolution: {integrity: sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==} @@ -8754,10 +8369,6 @@ packages: fixturify-project@1.10.0: resolution: {integrity: sha512-L1k9uiBQuN0Yr8tA9Noy2VSQ0dfg0B8qMdvT7Wb5WQKc7f3dn3bzCbSrqlb+etLW+KDV4cBC7R1OvcMg3kcxmA==} - fixturify-project@2.1.1: - resolution: {integrity: sha512-sP0gGMTr4iQ8Kdq5Ez0CVJOZOGWqzP5dv/veOTdFNywioKjkNWCHBi1q65DMpcNGUGeoOUWehyji274Q2wRgxA==} - engines: {node: 10.* || >= 12.*} - fixturify-project@7.1.3: resolution: {integrity: sha512-araEoNawWCIV9xT/+kAQ+H3aiFTVVH1nUDuYU7syhbWnlyA6BzuRE7vhdZQ7m+1+T5A3zG2JljGxRkNP1EhvXQ==} engines: {node: '>= 14.*'} @@ -8766,18 +8377,10 @@ packages: resolution: {integrity: sha512-tL0svlOy56pIMMUQ4bU1xRe6NZbFSa/ABTWMxW2mH38lFGc9TrNAKWcMBQ7eIjo3wqSS8f2ICabFaatFyFmrVQ==} engines: {node: 6.* || 8.* || >= 10.*} - fixturify@2.1.1: - resolution: {integrity: sha512-SRgwIMXlxkb6AUgaVjIX+jCEqdhyXu9hah7mcK+lWynjKtX73Ux1TDv71B7XyaQ+LJxkYRHl5yCL8IycAvQRUw==} - engines: {node: 10.* || >= 12.*} - fixturify@3.0.0: resolution: {integrity: sha512-PFOf/DT9/t2NCiVyiQ5cBMJtGZfWh3aeOV8XVqQQOPBlTv8r6l0k75/hm36JOaiJlrWFk/8aYFyOKAvOkrkjrw==} engines: {node: 14.* || >= 16.*} - flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} - flat-cache@4.0.1: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} @@ -8789,8 +8392,8 @@ packages: resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} hasBin: true - flatted@3.3.3: - resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + flatted@3.3.4: + resolution: {integrity: sha512-3+mMldrTAPdta5kjX2G2J7iX4zxtnwpdA8Tr2ZSjkyPSanvbZAcy6flmtnXbEybHrDcU9641lxrMfFuUxVz9vA==} follow-redirects@1.15.11: resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} @@ -8840,9 +8443,6 @@ packages: resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} engines: {node: '>= 0.8'} - from@0.1.7: - resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==} - fs-constants@1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} @@ -8856,8 +8456,8 @@ packages: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} - fs-extra@11.3.3: - resolution: {integrity: sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==} + fs-extra@11.3.4: + resolution: {integrity: sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==} engines: {node: '>=14.14'} fs-extra@4.0.3: @@ -8994,9 +8594,6 @@ packages: resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} engines: {node: '>=0.10.0'} - git-hooks-list@1.0.3: - resolution: {integrity: sha512-Y7wLWcrLUXwk2noSka166byGCvhMtDRpgHdzCno1UQv/n/Hegp++a2xBWJL1lJarnKD3SWaljD+0z1ztqxuKyQ==} - git-hooks-list@3.2.0: resolution: {integrity: sha512-ZHG9a1gEhUMX1TvGrLdyWb9kDopCBbTnI8z4JgRMYxsijWipgjSEYoPWqBuIB0DnRnvqlQSEeVmzpeuPm7NdFQ==} @@ -9034,9 +8631,9 @@ packages: deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true - glob@13.0.2: - resolution: {integrity: sha512-035InabNu/c1lW0tzPhAgapKctblppqsKKG9ZaNzbr+gXwWMjXoiyGSyB9sArzrjG7jY+zntRq5ZSUYemrnWVQ==} - engines: {node: 20 || >=22} + glob@13.0.6: + resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} + engines: {node: 18 || 20 || >=22} glob@5.0.15: resolution: {integrity: sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==} @@ -9072,14 +8669,6 @@ packages: resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} engines: {node: '>=6'} - globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - - globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} - globals@14.0.0: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} @@ -9099,10 +8688,6 @@ packages: globalyzer@0.1.0: resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==} - globby@10.0.0: - resolution: {integrity: sha512-3LifW9M4joGZasyYPz2A1U74zbC/45fvpXUvO/9KbSa+VV0aGZarWkfdgKyR9sExNP0t0x0ss/UMJpNpcaTspw==} - engines: {node: '>=8'} - globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} @@ -9131,12 +8716,6 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - grapheme-splitter@1.0.4: - resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} - - graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - growly@1.3.0: resolution: {integrity: sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==} @@ -9208,11 +8787,11 @@ packages: resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} engines: {node: '>=0.10.0'} - hash-for-dep@1.5.1: - resolution: {integrity: sha512-/dQ/A2cl7FBPI2pO0CANkvuuVi/IFS5oTyJ0PsOb6jW6WbVW1js5qJXMJTNbWHXBIPdFTWFbabjB+mE0d+gelw==} + hash-for-dep@1.5.2: + resolution: {integrity: sha512-+kJRJpgO+V8x6c3UQuzO+gzHu5euS8HDOIaIUsOPdQrVu7ajNKkMykbSC8O0VX3LuRnUNf4hHE0o/rJ+nB8czw==} - hashery@1.4.0: - resolution: {integrity: sha512-Wn2i1In6XFxl8Az55kkgnFRiAlIAushzh26PTjL2AKtQcEfXrcLa7Hn5QOWGZEf3LU057P9TwwZjFyxfS1VuvQ==} + hashery@1.5.0: + resolution: {integrity: sha512-nhQ6ExaOIqti2FDWoEMWARUqIKyjr2VcZzXShrI+A3zpeiuPWzx6iPftt44LhP74E5sW36B75N6VHbvRtpvO6Q==} engines: {node: '>=20'} hasown@2.0.2: @@ -9260,14 +8839,6 @@ packages: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} engines: {node: '>=10'} - hosted-git-info@6.1.3: - resolution: {integrity: sha512-HVJyzUrLIL1c0QmviVh5E8VGyUS7xCFPS6yydaVd1UegW+ibV/CohqTH9MkOLDp5o+rb82DMo77PTuc9F/8GKw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - hosted-git-info@8.1.0: - resolution: {integrity: sha512-Rw/B2DNQaPBICNXEm8balFz9a6WpZrkCGpcWFpy7nCj+NyhSdqXipmfvtmWt9xGfp0wZnBxB+iVpLmQMYt47Tw==} - engines: {node: ^18.17.0 || >=20.5.0} - hosted-git-info@9.0.2: resolution: {integrity: sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg==} engines: {node: ^20.17.0 || >=22.9.0} @@ -9459,10 +9030,6 @@ packages: resolution: {integrity: sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==} engines: {node: '>=8.0.0'} - inquirer@9.3.8: - resolution: {integrity: sha512-pFGGdaHrmRKMh4WoDDSowddgjT1Vkl90atobmTeSmcPGdYiwikch/m/Ef5wRaiamHejtw0cUUMMerzDUXCci2w==} - engines: {node: '>=18'} - internal-slot@1.1.0: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} @@ -9593,9 +9160,6 @@ packages: resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} engines: {node: '>=8'} - is-language-code@3.1.0: - resolution: {integrity: sha512-zJdQ3QTeLye+iphMeK3wks+vXSRFKh68/Pnlw7aOfApFSEIOhYa8P9vwwa6QrImNNBMJTiL1PpYF0f4BxDuEgA==} - is-language-code@5.1.3: resolution: {integrity: sha512-LI43ua9ZYquG9kxzUl3laVQ2Ly8VGGr8vOfYv64DaK3uOGejz6ANDzteOvZlgPT40runzARzRMQZnRZg99ZW4g==} engines: {node: '>=14.18.0'} @@ -9624,18 +9188,10 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - is-obj@2.0.0: - resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} - engines: {node: '>=8'} - is-observable@1.1.0: resolution: {integrity: sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==} engines: {node: '>=4'} - is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - is-plain-obj@1.1.0: resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} engines: {node: '>=0.10.0'} @@ -9723,9 +9279,6 @@ packages: resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} - is-typedarray@1.0.0: - resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} - is-unicode-supported@0.1.0: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} @@ -9849,11 +9402,6 @@ packages: canvas: optional: true - jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} @@ -9871,9 +9419,9 @@ packages: json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - json-parse-even-better-errors@3.0.2: - resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + json-parse-even-better-errors@4.0.0: + resolution: {integrity: sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA==} + engines: {node: ^18.17.0 || >=20.5.0} json-query@2.2.2: resolution: {integrity: sha512-y+IcVZSdqNmS4fO8t1uZF6RMMs0xh3SrTjJr9bp1X3+v0Q13+7Cyv12dSmKwDswp/H427BVtpkLWhGxYu3ZWRA==} @@ -9894,10 +9442,6 @@ packages: json-stringify-safe@5.0.1: resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} - json-to-ast@2.1.0: - resolution: {integrity: sha512-W9Lq347r8tA1DfMvAGn9QNcgYm4Wm7Yc+k8e6vezpMnRT+NHbtlxgNBXRVjXe9YM6eTn6+p/MKOlV/aABJcSnQ==} - engines: {node: '>= 4'} - json5@1.0.2: resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} hasBin: true @@ -9993,9 +9537,6 @@ packages: linkify-it@1.2.4: resolution: {integrity: sha512-eGHwtlABkp1NOJSiKUNqBf3SYAS5jPHtvRXPAgNaQwTqmkTahjtiLH9NtxdR5IOPhNvwNMN/diswSfZKzUkhGg==} - linkify-it@4.0.1: - resolution: {integrity: sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==} - linkify-it@5.0.0: resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} @@ -10020,10 +9561,6 @@ packages: livereload-js@3.4.1: resolution: {integrity: sha512-5MP0uUeVCec89ZbNOT/i97Mc+q3SxXmiUGhRFOTmhrGPn//uWVQdCvcLJDy64MSBR5MidFdOR7B9viumoavy6g==} - load-json-file@4.0.0: - resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==} - engines: {node: '>=4'} - load-json-file@6.2.0: resolution: {integrity: sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==} engines: {node: '>=8'} @@ -10121,10 +9658,6 @@ packages: lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - lodash.omit@4.5.0: - resolution: {integrity: sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==} - deprecated: This package is deprecated. Use destructuring assignment syntax instead. - lodash.template@4.5.0: resolution: {integrity: sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==} deprecated: This package is deprecated. Use https://socket.dev/npm/package/eta instead. @@ -10138,9 +9671,6 @@ packages: lodash.union@4.6.0: resolution: {integrity: sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==} - lodash.uniq@4.5.0: - resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} - lodash@4.17.23: resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==} @@ -10191,10 +9721,6 @@ packages: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} - lru-cache@7.18.3: - resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} - engines: {node: '>=12'} - magic-string@0.25.9: resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} @@ -10224,9 +9750,6 @@ packages: resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} engines: {node: '>=8'} - map-stream@0.1.0: - resolution: {integrity: sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==} - map-visit@1.0.0: resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==} engines: {node: '>=0.10.0'} @@ -10236,12 +9759,8 @@ packages: peerDependencies: markdown-it: '>= 13.0.0' - markdown-it@13.0.2: - resolution: {integrity: sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w==} - hasBin: true - - markdown-it@14.1.0: - resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} + markdown-it@14.1.1: + resolution: {integrity: sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==} hasBin: true markdown-it@4.4.0: @@ -10268,8 +9787,8 @@ packages: mdn-data@2.0.14: resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} - mdn-data@2.12.2: - resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} + mdn-data@2.27.1: + resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} mdn-links@0.1.0: resolution: {integrity: sha512-m+gI2Hrgro1O0SwqHd9cFkqN8VGzP56eprB63gxu6z9EFQDMeaR083wcNqMVADIbgiMP/TOCCe0ZIXHLBv2tUg==} @@ -10288,10 +9807,6 @@ packages: resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} engines: {node: '>= 0.8'} - mem@5.1.1: - resolution: {integrity: sha512-qvwipnozMohxLXG1pOqoLiZKNkC4r4qqRucSoDwXowsNGDSULiqFTRUF05vcZWnwJSG22qTsynQhxbaMtnX9gw==} - engines: {node: '>=8'} - mem@8.1.1: resolution: {integrity: sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==} engines: {node: '>=10'} @@ -10398,40 +9913,21 @@ packages: peerDependencies: webpack: ^5.0.0 - minimatch@10.1.2: - resolution: {integrity: sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==} - engines: {node: 20 || >=22} - minimatch@10.2.4: resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} engines: {node: 18 || 20 || >=22} - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - minimatch@3.1.5: resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} - minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} - minimatch@5.1.9: resolution: {integrity: sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==} engines: {node: '>=10'} - minimatch@7.4.6: - resolution: {integrity: sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==} - engines: {node: '>=10'} - minimatch@8.0.7: resolution: {integrity: sha512-V+1uQNdzybxa14e/p00HZnQNNcTjnRJjDxg2V8wtkjFctq4M7hXFws4oekyTP0Jebeq7QYtpFyOeBAjc88zvYg==} engines: {node: '>=16 || 14 >=14.17'} - minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} - engines: {node: '>=16 || 14 >=14.17'} - minimatch@9.0.9: resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} engines: {node: '>=16 || 14 >=14.17'} @@ -10450,8 +9946,8 @@ packages: resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==} engines: {node: '>=8'} - minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} engines: {node: '>=16 || 14 >=14.17'} mixin-deep@1.3.2: @@ -10509,10 +10005,6 @@ packages: mute-stream@0.0.8: resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} - mute-stream@1.0.0: - resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - mute-stream@3.0.0: resolution: {integrity: sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==} engines: {node: ^20.17.0 || >=22.9.0} @@ -10558,17 +10050,14 @@ packages: no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} - node-gzip@1.1.2: - resolution: {integrity: sha512-ZB6zWpfZHGtxZnPMrJSKHVPrRjURoUzaDbLFj3VO70mpLTW5np96vXyHwft4Id0o+PYIzgDkBUjIzaNHhQ8srw==} - node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} node-notifier@10.0.1: resolution: {integrity: sha512-YX7TSyDukOZ0g+gmzjB6abKu+hTGvO8+8+gIFDsRCU2t8fLV/P2unmt+LGFaIa4y64aX98Qksa97rgz4vMNeLQ==} - node-releases@2.0.27: - resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} + node-releases@2.0.36: + resolution: {integrity: sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==} node-uuid@1.4.8: resolution: {integrity: sha512-TkCET/3rr9mUuRp+CpO7qfgT++aAxfDRaalQhwPFzI9BY/2rCDn6OfpZOVggi1AXfTPpfkTrg5f5WQx5G1uLxA==} @@ -10617,16 +10106,8 @@ packages: resolution: {integrity: sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - npm-normalize-package-bin@3.0.1: - resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - npm-package-arg@10.1.0: - resolution: {integrity: sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - npm-package-arg@12.0.2: - resolution: {integrity: sha512-f1NpFjNI9O4VbKMOlA5QoBq/vSQPORHcTZ2feJpFkTHJ9eQkdlmZEKSjcAhxTGInC7RlEyScT9ui67NaOsjFWA==} + npm-normalize-package-bin@4.0.0: + resolution: {integrity: sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==} engines: {node: ^18.17.0 || >=20.5.0} npm-package-arg@13.0.2: @@ -10638,14 +10119,14 @@ packages: engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} hasBin: true - npm-run-all2@6.2.6: - resolution: {integrity: sha512-tkyb4pc0Zb0oOswCb5tORPk9MvVL6gcDq1cMItQHmsbVk1skk7YF6cH+UU2GxeNLHMuk6wFEOSmEmJ2cnAK1jg==} - engines: {node: ^14.18.0 || ^16.13.0 || >=18.0.0, npm: '>= 8'} + npm-run-all2@5.0.2: + resolution: {integrity: sha512-S2G6FWZ3pNWAAKm2PFSOtEAG/N+XO/kz3+9l6V91IY+Y3XFSt7Lp7DV92KCgEboEW0hRTu0vFaMe4zXDZYaOyA==} + engines: {node: '>= 10'} hasBin: true - npm-run-all@4.1.5: - resolution: {integrity: sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==} - engines: {node: '>= 4'} + npm-run-all2@8.0.4: + resolution: {integrity: sha512-wdbB5My48XKp2ZfJUlhnLVihzeuA1hgBnqB2J9ahV77wLS+/YAJAlN8I+X3DIFIPZ3m5L7nplmlbhNiFDmXRDA==} + engines: {node: ^20.5.0 || >=22.0.0, npm: '>= 10'} hasBin: true npm-run-path@2.0.2: @@ -10774,10 +10255,6 @@ packages: resolution: {integrity: sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==} engines: {node: '>=0.10.0'} - os-locale@5.0.0: - resolution: {integrity: sha512-tqZcNEDAIZKBEPnHPlVDvKrp7NzgLi7jRmhKiUoa2NUmhl13FtkAGLUVR+ZsYvApBQdBfYm43A4tXXQ4IrYLBA==} - engines: {node: '>=10'} - os-locale@6.0.2: resolution: {integrity: sha512-qIb8bzRqaN/vVqEYZ7lTAg6PonskO7xOmM7OClD28F6eFa4s5XGe4bGpHUHMoCHbNNuR0pDYFeSLiW5bnjWXIA==} engines: {node: '>=12.20'} @@ -10794,8 +10271,8 @@ packages: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} - oxc-resolver@11.17.1: - resolution: {integrity: sha512-pyRXK9kH81zKlirHufkFhOFBZRks8iAMLwPH8gU7lvKFiuzUH9L8MxDEllazwOb8fjXMcWjY1PMDfMJ2/yh5cw==} + oxc-resolver@11.19.1: + resolution: {integrity: sha512-qE/CIg/spwrTBFt5aKmwe3ifeDdLfA2NESN30E42X/lII5ClF8V7Wt6WIJhcGZjp0/Q+nQ+9vgxGk//xZNX2hg==} p-cancelable@1.1.0: resolution: {integrity: sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==} @@ -10805,10 +10282,6 @@ packages: resolution: {integrity: sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==} engines: {node: '>=4'} - p-defer@3.0.0: - resolution: {integrity: sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==} - engines: {node: '>=8'} - p-defer@4.0.1: resolution: {integrity: sha512-Mr5KC5efvAK5VUptYEIopP1bakB85k2IWXaRC0rsh1uwn1L6M0LVml8OIQ4Gudg4oyZakf7FmeRLkMMtZW1i5A==} engines: {node: '>=12'} @@ -10821,10 +10294,6 @@ packages: resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} engines: {node: '>=4'} - p-is-promise@2.1.0: - resolution: {integrity: sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==} - engines: {node: '>=6'} - p-limit@1.3.0: resolution: {integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==} engines: {node: '>=4'} @@ -10989,9 +10458,9 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} - path-scurry@2.0.1: - resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==} - engines: {node: 20 || >=22} + path-scurry@2.0.2: + resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} + engines: {node: 18 || 20 || >=22} path-temp@2.1.1: resolution: {integrity: sha512-2pIjpQb28baC42ttBsQuRRqZ33a8DnWzfSwEFKJjz7SMiCmBECUOebUNLTmmPCG8F4ZIXG7ZRJ8FAxYXdx0Jiw==} @@ -11003,10 +10472,6 @@ packages: path-to-regexp@8.3.0: resolution: {integrity: sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==} - path-type@3.0.0: - resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==} - engines: {node: '>=4'} - path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -11021,9 +10486,6 @@ packages: pathval@1.1.1: resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - pause-stream@0.0.11: - resolution: {integrity: sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==} - picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -11039,8 +10501,8 @@ packages: resolution: {integrity: sha512-OlE82n3yMOE5dY9RMOwxhoWefeMlxwk5IVxoj0sSzSFIlmvhN4obzTvO3s/d/b5JhcgXikjaspsy/HuUDTqbBg==} engines: {node: '>=4'} - pidtree@0.3.1: - resolution: {integrity: sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==} + pidtree@0.5.0: + resolution: {integrity: sha512-9nxspIM7OpZuhBxPg73Zvyq7j1QMPMPsGKTqRc2XOaFQauDvoNz9fM1Wdkjmeo7l9GXOZiRs97sPkuayl39wjA==} engines: {node: '>=0.10'} hasBin: true @@ -11049,10 +10511,6 @@ packages: engines: {node: '>=0.10'} hasBin: true - pify@3.0.0: - resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} - engines: {node: '>=4'} - pirates@4.0.7: resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} engines: {node: '>= 6'} @@ -11128,10 +10586,6 @@ packages: postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.5.6: - resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} - engines: {node: ^10 || ^12 || >=14} - postcss@8.5.8: resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} engines: {node: ^10 || ^12 || >=14} @@ -11144,10 +10598,6 @@ packages: resolution: {integrity: sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==} engines: {node: '>=4'} - prettier-linter-helpers@1.0.1: - resolution: {integrity: sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==} - engines: {node: '>=6.0.0'} - prettier-plugin-ember-template-tag@2.1.3: resolution: {integrity: sha512-FfAvkU+fqDC3Zs8+qGhBHYuwq1DED+UTPMH33QXxivZxRekkItBNXfi1Y+YkIbhCnu6UeTE2aYdbQSLlkOC2bA==} engines: {node: 18.* || >= 20} @@ -11187,14 +10637,6 @@ packages: resolution: {integrity: sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==} engines: {node: '>= 0.6'} - proc-log@3.0.0: - resolution: {integrity: sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - proc-log@5.0.0: - resolution: {integrity: sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==} - engines: {node: ^18.17.0 || >=20.5.0} - proc-log@6.1.0: resolution: {integrity: sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==} engines: {node: ^20.17.0 || >=22.9.0} @@ -11227,24 +10669,19 @@ packages: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} - ps-tree@1.2.0: - resolution: {integrity: sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==} - engines: {node: '>= 0.10'} - hasBin: true - pseudomap@1.0.2: resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} psl@1.15.0: resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} - publint@0.3.17: - resolution: {integrity: sha512-Q3NLegA9XM6usW+dYQRG1g9uEHiYUzcCVBJDJ7yMcWRqVU9LYZUWdqbwMZfmTCFC5PZLQpLAmhvRcQRl3exqkw==} + publint@0.3.18: + resolution: {integrity: sha512-JRJFeBTrfx4qLwEuGFPk+haJOJN97KnPuK01yj+4k/Wj5BgoOK5uNsivporiqBjk2JDaslg7qJOhGRnpltGeog==} engines: {node: '>=18'} hasBin: true - pump@3.0.3: - resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} + pump@3.0.4: + resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} punycode.js@2.3.1: resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} @@ -11259,7 +10696,6 @@ packages: engines: {node: '>=0.6.0', teleport: '>=0.2.0'} deprecated: |- You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other. - (For a CapTP with native promises, see @endo/eventual-send and @endo/captp) qified@0.6.0: @@ -11269,8 +10705,12 @@ packages: qs@1.0.2: resolution: {integrity: sha512-tHuOP9TN/1VmDM/ylApGK1QF3PSIP8I6bHDEfoKNQeViREQ/sfu1bAUrA1hoDun8p8Tpm7jcsz47g+3PiGoYdg==} - qs@6.14.1: - resolution: {integrity: sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==} + qs@6.14.2: + resolution: {integrity: sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==} + engines: {node: '>=0.6'} + + qs@6.15.0: + resolution: {integrity: sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==} engines: {node: '>=0.6'} querystringify@2.2.0: @@ -11336,18 +10776,14 @@ packages: resolution: {integrity: sha512-zz4qv/sKETv7nAkATqSJ9YMbKD8NXRPuA8d17VdYCuNYrVstB1S6UAMU6aytf5vRa9MESbZN7jLZdcmrOxz4gg==} engines: {node: '>=14.6'} - read-package-json-fast@3.0.2: - resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + read-package-json-fast@4.0.0: + resolution: {integrity: sha512-qpt8EwugBWDw2cgE2W+/3oxC+KTez2uSVR8JU9Q36TXPAGCaozfQUs59v4j4GFpWTaw0i6hAZSvOmu1J0uOEUg==} + engines: {node: ^18.17.0 || >=20.5.0} read-pkg-up@7.0.1: resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} engines: {node: '>=8'} - read-pkg@3.0.0: - resolution: {integrity: sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==} - engines: {node: '>=4'} - read-pkg@5.2.0: resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} engines: {node: '>=8'} @@ -11417,10 +10853,6 @@ packages: resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} engines: {node: '>= 0.4'} - regexpp@3.2.0: - resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} - engines: {node: '>=8'} - regexpu-core@6.4.0: resolution: {integrity: sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==} engines: {node: '>=4'} @@ -11564,11 +10996,6 @@ packages: rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - rimraf@2.5.4: - resolution: {integrity: sha512-Lw7SHMjssciQb/rRz7JyPIy9+bbUshEucPoLRvWqy09vC5zQixl8Uet+Zl+SROBB/JMWHJRdCk1qdxNWHNMvlQ==} - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true - rimraf@2.6.3: resolution: {integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==} deprecated: Rimraf versions prior to v4 are no longer supported @@ -11588,8 +11015,8 @@ packages: resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} hasBin: true - rimraf@6.1.2: - resolution: {integrity: sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==} + rimraf@6.1.3: + resolution: {integrity: sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==} engines: {node: 20 || >=22} hasBin: true @@ -11605,13 +11032,6 @@ packages: resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} engines: {node: '>= 18'} - router_js@8.0.6: - resolution: {integrity: sha512-AjGxRDIpTGoAG8admFmvP/cxn1AlwwuosCclMU4R5oGHGt7ER0XtB3l9O04ToBDdPe4ivM/YcLopgBEpJssJ/Q==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - route-recognizer: ^0.3.4 - rsvp: ^4.8.5 - rrweb-cssom@0.7.1: resolution: {integrity: sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==} @@ -11636,10 +11056,6 @@ packages: resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} engines: {node: '>=0.12.0'} - run-async@3.0.0: - resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} - engines: {node: '>=0.12.0'} - run-async@4.0.6: resolution: {integrity: sha512-IoDlSLTs3Yq593mb3ZoKWKXMNu3UpObxhgA/Xuid5p4bbfi2jdY1Hj0m1K+0/tEuQTxIGMhQDqGjKb7RuxGpAQ==} engines: {node: '>=0.12.0'} @@ -11901,10 +11317,6 @@ packages: sort-object-keys@2.1.0: resolution: {integrity: sha512-SOiEnthkJKPv2L6ec6HMwhUcN0/lppkeYuN1x63PbyPRrgSPIuBJCiYxYyvWRTtjMlOi14vQUCGUJqS6PLVm8g==} - sort-package-json@1.57.0: - resolution: {integrity: sha512-FYsjYn2dHTRb41wqnv+uEqCUvBpK3jZcTp9rbz2qDTmel7Pmdtf+i2rLaaPMRZeSVM60V3Se31GyWFpmKs4Q5Q==} - hasBin: true - sort-package-json@2.15.1: resolution: {integrity: sha512-9x9+o8krTT2saA9liI4BljNjwAbvUnWf11Wq+i/iZt8nl2UGYnf3TH5uBydE7VALmP7AGwlfszuEeL8BDyb0YA==} hasBin: true @@ -11965,8 +11377,8 @@ packages: spdx-expression-parse@3.0.1: resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - spdx-license-ids@3.0.22: - resolution: {integrity: sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==} + spdx-license-ids@3.0.23: + resolution: {integrity: sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==} split-string@3.1.0: resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} @@ -11975,9 +11387,6 @@ packages: split2@3.2.2: resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} - split@0.3.3: - resolution: {integrity: sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==} - sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} @@ -11991,10 +11400,6 @@ packages: stacktracey@2.1.8: resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==} - stagehand@1.0.1: - resolution: {integrity: sha512-GqXBq2SPWv9hTXDFKS8WrKK1aISB0aKGHZzH+uD4ShAgs+Fz20ZfoerLOm8U+f62iRWLrw6nimOY/uYuTcVhvg==} - engines: {node: 6.* || 8.* || >= 10.*} - static-extend@0.1.2: resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} engines: {node: '>=0.10.0'} @@ -12015,9 +11420,6 @@ packages: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} - stream-combiner@0.0.4: - resolution: {integrity: sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==} - string-length@4.0.2: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} engines: {node: '>=10'} @@ -12045,10 +11447,6 @@ packages: resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} engines: {node: '>= 0.4'} - string.prototype.padend@3.1.6: - resolution: {integrity: sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==} - engines: {node: '>= 0.4'} - string.prototype.trim@1.2.10: resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} engines: {node: '>= 0.4'} @@ -12098,8 +11496,8 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} - strip-ansi@7.1.2: - resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} engines: {node: '>=12'} strip-bom@3.0.0: @@ -12141,8 +11539,8 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - strnum@2.1.2: - resolution: {integrity: sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ==} + strnum@2.2.0: + resolution: {integrity: sha512-Y7Bj8XyJxnPAORMZj/xltsfo55uOiyHcU2tnAVzHUnSJR/KsEX+9RoDeXEnsXtl/CX4fAcrt64gZ13aGaWPeBg==} stubborn-fs@2.0.0: resolution: {integrity: sha512-Y0AvSwDw8y+nlSNFXMm2g6L51rBGdAQT20J3YSOqxC53Lo3bjWRtr2BKcfYoAf352WYpsZSTURrA0tqhfgudPA==} @@ -12159,12 +11557,24 @@ packages: styled_string@0.0.1: resolution: {integrity: sha512-DU2KZiB6VbPkO2tGSqQ9n96ZstUPjW7X4sGO6V2m1myIQluX0p1Ol8BrA/l6/EesqhMqXOIXs3cJNOy1UuU2BA==} + stylelint-config-recommended@14.0.1: + resolution: {integrity: sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg==} + engines: {node: '>=18.12.0'} + peerDependencies: + stylelint: ^16.1.0 + stylelint-config-recommended@16.0.0: resolution: {integrity: sha512-4RSmPjQegF34wNcK1e1O3Uz91HN8P1aFdFzio90wNK9mjgAI19u5vsU868cVZboKzCaa5XbpvtTzAAGQAxpcXA==} engines: {node: '>=18.12.0'} peerDependencies: stylelint: ^16.16.0 + stylelint-config-standard@36.0.1: + resolution: {integrity: sha512-8aX8mTzJ6cuO8mmD5yon61CWuIM4UD8Q5aBcWKGSf6kg+EC3uhB+iOywpTK4ca6ZL7B49en8yanOFtUW0qNzyw==} + engines: {node: '>=18.12.0'} + peerDependencies: + stylelint: ^16.1.0 + stylelint-config-standard@38.0.0: resolution: {integrity: sha512-uj3JIX+dpFseqd/DJx8Gy3PcRAJhlEZ2IrlFOc4LUxBX/PNMEQ198x7LCOE2Q5oT9Vw8nyc4CIL78xSqPr6iag==} engines: {node: '>=18.12.0'} @@ -12229,10 +11639,6 @@ packages: resolution: {integrity: sha512-vngT2JmkSapgq0z7uIoYtB9kWOOzMihAAYq/D3Pjm/ODOGMgS4r++B+OZ09U4hWR6EaOdy9eqQ7/8ygbH3wehA==} engines: {node: 8.* || >= 10.*} - synckit@0.11.12: - resolution: {integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==} - engines: {node: ^14.18.0 || >=16.0.0} - table@6.9.0: resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==} engines: {node: '>=10.0.0'} @@ -12249,16 +11655,12 @@ packages: resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} engines: {node: '>=6'} - temp-fs@0.9.9: - resolution: {integrity: sha512-WfecDCR1xC9b0nsrzSaxPf3ZuWeWLUWblW4vlDQAa1biQaKHiImHnJfeQocQe/hXKMcolRzgkcVX/7kK4zoWbw==} - engines: {node: '>=0.8.0'} - temp@0.9.4: resolution: {integrity: sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==} engines: {node: '>=6.0.0'} - terser-webpack-plugin@5.3.16: - resolution: {integrity: sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==} + terser-webpack-plugin@5.3.17: + resolution: {integrity: sha512-YR7PtUp6GMU91BgSJmlaX/rS2lGDbAF7D+Wtq7hRO+MiljNmodYvqslzCFiYVAgW+Qoaaia/QUIP4lGXufjdZw==} engines: {node: '>= 10.13.0'} peerDependencies: '@swc/core': '*' @@ -12290,9 +11692,6 @@ packages: engines: {node: '>= 7.*'} hasBin: true - text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - textextensions@2.6.0: resolution: {integrity: sha512-49WtAWS+tcsy93dRt6P0P3AMD2m5PvXRhuEA0kaXos5ZLlujtYmpmFsB+QvWUSxE1ZsstmYXfQ7L40+EcQgpAQ==} engines: {node: '>=0.8'} @@ -12328,15 +11727,15 @@ packages: tldts-core@6.1.86: resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} - tldts-core@7.0.23: - resolution: {integrity: sha512-0g9vrtDQLrNIiCj22HSe9d4mLVG3g5ph5DZ8zCKBr4OtrspmNB6ss7hVyzArAeE88ceZocIEGkyW1Ime7fxPtQ==} + tldts-core@7.0.24: + resolution: {integrity: sha512-pj7yygNMoMRqG7ML2SDQ0xNIOfN3IBDUcPVM2Sg6hP96oFNN2nqnzHreT3z9xLq85IWJyNTvD38O002DdOrPMw==} tldts@6.1.86: resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} hasBin: true - tldts@7.0.23: - resolution: {integrity: sha512-ASdhgQIBSay0R/eXggAkQ53G4nTJqTXqC2kbaBbdDwM7SkjyZyO0OaaN1/FH7U/yCeqOHDwFO5j8+Os/IS1dXw==} + tldts@7.0.24: + resolution: {integrity: sha512-1r6vQTTt1rUiJkI5vX7KG8PR342Ru/5Oh13kEQP2SMbRSZpOey9SrBe27IDxkoWulx8ShWu4K6C0BkctP8Z1bQ==} hasBin: true tmp-sync@1.1.2: @@ -12362,10 +11761,6 @@ packages: tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} - to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - to-object-path@0.3.0: resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} engines: {node: '>=0.10.0'} @@ -12414,6 +11809,9 @@ packages: tracked-built-ins@4.1.0: resolution: {integrity: sha512-v1+jca3sD3LgbAFVsontSONTv7HsZll3yeUB00L6KPwLilFRrY77gvgptDe35fTalk9ea7mmrM2wABD56pTvuw==} + tracked-built-ins@4.1.2: + resolution: {integrity: sha512-KiiV/Pzi7VNKTn9Fip6Ic54AjKgFfqows1Jq3L0WLVqZcvfswdhVxQ9yqqhTXsmgLhVzIgtdzNBH4ExqWf34BQ==} + tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true @@ -12483,10 +11881,6 @@ packages: resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} engines: {node: '>=4'} - type-fest@0.11.0: - resolution: {integrity: sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==} - engines: {node: '>=8'} - type-fest@0.18.1: resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} engines: {node: '>=10'} @@ -12535,14 +11929,11 @@ packages: resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} engines: {node: '>= 0.4'} - typedarray-to-buffer@3.1.5: - resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} - - typescript-eslint@8.55.0: - resolution: {integrity: sha512-HE4wj+r5lmDVS9gdaN0/+iqNvPZwGfnJ5lZuz7s5vLlg9ODw0bIiiETaios9LvFI1U94/VBXGm3CB2Y5cNFMpw==} + typescript-eslint@8.56.1: + resolution: {integrity: sha512-U4lM6pjmBX7J5wk4szltF7I1cGBHXZopnAXCMXb3+fZ3B/0Z3hq3wS/CCUB2NZBNAExK92mCU2tEohWuwVMsDQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.0.0' typescript-memoize@1.1.1: @@ -12579,8 +11970,8 @@ packages: underscore@1.1.7: resolution: {integrity: sha512-w4QtCHoLBXw1mjofIDoMyexaEdWGMedWNDhlWTtT1V1lCRqi65Pnoygkh6+WRdr+Bm8ldkBNkNeCsXGMlQS9HQ==} - underscore@1.13.7: - resolution: {integrity: sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==} + underscore@1.13.8: + resolution: {integrity: sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==} undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} @@ -12702,14 +12093,6 @@ packages: resolution: {integrity: sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - validate-npm-package-name@5.0.1: - resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - validate-npm-package-name@6.0.2: - resolution: {integrity: sha512-IUoow1YUtvoBBC06dXs8bR8B9vuA3aJfmQNKMoaPG/OFsPmoQvw8xh+6Ye25Gx9DQhoEom3Pcu9MKHerm/NpUQ==} - engines: {node: ^18.17.0 || >=20.5.0} - validate-npm-package-name@7.0.2: resolution: {integrity: sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A==} engines: {node: ^20.17.0 || >=22.9.0} @@ -12851,12 +12234,12 @@ packages: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} - webpack-sources@3.3.3: - resolution: {integrity: sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==} + webpack-sources@3.3.4: + resolution: {integrity: sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==} engines: {node: '>=10.13.0'} - webpack@5.105.1: - resolution: {integrity: sha512-Gdj3X74CLJJ8zy4URmK42W7wTZUJrqL+z8nyGEr4dTN0kb3nVs+ZvjbTOqRYPD7qX4tUmwyHL9Q9K6T1seW6Yw==} + webpack@5.105.4: + resolution: {integrity: sha512-jTywjboN9aHxFlToqb0K0Zs9SbBoW4zRUlGzI2tYNxVYcEi/IPpn+Xi4ye5jTLvX2YeLuic/IvxNot+Q1jMoOw==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -12914,16 +12297,16 @@ packages: engines: {node: '>= 8'} hasBin: true - which@3.0.1: - resolution: {integrity: sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true - which@4.0.0: resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==} engines: {node: ^16.13.0 || >=18.0.0} hasBin: true + which@5.0.0: + resolution: {integrity: sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==} + engines: {node: ^18.17.0 || >=20.5.0} + hasBin: true + wide-align@1.1.5: resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} @@ -12947,9 +12330,6 @@ packages: workerpool@6.5.1: resolution: {integrity: sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==} - workerpool@9.3.4: - resolution: {integrity: sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==} - wrap-ansi@3.0.1: resolution: {integrity: sha512-iXR3tDXpbnTpzjKSylUJRkLuOrEC7hwEB221cgn6wtF8wpmz28puFXAEfPT5zrjM3wahygB//VuWEr1vTkDcNQ==} engines: {node: '>=4'} @@ -12969,9 +12349,6 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - write-file-atomic@3.0.3: - resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} - write-file-atomic@4.0.2: resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -13008,10 +12385,6 @@ packages: utf-8-validate: optional: true - xdg-basedir@4.0.0: - resolution: {integrity: sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==} - engines: {node: '>=8'} - xdg-basedir@5.1.0: resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==} engines: {node: '>=12'} @@ -13072,10 +12445,6 @@ packages: resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==} engines: {node: '>=12.20'} - yoctocolors-cjs@2.1.3: - resolution: {integrity: sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==} - engines: {node: '>=18'} - yoctocolors@2.1.2: resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} engines: {node: '>=18'} @@ -13106,21 +12475,21 @@ snapshots: '@aws-crypto/crc32@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.1 + '@aws-sdk/types': 3.973.5 tslib: 2.8.1 '@aws-crypto/crc32c@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.1 + '@aws-sdk/types': 3.973.5 tslib: 2.8.1 '@aws-crypto/sha1-browser@5.2.0': dependencies: '@aws-crypto/supports-web-crypto': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-locate-window': 3.965.4 + '@aws-sdk/types': 3.973.5 + '@aws-sdk/util-locate-window': 3.965.5 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 @@ -13129,15 +12498,15 @@ snapshots: '@aws-crypto/sha256-js': 5.2.0 '@aws-crypto/supports-web-crypto': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-locate-window': 3.965.4 + '@aws-sdk/types': 3.973.5 + '@aws-sdk/util-locate-window': 3.965.5 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 '@aws-crypto/sha256-js@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.1 + '@aws-sdk/types': 3.973.5 tslib: 2.8.1 '@aws-crypto/supports-web-crypto@5.2.0': @@ -13146,452 +12515,401 @@ snapshots: '@aws-crypto/util@5.2.0': dependencies: - '@aws-sdk/types': 3.973.1 + '@aws-sdk/types': 3.973.5 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 - '@aws-sdk/client-s3@3.986.0': + '@aws-sdk/client-s3@3.1003.0': dependencies: '@aws-crypto/sha1-browser': 5.2.0 '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.973.7 - '@aws-sdk/credential-provider-node': 3.972.6 - '@aws-sdk/middleware-bucket-endpoint': 3.972.3 - '@aws-sdk/middleware-expect-continue': 3.972.3 - '@aws-sdk/middleware-flexible-checksums': 3.972.5 - '@aws-sdk/middleware-host-header': 3.972.3 - '@aws-sdk/middleware-location-constraint': 3.972.3 - '@aws-sdk/middleware-logger': 3.972.3 - '@aws-sdk/middleware-recursion-detection': 3.972.3 - '@aws-sdk/middleware-sdk-s3': 3.972.7 - '@aws-sdk/middleware-ssec': 3.972.3 - '@aws-sdk/middleware-user-agent': 3.972.7 - '@aws-sdk/region-config-resolver': 3.972.3 - '@aws-sdk/signature-v4-multi-region': 3.986.0 - '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-endpoints': 3.986.0 - '@aws-sdk/util-user-agent-browser': 3.972.3 - '@aws-sdk/util-user-agent-node': 3.972.5 - '@smithy/config-resolver': 4.4.6 - '@smithy/core': 3.23.0 - '@smithy/eventstream-serde-browser': 4.2.8 - '@smithy/eventstream-serde-config-resolver': 4.3.8 - '@smithy/eventstream-serde-node': 4.2.8 - '@smithy/fetch-http-handler': 5.3.9 - '@smithy/hash-blob-browser': 4.2.9 - '@smithy/hash-node': 4.2.8 - '@smithy/hash-stream-node': 4.2.8 - '@smithy/invalid-dependency': 4.2.8 - '@smithy/md5-js': 4.2.8 - '@smithy/middleware-content-length': 4.2.8 - '@smithy/middleware-endpoint': 4.4.14 - '@smithy/middleware-retry': 4.4.31 - '@smithy/middleware-serde': 4.2.9 - '@smithy/middleware-stack': 4.2.8 - '@smithy/node-config-provider': 4.3.8 - '@smithy/node-http-handler': 4.4.10 - '@smithy/protocol-http': 5.3.8 - '@smithy/smithy-client': 4.11.3 - '@smithy/types': 4.12.0 - '@smithy/url-parser': 4.2.8 - '@smithy/util-base64': 4.3.0 - '@smithy/util-body-length-browser': 4.2.0 - '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.30 - '@smithy/util-defaults-mode-node': 4.2.33 - '@smithy/util-endpoints': 3.2.8 - '@smithy/util-middleware': 4.2.8 - '@smithy/util-retry': 4.2.8 - '@smithy/util-stream': 4.5.12 - '@smithy/util-utf8': 4.2.0 - '@smithy/util-waiter': 4.2.8 - tslib: 2.8.1 - transitivePeerDependencies: - - aws-crt - - '@aws-sdk/client-sso@3.985.0': - dependencies: - '@aws-crypto/sha256-browser': 5.2.0 - '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.973.7 - '@aws-sdk/middleware-host-header': 3.972.3 - '@aws-sdk/middleware-logger': 3.972.3 - '@aws-sdk/middleware-recursion-detection': 3.972.3 - '@aws-sdk/middleware-user-agent': 3.972.7 - '@aws-sdk/region-config-resolver': 3.972.3 - '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-endpoints': 3.985.0 - '@aws-sdk/util-user-agent-browser': 3.972.3 - '@aws-sdk/util-user-agent-node': 3.972.5 - '@smithy/config-resolver': 4.4.6 - '@smithy/core': 3.23.0 - '@smithy/fetch-http-handler': 5.3.9 - '@smithy/hash-node': 4.2.8 - '@smithy/invalid-dependency': 4.2.8 - '@smithy/middleware-content-length': 4.2.8 - '@smithy/middleware-endpoint': 4.4.14 - '@smithy/middleware-retry': 4.4.31 - '@smithy/middleware-serde': 4.2.9 - '@smithy/middleware-stack': 4.2.8 - '@smithy/node-config-provider': 4.3.8 - '@smithy/node-http-handler': 4.4.10 - '@smithy/protocol-http': 5.3.8 - '@smithy/smithy-client': 4.11.3 - '@smithy/types': 4.12.0 - '@smithy/url-parser': 4.2.8 - '@smithy/util-base64': 4.3.0 - '@smithy/util-body-length-browser': 4.2.0 - '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.30 - '@smithy/util-defaults-mode-node': 4.2.33 - '@smithy/util-endpoints': 3.2.8 - '@smithy/util-middleware': 4.2.8 - '@smithy/util-retry': 4.2.8 - '@smithy/util-utf8': 4.2.0 + '@aws-sdk/core': 3.973.18 + '@aws-sdk/credential-provider-node': 3.972.17 + '@aws-sdk/middleware-bucket-endpoint': 3.972.7 + '@aws-sdk/middleware-expect-continue': 3.972.7 + '@aws-sdk/middleware-flexible-checksums': 3.973.4 + '@aws-sdk/middleware-host-header': 3.972.7 + '@aws-sdk/middleware-location-constraint': 3.972.7 + '@aws-sdk/middleware-logger': 3.972.7 + '@aws-sdk/middleware-recursion-detection': 3.972.7 + '@aws-sdk/middleware-sdk-s3': 3.972.18 + '@aws-sdk/middleware-ssec': 3.972.7 + '@aws-sdk/middleware-user-agent': 3.972.18 + '@aws-sdk/region-config-resolver': 3.972.7 + '@aws-sdk/signature-v4-multi-region': 3.996.6 + '@aws-sdk/types': 3.973.5 + '@aws-sdk/util-endpoints': 3.996.4 + '@aws-sdk/util-user-agent-browser': 3.972.7 + '@aws-sdk/util-user-agent-node': 3.973.3 + '@smithy/config-resolver': 4.4.10 + '@smithy/core': 3.23.8 + '@smithy/eventstream-serde-browser': 4.2.11 + '@smithy/eventstream-serde-config-resolver': 4.3.11 + '@smithy/eventstream-serde-node': 4.2.11 + '@smithy/fetch-http-handler': 5.3.13 + '@smithy/hash-blob-browser': 4.2.12 + '@smithy/hash-node': 4.2.11 + '@smithy/hash-stream-node': 4.2.11 + '@smithy/invalid-dependency': 4.2.11 + '@smithy/md5-js': 4.2.11 + '@smithy/middleware-content-length': 4.2.11 + '@smithy/middleware-endpoint': 4.4.22 + '@smithy/middleware-retry': 4.4.39 + '@smithy/middleware-serde': 4.2.12 + '@smithy/middleware-stack': 4.2.11 + '@smithy/node-config-provider': 4.3.11 + '@smithy/node-http-handler': 4.4.14 + '@smithy/protocol-http': 5.3.11 + '@smithy/smithy-client': 4.12.2 + '@smithy/types': 4.13.0 + '@smithy/url-parser': 4.2.11 + '@smithy/util-base64': 4.3.2 + '@smithy/util-body-length-browser': 4.2.2 + '@smithy/util-body-length-node': 4.2.3 + '@smithy/util-defaults-mode-browser': 4.3.38 + '@smithy/util-defaults-mode-node': 4.2.41 + '@smithy/util-endpoints': 3.3.2 + '@smithy/util-middleware': 4.2.11 + '@smithy/util-retry': 4.2.11 + '@smithy/util-stream': 4.5.17 + '@smithy/util-utf8': 4.2.2 + '@smithy/util-waiter': 4.2.11 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/core@3.973.7': - dependencies: - '@aws-sdk/types': 3.973.1 - '@aws-sdk/xml-builder': 3.972.4 - '@smithy/core': 3.23.0 - '@smithy/node-config-provider': 4.3.8 - '@smithy/property-provider': 4.2.8 - '@smithy/protocol-http': 5.3.8 - '@smithy/signature-v4': 5.3.8 - '@smithy/smithy-client': 4.11.3 - '@smithy/types': 4.12.0 - '@smithy/util-base64': 4.3.0 - '@smithy/util-middleware': 4.2.8 - '@smithy/util-utf8': 4.2.0 + '@aws-sdk/core@3.973.18': + dependencies: + '@aws-sdk/types': 3.973.5 + '@aws-sdk/xml-builder': 3.972.10 + '@smithy/core': 3.23.8 + '@smithy/node-config-provider': 4.3.11 + '@smithy/property-provider': 4.2.11 + '@smithy/protocol-http': 5.3.11 + '@smithy/signature-v4': 5.3.11 + '@smithy/smithy-client': 4.12.2 + '@smithy/types': 4.13.0 + '@smithy/util-base64': 4.3.2 + '@smithy/util-middleware': 4.2.11 + '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 - '@aws-sdk/crc64-nvme@3.972.0': + '@aws-sdk/crc64-nvme@3.972.4': dependencies: - '@smithy/types': 4.12.0 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-env@3.972.5': + '@aws-sdk/credential-provider-env@3.972.16': dependencies: - '@aws-sdk/core': 3.973.7 - '@aws-sdk/types': 3.973.1 - '@smithy/property-provider': 4.2.8 - '@smithy/types': 4.12.0 + '@aws-sdk/core': 3.973.18 + '@aws-sdk/types': 3.973.5 + '@smithy/property-provider': 4.2.11 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-http@3.972.7': - dependencies: - '@aws-sdk/core': 3.973.7 - '@aws-sdk/types': 3.973.1 - '@smithy/fetch-http-handler': 5.3.9 - '@smithy/node-http-handler': 4.4.10 - '@smithy/property-provider': 4.2.8 - '@smithy/protocol-http': 5.3.8 - '@smithy/smithy-client': 4.11.3 - '@smithy/types': 4.12.0 - '@smithy/util-stream': 4.5.12 + '@aws-sdk/credential-provider-http@3.972.18': + dependencies: + '@aws-sdk/core': 3.973.18 + '@aws-sdk/types': 3.973.5 + '@smithy/fetch-http-handler': 5.3.13 + '@smithy/node-http-handler': 4.4.14 + '@smithy/property-provider': 4.2.11 + '@smithy/protocol-http': 5.3.11 + '@smithy/smithy-client': 4.12.2 + '@smithy/types': 4.13.0 + '@smithy/util-stream': 4.5.17 tslib: 2.8.1 - '@aws-sdk/credential-provider-ini@3.972.5': - dependencies: - '@aws-sdk/core': 3.973.7 - '@aws-sdk/credential-provider-env': 3.972.5 - '@aws-sdk/credential-provider-http': 3.972.7 - '@aws-sdk/credential-provider-login': 3.972.5 - '@aws-sdk/credential-provider-process': 3.972.5 - '@aws-sdk/credential-provider-sso': 3.972.5 - '@aws-sdk/credential-provider-web-identity': 3.972.5 - '@aws-sdk/nested-clients': 3.985.0 - '@aws-sdk/types': 3.973.1 - '@smithy/credential-provider-imds': 4.2.8 - '@smithy/property-provider': 4.2.8 - '@smithy/shared-ini-file-loader': 4.4.3 - '@smithy/types': 4.12.0 + '@aws-sdk/credential-provider-ini@3.972.16': + dependencies: + '@aws-sdk/core': 3.973.18 + '@aws-sdk/credential-provider-env': 3.972.16 + '@aws-sdk/credential-provider-http': 3.972.18 + '@aws-sdk/credential-provider-login': 3.972.16 + '@aws-sdk/credential-provider-process': 3.972.16 + '@aws-sdk/credential-provider-sso': 3.972.16 + '@aws-sdk/credential-provider-web-identity': 3.972.16 + '@aws-sdk/nested-clients': 3.996.6 + '@aws-sdk/types': 3.973.5 + '@smithy/credential-provider-imds': 4.2.11 + '@smithy/property-provider': 4.2.11 + '@smithy/shared-ini-file-loader': 4.4.6 + '@smithy/types': 4.13.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-login@3.972.5': + '@aws-sdk/credential-provider-login@3.972.16': dependencies: - '@aws-sdk/core': 3.973.7 - '@aws-sdk/nested-clients': 3.985.0 - '@aws-sdk/types': 3.973.1 - '@smithy/property-provider': 4.2.8 - '@smithy/protocol-http': 5.3.8 - '@smithy/shared-ini-file-loader': 4.4.3 - '@smithy/types': 4.12.0 + '@aws-sdk/core': 3.973.18 + '@aws-sdk/nested-clients': 3.996.6 + '@aws-sdk/types': 3.973.5 + '@smithy/property-provider': 4.2.11 + '@smithy/protocol-http': 5.3.11 + '@smithy/shared-ini-file-loader': 4.4.6 + '@smithy/types': 4.13.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-node@3.972.6': - dependencies: - '@aws-sdk/credential-provider-env': 3.972.5 - '@aws-sdk/credential-provider-http': 3.972.7 - '@aws-sdk/credential-provider-ini': 3.972.5 - '@aws-sdk/credential-provider-process': 3.972.5 - '@aws-sdk/credential-provider-sso': 3.972.5 - '@aws-sdk/credential-provider-web-identity': 3.972.5 - '@aws-sdk/types': 3.973.1 - '@smithy/credential-provider-imds': 4.2.8 - '@smithy/property-provider': 4.2.8 - '@smithy/shared-ini-file-loader': 4.4.3 - '@smithy/types': 4.12.0 + '@aws-sdk/credential-provider-node@3.972.17': + dependencies: + '@aws-sdk/credential-provider-env': 3.972.16 + '@aws-sdk/credential-provider-http': 3.972.18 + '@aws-sdk/credential-provider-ini': 3.972.16 + '@aws-sdk/credential-provider-process': 3.972.16 + '@aws-sdk/credential-provider-sso': 3.972.16 + '@aws-sdk/credential-provider-web-identity': 3.972.16 + '@aws-sdk/types': 3.973.5 + '@smithy/credential-provider-imds': 4.2.11 + '@smithy/property-provider': 4.2.11 + '@smithy/shared-ini-file-loader': 4.4.6 + '@smithy/types': 4.13.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-process@3.972.5': + '@aws-sdk/credential-provider-process@3.972.16': dependencies: - '@aws-sdk/core': 3.973.7 - '@aws-sdk/types': 3.973.1 - '@smithy/property-provider': 4.2.8 - '@smithy/shared-ini-file-loader': 4.4.3 - '@smithy/types': 4.12.0 + '@aws-sdk/core': 3.973.18 + '@aws-sdk/types': 3.973.5 + '@smithy/property-provider': 4.2.11 + '@smithy/shared-ini-file-loader': 4.4.6 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-sso@3.972.5': + '@aws-sdk/credential-provider-sso@3.972.16': dependencies: - '@aws-sdk/client-sso': 3.985.0 - '@aws-sdk/core': 3.973.7 - '@aws-sdk/token-providers': 3.985.0 - '@aws-sdk/types': 3.973.1 - '@smithy/property-provider': 4.2.8 - '@smithy/shared-ini-file-loader': 4.4.3 - '@smithy/types': 4.12.0 + '@aws-sdk/core': 3.973.18 + '@aws-sdk/nested-clients': 3.996.6 + '@aws-sdk/token-providers': 3.1003.0 + '@aws-sdk/types': 3.973.5 + '@smithy/property-provider': 4.2.11 + '@smithy/shared-ini-file-loader': 4.4.6 + '@smithy/types': 4.13.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-web-identity@3.972.5': + '@aws-sdk/credential-provider-web-identity@3.972.16': dependencies: - '@aws-sdk/core': 3.973.7 - '@aws-sdk/nested-clients': 3.985.0 - '@aws-sdk/types': 3.973.1 - '@smithy/property-provider': 4.2.8 - '@smithy/shared-ini-file-loader': 4.4.3 - '@smithy/types': 4.12.0 + '@aws-sdk/core': 3.973.18 + '@aws-sdk/nested-clients': 3.996.6 + '@aws-sdk/types': 3.973.5 + '@smithy/property-provider': 4.2.11 + '@smithy/shared-ini-file-loader': 4.4.6 + '@smithy/types': 4.13.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/middleware-bucket-endpoint@3.972.3': + '@aws-sdk/middleware-bucket-endpoint@3.972.7': dependencies: - '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-arn-parser': 3.972.2 - '@smithy/node-config-provider': 4.3.8 - '@smithy/protocol-http': 5.3.8 - '@smithy/types': 4.12.0 - '@smithy/util-config-provider': 4.2.0 + '@aws-sdk/types': 3.973.5 + '@aws-sdk/util-arn-parser': 3.972.3 + '@smithy/node-config-provider': 4.3.11 + '@smithy/protocol-http': 5.3.11 + '@smithy/types': 4.13.0 + '@smithy/util-config-provider': 4.2.2 tslib: 2.8.1 - '@aws-sdk/middleware-expect-continue@3.972.3': + '@aws-sdk/middleware-expect-continue@3.972.7': dependencies: - '@aws-sdk/types': 3.973.1 - '@smithy/protocol-http': 5.3.8 - '@smithy/types': 4.12.0 + '@aws-sdk/types': 3.973.5 + '@smithy/protocol-http': 5.3.11 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@aws-sdk/middleware-flexible-checksums@3.972.5': + '@aws-sdk/middleware-flexible-checksums@3.973.4': dependencies: '@aws-crypto/crc32': 5.2.0 '@aws-crypto/crc32c': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/core': 3.973.7 - '@aws-sdk/crc64-nvme': 3.972.0 - '@aws-sdk/types': 3.973.1 - '@smithy/is-array-buffer': 4.2.0 - '@smithy/node-config-provider': 4.3.8 - '@smithy/protocol-http': 5.3.8 - '@smithy/types': 4.12.0 - '@smithy/util-middleware': 4.2.8 - '@smithy/util-stream': 4.5.12 - '@smithy/util-utf8': 4.2.0 + '@aws-sdk/core': 3.973.18 + '@aws-sdk/crc64-nvme': 3.972.4 + '@aws-sdk/types': 3.973.5 + '@smithy/is-array-buffer': 4.2.2 + '@smithy/node-config-provider': 4.3.11 + '@smithy/protocol-http': 5.3.11 + '@smithy/types': 4.13.0 + '@smithy/util-middleware': 4.2.11 + '@smithy/util-stream': 4.5.17 + '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 - '@aws-sdk/middleware-host-header@3.972.3': + '@aws-sdk/middleware-host-header@3.972.7': dependencies: - '@aws-sdk/types': 3.973.1 - '@smithy/protocol-http': 5.3.8 - '@smithy/types': 4.12.0 + '@aws-sdk/types': 3.973.5 + '@smithy/protocol-http': 5.3.11 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@aws-sdk/middleware-location-constraint@3.972.3': + '@aws-sdk/middleware-location-constraint@3.972.7': dependencies: - '@aws-sdk/types': 3.973.1 - '@smithy/types': 4.12.0 + '@aws-sdk/types': 3.973.5 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@aws-sdk/middleware-logger@3.972.3': + '@aws-sdk/middleware-logger@3.972.7': dependencies: - '@aws-sdk/types': 3.973.1 - '@smithy/types': 4.12.0 + '@aws-sdk/types': 3.973.5 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@aws-sdk/middleware-recursion-detection@3.972.3': + '@aws-sdk/middleware-recursion-detection@3.972.7': dependencies: - '@aws-sdk/types': 3.973.1 + '@aws-sdk/types': 3.973.5 '@aws/lambda-invoke-store': 0.2.3 - '@smithy/protocol-http': 5.3.8 - '@smithy/types': 4.12.0 + '@smithy/protocol-http': 5.3.11 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@aws-sdk/middleware-sdk-s3@3.972.7': - dependencies: - '@aws-sdk/core': 3.973.7 - '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-arn-parser': 3.972.2 - '@smithy/core': 3.23.0 - '@smithy/node-config-provider': 4.3.8 - '@smithy/protocol-http': 5.3.8 - '@smithy/signature-v4': 5.3.8 - '@smithy/smithy-client': 4.11.3 - '@smithy/types': 4.12.0 - '@smithy/util-config-provider': 4.2.0 - '@smithy/util-middleware': 4.2.8 - '@smithy/util-stream': 4.5.12 - '@smithy/util-utf8': 4.2.0 + '@aws-sdk/middleware-sdk-s3@3.972.18': + dependencies: + '@aws-sdk/core': 3.973.18 + '@aws-sdk/types': 3.973.5 + '@aws-sdk/util-arn-parser': 3.972.3 + '@smithy/core': 3.23.8 + '@smithy/node-config-provider': 4.3.11 + '@smithy/protocol-http': 5.3.11 + '@smithy/signature-v4': 5.3.11 + '@smithy/smithy-client': 4.12.2 + '@smithy/types': 4.13.0 + '@smithy/util-config-provider': 4.2.2 + '@smithy/util-middleware': 4.2.11 + '@smithy/util-stream': 4.5.17 + '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 - '@aws-sdk/middleware-ssec@3.972.3': + '@aws-sdk/middleware-ssec@3.972.7': dependencies: - '@aws-sdk/types': 3.973.1 - '@smithy/types': 4.12.0 + '@aws-sdk/types': 3.973.5 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@aws-sdk/middleware-user-agent@3.972.7': + '@aws-sdk/middleware-user-agent@3.972.18': dependencies: - '@aws-sdk/core': 3.973.7 - '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-endpoints': 3.985.0 - '@smithy/core': 3.23.0 - '@smithy/protocol-http': 5.3.8 - '@smithy/types': 4.12.0 + '@aws-sdk/core': 3.973.18 + '@aws-sdk/types': 3.973.5 + '@aws-sdk/util-endpoints': 3.996.4 + '@smithy/core': 3.23.8 + '@smithy/protocol-http': 5.3.11 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@aws-sdk/nested-clients@3.985.0': + '@aws-sdk/nested-clients@3.996.6': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.973.7 - '@aws-sdk/middleware-host-header': 3.972.3 - '@aws-sdk/middleware-logger': 3.972.3 - '@aws-sdk/middleware-recursion-detection': 3.972.3 - '@aws-sdk/middleware-user-agent': 3.972.7 - '@aws-sdk/region-config-resolver': 3.972.3 - '@aws-sdk/types': 3.973.1 - '@aws-sdk/util-endpoints': 3.985.0 - '@aws-sdk/util-user-agent-browser': 3.972.3 - '@aws-sdk/util-user-agent-node': 3.972.5 - '@smithy/config-resolver': 4.4.6 - '@smithy/core': 3.23.0 - '@smithy/fetch-http-handler': 5.3.9 - '@smithy/hash-node': 4.2.8 - '@smithy/invalid-dependency': 4.2.8 - '@smithy/middleware-content-length': 4.2.8 - '@smithy/middleware-endpoint': 4.4.14 - '@smithy/middleware-retry': 4.4.31 - '@smithy/middleware-serde': 4.2.9 - '@smithy/middleware-stack': 4.2.8 - '@smithy/node-config-provider': 4.3.8 - '@smithy/node-http-handler': 4.4.10 - '@smithy/protocol-http': 5.3.8 - '@smithy/smithy-client': 4.11.3 - '@smithy/types': 4.12.0 - '@smithy/url-parser': 4.2.8 - '@smithy/util-base64': 4.3.0 - '@smithy/util-body-length-browser': 4.2.0 - '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.30 - '@smithy/util-defaults-mode-node': 4.2.33 - '@smithy/util-endpoints': 3.2.8 - '@smithy/util-middleware': 4.2.8 - '@smithy/util-retry': 4.2.8 - '@smithy/util-utf8': 4.2.0 + '@aws-sdk/core': 3.973.18 + '@aws-sdk/middleware-host-header': 3.972.7 + '@aws-sdk/middleware-logger': 3.972.7 + '@aws-sdk/middleware-recursion-detection': 3.972.7 + '@aws-sdk/middleware-user-agent': 3.972.18 + '@aws-sdk/region-config-resolver': 3.972.7 + '@aws-sdk/types': 3.973.5 + '@aws-sdk/util-endpoints': 3.996.4 + '@aws-sdk/util-user-agent-browser': 3.972.7 + '@aws-sdk/util-user-agent-node': 3.973.3 + '@smithy/config-resolver': 4.4.10 + '@smithy/core': 3.23.8 + '@smithy/fetch-http-handler': 5.3.13 + '@smithy/hash-node': 4.2.11 + '@smithy/invalid-dependency': 4.2.11 + '@smithy/middleware-content-length': 4.2.11 + '@smithy/middleware-endpoint': 4.4.22 + '@smithy/middleware-retry': 4.4.39 + '@smithy/middleware-serde': 4.2.12 + '@smithy/middleware-stack': 4.2.11 + '@smithy/node-config-provider': 4.3.11 + '@smithy/node-http-handler': 4.4.14 + '@smithy/protocol-http': 5.3.11 + '@smithy/smithy-client': 4.12.2 + '@smithy/types': 4.13.0 + '@smithy/url-parser': 4.2.11 + '@smithy/util-base64': 4.3.2 + '@smithy/util-body-length-browser': 4.2.2 + '@smithy/util-body-length-node': 4.2.3 + '@smithy/util-defaults-mode-browser': 4.3.38 + '@smithy/util-defaults-mode-node': 4.2.41 + '@smithy/util-endpoints': 3.3.2 + '@smithy/util-middleware': 4.2.11 + '@smithy/util-retry': 4.2.11 + '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/region-config-resolver@3.972.3': + '@aws-sdk/region-config-resolver@3.972.7': dependencies: - '@aws-sdk/types': 3.973.1 - '@smithy/config-resolver': 4.4.6 - '@smithy/node-config-provider': 4.3.8 - '@smithy/types': 4.12.0 + '@aws-sdk/types': 3.973.5 + '@smithy/config-resolver': 4.4.10 + '@smithy/node-config-provider': 4.3.11 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@aws-sdk/signature-v4-multi-region@3.986.0': + '@aws-sdk/signature-v4-multi-region@3.996.6': dependencies: - '@aws-sdk/middleware-sdk-s3': 3.972.7 - '@aws-sdk/types': 3.973.1 - '@smithy/protocol-http': 5.3.8 - '@smithy/signature-v4': 5.3.8 - '@smithy/types': 4.12.0 + '@aws-sdk/middleware-sdk-s3': 3.972.18 + '@aws-sdk/types': 3.973.5 + '@smithy/protocol-http': 5.3.11 + '@smithy/signature-v4': 5.3.11 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@aws-sdk/token-providers@3.985.0': + '@aws-sdk/token-providers@3.1003.0': dependencies: - '@aws-sdk/core': 3.973.7 - '@aws-sdk/nested-clients': 3.985.0 - '@aws-sdk/types': 3.973.1 - '@smithy/property-provider': 4.2.8 - '@smithy/shared-ini-file-loader': 4.4.3 - '@smithy/types': 4.12.0 + '@aws-sdk/core': 3.973.18 + '@aws-sdk/nested-clients': 3.996.6 + '@aws-sdk/types': 3.973.5 + '@smithy/property-provider': 4.2.11 + '@smithy/shared-ini-file-loader': 4.4.6 + '@smithy/types': 4.13.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/types@3.973.1': - dependencies: - '@smithy/types': 4.12.0 - tslib: 2.8.1 - - '@aws-sdk/util-arn-parser@3.972.2': + '@aws-sdk/types@3.973.5': dependencies: + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@aws-sdk/util-endpoints@3.985.0': + '@aws-sdk/util-arn-parser@3.972.3': dependencies: - '@aws-sdk/types': 3.973.1 - '@smithy/types': 4.12.0 - '@smithy/url-parser': 4.2.8 - '@smithy/util-endpoints': 3.2.8 tslib: 2.8.1 - '@aws-sdk/util-endpoints@3.986.0': + '@aws-sdk/util-endpoints@3.996.4': dependencies: - '@aws-sdk/types': 3.973.1 - '@smithy/types': 4.12.0 - '@smithy/url-parser': 4.2.8 - '@smithy/util-endpoints': 3.2.8 + '@aws-sdk/types': 3.973.5 + '@smithy/types': 4.13.0 + '@smithy/url-parser': 4.2.11 + '@smithy/util-endpoints': 3.3.2 tslib: 2.8.1 - '@aws-sdk/util-locate-window@3.965.4': + '@aws-sdk/util-locate-window@3.965.5': dependencies: tslib: 2.8.1 - '@aws-sdk/util-user-agent-browser@3.972.3': + '@aws-sdk/util-user-agent-browser@3.972.7': dependencies: - '@aws-sdk/types': 3.973.1 - '@smithy/types': 4.12.0 + '@aws-sdk/types': 3.973.5 + '@smithy/types': 4.13.0 bowser: 2.14.1 tslib: 2.8.1 - '@aws-sdk/util-user-agent-node@3.972.5': + '@aws-sdk/util-user-agent-node@3.973.3': dependencies: - '@aws-sdk/middleware-user-agent': 3.972.7 - '@aws-sdk/types': 3.973.1 - '@smithy/node-config-provider': 4.3.8 - '@smithy/types': 4.12.0 + '@aws-sdk/middleware-user-agent': 3.972.18 + '@aws-sdk/types': 3.973.5 + '@smithy/node-config-provider': 4.3.11 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@aws-sdk/xml-builder@3.972.4': + '@aws-sdk/xml-builder@3.972.10': dependencies: - '@smithy/types': 4.12.0 - fast-xml-parser: 5.3.4 + '@smithy/types': 4.13.0 + fast-xml-parser: 5.4.1 tslib: 2.8.1 '@aws/lambda-invoke-store@0.2.3': {} @@ -13629,7 +12947,7 @@ snapshots: '@babel/code-frame': 7.29.0 '@babel/generator': 7.29.1 '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0(supports-color@8.1.1))(supports-color@8.1.1) '@babel/helpers': 7.28.6 '@babel/parser': 7.29.0 '@babel/template': 7.28.6 @@ -13644,29 +12962,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1)': - dependencies: - '@babel/core': 7.29.0 - '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 - eslint: 8.57.1 - eslint-visitor-keys: 2.1.0 - semver: 6.3.1 - - '@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@9.39.2)': + '@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@9.39.3)': dependencies: '@babel/core': 7.29.0 '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 - eslint: 9.39.2 + eslint: 9.39.3 eslint-visitor-keys: 2.1.0 semver: 6.3.1 - '@babel/generator@7.23.6': - dependencies: - '@babel/types': 7.29.0 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - jsesc: 2.5.2 - '@babel/generator@7.29.1': dependencies: '@babel/parser': 7.29.0 @@ -13713,20 +13016,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-member-expression-to-functions': 7.28.5(supports-color@8.1.1) - '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/helper-skip-transparent-expression-wrappers': 7.27.1(supports-color@8.1.1) - '@babel/traverse': 7.29.0(supports-color@8.1.1) - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - optional: true - '@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@7.29.0(supports-color@8.1.1))': dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) @@ -13752,7 +13041,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-define-polyfill-provider@0.6.6(@babel/core@7.29.0)(supports-color@8.1.1)': + '@babel/helper-define-polyfill-provider@0.6.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-compilation-targets': 7.28.6 @@ -13763,29 +13052,16 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-environment-visitor@7.24.7': + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-member-expression-to-functions@7.28.5(supports-color@8.1.1)': dependencies: + '@babel/traverse': 7.29.0(supports-color@8.1.1) '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color - '@babel/helper-function-name@7.24.7': - dependencies: - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 - - '@babel/helper-globals@7.28.0': {} - - '@babel/helper-hoist-variables@7.24.7': - dependencies: - '@babel/types': 7.29.0 - - '@babel/helper-member-expression-to-functions@7.28.5(supports-color@8.1.1)': - dependencies: - '@babel/traverse': 7.29.0(supports-color@8.1.1) - '@babel/types': 7.29.0 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-imports@7.28.6(supports-color@8.1.1)': + '@babel/helper-module-imports@7.28.6(supports-color@8.1.1)': dependencies: '@babel/traverse': 7.29.0(supports-color@8.1.1) '@babel/types': 7.29.0 @@ -13810,15 +13086,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-module-imports': 7.28.6(supports-color@8.1.1) - '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.29.0(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - '@babel/helper-optimise-call-expression@7.27.1': dependencies: '@babel/types': 7.29.0 @@ -13843,16 +13110,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-wrap-function': 7.28.6(supports-color@8.1.1) - '@babel/traverse': 7.29.0(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - optional: true - '@babel/helper-replace-supers@7.28.6(@babel/core@7.29.0(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) @@ -13871,16 +13128,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-replace-supers@7.28.6(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-member-expression-to-functions': 7.28.5(supports-color@8.1.1) - '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/traverse': 7.29.0(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - optional: true - '@babel/helper-skip-transparent-expression-wrappers@7.27.1(supports-color@8.1.1)': dependencies: '@babel/traverse': 7.29.0(supports-color@8.1.1) @@ -13888,10 +13135,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-split-export-declaration@7.24.7': - dependencies: - '@babel/types': 7.29.0 - '@babel/helper-string-parser@7.27.1': {} '@babel/helper-validator-identifier@7.28.5': {} @@ -13923,7 +13166,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.29.0)(supports-color@8.1.1)': + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 @@ -13969,16 +13212,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-skip-transparent-expression-wrappers': 7.27.1(supports-color@8.1.1) - '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - optional: true - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6(@babel/core@7.29.0(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) @@ -13987,7 +13220,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6(@babel/core@7.29.0)(supports-color@8.1.1)': + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 @@ -14118,16 +13351,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-async-generator-functions@7.29.0(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/traverse': 7.29.0(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - optional: true - '@babel/plugin-transform-async-to-generator@7.28.6(@babel/core@7.29.0(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) @@ -14146,16 +13369,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-async-to-generator@7.28.6(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-module-imports': 7.28.6(supports-color@8.1.1) - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.0)(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - optional: true - '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.29.0(supports-color@8.1.1))': dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) @@ -14192,15 +13405,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-class-properties@7.28.6(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/helper-plugin-utils': 7.28.6 - transitivePeerDependencies: - - supports-color - optional: true - '@babel/plugin-transform-class-static-block@7.28.6(@babel/core@7.29.0(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) @@ -14217,15 +13421,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-class-static-block@7.28.6(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/helper-plugin-utils': 7.28.6 - transitivePeerDependencies: - - supports-color - optional: true - '@babel/plugin-transform-classes@7.28.6(@babel/core@7.29.0(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) @@ -14250,19 +13445,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-classes@7.28.6(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-globals': 7.28.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/traverse': 7.29.0(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - optional: true - '@babel/plugin-transform-computed-properties@7.28.6(@babel/core@7.29.0(supports-color@8.1.1))': dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) @@ -14283,7 +13465,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.29.0)(supports-color@8.1.1)': + '@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 @@ -14347,18 +13529,9 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0)(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-explicit-resource-management@7.28.6(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0)(supports-color@8.1.1) + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) transitivePeerDependencies: - supports-color - optional: true '@babel/plugin-transform-exponentiation-operator@7.28.6(@babel/core@7.29.0(supports-color@8.1.1))': dependencies: @@ -14396,15 +13569,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-skip-transparent-expression-wrappers': 7.27.1(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - optional: true - '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.29.0(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) @@ -14414,7 +13578,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.29.0)(supports-color@8.1.1)': + '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-compilation-targets': 7.28.6 @@ -14479,15 +13643,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/helper-plugin-utils': 7.28.6 - transitivePeerDependencies: - - supports-color - optional: true - '@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.29.0(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) @@ -14504,15 +13659,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/helper-plugin-utils': 7.28.6 - transitivePeerDependencies: - - supports-color - optional: true - '@babel/plugin-transform-modules-systemjs@7.29.0(@babel/core@7.29.0(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) @@ -14533,17 +13679,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-systemjs@7.29.0(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.29.0(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - optional: true - '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.29.0(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) @@ -14560,15 +13695,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/helper-plugin-utils': 7.28.6 - transitivePeerDependencies: - - supports-color - optional: true - '@babel/plugin-transform-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0(supports-color@8.1.1))': dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) @@ -14627,23 +13753,11 @@ snapshots: '@babel/core': 7.29.0 '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.29.0) - '@babel/traverse': 7.29.0(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0)(supports-color@8.1.1) + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.29.0) '@babel/traverse': 7.29.0(supports-color@8.1.1) transitivePeerDependencies: - supports-color - optional: true '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.29.0(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: @@ -14661,15 +13775,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - optional: true - '@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.29.0(supports-color@8.1.1))': dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) @@ -14696,15 +13801,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-skip-transparent-expression-wrappers': 7.27.1(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - optional: true - '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.29.0(supports-color@8.1.1))': dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) @@ -14731,15 +13827,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-private-methods@7.28.6(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/helper-plugin-utils': 7.28.6 - transitivePeerDependencies: - - supports-color - optional: true - '@babel/plugin-transform-private-property-in-object@7.28.6(@babel/core@7.29.0(supports-color@8.1.1))(supports-color@8.1.1)': dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) @@ -14758,16 +13845,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-private-property-in-object@7.28.6(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/helper-plugin-utils': 7.28.6 - transitivePeerDependencies: - - supports-color - optional: true - '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.29.0(supports-color@8.1.1))': dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) @@ -14815,9 +13892,9 @@ snapshots: '@babel/core': 7.29.0 '@babel/helper-module-imports': 7.28.6(supports-color@8.1.1) '@babel/helper-plugin-utils': 7.28.6 - babel-plugin-polyfill-corejs2: 0.4.15(@babel/core@7.29.0)(supports-color@8.1.1) + babel-plugin-polyfill-corejs2: 0.4.15(@babel/core@7.29.0) babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.29.0) - babel-plugin-polyfill-regenerator: 0.6.6(@babel/core@7.29.0)(supports-color@8.1.1) + babel-plugin-polyfill-regenerator: 0.6.6(@babel/core@7.29.0) semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -14848,15 +13925,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-spread@7.28.6(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-skip-transparent-expression-wrappers': 7.27.1(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - optional: true - '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.29.0(supports-color@8.1.1))': dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) @@ -14898,12 +13966,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-typescript@7.4.5(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.29.0(supports-color@8.1.1))': dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) @@ -15038,11 +14100,11 @@ snapshots: '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-validator-option': 7.27.1 - '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.28.5(@babel/core@7.29.0)(supports-color@8.1.1) + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.28.5(@babel/core@7.29.0) '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.29.0) '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.29.0) '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.28.6(@babel/core@7.29.0) '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.0) '@babel/plugin-syntax-import-assertions': 7.28.6(@babel/core@7.29.0) '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.0) @@ -15056,7 +14118,7 @@ snapshots: '@babel/plugin-transform-class-static-block': 7.28.6(@babel/core@7.29.0) '@babel/plugin-transform-classes': 7.28.6(@babel/core@7.29.0) '@babel/plugin-transform-computed-properties': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0)(supports-color@8.1.1) + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) '@babel/plugin-transform-dotall-regex': 7.28.6(@babel/core@7.29.0) '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.29.0) '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.29.0(@babel/core@7.29.0) @@ -15065,7 +14127,7 @@ snapshots: '@babel/plugin-transform-exponentiation-operator': 7.28.6(@babel/core@7.29.0) '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.29.0) '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.29.0)(supports-color@8.1.1) + '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.29.0) '@babel/plugin-transform-json-strings': 7.28.6(@babel/core@7.29.0) '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.29.0) '@babel/plugin-transform-logical-assignment-operators': 7.28.6(@babel/core@7.29.0) @@ -15099,90 +14161,13 @@ snapshots: '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.29.0) '@babel/plugin-transform-unicode-sets-regex': 7.28.6(@babel/core@7.29.0) '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.29.0) - babel-plugin-polyfill-corejs2: 0.4.15(@babel/core@7.29.0)(supports-color@8.1.1) - babel-plugin-polyfill-corejs3: 0.14.0(@babel/core@7.29.0)(supports-color@8.1.1) - babel-plugin-polyfill-regenerator: 0.6.6(@babel/core@7.29.0)(supports-color@8.1.1) - core-js-compat: 3.48.0 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - '@babel/preset-env@7.29.0(@babel/core@7.29.0)(supports-color@8.1.1)': - dependencies: - '@babel/compat-data': 7.29.0 - '@babel/core': 7.29.0 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-validator-option': 7.27.1 - '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.28.5(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.0) - '@babel/plugin-syntax-import-assertions': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.29.0) - '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-async-generator-functions': 7.29.0(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-transform-async-to-generator': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-block-scoping': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-class-properties': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-transform-class-static-block': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-transform-classes': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-transform-computed-properties': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-transform-dotall-regex': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.29.0(@babel/core@7.29.0) - '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-explicit-resource-management': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-transform-exponentiation-operator': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-transform-json-strings': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-logical-assignment-operators': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-transform-modules-systemjs': 7.29.0(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-transform-named-capturing-groups-regex': 7.29.0(@babel/core@7.29.0) - '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-nullish-coalescing-operator': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-numeric-separator': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-object-rest-spread': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-transform-optional-catch-binding': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.29.0) - '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-transform-private-property-in-object': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-regenerator': 7.29.0(@babel/core@7.29.0) - '@babel/plugin-transform-regexp-modifiers': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-spread': 7.28.6(@babel/core@7.29.0)(supports-color@8.1.1) - '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-unicode-property-regex': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-unicode-sets-regex': 7.28.6(@babel/core@7.29.0) - '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.29.0) - babel-plugin-polyfill-corejs2: 0.4.15(@babel/core@7.29.0)(supports-color@8.1.1) - babel-plugin-polyfill-corejs3: 0.14.0(@babel/core@7.29.0)(supports-color@8.1.1) - babel-plugin-polyfill-regenerator: 0.6.6(@babel/core@7.29.0)(supports-color@8.1.1) + babel-plugin-polyfill-corejs2: 0.4.15(@babel/core@7.29.0) + babel-plugin-polyfill-corejs3: 0.14.0(@babel/core@7.29.0) + babel-plugin-polyfill-regenerator: 0.6.6(@babel/core@7.29.0) core-js-compat: 3.48.0 semver: 6.3.1 transitivePeerDependencies: - supports-color - optional: true '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.29.0(supports-color@8.1.1))': dependencies: @@ -15210,21 +14195,6 @@ snapshots: '@babel/parser': 7.29.0 '@babel/types': 7.29.0 - '@babel/traverse@7.23.9': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.23.6 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-function-name': 7.24.7 - '@babel/helper-hoist-variables': 7.24.7 - '@babel/helper-split-export-declaration': 7.24.7 - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 - debug: 4.4.3(supports-color@8.1.1) - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - '@babel/traverse@7.29.0(supports-color@8.1.1)': dependencies: '@babel/code-frame': 7.29.0 @@ -15237,27 +14207,21 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/types@7.23.0': - dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 - to-fast-properties: 2.0.0 - '@babel/types@7.29.0': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@cacheable/memory@2.0.7': + '@cacheable/memory@2.0.8': dependencies: - '@cacheable/utils': 2.3.4 + '@cacheable/utils': 2.4.0 '@keyv/bigmap': 1.3.1(keyv@5.6.0) hookified: 1.15.1 keyv: 5.6.0 - '@cacheable/utils@2.3.4': + '@cacheable/utils@2.4.0': dependencies: - hashery: 1.4.0 + hashery: 1.5.0 keyv: 5.6.0 '@cnakazawa/watch@1.0.4': @@ -15290,7 +14254,7 @@ snapshots: dependencies: '@csstools/css-tokenizer': 3.0.4 - '@csstools/css-syntax-patches-for-csstree@1.0.27': {} + '@csstools/css-syntax-patches-for-csstree@1.1.0': {} '@csstools/css-tokenizer@3.0.4': {} @@ -15305,136 +14269,8 @@ snapshots: '@dual-bundle/import-meta-resolve@4.2.1': {} - '@ember-data/adapter@5.8.1(@babel/core@7.29.0)': - dependencies: - '@ember/edition-utils': 1.2.0 - '@embroider/macros': 1.19.7(@babel/core@7.29.0) - '@warp-drive/core': 5.8.1(@babel/core@7.29.0) - '@warp-drive/legacy': 5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0))(@warp-drive/utilities@5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0))) - '@warp-drive/utilities': 5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0)) - ember-cli-path-utils: 1.0.0 - ember-cli-string-utils: 1.1.0 - ember-cli-test-info: 1.0.0 - transitivePeerDependencies: - - '@babel/core' - - '@glint/template' - - supports-color - - '@ember-data/debug@5.8.1(@babel/core@7.29.0)': - dependencies: - '@ember/edition-utils': 1.2.0 - '@embroider/macros': 1.19.7(@babel/core@7.29.0) - '@warp-drive/core': 5.8.1(@babel/core@7.29.0) - '@warp-drive/utilities': 5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0)) - transitivePeerDependencies: - - '@babel/core' - - '@glint/template' - - supports-color - - '@ember-data/graph@5.8.1(@babel/core@7.29.0)': - dependencies: - '@embroider/macros': 1.19.7(@babel/core@7.29.0) - '@warp-drive/core': 5.8.1(@babel/core@7.29.0) - transitivePeerDependencies: - - '@babel/core' - - '@glint/template' - - supports-color - - '@ember-data/json-api@5.8.1(@babel/core@7.29.0)': - dependencies: - '@embroider/macros': 1.19.7(@babel/core@7.29.0) - '@warp-drive/core': 5.8.1(@babel/core@7.29.0) - '@warp-drive/json-api': 5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0)) - '@warp-drive/utilities': 5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0)) - transitivePeerDependencies: - - '@babel/core' - - '@glint/template' - - supports-color - - '@ember-data/legacy-compat@5.8.1(@babel/core@7.29.0)': - dependencies: - '@embroider/macros': 1.19.7(@babel/core@7.29.0) - '@warp-drive/core': 5.8.1(@babel/core@7.29.0) - '@warp-drive/legacy': 5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0))(@warp-drive/utilities@5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0))) - '@warp-drive/utilities': 5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0)) - transitivePeerDependencies: - - '@babel/core' - - '@glint/template' - - supports-color - - '@ember-data/model@5.8.1(@babel/core@7.29.0)': - dependencies: - '@ember/edition-utils': 1.2.0 - '@embroider/macros': 1.19.7(@babel/core@7.29.0) - '@warp-drive/core': 5.8.1(@babel/core@7.29.0) - '@warp-drive/legacy': 5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0))(@warp-drive/utilities@5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0))) - '@warp-drive/utilities': 5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0)) - ember-cli-string-utils: 1.1.0 - ember-cli-test-info: 1.0.0 - inflection: 3.0.2 - transitivePeerDependencies: - - '@babel/core' - - '@glint/template' - - supports-color - - '@ember-data/request-utils@5.8.1(@babel/core@7.29.0)': - dependencies: - '@embroider/macros': 1.19.7(@babel/core@7.29.0) - '@warp-drive/core': 5.8.1(@babel/core@7.29.0) - '@warp-drive/utilities': 5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0)) - transitivePeerDependencies: - - '@babel/core' - - '@glint/template' - - supports-color - - '@ember-data/request@5.8.1(@babel/core@7.29.0)': - dependencies: - '@embroider/macros': 1.19.7(@babel/core@7.29.0) - '@warp-drive/core': 5.8.1(@babel/core@7.29.0) - transitivePeerDependencies: - - '@babel/core' - - '@glint/template' - - supports-color - '@ember-data/rfc395-data@0.0.4': {} - '@ember-data/serializer@5.8.1(@babel/core@7.29.0)': - dependencies: - '@ember/edition-utils': 1.2.0 - '@embroider/macros': 1.19.7(@babel/core@7.29.0) - '@warp-drive/core': 5.8.1(@babel/core@7.29.0) - '@warp-drive/legacy': 5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0))(@warp-drive/utilities@5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0))) - '@warp-drive/utilities': 5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0)) - ember-cli-path-utils: 1.0.0 - ember-cli-string-utils: 1.1.0 - ember-cli-test-info: 1.0.0 - transitivePeerDependencies: - - '@babel/core' - - '@glint/template' - - supports-color - - '@ember-data/store@5.8.1(@babel/core@7.29.0)(@ember-data/tracking@5.8.1(@babel/core@7.29.0)(@ember/test-waiters@3.1.0))(@ember/test-waiters@3.1.0)': - dependencies: - '@embroider/macros': 1.19.7(@babel/core@7.29.0) - '@warp-drive/core': 5.8.1(@babel/core@7.29.0) - optionalDependencies: - '@ember-data/tracking': 5.8.1(@babel/core@7.29.0)(@ember/test-waiters@3.1.0) - '@ember/test-waiters': 3.1.0 - transitivePeerDependencies: - - '@babel/core' - - '@glint/template' - - supports-color - - '@ember-data/tracking@5.8.1(@babel/core@7.29.0)(@ember/test-waiters@3.1.0)': - dependencies: - '@ember/test-waiters': 3.1.0 - '@embroider/macros': 1.19.7(@babel/core@7.29.0) - '@warp-drive/core': 5.8.1(@babel/core@7.29.0) - transitivePeerDependencies: - - '@babel/core' - - '@glint/template' - - supports-color - '@ember-tooling/blueprint-blueprint@0.2.1': {} '@ember-tooling/blueprint-model@0.5.0': @@ -15449,13 +14285,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@ember-tooling/classic-build-addon-blueprint@6.10.0': + '@ember-tooling/classic-build-addon-blueprint@6.11.0': dependencies: '@ember-tooling/blueprint-model': 0.5.0 chalk: 5.6.2 ember-cli-normalize-entity-name: 1.0.0 ember-cli-string-utils: 1.1.0 - fs-extra: 11.3.3 + fs-extra: 11.3.4 lodash: 4.17.23 silent-error: 1.1.1 sort-package-json: 2.15.1 @@ -15463,7 +14299,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@ember-tooling/classic-build-app-blueprint@6.10.0': + '@ember-tooling/classic-build-app-blueprint@6.11.0': dependencies: '@ember-tooling/blueprint-model': 0.5.0 chalk: 5.6.2 @@ -15471,7 +14307,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@ember/app-blueprint@6.10.4': + '@ember/app-blueprint@6.11.1': dependencies: chalk: 4.1.2 ejs: 3.1.10 @@ -15493,37 +14329,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@ember/string@3.1.1': - dependencies: - ember-cli-babel: 7.26.11 - transitivePeerDependencies: - - supports-color - '@ember/string@4.0.1': {} - '@ember/test-helpers@3.3.1(@babel/core@7.29.0)(ember-source@)(webpack@5.105.1)': - dependencies: - '@ember/test-waiters': 3.1.0 - '@embroider/macros': 1.19.7(@babel/core@7.29.0) - '@simple-dom/interface': 1.4.0 - broccoli-debug: 0.6.5 - broccoli-funnel: 3.0.8 - dom-element-descriptors: 0.5.1 - ember-auto-import: 2.12.1(webpack@5.105.1) - ember-cli-babel: 8.3.1(@babel/core@7.29.0) - ember-cli-htmlbars: 7.0.0(@babel/core@7.29.0)(ember-source@) - ember-source: 'link:' - transitivePeerDependencies: - - '@babel/core' - - '@glint/template' - - supports-color - - webpack - '@ember/test-helpers@5.4.1(@babel/core@7.29.0)': dependencies: '@ember/test-waiters': 4.1.1(@babel/core@7.29.0) '@embroider/addon-shim': 1.10.2 - '@embroider/macros': 1.19.7(@babel/core@7.29.0) + '@embroider/macros': 1.20.1(@babel/core@7.29.0) '@simple-dom/interface': 1.4.0 decorator-transforms: 2.3.1(@babel/core@7.29.0) dom-element-descriptors: 0.5.1 @@ -15532,19 +14344,10 @@ snapshots: - '@glint/template' - supports-color - '@ember/test-waiters@3.1.0': - dependencies: - calculate-cache-key-for-tree: 2.0.0 - ember-cli-babel: 7.26.11 - ember-cli-version-checker: 5.1.2 - semver: 7.7.4 - transitivePeerDependencies: - - supports-color - '@ember/test-waiters@4.1.1(@babel/core@7.29.0)': dependencies: '@embroider/addon-shim': 1.10.2 - '@embroider/macros': 1.19.7(@babel/core@7.29.0) + '@embroider/macros': 1.20.1(@babel/core@7.29.0) transitivePeerDependencies: - '@babel/core' - '@glint/template' @@ -15559,25 +14362,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@embroider/babel-loader-9@3.1.3(@embroider/core@3.5.9)(supports-color@8.1.1)(webpack@5.105.1(@swc/core@1.15.11))': + '@embroider/babel-loader-9@3.1.3(@embroider/core@3.5.9)(supports-color@8.1.1)(webpack@5.105.4(@swc/core@1.15.18))': dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) '@embroider/core': 3.5.9 - babel-loader: 9.2.1(@babel/core@7.29.0(supports-color@8.1.1))(webpack@5.105.1(@swc/core@1.15.11)) + babel-loader: 9.2.1(@babel/core@7.29.0(supports-color@8.1.1))(webpack@5.105.4(@swc/core@1.15.18)) transitivePeerDependencies: - supports-color - webpack - '@embroider/babel-loader-9@3.1.3(@embroider/core@3.5.9)(supports-color@8.1.1)(webpack@5.105.1)': - dependencies: - '@babel/core': 7.29.0(supports-color@8.1.1) - '@embroider/core': 3.5.9 - babel-loader: 9.2.1(@babel/core@7.29.0)(webpack@5.105.1) - transitivePeerDependencies: - - supports-color - - webpack - optional: true - '@embroider/compat@3.9.3(@embroider/core@3.5.9)': dependencies: '@babel/code-frame': 7.29.0 @@ -15590,7 +14383,7 @@ snapshots: '@babel/runtime': 7.28.6 '@babel/traverse': 7.29.0(supports-color@8.1.1) '@embroider/core': 3.5.9 - '@embroider/macros': 1.19.7(@babel/core@7.29.0) + '@embroider/macros': 1.20.1(@babel/core@7.29.0) '@types/babel__code-frame': 7.27.0 '@types/yargs': 17.0.35 assert-never: 1.4.0 @@ -15600,7 +14393,7 @@ snapshots: babylon: 6.18.0 bind-decorator: 1.0.11 broccoli: 3.5.2 - broccoli-concat: 4.2.5 + broccoli-concat: 4.2.7 broccoli-file-creator: 2.1.1 broccoli-funnel: 3.0.8 broccoli-merge-trees: 4.2.0 @@ -15631,7 +14424,7 @@ snapshots: - supports-color - utf-8-validate - '@embroider/compat@4.1.13(@embroider/core@4.4.3)': + '@embroider/compat@4.1.15(@embroider/core@4.4.5)': dependencies: '@babel/code-frame': 7.29.0 '@babel/core': 7.29.0 @@ -15642,8 +14435,8 @@ snapshots: '@babel/preset-env': 7.29.0(@babel/core@7.29.0) '@babel/runtime': 7.28.6 '@babel/traverse': 7.29.0(supports-color@8.1.1) - '@embroider/core': 4.4.3 - '@embroider/macros': 1.19.7(@babel/core@7.29.0) + '@embroider/core': 4.4.5 + '@embroider/macros': 1.20.1(@babel/core@7.29.0) '@types/babel__code-frame': 7.27.0 assert-never: 1.4.0 babel-import-util: 3.0.1 @@ -15654,7 +14447,7 @@ snapshots: babylon: 6.18.0 bind-decorator: 1.0.11 broccoli: 4.0.0 - broccoli-concat: 4.2.5 + broccoli-concat: 4.2.7 broccoli-file-creator: 2.1.1 broccoli-funnel: 3.0.8 broccoli-merge-trees: 4.2.0 @@ -15691,7 +14484,7 @@ snapshots: '@babel/core': 7.29.0 '@babel/parser': 7.29.0 '@babel/traverse': 7.29.0(supports-color@8.1.1) - '@embroider/macros': 1.19.7(@babel/core@7.29.0) + '@embroider/macros': 1.20.1(@babel/core@7.29.0) '@embroider/shared-internals': 2.9.2(supports-color@8.1.1) assert-never: 1.4.0 babel-plugin-ember-template-compilation: 2.3.0 @@ -15720,12 +14513,12 @@ snapshots: - supports-color - utf-8-validate - '@embroider/core@4.4.3': + '@embroider/core@4.4.5': dependencies: '@babel/core': 7.29.0 '@babel/parser': 7.29.0 '@babel/traverse': 7.29.0(supports-color@8.1.1) - '@embroider/macros': 1.19.7(@babel/core@7.29.0) + '@embroider/macros': 1.20.1(@babel/core@7.29.0) '@embroider/reverse-exports': 0.2.0 '@embroider/shared-internals': 3.0.2 assert-never: 1.4.0 @@ -15756,16 +14549,10 @@ snapshots: - supports-color - utf-8-validate - '@embroider/hbs-loader@3.0.5(@embroider/core@3.5.9)(webpack@5.105.1(@swc/core@1.15.11))': + '@embroider/hbs-loader@3.0.5(@embroider/core@3.5.9)(webpack@5.105.4(@swc/core@1.15.18))': dependencies: '@embroider/core': 3.5.9 - webpack: 5.105.1(@swc/core@1.15.11) - - '@embroider/hbs-loader@3.0.5(@embroider/core@3.5.9)(webpack@5.105.1)': - dependencies: - '@embroider/core': 3.5.9 - webpack: 5.105.1 - optional: true + webpack: 5.105.4(@swc/core@1.15.18) '@embroider/legacy-inspector-support@0.1.3': dependencies: @@ -15773,20 +14560,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@embroider/macros@1.19.7(@babel/core@7.29.0)': - dependencies: - '@embroider/shared-internals': 3.0.2 - assert-never: 1.4.0 - babel-import-util: 3.0.1 - ember-cli-babel: 8.3.1(@babel/core@7.29.0) - find-up: 5.0.0 - lodash: 4.17.23 - resolve: 1.22.11 - semver: 7.7.4 - transitivePeerDependencies: - - '@babel/core' - - supports-color - '@embroider/macros@1.20.1(@babel/core@7.29.0)': dependencies: '@embroider/shared-internals': 3.0.2 @@ -15806,12 +14579,12 @@ snapshots: mem: 8.1.1 resolve.exports: 2.0.3 - '@embroider/router@3.0.6(@babel/core@7.29.0)(@embroider/core@4.4.3)': + '@embroider/router@3.0.6(@babel/core@7.29.0)(@embroider/core@4.4.5)': dependencies: '@ember/test-waiters': 4.1.1(@babel/core@7.29.0) '@embroider/addon-shim': 1.10.2 optionalDependencies: - '@embroider/core': 4.4.3 + '@embroider/core': 4.4.5 transitivePeerDependencies: - '@babel/core' - '@glint/template' @@ -15826,7 +14599,7 @@ snapshots: is-subdir: 1.2.0 js-string-escape: 1.0.1 lodash: 4.17.23 - minimatch: 3.1.2 + minimatch: 3.1.5 pkg-entry-points: 1.1.1 resolve-package-path: 4.0.3 semver: 7.7.4 @@ -15852,22 +14625,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@embroider/test-setup@4.0.0(@embroider/compat@3.9.3(@embroider/core@3.5.9))(@embroider/core@3.5.9)(@embroider/webpack@4.1.2(@embroider/core@3.5.9)(webpack@5.105.1))': - dependencies: - lodash: 4.17.23 - resolve: 1.22.11 - optionalDependencies: - '@embroider/compat': 3.9.3(@embroider/core@3.5.9) - '@embroider/core': 3.5.9 - '@embroider/webpack': 4.1.2(@embroider/core@3.5.9)(webpack@5.105.1) - - '@embroider/vite@1.5.2(@embroider/core@4.4.3)(rollup@4.59.0)(vite@5.4.21(@types/node@22.19.11)(terser@5.46.0))': + '@embroider/vite@1.6.1(@embroider/core@4.4.5)(vite@5.4.21(@types/node@22.19.15)(terser@5.46.0))': dependencies: '@babel/core': 7.29.0 - '@embroider/core': 4.4.3 - '@embroider/macros': 1.19.7(@babel/core@7.29.0) + '@embroider/core': 4.4.5 + '@embroider/macros': 1.20.1(@babel/core@7.29.0) '@embroider/reverse-exports': 0.2.0 - '@rollup/pluginutils': 5.3.0(rollup@4.59.0) assert-never: 1.4.0 browserslist: 4.28.1 browserslist-to-esbuild: 2.1.1(browserslist@4.28.1) @@ -15880,22 +14643,20 @@ snapshots: send: 0.18.0 source-map-url: 0.4.1 terser: 5.46.0 - vite: 5.4.21(@types/node@22.19.11)(terser@5.46.0) + vite: 5.4.21(@types/node@22.19.15)(terser@5.46.0) transitivePeerDependencies: - '@glint/template' - bufferutil - canvas - - rollup - supports-color - utf-8-validate - '@embroider/vite@1.5.2(@embroider/core@4.4.3)(rollup@4.59.0)(vite@7.3.1(@types/node@22.19.11)(terser@5.46.0))': + '@embroider/vite@1.6.1(@embroider/core@4.4.5)(vite@7.3.1(@types/node@22.19.15)(terser@5.46.0))': dependencies: '@babel/core': 7.29.0 - '@embroider/core': 4.4.3 - '@embroider/macros': 1.19.7(@babel/core@7.29.0) + '@embroider/core': 4.4.5 + '@embroider/macros': 1.20.1(@babel/core@7.29.0) '@embroider/reverse-exports': 0.2.0 - '@rollup/pluginutils': 5.3.0(rollup@4.59.0) assert-never: 1.4.0 browserslist: 4.28.1 browserslist-to-esbuild: 2.1.1(browserslist@4.28.1) @@ -15908,77 +14669,44 @@ snapshots: send: 0.18.0 source-map-url: 0.4.1 terser: 5.46.0 - vite: 7.3.1(@types/node@22.19.11)(terser@5.46.0) + vite: 7.3.1(@types/node@22.19.15)(terser@5.46.0) transitivePeerDependencies: - '@glint/template' - bufferutil - canvas - - rollup - supports-color - utf-8-validate - '@embroider/webpack@4.1.2(@embroider/core@3.5.9)(webpack@5.105.1(@swc/core@1.15.11))': + '@embroider/webpack@4.1.2(@embroider/core@3.5.9)(webpack@5.105.4(@swc/core@1.15.18))': dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) '@babel/preset-env': 7.29.0(@babel/core@7.29.0(supports-color@8.1.1))(supports-color@8.1.1) - '@embroider/babel-loader-9': 3.1.3(@embroider/core@3.5.9)(supports-color@8.1.1)(webpack@5.105.1(@swc/core@1.15.11)) - '@embroider/core': 3.5.9 - '@embroider/hbs-loader': 3.0.5(@embroider/core@3.5.9)(webpack@5.105.1(@swc/core@1.15.11)) - '@embroider/shared-internals': 2.9.2(supports-color@8.1.1) - '@types/supports-color': 8.1.3 - assert-never: 1.4.0 - babel-loader: 8.4.1(@babel/core@7.29.0(supports-color@8.1.1))(webpack@5.105.1(@swc/core@1.15.11)) - css-loader: 5.2.7(webpack@5.105.1(@swc/core@1.15.11)) - csso: 4.2.0 - debug: 4.4.3(supports-color@8.1.1) - escape-string-regexp: 4.0.0 - fs-extra: 9.1.0 - jsdom: 25.0.1(supports-color@8.1.1) - lodash: 4.17.23 - mini-css-extract-plugin: 2.10.0(webpack@5.105.1(@swc/core@1.15.11)) - semver: 7.7.4 - source-map-url: 0.4.1 - style-loader: 2.0.0(webpack@5.105.1(@swc/core@1.15.11)) - supports-color: 8.1.1 - terser: 5.46.0 - thread-loader: 3.0.4(webpack@5.105.1(@swc/core@1.15.11)) - webpack: 5.105.1(@swc/core@1.15.11) - transitivePeerDependencies: - - bufferutil - - canvas - - utf-8-validate - - '@embroider/webpack@4.1.2(@embroider/core@3.5.9)(webpack@5.105.1)': - dependencies: - '@babel/core': 7.29.0(supports-color@8.1.1) - '@babel/preset-env': 7.29.0(@babel/core@7.29.0)(supports-color@8.1.1) - '@embroider/babel-loader-9': 3.1.3(@embroider/core@3.5.9)(supports-color@8.1.1)(webpack@5.105.1) + '@embroider/babel-loader-9': 3.1.3(@embroider/core@3.5.9)(supports-color@8.1.1)(webpack@5.105.4(@swc/core@1.15.18)) '@embroider/core': 3.5.9 - '@embroider/hbs-loader': 3.0.5(@embroider/core@3.5.9)(webpack@5.105.1) + '@embroider/hbs-loader': 3.0.5(@embroider/core@3.5.9)(webpack@5.105.4(@swc/core@1.15.18)) '@embroider/shared-internals': 2.9.2(supports-color@8.1.1) '@types/supports-color': 8.1.3 assert-never: 1.4.0 - babel-loader: 8.4.1(@babel/core@7.29.0)(webpack@5.105.1) - css-loader: 5.2.7(webpack@5.105.1) + babel-loader: 8.4.1(@babel/core@7.29.0(supports-color@8.1.1))(webpack@5.105.4(@swc/core@1.15.18)) + css-loader: 5.2.7(webpack@5.105.4(@swc/core@1.15.18)) csso: 4.2.0 debug: 4.4.3(supports-color@8.1.1) escape-string-regexp: 4.0.0 fs-extra: 9.1.0 jsdom: 25.0.1(supports-color@8.1.1) lodash: 4.17.23 - mini-css-extract-plugin: 2.10.0(webpack@5.105.1) + mini-css-extract-plugin: 2.10.0(webpack@5.105.4(@swc/core@1.15.18)) semver: 7.7.4 source-map-url: 0.4.1 - style-loader: 2.0.0(webpack@5.105.1) + style-loader: 2.0.0(webpack@5.105.4(@swc/core@1.15.18)) supports-color: 8.1.1 terser: 5.46.0 - thread-loader: 3.0.4(webpack@5.105.1) - webpack: 5.105.1 + thread-loader: 3.0.4(webpack@5.105.4(@swc/core@1.15.18)) + webpack: 5.105.4(@swc/core@1.15.18) transitivePeerDependencies: - bufferutil - canvas - utf-8-validate - optional: true '@emnapi/core@1.8.1': dependencies: @@ -16143,14 +14871,9 @@ snapshots: '@esbuild/win32-x64@0.27.3': optional: true - '@eslint-community/eslint-utils@4.9.1(eslint@8.57.1)': - dependencies: - eslint: 8.57.1 - eslint-visitor-keys: 3.4.3 - - '@eslint-community/eslint-utils@4.9.1(eslint@9.39.2)': + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.3)': dependencies: - eslint: 9.39.2 + eslint: 9.39.3 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -16159,7 +14882,7 @@ snapshots: dependencies: '@eslint/object-schema': 2.1.7 debug: 4.4.3(supports-color@8.1.1) - minimatch: 3.1.2 + minimatch: 3.1.5 transitivePeerDependencies: - supports-color @@ -16171,37 +14894,21 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 - '@eslint/eslintrc@2.1.4': - dependencies: - ajv: 6.12.6 - debug: 4.4.3(supports-color@8.1.1) - espree: 9.6.1 - globals: 13.24.0 - ignore: 5.3.2 - import-fresh: 3.3.1 - js-yaml: 4.1.1 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - - '@eslint/eslintrc@3.3.3': + '@eslint/eslintrc@3.3.4': dependencies: - ajv: 6.12.6 + ajv: 6.14.0 debug: 4.4.3(supports-color@8.1.1) espree: 10.4.0 globals: 14.0.0 ignore: 5.3.2 import-fresh: 3.3.1 js-yaml: 4.1.1 - minimatch: 3.1.2 + minimatch: 3.1.5 strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color - '@eslint/js@8.57.1': {} - - '@eslint/js@9.39.2': {} + '@eslint/js@9.39.3': {} '@eslint/object-schema@2.1.7': {} @@ -16232,10 +14939,6 @@ snapshots: dependencies: '@simple-dom/interface': 1.4.0 - '@glimmer/interfaces@0.88.1': - dependencies: - '@simple-dom/interface': 1.4.0 - '@glimmer/interfaces@0.94.6': dependencies: '@simple-dom/interface': 1.4.0 @@ -16282,14 +14985,6 @@ snapshots: '@handlebars/parser': 2.0.0 simple-html-tokenizer: 0.5.11 - '@glimmer/syntax@0.88.1': - dependencies: - '@glimmer/interfaces': 0.88.1 - '@glimmer/util': 0.88.1 - '@glimmer/wire-format': 0.88.1 - '@handlebars/parser': 2.0.0 - simple-html-tokenizer: 0.5.11 - '@glimmer/syntax@0.95.0': dependencies: '@glimmer/interfaces': 0.94.6 @@ -16309,11 +15004,6 @@ snapshots: '@glimmer/interfaces': 0.84.3 '@simple-dom/interface': 1.4.0 - '@glimmer/util@0.88.1': - dependencies: - '@glimmer/env': 0.1.7 - '@glimmer/interfaces': 0.88.1 - '@glimmer/util@0.94.8': dependencies: '@glimmer/interfaces': 0.94.6 @@ -16334,11 +15024,6 @@ snapshots: dependencies: '@glimmer/interfaces': 0.94.6 - '@glimmer/wire-format@0.88.1': - dependencies: - '@glimmer/interfaces': 0.88.1 - '@glimmer/util': 0.88.1 - '@glimmer/wire-format@0.94.8': dependencies: '@glimmer/interfaces': 0.94.6 @@ -16356,159 +15041,134 @@ snapshots: '@humanfs/core': 0.19.1 '@humanwhocodes/retry': 0.4.3 - '@humanwhocodes/config-array@0.13.0': - dependencies: - '@humanwhocodes/object-schema': 2.0.3 - debug: 4.4.3(supports-color@8.1.1) - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - '@humanwhocodes/module-importer@1.0.1': {} - '@humanwhocodes/object-schema@2.0.3': {} - '@humanwhocodes/retry@0.4.3': {} '@inquirer/ansi@2.0.3': {} - '@inquirer/checkbox@5.1.0(@types/node@22.19.11)': + '@inquirer/checkbox@5.1.0(@types/node@22.19.15)': dependencies: '@inquirer/ansi': 2.0.3 - '@inquirer/core': 11.1.5(@types/node@22.19.11) + '@inquirer/core': 11.1.5(@types/node@22.19.15) '@inquirer/figures': 2.0.3 - '@inquirer/type': 4.0.3(@types/node@22.19.11) + '@inquirer/type': 4.0.3(@types/node@22.19.15) optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 - '@inquirer/confirm@6.0.8(@types/node@22.19.11)': + '@inquirer/confirm@6.0.8(@types/node@22.19.15)': dependencies: - '@inquirer/core': 11.1.5(@types/node@22.19.11) - '@inquirer/type': 4.0.3(@types/node@22.19.11) + '@inquirer/core': 11.1.5(@types/node@22.19.15) + '@inquirer/type': 4.0.3(@types/node@22.19.15) optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 - '@inquirer/core@11.1.5(@types/node@22.19.11)': + '@inquirer/core@11.1.5(@types/node@22.19.15)': dependencies: '@inquirer/ansi': 2.0.3 '@inquirer/figures': 2.0.3 - '@inquirer/type': 4.0.3(@types/node@22.19.11) + '@inquirer/type': 4.0.3(@types/node@22.19.15) cli-width: 4.1.0 fast-wrap-ansi: 0.2.0 mute-stream: 3.0.0 signal-exit: 4.1.0 optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 - '@inquirer/editor@5.0.8(@types/node@22.19.11)': + '@inquirer/editor@5.0.8(@types/node@22.19.15)': dependencies: - '@inquirer/core': 11.1.5(@types/node@22.19.11) - '@inquirer/external-editor': 2.0.3(@types/node@22.19.11) - '@inquirer/type': 4.0.3(@types/node@22.19.11) + '@inquirer/core': 11.1.5(@types/node@22.19.15) + '@inquirer/external-editor': 2.0.3(@types/node@22.19.15) + '@inquirer/type': 4.0.3(@types/node@22.19.15) optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 - '@inquirer/expand@5.0.8(@types/node@22.19.11)': + '@inquirer/expand@5.0.8(@types/node@22.19.15)': dependencies: - '@inquirer/core': 11.1.5(@types/node@22.19.11) - '@inquirer/type': 4.0.3(@types/node@22.19.11) + '@inquirer/core': 11.1.5(@types/node@22.19.15) + '@inquirer/type': 4.0.3(@types/node@22.19.15) optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 - '@inquirer/external-editor@1.0.3(@types/node@22.19.11)': + '@inquirer/external-editor@2.0.3(@types/node@22.19.15)': dependencies: chardet: 2.1.1 iconv-lite: 0.7.2 optionalDependencies: - '@types/node': 22.19.11 - - '@inquirer/external-editor@2.0.3(@types/node@22.19.11)': - dependencies: - chardet: 2.1.1 - iconv-lite: 0.7.2 - optionalDependencies: - '@types/node': 22.19.11 - - '@inquirer/figures@1.0.15': {} + '@types/node': 22.19.15 '@inquirer/figures@2.0.3': {} - '@inquirer/input@5.0.8(@types/node@22.19.11)': + '@inquirer/input@5.0.8(@types/node@22.19.15)': dependencies: - '@inquirer/core': 11.1.5(@types/node@22.19.11) - '@inquirer/type': 4.0.3(@types/node@22.19.11) + '@inquirer/core': 11.1.5(@types/node@22.19.15) + '@inquirer/type': 4.0.3(@types/node@22.19.15) optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 - '@inquirer/number@4.0.8(@types/node@22.19.11)': + '@inquirer/number@4.0.8(@types/node@22.19.15)': dependencies: - '@inquirer/core': 11.1.5(@types/node@22.19.11) - '@inquirer/type': 4.0.3(@types/node@22.19.11) + '@inquirer/core': 11.1.5(@types/node@22.19.15) + '@inquirer/type': 4.0.3(@types/node@22.19.15) optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 - '@inquirer/password@5.0.8(@types/node@22.19.11)': + '@inquirer/password@5.0.8(@types/node@22.19.15)': dependencies: '@inquirer/ansi': 2.0.3 - '@inquirer/core': 11.1.5(@types/node@22.19.11) - '@inquirer/type': 4.0.3(@types/node@22.19.11) + '@inquirer/core': 11.1.5(@types/node@22.19.15) + '@inquirer/type': 4.0.3(@types/node@22.19.15) optionalDependencies: - '@types/node': 22.19.11 - - '@inquirer/prompts@8.3.0(@types/node@22.19.11)': - dependencies: - '@inquirer/checkbox': 5.1.0(@types/node@22.19.11) - '@inquirer/confirm': 6.0.8(@types/node@22.19.11) - '@inquirer/editor': 5.0.8(@types/node@22.19.11) - '@inquirer/expand': 5.0.8(@types/node@22.19.11) - '@inquirer/input': 5.0.8(@types/node@22.19.11) - '@inquirer/number': 4.0.8(@types/node@22.19.11) - '@inquirer/password': 5.0.8(@types/node@22.19.11) - '@inquirer/rawlist': 5.2.4(@types/node@22.19.11) - '@inquirer/search': 4.1.4(@types/node@22.19.11) - '@inquirer/select': 5.1.0(@types/node@22.19.11) + '@types/node': 22.19.15 + + '@inquirer/prompts@8.3.0(@types/node@22.19.15)': + dependencies: + '@inquirer/checkbox': 5.1.0(@types/node@22.19.15) + '@inquirer/confirm': 6.0.8(@types/node@22.19.15) + '@inquirer/editor': 5.0.8(@types/node@22.19.15) + '@inquirer/expand': 5.0.8(@types/node@22.19.15) + '@inquirer/input': 5.0.8(@types/node@22.19.15) + '@inquirer/number': 4.0.8(@types/node@22.19.15) + '@inquirer/password': 5.0.8(@types/node@22.19.15) + '@inquirer/rawlist': 5.2.4(@types/node@22.19.15) + '@inquirer/search': 4.1.4(@types/node@22.19.15) + '@inquirer/select': 5.1.0(@types/node@22.19.15) optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 - '@inquirer/rawlist@5.2.4(@types/node@22.19.11)': + '@inquirer/rawlist@5.2.4(@types/node@22.19.15)': dependencies: - '@inquirer/core': 11.1.5(@types/node@22.19.11) - '@inquirer/type': 4.0.3(@types/node@22.19.11) + '@inquirer/core': 11.1.5(@types/node@22.19.15) + '@inquirer/type': 4.0.3(@types/node@22.19.15) optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 - '@inquirer/search@4.1.4(@types/node@22.19.11)': + '@inquirer/search@4.1.4(@types/node@22.19.15)': dependencies: - '@inquirer/core': 11.1.5(@types/node@22.19.11) + '@inquirer/core': 11.1.5(@types/node@22.19.15) '@inquirer/figures': 2.0.3 - '@inquirer/type': 4.0.3(@types/node@22.19.11) + '@inquirer/type': 4.0.3(@types/node@22.19.15) optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 - '@inquirer/select@5.1.0(@types/node@22.19.11)': + '@inquirer/select@5.1.0(@types/node@22.19.15)': dependencies: '@inquirer/ansi': 2.0.3 - '@inquirer/core': 11.1.5(@types/node@22.19.11) + '@inquirer/core': 11.1.5(@types/node@22.19.15) '@inquirer/figures': 2.0.3 - '@inquirer/type': 4.0.3(@types/node@22.19.11) + '@inquirer/type': 4.0.3(@types/node@22.19.15) optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 - '@inquirer/type@4.0.3(@types/node@22.19.11)': + '@inquirer/type@4.0.3(@types/node@22.19.15)': optionalDependencies: - '@types/node': 22.19.11 - - '@isaacs/balanced-match@4.0.1': {} - - '@isaacs/brace-expansion@5.0.1': - dependencies: - '@isaacs/balanced-match': 4.0.1 + '@types/node': 22.19.15 '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.2 + strip-ansi: 7.2.0 strip-ansi-cjs: strip-ansi@6.0.1 wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 @@ -16544,7 +15204,7 @@ snapshots: '@keyv/bigmap@1.3.1(keyv@5.6.0)': dependencies: - hashery: 1.4.0 + hashery: 1.5.0 hookified: 1.15.1 keyv: 5.6.0 @@ -16616,7 +15276,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@oclif/core@2.16.0(@swc/core@1.15.11)(@types/node@22.19.11)(typescript@5.9.3)': + '@oclif/core@2.16.0(@swc/core@1.15.18)(@types/node@22.19.15)(typescript@5.9.3)': dependencies: '@types/cli-progress': 3.11.6 ansi-escapes: 4.3.2 @@ -16641,7 +15301,7 @@ snapshots: strip-ansi: 6.0.1 supports-color: 8.1.1 supports-hyperlinks: 2.3.0 - ts-node: 10.9.2(@swc/core@1.15.11)(@types/node@22.19.11)(typescript@5.9.3) + ts-node: 10.9.2(@swc/core@1.15.18)(@types/node@22.19.15)(typescript@5.9.3) tslib: 2.8.1 widest-line: 3.1.0 wordwrap: 1.0.0 @@ -16683,18 +15343,18 @@ snapshots: chalk: 4.1.2 tslib: 2.8.1 - '@oclif/plugin-help@5.2.20(@swc/core@1.15.11)(@types/node@22.19.11)(typescript@5.9.3)': + '@oclif/plugin-help@5.2.20(@swc/core@1.15.18)(@types/node@22.19.15)(typescript@5.9.3)': dependencies: - '@oclif/core': 2.16.0(@swc/core@1.15.11)(@types/node@22.19.11)(typescript@5.9.3) + '@oclif/core': 2.16.0(@swc/core@1.15.18)(@types/node@22.19.15)(typescript@5.9.3) transitivePeerDependencies: - '@swc/core' - '@swc/wasm' - '@types/node' - typescript - '@oclif/plugin-warn-if-update-available@2.1.1(@swc/core@1.15.11)(@types/node@22.19.11)(typescript@5.9.3)': + '@oclif/plugin-warn-if-update-available@2.1.1(@swc/core@1.15.18)(@types/node@22.19.15)(typescript@5.9.3)': dependencies: - '@oclif/core': 2.16.0(@swc/core@1.15.11)(@types/node@22.19.11)(typescript@5.9.3) + '@oclif/core': 2.16.0(@swc/core@1.15.18)(@types/node@22.19.15)(typescript@5.9.3) chalk: 4.1.2 debug: 4.4.3(supports-color@8.1.1) http-call: 5.3.0 @@ -16707,73 +15367,71 @@ snapshots: - supports-color - typescript - '@oxc-resolver/binding-android-arm-eabi@11.17.1': + '@oxc-resolver/binding-android-arm-eabi@11.19.1': optional: true - '@oxc-resolver/binding-android-arm64@11.17.1': + '@oxc-resolver/binding-android-arm64@11.19.1': optional: true - '@oxc-resolver/binding-darwin-arm64@11.17.1': + '@oxc-resolver/binding-darwin-arm64@11.19.1': optional: true - '@oxc-resolver/binding-darwin-x64@11.17.1': + '@oxc-resolver/binding-darwin-x64@11.19.1': optional: true - '@oxc-resolver/binding-freebsd-x64@11.17.1': + '@oxc-resolver/binding-freebsd-x64@11.19.1': optional: true - '@oxc-resolver/binding-linux-arm-gnueabihf@11.17.1': + '@oxc-resolver/binding-linux-arm-gnueabihf@11.19.1': optional: true - '@oxc-resolver/binding-linux-arm-musleabihf@11.17.1': + '@oxc-resolver/binding-linux-arm-musleabihf@11.19.1': optional: true - '@oxc-resolver/binding-linux-arm64-gnu@11.17.1': + '@oxc-resolver/binding-linux-arm64-gnu@11.19.1': optional: true - '@oxc-resolver/binding-linux-arm64-musl@11.17.1': + '@oxc-resolver/binding-linux-arm64-musl@11.19.1': optional: true - '@oxc-resolver/binding-linux-ppc64-gnu@11.17.1': + '@oxc-resolver/binding-linux-ppc64-gnu@11.19.1': optional: true - '@oxc-resolver/binding-linux-riscv64-gnu@11.17.1': + '@oxc-resolver/binding-linux-riscv64-gnu@11.19.1': optional: true - '@oxc-resolver/binding-linux-riscv64-musl@11.17.1': + '@oxc-resolver/binding-linux-riscv64-musl@11.19.1': optional: true - '@oxc-resolver/binding-linux-s390x-gnu@11.17.1': + '@oxc-resolver/binding-linux-s390x-gnu@11.19.1': optional: true - '@oxc-resolver/binding-linux-x64-gnu@11.17.1': + '@oxc-resolver/binding-linux-x64-gnu@11.19.1': optional: true - '@oxc-resolver/binding-linux-x64-musl@11.17.1': + '@oxc-resolver/binding-linux-x64-musl@11.19.1': optional: true - '@oxc-resolver/binding-openharmony-arm64@11.17.1': + '@oxc-resolver/binding-openharmony-arm64@11.19.1': optional: true - '@oxc-resolver/binding-wasm32-wasi@11.17.1': + '@oxc-resolver/binding-wasm32-wasi@11.19.1': dependencies: '@napi-rs/wasm-runtime': 1.1.1 optional: true - '@oxc-resolver/binding-win32-arm64-msvc@11.17.1': + '@oxc-resolver/binding-win32-arm64-msvc@11.19.1': optional: true - '@oxc-resolver/binding-win32-ia32-msvc@11.17.1': + '@oxc-resolver/binding-win32-ia32-msvc@11.19.1': optional: true - '@oxc-resolver/binding-win32-x64-msvc@11.17.1': + '@oxc-resolver/binding-win32-x64-msvc@11.19.1': optional: true '@pkgjs/parseargs@0.11.0': optional: true - '@pkgr/core@0.2.9': {} - '@pnpm/cli-meta@6.0.1': dependencies: '@pnpm/types': 10.1.0 @@ -16828,8 +15486,6 @@ snapshots: '@pnpm/constants@1001.3.1': {} - '@pnpm/constants@7.1.1': {} - '@pnpm/constants@8.0.0': {} '@pnpm/core-loggers@10.0.1(@pnpm/logger@5.2.0)': @@ -16876,10 +15532,6 @@ snapshots: dependencies: '@pnpm/constants': 1001.3.1 - '@pnpm/error@5.0.3': - dependencies: - '@pnpm/constants': 7.1.1 - '@pnpm/error@6.0.1': dependencies: '@pnpm/constants': 8.0.0 @@ -16899,11 +15551,6 @@ snapshots: '@pnpm/error': 1000.0.5 find-up: 5.0.0 - '@pnpm/find-workspace-dir@6.0.3': - dependencies: - '@pnpm/error': 5.0.3 - find-up: 5.0.0 - '@pnpm/find-workspace-dir@7.0.3': dependencies: '@pnpm/error': 6.0.3 @@ -16940,7 +15587,7 @@ snapshots: '@pnpm/logger@5.2.0': dependencies: - bole: 5.0.27 + bole: 5.0.28 ndjson: 2.0.0 '@pnpm/manifest-utils@6.0.2(@pnpm/logger@5.2.0)': @@ -17198,254 +15845,254 @@ snapshots: '@sindresorhus/merge-streams@4.0.0': {} - '@smithy/abort-controller@4.2.8': + '@smithy/abort-controller@4.2.11': dependencies: - '@smithy/types': 4.12.0 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@smithy/chunked-blob-reader-native@4.2.1': + '@smithy/chunked-blob-reader-native@4.2.3': dependencies: - '@smithy/util-base64': 4.3.0 + '@smithy/util-base64': 4.3.2 tslib: 2.8.1 - '@smithy/chunked-blob-reader@5.2.0': + '@smithy/chunked-blob-reader@5.2.2': dependencies: tslib: 2.8.1 - '@smithy/config-resolver@4.4.6': + '@smithy/config-resolver@4.4.10': dependencies: - '@smithy/node-config-provider': 4.3.8 - '@smithy/types': 4.12.0 - '@smithy/util-config-provider': 4.2.0 - '@smithy/util-endpoints': 3.2.8 - '@smithy/util-middleware': 4.2.8 + '@smithy/node-config-provider': 4.3.11 + '@smithy/types': 4.13.0 + '@smithy/util-config-provider': 4.2.2 + '@smithy/util-endpoints': 3.3.2 + '@smithy/util-middleware': 4.2.11 tslib: 2.8.1 - '@smithy/core@3.23.0': - dependencies: - '@smithy/middleware-serde': 4.2.9 - '@smithy/protocol-http': 5.3.8 - '@smithy/types': 4.12.0 - '@smithy/util-base64': 4.3.0 - '@smithy/util-body-length-browser': 4.2.0 - '@smithy/util-middleware': 4.2.8 - '@smithy/util-stream': 4.5.12 - '@smithy/util-utf8': 4.2.0 - '@smithy/uuid': 1.1.0 + '@smithy/core@3.23.8': + dependencies: + '@smithy/middleware-serde': 4.2.12 + '@smithy/protocol-http': 5.3.11 + '@smithy/types': 4.13.0 + '@smithy/util-base64': 4.3.2 + '@smithy/util-body-length-browser': 4.2.2 + '@smithy/util-middleware': 4.2.11 + '@smithy/util-stream': 4.5.17 + '@smithy/util-utf8': 4.2.2 + '@smithy/uuid': 1.1.2 tslib: 2.8.1 - '@smithy/credential-provider-imds@4.2.8': + '@smithy/credential-provider-imds@4.2.11': dependencies: - '@smithy/node-config-provider': 4.3.8 - '@smithy/property-provider': 4.2.8 - '@smithy/types': 4.12.0 - '@smithy/url-parser': 4.2.8 + '@smithy/node-config-provider': 4.3.11 + '@smithy/property-provider': 4.2.11 + '@smithy/types': 4.13.0 + '@smithy/url-parser': 4.2.11 tslib: 2.8.1 - '@smithy/eventstream-codec@4.2.8': + '@smithy/eventstream-codec@4.2.11': dependencies: '@aws-crypto/crc32': 5.2.0 - '@smithy/types': 4.12.0 - '@smithy/util-hex-encoding': 4.2.0 + '@smithy/types': 4.13.0 + '@smithy/util-hex-encoding': 4.2.2 tslib: 2.8.1 - '@smithy/eventstream-serde-browser@4.2.8': + '@smithy/eventstream-serde-browser@4.2.11': dependencies: - '@smithy/eventstream-serde-universal': 4.2.8 - '@smithy/types': 4.12.0 + '@smithy/eventstream-serde-universal': 4.2.11 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@smithy/eventstream-serde-config-resolver@4.3.8': + '@smithy/eventstream-serde-config-resolver@4.3.11': dependencies: - '@smithy/types': 4.12.0 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@smithy/eventstream-serde-node@4.2.8': + '@smithy/eventstream-serde-node@4.2.11': dependencies: - '@smithy/eventstream-serde-universal': 4.2.8 - '@smithy/types': 4.12.0 + '@smithy/eventstream-serde-universal': 4.2.11 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@smithy/eventstream-serde-universal@4.2.8': + '@smithy/eventstream-serde-universal@4.2.11': dependencies: - '@smithy/eventstream-codec': 4.2.8 - '@smithy/types': 4.12.0 + '@smithy/eventstream-codec': 4.2.11 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@smithy/fetch-http-handler@5.3.9': + '@smithy/fetch-http-handler@5.3.13': dependencies: - '@smithy/protocol-http': 5.3.8 - '@smithy/querystring-builder': 4.2.8 - '@smithy/types': 4.12.0 - '@smithy/util-base64': 4.3.0 + '@smithy/protocol-http': 5.3.11 + '@smithy/querystring-builder': 4.2.11 + '@smithy/types': 4.13.0 + '@smithy/util-base64': 4.3.2 tslib: 2.8.1 - '@smithy/hash-blob-browser@4.2.9': + '@smithy/hash-blob-browser@4.2.12': dependencies: - '@smithy/chunked-blob-reader': 5.2.0 - '@smithy/chunked-blob-reader-native': 4.2.1 - '@smithy/types': 4.12.0 + '@smithy/chunked-blob-reader': 5.2.2 + '@smithy/chunked-blob-reader-native': 4.2.3 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@smithy/hash-node@4.2.8': + '@smithy/hash-node@4.2.11': dependencies: - '@smithy/types': 4.12.0 - '@smithy/util-buffer-from': 4.2.0 - '@smithy/util-utf8': 4.2.0 + '@smithy/types': 4.13.0 + '@smithy/util-buffer-from': 4.2.2 + '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 - '@smithy/hash-stream-node@4.2.8': + '@smithy/hash-stream-node@4.2.11': dependencies: - '@smithy/types': 4.12.0 - '@smithy/util-utf8': 4.2.0 + '@smithy/types': 4.13.0 + '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 - '@smithy/invalid-dependency@4.2.8': + '@smithy/invalid-dependency@4.2.11': dependencies: - '@smithy/types': 4.12.0 + '@smithy/types': 4.13.0 tslib: 2.8.1 '@smithy/is-array-buffer@2.2.0': dependencies: tslib: 2.8.1 - '@smithy/is-array-buffer@4.2.0': + '@smithy/is-array-buffer@4.2.2': dependencies: tslib: 2.8.1 - '@smithy/md5-js@4.2.8': + '@smithy/md5-js@4.2.11': dependencies: - '@smithy/types': 4.12.0 - '@smithy/util-utf8': 4.2.0 + '@smithy/types': 4.13.0 + '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 - '@smithy/middleware-content-length@4.2.8': + '@smithy/middleware-content-length@4.2.11': dependencies: - '@smithy/protocol-http': 5.3.8 - '@smithy/types': 4.12.0 + '@smithy/protocol-http': 5.3.11 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@smithy/middleware-endpoint@4.4.14': + '@smithy/middleware-endpoint@4.4.22': dependencies: - '@smithy/core': 3.23.0 - '@smithy/middleware-serde': 4.2.9 - '@smithy/node-config-provider': 4.3.8 - '@smithy/shared-ini-file-loader': 4.4.3 - '@smithy/types': 4.12.0 - '@smithy/url-parser': 4.2.8 - '@smithy/util-middleware': 4.2.8 + '@smithy/core': 3.23.8 + '@smithy/middleware-serde': 4.2.12 + '@smithy/node-config-provider': 4.3.11 + '@smithy/shared-ini-file-loader': 4.4.6 + '@smithy/types': 4.13.0 + '@smithy/url-parser': 4.2.11 + '@smithy/util-middleware': 4.2.11 tslib: 2.8.1 - '@smithy/middleware-retry@4.4.31': + '@smithy/middleware-retry@4.4.39': dependencies: - '@smithy/node-config-provider': 4.3.8 - '@smithy/protocol-http': 5.3.8 - '@smithy/service-error-classification': 4.2.8 - '@smithy/smithy-client': 4.11.3 - '@smithy/types': 4.12.0 - '@smithy/util-middleware': 4.2.8 - '@smithy/util-retry': 4.2.8 - '@smithy/uuid': 1.1.0 + '@smithy/node-config-provider': 4.3.11 + '@smithy/protocol-http': 5.3.11 + '@smithy/service-error-classification': 4.2.11 + '@smithy/smithy-client': 4.12.2 + '@smithy/types': 4.13.0 + '@smithy/util-middleware': 4.2.11 + '@smithy/util-retry': 4.2.11 + '@smithy/uuid': 1.1.2 tslib: 2.8.1 - '@smithy/middleware-serde@4.2.9': + '@smithy/middleware-serde@4.2.12': dependencies: - '@smithy/protocol-http': 5.3.8 - '@smithy/types': 4.12.0 + '@smithy/protocol-http': 5.3.11 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@smithy/middleware-stack@4.2.8': + '@smithy/middleware-stack@4.2.11': dependencies: - '@smithy/types': 4.12.0 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@smithy/node-config-provider@4.3.8': + '@smithy/node-config-provider@4.3.11': dependencies: - '@smithy/property-provider': 4.2.8 - '@smithy/shared-ini-file-loader': 4.4.3 - '@smithy/types': 4.12.0 + '@smithy/property-provider': 4.2.11 + '@smithy/shared-ini-file-loader': 4.4.6 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@smithy/node-http-handler@4.4.10': + '@smithy/node-http-handler@4.4.14': dependencies: - '@smithy/abort-controller': 4.2.8 - '@smithy/protocol-http': 5.3.8 - '@smithy/querystring-builder': 4.2.8 - '@smithy/types': 4.12.0 + '@smithy/abort-controller': 4.2.11 + '@smithy/protocol-http': 5.3.11 + '@smithy/querystring-builder': 4.2.11 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@smithy/property-provider@4.2.8': + '@smithy/property-provider@4.2.11': dependencies: - '@smithy/types': 4.12.0 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@smithy/protocol-http@5.3.8': + '@smithy/protocol-http@5.3.11': dependencies: - '@smithy/types': 4.12.0 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@smithy/querystring-builder@4.2.8': + '@smithy/querystring-builder@4.2.11': dependencies: - '@smithy/types': 4.12.0 - '@smithy/util-uri-escape': 4.2.0 + '@smithy/types': 4.13.0 + '@smithy/util-uri-escape': 4.2.2 tslib: 2.8.1 - '@smithy/querystring-parser@4.2.8': + '@smithy/querystring-parser@4.2.11': dependencies: - '@smithy/types': 4.12.0 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@smithy/service-error-classification@4.2.8': + '@smithy/service-error-classification@4.2.11': dependencies: - '@smithy/types': 4.12.0 + '@smithy/types': 4.13.0 - '@smithy/shared-ini-file-loader@4.4.3': + '@smithy/shared-ini-file-loader@4.4.6': dependencies: - '@smithy/types': 4.12.0 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@smithy/signature-v4@5.3.8': + '@smithy/signature-v4@5.3.11': dependencies: - '@smithy/is-array-buffer': 4.2.0 - '@smithy/protocol-http': 5.3.8 - '@smithy/types': 4.12.0 - '@smithy/util-hex-encoding': 4.2.0 - '@smithy/util-middleware': 4.2.8 - '@smithy/util-uri-escape': 4.2.0 - '@smithy/util-utf8': 4.2.0 + '@smithy/is-array-buffer': 4.2.2 + '@smithy/protocol-http': 5.3.11 + '@smithy/types': 4.13.0 + '@smithy/util-hex-encoding': 4.2.2 + '@smithy/util-middleware': 4.2.11 + '@smithy/util-uri-escape': 4.2.2 + '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 - '@smithy/smithy-client@4.11.3': + '@smithy/smithy-client@4.12.2': dependencies: - '@smithy/core': 3.23.0 - '@smithy/middleware-endpoint': 4.4.14 - '@smithy/middleware-stack': 4.2.8 - '@smithy/protocol-http': 5.3.8 - '@smithy/types': 4.12.0 - '@smithy/util-stream': 4.5.12 + '@smithy/core': 3.23.8 + '@smithy/middleware-endpoint': 4.4.22 + '@smithy/middleware-stack': 4.2.11 + '@smithy/protocol-http': 5.3.11 + '@smithy/types': 4.13.0 + '@smithy/util-stream': 4.5.17 tslib: 2.8.1 - '@smithy/types@4.12.0': + '@smithy/types@4.13.0': dependencies: tslib: 2.8.1 - '@smithy/url-parser@4.2.8': + '@smithy/url-parser@4.2.11': dependencies: - '@smithy/querystring-parser': 4.2.8 - '@smithy/types': 4.12.0 + '@smithy/querystring-parser': 4.2.11 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@smithy/util-base64@4.3.0': + '@smithy/util-base64@4.3.2': dependencies: - '@smithy/util-buffer-from': 4.2.0 - '@smithy/util-utf8': 4.2.0 + '@smithy/util-buffer-from': 4.2.2 + '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 - '@smithy/util-body-length-browser@4.2.0': + '@smithy/util-body-length-browser@4.2.2': dependencies: tslib: 2.8.1 - '@smithy/util-body-length-node@4.2.1': + '@smithy/util-body-length-node@4.2.3': dependencies: tslib: 2.8.1 @@ -17454,65 +16101,65 @@ snapshots: '@smithy/is-array-buffer': 2.2.0 tslib: 2.8.1 - '@smithy/util-buffer-from@4.2.0': + '@smithy/util-buffer-from@4.2.2': dependencies: - '@smithy/is-array-buffer': 4.2.0 + '@smithy/is-array-buffer': 4.2.2 tslib: 2.8.1 - '@smithy/util-config-provider@4.2.0': + '@smithy/util-config-provider@4.2.2': dependencies: tslib: 2.8.1 - '@smithy/util-defaults-mode-browser@4.3.30': + '@smithy/util-defaults-mode-browser@4.3.38': dependencies: - '@smithy/property-provider': 4.2.8 - '@smithy/smithy-client': 4.11.3 - '@smithy/types': 4.12.0 + '@smithy/property-provider': 4.2.11 + '@smithy/smithy-client': 4.12.2 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@smithy/util-defaults-mode-node@4.2.33': + '@smithy/util-defaults-mode-node@4.2.41': dependencies: - '@smithy/config-resolver': 4.4.6 - '@smithy/credential-provider-imds': 4.2.8 - '@smithy/node-config-provider': 4.3.8 - '@smithy/property-provider': 4.2.8 - '@smithy/smithy-client': 4.11.3 - '@smithy/types': 4.12.0 + '@smithy/config-resolver': 4.4.10 + '@smithy/credential-provider-imds': 4.2.11 + '@smithy/node-config-provider': 4.3.11 + '@smithy/property-provider': 4.2.11 + '@smithy/smithy-client': 4.12.2 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@smithy/util-endpoints@3.2.8': + '@smithy/util-endpoints@3.3.2': dependencies: - '@smithy/node-config-provider': 4.3.8 - '@smithy/types': 4.12.0 + '@smithy/node-config-provider': 4.3.11 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@smithy/util-hex-encoding@4.2.0': + '@smithy/util-hex-encoding@4.2.2': dependencies: tslib: 2.8.1 - '@smithy/util-middleware@4.2.8': + '@smithy/util-middleware@4.2.11': dependencies: - '@smithy/types': 4.12.0 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@smithy/util-retry@4.2.8': + '@smithy/util-retry@4.2.11': dependencies: - '@smithy/service-error-classification': 4.2.8 - '@smithy/types': 4.12.0 + '@smithy/service-error-classification': 4.2.11 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@smithy/util-stream@4.5.12': + '@smithy/util-stream@4.5.17': dependencies: - '@smithy/fetch-http-handler': 5.3.9 - '@smithy/node-http-handler': 4.4.10 - '@smithy/types': 4.12.0 - '@smithy/util-base64': 4.3.0 - '@smithy/util-buffer-from': 4.2.0 - '@smithy/util-hex-encoding': 4.2.0 - '@smithy/util-utf8': 4.2.0 + '@smithy/fetch-http-handler': 5.3.13 + '@smithy/node-http-handler': 4.4.14 + '@smithy/types': 4.13.0 + '@smithy/util-base64': 4.3.2 + '@smithy/util-buffer-from': 4.2.2 + '@smithy/util-hex-encoding': 4.2.2 + '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 - '@smithy/util-uri-escape@4.2.0': + '@smithy/util-uri-escape@4.2.2': dependencies: tslib: 2.8.1 @@ -17521,36 +16168,36 @@ snapshots: '@smithy/util-buffer-from': 2.2.0 tslib: 2.8.1 - '@smithy/util-utf8@4.2.0': + '@smithy/util-utf8@4.2.2': dependencies: - '@smithy/util-buffer-from': 4.2.0 + '@smithy/util-buffer-from': 4.2.2 tslib: 2.8.1 - '@smithy/util-waiter@4.2.8': + '@smithy/util-waiter@4.2.11': dependencies: - '@smithy/abort-controller': 4.2.8 - '@smithy/types': 4.12.0 + '@smithy/abort-controller': 4.2.11 + '@smithy/types': 4.13.0 tslib: 2.8.1 - '@smithy/uuid@1.1.0': + '@smithy/uuid@1.1.2': dependencies: tslib: 2.8.1 '@socket.io/component-emitter@3.1.2': {} - '@swc-node/core@1.14.1(@swc/core@1.15.11)(@swc/types@0.1.25)': + '@swc-node/core@1.14.1(@swc/core@1.15.18)(@swc/types@0.1.25)': dependencies: - '@swc/core': 1.15.11 + '@swc/core': 1.15.18 '@swc/types': 0.1.25 - '@swc-node/register@1.11.1(@swc/core@1.15.11)(@swc/types@0.1.25)(typescript@5.1.6)': + '@swc-node/register@1.11.1(@swc/core@1.15.18)(@swc/types@0.1.25)(typescript@5.1.6)': dependencies: - '@swc-node/core': 1.14.1(@swc/core@1.15.11)(@swc/types@0.1.25) + '@swc-node/core': 1.14.1(@swc/core@1.15.18)(@swc/types@0.1.25) '@swc-node/sourcemap-support': 0.6.1 - '@swc/core': 1.15.11 + '@swc/core': 1.15.18 colorette: 2.0.20 debug: 4.4.3(supports-color@8.1.1) - oxc-resolver: 11.17.1 + oxc-resolver: 11.19.1 pirates: 4.0.7 tslib: 2.8.1 typescript: 5.1.6 @@ -17558,14 +16205,14 @@ snapshots: - '@swc/types' - supports-color - '@swc-node/register@1.11.1(@swc/core@1.15.11)(@swc/types@0.1.25)(typescript@5.9.3)': + '@swc-node/register@1.11.1(@swc/core@1.15.18)(@swc/types@0.1.25)(typescript@5.9.3)': dependencies: - '@swc-node/core': 1.14.1(@swc/core@1.15.11)(@swc/types@0.1.25) + '@swc-node/core': 1.14.1(@swc/core@1.15.18)(@swc/types@0.1.25) '@swc-node/sourcemap-support': 0.6.1 - '@swc/core': 1.15.11 + '@swc/core': 1.15.18 colorette: 2.0.20 debug: 4.4.3(supports-color@8.1.1) - oxc-resolver: 11.17.1 + oxc-resolver: 11.19.1 pirates: 4.0.7 tslib: 2.8.1 typescript: 5.9.3 @@ -17578,51 +16225,51 @@ snapshots: source-map-support: 0.5.21 tslib: 2.8.1 - '@swc/core-darwin-arm64@1.15.11': + '@swc/core-darwin-arm64@1.15.18': optional: true - '@swc/core-darwin-x64@1.15.11': + '@swc/core-darwin-x64@1.15.18': optional: true - '@swc/core-linux-arm-gnueabihf@1.15.11': + '@swc/core-linux-arm-gnueabihf@1.15.18': optional: true - '@swc/core-linux-arm64-gnu@1.15.11': + '@swc/core-linux-arm64-gnu@1.15.18': optional: true - '@swc/core-linux-arm64-musl@1.15.11': + '@swc/core-linux-arm64-musl@1.15.18': optional: true - '@swc/core-linux-x64-gnu@1.15.11': + '@swc/core-linux-x64-gnu@1.15.18': optional: true - '@swc/core-linux-x64-musl@1.15.11': + '@swc/core-linux-x64-musl@1.15.18': optional: true - '@swc/core-win32-arm64-msvc@1.15.11': + '@swc/core-win32-arm64-msvc@1.15.18': optional: true - '@swc/core-win32-ia32-msvc@1.15.11': + '@swc/core-win32-ia32-msvc@1.15.18': optional: true - '@swc/core-win32-x64-msvc@1.15.11': + '@swc/core-win32-x64-msvc@1.15.18': optional: true - '@swc/core@1.15.11': + '@swc/core@1.15.18': dependencies: '@swc/counter': 0.1.3 '@swc/types': 0.1.25 optionalDependencies: - '@swc/core-darwin-arm64': 1.15.11 - '@swc/core-darwin-x64': 1.15.11 - '@swc/core-linux-arm-gnueabihf': 1.15.11 - '@swc/core-linux-arm64-gnu': 1.15.11 - '@swc/core-linux-arm64-musl': 1.15.11 - '@swc/core-linux-x64-gnu': 1.15.11 - '@swc/core-linux-x64-musl': 1.15.11 - '@swc/core-win32-arm64-msvc': 1.15.11 - '@swc/core-win32-ia32-msvc': 1.15.11 - '@swc/core-win32-x64-msvc': 1.15.11 + '@swc/core-darwin-arm64': 1.15.18 + '@swc/core-darwin-x64': 1.15.18 + '@swc/core-linux-arm-gnueabihf': 1.15.18 + '@swc/core-linux-arm64-gnu': 1.15.18 + '@swc/core-linux-arm64-musl': 1.15.18 + '@swc/core-linux-x64-gnu': 1.15.18 + '@swc/core-linux-x64-musl': 1.15.18 + '@swc/core-win32-arm64-msvc': 1.15.18 + '@swc/core-win32-ia32-msvc': 1.15.18 + '@swc/core-win32-x64-msvc': 1.15.18 '@swc/counter@0.1.3': {} @@ -17634,13 +16281,13 @@ snapshots: dependencies: defer-to-connect: 1.1.3 - '@tracerbench/core@8.0.1(patch_hash=94ed69d4e124c0c94f1c1e3332668ae5d3265509b12cc97dd634feee8ed7e846)': + '@tracerbench/core@8.0.1(patch_hash=ee5cfa4adb0f65df07ef51d9be56c31150b4330d7ac7e1fbbb0a87329938af0a)': dependencies: '@tracerbench/har': 8.0.0 '@tracerbench/trace-event': 8.0.0 '@tracerbench/trace-model': 8.0.0 '@types/d3-hierarchy': 3.1.7 - '@types/node': 22.19.11 + '@types/node': 22.19.15 array-binsearch: 1.0.1 chalk: 4.1.2 chrome-debugging-client: 2.1.0(devtools-protocol@0.0.975963) @@ -17746,7 +16393,7 @@ snapshots: '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 - '@types/node': 22.19.11 + '@types/node': 22.19.15 '@types/chai-as-promised@7.1.8': dependencies: @@ -17756,15 +16403,15 @@ snapshots: '@types/cli-progress@3.11.6': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 '@types/connect@3.4.38': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 '@types/cors@2.8.19': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 '@types/d3-hierarchy@3.1.7': {} @@ -17787,8 +16434,8 @@ snapshots: '@types/express-serve-static-core@4.19.8': dependencies: - '@types/node': 22.19.11 - '@types/qs': 6.14.0 + '@types/node': 22.19.15 + '@types/qs': 6.15.0 '@types/range-parser': 1.2.7 '@types/send': 1.2.1 @@ -17796,25 +16443,16 @@ snapshots: dependencies: '@types/body-parser': 1.19.6 '@types/express-serve-static-core': 4.19.8 - '@types/qs': 6.14.0 + '@types/qs': 6.15.0 '@types/serve-static': 1.15.10 '@types/fs-extra@5.1.0': dependencies: - '@types/node': 22.19.11 - - '@types/fs-extra@8.1.5': - dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 '@types/fs-extra@9.0.13': dependencies: - '@types/node': 20.19.33 - - '@types/glob@7.2.0': - dependencies: - '@types/minimatch': 6.0.0 - '@types/node': 22.19.11 + '@types/node': 22.19.15 '@types/glob@9.0.0': dependencies: @@ -17828,7 +16466,7 @@ snapshots: '@types/keyv@3.1.4': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 '@types/mime@1.3.5': {} @@ -17836,23 +16474,19 @@ snapshots: '@types/minimatch@5.1.2': {} - '@types/minimatch@6.0.0': - dependencies: - minimatch: 7.4.6 - '@types/minimist@1.2.5': {} - '@types/node@20.19.33': + '@types/node@20.19.37': dependencies: undici-types: 6.21.0 - '@types/node@22.19.11': + '@types/node@22.19.15': dependencies: undici-types: 6.21.0 '@types/normalize-package-data@2.4.4': {} - '@types/qs@6.14.0': {} + '@types/qs@6.15.0': {} '@types/qunit@2.19.13': {} @@ -17860,38 +16494,38 @@ snapshots: '@types/responselike@1.0.3': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 '@types/rimraf@2.0.5': dependencies: '@types/glob': 9.0.0 - '@types/node': 22.19.11 + '@types/node': 22.19.15 '@types/rimraf@3.0.2': dependencies: '@types/glob': 9.0.0 - '@types/node': 20.19.33 + '@types/node': 22.19.15 '@types/rsvp@4.0.9': {} '@types/send@0.17.6': dependencies: '@types/mime': 1.3.5 - '@types/node': 22.19.11 + '@types/node': 22.19.15 '@types/send@1.2.1': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 '@types/serve-static@1.15.10': dependencies: '@types/http-errors': 2.0.5 - '@types/node': 22.19.11 + '@types/node': 22.19.15 '@types/send': 0.17.6 '@types/ssri@7.1.5': dependencies: - '@types/node': 20.19.33 + '@types/node': 22.19.15 '@types/supports-color@8.1.3': {} @@ -17903,15 +16537,15 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@8.55.0(@typescript-eslint/parser@8.55.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.56.1(@typescript-eslint/parser@8.56.1(eslint@9.39.3)(typescript@5.9.3))(eslint@9.39.3)(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.55.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.55.0 - '@typescript-eslint/type-utils': 8.55.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/utils': 8.55.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.55.0 - eslint: 9.39.2 + '@typescript-eslint/parser': 8.56.1(eslint@9.39.3)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.56.1 + '@typescript-eslint/type-utils': 8.56.1(eslint@9.39.3)(typescript@5.9.3) + '@typescript-eslint/utils': 8.56.1(eslint@9.39.3)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.56.1 + eslint: 9.39.3 ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.4.0(typescript@5.9.3) @@ -17919,71 +16553,58 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.55.0(eslint@8.57.1)(typescript@5.9.3)': - dependencies: - '@typescript-eslint/scope-manager': 8.55.0 - '@typescript-eslint/types': 8.55.0 - '@typescript-eslint/typescript-estree': 8.55.0(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.55.0 - debug: 4.4.3(supports-color@8.1.1) - eslint: 8.57.1 - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - optional: true - - '@typescript-eslint/parser@8.55.0(eslint@9.39.2)(typescript@5.9.3)': + '@typescript-eslint/parser@8.56.1(eslint@9.39.3)(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.55.0 - '@typescript-eslint/types': 8.55.0 - '@typescript-eslint/typescript-estree': 8.55.0(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.55.0 + '@typescript-eslint/scope-manager': 8.56.1 + '@typescript-eslint/types': 8.56.1 + '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.56.1 debug: 4.4.3(supports-color@8.1.1) - eslint: 9.39.2 + eslint: 9.39.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.55.0(typescript@5.9.3)': + '@typescript-eslint/project-service@8.56.1(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.55.0(typescript@5.9.3) - '@typescript-eslint/types': 8.55.0 + '@typescript-eslint/tsconfig-utils': 8.56.1(typescript@5.9.3) + '@typescript-eslint/types': 8.56.1 debug: 4.4.3(supports-color@8.1.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.55.0': + '@typescript-eslint/scope-manager@8.56.1': dependencies: - '@typescript-eslint/types': 8.55.0 - '@typescript-eslint/visitor-keys': 8.55.0 + '@typescript-eslint/types': 8.56.1 + '@typescript-eslint/visitor-keys': 8.56.1 - '@typescript-eslint/tsconfig-utils@8.55.0(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.56.1(typescript@5.9.3)': dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.55.0(eslint@9.39.2)(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.56.1(eslint@9.39.3)(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.55.0 - '@typescript-eslint/typescript-estree': 8.55.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.55.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/types': 8.56.1 + '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.56.1(eslint@9.39.3)(typescript@5.9.3) debug: 4.4.3(supports-color@8.1.1) - eslint: 9.39.2 + eslint: 9.39.3 ts-api-utils: 2.4.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.55.0': {} + '@typescript-eslint/types@8.56.1': {} - '@typescript-eslint/typescript-estree@8.55.0(typescript@5.9.3)': + '@typescript-eslint/typescript-estree@8.56.1(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.55.0(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.55.0(typescript@5.9.3) - '@typescript-eslint/types': 8.55.0 - '@typescript-eslint/visitor-keys': 8.55.0 + '@typescript-eslint/project-service': 8.56.1(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.56.1(typescript@5.9.3) + '@typescript-eslint/types': 8.56.1 + '@typescript-eslint/visitor-keys': 8.56.1 debug: 4.4.3(supports-color@8.1.1) - minimatch: 9.0.9 + minimatch: 10.2.4 semver: 7.7.4 tinyglobby: 0.2.15 ts-api-utils: 2.4.0(typescript@5.9.3) @@ -17991,106 +16612,30 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.55.0(eslint@9.39.2)(typescript@5.9.3)': + '@typescript-eslint/utils@8.56.1(eslint@9.39.3)(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2) - '@typescript-eslint/scope-manager': 8.55.0 - '@typescript-eslint/types': 8.55.0 - '@typescript-eslint/typescript-estree': 8.55.0(typescript@5.9.3) - eslint: 9.39.2 + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.3) + '@typescript-eslint/scope-manager': 8.56.1 + '@typescript-eslint/types': 8.56.1 + '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3) + eslint: 9.39.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.55.0': + '@typescript-eslint/visitor-keys@8.56.1': dependencies: - '@typescript-eslint/types': 8.55.0 - eslint-visitor-keys: 4.2.1 + '@typescript-eslint/types': 8.56.1 + eslint-visitor-keys: 5.0.1 - '@ungap/structured-clone@1.3.0': {} - - '@warp-drive/build-config@5.8.1(@babel/core@7.29.0)': + '@webassemblyjs/ast@1.14.1': dependencies: - '@embroider/addon-shim': 1.10.2 - '@embroider/macros': 1.19.7(@babel/core@7.29.0) - babel-import-util: 2.1.1 - babel-plugin-debug-macros: 2.0.0(@babel/core@7.29.0) - semver: 7.7.4 - transitivePeerDependencies: - - '@babel/core' - - '@glint/template' - - supports-color + '@webassemblyjs/helper-numbers': 1.13.2 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@warp-drive/core-types@5.8.1(@babel/core@7.29.0)': - dependencies: - '@embroider/macros': 1.19.7(@babel/core@7.29.0) - '@warp-drive/core': 5.8.1(@babel/core@7.29.0) - transitivePeerDependencies: - - '@babel/core' - - '@glint/template' - - supports-color + '@webassemblyjs/floating-point-hex-parser@1.13.2': {} - '@warp-drive/core@5.8.1(@babel/core@7.29.0)': - dependencies: - '@embroider/macros': 1.19.7(@babel/core@7.29.0) - '@warp-drive/build-config': 5.8.1(@babel/core@7.29.0) - transitivePeerDependencies: - - '@babel/core' - - '@glint/template' - - supports-color - - '@warp-drive/ember@5.8.1(@babel/core@7.29.0)(@ember/test-waiters@3.1.0)': - dependencies: - '@ember/test-waiters': 3.1.0 - '@embroider/macros': 1.19.7(@babel/core@7.29.0) - '@warp-drive/core': 5.8.1(@babel/core@7.29.0) - transitivePeerDependencies: - - '@babel/core' - - '@glint/template' - - supports-color - - '@warp-drive/json-api@5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0))': - dependencies: - '@embroider/macros': 1.19.7(@babel/core@7.29.0) - '@warp-drive/core': 5.8.1(@babel/core@7.29.0) - fuse.js: 7.1.0 - json-to-ast: 2.1.0 - transitivePeerDependencies: - - '@babel/core' - - '@glint/template' - - supports-color - - '@warp-drive/legacy@5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0))(@warp-drive/utilities@5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0)))': - dependencies: - '@ember/edition-utils': 1.2.0 - '@embroider/macros': 1.19.7(@babel/core@7.29.0) - '@warp-drive/core': 5.8.1(@babel/core@7.29.0) - '@warp-drive/utilities': 5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0)) - ember-cli-string-utils: 1.1.0 - ember-cli-test-info: 1.0.0 - inflection: 3.0.2 - transitivePeerDependencies: - - '@babel/core' - - '@glint/template' - - supports-color - - '@warp-drive/utilities@5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0))': - dependencies: - '@embroider/macros': 1.19.7(@babel/core@7.29.0) - '@warp-drive/core': 5.8.1(@babel/core@7.29.0) - transitivePeerDependencies: - - '@babel/core' - - '@glint/template' - - supports-color - - '@webassemblyjs/ast@1.14.1': - dependencies: - '@webassemblyjs/helper-numbers': 1.13.2 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - - '@webassemblyjs/floating-point-hex-parser@1.13.2': {} - - '@webassemblyjs/helper-api-error@1.13.2': {} + '@webassemblyjs/helper-api-error@1.13.2': {} '@webassemblyjs/helper-buffer@1.14.1': {} @@ -18185,19 +16730,19 @@ snapshots: mime-types: 3.0.2 negotiator: 1.0.0 - acorn-import-phases@1.0.4(acorn@8.15.0): + acorn-import-phases@1.0.4(acorn@8.16.0): dependencies: - acorn: 8.15.0 + acorn: 8.16.0 - acorn-jsx@5.3.2(acorn@8.15.0): + acorn-jsx@5.3.2(acorn@8.16.0): dependencies: - acorn: 8.15.0 + acorn: 8.16.0 - acorn-walk@8.3.4: + acorn-walk@8.3.5: dependencies: - acorn: 8.15.0 + acorn: 8.16.0 - acorn@8.15.0: {} + acorn@8.16.0: {} agent-base@4.3.0: dependencies: @@ -18213,23 +16758,16 @@ snapshots: ajv-formats@2.1.1: dependencies: - ajv: 8.17.1 + ajv: 8.18.0 ajv-keywords@3.5.2(ajv@6.14.0): dependencies: ajv: 6.14.0 - ajv-keywords@5.1.0(ajv@8.17.1): - dependencies: - ajv: 8.17.1 - fast-deep-equal: 3.1.3 - - ajv@6.12.6: + ajv-keywords@5.1.0(ajv@8.18.0): dependencies: + ajv: 8.18.0 fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 ajv@6.14.0: dependencies: @@ -18238,7 +16776,7 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ajv@8.17.1: + ajv@8.18.0: dependencies: fast-deep-equal: 3.1.3 fast-uri: 3.1.0 @@ -18299,11 +16837,9 @@ snapshots: dependencies: color-convert: 2.0.1 - ansi-styles@6.2.3: {} + ansi-styles@5.2.0: {} - ansi-to-html@0.6.15: - dependencies: - entities: 2.2.0 + ansi-styles@6.2.3: {} ansicolors@0.2.1: {} @@ -18563,38 +17099,30 @@ snapshots: babel-import-util@3.0.1: {} - babel-loader@8.4.1(@babel/core@7.29.0(supports-color@8.1.1))(webpack@5.105.1(@swc/core@1.15.11)): + babel-loader@8.4.1(@babel/core@7.29.0(supports-color@8.1.1))(webpack@5.105.4(@swc/core@1.15.18)): dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) find-cache-dir: 3.3.2 loader-utils: 2.0.4 make-dir: 3.1.0 schema-utils: 2.7.1 - webpack: 5.105.1(@swc/core@1.15.11) + webpack: 5.105.4(@swc/core@1.15.18) - babel-loader@8.4.1(@babel/core@7.29.0)(webpack@5.105.1): + babel-loader@8.4.1(@babel/core@7.29.0)(webpack@5.105.4): dependencies: '@babel/core': 7.29.0 find-cache-dir: 3.3.2 loader-utils: 2.0.4 make-dir: 3.1.0 schema-utils: 2.7.1 - webpack: 5.105.1 + webpack: 5.105.4 - babel-loader@9.2.1(@babel/core@7.29.0(supports-color@8.1.1))(webpack@5.105.1(@swc/core@1.15.11)): + babel-loader@9.2.1(@babel/core@7.29.0(supports-color@8.1.1))(webpack@5.105.4(@swc/core@1.15.18)): dependencies: '@babel/core': 7.29.0(supports-color@8.1.1) find-cache-dir: 4.0.0 schema-utils: 4.3.3 - webpack: 5.105.1(@swc/core@1.15.11) - - babel-loader@9.2.1(@babel/core@7.29.0)(webpack@5.105.1): - dependencies: - '@babel/core': 7.29.0 - find-cache-dir: 4.0.0 - schema-utils: 4.3.3 - webpack: 5.105.1 - optional: true + webpack: 5.105.4(@swc/core@1.15.18) babel-plugin-debug-macros@0.3.4(@babel/core@7.29.0): dependencies: @@ -18676,11 +17204,11 @@ snapshots: transitivePeerDependencies: - supports-color - babel-plugin-polyfill-corejs2@0.4.15(@babel/core@7.29.0)(supports-color@8.1.1): + babel-plugin-polyfill-corejs2@0.4.15(@babel/core@7.29.0): dependencies: '@babel/compat-data': 7.29.0 '@babel/core': 7.29.0 - '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0)(supports-color@8.1.1) + '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0) semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -18688,7 +17216,7 @@ snapshots: babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.29.0): dependencies: '@babel/core': 7.29.0 - '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0)(supports-color@8.1.1) + '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0) core-js-compat: 3.48.0 transitivePeerDependencies: - supports-color @@ -18701,10 +17229,10 @@ snapshots: transitivePeerDependencies: - supports-color - babel-plugin-polyfill-corejs3@0.14.0(@babel/core@7.29.0)(supports-color@8.1.1): + babel-plugin-polyfill-corejs3@0.14.0(@babel/core@7.29.0): dependencies: '@babel/core': 7.29.0 - '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0)(supports-color@8.1.1) + '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0) core-js-compat: 3.48.0 transitivePeerDependencies: - supports-color @@ -18716,10 +17244,10 @@ snapshots: transitivePeerDependencies: - supports-color - babel-plugin-polyfill-regenerator@0.6.6(@babel/core@7.29.0)(supports-color@8.1.1): + babel-plugin-polyfill-regenerator@0.6.6(@babel/core@7.29.0): dependencies: '@babel/core': 7.29.0 - '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0)(supports-color@8.1.1) + '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0) transitivePeerDependencies: - supports-color @@ -18738,7 +17266,7 @@ snapshots: backbone@1.6.1: dependencies: - underscore: 1.13.7 + underscore: 1.13.8 backburner.js@2.8.0: {} @@ -18762,7 +17290,7 @@ snapshots: mixin-deep: 1.3.2 pascalcase: 0.1.1 - baseline-browser-mapping@2.9.19: {} + baseline-browser-mapping@2.10.0: {} basic-auth@2.0.1: dependencies: @@ -18809,7 +17337,7 @@ snapshots: http-errors: 2.0.1 iconv-lite: 0.4.24 on-finished: 2.4.1 - qs: 6.14.1 + qs: 6.14.2 raw-body: 2.5.3 type-is: 1.6.18 unpipe: 1.0.0 @@ -18824,7 +17352,7 @@ snapshots: http-errors: 2.0.1 iconv-lite: 0.7.2 on-finished: 2.4.1 - qs: 6.14.1 + qs: 6.15.0 raw-body: 3.0.2 type-is: 2.0.1 transitivePeerDependencies: @@ -18837,7 +17365,7 @@ snapshots: raw-body: 1.1.7 safe-json-parse: 1.0.1 - bole@5.0.27: + bole@5.0.28: dependencies: fast-safe-stringify: 2.1.1 individual: 3.0.0 @@ -18898,7 +17426,7 @@ snapshots: broccoli-filter: 1.3.0 broccoli-persistent-filter: 1.4.6 json-stable-stringify: 1.3.0 - minimatch: 3.1.2 + minimatch: 3.1.5 rsvp: 3.6.2 transitivePeerDependencies: - supports-color @@ -18917,7 +17445,7 @@ snapshots: broccoli-merge-trees: 3.0.2 broccoli-persistent-filter: 2.3.1 clone: 2.1.2 - hash-for-dep: 1.5.1 + hash-for-dep: 1.5.2 heimdalljs: 0.2.6 heimdalljs-logger: 0.1.10 json-stable-stringify: 1.3.0 @@ -18931,7 +17459,7 @@ snapshots: '@babel/core': 7.29.0 broccoli-persistent-filter: 3.1.3 clone: 2.1.2 - hash-for-dep: 1.5.1 + hash-for-dep: 1.5.2 heimdalljs: 0.2.6 heimdalljs-logger: 0.1.10 json-stable-stringify: 1.3.0 @@ -18940,18 +17468,6 @@ snapshots: transitivePeerDependencies: - supports-color - broccoli-builder@0.18.14: - dependencies: - broccoli-node-info: 1.1.0 - heimdalljs: 0.2.6 - promise-map-series: 0.2.3 - quick-temp: 0.1.9 - rimraf: 2.7.1 - rsvp: 3.6.2 - silent-error: 1.1.1 - transitivePeerDependencies: - - supports-color - broccoli-caching-writer@2.0.4: dependencies: broccoli-kitchen-sink-helpers: 0.2.9 @@ -18986,19 +17502,16 @@ snapshots: transitivePeerDependencies: - supports-color - broccoli-concat@4.2.5: + broccoli-concat@4.2.7: dependencies: broccoli-debug: 0.6.5 - broccoli-kitchen-sink-helpers: 0.3.1 broccoli-plugin: 4.0.7 ensure-posix-path: 1.1.1 fast-sourcemap-concat: 2.1.1 find-index: 1.1.1 fs-extra: 8.1.0 fs-tree-diff: 2.0.1 - lodash.merge: 4.6.2 - lodash.omit: 4.5.0 - lodash.uniq: 4.5.0 + lodash: 4.17.23 transitivePeerDependencies: - supports-color @@ -19008,9 +17521,8 @@ snapshots: transitivePeerDependencies: - supports-color - broccoli-config-replace@1.1.2: + broccoli-config-replace@1.1.3: dependencies: - broccoli-kitchen-sink-helpers: 0.3.1 broccoli-plugin: 1.3.1 debug: 2.6.9 fs-extra: 0.24.0 @@ -19074,7 +17586,7 @@ snapshots: debug: 4.4.3(supports-color@8.1.1) fs-tree-diff: 2.0.1 heimdalljs: 0.2.6 - minimatch: 3.1.2 + minimatch: 3.1.5 walk-sync: 2.2.0 transitivePeerDependencies: - supports-color @@ -19125,8 +17637,6 @@ snapshots: broccoli-node-api@1.7.0: {} - broccoli-node-info@1.1.0: {} - broccoli-node-info@2.2.0: {} broccoli-output-wrapper@3.2.5: @@ -19143,7 +17653,7 @@ snapshots: async-promise-queue: 1.0.5 broccoli-plugin: 1.3.1 fs-tree-diff: 0.5.9 - hash-for-dep: 1.5.1 + hash-for-dep: 1.5.2 heimdalljs: 0.2.6 heimdalljs-logger: 0.1.10 mkdirp: 0.5.6 @@ -19161,7 +17671,7 @@ snapshots: async-promise-queue: 1.0.5 broccoli-plugin: 1.3.1 fs-tree-diff: 2.0.1 - hash-for-dep: 1.5.1 + hash-for-dep: 1.5.2 heimdalljs: 0.2.6 heimdalljs-logger: 0.1.10 mkdirp: 0.5.6 @@ -19180,7 +17690,7 @@ snapshots: async-promise-queue: 1.0.5 broccoli-plugin: 4.0.7 fs-tree-diff: 2.0.1 - hash-for-dep: 1.5.1 + hash-for-dep: 1.5.2 heimdalljs: 0.2.6 heimdalljs-logger: 0.1.10 promise-map-series: 0.2.3 @@ -19320,7 +17830,7 @@ snapshots: heimdalljs-logger: 0.1.10 mime-types: 3.0.2 resolve-path: 1.4.0 - rimraf: 6.1.2 + rimraf: 6.1.3 sane: 5.0.1 tmp: 0.2.5 tree-sync: 2.1.0 @@ -19329,10 +17839,6 @@ snapshots: transitivePeerDependencies: - supports-color - brotli@1.3.3: - dependencies: - base64-js: 1.5.1 - browser-stdout@1.3.1: {} browserslist-to-esbuild@2.1.1(browserslist@4.28.1): @@ -19342,19 +17848,18 @@ snapshots: browserslist@4.28.1: dependencies: - baseline-browser-mapping: 2.9.19 - caniuse-lite: 1.0.30001769 - electron-to-chromium: 1.5.286 - node-releases: 2.0.27 + baseline-browser-mapping: 2.10.0 + caniuse-lite: 1.0.30001776 + electron-to-chromium: 1.5.307 + node-releases: 2.0.36 update-browserslist-db: 1.2.3(browserslist@4.28.1) - browserstack-local@1.5.9: + browserstack-local@1.5.12: dependencies: agent-base: 6.0.2 https-proxy-agent: 5.0.1 is-running: 2.1.0 - ps-tree: 1.2.0 - temp-fs: 0.9.9 + tree-kill: 1.2.2 transitivePeerDependencies: - supports-color @@ -19407,10 +17912,10 @@ snapshots: normalize-url: 4.5.1 responselike: 1.0.2 - cacheable@2.3.2: + cacheable@2.3.3: dependencies: - '@cacheable/memory': 2.0.7 - '@cacheable/utils': 2.3.4 + '@cacheable/memory': 2.0.8 + '@cacheable/utils': 2.4.0 hookified: 1.15.1 keyv: 5.6.0 qified: 0.6.0 @@ -19461,7 +17966,7 @@ snapshots: dependencies: path-temp: 2.1.1 - caniuse-lite@1.0.30001769: {} + caniuse-lite@1.0.30001776: {} capture-exit@2.0.0: dependencies: @@ -19582,7 +18087,7 @@ snapshots: chrome-launcher@1.2.1: dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 2.0.2 @@ -19591,8 +18096,6 @@ snapshots: chrome-trace-event@1.0.4: {} - ci-info@3.9.0: {} - ci-info@4.4.0: {} cjson@0.3.0: @@ -19695,8 +18198,6 @@ snapshots: dependencies: q: 0.9.7 - code-error-fragment@0.0.230: {} - code-point-at@1.1.0: {} codsen-utils@1.7.3: @@ -19802,15 +18303,6 @@ snapshots: ini: 1.3.8 proto-list: 1.2.4 - configstore@5.0.1: - dependencies: - dot-prop: 5.3.0 - graceful-fs: 4.2.11 - make-dir: 3.1.0 - unique-string: 2.0.0 - write-file-atomic: 3.0.3 - xdg-basedir: 4.0.0 - configstore@7.1.0: dependencies: atomically: 2.1.1 @@ -19837,7 +18329,7 @@ snapshots: ora: 3.4.0 through2: 3.0.2 - consolidate@0.16.0(ejs@3.1.10)(handlebars@4.7.8)(lodash@4.17.23)(mustache@4.2.0)(underscore@1.13.7): + consolidate@0.16.0(ejs@3.1.10)(handlebars@4.7.8)(lodash@4.17.23)(mustache@4.2.0)(underscore@1.13.8): dependencies: bluebird: 3.7.2 optionalDependencies: @@ -19845,7 +18337,7 @@ snapshots: handlebars: 4.7.8 lodash: 4.17.23 mustache: 4.2.0 - underscore: 1.13.7 + underscore: 1.13.8 content-disposition@0.5.4: dependencies: @@ -19892,7 +18384,7 @@ snapshots: object-assign: 4.1.1 vary: 1.1.2 - cosmiconfig@9.0.0(typescript@5.9.3): + cosmiconfig@9.0.1(typescript@5.9.3): dependencies: env-paths: 2.2.1 import-fresh: 3.3.1 @@ -19939,7 +18431,7 @@ snapshots: css-functions-list@3.3.3: {} - css-loader@5.2.7(webpack@5.105.1(@swc/core@1.15.11)): + css-loader@5.2.7(webpack@5.105.4(@swc/core@1.15.18)): dependencies: icss-utils: 5.1.0(postcss@8.5.8) loader-utils: 2.0.4 @@ -19951,9 +18443,9 @@ snapshots: postcss-value-parser: 4.2.0 schema-utils: 3.3.0 semver: 7.7.4 - webpack: 5.105.1(@swc/core@1.15.11) + webpack: 5.105.4(@swc/core@1.15.18) - css-loader@5.2.7(webpack@5.105.1): + css-loader@5.2.7(webpack@5.105.4): dependencies: icss-utils: 5.1.0(postcss@8.5.8) loader-utils: 2.0.4 @@ -19965,16 +18457,16 @@ snapshots: postcss-value-parser: 4.2.0 schema-utils: 3.3.0 semver: 7.7.4 - webpack: 5.105.1 + webpack: 5.105.4 css-tree@1.1.3: dependencies: mdn-data: 2.0.14 source-map: 0.6.1 - css-tree@3.1.0: + css-tree@3.2.1: dependencies: - mdn-data: 2.12.2 + mdn-data: 2.27.1 source-map-js: 1.2.1 cssesc@3.0.0: {} @@ -20161,14 +18653,10 @@ snapshots: detect-file@1.0.0: {} - detect-indent@6.1.0: {} - detect-indent@7.0.2: {} detect-libc@2.1.2: {} - detect-newline@3.1.0: {} - detect-newline@4.0.1: {} devtools-protocol@0.0.975963: {} @@ -20191,10 +18679,6 @@ snapshots: dependencies: esutils: 2.0.3 - doctrine@3.0.0: - dependencies: - esutils: 2.0.3 - dom-element-descriptors@0.5.1: {} dom-types@1.1.3: {} @@ -20204,10 +18688,6 @@ snapshots: no-case: 3.0.4 tslib: 2.8.1 - dot-prop@5.3.0: - dependencies: - is-obj: 2.0.0 - dot-prop@9.0.0: dependencies: type-fest: 4.41.0 @@ -20220,8 +18700,6 @@ snapshots: duplexer3@0.1.5: {} - duplexer@0.1.2: {} - eastasianwidth@0.2.0: {} ebnf-parser@0.1.10: {} @@ -20239,11 +18717,11 @@ snapshots: dependencies: jake: 10.9.4 - electron-to-chromium@1.5.286: {} + electron-to-chromium@1.5.307: {} elegant-spinner@1.0.1: {} - ember-auto-import@2.12.1(webpack@5.105.1): + ember-auto-import@2.13.0(webpack@5.105.4): dependencies: '@babel/core': 7.29.0 '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.29.0) @@ -20254,7 +18732,7 @@ snapshots: '@embroider/macros': 1.20.1(@babel/core@7.29.0) '@embroider/reverse-exports': 0.2.0 '@embroider/shared-internals': 2.9.2(supports-color@8.1.1) - babel-loader: 8.4.1(@babel/core@7.29.0)(webpack@5.105.1) + babel-loader: 8.4.1(@babel/core@7.29.0)(webpack@5.105.4) babel-plugin-ember-modules-api-polyfill: 3.5.0 babel-plugin-ember-template-compilation: 2.4.1 babel-plugin-htmlbars-inline-precompile: 5.3.1 @@ -20264,7 +18742,7 @@ snapshots: broccoli-merge-trees: 4.2.0 broccoli-plugin: 4.0.7 broccoli-source: 3.0.1 - css-loader: 5.2.7(webpack@5.105.1) + css-loader: 5.2.7(webpack@5.105.4) debug: 4.4.3(supports-color@8.1.1) fs-extra: 10.1.0 fs-tree-diff: 2.0.1 @@ -20272,14 +18750,14 @@ snapshots: is-subdir: 1.2.0 js-string-escape: 1.0.1 lodash: 4.17.23 - mini-css-extract-plugin: 2.10.0(webpack@5.105.1) + mini-css-extract-plugin: 2.10.0(webpack@5.105.4) minimatch: 3.1.5 parse5: 6.0.1 pkg-entry-points: 1.1.1 resolve: 1.22.11 resolve-package-path: 4.0.3 semver: 7.7.4 - style-loader: 2.0.0(webpack@5.105.1) + style-loader: 2.0.0(webpack@5.105.4) typescript-memoize: 1.1.1 walk-sync: 3.0.0 transitivePeerDependencies: @@ -20287,6 +18765,14 @@ snapshots: - supports-color - webpack + ember-cli-app-version@7.0.0(ember-source@): + dependencies: + ember-cli-babel: 7.26.11 + ember-source: 'link:' + git-repo-info: 2.1.1 + transitivePeerDependencies: + - supports-color + ember-cli-babel-plugin-helpers@1.1.1: {} ember-cli-babel@7.26.11: @@ -20373,26 +18859,25 @@ snapshots: ember-cli-browserstack@2.1.0: dependencies: browserstack: 1.6.1 - browserstack-local: 1.5.9 + browserstack-local: 1.5.12 debug: 4.4.3(supports-color@8.1.1) rsvp: 4.8.5 yargs: 17.7.2 transitivePeerDependencies: - supports-color - ember-cli-dependency-checker@3.3.3(ember-cli@5.7.0(@types/node@22.19.11)): + ember-cli-clean-css@3.0.0: dependencies: - chalk: 2.4.2 - ember-cli: 5.7.0(@types/node@22.19.11) - find-yarn-workspace-root: 2.0.0 - is-git-url: 1.0.0 - resolve: 1.22.11 - semver: 5.7.2 + broccoli-persistent-filter: 3.1.3 + clean-css: 5.3.3 + json-stable-stringify: 1.3.0 + transitivePeerDependencies: + - supports-color - ember-cli-dependency-checker@3.3.3(ember-cli@6.5.0(@types/node@22.19.11)(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.7)): + ember-cli-dependency-checker@3.3.3(ember-cli@6.11.0(@types/node@22.19.15)(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.8)): dependencies: chalk: 2.4.2 - ember-cli: 6.5.0(@types/node@22.19.11)(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.7) + ember-cli: 6.11.0(@types/node@22.19.15)(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.8) find-yarn-workspace-root: 2.0.0 is-git-url: 1.0.0 resolve: 1.22.11 @@ -20406,6 +18891,14 @@ snapshots: transitivePeerDependencies: - supports-color + ember-cli-deprecation-workflow@4.0.1(@babel/core@7.29.0): + dependencies: + '@embroider/addon-shim': 1.10.2 + decorator-transforms: 2.3.1(@babel/core@7.29.0) + transitivePeerDependencies: + - '@babel/core' + - supports-color + ember-cli-get-component-path-option@1.0.0: {} ember-cli-htmlbars@6.3.0: @@ -20418,7 +18911,7 @@ snapshots: broccoli-plugin: 4.0.7 ember-cli-version-checker: 5.1.2 fs-tree-diff: 2.0.1 - hash-for-dep: 1.5.1 + hash-for-dep: 1.5.2 heimdalljs-logger: 0.1.10 js-string-escape: 1.0.1 semver: 7.7.4 @@ -20468,8 +18961,6 @@ snapshots: ember-cli-is-package-missing@1.0.0: {} - ember-cli-lodash-subset@2.0.1: {} - ember-cli-normalize-entity-name@1.0.0: dependencies: silent-error: 1.1.1 @@ -20499,16 +18990,6 @@ snapshots: transitivePeerDependencies: - supports-color - ember-cli-test-info@1.0.0: - dependencies: - ember-cli-string-utils: 1.1.0 - - ember-cli-test-loader@3.1.0: - dependencies: - ember-cli-babel: 7.26.11 - transitivePeerDependencies: - - supports-color - ember-cli-typescript-blueprint-polyfill@0.1.0: dependencies: chalk: 4.1.2 @@ -20516,24 +18997,6 @@ snapshots: transitivePeerDependencies: - supports-color - ember-cli-typescript@2.0.2(@babel/core@7.29.0): - dependencies: - '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.29.0) - '@babel/plugin-transform-typescript': 7.4.5(@babel/core@7.29.0) - ansi-to-html: 0.6.15 - debug: 4.4.3(supports-color@8.1.1) - ember-cli-babel-plugin-helpers: 1.1.1 - execa: 1.0.0 - fs-extra: 7.0.1 - resolve: 1.22.11 - rsvp: 4.8.5 - semver: 6.3.1 - stagehand: 1.0.1 - walk-sync: 1.1.4 - transitivePeerDependencies: - - '@babel/core' - - supports-color - ember-cli-version-checker@3.1.3: dependencies: resolve-package-path: 1.2.7 @@ -20565,14 +19028,19 @@ snapshots: transitivePeerDependencies: - supports-color - ember-cli@5.7.0(@types/node@22.19.11): + ember-cli@6.11.0(@types/node@22.19.15)(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.8): dependencies: - '@pnpm/find-workspace-dir': 6.0.3 - broccoli: 3.5.2 - broccoli-builder: 0.18.14 - broccoli-concat: 4.2.5 + '@ember-tooling/blueprint-blueprint': 0.2.1 + '@ember-tooling/blueprint-model': 0.5.0 + '@ember-tooling/classic-build-addon-blueprint': 6.11.0 + '@ember-tooling/classic-build-app-blueprint': 6.11.0 + '@ember/app-blueprint': 6.11.1 + '@pnpm/find-workspace-dir': 1000.1.4 + babel-remove-types: 1.1.0 + broccoli: 4.0.0 + broccoli-concat: 4.2.7 broccoli-config-loader: 1.0.1 - broccoli-config-replace: 1.1.2 + broccoli-config-replace: 1.1.3 broccoli-debug: 0.6.5 broccoli-funnel: 3.0.8 broccoli-funnel-reducer: 1.0.0 @@ -20583,73 +19051,69 @@ snapshots: broccoli-stew: 3.0.0 calculate-cache-key-for-tree: 2.0.0 capture-exit: 2.0.0 - chalk: 4.1.2 - ci-info: 3.9.0 + chalk: 5.6.2 + ci-info: 4.4.0 clean-base-url: 1.0.0 compression: 1.8.1 - configstore: 5.0.1 + configstore: 7.1.0 console-ui: 3.1.2 + content-tag: 4.1.0 core-object: 3.1.5 dag-map: 2.0.2 - diff: 5.2.2 + diff: 8.0.3 ember-cli-is-package-missing: 1.0.0 - ember-cli-lodash-subset: 2.0.1 ember-cli-normalize-entity-name: 1.0.0 ember-cli-preprocess-registry: 5.0.1 ember-cli-string-utils: 1.1.0 - ember-template-tag: 2.3.16 ensure-posix-path: 1.1.1 - execa: 5.1.1 + execa: 9.6.1 exit: 0.1.2 - express: 4.22.1 - filesize: 10.1.6 - find-up: 5.0.0 + express: 5.2.1 + filesize: 11.0.13 + find-up: 8.0.0 find-yarn-workspace-root: 2.0.0 - fixturify-project: 2.1.1 - fs-extra: 11.3.3 + fs-extra: 11.3.4 fs-tree-diff: 2.0.1 get-caller-file: 2.0.5 git-repo-info: 2.1.1 - glob: 8.1.0 + glob: 13.0.6 heimdalljs: 0.2.6 heimdalljs-fs-monitor: 1.1.2 heimdalljs-graph: 1.0.0 heimdalljs-logger: 0.1.10 http-proxy: 1.18.1 - inflection: 2.0.1 - inquirer: 9.3.8(@types/node@22.19.11) + inflection: 3.0.2 + inquirer: 13.3.0(@types/node@22.19.15) is-git-url: 1.0.0 - is-language-code: 3.1.0 - isbinaryfile: 5.0.7 - lodash.template: 4.5.0 - markdown-it: 13.0.2 - markdown-it-terminal: 0.4.0(markdown-it@13.0.2) - minimatch: 7.4.6 + is-language-code: 5.1.3 + lodash: 4.17.23 + markdown-it: 14.1.1 + markdown-it-terminal: 0.4.0(markdown-it@14.1.1) + minimatch: 10.2.4 morgan: 1.10.1 nopt: 3.0.6 - npm-package-arg: 10.1.0 - os-locale: 5.0.0 - p-defer: 3.0.0 + npm-package-arg: 13.0.2 + os-locale: 6.0.2 + p-defer: 4.0.1 portfinder: 1.0.38 promise-map-series: 0.3.0 promise.hash.helper: 1.0.8 quick-temp: 0.1.9 - remove-types: 1.0.0 resolve: 1.22.11 resolve-package-path: 4.0.3 safe-stable-stringify: 2.5.0 sane: 5.0.1 semver: 7.7.4 silent-error: 1.1.1 - sort-package-json: 1.57.0 + sort-package-json: 3.6.1 symlink-or-copy: 1.3.1 temp: 0.9.4 - testem: 3.17.0(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.7) + testem: 3.17.0(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.8) tiny-lr: 2.0.0 tree-sync: 2.1.0 - walk-sync: 3.0.0 + walk-sync: 4.0.1 watch-detector: 1.0.2 - workerpool: 6.5.1 + workerpool: 10.0.1 yam: 1.0.0 transitivePeerDependencies: - '@types/node' @@ -20709,367 +19173,23 @@ snapshots: - walrus - whiskers - ember-cli@6.10.2(@types/node@22.19.11)(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.7): + ember-eslint-parser@0.5.13(@babel/core@7.29.0)(@typescript-eslint/parser@8.56.1(eslint@9.39.3)(typescript@5.9.3))(eslint@9.39.3)(typescript@5.9.3): dependencies: - '@ember-tooling/blueprint-blueprint': 0.2.1 - '@ember-tooling/blueprint-model': 0.5.0 - '@ember-tooling/classic-build-addon-blueprint': 6.10.0 - '@ember-tooling/classic-build-app-blueprint': 6.10.0 - '@ember/app-blueprint': 6.10.4 - '@pnpm/find-workspace-dir': 1000.1.4 - babel-remove-types: 1.1.0 - broccoli: 4.0.0 - broccoli-concat: 4.2.5 - broccoli-config-loader: 1.0.1 - broccoli-config-replace: 1.1.2 - broccoli-debug: 0.6.5 - broccoli-funnel: 3.0.8 - broccoli-funnel-reducer: 1.0.0 - broccoli-merge-trees: 4.2.0 - broccoli-middleware: 2.1.1 - broccoli-slow-trees: 3.1.0 - broccoli-source: 3.0.1 - broccoli-stew: 3.0.0 - calculate-cache-key-for-tree: 2.0.0 - capture-exit: 2.0.0 - chalk: 5.6.2 - ci-info: 4.4.0 - clean-base-url: 1.0.0 - compression: 1.8.1 - configstore: 7.1.0 - console-ui: 3.1.2 - content-tag: 4.1.0 - core-object: 3.1.5 - dag-map: 2.0.2 - diff: 8.0.3 - ember-cli-is-package-missing: 1.0.0 - ember-cli-normalize-entity-name: 1.0.0 - ember-cli-preprocess-registry: 5.0.1 - ember-cli-string-utils: 1.1.0 - ensure-posix-path: 1.1.1 - execa: 9.6.1 - exit: 0.1.2 - express: 5.2.1 - filesize: 11.0.13 - find-up: 8.0.0 - find-yarn-workspace-root: 2.0.0 - fs-extra: 11.3.3 - fs-tree-diff: 2.0.1 - get-caller-file: 2.0.5 - git-repo-info: 2.1.1 - glob: 13.0.2 - heimdalljs: 0.2.6 - heimdalljs-fs-monitor: 1.1.2 - heimdalljs-graph: 1.0.0 - heimdalljs-logger: 0.1.10 - http-proxy: 1.18.1 - inflection: 3.0.2 - inquirer: 13.3.0(@types/node@22.19.11) - is-git-url: 1.0.0 - is-language-code: 5.1.3 - lodash: 4.17.23 - markdown-it: 14.1.0 - markdown-it-terminal: 0.4.0(markdown-it@14.1.0) - minimatch: 10.1.2 - morgan: 1.10.1 - nopt: 3.0.6 - npm-package-arg: 13.0.2 - os-locale: 6.0.2 - p-defer: 4.0.1 - portfinder: 1.0.38 - promise-map-series: 0.3.0 - promise.hash.helper: 1.0.8 - quick-temp: 0.1.9 - resolve: 1.22.11 - resolve-package-path: 4.0.3 - safe-stable-stringify: 2.5.0 - sane: 5.0.1 - semver: 7.7.4 - silent-error: 1.1.1 - sort-package-json: 3.6.1 - symlink-or-copy: 1.3.1 - temp: 0.9.4 - testem: 3.17.0(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.7) - tiny-lr: 2.0.0 - tree-sync: 2.1.0 - walk-sync: 4.0.1 - watch-detector: 1.0.2 - workerpool: 10.0.1 - yam: 1.0.0 - transitivePeerDependencies: - - '@types/node' - - arc-templates - - atpl - - babel-core - - bracket-template - - bufferutil - - coffee-script - - debug - - dot - - dust - - dustjs-helpers - - dustjs-linkedin - - eco - - ect - - ejs - - haml-coffee - - hamlet - - hamljs - - handlebars - - hogan.js - - htmling - - jade - - jazz - - jqtpl - - just - - liquid-node - - liquor - - marko - - mote - - nunjucks - - plates - - pug - - qejs - - ractive - - razor-tmpl - - react - - react-dom - - slm - - squirrelly - - supports-color - - swig - - swig-templates - - teacup - - templayed - - then-jade - - then-pug - - tinyliquid - - toffee - - twig - - twing - - underscore - - utf-8-validate - - vash - - velocityjs - - walrus - - whiskers - - ember-cli@6.5.0(@types/node@22.19.11)(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.7): - dependencies: - '@pnpm/find-workspace-dir': 1000.1.4 - babel-remove-types: 1.1.0 - broccoli: 3.5.2 - broccoli-concat: 4.2.5 - broccoli-config-loader: 1.0.1 - broccoli-config-replace: 1.1.2 - broccoli-debug: 0.6.5 - broccoli-funnel: 3.0.8 - broccoli-funnel-reducer: 1.0.0 - broccoli-merge-trees: 4.2.0 - broccoli-middleware: 2.1.1 - broccoli-slow-trees: 3.1.0 - broccoli-source: 3.0.1 - broccoli-stew: 3.0.0 - calculate-cache-key-for-tree: 2.0.0 - capture-exit: 2.0.0 - chalk: 4.1.2 - ci-info: 4.4.0 - clean-base-url: 1.0.0 - compression: 1.8.1 - configstore: 5.0.1 - console-ui: 3.1.2 - content-tag: 3.1.3 - core-object: 3.1.5 - dag-map: 2.0.2 - diff: 7.0.0 - ember-cli-is-package-missing: 1.0.0 - ember-cli-normalize-entity-name: 1.0.0 - ember-cli-preprocess-registry: 5.0.1 - ember-cli-string-utils: 1.1.0 - ensure-posix-path: 1.1.1 - execa: 5.1.1 - exit: 0.1.2 - express: 4.22.1 - filesize: 10.1.6 - find-up: 5.0.0 - find-yarn-workspace-root: 2.0.0 - fixturify-project: 2.1.1 - fs-extra: 11.3.3 - fs-tree-diff: 2.0.1 - get-caller-file: 2.0.5 - git-repo-info: 2.1.1 - glob: 8.1.0 - heimdalljs: 0.2.6 - heimdalljs-fs-monitor: 1.1.2 - heimdalljs-graph: 1.0.0 - heimdalljs-logger: 0.1.10 - http-proxy: 1.18.1 - inflection: 2.0.1 - inquirer: 9.3.8(@types/node@22.19.11) - is-git-url: 1.0.0 - is-language-code: 3.1.0 - isbinaryfile: 5.0.7 - lodash: 4.17.23 - markdown-it: 14.1.0 - markdown-it-terminal: 0.4.0(markdown-it@14.1.0) - minimatch: 7.4.6 - morgan: 1.10.1 - nopt: 3.0.6 - npm-package-arg: 12.0.2 - os-locale: 5.0.0 - p-defer: 3.0.0 - portfinder: 1.0.38 - promise-map-series: 0.3.0 - promise.hash.helper: 1.0.8 - quick-temp: 0.1.9 - resolve: 1.22.11 - resolve-package-path: 4.0.3 - safe-stable-stringify: 2.5.0 - sane: 5.0.1 - semver: 7.7.4 - silent-error: 1.1.1 - sort-package-json: 2.15.1 - symlink-or-copy: 1.3.1 - temp: 0.9.4 - testem: 3.17.0(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.7) - tiny-lr: 2.0.0 - tree-sync: 2.1.0 - walk-sync: 3.0.0 - watch-detector: 1.0.2 - workerpool: 9.3.4 - yam: 1.0.0 - transitivePeerDependencies: - - '@types/node' - - arc-templates - - atpl - - babel-core - - bracket-template - - bufferutil - - coffee-script - - debug - - dot - - dust - - dustjs-helpers - - dustjs-linkedin - - eco - - ect - - ejs - - haml-coffee - - hamlet - - hamljs - - handlebars - - hogan.js - - htmling - - jade - - jazz - - jqtpl - - just - - liquid-node - - liquor - - marko - - mote - - nunjucks - - plates - - pug - - qejs - - ractive - - razor-tmpl - - react - - react-dom - - slm - - squirrelly - - supports-color - - swig - - swig-templates - - teacup - - templayed - - then-jade - - then-pug - - tinyliquid - - toffee - - twig - - twing - - underscore - - utf-8-validate - - vash - - velocityjs - - walrus - - whiskers - - ember-data@5.8.1(@babel/core@7.29.0)(@ember/test-helpers@3.3.1(@babel/core@7.29.0)(ember-source@)(webpack@5.105.1))(@ember/test-waiters@3.1.0)(qunit@2.25.0): - dependencies: - '@ember-data/adapter': 5.8.1(@babel/core@7.29.0) - '@ember-data/debug': 5.8.1(@babel/core@7.29.0) - '@ember-data/graph': 5.8.1(@babel/core@7.29.0) - '@ember-data/json-api': 5.8.1(@babel/core@7.29.0) - '@ember-data/legacy-compat': 5.8.1(@babel/core@7.29.0) - '@ember-data/model': 5.8.1(@babel/core@7.29.0) - '@ember-data/request': 5.8.1(@babel/core@7.29.0) - '@ember-data/request-utils': 5.8.1(@babel/core@7.29.0) - '@ember-data/serializer': 5.8.1(@babel/core@7.29.0) - '@ember-data/store': 5.8.1(@babel/core@7.29.0)(@ember-data/tracking@5.8.1(@babel/core@7.29.0)(@ember/test-waiters@3.1.0))(@ember/test-waiters@3.1.0) - '@ember-data/tracking': 5.8.1(@babel/core@7.29.0)(@ember/test-waiters@3.1.0) - '@ember/edition-utils': 1.2.0 - '@ember/test-waiters': 3.1.0 - '@embroider/macros': 1.19.7(@babel/core@7.29.0) - '@warp-drive/core': 5.8.1(@babel/core@7.29.0) - '@warp-drive/core-types': 5.8.1(@babel/core@7.29.0) - '@warp-drive/ember': 5.8.1(@babel/core@7.29.0)(@ember/test-waiters@3.1.0) - '@warp-drive/json-api': 5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0)) - '@warp-drive/legacy': 5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0))(@warp-drive/utilities@5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0))) - '@warp-drive/utilities': 5.8.1(@babel/core@7.29.0)(@warp-drive/core@5.8.1(@babel/core@7.29.0)) - optionalDependencies: - '@ember/test-helpers': 3.3.1(@babel/core@7.29.0)(ember-source@)(webpack@5.105.1) - qunit: 2.25.0 - transitivePeerDependencies: - - '@babel/core' - - '@glint/template' - - ember-inflector - - ember-provide-consume-context - - supports-color - - ember-eslint-parser@0.5.13(@babel/core@7.29.0)(@typescript-eslint/parser@8.55.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3): - dependencies: - '@babel/core': 7.29.0 - '@babel/eslint-parser': 7.28.6(@babel/core@7.29.0)(eslint@8.57.1) - '@glimmer/syntax': 0.95.0 - '@typescript-eslint/tsconfig-utils': 8.55.0(typescript@5.9.3) - content-tag: 2.0.3 - eslint-scope: 7.2.2 - html-tags: 3.3.1 - mathml-tag-names: 2.1.3 - svg-tags: 1.0.0 - optionalDependencies: - '@typescript-eslint/parser': 8.55.0(eslint@8.57.1)(typescript@5.9.3) + '@babel/core': 7.29.0 + '@babel/eslint-parser': 7.28.6(@babel/core@7.29.0)(eslint@9.39.3) + '@glimmer/syntax': 0.95.0 + '@typescript-eslint/tsconfig-utils': 8.56.1(typescript@5.9.3) + content-tag: 2.0.3 + eslint-scope: 7.2.2 + html-tags: 3.3.1 + mathml-tag-names: 2.1.3 + svg-tags: 1.0.0 + optionalDependencies: + '@typescript-eslint/parser': 8.56.1(eslint@9.39.3)(typescript@5.9.3) transitivePeerDependencies: - eslint - typescript - ember-eslint-parser@0.5.13(@babel/core@7.29.0)(@typescript-eslint/parser@8.55.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3): - dependencies: - '@babel/core': 7.29.0 - '@babel/eslint-parser': 7.28.6(@babel/core@7.29.0)(eslint@9.39.2) - '@glimmer/syntax': 0.95.0 - '@typescript-eslint/tsconfig-utils': 8.55.0(typescript@5.9.3) - content-tag: 2.0.3 - eslint-scope: 7.2.2 - html-tags: 3.3.1 - mathml-tag-names: 2.1.3 - svg-tags: 1.0.0 - optionalDependencies: - '@typescript-eslint/parser': 8.55.0(eslint@9.39.2)(typescript@5.9.3) - transitivePeerDependencies: - - eslint - - typescript - - ember-load-initializers@2.1.2(@babel/core@7.29.0): - dependencies: - ember-cli-babel: 7.26.11 - ember-cli-typescript: 2.0.2(@babel/core@7.29.0) - transitivePeerDependencies: - - '@babel/core' - - supports-color - ember-load-initializers@3.0.1(ember-source@): dependencies: ember-source: 'link:' @@ -21082,14 +19202,6 @@ snapshots: - '@babel/core' - supports-color - ember-page-title@8.2.4(ember-source@): - dependencies: - '@embroider/addon-shim': 1.10.2 - '@simple-dom/document': 1.4.0 - ember-source: 'link:' - transitivePeerDependencies: - - supports-color - ember-page-title@9.0.3: dependencies: '@embroider/addon-shim': 1.10.2 @@ -21097,25 +19209,11 @@ snapshots: transitivePeerDependencies: - supports-color - ember-qunit@8.1.1(@babel/core@7.29.0)(@ember/test-helpers@3.3.1(@babel/core@7.29.0)(ember-source@)(webpack@5.105.1))(ember-source@)(qunit@2.25.0): - dependencies: - '@ember/test-helpers': 3.3.1(@babel/core@7.29.0)(ember-source@)(webpack@5.105.1) - '@embroider/addon-shim': 1.10.2 - '@embroider/macros': 1.19.7(@babel/core@7.29.0) - ember-cli-test-loader: 3.1.0 - ember-source: 'link:' - qunit: 2.25.0 - qunit-theme-ember: 1.0.0 - transitivePeerDependencies: - - '@babel/core' - - '@glint/template' - - supports-color - ember-qunit@9.0.4(@babel/core@7.29.0)(@ember/test-helpers@5.4.1(@babel/core@7.29.0))(qunit@2.25.0): dependencies: '@ember/test-helpers': 5.4.1(@babel/core@7.29.0) '@embroider/addon-shim': 1.10.2 - '@embroider/macros': 1.19.7(@babel/core@7.29.0) + '@embroider/macros': 1.20.1(@babel/core@7.29.0) qunit: 2.25.0 qunit-theme-ember: 1.0.0 transitivePeerDependencies: @@ -21123,19 +19221,7 @@ snapshots: - '@glint/template' - supports-color - ember-resolver@11.0.1(ember-source@): - dependencies: - ember-cli-babel: 7.26.11 - optionalDependencies: - ember-source: 'link:' - transitivePeerDependencies: - - supports-color - - ember-resolver@13.1.1: - dependencies: - ember-cli-babel: 7.26.11 - transitivePeerDependencies: - - supports-color + ember-resolver@13.2.0: {} ember-rfc176-data@0.3.18: {} @@ -21221,15 +19307,6 @@ snapshots: transitivePeerDependencies: - supports-color - ember-template-tag@2.3.16: - dependencies: - '@babel/generator': 7.23.6 - '@babel/traverse': 7.23.9 - '@babel/types': 7.23.0 - '@glimmer/syntax': 0.88.1 - transitivePeerDependencies: - - supports-color - ember-tracked-storage-polyfill@1.0.0(@babel/core@7.29.0)(ember-source@): dependencies: ember-cli-babel: 7.26.11 @@ -21239,12 +19316,6 @@ snapshots: - ember-source - supports-color - ember-welcome-page@7.0.2: - dependencies: - '@embroider/addon-shim': 1.10.2 - transitivePeerDependencies: - - supports-color - emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -21264,7 +19335,7 @@ snapshots: engine.io@6.6.5: dependencies: '@types/cors': 2.8.19 - '@types/node': 22.19.11 + '@types/node': 22.19.15 accepts: 1.3.8 base64id: 2.0.0 cookie: 0.7.2 @@ -21277,7 +19348,7 @@ snapshots: - supports-color - utf-8-validate - enhanced-resolve@5.19.0: + enhanced-resolve@5.20.0: dependencies: graceful-fs: 4.2.11 tapable: 2.3.0 @@ -21286,10 +19357,6 @@ snapshots: entities@1.1.2: {} - entities@2.2.0: {} - - entities@3.0.1: {} - entities@4.5.0: {} entities@6.0.1: {} @@ -21467,18 +19534,18 @@ snapshots: optionalDependencies: source-map: 0.1.43 - eslint-compat-utils@0.5.1(eslint@9.39.2): + eslint-compat-utils@0.5.1(eslint@9.39.3): dependencies: - eslint: 9.39.2 + eslint: 9.39.3 semver: 7.7.4 - eslint-config-prettier@10.1.8(eslint@9.39.2): + eslint-config-prettier@10.1.8(eslint@9.39.3): dependencies: - eslint: 9.39.2 + eslint: 9.39.3 - eslint-config-prettier@9.1.2(eslint@8.57.1): + eslint-config-prettier@9.1.2(eslint@9.39.3): dependencies: - eslint: 8.57.1 + eslint: 9.39.3 eslint-formatter-kakoune@1.0.0: {} @@ -21490,11 +19557,11 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(eslint-import-resolver-node@0.3.9)(eslint@9.39.2): + eslint-module-utils@2.12.1(eslint-import-resolver-node@0.3.9)(eslint@9.39.3): dependencies: debug: 3.2.7 optionalDependencies: - eslint: 9.39.2 + eslint: 9.39.3 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color @@ -21503,64 +19570,39 @@ snapshots: dependencies: requireindex: 1.1.0 - eslint-plugin-ember-internal@3.0.0(eslint@9.39.2): + eslint-plugin-ember-internal@3.0.0(eslint@9.39.3): dependencies: - eslint: 9.39.2 + eslint: 9.39.3 line-column: 1.0.2 requireindex: 1.2.0 - eslint-plugin-ember@12.7.5(@babel/core@7.29.0)(@typescript-eslint/parser@8.55.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3): + eslint-plugin-ember@12.7.5(@babel/core@7.29.0)(@typescript-eslint/parser@8.56.1(eslint@9.39.3)(typescript@5.9.3))(eslint@9.39.3)(typescript@5.9.3): dependencies: '@ember-data/rfc395-data': 0.0.4 - css-tree: 3.1.0 - ember-eslint-parser: 0.5.13(@babel/core@7.29.0)(@typescript-eslint/parser@8.55.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3) + css-tree: 3.2.1 + ember-eslint-parser: 0.5.13(@babel/core@7.29.0)(@typescript-eslint/parser@8.56.1(eslint@9.39.3)(typescript@5.9.3))(eslint@9.39.3)(typescript@5.9.3) ember-rfc176-data: 0.3.18 - eslint: 8.57.1 - eslint-utils: 3.0.0(eslint@8.57.1) + eslint: 9.39.3 + eslint-utils: 3.0.0(eslint@9.39.3) estraverse: 5.3.0 lodash.camelcase: 4.3.0 lodash.kebabcase: 4.1.1 requireindex: 1.2.0 snake-case: 3.0.4 optionalDependencies: - '@typescript-eslint/parser': 8.55.0(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/parser': 8.56.1(eslint@9.39.3)(typescript@5.9.3) transitivePeerDependencies: - '@babel/core' - typescript - eslint-plugin-ember@12.7.5(@babel/core@7.29.0)(@typescript-eslint/parser@8.55.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3): + eslint-plugin-es-x@7.8.0(eslint@9.39.3): dependencies: - '@ember-data/rfc395-data': 0.0.4 - css-tree: 3.1.0 - ember-eslint-parser: 0.5.13(@babel/core@7.29.0)(@typescript-eslint/parser@8.55.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) - ember-rfc176-data: 0.3.18 - eslint: 9.39.2 - eslint-utils: 3.0.0(eslint@9.39.2) - estraverse: 5.3.0 - lodash.camelcase: 4.3.0 - lodash.kebabcase: 4.1.1 - requireindex: 1.2.0 - snake-case: 3.0.4 - optionalDependencies: - '@typescript-eslint/parser': 8.55.0(eslint@9.39.2)(typescript@5.9.3) - transitivePeerDependencies: - - '@babel/core' - - typescript - - eslint-plugin-es-x@7.8.0(eslint@9.39.2): - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.3) '@eslint-community/regexpp': 4.12.2 - eslint: 9.39.2 - eslint-compat-utils: 0.5.1(eslint@9.39.2) - - eslint-plugin-es@3.0.1(eslint@8.57.1): - dependencies: - eslint: 8.57.1 - eslint-utils: 2.1.0 - regexpp: 3.2.0 + eslint: 9.39.3 + eslint-compat-utils: 0.5.1(eslint@9.39.3) - eslint-plugin-import@2.32.0(eslint@9.39.2): + eslint-plugin-import@2.32.0(eslint@9.39.3): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -21569,13 +19611,13 @@ snapshots: array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.39.2 + eslint: 9.39.3 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(eslint-import-resolver-node@0.3.9)(eslint@9.39.2) + eslint-module-utils: 2.12.1(eslint-import-resolver-node@0.3.9)(eslint@9.39.3) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 - minimatch: 3.1.2 + minimatch: 3.1.5 object.fromentries: 2.0.8 object.groupby: 1.0.3 object.values: 1.2.1 @@ -21587,12 +19629,12 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-n@17.23.2(eslint@9.39.2)(typescript@5.9.3): + eslint-plugin-n@17.24.0(eslint@9.39.3)(typescript@5.9.3): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2) - enhanced-resolve: 5.19.0 - eslint: 9.39.2 - eslint-plugin-es-x: 7.8.0(eslint@9.39.2) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.3) + enhanced-resolve: 5.20.0 + eslint: 9.39.3 + eslint-plugin-es-x: 7.8.0(eslint@9.39.3) get-tsconfig: 4.13.6 globals: 15.15.0 globrex: 0.1.2 @@ -21602,51 +19644,10 @@ snapshots: transitivePeerDependencies: - typescript - eslint-plugin-n@17.24.0(eslint@9.39.2)(typescript@5.9.3): + eslint-plugin-qunit@8.2.6(eslint@9.39.3): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2) - enhanced-resolve: 5.19.0 - eslint: 9.39.2 - eslint-plugin-es-x: 7.8.0(eslint@9.39.2) - get-tsconfig: 4.13.6 - globals: 15.15.0 - globrex: 0.1.2 - ignore: 5.3.2 - semver: 7.7.4 - ts-declaration-location: 1.0.7(typescript@5.9.3) - transitivePeerDependencies: - - typescript - - eslint-plugin-node@11.1.0(eslint@8.57.1): - dependencies: - eslint: 8.57.1 - eslint-plugin-es: 3.0.1(eslint@8.57.1) - eslint-utils: 2.1.0 - ignore: 5.3.2 - minimatch: 3.1.2 - resolve: 1.22.11 - semver: 6.3.1 - - eslint-plugin-prettier@5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@9.1.2(eslint@8.57.1))(eslint@8.57.1)(prettier@3.8.1): - dependencies: - eslint: 8.57.1 - prettier: 3.8.1 - prettier-linter-helpers: 1.0.1 - synckit: 0.11.12 - optionalDependencies: - '@types/eslint': 9.6.1 - eslint-config-prettier: 9.1.2(eslint@8.57.1) - - eslint-plugin-qunit@8.2.6(eslint@8.57.1): - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1) - eslint: 8.57.1 - requireindex: 1.2.0 - - eslint-plugin-qunit@8.2.6(eslint@9.39.2): - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2) - eslint: 9.39.2 + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.3) + eslint: 9.39.3 requireindex: 1.2.0 eslint-scope@5.1.1: @@ -21659,91 +19660,39 @@ snapshots: esrecurse: 4.3.0 estraverse: 5.3.0 - eslint-scope@8.4.0: - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - - eslint-utils@2.1.0: - dependencies: - eslint-visitor-keys: 1.3.0 - - eslint-utils@3.0.0(eslint@8.57.1): - dependencies: - eslint: 8.57.1 - eslint-visitor-keys: 2.1.0 - - eslint-utils@3.0.0(eslint@9.39.2): - dependencies: - eslint: 9.39.2 - eslint-visitor-keys: 2.1.0 - - eslint-visitor-keys@1.3.0: {} - - eslint-visitor-keys@2.1.0: {} - - eslint-visitor-keys@3.4.3: {} - - eslint-visitor-keys@4.2.1: {} - - eslint@8.57.1: - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1) - '@eslint-community/regexpp': 4.12.2 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.1 - '@humanwhocodes/config-array': 0.13.0 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.3.0 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.4.3(supports-color@8.1.1) - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.7.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.1 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - strip-ansi: 6.0.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-utils@3.0.0(eslint@9.39.3): + dependencies: + eslint: 9.39.3 + eslint-visitor-keys: 2.1.0 + + eslint-visitor-keys@2.1.0: {} + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint-visitor-keys@5.0.1: {} - eslint@9.39.2: + eslint@9.39.3: dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.3) '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.21.1 '@eslint/config-helpers': 0.4.2 '@eslint/core': 0.17.0 - '@eslint/eslintrc': 3.3.3 - '@eslint/js': 9.39.2 + '@eslint/eslintrc': 3.3.4 + '@eslint/js': 9.39.3 '@eslint/plugin-kit': 0.4.1 '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 '@types/estree': 1.0.8 - ajv: 6.12.6 + ajv: 6.14.0 chalk: 4.1.2 cross-spawn: 7.0.6 debug: 4.4.3(supports-color@8.1.1) @@ -21762,7 +19711,7 @@ snapshots: is-glob: 4.0.3 json-stable-stringify-without-jsonify: 1.0.1 lodash.merge: 4.6.2 - minimatch: 3.1.2 + minimatch: 3.1.5 natural-compare: 1.4.0 optionator: 0.9.4 transitivePeerDependencies: @@ -21772,16 +19721,10 @@ snapshots: espree@10.4.0: dependencies: - acorn: 8.15.0 - acorn-jsx: 5.3.2(acorn@8.15.0) + acorn: 8.16.0 + acorn-jsx: 5.3.2(acorn@8.16.0) eslint-visitor-keys: 4.2.1 - espree@9.6.1: - dependencies: - acorn: 8.15.0 - acorn-jsx: 5.3.2(acorn@8.15.0) - eslint-visitor-keys: 3.4.3 - esprima@1.1.1: {} esprima@3.0.0: {} @@ -21810,16 +19753,6 @@ snapshots: etag@1.8.1: {} - event-stream@3.3.4: - dependencies: - duplexer: 0.1.2 - from: 0.1.7 - map-stream: 0.1.0 - pause-stream: 0.0.11 - split: 0.3.3 - stream-combiner: 0.0.4 - through: 2.3.8 - eventemitter3@4.0.7: {} events-to-array@1.1.2: {} @@ -21946,7 +19879,7 @@ snapshots: parseurl: 1.3.3 path-to-regexp: 0.1.12 proxy-addr: 2.0.7 - qs: 6.14.1 + qs: 6.14.2 range-parser: 1.2.1 safe-buffer: 5.2.1 send: 0.19.2 @@ -21981,7 +19914,7 @@ snapshots: once: 1.4.0 parseurl: 1.3.3 proxy-addr: 2.0.7 - qs: 6.14.1 + qs: 6.15.0 range-parser: 1.2.1 router: 2.2.0 send: 1.2.1 @@ -22024,8 +19957,6 @@ snapshots: fast-deep-equal@3.1.3: {} - fast-diff@1.3.0: {} - fast-glob@3.3.3: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -22068,9 +19999,12 @@ snapshots: dependencies: fast-string-width: 3.0.2 - fast-xml-parser@5.3.4: + fast-xml-builder@1.0.0: {} + + fast-xml-parser@5.4.1: dependencies: - strnum: 2.1.2 + fast-xml-builder: 1.0.0 + strnum: 2.2.0 fastest-levenshtein@1.0.16: {} @@ -22111,15 +20045,11 @@ snapshots: dependencies: flat-cache: 6.1.20 - file-entry-cache@6.0.1: - dependencies: - flat-cache: 3.2.0 - file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 - filelist@1.0.4: + filelist@1.0.6: dependencies: minimatch: 5.1.9 @@ -22260,12 +20190,6 @@ snapshots: fixturify: 1.3.0 tmp: 0.0.33 - fixturify-project@2.1.1: - dependencies: - fixturify: 2.1.1 - tmp: 0.0.33 - type-fest: 0.11.0 - fixturify-project@7.1.3: dependencies: '@embroider/shared-internals': 2.9.2(supports-color@8.1.1) @@ -22292,15 +20216,6 @@ snapshots: fs-extra: 7.0.1 matcher-collection: 2.0.1 - fixturify@2.1.1: - dependencies: - '@types/fs-extra': 8.1.5 - '@types/minimatch': 3.0.5 - '@types/rimraf': 2.0.5 - fs-extra: 8.1.0 - matcher-collection: 2.0.1 - walk-sync: 2.2.0 - fixturify@3.0.0: dependencies: '@types/fs-extra': 9.0.13 @@ -22310,26 +20225,20 @@ snapshots: matcher-collection: 2.0.1 walk-sync: 3.0.0 - flat-cache@3.2.0: - dependencies: - flatted: 3.3.3 - keyv: 4.5.4 - rimraf: 3.0.2 - flat-cache@4.0.1: dependencies: - flatted: 3.3.3 + flatted: 3.3.4 keyv: 4.5.4 flat-cache@6.1.20: dependencies: - cacheable: 2.3.2 - flatted: 3.3.3 + cacheable: 2.3.3 + flatted: 3.3.4 hookified: 1.15.1 flat@5.0.2: {} - flatted@3.3.3: {} + flatted@3.3.4: {} follow-redirects@1.15.11: {} @@ -22371,8 +20280,6 @@ snapshots: fresh@2.0.0: {} - from@0.1.7: {} - fs-constants@1.0.0: {} fs-extra@0.24.0: @@ -22396,7 +20303,7 @@ snapshots: jsonfile: 6.2.0 universalify: 2.0.1 - fs-extra@11.3.3: + fs-extra@11.3.4: dependencies: graceful-fs: 4.2.11 jsonfile: 6.2.0 @@ -22552,11 +20459,11 @@ snapshots: get-stream@4.1.0: dependencies: - pump: 3.0.3 + pump: 3.0.4 get-stream@5.2.0: dependencies: - pump: 3.0.3 + pump: 3.0.4 get-stream@6.0.1: {} @@ -22579,8 +20486,6 @@ snapshots: get-value@2.0.6: {} - git-hooks-list@1.0.3: {} - git-hooks-list@3.2.0: {} git-hooks-list@4.2.1: {} @@ -22612,21 +20517,21 @@ snapshots: foreground-child: 3.3.1 jackspeak: 3.4.3 minimatch: 9.0.9 - minipass: 7.1.2 + minipass: 7.1.3 package-json-from-dist: 1.0.1 path-scurry: 1.11.1 - glob@13.0.2: + glob@13.0.6: dependencies: - minimatch: 10.1.2 - minipass: 7.1.2 - path-scurry: 2.0.1 + minimatch: 10.2.4 + minipass: 7.1.3 + path-scurry: 2.0.2 glob@5.0.15: dependencies: inflight: 1.0.6 inherits: 2.0.4 - minimatch: 3.1.2 + minimatch: 3.1.5 once: 1.4.0 path-is-absolute: 1.0.1 @@ -22644,7 +20549,7 @@ snapshots: fs.realpath: 1.0.0 inflight: 1.0.6 inherits: 2.0.4 - minimatch: 5.1.6 + minimatch: 5.1.9 once: 1.4.0 glob@9.3.5: @@ -22678,12 +20583,6 @@ snapshots: kind-of: 6.0.3 which: 1.3.1 - globals@11.12.0: {} - - globals@13.24.0: - dependencies: - type-fest: 0.20.2 - globals@14.0.0: {} globals@15.15.0: {} @@ -22697,17 +20596,6 @@ snapshots: globalyzer@0.1.0: {} - globby@10.0.0: - dependencies: - '@types/glob': 7.2.0 - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.3 - glob: 7.2.3 - ignore: 5.3.2 - merge2: 1.4.1 - slash: 3.0.0 - globby@11.1.0: dependencies: array-union: 2.1.0 @@ -22752,10 +20640,6 @@ snapshots: graceful-fs@4.2.11: {} - grapheme-splitter@1.0.4: {} - - graphemer@1.4.0: {} - growly@1.3.0: {} handlebars@4.7.8: @@ -22823,18 +20707,16 @@ snapshots: is-number: 3.0.0 kind-of: 4.0.0 - hash-for-dep@1.5.1: + hash-for-dep@1.5.2: dependencies: - broccoli-kitchen-sink-helpers: 0.3.1 heimdalljs: 0.2.6 heimdalljs-logger: 0.1.10 - path-root: 0.1.1 resolve: 1.22.11 resolve-package-path: 1.2.7 transitivePeerDependencies: - supports-color - hashery@1.4.0: + hashery@1.5.0: dependencies: hookified: 1.15.1 @@ -22890,14 +20772,6 @@ snapshots: dependencies: lru-cache: 6.0.0 - hosted-git-info@6.1.3: - dependencies: - lru-cache: 7.18.3 - - hosted-git-info@8.1.0: - dependencies: - lru-cache: 10.4.3 - hosted-git-info@9.0.2: dependencies: lru-cache: 11.2.6 @@ -23081,17 +20955,17 @@ snapshots: ini@3.0.1: {} - inquirer@13.3.0(@types/node@22.19.11): + inquirer@13.3.0(@types/node@22.19.15): dependencies: '@inquirer/ansi': 2.0.3 - '@inquirer/core': 11.1.5(@types/node@22.19.11) - '@inquirer/prompts': 8.3.0(@types/node@22.19.11) - '@inquirer/type': 4.0.3(@types/node@22.19.11) + '@inquirer/core': 11.1.5(@types/node@22.19.15) + '@inquirer/prompts': 8.3.0(@types/node@22.19.15) + '@inquirer/type': 4.0.3(@types/node@22.19.15) mute-stream: 3.0.0 run-async: 4.0.6 rxjs: 7.8.2 optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 inquirer@6.5.2: dependencies: @@ -23125,23 +20999,6 @@ snapshots: strip-ansi: 6.0.1 through: 2.3.8 - inquirer@9.3.8(@types/node@22.19.11): - dependencies: - '@inquirer/external-editor': 1.0.3(@types/node@22.19.11) - '@inquirer/figures': 1.0.15 - ansi-escapes: 4.3.2 - cli-width: 4.1.0 - mute-stream: 1.0.0 - ora: 5.4.1 - run-async: 3.0.0 - rxjs: 7.8.2 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 6.2.0 - yoctocolors-cjs: 2.1.3 - transitivePeerDependencies: - - '@types/node' - internal-slot@1.1.0: dependencies: es-errors: 1.3.0 @@ -23265,10 +21122,6 @@ snapshots: is-interactive@1.0.0: {} - is-language-code@3.1.0: - dependencies: - '@babel/runtime': 7.28.6 - is-language-code@5.1.3: dependencies: codsen-utils: 1.7.3 @@ -23293,14 +21146,10 @@ snapshots: is-number@7.0.0: {} - is-obj@2.0.0: {} - is-observable@1.1.0: dependencies: symbol-observable: 1.2.0 - is-path-inside@3.0.3: {} - is-plain-obj@1.1.0: {} is-plain-obj@2.1.0: {} @@ -23369,8 +21218,6 @@ snapshots: dependencies: which-typed-array: 1.1.20 - is-typedarray@1.0.0: {} - is-unicode-supported@0.1.0: {} is-unicode-supported@2.1.0: {} @@ -23431,12 +21278,12 @@ snapshots: jake@10.9.4: dependencies: async: 3.2.6 - filelist: 1.0.4 + filelist: 1.0.6 picocolors: 1.1.1 jest-worker@27.5.1: dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -23526,8 +21373,6 @@ snapshots: - supports-color - utf-8-validate - jsesc@2.5.2: {} - jsesc@3.1.0: {} json-buffer@3.0.0: {} @@ -23538,7 +21383,7 @@ snapshots: json-parse-even-better-errors@2.3.1: {} - json-parse-even-better-errors@3.0.2: {} + json-parse-even-better-errors@4.0.0: {} json-query@2.2.2: {} @@ -23558,11 +21403,6 @@ snapshots: json-stringify-safe@5.0.1: {} - json-to-ast@2.1.0: - dependencies: - code-error-fragment: 0.0.230 - grapheme-splitter: 1.0.4 - json5@1.0.2: dependencies: minimist: 1.2.8 @@ -23664,10 +21504,6 @@ snapshots: dependencies: uc.micro: 1.0.6 - linkify-it@4.0.1: - dependencies: - uc.micro: 1.0.6 - linkify-it@5.0.0: dependencies: uc.micro: 2.1.0 @@ -23710,13 +21546,6 @@ snapshots: livereload-js@3.4.1: {} - load-json-file@4.0.0: - dependencies: - graceful-fs: 4.2.11 - parse-json: 4.0.0 - pify: 3.0.0 - strip-bom: 3.0.0 - load-json-file@6.2.0: dependencies: graceful-fs: 4.2.11 @@ -23806,8 +21635,6 @@ snapshots: lodash.merge@4.6.2: {} - lodash.omit@4.5.0: {} - lodash.template@4.5.0: dependencies: lodash._reinterpolate: 3.0.0 @@ -23821,8 +21648,6 @@ snapshots: lodash.union@4.6.0: {} - lodash.uniq@4.5.0: {} - lodash@4.17.23: {} log-symbols@1.0.2: @@ -23873,8 +21698,6 @@ snapshots: dependencies: yallist: 4.0.0 - lru-cache@7.18.3: {} - magic-string@0.25.9: dependencies: sourcemap-codec: 1.4.8 @@ -23899,37 +21722,19 @@ snapshots: map-obj@4.3.0: {} - map-stream@0.1.0: {} - map-visit@1.0.0: dependencies: object-visit: 1.0.1 - markdown-it-terminal@0.4.0(markdown-it@13.0.2): - dependencies: - ansi-styles: 3.2.1 - cardinal: 1.0.0 - cli-table: 0.3.11 - lodash.merge: 4.6.2 - markdown-it: 13.0.2 - - markdown-it-terminal@0.4.0(markdown-it@14.1.0): + markdown-it-terminal@0.4.0(markdown-it@14.1.1): dependencies: ansi-styles: 3.2.1 cardinal: 1.0.0 cli-table: 0.3.11 lodash.merge: 4.6.2 - markdown-it: 14.1.0 - - markdown-it@13.0.2: - dependencies: - argparse: 2.0.1 - entities: 3.0.1 - linkify-it: 4.0.1 - mdurl: 1.0.1 - uc.micro: 1.0.6 + markdown-it: 14.1.1 - markdown-it@14.1.0: + markdown-it@14.1.1: dependencies: argparse: 2.0.1 entities: 4.5.0 @@ -23950,7 +21755,7 @@ snapshots: matcher-collection@1.1.2: dependencies: - minimatch: 3.1.2 + minimatch: 3.1.5 matcher-collection@2.0.1: dependencies: @@ -23963,7 +21768,7 @@ snapshots: mdn-data@2.0.14: {} - mdn-data@2.12.2: {} + mdn-data@2.27.1: {} mdn-links@0.1.0: {} @@ -23975,12 +21780,6 @@ snapshots: media-typer@1.1.0: {} - mem@5.1.1: - dependencies: - map-age-cleaner: 0.1.3 - mimic-fn: 2.1.0 - p-is-promise: 2.1.0 - mem@8.1.1: dependencies: map-age-cleaner: 0.1.3 @@ -24080,54 +21879,34 @@ snapshots: min-indent@1.0.1: {} - mini-css-extract-plugin@2.10.0(webpack@5.105.1(@swc/core@1.15.11)): + mini-css-extract-plugin@2.10.0(webpack@5.105.4(@swc/core@1.15.18)): dependencies: schema-utils: 4.3.3 tapable: 2.3.0 - webpack: 5.105.1(@swc/core@1.15.11) + webpack: 5.105.4(@swc/core@1.15.18) - mini-css-extract-plugin@2.10.0(webpack@5.105.1): + mini-css-extract-plugin@2.10.0(webpack@5.105.4): dependencies: schema-utils: 4.3.3 tapable: 2.3.0 - webpack: 5.105.1 - - minimatch@10.1.2: - dependencies: - '@isaacs/brace-expansion': 5.0.1 + webpack: 5.105.4 minimatch@10.2.4: dependencies: brace-expansion: 5.0.4 - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.12 - minimatch@3.1.5: dependencies: brace-expansion: 1.1.12 - minimatch@5.1.6: - dependencies: - brace-expansion: 2.0.2 - minimatch@5.1.9: dependencies: brace-expansion: 2.0.2 - minimatch@7.4.6: - dependencies: - brace-expansion: 2.0.2 - minimatch@8.0.7: dependencies: brace-expansion: 2.0.2 - minimatch@9.0.5: - dependencies: - brace-expansion: 2.0.2 - minimatch@9.0.9: dependencies: brace-expansion: 2.0.2 @@ -24147,7 +21926,7 @@ snapshots: minipass@4.2.8: {} - minipass@7.1.2: {} + minipass@7.1.3: {} mixin-deep@1.3.2: dependencies: @@ -24183,7 +21962,7 @@ snapshots: he: 1.2.0 js-yaml: 4.1.1 log-symbols: 4.1.0 - minimatch: 5.1.6 + minimatch: 5.1.9 ms: 2.1.3 serialize-javascript: 6.0.2 strip-json-comments: 3.1.1 @@ -24215,8 +21994,6 @@ snapshots: mute-stream@0.0.8: {} - mute-stream@1.0.0: {} - mute-stream@3.0.0: {} nanoid@3.3.11: {} @@ -24264,8 +22041,6 @@ snapshots: lower-case: 2.0.2 tslib: 2.8.1 - node-gzip@1.1.2: {} - node-int64@0.4.0: {} node-notifier@10.0.1: @@ -24277,7 +22052,7 @@ snapshots: uuid: 8.3.2 which: 2.0.2 - node-releases@2.0.27: {} + node-releases@2.0.36: {} node-uuid@1.4.8: {} @@ -24322,21 +22097,7 @@ snapshots: npm-normalize-package-bin@2.0.0: {} - npm-normalize-package-bin@3.0.1: {} - - npm-package-arg@10.1.0: - dependencies: - hosted-git-info: 6.1.3 - proc-log: 3.0.0 - semver: 7.7.4 - validate-npm-package-name: 5.0.1 - - npm-package-arg@12.0.2: - dependencies: - hosted-git-info: 8.1.0 - proc-log: 5.0.0 - semver: 7.7.4 - validate-npm-package-name: 6.0.2 + npm-normalize-package-bin@4.0.0: {} npm-package-arg@13.0.2: dependencies: @@ -24352,28 +22113,26 @@ snapshots: npm-bundled: 2.0.1 npm-normalize-package-bin: 2.0.0 - npm-run-all2@6.2.6: + npm-run-all2@5.0.2: dependencies: - ansi-styles: 6.2.3 + ansi-styles: 5.2.0 cross-spawn: 7.0.6 memorystream: 0.3.1 - minimatch: 9.0.5 - pidtree: 0.6.0 - read-package-json-fast: 3.0.2 + minimatch: 3.1.5 + pidtree: 0.5.0 + read-pkg: 5.2.0 shell-quote: 1.8.3 - which: 3.0.1 - npm-run-all@4.1.5: + npm-run-all2@8.0.4: dependencies: - ansi-styles: 3.2.1 - chalk: 2.4.2 - cross-spawn: 6.0.6 + ansi-styles: 6.2.3 + cross-spawn: 7.0.6 memorystream: 0.3.1 - minimatch: 3.1.2 - pidtree: 0.3.1 - read-pkg: 3.0.0 + picomatch: 4.0.3 + pidtree: 0.6.0 + read-package-json-fast: 4.0.0 shell-quote: 1.8.3 - string.prototype.padend: 3.1.6 + which: 5.0.0 npm-run-path@2.0.2: dependencies: @@ -24522,12 +22281,6 @@ snapshots: os-homedir@1.0.2: {} - os-locale@5.0.0: - dependencies: - execa: 4.1.0 - lcid: 3.1.1 - mem: 5.1.1 - os-locale@6.0.2: dependencies: lcid: 3.1.1 @@ -24545,35 +22298,33 @@ snapshots: object-keys: 1.1.1 safe-push-apply: 1.0.0 - oxc-resolver@11.17.1: + oxc-resolver@11.19.1: optionalDependencies: - '@oxc-resolver/binding-android-arm-eabi': 11.17.1 - '@oxc-resolver/binding-android-arm64': 11.17.1 - '@oxc-resolver/binding-darwin-arm64': 11.17.1 - '@oxc-resolver/binding-darwin-x64': 11.17.1 - '@oxc-resolver/binding-freebsd-x64': 11.17.1 - '@oxc-resolver/binding-linux-arm-gnueabihf': 11.17.1 - '@oxc-resolver/binding-linux-arm-musleabihf': 11.17.1 - '@oxc-resolver/binding-linux-arm64-gnu': 11.17.1 - '@oxc-resolver/binding-linux-arm64-musl': 11.17.1 - '@oxc-resolver/binding-linux-ppc64-gnu': 11.17.1 - '@oxc-resolver/binding-linux-riscv64-gnu': 11.17.1 - '@oxc-resolver/binding-linux-riscv64-musl': 11.17.1 - '@oxc-resolver/binding-linux-s390x-gnu': 11.17.1 - '@oxc-resolver/binding-linux-x64-gnu': 11.17.1 - '@oxc-resolver/binding-linux-x64-musl': 11.17.1 - '@oxc-resolver/binding-openharmony-arm64': 11.17.1 - '@oxc-resolver/binding-wasm32-wasi': 11.17.1 - '@oxc-resolver/binding-win32-arm64-msvc': 11.17.1 - '@oxc-resolver/binding-win32-ia32-msvc': 11.17.1 - '@oxc-resolver/binding-win32-x64-msvc': 11.17.1 + '@oxc-resolver/binding-android-arm-eabi': 11.19.1 + '@oxc-resolver/binding-android-arm64': 11.19.1 + '@oxc-resolver/binding-darwin-arm64': 11.19.1 + '@oxc-resolver/binding-darwin-x64': 11.19.1 + '@oxc-resolver/binding-freebsd-x64': 11.19.1 + '@oxc-resolver/binding-linux-arm-gnueabihf': 11.19.1 + '@oxc-resolver/binding-linux-arm-musleabihf': 11.19.1 + '@oxc-resolver/binding-linux-arm64-gnu': 11.19.1 + '@oxc-resolver/binding-linux-arm64-musl': 11.19.1 + '@oxc-resolver/binding-linux-ppc64-gnu': 11.19.1 + '@oxc-resolver/binding-linux-riscv64-gnu': 11.19.1 + '@oxc-resolver/binding-linux-riscv64-musl': 11.19.1 + '@oxc-resolver/binding-linux-s390x-gnu': 11.19.1 + '@oxc-resolver/binding-linux-x64-gnu': 11.19.1 + '@oxc-resolver/binding-linux-x64-musl': 11.19.1 + '@oxc-resolver/binding-openharmony-arm64': 11.19.1 + '@oxc-resolver/binding-wasm32-wasi': 11.19.1 + '@oxc-resolver/binding-win32-arm64-msvc': 11.19.1 + '@oxc-resolver/binding-win32-ia32-msvc': 11.19.1 + '@oxc-resolver/binding-win32-x64-msvc': 11.19.1 p-cancelable@1.1.0: {} p-defer@1.0.0: {} - p-defer@3.0.0: {} - p-defer@4.0.1: {} p-filter@2.1.0: @@ -24582,8 +22333,6 @@ snapshots: p-finally@1.0.0: {} - p-is-promise@2.1.0: {} - p-limit@1.3.0: dependencies: p-try: 1.0.0 @@ -24719,12 +22468,12 @@ snapshots: path-scurry@1.11.1: dependencies: lru-cache: 10.4.3 - minipass: 7.1.2 + minipass: 7.1.3 - path-scurry@2.0.1: + path-scurry@2.0.2: dependencies: lru-cache: 11.2.6 - minipass: 7.1.2 + minipass: 7.1.3 path-temp@2.1.1: dependencies: @@ -24734,10 +22483,6 @@ snapshots: path-to-regexp@8.3.0: {} - path-type@3.0.0: - dependencies: - pify: 3.0.0 - path-type@4.0.0: {} path-type@6.0.0: {} @@ -24749,10 +22494,6 @@ snapshots: pathval@1.1.1: {} - pause-stream@0.0.11: - dependencies: - through: 2.3.8 - picocolors@1.1.1: {} picomatch@2.3.1: {} @@ -24763,12 +22504,10 @@ snapshots: dependencies: execa: 0.9.0 - pidtree@0.3.1: {} + pidtree@0.5.0: {} pidtree@0.6.0: {} - pify@3.0.0: {} - pirates@4.0.7: {} pkg-dir@4.2.0: @@ -24823,9 +22562,9 @@ snapshots: postcss-resolve-nested-selector@0.1.6: {} - postcss-safe-parser@7.0.1(postcss@8.5.6): + postcss-safe-parser@7.0.1(postcss@8.5.8): dependencies: - postcss: 8.5.6 + postcss: 8.5.8 postcss-selector-parser@7.1.1: dependencies: @@ -24834,12 +22573,6 @@ snapshots: postcss-value-parser@4.2.0: {} - postcss@8.5.6: - dependencies: - nanoid: 3.3.11 - picocolors: 1.1.1 - source-map-js: 1.2.1 - postcss@8.5.8: dependencies: nanoid: 3.3.11 @@ -24850,10 +22583,6 @@ snapshots: prepend-http@2.0.0: {} - prettier-linter-helpers@1.0.1: - dependencies: - fast-diff: 1.3.0 - prettier-plugin-ember-template-tag@2.1.3(prettier@3.8.1): dependencies: '@babel/traverse': 7.29.0(supports-color@8.1.1) @@ -24882,10 +22611,6 @@ snapshots: private@0.1.8: {} - proc-log@3.0.0: {} - - proc-log@5.0.0: {} - proc-log@6.1.0: {} process-nextick-args@2.0.1: {} @@ -24913,24 +22638,20 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 - ps-tree@1.2.0: - dependencies: - event-stream: 3.3.4 - pseudomap@1.0.2: {} psl@1.15.0: dependencies: punycode: 2.3.1 - publint@0.3.17: + publint@0.3.18: dependencies: '@publint/pack': 0.1.4 package-manager-detector: 1.6.0 picocolors: 1.1.1 sade: 1.8.1 - pump@3.0.3: + pump@3.0.4: dependencies: end-of-stream: 1.4.5 once: 1.4.0 @@ -24947,7 +22668,11 @@ snapshots: qs@1.0.2: {} - qs@6.14.1: + qs@6.14.2: + dependencies: + side-channel: 1.1.0 + + qs@6.15.0: dependencies: side-channel: 1.1.0 @@ -25021,10 +22746,10 @@ snapshots: ini: 3.0.1 strip-bom: 4.0.0 - read-package-json-fast@3.0.2: + read-package-json-fast@4.0.0: dependencies: - json-parse-even-better-errors: 3.0.2 - npm-normalize-package-bin: 3.0.1 + json-parse-even-better-errors: 4.0.0 + npm-normalize-package-bin: 4.0.0 read-pkg-up@7.0.1: dependencies: @@ -25032,12 +22757,6 @@ snapshots: read-pkg: 5.2.0 type-fest: 0.8.1 - read-pkg@3.0.0: - dependencies: - load-json-file: 4.0.0 - normalize-package-data: 2.5.0 - path-type: 3.0.0 - read-pkg@5.2.0: dependencies: '@types/normalize-package-data': 2.4.4 @@ -25144,8 +22863,6 @@ snapshots: gopd: 1.2.0 set-function-name: 2.0.2 - regexpp@3.2.0: {} - regexpu-core@6.4.0: dependencies: regenerate: 1.4.2 @@ -25286,10 +23003,6 @@ snapshots: rfdc@1.4.1: {} - rimraf@2.5.4: - dependencies: - glob: 7.2.3 - rimraf@2.6.3: dependencies: glob: 7.2.3 @@ -25306,9 +23019,9 @@ snapshots: dependencies: glob: 10.5.0 - rimraf@6.1.2: + rimraf@6.1.3: dependencies: - glob: 13.0.2 + glob: 13.0.6 package-json-from-dist: 1.0.1 rollup@4.59.0: @@ -25354,12 +23067,6 @@ snapshots: transitivePeerDependencies: - supports-color - router_js@8.0.6(route-recognizer@0.3.4)(rsvp@4.8.5): - dependencies: - '@glimmer/env': 0.1.7 - route-recognizer: 0.3.4 - rsvp: 4.8.5 - rrweb-cssom@0.7.1: {} rrweb-cssom@0.8.0: {} @@ -25374,8 +23081,6 @@ snapshots: run-async@2.4.1: {} - run-async@3.0.0: {} - run-async@4.0.6: {} run-parallel@1.2.0: @@ -25488,9 +23193,9 @@ snapshots: schema-utils@4.3.3: dependencies: '@types/json-schema': 7.0.15 - ajv: 8.17.1 + ajv: 8.18.0 ajv-formats: 2.1.1 - ajv-keywords: 5.1.0(ajv@8.17.1) + ajv-keywords: 5.1.0(ajv@8.18.0) semver@5.7.2: {} @@ -25760,15 +23465,6 @@ snapshots: sort-object-keys@2.1.0: {} - sort-package-json@1.57.0: - dependencies: - detect-indent: 6.1.0 - detect-newline: 3.1.0 - git-hooks-list: 1.0.3 - globby: 10.0.0 - is-plain-obj: 2.1.0 - sort-object-keys: 1.1.3 - sort-package-json@2.15.1: dependencies: detect-indent: 7.0.2 @@ -25829,16 +23525,16 @@ snapshots: spdx-correct@3.2.0: dependencies: spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.22 + spdx-license-ids: 3.0.23 spdx-exceptions@2.5.0: {} spdx-expression-parse@3.0.1: dependencies: spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.22 + spdx-license-ids: 3.0.23 - spdx-license-ids@3.0.22: {} + spdx-license-ids@3.0.23: {} split-string@3.1.0: dependencies: @@ -25848,10 +23544,6 @@ snapshots: dependencies: readable-stream: 3.6.2 - split@0.3.3: - dependencies: - through: 2.3.8 - sprintf-js@1.0.3: {} sprintf-js@1.1.3: {} @@ -25863,12 +23555,6 @@ snapshots: as-table: 1.0.55 get-source: 2.0.12 - stagehand@1.0.1: - dependencies: - debug: 4.4.3(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - static-extend@0.1.2: dependencies: define-property: 0.2.5 @@ -25885,10 +23571,6 @@ snapshots: es-errors: 1.3.0 internal-slot: 1.1.0 - stream-combiner@0.0.4: - dependencies: - duplexer: 0.1.2 - string-length@4.0.2: dependencies: char-regex: 1.0.2 @@ -25917,7 +23599,7 @@ snapshots: dependencies: eastasianwidth: 0.2.0 emoji-regex: 9.2.2 - strip-ansi: 7.1.2 + strip-ansi: 7.2.0 string.prototype.matchall@4.0.12: dependencies: @@ -25935,13 +23617,6 @@ snapshots: set-function-name: 2.0.2 side-channel: 1.1.0 - string.prototype.padend@3.1.6: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-object-atoms: 1.1.1 - string.prototype.trim@1.2.10: dependencies: call-bind: 1.0.8 @@ -26003,7 +23678,7 @@ snapshots: dependencies: ansi-regex: 5.0.1 - strip-ansi@7.1.2: + strip-ansi@7.2.0: dependencies: ansi-regex: 6.2.2 @@ -26029,7 +23704,7 @@ snapshots: strip-json-comments@3.1.1: {} - strnum@2.1.2: {} + strnum@2.2.0: {} stubborn-fs@2.0.0: dependencies: @@ -26037,24 +23712,33 @@ snapshots: stubborn-utils@1.0.2: {} - style-loader@2.0.0(webpack@5.105.1(@swc/core@1.15.11)): + style-loader@2.0.0(webpack@5.105.4(@swc/core@1.15.18)): dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.105.1(@swc/core@1.15.11) + webpack: 5.105.4(@swc/core@1.15.18) - style-loader@2.0.0(webpack@5.105.1): + style-loader@2.0.0(webpack@5.105.4): dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.105.1 + webpack: 5.105.4 styled_string@0.0.1: {} + stylelint-config-recommended@14.0.1(stylelint@16.26.1(typescript@5.9.3)): + dependencies: + stylelint: 16.26.1(typescript@5.9.3) + stylelint-config-recommended@16.0.0(stylelint@16.26.1(typescript@5.9.3)): dependencies: stylelint: 16.26.1(typescript@5.9.3) + stylelint-config-standard@36.0.1(stylelint@16.26.1(typescript@5.9.3)): + dependencies: + stylelint: 16.26.1(typescript@5.9.3) + stylelint-config-recommended: 14.0.1(stylelint@16.26.1(typescript@5.9.3)) + stylelint-config-standard@38.0.0(stylelint@16.26.1(typescript@5.9.3)): dependencies: stylelint: 16.26.1(typescript@5.9.3) @@ -26063,16 +23747,16 @@ snapshots: stylelint@16.26.1(typescript@5.9.3): dependencies: '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) - '@csstools/css-syntax-patches-for-csstree': 1.0.27 + '@csstools/css-syntax-patches-for-csstree': 1.1.0 '@csstools/css-tokenizer': 3.0.4 '@csstools/media-query-list-parser': 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1) '@dual-bundle/import-meta-resolve': 4.2.1 balanced-match: 2.0.0 colord: 2.9.3 - cosmiconfig: 9.0.0(typescript@5.9.3) + cosmiconfig: 9.0.1(typescript@5.9.3) css-functions-list: 3.3.3 - css-tree: 3.1.0 + css-tree: 3.2.1 debug: 4.4.3(supports-color@8.1.1) fast-glob: 3.3.3 fastest-levenshtein: 1.0.16 @@ -26090,9 +23774,9 @@ snapshots: micromatch: 4.0.8 normalize-path: 3.0.0 picocolors: 1.1.1 - postcss: 8.5.6 + postcss: 8.5.8 postcss-resolve-nested-selector: 0.1.6 - postcss-safe-parser: 7.0.1(postcss@8.5.6) + postcss-safe-parser: 7.0.1(postcss@8.5.8) postcss-selector-parser: 7.1.1 postcss-value-parser: 4.2.0 resolve-from: 5.0.0 @@ -26161,13 +23845,9 @@ snapshots: transitivePeerDependencies: - supports-color - synckit@0.11.12: - dependencies: - '@pkgr/core': 0.2.9 - table@6.9.0: dependencies: - ajv: 8.17.1 + ajv: 8.18.0 lodash.truncate: 4.4.2 slice-ansi: 4.0.0 string-width: 4.2.3 @@ -26189,39 +23869,33 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 - temp-fs@0.9.9: - dependencies: - rimraf: 2.5.4 - temp@0.9.4: dependencies: mkdirp: 0.5.6 rimraf: 2.6.3 - terser-webpack-plugin@5.3.16(@swc/core@1.15.11)(webpack@5.105.1(@swc/core@1.15.11)): + terser-webpack-plugin@5.3.17(@swc/core@1.15.18)(webpack@5.105.4(@swc/core@1.15.18)): dependencies: '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 schema-utils: 4.3.3 - serialize-javascript: 6.0.2 terser: 5.46.0 - webpack: 5.105.1(@swc/core@1.15.11) + webpack: 5.105.4(@swc/core@1.15.18) optionalDependencies: - '@swc/core': 1.15.11 + '@swc/core': 1.15.18 - terser-webpack-plugin@5.3.16(webpack@5.105.1): + terser-webpack-plugin@5.3.17(webpack@5.105.4): dependencies: '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 schema-utils: 4.3.3 - serialize-javascript: 6.0.2 terser: 5.46.0 - webpack: 5.105.1 + webpack: 5.105.4 terser@5.46.0: dependencies: '@jridgewell/source-map': 0.3.11 - acorn: 8.15.0 + acorn: 8.16.0 commander: 2.20.3 source-map-support: 0.5.21 @@ -26232,9 +23906,9 @@ snapshots: stringify-object-es5: 2.5.0 theredoc: 1.0.0 - testem-failure-only-reporter@1.0.0(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.7): + testem-failure-only-reporter@1.0.0(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.8): dependencies: - testem: 3.17.0(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.7) + testem: 3.17.0(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.8) transitivePeerDependencies: - arc-templates - atpl @@ -26292,7 +23966,7 @@ snapshots: - walrus - whiskers - testem@3.17.0(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.7): + testem@3.17.0(ejs@3.1.10)(handlebars@4.7.8)(underscore@1.13.8): dependencies: '@xmldom/xmldom': 0.8.11 backbone: 1.6.1 @@ -26300,7 +23974,7 @@ snapshots: charm: 1.0.2 commander: 2.20.3 compression: 1.8.1 - consolidate: 0.16.0(ejs@3.1.10)(handlebars@4.7.8)(lodash@4.17.23)(mustache@4.2.0)(underscore@1.13.7) + consolidate: 0.16.0(ejs@3.1.10)(handlebars@4.7.8)(lodash@4.17.23)(mustache@4.2.0)(underscore@1.13.8) execa: 1.0.0 express: 4.22.1 fireworm: 0.7.2 @@ -26376,30 +24050,18 @@ snapshots: - walrus - whiskers - text-table@0.2.0: {} - textextensions@2.6.0: {} theredoc@1.0.0: {} - thread-loader@3.0.4(webpack@5.105.1(@swc/core@1.15.11)): - dependencies: - json-parse-better-errors: 1.0.2 - loader-runner: 4.3.1 - loader-utils: 2.0.4 - neo-async: 2.6.2 - schema-utils: 3.3.0 - webpack: 5.105.1(@swc/core@1.15.11) - - thread-loader@3.0.4(webpack@5.105.1): + thread-loader@3.0.4(webpack@5.105.4(@swc/core@1.15.18)): dependencies: json-parse-better-errors: 1.0.2 loader-runner: 4.3.1 loader-utils: 2.0.4 neo-async: 2.6.2 schema-utils: 3.3.0 - webpack: 5.105.1 - optional: true + webpack: 5.105.4(@swc/core@1.15.18) through2@3.0.2: dependencies: @@ -26424,7 +24086,7 @@ snapshots: faye-websocket: 0.11.4 livereload-js: 3.4.1 object-assign: 4.1.1 - qs: 6.14.1 + qs: 6.15.0 transitivePeerDependencies: - supports-color @@ -26435,16 +24097,16 @@ snapshots: tldts-core@6.1.86: {} - tldts-core@7.0.23: + tldts-core@7.0.24: optional: true tldts@6.1.86: dependencies: tldts-core: 6.1.86 - tldts@7.0.23: + tldts@7.0.24: dependencies: - tldts-core: 7.0.23 + tldts-core: 7.0.24 optional: true tmp-sync@1.1.2: @@ -26468,8 +24130,6 @@ snapshots: tmpl@1.0.5: {} - to-fast-properties@2.0.0: {} - to-object-path@0.3.0: dependencies: kind-of: 3.2.2 @@ -26507,22 +24167,22 @@ snapshots: tough-cookie@6.0.0: dependencies: - tldts: 7.0.23 + tldts: 7.0.24 optional: true tr46@5.1.1: dependencies: punycode: 2.3.1 - tracerbench@8.0.1(@swc/core@1.15.11)(@types/node@22.19.11)(typescript@5.9.3): + tracerbench@8.0.1(@swc/core@1.15.18)(@types/node@22.19.15)(typescript@5.9.3): dependencies: '@oclif/command': 1.8.36 '@oclif/config': 1.18.17 '@oclif/errors': 1.3.6 '@oclif/parser': 3.8.17 - '@oclif/plugin-help': 5.2.20(@swc/core@1.15.11)(@types/node@22.19.11)(typescript@5.9.3) - '@oclif/plugin-warn-if-update-available': 2.1.1(@swc/core@1.15.11)(@types/node@22.19.11)(typescript@5.9.3) - '@tracerbench/core': 8.0.1(patch_hash=94ed69d4e124c0c94f1c1e3332668ae5d3265509b12cc97dd634feee8ed7e846) + '@oclif/plugin-help': 5.2.20(@swc/core@1.15.18)(@types/node@22.19.15)(typescript@5.9.3) + '@oclif/plugin-warn-if-update-available': 2.1.1(@swc/core@1.15.18)(@types/node@22.19.15)(typescript@5.9.3) + '@tracerbench/core': 8.0.1(patch_hash=ee5cfa4adb0f65df07ef51d9be56c31150b4330d7ac7e1fbbb0a87329938af0a) '@tracerbench/stats': 8.0.1 '@tracerbench/trace-event': 8.0.0 archiver: 5.3.2 @@ -26563,6 +24223,14 @@ snapshots: - ember-source - supports-color + tracked-built-ins@4.1.2(@babel/core@7.29.0): + dependencies: + '@embroider/addon-shim': 1.10.2 + decorator-transforms: 2.3.1(@babel/core@7.29.0) + transitivePeerDependencies: + - '@babel/core' + - supports-color + tree-kill@1.2.2: {} tree-sync@1.4.0: @@ -26596,16 +24264,16 @@ snapshots: picomatch: 4.0.3 typescript: 5.9.3 - ts-node@10.9.2(@swc/core@1.15.11)(@types/node@22.19.11)(typescript@5.9.3): + ts-node@10.9.2(@swc/core@1.15.18)(@types/node@22.19.15)(typescript@5.9.3): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.12 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 22.19.11 - acorn: 8.15.0 - acorn-walk: 8.3.4 + '@types/node': 22.19.15 + acorn: 8.16.0 + acorn-walk: 8.3.5 arg: 4.1.3 create-require: 1.1.1 diff: 4.0.4 @@ -26614,7 +24282,7 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 optionalDependencies: - '@swc/core': 1.15.11 + '@swc/core': 1.15.18 tsconfig-paths@3.15.0: dependencies: @@ -26644,8 +24312,6 @@ snapshots: type-detect@4.1.0: {} - type-fest@0.11.0: {} - type-fest@0.18.1: {} type-fest@0.20.2: {} @@ -26702,17 +24368,13 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 - typedarray-to-buffer@3.1.5: - dependencies: - is-typedarray: 1.0.0 - - typescript-eslint@8.55.0(eslint@9.39.2)(typescript@5.9.3): + typescript-eslint@8.56.1(eslint@9.39.3)(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.55.0(@typescript-eslint/parser@8.55.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/parser': 8.55.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.55.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.55.0(eslint@9.39.2)(typescript@5.9.3) - eslint: 9.39.2 + '@typescript-eslint/eslint-plugin': 8.56.1(@typescript-eslint/parser@8.56.1(eslint@9.39.3)(typescript@5.9.3))(eslint@9.39.3)(typescript@5.9.3) + '@typescript-eslint/parser': 8.56.1(eslint@9.39.3)(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.56.1(eslint@9.39.3)(typescript@5.9.3) + eslint: 9.39.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -26744,7 +24406,7 @@ snapshots: underscore@1.1.7: {} - underscore@1.13.7: {} + underscore@1.13.8: {} undici-types@6.21.0: {} @@ -26847,10 +24509,6 @@ snapshots: dependencies: builtins: 5.1.0 - validate-npm-package-name@5.0.1: {} - - validate-npm-package-name@6.0.2: {} - validate-npm-package-name@7.0.2: {} validate-peer-dependencies@1.2.0: @@ -26860,26 +24518,26 @@ snapshots: vary@1.1.2: {} - vite@5.4.21(@types/node@22.19.11)(terser@5.46.0): + vite@5.4.21(@types/node@22.19.15)(terser@5.46.0): dependencies: esbuild: 0.21.5 - postcss: 8.5.6 + postcss: 8.5.8 rollup: 4.59.0 optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 fsevents: 2.3.3 terser: 5.46.0 - vite@7.3.1(@types/node@22.19.11)(terser@5.46.0): + vite@7.3.1(@types/node@22.19.15)(terser@5.46.0): dependencies: esbuild: 0.27.3 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 - postcss: 8.5.6 + postcss: 8.5.8 rollup: 4.59.0 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.15 fsevents: 2.3.3 terser: 5.46.0 @@ -26962,9 +24620,9 @@ snapshots: webidl-conversions@7.0.0: {} - webpack-sources@3.3.3: {} + webpack-sources@3.3.4: {} - webpack@5.105.1: + webpack@5.105.4: dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.8 @@ -26972,11 +24630,11 @@ snapshots: '@webassemblyjs/ast': 1.14.1 '@webassemblyjs/wasm-edit': 1.14.1 '@webassemblyjs/wasm-parser': 1.14.1 - acorn: 8.15.0 - acorn-import-phases: 1.0.4(acorn@8.15.0) + acorn: 8.16.0 + acorn-import-phases: 1.0.4(acorn@8.16.0) browserslist: 4.28.1 chrome-trace-event: 1.0.4 - enhanced-resolve: 5.19.0 + enhanced-resolve: 5.20.0 es-module-lexer: 2.0.0 eslint-scope: 5.1.1 events: 3.3.0 @@ -26988,15 +24646,15 @@ snapshots: neo-async: 2.6.2 schema-utils: 4.3.3 tapable: 2.3.0 - terser-webpack-plugin: 5.3.16(webpack@5.105.1) + terser-webpack-plugin: 5.3.17(webpack@5.105.4) watchpack: 2.5.1 - webpack-sources: 3.3.3 + webpack-sources: 3.3.4 transitivePeerDependencies: - '@swc/core' - esbuild - uglify-js - webpack@5.105.1(@swc/core@1.15.11): + webpack@5.105.4(@swc/core@1.15.18): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.8 @@ -27004,11 +24662,11 @@ snapshots: '@webassemblyjs/ast': 1.14.1 '@webassemblyjs/wasm-edit': 1.14.1 '@webassemblyjs/wasm-parser': 1.14.1 - acorn: 8.15.0 - acorn-import-phases: 1.0.4(acorn@8.15.0) + acorn: 8.16.0 + acorn-import-phases: 1.0.4(acorn@8.16.0) browserslist: 4.28.1 chrome-trace-event: 1.0.4 - enhanced-resolve: 5.19.0 + enhanced-resolve: 5.20.0 es-module-lexer: 2.0.0 eslint-scope: 5.1.1 events: 3.3.0 @@ -27020,9 +24678,9 @@ snapshots: neo-async: 2.6.2 schema-utils: 4.3.3 tapable: 2.3.0 - terser-webpack-plugin: 5.3.16(@swc/core@1.15.11)(webpack@5.105.1(@swc/core@1.15.11)) + terser-webpack-plugin: 5.3.17(@swc/core@1.15.18)(webpack@5.105.4(@swc/core@1.15.18)) watchpack: 2.5.1 - webpack-sources: 3.3.3 + webpack-sources: 3.3.4 transitivePeerDependencies: - '@swc/core' - esbuild @@ -27098,11 +24756,11 @@ snapshots: dependencies: isexe: 2.0.0 - which@3.0.1: + which@4.0.0: dependencies: - isexe: 2.0.0 + isexe: 3.1.5 - which@4.0.0: + which@5.0.0: dependencies: isexe: 3.1.5 @@ -27130,8 +24788,6 @@ snapshots: workerpool@6.5.1: {} - workerpool@9.3.4: {} - wrap-ansi@3.0.1: dependencies: string-width: 2.1.1 @@ -27153,17 +24809,10 @@ snapshots: dependencies: ansi-styles: 6.2.3 string-width: 5.1.2 - strip-ansi: 7.1.2 + strip-ansi: 7.2.0 wrappy@1.0.2: {} - write-file-atomic@3.0.3: - dependencies: - imurmurhash: 0.1.4 - is-typedarray: 1.0.0 - signal-exit: 3.0.7 - typedarray-to-buffer: 3.1.5 - write-file-atomic@4.0.2: dependencies: imurmurhash: 0.1.4 @@ -27183,8 +24832,6 @@ snapshots: ws@8.19.0: {} - xdg-basedir@4.0.0: {} - xdg-basedir@5.1.0: {} xml-name-validator@5.0.0: {} @@ -27241,8 +24888,6 @@ snapshots: yocto-queue@1.2.2: {} - yoctocolors-cjs@2.1.3: {} - yoctocolors@2.1.2: {} yui@3.18.1: diff --git a/rollup.config.mjs b/rollup.config.mjs index bbb33dbdfed..70d3ae07bba 100644 --- a/rollup.config.mjs +++ b/rollup.config.mjs @@ -42,6 +42,8 @@ let configs = [ }), templateCompilerConfig(), glimmerComponent(), + glimmerSyntaxESM(), + glimmerSyntaxCJS(), ]; if (process.env.DEBUG_SINGLE_CONFIG) { @@ -116,6 +118,49 @@ function sharedESMConfig({ input, debugMacrosMode }) { }; } +function glimmerSyntaxESM() { + return { + onLog: handleRollupWarnings, + input: './packages/@glimmer/syntax/index.ts', + output: { + format: 'es', + file: 'packages/@glimmer/syntax/dist/es/index.js', + hoistTransitiveImports: false, + }, + plugins: [ + babel({ + babelHelpers: 'bundled', + extensions: ['.js', '.ts'], + configFile: false, + ...sharedBabelConfig, + }), + resolveTS(), + resolvePackages({ ...exposedDependencies(), ...hiddenDependencies() }), + ], + }; +} +function glimmerSyntaxCJS() { + return { + onLog: handleRollupWarnings, + input: './packages/@glimmer/syntax/index.ts', + output: { + format: 'cjs', + file: 'packages/@glimmer/syntax/dist/cjs/index.cjs', + hoistTransitiveImports: false, + }, + plugins: [ + babel({ + babelHelpers: 'bundled', + extensions: ['.js', '.ts'], + configFile: false, + ...sharedBabelConfig, + }), + resolveTS(), + resolvePackages({ ...exposedDependencies(), ...hiddenDependencies() }), + ], + }; +} + function glimmerComponent() { return { onLog: handleRollupWarnings, @@ -249,6 +294,7 @@ function rolledUpPackages() { '@ember/-internals/metal', '@ember/-internals/utils', '@ember/-internals/container', + 'router_js', ]; } @@ -260,7 +306,7 @@ export function exposedDependencies() { 'backburner.js': require.resolve('backburner.js/dist/es6/backburner.js'), rsvp: require.resolve('rsvp/lib/rsvp.js'), 'dag-map': require.resolve('dag-map/dag-map.js'), - router_js: require.resolve('router_js/dist/modules/index.js'), + router_js: require.resolve('router_js'), 'route-recognizer': require.resolve('route-recognizer/dist/route-recognizer.es.js'), ...walkGlimmerDeps([ '@glimmer/node', diff --git a/smoke-tests/app-template/.eslintignore b/smoke-tests/app-template/.eslintignore deleted file mode 100644 index d474a40bd59..00000000000 --- a/smoke-tests/app-template/.eslintignore +++ /dev/null @@ -1,25 +0,0 @@ -# unconventional js -/blueprints/*/files/ -/vendor/ - -# compiled output -/dist/ -/tmp/ - -# dependencies -/bower_components/ -/node_modules/ - -# misc -/coverage/ -!.* -.*/ -.eslintcache - -# ember-try -/.node_modules.ember-try/ -/bower.json.ember-try -/npm-shrinkwrap.json.ember-try -/package.json.ember-try -/package-lock.json.ember-try -/yarn.lock.ember-try diff --git a/smoke-tests/app-template/.eslintrc.js b/smoke-tests/app-template/.eslintrc.js deleted file mode 100644 index e2004073b03..00000000000 --- a/smoke-tests/app-template/.eslintrc.js +++ /dev/null @@ -1,53 +0,0 @@ -'use strict'; - -module.exports = { - root: true, - parser: 'babel-eslint', - parserOptions: { - ecmaVersion: 2018, - sourceType: 'module', - ecmaFeatures: { - legacyDecorators: true, - }, - }, - plugins: ['ember'], - extends: [ - 'eslint:recommended', - 'plugin:ember/recommended', - 'plugin:prettier/recommended', - ], - env: { - browser: true, - }, - rules: {}, - overrides: [ - // node files - { - files: [ - './.eslintrc.js', - './.prettierrc.js', - './.template-lintrc.js', - './ember-cli-build.js', - './testem.js', - './blueprints/*/index.js', - './config/**/*.js', - './lib/*/index.js', - './server/**/*.js', - ], - parserOptions: { - sourceType: 'script', - }, - env: { - browser: false, - node: true, - }, - plugins: ['n'], - extends: ['plugin:n/recommended'], - }, - { - // test files - files: ['tests/**/*-test.{js,ts}'], - extends: ['plugin:qunit/recommended'], - }, - ], -}; diff --git a/smoke-tests/app-template/.github/workflows/ci.yml b/smoke-tests/app-template/.github/workflows/ci.yml new file mode 100644 index 00000000000..8a43ff0d429 --- /dev/null +++ b/smoke-tests/app-template/.github/workflows/ci.yml @@ -0,0 +1,47 @@ +name: CI + +on: + push: + branches: + - main + - master + pull_request: {} + +concurrency: + group: ci-${{ github.head_ref || github.ref }} + cancel-in-progress: true + +jobs: + lint: + name: "Lint" + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v3 + - name: Install Node + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: npm + - name: Install Dependencies + run: npm ci + - name: Lint + run: npm run lint + + test: + name: "Test" + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v3 + - name: Install Node + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: npm + - name: Install Dependencies + run: npm ci + - name: Run Tests + run: npm test diff --git a/smoke-tests/app-template/.gitignore b/smoke-tests/app-template/.gitignore index e8c68e0ebbd..f0dde6db94f 100644 --- a/smoke-tests/app-template/.gitignore +++ b/smoke-tests/app-template/.gitignore @@ -1,36 +1,18 @@ -# See https://help.github.com/ignore-files/ for more about ignoring files. -# This smoke test ensures that a stable new'd app can run with latest ember-source -# and not having the lock file will help us catch issues that maybe come from elsewhere. -yarn.lock -pnpm-lock.yaml - # compiled output /dist/ -/tmp/ +/declarations/ # dependencies -/bower_components/ /node_modules/ # misc /.env* /.pnp* -/.sass-cache /.eslintcache -/connect.lock /coverage/ -/libpeerconnection.log /npm-debug.log* /testem.log /yarn-error.log -# ember-try -/.node_modules.ember-try/ -/bower.json.ember-try -/npm-shrinkwrap.json.ember-try -/package.json.ember-try -/package-lock.json.ember-try -/yarn.lock.ember-try - # broccoli-debug /DEBUG/ diff --git a/smoke-tests/app-template/.prettierignore b/smoke-tests/app-template/.prettierignore index 4178fd571e6..d7ab45945f5 100644 --- a/smoke-tests/app-template/.prettierignore +++ b/smoke-tests/app-template/.prettierignore @@ -1,25 +1,13 @@ # unconventional js /blueprints/*/files/ -/vendor/ # compiled output /dist/ -/tmp/ - -# dependencies -/bower_components/ -/node_modules/ # misc /coverage/ !.* -.eslintcache -.lint-todo/ - -# ember-try -/.node_modules.ember-try/ -/bower.json.ember-try -/npm-shrinkwrap.json.ember-try -/package.json.ember-try -/package-lock.json.ember-try -/yarn.lock.ember-try +.*/ +/pnpm-lock.yaml +ember-cli-update.json +*.html diff --git a/smoke-tests/app-template/.prettierrc.js b/smoke-tests/app-template/.prettierrc.js index 534e6d35aab..8e62a451ad5 100644 --- a/smoke-tests/app-template/.prettierrc.js +++ b/smoke-tests/app-template/.prettierrc.js @@ -1,5 +1,14 @@ 'use strict'; module.exports = { - singleQuote: true, + plugins: ['prettier-plugin-ember-template-tag'], + overrides: [ + { + files: '*.{js,gjs,ts,gts,mjs,mts,cjs,cts}', + options: { + singleQuote: true, + templateSingleQuote: false, + }, + }, + ], }; diff --git a/smoke-tests/app-template/.stylelintignore b/smoke-tests/app-template/.stylelintignore new file mode 100644 index 00000000000..fc178a0b910 --- /dev/null +++ b/smoke-tests/app-template/.stylelintignore @@ -0,0 +1,5 @@ +# unconventional files +/blueprints/*/files/ + +# compiled output +/dist/ diff --git a/smoke-tests/app-template/.stylelintrc.js b/smoke-tests/app-template/.stylelintrc.js new file mode 100644 index 00000000000..56a013c908f --- /dev/null +++ b/smoke-tests/app-template/.stylelintrc.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = { + extends: ['stylelint-config-standard'], +}; diff --git a/smoke-tests/app-template/.watchmanconfig b/smoke-tests/app-template/.watchmanconfig index e7834e3e4f3..f9c3d8f84fb 100644 --- a/smoke-tests/app-template/.watchmanconfig +++ b/smoke-tests/app-template/.watchmanconfig @@ -1,3 +1,3 @@ { - "ignore_dirs": ["tmp", "dist"] + "ignore_dirs": ["dist"] } diff --git a/smoke-tests/app-template/README.md b/smoke-tests/app-template/README.md new file mode 100644 index 00000000000..c8f37a308e7 --- /dev/null +++ b/smoke-tests/app-template/README.md @@ -0,0 +1,56 @@ +# ember-test-app + +This README outlines the details of collaborating on this Ember application. +A short introduction of this app could easily go here. + +## Prerequisites + +You will need the following things properly installed on your computer. + +- [Git](https://git-scm.com/) +- [Node.js](https://nodejs.org/) (with npm) +- [Ember CLI](https://cli.emberjs.com/release/) +- [Google Chrome](https://google.com/chrome/) + +## Installation + +- `git clone ` this repository +- `cd ember-test-app` +- `npm install` + +## Running / Development + +- `npm run start` +- Visit your app at [http://localhost:4200](http://localhost:4200). +- Visit your tests at [http://localhost:4200/tests](http://localhost:4200/tests). + +### Code Generators + +Make use of the many generators for code, try `ember help generate` for more details + +### Running Tests + +- `npm run test` +- `npm run test:ember -- --server` + +### Linting + +- `npm run lint` +- `npm run lint:fix` + +### Building + +- `npm exec ember build` (development) +- `npm run build` (production) + +### Deploying + +Specify what it takes to deploy your app. + +## Further Reading / Useful Links + +- [ember.js](https://emberjs.com/) +- [ember-cli](https://cli.emberjs.com/release/) +- Development Browser Extensions + - [ember inspector for chrome](https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi) + - [ember inspector for firefox](https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/) diff --git a/smoke-tests/app-template/app/app.js b/smoke-tests/app-template/app/app.js index b6e3fcb9768..fc13e7c2f5b 100644 --- a/smoke-tests/app-template/app/app.js +++ b/smoke-tests/app-template/app/app.js @@ -2,6 +2,11 @@ import Application from '@ember/application'; import Resolver from 'ember-resolver'; import loadInitializers from 'ember-load-initializers'; import config from 'ember-test-app/config/environment'; +import { importSync, isDevelopingApp, macroCondition } from '@embroider/macros'; + +if (macroCondition(isDevelopingApp())) { + importSync('./deprecation-workflow'); +} export default class App extends Application { modulePrefix = config.modulePrefix; diff --git a/smoke-tests/app-template/app/deprecation-workflow.js b/smoke-tests/app-template/app/deprecation-workflow.js new file mode 100644 index 00000000000..274a689db8e --- /dev/null +++ b/smoke-tests/app-template/app/deprecation-workflow.js @@ -0,0 +1,24 @@ +import setupDeprecationWorkflow from 'ember-cli-deprecation-workflow'; + +/** + * Docs: https://github.com/ember-cli/ember-cli-deprecation-workflow + */ +setupDeprecationWorkflow({ + /** + false by default, but if a developer / team wants to be more aggressive about being proactive with + handling their deprecations, this should be set to "true" + */ + throwOnUnhandled: false, + workflow: [ + /* ... handlers ... */ + /* to generate this list, run your app for a while (or run the test suite), + * and then run in the browser console: + * + * deprecationWorkflow.flushDeprecations() + * + * And copy the handlers here + */ + /* example: */ + /* { handler: 'silence', matchId: 'template-action' }, */ + ], +}); diff --git a/smoke-tests/app-template/app/models/.gitkeep b/smoke-tests/app-template/app/models/.gitkeep deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/smoke-tests/app-template/app/router.js b/smoke-tests/app-template/app/router.js index 7bc3daf7a36..aeffbcc03fb 100644 --- a/smoke-tests/app-template/app/router.js +++ b/smoke-tests/app-template/app/router.js @@ -6,5 +6,4 @@ export default class Router extends EmberRouter { rootURL = config.rootURL; } -Router.map(function () { -}); +Router.map(function () {}); diff --git a/smoke-tests/app-template/app/styles/app.css b/smoke-tests/app-template/app/styles/app.css index e69de29bb2d..2763afa4cfa 100644 --- a/smoke-tests/app-template/app/styles/app.css +++ b/smoke-tests/app-template/app/styles/app.css @@ -0,0 +1 @@ +/* Ember supports plain CSS out of the box. More info: https://cli.emberjs.com/release/advanced-use/stylesheets/ */ diff --git a/smoke-tests/app-template/app/templates/application.gjs b/smoke-tests/app-template/app/templates/application.gjs new file mode 100644 index 00000000000..15bc4ae747c --- /dev/null +++ b/smoke-tests/app-template/app/templates/application.gjs @@ -0,0 +1,9 @@ +import pageTitle from 'ember-page-title/helpers/page-title'; + + diff --git a/smoke-tests/app-template/app/templates/application.hbs b/smoke-tests/app-template/app/templates/application.hbs deleted file mode 100644 index e16882a4082..00000000000 --- a/smoke-tests/app-template/app/templates/application.hbs +++ /dev/null @@ -1,4 +0,0 @@ -{{page-title "EmberTestApp"}} - -{{outlet}} - diff --git a/smoke-tests/app-template/app/templates/index.hbs b/smoke-tests/app-template/app/templates/index.hbs deleted file mode 100644 index 2017d4b9197..00000000000 --- a/smoke-tests/app-template/app/templates/index.hbs +++ /dev/null @@ -1,4 +0,0 @@ -{{!-- The following component displays Ember's default welcome message. --}} - -{{!-- Feel free to remove this! --}} - diff --git a/smoke-tests/app-template/config/ember-cli-update.json b/smoke-tests/app-template/config/ember-cli-update.json index 43bb76a4e38..e5993ab805e 100644 --- a/smoke-tests/app-template/config/ember-cli-update.json +++ b/smoke-tests/app-template/config/ember-cli-update.json @@ -2,15 +2,17 @@ "schemaVersion": "1.0.0", "packages": [ { - "name": "ember-cli", - "version": "4.8.0", + "name": "@ember-tooling/classic-build-app-blueprint", + "version": "6.11.0", "blueprints": [ { - "name": "app", - "outputRepo": "https://github.com/ember-cli/ember-new-output", - "codemodsSource": "ember-app-codemods-manifest@1", + "name": "@ember-tooling/classic-build-app-blueprint", "isBaseBlueprint": true, - "options": [] + "options": [ + "--no-welcome", + "--ci-provider=github", + "--no-ember-data" + ] } ] } diff --git a/smoke-tests/app-template/config/environment.js b/smoke-tests/app-template/config/environment.js index 93c6c975869..f5e5c491ff3 100644 --- a/smoke-tests/app-template/config/environment.js +++ b/smoke-tests/app-template/config/environment.js @@ -7,6 +7,11 @@ module.exports = function (environment) { rootURL: '/', locationType: 'history', EmberENV: { + /* The following enables the infrastructure allow us to test as if deprecations + have been turned into errors at a specific version. + */ + _OVERRIDE_DEPRECATION_VERSION: process.env.OVERRIDE_DEPRECATION_VERSION, + EXTEND_PROTOTYPES: false, FEATURES: { // Here you can enable experimental features on an ember canary build // e.g. EMBER_NATIVE_DECORATOR_SUPPORT: true diff --git a/smoke-tests/app-template/config/optional-features.json b/smoke-tests/app-template/config/optional-features.json index 688a5b7739d..5329dd9913b 100644 --- a/smoke-tests/app-template/config/optional-features.json +++ b/smoke-tests/app-template/config/optional-features.json @@ -1,4 +1,7 @@ { + "application-template-wrapper": false, "default-async-observers": true, - "jquery-integration": false + "jquery-integration": false, + "template-only-glimmer-components": true, + "no-implicit-route-model": true } diff --git a/smoke-tests/app-template/ember-cli-build.js b/smoke-tests/app-template/ember-cli-build.js index 77e5ad90726..ed991bd98f6 100644 --- a/smoke-tests/app-template/ember-cli-build.js +++ b/smoke-tests/app-template/ember-cli-build.js @@ -1,28 +1,11 @@ 'use strict'; const EmberApp = require('ember-cli/lib/broccoli/ember-app'); -const { maybeEmbroider } = require('@embroider/test-setup'); module.exports = function (defaults) { const app = new EmberApp(defaults, { // Add options here }); - // Use `app.import` to add additional libraries to the generated - // output files. - // - // If you need to use different assets in different - // environments, specify an object as the first parameter. That - // object's keys should be the environment name and the values - // should be the asset to use in that environment. - // - // If the library that you are including contains AMD or ES6 - // modules that you would like to import into your application - // please specify an object with the list of modules as keys - // along with the exports of each module as its value. - - // when we're testing under embroider, test under the most optimized settings. - process.env.EMBROIDER_TEST_SETUP_OPTIONS = 'optimized'; - - return maybeEmbroider(app); + return app.toTree(); }; diff --git a/smoke-tests/app-template/eslint.config.mjs b/smoke-tests/app-template/eslint.config.mjs new file mode 100644 index 00000000000..a29e5cd3bd9 --- /dev/null +++ b/smoke-tests/app-template/eslint.config.mjs @@ -0,0 +1,126 @@ +/** + * Debugging: + * https://eslint.org/docs/latest/use/configure/debug + * ---------------------------------------------------- + * + * Print a file's calculated configuration + * + * npx eslint --print-config path/to/file.js + * + * Inspecting the config + * + * npx eslint --inspect-config + * + */ +import globals from 'globals'; +import js from '@eslint/js'; + +import ember from 'eslint-plugin-ember/recommended'; +import eslintConfigPrettier from 'eslint-config-prettier'; +import qunit from 'eslint-plugin-qunit'; +import n from 'eslint-plugin-n'; + +import babelParser from '@babel/eslint-parser'; + +const esmParserOptions = { + ecmaFeatures: { modules: true }, + ecmaVersion: 'latest', + requireConfigFile: false, + babelOptions: { + plugins: [ + ['@babel/plugin-proposal-decorators', { decoratorsBeforeExport: true }], + ], + }, +}; + +export default [ + js.configs.recommended, + eslintConfigPrettier, + ember.configs.base, + ember.configs.gjs, + /** + * Ignores must be in their own object + * https://eslint.org/docs/latest/use/configure/ignore + */ + { + ignores: ['dist/', 'node_modules/', 'coverage/', '!**/.*'], + }, + /** + * https://eslint.org/docs/latest/use/configure/configuration-files#configuring-linter-options + */ + { + linterOptions: { + reportUnusedDisableDirectives: 'error', + }, + }, + { + files: ['**/*.js'], + languageOptions: { + parser: babelParser, + }, + }, + { + files: ['**/*.{js,gjs}'], + languageOptions: { + parserOptions: esmParserOptions, + globals: { + ...globals.browser, + }, + }, + }, + { + ...qunit.configs.recommended, + files: ['tests/**/*-test.{js,gjs}'], + plugins: { + qunit, + }, + }, + /** + * CJS node files + */ + { + ...n.configs['flat/recommended-script'], + files: [ + '**/*.cjs', + 'config/**/*.js', + 'tests/dummy/config/**/*.js', + 'testem.js', + 'testem*.js', + 'index.js', + '.prettierrc.js', + '.stylelintrc.js', + '.template-lintrc.js', + 'ember-cli-build.js', + ], + plugins: { + n, + }, + + languageOptions: { + sourceType: 'script', + ecmaVersion: 'latest', + globals: { + ...globals.node, + }, + }, + }, + /** + * ESM node files + */ + { + ...n.configs['flat/recommended-module'], + files: ['**/*.mjs'], + plugins: { + n, + }, + + languageOptions: { + sourceType: 'module', + ecmaVersion: 'latest', + parserOptions: esmParserOptions, + globals: { + ...globals.node, + }, + }, + }, +]; diff --git a/smoke-tests/app-template/package.json b/smoke-tests/app-template/package.json index 62cb6571ce6..66b4c40cff3 100644 --- a/smoke-tests/app-template/package.json +++ b/smoke-tests/app-template/package.json @@ -12,8 +12,12 @@ }, "scripts": { "build": "ember build --environment=production", - "lint": "npm-run-all --print-name --aggregate-output --continue-on-error --parallel \"lint:!(fix)\"", - "lint:fix": "npm-run-all --print-name --aggregate-output --continue-on-error --parallel \"lint:*:fix\"", + "format": "prettier . --cache --write", + "lint": "concurrently \"npm:lint:*(!fix)\" --names \"lint:\" --prefixColors auto", + "lint:css": "stylelint \"**/*.css\"", + "lint:css:fix": "concurrently \"npm:lint:css -- --fix\"", + "lint:fix": "concurrently \"npm:lint:*:fix\" --names \"fix:\" --prefixColors auto && npm run format", + "lint:format": "prettier . --cache --check", "lint:hbs": "ember-template-lint .", "lint:hbs:fix": "ember-template-lint . --fix", "lint:js": "eslint . --cache", @@ -23,48 +27,54 @@ "test:ember": "ember test" }, "devDependencies": { - "@babel/core": "^7.24.4", + "@babel/core": "^7.29.0", + "@babel/eslint-parser": "^7.28.6", + "@babel/plugin-proposal-decorators": "^7.29.0", "@ember/optional-features": "^2.3.0", - "@ember/string": "^3.0.1", - "@ember/test-helpers": "^3.3.0", - "@ember/test-waiters": "^3.1.0", - "@embroider/test-setup": "^4.0.0", + "@ember/test-helpers": "^5.4.1", + "@embroider/macros": "^1.19.7", + "@eslint/js": "^9.39.2", "@glimmer/component": "workspace:^", "@glimmer/tracking": "^1.1.2", "broccoli-asset-rev": "^3.0.0", - "ember-auto-import": "^2.12.0", - "ember-cli": "~5.7.0", - "ember-cli-babel": "^8.2.0", - "ember-cli-dependency-checker": "^3.3.1", + "concurrently": "^9.2.1", + "ember-auto-import": "^2.13.0", + "ember-cli": "~6.11.0", + "ember-cli-app-version": "^7.0.0", + "ember-cli-babel": "^8.3.1", + "ember-cli-clean-css": "^3.0.0", + "ember-cli-dependency-checker": "^3.3.3", + "ember-cli-deprecation-workflow": "^3.4.0", "ember-cli-htmlbars": "^7.0.0", "ember-cli-inject-live-reload": "^2.1.0", "ember-cli-sri": "^2.1.1", "ember-cli-terser": "^4.0.2", - "ember-data": "~5.8.1", - "ember-load-initializers": "^2.1.2", - "ember-page-title": "^8.2.3", - "ember-qunit": "^8.0.2", - "ember-resolver": "^11.0.1", + "ember-load-initializers": "^3.0.1", + "ember-modifier": "^4.3.0", + "ember-page-title": "^9.0.3", + "ember-qunit": "^9.0.4", + "ember-resolver": "^13.1.1", "ember-source": "workspace:*", - "ember-template-imports": "^4.1.2", - "ember-template-lint": "^6.0.0", - "ember-welcome-page": "^7.0.2", - "eslint": "^8.0.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-ember": "^12.0.2", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-qunit": "^8.1.1", + "ember-template-imports": "^4.4.0", + "ember-template-lint": "^6.1.0", + "eslint": "^9.39.2", + "eslint-config-prettier": "^9.1.2", + "eslint-plugin-ember": "^12.7.5", + "eslint-plugin-n": "^17.24.0", + "eslint-plugin-qunit": "^8.2.6", + "globals": "^15.15.0", "loader.js": "^4.7.0", - "npm-run-all": "^4.1.5", - "prettier": "^3.2.5", - "qunit": "^2.19.2", - "qunit-dom": "^3.1.1", - "tracked-built-ins": "^4.1.0", - "webpack": "^5.74.0" + "prettier": "^3.8.1", + "prettier-plugin-ember-template-tag": "^2.1.3", + "qunit": "^2.25.0", + "qunit-dom": "^3.5.0", + "stylelint": "^16.26.1", + "stylelint-config-standard": "^36.0.1", + "tracked-built-ins": "^4.1.2", + "webpack": "^5.105.2" }, "engines": { - "node": "16.* || >= 18" + "node": ">= 20.19" }, "ember": { "edition": "octane" diff --git a/smoke-tests/app-template/tests/helpers/index.js b/smoke-tests/app-template/tests/helpers/index.js index 7f70de80f4d..ab04c162ddf 100644 --- a/smoke-tests/app-template/tests/helpers/index.js +++ b/smoke-tests/app-template/tests/helpers/index.js @@ -4,7 +4,7 @@ import { setupTest as upstreamSetupTest, } from 'ember-qunit'; -// This file exists to provide wrappers around ember-qunit's / ember-mocha's +// This file exists to provide wrappers around ember-qunit's // test setup functions. This way, you can easily extend the setup that is // needed per test type. @@ -23,7 +23,7 @@ function setupApplicationTest(hooks, options) { // This is also a good place to call test setup functions coming // from other addons: // - // setupIntl(hooks); // ember-intl + // setupIntl(hooks, 'en-us'); // ember-intl // setupMirage(hooks); // ember-cli-mirage } diff --git a/smoke-tests/app-template/tests/test-helper.js b/smoke-tests/app-template/tests/test-helper.js index 2edd1d30e3c..4a55d87eab2 100644 --- a/smoke-tests/app-template/tests/test-helper.js +++ b/smoke-tests/app-template/tests/test-helper.js @@ -3,10 +3,12 @@ import config from 'ember-test-app/config/environment'; import * as QUnit from 'qunit'; import { setApplication } from '@ember/test-helpers'; import { setup } from 'qunit-dom'; -import { start } from 'ember-qunit'; +import { loadTests } from 'ember-qunit/test-loader'; +import { start, setupEmberOnerrorValidation } from 'ember-qunit'; setApplication(Application.create(config.APP)); setup(QUnit.assert); - +setupEmberOnerrorValidation(); +loadTests(); start(); diff --git a/smoke-tests/app-template/vendor/.gitkeep b/smoke-tests/app-template/vendor/.gitkeep deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/smoke-tests/node-template/package.json b/smoke-tests/node-template/package.json index c33b74d91c5..ea6c1920432 100644 --- a/smoke-tests/node-template/package.json +++ b/smoke-tests/node-template/package.json @@ -7,10 +7,8 @@ "test:node": "qunit tests/node/**/*-test.js" }, "dependencies": { - "git-repo-info": "^2.1.1", "html-differ": "^1.4.0", "qunit": "^2.20.1", - "semver": "^7.6.0", "simple-dom": "^1.4.0" } } diff --git a/smoke-tests/scenarios/basic-test.ts b/smoke-tests/scenarios/basic-test.ts index 1e575338e0e..b58d060f79a 100644 --- a/smoke-tests/scenarios/basic-test.ts +++ b/smoke-tests/scenarios/basic-test.ts @@ -223,6 +223,41 @@ function basicTest(scenarios: Scenarios, appName: string) { }); `, + 'debug-render-tree-test.gjs': ` + import { module, test } from 'qunit'; + import { setupRenderingTest } from 'ember-qunit'; + import { render } from '@ember/test-helpers'; + import { captureRenderTree } from '@ember/debug'; + import Component from '@glimmer/component'; + + function flattenTree(nodes) { + let result = []; + for (let node of nodes) { + result.push(node); + if (node.children) { + result.push(...flattenTree(node.children)); + } + } + return result; + } + + class HelloWorld extends Component { + + } + + module('Integration | captureRenderTree', function (hooks) { + setupRenderingTest(hooks); + + test('scope-based components have correct names in debugRenderTree', async function (assert) { + await render(); + + let tree = captureRenderTree(this.owner); + let allNodes = flattenTree(tree); + let names = allNodes.filter(n => n.type === 'component').map(n => n.name); + assert.true(names.includes('HelloWorld'), 'HelloWorld component name is preserved in the render tree (found: ' + names.join(', ') + ')'); + }); + }); + `, }, }, }); diff --git a/smoke-tests/v2-app-template/package.json b/smoke-tests/v2-app-template/package.json index f3132085247..2d40e14e1c0 100644 --- a/smoke-tests/v2-app-template/package.json +++ b/smoke-tests/v2-app-template/package.json @@ -51,9 +51,9 @@ "babel-plugin-ember-template-compilation": "^3.1.0", "concurrently": "^9.2.1", "decorator-transforms": "^2.3.1", - "ember-cli": "~6.10.2", + "ember-cli": "~6.11.0", "ember-cli-babel": "^8.3.1", - "ember-cli-deprecation-workflow": "^3.4.0", + "ember-cli-deprecation-workflow": "^4.0.0", "ember-load-initializers": "^3.0.1", "ember-modifier": "^4.3.0", "ember-page-title": "^9.0.3", diff --git a/tests/docs/expected.js b/tests/docs/expected.js index c5c0292d878..57caa8fb9a3 100644 --- a/tests/docs/expected.js +++ b/tests/docs/expected.js @@ -24,7 +24,6 @@ module.exports = { '_fullyScopeQueryParams', '_getObjectsOnNamespaces', '_getQPMeta', - '_globalsMode', '_helpers', '_hydrateUnsuppliedQueryParams', '_initializersRan', @@ -34,7 +33,6 @@ module.exports = { '_onLookup', '_options', '_optionsForQueryParam', - '_prepareForGlobalsMode', '_prepareQueryParams', '_pruneDefaultQueryParamValues', '_qp',