diff --git a/.agent/skills/adev-writing-guide/SKILL.md b/.agent/skills/adev-writing-guide/SKILL.md index 250afcbfad1a..bc70c81cd7d4 100644 --- a/.agent/skills/adev-writing-guide/SKILL.md +++ b/.agent/skills/adev-writing-guide/SKILL.md @@ -70,23 +70,24 @@ Use the appropriate language identifier for syntax highlighting: - **TypeScript (Generic):** Use `ts` for plain TypeScript. - **HTML (Generic):** Use `html` for plain HTML. - **Shell/Terminal:** Use `shell` or `bash`. -- **Mermaid Diagrams:** Use `mermaid`. +- **Mermaid Diagrams:** Use a `mermaid` fenced block. `` is not supported and fails the build. #### Attributes -You can enhance code blocks with attributes in curly braces `{}` after the language identifier: +You can enhance code blocks with attributes in curly braces `{}` after the language identifier. `header` and `highlight` take a value after a colon; the rest are bare flags, and writing one as `flag: true` fails the build with `Invalid code block metadata`, as does an unrecognized key: -- `header="Title"`: Adds a title to the code block. +- `header: "Title"`: Adds a title to the code block. - `linenums`: Enables line numbering. -- `highlight="[1, 3-5]"`: Highlights specific lines. +- `highlight: [2]`: Highlights specific lines. An ascending two-number array is a range, so `[12, 19]` highlights lines 12 through 19. One number, or three or more, is a literal list. Nest one level to mix the two: `[[3,7], 9]`. - `hideCopy`: Hides the copy button. +- `hideDollar`: Hides the `$` prompt in shell examples. - `prefer`: Marks code as a preferred example (green border/check). - `avoid`: Marks code as an example to avoid (red border/cross). **Example:** ````markdown -```angular-ts {header:"My Component", linenums, highlight="[2]"} +```angular-ts {header: "My Component", linenums, highlight: [2]} @Component({ selector: 'my-app', template: '

Hello

', @@ -97,18 +98,19 @@ export class App {} #### `` Component -For more advanced code block features, use the `` component: +For more advanced code block features, use the `` component. Its attributes use HTML syntax, `attr="value"` with double quotes, and bare names for the boolean ones. It validates nothing, so an unrecognized attribute and a single-quoted value are both ignored without an error: - `path`: Path to a source file (e.g., `adev/src/content/examples/...`). - `header`: Custom header text. -- `language`: Language identifier (e.g., `angular-ts`). +- `language`: Language identifier (e.g., `angular-ts`). When omitted, it is inferred from the file extension, and an extension it does not recognize falls back to `angular-ts`, so set it for shell, markdown and scss files. - `linenums`: Boolean attribute. -- `highlight`: Array of line numbers/ranges (e.g., `[[3,7], 9]`). -- `diff`: Path to diff file. +- `highlight`: Array of line numbers/ranges, with the same semantics as the fenced form (e.g., `[[3,7], 9]`). - `visibleLines`: Range of lines to show initially (collapsible). - `region`: Region to extract from source file. -- `preview`: Boolean. Renders a live preview (StackBlitz). _Only works with standalone examples._ +- `preview`: Boolean. Renders the example as a running component below the code. _Only works with standalone examples._ - `hideCode`: Boolean. Collapses code by default. +- `hideDollar`: Hides the `$` prompt in shell examples. +- `prefer` / `avoid`: Mark the example as preferred or as one to avoid. **Multifile Example:** @@ -127,7 +129,7 @@ Use specific keywords followed by a colon for alerts. These render as styled blo - `TIP:` For helpful hints or shortcuts. - `IMPORTANT:` For crucial information. - `CRITICAL:` For warnings about potential data loss or severe issues. -- `TODO`: For incomplete documentation. +- `TODO:` For incomplete documentation. - `QUESTION:` To pose a question to the reader. - `SUMMARY:` For section summaries. - `TLDR:` For concise summaries. @@ -142,8 +144,9 @@ TIP: Use `ng serve` to run your application locally. ### Custom Components - **Cards (``):** - - Must be inside ``. - - Attributes: `title`, `link`, `href`. + - Usually inside ``; a single card also renders on its own. + - Attributes: `title`, `href`, `link`, `imgSrc`, `iconImgSrc`, `titleInline`. + - `href` is the destination and `link` only replaces the default "Learn more" label, so a URL written in `link` renders as text and a card without `href` is not clickable. - **Callouts (``):** - Attributes: `title`, `important`, `critical`. - **Pills (``):** @@ -156,7 +159,7 @@ TIP: Use `ng serve` to run your application locally. - Must be inside ``. - Attributes: `label`. - **Videos (``):** - - Attributes: `src` (YouTube embed URL), `alt`. + - Attributes: `src` (YouTube embed URL), `title` (names the video in the play link's label). ### Images diff --git a/.agent/skills/pr_review/SKILL.md b/.agent/skills/pr_review/SKILL.md index f407ad4fe904..c565fa73610b 100644 --- a/.agent/skills/pr_review/SKILL.md +++ b/.agent/skills/pr_review/SKILL.md @@ -13,7 +13,8 @@ When reviewing a pull request for the `angular` repository, follow these essenti 2. **Key Focus Areas**: - **Comprehensive Reviews**: You **MUST always** perform a deep, comprehensive review of the _entire_ pull request. If the user asks you to look into a specific issue, file, or area of concern, you must investigate that specific area _in addition to_ reviewing the rest of the PR's substantive changes. Do not terminate your review after addressing only the user's focal point. - - **Package-Specific Guidelines**: Check if there are specific guidelines for the package being modified in the `reference/` directory (e.g., `reference/router.md`). Always prioritize these rules for their respective packages. + - **Package-Specific & Topic Guidelines**: Check if there are specific guidelines for the package or topic being modified in the `reference/` directory (e.g., `reference/router.md` or `reference/object_create_null.md`). Always prioritize these rules for their respective areas. + - **Prototype Collision & `Object.create(null)` PRs**: When reviewing PRs that swap `{}` for `Object.create(null)`, consult `reference/object_create_null.md` for technical evaluation criteria and rules. - **Commit Messages**: Evaluate the quality of commit messages. They should explain the _why_ behind the change, not just the _what_. Someone should be able to look at the commit history years from now and clearly understand the context and reasoning for the change. - **Code Cleanliness**: Ensure the code is readable, maintainable, and follows Angular's project standards. - **Performance**: Look out for code that might negatively impact runtime performance or bundle size, particularly in hot paths like change detection or rendering. diff --git a/.agent/skills/pr_review/reference/object_create_null.md b/.agent/skills/pr_review/reference/object_create_null.md new file mode 100644 index 000000000000..cdebf3e03e73 --- /dev/null +++ b/.agent/skills/pr_review/reference/object_create_null.md @@ -0,0 +1,38 @@ +# Rules for `Object.create(null)` and Prototype Collision Prevention + +This guide outlines the technical rules and evaluation criteria for using `Object.create(null)` versus standard object literals (`{}`) or `Map` in the Angular codebase. + +--- + +## 1. When `Object.create(null)` is Appropriate + +Using `Object.create(null)` (or `Map`) is appropriate when **all** of the following conditions are met: + +1. The object is used as an **internal key-value lookup map or set**. +2. The keys are **arbitrary or untrusted dynamic strings** (e.g., URL query parameters in `$locationShim`, HTML sanitizer tag sets, or `jsaction` DOM event-type resolvers). +3. Property existence is checked via direct indexing or key checks (e.g., `map[key] !== undefined` or `key in map`), where a key matching an `Object.prototype` member (such as `'toString'`, `'constructor'`, or `'hasOwnProperty'`) causes false positive matches or incorrect behavior. + +--- + +## 2. Handling Public API and Boundary Objects + +If an object receives untrusted dynamic keys **and** is exposed to public consumers or third-party code (e.g., `SimpleChanges` in `ngOnChanges`): + +- **Do NOT blindly change the object to `Object.create(null)`**: Stripping `Object.prototype` from public objects is a breaking API change. Consumer code calling `.hasOwnProperty()`, `.toString()`, `.valueOf()`, or using string interpolation (`` `${obj}` ``) will fail at runtime (`TypeError: obj.hasOwnProperty is not a function`). +- **Safe Alternatives for Public Objects:** + - **`Object.hasOwn(obj, key)`**: Use `Object.hasOwn` for internal framework property lookups instead of direct index or `in` checks. This prevents prototype collision during internal reads without breaking the object's prototype for consumers. + - **Input Key Sanitization**: Filter or delete dangerous key names (`__proto__`, `constructor`, `prototype`) when populating the object. + - **`Map` or Custom Classes**: For new public APIs requiring key-value stores with dynamic keys, prefer `Map` or dedicated classes with explicit `.get()` and `.has()` methods. + - **Deprecation / Breaking Change Process**: If changing a public object's prototype to `null` is unavoidable, it must follow Angular's formal deprecation and major version breaking change process. + +--- + +## 3. When `Object.create(null)` Should NOT Be Used + +Do not replace `{}` with `Object.create(null)` in the following scenarios: + +1. **Fixed-Shape Structs and DTOs:** Objects with hardcoded static property names (e.g., `let sortedBreakpoints: {breakpoints?: number[]} = {}`). `Object.assign({}, ...)` only copies _own_ enumerable properties, so prototype properties on sources are never copied. +2. **Numeric-Key Maps:** Objects indexed by numbers (e.g., `tasksByHandleId: {[id: number]: Task}`). Numeric keys do not collide with `Object.prototype` string members. +3. **Reference Sentinels:** Objects used purely for reference identity checks (e.g., `const EMPTY_OBJECT = {}` or `const IN_PROGRESS_RESOLUTION = {}`). +4. **Internal Compiler AST and Visitor State:** Temporary objects with internally generated keys where untrusted user input cannot poison key names. +5. **Hot Performance Paths and Size-Critical Bundles:** Standard `{}` literals use V8 fast hidden classes and monomorphic inline caching. `Object.create(null)` forces V8 dictionary mode and increases minified bundle size (e.g., in inline polyfills like `event-dispatch-contract` or SSR hydration bundles). diff --git a/.agent/skills/pr_review/scripts/determine_review_type.sh b/.agent/skills/pr_review/scripts/determine_review_type.sh index d773b40f6e42..06f79be4efeb 100755 --- a/.agent/skills/pr_review/scripts/determine_review_type.sh +++ b/.agent/skills/pr_review/scripts/determine_review_type.sh @@ -4,24 +4,28 @@ set -euo pipefail # determine_review_type.sh # Determines if the PR should be reviewed locally or remotely based on author. -if [ -z "$1" ]; then - echo "Usage: determine_review_type.sh " +if [ "$#" -lt 1 ] || [ -z "$1" ]; then + echo "Usage: $0 " >&2 exit 1 fi -PR_NUMBER=$1 +PR_NUMBER="$1" + +# Ensure gh cli is installed +if ! command -v gh &> /dev/null; then + echo "Error: gh CLI could not be found. Please install and authenticate." >&2 + exit 1 +fi # Get current authenticated user -CURRENT_USER=$(gh api user -q .login 2>/dev/null) -if [ $? -ne 0 ]; then - echo "Error: Could not determine current GitHub user. Are you logged in to gh?" +if ! CURRENT_USER=$(gh api user -q .login); then + echo "Error: Could not determine current GitHub user. Are you logged in to gh?" >&2 exit 1 fi -# Get PR author -PR_AUTHOR=$(gh pr view "$PR_NUMBER" --json author -q .author.login 2>/dev/null) -if [ $? -ne 0 ]; then - echo "Error: Could not retrieve PR information for $PR_NUMBER." +# Get PR author. `--` keeps a leading dash in the argument from being read as a flag. +if ! PR_AUTHOR=$(gh pr view --json author -q .author.login -- "$PR_NUMBER"); then + echo "Error: Could not retrieve PR information for $PR_NUMBER." >&2 exit 1 fi diff --git a/.agent/skills/reference-compiler-cli/SKILL.md b/.agent/skills/reference-compiler-cli/SKILL.md index c26878c38c16..a969d556a275 100644 --- a/.agent/skills/reference-compiler-cli/SKILL.md +++ b/.agent/skills/reference-compiler-cli/SKILL.md @@ -49,12 +49,12 @@ The compiler is designed as a **lazy, incremental, and partial** compilation pip ### 4. Template Type Checking (`ngtsc/typecheck`) - **`TemplateTypeChecker`**: Generates "Type Check Blocks" (TCBs). A TCB is a block of TypeScript code that represents the template's logic in a way `tsc` can understand and check for errors. -- **`TypeCheckBlock`**: The actual generated code that validates bindings, events, and structural directives. +- **`generateTypeCheckBlock`** (from `@angular/compiler`, called by `TypeCheckFile` and `InlineTcbOp`): Generates TypeScript source for checking template bindings, events, directive usage, and host bindings. ### 5. Metadata & Scope (`ngtsc/metadata`, `ngtsc/scope`) - **`MetadataReader`**: Reads Angular metadata from source files (using `LocalMetadataRegistry`) and `.d.ts` files (using `DtsMetadataReader`). -- **`ScopeRegistry`**: Determines the "compilation scope" of a component (which directives/pipes are available to it), handling `NgModule` transitive exports and Standalone Component imports. +- **`ComponentScopeReader`**: Determines the "compilation scope" of a component (which directives/pipes are available to it), handling `NgModule` transitive exports and Standalone Component imports. ### 6. Emit & Transformation (`ngtsc/transform`) @@ -71,7 +71,7 @@ The compiler is designed as a **lazy, incremental, and partial** compilation pip - No cross-file resolution happens here (allowing for parallelism and caching). 3. **Resolution** (`resolve`): - `TraitCompiler` resolves traits. - - Components link their templates to specific Directives and Pipes (found via `ScopeRegistry`). + - Components link their templates to specific Directives and Pipes (found via `ComponentScopeReader`). - Import cycles are detected and handled (e.g., via "remote scoping"). 4. **Type Checking**: - `TemplateTypeChecker` creates TCBs for all components. @@ -87,5 +87,5 @@ The compiler is designed as a **lazy, incremental, and partial** compilation pip - `packages/compiler-cli/src/ngtsc/core/src/compiler.ts`: Core logic (`NgCompiler`). - `packages/compiler-cli/src/ngtsc/transform/src/trait.ts`: Trait state machine. - `packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts`: Component compilation logic. -- `packages/compiler-cli/src/ngtsc/typecheck/src/template_type_checker.ts`: Type checking logic. +- `packages/compiler-cli/src/ngtsc/typecheck/src/checker.ts`: Type checking logic (`TemplateTypeCheckerImpl`). - `packages/compiler-cli/src/ngtsc/transform/src/transform.ts`: AST transformation logic. diff --git a/.agent/skills/reference-core/SKILL.md b/.agent/skills/reference-core/SKILL.md index aecc3f9c801b..432202b11deb 100644 --- a/.agent/skills/reference-core/SKILL.md +++ b/.agent/skills/reference-core/SKILL.md @@ -31,13 +31,13 @@ The rendering engine (located in `packages/core/src/render3`) uses an **instruct - Directive/Component instances. - _Context_: `packages/core/src/render3/interfaces/view.ts` -- **TView (Template View)**: An array containing the _static structure_ of a view. It is shared across all instances (`LView`s) of the same component/template. It holds: +- **TView (Template View)**: An object describing the _static structure_ of a view; its parallel array is `TView.data`. It is shared across all instances (`LView`s) of the same component/template. It holds: - Property names for bindings. - Node relationship information. - Compiled directive definitions. - _Context_: `packages/core/src/render3/interfaces/view.ts` -- **Memory Layout**: `LView` and `TView` are parallel arrays. Index `i` in `LView` corresponds to metadata at index `i` in `TView`. +- **Memory Layout**: `LView` and `TView.data` are parallel arrays. Index `i` in `LView` corresponds to metadata at index `i` in `TView.data`. - `HEADER`: Fixed size, contains context (Parent, Host, etc.). - `DECLS`: Static nodes (elements, text, pipes). - `VARS`: Binding values. @@ -69,8 +69,8 @@ DI in Angular is hierarchical and split into two systems that interact: - **Dirty Checking**: Angular checks if values bound in templates have changed. - **Strategies**: - - `Default`: Checks everything. - - `OnPush`: Checks only if inputs change, events fire, or signals update. + - `OnPush`: The default. Checks when inputs change, events fire, template signals update, or the view is explicitly marked for checking. + - `Eager`: Checks whenever the change detection traversal reaches the component. (`Default` is the deprecated alias for `Eager`.) - **Signals**: The new reactivity primitive. Signals notify the scheduler when they change, potentially allowing for fine-grained updates (Zoneless). ## 5. Key Directories to Know @@ -81,7 +81,7 @@ DI in Angular is hierarchical and split into two systems that interact: - `src/di`: Dependency injection system. - `src/change_detection`: Change detection logic. - `src/zone`: Zone.js integration. -- `src/signal`: Signals implementation (if present in this version, otherwise likely in `primitives`). +- `src/render3/reactivity`: Signals implementation (`signal`, `computed`, `effect`), built on the reactive graph in `primitives/signals`. ## 6. Conventions & Gotchas diff --git a/.agent/skills/reference-signal-forms/SKILL.md b/.agent/skills/reference-signal-forms/SKILL.md index b373b2011748..752f9655f3c2 100644 --- a/.agent/skills/reference-signal-forms/SKILL.md +++ b/.agent/skills/reference-signal-forms/SKILL.md @@ -5,7 +5,7 @@ description: Explains the mental model and architecture of the code under `packa # Signal Forms Architecture -The `packages/forms/signals` directory contains an experimental, signal-based forms API for Angular. +The `packages/forms/signals` directory contains the signal-based forms API for Angular. This system differs significantly from the existing Reactive and Template-driven forms. ## Mental Model @@ -36,27 +36,27 @@ The central internal class representing a single field in the form graph. It agg - `structure`: Manages parent/child relationships and signal slicing. - `validationState`: Computes `valid`, `invalid`, `errors` signals. -- `nodeState`: Tracks `touched`, `dirty`, `pristine`. +- `nodeState`: Tracks `touched`, `dirty`, and derived logical state. - `metadataState`: Stores metadata like `min`, `max`, `required`. - `submitState`: Tracks submission status and server errors. -### 2. `ValidationState` (`src/field/validation.ts`) +### 2. `FieldValidationState` (`src/field/validation.ts`) -Manages the complexity of validation: +Implements `ValidationState` and manages the complexity of validation: - **Synchronous Errors**: Derived from schema rules. - **Asynchronous Errors**: Handled via signals, including 'pending' states. - **Tree Errors**: Errors that bubble up or are targeted at specific fields. - **Submission Errors**: Server-side errors injected imperatively via `submit()`. -### 3. `FormField` Directive (`src/directive/form_field_directive.ts`) +### 3. `FormField` Directive (`src/directive/form_field.ts`) The bridge between the `FieldNode` and the DOM. - Selector: `[formField]` - It supports: - **Native Elements**: ``, ``}, }); const fixture = initTest(FormControlComp); const control = new FormControl('old'); fixture.componentInstance.control = control; - fixture.detectChanges(); + await fixture.whenStable(); // model -> view const textarea = fixture.debugElement.query(By.css('textarea')); @@ -127,14 +128,14 @@ describe('value accessors', () => { expect(control.value).toEqual('new'); }); - it('should support ', () => { + it('should support ', async () => { TestBed.overrideComponent(FormControlComp, { set: {template: ``}, }); const fixture = initTest(FormControlComp); const control = new FormControl(true); fixture.componentInstance.control = control; - fixture.detectChanges(); + await fixture.whenStable(); // model -> view const input = fixture.debugElement.query(By.css('input')); @@ -148,11 +149,11 @@ describe('value accessors', () => { }); describe('should support ', () => { - it('with basic use case', () => { + it('with basic use case', async () => { const fixture = initTest(FormControlNumberInput); const control = new FormControl(10); fixture.componentInstance.control = control; - fixture.detectChanges(); + await fixture.whenStable(); // model -> view const input = fixture.debugElement.query(By.css('input')); @@ -165,11 +166,11 @@ describe('value accessors', () => { expect(control.value).toEqual(20); }); - it('when value is cleared in the UI', () => { + it('when value is cleared in the UI', async () => { const fixture = initTest(FormControlNumberInput); const control = new FormControl(10, Validators.required); fixture.componentInstance.control = control; - fixture.detectChanges(); + await fixture.whenStable(); const input = fixture.debugElement.query(By.css('input')); input.nativeElement.value = ''; @@ -185,11 +186,11 @@ describe('value accessors', () => { expect(control.value).toEqual(0); }); - it('should ignore the change event', () => { + it('should ignore the change event', async () => { const fixture = initTest(FormControlNumberInput); const control = new FormControl(); fixture.componentInstance.control = control; - fixture.detectChanges(); + await fixture.whenStable(); control.valueChanges.subscribe({ next: (value) => { @@ -202,11 +203,11 @@ describe('value accessors', () => { dispatchEvent(input.nativeElement, 'change'); }); - it('when value is cleared programmatically', () => { + it('when value is cleared programmatically', async () => { const fixture = initTest(FormControlNumberInput); const control = new FormControl(10); fixture.componentInstance.control = control; - fixture.detectChanges(); + await fixture.whenStable(); control.setValue(null); @@ -217,10 +218,10 @@ describe('value accessors', () => { describe('select controls', () => { describe('in reactive forms', () => { - it(`should support primitive values`, () => { + it(`should support primitive values`, async () => { if (isNode) return; const fixture = initTest(FormControlNameSelect); - fixture.detectChanges(); + await fixture.whenStable(); // model -> view const select = fixture.debugElement.query(By.css('select')); @@ -230,17 +231,17 @@ describe('value accessors', () => { select.nativeElement.value = 'NY'; dispatchEvent(select.nativeElement, 'change'); - fixture.detectChanges(); + await fixture.whenStable(); // view -> model expect(sfOption.nativeElement.selected).toBe(false); expect(fixture.componentInstance.form.value).toEqual({'city': 'NY'}); }); - it(`should support objects`, () => { + it(`should support objects`, async () => { if (isNode) return; const fixture = initTest(FormControlSelectNgValue); - fixture.detectChanges(); + await fixture.whenStable(); // model -> view const select = fixture.debugElement.query(By.css('select')); @@ -249,18 +250,18 @@ describe('value accessors', () => { expect(sfOption.nativeElement.selected).toBe(true); }); - it('should throw an error if compareWith is not a function', () => { + it('should throw an error if compareWith is not a function', async () => { const fixture = initTest(FormControlSelectWithCompareFn); fixture.componentInstance.compareFn = null!; - expect(() => fixture.detectChanges()).toThrowError( + await expectAsync(fixture.whenStable()).toBeRejectedWithError( /compareWith must be a function, but received null/, ); }); - it('should compare options using provided compareWith function', () => { + it('should compare options using provided compareWith function', async () => { if (isNode) return; const fixture = initTest(FormControlSelectWithCompareFn); - fixture.detectChanges(); + await fixture.whenStable(); const select = fixture.debugElement.query(By.css('select')); const sfOption = fixture.debugElement.query(By.css('option')); @@ -268,17 +269,17 @@ describe('value accessors', () => { expect(sfOption.nativeElement.selected).toBe(true); }); - it('should support re-assigning the options array with compareWith', () => { + it('should support re-assigning the options array with compareWith', async () => { if (isNode) return; const fixture = initTest(FormControlSelectWithCompareFn); - fixture.detectChanges(); + await fixture.whenStable(); // Option IDs start out as 0 and 1, so setting the select value to "1: Object" // will select the second option (NY). const select = fixture.debugElement.query(By.css('select')); select.nativeElement.value = '1: Object'; dispatchEvent(select.nativeElement, 'change'); - fixture.detectChanges(); + await fixture.whenStable(); expect(fixture.componentInstance.form.value).toEqual({city: {id: 2, name: 'NY'}}); @@ -287,7 +288,7 @@ describe('value accessors', () => { {id: 2, name: 'NY'}, ]; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); + await fixture.whenStable(); // Now that the options array has been re-assigned, new option instances will // be created by ngFor. These instances will have different option IDs, subsequent @@ -306,8 +307,7 @@ describe('value accessors', () => { const comp = fixture.componentInstance; comp.cities = [{'name': 'SF'}, {'name': 'NYC'}, {'name': 'Buffalo'}]; comp.selectedCity = comp.cities[1]; - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); const select = fixture.debugElement.query(By.css('select')); const nycOption = fixture.debugElement.queryAll(By.css('option'))[1]; @@ -318,8 +318,7 @@ describe('value accessors', () => { select.nativeElement.value = '2: Object'; dispatchEvent(select.nativeElement, 'change'); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); // view -> model expect(comp.selectedCity['name']).toEqual('Buffalo'); @@ -332,14 +331,12 @@ describe('value accessors', () => { comp.cities = [{'name': 'SF'}, {'name': 'NYC'}]; comp.selectedCity = comp.cities[1]; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); comp.cities.push({'name': 'Buffalo'}); comp.selectedCity = comp.cities[2]; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); const select = fixture.debugElement.query(By.css('select')); const buffalo = fixture.debugElement.queryAll(By.css('option'))[2]; @@ -353,16 +350,14 @@ describe('value accessors', () => { comp.cities = [{'name': 'SF'}, {'name': 'NYC'}]; comp.selectedCity = comp.cities[1]; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); const select = fixture.debugElement.query(By.css('select')); expect(select.nativeElement.value).toEqual('1: Object'); comp.cities.pop(); fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); expect(select.nativeElement.value).not.toEqual('1: Object'); }); @@ -374,12 +369,11 @@ describe('value accessors', () => { comp.cities = [{'name': 'SF'}, {'name': 'NYC'}, {'name': 'NYC'}]; comp.selectedCity = comp.cities[0]; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); + await fixture.whenStable(); comp.selectedCity = comp.cities[2]; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); const select = fixture.debugElement.query(By.css('select')); const secondNYC = fixture.debugElement.queryAll(By.css('option'))[2]; @@ -399,21 +393,19 @@ describe('value accessors', () => { select.nativeElement.value = '2: Object'; dispatchEvent(select.nativeElement, 'change'); await fixture.whenStable(); - await timeout(); expect(comp.selectedCity!['name']).toEqual('NYC'); select.nativeElement.value = '0: null'; dispatchEvent(select.nativeElement, 'change'); await fixture.whenStable(); - await timeout(); expect(comp.selectedCity).toEqual(null); }); - it('should throw an error when compareWith is not a function', () => { + it('should throw an error when compareWith is not a function', async () => { const fixture = initTest(NgModelSelectWithCustomCompareFnForm); const comp = fixture.componentInstance; comp.compareFn = null!; - expect(() => fixture.detectChanges()).toThrowError( + await expectAsync(fixture.whenStable()).toBeRejectedWithError( /compareWith must be a function, but received null/, ); }); @@ -427,8 +419,7 @@ describe('value accessors', () => { {id: 1, name: 'SF'}, {id: 2, name: 'LA'}, ]; - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); const select = fixture.debugElement.query(By.css('select')); const sfOption = fixture.debugElement.query(By.css('option')); @@ -445,15 +436,14 @@ describe('value accessors', () => { {id: 2, name: 'NY'}, ]; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); // Option IDs start out as 0 and 1, so setting the select value to "1: Object" // will select the second option (NY). const select = fixture.debugElement.query(By.css('select')); select.nativeElement.value = '1: Object'; dispatchEvent(select.nativeElement, 'change'); - fixture.detectChanges(); + await fixture.whenStable(); const model = fixture.debugElement.children[0].injector.get(NgModel); expect(model.value).toEqual({id: 2, name: 'NY'}); @@ -463,8 +453,7 @@ describe('value accessors', () => { {id: 2, name: 'NY'}, ]; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); // Now that the options array has been re-assigned, new option instances will // be created by ngFor. These instances will have different option IDs, subsequent @@ -479,10 +468,10 @@ describe('value accessors', () => { describe('select multiple controls', () => { describe('in reactive forms', () => { - it('should support primitive values', () => { + it('should support primitive values', async () => { if (isNode) return; const fixture = initTest(FormControlSelectMultiple); - fixture.detectChanges(); + await fixture.whenStable(); const select = fixture.debugElement.query(By.css('select')); const sfOption = fixture.debugElement.query(By.css('option')); @@ -490,10 +479,10 @@ describe('value accessors', () => { expect(sfOption.nativeElement.selected).toBe(true); }); - it('should support objects', () => { + it('should support objects', async () => { if (isNode) return; const fixture = initTest(FormControlSelectMultipleNgValue); - fixture.detectChanges(); + await fixture.whenStable(); const select = fixture.debugElement.query(By.css('select')); const sfOption = fixture.debugElement.query(By.css('option')); @@ -501,10 +490,10 @@ describe('value accessors', () => { expect(sfOption.nativeElement.selected).toBe(true); }); - it('should throw an error when compareWith is not a function', () => { + it('should throw an error when compareWith is not a function', async () => { const fixture = initTest(FormControlSelectMultipleWithCompareFn); fixture.componentInstance.compareFn = null!; - expect(() => fixture.detectChanges()).toThrowError( + await expectAsync(fixture.whenStable()).toBeRejectedWithError( /compareWith must be a function, but received null/, ); }); @@ -512,8 +501,7 @@ describe('value accessors', () => { it('should compare options using provided compareWith function', async () => { if (isNode) return; const fixture = initTest(FormControlSelectMultipleWithCompareFn); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); const select = fixture.debugElement.query(By.css('select')); const sfOption = fixture.debugElement.query(By.css('option')); @@ -532,22 +520,17 @@ describe('value accessors', () => { comp.cities = [{'name': 'SF'}, {'name': 'NYC'}, {'name': 'Buffalo'}]; }); - const detectChangesAndTick = async (): Promise => { - fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - await timeout(); - }; - const setSelectedCities = async (selectedCities: any): Promise => { comp.selectedCities = selectedCities; - await detectChangesAndTick(); + fixture.changeDetectorRef.markForCheck(); + await fixture.whenStable(); }; - const selectOptionViaUI = (valueString: string): void => { + const selectOptionViaUI = async (valueString: string): Promise => { const select = fixture.debugElement.query(By.css('select')); select.nativeElement.value = valueString; dispatchEvent(select.nativeElement, 'change'); - detectChangesAndTick(); + await fixture.whenStable(); }; const assertOptionElementSelectedState = (selectedStates: boolean[]): void => { @@ -561,7 +544,7 @@ describe('value accessors', () => { }; it('verify that native `selectedOptions` field is used while detecting the list of selected options', async () => { - if (isNode || !HTMLSelectElement.prototype.hasOwnProperty('selectedOptions')) return; + if (isNode || !Object.hasOwn(HTMLSelectElement.prototype, 'selectedOptions')) return; const spy = spyOnProperty( HTMLSelectElement.prototype, 'selectedOptions', @@ -569,7 +552,7 @@ describe('value accessors', () => { ).and.callThrough(); await setSelectedCities([]); - selectOptionViaUI('1: Object'); + await selectOptionViaUI('1: Object'); assertOptionElementSelectedState([false, true, false]); expect(spy).toHaveBeenCalled(); }); @@ -578,11 +561,12 @@ describe('value accessors', () => { if (isNode) return; await setSelectedCities([]); - selectOptionViaUI('1: Object'); + await selectOptionViaUI('1: Object'); assertOptionElementSelectedState([false, true, false]); comp.cities.push({'name': 'Chicago'}); - await detectChangesAndTick(); + fixture.changeDetectorRef.markForCheck(); + await fixture.whenStable(); assertOptionElementSelectedState([false, true, false, false]); }); @@ -591,21 +575,22 @@ describe('value accessors', () => { if (isNode) return; await setSelectedCities([]); - selectOptionViaUI('1: Object'); + await selectOptionViaUI('1: Object'); assertOptionElementSelectedState([false, true, false]); comp.cities.pop(); - await detectChangesAndTick(); + fixture.changeDetectorRef.markForCheck(); + await fixture.whenStable(); assertOptionElementSelectedState([false, true]); }); }); - it('should throw an error when compareWith is not a function', () => { + it('should throw an error when compareWith is not a function', async () => { const fixture = initTest(NgModelSelectMultipleWithCustomCompareFnForm); const comp = fixture.componentInstance; comp.compareFn = null!; - expect(() => fixture.detectChanges()).toThrowError( + await expectAsync(fixture.whenStable()).toBeRejectedWithError( /compareWith must be a function, but received null/, ); }); @@ -619,8 +604,7 @@ describe('value accessors', () => { {id: 2, name: 'LA'}, ]; comp.selectedCities = [comp.cities[0]]; - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); const select = fixture.debugElement.query(By.css('select')); const sfOption = fixture.debugElement.query(By.css('option')); @@ -631,14 +615,14 @@ describe('value accessors', () => { describe('should support ', () => { describe('in reactive forms', () => { - it('should support basic functionality', () => { + it('should support basic functionality', async () => { const fixture = initTest(FormControlRadioButtons); const form = new FormGroup({ 'food': new FormControl('fish'), 'drink': new FormControl('sprite'), }); fixture.componentInstance.form = form; - fixture.detectChanges(); + await fixture.whenStable(); // model -> view const inputs = fixture.debugElement.queryAll(By.css('input')); @@ -646,77 +630,93 @@ describe('value accessors', () => { expect(inputs[1].nativeElement.checked).toEqual(true); dispatchEvent(inputs[0].nativeElement, 'change'); - fixture.detectChanges(); + await fixture.whenStable(); // view -> model expect(form.get('food')!.value).toEqual('chicken'); expect(inputs[1].nativeElement.checked).toEqual(false); form.get('food')!.setValue('fish'); - fixture.detectChanges(); + await fixture.whenStable(); // programmatic change -> view expect(inputs[0].nativeElement.checked).toEqual(false); expect(inputs[1].nativeElement.checked).toEqual(true); }); - it('should support an initial undefined value', () => { + it('should update the checked state when a reused radio changes value', async () => { + const fixture = initTest(DynamicRadioForm); + await fixture.whenStable(); + + expect(getRadioCheckedStates(fixture)).toEqual([false, true]); + + fixture.componentInstance.form.patchValue({answer: 'selected'}); + fixture.componentInstance.options.set([ + {id: 'new', value: 'other'}, + {id: 'shared', value: 'selected'}, + ]); + await fixture.whenStable(); + + expect(getRadioCheckedStates(fixture)).toEqual([false, true]); + }); + + it('should support an initial undefined value', async () => { const fixture = initTest(FormControlRadioButtons); const form = new FormGroup({'food': new FormControl(), 'drink': new FormControl()}); fixture.componentInstance.form = form; - fixture.detectChanges(); + await fixture.whenStable(); const inputs = fixture.debugElement.queryAll(By.css('input')); expect(inputs[0].nativeElement.checked).toEqual(false); expect(inputs[1].nativeElement.checked).toEqual(false); }); - it('should reset properly', () => { + it('should reset properly', async () => { const fixture = initTest(FormControlRadioButtons); const form = new FormGroup({ 'food': new FormControl('fish'), 'drink': new FormControl('sprite'), }); fixture.componentInstance.form = form; - fixture.detectChanges(); + await fixture.whenStable(); form.reset(); - fixture.detectChanges(); + await fixture.whenStable(); const inputs = fixture.debugElement.queryAll(By.css('input')); expect(inputs[0].nativeElement.checked).toEqual(false); expect(inputs[1].nativeElement.checked).toEqual(false); }); - it('should properly set value to null and undefined', () => { + it('should properly set value to null and undefined', async () => { const fixture = initTest(FormControlRadioButtons); const form: FormGroup = new FormGroup({ 'food': new FormControl('chicken'), 'drink': new FormControl('sprite'), }); fixture.componentInstance.form = form; - fixture.detectChanges(); + await fixture.whenStable(); form.get('food')!.setValue(null); - fixture.detectChanges(); + await fixture.whenStable(); const inputs = fixture.debugElement.queryAll(By.css('input')); expect(inputs[0].nativeElement.checked).toEqual(false); form.get('food')!.setValue('chicken'); - fixture.detectChanges(); + await fixture.whenStable(); form.get('food')!.setValue(undefined); - fixture.detectChanges(); + await fixture.whenStable(); expect(inputs[0].nativeElement.checked).toEqual(false); }); - it('should use formControlName to group radio buttons when name is absent', () => { + it('should use formControlName to group radio buttons when name is absent', async () => { const fixture = initTest(FormControlRadioButtons); const foodCtrl = new FormControl('fish'); const drinkCtrl = new FormControl('sprite'); fixture.componentInstance.form = new FormGroup({'food': foodCtrl, 'drink': drinkCtrl}); - fixture.detectChanges(); + await fixture.whenStable(); const inputs = fixture.debugElement.queryAll(By.css('input')); expect(inputs[0].nativeElement.checked).toEqual(false); @@ -726,7 +726,7 @@ describe('value accessors', () => { dispatchEvent(inputs[0].nativeElement, 'change'); inputs[0].nativeElement.checked = true; - fixture.detectChanges(); + await fixture.whenStable(); const value = fixture.componentInstance.form.value; expect(value.food).toEqual('chicken'); @@ -735,7 +735,7 @@ describe('value accessors', () => { expect(inputs[3].nativeElement.checked).toEqual(true); drinkCtrl.setValue('cola'); - fixture.detectChanges(); + await fixture.whenStable(); expect(inputs[0].nativeElement.checked).toEqual(true); expect(inputs[1].nativeElement.checked).toEqual(false); @@ -743,7 +743,7 @@ describe('value accessors', () => { expect(inputs[3].nativeElement.checked).toEqual(false); }); - it('should support removing controls from ', () => { + it('should support removing controls from ', async () => { const fixture = initTest(FormControlRadioButtons); const showRadio = new FormControl('yes'); const form: FormGroup = new FormGroup({ @@ -757,16 +757,16 @@ describe('value accessors', () => { ? form.addControl('food', new FormControl('fish')) : form.removeControl('food'); }); - fixture.detectChanges(); + await fixture.whenStable(); const input = fixture.debugElement.query(By.css('[value="no"]')); dispatchEvent(input.nativeElement, 'change'); - fixture.detectChanges(); + await fixture.whenStable(); expect(form.value).toEqual({drink: 'sprite'}); }); - it('should differentiate controls on different levels with the same name', () => { + it('should differentiate controls on different levels with the same name', async () => { TestBed.overrideComponent(FormControlRadioButtons, { set: { template: ` @@ -787,7 +787,7 @@ describe('value accessors', () => { nested: new FormGroup({food: new FormControl('fish')}), }); fixture.componentInstance.form = form; - fixture.detectChanges(); + await fixture.whenStable(); // model -> view const inputs = fixture.debugElement.queryAll(By.css('input')); @@ -797,7 +797,7 @@ describe('value accessors', () => { expect(inputs[3].nativeElement.checked).toEqual(true); dispatchEvent(inputs[0].nativeElement, 'change'); - fixture.detectChanges(); + await fixture.whenStable(); // view -> model expect(form.get('food')!.value).toEqual('chicken'); @@ -808,11 +808,11 @@ describe('value accessors', () => { expect(inputs[3].nativeElement.checked).toEqual(true); }); - it('should disable all radio buttons when disable() is called', () => { + it('should disable all radio buttons when disable() is called', async () => { const fixture = initTest(FormControlRadioButtons); const form = new FormGroup({food: new FormControl('fish'), drink: new FormControl('cola')}); fixture.componentInstance.form = form; - fixture.detectChanges(); + await fixture.whenStable(); const inputs = fixture.debugElement.queryAll(By.css('input')); expect(inputs[0].nativeElement.disabled).toEqual(false); @@ -839,14 +839,14 @@ describe('value accessors', () => { expect(inputs[3].nativeElement.disabled).toEqual(false); }); - it('should disable all radio buttons when initially disabled', () => { + it('should disable all radio buttons when initially disabled', async () => { const fixture = initTest(FormControlRadioButtons); const form = new FormGroup({ food: new FormControl({value: 'fish', disabled: true}), drink: new FormControl('cola'), }); fixture.componentInstance.form = form; - fixture.detectChanges(); + await fixture.whenStable(); const inputs = fixture.debugElement.queryAll(By.css('input')); expect(inputs[0].nativeElement.disabled).toEqual(true); @@ -855,21 +855,22 @@ describe('value accessors', () => { expect(inputs[3].nativeElement.disabled).toEqual(false); }); - it('should work with reusing controls', () => { + it('should work with reusing controls', async () => { const fixture = initTest(FormControlRadioButtons); const food = new FormControl('chicken'); fixture.componentInstance.form = new FormGroup({ 'food': food, 'drink': new FormControl(''), }); - fixture.detectChanges(); + await fixture.whenStable(); const newForm = new FormGroup({'food': food, 'drink': new FormControl('')}); fixture.componentInstance.form = newForm; - fixture.detectChanges(); + fixture.changeDetectorRef.markForCheck(); + await fixture.whenStable(); newForm.setValue({food: 'fish', drink: ''}); - fixture.detectChanges(); + await fixture.whenStable(); const inputs = fixture.debugElement.queryAll(By.css('input')); expect(inputs[0].nativeElement.checked).toBe(false); expect(inputs[1].nativeElement.checked).toBe(true); @@ -880,8 +881,7 @@ describe('value accessors', () => { it('should support basic functionality', async () => { const fixture = initTest(NgModelRadioForm); fixture.componentInstance.food = 'fish'; - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); // model -> view const inputs = fixture.debugElement.queryAll(By.css('input')); @@ -889,7 +889,7 @@ describe('value accessors', () => { expect(inputs[1].nativeElement.checked).toEqual(true); dispatchEvent(inputs[0].nativeElement, 'change'); - await timeout(); + await fixture.whenStable(); // view -> model expect(fixture.componentInstance.food).toEqual('chicken'); @@ -900,8 +900,7 @@ describe('value accessors', () => { const fixture = initTest(NgModelRadioForm); fixture.componentInstance.food = 'fish'; fixture.componentInstance.drink = 'sprite'; - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); const inputs = fixture.debugElement.queryAll(By.css('input')); expect(inputs[0].nativeElement.checked).toEqual(false); @@ -910,7 +909,7 @@ describe('value accessors', () => { expect(inputs[3].nativeElement.checked).toEqual(true); dispatchEvent(inputs[0].nativeElement, 'change'); - await timeout(); + await fixture.whenStable(); expect(fixture.componentInstance.food).toEqual('chicken'); expect(fixture.componentInstance.drink).toEqual('sprite'); @@ -921,8 +920,7 @@ describe('value accessors', () => { it('should support initial undefined value', async () => { const fixture = initTest(NgModelRadioForm); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); const inputs = fixture.debugElement.queryAll(By.css('input')); expect(inputs[0].nativeElement.checked).toEqual(false); @@ -934,13 +932,11 @@ describe('value accessors', () => { it('should support resetting properly', async () => { const fixture = initTest(NgModelRadioForm); fixture.componentInstance.food = 'chicken'; - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); const form = fixture.debugElement.query(By.css('form')); dispatchEvent(form.nativeElement, 'reset'); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); const inputs = fixture.debugElement.queryAll(By.css('input')); expect(inputs[0].nativeElement.checked).toEqual(false); @@ -951,13 +947,11 @@ describe('value accessors', () => { const fixture = initTest(NgModelRadioForm); fixture.componentInstance.food = 'chicken'; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); fixture.componentInstance.food = null!; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); const inputs = fixture.debugElement.queryAll(By.css('input')); expect(inputs[0].nativeElement.checked).toEqual(false); @@ -965,13 +959,11 @@ describe('value accessors', () => { fixture.componentInstance.food = 'chicken'; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); fixture.componentInstance.food = undefined!; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); expect(inputs[0].nativeElement.checked).toEqual(false); expect(inputs[1].nativeElement.checked).toEqual(false); }); @@ -979,12 +971,11 @@ describe('value accessors', () => { it('should disable radio controls properly with programmatic call', async () => { const fixture = initTest(NgModelRadioForm); fixture.componentInstance.food = 'fish'; - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); const form = fixture.debugElement.children[0].injector.get(NgForm); form.control.get('food')!.disable(); - await timeout(); + await fixture.whenStable(); const inputs = fixture.debugElement.queryAll(By.css('input')); expect(inputs[0].nativeElement.disabled).toBe(true); @@ -993,7 +984,7 @@ describe('value accessors', () => { expect(inputs[3].nativeElement.disabled).toBe(false); form.control.disable(); - await timeout(); + await fixture.whenStable(); expect(inputs[0].nativeElement.disabled).toBe(true); expect(inputs[1].nativeElement.disabled).toBe(true); @@ -1001,7 +992,7 @@ describe('value accessors', () => { expect(inputs[3].nativeElement.disabled).toBe(true); form.control.enable(); - await timeout(); + await fixture.whenStable(); expect(inputs[0].nativeElement.disabled).toBe(false); expect(inputs[1].nativeElement.disabled).toBe(false); @@ -1013,11 +1004,11 @@ describe('value accessors', () => { describe('should support ', () => { describe('in reactive forms', () => { - it('with basic use case', () => { + it('with basic use case', async () => { const fixture = initTest(FormControlRangeInput); const control = new FormControl(10); fixture.componentInstance.control = control; - fixture.detectChanges(); + await fixture.whenStable(); // model -> view const input = fixture.debugElement.query(By.css('input')); @@ -1030,11 +1021,11 @@ describe('value accessors', () => { expect(control.value).toEqual(20); }); - it('when value is cleared in the UI', () => { + it('when value is cleared in the UI', async () => { const fixture = initTest(FormControlNumberInput); const control = new FormControl(10, Validators.required); fixture.componentInstance.control = control; - fixture.detectChanges(); + await fixture.whenStable(); const input = fixture.debugElement.query(By.css('input')); input.nativeElement.value = ''; @@ -1050,11 +1041,11 @@ describe('value accessors', () => { expect(control.value).toEqual(0); }); - it('when value is cleared programmatically', () => { + it('when value is cleared programmatically', async () => { const fixture = initTest(FormControlNumberInput); const control = new FormControl(10); fixture.componentInstance.control = control; - fixture.detectChanges(); + await fixture.whenStable(); control.setValue(null); @@ -1065,10 +1056,10 @@ describe('value accessors', () => { describe('select controls', () => { describe('in reactive forms', () => { - it(`should support primitive values`, () => { + it(`should support primitive values`, async () => { if (isNode) return; const fixture = initTest(FormControlNameSelect); - fixture.detectChanges(); + await fixture.whenStable(); // model -> view const select = fixture.debugElement.query(By.css('select')); @@ -1078,17 +1069,17 @@ describe('value accessors', () => { select.nativeElement.value = 'NY'; dispatchEvent(select.nativeElement, 'change'); - fixture.detectChanges(); + await fixture.whenStable(); // view -> model expect(sfOption.nativeElement.selected).toBe(false); expect(fixture.componentInstance.form.value).toEqual({'city': 'NY'}); }); - it(`should support objects`, () => { + it(`should support objects`, async () => { if (isNode) return; const fixture = initTest(FormControlSelectNgValue); - fixture.detectChanges(); + await fixture.whenStable(); // model -> view const select = fixture.debugElement.query(By.css('select')); @@ -1097,18 +1088,18 @@ describe('value accessors', () => { expect(sfOption.nativeElement.selected).toBe(true); }); - it('should throw an error if compareWith is not a function', () => { + it('should throw an error if compareWith is not a function', async () => { const fixture = initTest(FormControlSelectWithCompareFn); fixture.componentInstance.compareFn = null!; - expect(() => fixture.detectChanges()).toThrowError( + await expectAsync(fixture.whenStable()).toBeRejectedWithError( /compareWith must be a function, but received null/, ); }); - it('should compare options using provided compareWith function', () => { + it('should compare options using provided compareWith function', async () => { if (isNode) return; const fixture = initTest(FormControlSelectWithCompareFn); - fixture.detectChanges(); + await fixture.whenStable(); const select = fixture.debugElement.query(By.css('select')); const sfOption = fixture.debugElement.query(By.css('option')); @@ -1116,10 +1107,10 @@ describe('value accessors', () => { expect(sfOption.nativeElement.selected).toBe(true); }); - it('should support re-assigning the options array with compareWith', () => { + it('should support re-assigning the options array with compareWith', async () => { if (isNode) return; const fixture = initTest(FormControlSelectWithCompareFn); - fixture.detectChanges(); + await fixture.whenStable(); // Option IDs start out as 0 and 1, so setting the select value to "1: Object" // will select the second option (NY). @@ -1128,7 +1119,7 @@ describe('value accessors', () => { select.nativeElement.value = '1: Object'; dispatchEvent(select.nativeElement, 'change'); - fixture.detectChanges(); + await fixture.whenStable(); expect(fixture.componentInstance.form.value).toEqual({city: {id: 2, name: 'NY'}}); @@ -1137,7 +1128,7 @@ describe('value accessors', () => { {id: 2, name: 'NY'}, ]; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); + await fixture.whenStable(); // Now that the options array has been re-assigned, new option instances will // be created by ngFor. These instances will have different option IDs, subsequent @@ -1148,10 +1139,10 @@ describe('value accessors', () => { expect(nyOption.nativeElement.selected).toBe(true); }); - it('should support re-assigning the options array with compareWith and trackBy', () => { + it('should support re-assigning the options array with compareWith and trackBy', async () => { if (isNode) return; const fixture = initTest(FormControlSelectWithCompareTrackByFn); - fixture.detectChanges(); + await fixture.whenStable(); // Option IDs start out as 0 and 1, so setting the select value to "1: Object" // will select the second option (NY). @@ -1160,7 +1151,7 @@ describe('value accessors', () => { select.nativeElement.value = '1: Object'; dispatchEvent(select.nativeElement, 'change'); - fixture.detectChanges(); + await fixture.whenStable(); expect(fixture.componentInstance.form.value).toEqual({city: {id: 2, name: 'NY'}}); @@ -1169,7 +1160,7 @@ describe('value accessors', () => { {id: 4, name: 'BXL'}, ]; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); + await fixture.whenStable(); // using trackBy, instances can be re-used, the option IDs stays the same but their // (ng)value can change @@ -1185,10 +1176,10 @@ describe('value accessors', () => { expect(fixture.componentInstance.form.value).toEqual({city: {id: 2, name: 'NY'}}); }); - it('should keep current value when selected option is removed/replaced', () => { + it('should keep current value when selected option is removed/replaced', async () => { if (isNode) return; const fixture = initTest(FormControlSelectWithCompareFn); - fixture.detectChanges(); + await fixture.whenStable(); // Option IDs start out as 0 and 1, so setting the select value to "1: Object" // will select the second option (NY). @@ -1197,7 +1188,7 @@ describe('value accessors', () => { select.nativeElement.value = '1: Object'; dispatchEvent(select.nativeElement, 'change'); - fixture.detectChanges(); + await fixture.whenStable(); expect(fixture.componentInstance.form.value).toEqual({city: {id: 2, name: 'NY'}}); @@ -1206,7 +1197,7 @@ describe('value accessors', () => { {id: 3, name: 'LA'}, ]; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); + await fixture.whenStable(); // Now that the options array has been re-assigned, new option instances will // be created by ngFor. These instances will have different option IDs, subsequent @@ -1227,24 +1218,24 @@ describe('value accessors', () => { ); }); - it('should call compareWith once for each added option until a match is found', () => { + it('should call compareWith once for each added option until a match is found', async () => { // see issue #41330 if (isNode) return; const fixture = initTest(FormControlSelectWithComparePerfFn); - fixture.detectChanges(); + await fixture.whenStable(); // compareWith should only be called once since first city is selected expect(fixture.componentInstance.compareFnCalls).toEqual(1); }); - it('should not call compareWith for removed options', () => { + it('should not call compareWith for removed options', async () => { if (isNode) return; const fixture = initTest(FormControlSelectWithComparePerfFn); - fixture.detectChanges(); + await fixture.whenStable(); fixture.componentInstance.compareFnCalls = 0; fixture.componentInstance.cities.splice(2, 2); fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); + await fixture.whenStable(); // compareWith should only be called once since first city is still selected expect(fixture.componentInstance.compareFnCalls).toBe(1); @@ -1258,8 +1249,7 @@ describe('value accessors', () => { const comp = fixture.componentInstance; comp.cities = [{'name': 'SF'}, {'name': 'NYC'}, {'name': 'Buffalo'}]; comp.selectedCity = comp.cities[1]; - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); const select = fixture.debugElement.query(By.css('select')); const nycOption = fixture.debugElement.queryAll(By.css('option'))[1]; @@ -1270,8 +1260,7 @@ describe('value accessors', () => { select.nativeElement.value = '2: Object'; dispatchEvent(select.nativeElement, 'change'); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); // view -> model expect(comp.selectedCity['name']).toEqual('Buffalo'); @@ -1284,14 +1273,12 @@ describe('value accessors', () => { comp.cities = [{'name': 'SF'}, {'name': 'NYC'}]; comp.selectedCity = comp.cities[1]; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); comp.cities.push({'name': 'Buffalo'}); comp.selectedCity = comp.cities[2]; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); const select = fixture.debugElement.query(By.css('select')); const buffalo = fixture.debugElement.queryAll(By.css('option'))[2]; @@ -1304,13 +1291,11 @@ describe('value accessors', () => { if (isNode) return; const fixture = initTest(NgModelSelectForm); const comp = fixture.componentInstance; - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); comp.cities.push({name: 'Minneapolis'}); fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); const select = fixture.debugElement.query(By.css('select')); expect(select.nativeElement.selectedIndex).toEqual(-1); @@ -1323,8 +1308,7 @@ describe('value accessors', () => { const fixture = initTest(NgModelSelectWithPlaceholderForm); const comp = fixture.componentInstance; comp.cities = [{'name': 'SF'}, {'name': 'NYC'}]; - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); const placeholder = fixture.debugElement.queryAll(By.css('option'))[0]; expect(placeholder.nativeElement.selected).toBe(true); @@ -1337,16 +1321,14 @@ describe('value accessors', () => { comp.cities = [{'name': 'SF'}, {'name': 'NYC'}]; comp.selectedCity = comp.cities[1]; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); const select = fixture.debugElement.query(By.css('select')); expect(select.nativeElement.value).toEqual('1: Object'); comp.cities.pop(); fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); // no option should be selected, since ngModel doesn't match anything in cities array expect(select.nativeElement.value).not.toEqual('1: Object'); @@ -1373,7 +1355,6 @@ describe('value accessors', () => { const comp = fixture.componentInstance; comp.cities = [{'name': 'SF'}, {'name': 'NYC'}]; comp.selectedCity = comp.cities[1]; - fixture.autoDetectChanges(); await fixture.whenStable(); const select = fixture.debugElement.query(By.css('select')); @@ -1395,12 +1376,11 @@ describe('value accessors', () => { comp.cities = [{'name': 'SF'}, {'name': 'NYC'}, {'name': 'NYC'}]; comp.selectedCity = comp.cities[0]; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); + await fixture.whenStable(); comp.selectedCity = comp.cities[2]; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); const select = fixture.debugElement.query(By.css('select')); const secondNYC = fixture.debugElement.queryAll(By.css('option'))[2]; @@ -1414,30 +1394,28 @@ describe('value accessors', () => { comp.cities = [{'name': 'SF'}, {'name': 'NYC'}]; comp.selectedCity = null; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); + await fixture.whenStable(); const select = fixture.debugElement.query(By.css('select')); select.nativeElement.value = '2: Object'; dispatchEvent(select.nativeElement, 'change'); fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); expect(comp.selectedCity!['name']).toEqual('NYC'); select.nativeElement.value = '0: null'; dispatchEvent(select.nativeElement, 'change'); fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); expect(comp.selectedCity).toEqual(null); }); - it('should throw an error when compareWith is not a function', () => { + it('should throw an error when compareWith is not a function', async () => { const fixture = initTest(NgModelSelectWithCustomCompareFnForm); const comp = fixture.componentInstance; comp.compareFn = null!; - expect(() => fixture.detectChanges()).toThrowError( + await expectAsync(fixture.whenStable()).toBeRejectedWithError( /compareWith must be a function, but received null/, ); }); @@ -1451,8 +1429,7 @@ describe('value accessors', () => { {id: 1, name: 'SF'}, {id: 2, name: 'LA'}, ]; - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); const select = fixture.debugElement.query(By.css('select')); const sfOption = fixture.debugElement.query(By.css('option')); @@ -1469,15 +1446,14 @@ describe('value accessors', () => { {id: 2, name: 'NY'}, ]; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); // Option IDs start out as 0 and 1, so setting the select value to "1: Object" // will select the second option (NY). const select = fixture.debugElement.query(By.css('select')); select.nativeElement.value = '1: Object'; dispatchEvent(select.nativeElement, 'change'); - fixture.detectChanges(); + await fixture.whenStable(); const model = fixture.debugElement.children[0].injector.get(NgModel); expect(model.value).toEqual({id: 2, name: 'NY'}); @@ -1487,8 +1463,7 @@ describe('value accessors', () => { {id: 2, name: 'NY'}, ]; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - await timeout(); + await fixture.whenStable(); // Now that the options array has been re-assigned, new option instances will // be created by ngFor. These instances will have different option IDs, subsequent @@ -1504,11 +1479,11 @@ describe('value accessors', () => { describe('custom value accessors', () => { describe('in reactive forms', () => { - it('should support basic functionality', () => { + it('should support basic functionality', async () => { const fixture = initTest(WrappedValueForm, WrappedValue); const form = new FormGroup({'login': new FormControl('aa')}); fixture.componentInstance.form = form; - fixture.detectChanges(); + await fixture.whenStable(); // model -> view const input = fixture.debugElement.query(By.css('input')); @@ -1526,10 +1501,10 @@ describe('value accessors', () => { expect(form.get('login')!.errors).toEqual(null); }); - it("should support non builtin input elements that fire a change event without a 'target' property", () => { + it("should support non builtin input elements that fire a change event without a 'target' property", async () => { const fixture = initTest(MyInputForm, MyInput); fixture.componentInstance.form = new FormGroup({'login': new FormControl('aa')}); - fixture.detectChanges(); + await fixture.whenStable(); const input = fixture.debugElement.query(By.css('my-input')); expect(input.componentInstance.value).toEqual('!aa!'); @@ -1541,23 +1516,23 @@ describe('value accessors', () => { input.componentInstance.dispatchChangeEvent(); }); - it('should support custom accessors without setDisabledState - formControlName', () => { + it('should support custom accessors without setDisabledState - formControlName', async () => { const fixture = initTest(WrappedValueForm, WrappedValue); fixture.componentInstance.form = new FormGroup({ 'login': new FormControl({value: 'aa', disabled: true}), }); - fixture.detectChanges(); + await fixture.whenStable(); expect(fixture.componentInstance.form.status).toEqual('DISABLED'); expect(fixture.componentInstance.form.get('login')!.status).toEqual('DISABLED'); }); - it('should support custom accessors without setDisabledState - formControlDirective', () => { + it('should support custom accessors without setDisabledState - formControlDirective', async () => { TestBed.overrideComponent(FormControlComp, { set: {template: ``}, }); const fixture = initTest(FormControlComp); fixture.componentInstance.control = new FormControl({value: 'aa', disabled: true}); - fixture.detectChanges(); + await fixture.whenStable(); expect(fixture.componentInstance.control.status).toEqual('DISABLED'); }); @@ -1568,11 +1543,11 @@ describe('value accessors', () => { fixture = initTest(CvaWithDisabledStateForm, CvaWithDisabledState); }); - it('sets the disabled state when the control is initially disabled', () => { + it('sets the disabled state when the control is initially disabled', async () => { fixture.componentInstance.form = new FormGroup({ 'login': new FormControl({value: 'aa', disabled: true}), }); - fixture.detectChanges(); + await fixture.whenStable(); expect(fixture.componentInstance.form.status).toEqual('DISABLED'); expect(fixture.componentInstance.form.get('login')!.status).toEqual('DISABLED'); @@ -1582,11 +1557,11 @@ describe('value accessors', () => { ).toContain('DISABLED'); }); - it('sets the enabled state when the control is initially enabled', () => { + it('sets the enabled state when the control is initially enabled', async () => { fixture.componentInstance.form = new FormGroup({ 'login': new FormControl({value: 'aa', disabled: false}), }); - fixture.detectChanges(); + await fixture.whenStable(); expect(fixture.componentInstance.form.status).toEqual('VALID'); expect(fixture.componentInstance.form.get('login')!.status).toEqual('VALID'); @@ -1597,10 +1572,10 @@ describe('value accessors', () => { }); }); - it('should populate control in ngOnInit when injecting NgControl', () => { + it('should populate control in ngOnInit when injecting NgControl', async () => { const fixture = initTest(MyInputForm, MyInput); fixture.componentInstance.form = new FormGroup({'login': new FormControl('aa')}); - fixture.detectChanges(); + await fixture.whenStable(); expect(fixture.componentInstance.myInput!.control).toBeDefined(); expect(fixture.componentInstance.myInput!.control).toEqual( @@ -1613,9 +1588,6 @@ describe('value accessors', () => { it('should support standard writing to view and model', async () => { const fixture = initTest(NgModelCustomWrapper, NgModelCustomComp); fixture.componentInstance.name = 'Nancy'; - fixture.detectChanges(); - await fixture.whenStable(); - fixture.detectChanges(); await fixture.whenStable(); // model -> view @@ -1624,7 +1596,7 @@ describe('value accessors', () => { customInput.nativeElement.value = 'Carson'; dispatchEvent(customInput.nativeElement, 'input'); - fixture.detectChanges(); + await fixture.whenStable(); // view -> model expect(fixture.componentInstance.name).toEqual('Carson'); @@ -1636,7 +1608,6 @@ describe('value accessors', () => { @Component({ selector: 'parent', template: '', - changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, }) class Parent { @@ -1647,7 +1618,7 @@ describe('value accessors', () => { setTimeoutAndChangeValue(): void { setTimeout(() => { this.value = 'Carson'; - this.ref.detectChanges(); + this.ref.markForCheck(); }, 50); } } @@ -1672,10 +1643,6 @@ describe('value accessors', () => { const fixture = initTest(Parent, Child); fixture.componentInstance.value = 'Nancy'; - fixture.detectChanges(); - - await fixture.whenStable(); - fixture.detectChanges(); await fixture.whenStable(); const child = fixture.debugElement.query(By.css('child')); @@ -1687,7 +1654,6 @@ describe('value accessors', () => { await timeout(50); - fixture.detectChanges(); await fixture.whenStable(); expect(child.nativeElement.innerHTML).toEqual('Value: Carson'); @@ -1697,6 +1663,8 @@ describe('value accessors', () => { }); describe('value accessors in reactive forms with custom options', () => { + useAutoTick(); + function initTest(component: Type, ...directives: Type[]): ComponentFixture { TestBed.configureTestingModule({ declarations: [component, ...directives], @@ -1714,11 +1682,11 @@ describe('value accessors in reactive forms with custom options', () => { fixture = initTest(CvaWithDisabledStateForm, CvaWithDisabledState); }); - it('does not set the enabled state when the control is initially enabled', () => { + it('does not set the enabled state when the control is initially enabled', async () => { fixture.componentInstance.form = new FormGroup({ 'login': new FormControl({value: 'aa', disabled: false}), }); - fixture.detectChanges(); + await fixture.whenStable(); expect(fixture.componentInstance.form.status).toEqual('VALID'); expect(fixture.componentInstance.form.get('login')!.status).toEqual('VALID'); @@ -2047,6 +2015,41 @@ export class FormControlRadioButtons { showRadio = new FormControl('yes'); } +interface RadioOption { + readonly id: string; + readonly value: string; +} + +@Component({ + selector: 'dynamic-radio-form', + template: ` +
+ @for (option of options(); track option.id) { + + } +
+ `, + standalone: false, + changeDetection: ChangeDetectionStrategy.Eager, +}) +class DynamicRadioForm { + readonly form = new FormGroup({ + answer: new FormControl('selected', {nonNullable: true}), + }); + readonly options = signal>([ + {id: 'shared', value: 'other'}, + {id: 'old', value: 'selected'}, + ]); +} + +function getRadioCheckedStates(fixture: ComponentFixture): boolean[] { + const element = fixture.nativeElement as HTMLElement; + + return Array.from(element.querySelectorAll('input')).map( + (input) => input.checked, + ); +} + @Component({ selector: 'ng-model-radio-form', template: ` diff --git a/packages/language-service/src/attribute_completions.ts b/packages/language-service/src/attribute_completions.ts index b402b18c99ce..fee62fc19241 100644 --- a/packages/language-service/src/attribute_completions.ts +++ b/packages/language-service/src/attribute_completions.ts @@ -225,8 +225,7 @@ export function buildAttributeCompletionTable( // Use the `ElementSymbol` or `TemplateSymbol` to iterate over directives present on the node, and // their inputs/outputs. These have the highest priority of completion results. const symbol: ElementSymbol | TemplateSymbol = checker.getSymbolOfNode(element, component) as - | ElementSymbol - | TemplateSymbol; + ElementSymbol | TemplateSymbol; const presentDirectives = new Set(); if (symbol !== null) { // An `ElementSymbol` was available. This means inputs and outputs for directives on the @@ -248,7 +247,10 @@ export function buildAttributeCompletionTable( let propertyName: string; if (dirSymbol.matchSource === MatchSource.HostDirective) { - if (!dirSymbol.exposedInputs?.hasOwnProperty(bindingPropertyName)) { + if ( + !dirSymbol.exposedInputs || + !Object.hasOwn(dirSymbol.exposedInputs, bindingPropertyName) + ) { continue; } propertyName = dirSymbol.exposedInputs[bindingPropertyName]; @@ -273,7 +275,10 @@ export function buildAttributeCompletionTable( let propertyName: string; if (dirSymbol.matchSource === MatchSource.HostDirective) { - if (!dirSymbol.exposedOutputs?.hasOwnProperty(bindingPropertyName)) { + if ( + !dirSymbol.exposedOutputs || + !Object.hasOwn(dirSymbol.exposedOutputs, bindingPropertyName) + ) { continue; } propertyName = dirSymbol.exposedOutputs[bindingPropertyName]; diff --git a/packages/language-service/src/codefixes/fix_missing_import.ts b/packages/language-service/src/codefixes/fix_missing_import.ts index 09d347127320..a03cbb8a7f25 100644 --- a/packages/language-service/src/codefixes/fix_missing_import.ts +++ b/packages/language-service/src/codefixes/fix_missing_import.ts @@ -95,6 +95,7 @@ function getCodeActions({typeCheckInfo, start, compiler, tsLs, preferences}: Cod currMatch, tsLs, preferences.includeCompletionsForModuleExports, + preferences, ) ?? []; codeActions.push( diff --git a/packages/language-service/src/completions.ts b/packages/language-service/src/completions.ts index 2d8a4a4f23eb..97f72d6fdfae 100644 --- a/packages/language-service/src/completions.ts +++ b/packages/language-service/src/completions.ts @@ -233,7 +233,15 @@ export class CompletionBuilder { options: ts.GetCompletionsAtPositionOptions | undefined, ): ts.WithMetadata | undefined { const blocksWithParens = ['if', 'else if', 'for', 'switch', 'case', 'defer']; - const blocksWithoutParens = ['else', 'empty', 'placeholder', 'error', 'loading', 'default']; + const blocksWithoutParens = [ + 'else', + 'empty', + 'placeholder', + 'error', + 'loading', + 'default', + 'boundary', + ]; // Determine whether to provide a snippet, which includes parens and curly braces. // If the block has any expressions or a body, don't provide a snippet as the completion. @@ -865,6 +873,7 @@ export class CompletionBuilder { directive, this.tsLS, options?.includeCompletionsWithInsertText, + options, ) : undefined; @@ -1325,6 +1334,7 @@ export class CompletionBuilder { directive, this.tsLS, preferences?.includeCompletionsWithInsertText, + preferences, ) : undefined; diff --git a/packages/language-service/src/document_symbols.ts b/packages/language-service/src/document_symbols.ts index 4ffa36e35c23..9292ed06e6fa 100644 --- a/packages/language-service/src/document_symbols.ts +++ b/packages/language-service/src/document_symbols.ts @@ -11,6 +11,8 @@ import { ASTWithSource, TmplAstBoundAttribute, TmplAstBoundDeferredTrigger, + TmplAstBoundaryBlock, + TmplAstBoundaryErrorBlock, TmplAstComponent, TmplAstContent, TmplAstDeferredBlock, @@ -524,6 +526,57 @@ class TemplateSymbolVisitor extends TmplAstRecursiveVisitor { tmplAstVisitAll(this, block.children); this.popChildren(); } + override visitBoundaryBlock(block: TmplAstBoundaryBlock): void { + const symbol: TemplateDocumentSymbol = { + text: '@boundary', + kind: ts.ScriptElementKind.functionElement, + lspKind: AngularSymbolKind.Event, // @boundary → Event ⚡ + spans: [toTextSpan(block.mainBlockSpan)], + nameSpan: toTextSpan(block.startSourceSpan), + }; + this.addSymbol(symbol); + this.pushChildren(symbol); + tmplAstVisitAll(this, block.children); + tmplAstVisitAll(this, block.errorBlocks); + this.popChildren(); + } + + override visitBoundaryErrorBlock(block: TmplAstBoundaryErrorBlock): void { + const triggers: string[] = []; + if (block.expression) { + const exprText = getExpressionText(block.expression); + triggers.push(`when ${exprText}`); + } + const name = triggers.length > 0 ? `@error (${triggers.join('; ')})` : '@error'; + + const symbol: TemplateDocumentSymbol = { + text: name, + kind: ts.ScriptElementKind.functionElement, + lspKind: AngularSymbolKind.Event, // @error → Event ⚡ + spans: [toTextSpan(block.sourceSpan)], + nameSpan: toTextSpan(block.startSourceSpan), + }; + this.addSymbol(symbol); + this.pushChildren(symbol); + + for (const contextVar of block.contextVariables) { + this.processedVariables.add(contextVar); + // Show if explicitly aliased (name differs from value) OR if showImplicitForVariables is enabled + const isExplicitlyAliased = contextVar.name !== contextVar.value; + if (isExplicitlyAliased || this.options.showImplicitForVariables) { + const contextSymbol: TemplateDocumentSymbol = { + text: `let ${contextVar.name}`, + kind: ts.ScriptElementKind.localVariableElement, + spans: [toTextSpan(contextVar.keySpan)], + nameSpan: toTextSpan(contextVar.keySpan), + }; + this.addSymbol(contextSymbol); + } + } + + tmplAstVisitAll(this, block.children); + this.popChildren(); + } // Elements and components override visitElement(element: TmplAstElement): void { diff --git a/packages/language-service/src/language_service.ts b/packages/language-service/src/language_service.ts index fa836a4dda0f..4b483e2d6892 100644 --- a/packages/language-service/src/language_service.ts +++ b/packages/language-service/src/language_service.ts @@ -8,18 +8,18 @@ import {AST, TmplAstNode} from '@angular/compiler'; import { - AbsoluteFsPath, absoluteFrom, + AbsoluteFsPath, CompilerOptions, ConfigurationHost, ErrorCode, FileUpdate, + InliningMode, isExternalResource, isFatalDiagnosticError, isNamedClassDeclaration, - ngErrorCode, NgCompiler, - InliningMode, + ngErrorCode, OptimizeFor, PerfPhase, ProgramDriver, @@ -899,7 +899,7 @@ export class LanguageService { project.readFile(path), ); - if (!this.options.strictTemplates) { + if (this.options.strictTemplates === false) { diagnostics.push({ messageText: 'Some language features are not available. ' + @@ -994,6 +994,17 @@ function parseNgCompilerOptions( } } + // Prior to v22, strictTemplates was set to false by default + if (options.strictTemplates === undefined && typeof options['_angularCoreVersion'] === 'string') { + const version = options['_angularCoreVersion']; + if (version !== `0.0.0-${'PLACEHOLDER'}`) { + const major = parseInt(version.split('.')[0], 10); + if (!Number.isNaN(major) && major < 22) { + options.strictTemplates = false; + } + } + } + return options; } diff --git a/packages/language-service/src/outlining_spans.ts b/packages/language-service/src/outlining_spans.ts index b478567a8283..4d1a47f522fa 100644 --- a/packages/language-service/src/outlining_spans.ts +++ b/packages/language-service/src/outlining_spans.ts @@ -16,6 +16,7 @@ import { TmplAstNode, TmplAstRecursiveVisitor, TmplAstSwitchBlockCase, + TmplAstBoundaryBlock, tmplAstVisitAll, } from '@angular/compiler'; import {isExternalResource, isNamedClassDeclaration, NgCompiler} from '@angular/compiler-cli'; @@ -68,7 +69,11 @@ class BlockVisitor extends TmplAstRecursiveVisitor { // The source span of for loops and deferred blocks contain all parts (ForLoopBlockEmpty, // DeferredBlockLoading, etc.). The folding range should only include the main block span for // these. - if (block instanceof TmplAstForLoopBlock || block instanceof TmplAstDeferredBlock) { + if ( + block instanceof TmplAstForLoopBlock || + block instanceof TmplAstDeferredBlock || + block instanceof TmplAstBoundaryBlock + ) { mainBlockSpan = block.mainBlockSpan; } return { diff --git a/packages/language-service/src/semantic_tokens.ts b/packages/language-service/src/semantic_tokens.ts index ede48b4aec2b..bc894bf67c20 100644 --- a/packages/language-service/src/semantic_tokens.ts +++ b/packages/language-service/src/semantic_tokens.ts @@ -39,6 +39,8 @@ import { TmplAstUnknownBlock, TmplAstVariable, TmplAstVisitor, + TmplAstBoundaryBlock, + TmplAstBoundaryErrorBlock, } from '@angular/compiler'; import {NgCompiler, PotentialDirective} from '@angular/compiler-cli'; @@ -205,6 +207,15 @@ class ClassificationVisitor implements TmplAstVisitor { this.visitAll(block.children); } + visitBoundaryBlock(block: TmplAstBoundaryBlock) { + this.visitAll(block.children); + this.visitAll(block.errorBlocks); + } + + visitBoundaryErrorBlock(block: TmplAstBoundaryErrorBlock) { + this.visitAll(block.children); + } + visitTemplate(template: TmplAstTemplate) { this.visitAll(template.children); } diff --git a/packages/language-service/src/template_target.ts b/packages/language-service/src/template_target.ts index 3609a23e0def..1fe043b428e0 100644 --- a/packages/language-service/src/template_target.ts +++ b/packages/language-service/src/template_target.ts @@ -18,6 +18,8 @@ import { RecursiveAstVisitor, SafeCall, ThisReceiver, + TmplAstBoundaryBlock, + TmplAstBoundaryErrorBlock, TmplAstBoundAttribute, TmplAstBoundDeferredTrigger, TmplAstBoundEvent, @@ -54,7 +56,6 @@ import { tmplAstVisitAll, TmplAstVisitor, } from '@angular/compiler'; -import {NgCompiler} from '@angular/compiler-cli'; import {findFirstMatchingNode} from '@angular/compiler-cli/private/hybrid_analysis'; import tss from 'typescript'; @@ -63,7 +64,6 @@ import { isTemplateNodeWithKeyAndValue, isWithin, isWithinKeyValue, - TypeCheckInfo, } from './utils'; /** @@ -703,6 +703,17 @@ class TemplateTargetVisitor implements TmplAstVisitor { this.visitAll(block.children); } + visitBoundaryBlock(block: TmplAstBoundaryBlock) { + this.visitAll(block.children); + this.visitAll(block.errorBlocks); + } + + visitBoundaryErrorBlock(block: TmplAstBoundaryErrorBlock) { + this.visitAll(block.contextVariables); + block.expression && this.visitBinding(block.expression); + this.visitAll(block.children); + } + visitUnknownBlock(block: TmplAstUnknownBlock) {} visitLetDeclaration(decl: TmplAstLetDeclaration) { diff --git a/packages/language-service/src/utils/index.ts b/packages/language-service/src/utils/index.ts index 5c1e65b678a0..457ada1fd60c 100644 --- a/packages/language-service/src/utils/index.ts +++ b/packages/language-service/src/utils/index.ts @@ -77,7 +77,7 @@ interface NodeWithKeyAndValue extends TmplAstNode { export function isTemplateNodeWithKeyAndValue( node: TmplAstNode | AST, ): node is NodeWithKeyAndValue { - return isTemplateNode(node) && node.hasOwnProperty('keySpan'); + return isTemplateNode(node) && Object.hasOwn(node, 'keySpan'); } export function isWithinKey(position: number, node: NodeWithKeyAndValue): boolean { diff --git a/packages/language-service/src/utils/ts_utils.ts b/packages/language-service/src/utils/ts_utils.ts index cb9052ab1023..d45f8fda578b 100644 --- a/packages/language-service/src/utils/ts_utils.ts +++ b/packages/language-service/src/utils/ts_utils.ts @@ -375,6 +375,7 @@ export function updateImportsForTypescriptFile( symbolName: string, declarationName: string, moduleSpecifier: string, + preferences?: ts.UserPreferences, ): [ts.TextChange[], string] { // The trait might already be imported, possibly under a different name. If so, determine the // local name of the imported trait. @@ -421,11 +422,40 @@ export function updateImportsForTypescriptFile( // TODO: Why does the compiler insist this is null? span.start = lastImport!.getStart() + lastImport!.getWidth(); } - const newImportDeclaration = generateImport(symbolName, importName, moduleSpecifier); + const newImportDeclaration = generateImport( + symbolName, + importName, + moduleSpecifier, + shouldUseSingleQuotes(file, preferences), + ); const importString = '\n' + printNode(newImportDeclaration, file); return [[{span, newText: importString}], importName]; } +/** + * Whether new string literals in the given file should use single quotes, based on the + * user's `quotePreference`. When the preference is `auto` (or absent), the style is inferred + * from the first existing import in the file, mirroring TypeScript's own behavior. Defaults + * to double quotes when there is nothing to infer from. + */ +export function shouldUseSingleQuotes( + file: ts.SourceFile, + preferences: ts.UserPreferences | undefined, +): boolean { + if (preferences?.quotePreference === 'single') { + return true; + } + if (preferences?.quotePreference === 'double') { + return false; + } + for (const statement of file.statements) { + if (ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier)) { + return file.text[statement.moduleSpecifier.getStart(file)] === `'`; + } + } + return false; +} + /** * Updates a given Angular trait, such as an NgModule or standalone Component, by adding * `importName` to the list of imports on the decorator arguments. @@ -590,13 +620,14 @@ export function generateImport( localName: string, exportedSpecifierName: string | null, rawModuleSpecifier: string, + useSingleQuotes = false, ): ts.ImportDeclaration { let propName: ts.Identifier | undefined; if (exportedSpecifierName !== null && exportedSpecifierName !== localName) { propName = ts.factory.createIdentifier(exportedSpecifierName); } const name = ts.factory.createIdentifier(localName); - const moduleSpec = ts.factory.createStringLiteral(rawModuleSpecifier); + const moduleSpec = ts.factory.createStringLiteral(rawModuleSpecifier, useSingleQuotes); let importClauseName: ts.Identifier | undefined; let importBindings: ts.NamedImportBindings | undefined; @@ -692,6 +723,7 @@ export function getCodeActionToImportTheDirectiveDeclaration( directive: PotentialDirective | PotentialPipe, tsLs: ts.LanguageService, includeCompletionsForModuleExports?: boolean, + preferences?: ts.UserPreferences, ): ts.CodeAction[] | undefined { const codeActions: ts.CodeAction[] = []; @@ -741,6 +773,7 @@ export function getCodeActionToImportTheDirectiveDeclaration( potentialImport.symbolName, declarationName, potentialImport.moduleSpecifier, + preferences, ); importName = generatedImportName; fileImportChanges.push(...importChanges); @@ -753,6 +786,7 @@ export function getCodeActionToImportTheDirectiveDeclaration( 'forwardRef', declarationName, '@angular/core', + preferences, ); fileImportChanges.push(...forwardRefImports); forwardRefName = generatedForwardRefName; diff --git a/packages/language-service/test/code_fixes_spec.ts b/packages/language-service/test/code_fixes_spec.ts index cdc420eac2b3..359e72363826 100644 --- a/packages/language-service/test/code_fixes_spec.ts +++ b/packages/language-service/test/code_fixes_spec.ts @@ -593,6 +593,80 @@ describe('code fixes', () => { const fixFile = project.openFile('foo.ts'); fixFile.moveCursorToText('<¦bar>'); + const codeActions = project.getCodeFixesAtPosition('foo.ts', fixFile.cursor, fixFile.cursor, [ + diags[0].code, + ]); + const actionChanges = allChangesForCodeActions(fixFile.contents, codeActions); + actionChangesMatch(actionChanges, `Import BarComponent from './bar' on FooComponent`, [ + [``, `import { BarComponent } from './bar';`], + [``, `, imports: [BarComponent]`], + ]); + }); + + it('respects an explicit double quote preference for the generated import', () => { + const standaloneFiles = { + 'foo.ts': ` + import {Component} from '@angular/core'; + @Component({ + selector: 'foo', + template: '' + }) + export class FooComponent {} + `, + 'bar.ts': ` + import {Component} from '@angular/core'; + @Component({ + selector: 'bar', + template: '
bar
' + }) + export class BarComponent {} + `, + }; + + const project = createModuleAndProjectWithDeclarations(env, 'test', {}, {}, standaloneFiles); + const diags = project.getDiagnosticsForFile('foo.ts'); + const fixFile = project.openFile('foo.ts'); + fixFile.moveCursorToText('<¦bar>'); + + const codeActions = project.getCodeFixesAtPosition( + 'foo.ts', + fixFile.cursor, + fixFile.cursor, + [diags[0].code], + {quotePreference: 'double'}, + ); + const actionChanges = allChangesForCodeActions(fixFile.contents, codeActions); + actionChangesMatch(actionChanges, `Import BarComponent from './bar' on FooComponent`, [ + [``, `import { BarComponent } from "./bar";`], + [``, `, imports: [BarComponent]`], + ]); + }); + + it('matches the quote style of existing imports for the generated import', () => { + const standaloneFiles = { + 'foo.ts': ` + import {Component} from "@angular/core"; + @Component({ + selector: 'foo', + template: '' + }) + export class FooComponent {} + `, + 'bar.ts': ` + import {Component} from '@angular/core'; + @Component({ + selector: 'bar', + template: '
bar
' + }) + export class BarComponent {} + `, + }; + + const project = createModuleAndProjectWithDeclarations(env, 'test', {}, {}, standaloneFiles); + const diags = project.getDiagnosticsForFile('foo.ts'); + const fixFile = project.openFile('foo.ts'); + fixFile.moveCursorToText('<¦bar>'); + const codeActions = project.getCodeFixesAtPosition('foo.ts', fixFile.cursor, fixFile.cursor, [ diags[0].code, ]); @@ -640,7 +714,7 @@ describe('code fixes', () => { ]); const actionChanges = allChangesForCodeActions(fixFile.contents, codeActions); actionChangesMatch(actionChanges, `Import BarModule from './bar' on FooComponent`, [ - [``, `import { BarModule } from "./bar";`], + [``, `import { BarModule } from './bar';`], [``, `, imports: [BarModule]`], ]); }); @@ -682,7 +756,7 @@ describe('code fixes', () => { ]); const actionChanges = allChangesForCodeActions(fixFile.contents, codeActions); actionChangesMatch(actionChanges, `Import BarComponent from './bar' on FooModule`, [ - [``, `import { BarComponent } from "./bar";`], + [``, `import { BarComponent } from './bar';`], [`imports: []`, `imports: [BarComponent]`], ]); }); @@ -721,7 +795,7 @@ describe('code fixes', () => { const actionChanges = allChangesForCodeActions(fixFile.contents, codeActions); actionChangesMatch(actionChanges, `Import BarPipe from './bar' on FooComponent`, [ - [``, `import { BarPipe } from "./bar";`], + [``, `import { BarPipe } from './bar';`], ['', `, imports: [BarPipe]`], ]); }); @@ -768,11 +842,11 @@ describe('code fixes', () => { ]); const actionChanges = allChangesForCodeActions(fixFile.contents, codeActions); actionChangesMatch(actionChanges, `Import BarModule from './bar' on FooComponent`, [ - [``, `import { BarModule } from "./bar";`], + [``, `import { BarModule } from './bar';`], [``, `, imports: [BarModule]`], ]); actionChangesMatch(actionChanges, `Import Bar2Module from './bar' on FooComponent`, [ - [``, `import { Bar2Module } from "./bar";`], + [``, `import { Bar2Module } from './bar';`], [``, `, imports: [Bar2Module]`], ]); }); @@ -808,7 +882,7 @@ describe('code fixes', () => { ]); const actionChanges = allChangesForCodeActions(fixFile.contents, codeActions); actionChangesMatch(actionChanges, `Import BarComponent from './bar' on FooComponent`, [ - [``, `import BarComponent from "./bar";`], + [``, `import BarComponent from './bar';`], [``, `, imports: [BarComponent]`], ]); }); @@ -948,7 +1022,7 @@ describe('code fixes', () => { ]); const actionChanges = allChangesForCodeActions(fixFile.contents, codeActions); actionChangesMatch(actionChanges, `Import MatCard from '@angular/common' on FooComponent`, [ - [``, `import { MatCard } from "@angular/common";`], + [``, `import { MatCard } from '@angular/common';`], [``, `, imports: [MatCard]`], ]); }); @@ -988,7 +1062,7 @@ describe('code fixes', () => { ); const actionChanges = allChangesForCodeActions(fixFile.contents, codeActions); actionChangesMatch(actionChanges, `Import BarComponent from '@app/bar' on FooComponent`, [ - [``, `import { BarComponent } from "@app/bar";`], + [``, `import { BarComponent } from '@app/bar';`], [``, `, imports: [BarComponent]`], ]); }); @@ -1041,7 +1115,7 @@ describe('code fixes', () => { actionChanges, `Import NewBarComponent3 from '@app/index' on FooComponent`, [ - [``, `import { NewBarComponent3 } from "@app/index";`], + [``, `import { NewBarComponent3 } from '@app/index';`], [``, `, imports: [NewBarComponent3]`], ], ); @@ -1197,7 +1271,7 @@ describe('code fixes', () => { actionChanges, `Import BarModule from '../component/share/bar.module' on FooComponent`, [ - [``, `import { BarModule } from "../component/share/bar.module";`], + [``, `import { BarModule } from '../component/share/bar.module';`], [``, `, imports: [BarModule]`], ], ); @@ -1255,7 +1329,7 @@ describe('code fixes', () => { const actionChanges = allChangesForCodeActions(appModuleContents, codeActions); actionChangesMatch(actionChanges, `Import BarComponent from './bar' on AppModule`, [ - [``, `import { BarComponent } from "./bar";`], + [``, `import { BarComponent } from './bar';`], [`imports: []`, `imports: [BarComponent]`], ]); }); diff --git a/packages/language-service/test/completions_spec.ts b/packages/language-service/test/completions_spec.ts index 311872529edb..fed98546eaa3 100644 --- a/packages/language-service/test/completions_spec.ts +++ b/packages/language-service/test/completions_spec.ts @@ -1599,7 +1599,7 @@ describe('completions', () => { 'start': 303, 'length': 0, }, - 'newText': '\nimport { HighlightDirective } from "@app/highlight";', + 'newText': "\nimport { HighlightDirective } from '@app/highlight';", }, { 'span': { @@ -1805,7 +1805,7 @@ describe('completions', () => { 'start': 303, 'length': 0, }, - 'newText': '\nimport { HighlightDirective } from "@app/highlight";', + 'newText': "\nimport { HighlightDirective } from '@app/highlight';", }, { 'span': { diff --git a/packages/language-service/test/get_outlining_spans_spec.ts b/packages/language-service/test/get_outlining_spans_spec.ts index 360d172667da..62b636d1acda 100644 --- a/packages/language-service/test/get_outlining_spans_spec.ts +++ b/packages/language-service/test/get_outlining_spans_spec.ts @@ -203,6 +203,35 @@ describe('get outlining spans', () => { expect(getTrimmedSpanText(result[0].textSpan, files['app.ts'])).toEqual('{{item}}'); expect(getTrimmedSpanText(result[1].textSpan, files['app.ts'])).toEqual('empty list'); }); + + it('should have outlining spans for boundary and error blocks', () => { + const files = { + 'app.ts': ` + import {Component} from '@angular/core'; + + @Component({ + template: \` + @boundary { + boundary body + } @error (let err) { + error body + } + \`, + standalone: false, + }) + export class AppCmp { + }`, + }; + const env = LanguageServiceTestEnv.setup(); + const project = createModuleAndProjectWithDeclarations(env, 'test', files); + project.expectNoSourceDiagnostics(); + + const appFile = project.openFile('app.ts'); + const result = appFile.getOutliningSpans(); + expect(result.length).toEqual(2); + expect(getTrimmedSpanText(result[0].textSpan, files['app.ts'])).toEqual('boundary body'); + expect(getTrimmedSpanText(result[1].textSpan, files['app.ts'])).toEqual('error body'); + }); }); function getTrimmedSpanText(span: ts.TextSpan, contents: string) { diff --git a/packages/language-service/test/legacy/language_service_spec.ts b/packages/language-service/test/legacy/language_service_spec.ts index cfb967214824..323674c51e60 100644 --- a/packages/language-service/test/legacy/language_service_spec.ts +++ b/packages/language-service/test/legacy/language_service_spec.ts @@ -35,7 +35,6 @@ describe('language service adapter', () => { it('should initialize with angularCompilerOptions from tsconfig.json', () => { expect(ngLS.getCompilerOptions()).toEqual( jasmine.objectContaining({ - strictTemplates: true, strictInjectionParameters: true, }), ); @@ -44,7 +43,6 @@ describe('language service adapter', () => { it('should reparse angularCompilerOptions on tsconfig.json change', () => { expect(ngLS.getCompilerOptions()).toEqual( jasmine.objectContaining({ - strictTemplates: true, strictInjectionParameters: true, }), ); @@ -107,9 +105,11 @@ describe('language service adapter', () => { }); describe('compiler options diagnostics', () => { - it('suggests turning on strict flag', () => { + it('suggests turning on strict flag when strictTemplates is explicitly false', () => { configFileFs.overwriteConfigFile(TSCONFIG, { - angularCompilerOptions: {}, + angularCompilerOptions: { + strictTemplates: false, + }, }); const diags = ngLS.getCompilerOptionsDiagnostics(); const diag = diags.find(isSuggestStrictTemplatesDiag); @@ -128,6 +128,16 @@ describe('language service adapter', () => { const diag = diags.find(isSuggestStrictTemplatesDiag); expect(diag).toBeUndefined(); }); + + it('does not suggest turning on strict mode is strictTemplates flag is ommitted', () => { + configFileFs.overwriteConfigFile(TSCONFIG, { + angularCompilerOptions: {}, + }); + const diags = ngLS.getCompilerOptionsDiagnostics(); + const diag = diags.find(isSuggestStrictTemplatesDiag); + expect(diag).toBeUndefined(); + }); + function isSuggestStrictTemplatesDiag(diag: ts.Diagnostic) { return diag.code === ngErrorCode(ErrorCode.SUGGEST_STRICT_TEMPLATES); } diff --git a/packages/language-service/test/legacy/project/tsconfig.json b/packages/language-service/test/legacy/project/tsconfig.json index 36d6c348cf6f..b37289b0158f 100644 --- a/packages/language-service/test/legacy/project/tsconfig.json +++ b/packages/language-service/test/legacy/project/tsconfig.json @@ -1,23 +1,17 @@ { "//00": "This file is used for both IDE and the actual Project creation in Ivy language service for testing purpose", "compilerOptions": { - "lib": [ - "es2015", - "dom" - ], - "strict": true, + "stableTypeOrdering": true, + "lib": ["es2015", "dom"], "experimentalDecorators": true, "moduleResolution": "node", "target": "es2015", "baseUrl": "../../../../../", "paths": { - "@angular/*": [ - "packages/*" - ] + "@angular/*": ["packages/*"] } }, "angularCompilerOptions": { - "strictTemplates": true, "strictInjectionParameters": true } } diff --git a/packages/language-service/test/quick_info_spec.ts b/packages/language-service/test/quick_info_spec.ts index cbb8243d7265..e8e22149774a 100644 --- a/packages/language-service/test/quick_info_spec.ts +++ b/packages/language-service/test/quick_info_spec.ts @@ -848,6 +848,22 @@ describe('quick info', () => { }); }); + it('boundary error block context variables', () => { + expectQuickInfo({ + templateOverride: `@boundary { } @error (let er¦r) { }`, + expectedSpanText: 'err', + expectedDisplayString: '(variable) err: Error', + }); + }); + + it('boundary error block retry context variable', () => { + expectQuickInfo({ + templateOverride: `@boundary { } @error (let err, rt¦ry = $reset) { }`, + expectedSpanText: 'rtry', + expectedDisplayString: '(variable) rtry: () => void', + }); + }); + it('if block alias variable narrowed', () => { expectQuickInfo({ templateOverride: `@if (signalValue; as al¦iasName) {}`, diff --git a/packages/language-service/test/version_detection_spec.ts b/packages/language-service/test/version_detection_spec.ts index 29d3f6d905d8..61415dd9ed94 100644 --- a/packages/language-service/test/version_detection_spec.ts +++ b/packages/language-service/test/version_detection_spec.ts @@ -17,32 +17,63 @@ describe('Angular version detection', () => { it('should detect Angular version per project', () => { // Project 1: Angular v16 - const project1 = env.addProject('project1', { - 'tsconfig.json': '{}', - 'app.ts': 'export class App {}', - 'node_modules/@angular/core/package.json': JSON.stringify({ - name: '@angular/core', - version: '16.0.0', - }), - }); + const project1 = env.addProject( + 'project1', + { + 'tsconfig.json': '{}', + 'app.ts': 'export class App {}', + 'node_modules/@angular/core/package.json': JSON.stringify({ + name: '@angular/core', + version: '16.0.0', + }), + }, + // By default our testing env sets strictTemplates to true, we unset it here. + {strictTemplates: undefined}, + ); // Project 2: Angular v17 - const project2 = env.addProject('project2', { - 'tsconfig.json': '{}', - 'app.ts': 'export class App {}', - 'node_modules/@angular/core/package.json': JSON.stringify({ - name: '@angular/core', - version: '17.0.0', - }), - }); + const project2 = env.addProject( + 'project2', + { + 'tsconfig.json': '{}', + 'app.ts': 'export class App {}', + 'node_modules/@angular/core/package.json': JSON.stringify({ + name: '@angular/core', + version: '17.0.0', + }), + }, + // By default our testing env sets strictTemplates to true, we unset it here. + {strictTemplates: undefined}, + ); + + // Project 3: Angular v22 + const project3 = env.addProject( + 'project3', + { + 'tsconfig.json': '{}', + 'app.ts': 'export class App {}', + 'node_modules/@angular/core/package.json': JSON.stringify({ + name: '@angular/core', + version: '22.0.0', + }), + }, + // By default our testing env sets strictTemplates to true, we unset it here. + {strictTemplates: undefined}, + ); // We need to access the internal options to verify detection // Project wrapper in testing exposes ngLS const options1 = project1.ngLS.getCompilerOptions(); expect(options1['_angularCoreVersion']).toBe('16.0.0'); + expect(options1.strictTemplates).toBeFalse(); const options2 = project2.ngLS.getCompilerOptions(); expect(options2['_angularCoreVersion']).toBe('17.0.0'); + expect(options2.strictTemplates).toBeFalse(); + + const options3 = project3.ngLS.getCompilerOptions(); + expect(options3['_angularCoreVersion']).toBe('22.0.0'); + expect(options3.strictTemplates).toBeUndefined(); }); it('should fallback to default if detection fails', () => { diff --git a/packages/language-service/testing/src/project.ts b/packages/language-service/testing/src/project.ts index e4635659b675..05310763f6ab 100644 --- a/packages/language-service/testing/src/project.ts +++ b/packages/language-service/testing/src/project.ts @@ -216,6 +216,7 @@ export class Project { start: number, end: number, errorCodes: readonly number[], + preferences: ts.UserPreferences = {}, ): readonly ts.CodeFixAction[] { const fileName = absoluteFrom(`/${this.name}/${projectFileName}`); return this.ngLS.getCodeFixesAtPosition( @@ -226,6 +227,7 @@ export class Project { {}, { includeCompletionsForModuleExports: true, + ...preferences, }, ); } diff --git a/packages/localize/src/utils/src/messages.ts b/packages/localize/src/utils/src/messages.ts index 61f6ffb6db1b..0b7e0a43c507 100644 --- a/packages/localize/src/utils/src/messages.ts +++ b/packages/localize/src/utils/src/messages.ts @@ -138,7 +138,7 @@ export interface ParsedMessage extends MessageMetadata { /** * A mapping of placeholder names to substitution values. */ - substitutions: Record; + substitutions: Record; /** * An optional mapping of placeholder names to associated MessageIds. * This can be used to match ICU placeholders to the message that contains the ICU. @@ -170,12 +170,12 @@ export interface ParsedMessage extends MessageMetadata { */ export function parseMessage( messageParts: TemplateStringsArray, - expressions?: readonly any[], + expressions?: readonly unknown[], location?: SourceLocation, messagePartLocations?: (SourceLocation | undefined)[], expressionLocations: (SourceLocation | undefined)[] = [], ): ParsedMessage { - const substitutions: {[placeholderName: string]: any} = {}; + const substitutions: Record = {}; const substitutionLocations: {[placeholderName: string]: SourceLocation | undefined} = {}; const associatedMessageIds: {[placeholderName: string]: MessageId} = {}; const metadata = parseMetadata(messageParts[0], messageParts.raw[0]); diff --git a/packages/localize/src/utils/src/translations.ts b/packages/localize/src/utils/src/translations.ts index 00a3751d38b0..d947f61a19b0 100644 --- a/packages/localize/src/utils/src/translations.ts +++ b/packages/localize/src/utils/src/translations.ts @@ -22,14 +22,18 @@ export interface ParsedTranslation extends MessageMetadata { export type ParsedTranslations = Record; export class MissingTranslationError extends Error { - private readonly type = 'MissingTranslationError'; + readonly type = 'MissingTranslationError'; constructor(readonly parsedMessage: ParsedMessage) { super(`No translation found for ${describeMessage(parsedMessage)}.`); } } -export function isMissingTranslationError(e: any): e is MissingTranslationError { - return e.type === 'MissingTranslationError'; +export function isMissingTranslationError(e: unknown): e is MissingTranslationError { + return ( + typeof e === 'object' && + e !== null && + (e as MissingTranslationError).type === 'MissingTranslationError' + ); } /** @@ -51,8 +55,8 @@ export function isMissingTranslationError(e: any): e is MissingTranslationError export function translate( translations: Record, messageParts: TemplateStringsArray, - substitutions: readonly any[], -): [TemplateStringsArray, readonly any[]] { + substitutions: readonly unknown[], +): [TemplateStringsArray, readonly unknown[]] { const message = parseMessage(messageParts, substitutions); // Look up the translation using the messageId, and then the legacyId if available. let translation = translations[message.id]; @@ -137,7 +141,7 @@ export function makeParsedTranslation( */ export function makeTemplateObject(cooked: string[], raw: string[]): TemplateStringsArray { Object.defineProperty(cooked, 'raw', {value: raw}); - return cooked as any; + return cooked as unknown as TemplateStringsArray; } function describeMessage(message: ParsedMessage): string { diff --git a/packages/localize/test/translate_spec.ts b/packages/localize/test/translate_spec.ts index cea117b53fbe..404bb8727172 100644 --- a/packages/localize/test/translate_spec.ts +++ b/packages/localize/test/translate_spec.ts @@ -119,7 +119,7 @@ describe('$localize tag with translations', () => { // The malicious id must be stored as an own key rather than assigned through the inherited // `__proto__` setter, which would reparent the map (and drop the entry). expect(Object.getPrototypeOf(store)).toBe(null); - expect(Object.prototype.hasOwnProperty.call(store, '__proto__')).toBe(true); + expect(Object.hasOwn(store, '__proto__')).toBe(true); // A translation loaded alongside it still resolves. expect($localize`abc`).toEqual('abc'); }); diff --git a/packages/localize/tools/src/extract/translation_files/legacy_message_id_migration_serializer.ts b/packages/localize/tools/src/extract/translation_files/legacy_message_id_migration_serializer.ts index c410258a2973..c29bbc96347e 100644 --- a/packages/localize/tools/src/extract/translation_files/legacy_message_id_migration_serializer.ts +++ b/packages/localize/tools/src/extract/translation_files/legacy_message_id_migration_serializer.ts @@ -23,7 +23,7 @@ export class LegacyMessageIdMigrationSerializer implements TranslationSerializer (output, message) => { if (shouldMigrate(message)) { for (const legacyId of message.legacyIds!) { - if (output.hasOwnProperty(legacyId)) { + if (Object.hasOwn(output, legacyId)) { this._diagnostics.warn(`Detected duplicate legacy ID ${legacyId}.`); } diff --git a/packages/localize/tools/test/extract/translation_files/mock_message.ts b/packages/localize/tools/test/extract/translation_files/mock_message.ts index c16261d96e49..8905153cd7ec 100644 --- a/packages/localize/tools/test/extract/translation_files/mock_message.ts +++ b/packages/localize/tools/test/extract/translation_files/mock_message.ts @@ -35,7 +35,7 @@ export function mockMessage( text += `{$${placeholderNames[i - 1]}}${messageParts[i]}`; } return { - substitutions: [], + substitutions: {}, ...options, id: options.customId || id, // customId trumps id text, diff --git a/packages/misc/angular-in-memory-web-api/README.md b/packages/misc/angular-in-memory-web-api/README.md index a36229fb33d8..5b0637985282 100644 --- a/packages/misc/angular-in-memory-web-api/README.md +++ b/packages/misc/angular-in-memory-web-api/README.md @@ -3,6 +3,13 @@ An in-memory web api for Angular demos and tests that emulates CRUD operations over a RESTy API. +> **WARNING** +> +> This package is a development and testing tool only. +> The in-memory data store applies no authentication or authorization +> to the requests it answers. +> Never ship it in a production app. + It intercepts Angular `Http` and `HttpClient` requests that would otherwise go to the remote server and redirects them to an in-memory data store that you control. See [Austin McDaniel's article](https://medium.com/@amcdnl/mocking-with-angular-more-than-just-unit-testing-cbb7908c9fcc) diff --git a/packages/misc/angular-in-memory-web-api/package.json b/packages/misc/angular-in-memory-web-api/package.json index fc1625c79b44..e6bc2b7b68b0 100644 --- a/packages/misc/angular-in-memory-web-api/package.json +++ b/packages/misc/angular-in-memory-web-api/package.json @@ -5,8 +5,8 @@ "author": "angular", "license": "MIT", "peerDependencies": { - "@angular/core": "^22.1.0-next", - "@angular/common": "^22.1.0-next", + "@angular/core": "^22.2.0-next", + "@angular/common": "^22.2.0-next", "rxjs": "^6.5.3 || ^7.4.0" }, "dependencies": { diff --git a/packages/platform-browser/src/browser/meta.ts b/packages/platform-browser/src/browser/meta.ts index 36e2a8bf1f7b..00491db411fd 100644 --- a/packages/platform-browser/src/browser/meta.ts +++ b/packages/platform-browser/src/browser/meta.ts @@ -7,11 +7,14 @@ */ import {DOCUMENT, ɵgetDOM as getDOM} from '@angular/common'; -import {inject, Service} from '@angular/core'; +import {inject, ɵRuntimeError as RuntimeError, Service} from '@angular/core'; + +import {RuntimeErrorCode} from '../errors'; /** * Represents the attributes of an HTML `` element. The element itself is - * represented by the internal `HTMLMetaElement`. + * represented by the internal `HTMLMetaElement`. Event handler attributes, which start with + * `on`, are not allowed. * * @see [HTML meta tag](https://developer.mozilla.org/docs/Web/HTML/Element/meta) * @see {@link Meta} @@ -124,6 +127,7 @@ export class Meta { * @return The modified element. */ updateTag(tag: MetaDefinition, selector?: string): HTMLMetaElement | null { + validateMetaDefinition(tag); selector ??= parseSelector(tag); const meta = this.getTag(selector); if (meta) { @@ -156,6 +160,7 @@ export class Meta { meta: MetaDefinition, forceCreation: boolean = false, ): HTMLMetaElement { + validateMetaDefinition(meta); if (!forceCreation) { const selector: string = parseSelector(meta); // It's allowed to have multiple elements with the same name so it's not enough to @@ -180,6 +185,19 @@ function setMetaElementAttributes(tag: MetaDefinition, el: HTMLMetaElement) { Object.keys(tag).forEach((prop: string) => el.setAttribute(getMetaKeyMap(prop), tag[prop])); } +function validateMetaDefinition(tag: MetaDefinition): void { + for (const prop of Object.keys(tag)) { + const attributeName = getMetaKeyMap(prop); + if (attributeName.toLowerCase().startsWith('on')) { + throw new RuntimeError( + RuntimeErrorCode.INVALID_EVENT_ATTRIBUTE, + (typeof ngDevMode === 'undefined' || ngDevMode) && + `The Meta service does not allow setting event handler attribute '${attributeName}' for security reasons.`, + ); + } + } +} + function parseSelector(tag: MetaDefinition): string { const attr: string = tag.name ? 'name' : 'property'; return `${attr}=${escapeSelectorValue(String(tag[attr]))}`; @@ -196,7 +214,7 @@ function containsAttributes(tag: MetaDefinition, elem: HTMLMetaElement): boolean } function getMetaKeyMap(prop: string): string { - return META_KEYS_MAP[prop] || prop; + return Object.hasOwn(META_KEYS_MAP, prop) ? META_KEYS_MAP[prop] : prop; } function isMetaTag(tag: HTMLElement | null): tag is HTMLMetaElement { diff --git a/packages/platform-browser/src/dom/dom_renderer.ts b/packages/platform-browser/src/dom/dom_renderer.ts index c04a679bb35d..92e152ca131b 100644 --- a/packages/platform-browser/src/dom/dom_renderer.ts +++ b/packages/platform-browser/src/dom/dom_renderer.ts @@ -20,6 +20,7 @@ import { RendererStyleFlags2, RendererType2, ViewEncapsulation, + ɵdescribeDomNode as describeDomNode, ɵRuntimeError as RuntimeError, type ListenerOptions, ɵTracingService as TracingService, @@ -353,6 +354,18 @@ class DefaultDomRenderer2 implements Renderer2 { insertBefore(parent: any, newChild: any, refChild: any): void { if (parent) { const targetParent = isTemplateNode(parent) ? parent.content : parent; + // If something outside Angular removed or moved `refChild` (a browser extension, for + // example), the native call below throws a `NotFoundError` with no useful info. Catch it + // here so we can say what actually happened. + if (refChild != null && refChild.parentNode !== targetParent) { + throw new RuntimeError( + RuntimeErrorCode.INSERT_BEFORE_NODE_NOT_FOUND, + ngDevMode && + `Angular could not insert a node before ${describeDomNode(refChild)} because it is no longer a child of ${describeDomNode(targetParent)}. ` + + `This can happen when code outside of Angular's control (for example, a browser extension or a script that directly manipulates the DOM) ` + + `has moved or removed a node that Angular is still managing.`, + ); + } targetParent.insertBefore(newChild, refChild); } } @@ -543,11 +556,11 @@ function isTemplateNode(node: any): node is HTMLTemplateElement { } class ShadowDomRenderer extends DefaultDomRenderer2 { - private shadowRoot: any; + private readonly shadowRoot: ShadowRoot; constructor( eventManager: EventManager, - private hostEl: any, + private readonly hostEl: Element, component: RendererType2, doc: Document, ngZone: NgZone, @@ -557,7 +570,7 @@ class ShadowDomRenderer extends DefaultDomRenderer2 { private sharedStylesHost?: SharedStylesHost, ) { super(eventManager, doc, ngZone, tracingService, cssVarNamespace); - this.shadowRoot = (hostEl as any).attachShadow({mode: 'open'}); + this.shadowRoot = hostEl.attachShadow({mode: 'open'}); // SharedStylesHost is used to add styles to the shadow root by ShadowDom. // This is optional as it is not used by ExperimentalIsolatedShadowDom. diff --git a/packages/platform-browser/src/dom/shared_styles_host.ts b/packages/platform-browser/src/dom/shared_styles_host.ts index a8153d02ef94..0278d400bd32 100644 --- a/packages/platform-browser/src/dom/shared_styles_host.ts +++ b/packages/platform-browser/src/dom/shared_styles_host.ts @@ -57,7 +57,7 @@ function createStyleElement(style: string, doc: Document): HTMLStyleElement { * Searches a DOM document's head element for style elements with a matching application * identifier attribute (`ng-app-id`) to the provide identifier and adds usage records for each. * @param doc An HTML DOM document instance. - * @param appId A string containing an Angular application identifer. + * @param appId A string containing an Angular application identifier. * @param inline A Map object for tracking inline (defined via `styles` in component decorator) style usage. * @param external A Map object for tracking external (defined via `styleUrls` in component decorator) style usage. * @returns Whether or not styles were added. diff --git a/packages/platform-browser/src/errors.ts b/packages/platform-browser/src/errors.ts index 97e17883c99e..2fd52bb3bf58 100644 --- a/packages/platform-browser/src/errors.ts +++ b/packages/platform-browser/src/errors.ts @@ -21,11 +21,13 @@ export const enum RuntimeErrorCode { TESTABILITY_NOT_FOUND = 5103, ROOT_NODE_NOT_FOUND = -5104, UNEXPECTED_SYNTHETIC_PROPERTY = 5105, + INSERT_BEFORE_NODE_NOT_FOUND = -5106, // Sanitization-related errors (5200-5300 range) SANITIZATION_UNSAFE_SCRIPT = 5200, SANITIZATION_UNSAFE_RESOURCE_URL = -5201, SANITIZATION_UNEXPECTED_CTX = 5202, + INVALID_EVENT_ATTRIBUTE = 5203, // Animations related errors (5300-5400 range) ANIMATION_RENDERER_ASYNC_LOADING_FAILURE = 5300, diff --git a/packages/platform-browser/test/browser/meta_spec.ts b/packages/platform-browser/test/browser/meta_spec.ts index 314c9eeb99b1..c72046468d87 100644 --- a/packages/platform-browser/test/browser/meta_spec.ts +++ b/packages/platform-browser/test/browser/meta_spec.ts @@ -90,6 +90,26 @@ describe('Meta service', () => { expect(actual!.getAttribute('content')).toEqual('4321'); }); + it('should reject event handler attributes targeting a body meta tag', () => { + doc.body.appendChild(defaultMeta); + + const evil = 'alert(1)'; + + expect(metaService.getTag('property="fb:app_id"')).toBe(defaultMeta); + expect(() => + metaService.updateTag({ + property: 'fb:app_id', + style: 'content-visibility:auto', + oncontentvisibilityautostatechange: evil, + }), + ).toThrowError( + /NG05203: The Meta service does not allow setting event handler attribute 'oncontentvisibilityautostatechange'/, + ); + + expect(defaultMeta.getAttribute('style')).toBeNull(); + expect(defaultMeta.getAttribute('oncontentvisibilityautostatechange')).toBeNull(); + }); + it('should not allow a custom selector to match off target elements like the body tag', () => { // This payload attempts to break out of the `meta[name="..."]` constraint entirely // and inject a comma to target arbitrary DOM elements like the `body` tag via the @@ -144,6 +164,42 @@ describe('Meta service', () => { metaService.removeTagElement(actual); }); + it('should reject event handler attributes without adding a tag', () => { + const selector = 'name="og:title"'; + const evil = 'alert(1)'; + + expect(() => + metaService.addTag({ + name: 'og:title', + style: 'content-visibility:auto', + oncontentvisibilityautostatechange: evil, + }), + ).toThrowError( + /NG05203: The Meta service does not allow setting event handler attribute 'oncontentvisibilityautostatechange'/, + ); + + expect(metaService.getTag(selector)).toBeNull(); + }); + + it('should reject event handler attributes in addTags without adding tags', () => { + const selector = 'name="og:title"'; + const evil = 'alert(1)'; + + expect(() => + metaService.addTags([ + { + name: 'og:title', + style: 'content-visibility:auto', + oncontentvisibilityautostatechange: evil, + }, + ]), + ).toThrowError( + /NG05203: The Meta service does not allow setting event handler attribute 'oncontentvisibilityautostatechange'/, + ); + + expect(metaService.getTag(selector)).toBeNull(); + }); + it('should add httpEquiv meta tag as http-equiv', () => { metaService.addTag({httpEquiv: 'refresh', content: '3;url=http://test'}); @@ -156,6 +212,22 @@ describe('Meta service', () => { metaService.removeTagElement(actual); }); + it('should add attributes whose names match Object prototype keys', () => { + const meta = metaService.addTag({ + name: 'prototype-keys', + constructor: 'constructor', + toString: 'toString', + ['__proto__']: '__proto__', + })!; + + expect(meta.getAttribute('constructor')).toEqual('constructor'); + expect(meta.getAttribute('toString')).toEqual('toString'); + expect(meta.getAttribute('__proto__')).toEqual('__proto__'); + + // clean up + metaService.removeTagElement(meta); + }); + it('should escape selector values when deriving the match selector', () => { // This payload attempts to prematurely close the attribute selector // and match another attribute. diff --git a/packages/platform-browser/test/dom/dom_renderer_spec.ts b/packages/platform-browser/test/dom/dom_renderer_spec.ts index 2696e976d940..47945c968566 100644 --- a/packages/platform-browser/test/dom/dom_renderer_spec.ts +++ b/packages/platform-browser/test/dom/dom_renderer_spec.ts @@ -5,6 +5,7 @@ * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.dev/license */ +import {NgIf} from '@angular/common'; import {ChangeDetectionStrategy} from '@angular/compiler'; import {Component, Renderer2, ViewEncapsulation} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; @@ -28,18 +29,6 @@ describe('DefaultDomRendererV2', () => { let renderer: Renderer2; beforeEach(() => { - TestBed.configureTestingModule({ - declarations: [ - TestCmp, - SomeApp, - IsolatedShadowComponentParentApp, - SomeAppForCleanUp, - CmpEncapsulationEmulated, - CmpEncapsulationNone, - CmpEncapsulationShadow, - CmpEncapsulationIsolatedShadowWithChildren, - ], - }); renderer = TestBed.createComponent(TestCmp).componentInstance.renderer; }); @@ -113,9 +102,9 @@ describe('DefaultDomRendererV2', () => { }); }); - it('should style non-descendant components correctly with different types of encapsulation', () => { + it('should style non-descendant components correctly with different types of encapsulation', async () => { const fixture = TestBed.createComponent(SomeApp); - fixture.detectChanges(); + await fixture.whenStable(); const cmp = fixture.debugElement.query(By.css('cmp-shadow')).nativeElement; const shadowRoot = cmp.shadowRoot; @@ -129,9 +118,9 @@ describe('DefaultDomRendererV2', () => { expect(window.getComputedStyle(none).color).toEqual('rgb(0, 255, 0)'); }); - it('should encapsulate shadow DOM components, with child components inheriting from shadow styles not global styles', () => { + it('should encapsulate shadow DOM components, with child components inheriting from shadow styles not global styles', async () => { const fixture = TestBed.createComponent(IsolatedShadowComponentParentApp); - fixture.detectChanges(); + await fixture.whenStable(); const shadowcmp = fixture.debugElement.query(By.css('cmp-shadow-children')).nativeElement; const shadowRoot = shadowcmp.shadowRoot; @@ -145,9 +134,9 @@ describe('DefaultDomRendererV2', () => { expect(window.getComputedStyle(none).color).toEqual('rgb(255, 0, 0)'); }); - it('child components of shadow components should inherit browser defaults rather than their component styles', () => { + it('child components of shadow components should inherit browser defaults rather than their component styles', async () => { const fixture = TestBed.createComponent(IsolatedShadowComponentParentApp); - fixture.detectChanges(); + await fixture.whenStable(); const shadowcmp = fixture.debugElement.query(By.css('cmp-shadow-children')).nativeElement; const shadowRoot = shadowcmp.shadowRoot; @@ -161,9 +150,9 @@ describe('DefaultDomRendererV2', () => { expect(window.getComputedStyle(none).backgroundColor).toEqual('rgba(0, 0, 0, 0)'); }); - it('shadow components should not be polluted by child components styles when using ExperimentalIsolatedShadowDom', () => { + it('shadow components should not be polluted by child components styles when using ExperimentalIsolatedShadowDom', async () => { const fixture = TestBed.createComponent(IsolatedShadowComponentParentApp); - fixture.detectChanges(); + await fixture.whenStable(); const cmp = fixture.debugElement.query(By.css('cmp-shadow-children')).nativeElement; const shadowRoot = cmp.shadowRoot; @@ -192,12 +181,48 @@ describe('DefaultDomRendererV2', () => { expect(otherChild.parentNode).toBe(template.content); }); + it('should be able to insert a child when `refChild` is `null`', () => { + const parent = document.createElement('div'); + const child = document.createElement('div'); + + renderer.insertBefore(parent, child, null); + + expect(child.parentNode).toBe(parent); + }); + + describe('when the reference node was detached outside of Angular', () => { + it('should throw a descriptive error instead of a native NotFoundError', () => { + const parent = document.createElement('div'); + const refChild = document.createElement('span'); + const newChild = document.createElement('div'); + parent.appendChild(refChild); + + // pretend something outside Angular removed it + refChild.remove(); + + expect(() => renderer.insertBefore(parent, newChild, refChild)).toThrowError(/NG05106/); + expect(newChild.parentNode).toBeNull(); + }); + + it('should throw a descriptive error when the reference node was moved to another parent', () => { + const parent = document.createElement('div'); + const otherParent = document.createElement('div'); + const refChild = document.createElement('span'); + const newChild = document.createElement('div'); + parent.appendChild(refChild); + + otherParent.appendChild(refChild); + + expect(() => renderer.insertBefore(parent, newChild, refChild)).toThrowError(/NG05106/); + }); + }); + describe('should not cleanup styles of destroyed components when `REMOVE_STYLES_ON_COMPONENT_DESTROY` is `false`', () => { beforeEach(() => { TestBed.resetTestingModule(); TestBed.configureTestingModule({ - declarations: [SomeAppForCleanUp, CmpEncapsulationEmulated, CmpEncapsulationNone], + imports: [SomeAppForCleanUp], providers: [ { provide: REMOVE_STYLES_ON_COMPONENT_DESTROY, @@ -212,21 +237,22 @@ describe('DefaultDomRendererV2', () => { const compInstance = fixture.componentInstance; compInstance.showEmulatedComponents = true; - fixture.detectChanges(); + fixture.changeDetectorRef.markForCheck(); + await fixture.whenStable(); // verify style is in DOM expect(await styleCount(fixture, '.emulated')).toBe(1); // Remove a single instance of the component. compInstance.componentOneInstanceHidden = true; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); + await fixture.whenStable(); // Verify style is still in DOM expect(await styleCount(fixture, '.emulated')).toBe(1); // Hide all instances of the component compInstance.componentTwoInstanceHidden = true; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); + await fixture.whenStable(); // Verify style is still in DOM expect(await styleCount(fixture, '.emulated')).toBe(1); @@ -237,21 +263,22 @@ describe('DefaultDomRendererV2', () => { const compInstance = fixture.componentInstance; compInstance.showEmulatedComponents = false; - fixture.detectChanges(); + fixture.changeDetectorRef.markForCheck(); + await fixture.whenStable(); // verify style is in DOM expect(await styleCount(fixture, '.none')).toBe(1); // Remove a single instance of the component. compInstance.componentOneInstanceHidden = true; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); + await fixture.whenStable(); // Verify style is still in DOM expect(await styleCount(fixture, '.none')).toBe(1); // Hide all instances of the component compInstance.componentTwoInstanceHidden = true; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); + await fixture.whenStable(); // Verify style is still in DOM expect(await styleCount(fixture, '.none')).toBe(1); @@ -263,21 +290,22 @@ describe('DefaultDomRendererV2', () => { const fixture = TestBed.createComponent(SomeAppForCleanUp); const compInstance = fixture.componentInstance; compInstance.showEmulatedComponents = true; - fixture.detectChanges(); + fixture.changeDetectorRef.markForCheck(); + await fixture.whenStable(); // verify style is in DOM expect(await styleCount(fixture, '.emulated')).toBe(1); // Remove a single instance of the component. compInstance.componentOneInstanceHidden = true; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); + await fixture.whenStable(); // Verify style is still in DOM expect(await styleCount(fixture, '.emulated')).toBe(1); // Hide all instances of the component compInstance.componentTwoInstanceHidden = true; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); + await fixture.whenStable(); // Verify style is not in DOM expect(await styleCount(fixture, '.emulated')).toBe(0); @@ -288,21 +316,22 @@ describe('DefaultDomRendererV2', () => { const compInstance = fixture.componentInstance; compInstance.showEmulatedComponents = false; - fixture.detectChanges(); + fixture.changeDetectorRef.markForCheck(); + await fixture.whenStable(); // verify style is in DOM expect(await styleCount(fixture, '.none')).toBe(1); // Remove a single instance of the component. compInstance.componentOneInstanceHidden = true; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); + await fixture.whenStable(); // Verify style is still in DOM expect(await styleCount(fixture, '.none')).toBe(1); // Hide all instances of the component compInstance.componentTwoInstanceHidden = true; fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); + await fixture.whenStable(); // Verify style is not in DOM expect(await styleCount(fixture, '.emulated')).toBe(0); @@ -323,15 +352,12 @@ describe('DefaultDomRendererV2', () => { }); }); - it('should update an external sourceMappingURL by prepending the baseHref as a prefix', () => { + it('should update an external sourceMappingURL by prepending the baseHref as a prefix', async () => { document.head.innerHTML = ``; TestBed.resetTestingModule(); - TestBed.configureTestingModule({ - declarations: [CmpEncapsulationNoneWithSourceMap], - }); const fixture = TestBed.createComponent(CmpEncapsulationNoneWithSourceMap); - fixture.detectChanges(); + await fixture.whenStable(); expect(document.head.querySelector('style')?.textContent).toContain( '/*# sourceMappingURL=/base/cmp-none.css.map */', @@ -364,7 +390,7 @@ describe('DefaultDomRendererV2', () => { providers: [provideCssVarNamespacing('my-namespace')], }); const fixture = TestBed.createComponent(CmpNamespaceEmulated); - fixture.detectChanges(); + await fixture.whenStable(); expect(await styleCount(fixture, 'var(--my-namespace_foo)')).toBe(1); }); @@ -387,12 +413,12 @@ describe('DefaultDomRendererV2', () => { providers: [provideCssVarNamespacing('my-namespace')], }); const fixture = TestBed.createComponent(CmpNamespaceNone); - fixture.detectChanges(); + await fixture.whenStable(); expect(await styleCount(fixture, 'var(--my-namespace_foo)')).toBe(1); }); - it('should replace `%NS%` in styles for `ShadowDom` encapsulation', () => { + it('should replace `%NS%` in styles for `ShadowDom` encapsulation', async () => { @Component({ selector: 'cmp-namespace-shadow', template: '', @@ -410,7 +436,7 @@ describe('DefaultDomRendererV2', () => { providers: [provideCssVarNamespacing('my-namespace')], }); const fixture = TestBed.createComponent(CmpNamespaceShadow); - fixture.detectChanges(); + await fixture.whenStable(); const styles = fixture.nativeElement.shadowRoot.querySelectorAll( 'style', @@ -441,7 +467,7 @@ describe('DefaultDomRendererV2', () => { providers: [], // No `provideCssVarNamespacing`. }); const fixture = TestBed.createComponent(CmpNamespaceEmulated); - fixture.detectChanges(); + await fixture.whenStable(); expect(await styleCount(fixture, 'var(--foo)')).toBe(1); }); @@ -464,12 +490,12 @@ describe('DefaultDomRendererV2', () => { providers: [], // No `provideCssVarNamespacing`. }); const fixture = TestBed.createComponent(CmpNamespaceNone); - fixture.detectChanges(); + await fixture.whenStable(); expect(await styleCount(fixture, 'var(--foo)')).toBe(1); }); - it('should replace `%NS%` in styles for `ShadowDom` encapsulation', () => { + it('should replace `%NS%` in styles for `ShadowDom` encapsulation', async () => { @Component({ selector: 'cmp-namespace-shadow', template: '', @@ -487,7 +513,7 @@ describe('DefaultDomRendererV2', () => { providers: [], // No `provideCssVarNamespacing`. }); const fixture = TestBed.createComponent(CmpNamespaceShadow); - fixture.detectChanges(); + await fixture.whenStable(); const styles = fixture.nativeElement.shadowRoot.querySelectorAll( 'style', @@ -500,7 +526,7 @@ describe('DefaultDomRendererV2', () => { }); describe('style property bindings namespacing', () => { - it('should namespace style property bindings starting with `--`', () => { + it('should namespace style property bindings starting with `--`', async () => { @Component({ selector: 'cmp-style-prop-namespace', template: `
`, @@ -513,7 +539,7 @@ describe('DefaultDomRendererV2', () => { providers: [provideCssVarNamespacing('my-namespace')], }); const fixture = TestBed.createComponent(CmpStylePropNamespace); - fixture.detectChanges(); + await fixture.whenStable(); const div = fixture.nativeElement.querySelector('div'); expect(div.style.getPropertyValue('--my-namespace_foo')).toBe('blue'); @@ -668,7 +694,6 @@ async function styleCount( `, ], encapsulation: ViewEncapsulation.Emulated, - standalone: false, }) class CmpEncapsulationEmulated {} @@ -684,7 +709,6 @@ class CmpEncapsulationEmulated {} `, ], encapsulation: ViewEncapsulation.None, - standalone: false, }) class CmpEncapsulationNone {} @@ -702,7 +726,6 @@ class CmpEncapsulationNone {} `, ], encapsulation: ViewEncapsulation.None, - standalone: false, }) class CmpEncapsulationNoneWithSourceMap {} @@ -717,7 +740,6 @@ class CmpEncapsulationNoneWithSourceMap {} `, ], encapsulation: ViewEncapsulation.ShadowDom, - standalone: false, }) class CmpEncapsulationShadow {} @@ -735,7 +757,7 @@ class CmpEncapsulationShadow {} `, ], encapsulation: ViewEncapsulation.ExperimentalIsolatedShadowDom, - standalone: false, + imports: [CmpEncapsulationEmulated, CmpEncapsulationNone], }) class CmpEncapsulationIsolatedShadowWithChildren {} @@ -746,7 +768,7 @@ class CmpEncapsulationIsolatedShadowWithChildren {} `, - standalone: false, + imports: [CmpEncapsulationShadow, CmpEncapsulationEmulated, CmpEncapsulationNone], changeDetection: ChangeDetectionStrategy.Eager, }) export class SomeApp {} @@ -754,7 +776,7 @@ export class SomeApp {} @Component({ selector: 'shadow-parent-app-with-children', template: ` `, - standalone: false, + imports: [CmpEncapsulationIsolatedShadowWithChildren], changeDetection: ChangeDetectionStrategy.Eager, }) export class IsolatedShadowComponentParentApp {} @@ -762,7 +784,6 @@ export class IsolatedShadowComponentParentApp {} @Component({ selector: 'test-cmp', template: '', - standalone: false, changeDetection: ChangeDetectionStrategy.Eager, }) class TestCmp { @@ -778,7 +799,7 @@ class TestCmp { `, - standalone: false, + imports: [NgIf, CmpEncapsulationEmulated, CmpEncapsulationNone], changeDetection: ChangeDetectionStrategy.Eager, }) export class SomeAppForCleanUp { diff --git a/packages/platform-browser/test/testing_public_spec.ts b/packages/platform-browser/test/testing_public_spec.ts index d1fbc2d2635b..120abbf6fa1b 100644 --- a/packages/platform-browser/test/testing_public_spec.ts +++ b/packages/platform-browser/test/testing_public_spec.ts @@ -924,12 +924,7 @@ describe('public testing API', () => { let originalJasmineIt: (description: string, func: () => void) => jasmine.Spec; const patchJasmineIt = () => { - let resolve: (result: any) => void; - let reject: (error: any) => void; - const promise = new Promise((res, rej) => { - resolve = res; - reject = rej; - }); + const {promise, resolve, reject} = Promise.withResolvers(); const jasmineEnv = jasmine.getEnv() as any; originalJasmineIt = jasmineEnv.it; jasmineEnv.it = (description: string, fn: (done: DoneFn) => void): any => { diff --git a/packages/platform-server/BUILD.bazel b/packages/platform-server/BUILD.bazel index e63646889811..cd989800ce4f 100644 --- a/packages/platform-server/BUILD.bazel +++ b/packages/platform-server/BUILD.bazel @@ -49,7 +49,7 @@ ng_package( ], substitutions = { # Needed for the FESM files. - "\\./(.+)/third_party/domino/bundled-domino": "../third_party/domino/bundled-domino.mjs", + "(? { // These props are just a getter and cannot be changed continue; } - if (globalClone.hasOwnProperty(prop)) { + if (Object.hasOwn(globalClone, prop)) { (global as any)[prop] = (globalClone as any)[prop]; } else { delete (global as any)[prop]; diff --git a/packages/platform-server/src/http.ts b/packages/platform-server/src/http.ts index 6a0e8c06a60a..16e0eb4994ea 100644 --- a/packages/platform-server/src/http.ts +++ b/packages/platform-server/src/http.ts @@ -17,7 +17,7 @@ import {inject, Injectable, Provider, ɵRuntimeError as RuntimeError} from '@ang import {Observable} from 'rxjs'; import {RuntimeErrorCode} from './errors'; -import {resolveUrl} from './url'; +import {HTTP_OR_HTTPS_NO_AUTHORITY_REGEXP, resolveUrl} from './url'; @Injectable() /** @@ -73,9 +73,8 @@ function relativeUrlsTransformerInterceptorFn( request: HttpRequest, next: HttpHandlerFn, ): Observable> { - const trimmedUrl = request.url.trim(); - if (URL_SCHEMA_REGEXP.test(trimmedUrl)) { - // URLs with a schema should be left unchanged. + if (URL_SCHEMA_REGEXP.test(request.url) && !HTTP_OR_HTTPS_NO_AUTHORITY_REGEXP.test(request.url)) { + // URLs with a schema (and an authority for http(s)) should be left unchanged. return next(request); } diff --git a/packages/platform-server/src/url.ts b/packages/platform-server/src/url.ts index 8dad4ac18c80..2aea97d340f8 100644 --- a/packages/platform-server/src/url.ts +++ b/packages/platform-server/src/url.ts @@ -13,7 +13,14 @@ import {RuntimeErrorCode} from './errors'; /** * Matches http: or https: */ -const HTTP_OR_HTTPS_PROTOCOL_REGEX = /^https?:/i; +const HTTP_OR_HTTPS_PROTOCOL_REGEXP = /^https?:/i; + +/** + * Matches an HTTP or HTTPS URL that does not have an authority (i.e. missing `//` or `\\`). + * In the WHATWG standard, when resolved against a base of the same scheme, these URLs are relative. + * @internal + */ +export const HTTP_OR_HTTPS_NO_AUTHORITY_REGEXP = /^https?:(?![/\\]{2})/i; /** * Options for {@link resolveUrl}. @@ -57,13 +64,14 @@ export function resolveUrl( return originUrl || null; } - urlStr = urlStr.trim(); - // Fast-path: if the URL is a valid, standard absolute URL, parse and return it immediately. + // URLs with no authority (e.g. `http:/path` or `http:path`) must be resolved against the origin when one is provided. let resolved: URL | undefined; - try { - resolved = new URL(urlStr); - } catch {} + if (!originUrl || !HTTP_OR_HTTPS_NO_AUTHORITY_REGEXP.test(urlStr)) { + try { + resolved = new URL(urlStr); + } catch {} + } const {allowProtocolRelative = false, allowOriginChange = true} = options; if (resolved) { @@ -149,5 +157,7 @@ function isSafeOriginChange( return false; } - return HTTP_OR_HTTPS_PROTOCOL_REGEX.test(urlStr); + return ( + HTTP_OR_HTTPS_PROTOCOL_REGEXP.test(urlStr) && !HTTP_OR_HTTPS_NO_AUTHORITY_REGEXP.test(urlStr) + ); } diff --git a/packages/platform-server/test/full_app_hydration_spec.ts b/packages/platform-server/test/full_app_hydration_spec.ts index 7ad8c114c0c2..8c365afc2933 100644 --- a/packages/platform-server/test/full_app_hydration_spec.ts +++ b/packages/platform-server/test/full_app_hydration_spec.ts @@ -211,6 +211,26 @@ describe('platform-server full application hydration integration', () => { expect(ssrContents).not.toContain(extraChildNodes); expect(ssrContents).toContain('
Some content
'); }); + + it('should serialize input values correctly for both null and normal non-empty values during SSR', async () => { + @Component({ + selector: 'app', + template: ` + + + `, + }) + class AppComponent { + nullValue: string | null = null; + normalValue = 'hello'; + } + + const html = await ssr(AppComponent); + const ssrContents = getAppContents(html); + + expect(ssrContents).not.toContain('value="null"'); + expect(ssrContents).toContain('id="input-normal" value="hello"'); + }); }); describe('hydration', () => { @@ -1958,7 +1978,7 @@ describe('platform-server full application hydration integration', () => { const content = clientRootNode.querySelector('app-content'); expect(content.innerHTML).toBe( - 'Start Inner Start Hello World! Inner End Middle Span End', + 'Start Inner Start Hello World! Inner End Middle Span End', ); }); @@ -2010,7 +2030,7 @@ describe('platform-server full application hydration integration', () => { const content = clientRootNode.querySelector('app-content-outer'); expect(content.innerHTML).toBe( - 'Start Outer Start Span Hello World! Outer End Middle End', + 'Start Outer Start Span Hello World! Outer End Middle End', ); }); @@ -2247,7 +2267,7 @@ describe('platform-server full application hydration integration', () => { verifyClientAndSSRContentsMatch(ssrContents, clientRootNode); const div = clientRootNode.querySelector('div'); - expect(div.innerHTML).toMatch(/Some strong<\/strong> content/); + expect(div.innerHTML).toMatch(/Some strong<\/strong> content/); }); it('should support translations that remove elements', async () => { @@ -6232,6 +6252,288 @@ describe('platform-server full application hydration integration', () => { }); }); + it( + 'should throw a coded RuntimeError, not a raw TypeError, when an element ' + + 'instruction locates a Text node in production mode (ngDevMode off)', + async () => { + // Regression test. `locateOrCreateElementNodeImpl` always calls + // `hasSkipHydrationAttrOnRElement(native)`, which calls + // `native.hasAttribute(...)`. The `validateMatchingNode` check that would + // normally catch a "found a Text node instead of an element" mismatch + // only runs in dev mode, so it's removed from production builds. Without + // the extra `nodeType` guard added for this fix, if hydration finds a Text + // node here instead of an Element (because the server-rendered DOM didn't + // match what the client's compiled template expected), production would + // hit `native.hasAttribute`, which doesn't exist on a Text node, and throw + // a raw TypeError instead of a coded RuntimeError. + @Component({ + selector: 'app', + template: ` +
+

This is an original content

+ Bold text + Italic text +
+ `, + }) + class SimpleComponent { + private doc = inject(DOCUMENT); + private isServer = isPlatformServer(inject(PLATFORM_ID)); + ngAfterViewInit() { + // Only change the DOM on the server, right before it gets serialized. + // The client's compiled template still expects a `` element here, + // but the serialized (and later hydrated) DOM will have a plain Text + // node instead. + if (this.isServer) { + const b = this.doc.querySelector('b'); + const text = this.doc.createTextNode('Not an element anymore!'); + b?.parentNode?.replaceChild(text, b); + } + } + } + + const html = await ssr(SimpleComponent); + const ssrContents = getAppContents(html); + + expect(ssrContents).toContain(' { + // Regression test. When the client-rendered DOM has fewer nodes than the + // server-rendered HTML (e.g. a node was removed before hydration runs), + // `locateNextRNode` returns `null`. The `validateMatchingNode` check that + // would normally catch this only runs in dev mode, so it's removed from + // production builds. Without a dedicated null guard, production would fall + // through to `native.nodeType`, which throws a raw TypeError instead of a + // coded RuntimeError. + @Component({ + selector: 'app', + template: ` +
+

This is an original content

+ Bold text + Italic text +
+ `, + }) + class SimpleComponent { + private doc = inject(DOCUMENT); + private isServer = isPlatformServer(inject(PLATFORM_ID)); + ngAfterViewInit() { + // Only change the DOM on the server, right before it gets serialized. + // `` is the last child, so removing it means hydration's sibling walk + // runs off the end of the DOM (`nextSibling` is `null`) instead of landing + // on some other, wrongly-typed node — exercising the missing-node path + // rather than the node-mismatch path covered by the test above. + if (this.isServer) { + this.doc.querySelector('i')?.remove(); + } + } + } + + const html = await ssr(SimpleComponent); + const ssrContents = getAppContents(html); + + expect(ssrContents).toContain(''); + expect(error.message).not.toContain("reading 'nodeType'"); + } finally { + (globalThis as any).ngDevMode = previousNgDevMode; + } + }, + ); + + it( + 'should throw a coded RuntimeError, not a raw TypeError, when siblingAfter runs out ' + + 'of DOM siblings to skip in production mode (ngDevMode off)', + async () => { + // Regression test. `siblingAfter` walks forward a fixed number of DOM siblings + // (based on the server-serialized container size) to find a container's anchor + // comment node. The dev-mode check that would normally catch a missing sibling + // (`validateSiblingNodeExists`) is gated behind `ngDevMode`, so it's removed from + // production builds. If the client DOM has fewer real siblings than the server + // expected (here, two of the three `@for`-rendered items are removed before + // hydration runs), production keeps walking past the end of the DOM and throws a + // raw TypeError instead of a coded RuntimeError. + @Component({ + selector: 'app', + template: ` +
+ @for (item of items; track item) { +

{{ item }}

+ } +
+ `, + }) + class SimpleComponent { + items = [1, 2, 3]; + private doc = inject(DOCUMENT); + private isServer = isPlatformServer(inject(PLATFORM_ID)); + ngAfterViewInit() { + // Only change the DOM on the server, right before it gets serialized. The + // serialized container size still says "3 items", but the DOM hydration + // actually sees will only have 1. + if (this.isServer) { + const items = this.doc.querySelectorAll('#abc p'); + items[1]?.remove(); + items[2]?.remove(); + } + } + } + + const html = await ssr(SimpleComponent); + const ssrContents = getAppContents(html); + + expect(ssrContents).toContain(' { + // Regression test for getParentRElement() (node_manipulation.ts) receiving a null + // TNode. Unlike the siblingAfter/navigateToNode bugs above, this one isn't gated + // behind ngDevMode at all in the original code — it reproduces every time, with no + // need to simulate a production build. + // + // The mechanism: an @if/@switch branch's content is its own embedded template, with + // its own TView, built lazily the first time that branch is actually rendered + // (renderView() in render.ts). If an error is thrown partway through that *first* + // pass — here, a hydration node-mismatch on the branch's *second* child, so the + // first child's TNode is created but the second's never is — TView.firstCreatePass + // still gets flipped to false in render.ts's `catch` block before the error + // propagates, and the TView is marked `incompleteFirstPass`. Unlike a *component's* + // TView (which gets rebuilt from scratch next time via + // getOrCreateComponentTView()'s `incompleteFirstPass` check), nothing rebuilds an + // *embedded view's* TView. So the next time this exact branch is selected again — + // here, by flipping the condition off and back on — its instructions see + // `!tView.firstCreatePass` and read straight from `tView.data[slot]` instead of + // creating a fresh TNode, and the second child's slot is still null from the + // interrupted first pass. + let instance!: SimpleComponent; + + @Component({ + selector: 'app', + template: ` + @if (cond()) { + first + {{ text() }} + } @else { + else + } + `, + }) + class SimpleComponent { + cond = signal(true); + text = signal('orig'); + private doc = inject(DOCUMENT); + constructor() { + instance = this; + } + ngAfterViewInit() { + // Swap the second for a
, bypassing Angular's own node tracking + // (mimics a third-party script mutating the DOM, like the test above), so + // hydration hits a tag mismatch on the branch's SECOND node specifically, + // interrupting its first creation pass after the first node already succeeded. + const spans = this.doc.querySelectorAll('app span'); + if (spans.length >= 2) { + const bad = this.doc.createElement('div'); + bad.textContent = spans[1].textContent; + spans[1].replaceWith(bad); + } + } + } + + const html = await ssr(SimpleComponent); + resetTViewsFor(SimpleComponent); + + const appRef = await prepareEnvironmentAndHydrate(doc, html, SimpleComponent, { + envProviders: [withNoopErrorHandler()], + }); + + // Re-enter the same @if branch: leave it, then come back. This is what exposes the + // corrupted TView from the interrupted first pass above. + instance.cond.set(false); + appRef.tick(); + instance.cond.set(true); + + expect(() => appRef.tick()).toThrowError(/NG0510/); + }, + ); + it('should if there are any third-party scripts that manipulate the DOM', async () => { @Component({ selector: 'app', @@ -7737,6 +8039,146 @@ describe('platform-server full application hydration integration', () => { }); }); + describe('@boundary', () => { + it('should hydrate successfully when no error occurs', async () => { + const doc = TestBed.inject(DOCUMENT); + @Component({ + selector: 'app', + template: ` + @boundary { + Hello, {{ name }} + } @error { + Error occurred! + } + `, + changeDetection: ChangeDetectionStrategy.Eager, + }) + class SimpleComponent { + name = 'Frodo'; + } + + const html = await ssr(SimpleComponent); + const ssrContents = getAppContents(html); + + expect(ssrContents).toContain('(appRef); + appRef.tick(); + + const clientRootNode = compRef.location.nativeElement; + verifyAllNodesClaimedForHydration(clientRootNode); + verifyClientAndSSRContentsMatch(ssrContents, clientRootNode); + expect(clientRootNode.textContent).toContain('Hello, Frodo'); + + compRef.instance.name = 'Bilbo'; + compRef.changeDetectorRef.detectChanges(); + expect(clientRootNode.textContent).toContain('Hello, Bilbo'); + }); + + it('should render fallback during SSR and recover to primary during client hydration if error is resolved', async () => { + const doc = TestBed.inject(DOCUMENT); + @Component({ + selector: 'child', + template: 'Child rendering...', + }) + class ChildComponent { + @Input() fail = false; + ngOnInit() { + if (this.fail) { + throw new Error('Server error'); + } + } + } + + @Component({ + selector: 'app', + imports: [ChildComponent], + template: ` + @boundary { + + } @error { + Error occurred on server! + } + `, + changeDetection: ChangeDetectionStrategy.Eager, + }) + class SimpleComponent { + fail = isPlatformServer(inject(PLATFORM_ID)); + } + + // 1. SSR where an error occurs + const html = await ssr(SimpleComponent); + const ssrContents = getAppContents(html); + + // Ensure server rendered the fallback + expect(ssrContents).toContain('Error occurred on server!'); + expect(ssrContents).not.toContain('Child rendering...'); + + // 2. Hydration where error does NOT occur (fail is false on client) + const appRef = await prepareEnvironmentAndHydrate(doc, html, SimpleComponent); + const compRef = getComponentRef(appRef); + appRef.tick(); + + const clientRootNode = compRef.location.nativeElement; + + // Since the server rendered fallback but client successfully rendered primary, + // it shouldn't crash, and the fallback should be replaced with primary. + expect(clientRootNode.textContent).toContain('Child rendering...'); + expect(clientRootNode.textContent).not.toContain('Error occurred on server!'); + }); + + it('should render fallback during SSR and remain in error state during client hydration if error persists', async () => { + const doc = TestBed.inject(DOCUMENT); + @Component({ + selector: 'child', + template: 'Child rendering...', + }) + class ChildComponent { + @Input() fail = false; + ngOnInit() { + if (this.fail) { + throw new Error('Persistent error'); + } + } + } + + @Component({ + selector: 'app', + imports: [ChildComponent], + template: ` + @boundary { + + } @error { + Error occurred on server and client! + } + `, + changeDetection: ChangeDetectionStrategy.Eager, + }) + class SimpleComponent {} + + // 1. SSR where an error occurs + const html = await ssr(SimpleComponent); + const ssrContents = getAppContents(html); + + expect(ssrContents).toContain('Error occurred on server and client!'); + + // 2. Hydration where error DOES occur again + const appRef = await prepareEnvironmentAndHydrate(doc, html, SimpleComponent); + const compRef = getComponentRef(appRef); + appRef.tick(); + + const clientRootNode = compRef.location.nativeElement; + + // The fallback should still be rendered (either hydrated or re-created) + expect(clientRootNode.textContent).toContain('Error occurred on server and client!'); + }); + }); + describe('Router', () => { it('should wait for lazy routes before triggering post-hydration cleanup', async () => { const ngZone = TestBed.inject(NgZone); diff --git a/packages/platform-server/test/incremental_hydration_spec.ts b/packages/platform-server/test/incremental_hydration_spec.ts index 5661c79da256..e8f8a318b8b0 100644 --- a/packages/platform-server/test/incremental_hydration_spec.ts +++ b/packages/platform-server/test/incremental_hydration_spec.ts @@ -10,6 +10,7 @@ import { APP_ID, ApplicationRef, Component, + Directive, ɵDEHYDRATED_BLOCK_REGISTRY as DEHYDRATED_BLOCK_REGISTRY, destroyPlatform, ɵgetDocument as getDocument, @@ -21,10 +22,13 @@ import { PLATFORM_ID, Provider, QueryList, + ɵresetIncrementalHydrationRuntimeForTests as resetIncrementalHydrationRuntimeForTests, ɵresetIncrementalHydrationEnabledWarnedForTests as resetIncrementalHydrationEnabledWarnedForTests, signal, ɵTimerScheduler as TimerScheduler, + ViewChild, ViewChildren, + ViewContainerRef, ɵDEFER_BLOCK_DEPENDENCY_INTERCEPTOR, } from '@angular/core'; @@ -1317,6 +1321,71 @@ describe('platform-server partial hydration integration', () => { expect(activeObservers.length).toBe(1); expect(activeObservers[0].options).toEqual({rootMargin: '123px', threshold: 0.5}); }); + + it('should create an IntersectionObserver for a nested routed viewport block', async () => { + @Component({ + selector: 'routed', + template: ` + @defer (hydrate on interaction) { +
+ @defer (hydrate on viewport({rootMargin: '123px', threshold: 0.5})) { +
defer block rendered!
+ } @placeholder { + Inner block placeholder + } +
+ } @placeholder { + Outer block placeholder + } + `, + }) + class RoutedComponent {} + + @Component({ + selector: 'app', + imports: [RouterOutlet], + template: '', + }) + class SimpleComponent {} + + const providers = [ + {provide: APP_ID, useValue: 'custom-app-id'}, + {provide: PlatformLocation, useClass: MockPlatformLocation}, + provideRouter([{path: '', component: RoutedComponent}]), + ] as unknown as Provider[]; + const hydrationFeatures = () => [withIncrementalHydration()]; + + const html = await ssr(SimpleComponent, {envProviders: providers, hydrationFeatures}); + const ssrContents = getAppContents(html); + + expect(ssrContents).toContain( + '"__nghDeferData__":{"d0":{"r":1,"s":2},"d1":{"r":1,"s":2,"t":[{"trigger":2,"intersectionObserverOptions":{"rootMargin":"123px","threshold":0.5}}],"p":"d0"}}', + ); + + // Internal cleanup before we do server->client transition in this test. + resetTViewsFor(SimpleComponent, RoutedComponent); + // The root view has no hydration triggers, so verify that the routed view activates a + // cold client runtime. + resetIncrementalHydrationRuntimeForTests(); + + //////////////////////////////// + const doc = getDocument(); + const appRef = await prepareEnvironmentAndHydrate(doc, html, SimpleComponent, { + envProviders: [...providers, {provide: PLATFORM_ID, useValue: 'browser'}], + hydrationFeatures, + }); + appRef.tick(); + await appRef.whenStable(); + + expect(activeObservers.length).toBe(1); + expect(activeObservers[0].options).toEqual({rootMargin: '123px', threshold: 0.5}); + + const article = doc.getElementsByTagName('article')[0]; + MockIntersectionObserver.invokeCallbacksForElement(article, true); + await appRef.whenStable(); + + expect(activeObservers[0].observedElements.size).toBe(0); + }); }); it('immediate', async () => { @@ -2873,6 +2942,211 @@ describe('platform-server partial hydration integration', () => { expect(contract.instance!.cleanUp).not.toHaveBeenCalled(); expect(registry.cleanup).toHaveBeenCalledTimes(1); }); + + it( + 'should not remove a still-pending dehydrated view (e.g. from a plain ' + + 'ViewContainerRef.createComponent() call guarded by PendingTasks) when an ' + + 'unrelated @defer block on the same page hydrates first', + async () => { + // Represents content created dynamically via `ViewContainerRef.createComponent()` + // -- NOT a `@defer` block -- so its dehydrated view carries no `DEFER_BLOCK_ID`. + @Component({ + selector: 'dynamic-cmp', + template: `

Dynamically created

`, + }) + class DynamicCmp {} + + @Component({ + selector: 'app', + template: ` + @defer (hydrate on immediate) { +

defer block

+ } + + `, + }) + class SimpleComponent { + @ViewChild('container', {read: ViewContainerRef, static: true}) + container!: ViewContainerRef; + + private readonly pendingTasks = inject(PendingTasks); + + ngAfterViewInit() { + // Mirrors a real dynamic-component loader: creation is guarded by + // `PendingTasks` (so SSR waits for it), but the creation itself is + // genuinely async (e.g. behind a lazy-loaded chunk) on the client -- + // giving the unrelated @defer block above time to hydrate and run + // its cleanup first. + this.pendingTasks.run(async () => { + await dynamicImportOf(DynamicCmp, 101); + this.container.createComponent(DynamicCmp); + }); + } + } + + const appId = 'custom-app-id'; + const providers = [{provide: APP_ID, useValue: appId}]; + const hydrationFeatures = () => [withIncrementalHydration()]; + + const html = await ssr(SimpleComponent, {envProviders: providers, hydrationFeatures}); + const ssrContents = getAppContents(html); + + expect(ssrContents).toContain('

Dynamically created

'); + expect(ssrContents).toContain('

defer block

'); + + // Internal cleanup before we do server->client transition in this test. + resetTViewsFor(SimpleComponent, DynamicCmp); + + //////////////////////////////// + const doc = getDocument(); + const appRef = await prepareEnvironmentAndHydrate(doc, html, SimpleComponent, { + envProviders: [...providers, {provide: PLATFORM_ID, useValue: 'browser'}], + hydrationFeatures, + }); + + appRef.tick(); + + // Let the @defer (hydrate on immediate) block finish hydrating -- its + // completion triggers a GLOBAL `cleanupDehydratedViews` sweep over every + // LView on the page -- well before our own PendingTasks-guarded dynamic + // component creation resolves (that's still ~101ms away). + await timeout(20); + + // BUG: `dynamic-content` was never claimed or replaced by anything at + // this point -- our own creation logic hasn't run yet. It should still + // be exactly the server-rendered content sitting untouched in the DOM. + // Before the fix, the @defer block's cleanup sweep incorrectly deletes + // it here because it carries no DEFER_BLOCK_ID, well before the code + // that's actually supposed to claim it ever gets a chance to run. + expect(doc.getElementById('dynamic-content')).not.toBeNull(); + + await allPendingDynamicImports(); + appRef.tick(); + await appRef.whenStable(); + + expect(doc.getElementById('dynamic-content')).not.toBeNull(); + }, + ); + + it( + 'should not remove a dehydrated view that a PendingTasks-guarded ' + + 'createComponent() inside the hydrating @defer block is about to claim', + async () => { + @Component({selector: 'late-cmp', template: `

Late content

`}) + class LateCmp {} + + // Creates `LateCmp` after a slow dynamic import, holding a pending task the whole time. + @Directive({selector: '[lateHost]'}) + class LateHost { + private readonly vcr = inject(ViewContainerRef); + private readonly pendingTasks = inject(PendingTasks); + + ngOnInit() { + this.pendingTasks.run(async () => { + await dynamicImportOf(LateCmp, 101); + this.vcr.createComponent(LateCmp); + }); + } + } + + @Component({ + selector: 'app', + imports: [LateHost], + template: ` +
+ @defer (hydrate on immediate) { + + } +
+ `, + }) + class SimpleComponent {} + + const appId = 'custom-app-id'; + const providers = [{provide: APP_ID, useValue: appId}]; + const hydrationFeatures = () => [withIncrementalHydration()]; + + const html = await ssr(SimpleComponent, {envProviders: providers, hydrationFeatures}); + expect(getAppContents(html)).toContain('

Late content

'); + + // Internal cleanup before we do server->client transition in this test. + resetTViewsFor(SimpleComponent, LateCmp); + + //////////////////////////////// + const doc = getDocument(); + const appRef = await prepareEnvironmentAndHydrate(doc, html, SimpleComponent, { + envProviders: [...providers, {provide: PLATFORM_ID, useValue: 'browser'}], + hydrationFeatures, + }); + const serverNode = doc.getElementById('late-content'); + expect(serverNode).not.toBeNull(); + + await appRef.whenStable(); + await allPendingDynamicImports(); + appRef.tick(); + await appRef.whenStable(); + + // The server-rendered node is claimed by `createComponent()`, not deleted and rebuilt. + expect(serverNode!.isConnected).toBeTrue(); + expect(doc.getElementById('late-content')).toBe(serverNode); + }, + ); + + it('should skip the cleanup when the app is destroyed while it waits for stability', async () => { + let hydratedCount = 0; + + @Component({selector: 'block-content', template: `

defer block

`}) + class BlockContent { + constructor() { + if (!isPlatformServer(inject(PLATFORM_ID))) { + hydratedCount++; + } + } + } + + @Component({ + selector: 'app', + imports: [BlockContent], + template: ` + @defer (hydrate on immediate) { + + } + `, + }) + class SimpleComponent {} + + const appId = 'custom-app-id'; + const providers = [{provide: APP_ID, useValue: appId}]; + const hydrationFeatures = () => [withIncrementalHydration()]; + + const html = await ssr(SimpleComponent, {envProviders: providers, hydrationFeatures}); + + // Internal cleanup before we do server->client transition in this test. + resetTViewsFor(SimpleComponent, BlockContent); + + //////////////////////////////// + const doc = getDocument(); + const appRef = await prepareEnvironmentAndHydrate(doc, html, SimpleComponent, { + envProviders: [...providers, {provide: PLATFORM_ID, useValue: 'browser'}], + hydrationFeatures, + }); + const registry = appRef.injector.get(DEHYDRATED_BLOCK_REGISTRY); + spyOn(registry, 'cleanup').and.callThrough(); + + // This task is never removed, so the cleanup keeps waiting for stability. + appRef.injector.get(PendingTasks).add(); + appRef.tick(); + await timeout(60); + + // The block is hydrated, but its cleanup is still waiting. + expect(hydratedCount).toBe(1); + expect(registry.cleanup).not.toHaveBeenCalled(); + + appRef.destroy(); + await timeout(60); + + expect(registry.cleanup).not.toHaveBeenCalled(); + }); }); describe('Router', () => { @@ -3068,6 +3342,9 @@ describe('platform-server partial hydration integration', () => { expect(ssrContents).toContain(`

nope

`); resetTViewsFor(SimpleComponent, LazyCmp); + // The immediate trigger is nested in a lazy route, so verify that it is discovered with a + // cold client runtime. + resetIncrementalHydrationRuntimeForTests(); const doc = getDocument(); const appRef = await prepareEnvironmentAndHydrate(doc, html, SimpleComponent, { @@ -3084,6 +3361,75 @@ describe('platform-server partial hydration integration', () => { ); expect(appHostNode.outerHTML).toContain(`

yup

`); }); + + it( + 'should not remove the server-rendered DOM of a lazy route that is still loading ' + + 'when a @defer block in the app shell hydrates', + async () => { + @Component({selector: 'routed-page', template: `

Routed page

`}) + class RoutedPage {} + + @Component({ + selector: 'shell-widget', + template: ``, + }) + class ShellWidget { + clicks = signal(0); + } + + const routes: Routes = [{path: '', loadComponent: () => dynamicImportOf(RoutedPage, 100)}]; + + // The `@defer` block sits outside the ``, so it hydrates while the + // navigation is still waiting for the lazy route. + @Component({ + selector: 'app', + imports: [RouterOutlet, ShellWidget], + template: ` +
+ @defer (hydrate on immediate) { + + } +
+
+ `, + }) + class SimpleComponent {} + + const appId = 'custom-app-id'; + const providers = [ + {provide: APP_ID, useValue: appId}, + {provide: PlatformLocation, useClass: MockPlatformLocation}, + provideRouter(routes), + ] as unknown as Provider[]; + const hydrationFeatures = () => [withIncrementalHydration()]; + + const html = await ssr(SimpleComponent, {envProviders: providers, hydrationFeatures}); + expect(getAppContents(html)).toContain('

Routed page

'); + + // Internal cleanup before we do server->client transition in this test. + resetTViewsFor(SimpleComponent, RoutedPage, ShellWidget); + + //////////////////////////////// + const doc = getDocument(); + const appRef = await prepareEnvironmentAndHydrate(doc, html, SimpleComponent, { + envProviders: [...providers], + hydrationFeatures, + }); + const serverNode = doc.getElementById('routed-content'); + expect(serverNode).not.toBeNull(); + + await appRef.whenStable(); + await allPendingDynamicImports(); + appRef.tick(); + await appRef.whenStable(); + + // The router claims the server-rendered node, it is not deleted and rebuilt. + expect(serverNode!.isConnected).toBeTrue(); + expect(doc.getElementById('routed-content')).toBe(serverNode); + }, + ); }); describe('misconfiguration', () => { diff --git a/packages/platform-server/test/integration_spec.ts b/packages/platform-server/test/integration_spec.ts index ace92bf8ca2a..67760f0a7a74 100644 --- a/packages/platform-server/test/integration_spec.ts +++ b/packages/platform-server/test/integration_spec.ts @@ -1582,6 +1582,51 @@ class HiddenModule {} }); }); + it('should resolve non-breaking space prefixed URLs as relative paths on the same origin', async () => { + ref.injector.get(NgZone).run(() => { + http.get('\u00A0//attacker.example/collect').subscribe((body) => { + expect(body).toEqual('success!'); + }); + mock + .expectOne('http://localhost:4000/%C2%A0//attacker.example/collect') + .flush('success!'); + }); + }); + + it('should resolve unicode whitespace prefixed scheme URLs as relative paths on the same origin', async () => { + const urls = [ + ['\u00A0http://attacker.example/collect', '%C2%A0'], + ['\uFEFFhttp://attacker.example/collect', '%EF%BB%BF'], + ]; + + ref.injector.get(NgZone).run(() => { + for (const [url, encodedWhitespace] of urls) { + http.get(url).subscribe((body) => { + expect(body).toEqual('success!'); + }); + mock + .expectOne( + `http://localhost:4000/${encodedWhitespace}http://attacker.example/collect`, + ) + .flush('success!'); + } + }); + }); + + it('should resolve scheme URLs without authority as relative paths on the same origin', async () => { + ref.injector.get(NgZone).run(() => { + http.get('http:/localhost:9999/steal-a').subscribe((body) => { + expect(body).toEqual('success!'); + }); + mock.expectOne('http://localhost:4000/localhost:9999/steal-a').flush('success!'); + + http.get('http:localhost:9999/steal-b').subscribe((body) => { + expect(body).toEqual('success!'); + }); + mock.expectOne('http://localhost:4000/localhost:9999/steal-b').flush('success!'); + }); + }); + it('should reject backslash bypass SSRF attempts in relative requests and throw a suspicious origin error', async () => { const badUrls = [ '/\\attacker.com', diff --git a/packages/platform-server/test/render_spec.ts b/packages/platform-server/test/render_spec.ts index 34b100fcef87..54126d12d524 100644 --- a/packages/platform-server/test/render_spec.ts +++ b/packages/platform-server/test/render_spec.ts @@ -35,4 +35,15 @@ describe('renderApplication', () => { const html = await ssr(SomeComponent); expect(html).toContain('aria-label="a third label"'); }); + it('should not serialize MathML script elements', async () => { + @Component({ + selector: 'app', + template: '', + }) + class SomeComponent {} + + const html = await ssr(SomeComponent, {enableHydration: false}); + + expect(html).not.toContain(' { const url = 'ht\ntp://evil.com/path'; expect(() => resolveUrl(url, 'http://test.com')).toThrowError(/NG05703/); }); + + it('should not trim unicode whitespace into protocol-relative URLs', () => { + const urls = ['\u00A0//attacker.example/collect', '\uFEFF//attacker.example/collect']; + + for (const urlStr of urls) { + const urlWithProtocolRelative = resolveUrl(urlStr, 'http://test.com', { + allowProtocolRelative: true, + }); + expect(urlWithProtocolRelative.origin).toBe('http://test.com'); + expect(urlWithProtocolRelative.pathname).toContain('//attacker.example/collect'); + + const urlWithoutProtocolRelative = resolveUrl(urlStr, 'http://test.com'); + expect(urlWithoutProtocolRelative.origin).toBe('http://test.com'); + expect(urlWithoutProtocolRelative.pathname).toContain('//attacker.example/collect'); + } + }); + + it('should resolve scheme URLs without authority against origin of the same scheme', () => { + const urlA = resolveUrl('http:/attacker.example/steal', 'http://test.com'); + expect(urlA.origin).toBe('http://test.com'); + expect(urlA.pathname).toBe('/attacker.example/steal'); + + const urlB = resolveUrl('http:attacker.example/steal', 'http://test.com'); + expect(urlB.origin).toBe('http://test.com'); + expect(urlB.pathname).toBe('/attacker.example/steal'); + + const urlHttpsA = resolveUrl('https:/attacker.example/steal', 'https://test.com'); + expect(urlHttpsA.origin).toBe('https://test.com'); + expect(urlHttpsA.pathname).toBe('/attacker.example/steal'); + + const urlHttpsB = resolveUrl('https:attacker.example/steal', 'https://test.com'); + expect(urlHttpsB.origin).toBe('https://test.com'); + expect(urlHttpsB.pathname).toBe('/attacker.example/steal'); + + const urlBackslash = resolveUrl('http:\\attacker.example/steal', 'http://test.com'); + expect(urlBackslash.origin).toBe('http://test.com'); + expect(urlBackslash.pathname).toBe('/attacker.example/steal'); + }); + + it('should throw on scheme URLs without authority when origin scheme differs', () => { + expect(() => resolveUrl('http:/attacker.example/steal', 'https://test.com')).toThrowError( + /NG05703/, + ); + expect(() => resolveUrl('http:attacker.example/steal', 'https://test.com')).toThrowError( + /NG05703/, + ); + expect(() => resolveUrl('https:/attacker.example/steal', 'http://test.com')).toThrowError( + /NG05703/, + ); + expect(() => resolveUrl('https:attacker.example/steal', 'http://test.com')).toThrowError( + /NG05703/, + ); + expect(() => resolveUrl('http:\\attacker.example/steal', 'https://test.com')).toThrowError( + /NG05703/, + ); + }); }); describe('without origin', () => { @@ -76,6 +132,7 @@ describe('resolveUrl', () => { expect(resolveUrl('deep/path')).toBeNull(); expect(resolveUrl('/\\attacker.com/deep/path')).toBeNull(); expect(resolveUrl('\\\\attacker.com/deep/path')).toBeNull(); + expect(resolveUrl('\u00A0//attacker.com/deep/path')).toBeNull(); }); it('should parse valid absolute URLs', () => { diff --git a/packages/platform-server/test/utils_spec.ts b/packages/platform-server/test/utils_spec.ts index 198eae72e329..a5410b97a9b6 100644 --- a/packages/platform-server/test/utils_spec.ts +++ b/packages/platform-server/test/utils_spec.ts @@ -61,7 +61,11 @@ describe('allowedHosts validation in renderApplication', () => { }); it('should reject URLs with wrong host', async () => { - const relativeUrls = ['http://evil.com/deep/path', 'ht\ttp://evil.com/deep/path']; + const relativeUrls = [ + 'http://evil.com/deep/path', + 'http:/evil.com/deep/path', + 'ht\ttp://evil.com/deep/path', + ]; for (const url of relativeUrls) { await expectAsync( diff --git a/packages/private/testing/src/browser_utils.ts b/packages/private/testing/src/browser_utils.ts index 69c42ec84cee..0681cf8ea531 100644 --- a/packages/private/testing/src/browser_utils.ts +++ b/packages/private/testing/src/browser_utils.ts @@ -9,6 +9,11 @@ import {ɵgetDOM as getDOM} from '@angular/common'; import {NgZone} from '@angular/core'; +/** Waits for callbacks queued for the next animation frame to run. */ +export function nextAnimationFrame(): Promise { + return new Promise((resolve) => requestAnimationFrame(() => resolve())); +} + export function dispatchEvent(element: any, eventType: any): Event { const evt: Event = getDOM().getDefaultDocument().createEvent('Event'); evt.initEvent(eventType, true, true); diff --git a/packages/private/testing/src/utils.ts b/packages/private/testing/src/utils.ts index 539ad439de59..e1e991c2c12c 100644 --- a/packages/private/testing/src/utils.ts +++ b/packages/private/testing/src/utils.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ import {TestBed} from '../../../core/testing'; -import {ɵresetJitOptions as resetJitOptions} from '@angular/core'; +import {ApplicationRef, ɵresetJitOptions as resetJitOptions} from '@angular/core'; /** * Wraps a function in a new function which sets up document and HTML for running a test. @@ -298,3 +298,44 @@ export async function waitFor( await new Promise((resolve) => void realSetTimeout(resolve, interval)); } } + +/** + * Executes a function and waits for the application to become stable. + * + * Use this when the action triggers asynchronous work + * (e.g. a `resource` loader) that must complete before assertions run. + * + * @example + * ```ts + * const res = await actAsync(() => resource({ loader: fetchUser, injector })); + * expect(res.status()).toBe('resolved'); + * ``` + */ +export async function actAsync(fn: () => T): Promise { + const result = fn(); + await TestBed.inject(ApplicationRef).whenStable(); + return result; +} + +/** + * Executes a function and flushes the Angular scheduler synchronously. + * + * Use this when the action triggers synchronous state + * changes that need to be flushed through the scheduler before assertions run. + * + * @example + * ```ts + * const fixture = act(() => TestBed.createComponent(TestComp)); + * expect(fixture.nativeElement.textContent).toBe('initial'); + * + * act(() => fixture.componentInstance.value.set('updated')); + * expect(fixture.nativeElement.textContent).toBe('updated'); + * ``` + */ +export function act(fn: () => T): T { + try { + return fn(); + } finally { + TestBed.tick(); + } +} diff --git a/packages/router/docs/injector_cleanup.md b/packages/router/docs/injector_cleanup.md index c93b9d97a486..59739aa6dbc6 100644 --- a/packages/router/docs/injector_cleanup.md +++ b/packages/router/docs/injector_cleanup.md @@ -87,13 +87,39 @@ The current parent-first (pre-order) traversal was chosen for its implementation ### Destruction During Activation Traversal -Another alternative considered was performing the destruction of injectors during the activation traversal itself. For instance, if a route is being deactivated and not stored for reuse, its injector could be destroyed immediately. +Another alternative considered was performing the destruction of injectors during route deactivation in `ActivateRoutes` (similar to how components and `_localInjector` are destroyed). -- **Pros**: This approach would not require any additional traversal logic, as the router is already traversing the route tree during activation. -- **Cons**: - - This approach is not viable because of how the router handles route reuse. A child route can be stored for reuse even if its parent is not. Since the activation traversal is top-down, the router might encounter a parent route that is not being reused and destroy its injector, only to later discover that one of its children _is_ being reused and requires the parent's injector to remain alive. By deferring cleanup until after navigation completes, we can accurately identify all necessary injectors by looking at the final state of both the active route tree and the stored handles. - - We could handle the problem of descendants detaching after the parent injector was destroyed by _not_ querying `shouldDetach` in the first place on any descendants if the a parent injector was destroyed. However, this couples the detach logic with the injector destroy. You now need to be careful about destroying parents if you're going to detach a child. Our current approach handles this for you so the concerns are kept separate and the Router handles the question of what even can be destroyed safely. - - Additionally, there would be no good, safe way to destroy the injector for a previously stored handle that is being disposed of. For example, if a developer decides to drop a stored handle, they would need to manually destroy its injector, which could easily be done at the wrong time or forgotten entirely. +- **Pros**: Would eliminate the need for an additional post-navigation traversal pass. +- **Cons**: This approach is not viable for injectors attached to static `Route` configurations: + 1. **Re-activation of the Same Route Config**: When navigating between parameter changes where the route is not reused (e.g., `/detail/1` to `/detail/2` with `shouldReuseRoute` returning `false`), `/detail/2` binds to `detailRoute._injector` during recognition. If deactivating `/detail/1` destroyed `detailRoute._injector`, it would destroy the injector that `/detail/2` has already captured and is about to activate with. + 2. **Cross-Navigation Detached Handles**: While deactivation within a single transition is bottom-up (children are deactivated before parents), a child route could have been detached and stored in `RouteReuseStrategy` in an earlier navigation. If the parent route is deactivated in a subsequent navigation, destroying the parent's injector would break the DI hierarchy of the stored child handle. A local deactivation pass cannot detect this dependency without inspecting the entire reuse cache. + 3. **Handling Discarded Handles and Preloading**: Injectors created during route preloading, or injectors left behind when a handle is evicted from `RouteReuseStrategy`, never undergo deactivation. A post-navigation sweep is the only mechanism that can reconcile these unreferenced injectors. + +### Fundamental Differences from `ActivatedRoute._localInjector` + +With the introduction of route-level resources, the router created a local `EnvironmentInjector` on `ActivatedRoute` instances (`route._localInjector`). A natural question is why `Route._injector` (and `Route._loadedInjector`) cannot share the exact same destruction timing and lifecycle as `ActivatedRoute._localInjector`: + +- `_localInjector` is destroyed immediately during deactivation in `ActivateRoutes` (`deactivateRouteAndOutlet`). +- `_localInjector` is rolled back on `NavigationCancel` or `NavigationError` in `rollbackState`. +- `_localInjector` is destroyed on handle eviction via `destroyDetachedRouteHandle(handle)`. + +The reasons these two injector types cannot share the same destruction logic are fundamental to where they live and their role in the DI hierarchy: + +1. **Storage Target & Cardinality (Static Definition vs. Activation Instance)**: + - `Route._injector` is attached directly to the **static `Route` definition**. When navigating between parameter changes of the same route config where the route is not reused (e.g., `/detail/1` to `/detail/2` with `shouldReuseRoute` returning `false`), both activations share the same static `Route` definition. During URL recognition, the incoming `/detail/2` snapshot captures the existing `detailRoute._injector`. If deactivation of `/detail/1` destroyed `detailRoute._injector`, it would destroy the injector that `/detail/2` has already captured and is about to activate its component with. + - `_localInjector` is an instance property on `ActivatedRoute`. `/detail/1` and `/detail/2` have completely distinct `ActivatedRoute` instances (`activatedRoute1._localInjector` vs. `activatedRoute2._localInjector`). Destroying instance 1 during deactivation has no impact on instance 2. + +2. **DI Hierarchy Position (Ancestor vs. Leaf)**: + - `Route._injector` is an **ancestor injector** for all child routes and their component hierarchies. If a child route was detached and stored in `RouteReuseStrategy` in an earlier navigation, destroying a deactivated parent's `Route._injector` severs the DI hierarchy for that stored child handle. When the child is later reattached, any dependency lookups ascending to the parent injector will fail. A local deactivation step cannot detect this dependency without inspecting the entire reuse cache. + - `_localInjector` is strictly a **leaf injector** containing only route-level resources for that specific route. Descendant routes do not inherit from a parent route's `_localInjector` (they inherit from `parentSnapshot._environmentInjector`, which points to `Route._injector`). Therefore, destroying a deactivated parent's `_localInjector` never corrupts a child's DI chain. + +3. **Creation Timing & Non-Activation Lifecycles**: + - `Route._injector` is created during URL recognition (`canMatch`) or preloading (`RouterPreloader`), well before activation. A preloaded route may never be activated, so it can never be deactivated; only a post-navigation sweep can reclaim it. + - `_localInjector` is created strictly during preactivation (`setupAndRunResources`) for a specific `ActivatedRoute`, so its lifecycle is 1:1 with that route's activation and deactivation. + +4. **Detached Handle Disposal**: + - `destroyDetachedRouteHandle(handle)` can safely destroy `handle.route.value._localInjector` because that injector belongs exclusively to that handle's `ActivatedRoute` instance. + - It cannot destroy `handle.route.value.routeConfig._injector`, because that static `Route` config might currently be active in another outlet or shared by another cached handle. ### 3.2. Manual DetachedRouteHandle Cleanup diff --git a/packages/router/src/activated_route_injector_feature.ts b/packages/router/src/activated_route_injector_feature.ts deleted file mode 100644 index 016d54cfa231..000000000000 --- a/packages/router/src/activated_route_injector_feature.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.dev/license - */ - -import {InjectionToken} from '@angular/core'; -import {OperatorFunction} from 'rxjs'; -import type {NavigationTransition} from './navigation_transition'; - -export interface ActivatedRouteInjectorFeature { - operator(): OperatorFunction; -} - -export const ACTIVATED_ROUTE_INJECTOR_FEATURE = new InjectionToken( - typeof ngDevMode === 'undefined' || ngDevMode ? 'ActivatedRoute injector feature' : '', -); diff --git a/packages/router/src/create_router_state.ts b/packages/router/src/create_router_state.ts index c7f1210c6821..2e8ba428c34b 100644 --- a/packages/router/src/create_router_state.ts +++ b/packages/router/src/create_router_state.ts @@ -41,7 +41,7 @@ function createNode( // reuse an activated route that is currently displayed on the screen if (prevState && routeReuseStrategy.shouldReuseRoute(curr.value, prevState.value.snapshot)) { const value = prevState.value; - value._futureSnapshot = curr.value; + value._setPending(curr.value); const children = createOrReuseChildren(routeReuseStrategy, curr, prevState, newlyCreatedRoutes); return new TreeNode(value, children); } else { @@ -50,7 +50,7 @@ function createNode( const detachedRouteHandle = routeReuseStrategy.retrieve(curr.value); if (detachedRouteHandle !== null) { const tree = (detachedRouteHandle as DetachedRouteHandleInternal).route; - tree.value._futureSnapshot = curr.value; + tree.value._setPending(curr.value); tree.children = curr.children.map((c) => createNode(routeReuseStrategy, c, undefined, newlyCreatedRoutes), ); @@ -59,6 +59,7 @@ function createNode( } const value = createActivatedRoute(curr.value); + value._setPending(curr.value); newlyCreatedRoutes.add(value); const children = curr.children.map((c) => createNode(routeReuseStrategy, c, undefined, newlyCreatedRoutes), diff --git a/packages/router/src/directives/router_outlet.ts b/packages/router/src/directives/router_outlet.ts index 974481aaa15e..ea8958ef0359 100644 --- a/packages/router/src/directives/router_outlet.ts +++ b/packages/router/src/directives/router_outlet.ts @@ -10,6 +10,8 @@ import { ChangeDetectorRef, ComponentRef, Directive, + effect, + EffectRef, EnvironmentInjector, EventEmitter, inject, @@ -27,14 +29,15 @@ import { SimpleChanges, ViewContainerRef, } from '@angular/core'; -import {combineLatest, Observable, of, Subscription} from 'rxjs'; +import {combineLatest, of, Subscription} from 'rxjs'; import {switchMap} from 'rxjs/operators'; import {RuntimeErrorCode} from '../errors'; +import type {RouterResourcesFeatureImplementation} from '../router_resource_feature'; import {Data} from '../models'; import {ChildrenOutletContexts} from '../router_outlet_context'; import {ActivatedRoute} from '../router_state'; -import {Params, PRIMARY_OUTLET} from '../shared'; +import {PRIMARY_OUTLET} from '../shared'; import {ComponentInputBindingOptions} from '../router_config'; /** @@ -364,7 +367,7 @@ export class RouterOutlet implements OnDestroy, OnInit, RouterOutletContract { this.activated = ref; this._activatedRoute = activatedRoute; this.location.insert(ref.hostView); - this.inputBinder?.bindActivatedRouteToOutletComponent(this); + this.inputBinder?.bindActivatedRouteToOutletComponent(this, this.location.injector); this.attachEvents.emit(ref.instance); } @@ -406,7 +409,7 @@ export class RouterOutlet implements OnDestroy, OnInit, RouterOutletContract { // Calling `markForCheck` to make sure we will run the change detection when the // `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component. this.changeDetector.markForCheck(); - this.inputBinder?.bindActivatedRouteToOutletComponent(this); + this.inputBinder?.bindActivatedRouteToOutletComponent(this, this.location.injector); this.activateEvents.emit(this.activated.instance); } } @@ -459,24 +462,47 @@ export const INPUT_BINDER = new InjectionToken( export class RoutedComponentInputBinder { private outletDataSubscriptions = new Map(); private outletSeenKeys = new Map>(); + private outletEffects = new Map(); - constructor(private options: ComponentInputBindingOptions) { + constructor( + private options: ComponentInputBindingOptions, + private feature: RouterResourcesFeatureImplementation | null = null, + ) { this.options.queryParams ??= true; } - bindActivatedRouteToOutletComponent(outlet: RouterOutlet): void { + bindActivatedRouteToOutletComponent(outlet: RouterOutlet, injector: Injector): void { this.unsubscribeFromRouteData(outlet); - this.subscribeToRouteData(outlet); + this.subscribeToRouteData(outlet, injector); } unsubscribeFromRouteData(outlet: RouterOutlet): void { this.outletDataSubscriptions.get(outlet)?.unsubscribe(); this.outletDataSubscriptions.delete(outlet); this.outletSeenKeys.delete(outlet); + this.outletEffects.get(outlet)?.forEach((effect) => effect.destroy()); + this.outletEffects.delete(outlet); } - private subscribeToRouteData(outlet: RouterOutlet) { + private subscribeToRouteData(outlet: RouterOutlet, injector: Injector) { const {activatedRoute} = outlet; + + const effects: EffectRef[] = []; + let keysBoundToBlockingResources: string[] = []; + + if (this.feature?.createResourceOutletBindingEffects && outlet.activatedComponentRef) { + const {handledKeys, createdEffects} = this.feature.createResourceOutletBindingEffects( + outlet.activatedComponentRef, + activatedRoute, + ); + effects.push(...createdEffects); + keysBoundToBlockingResources = handledKeys; + } + + if (effects.length > 0) { + this.outletEffects.set(outlet, effects); + } + const dataSubscription = combineLatest([ this.options.queryParams ? activatedRoute.queryParams : of({}), activatedRoute.params, @@ -484,7 +510,14 @@ export class RoutedComponentInputBinder { ]) .pipe( switchMap(([queryParams, params, data], index) => { - data = {...queryParams, ...params, ...data}; + // Precedence when keys collide is determined by the spread order: + // resources > data (including resolvers) > path params > query params + data = { + ...queryParams, + ...params, + ...data, + ...activatedRoute.resources, + }; // Get the first result from the data subscription synchronously so it's available to // the component as soon as possible (and doesn't require a second change detection). if (index === 0) { @@ -509,8 +542,8 @@ export class RoutedComponentInputBinder { return; } - const mirror = reflectComponentType(activatedRoute.component); - if (!mirror) { + const currentMirror = reflectComponentType(activatedRoute.component); + if (!currentMirror) { this.unsubscribeFromRouteData(outlet); return; } @@ -527,7 +560,10 @@ export class RoutedComponentInputBinder { const behavior = this.options.unmatchedInputBehavior ?? 'alwaysUndefined'; - for (const {templateName} of mirror.inputs) { + for (const {templateName} of currentMirror.inputs) { + if (keysBoundToBlockingResources.includes(templateName)) { + continue; + } const value = data[templateName]; if (value !== undefined || behavior === 'alwaysUndefined' || seenKeys.has(templateName)) { outlet.activatedComponentRef.setInput(templateName, value); diff --git a/packages/router/src/index.ts b/packages/router/src/index.ts index 6513a0d7044f..2a89606dc0b6 100644 --- a/packages/router/src/index.ts +++ b/packages/router/src/index.ts @@ -7,6 +7,7 @@ */ export {createUrlTreeFromSnapshot} from './create_url_tree'; +export {nonBlocking} from './router_resource'; export {RouterLink, RouterLinkWithHref} from './directives/router_link'; export {RouterLinkActive} from './directives/router_link_active'; export {ROUTER_OUTLET_DATA, RouterOutlet, RouterOutletContract} from './directives/router_outlet'; @@ -65,6 +66,8 @@ export { RunGuardsAndResolvers, UrlMatcher, UrlMatchResult, + ResourceContext, + ResourceResult, } from './models'; export {ViewTransitionInfo, ViewTransitionsFeatureOptions} from './utils/view_transition'; @@ -72,6 +75,7 @@ export * from './models_deprecated'; export {Navigation, NavigationExtras, UrlCreationOptions} from './navigation_transition'; export {DefaultTitleStrategy, TitleStrategy} from './page_title_strategy'; export { + AutoCleanupInjectorsFeature, ComponentInputBindingFeature, DebugTracingFeature, DisabledInitialNavigationFeature, @@ -91,6 +95,7 @@ export { withDisabledInitialNavigation, withEnabledBlockingInitialNavigation, withExperimentalAutoCleanupInjectors, + withAutoCleanupInjectors, withExperimentalPlatformNavigation, withHashLocation, withInMemoryScrolling, @@ -98,6 +103,8 @@ export { withPreloading, withRouterConfig, withViewTransitions, + withRouterResources, + RouterResourcesFeature, } from './provide_router'; export { @@ -140,6 +147,7 @@ export { UrlSegmentGroup, UrlSerializer, UrlTree, + containsTree, } from './url_tree'; export { mapToCanActivate, diff --git a/packages/router/src/models.ts b/packages/router/src/models.ts index 4fc11ae52080..fcb50385979b 100644 --- a/packages/router/src/models.ts +++ b/packages/router/src/models.ts @@ -13,14 +13,60 @@ import { NgModuleFactory, Provider, ProviderToken, + Signal, Type, + Resource, + WritableResource, } from '@angular/core'; import {Observable} from 'rxjs'; export {DefaultExport} from '@angular/core'; import type {ActivatedRouteSnapshot, RouterStateSnapshot} from './router_state'; +import {Params} from './shared'; import type {UrlSegment, UrlSegmentGroup, UrlTree} from './url_tree'; +/** + * The expected return type of a `resources` function. + * @developerPreview 22.2 + */ +export type ResourceResult = Record< + string, + Resource & Pick, 'reload'> +>; + +// Developer notes: properties are exposed as a plain Record (`Params`) rather than a `ParamMap` +// to allow future type-check layers to infer exact keys (e.g., `{ id: string }`). +// Same applies to data and queryparams. +/** + * The contextual information provided to a `resources` function. + * @developerPreview 22.2 + */ +export interface ResourceContext { + /** + * The path and matrix parameters available to the route. + * + * @developerPreview 22.2 + */ + params: Signal; + /** + * The query parameters of the route. + * + * @developerPreview 22.2 + */ + queryParams: Signal; + /** + * The URL fragment. + * @developerPreview 22.2 + */ + fragment: Signal; + /** + * Data provided in the route configuration. + * + * @developerPreview 22.2 + */ + data: Signal>; +} + /** * How to handle a navigation request to the current URL. One of: * @@ -117,11 +163,14 @@ export type GuardResult = boolean | UrlTree | RedirectCommand; * * @publicApi */ -export class RedirectCommand { +export class RedirectCommand extends Error { constructor( readonly redirectTo: UrlTree, readonly navigationBehaviorOptions?: NavigationBehaviorOptions, - ) {} + ) { + super(); + Object.setPrototypeOf(this, RedirectCommand.prototype); + } } /** @@ -710,6 +759,13 @@ export interface Route { * @see [Resolve](guide/routing/data-resolvers#what-are-data-resolvers) */ resolve?: ResolveData; + /** + * A function that returns a record of resources. + * This function is executed during the Main Loading Phase of a navigation. + * @developerPreview 22.2 + */ + resources?: (ctx: ResourceContext) => ResourceResult | Promise; + /** * An array of child `Route` objects that specifies a nested route * configuration. diff --git a/packages/router/src/navigation_transition.ts b/packages/router/src/navigation_transition.ts index 721e93e22986..9587ece1a810 100644 --- a/packages/router/src/navigation_transition.ts +++ b/packages/router/src/navigation_transition.ts @@ -63,6 +63,7 @@ import {ActivateRoutes} from './operators/activate_routes'; import {checkGuards} from './operators/check_guards'; import {recognize} from './operators/recognize'; import {resolveData} from './operators/resolve_data'; +import {ROUTER_RESOURCES_FEATURE} from './router_resource_feature'; import {switchTap} from './operators/switch_tap'; import {TitleStrategy} from './page_title_strategy'; import type {Router} from './router'; @@ -83,7 +84,7 @@ import {UrlSerializer, UrlTree} from './url_tree'; import {abortSignalToObservable} from './utils/abort_signal_to_observable'; import {Checks, getAllRouteGuards} from './utils/preactivation'; import {CREATE_VIEW_TRANSITION} from './utils/view_transition'; -import {ACTIVATED_ROUTE_INJECTOR_FEATURE} from './activated_route_injector_feature'; +import {TreeNode} from './utils/tree'; /** * @description @@ -202,7 +203,7 @@ export interface UrlCreationOptions { * * @see {@link Router#navigate} * @see {@link Router#navigateByUrl} - * @see {@link Router#createurltree} + * @see {@link Router#createUrlTree} * @see [Routing and Navigation guide](guide/routing/common-router-tasks) * @see {@link UrlCreationOptions} * @see {@link NavigationBehaviorOptions} @@ -231,7 +232,7 @@ export type RestoredState = { * * *id* : The unique identifier of the current navigation. * * *initialUrl* : The target URL passed into the `Router#navigateByUrl()` call before navigation. * This is the value before the router has parsed or applied redirects to it. - * * *extractedUrl* : The initial target URL after being parsed with `UrlSerializer.extract()`. + * * *extractedUrl* : The initial target URL after being parsed with `UrlHandlingStrategy.extract()`. * * *finalUrl* : The extracted URL after redirects have been applied. * This URL may not be available immediately, therefore this property can be `undefined`. * It is guaranteed to be set after the `RoutesRecognized` event fires. @@ -317,6 +318,7 @@ export interface NavigationTransition { urlAfterRedirects?: UrlTree; rawUrl: UrlTree; extras: NavigationExtras; + hasUAVisualTransition?: boolean; resolve: (value: boolean | PromiseLike) => void; reject: (reason?: any) => void; promise: Promise; @@ -369,7 +371,7 @@ export class NavigationTransitions { private readonly urlHandlingStrategy = inject(UrlHandlingStrategy); private readonly createViewTransition = inject(CREATE_VIEW_TRANSITION, {optional: true}); private readonly navigationErrorHandler = inject(NAVIGATION_ERROR_HANDLER, {optional: true}); - private readonly activatedRouteInjectorFeature = inject(ACTIVATED_ROUTE_INJECTOR_FEATURE, { + private readonly routerResourcesFeature = inject(ROUTER_RESOURCES_FEATURE, { optional: true, }); @@ -413,6 +415,7 @@ export class NavigationTransitions { | 'currentRawUrl' | 'rawUrl' | 'extras' + | 'hasUAVisualTransition' | 'resolve' | 'reject' | 'promise' @@ -765,17 +768,16 @@ export class NavigationTransitions { return of(t); }), - this.activatedRouteInjectorFeature?.operator() ?? ((t) => t), - + this.routerResourcesFeature?.setupAndRunResources(abortController.signal) ?? ((t) => t), switchTap(() => this.afterPreactivation()), - // TODO(atscott): Move this into the last block below. switchMap(() => { const {currentSnapshot, targetSnapshot} = overallTransitionState; const viewTransitionStarted = this.createViewTransition?.( this.environmentInjector, currentSnapshot.root, targetSnapshot!.root, + overallTransitionState.hasUAVisualTransition, ); // If view transitions are enabled, block the navigation until the view @@ -813,6 +815,8 @@ export class NavigationTransitions { return; } + resetPendingRoutes(t.targetRouterState); + completedOrAborted = true; this.currentNavigation.update((nav) => { (nav as Writable).abort = noop; @@ -832,7 +836,7 @@ export class NavigationTransitions { takeUntil( abortSignalToObservable(abortController.signal).pipe( - // Ignore aborts if we are already completed, canceled, or are in the activation stage (we have targetRouterState) + // Ignore aborts if we are already completed, canceled, or the transition has entered the non-abortable activation stage filter(() => !completedOrAborted && abortable), tap(() => { this.cancelNavigationTransition( @@ -893,7 +897,7 @@ export class NavigationTransitions { }), catchError((e) => { completedOrAborted = true; - discardNewActivatedRoutes(overallTransitionState); + rollbackState(overallTransitionState); // If the application is already destroyed, the catch block should not // execute anything in practice because other resources have already // been released and destroyed. @@ -902,6 +906,10 @@ export class NavigationTransitions { return EMPTY; } + if (e instanceof RedirectCommand) { + e = redirectingNavigationError(this.urlSerializer, e); + } + /* This error type is issued during Redirect, and is handled as a * cancellation rather than an error. */ if (isNavigationCancelingError(e)) { @@ -992,7 +1000,7 @@ export class NavigationTransitions { reason: string, code: NavigationCancellationCode, ) { - discardNewActivatedRoutes(t); + rollbackState(t); const navCancel = new NavigationCancel( t.id, this.urlSerializer.serialize(t.extractedUrl), @@ -1046,11 +1054,21 @@ export function isBrowserTriggeredNavigation(source: NavigationTrigger) { return source !== IMPERATIVE_NAVIGATION; } -function discardNewActivatedRoutes(t: NavigationTransition): void { - if (!t.newlyCreatedRoutes) { - return; - } - for (const r of t.newlyCreatedRoutes) { +function rollbackState(t: NavigationTransition): void { + for (const r of t.newlyCreatedRoutes ?? []) { r._localInjector?.destroy(); + r._localInjector = undefined; + } + resetPendingRoutes(t.targetRouterState); +} + +function resetPendingRoutes(targetRouterState?: RouterState | null): void { + if (!targetRouterState) { + return; } + const traverse = (node: TreeNode) => { + node.value.pending?.set(false); + node.children.forEach(traverse); + }; + traverse(targetRouterState._root); } diff --git a/packages/router/src/operators/activate_routes.ts b/packages/router/src/operators/activate_routes.ts index 7f0569d3bfc7..2e7018b23074 100644 --- a/packages/router/src/operators/activate_routes.ts +++ b/packages/router/src/operators/activate_routes.ts @@ -107,7 +107,11 @@ export class ActivateRoutes { if (context && context.outlet) { const componentRef = context.outlet.detach(); - const contexts = context.children.onOutletDeactivated(); + // Reset child contexts so subsequent activations in this outlet do not mutate the detached + // tree (see #57285). The detached outlets are still alive, so `onOutletDeactivated()` (which + // the destruction path uses to prune) is intentionally not called here. + const contexts = context.children.contexts; + context.resetChildren(); this.routeReuseStrategy.store(route.value.snapshot, {componentRef, route, contexts}); } } diff --git a/packages/router/src/operators/setup_activated_route_injectors.ts b/packages/router/src/operators/setup_activated_route_injectors.ts deleted file mode 100644 index ec7c47ad50f0..000000000000 --- a/packages/router/src/operators/setup_activated_route_injectors.ts +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.dev/license - */ - -import {OperatorFunction} from 'rxjs'; -import {ActivatedRoute, ActivatedRouteSnapshot} from '../router_state'; -import {TreeNode} from '../utils/tree'; -import {NavigationTransition} from '../navigation_transition'; -import {createEnvironmentInjector} from '@angular/core'; -import {tap} from 'rxjs/operators'; - -export function setupActivatedRouteInjectors(): OperatorFunction< - NavigationTransition, - NavigationTransition -> { - return tap(({newlyCreatedRoutes, targetRouterState}) => { - if (!newlyCreatedRoutes || !targetRouterState) { - return; - } - - // Obviously the easier way would be to just iterate newlyCreatedRoutes - // and create injectors for them. However, the feature will eventually - // want to do things for routes that are being reused. - const traverse = (stateNode: TreeNode) => { - const route = stateNode.value; - if (route) { - processRoute(route, newlyCreatedRoutes); - } - - for (const childState of stateNode.children) { - traverse(childState); - } - }; - - traverse(targetRouterState._root); - }); -} - -function processRoute(route: ActivatedRoute, newlyCreatedRoutes: Set) { - // Only create injectors for routes with the feature enabled - const useActivatedRouteInjector = (route?.routeConfig as any)?.ɵUseActivatedRouteInjector; - if (!useActivatedRouteInjector) { - return; - } - - if (newlyCreatedRoutes.has(route)) { - setupNewActivatedRouteInjector(route._futureSnapshot, route); - } else { - // TODO: Do something with injectors that already exist - } -} - -function setupNewActivatedRouteInjector(snapshot: ActivatedRouteSnapshot, route: ActivatedRoute) { - if (ngDevMode && !!route._localInjector) { - throw new Error( - 'invalid state: _localInjector should not exist on newly created ActivatedRoute yet', - ); - } - route._localInjector = createEnvironmentInjector([], snapshot._environmentInjector); -} diff --git a/packages/router/src/operators/setup_and_run_resources.ts b/packages/router/src/operators/setup_and_run_resources.ts new file mode 100644 index 000000000000..d52399623137 --- /dev/null +++ b/packages/router/src/operators/setup_and_run_resources.ts @@ -0,0 +1,218 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ +import { + createEnvironmentInjector, + runInInjectionContext, + Resource, + effect, + DestroyRef, + EnvironmentInjector, +} from '@angular/core'; +import {OperatorFunction, pipe} from 'rxjs'; +import {ResourceContext, ResourceResult, Route} from '../models'; +import {NavigationTransition} from '../navigation_transition'; +import {ActivatedRoute, ActivatedRouteSnapshot, initializeActivatedRoute} from '../router_state'; +import {TreeNode} from '../utils/tree'; +import { + BLOCKING_SYMBOL, + InternalRouterResource, + routerResource, + SOURCE_RESOURCE_SYMBOL, +} from '../router_resource'; +import {switchTap} from './switch_tap'; + +export function setupAndRunResources( + abortSignal: AbortSignal, +): OperatorFunction { + return pipe( + switchTap(({newlyCreatedRoutes, targetRouterState}) => { + if (!newlyCreatedRoutes || !targetRouterState || abortSignal.aborted) { + return; + } + + const resourceSetupPromises: Array> = []; + const blockingResourcePromises: Array> = []; + + const traverse = (stateNode: TreeNode) => { + const route = stateNode.value; + if (route) { + initializeActivatedRoute(route); + processRoute( + route, + newlyCreatedRoutes, + resourceSetupPromises, + abortSignal, + blockingResourcePromises, + ); + } + + for (const childState of stateNode.children) { + traverse(childState); + } + }; + + traverse(targetRouterState._root); + + return Promise.all(resourceSetupPromises).then(() => Promise.all(blockingResourcePromises)); + }), + ); +} + +function processRoute( + route: ActivatedRoute, + newlyCreatedRoutes: Set, + resourceSetupPromises: Array>, + abortSignal: AbortSignal, + blockingResourcePromises: Array>, +) { + const resources = route.routeConfig?.resources; + if (!resources) { + return; + } + + if (newlyCreatedRoutes.has(route)) { + // This route is new. We need to run its resources function once. + resourceSetupPromises.push( + setupNewRouterResources(route, resources, abortSignal, blockingResourcePromises), + ); + } else { + updateExistingResources(route, blockingResourcePromises, abortSignal); + } +} + +async function setupNewRouterResources( + route: ActivatedRoute, + resourcesFn: NonNullable, + abortSignal: AbortSignal, + blockingResourcePromises: Promise[], +) { + const parentInjector = route._futureSnapshot._environmentInjector; + + let childInjector = route._localInjector; + if (!childInjector) { + childInjector = createEnvironmentInjector([], parentInjector); + route._localInjector = childInjector; // Attach to route for cleanup + } + + const context: ResourceContext = { + params: route.paramsSignal, + queryParams: route.queryParamsSignal, + fragment: route.fragmentSignal, + data: route.dataSignal, + }; + + const resourceResult = await runInInjectionContext(childInjector, () => resourcesFn(context)); + if (abortSignal.aborted || !resourceResult) return; + + const wrappedResult: ResourceResult = {}; + runInInjectionContext(childInjector, () => { + for (const [key, res] of Object.entries(resourceResult)) { + if ( + (typeof ngDevMode === 'undefined' || ngDevMode) && + (!res || + typeof res !== 'object' || + typeof (res as Partial>).snapshot !== 'function') + ) { + throw new Error( + `Invalid resource returned for key "${key}". Expected a Resource, but got ${res === null ? 'null' : typeof res}.`, + ); + } + wrappedResult[key] = routerResource(res); + } + }); + + route.resources = route._futureSnapshot.resources = wrappedResult; + setupBlocking(route, wrappedResult, blockingResourcePromises, abortSignal); +} + +function updateExistingResources( + route: ActivatedRoute, + blockingResourcePromises: Promise[], + abortSignal: AbortSignal, +) { + // This route is reused. We must eagerly update the resource context signals + // so that resources can react and fetch new data during the pending navigation. + const currentResources = route.snapshot?.resources; + if (!currentResources) { + return; + } + + for (const r of Object.values(currentResources)) { + const underlyingRes = (r as InternalRouterResource)[SOURCE_RESOURCE_SYMBOL]; + if (underlyingRes.status() === 'error') { + // If a resource previously failed and the route is reused identically, + // the parameter signals won't change, meaning the internal effect won't automatically refetch. + // We must manually trigger a reload to ensure the new navigation attempts a retry. + (underlyingRes as Partial).reload?.(); + } + } + + route._futureSnapshot.resources = currentResources; + setupBlocking(route, currentResources, blockingResourcePromises, abortSignal); +} + +function setupBlocking( + route: ActivatedRoute, + resourceResult: ResourceResult, + blockingResourcePromises: Array>, + abortSignal: AbortSignal, +) { + if (abortSignal.aborted) return; + const childInjector = route._localInjector; + if (!childInjector || !resourceResult) return; + + for (const res of Object.values(resourceResult)) { + const internalRes = res as InternalRouterResource; + if (internalRes[BLOCKING_SYMBOL] !== false) { + blockingResourcePromises.push(waitForResource(internalRes, childInjector, abortSignal)); + } + } +} + +function waitForResource( + resource: InternalRouterResource, + injector: EnvironmentInjector, + abortSignal: AbortSignal, +): Promise { + return new Promise((resolve, reject) => { + const underlyingRes = resource[SOURCE_RESOURCE_SYMBOL]; + let isDestroyed = false; + let unregisterDestroy: (() => void) | undefined; + + const cleanup = () => { + isDestroyed = true; + blockingEffect.destroy(); + unregisterDestroy?.(); + abortSignal.removeEventListener('abort', onDone); + }; + + const onDone = () => { + cleanup(); + resolve(); + }; + + abortSignal.addEventListener('abort', onDone, {once: true}); + + const blockingEffect = effect( + () => { + if (isDestroyed) return; + const status = underlyingRes.status(); + if (status === 'error') { + cleanup(); + reject(underlyingRes.error()); + } else if (!underlyingRes.isLoading()) { + cleanup(); + resolve(); + } + }, + {injector, manualCleanup: true}, + ); + + unregisterDestroy = injector.get(DestroyRef).onDestroy(onDone); + }); +} diff --git a/packages/router/src/private_export.ts b/packages/router/src/private_export.ts index 1094335fafee..b508c826258a 100644 --- a/packages/router/src/private_export.ts +++ b/packages/router/src/private_export.ts @@ -11,4 +11,3 @@ export {RestoredState as ɵRestoredState} from './navigation_transition'; export {loadChildren as ɵloadChildren} from './router_config_loader'; export {ROUTER_PROVIDERS as ɵROUTER_PROVIDERS} from './router_module'; export {afterNextNavigation as ɵafterNextNavigation} from './utils/navigations'; -export {withActivatedRouteInjectors as ɵwithActivatedRouteInjectors} from './provide_router'; diff --git a/packages/router/src/provide_router.ts b/packages/router/src/provide_router.ts index ab73bfe0f612..f7bde119b976 100644 --- a/packages/router/src/provide_router.ts +++ b/packages/router/src/provide_router.ts @@ -36,6 +36,7 @@ import { import {of, Subject} from 'rxjs'; import {INPUT_BINDER, RoutedComponentInputBinder} from './directives/router_outlet'; +import {createResourceOutletBindingEffects} from './router_resource'; import {Event, NavigationError, stringifyEvent} from './events'; import {RedirectCommand, Routes} from './models'; import {NAVIGATION_ERROR_HANDLER, NavigationTransitions} from './navigation_transition'; @@ -48,6 +49,7 @@ import { RouterConfigOptions, } from './router_config'; import {ROUTES} from './router_config_loader'; +import {setupAndRunResources} from './operators/setup_and_run_resources'; import {PreloadingStrategy, RouterPreloader} from './router_preloader'; import {ROUTER_SCROLLER, RouterScroller} from './router_scroller'; @@ -63,8 +65,7 @@ import { VIEW_TRANSITION_OPTIONS, ViewTransitionsFeatureOptions, } from './utils/view_transition'; -import {ACTIVATED_ROUTE_INJECTOR_FEATURE} from './activated_route_injector_feature'; -import {setupActivatedRouteInjectors} from './operators/setup_activated_route_injectors'; +import {ROUTER_RESOURCES_FEATURE} from './router_resource_feature'; /** * Sets up providers necessary to enable `Router` functionality for the application. @@ -363,8 +364,7 @@ export type EnabledBlockingInitialNavigationFeature = * @publicApi */ export type InitialNavigationFeature = - | EnabledBlockingInitialNavigationFeature - | DisabledInitialNavigationFeature; + EnabledBlockingInitialNavigationFeature | DisabledInitialNavigationFeature; /** * Configures initial navigation to start before the root component is created. @@ -732,15 +732,15 @@ export function withNavigationErrorHandler( } /** - * A type alias for providers returned by `withExperimentalAutoCleanupInjectors` for use with `provideRouter`. + * A type alias for providers returned by `withAutoCleanupInjectors` for use with `provideRouter`. * - * @see {@link withExperimentalAutoCleanupInjectors} + * @see {@link withAutoCleanupInjectors} * @see {@link provideRouter} * - * @experimental 21.1 + * @publicApi 22.2 */ -export type ExperimentalAutoCleanupInjectorsFeature = - RouterFeature; +export type AutoCleanupInjectorsFeature = + RouterFeature; /** * Enables automatic destruction of unused route injectors. @@ -755,14 +755,25 @@ export type ExperimentalAutoCleanupInjectorsFeature = * should also implement `retrieveStoredRouteHandles` to ensure injectors for handles that will be * reattached are not destroyed. * - * @experimental 21.1 + * @publicApi 22.2 */ -export function withExperimentalAutoCleanupInjectors(): ExperimentalAutoCleanupInjectorsFeature { - return routerFeature(RouterFeatureKind.ExperimentalAutoCleanupInjectorsFeature, [ +export function withAutoCleanupInjectors(): AutoCleanupInjectorsFeature { + return routerFeature(RouterFeatureKind.AutoCleanupInjectorsFeature, [ {provide: ROUTE_INJECTOR_CLEANUP, useValue: routeInjectorCleanup}, ]); } +/** + * Enables automatic destruction of unused route injectors. + * + * @deprecated Use `withAutoCleanupInjectors` instead. + * @see {@link withAutoCleanupInjectors} + * @publicApi + */ +export function withExperimentalAutoCleanupInjectors(): AutoCleanupInjectorsFeature { + return withAutoCleanupInjectors(); +} + /** * A type alias for providers returned by `withComponentInputBinding` for use with `provideRouter`. * @@ -840,7 +851,11 @@ export function withComponentInputBinding( options: ComponentInputBindingOptions = {}, ): ComponentInputBindingFeature { const providers = [ - {provide: INPUT_BINDER, useFactory: () => new RoutedComponentInputBinder(options)}, + { + provide: INPUT_BINDER, + useFactory: () => + new RoutedComponentInputBinder(options, inject(ROUTER_RESOURCES_FEATURE, {optional: true})), + }, ]; return routerFeature(RouterFeatureKind.ComponentInputBindingFeature, providers); @@ -888,18 +903,47 @@ export function withViewTransitions( return routerFeature(RouterFeatureKind.ViewTransitionsFeature, providers); } -export type ActivatedRouteInjectorFeature = - RouterFeature; -export function withActivatedRouteInjectors(): ActivatedRouteInjectorFeature { +/** + * A type alias for providers returned by `withRouterResources` for use with `provideRouter`. + * + * @see {@link withRouterResources} + * @see {@link provideRouter} + * + * @developerPreview 22.2 + */ +export type RouterResourcesFeature = RouterFeature; + +/** + * Enables `resources` capabilities for Route definitions. + * + * @usageNotes + * + * Basic example of how you can enable the feature: + * ```ts + * const appRoutes: Routes = []; + * bootstrapApplication(AppComponent, + * { + * providers: [ + * provideRouter(appRoutes, withRouterResources()) + * ] + * } + * ); + * ``` + * + * @developerPreview 22.2 + * @returns A set of providers for use with `provideRouter`. + */ +export function withRouterResources(): RouterResourcesFeature { const providers = [ { - provide: ACTIVATED_ROUTE_INJECTOR_FEATURE, + provide: ROUTER_RESOURCES_FEATURE, useValue: { - operator: setupActivatedRouteInjectors, + setupAndRunResources, + createResourceOutletBindingEffects, }, }, ]; - return routerFeature(RouterFeatureKind.ViewTransitionsFeature, providers); + return routerFeature(RouterFeatureKind.RouterResourcesFeature, providers); } /** @@ -921,9 +965,10 @@ export type RouterFeatures = | NavigationErrorHandlerFeature | ComponentInputBindingFeature | ViewTransitionsFeature - | ExperimentalAutoCleanupInjectorsFeature + | AutoCleanupInjectorsFeature | RouterHashLocationFeature - | ExperimentalPlatformNavigationFeature; + | ExperimentalPlatformNavigationFeature + | RouterResourcesFeature; /** * The list of features as an enum to uniquely type each feature. @@ -939,6 +984,7 @@ export const enum RouterFeatureKind { NavigationErrorHandlerFeature, ComponentInputBindingFeature, ViewTransitionsFeature, - ExperimentalAutoCleanupInjectorsFeature, + AutoCleanupInjectorsFeature, ExperimentalPlatformNavigationFeature, + RouterResourcesFeature, } diff --git a/packages/router/src/route_injector_cleanup.ts b/packages/router/src/route_injector_cleanup.ts index 1ef09690ca1b..0ae77eea5d4c 100644 --- a/packages/router/src/route_injector_cleanup.ts +++ b/packages/router/src/route_injector_cleanup.ts @@ -9,11 +9,7 @@ import {InjectionToken} from '@angular/core'; import {Route, Routes} from './models'; -import { - DetachedRouteHandleInternal, - ExperimentalRouteReuseStrategy, - RouteReuseStrategy, -} from './route_reuse_strategy'; +import {DetachedRouteHandleInternal, RouteReuseStrategy} from './route_reuse_strategy'; import {ActivatedRouteSnapshot, RouterState} from './router_state'; /** @@ -37,8 +33,7 @@ export function routeInjectorCleanup( } // For stored routes, collect them and all their parents by iterating pathFromRoot. - const storedHandles = - (routeReuseStrategy as ExperimentalRouteReuseStrategy).retrieveStoredRouteHandles?.() || []; + const storedHandles = routeReuseStrategy.retrieveStoredRouteHandles?.() || []; for (const handle of storedHandles) { const internalHandle = handle as DetachedRouteHandleInternal; if (internalHandle?.route?.value?.snapshot) { @@ -75,7 +70,7 @@ function destroyUnusedInjectors( !!( (route._injector || route._loadedInjector) && !activeRoutes.has(route) && - ((strategy as ExperimentalRouteReuseStrategy).shouldDestroyInjector?.(route) ?? false) + (strategy.shouldDestroyInjector?.(route) ?? false) ); if (route.children) { diff --git a/packages/router/src/route_reuse_strategy.ts b/packages/router/src/route_reuse_strategy.ts index 7e74bf32bdc5..42a25c33e28d 100644 --- a/packages/router/src/route_reuse_strategy.ts +++ b/packages/router/src/route_reuse_strategy.ts @@ -42,7 +42,7 @@ export type DetachedRouteHandleInternal = { * * @param handle The detached route handle to destroy. * - * @publicApi + * @publicApi 22.2 * @see [Manually destroying detached route handles](guide/routing/customizing-route-behavior#manually-destroying-detached-route-handles) */ export function destroyDetachedRouteHandle(handle: DetachedRouteHandle): void { @@ -58,11 +58,6 @@ export function destroyDetachedRouteHandle(handle: DetachedRouteHandle): void { } } -export interface ExperimentalRouteReuseStrategy { - shouldDestroyInjector?(route: Route): boolean; - retrieveStoredRouteHandles?(): Array; -} - /** * @description * @@ -90,6 +85,25 @@ export abstract class RouteReuseStrategy { /** Determines if a route should be reused */ abstract shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean; + + /** + * Returns a list of all currently stored `DetachedRouteHandle`s. + * + * This method is called by the router after navigations to identify which injectors + * are still needed by detached routes. + * + * @see {@link withAutoCleanupInjectors} + */ + retrieveStoredRouteHandles?(): Array; + + /** + * Determines if the injector for the given route should be destroyed. + * + * If this method returns `true`, the router will destroy the injector for the given route. + * + * @see {@link withAutoCleanupInjectors} + */ + shouldDestroyInjector?(route: Route): boolean; } /** @@ -145,11 +159,10 @@ export abstract class BaseRouteReuseStrategy implements RouteReuseStrategy { /** * Determines if the injector for the given route should be destroyed. * - * This method is called by the router when the `RouteReuseStrategy` is destroyed. + * This method is called by the router after navigations. * If this method returns `true`, the router will destroy the injector for the given route. * - * @see {@link withExperimentalAutoCleanupInjectors} - * @xperimental 21.1 + * @see {@link withAutoCleanupInjectors} */ shouldDestroyInjector(route: Route): boolean { return true; diff --git a/packages/router/src/router.ts b/packages/router/src/router.ts index 295566658909..760f41a0e8f7 100644 --- a/packages/router/src/router.ts +++ b/packages/router/src/router.ts @@ -233,11 +233,18 @@ export class Router { ...opts, }; - this.scheduleNavigation(mergedTree, IMPERATIVE_NAVIGATION, null, extras, { - resolve: currentTransition.resolve, - reject: currentTransition.reject, - promise: currentTransition.promise, - }); + this.scheduleNavigation( + mergedTree, + IMPERATIVE_NAVIGATION, + null, + extras, + currentTransition.hasUAVisualTransition, + { + resolve: currentTransition.resolve, + reject: currentTransition.reject, + promise: currentTransition.promise, + }, + ); } } @@ -288,8 +295,8 @@ export class Router { // run into ngZone this.nonRouterCurrentEntryChangeSubscription ??= this.stateManager.registerNonRouterCurrentEntryChangeListener( - (url, state, source, extras) => { - this.navigateToSyncWithBrowser(url, source, state, extras); + (url, state, source, extras, hasUAVisualTransition) => { + this.navigateToSyncWithBrowser(url, source, state, extras, hasUAVisualTransition); }, ); } @@ -306,6 +313,7 @@ export class Router { source: NavigationTrigger, state: RestoredState | null | undefined, extras: NavigationExtras, + hasUAVisualTransition?: boolean, ) { // TODO: restoredState should always include the entire state, regardless // of navigationId. This requires a breaking change to update the type on @@ -338,12 +346,14 @@ export class Router { } const urlTree = this.parseUrl(routerUrl); - this.scheduleNavigation(urlTree, source, restoredState, extras).catch((e) => { - if (this.disposed) { - return; - } - this.injector.get(ɵINTERNAL_APPLICATION_ERROR_HANDLER)(e); - }); + this.scheduleNavigation(urlTree, source, restoredState, extras, hasUAVisualTransition).catch( + (e) => { + if (this.disposed) { + return; + } + this.injector.get(ɵINTERNAL_APPLICATION_ERROR_HANDLER)(e); + }, + ); } /** The current URL. */ @@ -657,6 +667,7 @@ export class Router { source: NavigationTrigger, restoredState: RestoredState | null, extras: NavigationExtras, + hasUAVisualTransition?: boolean, priorPromise?: { resolve: (result: boolean | PromiseLike) => void; reject: (reason?: any) => void; @@ -696,6 +707,7 @@ export class Router { currentRawUrl: this.currentUrlTree, rawUrl, extras, + hasUAVisualTransition, resolve: resolve!, reject: reject!, promise, diff --git a/packages/router/src/router_config.ts b/packages/router/src/router_config.ts index a7744cca423e..4a0f34cb28de 100644 --- a/packages/router/src/router_config.ts +++ b/packages/router/src/router_config.ts @@ -169,20 +169,20 @@ export interface InMemoryScrollingOptions { * in the following example. * * ```ts - * class AppComponent { - * movieData: any; + * class App { + * movieData = signal(null); + * private router = inject(Router); + * private viewportScroller = inject(ViewportScroller); + * private changeDetectorRef = inject(ChangeDetectorRef); * - * constructor(private router: Router, private viewportScroller: ViewportScroller, - * changeDetectorRef: ChangeDetectorRef) { - * router.events.pipe(filter((event: Event): event is Scroll => event instanceof Scroll) + * constructor() { + * this.router.events.pipe(filter((event: Event): event is Scroll => event instanceof Scroll) * ).subscribe(e => { * fetch('http://example.com/movies.json').then(response => { - * this.movieData = response.json(); - * // update the template with the data before restoring scroll - * changeDetectorRef.detectChanges(); + * this.movieData.set(response.json()); * * if (e.position) { - * viewportScroller.scrollToPosition(e.position); + * this.viewportScroller.scrollToPosition(e.position); * } * }); * }); diff --git a/packages/router/src/router_outlet_context.ts b/packages/router/src/router_outlet_context.ts index 64b1ead82935..0eb12f713b68 100644 --- a/packages/router/src/router_outlet_context.ts +++ b/packages/router/src/router_outlet_context.ts @@ -28,6 +28,14 @@ export class OutletContext { constructor(private readonly rootInjector: EnvironmentInjector) { this.children = new ChildrenOutletContexts(this.rootInjector); } + + /** + * Replaces `children` with a fresh instance, keeping the same root injector. + * @internal + */ + resetChildren(): void { + this.children = new ChildrenOutletContexts(this.rootInjector); + } } /** @@ -37,8 +45,11 @@ export class OutletContext { */ @Injectable({providedIn: 'root'}) export class ChildrenOutletContexts { - // contexts for child outlets, by name. - private contexts = new Map(); + /** + * Contexts for child outlets, keyed by outlet name. + * @internal + */ + contexts = new Map(); /** @docs-private */ constructor(private rootInjector: EnvironmentInjector) {} diff --git a/packages/router/src/router_preloader.ts b/packages/router/src/router_preloader.ts index 0e5b91913621..05cee718796b 100644 --- a/packages/router/src/router_preloader.ts +++ b/packages/router/src/router_preloader.ts @@ -125,7 +125,7 @@ export class RouterPreloader implements OnDestroy { } private processRoutes(injector: EnvironmentInjector, routes: Routes): Observable { - const res: Observable[] = []; + const res: Observable[] = []; for (const route of routes) { if (route.providers && !route._injector) { route._injector = createEnvironmentInjector( diff --git a/packages/router/src/router_resource.ts b/packages/router/src/router_resource.ts new file mode 100644 index 000000000000..49b24fe08cb2 --- /dev/null +++ b/packages/router/src/router_resource.ts @@ -0,0 +1,214 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import { + ComponentRef, + EffectRef, + inject, + Injector, + Resource, + resourceFromSnapshots, + Signal, + signal, + DestroyRef, + ResourceSnapshot, + effect, + computed, + assertInInjectionContext, + reflectComponentType, +} from '@angular/core'; +import {Router} from './router'; +import type {ActivatedRoute} from './router_state'; +import { + NavigationStart, + NavigationEnd, + NavigationCancel, + NavigationError, + NavigationSkipped, + NavigationCancellationCode, +} from './events'; + +export const BLOCKING_SYMBOL: unique symbol = /* @__PURE__ */ Symbol( + typeof ngDevMode === 'undefined' || ngDevMode ? '__isBlocking' : '', +); +export const SOURCE_RESOURCE_SYMBOL: unique symbol = /* @__PURE__ */ Symbol( + typeof ngDevMode === 'undefined' || ngDevMode ? '__sourceResource' : '', +); + +/** + * @internal + */ +export interface InternalRouterResource extends Resource { + [SOURCE_RESOURCE_SYMBOL]: Resource; + [BLOCKING_SYMBOL]?: boolean; + reload(): boolean; +} + +/** + * Marks a resource as non-blocking. The Router will NOT wait for this resource to resolve + * before completing the navigation. + * @developerPreview 22.2 + */ +export function nonBlocking>(res: R): R { + (res as unknown as InternalRouterResource)[BLOCKING_SYMBOL] = false; + return res; +} + +/** + * Wraps a Resource to make it cooperative with the Angular Router, freezing its state + * during navigation transitions and handling rollback recovery. + */ +export function routerResource(source: Resource): Resource & {reload(): boolean} { + ngDevMode && assertInInjectionContext(routerResource); + const injector = inject(Injector); + const router = injector.get(Router); + + const {snapshot: snapshotSignal, frozenSnapshot} = createTransactionalSnapshot( + source, + router, + injector, + ); + + const res = resourceFromSnapshots(snapshotSignal) as unknown as InternalRouterResource; + + res[SOURCE_RESOURCE_SYMBOL] = source; + res[BLOCKING_SYMBOL] = + (source as unknown as InternalRouterResource)[BLOCKING_SYMBOL] !== false; + + res.reload = function (): boolean { + // If the resource is currently frozen (e.g., during an active navigation transition + // or while recovering from a cancelled navigation), we reject manual reload requests. + // Triggering a reload during an active navigation (where the resource may already be + // reactively loading new parameters behind the scenes) would disrupt the router's resource + // tracking for the transition. Similarly, during a rollback recovery, the router is + // already managing the resource reload to restore the previous state. + if (frozenSnapshot() !== null) { + return false; + } + return (source as any).reload?.() ?? false; + }; + + return res; +} + +/** + * Creates a signal that tracks the resource snapshot and handles transactional behavior + * (freezing during navigation and rollback recovery). + */ +function createTransactionalSnapshot( + source: Resource, + router: Router, + injector: Injector, +): { + snapshot: Signal>; + frozenSnapshot: Signal | null>; +} { + // Holds a snapshot of the resource to keep the UI masked (frozen) during pending navigations + // or while recovering from a cancelled navigation. + const frozenSnapshot = signal | null>(null); + + // Tracks whether we are in a recovery phase after a cancelled navigation. + // The intended behavior is that on cancellation, the router reverts to the previous state. + // This reversion might trigger a new load of the previous state because the signal dependencies + // changed. If we were to release the frozen resource state immediately, the user would see a loading state + // for data they were just looking at. To avoid this "loading flash", we retain the frozen + // value (via frozenSnapshot) during this recovery load/reload until the resource settles. + const isRollbackRecoveryPending = signal(false); + + const sub = router.events.subscribe((e) => { + if (e instanceof NavigationStart) { + isRollbackRecoveryPending.set(false); + + if (frozenSnapshot() === null) { + // Freeze the snapshot at the start of navigation to keep the UI stable. + frozenSnapshot.set(source.snapshot()); + } + } else if (e instanceof NavigationEnd) { + // Navigation succeeded, so we can unfreeze and use the live state. + frozenSnapshot.set(null); + isRollbackRecoveryPending.set(false); + } else if (e instanceof NavigationSkipped) { + // If a navigation is skipped while we have a frozen snapshot (e.g. navigating to the + // current URL to cancel an in-flight navigation), the in-flight navigation is aborted + // and parameter rollback begins. We must maintain the frozen snapshot until the rollback + // recovery load completes to prevent flashing a loading state. + if (frozenSnapshot() !== null) { + isRollbackRecoveryPending.set(true); + } + } else if (e instanceof NavigationCancel || e instanceof NavigationError) { + const isRollback = + e instanceof NavigationError || + (e instanceof NavigationCancel && + e.code !== NavigationCancellationCode.SupersededByNewNavigation && + e.code !== NavigationCancellationCode.Redirect); + + if (!isRollback) return; + + isRollbackRecoveryPending.set(true); + } + }); + + injector.get(DestroyRef).onDestroy(() => sub.unsubscribe()); + + effect( + () => { + if (isRollbackRecoveryPending() && !source.isLoading()) { + isRollbackRecoveryPending.set(false); + frozenSnapshot.set(null); + } + }, + {injector}, + ); + + return { + snapshot: computed(() => frozenSnapshot() ?? source.snapshot()), + frozenSnapshot, + }; +} + +/** + * Creates reactive effects to bind the unwrapped values of blocking router resources + * to matching component inputs. + * + * Non-blocking resources are bound as the `Resource` instance itself through the standard + * route data stream in `RoutedComponentInputBinder`. In contrast, blocking resources have + * resolved before navigation completes and bind their unwrapped `.value()` to the component + * input. This sets up an `effect` for each matching blocking resource to keep the component + * input reactively updated, and returns the handled keys so the standard data subscription + * skips them. + */ +export function createResourceOutletBindingEffects( + componentRef: ComponentRef, + route: ActivatedRoute, +): {createdEffects: EffectRef[]; handledKeys: string[]} { + const createdEffects: EffectRef[] = []; + const handledKeys: string[] = []; + const mirror = route.component ? reflectComponentType(route.component) : null; + const resources = route.resources; + if (!mirror || !resources) { + return {createdEffects, handledKeys}; + } + + for (const {templateName} of mirror.inputs) { + const resource = resources[templateName]; + if (!resource || !(resource as InternalRouterResource)[BLOCKING_SYMBOL]) { + continue; + } + + const effectRef = effect( + () => { + componentRef.setInput(templateName, resource.value()); + }, + {injector: componentRef.injector}, + ); + createdEffects.push(effectRef); + handledKeys.push(templateName); + } + + return {createdEffects, handledKeys}; +} diff --git a/packages/router/src/router_resource_feature.ts b/packages/router/src/router_resource_feature.ts new file mode 100644 index 000000000000..7af46acbdde0 --- /dev/null +++ b/packages/router/src/router_resource_feature.ts @@ -0,0 +1,27 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import {ComponentRef, EffectRef, InjectionToken} from '@angular/core'; +import {OperatorFunction} from 'rxjs'; +import type {NavigationTransition} from './navigation_transition'; + +import type {ActivatedRoute} from './router_state'; + +export interface RouterResourcesFeatureImplementation { + setupAndRunResources( + abortSignal: AbortSignal, + ): OperatorFunction; + createResourceOutletBindingEffects?: ( + componentRef: ComponentRef, + route: ActivatedRoute, + ) => {createdEffects: EffectRef[]; handledKeys: string[]}; +} + +export const ROUTER_RESOURCES_FEATURE = new InjectionToken( + typeof ngDevMode === 'undefined' || ngDevMode ? 'Router Resources Feature' : '', +); diff --git a/packages/router/src/router_state.ts b/packages/router/src/router_state.ts index 2923541ef63d..d256d8cc75d8 100644 --- a/packages/router/src/router_state.ts +++ b/packages/router/src/router_state.ts @@ -6,11 +6,19 @@ * found in the LICENSE file at https://angular.dev/license */ -import {EnvironmentInjector, Type} from '@angular/core'; +import { + computed, + EnvironmentInjector, + signal, + Signal, + Type, + WritableSignal, + ɵWritable as Writable, +} from '@angular/core'; import {BehaviorSubject, Observable, of} from 'rxjs'; import {map} from 'rxjs/operators'; -import {Data, ResolveData, Route} from './models'; +import {Data, ResourceResult, ResolveData, Route} from './models'; import {convertToParamMap, ParamMap, Params, PRIMARY_OUTLET, RouteTitleKey} from './shared'; import {equalSegments, UrlSegment} from './url_tree'; import {shallowEqual, shallowEqualArrays} from './utils/collection'; @@ -154,13 +162,44 @@ export class ActivatedRoute { /** An observable of the static and resolved data of this route. */ public data: Observable; + // ================================= + // ===== Resource integration ====== + // ================================= + + // Note for framework developers: Unlike `data` and `params`, the `resources` property + // is assigned once when the route is first initialized and its reference remains stable + // for the entire lifetime of the `ActivatedRoute` instance. Do NOT replace or swap this + // reference during pending navigations or route reuse, as doing so breaks reactivity + // for components subscribed to the underlying resource signals. /** - * Injector scoped to the lifetime of this ActivatedRoute object. - * Created only when features tied to ActivatedRoute lifetime are used. + * A map of resources for this route. * - * @internal + * @developerPreview 22.2 */ + resources?: ResourceResult; + /** @internal */ _localInjector?: EnvironmentInjector; + /** @internal */ + readonly pending?: WritableSignal; + // Note for framework developers: `paramsSignal`, `queryParamsSignal`, and `dataSignal` + // do NOT use `{equal: shallowEqual}`. Even though navigations can re-emit structurally + // identical parameters, we rely on the default strict equality (`===`) so that any consumer + // depending on the entire object is correctly invalidated. This encourages developers to properly + // project nested scalar properties (e.g. `paramMap().get('id')`) instead of subscribing to the + // naked object. Furthermore, `shallowEqual` unsafely relies on mutations (`.sort()`) for generic + // arrays, making it unsuitable for signals that might carry complex `data` objects. + /** @internal */ + readonly paramsSignal!: Signal; + /** @internal */ + readonly queryParamsSignal!: Signal; + /** @internal */ + readonly paramMapSignal!: Signal; + /** @internal */ + readonly queryParamMapSignal!: Signal; + /** @internal */ + readonly fragmentSignal!: Signal; + /** @internal */ + readonly dataSignal!: Signal; /** @internal */ constructor( @@ -244,6 +283,12 @@ export class ActivatedRoute { toString(): string { return this.snapshot ? this.snapshot.toString() : `Future(${this._futureSnapshot})`; } + + /** @internal */ + _setPending(snapshot: ActivatedRouteSnapshot): void { + this._futureSnapshot = snapshot; + this.pending?.set(true); + } } export type ParamsInheritanceStrategy = 'emptyOnly' | 'always'; @@ -352,6 +397,11 @@ export class ActivatedRouteSnapshot { _queryParamMap?: ParamMap; /** @internal */ readonly _environmentInjector: EnvironmentInjector; + /** + * The result of running the route's resources function. + * @developerPreview 22.2 + */ + resources?: ResourceResult; /** The resolved route title */ get title(): string | undefined { @@ -531,6 +581,41 @@ export function advanceActivatedRoute(route: ActivatedRoute): void { } } +export function initializeActivatedRoute(route: ActivatedRoute): void { + if (route.paramsSignal !== undefined) { + return; + } + const writableRoute = route as Writable; + const pendingSignal = signal(false); + writableRoute.pending = pendingSignal; + + writableRoute.paramsSignal = computed(() => + pendingSignal() || !route.snapshot ? route._futureSnapshot.params : route.snapshot.params, + ); + + writableRoute.queryParamsSignal = computed(() => + pendingSignal() || !route.snapshot + ? route._futureSnapshot.queryParams + : route.snapshot.queryParams, + ); + + writableRoute.paramMapSignal = computed(() => convertToParamMap(route.paramsSignal())); + writableRoute.queryParamMapSignal = computed(() => convertToParamMap(route.queryParamsSignal())); + + writableRoute.fragmentSignal = computed(() => + pendingSignal() || !route.snapshot ? route._futureSnapshot.fragment : route.snapshot.fragment, + ); + + writableRoute.dataSignal = computed(() => + pendingSignal() || !route.snapshot ? route._futureSnapshot.data : route.snapshot.data, + ); + + writableRoute._setPending = (snapshot: ActivatedRouteSnapshot) => { + route._futureSnapshot = snapshot; + pendingSignal.set(true); + }; +} + export function equalParamsAndUrlSegments( a: ActivatedRouteSnapshot, b: ActivatedRouteSnapshot, diff --git a/packages/router/src/shared.ts b/packages/router/src/shared.ts index 2ccfb2e10c72..e719a542a1b9 100644 --- a/packages/router/src/shared.ts +++ b/packages/router/src/shared.ts @@ -80,7 +80,7 @@ class ParamsAsMap implements ParamMap { } has(name: string): boolean { - return Object.prototype.hasOwnProperty.call(this.params, name); + return Object.hasOwn(this.params, name); } get(name: string): string | null { diff --git a/packages/router/src/statemanager/navigation_state_manager.ts b/packages/router/src/statemanager/navigation_state_manager.ts index 990e9d96ff58..0139727048c7 100644 --- a/packages/router/src/statemanager/navigation_state_manager.ts +++ b/packages/router/src/statemanager/navigation_state_manager.ts @@ -101,6 +101,7 @@ export class NavigationStateManager extends StateManager { private nonRouterCurrentEntryChangeSubject = new Subject<{ path: string; state: RestoredState | null | undefined; + hasUAVisualTransition?: boolean; }>(); nonRouterEntryChangeListener?: SubscriptionLike; @@ -130,16 +131,18 @@ export class NavigationStateManager extends StateManager { state: RestoredState | null | undefined, trigger: NavigationTrigger, extras: NavigationExtras, + hasUAVisualTransition?: boolean, ) => void, ): SubscriptionLike { this.activeHistoryEntry = this.navigation.currentEntry!; this.nonRouterEntryChangeListener = this.nonRouterCurrentEntryChangeSubject.subscribe( - ({path, state}) => { + ({path, state, hasUAVisualTransition}) => { listener( path, state, 'popstate', !this.precommitHandlerSupported ? {replaceUrl: true} : {}, + hasUAVisualTransition, ); }, ); @@ -538,7 +541,11 @@ export class NavigationStateManager extends StateManager { // The url will always start with the appRootUrl because of the boundary check in handleNavigate. const path = event.destination.url.substring(this.appRootUrl.href.length - 1); const state = event.destination.getState() as RestoredState | null | undefined; - this.nonRouterCurrentEntryChangeSubject.next({path, state}); + this.nonRouterCurrentEntryChangeSubject.next({ + path, + state, + hasUAVisualTransition: event.hasUAVisualTransition, + }); } private eventAndRouterDestinationsMatch( diff --git a/packages/router/src/statemanager/state_manager.ts b/packages/router/src/statemanager/state_manager.ts index afecaedae0e0..89b83c7cc828 100644 --- a/packages/router/src/statemanager/state_manager.ts +++ b/packages/router/src/statemanager/state_manager.ts @@ -153,6 +153,7 @@ export abstract class StateManager { state: RestoredState | null | undefined, trigger: NavigationTrigger, extras: NavigationExtras, + hasUAVisualTransition?: boolean, ) => void, ): SubscriptionLike; @@ -194,6 +195,7 @@ export class HistoryStateManager extends StateManager { state: RestoredState | null | undefined, trigger: NavigationTrigger, extras: NavigationExtras, + hasUAVisualTransition?: boolean, ) => void, ): SubscriptionLike { return this.location.subscribe((event) => { @@ -201,9 +203,15 @@ export class HistoryStateManager extends StateManager { // The `setTimeout` was added in #12160 and is likely to support Angular/AngularJS // hybrid apps. setTimeout(() => { - listener(event['url']!, event.state as RestoredState | null | undefined, 'popstate', { - replaceUrl: true, - }); + listener( + event['url']!, + event.state as RestoredState | null | undefined, + 'popstate', + { + replaceUrl: true, + }, + event.hasUAVisualTransition, + ); }); } }); diff --git a/packages/router/src/url_tree.ts b/packages/router/src/url_tree.ts index ee6853cc0872..6e04e90fe19f 100644 --- a/packages/router/src/url_tree.ts +++ b/packages/router/src/url_tree.ts @@ -123,22 +123,41 @@ export function isActive( ): Signal { const urlTree = url instanceof UrlTree ? url : router.parseUrl(url); return computed(() => - containsTree(router.lastSuccessfulNavigation()?.finalUrl ?? new UrlTree(), urlTree, { - ...subsetMatchOptions, - ...matchOptions, - }), + containsTree( + router.lastSuccessfulNavigation()?.finalUrl ?? new UrlTree(), + urlTree, + matchOptions, + ), ); } +/** + * Determines if a `UrlTree` is contained within another `UrlTree` based on the provided matching options. + * + * @param container The outer or reference `UrlTree`. + * @param containee The target `UrlTree` to test against the container. + * @param options Optional, matching options: + * - `paths`: Defines how to compare URL segments ('exact' or 'subset'). Defaults to 'subset'. + * - `matrixParams`: Defines how to compare matrix parameters ('exact', 'subset', or 'ignored'). Defaults to 'ignored'. + * - `queryParams`: Defines how to compare query parameters ('exact', 'subset', or 'ignored'). Defaults to 'subset'. + * - `fragment`: Defines how to compare URL fragments ('exact' or 'ignored'). Defaults to 'ignored'. + * + * @publicApi + */ export function containsTree( container: UrlTree, containee: UrlTree, - options: IsActiveMatchOptions, + options?: Partial, ): boolean { + const matchOptions: IsActiveMatchOptions = { + ...subsetMatchOptions, + ...(options || {}), + }; + return ( - pathCompareMap[options.paths](container.root, containee.root, options.matrixParams) && - paramCompareMap[options.queryParams](container.queryParams, containee.queryParams) && - !(options.fragment === 'exact' && container.fragment !== containee.fragment) + pathCompareMap[matchOptions.paths](container.root, containee.root, matchOptions.matrixParams) && + paramCompareMap[matchOptions.queryParams](container.queryParams, containee.queryParams) && + !(matchOptions.fragment === 'exact' && container.fragment !== containee.fragment) ); } @@ -581,6 +600,23 @@ function serializeQueryParams(params: {[key: string]: any}): string { return strParams.length ? `?${strParams.join('&')}` : ''; } +// Above V8's threshold for requiring dictionary elements. +const SLOW_ELEMENTS_SENTINEL = 0x40000000; + +/** + * Avoids oversized V8 backing stores for numeric URL keys. + * Setting then deleting the sentinel keeps indexed properties in dictionary storage. + * Indices below 32 use little space, so leave them alone. + */ +function setUrlDerivedKey(target: {[key: string]: T}, key: string, value: T): void { + // Preserve URL keys that happen to equal the sentinel. + if (Number(key) >= 32 && !Object.hasOwn(target, SLOW_ELEMENTS_SENTINEL)) { + target[SLOW_ELEMENTS_SENTINEL] = value; + delete target[SLOW_ELEMENTS_SENTINEL]; + } + target[key] = value; +} + const SEGMENT_RE = /^[^\/()?;#]+/; function matchSegments(str: string): string { const match = str.match(SEGMENT_RE); @@ -714,7 +750,7 @@ class UrlParser { return; } this.capture(key); - let value: any = ''; + let value = ''; if (this.consumeOptional('=')) { const valueMatch = matchSegments(this.remaining); if (valueMatch) { @@ -723,7 +759,7 @@ class UrlParser { } } - params[decode(key)] = decode(value); + setUrlDerivedKey(params, decode(key), decode(value)); } // Parse a single query parameter `name[=value]` @@ -733,7 +769,7 @@ class UrlParser { return; } this.capture(key); - let value: any = ''; + let value = ''; if (this.consumeOptional('=')) { const valueMatch = matchUrlQueryParamValue(this.remaining); if (valueMatch) { @@ -792,10 +828,11 @@ class UrlParser { } const children = this.parseChildren(depth + 1); - segments[outletName ?? PRIMARY_OUTLET] = + const child = Object.keys(children).length === 1 && children[PRIMARY_OUTLET] ? children[PRIMARY_OUTLET] : new UrlSegmentGroup([], children); + setUrlDerivedKey(segments, outletName ?? PRIMARY_OUTLET, child); this.consumeOptional('//'); } @@ -853,11 +890,11 @@ export function squashSegmentGroup(segmentGroup: UrlSegmentGroup): UrlSegmentGro childCandidate.hasChildren() ) { for (const [grandChildOutlet, grandChild] of Object.entries(childCandidate.children)) { - newChildren[grandChildOutlet] = grandChild; + setUrlDerivedKey(newChildren, grandChildOutlet, grandChild); } } // don't add empty children else if (childCandidate.segments.length > 0 || childCandidate.hasChildren()) { - newChildren[childOutlet] = childCandidate; + setUrlDerivedKey(newChildren, childOutlet, childCandidate); } } const s = new UrlSegmentGroup(segmentGroup.segments, newChildren); diff --git a/packages/router/src/utils/preactivation.ts b/packages/router/src/utils/preactivation.ts index fc9a35e2f65c..e4a11a48666a 100644 --- a/packages/router/src/utils/preactivation.ts +++ b/packages/router/src/utils/preactivation.ts @@ -101,7 +101,7 @@ function getChildRouteGuards( // Process any children left from the current route (not active for the future route) Object.entries(prevChildren).forEach(([k, v]: [string, TreeNode]) => - deactivateRouteAndItsChildren(v, contexts!.getContext(k), checks), + deactivateRouteAndItsChildren(v, contexts!.getContext(k), contexts, checks), ); return checks; @@ -156,7 +156,7 @@ function getRouteGuards( } } else { if (curr) { - deactivateRouteAndItsChildren(currNode, context, checks); + deactivateRouteAndItsChildren(currNode, context, parentContexts, checks); } checks.canActivateChecks.push(new CanActivate(futurePath)); @@ -208,6 +208,7 @@ function shouldRunGuardsAndResolvers( function deactivateRouteAndItsChildren( route: TreeNode, context: OutletContext | null, + parentContexts: ChildrenOutletContexts | null, checks: Checks, ): void { const children = nodeChildrenAsMap(route); @@ -215,11 +216,24 @@ function deactivateRouteAndItsChildren( Object.entries(children).forEach(([childName, node]) => { if (!r.component) { - deactivateRouteAndItsChildren(node, context, checks); + // For componentless routes, children share the parent's outlet contexts. Look up each + // child by its outlet name in parentContexts rather than passing the same context + // (which was derived from the componentless route's own outlet and may be null or wrong). + deactivateRouteAndItsChildren( + node, + parentContexts ? parentContexts.getContext(childName) : null, + parentContexts, + checks, + ); } else if (context) { - deactivateRouteAndItsChildren(node, context.children.getContext(childName), checks); + deactivateRouteAndItsChildren( + node, + context.children.getContext(childName), + context.children, + checks, + ); } else { - deactivateRouteAndItsChildren(node, null, checks); + deactivateRouteAndItsChildren(node, null, null, checks); } }); diff --git a/packages/router/src/utils/view_transition.ts b/packages/router/src/utils/view_transition.ts index 103778009031..259fc19aed5d 100644 --- a/packages/router/src/utils/view_transition.ts +++ b/packages/router/src/utils/view_transition.ts @@ -63,17 +63,27 @@ export interface ViewTransitionInfo { /** * A helper function for using browser view transitions. This function skips the call to - * `startViewTransition` if the browser does not support it. + * `startViewTransition` if the browser does not support it or has already provided a transition. * - * @returns A Promise that resolves when the view transition callback begins. + * @returns A Promise that resolves when the view transition callback begins, or `undefined` when + * the user agent has already provided a transition and the navigation should continue immediately. */ export function createViewTransition( injector: Injector, from: ActivatedRouteSnapshot, to: ActivatedRouteSnapshot, -): Promise { + hasUAVisualTransition?: boolean, +): Promise | undefined { const transitionOptions = injector.get(VIEW_TRANSITION_OPTIONS); const document = injector.get(DOCUMENT); + + if (hasUAVisualTransition) { + transitionOptions.skipNextTransition = false; + // The browser has already started presenting the navigation. Continuing synchronously gives it + // the earliest opportunity to display the post-navigation DOM. + return; + } + if (!document.startViewTransition || transitionOptions.skipNextTransition) { transitionOptions.skipNextTransition = false; // The timing of `startViewTransition` is closer to a macrotask. It won't be called diff --git a/packages/router/test/activated_route_injector.spec.ts b/packages/router/test/activated_route_injector.spec.ts index b02e15c5ec5b..c200384fbd7e 100644 --- a/packages/router/test/activated_route_injector.spec.ts +++ b/packages/router/test/activated_route_injector.spec.ts @@ -18,7 +18,7 @@ import { Router, destroyDetachedRouteHandle, provideRouter, - ɵwithActivatedRouteInjectors, + withRouterResources, } from '@angular/router'; import {RouterTestingHarness} from '@angular/router/testing'; @@ -66,7 +66,7 @@ describe('ActivatedRoute local injector', () => { async function setUpRouter(routes: Route[]): Promise { TestBed.configureTestingModule({ providers: [ - provideRouter(routes, ɵwithActivatedRouteInjectors()), + provideRouter(routes, withRouterResources()), {provide: RouteReuseStrategy, useClass: CustomReuseStrategy}, ], }); @@ -76,13 +76,13 @@ describe('ActivatedRoute local injector', () => { return await RouterTestingHarness.create(); } - it('should create and destroy local injector for routes with ɵUseActivatedRouteInjector', async () => { + it('should create and destroy local injector for routes with resources', async () => { const harness = await setUpRouter([ { path: 'home', component: HomeComponent, - 'ɵUseActivatedRouteInjector': true, - } as any, + resources: () => ({}), + }, { path: 'away', component: AwayComponent, @@ -107,7 +107,7 @@ describe('ActivatedRoute local injector', () => { expect(destroyed).toBe(true); }); - it('should NOT create local injector for routes without ɵUseActivatedRouteInjector', async () => { + it('should NOT create local injector for routes without resources', async () => { const harness = await setUpRouter([ { path: 'home', @@ -127,8 +127,8 @@ describe('ActivatedRoute local injector', () => { { path: 'home', component: HomeComponent, - 'ɵUseActivatedRouteInjector': true, - } as any, + resources: () => ({}), + }, { path: 'away', component: AwayComponent, @@ -186,13 +186,13 @@ describe('ActivatedRoute local injector', () => { { path: 'home', component: HomeComponent, - 'ɵUseActivatedRouteInjector': true, - } as any, + resources: () => ({}), + }, { path: 'throwing', component: ThrowingComponent, - 'ɵUseActivatedRouteInjector': true, - } as any, + resources: () => ({}), + }, ]); await harness.navigateByUrl('/home'); diff --git a/packages/router/test/bootstrap.spec.ts b/packages/router/test/bootstrap.spec.ts index c05e85e21240..fae02051692a 100644 --- a/packages/router/test/bootstrap.spec.ts +++ b/packages/router/test/bootstrap.spec.ts @@ -90,7 +90,7 @@ describe('bootstrap', () => { doc.body.appendChild(el1); doc.body.appendChild(el2); - const {promise, resolveFn} = createPromise(); + const {promise, resolve: resolveFn} = Promise.withResolvers(); navigationEndPromise = promise; log = []; testProviders = [ @@ -455,7 +455,7 @@ describe('bootstrap', () => { spyOn(router as any, 'resetRootComponentType').and.callThrough(); const appRef: ApplicationRef = res.injector.get(ApplicationRef); - const {promise, resolveFn} = createPromise(); + const {promise, resolve: resolveFn} = Promise.withResolvers(); appRef.components[0].onDestroy(() => { appRef.bootstrap(SecondRootCmp); expect((router as any).resetRootComponentType).toHaveBeenCalled(); @@ -629,11 +629,3 @@ function provideNavigationEndAction(fn: Function) { }, }; } - -function createPromise() { - let resolveFn: () => void; - const promise = new Promise((r) => { - resolveFn = r; - }); - return {resolveFn: () => resolveFn(), promise}; -} diff --git a/packages/router/test/directives/router_outlet.spec.ts b/packages/router/test/directives/router_outlet.spec.ts index 6d9ba13d1a81..b2626465e83d 100644 --- a/packages/router/test/directives/router_outlet.spec.ts +++ b/packages/router/test/directives/router_outlet.spec.ts @@ -7,20 +7,30 @@ */ import {CommonModule, NgForOf} from '@angular/common'; -import {Component, inject, Input, Type, NgModule, signal} from '@angular/core'; +import {Component, inject, Input, Type, NgModule, signal, resource} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import { - provideRouter, + provideRouter as internalProvideRouter, Router, RouterModule, RouterOutlet, withComponentInputBinding, ROUTER_OUTLET_DATA, + withRouterResources, + nonBlocking, + Route, + RouterFeatures, } from '../../index'; import {RouterTestingHarness} from '../../testing'; -import {InjectionToken} from '../../../core/src/di'; +import {EnvironmentProviders, InjectionToken} from '../../../core/src/di'; import {useAutoTick, timeout} from '@angular/private/testing'; +export function provideRouter( + routes: Route[], + ...features: RouterFeatures[] +): EnvironmentProviders { + return internalProvideRouter(routes, ...features); +} describe('router outlet name', () => { useAutoTick(); it('should support name binding', async () => { @@ -472,6 +482,176 @@ describe('component input binding', () => { await harness.navigateByUrl('/root/child?myInput=2'); expect(harness.routeNativeElement!.innerText).toBe('2'); }); + + it('when keys conflict, sets inputs based on priority: resources > resolvers > data', async () => { + @Component({ + template: '', + standalone: false, + }) + class MyComponent { + @Input() result?: any; + } + + @Component({ + template: '', + standalone: false, + }) + class MyComponentWithoutResource { + @Input() result?: any; + } + + @Component({ + template: '', + standalone: false, + }) + class MyComponentWithoutResolver { + @Input() result?: any; + } + + TestBed.configureTestingModule({ + providers: [ + provideRouter( + [ + { + path: 'all', + component: MyComponent, + data: {'result': 'from data'}, + resolve: {'result': () => 'from resolver'}, + resources: () => ({ + result: resource({loader: async () => 'from resource'}), + }), + }, + { + path: 'no-resource', + component: MyComponentWithoutResource, + data: {'result': 'from data'}, + resolve: {'result': () => 'from resolver'}, + }, + { + path: 'no-resolver', + component: MyComponentWithoutResolver, + data: {'result': 'from data'}, + }, + ], + withComponentInputBinding(), + withRouterResources(), + ), + ], + }); + const harness = await RouterTestingHarness.create(); + + let instance = await harness.navigateByUrl('/all', MyComponent); + // Precedence: resources > resolvers > data + // resources wins, and it binds ONLY THE VALUE for blocking resources! + expect(typeof instance.result).toBe('string'); + expect(instance.result).toEqual('from resource'); + + const instance2 = await harness.navigateByUrl('/no-resource', MyComponentWithoutResource); + // No resources, so resolver wins! + expect(typeof instance2.result).toBe('string'); + expect(instance2.result).toEqual('from resolver'); + + const instance3 = await harness.navigateByUrl('/no-resolver', MyComponentWithoutResolver); + // No resource, no resolver, so data wins! + expect(typeof instance3.result).toBe('string'); + expect(instance3.result).toEqual('from data'); + }); + + it('binds the actual resource object for non-blocking resources', async () => { + @Component({ + template: '', + standalone: false, + }) + class MyComponent { + @Input() result?: any; + } + + TestBed.configureTestingModule({ + providers: [ + provideRouter( + [ + { + path: '**', + component: MyComponent, + resources: () => ({ + result: nonBlocking(resource({loader: async () => 'from non-blocking resource'})), + }), + }, + ], + withComponentInputBinding(), + withRouterResources(), + ), + ], + }); + const harness = await RouterTestingHarness.create(); + + const instance = await harness.navigateByUrl('/', MyComponent); + await harness.fixture.whenStable(); + expect(typeof instance.result).toBe('object'); + expect(instance.result?.value()).toEqual('from non-blocking resource'); + }); + + it('updates component inputs reactively and cleans up binding effects on outlet deactivation', async () => { + const trigger = signal('initial'); + + @Component({ + template: '', + standalone: false, + }) + class MyComponent { + @Input() result?: string; + } + + @Component({ + template: '', + standalone: false, + }) + class OtherComponent {} + + TestBed.configureTestingModule({ + providers: [ + provideRouter( + [ + { + path: 'resource', + component: MyComponent, + resources: () => ({ + result: resource({ + params: () => trigger(), + loader: async ({params}) => `data: ${params}`, + }), + }), + }, + { + path: 'other', + component: OtherComponent, + }, + ], + withComponentInputBinding(), + withRouterResources(), + ), + ], + }); + const harness = await RouterTestingHarness.create(); + + const instance = await harness.navigateByUrl('/resource', MyComponent); + await harness.fixture.whenStable(); + expect(instance.result).toEqual('data: initial'); + + // Trigger reactive update while active + trigger.set('updated'); + await harness.fixture.whenStable(); + expect(instance.result).toEqual('data: updated'); + + // Navigate away to deactivate outlet component + await harness.navigateByUrl('/other', OtherComponent); + await harness.fixture.whenStable(); + + // Trigger update after deactivation - effect should have been destroyed + trigger.set('after-destroy'); + await harness.fixture.whenStable(); + expect(instance.result).toEqual('data: updated'); + }); }); describe('injectors', () => { diff --git a/packages/router/test/integration/guards.spec.ts b/packages/router/test/integration/guards.spec.ts index a19376a8bd4c..c97cfeaa9d05 100644 --- a/packages/router/test/integration/guards.spec.ts +++ b/packages/router/test/integration/guards.spec.ts @@ -44,6 +44,7 @@ import { RunGuardsAndResolvers, Data, RouterModule, + RouterOutlet, NavigationCancellationCode, RouteConfigLoadStart, RouteConfigLoadEnd, @@ -1187,6 +1188,65 @@ export function guardsIntegrationSuite() { expect(log[0].component).toBeInstanceOf(AdminComponent); }); + it('should pass correct component to canDeactivate when using named outlets in componentless parent routes', async () => { + @Component({ + selector: 'outer', + template: '', + standalone: true, + imports: [RouterOutlet], + }) + class OuterCmp {} + + @Component({selector: 'inner1', template: '', standalone: true}) + class Inner1Cmp {} + + @Component({selector: 'inner2', template: '', standalone: true}) + class Inner2Cmp {} + + const router: Router = TestBed.inject(Router); + const fixture = await createRoot(router, RootCmp); + + router.resetConfig([ + { + path: '', + component: OuterCmp, + children: [ + { + path: 'one', + children: [ + { + path: '', + outlet: 'inner', + component: Inner1Cmp, + canDeactivate: [recordingDeactivate], + }, + ], + }, + { + path: 'two', + children: [ + { + path: '', + outlet: 'inner', + component: Inner2Cmp, + canDeactivate: [recordingDeactivate], + }, + ], + }, + ], + }, + ]); + + router.navigateByUrl('/one'); + await advance(fixture); + + router.navigateByUrl('/two'); + await advance(fixture); + + expect(log.length).toBe(1); + expect(log[0].component).toBeInstanceOf(Inner1Cmp); + }); + it('should not create a route state if navigation is canceled', async () => { const router: Router = TestBed.inject(Router); const location: Location = TestBed.inject(Location); @@ -2488,5 +2548,61 @@ export function guardsIntegrationSuite() { await router.navigateByUrl('/a?q=2'); expect(resolveCount).toBe(2); }); + + describe('throwing redirect', () => { + it('should redirect when a guard throws a RedirectCommand', async () => { + const router = TestBed.inject(Router); + const location = TestBed.inject(Location); + const fixture = await createRoot(router, RootCmp); + + router.resetConfig([ + { + path: 'a', + canActivate: [ + () => { + throw new RedirectCommand(router.parseUrl('/b')); + }, + ], + component: BlankCmp, + }, + { + path: 'b', + component: BlankCmp, + }, + ]); + + router.navigateByUrl('/a'); + await advance(fixture); + + expect(location.path()).toEqual('/b'); + }); + + it('should redirect when a resolver throws a RedirectCommand', async () => { + const router = TestBed.inject(Router); + const location = TestBed.inject(Location); + const fixture = await createRoot(router, RootCmp); + + router.resetConfig([ + { + path: 'a', + resolve: { + data: () => { + throw new RedirectCommand(router.parseUrl('/b')); + }, + }, + component: BlankCmp, + }, + { + path: 'b', + component: BlankCmp, + }, + ]); + + router.navigateByUrl('/a'); + await advance(fixture); + + expect(location.path()).toEqual('/b'); + }); + }); }); } diff --git a/packages/router/test/integration/integration.spec.ts b/packages/router/test/integration/integration.spec.ts index 749ef0e77c99..503ea0bfd97f 100644 --- a/packages/router/test/integration/integration.spec.ts +++ b/packages/router/test/integration/integration.spec.ts @@ -123,7 +123,6 @@ for (const browserAPI of ['navigation', 'history'] as const) { @Component({ selector: 'root-cmp', template: ``, - changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, }) class OnPushOutlet {} diff --git a/packages/router/test/integration/route_reuse_strategy.spec.ts b/packages/router/test/integration/route_reuse_strategy.spec.ts index b781341ba57b..178ed1072266 100644 --- a/packages/router/test/integration/route_reuse_strategy.spec.ts +++ b/packages/router/test/integration/route_reuse_strategy.spec.ts @@ -433,6 +433,222 @@ export function routeReuseIntegrationSuite() { expect(createdComps).toEqual(['parent', 'child', 'child']); }); + it('should render child routes on reused list when outer shell is destroyed and recreated', async () => { + // https://github.com/angular/angular/issues/57285 + + @Component({selector: 'root', template: '', standalone: false}) + class Root {} + + @Component({ + selector: 'events-shell-cmp', + template: '', + standalone: false, + }) + class EventsShellCmp {} + + @Component({ + selector: 'event-list-cmp', + template: '', + standalone: false, + }) + class EventListCmp {} + + @Component({ + selector: 'event-detail-cmp', + template: '', + standalone: false, + }) + class EventDetailCmp {} + + @Component({selector: 'event-edit-cmp', template: 'edit', standalone: false}) + class EventEditCmp {} + + @Component({selector: 'chats-cmp', template: 'chats', standalone: false}) + class ChatsCmp {} + + class ReusableStrategy implements RouteReuseStrategy { + private handles = new Map(); + + shouldDetach(route: ActivatedRouteSnapshot): boolean { + return !!route.routeConfig?.data?.['reusable']; + } + store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle | null): void { + if (route.routeConfig && handle) { + this.handles.set(route.routeConfig, handle); + } else if (route.routeConfig) { + this.handles.delete(route.routeConfig); + } + } + shouldAttach(route: ActivatedRouteSnapshot): boolean { + return !!(route.routeConfig && this.handles.has(route.routeConfig)); + } + retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | null { + return (route.routeConfig && this.handles.get(route.routeConfig)) ?? null; + } + shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { + return future.routeConfig === curr.routeConfig; + } + } + + @NgModule({ + declarations: [Root, EventsShellCmp, EventListCmp, EventDetailCmp, EventEditCmp, ChatsCmp], + imports: [...ROUTER_DIRECTIVES], + providers: [ + {provide: RouteReuseStrategy, useClass: ReusableStrategy}, + provideRouter([ + { + path: 'events', + component: EventsShellCmp, + children: [ + { + path: '', + data: {reusable: true}, + component: EventListCmp, + children: [ + { + path: ':id', + data: {reusable: true}, + component: EventDetailCmp, + children: [{path: 'edit', component: EventEditCmp}], + }, + ], + }, + ], + }, + {path: 'chats', component: ChatsCmp}, + ]), + ], + }) + class TestModule {} + + TestBed.configureTestingModule({imports: [TestModule]}); + const router = TestBed.inject(Router); + const fixture = await createRoot(router, Root); + + router.navigateByUrl('/chats'); + await advance(fixture); + + router.navigateByUrl('/events'); + await advance(fixture); + expect(fixture.debugElement.query(By.directive(EventListCmp))).toBeTruthy(); + + router.navigateByUrl('/chats'); + await advance(fixture); + + // Shell is recreated and the stored list is re-attached into it. + router.navigateByUrl('/events'); + await advance(fixture); + expect(fixture.debugElement.query(By.directive(EventListCmp))).toBeTruthy(); + + router.navigateByUrl('/events/1/edit'); + await advance(fixture); + expect(fixture.debugElement.query(By.directive(EventEditCmp))).toBeTruthy(); + }); + + it('should render child routes of a reused tab after a sibling tab was shown in the same outlet', async () => { + // https://github.com/angular/angular/issues/57285 (sibling outlet case) + + @Component({selector: 'root', template: '', standalone: false}) + class Root {} + + @Component({ + selector: 'tabs-shell-cmp', + template: '', + standalone: false, + }) + class TabsShellCmp {} + + @Component({ + selector: 'tab1-cmp', + template: '', + standalone: false, + }) + class Tab1Cmp {} + + @Component({selector: 'tab1-inner-cmp', template: 'tab1-inner', standalone: false}) + class Tab1InnerCmp {} + + @Component({ + selector: 'tab2-cmp', + template: '', + standalone: false, + }) + class Tab2Cmp {} + + @Component({selector: 'tab2-inner-cmp', template: 'tab2-inner', standalone: false}) + class Tab2InnerCmp {} + + class ReusableStrategy implements RouteReuseStrategy { + private handles = new Map(); + + shouldDetach(route: ActivatedRouteSnapshot): boolean { + return !!route.routeConfig?.data?.['reusable']; + } + store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle | null): void { + if (route.routeConfig && handle) { + this.handles.set(route.routeConfig, handle); + } else if (route.routeConfig) { + this.handles.delete(route.routeConfig); + } + } + shouldAttach(route: ActivatedRouteSnapshot): boolean { + return !!(route.routeConfig && this.handles.has(route.routeConfig)); + } + retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | null { + return (route.routeConfig && this.handles.get(route.routeConfig)) ?? null; + } + shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { + return future.routeConfig === curr.routeConfig; + } + } + + @NgModule({ + declarations: [Root, TabsShellCmp, Tab1Cmp, Tab1InnerCmp, Tab2Cmp, Tab2InnerCmp], + imports: [...ROUTER_DIRECTIVES], + providers: [ + {provide: RouteReuseStrategy, useClass: ReusableStrategy}, + provideRouter([ + { + path: 'tabs', + component: TabsShellCmp, + children: [ + { + path: 'tab1', + data: {reusable: true}, + component: Tab1Cmp, + children: [{path: 'inner', component: Tab1InnerCmp}], + }, + { + path: 'tab2', + component: Tab2Cmp, + children: [{path: 'inner', component: Tab2InnerCmp}], + }, + ], + }, + ]), + ], + }) + class TestModule {} + TestBed.configureTestingModule({imports: [TestModule]}); + + const router = TestBed.inject(Router); + const fixture = await createRoot(router, Root); + + router.navigateByUrl('/tabs/tab1/inner'); + await advance(fixture); + expect(fixture.debugElement.query(By.directive(Tab1InnerCmp))).toBeTruthy(); + + router.navigateByUrl('/tabs/tab2/inner'); + await advance(fixture); + expect(fixture.debugElement.query(By.directive(Tab2InnerCmp))).toBeTruthy(); + expect(fixture.debugElement.query(By.directive(Tab1InnerCmp))).toBeNull(); + + router.navigateByUrl('/tabs/tab1/inner'); + await advance(fixture); + expect(router.url).toEqual('/tabs/tab1/inner'); + expect(fixture.debugElement.query(By.directive(Tab1InnerCmp))).toBeTruthy(); + }); + it('should not try to detach the outlet of a route that does not get to attach a component', async () => { @Component({ selector: 'root', diff --git a/packages/router/test/regression_integration.spec.ts b/packages/router/test/regression_integration.spec.ts index fdec5145f4b8..76a4367725f3 100644 --- a/packages/router/test/regression_integration.spec.ts +++ b/packages/router/test/regression_integration.spec.ts @@ -214,7 +214,6 @@ describe('Integration', () => { isActive: {{ rla.isActive }}
`, - changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, }) class OnPushComponent {} diff --git a/packages/router/test/route_injector_cleanup.spec.ts b/packages/router/test/route_injector_cleanup.spec.ts index 7ee1b372ce4b..589e15e341f2 100644 --- a/packages/router/test/route_injector_cleanup.spec.ts +++ b/packages/router/test/route_injector_cleanup.spec.ts @@ -18,7 +18,7 @@ import { Router, RouterOutlet, provideRouter, - withExperimentalAutoCleanupInjectors, + withAutoCleanupInjectors, RouterModule, destroyDetachedRouteHandle, } from '@angular/router'; @@ -133,7 +133,7 @@ describe('Route Injector Destruction', () => { loadChildren: () => Promise.resolve(LazyModule), }, ], - withExperimentalAutoCleanupInjectors(), + withAutoCleanupInjectors(), ), {provide: RouteReuseStrategy, useClass: CustomReuseStrategy}, ], diff --git a/packages/router/test/router_resource_behavior_spec.ts b/packages/router/test/router_resource_behavior_spec.ts new file mode 100644 index 000000000000..52a2b69abb1b --- /dev/null +++ b/packages/router/test/router_resource_behavior_spec.ts @@ -0,0 +1,530 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import { + Component, + computed, + Resource, + ResourceStatus, + Signal, + signal, + WritableSignal, + resource, + ɵpromiseWithResolvers, +} from '@angular/core'; +import {TestBed} from '@angular/core/testing'; +import {provideRouter, Router, UrlTree} from '@angular/router'; +import {RouterTestingHarness} from '@angular/router/testing'; +import {routerResource} from '../src/router_resource'; +import {timeout, useAutoTick} from '../../private/testing/src/utils'; +import {rxResource} from '@angular/core/rxjs-interop'; +import {Subject} from 'rxjs'; + +@Component({template: ''}) +class DummyComponent {} + +describe('routerResource behavior tests', () => { + useAutoTick(); + let router: Router; + let harness: RouterTestingHarness; + + let guardPromise2: Promise; + let resolveGuard2: (val: boolean | UrlTree) => void; + + let guardPromise3: Promise; + let resolveGuard3: (val: boolean | UrlTree) => void; + + let paramSignal: WritableSignal; + let resolveLoader: (value: string) => void; + + beforeEach(async () => { + TestBed.configureTestingModule({ + providers: [ + provideRouter([ + {path: 'route1', component: DummyComponent}, + { + path: 'route2', + component: DummyComponent, + canActivate: [() => guardPromise2], + }, + { + path: 'route3', + component: DummyComponent, + canActivate: [() => guardPromise3], + }, + {path: 'route4', component: DummyComponent}, + ]), + ], + }); + + router = TestBed.inject(Router); + harness = await RouterTestingHarness.create(); + + // Navigate to /route1 to start at a settled state + await harness.navigateByUrl('/route1'); + await harness.fixture.whenStable(); + }); + + afterEach(() => { + router = undefined!; + harness = undefined!; + guardPromise2 = undefined!; + resolveGuard2 = undefined!; + guardPromise3 = undefined!; + resolveGuard3 = undefined!; + paramSignal = undefined!; + resolveLoader = undefined!; + }); + + // Helper to create a real resource controlled in tests + // Resolves the very first load immediately to 'initial', and returns a pending promise for subsequent loads. + function createRealResource() { + paramSignal = signal('initial'); + let resolveImmediately = true; + + return resource({ + params: () => paramSignal(), + loader: () => { + if (resolveImmediately) { + resolveImmediately = false; + return Promise.resolve('initial'); + } + const {promise, resolve} = Promise.withResolvers(); + resolveLoader = resolve; + return promise; + }, + }); + } + + // Helper to create a wrapped resource controlled in tests inside injection context + function createWrappedResource() { + return TestBed.runInInjectionContext(() => routerResource(createRealResource())); + } + + describe('Basic Snapshot Propagation', () => { + it("should propagate the source resource's snapshot", async () => { + const wrapped = createWrappedResource(); + await timeout(); + + expect(wrapped.status()).toBe('resolved'); + expect(wrapped.value()).toBe('initial'); + + // Update source by changing param and resolving the loader + paramSignal.set('updated'); + await timeout(); // Let the loader trigger + resolveLoader('updated'); + await harness.fixture.whenStable(); + + expect(wrapped.status()).toBe('resolved'); + expect(wrapped.value()).toBe('updated'); + }); + }); + + describe('Transactional Freezing during Navigation', () => { + it('should freeze the snapshot at the start of navigation', async () => { + const wrapped = createWrappedResource(); + await timeout(); + + // Setup pending navigation to /route2 + guardPromise2 = new Promise((resolve) => (resolveGuard2 = resolve)); + const navPromise = harness.navigateByUrl('/route2'); + await timeout(); + + // Update source snapshot while navigating (should be frozen) + paramSignal.set('updated'); + await timeout(); // Loader triggers + + // Should still be frozen at 'initial' + expect(wrapped.value()).toBe('initial'); + const snapshot = wrapped.snapshot(); + expect(snapshot.status).toBe('resolved'); + if (snapshot.status === 'resolved') { + expect(snapshot.value).toBe('initial'); + } + + // Complete navigation to avoid leaving router in pending state + resolveLoader('updated'); // Settle the resource loader + resolveGuard2(true); + await navPromise; + await harness.fixture.whenStable(); + }); + + it('should unfreeze the snapshot when navigation succeeds', async () => { + const wrapped = createWrappedResource(); + await timeout(); + + guardPromise2 = new Promise((resolve) => (resolveGuard2 = resolve)); + const navPromise = harness.navigateByUrl('/route2'); + await timeout(); + + paramSignal.set('updated'); + await timeout(); + + expect(wrapped.value()).toBe('initial'); + + // Let navigation succeed and resource resolve + resolveLoader('updated'); + resolveGuard2(true); + await navPromise; + await harness.fixture.whenStable(); + + // Should now be unfrozen and updated + expect(wrapped.value()).toBe('updated'); + }); + + it('should unfreeze the snapshot when navigation is skipped', async () => { + const wrapped = createWrappedResource(); + await timeout(); + + // Navigate to same URL (/route1) to trigger skipped navigation + const navPromise = harness.navigateByUrl('/route1'); + await timeout(); + + paramSignal.set('updated'); + await timeout(); + resolveLoader('updated'); + + await navPromise; + await harness.fixture.whenStable(); + + // Should be unfrozen and updated + expect(wrapped.value()).toBe('updated'); + }); + }); + + describe('Rollback Recovery', () => { + it('should maintain the freeze when navigation is cancelled due to redirect or being superseded', async () => { + const wrapped = createWrappedResource(); + await timeout(); + + // Block route3 with a pending guard so we can pause and inspect the redirect transition + guardPromise3 = new Promise((resolve) => (resolveGuard3 = resolve)); + + guardPromise2 = new Promise((resolve) => (resolveGuard2 = resolve)); + const navPromise = harness.navigateByUrl('/route2'); + await timeout(); + + paramSignal.set('updated'); + await timeout(); + + // Trigger redirect to /route3 + resolveLoader('updated'); + resolveGuard2(router.createUrlTree(['/route3'])); + await timeout(); // Let nav 1 cancel and redirect nav start + + // The resource should REMAIN frozen at 'initial' during the active redirect navigation + expect(wrapped.value()).toBe('initial'); + + // Now complete the redirect navigation + resolveGuard3(true); + await navPromise; + await harness.fixture.whenStable(); + + // Once the redirect completes, it should unfreeze + expect(wrapped.value()).toBe('updated'); + }); + + it('should initiate rollback recovery and remain frozen on true rollback until source finishes loading', async () => { + const wrapped = createWrappedResource(); + await timeout(); + + guardPromise2 = new Promise((resolve) => (resolveGuard2 = resolve)); + const navPromise = harness.navigateByUrl('/route2'); + await timeout(); + + // Change source value (simulating parameter rollback triggering a new reload of the old value) + paramSignal.set('rolled-back'); + await timeout(); + + // Reject guard to trigger true rollback + resolveGuard2(false); + await navPromise; + await timeout(); + + // Should still be frozen during recovery loading (status must remain 'resolved', not 'reloading'!) + expect(wrapped.status()).toBe('resolved'); + expect(wrapped.value()).toBe('initial'); + + // Complete loading the rolled-back state + resolveLoader('rolled-back-settled'); + await harness.fixture.whenStable(); + + // Now it should be unfrozen and show the settled rolled-back state + expect(wrapped.status()).toBe('resolved'); + expect(wrapped.value()).toBe('rolled-back-settled'); + }); + }); + + describe('Multi-Navigation Interactions', () => { + it('should ignore events from older navigations', async () => { + const wrapped = createWrappedResource(); + await timeout(); + + // Start Nav 1 (to /route2) + guardPromise2 = new Promise((resolve) => (resolveGuard2 = resolve)); + const nav1Promise = harness.navigateByUrl('/route2'); + await timeout(); + + // Start Nav 2 (to /route3), which cancels Nav 1 + guardPromise3 = new Promise((resolve) => (resolveGuard3 = resolve)); + const nav2Promise = harness.navigateByUrl('/route3'); + await timeout(); + + paramSignal.set('updated'); + await timeout(); + + // Resolve Nav 1's guard (should have no effect because Nav 1 was cancelled/superseded) + resolveLoader('updated'); + resolveGuard2(true); + await timeout(); // Wait a moment for events to process (Nav 1's promise is rejected in the background) + + expect(wrapped.value()).toBe('initial'); // Still frozen by Nav 2 + + // Let Nav 2 complete + resolveGuard3(true); + await nav2Promise; + await harness.fixture.whenStable(); + + expect(wrapped.value()).toBe('updated'); // Unfrozen! + + // Clean up Nav 1 promise rejection + await nav1Promise.catch(() => {}); + }); + + it('should clear rollback recovery if a new navigation starts', async () => { + const wrapped = createWrappedResource(); + await timeout(); + + // Start Nav 1 + guardPromise2 = new Promise((resolve) => (resolveGuard2 = resolve)); + const nav1Promise = harness.navigateByUrl('/route2'); + await timeout(); + + // Cancel Nav 1 with rollback + resolveGuard2(false); + // Synchronously trigger the reload to simulate rollback reload! + paramSignal.set('rolled-back'); + await nav1Promise; + await timeout(); + + // While recovery is pending, a new navigation (Nav 2) starts (to /route3) + guardPromise3 = new Promise((resolve) => (resolveGuard3 = resolve)); + const nav2Promise = harness.navigateByUrl('/route3'); + await timeout(); + + // Recovery should be cleared, but the resource is still frozen because of Nav 2. + // Now recovery loading completes (isLoading becomes false) + resolveLoader('rolled-back'); + await timeout(); + + // It should still be frozen at 'initial' because Nav 2 is active! + expect(wrapped.value()).toBe('initial'); + + // Let Nav 2 succeed + resolveGuard3(true); + await nav2Promise; + await harness.fixture.whenStable(); + + // Unfrozen! + expect(wrapped.value()).toBe('rolled-back'); + }); + }); + + describe('Reload Behavior', () => { + it('should allow reload and delegate to source when not frozen', async () => { + const wrapped = createWrappedResource(); + await timeout(); + + const result = wrapped.reload(); + expect(result).toBe(true); + + // Verify that the resource actually started reloading (proves delegation!) + await timeout(); + expect(wrapped.isLoading()).toBe(true); + }); + + it('should ignore reload and return false when frozen', async () => { + const wrapped = createWrappedResource(); + await timeout(); + + guardPromise2 = new Promise((resolve) => (resolveGuard2 = resolve)); + const navPromise = harness.navigateByUrl('/route2'); + await timeout(); + + const result = wrapped.reload(); + expect(result).toBe(false); + + // Clean up + resolveGuard2(true); + await navPromise; + await harness.fixture.whenStable(); + }); + }); + + describe('Reactive Integration with Router Navigation State', () => { + it('should reactively trigger loading but keep the wrapped resource frozen until navigation completes', async () => { + const wrapped = createWrappedResource(); + await harness.fixture.whenStable(); // Let the initial Promise.resolve('data-route1') resolve and the zone stabilize! + + // Initially, we are at route1 and resolved + expect(wrapped.status()).toBe('resolved'); + expect(wrapped.value()).toBe('initial'); + + // 1. Start navigation to route2 (blocked by guard) + guardPromise2 = new Promise((resolve) => (resolveGuard2 = resolve)); + const navPromise = harness.navigateByUrl('/route2'); + await timeout(); // Let router start and freeze the resource + + // 2. Manually trigger the parameter change while navigation is active + paramSignal.set('route2'); + await timeout(); // Let the resource loader trigger in the background + harness.fixture.detectChanges(); + + // The wrapped resource MUST remain frozen at route1's data! + expect(wrapped.status()).toBe('resolved'); + expect(wrapped.value()).toBe('initial'); + + // 3. Settle the resource loader for route2 + resolveLoader('data-route2'); + await timeout(); // Let the resource resolve + harness.fixture.detectChanges(); + + // But the wrapped resource MUST STILL remain frozen at route1's data because the navigation is still pending! + expect(wrapped.status()).toBe('resolved'); + expect(wrapped.value()).toBe('initial'); + + // 4. Resolve the guard to let the navigation complete + resolveGuard2(true); + await navPromise; + await harness.fixture.whenStable(); + + // Now that the navigation completed, the wrapped resource must unfreeze and show route2's data! + expect(wrapped.status()).toBe('resolved'); + expect(wrapped.value()).toBe('data-route2'); + }); + }); + + describe('rxResource Integration', () => { + it('should support wrapping rxResource natively and stream values without completion', async () => { + const triggerSignal = signal('initial'); + let resolveSubject!: Subject; + + const wrapped = TestBed.runInInjectionContext(() => { + return routerResource( + rxResource({ + params: () => triggerSignal(), + stream: () => { + resolveSubject = new Subject(); + return resolveSubject; + }, + }), + ); + }); + + // 1. Verify initial streaming (multiple emissions, no completion) + await timeout(); + resolveSubject.next('initial-1'); + await harness.fixture.whenStable(); + expect(wrapped.value()).toBe('initial-1'); + + resolveSubject.next('initial-2'); + await harness.fixture.whenStable(); + expect(wrapped.value()).toBe('initial-2'); + + // 2. Start navigation (should freeze at the last streamed value) + guardPromise2 = new Promise((resolve) => (resolveGuard2 = resolve)); + const navPromise = harness.navigateByUrl('/route2'); + await timeout(); + + // Trigger a parameter change which creates a new stream + triggerSignal.set('updated'); + await timeout(); + + // Emit a value on the new active stream + resolveSubject.next('updated-1'); + await timeout(); + + // Wrapper must remain frozen at 'initial-2' + expect(wrapped.value()).toBe('initial-2'); + + // 3. Complete navigation to unfreeze + resolveGuard2(true); + await navPromise; + await harness.fixture.whenStable(); + + // Wrapper should unfreeze and show the latest value from the new stream + expect(wrapped.value()).toBe('updated-1'); + + // 4. Verify streaming continues to work after unfreezing + resolveSubject.next('updated-2'); + await harness.fixture.whenStable(); + expect(wrapped.value()).toBe('updated-2'); + }); + + it('should maintain frozen state during rollback recovery until loading completes', async () => { + const valueSignal = signal('initial'); + const statusSignal = signal('resolved'); + const isLoadingSignal = signal(false); + const hasValueSignal = signal(true); + + const customResource: Resource = { + value: valueSignal as Signal, + status: statusSignal.asReadonly(), + isLoading: isLoadingSignal.asReadonly(), + hasValue: (() => hasValueSignal()) as any, + error: signal(undefined).asReadonly(), + snapshot: computed( + () => + ({ + status: statusSignal(), + value: valueSignal()!, + }) as any, + ), + }; + + const wrapped = TestBed.runInInjectionContext(() => routerResource(customResource)); + expect(wrapped.value()).toBe('initial'); + expect(wrapped.isLoading()).toBe(false); + + // Start navigation to route2 with a failing guard to trigger rollback + guardPromise2 = Promise.reject(new Error('Navigation failed')); + try { + await harness.navigateByUrl('/route2'); + } catch {} + + // Reset value and set hasValue to false to simulate recovery fetch starting + statusSignal.set('loading'); + isLoadingSignal.set(true); + valueSignal.set(undefined); + hasValueSignal.set(false); + await timeout(); + + // Wrapped snapshot should be frozen at 'initial' during recovery loading + expect(wrapped.value()).toBe('initial'); + expect(wrapped.isLoading()).toBe(false); + + // Resource receives value while isLoading() remains true and status is 'loading' + valueSignal.set('recovered-stream-1'); + hasValueSignal.set(true); + await timeout(); + + // Rollback recovery remains frozen because isLoading is still true + expect(wrapped.value()).toBe('initial'); + expect(wrapped.isLoading()).toBe(false); + + // Loading completes + statusSignal.set('resolved'); + isLoadingSignal.set(false); + await harness.fixture.whenStable(); + + // Rollback recovery unfreezes because loading is complete + expect(wrapped.value()).toBe('recovered-stream-1'); + expect(wrapped.isLoading()).toBe(false); + }); + }); +}); diff --git a/packages/router/test/router_resource_spec.ts b/packages/router/test/router_resource_spec.ts new file mode 100644 index 000000000000..0abb54f11921 --- /dev/null +++ b/packages/router/test/router_resource_spec.ts @@ -0,0 +1,1135 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import { + Component, + computed, + EnvironmentProviders, + EnvironmentInjector, + inject, + resource, + Resource, + ResourceSnapshot, + ResourceStatus, + Signal, + signal, + WritableResource, + ɵpromiseWithResolvers as promiseWithResolvers, +} from '@angular/core'; +import {TestBed} from '@angular/core/testing'; +import { + provideRouter, + Router, + NavigationError, + withNavigationErrorHandler, + RedirectCommand, + withRouterResources, + nonBlocking, + ActivatedRoute, + ResourceResult, + Route, + RouterFeatures, +} from '@angular/router'; +import {RouterTestingHarness} from '../testing'; +import {timeout, useAutoTick} from '../../private/testing/src/utils'; +import {rxResource} from '@angular/core/rxjs-interop'; +import {of} from 'rxjs'; +import {delay} from 'rxjs/operators'; + +async function setupRouter(routes: Route[], ...features: RouterFeatures[]) { + TestBed.configureTestingModule({ + providers: [provideRouter(routes, ...features, withRouterResources())], + }); + const harness = await RouterTestingHarness.create(); + const router = TestBed.inject(Router); + return {harness, router}; +} + +@Component({template: ''}) +class TargetCmp {} + +describe('Router resources integration', () => { + useAutoTick(); + + describe('Route Configuration and Execution', () => { + it('should execute resources on initial navigation and expose the result', async () => { + const loaderSpy = jasmine.createSpy('loader').and.resolveTo('loaded'); + + const {harness, router} = await setupRouter([ + { + path: 'test', + component: TargetCmp, + resources: () => ({ + data: nonBlocking(resource({loader: loaderSpy})), + }), + }, + ]); + + await harness.navigateByUrl('/test'); + await harness.fixture.whenStable(); + expect(loaderSpy).toHaveBeenCalled(); + + const resourceRef = router.routerState.root.firstChild?.resources?.['data']; + expect(resourceRef?.value()).toBe('loaded'); + }); + + it('should support async resource functions returning a Promise', async () => { + const loaderDeferred = promiseWithResolvers(); + + const {harness, router} = await setupRouter([ + { + path: 'test', + component: TargetCmp, + resources: async () => { + const data = nonBlocking( + resource({ + loader: async () => loaderDeferred.promise, + }), + ); + await timeout(10); + return {data}; + }, + }, + ]); + + await router.navigateByUrl('/test'); + + expect(router.url).toBe('/test'); + + const route = router.routerState.root.firstChild; + const resourceRef = route?.resources?.['data']; + expect(resourceRef).toBeDefined(); + expect(resourceRef?.isLoading()).toBe(true); + expect(resourceRef?.value()).toBeUndefined(); + + loaderDeferred.resolve('async loaded'); + await harness.fixture.whenStable(); + + expect(resourceRef?.isLoading()).toBe(false); + expect(resourceRef?.value()).toBe('async loaded'); + }); + + it('should support async resource functions returning a Promise (blocking)', async () => { + const {harness, router} = await setupRouter([ + { + path: 'test', + component: TargetCmp, + resources: async () => { + const data = resource({loader: async () => 'async loaded'}); + await timeout(10); + return {data}; + }, + }, + ]); + + await harness.navigateByUrl('/test'); + + const route = router.routerState.root.firstChild; + const resourceRef = route?.resources?.['data']; + expect(resourceRef).toBeDefined(); + expect(resourceRef?.value()).toBe('async loaded'); + }); + + it('should await blocking resource resolution even when resources function is async', async () => { + const loaderDeferred = promiseWithResolvers(); + + const {harness, router} = await setupRouter([ + { + path: 'test', + component: TargetCmp, + resources: async () => { + const data = resource({loader: () => loaderDeferred.promise}); + await timeout(10); + return {data}; + }, + }, + ]); + + const navPromise = harness.navigateByUrl('/test'); + + // 1. Wait past the async resources function delay (10ms) + await timeout(15); + harness.fixture.detectChanges(); + + // Navigation must STILL be pending because the blocking resource loader hasn't resolved yet + expect(router.url).not.toBe('/test'); + + // 2. Now resolve the blocking resource loader + loaderDeferred.resolve('resolved data'); + await navPromise; + + expect(router.url).toBe('/test'); + const route = router.routerState.root.firstChild; + const resourceRef = route?.resources?.['data']; + expect(resourceRef?.value()).toBe('resolved data'); + }); + + it('should cleanly ignore resolution of async resource function if navigation was cancelled', async () => { + const firstResources = promiseWithResolvers(); + + const {harness, router} = await setupRouter([ + { + path: 'first', + component: TargetCmp, + resources: () => { + const data = nonBlocking(resource({loader: async () => 'first data'})); + return firstResources.promise.then(() => ({data})); + }, + }, + { + path: 'second', + component: TargetCmp, + resources: () => ({ + data: nonBlocking(resource({loader: async () => 'second data'})), + }), + }, + ]); + + // Start navigation to /first (which will block waiting on firstResourcesPromise) + const nav1 = harness.navigateByUrl('/first'); + await timeout(10); + + // Supersede with navigation to /second + await harness.navigateByUrl('/second'); + await harness.fixture.whenStable(); + + expect(router.url).toBe('/second'); + + // Now resolve the cancelled /first resources promise + firstResources.resolve(); + await harness.fixture.whenStable(); + + // Navigation should remain on /second + expect(router.url).toBe('/second'); + }); + + it('should cleanly ignore resolution of async resource function if navigation was cancelled (blocking)', async () => { + const firstResources = promiseWithResolvers(); + + const {harness, router} = await setupRouter([ + { + path: 'first', + component: TargetCmp, + resources: () => { + const data = resource({loader: async () => 'first data'}); + return firstResources.promise.then(() => ({data})); + }, + }, + { + path: 'second', + component: TargetCmp, + resources: () => ({ + data: resource({loader: async () => 'second data'}), + }), + }, + ]); + + // Start navigation to /first (which will block waiting on firstResourcesPromise) + const nav1 = harness.navigateByUrl('/first'); + await timeout(10); + + // Supersede with navigation to /second + await harness.navigateByUrl('/second'); + await harness.fixture.whenStable(); + + expect(router.url).toBe('/second'); + + // Now resolve the cancelled /first resources promise + firstResources.resolve(); + await harness.fixture.whenStable(); + + // Navigation should remain on /second + expect(router.url).toBe('/second'); + }); + + it('should fail navigation when async resources function rejects', async () => { + const {harness, router} = await setupRouter([ + { + path: 'test', + component: TargetCmp, + resources: async () => { + throw new Error('Async setup failed'); + }, + }, + ]); + + await expectAsync(harness.navigateByUrl('/test')).toBeRejectedWithError(/Async setup failed/); + expect(router.url).not.toContain('/test'); + }); + + it('should not recreate and re-execute resources on subsequent navigations to the same route', async () => { + let callCount = 0; + + const {harness} = await setupRouter([ + { + path: 'test/:id', + component: TargetCmp, + resources: (ctx) => ({ + data: nonBlocking( + resource({ + params: () => ctx.params(), + loader: async () => { + callCount++; + return 'loaded'; + }, + }), + ), + }), + }, + ]); + + await harness.navigateByUrl('/test/1'); + expect(callCount).toBe(1); + + // Navigating to the identical URL should not trigger a refetch + await harness.navigateByUrl('/test/1'); + expect(callCount).toBe(1); + }); + + it('should support resources on componentless routes', async () => { + const {harness, router} = await setupRouter([ + { + path: 'parent', + resources: () => ({ + parentData: nonBlocking(resource({loader: async () => 'parent'})), + }), + children: [ + { + path: 'componentless', + resources: () => ({ + compData: nonBlocking(resource({loader: async () => 'comp'})), + }), + children: [{path: 'child', component: TargetCmp}], + }, + ], + }, + ]); + + await harness.navigateByUrl('/parent/componentless/child'); + await timeout(20); + + const parentRoute = router.routerState.root.firstChild!; + const componentlessRoute = parentRoute.firstChild!; + + expect(parentRoute.resources?.['parentData']?.value()).toBe('parent'); + expect(componentlessRoute.resources?.['compData']?.value()).toBe('comp'); + }); + + it('should throw an error in dev mode if resource function does not return a Resource', async () => { + const {harness} = await setupRouter([ + { + path: 'test', + component: TargetCmp, + resources: () => ({ + data: {foo: 'bar'} as unknown as Resource & + Pick, 'reload'>, + }), + }, + ]); + + await expectAsync(harness.navigateByUrl('/test')).toBeRejectedWithError( + /Invalid resource returned for key "data"/, + ); + }); + }); + + describe('Blocking vs Non-blocking Resources', () => { + it('should resolve resources before component initialization if blocking', async () => { + let resolverSpy = jasmine.createSpy('resolver'); + const deferred = promiseWithResolvers(); + + const {harness, router} = await setupRouter([ + { + path: 'test', + component: TargetCmp, + resources: () => ({ + data: resource({ + loader: async () => { + resolverSpy(); + return await deferred.promise; + }, + }), + }), + }, + ]); + + let completed = false; + const navPromise = harness.navigateByUrl('/test').then(() => { + completed = true; + }); + + await timeout(10); + expect(completed).toBe(false); + expect(router.url).toBe('/'); + expect(resolverSpy).toHaveBeenCalled(); + + deferred.resolve('resolved'); + await navPromise; + expect(completed).toBe(true); + expect(router.url).toBe('/test'); + }); + + it('should cancel navigation when blocking resource yields error', async () => { + const {harness, router} = await setupRouter([ + { + path: 'test', + component: TargetCmp, + resources: () => ({ + data: resource({ + loader: () => Promise.reject('test error'), + }), + }), + }, + ]); + + await harness.navigateByUrl('/test').catch(() => {}); + expect(router.url).not.toContain('/test'); + }); + + it('should emit NavigationError when blocking resource rejects', async () => { + const {harness, router} = await setupRouter([ + { + path: 'test', + component: TargetCmp, + resources: () => ({ + data: resource({ + loader: () => Promise.reject('test error'), + }), + }), + }, + ]); + + const error = await new Promise((resolve) => { + router.events.subscribe((e) => { + if (e instanceof NavigationError) resolve(e.error); + }); + harness.navigateByUrl('/test').catch(() => {}); + }); + expect(typeof error).toBe('object'); + expect(error).toBeDefined(); + }); + + it('should allow retrying a blocking route that previously threw an error', async () => { + let shouldError = false; + + const {harness, router} = await setupRouter([ + { + path: 'test/:id', + component: TargetCmp, + resources: () => ({ + data: resource({ + loader: async () => { + if (shouldError) throw new Error('Failed'); + return '1'; + }, + }), + }), + }, + ]); + + // 1. Initial navigation succeeds + await harness.navigateByUrl('/test/1'); + await harness.fixture.whenStable(); + expect(router.url).toBe('/test/1'); + + const resourceRef = router.routerState.root.firstChild?.resources?.['data']; + expect(resourceRef?.value()).toBe('1'); + + // 2. Resource encounters an error while on the route + shouldError = true; + resourceRef?.reload(); + await harness.fixture.whenStable(); + expect(resourceRef?.status()).toBe('error'); + + // 3. Retry the identical route with same parameters using onSameUrlNavigation: 'reload' + shouldError = false; + await router.navigateByUrl('/test/1', {onSameUrlNavigation: 'reload'}); + await harness.fixture.whenStable(); + + expect(router.url).toBe('/test/1'); // Succeeded! + expect(resourceRef?.status()).toBe('resolved'); + expect(resourceRef?.value()).toBe('1'); + }); + + it('should block navigation when a resource has a defaultValue until loading is complete', async () => { + const loaderDeferred = promiseWithResolvers(); + + const {harness, router} = await setupRouter([ + { + path: 'test', + component: TargetCmp, + resources: () => ({ + user: resource({ + defaultValue: 'default-user', + loader: async () => loaderDeferred.promise, + }), + }), + }, + ]); + + const nav = harness.navigateByUrl('/test'); + await timeout(); + + // Navigation is blocked on loading even though the resource has a defaultValue + expect(router.url).not.toBe('/test'); + + loaderDeferred.resolve('loaded-user'); + await nav; + + expect(router.url).toBe('/test'); + + const resourceRef = router.routerState.root.firstChild?.resources?.['user']; + expect(resourceRef?.value()).toBe('loaded-user'); + expect(resourceRef?.isLoading()).toBe(false); + }); + + it('should complete navigation and expose error for non-blocking resources', async () => { + const {harness, router} = await setupRouter([ + { + path: 'test', + component: TargetCmp, + resources: () => ({ + data: nonBlocking( + resource({ + loader: async () => { + throw new Error('Non-blocking error'); + }, + }), + ), + }), + }, + ]); + + // Non-blocking resource error doesn't cancel navigation + await harness.navigateByUrl('/test'); + await harness.fixture.whenStable(); + + expect(router.url).toBe('/test'); + const resourceRef = router.routerState.root.firstChild?.resources?.['data']; + expect(resourceRef?.error()?.message).toBe('Non-blocking error'); + expect(resourceRef?.isLoading()).toBe(false); + }); + + it('should complete navigation when a resource is idle and not loading', async () => { + const {harness, router} = await setupRouter([ + { + path: 'search', + component: TargetCmp, + resources: (ctx) => ({ + data: resource({ + params: () => ctx.queryParams()['q'], + loader: async ({params}) => `Query: ${params}`, + }), + }), + }, + ]); + + // Navigate without query params -> params() is undefined -> resource is idle + await harness.navigateByUrl('/search'); + + expect(router.url).toBe('/search'); + const resourceRef = router.routerState.root.firstChild?.resources?.['data']; + expect(resourceRef?.status()).toBe('idle'); + expect(resourceRef?.value()).toBeUndefined(); + }); + }); + + describe('Integration with Router Features', () => { + it('should work with resolvers', async () => { + const {harness, router} = await setupRouter([ + { + path: 'test', + component: TargetCmp, + resolve: {id: () => '123'}, + resources: (ctx) => ({ + data: nonBlocking( + resource({ + params: () => ctx.data(), + loader: async ({params}: any) => ({name: `user ${params['id']}`}), + }), + ), + }), + }, + ]); + + await harness.navigateByUrl('/test'); + const resourceRef = router.routerState.root.firstChild?.resources?.['data'] as any; + + await timeout(20); + expect(resourceRef?.value()).toEqual({name: 'user 123'}); + }); + + it('should rollback parameter state on failed navigation', async () => { + let canActivate = true; + + const {harness, router} = await setupRouter([ + { + path: 'test/:id', + component: TargetCmp, + canActivate: [ + async () => { + await timeout(10); + return canActivate; + }, + ], + resources: (ctx) => ({ + data: nonBlocking( + resource({ + params: () => ctx.params(), + loader: async ({params}: any) => params['id'], + }), + ), + }), + }, + ]); + + await harness.navigateByUrl('/test/1'); + await harness.fixture.whenStable(); + const resourceRef = router.routerState.root.firstChild?.resources?.['data']; + expect(resourceRef?.value()).toBe('1'); + + // Fail next navigation + canActivate = false; + await harness.navigateByUrl('/test/2'); + + // The navigation is cancelled so the resource should retain the old value without loading flicker. + expect(resourceRef?.value()).toBe('1'); + expect(resourceRef?.isLoading()).toBe(false); + }); + + it('should maintain frozen state on rollback when navigation fails until rollback reload completes', async () => { + let loaderDeferred = promiseWithResolvers(); + + const {harness, router} = await setupRouter([ + { + path: 'test/:id', + component: TargetCmp, + resources: (ctx) => ({ + data: resource({ + defaultValue: 'default-value', + params: () => ctx.params(), + loader: async ({params}) => { + if (params['id'] === '2') { + throw new Error('Failed navigation'); + } + return loaderDeferred.promise; + }, + }), + }), + }, + ]); + + // Initial navigation to /test/1 + const nav1 = harness.navigateByUrl('/test/1'); + await timeout(); + loaderDeferred.resolve('loaded-1'); + await nav1; + await harness.fixture.whenStable(); + + const resourceRef = router.routerState.root.firstChild?.resources?.['data'] as any; + expect(resourceRef.value()).toBe('loaded-1'); + expect(resourceRef.isLoading()).toBe(false); + + // Prepare a new deferred for the reload of id '1' when /test/2 fails and rolls back to /test/1 + loaderDeferred = promiseWithResolvers(); + + const nav2 = harness.navigateByUrl('/test/2').catch(() => {}); + await nav2; + await timeout(); + + // The rollback reload for /test/1 is pending (loaderDeferred is not resolved yet). + // The resource should remain frozen: value is 'loaded-1', isLoading is false, status is 'resolved' + expect(resourceRef.isLoading()).toBe(false); + expect(resourceRef.value()).toBe('loaded-1'); + expect(resourceRef.status()).toBe('resolved'); + + // Now resolve the rollback reload + loaderDeferred.resolve('reloaded-1'); + await harness.fixture.whenStable(); + + // After settling, resource is unfrozen and has the new value + expect(resourceRef.isLoading()).toBe(false); + expect(resourceRef.value()).toBe('reloaded-1'); + }); + + it('should abort previous request via AbortSignal when a new navigation comes in', async () => { + const deferred = promiseWithResolvers<{name: string}>(); + let aborted = false; + + const {harness, router} = await setupRouter([ + { + path: 'user/:id', + component: TargetCmp, + resources: (ctx) => ({ + user: nonBlocking( + resource({ + params: () => ctx.params(), + loader: async ({params, abortSignal}: any) => { + abortSignal.addEventListener('abort', () => (aborted = true)); + if (params['id'] === '1') return deferred.promise; + return {name: 'user 2'}; + }, + }), + ), + }), + }, + ]); + + harness.navigateByUrl('/user/1'); + await timeout(10); + + await harness.navigateByUrl('/user/2'); + await harness.fixture.whenStable(); + expect(aborted).toBe(true); + + const userResource = router.routerState.root.firstChild?.resources?.['user']; + expect(userResource?.value()).toEqual({name: 'user 2'}); + + // Resolving the old promise should have no effect + deferred.resolve({name: 'user 1'}); + await timeout(10); + expect(userResource?.value()).toEqual({name: 'user 2'}); + }); + + it('should correctly propagate parameter state when a pending navigation supersedes identically reused routes', async () => { + const p2 = new Promise(() => {}); // never resolves + const p3 = promiseWithResolvers(); + + let loadedParams: any[] = []; + + const {harness, router} = await setupRouter([ + { + path: 'test/:id', + component: TargetCmp, + resources: (ctx: any) => ({ + data: resource({ + params: () => ctx.params(), + loader: async ({params}: any) => { + loadedParams.push(params['id']); + if (params['id'] === '2') return p2; + if (params['id'] === '3') return p3.promise; + return params['id']; + }, + }), + }), + }, + ]); + + await harness.navigateByUrl('/test/1'); + + // Trigger nav2 and let it pend. + harness.navigateByUrl('/test/2'); + await timeout(10); + + // Supersede with identical route (/test/2 -> /test/3) + const nav3 = harness.navigateByUrl('/test/3'); + await timeout(10); + + expect(loadedParams).toEqual(['1', '2', '3']); + + p3.resolve('loaded-3'); + await nav3; + + const resourceRef = router.routerState.root.firstChild?.resources?.['data']; + expect(resourceRef?.value()).toBe('loaded-3'); + }); + + it('should mask loading states during multi-step Guard UrlTree redirects', async () => { + let loader = promiseWithResolvers(); + + const {harness, router} = await setupRouter([ + { + path: 'target/:id', + component: TargetCmp, + resources: (ctx: any) => ({ + data: resource({ + params: () => ctx.params(), + loader: async () => loader.promise, + }), + }), + }, + { + path: 'bad-link', + canActivate: [() => TestBed.inject(Router).createUrlTree(['/target/3'])], + component: TargetCmp, + }, + ]); + + // Settle initial state + loader.resolve('1'); + await harness.navigateByUrl('/target/1'); + await harness.fixture.whenStable(); + + const resourceRef = router.routerState.root.firstChild?.resources?.['data']; + expect(resourceRef?.value()).toBe('1'); + expect(resourceRef?.isLoading()).toBe(false); + + loader = promiseWithResolvers(); + + // Initiate a navigation to a link that Redirects using a UrlTree Guard. + const nav2 = harness.navigateByUrl('/bad-link'); + await timeout(50); + + // UI is still masked looking like '1' + expect(resourceRef?.isLoading()).toBe(false); + expect(resourceRef?.value()).toBe('1'); + + loader.resolve('3'); + await nav2; + await harness.fixture.whenStable(); + + expect(resourceRef?.isLoading()).toBe(false); + expect(resourceRef?.value()).toBe('3'); + }); + + it('should be able to redirect from a blocking resource using a NavigationErrorHandler', async () => { + let handleCount = 0; + let errorRef: unknown = null; + + const {harness, router} = await setupRouter( + [ + { + path: 'test', + component: TargetCmp, + resources: () => ({ + data: resource({ + loader: async () => { + throw new Error('Resource failed!'); + }, + }), + }), + }, + { + path: 'error', + component: TargetCmp, + }, + ], + withNavigationErrorHandler((e: NavigationError) => { + handleCount++; + errorRef = e.error; + return new RedirectCommand(TestBed.inject(Router).parseUrl('/error')); + }), + ); + + await harness.navigateByUrl('/test'); + + expect(router.url).toBe('/error'); + expect(handleCount).toBe(1); + expect((errorRef as Error).message).toBe('Resource failed!'); + }); + + it('should redirect when a blocking resource throws a RedirectCommand', async () => { + const {harness, router} = await setupRouter([ + { + path: 'test', + component: TargetCmp, + resources: () => ({ + data: resource({ + loader: async () => { + throw new RedirectCommand(TestBed.inject(Router).parseUrl('/redirected')); + }, + }), + }), + }, + { + path: 'redirected', + component: TargetCmp, + }, + ]); + + await harness.navigateByUrl('/test'); + + expect(router.url).toBe('/redirected'); + }); + }); + + describe('rxResource Integration', () => { + it('should successfully wrap and await an rxResource', async () => { + const {harness, router} = await setupRouter([ + { + path: 'rx/:id', + component: TargetCmp, + resources: (ctx) => ({ + data: rxResource({ + params: () => ctx.params(), + stream: ({params}: any) => of(`rx loaded ${params['id']}`).pipe(delay(10)), + }), + }), + }, + ]); + + const nav = harness.navigateByUrl('/rx/123'); + await timeout(5); + + const resourceRef = router.routerState.root.firstChild?.resources?.['data']; + expect(resourceRef?.isLoading()).toBe(true); + expect(resourceRef?.value()).toBeUndefined(); + + await nav; + + expect(resourceRef?.isLoading()).toBe(false); + expect(resourceRef?.value()).toBe('rx loaded 123'); + }); + + it('should remain blocked when a resource emits a value while remaining in loading state until loading completes', async () => { + const valueSignal = signal(undefined); + const statusSignal = signal('loading'); + const isLoadingSignal = signal(true); + const hasValueSignal = signal(false); + + const customResource: Resource & {reload(): boolean} = { + value: valueSignal.asReadonly(), + status: statusSignal.asReadonly(), + isLoading: isLoadingSignal.asReadonly(), + hasValue(): this is Resource { + return hasValueSignal(); + }, + error: signal(undefined).asReadonly(), + snapshot: computed>(() => ({ + status: statusSignal() as 'loading' | 'resolved', + value: valueSignal(), + })), + reload: () => false, + }; + + const {harness, router} = await setupRouter([ + { + path: 'stream', + component: TargetCmp, + resources: () => ({ + data: customResource, + }), + }, + ]); + + const nav = harness.navigateByUrl('/stream'); + await timeout(); + + // Navigation should be pending because customResource is in loading state + expect(router.url).not.toBe('/stream'); + + // Custom resource emits a value while retaining isLoading() === true and status 'loading' + valueSignal.set('streamed-1'); + hasValueSignal.set(true); + await timeout(); + + // Navigation should still be blocked because loading state is true + expect(router.url).not.toBe('/stream'); + + // Resource finishes loading + statusSignal.set('resolved'); + isLoadingSignal.set(false); + await nav; + + expect(router.url).toBe('/stream'); + const resourceRef = router.routerState.root.firstChild?.resources?.['data']; + expect(resourceRef?.value()).toBe('streamed-1'); + expect(resourceRef?.isLoading()).toBe(false); + }); + + describe('dependent resources', () => { + it('should support resources depending on each other on the same route', async () => { + const {promise: userPromise, resolve: resolveUser} = promiseWithResolvers<{ + id: string; + teamId: string; + }>(); + + const {harness, router} = await setupRouter([ + { + path: 'user-team', + component: TargetCmp, + resources: () => { + const user = resource({ + loader: () => userPromise, + }); + const team = resource({ + params: ({chain}) => chain(user)?.teamId, + loader: async ({params: teamId}) => ({id: teamId, name: 'Angular Team'}), + }); + return {user, team}; + }, + }, + ]); + + const nav = harness.navigateByUrl('/user-team'); + await timeout(); + + // Navigation is blocked because user is loading and team depends on user + expect(router.url).not.toBe('/user-team'); + + // Resolve user + resolveUser({id: 'u1', teamId: 't42'}); + await nav; + + expect(router.url).toBe('/user-team'); + const resources = router.routerState.root.firstChild?.resources; + expect(resources?.['user']?.value()).toEqual({id: 'u1', teamId: 't42'}); + expect(resources?.['team']?.value()).toEqual({id: 't42', name: 'Angular Team'}); + }); + + it('should support child route resource depending on shared signal updated by parent resource', async () => { + const {promise: parentPromise, resolve: resolveParent} = promiseWithResolvers(); + const {promise: childPromise, resolve: resolveChild} = promiseWithResolvers(); + + const sharedUserSignal = signal(undefined); + + const {harness, router} = await setupRouter([ + { + path: 'user/:id', + component: TargetCmp, + resources: () => ({ + user: resource({ + loader: async () => { + const user = await parentPromise; + sharedUserSignal.set(user); + return user; + }, + }), + }), + children: [ + { + path: 'details', + component: TargetCmp, + resources: () => ({ + details: resource({ + params: () => sharedUserSignal()?.role, + loader: async ({params: role}) => { + if (!role) { + return new Promise(() => {}); + } + return childPromise; + }, + }), + }), + }, + ], + }, + ]); + + const nav = harness.navigateByUrl('/user/1/details'); + await timeout(); + + // Navigation is blocked + expect(router.url).not.toBe('/user/1/details'); + + // Resolve parent + resolveParent({id: '1', role: 'admin'}); + await timeout(); + + // Still blocked on child + expect(router.url).not.toBe('/user/1/details'); + + // Resolve child + resolveChild({role: 'admin', permissions: ['read', 'write']}); + await nav; + + expect(router.url).toBe('/user/1/details'); + const parentRoute = router.routerState.root.firstChild!; + const childRoute = parentRoute.firstChild!; + expect(parentRoute.resources?.['user'].value()).toEqual({id: '1', role: 'admin'}); + expect(childRoute.resources?.['details'].value()).toEqual({ + role: 'admin', + permissions: ['read', 'write'], + }); + }); + }); + + describe('Resource reloading', () => { + it('should expose reload() on ActivatedRoute.resources without requiring a cast', async () => { + let fetchCount = 0; + @Component({ + template: '

{{ userResource?.value() }}

', + }) + class UserProfileCmp { + userResource = inject(ActivatedRoute).resources?.['user']; + + refreshUser(): boolean | undefined { + return this.userResource?.reload(); + } + } + + const {harness} = await setupRouter([ + { + path: 'user', + component: UserProfileCmp, + resources: () => ({ + user: resource({ + loader: async () => `User #${++fetchCount}`, + }), + }), + }, + ]); + + const instance = await harness.navigateByUrl('/user', UserProfileCmp); + + expect(fetchCount).toBe(1); + expect(instance.userResource?.value()).toBe('User #1'); + + const reloaded = instance.refreshUser(); + expect(reloaded).toBe(true); + await timeout(); + + expect(fetchCount).toBe(2); + expect(instance.userResource?.value()).toBe('User #2'); + }); + + it('should type resources on ActivatedRoute with reload()', async () => { + const {harness, router} = await setupRouter([ + { + path: 'test', + component: TargetCmp, + resources: () => ({ + data: resource({loader: async () => 'hello'}), + }), + }, + ]); + + await harness.navigateByUrl('/test'); + await harness.fixture.whenStable(); + + const route = router.routerState.root.firstChild!; + const dataResource = route.resources?.['data']; + expect(dataResource?.reload()).toBe(true); + expect(dataResource?.value()).toBe('hello'); + }); + + it('should return false from reload() when the underlying resource does not support reload', async () => { + const customResource: Resource = { + value: signal('static').asReadonly(), + status: signal('resolved').asReadonly(), + isLoading: signal(false).asReadonly(), + hasValue(): this is Resource { + return true; + }, + error: signal(undefined).asReadonly(), + snapshot: signal>({ + status: 'resolved', + value: 'static', + }), + }; + + const {harness, router} = await setupRouter([ + { + path: 'custom', + component: TargetCmp, + resources: () => + ({ + custom: customResource, + }) as unknown as ResourceResult, + }, + ]); + + await harness.navigateByUrl('/custom'); + + const route = router.routerState.root.firstChild!; + expect(route.resources?.['custom']?.reload()).toBe(false); + expect(route.resources?.['custom']?.value()).toBe('static'); + }); + }); + }); +}); diff --git a/packages/router/test/url_serializer.spec.ts b/packages/router/test/url_serializer.spec.ts index 70329510ab0b..3342fe20cbdf 100644 --- a/packages/router/test/url_serializer.spec.ts +++ b/packages/router/test/url_serializer.spec.ts @@ -472,6 +472,36 @@ describe('url serializer', () => { expect(() => url.parse(`/${urlStr}`)).not.toThrow(); }); }); + + describe('numeric parameter and outlet names', () => { + it('should round-trip numeric names without adding the internal sentinel', () => { + const tree = url.parse('/one;7=a;32=b;032=c;1e3=d(32:two)'); + + expect(tree.root.children[PRIMARY_OUTLET].segments[0].parameters).toEqual({ + '7': 'a', + '32': 'b', + '032': 'c', + '1e3': 'd', + }); + expectSegment(tree.root.children['32'], 'two'); + expect(url.serialize(tree)).toEqual('/one;7=a;32=b;032=c;1e3=d(32:two)'); + }); + + it('should preserve names that match the internal sentinel', () => { + // 1073741824 is the helper's sentinel. + const tree = url.parse('/one;1073741824=keep;32=other(1073741824:two//32:three)'); + + expect(tree.root.children[PRIMARY_OUTLET].segments[0].parameters).toEqual({ + '1073741824': 'keep', + '32': 'other', + }); + expectSegment(tree.root.children['1073741824'], 'two'); + expectSegment(tree.root.children['32'], 'three'); + expect(url.serialize(tree)).toEqual( + '/one;32=other;1073741824=keep(32:three//1073741824:two)', + ); + }); + }); }); function expectSegment( diff --git a/packages/router/test/url_tree.spec.ts b/packages/router/test/url_tree.spec.ts index 7854a9b2419c..19bbf5174ce3 100644 --- a/packages/router/test/url_tree.spec.ts +++ b/packages/router/test/url_tree.spec.ts @@ -371,6 +371,61 @@ describe('UrlTree', () => { }, ); }); + + describe('options', () => { + it('should default to subset matching when options are omitted', () => { + const t1 = serializer.parse('/one/two/three'); + const t2 = serializer.parse('/one/two'); + expect(containsTree(t1, t2)).toBe(true); + }); + + it('should perform exact matching when passing exactMatchOptions', () => { + const t1 = serializer.parse('/one/two/three'); + const t2 = serializer.parse('/one/two'); + expect(containsTree(t1, t2, exactMatchOptions)).toBe(false); + + const t3 = serializer.parse('/one/two'); + expect(containsTree(t3, t2, exactMatchOptions)).toBe(true); + }); + + it('should require exact query parameter matches when passing exactMatchOptions', () => { + const t1 = serializer.parse('/one/two?a=1&b=2'); + const t2 = serializer.parse('/one/two?a=1'); + expect(containsTree(t1, t2, exactMatchOptions)).toBe(false); + }); + + it('should default to subset matching when passed an empty options object', () => { + const t1 = serializer.parse('/one/two/three'); + const t2 = serializer.parse('/one/two'); + expect(containsTree(t1, t2, {})).toBe(true); + }); + + it('should handle undefined options without throwing', () => { + const t1 = serializer.parse('/one/two/three'); + const t2 = serializer.parse('/one/two'); + expect(containsTree(t1, t2, undefined)).toBe(true); + }); + + it('should handle null options gracefully', () => { + const t1 = serializer.parse('/one/two/three'); + const t2 = serializer.parse('/one/two'); + expect(containsTree(t1, t2, null as any)).toBe(true); + }); + }); + + describe('partial options', () => { + it('should allow overriding specific options while applying subset defaults for the rest', () => { + const t1 = serializer.parse('/one/two/three?test=1&page=5'); + const t2 = serializer.parse('/one/two?test=1'); + expect(containsTree(t1, t2, {paths: 'subset'})).toBe(true); + }); + + it('should enforce exact paths when explicitly set while keeping subset queryParams default', () => { + const t1 = serializer.parse('/one/two/three?test=1&page=5'); + const t2 = serializer.parse('/one/two?test=1'); + expect(containsTree(t1, t2, {paths: 'exact'})).toBe(false); + }); + }); }); }); }); diff --git a/packages/service-worker/src/provider.ts b/packages/service-worker/src/provider.ts index e9d0dd3f1a8a..b14dcc43a7c2 100644 --- a/packages/service-worker/src/provider.ts +++ b/packages/service-worker/src/provider.ts @@ -143,8 +143,7 @@ export function ngswCommChannelFactory(): NgswCommChannel { * You can use this token to define a provider that generates the registration options at runtime, * for example via a function call: * - * {@example service-worker/registration-options/module.ts region="registration-options" - * header="app.module.ts"} + * {@example service-worker/registration-options/module.ts region="registration-options"} * * @see [Service worker configuration](ecosystem/service-workers/getting-started#service-worker-configuration) * diff --git a/packages/service-worker/src/push.ts b/packages/service-worker/src/push.ts index 98d8118efbbe..e13e1e805a0b 100644 --- a/packages/service-worker/src/push.ts +++ b/packages/service-worker/src/push.ts @@ -24,16 +24,14 @@ import {ERR_SW_NOT_SUPPORTED, NgswCommChannel, PushEvent} from './low_level'; * You can inject a `SwPush` instance into any component or service * as a dependency. * - * + * {@example service-worker/push/service_worker_component.ts region='inject-sw-push'} * * To subscribe, call `SwPush.requestSubscription()`, which asks the user for permission. * The call returns a `Promise` with a new * [`PushSubscription`](https://developer.mozilla.org/en-US/docs/Web/API/PushSubscription) * instance. * - * + * {@example service-worker/push/service_worker_component.ts region='subscribe-to-push'} * * A request is rejected if the user denies permission, or if the browser * blocks or does not support the Push API or ServiceWorkers. @@ -78,8 +76,7 @@ import {ERR_SW_NOT_SUPPORTED, NgswCommChannel, PushEvent} from './low_level'; * An application can subscribe to `SwPush.notificationClicks` observable to be notified when a user * clicks on a notification. For example: * - * + * {@example service-worker/push/service_worker_component.ts region='subscribe-to-notification-clicks'} * * You can read more on handling notification clicks in the [Service worker notifications * guide](ecosystem/service-workers/push-notifications). diff --git a/packages/service-worker/worker/src/driver.ts b/packages/service-worker/worker/src/driver.ts index c48a63c230a2..2e2d4cdb88bd 100644 --- a/packages/service-worker/worker/src/driver.ts +++ b/packages/service-worker/worker/src/driver.ts @@ -417,7 +417,7 @@ export class Driver implements Debuggable, UpdateSource { } const desc = data.notification as {[key: string]: string | undefined}; let options: {[key: string]: string | undefined} = {}; - NOTIFICATION_OPTION_NAMES.filter((name) => desc.hasOwnProperty(name)).forEach( + NOTIFICATION_OPTION_NAMES.filter((name) => Object.hasOwn(desc, name)).forEach( (name) => (options[name] = desc[name]), ); await this.scope.registration.showNotification(desc['title']!, options); @@ -671,7 +671,7 @@ export class Driver implements Debuggable, UpdateSource { // Make sure latest manifest is correctly installed. If not (e.g. corrupted data), // it could stay locked in EXISTING_CLIENTS_ONLY or SAFE_MODE state. - if (!this.versions.has(latest.latest) && !manifests.hasOwnProperty(latest.latest)) { + if (!this.versions.has(latest.latest) && !Object.hasOwn(manifests, latest.latest)) { this.debugger.log( `Missing manifest for latest version hash ${latest.latest}`, 'initialize: read from DB', diff --git a/packages/tsconfig-build.json b/packages/tsconfig-build.json index ea0e84bc1e46..2847489ae2a5 100644 --- a/packages/tsconfig-build.json +++ b/packages/tsconfig-build.json @@ -9,17 +9,15 @@ "stripInternal": true, "noImplicitAny": true, "noImplicitOverride": true, - "strictNullChecks": true, + "stableTypeOrdering": true, "noImplicitReturns": true, "noPropertyAccessFromIndexSignature": true, "esModuleInterop": true, - "strict": true, - "strictPropertyInitialization": true, "noFallthroughCasesInSwitch": true, "moduleResolution": "bundler", "module": "esnext", "target": "es2022", - "lib": ["es2020", "es2022", "dom", "dom.iterable"], + "lib": ["es2022", "es2024.promise", "dom", "dom.iterable"], "skipLibCheck": true, // don't auto-discover @types/node, it results in a ///window).angular; } } catch { diff --git a/packages/upgrade/src/common/src/downgrade_component_adapter.ts b/packages/upgrade/src/common/src/downgrade_component_adapter.ts index f760971b2b3b..fb4bdfbd3277 100644 --- a/packages/upgrade/src/common/src/downgrade_component_adapter.ts +++ b/packages/upgrade/src/common/src/downgrade_component_adapter.ts @@ -139,7 +139,7 @@ export class DowngradeComponentAdapter { const inputBinding = new PropertyBinding(input.propName, input.templateName); let expr: string | null = null; - if (attrs.hasOwnProperty(inputBinding.attr)) { + if (Object.hasOwn(attrs, inputBinding.attr)) { const observeFn = ((prop, isSignal) => { let prevValue = INITIAL_VALUE; return (currValue: any) => { @@ -164,13 +164,13 @@ export class DowngradeComponentAdapter { unwatch = null; observeFn(attrs[inputBinding.attr]); }); - } else if (attrs.hasOwnProperty(inputBinding.bindAttr)) { + } else if (Object.hasOwn(attrs, inputBinding.bindAttr)) { expr = attrs[inputBinding.bindAttr]; - } else if (attrs.hasOwnProperty(inputBinding.bracketAttr)) { + } else if (Object.hasOwn(attrs, inputBinding.bracketAttr)) { expr = attrs[inputBinding.bracketAttr]; - } else if (attrs.hasOwnProperty(inputBinding.bindonAttr)) { + } else if (Object.hasOwn(attrs, inputBinding.bindonAttr)) { expr = attrs[inputBinding.bindonAttr]; - } else if (attrs.hasOwnProperty(inputBinding.bracketParenAttr)) { + } else if (Object.hasOwn(attrs, inputBinding.bracketParenAttr)) { expr = attrs[inputBinding.bracketParenAttr]; } if (expr != null) { @@ -238,16 +238,16 @@ export class DowngradeComponentAdapter { outputBindings.bracketParenAttr.length - 8, )})]`; // order below is important - first update bindings then evaluate expressions - if (attrs.hasOwnProperty(bindonAttr)) { + if (Object.hasOwn(attrs, bindonAttr)) { this.subscribeToOutput(componentRef, outputBindings, attrs[bindonAttr], true); } - if (attrs.hasOwnProperty(bracketParenAttr)) { + if (Object.hasOwn(attrs, bracketParenAttr)) { this.subscribeToOutput(componentRef, outputBindings, attrs[bracketParenAttr], true); } - if (attrs.hasOwnProperty(outputBindings.onAttr)) { + if (Object.hasOwn(attrs, outputBindings.onAttr)) { this.subscribeToOutput(componentRef, outputBindings, attrs[outputBindings.onAttr]); } - if (attrs.hasOwnProperty(outputBindings.parenAttr)) { + if (Object.hasOwn(attrs, outputBindings.parenAttr)) { this.subscribeToOutput(componentRef, outputBindings, attrs[outputBindings.parenAttr]); } } diff --git a/packages/upgrade/src/common/test/downgrade_injectable_spec.ts b/packages/upgrade/src/common/test/downgrade_injectable_spec.ts index 0d4adfd442c6..9166f7a9adfb 100644 --- a/packages/upgrade/src/common/test/downgrade_injectable_spec.ts +++ b/packages/upgrade/src/common/test/downgrade_injectable_spec.ts @@ -16,7 +16,7 @@ describe('downgradeInjectable', () => { const setupMockInjectors = (downgradedModule = '') => { const mockNg1Injector = jasmine.createSpyObj(['get', 'has']); mockNg1Injector.get.and.callFake((key: string) => mockDependencies[key]); - mockNg1Injector.has.and.callFake((key: string) => mockDependencies.hasOwnProperty(key)); + mockNg1Injector.has.and.callFake((key: string) => Object.hasOwn(mockDependencies, key)); const mockNg2Injector = jasmine.createSpyObj(['get']); mockNg2Injector.get.and.returnValue('service value'); diff --git a/packages/upgrade/static/PACKAGE.md b/packages/upgrade/static/PACKAGE.md index 9dbd7bccecec..f5454830a6e3 100644 --- a/packages/upgrade/static/PACKAGE.md +++ b/packages/upgrade/static/PACKAGE.md @@ -1,2 +1,4 @@ +IMPORTANT: The `@angular/upgrade` package is in maintenance mode. We will not be accepting any new features or bug fixes other than security fixes. + Supports the upgrade path from AngularJS to Angular, allowing components and services from both systems to be used in the same application. diff --git a/packages/upgrade/static/src/downgrade_module.ts b/packages/upgrade/static/src/downgrade_module.ts index fb2db39d291b..5ff93d0b9300 100644 --- a/packages/upgrade/static/src/downgrade_module.ts +++ b/packages/upgrade/static/src/downgrade_module.ts @@ -125,8 +125,8 @@ let moduleUid = 0; * `StaticProvider`s, when creating the `PlatformRef` (e.g. via `platformBrowser` or * `platformBrowserDynamic`). * - * - When using {@link PlatformRef#bootstrapmodule `bootstrapModule()`} or - * {@link PlatformRef#bootstrapmodulefactory `bootstrapModuleFactory()`} to bootstrap the + * - When using {@link PlatformRef#bootstrapModule `bootstrapModule()`} or + * {@link PlatformRef#bootstrapModuleFactory `bootstrapModuleFactory()`} to bootstrap the * downgraded modules, each one is considered a "root" module. As a consequence, a new instance * will be created for every injectable provided in `"root"` (via * {@link /api/core/Injectable#providedIn providedIn} @@ -241,8 +241,8 @@ export function downgradeModule( * `StaticProvider`s, when creating the `PlatformRef` (e.g. via `platformBrowser` or * `platformBrowserDynamic`). * - * - When using {@link PlatformRef#bootstrapmodule `bootstrapModule()`} or - * {@link PlatformRef#bootstrapmodulefactory `bootstrapModuleFactory()`} to bootstrap the + * - When using {@link PlatformRef#bootstrapModule `bootstrapModule()`} or + * {@link PlatformRef#bootstrapModuleFactory `bootstrapModuleFactory()`} to bootstrap the * downgraded modules, each one is considered a "root" module. As a consequence, a new instance * will be created for every injectable provided in `"root"` (via * {@link /api/core/Injectable#providedIn providedIn} @@ -358,8 +358,8 @@ export function downgradeModule(moduleOrBootstrapFn: NgModuleFactory): str * `StaticProvider`s, when creating the `PlatformRef` (e.g. via `platformBrowser` or * `platformBrowserDynamic`). * - * - When using {@link PlatformRef#bootstrapmodule `bootstrapModule()`} or - * {@link PlatformRef#bootstrapmodulefactory `bootstrapModuleFactory()`} to bootstrap the + * - When using {@link PlatformRef#bootstrapModule `bootstrapModule()`} or + * {@link PlatformRef#bootstrapModuleFactory `bootstrapModuleFactory()`} to bootstrap the * downgraded modules, each one is considered a "root" module. As a consequence, a new instance * will be created for every injectable provided in `"root"` (via * {@link /api/core/Injectable#providedIn providedIn} @@ -372,9 +372,7 @@ export function downgradeModule(moduleOrBootstrapFn: NgModuleFactory): str */ export function downgradeModule( moduleOrBootstrapFn: - | Type - | NgModuleFactory - | ((extraProviders: StaticProvider[]) => Promise>), + Type | NgModuleFactory | ((extraProviders: StaticProvider[]) => Promise>), ): string { const lazyModuleName = `${ɵconstants.UPGRADE_MODULE_NAME}.lazy${++moduleUid}`; const lazyModuleRefKey = `${ɵconstants.LAZY_MODULE_REF}${lazyModuleName}`; diff --git a/packages/upgrade/static/src/upgrade_module.ts b/packages/upgrade/static/src/upgrade_module.ts index 354a7e7bc14d..084e97aad03b 100644 --- a/packages/upgrade/static/src/upgrade_module.ts +++ b/packages/upgrade/static/src/upgrade_module.ts @@ -42,7 +42,7 @@ import {NgAdapterInjector} from './util'; * that it can be used in an AngularJS template. See `downgradeComponent`. * 3. Creation of an Angular root injector provider that wraps and exposes an AngularJS * service so that it can be injected into an Angular context. See - * {@link UpgradeModule#upgrading-an-angular-1-service Upgrading an AngularJS service} below. + * {@link UpgradeModule#upgrading-an-angularjs-service Upgrading an AngularJS service} below. * 4. Creation of an AngularJS service that wraps and exposes an Angular injectable * so that it can be injected into an AngularJS context. See `downgradeInjectable`. * 5. Bootstrapping of a hybrid Angular application which contains both of the frameworks @@ -151,7 +151,7 @@ export class UpgradeModule { /** * The AngularJS `$injector` for the upgrade application. */ - public $injector: any /*angular.IInjectorService*/; + public $injector: any; /*angular.IInjectorService*/ /** The Angular Injector **/ public injector: Injector; private readonly applicationRef: ApplicationRef; @@ -266,7 +266,7 @@ export class UpgradeModule { ); // the `flush` method will be present when ngMocks is used - if (intervalDelegate.hasOwnProperty('flush')) { + if (Object.hasOwn(intervalDelegate, 'flush')) { (wrappedInterval as any)['flush'] = () => { (intervalDelegate as any)['flush'](); return wrappedInterval; diff --git a/packages/upgrade/static/testing/PACKAGE.md b/packages/upgrade/static/testing/PACKAGE.md index f34d15a58207..9264cbefeedc 100644 --- a/packages/upgrade/static/testing/PACKAGE.md +++ b/packages/upgrade/static/testing/PACKAGE.md @@ -1 +1,3 @@ +IMPORTANT: The `@angular/upgrade` package is in maintenance mode. We will not be accepting any new features or bug fixes other than security fixes. + Supplies testing functions for the AngularJS-to-Angular upgrade path. diff --git a/packages/zone.js/CHANGELOG.md b/packages/zone.js/CHANGELOG.md index c14980b88ba4..5610e067a430 100644 --- a/packages/zone.js/CHANGELOG.md +++ b/packages/zone.js/CHANGELOG.md @@ -1,3 +1,15 @@ +## 0.16.3 (2026-09-02) + +* docs(zone.js): point the Bluebird link at the project repo ([731c838](https://github.com/angular/angular/commit/731c838)) +* fix(zone.js): preserve accessor and non-enumerable event listener options ([4c4a705](https://github.com/angular/angular/commit/4c4a705)), closes [#54142](https://github.com/angular/angular/issues/54142) [#54142](https://github.com/angular/angular/issues/54142) [#70431](https://github.com/angular/angular/issues/70431) +* ci: add Alan as a zone.js reviewer ([5553699](https://github.com/angular/angular/commit/5553699)) +* fix(zone.js): guard against null handle when detecting refreshable timers ([36c2197](https://github.com/angular/angular/commit/36c2197)), closes [#70044](https://github.com/angular/angular/issues/70044) +* fix(zone.js): vitest patching of describe/it curried calls ([e23541b](https://github.com/angular/angular/commit/e23541b)), closes [#69748](https://github.com/angular/angular/issues/69748) +* fix(zone.js): harden zoneSymbolEventNames and patches against __proto__ key ([2d33fd5](https://github.com/angular/angular/commit/2d33fd5)) +* fix(zone.js): harden zoneSymbolEventNames against __proto__ key (defense-in-depth) ([fd7c2da](https://github.com/angular/angular/commit/fd7c2da)) +* fix(zone.js): avoid type error on custom object rejection with rejection property ([fa75800](https://github.com/angular/angular/commit/fa75800)) +* fix(zone.js): validate __Zone_symbol_prefix to prevent DOM clobbering attacks ([e50f504](https://github.com/angular/angular/commit/e50f504)) + ## 0.16.2 (2026-05-06) * feat(zone.js): support vitest patching in zone.js/testing (#68395) ([62c6e3b](https://github.com/angular/angular/commit/62c6e3b)), closes [#68395](https://github.com/angular/angular/issues/68395) [#68395](https://github.com/angular/angular/issues/68395) diff --git a/packages/zone.js/DEVELOPER.md b/packages/zone.js/DEVELOPER.md index 8917a0cfc3ed..b1027b8dcc86 100644 --- a/packages/zone.js/DEVELOPER.md +++ b/packages/zone.js/DEVELOPER.md @@ -34,8 +34,7 @@ Run all checks (lint/format/browser test/test-node): Please make sure you pass all following checks before commit -- pnpm gulp lint (tslint) -- pnpm gulp format (prettier) +- pnpm lint (tslint and format) - pnpm promisetest (promise a+ test) - pnpm bazel test //packages/zone.js/... (all tests) @@ -53,14 +52,7 @@ pnpm webdriver-test ## Releasing -Releasing `zone.js` is a two step process. - -1. Create a PR which updates the changelog, and get it merged using normal merge process. -2. Once the PR is merged check out the merge SHA of the PR and release `zone.js` from that SHA and tag it. - -### Automated Release - -You can use the automated release script which handles both steps (run from the root of the repo): +Releasing `zone.js` is handled via the release script (run from the root of the repo): ```bash pnpm zonejs:release @@ -68,55 +60,7 @@ pnpm zonejs:release Follow the interactive prompts to either create a PR or cut a release. ---- +Releasing is a two step process: -### Manual Release (Legacy) - -#### 1. Creating a PR for release - -``` -rm -rf node_modules && pnpm install -export PREVIOUS_ZONE_TAG=`git tag -l 'zone.js-0.15.*' | tail -n1` -export VERSION=`(cd packages/zone.js; npm version patch --no-git-tag-version)` -export VERSION=${VERSION#v} -export TAG="zone.js-${VERSION}" -echo "Releasing zone.js version ${TAG}. Last release was ${PREVIOUS_ZONE_TAG}." -pnpm gulp changelog:zonejs -``` - -Inspect the `packages/zone.js/CHANGELOG.md` for any issues and than commit it with this command. - -Create a dry run build to make sure everything is ready. - -``` -pnpm bazel build //packages/zone.js:npm_package --workspace_status_command="echo STABLE_PROJECT_VERSION $VERSION" -``` - -If everything looks good, commit the changes and push them to your origin to create a PR. - -``` -git checkout -b "release_${TAG}" -git add packages/zone.js/CHANGELOG.md packages/zone.js/package.json -git commit -m "release: cut the ${TAG} release" -git push origin "release_${TAG}" -``` - -#### 2. Cutting a release - -Check out the SHA on main which has the changelog commit of the zone.js - -``` -git fetch upstream -git checkout upstream/main -rm -rf node_modules && pnpm install -export VERSION=`(node -e "console.log(require('./packages/zone.js/package.json').version)")` -export TAG="zone.js-${VERSION}" -export SHA=`git log upstream/main --oneline -n 1000 | grep "release: cut the ${TAG} release" | cut -f 1 -d " "` -echo "Releasing '$VERSION' which will be tagged as '$TAG' from SHA '$SHA'." -git checkout ${SHA} -npm login --registry https://wombat-dressing-room.appspot.com -pnpm bazel build //packages/zone.js:npm_package --config=release --workspace_status_command="echo STABLE_PROJECT_VERSION $VERSION" -npm publish dist/bin/packages/zone.js/npm_package --access public --tag latest -git tag ${TAG} ${SHA} -git push upstream ${TAG} -``` +1. **Create a PR for release**: updates the version in `packages/zone.js/package.json`, generates the `packages/zone.js/CHANGELOG.md` with all changes since the last zone.js release, runs a dry-run build, creates and pushes the release branch, and provides a PR link. +2. **Cut a release (publish)**: once the PR is merged, check out the merged release commit, build the package with release config, publish to npm, and tag and push the `zone.js-` release tag. diff --git a/packages/zone.js/NON-STANDARD-APIS.md b/packages/zone.js/NON-STANDARD-APIS.md index e74aae602477..6a0411f2abf8 100644 --- a/packages/zone.js/NON-STANDARD-APIS.md +++ b/packages/zone.js/NON-STANDARD-APIS.md @@ -27,7 +27,7 @@ Usage: ## Currently Supported Non-Standard Common APIs -- [Bluebird](http://bluebirdjs.com/docs/getting-started.html) Promise +- [Bluebird](https://github.com/petkaantonov/bluebird) Promise Browser Usage: diff --git a/packages/zone.js/lib/browser/browser-util.ts b/packages/zone.js/lib/browser/browser-util.ts index 9fbce4b35925..97fb671e8f21 100644 --- a/packages/zone.js/lib/browser/browser-util.ts +++ b/packages/zone.js/lib/browser/browser-util.ts @@ -31,7 +31,7 @@ export function patchCallbacks( // We don't want to stop the application rendering if we couldn't patch some // callback, e.g. `attributeChangedCallback`. try { - if (prototype.hasOwnProperty(callback)) { + if (Object.hasOwn(prototype, callback)) { const descriptor = api.ObjectGetOwnPropertyDescriptor(prototype, callback); if (descriptor && descriptor.value) { descriptor.value = api.wrapWithCurrentZone(descriptor.value, source); diff --git a/packages/zone.js/lib/browser/shadydom.ts b/packages/zone.js/lib/browser/shadydom.ts index 3ffdfffde827..9aa9bccefd71 100644 --- a/packages/zone.js/lib/browser/shadydom.ts +++ b/packages/zone.js/lib/browser/shadydom.ts @@ -26,7 +26,7 @@ export function patchShadyDom(Zone: ZoneType): void { Document.prototype, ]; prototypes.forEach(function (proto) { - if (proto && proto.hasOwnProperty('addEventListener')) { + if (proto && Object.hasOwn(proto, 'addEventListener')) { proto[Zone.__symbol__('addEventListener')] = null; proto[Zone.__symbol__('removeEventListener')] = null; api.patchEventTarget(global, api, [proto]); diff --git a/packages/zone.js/lib/common/error-rewrite.ts b/packages/zone.js/lib/common/error-rewrite.ts index 47441e143c63..4f96592d535f 100644 --- a/packages/zone.js/lib/common/error-rewrite.ts +++ b/packages/zone.js/lib/common/error-rewrite.ts @@ -211,7 +211,7 @@ export function patchError(Zone: ZoneType): void { }); } - if (NativeError.hasOwnProperty('stackTraceLimit')) { + if (Object.hasOwn(NativeError, 'stackTraceLimit')) { // Extend default stack limit as we will be removing few frames. NativeError.stackTraceLimit = Math.max(NativeError.stackTraceLimit, 15); @@ -226,7 +226,7 @@ export function patchError(Zone: ZoneType): void { }); } - if (NativeError.hasOwnProperty('captureStackTrace')) { + if (Object.hasOwn(NativeError, 'captureStackTrace')) { Object.defineProperty(ZoneAwareError, 'captureStackTrace', { // add named function here because we need to remove this // stack frame when prepareStackTrace below diff --git a/packages/zone.js/lib/common/events.ts b/packages/zone.js/lib/common/events.ts index 73a67cfd2c8c..2b752f0731d6 100644 --- a/packages/zone.js/lib/common/events.ts +++ b/packages/zone.js/lib/common/events.ts @@ -92,6 +92,11 @@ export const globalSources: any = {}; const EVENT_NAME_SYMBOL_REGX = new RegExp('^' + ZONE_SYMBOL_PREFIX + '(\\w+)(true|false)$'); const IMMEDIATE_PROPAGATION_SYMBOL = zoneSymbol('propagationStopped'); +// Recognised members of the `AddEventListenerOptions` WebIDL dictionary, used +// by `copyEventListenerOptions` to recover accessors and non-enumerable +// properties that a caller-supplied options object may expose. +const KNOWN_EVENT_LISTENER_OPTIONS = ['capture', 'once', 'passive', 'signal']; + function prepareEventNames(eventName: string, eventNameToString?: (eventName: string) => string) { const falseEventName = (eventNameToString ? eventNameToString(eventName) : eventName) + FALSE_STR; const trueEventName = (eventNameToString ? eventNameToString(eventName) : eventName) + TRUE_STR; @@ -324,7 +329,7 @@ export function patchEventTarget( } let proto = obj; - while (proto && !proto.hasOwnProperty(ADD_EVENT_LISTENER)) { + while (proto && !Object.hasOwn(proto, ADD_EVENT_LISTENER)) { proto = ObjectGetPrototypeOf(proto); } if (!proto && obj[ADD_EVENT_LISTENER]) { @@ -381,7 +386,8 @@ export function patchEventTarget( return {passive: true}; } if (typeof options === 'object' && options.passive !== false) { - return {...options, passive: true}; + options.passive = true; + return options; } return options; } @@ -492,27 +498,22 @@ export function patchEventTarget( const passiveEvents: string[] = _global[zoneSymbol('PASSIVE_EVENTS')]; function copyEventListenerOptions(options: any) { - if (typeof options === 'object' && options !== null) { - // We need to destructure the target `options` object since it may - // be frozen or sealed (possibly provided implicitly by a third-party - // library), or its properties may be readonly. - const newOptions: any = {...options}; - // The `signal` option was recently introduced, which caused regressions in - // third-party scenarios where `AbortController` was directly provided to - // `addEventListener` as options. For instance, in cases like - // `document.addEventListener('keydown', callback, abortControllerInstance)`, - // which is valid because `AbortController` includes a `signal` getter, spreading - // `{...options}` wouldn't copy the `signal`. Additionally, using `Object.create` - // isn't feasible since `AbortController` is a built-in object type, and attempting - // to create a new object directly with it as the prototype might result in - // unexpected behavior. - if (options.signal) { - newOptions.signal = options.signal; + if (typeof options !== 'object' || options === null) { + return options; + } + // Spread copies own enumerable properties, invoking any getters exactly once. + const newOptions: any = {...options}; + // Anything the spread could not see (inherited accessors such as + // `AbortController.prototype.signal`, or non-enumerable properties defined + // via `Object.defineProperty`) is read directly from the source, exactly once. Reading + // from `options` rather than `newOptions` also gives prototype getters the + // correct receiver. + for (const key of KNOWN_EVENT_LISTENER_OPTIONS) { + if (!Object.hasOwn(newOptions, key) && key in options) { + newOptions[key] = options[key]; } - return newOptions; } - - return options; + return newOptions; } const makeAddListener = function ( @@ -556,7 +557,7 @@ export function patchEventTarget( } const passive = !!passiveEvents && passiveEvents.indexOf(eventName) !== -1; - const options = copyEventListenerOptions(buildEventListenerOptions(arguments[2], passive)); + const options = buildEventListenerOptions(copyEventListenerOptions(arguments[2]), passive); const signal: AbortSignal | undefined = options?.signal; if (signal?.aborted) { // the signal is an aborted one, just return without attaching the event listener. diff --git a/packages/zone.js/lib/common/promise.ts b/packages/zone.js/lib/common/promise.ts index dda37fd94218..26df70719ae5 100644 --- a/packages/zone.js/lib/common/promise.ts +++ b/packages/zone.js/lib/common/promise.ts @@ -160,8 +160,8 @@ export function patchPromise(Zone: ZoneType): void { if ( state !== REJECTED && value instanceof ZoneAwarePromise && - value.hasOwnProperty(symbolState) && - value.hasOwnProperty(symbolValue) && + Object.hasOwn(value, symbolState) && + Object.hasOwn(value, symbolValue) && (value as any)[symbolState] !== UNRESOLVED ) { clearRejectedNoCatch(value); @@ -212,7 +212,7 @@ export function patchPromise(Zone: ZoneType): void { } } - for (let i = 0; i < queue.length; ) { + for (let i = 0; i < queue.length;) { scheduleResolveOrReject(promise, queue[i++], queue[i++], queue[i++], queue[i++]); } if (queue.length == 0 && state == REJECTED) { diff --git a/packages/zone.js/lib/common/timers.ts b/packages/zone.js/lib/common/timers.ts index c6e8279611de..1cb265154705 100644 --- a/packages/zone.js/lib/common/timers.ts +++ b/packages/zone.js/lib/common/timers.ts @@ -49,7 +49,7 @@ export function patchTimer(window: any, setName: string, cancelName: string, nam } else { data.handle = handleOrId; // On Node.js a timeout and interval can be restarted over and over again by using the `.refresh` method. - data.isRefreshable = isFunction(handleOrId.refresh); + data.isRefreshable = isFunction(handleOrId?.refresh); } return task; diff --git a/packages/zone.js/lib/common/utils.ts b/packages/zone.js/lib/common/utils.ts index 03c9880c453f..4cee9846bb2e 100644 --- a/packages/zone.js/lib/common/utils.ts +++ b/packages/zone.js/lib/common/utils.ts @@ -210,7 +210,7 @@ export function patchProperty(obj: any, prop: string, prototype?: any) { } const onPropPatchedSymbol = zoneSymbol('on' + prop + 'patched'); - if (obj.hasOwnProperty(onPropPatchedSymbol) && obj[onPropPatchedSymbol]) { + if (Object.hasOwn(obj, onPropPatchedSymbol) && obj[onPropPatchedSymbol]) { return; } @@ -385,7 +385,7 @@ export function patchClass(className: string) { } for (prop in OriginalClass) { - if (prop !== 'prototype' && OriginalClass.hasOwnProperty(prop)) { + if (prop !== 'prototype' && Object.hasOwn(OriginalClass, prop)) { _global[className][prop] = OriginalClass[prop]; } } @@ -431,7 +431,7 @@ export function patchMethod( ) => (self: any, args: any[]) => any, ): Function | null { let proto = target; - while (proto && !proto.hasOwnProperty(name)) { + while (proto && !Object.hasOwn(proto, name)) { proto = ObjectGetPrototypeOf(proto); } if (!proto && target[name]) { @@ -441,7 +441,7 @@ export function patchMethod( const delegateName = zoneSymbol(name); let delegate: Function | null = null; - if (proto && (!(delegate = proto[delegateName]) || !proto.hasOwnProperty(delegateName))) { + if (proto && (!(delegate = proto[delegateName]) || !Object.hasOwn(proto, delegateName))) { delegate = proto[delegateName] = proto[name]; // check whether proto[name] is writable // some property is readonly in safari, such as HtmlCanvasElement.prototype.toBlob diff --git a/packages/zone.js/lib/jasmine/jasmine.ts b/packages/zone.js/lib/jasmine/jasmine.ts index c8335d6331d1..fc875bb2f9b2 100644 --- a/packages/zone.js/lib/jasmine/jasmine.ts +++ b/packages/zone.js/lib/jasmine/jasmine.ts @@ -16,7 +16,7 @@ declare let jest: any; export function patchJasmine(Zone: ZoneType): void { Zone.__load_patch('jasmine', (global: any, Zone: ZoneType, api: _ZonePrivate) => { const __extends = function (d: any, b: any) { - for (const p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + for (const p in b) if (Object.hasOwn(b, p)) d[p] = b[p]; function __(this: Object) { this.constructor = d; } diff --git a/packages/zone.js/lib/zone-impl.ts b/packages/zone.js/lib/zone-impl.ts index ba2fb0367e3b..ec76c9c5ca8d 100644 --- a/packages/zone.js/lib/zone-impl.ts +++ b/packages/zone.js/lib/zone-impl.ts @@ -628,12 +628,7 @@ export type TaskType = 'microTask' | 'macroTask' | 'eventTask'; * Task type: `notScheduled`, `scheduling`, `scheduled`, `running`, `canceling`, 'unknown'. */ export type TaskState = - | 'notScheduled' - | 'scheduling' - | 'scheduled' - | 'running' - | 'canceling' - | 'unknown'; + 'notScheduled' | 'scheduling' | 'scheduled' | 'running' | 'canceling' | 'unknown'; /** */ @@ -862,7 +857,7 @@ export function initZone(): ZoneType { public getZoneWith(key: string): AmbientZone | null { let current: ZoneImpl | null = this; while (current) { - if (current._properties.hasOwnProperty(key)) { + if (Object.hasOwn(current._properties, key)) { return current; } current = current._parent; diff --git a/packages/zone.js/lib/zone-spec/long-stack-trace.ts b/packages/zone.js/lib/zone-spec/long-stack-trace.ts index e5dc453f4f41..1df391a22c4e 100644 --- a/packages/zone.js/lib/zone-spec/long-stack-trace.ts +++ b/packages/zone.js/lib/zone-spec/long-stack-trace.ts @@ -56,7 +56,7 @@ export function patchLongStackTrace(Zone: ZoneType): void { for (let i = 0; i < trace.length; i++) { const frame = trace[i]; // Filter out the Frames which are part of stack capturing. - if (!IGNORE_FRAMES.hasOwnProperty(frame)) { + if (!Object.hasOwn(IGNORE_FRAMES, frame)) { lines.push(trace[i]); } } diff --git a/packages/zone.js/lib/zone-spec/wtf.ts b/packages/zone.js/lib/zone-spec/wtf.ts index 0f68517f40ab..7226d5dc8b9f 100644 --- a/packages/zone.js/lib/zone-spec/wtf.ts +++ b/packages/zone.js/lib/zone-spec/wtf.ts @@ -165,7 +165,7 @@ export function patchWtf(Zone: ZoneType): void { if (!obj || !depth) return null; const out: {[k: string]: any} = {}; for (const key in obj) { - if (obj.hasOwnProperty(key)) { + if (Object.hasOwn(obj, key)) { // explicit : any due to https://github.com/microsoft/TypeScript/issues/33191 let value: any = obj[key]; switch (typeof value) { diff --git a/packages/zone.js/package.json b/packages/zone.js/package.json index f4f6ec933b2c..0d14e02be9c2 100644 --- a/packages/zone.js/package.json +++ b/packages/zone.js/package.json @@ -1,6 +1,6 @@ { "name": "zone.js", - "version": "0.16.2", + "version": "0.16.3", "description": "Zones for JavaScript", "main": "./bundles/zone.umd.js", "module": "./fesm2015/zone.js", @@ -8,19 +8,19 @@ "fesm2015": "./fesm2015/zone.js", "typings": "./zone.d.ts", "devDependencies": { - "@csstools/css-calc": "3.2.1", - "@csstools/css-color-parser": "4.1.9", + "@csstools/css-calc": "3.3.0", + "@csstools/css-color-parser": "4.2.1", "@externs/nodejs": "1.5.0", "@types/jasmine": "6.0.0", "@types/node": "^24.3.0", "@types/systemjs": "6.15.4", "bluebird": "3.7.2", - "domino": "https://github.com/angular/domino.git#f88e5aa49cf2804d7c2df22ef1640eb4ec43dd56", + "domino": "https://github.com/angular/domino.git#4d97473116d000e3fd4d6f75ec98cbd67576fa6f", "esbuild-plugin-umd-wrapper": "3.0.0", "jest-environment-jsdom": "30.4.1", "jest-environment-node": "30.4.1", "jest": "30.4.2", - "mocha": "11.7.6", + "mocha": "12.0.0", "mock-require": "3.0.3", "jasmine": "6.3.0", "source-map-support": "0.5.21", @@ -29,7 +29,7 @@ "rxjs": "7.8.2", "systemjs": "6.15.1", "tslib": "^2.3.0", - "vitest": "^4.0.0" + "vitest": "^5.0.0" }, "scripts": { "electrontest": "cd test/extra && node electron.js", diff --git a/packages/zone.js/test/browser/browser.spec.ts b/packages/zone.js/test/browser/browser.spec.ts index d5e0eca9247c..c9bdd412d16d 100644 --- a/packages/zone.js/test/browser/browser.spec.ts +++ b/packages/zone.js/test/browser/browser.spec.ts @@ -434,7 +434,7 @@ describe('Zone Browser', function () { } const onPropPatchedSymbol = zoneSymbol('on' + prop + 'patched'); - if (obj.hasOwnProperty(onPropPatchedSymbol) && obj[onPropPatchedSymbol]) { + if (Object.hasOwn(obj, onPropPatchedSymbol) && obj[onPropPatchedSymbol]) { return true; } return false; @@ -2184,6 +2184,73 @@ describe('Zone Browser', function () { expect(logs).toEqual(['click2']); }); + // Options exposed as accessors or non-enumerable properties must still + // reach the native call. https://github.com/angular/angular/issues/54142 + describe('event listener options built with accessors', function () { + it('should invoke a non-enumerable `passive` getter (MDN feature-detect pattern)', function () { + let getCount = 0; + const opts = Object.defineProperty({}, 'passive', { + get: () => { + getCount++; + return false; + }, + }); + const listener = () => {}; + button.addEventListener('click', listener, opts as any); + expect(getCount).toBe(1); + button.removeEventListener('click', listener, opts as any); + }); + + it('should honour `capture: true` supplied as an accessor', function () { + const opts = Object.defineProperty({}, 'capture', {get: () => true}); + const inner = document.createElement('span'); + button.appendChild(inner); + let phase = -1; + const listener = (e: Event) => { + phase = e.eventPhase; + }; + button.addEventListener('click', listener, opts as any); + inner.dispatchEvent(clickEvent); + expect(phase).toBe(Event.CAPTURING_PHASE); + + button.removeEventListener('click', listener, opts as any); + phase = -1; + inner.dispatchEvent(clickEvent); + expect(phase).toBe(-1); + button.removeChild(inner); + }); + + it('should honour `once: true` supplied as an accessor', function () { + const opts = Object.defineProperty({}, 'once', {get: () => true}); + let callCount = 0; + button.addEventListener('click', () => callCount++, opts as any); + button.dispatchEvent(clickEvent); + button.dispatchEvent(clickEvent); + expect(callCount).toBe(1); + }); + + // `AbortController.prototype.signal` is a prototype accessor, so an + // own-properties-only copy would drop it. + it('should honour `signal` on an AbortController passed as options', function () { + const ac = new AbortController(); + const logs: string[] = []; + button.addEventListener('click', () => logs.push('click'), ac); + button.dispatchEvent(clickEvent); + ac.abort(); + button.dispatchEvent(clickEvent); + expect(logs).toEqual(['click']); + expect(button.eventListeners!('click').length).toBe(0); + }); + + // https://github.com/angular/angular/pull/55796 + it('should accept a frozen options object', function () { + const opts = Object.freeze({capture: true, once: true}); + const listener = () => {}; + expect(() => button.addEventListener('click', listener, opts as any)).not.toThrow(); + button.removeEventListener('click', listener, opts as any); + }); + }); + // https://github.com/angular/angular/issues/56148 it('should store the remove abort listener on the task itself and not the task data', function () { const logs: string[] = []; diff --git a/packages/zone.js/test/closure/zone.closure.ts b/packages/zone.js/test/closure/zone.closure.ts index 3d92c889d09b..bbf2b5ff1fc8 100644 --- a/packages/zone.js/test/closure/zone.closure.ts +++ b/packages/zone.js/test/closure/zone.closure.ts @@ -120,7 +120,7 @@ const testClosureFunction = () => { 'cancelTask', ]; zonePrototypeKeys.forEach((key) => { - if ((Zone as any).prototype.hasOwnProperty(key)) { + if (Object.hasOwn((Zone as any).prototype, key)) { logs.push(key); } }); @@ -138,7 +138,7 @@ const testClosureFunction = () => { 'onHasTask', ]; zoneSpecKeys.forEach((key) => { - if (testZoneSpec.hasOwnProperty(key)) { + if (Object.hasOwn(testZoneSpec, key)) { logs.push(key); } }); @@ -162,7 +162,7 @@ const testClosureFunction = () => { () => {}, ); zoneTaskKeys.forEach((key) => { - if (task.hasOwnProperty(key)) { + if (Object.hasOwn(task, key)) { logs.push(key); } }); diff --git a/packages/zone.js/test/common/Error.spec.ts b/packages/zone.js/test/common/Error.spec.ts index 407806ce5f1c..9184a5bd1c68 100644 --- a/packages/zone.js/test/common/Error.spec.ts +++ b/packages/zone.js/test/common/Error.spec.ts @@ -137,11 +137,11 @@ describe('ZoneAwareError', () => { it('should have browser specified property', () => { let myError = new Error('myError'); - if (Object.prototype.hasOwnProperty.call(Error.prototype, 'description')) { + if (Object.hasOwn(Error.prototype, 'description')) { // in IE, error has description property expect((myError).description).toEqual('myError'); } - if (Object.prototype.hasOwnProperty.call(Error.prototype, 'fileName')) { + if (Object.hasOwn(Error.prototype, 'fileName')) { // in firefox, error has fileName property expect((myError).fileName).toBeTruthy(); } diff --git a/packages/zone.js/test/common/setTimeout.spec.ts b/packages/zone.js/test/common/setTimeout.spec.ts index 393149f72e73..a7d21da77244 100644 --- a/packages/zone.js/test/common/setTimeout.spec.ts +++ b/packages/zone.js/test/common/setTimeout.spec.ts @@ -151,4 +151,17 @@ describe('setTimeout', function () { clearTimeout(null as any); clearTimeout({}); }); + + it('should not throw when the native timer returns null', function () { + // A wrapper that blocks a timer (e.g. a browser extension or automation + // harness) can return null instead of a handle, see issue #70044. + const fakeGlobal = { + setTimeout: function () { + return null; + }, + clearTimeout: function () {}, + }; + patchTimer(fakeGlobal, 'set', 'clear', 'Timeout'); + expect(() => (fakeGlobal as any).setTimeout(() => {}, 0)).not.toThrow(); + }); }); diff --git a/packages/zone.js/test/rxjs/rxjs.fromEvent.spec.ts b/packages/zone.js/test/rxjs/rxjs.fromEvent.spec.ts index 98d05889b79e..9b560a9ec1da 100644 --- a/packages/zone.js/test/rxjs/rxjs.fromEvent.spec.ts +++ b/packages/zone.js/test/rxjs/rxjs.fromEvent.spec.ts @@ -86,7 +86,7 @@ describe('Observable.fromEvent', () => { const clickEvent = document.createEvent('Event'); clickEvent.initEvent('click', false, false); - const subscriper: any = subscriptionZone.run(() => { + const subscriber: any = subscriptionZone.run(() => { return observable1.subscribe( (result: any) => { expect(Zone.current.name).toEqual(subscriptionZone.name); @@ -104,7 +104,7 @@ describe('Observable.fromEvent', () => { triggerZone.run(() => { button.dispatchEvent(clickEvent); - subscriper.complete(); + subscriber.complete(); }); expect(log).toEqual(['addListener', clickEvent, 'completed', 'removeListener']); }), diff --git a/packages/zone.js/test/test-env-setup-mocha.ts b/packages/zone.js/test/test-env-setup-mocha.ts index 7c7e1db22f97..79c14e734d0a 100644 --- a/packages/zone.js/test/test-env-setup-mocha.ts +++ b/packages/zone.js/test/test-env-setup-mocha.ts @@ -33,7 +33,7 @@ declare const global: any; let isEqual = true; for (let prop in a) { - if (a.hasOwnProperty(prop)) { + if (Object.hasOwn(a, prop)) { if (!eq(a[prop], b[prop])) { isEqual = false; break; @@ -50,7 +50,7 @@ declare const global: any; let isEqual = true; for (let prop in a) { - if (a.hasOwnProperty(prop)) { + if (Object.hasOwn(a, prop)) { if (!eq(a[prop], b[prop])) { isEqual = false; break; diff --git a/packages/zone.js/test/typings/package.json b/packages/zone.js/test/typings/package.json index f48db4ae05f4..eafa950be032 100644 --- a/packages/zone.js/test/typings/package.json +++ b/packages/zone.js/test/typings/package.json @@ -9,7 +9,7 @@ "author": "", "license": "MIT", "dependencies": { - "domino": "https://github.com/angular/domino.git#f88e5aa49cf2804d7c2df22ef1640eb4ec43dd56", + "domino": "https://github.com/angular/domino.git#4d97473116d000e3fd4d6f75ec98cbd67576fa6f", "zone.js": "workspace:*" }, "devDependencies": { diff --git a/packages/zone.js/test/typings/tsconfig.json b/packages/zone.js/test/typings/tsconfig.json index fabaf133d4d1..fde7e532bc85 100644 --- a/packages/zone.js/test/typings/tsconfig.json +++ b/packages/zone.js/test/typings/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "stableTypeOrdering": true, "forceConsistentCasingInFileNames": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, @@ -12,7 +13,6 @@ "moduleResolution": "Node16", "noEmitOnError": false, "stripInternal": false, - "strict": true, "lib": ["es5", "dom", "es2015.collection", "es2015.iterable", "es2015.promise", "es2022.object"] }, "files": ["./type.test.ts", "./node_modules/zone.js/zone.ts"] diff --git a/packages/zone.js/tools/release.mts b/packages/zone.js/tools/release.mts index 9644161dc00e..0dde08a7e5a0 100644 --- a/packages/zone.js/tools/release.mts +++ b/packages/zone.js/tools/release.mts @@ -85,7 +85,6 @@ async function createPrWorkflow(): Promise { await updatingPackageJsonVersion(newVersion); // Generate changelog - // pnpm gulp changelog:zonejs console.log(chalk.blue('Generating changelog...')); await execAndStream('pnpm', ['gulp', 'changelog:zonejs'], { env: { @@ -124,11 +123,14 @@ async function createPrWorkflow(): Promise { console.log(chalk.blue(`Pushing to ${forkRemote}...`)); await exec(`git push ${forkRemote} "${releaseBranch}"`); - console.log( - chalk.yellow( - `Please create a pull request by visiting: https://github.com/angular/angular/pull/new/${releaseBranch}`, - ), - ); + const {stdout: remoteUrl} = await exec(`git remote get-url ${forkRemote}`); + const {owner, repo} = getRepoDetails(remoteUrl); + const prUrl = + owner === 'angular' + ? `https://github.com/angular/angular/compare/main...${releaseBranch}` + : `https://github.com/angular/angular/compare/main...${owner}:${repo}:${releaseBranch}`; + + console.log(chalk.yellow(`Please create a pull request by visiting: ${prUrl}`)); const continueToPublish = await select({ message: 'Do you want to continue to the publish step once the PR is merged?', @@ -177,7 +179,7 @@ async function cutReleaseWorkflow(): Promise { console.log(chalk.blue(`Looking for release commit for ${tagName}...`)); const commitMessagePattern = `release: cut the ${tagName} release`; const {stdout: sha} = await exec( - `git log FETCH_HEAD --oneline -n 1000 | grep "${commitMessagePattern}" | cut -f 1 -d " "`, + `git log FETCH_HEAD --grep="^${commitMessagePattern}" --format=format:%H -n 1`, ); const trimmedSha = sha.trim(); @@ -230,7 +232,7 @@ async function cutReleaseWorkflow(): Promise { async function cleanAndInstall() { console.log(chalk.blue('Cleaning and installing dependencies...')); await exec('git clean -dxf'); - await execAndStream('pnpm', ['install', , '--frozen-lockfile']); + await execAndStream('pnpm', ['install', '--frozen-lockfile']); } async function checkCleanWorkingDirectory(): Promise { @@ -374,7 +376,7 @@ async function getForkRemoteName(): Promise { } function getRepoDetails(remoteUrl: string): {owner: string; repo: string} { - const match = remoteUrl.trim().match(/github\.com[/:]([\w-]+)\/([\w-]+)/); + const match = remoteUrl.trim().match(/github\.com[/:]([\w-]+)\/([\w-]+?)(?:\.git)?$/); return { owner: match ? match[1] : 'angular', repo: match ? match[2] : 'angular', diff --git a/packages/zone.js/tsconfig.json b/packages/zone.js/tsconfig.json index c4f34e08f941..ab88ce566a2b 100644 --- a/packages/zone.js/tsconfig.json +++ b/packages/zone.js/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "stableTypeOrdering": true, "module": "esnext", "target": "es2022", "moduleResolution": "node", @@ -9,7 +10,6 @@ "declaration": true, "noEmitOnError": false, "stripInternal": true, - "strict": true, "sourceMap": true, "noImplicitOverride": true, "lib": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6ad3a05f11a5..86066ccfa94a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,36 +6,36 @@ settings: packageExtensionsChecksum: sha256-3L73Fw32UVtE6x5BJxJPBtQtH/mgsr31grNpdhHP1IY= -pnpmfileChecksum: sha256-TYPFsbGgXlr65uhno3A1oHE+n2qqt8R+w/szQ+Wq97s= +pnpmfileChecksum: sha256-QunhHrx56db5oYtx13Qk+ZRpgE0xSUv0SrI3XoRbbdo= importers: .: dependencies: '@angular-devkit/core': - specifier: 22.1.0-next.4 - version: 22.1.0-next.4(chokidar@5.0.0) + specifier: 22.2.0-next.7 + version: 22.2.0-next.7(chokidar@5.0.0) '@angular-devkit/schematics': - specifier: 22.1.0-next.4 - version: 22.1.0-next.4(chokidar@5.0.0) + specifier: 22.2.0-next.7 + version: 22.2.0-next.7(chokidar@5.0.0) '@angular/animations': specifier: workspace:* version: link:packages/animations '@angular/aria': - specifier: 22.1.0-next.4 - version: 22.1.0-next.4(@angular/cdk@22.1.0-next.4(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2))(@angular/core@packages+core) + specifier: 22.2.0-next.5 + version: 22.2.0-next.5(@angular/cdk@22.2.0-next.5(@angular/common@packages+common)(@angular/core@packages+core)(@angular/forms@packages+forms)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2))(@angular/core@packages+core) '@angular/benchpress': - specifier: 'workspace: *' + specifier: workspace:* version: link:packages/benchpress '@angular/build': - specifier: 22.1.0-next.4 - version: 22.1.0-next.4(048f5165d9cdcac2cb54b2d790f738e3) + specifier: 22.2.0-next.7 + version: 22.2.0-next.7(e7ab0a794307bcb845f8633d1b339c6e) '@angular/cdk': - specifier: 22.1.0-next.4 - version: 22.1.0-next.4(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2) + specifier: 22.2.0-next.5 + version: 22.2.0-next.5(@angular/common@packages+common)(@angular/core@packages+core)(@angular/forms@packages+forms)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2) '@angular/cli': - specifier: 22.1.0-next.4 - version: 22.1.0-next.4(@cfworker/json-schema@4.1.1)(@types/node@20.19.43)(chokidar@5.0.0)(supports-color@10.2.2) + specifier: 22.2.0-next.7 + version: 22.2.0-next.7(@types/node@20.19.43)(chokidar@5.0.0) '@angular/common': specifier: workspace:* version: link:packages/common @@ -55,14 +55,14 @@ importers: specifier: workspace:* version: link:packages/forms '@angular/language-service': - specifier: 'workspace: *' + specifier: workspace:* version: link:packages/language-service '@angular/localize': - specifier: 'workspace: *' + specifier: workspace:* version: link:packages/localize '@angular/material': - specifier: 22.1.0-next.4 - version: 22.1.0-next.4(@angular/cdk@22.1.0-next.4(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2))(@angular/common@packages+common)(@angular/core@packages+core)(@angular/forms@packages+forms)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2) + specifier: 22.2.0-next.5 + version: 22.2.0-next.5(@angular/cdk@22.2.0-next.5(@angular/common@packages+common)(@angular/core@packages+core)(@angular/forms@packages+forms)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2))(@angular/common@packages+common)(@angular/core@packages+core)(@angular/forms@packages+forms)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2) '@angular/platform-browser': specifier: workspace:* version: link:packages/platform-browser @@ -79,10 +79,10 @@ importers: specifier: workspace:* version: link:packages/service-worker '@angular/ssr': - specifier: 22.1.0-next.4 - version: 22.1.0-next.4(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-server@packages+platform-server)(@angular/router@packages+router) + specifier: 22.2.0-next.7 + version: 22.2.0-next.7(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-server@packages+platform-server)(@angular/router@packages+router) '@angular/upgrade': - specifier: 'workspace: *' + specifier: workspace:* version: link:packages/upgrade '@babel/cli': specifier: 8.0.4 @@ -95,19 +95,19 @@ importers: version: 8.0.0 '@rollup/plugin-commonjs': specifier: ^29.0.0 - version: 29.0.3(rollup@4.62.2) + version: 29.0.3(rollup@4.63.0) '@rollup/plugin-node-resolve': specifier: ^16.0.0 - version: 16.0.3(rollup@4.62.2) + version: 16.0.3(rollup@4.63.0) '@schematics/angular': - specifier: 22.1.0-next.4 - version: 22.1.0-next.4(chokidar@5.0.0) + specifier: 22.2.0-next.7 + version: 22.2.0-next.7(chokidar@5.0.0) '@types/angular': specifier: ^1.6.47 version: 1.8.9 '@types/chrome': specifier: ^0.2.0 - version: 0.2.2 + version: 0.2.7 '@types/dom-navigation': specifier: ^1.0.5 version: 1.0.7 @@ -125,7 +125,7 @@ importers: version: 3.0.7 '@types/semver': specifier: ^7.3.4 - version: 7.7.1 + version: 7.8.0 '@types/yargs': specifier: ^17.0.3 version: 17.0.35 @@ -154,20 +154,20 @@ importers: specifier: npm:angular-mocks@1.8 version: angular-mocks@1.8.3 chalk: - specifier: ^5.4.1 - version: 5.6.2 + specifier: ^6.0.0 + version: 6.0.0 diff: specifier: ^9.0.0 version: 9.0.0 domino: - specifier: https://github.com/angular/domino.git#f88e5aa49cf2804d7c2df22ef1640eb4ec43dd56 - version: '@angular/domino@https://codeload.github.com/angular/domino/tar.gz/f88e5aa49cf2804d7c2df22ef1640eb4ec43dd56' + specifier: https://github.com/angular/domino.git#4d97473116d000e3fd4d6f75ec98cbd67576fa6f + version: '@angular/domino@https://codeload.github.com/angular/domino/tar.gz/4d97473116d000e3fd4d6f75ec98cbd67576fa6f' esbuild: - specifier: 0.28.1 - version: 0.28.1 + specifier: 0.28.2 + version: 0.28.2 http-server: specifier: ^14.0.0 - version: 14.1.1(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2) + version: 14.1.1(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0) jasmine: specifier: 6.3.0 version: 6.3.0 @@ -179,7 +179,7 @@ importers: version: 2.5.2 karma: specifier: ~6.4.0 - version: 6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6) + version: 6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6) karma-chrome-launcher: specifier: ^3.1.0 version: 3.2.0 @@ -188,25 +188,25 @@ importers: version: 2.1.3 karma-jasmine: specifier: ^5.0.0 - version: 5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6)) + version: 5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)) karma-sourcemap-loader: specifier: ^0.4.0 version: 0.4.0 magic-string: - specifier: ^0.30.8 - version: 0.30.21 + specifier: ^1.0.0 + version: 1.2.3 protractor: specifier: ^7.0.0 - version: 7.0.0(supports-color@10.2.2) + version: 7.0.0(supports-color@11.0.0) reflect-metadata: specifier: ^0.2.0 version: 0.2.2 rollup: - specifier: 4.62.2 - version: 4.62.2 + specifier: 4.63.0 + version: 4.63.0 rollup-plugin-dts: specifier: ^6.1.1 - version: 6.4.1(rollup@4.62.2)(typescript@6.0.3) + version: 6.5.1(rollup@4.63.0)(typescript@6.0.3) rxjs: specifier: ^7.0.0 version: 7.8.2 @@ -233,10 +233,10 @@ importers: version: 6.0.3 ws: specifier: ^8.15.0 - version: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) + version: 8.21.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) yargs: specifier: ^18.0.0 - version: 18.0.0 + version: 18.1.0 zone.js: specifier: 0.16.2 version: 0.16.2 @@ -248,11 +248,8 @@ importers: specifier: ^9.0.0 version: 9.1.1 '@angular/ng-dev': - specifier: https://github.com/angular/dev-infra-private-ng-dev-builds.git#7a67d5221a9efec2b69b102759d04223a3fc8552 - version: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/7a67d5221a9efec2b69b102759d04223a3fc8552(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)) - '@babel/plugin-transform-async-generator-functions': - specifier: ^8.0.0 - version: 8.0.1(@babel/core@8.0.1) + specifier: https://github.com/angular/dev-infra-private-ng-dev-builds.git#c3d7ed184d71d390d3eacff85f4b2b3f16b82660 + version: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/c3d7ed184d71d390d3eacff85f4b2b3f16b82660(@modelcontextprotocol/sdk@1.30.0(supports-color@11.0.0)) '@bazel/bazelisk': specifier: ^1.7.5 version: 1.28.1 @@ -264,7 +261,7 @@ importers: version: 0.28.0 '@inquirer/prompts': specifier: ^8.0.0 - version: 8.5.2(@types/node@20.19.43) + version: 8.7.0(@types/node@20.19.43) '@types/adm-zip': specifier: ^0.5.0 version: 0.5.8 @@ -285,37 +282,37 @@ importers: version: 0.5.5 conventional-changelog: specifier: ^8.0.0 - version: 8.1.0(conventional-commits-filter@6.0.1) + version: 8.1.3 cypress: - specifier: 15.18.1 - version: 15.18.1 + specifier: 16.0.0 + version: 16.0.0(bufferutil@4.1.0) firebase-tools: specifier: ^15.0.0 - version: 15.23.0(@cfworker/json-schema@4.1.1)(@types/node@20.19.43)(bufferutil@4.1.0)(encoding@0.1.13)(supports-color@10.2.2) + version: 15.28.2(@types/node@20.19.43)(bufferutil@4.1.0)(encoding@0.1.13)(supports-color@11.0.0) get-tsconfig: specifier: ^4.10.1 - version: 4.14.0 + version: 4.14.3 gulp: specifier: ^5.0.0 version: 5.0.1 gulp-conventional-changelog: specifier: ^5.0.0 - version: 5.0.0 + version: 5.0.0(conventional-commits-filter@5.0.0) husky: specifier: 9.1.7 version: 9.1.7 karma-coverage: specifier: ^2.2.1 - version: 2.2.1(supports-color@8.1.1) + version: 2.2.1(supports-color@11.0.0) karma-jasmine-html-reporter: specifier: ^2.2.0 - version: 2.2.0(jasmine-core@6.3.0)(karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6)))(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6)) + version: 2.3.0(jasmine-core@6.3.0)(karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)))(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)) prettier: specifier: ^3.8.0 - version: 3.9.5 + version: 3.9.6 rollup-plugin-sourcemaps2: specifier: ^0.5.1 - version: 0.5.8(@types/node@20.19.43)(rollup@4.62.2) + version: 0.5.8(@types/node@20.19.43)(rollup@4.63.0) semver: specifier: ^7.3.5 version: 7.8.5 @@ -332,32 +329,32 @@ importers: adev: dependencies: '@algolia/client-common': - specifier: 5.56.0 - version: 5.56.0 + specifier: 5.57.0 + version: 5.57.0 '@algolia/client-search': - specifier: 5.56.0 - version: 5.56.0 + specifier: 5.57.0 + version: 5.57.0 '@algolia/requester-browser-xhr': - specifier: 5.56.0 - version: 5.56.0 + specifier: 5.57.0 + version: 5.57.0 '@algolia/requester-node-http': - specifier: 5.56.0 - version: 5.56.0 + specifier: 5.57.0 + version: 5.57.0 '@angular/animations': specifier: workspace:* version: link:../packages/animations '@angular/aria': - specifier: 22.1.0-next.4 - version: 22.1.0-next.4(@angular/cdk@22.1.0-next.4(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2))(@angular/core@packages+core) + specifier: 22.2.0-next.5 + version: 22.2.0-next.5(@angular/cdk@22.2.0-next.5(@angular/common@packages+common)(@angular/core@packages+core)(@angular/forms@packages+forms)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2))(@angular/core@packages+core) '@angular/build': - specifier: 22.1.0-next.4 - version: 22.1.0-next.4(0b1055752a55c13ecb546c4fb1e33e8f) + specifier: 22.2.0-next.7 + version: 22.2.0-next.7(2acce862f67dc28f299e38c6f24193ce) '@angular/cdk': - specifier: 22.1.0-next.4 - version: 22.1.0-next.4(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2) + specifier: 22.2.0-next.5 + version: 22.2.0-next.5(@angular/common@packages+common)(@angular/core@packages+core)(@angular/forms@packages+forms)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2) '@angular/cli': - specifier: 22.1.0-next.4 - version: 22.1.0-next.4(@cfworker/json-schema@4.1.1)(@types/node@24.13.3)(chokidar@5.0.0)(supports-color@10.2.2) + specifier: 22.2.0-next.7 + version: 22.2.0-next.7(@types/node@24.13.3)(chokidar@5.0.0) '@angular/common': specifier: workspace:* version: link:../packages/common @@ -377,8 +374,8 @@ importers: specifier: workspace:* version: link:../packages/forms '@angular/material': - specifier: 22.1.0-next.4 - version: 22.1.0-next.4(@angular/cdk@22.1.0-next.4(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2))(@angular/common@packages+common)(@angular/core@packages+core)(@angular/forms@packages+forms)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2) + specifier: 22.2.0-next.5 + version: 22.2.0-next.5(@angular/cdk@22.2.0-next.5(@angular/common@packages+common)(@angular/core@packages+core)(@angular/forms@packages+forms)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2))(@angular/common@packages+common)(@angular/core@packages+core)(@angular/forms@packages+forms)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2) '@angular/platform-browser': specifier: workspace:* version: link:../packages/platform-browser @@ -389,14 +386,14 @@ importers: specifier: workspace:* version: link:../packages/router '@angular/ssr': - specifier: 22.1.0-next.4 - version: 22.1.0-next.4(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-server@packages+platform-server)(@angular/router@packages+router) + specifier: 22.2.0-next.7 + version: 22.2.0-next.7(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-server@packages+platform-server)(@angular/router@packages+router) '@codemirror/autocomplete': specifier: 6.20.3 version: 6.20.3 '@codemirror/commands': - specifier: 6.10.4 - version: 6.10.4 + specifier: 6.11.0 + version: 6.11.0 '@codemirror/lang-angular': specifier: 0.1.4 version: 0.1.4 @@ -404,8 +401,8 @@ importers: specifier: 6.3.1 version: 6.3.1 '@codemirror/lang-html': - specifier: 6.4.11 - version: 6.4.11 + specifier: 6.4.12 + version: 6.4.12 '@codemirror/lang-javascript': specifier: 6.2.5 version: 6.2.5 @@ -425,14 +422,14 @@ importers: specifier: 6.7.1 version: 6.7.1 '@codemirror/view': - specifier: 6.43.6 - version: 6.43.6 + specifier: 6.43.9 + version: 6.43.9 '@lezer/common': specifier: 1.5.2 version: 1.5.2 '@lezer/css': - specifier: 1.3.4 - version: 1.3.4 + specifier: 1.3.6 + version: 1.3.6 '@lezer/highlight': specifier: 1.2.3 version: 1.2.3 @@ -449,29 +446,29 @@ importers: specifier: 1.1.0 version: 1.1.0 '@marijn/find-cluster-break': - specifier: 1.0.3 - version: 1.0.3 + specifier: 1.0.4 + version: 1.0.4 '@shikijs/core': specifier: ^4.0.0 - version: 4.3.1 + version: 4.4.3 '@shikijs/engine-javascript': specifier: ^4.0.0 - version: 4.3.1 + version: 4.4.3 '@shikijs/engine-oniguruma': specifier: ^4.0.0 - version: 4.3.1 + version: 4.4.3 '@shikijs/langs': specifier: ^4.0.0 - version: 4.3.1 + version: 4.4.3 '@shikijs/primitive': specifier: ^4.0.0 - version: 4.3.1 + version: 4.4.3 '@shikijs/themes': specifier: ^4.0.0 - version: 4.3.1 + version: 4.4.3 '@shikijs/types': specifier: ^4.0.0 - version: 4.3.1 + version: 4.4.3 '@shikijs/vscode-textmate': specifier: ^10.0.2 version: 10.0.2 @@ -485,14 +482,14 @@ importers: specifier: 6.0.0 version: 6.0.0 '@types/jsdom': - specifier: 28.0.3 - version: 28.0.3 + specifier: 30.0.0 + version: 30.0.0 '@types/node': specifier: 24.13.3 version: 24.13.3 '@typescript/vfs': specifier: 1.6.4 - version: 1.6.4(supports-color@8.1.1)(typescript@6.0.3) + version: 1.6.4(supports-color@11.0.0)(typescript@6.0.3) '@webcontainer/api': specifier: 1.6.4 version: 1.6.4 @@ -503,11 +500,14 @@ importers: specifier: 6.0.0 version: 6.0.0 algoliasearch: - specifier: 5.56.0 - version: 5.56.0 + specifier: 5.57.0 + version: 5.57.0 angular-split: specifier: 20.0.0 version: 20.0.0(@angular/common@packages+common)(@angular/core@packages+core)(rxjs@7.8.2) + beasties: + specifier: 0.5.4 + version: 0.5.4 ccount: specifier: ^2.0.1 version: 2.0.1 @@ -545,41 +545,41 @@ importers: specifier: 6.3.0 version: 6.3.0 jsdom: - specifier: 29.1.1 - version: 29.1.1 + specifier: 30.0.1 + version: 30.0.1 karma-chrome-launcher: specifier: 3.2.0 version: 3.2.0 karma-coverage: specifier: 2.2.1 - version: 2.2.1(supports-color@10.2.2) + version: 2.2.1(supports-color@11.0.0) karma-jasmine: specifier: 5.1.0 - version: 5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6)) + version: 5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)) karma-jasmine-html-reporter: - specifier: 2.2.0 - version: 2.2.0(jasmine-core@6.3.0)(karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6)))(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6)) + specifier: 2.3.0 + version: 2.3.0(jasmine-core@6.3.0)(karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)))(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)) marked: - specifier: 18.0.6 - version: 18.0.6 + specifier: 18.0.11 + version: 18.0.11 mermaid: - specifier: 11.16.0 - version: 11.16.0 + specifier: 11.17.2 + version: 11.17.2 ngx-progressbar: specifier: 14.0.0 - version: 14.0.0(@angular/cdk@22.1.0-next.4(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2))(@angular/common@packages+common)(@angular/core@packages+core)(rxjs@7.8.2) + version: 14.0.0(@angular/cdk@22.2.0-next.5(@angular/common@packages+common)(@angular/core@packages+core)(@angular/forms@packages+forms)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2))(@angular/common@packages+common)(@angular/core@packages+core)(rxjs@7.8.2) playwright-core: - specifier: 1.61.1 - version: 1.61.1 + specifier: 1.62.1 + version: 1.62.1 preact: - specifier: 10.29.7 - version: 10.29.7(preact-render-to-string@6.7.0) + specifier: 10.29.8 + version: 10.29.8(preact-render-to-string@6.7.0) preact-render-to-string: specifier: 6.7.0 - version: 6.7.0(preact@10.29.7) + version: 6.7.0(preact@10.29.8) prettier: - specifier: 3.9.5 - version: 3.9.5 + specifier: 3.9.6 + version: 3.9.6 property-information: specifier: ^7.1.0 version: 7.2.0 @@ -587,8 +587,8 @@ importers: specifier: 7.8.2 version: 7.8.2 shiki: - specifier: 4.3.1 - version: 4.3.1 + specifier: 4.4.3 + version: 4.4.3 space-separated-tokens: specifier: ^2.0.2 version: 2.0.2 @@ -616,33 +616,33 @@ importers: devDependencies: autoprefixer: specifier: 10.5.4 - version: 10.5.4(postcss@8.5.20) + version: 10.5.4(postcss@8.5.26) karma: specifier: ~6.4.4 - version: 6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6) + version: 6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6) postcss: - specifier: 8.5.20 - version: 8.5.20 + specifier: 8.5.26 + version: 8.5.26 tailwindcss: specifier: 3.4.19 - version: 3.4.19(tsx@4.23.1)(yaml@2.9.0) + version: 3.4.19(tsx@4.23.13)(yaml@2.9.1) adev/shared-docs: dependencies: '@angular/common': - specifier: 'workspace: *' + specifier: workspace:* version: link:../../packages/common '@angular/core': - specifier: 'workspace: *' + specifier: workspace:* version: link:../../packages/core '@angular/forms': - specifier: 'workspace: *' + specifier: workspace:* version: link:../../packages/forms '@angular/platform-browser': - specifier: 'workspace: *' + specifier: workspace:* version: link:../../packages/platform-browser '@angular/router': - specifier: 'workspace: *' + specifier: workspace:* version: link:../../packages/router '@webcontainer/api': specifier: ^1.1.8 @@ -657,20 +657,20 @@ importers: specifier: ^0.8.2 version: 0.8.3 jsdom: - specifier: ~29.1.0 - version: 29.1.1 + specifier: ~30.0.0 + version: 30.0.1 marked: specifier: ~18.0.0 - version: 18.0.5 + version: 18.0.11 mermaid: specifier: ^11.0.0 - version: 11.16.0 + version: 11.17.2 rxjs: specifier: ^7.8.1 version: 7.8.2 shiki: specifier: ^4.0.0 - version: 4.3.1 + version: 4.4.3 tinyglobby: specifier: ^0.2.12 version: 0.2.17 @@ -711,8 +711,11 @@ importers: specifier: workspace:* version: link:../packages/router '@angular/ssr': - specifier: 22.1.0-next.4 - version: 22.1.0-next.4(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-server@packages+platform-server)(@angular/router@packages+router) + specifier: 22.2.0-next.7 + version: 22.2.0-next.7(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-server@packages+platform-server)(@angular/router@packages+router) + beasties: + specifier: 0.5.4 + version: 0.5.4 rxjs: specifier: ~7.8.0 version: 7.8.2 @@ -721,23 +724,23 @@ importers: version: 2.8.1 devDependencies: '@angular/build': - specifier: 22.1.0-next.4 - version: 22.1.0-next.4(0b1055752a55c13ecb546c4fb1e33e8f) + specifier: 22.2.0-next.7 + version: 22.2.0-next.7(2acce862f67dc28f299e38c6f24193ce) '@angular/cli': - specifier: 22.1.0-next.4 - version: 22.1.0-next.4(@cfworker/json-schema@4.1.1)(@types/node@24.13.3)(chokidar@5.0.0)(supports-color@10.2.2) + specifier: 22.2.0-next.7 + version: 22.2.0-next.7(@types/node@24.13.3)(chokidar@5.0.0) '@angular/compiler-cli': specifier: workspace:* version: link:../packages/compiler-cli jsdom: - specifier: ^29.0.0 - version: 29.1.1 + specifier: ^30.0.0 + version: 30.0.1 typescript: specifier: ~6.0.2 version: 6.0.3 vitest: - specifier: ^4.0.0 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.1)(jiti@1.21.7)(jsdom@29.1.1)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0) + specifier: ^5.0.0 + version: 5.0.0(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(jsdom@30.0.1)(vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.1)(sass@1.104.1)(tsx@4.23.13)(yaml@2.9.1)) devtools: dependencies: @@ -748,8 +751,8 @@ importers: specifier: ^7.0.14 version: 7.0.14 ngx-flamegraph: - specifier: 0.1.1 - version: 0.1.1(@angular/common@packages+common)(@angular/core@packages+core) + specifier: 0.2.0 + version: 0.2.0(@angular/common@packages+common)(@angular/core@packages+core) todomvc-app-css: specifier: ^2.3.0 version: 2.4.3 @@ -773,7 +776,7 @@ importers: specifier: workspace:* version: link:../packages/animations '@angular/benchpress': - specifier: 'workspace: *' + specifier: workspace:* version: link:../packages/benchpress '@angular/common': specifier: workspace:* @@ -794,7 +797,7 @@ importers: specifier: workspace:* version: link:../packages/forms '@angular/localize': - specifier: 'workspace: *' + specifier: workspace:* version: link:../packages/localize '@angular/platform-browser': specifier: workspace:* @@ -809,7 +812,7 @@ importers: specifier: workspace:* version: link:../packages/router '@angular/upgrade': - specifier: 'workspace: *' + specifier: workspace:* version: link:../packages/upgrade modules: @@ -821,8 +824,8 @@ importers: specifier: workspace:* version: link:../packages/benchpress '@angular/build': - specifier: 22.1.0-next.4 - version: 22.1.0-next.4(0b1055752a55c13ecb546c4fb1e33e8f) + specifier: 22.2.0-next.7 + version: 22.2.0-next.7(2acce862f67dc28f299e38c6f24193ce) '@angular/common': specifier: workspace:* version: link:../packages/common @@ -870,7 +873,7 @@ importers: version: angular@1.8.3 protractor: specifier: 7.0.0 - version: 7.0.0(supports-color@10.2.2) + version: 7.0.0(supports-color@11.0.0) reflect-metadata: specifier: 0.2.2 version: 0.2.2 @@ -887,8 +890,8 @@ importers: specifier: 2.8.1 version: 2.8.1 yargs: - specifier: 18.0.0 - version: 18.0.0 + specifier: 18.1.0 + version: 18.1.0 zone.js: specifier: 0.16.2 version: 0.16.2 @@ -896,7 +899,7 @@ importers: packages/animations: dependencies: '@angular/core': - specifier: 'workspace: *' + specifier: workspace:* version: link:../core tslib: specifier: ^2.3.0 @@ -905,8 +908,8 @@ importers: packages/benchpress: dependencies: '@angular/core': - specifier: ^22.1.0-next - version: 22.1.0-next.5(@angular/compiler@packages+compiler) + specifier: ^22.2.0-next + version: 22.2.0-next.4(@angular/compiler@packages+compiler) reflect-metadata: specifier: ^0.2.0 version: 0.2.2 @@ -917,7 +920,7 @@ importers: packages/common: dependencies: '@angular/core': - specifier: 'workspace: *' + specifier: workspace:* version: link:../core rxjs: specifier: ^6.5.3 || ^7.4.0 @@ -935,14 +938,14 @@ importers: packages/compiler-cli: dependencies: '@angular/compiler': - specifier: 'workspace: *' + specifier: workspace:* version: link:../compiler '@babel/core': specifier: 8.0.1 version: 8.0.1 '@jridgewell/sourcemap-codec': specifier: ^1.4.14 - version: 1.5.5 + version: 1.6.0 chokidar: specifier: ^5.0.0 version: 5.0.0 @@ -963,7 +966,7 @@ importers: version: 6.0.3 yargs: specifier: ^18.0.0 - version: 18.0.0 + version: 18.1.0 devDependencies: '@types/convert-source-map': specifier: ^2.0.0 @@ -981,7 +984,7 @@ importers: packages/core: dependencies: '@angular/compiler': - specifier: 'workspace: *' + specifier: workspace:* version: link:../compiler rxjs: specifier: ^6.5.3 || ^7.4.0 @@ -994,11 +997,14 @@ importers: version: 0.16.2 devDependencies: '@mcp-b/webmcp-polyfill': - specifier: ^4.0.0 - version: 4.0.0 + specifier: ^5.0.0 + version: 5.1.0 '@mcp-b/webmcp-types': - specifier: ^4.0.0 - version: 4.0.0 + specifier: ^5.0.0 + version: 5.1.0 + '@modelcontextprotocol/server': + specifier: ^2.0.0 + version: 2.0.0 packages/core/test/bundling: dependencies: @@ -1006,8 +1012,8 @@ importers: specifier: workspace:* version: link:../../../animations '@angular/build': - specifier: 22.1.0-next.4 - version: 22.1.0-next.4(0b1055752a55c13ecb546c4fb1e33e8f) + specifier: 22.2.0-next.7 + version: 22.2.0-next.7(e7ab0a794307bcb845f8633d1b339c6e) '@angular/common': specifier: workspace:* version: link:../../../common @@ -1033,7 +1039,7 @@ importers: packages/elements: dependencies: '@angular/core': - specifier: 'workspace: *' + specifier: workspace:* version: link:../core rxjs: specifier: ^6.5.3 || ^7.4.0 @@ -1045,13 +1051,13 @@ importers: packages/forms: dependencies: '@angular/common': - specifier: 'workspace: *' + specifier: workspace:* version: link:../common '@angular/core': - specifier: 'workspace: *' + specifier: workspace:* version: link:../core '@angular/platform-browser': - specifier: 'workspace: *' + specifier: workspace:* version: link:../platform-browser '@standard-schema/spec': specifier: ^1.0.0 @@ -1064,24 +1070,24 @@ importers: version: 2.8.1 zod: specifier: ^4.0.10 - version: 4.4.3 + version: 4.5.4 devDependencies: '@mcp-b/webmcp-polyfill': - specifier: ^4.0.0 - version: 4.0.0 + specifier: ^5.0.0 + version: 5.1.0 '@mcp-b/webmcp-types': - specifier: ^4.0.0 - version: 4.0.0 + specifier: ^5.0.0 + version: 5.1.0 packages/language-service: {} packages/localize: dependencies: '@angular/compiler': - specifier: 'workspace: *' + specifier: workspace:* version: link:../compiler '@angular/compiler-cli': - specifier: 'workspace: *' + specifier: workspace:* version: link:../compiler-cli '@babel/core': specifier: 8.0.1 @@ -1091,18 +1097,18 @@ importers: version: 0.2.17 yargs: specifier: ^18.0.0 - version: 18.0.0 + version: 18.1.0 packages/platform-browser: dependencies: '@angular/animations': - specifier: 'workspace: *' + specifier: workspace:* version: link:../animations '@angular/common': - specifier: 'workspace: *' + specifier: workspace:* version: link:../common '@angular/core': - specifier: 'workspace: *' + specifier: workspace:* version: link:../core tslib: specifier: ^2.3.0 @@ -1111,16 +1117,16 @@ importers: packages/platform-browser-dynamic: dependencies: '@angular/common': - specifier: 'workspace: *' + specifier: workspace:* version: link:../common '@angular/compiler': - specifier: 'workspace: *' + specifier: workspace:* version: link:../compiler '@angular/core': - specifier: 'workspace: *' + specifier: workspace:* version: link:../core '@angular/platform-browser': - specifier: 'workspace: *' + specifier: workspace:* version: link:../platform-browser tslib: specifier: ^2.3.0 @@ -1129,16 +1135,16 @@ importers: packages/platform-server: dependencies: '@angular/common': - specifier: 'workspace: *' + specifier: workspace:* version: link:../common '@angular/compiler': - specifier: 'workspace: *' + specifier: workspace:* version: link:../compiler '@angular/core': - specifier: 'workspace: *' + specifier: workspace:* version: link:../core '@angular/platform-browser': - specifier: 'workspace: *' + specifier: workspace:* version: link:../platform-browser rxjs: specifier: ^6.5.3 || ^7.4.0 @@ -1153,13 +1159,13 @@ importers: packages/router: dependencies: '@angular/common': - specifier: 'workspace: *' + specifier: workspace:* version: link:../common '@angular/core': - specifier: 'workspace: *' + specifier: workspace:* version: link:../core '@angular/platform-browser': - specifier: 'workspace: *' + specifier: workspace:* version: link:../platform-browser rxjs: specifier: ^6.5.3 || ^7.4.0 @@ -1175,7 +1181,7 @@ importers: packages/service-worker: dependencies: '@angular/core': - specifier: 'workspace: *' + specifier: workspace:* version: link:../core rxjs: specifier: ^6.5.3 || ^7.4.0 @@ -1187,16 +1193,16 @@ importers: packages/upgrade: dependencies: '@angular/compiler': - specifier: 'workspace: *' + specifier: workspace:* version: link:../compiler '@angular/core': - specifier: 'workspace: *' + specifier: workspace:* version: link:../core '@angular/platform-browser': - specifier: 'workspace: *' + specifier: workspace:* version: link:../platform-browser '@angular/platform-browser-dynamic': - specifier: 'workspace: *' + specifier: workspace:* version: link:../platform-browser-dynamic tslib: specifier: ^2.3.0 @@ -1205,11 +1211,11 @@ importers: packages/zone.js: devDependencies: '@csstools/css-calc': - specifier: 3.2.1 - version: 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + specifier: 3.3.0 + version: 3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) '@csstools/css-color-parser': - specifier: 4.1.9 - version: 4.1.9(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + specifier: 4.2.1 + version: 4.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) '@externs/nodejs': specifier: 1.5.0 version: 1.5.0 @@ -1226,8 +1232,8 @@ importers: specifier: 3.7.2 version: 3.7.2 domino: - specifier: https://github.com/angular/domino.git#f88e5aa49cf2804d7c2df22ef1640eb4ec43dd56 - version: '@angular/domino@https://codeload.github.com/angular/domino/tar.gz/f88e5aa49cf2804d7c2df22ef1640eb4ec43dd56' + specifier: https://github.com/angular/domino.git#4d97473116d000e3fd4d6f75ec98cbd67576fa6f + version: '@angular/domino@https://codeload.github.com/angular/domino/tar.gz/4d97473116d000e3fd4d6f75ec98cbd67576fa6f' esbuild-plugin-umd-wrapper: specifier: 3.0.0 version: 3.0.0 @@ -1242,16 +1248,16 @@ importers: version: 2.5.2 jest: specifier: 30.4.2 - version: 30.4.2(@types/node@24.13.3)(supports-color@10.2.2)(ts-node@10.9.2(@types/node@24.13.3)(typescript@6.0.3)) + version: 30.4.2(@types/node@24.13.3)(supports-color@11.0.0)(ts-node@10.9.2(@types/node@24.13.3)(typescript@6.0.3)) jest-environment-jsdom: specifier: 30.4.1 - version: 30.4.1(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) + version: 30.4.1(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6) jest-environment-node: specifier: 30.4.1 version: 30.4.1 mocha: - specifier: 11.7.6 - version: 11.7.6 + specifier: 12.0.0 + version: 12.0.0 mock-require: specifier: 3.0.3 version: 3.0.3 @@ -1268,14 +1274,14 @@ importers: specifier: ^2.3.0 version: 2.8.1 vitest: - specifier: ^4.0.0 - version: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.1)(jiti@1.21.7)(jsdom@29.1.1)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0) + specifier: ^5.0.0 + version: 5.0.0(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(jsdom@30.0.1)(vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.1)(sass@1.104.1)(tsx@4.23.13)(yaml@2.9.1)) packages/zone.js/test/typings: dependencies: domino: - specifier: https://github.com/angular/domino.git#f88e5aa49cf2804d7c2df22ef1640eb4ec43dd56 - version: '@angular/domino@https://codeload.github.com/angular/domino/tar.gz/f88e5aa49cf2804d7c2df22ef1640eb4ec43dd56' + specifier: https://github.com/angular/domino.git#4d97473116d000e3fd4d6f75ec98cbd67576fa6f + version: '@angular/domino@https://codeload.github.com/angular/domino/tar.gz/4d97473116d000e3fd4d6f75ec98cbd67576fa6f' zone.js: specifier: workspace:* version: link:../.. @@ -1310,13 +1316,13 @@ importers: version: 24.13.3 '@types/vscode': specifier: ^1.74.3 - version: 1.125.0 + version: 1.134.0 '@vscode/test-electron': - specifier: ~3.0.0 - version: 3.0.0(supports-color@10.2.2) + specifier: ~3.1.0 + version: 3.1.0(supports-color@11.0.0) '@vscode/vsce': specifier: ~3.9.0 - version: 3.9.2(supports-color@10.2.2) + version: 3.9.2(supports-color@11.0.0) jasmine: specifier: 6.3.0 version: 6.3.0 @@ -1342,14 +1348,14 @@ importers: specifier: 3.17.5 version: 3.17.5 vscode-languageserver-textdocument: - specifier: 1.0.12 - version: 1.0.12 + specifier: 1.0.14 + version: 1.0.14 vscode-tmgrammar-test: specifier: 0.1.3 version: 0.1.3 vscode-uri: - specifier: 3.1.0 - version: 3.1.0 + specifier: 3.2.0 + version: 3.2.0 xvfb: specifier: ^0.4.0 version: 0.4.0 @@ -1373,8 +1379,8 @@ importers: version: 7.8.2 devDependencies: ng-packagr: - specifier: 22.1.0-next.3 - version: 22.1.0-next.3(@angular/compiler-cli@packages+compiler-cli)(tailwindcss@3.4.19(tsx@4.23.1)(yaml@2.9.0))(tslib@2.8.1)(typescript@6.0.3) + specifier: 22.2.0-next.5 + version: 22.2.0-next.5(@angular/compiler-cli@packages+compiler-cli)(supports-color@11.0.0)(tailwindcss@3.4.19(tsx@4.23.13)(yaml@2.9.1))(tslib@2.8.1)(typescript@6.0.3) typescript: specifier: 6.0.3 version: 6.0.3 @@ -1401,11 +1407,11 @@ importers: specifier: 9.0.1 version: 9.0.1 vscode-languageserver-textdocument: - specifier: ^1.0.12 - version: 1.0.12 + specifier: 1.0.14 + version: 1.0.14 vscode-uri: - specifier: 3.1.0 - version: 3.1.0 + specifier: 3.2.0 + version: 3.2.0 packages: @@ -1427,116 +1433,60 @@ packages: '@actions/io@3.0.2': resolution: {integrity: sha512-nRBchcMM+QK1pdjO7/idu86rbJI5YHUKCvKs0KxnSYbVe3F51UfGxuZX4Qy/fWlp6l7gWFwIkrOzN+oUK03kfw==} - '@algolia/abtesting@1.21.2': - resolution: {integrity: sha512-uXj0rgk30EpsKvOpuS+R+1XFDrnm56hED1Lz56e8uBkZdKCxw99LS2U8eXBqAHYU8kpkbsnV1GC8velBG070Hg==} - engines: {node: '>= 14.0.0'} - - '@algolia/abtesting@1.22.0': - resolution: {integrity: sha512-BFR6zNowNKcY7Ou7TaJc9QWexES4YKPbmf/OTFofpdsdhz4x6q0lbxp3duO0EHnyrN7rE4ba/TSXuY+BDGu4+g==} - engines: {node: '>= 14.0.0'} - - '@algolia/client-abtesting@5.55.2': - resolution: {integrity: sha512-y7Epol8HcjlBxKXHhyhfFPFhm78B3P6x9cCbCyGTdxjsdVCptXCy5hpkZWxjGpnaLHvWsHS4QRF0TiBOLst2xg==} - engines: {node: '>= 14.0.0'} - - '@algolia/client-abtesting@5.56.0': - resolution: {integrity: sha512-7r4Z3NC7yU1oAQVWJNA2HX7tX481F3pJvCGyLIXiTdBcthz4Q/o21jwcMYDFkuI92UWTNBQQmHYgwHo1zS5dzg==} - engines: {node: '>= 14.0.0'} - - '@algolia/client-analytics@5.55.2': - resolution: {integrity: sha512-8Pxj2VVmpM2d+UZufnlTq7T1QIcYPVugLV5XC50PnHsV5uRM9CSoYkg2Y+CwqwRk2La0xK5QsfZ0obIU+9XftQ==} - engines: {node: '>= 14.0.0'} - - '@algolia/client-analytics@5.56.0': - resolution: {integrity: sha512-avmjXQSq+jadFO8Xl2em05/uQdQnEmHsJyOAdVbZkmVgpMfxL12aJwVVfGNwYr9nulcpuJN1X0lTaQ5wxuNGcA==} - engines: {node: '>= 14.0.0'} - - '@algolia/client-common@5.55.2': - resolution: {integrity: sha512-9L4IpIYUqA63a7sw1trnHQGUvwiAjKz67nsgDnal98JGAc7wyposRb0Iag+eiMuyzFFaSHLe2/rGyIo+PafRBA==} - engines: {node: '>= 14.0.0'} - - '@algolia/client-common@5.56.0': - resolution: {integrity: sha512-v2TPStUhY//ripPjIVclZ8AWc7DEGooXULZGFlFu37zNatgHjw34oZZ+OSbbc/YHO+xZwPl62I1k8xH1m4S2eg==} - engines: {node: '>= 14.0.0'} - - '@algolia/client-insights@5.55.2': - resolution: {integrity: sha512-ZBm2ytY5EHFcj+kjNsXxMNO/TGlOHe2fBFXGKHJOM1bk1rAy4o2YI+d9oV/w/jrqx44pvJMJlc8X6vKnCuDgUQ==} + '@algolia/abtesting@1.23.0': + resolution: {integrity: sha512-j45MBISstltys9QyQ4xf6quRiN1g7vMuwQL9VM4dx8YuRZvCQ173b9royZAx6iAbRX3IB1VnG1z//NuwyQ8jpQ==} engines: {node: '>= 14.0.0'} - '@algolia/client-insights@5.56.0': - resolution: {integrity: sha512-P0ehROpM4Sem3Sqo5x2cKPgj67D3G3jy0rh1Amwkcvsfr6tkvIcdCmerieanqTF7NxUMPNFLkpIFeMO8Rpa50w==} + '@algolia/client-abtesting@5.57.0': + resolution: {integrity: sha512-JVFFujiZUCguk5tz3LZr4fTQxqpIrj4/Jw3SI7kMljSqtfLxYn/s/TWH0J2s4iNfsDpxPhgFGMotCpmDI4kZ8w==} engines: {node: '>= 14.0.0'} - '@algolia/client-personalization@5.55.2': - resolution: {integrity: sha512-3FGVW/jDk7sdYwqa2NKnF/qXWcttc4bvGrwNbvqz3VoWSRv42CNvRk+3Y9QJFIUf1vY50hAuVWUoFKdyc8vaXA==} + '@algolia/client-analytics@5.57.0': + resolution: {integrity: sha512-6KqECK4ED3JJQEoDrQWnGPQzElA828xAD4qK5ceawNNyP/LcSvzAoLHjFkoTPksZ/kxj6VUtCRH+IHZesLltng==} engines: {node: '>= 14.0.0'} - '@algolia/client-personalization@5.56.0': - resolution: {integrity: sha512-SXK3Vn3WVxyzbm31oePZBJkp1wpOyuWdd4B/Pv7n0aXDxmeSWhC1R1FC1517mMrFAIaPH4Rt0x6RUe7ZNjz8FA==} + '@algolia/client-common@5.57.0': + resolution: {integrity: sha512-uqpGF3oXYsoCbQq5d7BzNrNTfIfuvJyGP1CKvSW27T9boUg7KOwyxsAw1AX0a3jSW2HrYEJ/NN+Z4MiGivbpeQ==} engines: {node: '>= 14.0.0'} - '@algolia/client-query-suggestions@5.55.2': - resolution: {integrity: sha512-JsG8LovDAYul5t8e533tZ3O1uZILxso5zsTtB7ONc5RJ8ACdTxAAC/jaOnsBNYb+x+STP7fzx/Iro55v5DNgoQ==} + '@algolia/client-insights@5.57.0': + resolution: {integrity: sha512-u5NboJVJXDEFplvNnqqX4CxkXPYysjJRj47hOSh9329H8kG5gFLKJBIiS5utMQ+GZm8xQl3Te7NInDk6elEADQ==} engines: {node: '>= 14.0.0'} - '@algolia/client-query-suggestions@5.56.0': - resolution: {integrity: sha512-5+ZdX8garFnmycnZgKhtXHePEaLj5zqDxI/0lkhhluzCcvTn0/PvvTirTg8hHYetQHvn7GDyeAiqTAieMvMW4A==} + '@algolia/client-personalization@5.57.0': + resolution: {integrity: sha512-uzc0b2LmHAK9/QID4xeo35OG84AkZl4YewkCqawqAOGLjT2eZpM/OZx45ESygMHG30Ws+ZTSdluPtMJcUnrbWQ==} engines: {node: '>= 14.0.0'} - '@algolia/client-search@5.55.2': - resolution: {integrity: sha512-5wDnoIfC75zJ2MSHv5SSzTlRL2z7jQMbqQ5jrzottuq2p3oBObv8pD/JpXWu8pRaimaxNr3/Bs/KZIGVXxJ7hg==} + '@algolia/client-query-suggestions@5.57.0': + resolution: {integrity: sha512-dIAhnM6ue/ssa5PjgNfu4g8A4yTojl9ZOUzZU3wIaIKRerL2R/3Emuf9n/D6ICXXP167KC6XCeC7nliSw7cuSw==} engines: {node: '>= 14.0.0'} - '@algolia/client-search@5.56.0': - resolution: {integrity: sha512-+mKUdYvqOi0BcvpAEyCEw49vSBptufIcfibtHz2bdr1pI789M46Yt0uQEk/sxtK3teh71OQvVFHaTDzShUWewQ==} + '@algolia/client-search@5.57.0': + resolution: {integrity: sha512-2TTPTTKSJmCptvhCm4Xf3bBYMqZni+Pgc2hVdqc4l9wsBpSJNVTVIKpnd10OubUgkGcmppVDj1XQqYaf6EnPSQ==} engines: {node: '>= 14.0.0'} - '@algolia/ingestion@1.55.2': - resolution: {integrity: sha512-da+SC6ikpza98W7C5ChsKEQDvZc8PQLQ0sxmQ5yMRsHpdD3iPKnclJA6ViB5Nr5T9qOX+IDswC6AyqY4V3rtug==} + '@algolia/ingestion@1.57.0': + resolution: {integrity: sha512-W4JseHKt+pzOxlFV+T3MWEG0h4Z2Se5zjoXUD0ewlw8aOWMG/yjRdopUdLQsXULepB/My2tDuZjkwk2sMfsUrQ==} engines: {node: '>= 14.0.0'} - '@algolia/ingestion@1.56.0': - resolution: {integrity: sha512-9g/zj+AZx5moFcdFIrYQoVrueXivjUcc3MQHtCYT8WhIuk1lUh1AyEhvJCS0XBZld09cLvd1AZ3BvDBpVpX2UA==} + '@algolia/monitoring@1.57.0': + resolution: {integrity: sha512-BrxJVE0/eLinEPICCD7BKN/2xnt0nkjge70u8zzE2ISP3fuB3tjLgcwpanUycvlHBFLI4gK0l5ol54p6IYuR/Q==} engines: {node: '>= 14.0.0'} - '@algolia/monitoring@1.55.2': - resolution: {integrity: sha512-Y8kEcPqCiIEeaGv83l9RRA09mfYECqAJHNnOyEtZc9UirI6XBMUyFVss/sSeYUiV/Lf30hkbWcl00V1uXsf86Q==} + '@algolia/recommend@5.57.0': + resolution: {integrity: sha512-Gc29jkeiLKlVfHvyrIgyUHHE+aYTdXEeLfK42rjr5/1TTVsYwUJz0XkvoIBIqfMjcDg6gXeHb1jTUZ0H+SYIlQ==} engines: {node: '>= 14.0.0'} - '@algolia/monitoring@1.56.0': - resolution: {integrity: sha512-Qf3Sr6f9A9uxCZUf3MXS0d2b877uYzEB5yxqpVGXAhcJnBCQjrRRon0KvefpGkxy+BshrIJs96OUoMtGqXTFDA==} + '@algolia/requester-browser-xhr@5.57.0': + resolution: {integrity: sha512-PIPnPN7MP3fp2VAi01BVXhCWmD366ZB2Hkq5TlYKtThd4KxUtMmaaNDpFgVCTXtSIqWVZLJntOHRvxg/sIPd8Q==} engines: {node: '>= 14.0.0'} - '@algolia/recommend@5.55.2': - resolution: {integrity: sha512-5zmobuCQqFZkx+84Nt+suL7vo6jTh2CfAs2ndDSeTS2QHvnzP8YEEGWtWftjyACI0cK/FuH8urWwCHP+d2j8TA==} + '@algolia/requester-fetch@5.57.0': + resolution: {integrity: sha512-AX3RlOudXMdTwtwUqdAf5hAVLvXfOZZH1FZh6ALDdrhVLT0TtAIe48N6nYcWcTnwoTxK/wDIQqZ19IMjK8zJAA==} engines: {node: '>= 14.0.0'} - '@algolia/recommend@5.56.0': - resolution: {integrity: sha512-GXWG1rWc5wu8hY4N33Y3b6ernY6sAdAvmKWN/zHAiACOx40WnpG0TVX5YazCAr/9gOYGInSiM2A0y2jy2xbiDA==} - engines: {node: '>= 14.0.0'} - - '@algolia/requester-browser-xhr@5.55.2': - resolution: {integrity: sha512-qnGUUuWG66dRMnr33owLsrYIh9fHVxtU4R2rd3SpneAHuoAUcGbDOWNrj05glVU6M8yOqo9gQ22K8zpz0I8Xpg==} - engines: {node: '>= 14.0.0'} - - '@algolia/requester-browser-xhr@5.56.0': - resolution: {integrity: sha512-7t24cBxaInS3mZb7ddEaZT/tp6q+/aR4YttsQVyP1/i+LmwPR34atO35KjaLFCcRVrlP7sYOAqkCfg6lIRB+ew==} - engines: {node: '>= 14.0.0'} - - '@algolia/requester-fetch@5.55.2': - resolution: {integrity: sha512-lKZ5uhafMvR7dWCJEyuaeyZitid1I3ICx+k0vGf5x/ktdIQvc7bndCiOPpmIDqUmN26FE3jTehkAzSqee95G2Q==} - engines: {node: '>= 14.0.0'} - - '@algolia/requester-fetch@5.56.0': - resolution: {integrity: sha512-R7ePHgVYmDFjZpvrsVAfbDz/d4RxKAYZ5/vgLfIsCVRZRryjWl/3INOxpOICzitehQ5FjNtNjcLQTrmHPTcHBQ==} - engines: {node: '>= 14.0.0'} - - '@algolia/requester-node-http@5.55.2': - resolution: {integrity: sha512-Zc90xvKWUvxcNicvvTO9Pr/hT2TAnkixOIzJm/KMj5Ptm2pKjk71ngTsdkbRtJQvhZ2Kr9N1YdIjLrNHB5P2xw==} - engines: {node: '>= 14.0.0'} - - '@algolia/requester-node-http@5.56.0': - resolution: {integrity: sha512-PIOUXlSnrqM0S+WOgDRb4RzotydJH7ZoT6tOyL7tAO7qJOfvX5wsEW8Pe+PMKMwvuI4/gIyK9cg2H7lJXqnc4Q==} + '@algolia/requester-node-http@5.57.0': + resolution: {integrity: sha512-cWZc1dKb7wy9/wPpwMtL1y89gK2G7y2A47Coa7zwf1ydtIeJm4+S+XxoQ2b/ZRiQnrC1YHavLjYUPDCdnT7Khg==} engines: {node: '>= 14.0.0'} '@alloc/quick-lru@5.2.0': @@ -1547,13 +1497,13 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@angular-devkit/architect@0.2201.0-next.4': - resolution: {integrity: sha512-iCXgG0JsLO4cjq2bGrupBsNdmJGCQSe2MZ7lkNx6xcwZdu6bUNihk+77zXGKWgzjbUocvr4DuH+E2eNT6BxbcQ==} + '@angular-devkit/architect@0.2202.0-next.7': + resolution: {integrity: sha512-WJA46KOarmSTmNOndPf15pb8O1sBFqLHh8yVSJQaoGwIFIb6jK3igP0UFCxlVCs0DqHDrELVseiD3KqrPXGCZg==} engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} hasBin: true - '@angular-devkit/core@22.1.0-next.4': - resolution: {integrity: sha512-EsY0CF1KV2IR17+mJBlpdaMPRoS7Ab0z6AfdgIRDZ9OYknWzFiGP5a9ghwUzZi9u0KVqBybnBAEbRyKNEs6d/w==} + '@angular-devkit/core@22.2.0-next.7': + resolution: {integrity: sha512-Gz+Gg3wGxQJ0wxinrJHKTIRRVrSvDSTWa0EDH3mFHYK39TYm6gG+2Q8Izg8hkLX1EovNBbI/tY0C2AJQP2aNDg==} engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: chokidar: ^5.0.0 @@ -1561,38 +1511,38 @@ packages: chokidar: optional: true - '@angular-devkit/schematics@22.1.0-next.4': - resolution: {integrity: sha512-u2RK8HmF1Zlnp0IVJniTDnRilwEVqvhEpLL369Fm4TW0lVIj8TSf9sarE7VfZo6uQMom0APBjsYElRgmGd+6Dw==} + '@angular-devkit/schematics@22.2.0-next.7': + resolution: {integrity: sha512-4FhjOH4e/PbMoOvXkLhVfxZhof7qUyJzoCeu5UB/njgRSotExiiFJf+au/YEniFl/m9ij+t9gD/CQcRKzRbklA==} engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - '@angular/aria@22.1.0-next.4': - resolution: {integrity: sha512-4KDfXzRSTkFUG/FJ6hH5JFVKKyN5O9wjDRQRV8jKeHMlRAT0RX9iJK1F/TVAejGXgM9nmTL7D9NZWpPyKxVvRQ==} + '@angular/aria@22.2.0-next.5': + resolution: {integrity: sha512-E2pgLvb0yAYNpzkJf3abPZUZJaUjqUdOMedxuDqpHIxA99U2A0/ePP9bcy3nHvfIH4T7tP5IPPoEMygzgRJK4w==} peerDependencies: - '@angular/cdk': 22.1.0-next.4 + '@angular/cdk': 22.2.0-next.5 '@angular/core': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 - '@angular/build@22.1.0-next.4': - resolution: {integrity: sha512-iHyIRRxwdzJVS3P9w5WqwwIouVOKd1KUszHY63DsZq0NxwRTqUWV2hjE2oMoPCetRPnhzxesNj3g+P4+TO4StQ==} + '@angular/build@22.2.0-next.7': + resolution: {integrity: sha512-mYvQE5M/TlCSJjAxuFR3zUjFp2FJgXDTTa7TzngYtLXrYcb+rePs07sGKKvbhLqfVg5lngpNt5KYCRmfJaA8IA==} engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: - '@angular/compiler': ^22.0.0 || ^22.1.0-next.0 - '@angular/compiler-cli': ^22.0.0 || ^22.1.0-next.0 - '@angular/core': ^22.0.0 || ^22.1.0-next.0 - '@angular/localize': ^22.0.0 || ^22.1.0-next.0 - '@angular/platform-browser': ^22.0.0 || ^22.1.0-next.0 - '@angular/platform-server': ^22.0.0 || ^22.1.0-next.0 - '@angular/service-worker': ^22.0.0 || ^22.1.0-next.0 - '@angular/ssr': ^22.1.0-next.4 + '@angular/compiler': ^22.0.0 || ^22.2.0-next.0 + '@angular/compiler-cli': ^22.0.0 || ^22.2.0-next.0 + '@angular/core': ^22.0.0 || ^22.2.0-next.0 + '@angular/localize': ^22.0.0 || ^22.2.0-next.0 + '@angular/platform-browser': ^22.0.0 || ^22.2.0-next.0 + '@angular/platform-server': ^22.0.0 || ^22.2.0-next.0 + '@angular/service-worker': ^22.0.0 || ^22.2.0-next.0 + '@angular/ssr': ^22.2.0-next.7 istanbul-lib-instrument: ^6.0.0 karma: ^6.4.0 less: ^4.2.0 - ng-packagr: ^22.0.0 || ^22.1.0-next.0 + ng-packagr: ^22.0.0 || ^22.2.0-next.0 postcss: ^8.4.0 rollup: ^4.0.0 tailwindcss: ^2.0.0 || ^3.0.0 || ^4.0.0 tslib: ^2.3.0 typescript: '>=6.0 <6.1' - vitest: ^4.0.8 + vitest: ^4.0.8 || ^5.0.0 peerDependenciesMeta: '@angular/core': optional: true @@ -1623,54 +1573,55 @@ packages: vitest: optional: true - '@angular/cdk@22.1.0-next.4': - resolution: {integrity: sha512-lWsn9LIWr1E7R7DoMoorxnLjLUc5tQ47QI6Zn1TNNWoPvKa7Hh89mMwLwvUo0sDvu/rhCw6mwENQCyLbl0kP/g==} + '@angular/cdk@22.2.0-next.5': + resolution: {integrity: sha512-ihTqQzTHgKOOwnSEtH7MuBsJoIPMJ5rUdXLaJGbqDZbxAZ5hAMmhRRvlv78cSmHGLWFdBybxfKlb9IEzIZ0RUw==} peerDependencies: '@angular/common': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 '@angular/core': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 + '@angular/forms': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 '@angular/platform-browser': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 rxjs: ^6.5.3 || ^7.4.0 - '@angular/cli@22.1.0-next.4': - resolution: {integrity: sha512-GPtdvl0P/htYAUPtLwM+24s1+zls0gka4DUrTLgGQWH4rWsV1Yl5s9d5QX4VynIkbYWD0/pEN1Dymny9d8RS/A==} + '@angular/cli@22.2.0-next.7': + resolution: {integrity: sha512-xrmNfEJ2aAiJDYuSyWyLLxCJ7ID+00HPRieJb51w5XWpbu5Q8ru2ttCeOwmHG47NZfkV4hLVVBVwfiBindhgpA==} engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} hasBin: true - '@angular/core@22.1.0-next.5': - resolution: {integrity: sha512-Iy9r+EdpoeUat/wP7mDcz6o7WTAoyxOKSNvWlYrOYn3xZkKj2FFlzrsfclZxO7MzKC/TJPuWwdRuh+E1cyCPJQ==} + '@angular/core@22.2.0-next.4': + resolution: {integrity: sha512-fkIhSgLg41rKMMBLiZ+jy3AA3jEPKE++LCqGZzXKy3nHRbLxhA9lHYWonVvZav4+/zT1Plxh5hFoeSuPBMcghw==} engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0} peerDependencies: - '@angular/compiler': 22.1.0-next.5 + '@angular/compiler': 22.2.0-next.4 peerDependenciesMeta: '@angular/compiler': optional: true - '@angular/domino@https://codeload.github.com/angular/domino/tar.gz/f88e5aa49cf2804d7c2df22ef1640eb4ec43dd56': - resolution: {gitHosted: true, integrity: sha512-eVKFxSkVT6SaPLkXKvIGXeD0NuI8np1mc2rH3DebHbCURzAYOwNbbasKShP1AkxZqDsEIv75kIKEIJSfqiNaCw==, tarball: https://codeload.github.com/angular/domino/tar.gz/f88e5aa49cf2804d7c2df22ef1640eb4ec43dd56} + '@angular/domino@https://codeload.github.com/angular/domino/tar.gz/4d97473116d000e3fd4d6f75ec98cbd67576fa6f': + resolution: {gitHosted: true, tarball: https://codeload.github.com/angular/domino/tar.gz/4d97473116d000e3fd4d6f75ec98cbd67576fa6f} version: 2.1.6 - '@angular/material@22.1.0-next.4': - resolution: {integrity: sha512-DFbQUTYF6ur0QgyHyOi9YuPQKwGYKXyWU6CEVREgwKZJVW+1PJ1BIoAtdiCA13ymMoqIuum7EAu2BwkXOHKZ3A==} + '@angular/material@22.2.0-next.5': + resolution: {integrity: sha512-EY0S6BmsBBNjrfO9zR8LRMtOcPfEwMKNr8HPnHyXUN/lN4cQcwr0SCYFU0WLV32dIq84DbEYCs1klZWtZKaaeQ==} peerDependencies: - '@angular/cdk': 22.1.0-next.4 + '@angular/cdk': 22.2.0-next.5 '@angular/common': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 '@angular/core': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 '@angular/forms': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 '@angular/platform-browser': ^22.0.0-0 || ^22.1.0-0 || ^22.2.0-0 || ^22.3.0-0 || ^23.0.0-0 rxjs: ^6.5.3 || ^7.4.0 - '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/7a67d5221a9efec2b69b102759d04223a3fc8552': - resolution: {gitHosted: true, integrity: sha512-DQnETQLANEERiT5UIcBj1D4S1WYlYVOuwtog4JpslthLq0JqSkKXCp7o+1roasNfBrFLaOYMD7wqZiRhsxbNSw==, tarball: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/7a67d5221a9efec2b69b102759d04223a3fc8552} - version: 0.0.0-7365173626bd7f475d30ba010bfb0e485233b199 + '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/c3d7ed184d71d390d3eacff85f4b2b3f16b82660': + resolution: {gitHosted: true, tarball: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/c3d7ed184d71d390d3eacff85f4b2b3f16b82660} + version: 0.0.0-f5c817076b8e4da7b6e91783dbcd553c5003a296 hasBin: true - '@angular/ssr@22.1.0-next.4': - resolution: {integrity: sha512-BBbnq8TgR0vpSyRNHOYnvzWTVEmmMiZCeveOfCO9DtEzpoSkZvOnxKo/KeZegC+6ib5bZe/43/MUEd/4QOOi1A==} + '@angular/ssr@22.2.0-next.7': + resolution: {integrity: sha512-zQG7qKnkNzxXvXDJ08AdVoFtAtGSU13cDCo2gLu6bnF8DoClnXEEhC0dbQJaJWWICXUHI6vcE5lUZl5cojycAA==} peerDependencies: - '@angular/common': ^22.0.0 || ^22.1.0-next.0 - '@angular/core': ^22.0.0 || ^22.1.0-next.0 - '@angular/platform-server': ^22.0.0 || ^22.1.0-next.0 - '@angular/router': ^22.0.0 || ^22.1.0-next.0 + '@angular/common': ^22.0.0 || ^22.2.0-next.0 + '@angular/core': ^22.0.0 || ^22.2.0-next.0 + '@angular/platform-server': ^22.0.0 || ^22.2.0-next.0 + '@angular/router': ^22.0.0 || ^22.2.0-next.0 peerDependenciesMeta: '@angular/platform-server': optional: true @@ -1687,20 +1638,13 @@ packages: '@asamuzakjp/css-color@3.2.0': resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} - '@asamuzakjp/css-color@5.1.11': - resolution: {integrity: sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - - '@asamuzakjp/dom-selector@7.1.1': - resolution: {integrity: sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - - '@asamuzakjp/generational-cache@1.0.1': - resolution: {integrity: sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + '@asamuzakjp/css-color@6.0.7': + resolution: {integrity: sha512-vC/bk1Lz7Tn/EfU9/apOTBk80/8dyGyWMowPoV1tJ52muDGsDqt2HPT2klrFUiY60MQmQv9q8yIht15JnBgDGw==} + engines: {node: ^22.13.0 || >=24.0.0} - '@asamuzakjp/nwsapi@2.3.9': - resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} + '@asamuzakjp/dom-selector@8.3.2': + resolution: {integrity: sha512-93Z1N+BQNXysodoicpOIyNh2drHfz/CTf9nnT0FEx72GJcIiwgydD7tGAr78j41LsYn3hlRn+LdGPuBLn1Bl8Q==} + engines: {node: ^22.13.0 || >=24.0.0} '@azu/format-text@1.0.2': resolution: {integrity: sha512-Swi4N7Edy1Eqq82GxgEECXSSLyn6GOb5htRFPzBDdUkECGXtlf12ynO5oJSpWKPwCaUssOu7NfhDcCWpIC6Ywg==} @@ -1708,48 +1652,56 @@ packages: '@azu/style-format@1.0.1': resolution: {integrity: sha512-AHcTojlNBdD/3/KxIKlg8sxIWHfOtQszLvOpagLTO+bjC3u7SAszu1lf//u7JJC50aUSH+BVWDD/KvaA6Gfn5g==} - '@azure/abort-controller@2.1.2': - resolution: {integrity: sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==} - engines: {node: '>=18.0.0'} + '@azure/abort-controller@2.2.0': + resolution: {integrity: sha512-fNAjWnA/nZ2jz31kxR/AqRaUT8ewHBw/WuBIosK0moMy1C9e5ValbDfFdIxJzVOOYaYkV/b2F1S4H/aHiqfVQg==} + engines: {node: '>=22.0.0'} - '@azure/core-auth@1.10.1': - resolution: {integrity: sha512-ykRMW8PjVAn+RS6ww5cmK9U2CyH9p4Q88YJwvUslfuMmN98w/2rdGRLPqJYObapBCdzBVeDgYWdJnFPFb7qzpg==} - engines: {node: '>=20.0.0'} + '@azure/core-auth@1.11.0': + resolution: {integrity: sha512-IUZydyTUkDnYdstOW9pFOOUQlBjAepK5teihDE3x6yxsPJs/hsAaaYpeGxdxrgtOiJbBKSjKW7MDk7AEhb4LRg==} + engines: {node: '>=22.0.0'} - '@azure/core-client@1.10.2': - resolution: {integrity: sha512-1D2LpsU7y9xrqKjdIbsB7PlrRePw0xsVV8p+AKTlzITrWmscajryfJCdDJB/oGwvDI5HmRo04eMMADB67uwAwQ==} - engines: {node: '>=20.0.0'} + '@azure/core-client@1.11.0': + resolution: {integrity: sha512-JjQWO6akOck45PH/XBrxzsQGAiKrfFl4m5iggJ0ItMIz5omRufOXWpqCPpdjKN3vKDzlSUvFjaMb7Zwf0gvAdA==} + engines: {node: '>=22.0.0'} - '@azure/core-rest-pipeline@1.24.0': - resolution: {integrity: sha512-PpLsoDQ3AMmKZ0VU+0GrmqMxgp/sExjlVm4R+nLWngeoEGAzOIPVifaxKGU5gMv+nWELUoHfvrolWD+ZS/nFJg==} - engines: {node: '>=20.0.0'} + '@azure/core-process@1.0.0': + resolution: {integrity: sha512-/shnJ+ooO8WPxDhPEeI/2oRQuubn16gZ6CvlbpWbEswZfzwI9tI/sMAHmF3x1LuQ9yZYXfLW3TjzGMLEC5blKg==} + engines: {node: '>=22.0.0'} - '@azure/core-tracing@1.3.1': - resolution: {integrity: sha512-9MWKevR7Hz8kNzzPLfX4EAtGM2b8mr50HPDBvio96bURP/9C+HjdH3sBlLSNNrvRAr5/k/svoH457gB5IKpmwQ==} - engines: {node: '>=20.0.0'} + '@azure/core-rest-pipeline@1.25.0': + resolution: {integrity: sha512-bMs8ekJLjX8wPV+9IPBges1SLPyuDtE9g5gLDWOpxzKcoOFQnpLGkbcT1tdw3FaAmDS1gnPmMmJ6y/T5B96kIA==} + engines: {node: '>=22.0.0'} - '@azure/core-util@1.13.1': - resolution: {integrity: sha512-XPArKLzsvl0Hf0CaGyKHUyVgF7oDnhKoP85Xv6M4StF/1AhfORhZudHtOyf2s+FcbuQ9dPRAjB8J2KvRRMUK2A==} - engines: {node: '>=20.0.0'} + '@azure/core-tracing@1.4.0': + resolution: {integrity: sha512-eGwxD0AtncrxeBM4tG8R55Pc3rdX1hNW2WibJAgYpCVA6E93mvvVH+LcssoVjOBrSKWS55yEIHsk0X8ctHmfOQ==} + engines: {node: '>=22.0.0'} - '@azure/identity@4.13.1': - resolution: {integrity: sha512-5C/2WD5Vb1lHnZS16dNQRPMjN6oV/Upba+C9nBIs15PmOi6A3ZGs4Lr2u60zw4S04gi+u3cEXiqTVP7M4Pz3kw==} - engines: {node: '>=20.0.0'} + '@azure/core-util@1.14.0': + resolution: {integrity: sha512-9n2pWK61veAuN0V20t9lOuoV4CFMdyAZ1ygZzvBGk/pBBJRib/PjL9PLXa/aI2CcPpyHfqVsxxqLCYl6uZlfDw==} + engines: {node: '>=22.0.0'} - '@azure/logger@1.3.0': - resolution: {integrity: sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA==} - engines: {node: '>=20.0.0'} + '@azure/identity@4.13.2': + resolution: {integrity: sha512-NXL2/pCJctLxgw8bvrwwgge743kEq8LBT+O1pmV0vyUwetzFPH9auP6jhkU/cgZCPPtWoewAe3ncaGCgPo07fA==} + engines: {node: '>=22.0.0'} + + '@azure/logger@1.4.0': + resolution: {integrity: sha512-rbAE25KUfjU/s3XHUdJgceoCP5dEOpMx85J04kF+QMdta73XkuG9JGHHinch+XIoKpBdqljin+KqURpJriSzLA==} + engines: {node: '>=22.0.0'} + + '@azure/msal-browser@5.20.0': + resolution: {integrity: sha512-mtOKr708E/E/+qhI50QufmhR8GS5C84IeFGEaH/guMOaPXT9B/obEt8TVzX5U8j5OEUgukn0PrRmwVKaigr2wA==} + engines: {node: '>=0.8.0'} - '@azure/msal-browser@5.17.0': - resolution: {integrity: sha512-/yTnW2TCk9Mh+2b/NOaHAN+MryUNxzRTaJD/YtrqOA9bpBWfTXn/iyReRbaLrK/btBo3stEzLyEvuWp2NZ5DuA==} + '@azure/msal-common@16.13.0': + resolution: {integrity: sha512-rOAy0KUcyBbdwVJ+f3uPpthXatFLLZN+/KWAsTLzk1aB23Xl9DRmmXYwSvBFOZyXj4jUQQ5FKxxRkhAFW1fOow==} engines: {node: '>=0.8.0'} - '@azure/msal-common@16.11.1': - resolution: {integrity: sha512-yPohvMwWLv1XnaWnIUyKUh8CvcVChCGqG/VluGwfGmaAfrZTNt5yQ+sIs462Sgw6+e2K83KGmMJ860p73ZSCrw==} + '@azure/msal-common@16.14.0': + resolution: {integrity: sha512-A4rb55hI86Q9tBl/+jBj7TMz7iX2RFgQs/nExFzcAtoI/BFRVdaH5SL/MivrYD7qvweMpN8AgVvVMHV8UBYxew==} engines: {node: '>=0.8.0'} - '@azure/msal-node@5.4.0': - resolution: {integrity: sha512-6EZEParwHRlnSSIikw8FNAnAzwmh71uhveUXdPNFeZFviJ9SH+rwFiurhjzXqICYTrpm3E+dj693QOwfPbJXAQ==} + '@azure/msal-node@5.6.0': + resolution: {integrity: sha512-uFY9NxrWHw8PwZx7gAX6PDn+9vdfS05+levc/kwkx77IkjfaldnQbbcQzzDIZ5Hq5Zdr6/z92oAIoRWKp6MnOA==} engines: {node: '>=20'} '@babel/cli@8.0.4': @@ -1783,18 +1735,14 @@ packages: resolution: {integrity: sha512-5FgxM4dLQpMJHSiVATk8foW263dVHQHBVpXYiimNECVWG01f4nFyEbQixeT6Mwvg7TayREJ2gpKl3o2RoMdnqw==} engines: {node: ^22.18.0 || >=24.11.0} - '@babel/generator@7.29.7': - resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==} + '@babel/generator@7.29.8': + resolution: {integrity: sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==} engines: {node: '>=6.9.0'} '@babel/generator@8.0.0': resolution: {integrity: sha512-NT9NrVwJsbSV6Y2FSstWa71EETOnzrjkL5/wX3D2mYHtKM+qvqB1DvR4D0Setb/gDBsHzRICifwEWMO8CnTF6g==} engines: {node: ^22.18.0 || >=24.11.0} - '@babel/helper-annotate-as-pure@8.0.0': - resolution: {integrity: sha512-NSpMkMsvvZqzThJ0p1B02cbtA2ObEyfBvq950bmNkyxsxvcxwhvvCB036rKhlEnuBBo30bOrk13u3FzlKSoRrw==} - engines: {node: ^22.18.0 || >=24.11.0} - '@babel/helper-compilation-targets@7.29.7': resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} engines: {node: '>=6.9.0'} @@ -1825,22 +1773,6 @@ packages: resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==} engines: {node: '>=6.9.0'} - '@babel/helper-plugin-utils@8.0.1': - resolution: {integrity: sha512-3PKFgjTyPlhFhorfP+SjKQxLViIL++zWjFOO4hGriYU+Bsm983DxEM1JmDRJVWXV0O9npu+xXRqz7Pbd3mh70g==} - engines: {node: ^22.18.0 || >=24.11.0} - peerDependencies: - '@babel/core': ^8.0.0 - - '@babel/helper-remap-async-to-generator@8.0.1': - resolution: {integrity: sha512-baAKuLEMmu6BCSY3tuiU7qglM1qOZt6F1SrFScA241oNqksxkxfEZEKztlGRmoVns9AQ5UgArH7RsUEjxWnzgQ==} - engines: {node: ^22.18.0 || >=24.11.0} - peerDependencies: - '@babel/core': ^8.0.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.29.7': resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} engines: {node: '>=6.9.0'} @@ -1865,10 +1797,6 @@ packages: resolution: {integrity: sha512-U4Dybxh4WESWHt5XhBeExi4DrY0/DNK1aHpQbsrQXCUbFHuMweT0TpLEWKvaraV2Y6fS+ZXunsZ8zIuZIgvF2Q==} engines: {node: ^22.18.0 || >=24.11.0} - '@babel/helper-wrap-function@8.0.0': - resolution: {integrity: sha512-Qpm8+wi5xfDkBfollanwriCcKniFfBmMmaKB01GVM6VGzKXo1fdxosZp04qEr5HM+LKhwr3hG1yRy8+ORsficA==} - engines: {node: ^22.18.0 || >=24.11.0} - '@babel/helpers@7.29.7': resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==} engines: {node: '>=6.9.0'} @@ -1877,8 +1805,8 @@ packages: resolution: {integrity: sha512-wfbi91pM3py96oIiJEz7qIpyXDytgr9zQC1HEWwlGNVRAEmItuU/0a41ZUKu1sJGyhhOIpc4t5vk4PYzt8wpsg==} engines: {node: ^22.18.0 || >=24.11.0} - '@babel/parser@7.29.7': - resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==} + '@babel/parser@7.29.8': + resolution: {integrity: sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==} engines: {node: '>=6.0.0'} hasBin: true @@ -1978,12 +1906,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-async-generator-functions@8.0.1': - resolution: {integrity: sha512-kqnSMF1YHBzuiQrl68675i5Ma1oljvo+SJsNEZFZVBu5BUrVIZm9KId3ui2PdtLK2sv2zM8sJnjPDfgLxQlEqQ==} - engines: {node: ^22.18.0 || >=24.11.0} - peerDependencies: - '@babel/core': ^8.0.0 - '@babel/template@7.29.7': resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} engines: {node: '>=6.9.0'} @@ -1992,16 +1914,16 @@ packages: resolution: {integrity: sha512-eAD0QW/AlbamBbw0FeGiwasbCVPq5ncW0HNVyLP3B9czqLyh4gvw+5JTSNt6le9+ziAU7mqDZsKTHf3jTb4chQ==} engines: {node: ^22.18.0 || >=24.11.0} - '@babel/traverse@7.29.7': - resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==} + '@babel/traverse@7.29.8': + resolution: {integrity: sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==} engines: {node: '>=6.9.0'} '@babel/traverse@8.0.4': resolution: {integrity: sha512-bZnmqzGG8UZneG1lLxBoWIH0G6Gr1D846Yu4/3XnY6FhCndMR49u26nTY08u/dAxWmLWF9vGQOuC+84FfIUoeg==} engines: {node: ^22.18.0 || >=24.11.0} - '@babel/types@7.29.7': - resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} + '@babel/types@7.29.8': + resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} engines: {node: '>=6.9.0'} '@babel/types@8.0.4': @@ -2030,8 +1952,8 @@ packages: resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==} hasBin: true - '@cfworker/json-schema@4.1.1': - resolution: {integrity: sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==} + '@bufbuild/protobuf@2.14.1': + resolution: {integrity: sha512-agRJn3+EJDUe8AvxTx/LnHA/GErvLE62pSaSk7+MwFOtOv8eWBu/qCq2qoZjBjVZ3C2aiFJCveuSs17KMkYGOw==} '@chevrotain/types@11.1.2': resolution: {integrity: sha512-U+HFai5+zmJCkK86QsaJtoITlboZHBqrVketcO2ROv865xfCMSFpELQoz1GkX5GzME8pTa+3kbKrZHQtI0gdbw==} @@ -2039,8 +1961,8 @@ packages: '@codemirror/autocomplete@6.20.3': resolution: {integrity: sha512-tlosUqb+3BbxCxZdu4tKeRghPFC+QM7q4X5YhKV2eCmPG+1r2F3f4AaSz5sCrFqUtX4Jh20VFTKecl16MgiV9g==} - '@codemirror/commands@6.10.4': - resolution: {integrity: sha512-Ryk9y9T0FFVF0cUGhAknveAyUOl/A1qReTFi+qPKtOh2Z9F4AUBz3XOrYD4ZEgZirdugVzHvd/2/Wcwy5OliTg==} + '@codemirror/commands@6.11.0': + resolution: {integrity: sha512-/K4Rl5BN0OtTiPWmJCdqODu38XnDMsDxKY5rgrPnCkutPTJf2wVbkoixLfealF5Kwse/s8P8M5jAiURiwSwnFA==} '@codemirror/lang-angular@0.1.4': resolution: {integrity: sha512-oap+gsltb/fzdlTQWD6BFF4bSLKcDnlxDsLdePiJpCVNKWXSTAbiiQeYI3UmES+BLAdkmIC1WjyztC1pi/bX4g==} @@ -2048,8 +1970,8 @@ packages: '@codemirror/lang-css@6.3.1': resolution: {integrity: sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==} - '@codemirror/lang-html@6.4.11': - resolution: {integrity: sha512-9NsXp7Nwp891pQchI7gPdTwBuSuT3K65NGTHWHNJ55HjYcHLllr0rbIZNdOzas9ztc1EUVBlHou85FFZS4BNnw==} + '@codemirror/lang-html@6.4.12': + resolution: {integrity: sha512-pw2ReWKUqSkbvh76RAT4NYxiogRu+PWkR2ukAwO9uOgrm8uipkzjtKKtNpyeAQwHOqxEeSvAXZ6vr3AfyB9y/w==} '@codemirror/lang-javascript@6.2.5': resolution: {integrity: sha512-zD4e5mS+50htS7F+TYjBPsiIFGanfVqg4HyUz6WNFikgOPf2BgKlx+TQedI1w6n/IqRBVBbBWmGFdLB/7uxO4A==} @@ -2069,8 +1991,8 @@ packages: '@codemirror/state@6.7.1': resolution: {integrity: sha512-9QzNDgE4EYDnAHfrTlR2lwiPciiOymLtwKK+8yHQzCc7GXhAP9xdEbEJFy2IWB1j9UGUl9BsgMmTo/ImA02T7A==} - '@codemirror/view@6.43.6': - resolution: {integrity: sha512-EVunGSYN1wz1p75WY1s3Xg7t3i8Yol0kGZGizNdX9BUFgMFILYVe8/u6EVpo7Ff5PwbZuILb4QAq7IZoKzIEQA==} + '@codemirror/view@6.43.9': + resolution: {integrity: sha512-sTuUzTpPMFebRhg6dawChoKKgndIwfjmJgKVxBefPElcU2NwQ6AFroupk0SFqEerQyZOGRfDNnSN8Dw/lMAsXw==} '@colors/colors@1.5.0': resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} @@ -2092,20 +2014,20 @@ packages: conventional-commits-parser: optional: true - '@conventional-changelog/git-client@3.1.0': - resolution: {integrity: sha512-Tqa/gHco2WJWa740NRjOrfKVvzIqxkZpecb8bemaQ8sKM5PXb1UK4uTyTb/1wIqNuOVaDOFxyBdhTIQZn6gdjQ==} + '@conventional-changelog/git-client@3.1.2': + resolution: {integrity: sha512-jZqwnJwf7nboIlAcw/mkOjVa6DexCcUOgT2oOQgkoi3z9vR8tGFkcMy2BFcYwjhL9sYcDDXkRQDayiDieCoW7A==} engines: {node: '>=22'} peerDependencies: conventional-commits-filter: ^6.0.1 - conventional-commits-parser: ^7.0.1 + conventional-commits-parser: ^7.1.2 peerDependenciesMeta: conventional-commits-filter: optional: true conventional-commits-parser: optional: true - '@conventional-changelog/template@1.2.1': - resolution: {integrity: sha512-TzlTVpKPjaqW6qOYjQcYUDuGsLCNsvFHVBXkYGTAnf5V37jCWrE5haKNXzz0WZUtVHjrpV76L1buANjwXMfT8w==} + '@conventional-changelog/template@1.4.0': + resolution: {integrity: sha512-aalGyl7dbB5PArRebDIX43ZvBlXrYm9uWzGJ26t+4SzJVPsOuvfILGGbw5X4yX7i50YEmJ8zvbiWnqH/AAnZqg==} engines: {node: '>=22'} '@cspotcode/source-map-support@0.8.1': @@ -2116,8 +2038,8 @@ packages: resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} engines: {node: '>=18'} - '@csstools/color-helpers@6.1.0': - resolution: {integrity: sha512-064IFJdjTfUqnjpCVpMOdbr8FLQBhinbZj6yRv2An2E41O/pLEXqfFRWqGq/SxlE5PEUYTlvWsG2r8MswAVvkg==} + '@csstools/color-helpers@6.1.1': + resolution: {integrity: sha512-gLNsunvwf3mCi5u5o46/Z/JcJMnhbHSaZ69rkgPzNM3J4s8hWwpPUQB6/tt0EDFyCiWzxANlx+2LJwpYj4zS1w==} engines: {node: '>=20.19.0'} '@csstools/css-calc@2.1.4': @@ -2127,8 +2049,8 @@ packages: '@csstools/css-parser-algorithms': ^3.0.5 '@csstools/css-tokenizer': ^3.0.4 - '@csstools/css-calc@3.2.1': - resolution: {integrity: sha512-DtdHlgXh5ZkA43cwBcAm+huzgJiwx3ZTWVjBs94kwz2xKqSimDA3lBgCjphYgwgVUMWatSM0pDd8TILB1yrVVg==} + '@csstools/css-calc@3.3.0': + resolution: {integrity: sha512-c5ihYsPkdG6JCkU2zTMm4+k6r7RXuGxtWYhu5DHMIiF1FHzrfmHL5so11AoFpUv/tu61xfcmT4AmKoFfMPoqdQ==} engines: {node: '>=20.19.0'} peerDependencies: '@csstools/css-parser-algorithms': ^4.0.0 @@ -2141,8 +2063,8 @@ packages: '@csstools/css-parser-algorithms': ^3.0.5 '@csstools/css-tokenizer': ^3.0.4 - '@csstools/css-color-parser@4.1.9': - resolution: {integrity: sha512-paQcIaOO53Rk5+YrBaBjm/SgrV4INImjo2BT1DtQRYr+XeTRbeAYlS+jxXp9drqvKmtFnWRJKIalDLhZZDu42A==} + '@csstools/css-color-parser@4.2.1': + resolution: {integrity: sha512-YpAJZhaHplYQkG8ib+/Fx5Y0eF2lVWi3tIvMJA6i39TLyUNp2439cifzW8VMjhlqrBjHzK5hVGugRRm2zTKI/A==} engines: {node: '>=20.19.0'} peerDependencies: '@csstools/css-parser-algorithms': ^4.0.0 @@ -2160,8 +2082,8 @@ packages: peerDependencies: '@csstools/css-tokenizer': ^4.0.0 - '@csstools/css-syntax-patches-for-csstree@1.1.6': - resolution: {integrity: sha512-TcJCWFbXLPpJYq6z7bfOyjWYJDiDg2/I4gyUC9pqPNqHFRIey0EB0q0L5cSnQDfWJg8Jd6VadakxdIez/3zkqQ==} + '@csstools/css-syntax-patches-for-csstree@1.1.10': + resolution: {integrity: sha512-xBja6gaAaH2R2c7eNyl0TY4dhnnZ2uhj+KXpLdEQ6M/wuk9bYFZM8wY0ykw3VO4TgEJ56KGlerXS/9KBKVR/Cg==} peerDependencies: css-tree: ^3.2.1 peerDependenciesMeta: @@ -2200,173 +2122,164 @@ packages: '@emnapi/core@1.10.0': resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} - '@emnapi/core@1.11.1': - resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} - '@emnapi/runtime@1.10.0': resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} - '@emnapi/runtime@1.11.1': - resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} - '@emnapi/wasi-threads@1.2.1': resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} - '@emnapi/wasi-threads@1.2.2': - resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} - - '@esbuild/aix-ppc64@0.28.1': - resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==} + '@esbuild/aix-ppc64@0.28.2': + resolution: {integrity: sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.28.1': - resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==} + '@esbuild/android-arm64@0.28.2': + resolution: {integrity: sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.28.1': - resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==} + '@esbuild/android-arm@0.28.2': + resolution: {integrity: sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.28.1': - resolution: {integrity: sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==} + '@esbuild/android-x64@0.28.2': + resolution: {integrity: sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.28.1': - resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==} + '@esbuild/darwin-arm64@0.28.2': + resolution: {integrity: sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.28.1': - resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==} + '@esbuild/darwin-x64@0.28.2': + resolution: {integrity: sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.28.1': - resolution: {integrity: sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==} + '@esbuild/freebsd-arm64@0.28.2': + resolution: {integrity: sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.28.1': - resolution: {integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==} + '@esbuild/freebsd-x64@0.28.2': + resolution: {integrity: sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.28.1': - resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==} + '@esbuild/linux-arm64@0.28.2': + resolution: {integrity: sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.28.1': - resolution: {integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==} + '@esbuild/linux-arm@0.28.2': + resolution: {integrity: sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.28.1': - resolution: {integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==} + '@esbuild/linux-ia32@0.28.2': + resolution: {integrity: sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.28.1': - resolution: {integrity: sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==} + '@esbuild/linux-loong64@0.28.2': + resolution: {integrity: sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.28.1': - resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==} + '@esbuild/linux-mips64el@0.28.2': + resolution: {integrity: sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.28.1': - resolution: {integrity: sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==} + '@esbuild/linux-ppc64@0.28.2': + resolution: {integrity: sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.28.1': - resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==} + '@esbuild/linux-riscv64@0.28.2': + resolution: {integrity: sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.28.1': - resolution: {integrity: sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==} + '@esbuild/linux-s390x@0.28.2': + resolution: {integrity: sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.28.1': - resolution: {integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==} + '@esbuild/linux-x64@0.28.2': + resolution: {integrity: sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.28.1': - resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==} + '@esbuild/netbsd-arm64@0.28.2': + resolution: {integrity: sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.28.1': - resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==} + '@esbuild/netbsd-x64@0.28.2': + resolution: {integrity: sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.28.1': - resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==} + '@esbuild/openbsd-arm64@0.28.2': + resolution: {integrity: sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.28.1': - resolution: {integrity: sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==} + '@esbuild/openbsd-x64@0.28.2': + resolution: {integrity: sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.28.1': - resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==} + '@esbuild/openharmony-arm64@0.28.2': + resolution: {integrity: sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.28.1': - resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==} + '@esbuild/sunos-x64@0.28.2': + resolution: {integrity: sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.28.1': - resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==} + '@esbuild/win32-arm64@0.28.2': + resolution: {integrity: sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.28.1': - resolution: {integrity: sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==} + '@esbuild/win32-ia32@0.28.2': + resolution: {integrity: sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.28.1': - resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==} + '@esbuild/win32-x64@0.28.2': + resolution: {integrity: sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -2383,72 +2296,75 @@ packages: '@externs/nodejs@1.5.0': resolution: {integrity: sha512-2J+FRDjGfKKldTQ5YqLmhQ04/sA9swTQ6OTtPzo4xhg41u1+eiufciXiqW6u3UXEcmm413a27NakgnLbzfp0wQ==} - '@firebase/ai@2.13.1': - resolution: {integrity: sha512-RhT/VViTPBSplhQSuEp62HhLvfsV+LowMh8ZUo5MMRDzG7oFtSget4Kmg5oHP50hDVyWQuQj6to9iPFEZk08Tw==} + '@firebase/ai@2.15.0': + resolution: {integrity: sha512-Aj7TbFdAIWZdkX8JfdDStERpR35g6WNs+7XhNPtFLFOizUotj6k4N/D8HJkR45165HhnMJBe4hjOeeaxnnn56Q==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app': 0.x '@firebase/app-types': 0.x - '@firebase/analytics-compat@0.2.28': - resolution: {integrity: sha512-lIAlqUUbBu93FJMlQfslryQtBwwzdzvp23ePC6FNgymXk6Ook5v4Uvc0vdutvoIeqmyA3LfP0ZeRFK8+11kOOQ==} + '@firebase/analytics-compat@0.2.30': + resolution: {integrity: sha512-uVZEKlLaW4AHAhv8zoN9cTmveX6v86AVqcJ4LCaRCMTChTH8/NsjbisTq1lpBfWCLWS1spqwSHB4vol/YSCdMA==} peerDependencies: + '@firebase/app': 0.x '@firebase/app-compat': 0.x - '@firebase/analytics-types@0.8.4': - resolution: {integrity: sha512-zQ+XTgkwH6CY/eUSHJRP7e4LxM30RCxlCmob5sy2axs25GE3Ny0XdgpDscMTHHQIGqWkxPXad4w2Mw9sCgT8zQ==} + '@firebase/analytics-types@0.8.5': + resolution: {integrity: sha512-kdnooE7Bis2jEnsqcerRwn/UQpH5D3uvHpku7OdUM9TJN3omlu6iYtbyAQ6XkAJRgJtO0aNf9OOkW8J6D59oCA==} - '@firebase/analytics@0.10.22': - resolution: {integrity: sha512-8BSaq/QRGU1+xyi8L2PTLTJU7MH9aMA72RQdIxrbhWFauOZY9OXo8f2YDN/972xA8d588tlnNVEQ2Mo69pT9Ow==} + '@firebase/analytics@0.10.24': + resolution: {integrity: sha512-OfIAcIIwoqXjBzS+DnUQpOZ7i3ePaNFg83KPpDWjBZUKJmqMwzzAtLJqmKZOkQnW8im6vFR6f2I3M/9hxVd+QA==} peerDependencies: '@firebase/app': 0.x - '@firebase/app-check-compat@0.4.5': - resolution: {integrity: sha512-JI17mVcZs34zO6ZeSCrw4U2iohqy+n6GIzkbmsA+TbVjmvFLkUKt3bs5M+qRBteQm/0IWzqSHYFzEQLzDTQebg==} + '@firebase/app-check-compat@0.4.7': + resolution: {integrity: sha512-fBb/xSMyIKv1nDmccfzz3IAGBzx/cQOxmZai66rJzifb1hMMkztf824Xx7LhpTUe7HNUbXwY90IvJ66fi8q6yg==} engines: {node: '>=20.0.0'} peerDependencies: + '@firebase/app': 0.x '@firebase/app-compat': 0.x - '@firebase/app-check-interop-types@0.3.4': - resolution: {integrity: sha512-zz3i6e13B8BfWiLy8MABtTh8aGIACgKbf9UVnyHcWs+yQzJXgQcl8A46b0zfaiJHdQ+niF0ouAfcpuf+3LMPQg==} + '@firebase/app-check-interop-types@0.3.5': + resolution: {integrity: sha512-qId34pVZ2CXTmtu4ofW5leiI93DvnOvIcr/5GT7MZPw5WXAi6nZoU+g9cNRgl7K90UJSbK0cXxten4meYMPyZg==} - '@firebase/app-check-types@0.5.4': - resolution: {integrity: sha512-xV7JsIyzVr15aA7f3Pi0rB9gdBuVubs89FGA8VkRYA4g0l78poADgdfrScgf7NndSg9mm7cR7PJyY0+t22KaGw==} + '@firebase/app-check-types@0.5.5': + resolution: {integrity: sha512-+DF4gzFrlwGFyky38o4T/YN/r51l70yCtJ2HTkwmRj8FCMwPjm4hLH4fQbj6BUvzkiFqliBkitFsRpf1/YZkWA==} - '@firebase/app-check@0.12.0': - resolution: {integrity: sha512-wMeT6HLWRAuW7Cp/5UjWBGKgjPNxWNOoNf4PRIv0weljoGMZVeqbUY7wNBWTI2/31cX1NlXx8gQruDLsUShB3Q==} + '@firebase/app-check@0.13.1': + resolution: {integrity: sha512-l8y3dmnhodXks/APAwx4tWqRl3tk8b9874KF1FJyKg1DIU+kMD0l52iz7S9/MW+eK8k6cjJg0G0iJ5KQAsQpow==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app': 0.x - '@firebase/app-compat@0.5.15': - resolution: {integrity: sha512-HaiSM9TwbGIR4b7F6+UncHWlqdH89eeY7VUskaOGOlI2PxHS5Z+6hHsYGvNLy0SHDE6zyXO+3QSA6a4aqQxsqA==} + '@firebase/app-compat@0.5.17': + resolution: {integrity: sha512-5GdJWobqs6jbNYOnaQiSa4Ng8gnFerhqr7nY+v5jlnT7o9QbEeIZRLPQpnLe0TxYSWfRV2lAMbyR0kbXeIos9Q==} engines: {node: '>=20.0.0'} - '@firebase/app-types@0.9.5': - resolution: {integrity: sha512-YevqTjvo7Iujsa9Dwowmd6dSoElhzmD63ZSrq6bzjvQ6POjYgNjOFHLmNIgJs48eNO093NCERibuFnxbfOvU7A==} + '@firebase/app-types@0.9.6': + resolution: {integrity: sha512-yPLahy7Esfu2w/yme3msVK4xTkDXQqq6szfQn8yVOQpCKiT5GVFjqNpLbuz6NkX0WuTwUidkmPewW3r4xkvpeg==} - '@firebase/app@0.15.1': - resolution: {integrity: sha512-iD9+Z5HcPo0Uop5f72/VYMeXwKucBhW7iFrISkJFvQ+lSZikTNgTz0FgAtaaTkAG0pEZSnCymA2Fu49n0rcufQ==} + '@firebase/app@0.16.1': + resolution: {integrity: sha512-tjUEorFyKrurH7PbLWv9zDHRuU4mLefgD/yY38D584ziorIRlQz/PVjx4c/SCGyCuUlmyzt72mK+Lh+COAywNQ==} engines: {node: '>=20.0.0'} - '@firebase/auth-compat@0.6.8': - resolution: {integrity: sha512-llcBREUC4iSNKZ6rvwud7Oz9Q7aAWU6KuQLa6pdu7Q+QAQsy4JLw6yFgxwtmzabsgznHmmcsX2UjHLLzqUxi3Q==} + '@firebase/auth-compat@0.6.10': + resolution: {integrity: sha512-Bvklg2nL7BrBFCAqdsleW8fse9Jh0fARqJPlJmA40uermfWx1bJiO7dnKyZN3J39d2TFVd4VJXtg3i6Wg92/YQ==} engines: {node: '>=20.0.0'} peerDependencies: + '@firebase/app': 0.x '@firebase/app-compat': 0.x - '@firebase/auth-interop-types@0.2.5': - resolution: {integrity: sha512-1Li/YuBDBAXcKv7BzY4U28gontUmAaw53sYiqbaVOMCFb2lFKK/c3CGMUWqtwe7+TXrl3poWnTCL5umYBg85Eg==} + '@firebase/auth-interop-types@0.2.6': + resolution: {integrity: sha512-FgwZqDrBqgK0BHI70QTv1v/5wmuDF9f8fsJFvKSxoRlK2PPfSQtZAk2jhXu4pe9BZzFi/e4UYusU/bEQHdf6Qg==} - '@firebase/auth-types@0.13.1': - resolution: {integrity: sha512-0c1Mnid0uMDfGJHeUS4zfvBa4/CedJXotGy/n/NZJnBjwiJawt0ZYU+wH2VAVLiRCEfG2ncCkAX3yd1/2nrB7g==} + '@firebase/auth-types@0.13.2': + resolution: {integrity: sha512-OU+miuoSxIWYN7GT291d2ylVJBL3k/OePo7/JDSoQtkFQoEiGBc4AHuMjj/seqFIsHrqnjrAfRCk4pfufoJolQ==} peerDependencies: '@firebase/app-types': 0.x '@firebase/util': 1.x - '@firebase/auth@1.13.3': - resolution: {integrity: sha512-bqiq4uubDN2YyQkdvSWPQeJyXAv2O76ImF41En9b6UhV5JuBVYDoHYrrrE3NzIuGkpFMKagfhMRP4Vz6t+yQSQ==} + '@firebase/auth@1.13.5': + resolution: {integrity: sha512-1AXoBJqBVD8WL8FZYo3S2GmJF9YUoom6Y6ngMxOSkzzhW5sT83pLchb6TGFgxes91dfXx8s/VYc5VrLDNqpLog==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app': 0.x @@ -2457,164 +2373,179 @@ packages: '@react-native-async-storage/async-storage': optional: true - '@firebase/component@0.7.3': - resolution: {integrity: sha512-wFofIaa2879ogD/WvkjYXJxRmfnL0scen6ORgaC3na1FNOR9ASIUANQdhqQcmWu/h77/pVHY7ch5flewa5Bcew==} + '@firebase/component@0.7.5': + resolution: {integrity: sha512-vuFDcL91Q+2ZuBJkyOh86T4q0B4ffNTDjc/A38tybO56odQABxRTFLTIowCWqAKeIcgo37GowWMVgFF73gD8Qw==} engines: {node: '>=20.0.0'} - '@firebase/data-connect@0.7.1': - resolution: {integrity: sha512-2LbUU8mmSA63HknxQMmWHjpzuNLBKflvVwQc2tpoVKg0biWleNEJX031ELks0vzFs+dDjOUkCJR72RP6mQHFOg==} + '@firebase/data-connect@0.7.4': + resolution: {integrity: sha512-su1aGWlzhxb+xtggCUSsufJn1FDa06SBDK71y+fpQ+g2zMhMExik6FUv/odkKzOF/xfWVjabCbWBcjJY3MceDA==} peerDependencies: '@firebase/app': 0.x - '@firebase/database-compat@2.1.4': - resolution: {integrity: sha512-3pK35F1MAgmqFJQlf2nhQl44vtAXQO1uaCaQOEUI9kCRtLFqi7N+QRKR7lFZPg+xIZIyubgxQaxY69YgfZRZWg==} + '@firebase/database-compat@2.1.7': + resolution: {integrity: sha512-lBq9sJm8MnJINKJnkAKSOj2MbC66xGoSVCcGkPtstl+lkoKEBtD46qHLbuDgW/WbLPoKVm17RIN8BxHj+Z2F2w==} engines: {node: '>=20.0.0'} + peerDependencies: + '@firebase/app': 0.x + '@firebase/app-compat': 0.x + peerDependenciesMeta: + '@firebase/app': + optional: true + '@firebase/app-compat': + optional: true - '@firebase/database-types@1.0.20': - resolution: {integrity: sha512-kegbOk/w8iU64pr0q6k2ItyNGjnQBMHFhwS7ohdWI4W+pc0/zhhdGXTdFj6X1oxItRjPoYOsSQmERgBkn/ihxw==} + '@firebase/database-types@1.0.22': + resolution: {integrity: sha512-YAZNXsjY9EQQ+pKw/3ax8n5FgolHC7Qew7EY5RceYdl0R2ZP+kCv1O0DkKlcceue8uQCOreHCNN7PWVFpY1Nug==} - '@firebase/database@1.1.3': - resolution: {integrity: sha512-XwWCa+E4TvNGpGwXrycLRNfdogADwFcvuhyow6wDWma9W54roaQIhe+4PM0KiLsIftBdSCGI7OKCXrdSRHbIhw==} + '@firebase/database@1.1.5': + resolution: {integrity: sha512-/JGpvszLoNXNgzilRXocigGfFF4hbcPA9wN1i1kjJx6oKkXgkHteZYl3lQs1lJX3ETDf6bv7zI15lPMVUp4sAQ==} engines: {node: '>=20.0.0'} - '@firebase/firestore-compat@0.4.11': - resolution: {integrity: sha512-W7o1WdwWq5aABK5Up2ncSvTQs/QGLR/fy7cVpFBNqhsXtxoMtflHf2xBIG6+aoptcuGAobddq4g2Sq27wqHaYw==} + '@firebase/firestore-compat@0.4.13': + resolution: {integrity: sha512-l9dCewxMzzLOIhcwTjERCKxrWOn1kZ9JvwOQq9zZNq4I/Nbvb/B9njT230V61uvQ9qZ3/qpUG758D8DDTEFXnw==} engines: {node: '>=20.0.0'} peerDependencies: + '@firebase/app': 0.x '@firebase/app-compat': 0.x - '@firebase/firestore-types@3.0.4': - resolution: {integrity: sha512-jGn+JSS4X9zZsrfu7Yw66v5YRdOLD1oyQh4USR0xWl4CUqV/DA6bNIXRPpxH/cUl3iVTNiP6MN7g+EL42A4qfA==} + '@firebase/firestore-types@3.0.5': + resolution: {integrity: sha512-dbdMAQkMd5dwWc48eupz/Y6/E9ruat3+gY5lhVKscvvT/HnDBEEMzJW38zdKhgdnglZHGk2vUsJMOHAphMHGMA==} peerDependencies: '@firebase/app-types': 0.x '@firebase/util': 1.x - '@firebase/firestore@4.16.0': - resolution: {integrity: sha512-qdHMHMvMr0nRMuZyWNR/ArWa0YlPE3C4eAbmxTASJMYXAesKPL0Y54p70moggrNPzaK7MSIIq5RDJJyntQyIYA==} + '@firebase/firestore@4.17.1': + resolution: {integrity: sha512-8lqPNf2w10CtYG+tayVjZO1pSyQpnhztQRudeD109VtXDzNbASTaYdO43sj5PMsDcWq0aOYY3RmJOUlXu9++jw==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app': 0.x - '@firebase/functions-compat@0.4.5': - resolution: {integrity: sha512-10qlUXGY25G5/1g9UihqksPp2po+ZqSE7LEizsrdUP7vrTmkysXxGSZCDyojSEp6mQe/ecRDdDDI+z4XRdb4wQ==} + '@firebase/functions-compat@0.5.0': + resolution: {integrity: sha512-T3BDIToESZUHt7438wyKYMkRjKg3m1xAIux5fVpNvTRQlDOFLukWniQWBDhJ2znpU9kxMTR6+e31TVo8P15PZw==} engines: {node: '>=20.0.0'} peerDependencies: + '@firebase/app': 0.x '@firebase/app-compat': 0.x - '@firebase/functions-types@0.6.4': - resolution: {integrity: sha512-zV6kgqtduR4rUAdC/ilS7kmb93XD7bEZoJDlVBZqlOw2uGGGCNBQBuleww2rr0Ulr3L9o2TDjumEt68/l1f9DQ==} + '@firebase/functions-types@0.6.5': + resolution: {integrity: sha512-Zc0pURjthHXzSj54ZivCkzKDSV1r/wIpnmHdhq82q2yFFPVoncG/ZJjnVMiANvQfeww/QnElhzODpfwUucVwdA==} - '@firebase/functions@0.13.5': - resolution: {integrity: sha512-bWCx713f4kE/uFV7gdFOLBS7lDoiZj48MRkbAqe35gkXcCeWF4QjRNO07Jhmve7EJIoQOBczL29y2r8VRuN1kw==} + '@firebase/functions@0.14.0': + resolution: {integrity: sha512-DhuYFr0eMhp+s/PNEk6SiMsYkc00+XVOUeKbrl8MOzQNZI3SKQpqoDR1d+keNDAutwmHRWTUAdXBoVPD+xxVUw==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app': 0.x - '@firebase/installations-compat@0.2.22': - resolution: {integrity: sha512-C/zpAuTP5S9OgKSPvXRupw3hoY/JZSlA1wFjD/Sb7LIQE0FNbcMdO8Y4KXVEkjVzma/DDDDIAzxEXqKMAzc88w==} + '@firebase/installations-compat@0.2.24': + resolution: {integrity: sha512-8M5nlcWwYt881x83COP2odq5vgf+NgwJh+RMd4LRSv8JI1pxwDfgrDJOERrjTgfC9J5Z0vnQX4b1pdN914e0Zw==} peerDependencies: + '@firebase/app': 0.x '@firebase/app-compat': 0.x - '@firebase/installations-types@0.5.4': - resolution: {integrity: sha512-U2eFapdHwjb43Vx9o+Pmj4dFfvcHEK1IirEFLqMtWrTHvmdrS3gBpBD1kmJk/9HjsOtoHZxJ2Paoe79e+L1ZPg==} + '@firebase/installations-types@0.5.5': + resolution: {integrity: sha512-e9UYcju3puDl1vdrcKIi5dExzHLameOT/Tc61Q48PYwxtsM1NzZh/ikGbdBQTsbRgg0EMZqdPr0/m5ODUBobrg==} peerDependencies: '@firebase/app-types': 0.x - '@firebase/installations@0.6.22': - resolution: {integrity: sha512-ef6nn3GGQTdReCfotRMG77PJZu8CqEbiK5pEoBnM0gTu/Z9v0i/az2p3HABsa/1beQmmyh1OsOjf7P5+pgwdZw==} + '@firebase/installations@0.6.24': + resolution: {integrity: sha512-Ui52ey8wHoWqkBbXRKJEKYWylI0JZogZmoLS+o8Anh1bxWtK27ZYjLla1UJAAdC5DCKLJ2qAp0VpJOjg8VOX1g==} peerDependencies: '@firebase/app': 0.x - '@firebase/logger@0.5.1': - resolution: {integrity: sha512-vZKLsqE1ABOy8OjQiE7cUTFn4gvaqlk88yp8N94Pk/sDpq61YqZGqmVFZTvOyflTwuYFcWirBdYGoJgbDaXKYQ==} + '@firebase/logger@0.5.2': + resolution: {integrity: sha512-J2VO4NFTc0xQFrxV1B/lm5balicm9cwuX2acR9Yn41fN8KgUeQFo+VJV222IqW2FPSXKDu9uo5WdQFWf9TPbYg==} engines: {node: '>=20.0.0'} - '@firebase/messaging-compat@0.2.27': - resolution: {integrity: sha512-JNOiu1PPgdHzEPEtoFiNxQuu0x9bm4bfETSQCpGfcTlgWkhlSK7uh7nlsjC10TQLUNgYetLmuutaYTh8aeYLVA==} + '@firebase/messaging-compat@0.2.29': + resolution: {integrity: sha512-8Twe4CeYvAx8AzjBxyyQFKzinaMGGt13hPQBqaARQ2QZjagrEaqSVBe+Zy6F4L/vT8DV168yRgRu7W/RK7p+4w==} peerDependencies: + '@firebase/app': 0.x '@firebase/app-compat': 0.x - '@firebase/messaging-interop-types@0.2.5': - resolution: {integrity: sha512-tUEKnaAP2Y/MNIqgnriPpV6e5l13Vs/+p2yrd6NGlncPJT9O3a8muYZtdnWe+IJ4fgKLHJVC79n/asxk/N5Msw==} + '@firebase/messaging-interop-types@0.2.6': + resolution: {integrity: sha512-MVzvkKe2V4H2dHu5oOxRfeKQcfTwWmCgnzsC4V1q3ixun5iiL8riCZ2qI35rDhCL4glPGiu0jHxDbpVNuTKfow==} - '@firebase/messaging@0.13.0': - resolution: {integrity: sha512-GZoo0uGRvEbszo83xcgbjJp4FpkmBEr4l8Z4hi8gl+P1Spn/MTK3HapanMzSX4yUHuTEiF5hasWRxOaz+o5sxQ==} + '@firebase/messaging@0.13.2': + resolution: {integrity: sha512-KcZoqUu2ih4sLH91dW9tmyHjCR0IQyNzSLZunX5uq7cLeImXb4uO2I0wq5FACduO2I+FoTeWa2BtUv7Jpowqdw==} peerDependencies: '@firebase/app': 0.x - '@firebase/performance-compat@0.2.25': - resolution: {integrity: sha512-q6NjTXpIPoFuUmCmMN/maCdTgzT6aExs9xZo+PxfVLj6uLVGvpyAD6XWjmcrb7jChsFBYbq7E5dyNDF7Zhy9kA==} + '@firebase/performance-compat@0.2.27': + resolution: {integrity: sha512-O/ozTf/EbChN94Pk7bd1eUC0PAC36726AwsaiJyC0bZzSBWfLGSWASGPH5pebUWXQPJtGxIJYRkkbX5l0Qa+Hw==} peerDependencies: + '@firebase/app': 0.x '@firebase/app-compat': 0.x - '@firebase/performance-types@0.2.4': - resolution: {integrity: sha512-kJSEk7b0uhpcPRyL4SQ/GPujLqk52XNKcXlnsKDbWGAb9vugcLvOU3u6zfEdwd+d8hWJb5S5ZizV1JFFI0nkKg==} + '@firebase/performance-types@0.2.5': + resolution: {integrity: sha512-PRzOgB+/M+6AKlEkY8a9xy5Ff5SfZPIh4iShXhn2WAcL/euSbK7bdLqWysHduunNJhGFsXa22Ag3ixqL6rQtYg==} - '@firebase/performance@0.7.12': - resolution: {integrity: sha512-fe7nV8teUU3OBHlMUZ9Lw4gLhCW2k4m5Uc3pfWGV+fl8uwJQBGp9Q3lqsJ+HSrFu3Q2pJyLAgrClPGSKyDeYgQ==} + '@firebase/performance@0.7.14': + resolution: {integrity: sha512-9PH1XEZVHErxGdbXluvGz4Uyjw4W955H8v7Mv9rHIybRrg5F2Ac2tvf5+mSf5EtnxWNmxrD2WLnvMFaZP4sMrQ==} peerDependencies: '@firebase/app': 0.x - '@firebase/remote-config-compat@0.2.27': - resolution: {integrity: sha512-FYwYWwSbUdza/pRX4NpSBm/Pimntum3jEIBpnDn5Ey1jHNWgjxrE8Z5SB4mCHd5wGCoYd3koJzxARl/VWIEx0Q==} + '@firebase/remote-config-compat@0.2.29': + resolution: {integrity: sha512-mY7JtTISK6F4g4T0x3kVepr5cp0NXL7f5yjIUXXGaTrg4qUlFBWRbENaHaqZ78dwmNcLm24h/yPsOVRlDXEXhA==} peerDependencies: + '@firebase/app': 0.x '@firebase/app-compat': 0.x - '@firebase/remote-config-types@0.5.1': - resolution: {integrity: sha512-cX/1LT6KQwkXzck2eSzeKnuvXZCyr8qaPpDcikoJs7jmI+oBOXixpDLeDtWj1U6GNMkIoXrEDNoyT2Ypcyp5/A==} + '@firebase/remote-config-types@0.5.2': + resolution: {integrity: sha512-i8k1omVfoAnaT1ZPv2FFjxMZrATYsO/GnFgHEj5+7fAJLzi8wLnGGv1WK06oEAD6ltrWXSO1HzeNyajn/NjMWw==} - '@firebase/remote-config@0.9.0': - resolution: {integrity: sha512-aNn6/eJhsSC+gXSToiXiYPv3ypLP9lFtzl+/q9kSOBPB7D6rae0Rt2uENZZLXGYbEgHYKQblOhijJAXGbbJjtQ==} + '@firebase/remote-config@0.9.2': + resolution: {integrity: sha512-Rii93DkXjM+RE/ytHdYa7EIiQLJbdBr+W8EEiqd/vbLCOC+1FdkDuRiumJBp6t3yewHGbdqbpjB3fk3z0cZ+8g==} peerDependencies: '@firebase/app': 0.x - '@firebase/storage-compat@0.4.3': - resolution: {integrity: sha512-gruVqjtUGX8tEoeNbaWXZm0Zfcfcb7fvmDmBxV8yPAbWvExRnZYLO2+qw9idxNE7BvPXt5csyjSYHy//dAizxw==} + '@firebase/storage-compat@0.4.5': + resolution: {integrity: sha512-vO0tFPxXbKDKdlTu8tYT08S9t9ezUTJYEdLCULpWxWq2aq6zojwN1QmAB+1a50AI/g47GlWUJn1XPncm/PDZsw==} engines: {node: '>=20.0.0'} peerDependencies: + '@firebase/app': 0.x '@firebase/app-compat': 0.x - '@firebase/storage-types@0.8.4': - resolution: {integrity: sha512-BT7cwxJOx8SWwlQfrlC+bD/Sk3Cw+1odCi8UZNFNWTVZoPsBnA5W+mqtZzVnvsdJpXCFGSGQ7R7vOR6dtM/BRA==} + '@firebase/storage-types@0.8.5': + resolution: {integrity: sha512-GEDs5P+rNUfNcS+wxIdOLAHficife2YXtvTJnyi3ssrX11AAtBg+nDUdbYh8vuBzWehVQZPmztGUUnud4L+4yg==} peerDependencies: '@firebase/app-types': 0.x '@firebase/util': 1.x - '@firebase/storage@0.14.3': - resolution: {integrity: sha512-YX4/YL6P6/fufSSeGnVhjWddcIXbFq2cWIhMKFTZo1E/Rtcl2mJj/BYUQTwJfcE1Tl8un1FOya4L05jcSLN/Eg==} + '@firebase/storage@0.14.5': + resolution: {integrity: sha512-r2tozN/BlEewLi70tJNUQPzWwbex9GM7NgXZsamHKQrjKEfcR0i4jGgHBKAKA4hbwiPE9eNMb3hcxWnDpeJZwg==} engines: {node: '>=20.0.0'} peerDependencies: '@firebase/app': 0.x - '@firebase/util@1.15.1': - resolution: {integrity: sha512-LUdM4Wg7YM9Pq/49nGYySJA0CSQEKnGffFzWV8+6gXN7mGxn+FL1IqvFbuZUtAQcfZgHYDwCE1wwlK7rB7gl2g==} + '@firebase/util@1.15.3': + resolution: {integrity: sha512-c/z/gaIlaaLZEuGbE6sLUuJ61tskg1JghvhcNQzW948ASBinbVBBRnZTC4b4yt4LaEtJQkYlyzqLHcutFwEIvA==} engines: {node: '>=20.0.0'} - '@firebase/webchannel-wrapper@1.0.6': - resolution: {integrity: sha512-Vr/Mqu79dMwGRAyGbJ4uN4+BtXB3/mRTdzetD1daWNeG8QaWuzhhbG77GltO5c0yYmYls8i250iX73624GJd7Q==} + '@firebase/webchannel-wrapper@1.0.7': + resolution: {integrity: sha512-phBFwieDLvkZGYN9CE9ZFNEIoBVksprzsnCzQejCmCHtgwCXReeuRpoEGN9C4EbhONztv8NRV1tau6Rb9pONwQ==} - '@google-cloud/cloud-sql-connector@1.11.2': - resolution: {integrity: sha512-ImHGgHunHoAHnQ9Bbsuq9an0rwmMdaPL8nrdQkVNnuIb0GKE+rTyjKNV+po7DJLuk84JPUUbK0cWW9AjPiAblA==} + '@google-cloud/cloud-sql-connector@1.11.3': + resolution: {integrity: sha512-dPnHkcabbH5LAksAQl99SJpC0HuG3YZwjcdcOxdz2QW58vOnGdfQ96d/Hpzl22h3eA03rKG0kMpEplC40xWtTQ==} engines: {node: '>=22'} - '@google-cloud/common@6.0.1': - resolution: {integrity: sha512-1uvKzbmAWUdchIYRsg0f4rUmezOamWuVBSWAPAhnYoUE5OiPEx6v6JOxFIdr3MsrqV+6fyLV3EI1vMPlHoeRvw==} + '@google-cloud/common@6.1.0': + resolution: {integrity: sha512-Ohjxjvusr65+SiEVBrilpyn1ir9CM8ZqWjcf7bA8ph1GCunxI6bbwtcl7iGl67A7Lr4Nz7WpNzITNETwggc7pw==} engines: {node: '>=18'} - '@google-cloud/paginator@6.0.2': - resolution: {integrity: sha512-S60tHt4oHsVvviXY5+Ti5Reg69y5WjBglwRjJqBiVdRHxniW/L+Mc3mp7yNMcxr2Gi6DkDO4aIognNWcUxf3Vg==} + '@google-cloud/paginator@6.1.0': + resolution: {integrity: sha512-9bxQ/QNhcq5c6ra75khWjA5Q9UHWp0vQnhwesmqPpLLF5PxmxCIsadIA5ssLxKted4/iZ2RlRPkW/E8p68W8cg==} engines: {node: '>=18'} - '@google-cloud/precise-date@5.1.0': - resolution: {integrity: sha512-Z9RVpJUZR+aMF9gPel07xbLURjdT+G4HV6x7jJhreNarQGcT/ZYn1IIfo55rd+tncGvJ4qZDfZnaF6PzqgsQkw==} + '@google-cloud/precise-date@5.2.0': + resolution: {integrity: sha512-ckZ1elVT/JXbO4kxltiT8tumYnTXGIY7OFrDMAJyVWAte/rUYiCuH1YbaKLQrZpYDp522xgTfPqqW/VxfXFdgA==} engines: {node: '>=18'} '@google-cloud/projectify@4.0.0': resolution: {integrity: sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==} engines: {node: '>=14.0.0'} - '@google-cloud/projectify@5.1.0': - resolution: {integrity: sha512-61RXiUnoPBjeIXTzG+WgGLdJlnE3lS7p63rbePw0CEC0tjMGpODKHEr8vFUmuD+iEl7sUWYKbu/ZTk/N2dXw6w==} + '@google-cloud/projectify@5.2.0': + resolution: {integrity: sha512-u4lTO+UI9bwyd/qaVkhVpp57jVH0Pc7wkHE0snZkpQyoKheHDJwmfStao8cWXSF03DmrQltLLSoDjM2CGBpFJA==} engines: {node: '>=18'} '@google-cloud/promisify@4.1.0': @@ -2633,8 +2564,8 @@ packages: resolution: {integrity: sha512-IJn+8A3QZJfe7FUtWqHVNo3xJs7KFpurCWGWCiCz3oEh+BkRymKZ1QxfAbU2yGMDzTytLGQ2IV6T2r3cuo75/w==} engines: {node: '>=18'} - '@google/genai@2.12.0': - resolution: {integrity: sha512-LUr972DZosqPUhf9Mb3CIVu/B99woD3QW6ZJV1T9aNgxaoimAZARmo+IyyDsxIL+zouFiYSdA4hzfEWXc9oNIQ==} + '@google/genai@2.20.0': + resolution: {integrity: sha512-kFEzARfA064oCNAmYTyOaAeJ9KSkbZ2Upxz36oO5eVNlcxAXsixLlGbwY1oy+Ab8HJ6nMWMD9hg+NdIron6wJw==} engines: {node: '>=20.0.0'} peerDependencies: '@modelcontextprotocol/sdk': ^1.25.2 @@ -2675,9 +2606,9 @@ packages: '@harperfast/extended-iterable@1.0.3': resolution: {integrity: sha512-sSAYhQca3rDWtQUHSAPeO7axFIUJOI6hn1gjRC5APVE1a90tuyT8f5WIgRsFhhWA7htNkju2veB9eWL6YHi/Lw==} - '@hono/node-server@1.19.14': - resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==} - engines: {node: '>=18.14.1'} + '@hono/node-server@2.1.1': + resolution: {integrity: sha512-ELuehkj5VCBdgEw9zs+ivkKwyzzUCSQuE96YmiPvn1ECBoZCczbFXJLeEGMTYjphP6gydh4pHMqEYPVMYUVgQg==} + engines: {node: '>=20'} peerDependencies: hono: ^4 @@ -2699,6 +2630,10 @@ packages: resolution: {integrity: sha512-3eTuUO1vH2cZm2ZKHeQxnOqlTi9EfZDGgIe3BL3I4u+rJHocr9Fz86M4fjYABPvFnQG/gGK551HqDiIcETwU6Q==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + '@inquirer/ansi@2.0.8': + resolution: {integrity: sha512-WpQM+Ti6Z40EFwwt+uL2p4UabT+W179zHp6HhLVOzfbwnVn05IPO/eXIZXGNqcT1jbQ15SujNLzQ39k4QPPxBQ==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + '@inquirer/checkbox@4.3.2': resolution: {integrity: sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==} engines: {node: '>=18'} @@ -2708,8 +2643,17 @@ packages: '@types/node': optional: true - '@inquirer/checkbox@5.2.1': - resolution: {integrity: sha512-b6xmA/VlTe0ZgDQHDui+Nav470u7u49nRd8/iuhOcQPO9Ch7lGuogydhi2VOmNlZ+zXcM8IcPuNSwQcdJaF/kw==} + '@inquirer/checkbox@5.2.3': + resolution: {integrity: sha512-XEYX2WA8SBkLPczL6/yXPHLPCvDoptmh9v56Cy05BSV1Smk1vWy19bTC4qJBuIffw7+6l4CcaYYzGqG60RfW1g==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/checkbox@5.2.5': + resolution: {integrity: sha512-bRt8J8m+Fot9CXv+zNQGXUq2ET0MggR1fPz7v6edN6MFYmsbfGnMmkmWZJEegMKqrAC8ej/o1sqisHZXZJMAfQ==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2726,8 +2670,17 @@ packages: '@types/node': optional: true - '@inquirer/confirm@6.1.1': - resolution: {integrity: sha512-eb8DBZcz/2qHWQda4rk2JiQk5h9QV/cVHi1yjt0f69WFZMRFn0sJTye3EAP8icut8UDMjQPsaH5KbcOogefrFQ==} + '@inquirer/confirm@6.3.0': + resolution: {integrity: sha512-pZHXJImFtERmSNMBHcjwuz8Ck5vEFEYNUZnwbb8aJpjHv/TwGuFErNxF2Hp8+V+pNJs2EYPMlyWscvFEqO9jOQ==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/confirm@6.3.2': + resolution: {integrity: sha512-Xvr/0HggjddPtGppuqVmxhTw+Hr8PvsZ/k0HmOEaAqQEt80OITNkFWnsdNmyT0/eM4Ab+iJLx2R8rctlEyfSVg==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2744,8 +2697,17 @@ packages: '@types/node': optional: true - '@inquirer/core@11.2.1': - resolution: {integrity: sha512-Qd6GJT1yVyrZZCfN8W2qKF5ApmqryXRhRKCuip8h01x2w/esJQ2XIYc6f9abMIHgKQdBfFTSOdbHRLAhuM09UA==} + '@inquirer/core@12.0.1': + resolution: {integrity: sha512-JMD5Jy/ScL5TZE18m83Nw25HjqGFLoWXwnEkW7IdwwAhZpB9Bus55/WU7zn3UqR1MOCjjTQOIYpiD4vjWA3LPw==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/core@12.0.3': + resolution: {integrity: sha512-wsSy0sznmXwkty+2PzZwx00Cazc/E0r0B7mAzdGROz2Ct+DFZXaK7WDjGZvgjRldxH5ZhFVfF2lgkYrqgOw2KA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2762,8 +2724,17 @@ packages: '@types/node': optional: true - '@inquirer/editor@5.2.2': - resolution: {integrity: sha512-ZRVd/oD+sYsUd5zVm0NflqEzlqfYCyHNsqkHl2oWXEUHs12tCbcSFi+wVFEvD8+LGRaMUsVrE7qeo6lSG/S1Vg==} + '@inquirer/editor@5.3.1': + resolution: {integrity: sha512-y43COoyVUjPWIobn2Qep/uI1drPS78aaZZZ9kVi94Tyu/GuW2N8d8Q4rifJXGAXCEAXCPTTMjD8gC1HyvM5ukA==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/editor@5.3.3': + resolution: {integrity: sha512-YsKkS2q63IiLtaDK/9nqzdComN97SDQrmKiyNggN+ceP4ty+Z6VwyTz3FpjeUWeW1Efss2xHFKCC9sx7hnrsxg==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2780,8 +2751,17 @@ packages: '@types/node': optional: true - '@inquirer/expand@5.1.1': - resolution: {integrity: sha512-YmQpenjbFSHAK3sOd44puHh3V1KXXr+JiNpUztoSQ4drLh2rTVzTap/YtlAVu/5xavifIlBfNEzJ/neZJ1a/1g==} + '@inquirer/expand@5.1.3': + resolution: {integrity: sha512-3NQJiXNJ/aj9wiAsr7pECdp5Qe9J0X9YUJCKsaFXS+ddOxfL6J4AIl3w3T4Gq3kK0WsQY5GMoDokK5X94m6lHw==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/expand@5.1.5': + resolution: {integrity: sha512-uHuXLmXW+TtIfT/9vSBotypAkqn1n34Ul+CLGPos/xANyO4Ff5xZzkYhbKR4NEcfVK4a9mHQOpwVZzluSHFRGw==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2798,8 +2778,17 @@ packages: '@types/node': optional: true - '@inquirer/external-editor@3.0.3': - resolution: {integrity: sha512-6thf5I8q7lZwzGLAxPaaGEREEkZ3nyePPDQ1oyobblxmEE8mqTLguScP7pDjUTAibiyb4hfXl+qjUEJ+di/aNA==} + '@inquirer/external-editor@3.0.4': + resolution: {integrity: sha512-tZbbaK2ovq6vlrRBNQvjrypmrED/p5x2ncIHQ79cD55tei3dD96v5glMMA+6tiq7K104i/25DVYKWVPJuV6ptA==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/external-editor@3.0.5': + resolution: {integrity: sha512-f3QQJRIX5ZEneBHNUIuPjmbdzHnmRFJA8r2dkcb8q+OM5Uv5KtnuAttQumnrjcBVBM3mcTX1CkmtAkU58VRZxg==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2811,8 +2800,12 @@ packages: resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==} engines: {node: '>=18'} - '@inquirer/figures@2.0.7': - resolution: {integrity: sha512-aJ8TBPOGB6f/2qziPfElISTCEd5XOYTFckA2SGjhNmiKzfK/u4ot3v0DUzGVdUnKjN10EqnnEPck36BkyfLnJw==} + '@inquirer/figures@2.0.8': + resolution: {integrity: sha512-tApbon79GM9ry56ja/Ud3SY2CL4TQsao9fIwDQbgTeNY55025GdMzQ2+UdegV/lx51VNGUB59M0v0nMpybYY4Q==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + + '@inquirer/figures@2.0.9': + resolution: {integrity: sha512-EAWgUTGQ/Umgga51dE3B2PUHbufuXarDfg86uVgoSgNHNNQnyFKcOrQLWVqYMghuSyHh8+2HUH0Js9cTC1WAdg==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} '@inquirer/input@4.3.1': @@ -2824,8 +2817,17 @@ packages: '@types/node': optional: true - '@inquirer/input@5.1.2': - resolution: {integrity: sha512-9K/DDBSQpOyZSkt6sOVP9Vo0TR7atX2kuILsUu0x3wVcVbe97lJwIJKMLdMw25tDYuXl/qp6erT0Xs1rfmcfZg==} + '@inquirer/input@5.1.4': + resolution: {integrity: sha512-3xQkQrOvgOzpSN2ciTVdRDlg1FWMCA8l+0KfB6SNlILoTCGzJTzO/gc0Rwjcb3usuGyKdaGtI6OiyMdeMeLWkg==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/input@5.1.6': + resolution: {integrity: sha512-HtcJhB2QFVXbLuJ5S3syhNbTUVxYvwqV4VRBDkQceBloC9bmTViUoRFP5PbSaDZb3HzfPmpuU/gG4ybVBz4FHA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2842,8 +2844,17 @@ packages: '@types/node': optional: true - '@inquirer/number@4.1.1': - resolution: {integrity: sha512-XF4IXAbPnGPgw0wsbC/i2tPcyfdZgDpUlhsqU0SfT4IRIGWha6Xm9VRgN5yYxJq+jnyXlfXI/nQ3ulfk0iEICA==} + '@inquirer/number@4.2.1': + resolution: {integrity: sha512-5KaqwZNLRpUuWcoCrYghPP9TMaXL5v2Sk4xqePM7RCVegcJStoXdWibio60YIC1bec+z1fCyb67N6XPJIkZtGA==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/number@4.2.3': + resolution: {integrity: sha512-6Yuwh1NGSbu1Lo4N1EWjXs1jKRntLg/ZCwhmeorEHde90v1XxAozdbd4Iu30eOQLW+6h1hp2O9ujNfLSbTPJnA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2860,8 +2871,17 @@ packages: '@types/node': optional: true - '@inquirer/password@5.1.1': - resolution: {integrity: sha512-3XBfF7DAsp5qeDsvN5Rd1HmbNokVvEQoUM0QLrRcybC9nX96w3Pbmu7qUsb3IT3J3jBvs2+mTXaKHOUsgHMLzg==} + '@inquirer/password@5.2.0': + resolution: {integrity: sha512-CvVcW09emkBESEOW+4R8CjLNkP3fB3XrjeL8CDvfpjgrJN+V9oerXmJAXXM3l+4xqYPD5Yaujzy/Ph0PLOdDuA==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/password@5.2.2': + resolution: {integrity: sha512-W9zYdyzogK+6110mqwaSJWCBu2yA5Q/OfnGSjjZB1bNpHlmUozXxTl0+QOZBNeVd6Qo81/qT75gW05gLAtITxw==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2878,8 +2898,17 @@ packages: '@types/node': optional: true - '@inquirer/prompts@8.5.2': - resolution: {integrity: sha512-IYR/3C/paEVVQYQvdDlFZVjRCJVYHHON0XXMH91KO9GSxs0TdKYWlUdvfQl2EfAHDxUaN3IBffkE/BDTh5nJ6g==} + '@inquirer/prompts@8.7.0': + resolution: {integrity: sha512-yQwBMYvpJ6jqrXtKiOwRD5XezjJoyt3VQvIyjsr5Arqb519nfIohOQymWVJ8/vEgg8xtZerrCsqlSaqt/LPC9A==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/prompts@8.7.2': + resolution: {integrity: sha512-QoRB4wFIjgH5iOhSjoIKMkTvSHDuV+O3OITlIqAYO0oK5x364GJILXiMBvlPiE+klg7Xx9tq5XVqQHcGUDYYPA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2896,8 +2925,17 @@ packages: '@types/node': optional: true - '@inquirer/rawlist@5.3.1': - resolution: {integrity: sha512-QqdTqQddL3qPX/PPrjobpsO25NZ4dWXgTLenrR445L2ptLEYE6Z+PD5c5CNDJNx4ugRgELAIpSIJxZaO2jJ2Og==} + '@inquirer/rawlist@5.3.3': + resolution: {integrity: sha512-Mu7WrtmDLaXBDEyrRLS70SZgX9ZSm4Up1w0ZxiH8C1OOp9oaVCn2k8q3QGgmlnhsKYUhuaU3zFWhAP6wxkVIMA==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/rawlist@5.3.5': + resolution: {integrity: sha512-1oHky1ONfCOwNrnkQGDE1oaSij/3fI6HFMSf2H/WsGO2lEyDX9My82iggITSy9ddSZ8yk8j9v41OI0fVoSIoaA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2914,8 +2952,17 @@ packages: '@types/node': optional: true - '@inquirer/search@4.2.1': - resolution: {integrity: sha512-xJj8QWKRSrfKoBIITLZK61dD3zwo0Rz11fgDImku30/Oe81zMdIdGgrLY2h6RkJ+KZ/GhNYIRMKnH/62qBTA5g==} + '@inquirer/search@4.3.1': + resolution: {integrity: sha512-0VWOvsHWI0rPj6CG70MoP4oXNCB6adcyN8bVFZXnh11eLDdPIK2f2XCmva78acPPDfJisfab7qNakwBh7hdBXw==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/search@4.3.3': + resolution: {integrity: sha512-fyuIU1Nbpvwlikjg3gXwJFDI11+EFjqQ7P+iByfmivIKQ1vmaykNrD/vy5unHuUqUpsOsnvJ25//tPF7E/RBRA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2932,8 +2979,17 @@ packages: '@types/node': optional: true - '@inquirer/select@5.2.1': - resolution: {integrity: sha512-FlDndEUww8m7BfukO2nJa25vhD+H5jxxCv4oGioKqzyWz3nPHhhw4LKdYRSlXuAx7DsdWia7iyaBPKKS95Evfw==} + '@inquirer/select@5.2.3': + resolution: {integrity: sha512-KuRTodDa6xBXX2noIpjuitpX/QT7Sfav7dIZ/OfUY54Hxg95nrGoshSzxx6Ey7qqLbImKdiGkSDt7KjPXjQgmA==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/select@5.2.5': + resolution: {integrity: sha512-9kc15hr8r/kI+3DO/xLog5nOzTz1jqsHXa6JBFzmQKhkoJ8Slda1I1L/uD8ZSZ9tF1yp79wwXe7mclvX1rqR2Q==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2950,8 +3006,17 @@ packages: '@types/node': optional: true - '@inquirer/type@4.0.7': - resolution: {integrity: sha512-t28inv14nMQ1PhKpsJPY+kEs/c00qzeCOS2gTNRyTjG5d6qsVA2fItxW4hkvGZ5lvanGLdtCzVIx5dwdRpN1+g==} + '@inquirer/type@4.1.0': + resolution: {integrity: sha512-FMiJpuHUG3Dk0ex+UIXkre7i+i4OcwHWk9YdcVtZHFwb/r2rnrU2ipTCNAB7A+QOP0ryzIcqOfy76fRyyvOEAw==} + engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/type@4.1.1': + resolution: {integrity: sha512-yJoHYrMnxIsJZCY+0Vb66Dy3he3kL3e2wOBKhoSwWWAzZAY82emlxwgprCtp6yRixvNRNq9ztfRWQYPNr3Go7A==} engines: {node: '>=23.5.0 || ^22.13.0 || ^20.17.0'} peerDependencies: '@types/node': '>=18' @@ -2979,8 +3044,8 @@ packages: resolution: {integrity: sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==} engines: {node: '>=8'} - '@jasminejs/reporters@1.0.0': - resolution: {integrity: sha512-rM3GG4vx2H1Gp5kYCTr9aKlOEJFd43pzpiMAiy5b1+FUc2ub4e6bS6yCi/WQNDzAa5MVp9++dwcoEtcIfoEnhA==} + '@jasminejs/reporters@1.1.0': + resolution: {integrity: sha512-JIrlfaf9c6m0+GtBAgZdcFB6RIRbFBbXxZDZ0WOewq4cLIEcVKEe0RgI1FA77M39FNzeSMTAm+LK/kcQVIkfGQ==} '@jest/console@30.4.1': resolution: {integrity: sha512-v3bhyxUh9Hgmo5p6hAOXe14/R3ZxZDOsvHleh4B07z3m/x4/ngPUXEm9XwK4sF4u+f+P2ORb0Ge+MgpaqRMVDA==} @@ -3084,8 +3149,8 @@ packages: resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} - '@jridgewell/sourcemap-codec@1.5.5': - resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + '@jridgewell/sourcemap-codec@1.6.0': + resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==} '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} @@ -3102,8 +3167,8 @@ packages: '@lezer/common@1.5.2': resolution: {integrity: sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ==} - '@lezer/css@1.3.4': - resolution: {integrity: sha512-N+tn9tej2hPvyKgHEApMOQfHczDJCwxrRFS3SPn9QjYN+uwHvEDnCgKRrb3mxDYxRS8sKMM8fhC3+lc04Abz5Q==} + '@lezer/css@1.3.6': + resolution: {integrity: sha512-YJE78Wcg+zX8f10hiHWQ4Az48Qr/c13eId0VtRQYLBpxHDmDeSrXIlkbl+fJGW42rWC/uoUco9mhBZeVWP/A1g==} '@lezer/highlight@1.2.3': resolution: {integrity: sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==} @@ -3120,12 +3185,12 @@ packages: '@lezer/sass@1.1.0': resolution: {integrity: sha512-3mMGdCTUZ/84ArHOuXWQr37pnf7f+Nw9ycPUeKX+wu19b7pSMcZGLbaXwvD2APMBDOGxPmpK/O6S1v1EvLoqgQ==} - '@listr2/prompt-adapter-inquirer@4.2.4': - resolution: {integrity: sha512-/KRI2DMD7JGSYaREF0Ygl7AefJ/2ase4Gc5cBiKqT5l4tFjsSJfhFGcc5nSkgl0Sp9LkCQNzl/cqbVJYP2L3dw==} + '@listr2/prompt-adapter-inquirer@4.2.7': + resolution: {integrity: sha512-k180vxSv2KqmnDxoato6pCqEJsov4U5C0EVmldZkAdNeVBxY48A/LM6TCNPGIzDK/iZSfsZP0Mw+gbWc5hXLyA==} engines: {node: '>=22.13.0'} peerDependencies: '@inquirer/prompts': '>= 3 < 9' - listr2: 10.2.1 + listr2: 11.1.0 '@lmdb/lmdb-darwin-arm64@3.5.6': resolution: {integrity: sha512-mY5FG4TjPAkY4P0w+OhHaUka5mDh2TX2WKYIwuKzJ1zeW3VvRgxdam/lGJTquI+bthTx5CSHDW+BAQCnNAzkEA==} @@ -3162,21 +3227,26 @@ packages: cpu: [x64] os: [win32] - '@marijn/find-cluster-break@1.0.3': - resolution: {integrity: sha512-FY+MKLBoTsLNJF/eLWaOsXGdz6uh3Iu1axjPf6TUq92IYumcTcXWHoS747JARLkcdlJ/Waiaxc5wQfFO8jC6NA==} + '@marijn/find-cluster-break@1.0.4': + resolution: {integrity: sha512-Wy0V7+SGUjnF9/TkiM1hKVDPj7jKXduPNboMVtHTA8dySMURWqfg/JZ9E2Sq8JgSJmkl7k7Qe9FLeMSrSraWmQ==} - '@mcp-b/webmcp-polyfill@4.0.0': - resolution: {integrity: sha512-7M6WS3IcxaIEhidbS9N7wrrGjtJf474Vi4Fn1hGkFkmYFT5EoFw/kS/4CSdUR/KmlInO1kyluHRY6t3avMQfFw==} - engines: {node: '>=18'} + '@mcp-b/webmcp-polyfill@5.1.0': + resolution: {integrity: sha512-KL09hniFssPY8HBO3qzurWPqm+1JYRwV3wx6x2XSySgo+6BL1XHGsHGIoAO7U9zzigv7TA5keNBoZ+3P1jq18g==} + engines: {node: '>=20'} - '@mcp-b/webmcp-types@4.0.0': - resolution: {integrity: sha512-CUBBmiut1UBsiD3FAF6xrLKeKAuJkzd6/BlL1C/uo8sVpwY42NW4mls9rLcTxmLF/8Cj5/ZOwJiLzXl/T3GIQg==} + '@mcp-b/webmcp-types@5.1.0': + resolution: {integrity: sha512-twOKDUr7al60K890HvRcNvoHSfQ2rnGeKJiQs6eUr+Leg+LQ6K+yz3F4K70jykMK1a09ZIgYb3Oc7mAypuKPig==} + engines: {node: '>=20'} + + '@mermaid-js/parser@1.2.1': + resolution: {integrity: sha512-n12NohV3mrUyUL2o93IgG/ifeW9FTyeJn3zDxkhwa8MJ9Fxg3HQMlA3RiGmD/3UnJvheztkjjQAjA2T4LmUcpw==} - '@mermaid-js/parser@1.2.0': - resolution: {integrity: sha512-oYPyv8A4As1yH5Bx+04iQEQxXuIQDe0GKCNSRgao6z8AM9jixXIfP0vsppRLvGf+nKIOb9/LdpWA4YuJiVvESA==} + '@modelcontextprotocol/core@2.0.0': + resolution: {integrity: sha512-pJCEwGG7Lfr/+PQp9ZTwKXNeO5wzbfKL7H3MYpCorM4oFBoQrdjnBgEoqG+RjhsvS1FKrDbKux+M1HhlnGWqcA==} + engines: {node: '>=20'} - '@modelcontextprotocol/sdk@1.29.0': - resolution: {integrity: sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==} + '@modelcontextprotocol/sdk@1.30.0': + resolution: {integrity: sha512-xKd8OIzlqNzcqcNumGAa6g+PW2kjD5vrpcKOnfldAUPP3j7lnqMPwlTXQm8gF+UwH72z0lqaRbjr9hqGz0eITA==} engines: {node: '>=18'} peerDependencies: '@cfworker/json-schema': ^4.1.1 @@ -3184,6 +3254,10 @@ packages: '@cfworker/json-schema': optional: true + '@modelcontextprotocol/server@2.0.0': + resolution: {integrity: sha512-YhHWdHfpFMQfd0prsEnxKeS3Qz3ytIGmsS0sth4KDjnacIT7hxk6hXHkJ9KysxlkvTM+WZAtQbbcUhdoP4Hvtw==} + engines: {node: '>=20'} + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4': resolution: {integrity: sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ==} cpu: [arm64] @@ -3218,6 +3292,13 @@ packages: resolution: {integrity: sha512-VVPPgHyQ6ShqnrmDWuxjmUIsO9gWyOZFmuOfLd9LfBGQJwZfy0gvv9pbHSJuoFNIYC7ZDX9aoFwowjcdSC4E8w==} engines: {node: '>=18'} + '@napi-rs/lzma-linux-x64-gnu@1.5.1': + resolution: {integrity: sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==} + engines: {node: ^22.20 || ^24.12 || >=25} + cpu: [x64] + os: [linux] + libc: [glibc] + '@napi-rs/nice-android-arm-eabi@1.1.1': resolution: {integrity: sha512-kjirL3N6TnRPv5iuHw36wnucNqXAO46dzK9oPb0wj076R5Xm8PfUVA9nAFB5ZNMmfJQJVKACAPd/Z2KYMppthw==} engines: {node: '>= 10'} @@ -3331,11 +3412,12 @@ packages: resolution: {integrity: sha512-xJIPs+bYuc9ASBl+cvGsKbGrJmS6fAKaSZCnT0lhahT5rhA2VVy9/EcIgd2JhtEuFOJNx7UHNn/qiTPTY4nrQw==} engines: {node: '>= 10'} - '@napi-rs/wasm-runtime@1.1.6': - resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + '@napi-rs/wasm-runtime@1.2.3': + resolution: {integrity: sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==} + engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0} peerDependencies: - '@emnapi/core': ^1.7.1 - '@emnapi/runtime': ^1.7.1 + '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.4 + '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.4 '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -3349,58 +3431,70 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@octokit/auth-app@8.2.0': - resolution: {integrity: sha512-vVjdtQQwomrZ4V46B9LaCsxsySxGoHsyw6IYBov/TqJVROrlYdyNgw5q6tQbB7KZt53v1l1W53RiqTvpzL907g==} + '@octokit/auth-app@8.3.1': + resolution: {integrity: sha512-XHWxZsF4mvGTQCv7AOxgby9t9OjVO19FBuKq+QmyBxFrf+B2hR/P5j/MTF8g95bITf8cRtR17KIXThpFNqiKbg==} engines: {node: '>= 20'} - '@octokit/auth-oauth-app@9.0.3': - resolution: {integrity: sha512-+yoFQquaF8OxJSxTb7rnytBIC2ZLbLqA/yb71I4ZXT9+Slw4TziV9j/kyGhUFRRTF2+7WlnIWsePZCWHs+OGjg==} + '@octokit/auth-oauth-app@9.0.5': + resolution: {integrity: sha512-Hn2yAlIDjFLGjAz7t+CRu7e9VYoFW1W3LLyOLyahFoJGlCf4PtDkHKtRET8w/2CJpsrC0FxIF5g5Xtx9E4O78w==} engines: {node: '>= 20'} - '@octokit/auth-oauth-device@8.0.3': - resolution: {integrity: sha512-zh2W0mKKMh/VWZhSqlaCzY7qFyrgd9oTWmTmHaXnHNeQRCZr/CXy2jCgHo4e4dJVTiuxP5dLa0YM5p5QVhJHbw==} + '@octokit/auth-oauth-device@8.0.5': + resolution: {integrity: sha512-kdJtjRhykMLJrMdcoC56XUBDfoUAuWEFKpkDxwYim+bNwYw1MreLolk+PLnwEYT8djm589YepeMuJ8+ECAIzVQ==} engines: {node: '>= 20'} - '@octokit/auth-oauth-user@6.0.2': - resolution: {integrity: sha512-qLoPPc6E6GJoz3XeDG/pnDhJpTkODTGG4kY0/Py154i/I003O9NazkrwJwRuzgCalhzyIeWQ+6MDvkUmKXjg/A==} + '@octokit/auth-oauth-user@6.0.4': + resolution: {integrity: sha512-eya2pMJ9pCBq1jrm1Rf6J3NI+NemEpzDMLo9J/GpRoK0KgdxIVXWX4LESIfwJ+GYeoq6QFIlUJNi1lVp5FBgmw==} engines: {node: '>= 20'} '@octokit/auth-token@6.0.0': resolution: {integrity: sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==} engines: {node: '>= 20'} - '@octokit/core@7.0.6': - resolution: {integrity: sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==} + '@octokit/core@7.0.8': + resolution: {integrity: sha512-L7y8eYc+AwxGr2PWI4WFt1VG4TiJ66c26BD16mXpYIlXxG0SMigM1+m4aTSlYyBr5BlQsGAlz8uDCoZN4SEMcg==} engines: {node: '>= 20'} - '@octokit/endpoint@11.0.3': - resolution: {integrity: sha512-FWFlNxghg4HrXkD3ifYbS/IdL/mDHjh9QcsNyhQjN8dplUoZbejsdpmuqdA76nxj2xoWPs7p8uX2SNr9rYu0Ag==} + '@octokit/endpoint@11.0.5': + resolution: {integrity: sha512-iXa654H3yFafF/ieHkukfbgWo2rmXD2ceD0ZOtrPhw1bc3FDch1d9N/TNs0FQ1/cIbwb7kspUX8jzIs8nzb9DQ==} engines: {node: '>= 20'} '@octokit/graphql-schema@15.26.1': resolution: {integrity: sha512-RFDC2MpRBd4AxSRvUeBIVeBU7ojN/SxDfALUd7iVYOSeEK3gZaqR2MGOysj4Zh2xj2RY5fQAUT+Oqq7hWTraMA==} - '@octokit/graphql@9.0.3': - resolution: {integrity: sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==} + '@octokit/graphql@9.0.5': + resolution: {integrity: sha512-bt/hm03LeU6Vy7FwTrkkC9p3XGT/lBwClglMqxBSe5/q0E5CdJTXeAqEI0vlw89/LF/G6tryTIH8HirZ3prMVg==} engines: {node: '>= 20'} '@octokit/oauth-authorization-url@8.0.0': resolution: {integrity: sha512-7QoLPRh/ssEA/HuHBHdVdSgF8xNLz/Bc5m9fZkArJE5bb6NmVkDm3anKxXPmN1zh6b5WKZPRr3697xKT/yM3qQ==} engines: {node: '>= 20'} - '@octokit/oauth-methods@6.0.2': - resolution: {integrity: sha512-HiNOO3MqLxlt5Da5bZbLV8Zarnphi4y9XehrbaFMkcoJ+FL7sMxH/UlUsCVxpddVu4qvNDrBdaTVE2o4ITK8ng==} + '@octokit/oauth-methods@6.0.5': + resolution: {integrity: sha512-/mAz7taDZD7DcV4zcG6TDw3Kr6TOldmYBRpvA62C3WIxRMmcgX8XxsTvVQomqKE7VEk/BgYhUao1aR2tYGyIKg==} engines: {node: '>= 20'} '@octokit/openapi-types@27.0.0': resolution: {integrity: sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==} + '@octokit/openapi-types@28.0.0': + resolution: {integrity: sha512-0rFyLuyHvIj6uuZWuDslxkowFYdPXoNIkeAv4b27dzm2Tf4vGWXnPsMcxs7d65kLdMERgP3wc1AEPlqMz8e1cQ==} + + '@octokit/openapi-types@29.0.1': + resolution: {integrity: sha512-9qWOMFNxxLokERcms42rU0PTLqQmVs7g5E41TI4mCOxmpFayD1rfC7XxOL55cG9MBZLFlC31BrR37myMKardwg==} + '@octokit/plugin-paginate-rest@14.0.0': resolution: {integrity: sha512-fNVRE7ufJiAA3XUrha2omTA39M6IXIc6GIZLvlbsm8QOQCYvpq/LkMNGyFlB1d8hTDzsAXa3OKtybdMAYsV/fw==} engines: {node: '>= 20'} peerDependencies: '@octokit/core': '>=6' + '@octokit/plugin-paginate-rest@15.0.0': + resolution: {integrity: sha512-lw9A9YL5s4VPj+VEx8uMxaxQm2YTgrPDkrLEuZuu18R8TK3oPcXF4K6t52nx6xn1RcogZC9i188sAr/4XYJaQQ==} + engines: {node: '>= 20'} + peerDependencies: + '@octokit/core': '>=6' + '@octokit/plugin-request-log@6.0.0': resolution: {integrity: sha512-UkOzeEN3W91/eBq9sPZNQ7sUBvYCqYbrrD8gTbBuGtHEuycE4/awMXcYvx6sVYo7LypPhmQwwpUe4Yyu4QZN5Q==} engines: {node: '>= 20'} @@ -3413,12 +3507,18 @@ packages: peerDependencies: '@octokit/core': '>=6' - '@octokit/request-error@7.1.0': - resolution: {integrity: sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==} + '@octokit/plugin-rest-endpoint-methods@18.0.0': + resolution: {integrity: sha512-1wM02pQTHEarWYij0Bb4gu8X8fBy2FJdI4HMTSFDxtYLbOkJErGVx5ywmM6jeS8tOmC0iCiRLrn6YsSIecUeOQ==} + engines: {node: '>= 20'} + peerDependencies: + '@octokit/core': '>=6' + + '@octokit/request-error@7.1.2': + resolution: {integrity: sha512-XZRuT3xZ84D3gYErI1DZvhJ33dCWVV6uzBtWkaBB4TvA/L6eOeTZodxLFVB44bBEEo3vEx7y00UfX1tBLrtLRg==} engines: {node: '>= 20'} - '@octokit/request@10.0.11': - resolution: {integrity: sha512-+s7HUxjfFqOMS9VlIwDffq0MikjSAK0gSpG73W+meAvVAvX4MBrHYTK5Bj3Uot55qFT4gzUtfzE4mGWY4Br8/Q==} + '@octokit/request@10.0.16': + resolution: {integrity: sha512-A0zWGjHzISIb+9ccG8s0dq7LKO5zVpJLRICjgUb+sJxEWqn8RUHB1rD3AE51+PECvXHIxqZ1VVvs4fHTSD9nUQ==} engines: {node: '>= 20'} '@octokit/rest@22.0.1': @@ -3428,6 +3528,12 @@ packages: '@octokit/types@16.0.0': resolution: {integrity: sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==} + '@octokit/types@17.0.0': + resolution: {integrity: sha512-ByP1v7YL5SMveFPP7+sj0/ZuWCOOg/Chs4NafOMpq6WNIM/hdGY0S7C0TCGDBWu1aGmOxmUIhMx3cO+IdwYZ1Q==} + + '@octokit/types@18.0.0': + resolution: {integrity: sha512-l6bAF43PNxkJp6g+W4PjoUSSkxHomXw2nOum5CTftJz1NlV3vu93NImgOYtLf6CbBUb5j+fiuzW0PPQ5JTSvZA==} + '@open-draft/deferred-promise@2.2.0': resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==} @@ -3441,8 +3547,8 @@ packages: resolution: {integrity: sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==} engines: {node: '>=8.0.0'} - '@opentelemetry/context-async-hooks@2.9.0': - resolution: {integrity: sha512-OQ0vzvbZBiUhjqLnUaoNfYmP8553Crr3aggB4y0ZUi815mZ7idpdJXQmoKdeBKJelYttoBlLSSHubmyw3wvX4w==} + '@opentelemetry/context-async-hooks@2.10.0': + resolution: {integrity: sha512-bvyMcgLEkozzSzpEEEo1OMoeQ97bxj6Qs2uN3mPrSdDvObMI1myffD/BPqcLlzZO9//d1SqQA/WPw7Cz2AiqhA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' @@ -3453,8 +3559,8 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' - '@opentelemetry/core@2.9.0': - resolution: {integrity: sha512-m2nckMT80NnmjTYSPjJQObBJ+8dgkoajEOUbznL8AHZ3T3yHRk2P7gI1PhEBc1+lOnrYE9UWrWHqJDsmqjmNbw==} + '@opentelemetry/core@2.10.0': + resolution: {integrity: sha512-/wNZ8twnEQQA4HoHu22+vcsdru6pWPWxW+7w+FlxT6Id7PE/WIbZmVKkte+PF72e0F2dnImFeHD2syyE1Mw6MQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' @@ -3471,95 +3577,211 @@ packages: resolution: {integrity: sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==} engines: {node: '>=14'} - '@oxc-project/types@0.139.0': - resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} + '@oxc-parser/binding-android-arm-eabi@0.149.0': + resolution: {integrity: sha512-OQmN5XYQ/GNRkbU0Ksb2QSaHOgKWhFw7Bz6lJvANBdwVkLzTlcHXDLj62XrNPtUf3pDxRBr7OoHJrKhHYOb9iA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxc-parser/binding-android-arm64@0.149.0': + resolution: {integrity: sha512-M7nHwfHY2Xv5Rm1iygvyOTPXrD4d5WRVw+C8eItLwoipzQBnkUMmwh3jvuGLBio2BGetfIH0F7J3Afb1Qn9dJg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxc-parser/binding-darwin-arm64@0.149.0': + resolution: {integrity: sha512-h6NrhqRAVKbgzfShjHoBgjeJ1vQR2o6iNM6/t8JCSej1XRKJyraV08Zz7ey6SsjPzof4ecp48Upg2vidqoDgtQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxc-parser/binding-darwin-x64@0.149.0': + resolution: {integrity: sha512-+WRRZeFYqVznJEEttiWNcI43Ij2iD0yphmMFkAuKNOQTyXQ+lLCAVW6aVLOD6nPO6FOymW7HtDh5KmnxZPi/2A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxc-parser/binding-freebsd-x64@0.149.0': + resolution: {integrity: sha512-kG0YUZj/4hdHBQDtIr2UZ7Nyxy3M5Et+w3A0V0eefRgtQWE4wJrNflBJMJfwFPiwMLPlPL6qJR+5JdeIqhzW/g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxc-parser/binding-linux-arm-gnueabihf@0.149.0': + resolution: {integrity: sha512-gOD5NhD8DG7aJ8CLZ+ve5xoDq0y0J0zKZSfkfMGfk96XLhu21IzSFvjpEvVUGodD7Yyy3Tr9rNdiPEdZjkuRqQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-parser/binding-linux-arm-musleabihf@0.149.0': + resolution: {integrity: sha512-UtPYQkciY1NzYRtfKBopYfOjSxPFFVyprs0iH+Z5KZKNv9at/71pGd2KNrlmALhRcNocnxEsc+KuhY3nUlhIxg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-parser/binding-linux-arm64-gnu@0.149.0': + resolution: {integrity: sha512-3jWkwykjJJegMD+5dU9n30mzwvTLi99fkUqHU9Pqdzw3fIVfyn6ZnjOl8l053jogr0BGQPxagTjIKBksp288eQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-arm64-musl@0.149.0': + resolution: {integrity: sha512-H7n8zPxnLVI0pkutAxyXJNE/IaCuCJS6ghgv2cl8IDIgXCDZWjG/Bs8rF8BHKQ9gsOpA4m+T4lFaFAdnGuk/cw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-linux-ppc64-gnu@0.149.0': + resolution: {integrity: sha512-aByOTCdLYp8FjwAUUmN7YYjAmPJ/9t0I1ACuhAkYun87fajIHbwuZ/opaBk0Pnfxzp2vYyD8hdG8OQWEglP5oA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-riscv64-gnu@0.149.0': + resolution: {integrity: sha512-SAdNs+uxMRBLPM6QuLlOxzE4duWia4EMhqGknsJS2EGnWni7i53gSZhaW3VYPxaP8nk/UsMQxMODIFwBHbRWcQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-riscv64-musl@0.149.0': + resolution: {integrity: sha512-RhmzD62QNtMjuBAeKJ15gzyNRv06Yz1ZFi6lgTiA5S3ixkrSMPJWIPGyqdlC4XiWxwAW9W4jeQNV4/Om9V27gA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-linux-s390x-gnu@0.149.0': + resolution: {integrity: sha512-HqEExoeKhlfUacdhj7KEe1m93B1SzCUkF88c1qLQR5Km6GPSoMHMIjK7qmRXLzjsO+ipSTWVsnYMVG0j2/mxNA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-x64-gnu@0.149.0': + resolution: {integrity: sha512-FuAv1J7GoSkmxg5glvzlHA88Ld7dOIg23VdAsVLngPZN/ZjZPtCaBZDby1GPn63Yj+7h47/wbcd7i1p2UJTeNQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-x64-musl@0.149.0': + resolution: {integrity: sha512-KDFOVgjMIOiMiRUw+jZlAIEZZFG0WgGk+adcldjc+/qz0/kvobnYJqDqNX0+REJbSpSsM1Knj0zrEGTQ6WTIng==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-openharmony-arm64@0.149.0': + resolution: {integrity: sha512-O3O+ZBhGEUhtbDXFWRMTuOCBg+fC2hf1wrtZBrd3VJUtV/MDd1LCwZXIHY2nMCnh9Akgjay965pBok2h5AXN0A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxc-parser/binding-win32-arm64-msvc@0.149.0': + resolution: {integrity: sha512-9hMvs3GZESAcbUGU3mqXFWRLgBd8TLeosNYfHusHp/hrBnk5lIP2nJtark3hZ6qT+lqSdS79sH8NoWHj1x9iUw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxc-parser/binding-win32-ia32-msvc@0.149.0': + resolution: {integrity: sha512-8hQaS1Urc1NnlutDfhQ+DwijRALGLY+AmqJSBHV4OmyPZDoqgtkmjTHl2tsTLK6PETe6PbIJLKmXcpJuqkf8Lw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxc-parser/binding-win32-x64-msvc@0.149.0': + resolution: {integrity: sha512-xFqDgKSKdY0m2EtHQL7uMuknuEGnvbtxkWllGle5hmhVe5xn5XZ0Zb9iViAsItFAf0CjSiZ5er3XqqAlr5oARA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@oxc-project/types@0.149.0': + resolution: {integrity: sha512-Efcc+iF0j3Bf67YjEqIqWXbX5XddXoK/Mw4K1/JuXwRCZ8N16VR7iT23nlCc9XrveFVh/E5Rqs2StT0V8v9LdA==} - '@parcel/watcher-android-arm64@2.5.6': - resolution: {integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==} + '@parcel/watcher-android-arm64@2.6.0': + resolution: {integrity: sha512-trgpLSCKRC/huFjXX/Smh+0sWe4+YtKfktIToiMl59ghz7z+qkH6kMvNnUbLyRs9N11t8l4svSCs1+5B3rOAhA==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [android] - '@parcel/watcher-darwin-arm64@2.5.6': - resolution: {integrity: sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==} + '@parcel/watcher-darwin-arm64@2.6.0': + resolution: {integrity: sha512-Y3QV0gl7Q1zbfueunkWIERICbEojQFCgpyG7YqOGNFLsckXyI1xu9mAIUpKY9QBYzBtSkN8dBPwd3yiAO9ovMw==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [darwin] - '@parcel/watcher-darwin-x64@2.5.6': - resolution: {integrity: sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==} + '@parcel/watcher-darwin-x64@2.6.0': + resolution: {integrity: sha512-Ohv6OpzhUfKYD7Beb8kDvG0jbIxORCYY1JRdZnaBtnjjkJxgD7ZVL0nw2sCYd0yTMKTvz3nnTnOF3cDifK+kvw==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [darwin] - '@parcel/watcher-freebsd-x64@2.5.6': - resolution: {integrity: sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==} + '@parcel/watcher-freebsd-x64@2.6.0': + resolution: {integrity: sha512-5HmXvDgs8VK+74jF9y9/2FE3/OnlcKmc56tjmSrEuZjpSZOGL+fvAu+HKJBdPs9uwoP2hE6TlSUpXZ/C5jUFmQ==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [freebsd] - '@parcel/watcher-linux-arm-glibc@2.5.6': - resolution: {integrity: sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==} + '@parcel/watcher-linux-arm-glibc@2.6.0': + resolution: {integrity: sha512-Ps/hui3A+vMbjdqlqAowK2ZL8+BO8dBjxeWXj6npTBs3jx4wWmbPpaLuqwrQrSqIVMCnpWo238bJ1U37GhQOYg==} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] libc: [glibc] - '@parcel/watcher-linux-arm-musl@2.5.6': - resolution: {integrity: sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==} + '@parcel/watcher-linux-arm-musl@2.6.0': + resolution: {integrity: sha512-9c6AUHgHoG+IY88MRIHupztQiQnrbqHYQjkM2btA+Bf/wQnQMuiD0Wfk1EVv3TlNT3x41uU71rn6E4xh/+zvkw==} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] libc: [musl] - '@parcel/watcher-linux-arm64-glibc@2.5.6': - resolution: {integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==} + '@parcel/watcher-linux-arm64-glibc@2.6.0': + resolution: {integrity: sha512-yHRqS2owEXe6Hic9z6Mh1ECsCd+ODVOGvZDyciqRd21+v+o+DnXMOrw50DSpIG2sb8GPEaPPmfeCAWKPJdq46g==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] libc: [glibc] - '@parcel/watcher-linux-arm64-musl@2.5.6': - resolution: {integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==} + '@parcel/watcher-linux-arm64-musl@2.6.0': + resolution: {integrity: sha512-WhB2e/V7rqdHHWZusBSPuy5Ei8S6lSz6FE5TKKQz5h3a0O+C+mhY7vxU9b/stqvMb8beLnPY82ZrFTLKs+SrKA==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] libc: [musl] - '@parcel/watcher-linux-x64-glibc@2.5.6': - resolution: {integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==} + '@parcel/watcher-linux-x64-glibc@2.6.0': + resolution: {integrity: sha512-ulGE6x6Oz6iAwg75T8YQSoguBWasniIbX+QWpaYPcCnDOpdWX3k+4xbEYPZVLxOuoJI+svJJPD3sEj8G7lrQ3A==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] libc: [glibc] - '@parcel/watcher-linux-x64-musl@2.5.6': - resolution: {integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==} + '@parcel/watcher-linux-x64-musl@2.6.0': + resolution: {integrity: sha512-tkBYKt7YQrjIJWYDnto2YgO8MRkjlMTSNoRHzsXinBqbLdeOM3L32wPZJvIZxqaLMfSlS/4sUjH/6STVP/XDLw==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] libc: [musl] - '@parcel/watcher-win32-arm64@2.5.6': - resolution: {integrity: sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==} + '@parcel/watcher-win32-arm64@2.6.0': + resolution: {integrity: sha512-gIZAP23jaHjGWasY/TY6yL7NHFClf0Ga7FN+iINvk+KN94rhm94lYZhFsbYFNcA04/onvGD9kKmiJLJB2HbNwQ==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [win32] - '@parcel/watcher-win32-ia32@2.5.6': - resolution: {integrity: sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==} - engines: {node: '>= 10.0.0'} - cpu: [ia32] - os: [win32] - - '@parcel/watcher-win32-x64@2.5.6': - resolution: {integrity: sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==} + '@parcel/watcher-win32-x64@2.6.0': + resolution: {integrity: sha512-cA+/pXV2YkfxlIcXOQ5fSWqAzzPyD78/x5qbK/I0vUkrlYHA8TIz+MXjAbGouguKVSI4bOmkTSJ1/poVSsgt+A==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [win32] - '@parcel/watcher@2.5.6': - resolution: {integrity: sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==} + '@parcel/watcher@2.6.0': + resolution: {integrity: sha512-7FNeNl8NCE7aINx7WXiKQrPYZWC/hvrTsmk6zmxbI7LTXE7hVek/n8AfVgpe2y82zl3w0HvCHN0bVKMBoJcC0w==} engines: {node: '>= 10.0.0'} '@pkgjs/parseargs@0.11.0': @@ -3629,97 +3851,98 @@ packages: '@protobufjs/utf8@1.1.2': resolution: {integrity: sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==} - '@rolldown/binding-android-arm64@1.1.5': - resolution: {integrity: sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==} + '@rolldown/binding-android-arm-eabi@1.2.8': + resolution: {integrity: sha512-tN5aztYkKCte4i5SIrrz5yK/HMjEuCqCSCJa418jOV8tZ1cBY3YF2otxB1ktPxzsLA1BeTqwapK0bfjxNvHJVw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@rolldown/binding-android-arm64@1.2.8': + resolution: {integrity: sha512-dIYTWl9XprMUiQFoc55KUyk/oS8SKYH3zFl0LTR7RT0Xj4hgSVyuJcroH8JUu8RcpF8fTB6E0aOwCkZoYPcDSQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.1.5': - resolution: {integrity: sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==} + '@rolldown/binding-darwin-arm64@1.2.8': + resolution: {integrity: sha512-PCSDQGXD2IyTEFrcgPyBM8jJuGmrbCMuoIOXdbEGVemruKACXoLQJrb+A45Z0L5t1RQkdfJprAYPkikbh7dzdA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.1.5': - resolution: {integrity: sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==} + '@rolldown/binding-darwin-x64@1.2.8': + resolution: {integrity: sha512-Uk7lRsGhPFHVX/sAUC6D5H9Ol30dFHd6iquokll2th3LpdJ3F5CzQB+7DHn0Ri2mG+U7k2zXiPHDrwZenXhwSA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.1.5': - resolution: {integrity: sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==} + '@rolldown/binding-freebsd-x64@1.2.8': + resolution: {integrity: sha512-DjszaTEVogPqA5bYzsEeqDCQxbcp2fexQwKcRspYji2yzR68fCf+e4fx6kBSRDwX5/brZaHw/hWS9+A/+/w9sQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.1.5': - resolution: {integrity: sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==} + '@rolldown/binding-linux-arm-gnueabihf@1.2.8': + resolution: {integrity: sha512-zmwa7FTmdzB6aaEEuuls18H6Ap5JmJPSoPTuXixeJZV6tG40SyLkApQtz1g8ptZtiEKqj9OM0oNLPh1AgvE31Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.1.5': - resolution: {integrity: sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==} + '@rolldown/binding-linux-arm64-gnu@1.2.8': + resolution: {integrity: sha512-KdYQDPHwJVnbFwdTGMgxsI9SqblBlz6STGM+w1We/d5B8OWWidYH0MwkU/uA1wM5fIpO2MkOVxXrNzzuZhw9ew==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-arm64-musl@1.1.5': - resolution: {integrity: sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==} + '@rolldown/binding-linux-arm64-musl@1.2.8': + resolution: {integrity: sha512-jFJTifHnNPY+yzOoNZQfSIysrVyXzEQPhPnOUjmD1bcQGHH6s7c8cViKWar8YplQImE5N9JRqMCLrM2CdxOrZA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@rolldown/binding-linux-ppc64-gnu@1.1.5': - resolution: {integrity: sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==} + '@rolldown/binding-linux-ppc64-gnu@1.2.8': + resolution: {integrity: sha512-FhiOziBDWPBjbcmRzfLyIJnaP7AVMFXT7YCXPjXxj7wKU3vx24RjrCNN/zjvVa+N2vVoHJwCoUBvsrN/DG3zIA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-s390x-gnu@1.1.5': - resolution: {integrity: sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==} + '@rolldown/binding-linux-s390x-gnu@1.2.8': + resolution: {integrity: sha512-WnHfADMzOV2Y55wlx1hzzQnar/wDt/VdvWSD99r18Mz9ylNieIGOkRx3UV21h7m/eJvjySYJkO26VvGNFkwsIQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-gnu@1.1.5': - resolution: {integrity: sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==} + '@rolldown/binding-linux-x64-gnu@1.2.8': + resolution: {integrity: sha512-H9tRr5ibfXFVLxbPOseVewewFpl28zcEdjRDt2FTUZU7odxP0gEv1ki4/kGmcGOh78oRwZuuQllGLZ9zTJp84g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-musl@1.1.5': - resolution: {integrity: sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==} + '@rolldown/binding-linux-x64-musl@1.2.8': + resolution: {integrity: sha512-UefiqfM3D6IVNlZ8tSGs9+Ejjud2T+oxO0IHADU45Y+lyEjD2dVFyZHbkfX0LUb5Zugo/oIv1eCO/KVYhgYJYA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@rolldown/binding-openharmony-arm64@1.1.5': - resolution: {integrity: sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==} + '@rolldown/binding-openharmony-arm64@1.2.8': + resolution: {integrity: sha512-637Ke4kWSy6rp9cxQ9gMOXlxPgIw/c1beASV4M//3+9I4uwBVOOl74G+e3zyU3u19U7RkRl/HuewixZ/Z6+Rjg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.1.5': - resolution: {integrity: sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [wasm32] - - '@rolldown/binding-win32-arm64-msvc@1.1.5': - resolution: {integrity: sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==} + '@rolldown/binding-win32-arm64-msvc@1.2.8': + resolution: {integrity: sha512-xWBkPOF1Q9k/Gv1nQXnVdLxKu74jXppuOM4Z3mnypVUJJJwLsMl7hNJGRAUJoG8A5MgOI1ACKM+wBFxSJzKy4A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.1.5': - resolution: {integrity: sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==} + '@rolldown/binding-win32-x64-msvc@1.2.8': + resolution: {integrity: sha512-uz2ZvfgXbxqNwijjjbxrnvALwpyODDcgc1T1N8N3rf/DXKQmaFwmB4LX4yyjggpwN2obdQLb2rgirX5ffCWYng==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -3736,15 +3959,6 @@ packages: rollup: optional: true - '@rollup/plugin-json@6.1.0': - resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - '@rollup/plugin-node-resolve@16.0.3': resolution: {integrity: sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg==} engines: {node: '>=14.0.0'} @@ -3763,151 +3977,146 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.62.2': - resolution: {integrity: sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==} + '@rollup/rollup-android-arm-eabi@4.63.0': + resolution: {integrity: sha512-70TeIFezKKy65LgAVyQh+w94/gjWhvPWaLaGGeMEgVrPkQhuj/M5bAYYZzIFUj9Y69oHyTm5Um/R6gcLh4A8JA==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.62.2': - resolution: {integrity: sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==} + '@rollup/rollup-android-arm64@4.63.0': + resolution: {integrity: sha512-YC86tYIHK6M1IV+wbzO+Bxk8RCBr6ZyWYgWxUCzaZD8mc8rrFoIJDNzDrkHBYRc/wKdrsIXmm6/F7NzrAO+OrA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.62.2': - resolution: {integrity: sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==} + '@rollup/rollup-darwin-arm64@4.63.0': + resolution: {integrity: sha512-oI+ECtUcli0y0fi4xpW82GdPIXdTkI8G8DSjG2LRuw09fPAGykaWYH/hXxiKuTxiAjiPSTIIuYUqof5Z2hShWw==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.62.2': - resolution: {integrity: sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==} + '@rollup/rollup-darwin-x64@4.63.0': + resolution: {integrity: sha512-NwV+1s7TiKrMe4owHyKB/dTLD7ZJD0YEBEhIz+hvav1Cu1GReJjF+rsdNwjzENQeIAbE/CoNiaAc5Vz2h5DPAA==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.62.2': - resolution: {integrity: sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==} + '@rollup/rollup-freebsd-arm64@4.63.0': + resolution: {integrity: sha512-tWtHBTu5gOPK4u4Urtk4qAHW3zZ9rQAmbssO8gp7ELvGTGI3aCiq6NqyTQ0PCIg7KbHJF2UkGDDs77YZGxfjCA==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.62.2': - resolution: {integrity: sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==} + '@rollup/rollup-freebsd-x64@4.63.0': + resolution: {integrity: sha512-2qPoJiwTvtHQ27NnYvTnsgk8laXWYuVmNESG8WFZBcEPKLfZ3I27qBJarjVRQtwGeYyRfq5ZowHXih9lm2BItw==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.62.2': - resolution: {integrity: sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==} + '@rollup/rollup-linux-arm-gnueabihf@4.63.0': + resolution: {integrity: sha512-FQwsTRvLNuHoTdICABJQfbPUSEueISGmnpT06tXTMpfprf5NiKLSXKA0A+w45wJnCmZAnzgqBwbt6ARFuyOi5w==} cpu: [arm] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm-musleabihf@4.62.2': - resolution: {integrity: sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==} + '@rollup/rollup-linux-arm-musleabihf@4.63.0': + resolution: {integrity: sha512-BBVTXziw8mY1a4ZbWME9tZyfzqXCDPqaC7Z3heQ29p5dkvXzwL0NwelO8zLa8c3RBKvl3YTuSnBgsBhYBtwjIw==} cpu: [arm] os: [linux] libc: [musl] - '@rollup/rollup-linux-arm64-gnu@4.62.2': - resolution: {integrity: sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==} + '@rollup/rollup-linux-arm64-gnu@4.63.0': + resolution: {integrity: sha512-w2Iyy9+RqKwx3d9qWMKsJg0FfRBsY0/pXNv0mCQ3ueRvJI6+QAScfD4nrMlzFLs2HNVW6Ew+mtZfDl9b7Ew5/Q==} cpu: [arm64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm64-musl@4.62.2': - resolution: {integrity: sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==} + '@rollup/rollup-linux-arm64-musl@4.63.0': + resolution: {integrity: sha512-YK++KtrFRHYE0P6/RtYEAy9t8F37znP+K03RrIuLPYOL6SVlObRumf/0OE4V/h63xL9DwkWbNssZfmA9hawuDA==} cpu: [arm64] os: [linux] libc: [musl] - '@rollup/rollup-linux-loong64-gnu@4.62.2': - resolution: {integrity: sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==} + '@rollup/rollup-linux-loong64-gnu@4.63.0': + resolution: {integrity: sha512-aBfOG6fP7YkkPmTqPwufRJeFyz7WPpECv9XNbnsk9+vg7rxdih0lbtEel7jcRng4LZrrmU3FfitCFyEj4BWDWg==} cpu: [loong64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-loong64-musl@4.62.2': - resolution: {integrity: sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==} + '@rollup/rollup-linux-loong64-musl@4.63.0': + resolution: {integrity: sha512-LGaHEOeHNAag9VuS1Crs5DFg4RrU9MPi2nVnNJk9DTePx/B6RRYKVmrIXt2h7YOJlwjaFJ6lwtFDliZxScTLrQ==} cpu: [loong64] os: [linux] libc: [musl] - '@rollup/rollup-linux-ppc64-gnu@4.62.2': - resolution: {integrity: sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==} + '@rollup/rollup-linux-ppc64-gnu@4.63.0': + resolution: {integrity: sha512-jClvk+J0FC3b7Udvegiw5/4hErbHtmsNsQgENnKXDWtNCJXsJYZH5WURvu7imDOO38xYml24eeh5x3A04ppwCw==} cpu: [ppc64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-ppc64-musl@4.62.2': - resolution: {integrity: sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==} + '@rollup/rollup-linux-ppc64-musl@4.63.0': + resolution: {integrity: sha512-0OJlaGK+8+B777Ql5okIpD7ua5Ro9+VB9Ve0OKa28OQJZ1RbuUBVNHK/e3pr4BROqsyPl1JrPO1ZxJseCNffcA==} cpu: [ppc64] os: [linux] libc: [musl] - '@rollup/rollup-linux-riscv64-gnu@4.62.2': - resolution: {integrity: sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==} + '@rollup/rollup-linux-riscv64-gnu@4.63.0': + resolution: {integrity: sha512-Ygsx+HoNH7afwi1bTIXbnTvVnsO+zurPLSYxybV1hHFVU72OWOCl6v05ql/z0hkpAPx+DK7Kn9Bi7MayCcjLTA==} cpu: [riscv64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-riscv64-musl@4.62.2': - resolution: {integrity: sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==} + '@rollup/rollup-linux-riscv64-musl@4.63.0': + resolution: {integrity: sha512-pDQxtMGb+OvG3fLwR2OkZlSd47hW+kWg4BYMG/++sR6RqorQccwPTDsxda5hPwiIeIErAnCF9ma3SAU06bdQtQ==} cpu: [riscv64] os: [linux] libc: [musl] - '@rollup/rollup-linux-s390x-gnu@4.62.2': - resolution: {integrity: sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==} + '@rollup/rollup-linux-s390x-gnu@4.63.0': + resolution: {integrity: sha512-0BnUG9mS8I4SSHr3XsxVhuCMEiu+rX61xxZF5vujso4LaiAGFZFxvDjg6Xn6tLPNTUAfuCvQYas4LMQMVsKRSQ==} cpu: [s390x] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-gnu@4.62.2': - resolution: {integrity: sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==} + '@rollup/rollup-linux-x64-gnu@4.63.0': + resolution: {integrity: sha512-Adu/VttB1dpPNW+FEacrZ+xVm9tFty84+RrFzsqlFaPxoJB+9XXyDGtp5dCOoBwGBIEVH0To7lExFXEx0BIF4A==} cpu: [x64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-musl@4.62.2': - resolution: {integrity: sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==} + '@rollup/rollup-linux-x64-musl@4.63.0': + resolution: {integrity: sha512-NQ3bDvjUbFKmP23671xUlXtKmqVsUBd6M4PQCvbmNtOy06hnQIdKHy8oG/6S3R/S6He1JgPk6A5VT+prAJMYEw==} cpu: [x64] os: [linux] libc: [musl] - '@rollup/rollup-openbsd-x64@4.62.2': - resolution: {integrity: sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==} + '@rollup/rollup-openbsd-x64@4.63.0': + resolution: {integrity: sha512-u2eDAl4+0aFvA13GxlGBtTI3SS3sdgwgtV0HyjZ0QaQVCgNE+jqNGey+GtxWiq+wxr/UycAx/OnfJzApCFamvA==} cpu: [x64] os: [openbsd] - '@rollup/rollup-openharmony-arm64@4.62.2': - resolution: {integrity: sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==} + '@rollup/rollup-openharmony-arm64@4.63.0': + resolution: {integrity: sha512-XvRb5vfW3wAZQ+ZUG21AnHHDKtNcw99eigzEhjr//NZ3u7SoBaPP0seSc7FgP7p1epAEdAoZckMW9WY/+4w70w==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.62.2': - resolution: {integrity: sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==} + '@rollup/rollup-win32-arm64-msvc@4.63.0': + resolution: {integrity: sha512-iZPmniy4kNBf5yo2RezbkYNNK5HPbXE9+g+twnbqSng7dtLEJy1SKoxiE/ni4FDacjyuZpEeb9U054N4EoKHYw==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.62.2': - resolution: {integrity: sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==} + '@rollup/rollup-win32-ia32-msvc@4.63.0': + resolution: {integrity: sha512-mFBBd+LF37fnE8JnYUOH+imj0aPFPK30vpar4ehJkgnLj9sZn8ZxiRENmLtgIwxK7TC8klF6N57fxdNBwQoqOA==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.62.2': - resolution: {integrity: sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==} + '@rollup/rollup-win32-x64-gnu@4.63.0': + resolution: {integrity: sha512-ujeqEY3B+zbGn3Z4Q03cUBG/LGWnBJncVT36WER31LcOsQk9+1dmINKKtvmmfChUvRbK1G0R8OhMWFgHgaZtAw==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.62.2': - resolution: {integrity: sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==} + '@rollup/rollup-win32-x64-msvc@4.63.0': + resolution: {integrity: sha512-hncn90N4sOky0L2LKE5oESKLbxCPeVo4eLA2LSMoDzM+879ml4WSr+Rr4DWknNIVVvS1Hirkc9hx02W6YxS8rQ==} cpu: [x64] os: [win32] - '@rollup/wasm-node@4.62.2': - resolution: {integrity: sha512-LseVv64SSO6S7eyc+LFGUnH36NMMFbtKN28vTUHFinRVzFKH4cVQ/BB22JfXM9Ei5l7x46AIQp+n2QzzJ9kxHg==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - - '@schematics/angular@22.1.0-next.4': - resolution: {integrity: sha512-TVXYXc+0avvQzfxfGS1d0OwiS67vCZv6Lf5xte8+j3dGKoeWBaR8MGzajOhisy8XVySqhKcje2a8NOlQqXz+5g==} + '@schematics/angular@22.2.0-next.7': + resolution: {integrity: sha512-FVJqS9zsdkqwtdaLVKhlqrxjTtxfHjSBGFqO3ge4BNTfhZtuSUIU6Yc4+T7nAFG39bNpYqzLp9bgbswlc5NThg==} engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} '@secretlint/config-creator@10.2.2': @@ -3955,32 +4164,32 @@ packages: resolution: {integrity: sha512-Nqc90v4lWCXyakD6xNyNACBJNJ0tNCwj2WNk/7ivyacYHxiITVgmLUFXTBOeCdy79iz6HtN9Y31uw/jbLrdOAg==} engines: {node: '>=20.0.0'} - '@shikijs/core@4.3.1': - resolution: {integrity: sha512-ANMDxuaPsNMdDC1m4vfvhlDmJweMwkE5XitTwrq2rWHx5jM+dlm4MmHt2PP6t0uejfR77SuhrhJ0zEijIF/uhA==} + '@shikijs/core@4.4.3': + resolution: {integrity: sha512-QCR4q2ZO/ILJEuwiBMel4wdcTDb1JGwfjKTxPDF6x8ixOaluPrVqIn06C99AcRPhmYlBR56d/Fb+GN58GzExpg==} engines: {node: '>=20'} - '@shikijs/engine-javascript@4.3.1': - resolution: {integrity: sha512-JBItcnPuYq7jVJdZo/vMj94r+szT7XEjHFX+mvFDGSEIbVAXAGyHAHzhbWzpGOwYidCZrErJLLgn2PVeiokHnQ==} + '@shikijs/engine-javascript@4.4.3': + resolution: {integrity: sha512-FbOjFJp9VLdo1Wevs10BBtVxiTWwNLqZh5Gkhjgda/ioL15YOgeSl9n+6XMa3qRlPQzfhFNe641SrynFHYG0nQ==} engines: {node: '>=20'} - '@shikijs/engine-oniguruma@4.3.1': - resolution: {integrity: sha512-OXyNMzg0pews+msMj4cHeqT4xiYKKvbnn6VbdAXxfoFl3SSx4fJTc8FadECuc5/H9p3BzhNAoAUXKwAu9rWYhg==} + '@shikijs/engine-oniguruma@4.4.3': + resolution: {integrity: sha512-EcOQkxdxGQrc1Row/cC2c96/v1dbZqGnEVu1qTuT/MJmp6+cXCvQussowVmCv5Tqr3KuY3c7IbM6HTW3LJ1k9w==} engines: {node: '>=20'} - '@shikijs/langs@4.3.1': - resolution: {integrity: sha512-m0l9nsDqgBHvbZbk7A0/kXz/impK3uB/c6rAn6Gpg/uPtdZRQ+alsN/17MU5thb68XTj/4DxkZAotrM0GGSpDQ==} + '@shikijs/langs@4.4.3': + resolution: {integrity: sha512-ePic0yfAJGOF83D5wBHK/00EjK65oahBYxFk5epgq33WRv7X9UuxLEV8PtR0szC0z8dl7INIpIodB99JRFlR+A==} engines: {node: '>=20'} - '@shikijs/primitive@4.3.1': - resolution: {integrity: sha512-CXQRQOYy1leqQ8ceTeJdmXv/bsUY++6QyLpXJ94LZAAYj5X2SKRdc5ipguv4NPyGVKItB2PPwUpRNe0Sjh5S1A==} + '@shikijs/primitive@4.4.3': + resolution: {integrity: sha512-m0wBeLDQDeIxRdUmrCPdQqfuUamDwRL5isCfYbguKD6NiaKpVbsv+3J81DyIKgNW5h4WAIIr8T4EkgQrBBxvaQ==} engines: {node: '>=20'} - '@shikijs/themes@4.3.1': - resolution: {integrity: sha512-dgpoJ4WqNi2yTmizQHBJ5zcX6j2lE6icN/0yt4l1kkf16jrY/pwPLoTb1ETsWMz0OBLf9ZNvwmxft+cH+N9qSA==} + '@shikijs/themes@4.4.3': + resolution: {integrity: sha512-w8UHjeUnIR965KMWJHUPXOc2mNJUnK3vpVLYLvw5IYU2mnTTJ89E24OrJDBNiJDQ0qzb0tc4l7mrIXx5cFeIyw==} engines: {node: '>=20'} - '@shikijs/types@4.3.1': - resolution: {integrity: sha512-CHFxE0jztBIZRHH6gxXE7DXUCFXjReEGxZ/j0rfSLGKZuwp2xBYycEP14875DSa9KLL/6700oxIq6oO6ef9K2g==} + '@shikijs/types@4.4.3': + resolution: {integrity: sha512-UEJxmRR++MAGR6hugn0vgVS2W/6lWAts84FFSrnlH9sP0LNol7E5+NQ792pH8liWUhyMyjhTgSUH3k7iD7tc5g==} engines: {node: '>=20'} '@shikijs/vscode-textmate@10.0.2': @@ -4039,26 +4248,27 @@ packages: '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} - '@textlint/ast-node-types@15.7.1': - resolution: {integrity: sha512-Wii5UgUKFEh9Uv6wbq1zr4/Kf+dtjiUuzPrrXzKp8H+ifkvKNzi23V4Nz+6wVyHQn5T28AFuc8VH8OtzvGYecA==} + '@textlint/ast-node-types@15.8.0': + resolution: {integrity: sha512-5CiH9COYmovWmExQgs7763DzX6Gy9zjkjJ7JxCC95wyTcjwQn/8poNF6fv3qzRlmx8CRRde8DHr9FcgAAiPzgw==} - '@textlint/linter-formatter@15.7.1': - resolution: {integrity: sha512-TdwZ/debWYFD05K3CcoHtwvnCrza29wZxD+BjDTk/V5N7iRqkK1dTTHSD4A8AIgROLiDkHJmIKQbasbmsg8AvA==} + '@textlint/linter-formatter@15.8.0': + resolution: {integrity: sha512-+oU3A235NATv6Lzi4xa4kJ65PuNJlIxesaO4AvDhDWA9FWm7y4XKWaoQCW1esgaQQ6dwnUiFKArQ8TcJ86mC4w==} + engines: {node: '>=20.18.0'} - '@textlint/module-interop@15.7.1': - resolution: {integrity: sha512-Jg+sQW2L/cRJypk59wtcMUVVpt8vmit5ZMT3gUnFwevP3A6Qp1HfOtUy9ObT4hBX3lOSGT/ekcCDxR1pL7uH1g==} + '@textlint/module-interop@15.8.0': + resolution: {integrity: sha512-rt+OR1WYGoLOY8HkA/aBPrqufF6yUUEsKEAh7XohTsT3lp9IyZFT6zOIbjul9P4FAzsmSPkcrYjVx3Bz/IUfkg==} - '@textlint/resolver@15.7.1': - resolution: {integrity: sha512-8XnO0pgF6mXnm41VvWmBbEIdGPhiCUt31uLZkOis1ECeg/1SoUcIT6Mx/F0e1rukq8l0UlOSeY9a31CsvRMK0g==} + '@textlint/resolver@15.8.0': + resolution: {integrity: sha512-E88tzfX3K8Jykk+38aJ9cy8RquD8ABVOPTO2rFEESq0wcg8x6/ypdAS8ZgR7OKiGqlRF0hkO/m5PbQwVfKM3VA==} - '@textlint/types@15.7.1': - resolution: {integrity: sha512-Vye/GmFNBTgVzZFtIFJTmLB+s2A7oIADxNG6r9UhfPuY+Czv0z5G3xeyFZZudPlfxURsKUyPIU5XsjOFqVp33A==} + '@textlint/types@15.8.0': + resolution: {integrity: sha512-Anhc6y5736YIsvqae0U6k0YmB2M/QVHkEeOv2aydAn/WIkdI69dCOiDbe3/+RagS3qstFTSFWJzNRA2lUjv19w==} '@tootallnate/quickjs-emscripten@0.23.0': resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} - '@tsconfig/node10@1.0.12': - resolution: {integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==} + '@tsconfig/node10@1.0.13': + resolution: {integrity: sha512-gcLdvR9HO1ZJBypsOGqaP6TFEzb6vIta0KSTLt9NAQ6pXQO3cRgSVyCN6pzYqI9DlJgY71XKO0dpDhCf08b3pg==} '@tsconfig/node12@1.0.11': resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} @@ -4096,8 +4306,8 @@ packages: '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} - '@types/chrome@0.2.2': - resolution: {integrity: sha512-8rSMZ4cvo2xmaSyQg0sN5yRL7oiDkntLoiHxUhfwQnv1mvnkrdoZ25SlNrKWmYKaeP50WvrfWj1pmc02+U9KKw==} + '@types/chrome@0.2.7': + resolution: {integrity: sha512-9kjBozQ+jyDVt1eai3VZqjHDTN95JCuRmbRHOryOltBJmzrTmUw/9r/DznmjRaQ8WlyIfeCA4WNzoj0IvormJA==} '@types/cldr@7.1.4': resolution: {integrity: sha512-p4J5+33G/iniIYGkt8ry/rCoBtJWSC2xFpW9LCygtkBNznKb870KFT/LCEU2Jd9h/6g1PteglodpWBjWdCKlpA==} @@ -4156,8 +4366,8 @@ packages: '@types/d3-format@3.0.4': resolution: {integrity: sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==} - '@types/d3-geo@3.1.0': - resolution: {integrity: sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==} + '@types/d3-geo@3.1.1': + resolution: {integrity: sha512-65Emv9fQiQQqphLlRkuQ5ypPsOmWPhtBGCMv61JDPEPMvsx+gzhGf74yw1a78xFKPj6zw4AgQICJoQv0vK9M2w==} '@types/d3-hierarchy@3.1.7': resolution: {integrity: sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==} @@ -4186,8 +4396,8 @@ packages: '@types/d3-selection@3.0.11': resolution: {integrity: sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==} - '@types/d3-shape@3.1.8': - resolution: {integrity: sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==} + '@types/d3-shape@3.2.0': + resolution: {integrity: sha512-kVd74ta9eof3eJOvbNd1vGKS/XERRyQbT26Og63hIsvDO84cjD5gEOhsXf26w3FSoNlPVz84DOFcKv/oou+fMw==} '@types/d3-time-format@4.0.3': resolution: {integrity: sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==} @@ -4270,8 +4480,8 @@ packages: '@types/jsdom@21.1.7': resolution: {integrity: sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==} - '@types/jsdom@28.0.3': - resolution: {integrity: sha512-/HQ2uFoetFTXuye8vzIcHw2z6Fwi7Hi/qcgC+RoS9NCyewiqxhVGqlG+ViGB6lkax481R6dmhf1I7lIGlzJStQ==} + '@types/jsdom@30.0.0': + resolution: {integrity: sha512-uAHGxujGE0cDaKGdK28zgDotFtNA7MKq5DXl8LrfdxdCI8VHcg15oJz+amHTChPNI5JpgEPQWc2xFdrw3em/nQ==} '@types/jsesc@2.5.1': resolution: {integrity: sha512-9VN+6yxLOPLOav+7PwjZbxiID2bVaeq0ED4qSQmdQTdjnXJSaCVKTR58t15oqH1H5t8Ng2ZX1SabJVoN9Q34bw==} @@ -4309,8 +4519,8 @@ packages: '@types/selenium-webdriver@3.0.7': resolution: {integrity: sha512-tHdDdGUBKTbiLLwf5mF78EP35F31UZekG+GRNowl8G5rMQoupAT4qWn/7AaGOvmaqvROdqC3Io/hP1ZyO58QkA==} - '@types/semver@7.7.1': - resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} + '@types/semver@7.8.0': + resolution: {integrity: sha512-1mAINjtQCXXeLkJ9ehXkwOcBpqtLxiVtKhpUf83DdRNdQKV0iXZpaHYqRr7nj+wvxuJzoAmAwXI+sCNMv1CzLQ==} '@types/sinonjs__fake-timers@8.1.1': resolution: {integrity: sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==} @@ -4342,8 +4552,8 @@ packages: '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} - '@types/vscode@1.125.0': - resolution: {integrity: sha512-0icm/ZQAaism87P0ekHqi4/Ju9du+Tm0RUW+y7vqRsxY2cY0FNRX1nAnaW7nT6npPt2tfHiheZ55Zm9UhqonFA==} + '@types/vscode@1.134.0': + resolution: {integrity: sha512-NDEu0hg4sF7+vvFsADsktqUJ6f80LHSZvVK2Ovo1XiQ0/VHck1O3zst+ZZyVA/uvz6vo6LcuoqU2q48YMqOwWw==} '@types/which@3.0.4': resolution: {integrity: sha512-liyfuo/106JdlgSchJzXEQCVArk0CvevqPote8F8HgWgJ3dRCcTHgJIsLDuee0kxk/mhbInzIZk3QWSZJ8R+2w==} @@ -4365,12 +4575,12 @@ packages: peerDependencies: typescript: '*' - '@typespec/ts-http-runtime@0.3.6': - resolution: {integrity: sha512-jIXhD0eWQ1JA6ln/5Dltyx22UxWNrw0hZmhy2rlv6m6KgF7kplHx3g0fzi09lNmTJQRR91OlemYp3xFnvDK9og==} - engines: {node: '>=20.0.0'} + '@typespec/ts-http-runtime@0.3.8': + resolution: {integrity: sha512-bLMpVcWZNzq6lYOybwFwOAR1IXKcHnhUNqYeHjl1bET/qE3jFPFH+p8Wrh3rU4xwdnifPxmKNESBYnvnmc75aA==} + engines: {node: '>=22.0.0'} - '@ungap/structured-clone@1.3.3': - resolution: {integrity: sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==} + '@ungap/structured-clone@1.4.0': + resolution: {integrity: sha512-1mEZtMKPM09vDmQt5y7YvmN2+DFTP7Tg0EWXdic8/C6VRnpb33e4ghisCIE3WZjsE2N8mf+QV1Zqh7ZFYLWInQ==} '@unrs/resolver-binding-android-arm-eabi@1.12.2': resolution: {integrity: sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==} @@ -4501,11 +4711,8 @@ packages: peerDependencies: vite: ^6.0.0 || ^7.0.0 || ^8.0.0 - '@vitest/expect@4.1.10': - resolution: {integrity: sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==} - - '@vitest/mocker@4.1.10': - resolution: {integrity: sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==} + '@vitest/mocker@5.0.0': + resolution: {integrity: sha512-66PGTMIiVJP3t4a5yxU9qPtf7MdTBs8jmToMvy+HVflB3Yy13WJZTtPePdvU+wjRV02SKK5doLbSA6o9pwOmiA==} peerDependencies: msw: ^2.4.9 vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -4515,26 +4722,14 @@ packages: vite: optional: true - '@vitest/pretty-format@4.1.10': - resolution: {integrity: sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==} - - '@vitest/runner@4.1.10': - resolution: {integrity: sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==} - - '@vitest/snapshot@4.1.10': - resolution: {integrity: sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==} - - '@vitest/spy@4.1.10': - resolution: {integrity: sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==} - - '@vitest/utils@4.1.10': - resolution: {integrity: sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==} + '@vitest/spy@5.0.0': + resolution: {integrity: sha512-uy+luWBAPw9XfthoHi5AkfHUnuPYEESjl0p/r+meoBnU8bxg5GDQ3Ey8MjcJ6sqahkL4PFyrvfMJJBw7LbU06g==} '@vscode/l10n@0.0.18': resolution: {integrity: sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ==} - '@vscode/test-electron@3.0.0': - resolution: {integrity: sha512-TY5mC7aAjxSLDXsyjhrG8cJHgc/HLdiE5lvtW7hABYQrY24Qwozzr5UoO3HiuAM4Hzz4b7K/eZlwrCILj94CcA==} + '@vscode/test-electron@3.1.0': + resolution: {integrity: sha512-CRqv5u+YYoseuNVJ6Tyo4k0sF0mx4qnKMihRB0PjsUF8Dc0WKtCXo6CNL6nWWm5esfFQsQA/pejMj4ZbpJVLTw==} engines: {node: '>=22'} '@vscode/vsce-sign-alpine-arm64@2.0.6': @@ -4582,8 +4777,8 @@ packages: cpu: [x64] os: [win32] - '@vscode/vsce-sign@2.0.9': - resolution: {integrity: sha512-8IvaRvtFyzUnGGl3f5+1Cnor3LqaUWvhaUjAYO8Y39OUYlOf3cRd+dowuQYLpZcP3uwSG+mURwjEBOSq4SOJ0g==} + '@vscode/vsce-sign@2.1.0': + resolution: {integrity: sha512-9AQrqazrBgTgRSuwleLVXUrIUphY02/SFCh2TKYoLV/xifJAdblhdmEmw5gUrYSPQ3sRwNs9iyCMD14sATEE6g==} '@vscode/vsce@3.9.2': resolution: {integrity: sha512-XSxMosEEDO6vLxELAHVkwmhC0qe0ijZni2jB9Rcs8kQsW4lhTDQ/wMzmwFs/buotAWSnpmUp/dRWD2ufG3UYKA==} @@ -4593,18 +4788,153 @@ packages: '@webcontainer/api@1.6.4': resolution: {integrity: sha512-r9sHCXg1FcC1AMgppGwAc0vYWaQhqvg282cnsuPbJEzYnWifAdCVvg+8ngJUEHyHcomhJJp+/zuytite4ITHLw==} - '@xmldom/xmldom@0.8.13': - resolution: {integrity: sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw==} - engines: {node: '>=10.0.0'} + '@xmldom/xmldom@0.8.15': + resolution: {integrity: sha512-/5NV/vDALVFDXgLmfsy9TRCBlKwO2LNBFzpzvb9iIj+jR+eSc6DLYYvVOdivT/jm7MtU6TebYuRmzEOI7w40UA==} + engines: {node: '>=10.0.0'} + + '@xterm/addon-fit@0.11.0': + resolution: {integrity: sha512-jYcgT6xtVYhnhgxh3QgYDnnNMYTcf8ElbxxFzX0IZo+vabQqSPAjC3c1wJrKB5E19VwQei89QCiZZP86DCPF7g==} + + '@xterm/xterm@6.0.0': + resolution: {integrity: sha512-TQwDdQGtwwDt+2cgKDLn0IRaSxYu1tSUjgKarSDkUM0ZNiSRXFpjxEsvc/Zgc5kq5omJ+V0a8/kIM2WD3sMOYg==} + + '@yarnpkg/lockfile@1.1.0': + resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==} + + '@yuku-codegen/binding-android-arm64@0.9.3': + resolution: {integrity: sha512-viote6xAyL5cKLquV2X2wRfopSckH+msDYbaI8Hh8JAaogYs8MJZVRUbSrbsY29TaPrIFZwNRwQ8+YSxs0dkGw==} + cpu: [arm64] + os: [android] + + '@yuku-codegen/binding-darwin-arm64@0.9.3': + resolution: {integrity: sha512-y2PGOLyxc724EJ+Et/5PxGfutQuV1Z2J9cxHo6W1I5CR3nk0i03J4yPrnw6rNJOfrtlISzcc7q0RrSyfPndpIg==} + cpu: [arm64] + os: [darwin] + + '@yuku-codegen/binding-darwin-x64@0.9.3': + resolution: {integrity: sha512-xZ9UpXUOLmsrKVUp7MRXxWU3drNiilRC42OLpjWEhnOehIGVF1bZgzHcqRYJxVyU53RMrkRMsaxplkGd6Qo/ow==} + cpu: [x64] + os: [darwin] + + '@yuku-codegen/binding-freebsd-x64@0.9.3': + resolution: {integrity: sha512-RGCYSZw3VonreVTpur9iOfnbMngR2/f7UOE7gwcDx5WoHjIhtmTK9EIq9qs78ARdMFAPzKp5OzHljl5QMaGJ7g==} + cpu: [x64] + os: [freebsd] + + '@yuku-codegen/binding-linux-arm-gnu@0.9.3': + resolution: {integrity: sha512-kjIJIw39GSPTF0hnq+jnM0tR+J5WlariAAWetxMtawNskITDT1ZigaK3YF5hMhDz2mAofaM1t+63qtx+7aXjeg==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@yuku-codegen/binding-linux-arm-musl@0.9.3': + resolution: {integrity: sha512-TVHeVdzaS4ub86URrQufiy4t01ZtdyKDZ5sTPqWFKAUbQJ7rQ0o5vIT+/jCeHQbP+Yf9p5peRdmPbcZewoDNiA==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@yuku-codegen/binding-linux-arm64-gnu@0.9.3': + resolution: {integrity: sha512-9aQeeLh1qaCa2GcyzHnwLKGfFrsI+KOyhnh4+fICSq5kyhzCWQfXVCCK4RTEZPLcyuVwfN5Id0JEYavRN4oNTQ==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@yuku-codegen/binding-linux-arm64-musl@0.9.3': + resolution: {integrity: sha512-TLXA5Hd1nr8VSP2MtxcFddsBIHj+DPpyG5eberEGMATndgG7STlKQmle51MV0MZ8UgsdYM6CybIVpzlCPQwP9w==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@yuku-codegen/binding-linux-x64-gnu@0.9.3': + resolution: {integrity: sha512-tk0BFbF3Clb9k9biPH3qmr+Qwk24rRM26+HY91hYXmZlzlepZG0scQ6OffZFWtzwKE5JjlZpMdcWj1lTiHbEjA==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@yuku-codegen/binding-linux-x64-musl@0.9.3': + resolution: {integrity: sha512-xo+pXshsCXruEEkDMbwHqkeTyC4XHb6A6oXr6x2YK3jOMcS5kZz0e26BmTCr40J0nY/K3ysmwG9R1xHygtiuwQ==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@yuku-codegen/binding-win32-arm64@0.9.3': + resolution: {integrity: sha512-70gAQo6HZzMgIJTjeMZOEO2XaRj4GcNGP/n81R9tXQv0x8d4ZHnZDv+ygeWfHo+xchAUPwpnrVZA4p6RhJa3GQ==} + cpu: [arm64] + os: [win32] + + '@yuku-codegen/binding-win32-x64@0.9.3': + resolution: {integrity: sha512-7Hz3NGlq6qBBR8zMEk6GMZivofNjnYZpMXSoUwUgz9Ur2LaivuP23HQh0ern+T6HVkTJEvilw4VJrg1rX1Ugcg==} + cpu: [x64] + os: [win32] + + '@yuku-parser/binding-android-arm64@0.9.3': + resolution: {integrity: sha512-z3tDGTaUXD5Q4IuebFOY/QHxhR/SqujMhkMv9C5bh25upyFEXdafp0MsXQIIheWhVZzn5VMOniyxFni/7s9LgQ==} + cpu: [arm64] + os: [android] + + '@yuku-parser/binding-darwin-arm64@0.9.3': + resolution: {integrity: sha512-hzKvKSKS7z3ufnu1VkQYEoxmS6A5uNnkwukKnc2atxpWdq648nLVOqut4h1jUXjbM2WcoTfuZLF6AHAGFf8cmg==} + cpu: [arm64] + os: [darwin] + + '@yuku-parser/binding-darwin-x64@0.9.3': + resolution: {integrity: sha512-OM2PiVlPATvzlj/KGHNlu+t8FC3YzM5joVNjhsz/EaigQ8x2UUQ1Q0agQLiv5GZ2L8TSzrLUwBCZ7YOvP8q+tw==} + cpu: [x64] + os: [darwin] + + '@yuku-parser/binding-freebsd-x64@0.9.3': + resolution: {integrity: sha512-WMn9M4LHNVysGNwsAJ9gpRPqQIW2lcPrDNGcyk0agx3IYqCJq1MQugh6Be8Otc5U08eGdE39o8Kx9YWJmXz7GA==} + cpu: [x64] + os: [freebsd] + + '@yuku-parser/binding-linux-arm-gnu@0.9.3': + resolution: {integrity: sha512-vqKjwiyW1FWvbykYMEQIcAJwA17WxK3rxxqDuyCvQwcNVaLEUxI4BXiUdlF3kHucc7MnoFQhoRPkySgOzlLM+Q==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@yuku-parser/binding-linux-arm-musl@0.9.3': + resolution: {integrity: sha512-qohilhYOT+zkt2gYzym4F1T6BzRdvPqS9/sFB03pmnVV8LrvjOXVsGwEBAa3CEvzJKhAZjdTmVz7zsVdjyHWLg==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@yuku-parser/binding-linux-arm64-gnu@0.9.3': + resolution: {integrity: sha512-tvTIyUvTGkeee68i4JIo9o27As+Ug6LXOZvElGgFbTs6+KBdb5LGhvugaIQljdfIsm2XnIbOLG6OnQSXHMLB9w==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@yuku-parser/binding-linux-arm64-musl@0.9.3': + resolution: {integrity: sha512-OWZBHW1wuChBpFlrF+On1yiBcFPMRrj2g0VKsM/PCBGffu1OM0ORkS+vLS3Snu6wYwndM5Dd9Ctvux6eUlrQjA==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@yuku-parser/binding-linux-x64-gnu@0.9.3': + resolution: {integrity: sha512-/tbk1h0dlADOCngbiQO9V3SHwBIJkoGBq8BDEraSw2CC3nGxPEPTCCYUDp5738Ij2FxVwy1FWVuhFkHvpMrPbQ==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@yuku-parser/binding-linux-x64-musl@0.9.3': + resolution: {integrity: sha512-u3+0sCso/mcjDvtc3866D2giV7l34PDyDVBkMesAWa3DWbIWPlybehi2SSnmScgArV22ctqSSgUzdBBVJ6zYAg==} + cpu: [x64] + os: [linux] + libc: [musl] - '@xterm/addon-fit@0.11.0': - resolution: {integrity: sha512-jYcgT6xtVYhnhgxh3QgYDnnNMYTcf8ElbxxFzX0IZo+vabQqSPAjC3c1wJrKB5E19VwQei89QCiZZP86DCPF7g==} + '@yuku-parser/binding-win32-arm64@0.9.3': + resolution: {integrity: sha512-xnGEvdhyjRkXozHtpXVpEEkyGZWAxJ3RoILv7XRV5SvTEztaTCk5GQyfcOzI9An/EJtcL4ERCI8QmS0TpDPJiA==} + cpu: [arm64] + os: [win32] - '@xterm/xterm@6.0.0': - resolution: {integrity: sha512-TQwDdQGtwwDt+2cgKDLn0IRaSxYu1tSUjgKarSDkUM0ZNiSRXFpjxEsvc/Zgc5kq5omJ+V0a8/kIM2WD3sMOYg==} + '@yuku-parser/binding-win32-x64@0.9.3': + resolution: {integrity: sha512-N5eShGcuwnrXEprePFmEjtng6acZmtnC4zgazK9xxkavcx1q1uX8Nz8lU5RS973EMlNr902cIc6Cd2D4tqZDBg==} + cpu: [x64] + os: [win32] - '@yarnpkg/lockfile@1.1.0': - resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==} + '@yuku-toolchain/types@0.9.3': + resolution: {integrity: sha512-rFE+5P4g2wxko5C85MugJOlVjBHEQq87dIkhLkniLXLp63PEtgaFjD954i5HXlfnyzLxPcZHsSOVDVgmo1HToA==} abbrev@5.0.0: resolution: {integrity: sha512-/XrFJgzQQQHpti1raDJC6m4ws6aNktmjBlhk8Fdlk7LwCEuDoieEJJY9OFHjfiFJFFRM2tK+Ky/IsfbbmlMu1w==} @@ -4626,8 +4956,8 @@ packages: resolution: {integrity: sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==} engines: {node: '>=0.4.0'} - acorn@8.17.0: - resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==} + acorn@8.18.0: + resolution: {integrity: sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==} engines: {node: '>=0.4.0'} hasBin: true @@ -4671,12 +5001,8 @@ packages: ajv@8.20.0: resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} - algoliasearch@5.55.2: - resolution: {integrity: sha512-OyacJsaeuLUvGWOynNqYc6sx88XvyoG39wMT8SYqL3l9wwaorDW/LPRbUPfhzw0bWsUWzNCZTnFYOrWFBKsUaw==} - engines: {node: '>= 14.0.0'} - - algoliasearch@5.56.0: - resolution: {integrity: sha512-PrqppUmhT4ENdas2pH9caE7efUcxy6EcSFhWzosiVuQBzu2tQ5yLTI6jwomT/1cuBnivzGfxiJCqDNN9FRRh+Q==} + algoliasearch@5.57.0: + resolution: {integrity: sha512-HpND7MBGctOAkd1GoQoDZCGoCpqNTS5NG1LuhElFet3RdLJkwnyTYZXZhXwtpAQPrI36fqQ3eT6KQrdKDTKu3A==} engines: {node: '>= 14.0.0'} angular-mocks@1.5.11: @@ -4737,8 +5063,8 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.2.2: - resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + ansi-regex@6.3.0: + resolution: {integrity: sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==} engines: {node: '>=12'} ansi-styles@2.2.1: @@ -4772,8 +5098,8 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} - arch@2.2.0: - resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} + arch@3.0.0: + resolution: {integrity: sha512-AmIAC+Wtm2AU8lGfTtHsw0Y9Qtftx2YXEEtiBP10xFUtMOA+sHHx6OAddyL52mUKh1vsXQ6/w1mVDptZCyUt4Q==} archiver-utils@5.0.2: resolution: {integrity: sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==} @@ -4959,17 +5285,17 @@ packages: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} - bare-events@2.9.1: - resolution: {integrity: sha512-Z0oHEHAFDZkffN8Qc39zNZjQlMDkPJRyyyZieU1VH7u8c5S+qHZ2S8ixdKIAxEjfHO7FJxXmJWgteOghVanIsg==} + bare-events@2.9.2: + resolution: {integrity: sha512-AIPKioV7/Y/8KfZ3AAhjPJxLLbY49S64Ym5DakZlUg75qQiTgUq9hEJoEwa4eUezPUlXRy/i5NpsKvo9jgKmoA==} peerDependencies: bare-abort-controller: '*' peerDependenciesMeta: bare-abort-controller: optional: true - bare-fs@4.7.4: - resolution: {integrity: sha512-y1kC+ffIx/tPLdTE693uNjHfzTfr+ravR5tvWlMXe25nELbkqV400S71qHDwbkAQ1FVEZobB1NFRzFbCCcyBCQ==} - engines: {bare: '>=1.16.0'} + bare-fs@4.8.1: + resolution: {integrity: sha512-N1nnXdHZAOSstz0XiHikGS4HGMH4CnSwhqWdGQQMqqdvp4Jybm9sE3R1WVnpWVd4SFkc8ryPDBLViNLwiEqECg==} + engines: {bare: '>=1.28.0'} peerDependencies: bare-buffer: '*' peerDependenciesMeta: @@ -4979,8 +5305,8 @@ packages: bare-path@3.1.1: resolution: {integrity: sha512-JprUlveX3QjApC1cTpsUOiscADftCGVWkzitbHsRqv84hzYwYHw2mbluddsq5TvI8mH/8Ov1f4BiMAdcB0oYnQ==} - bare-stream@2.13.3: - resolution: {integrity: sha512-Kc+brLqvEqGkjyfiwJmImAOqLZL7OsoLKuavx+hJjgVV3nLTOjloJyPMFxjUPerGGHrNH0fLU06jjykMLWrERQ==} + bare-stream@2.13.4: + resolution: {integrity: sha512-PcrQ8lVLbiJscNm1Kez+Yp4Gy4AHGcN1lzwjvf5NybWen7VvEgUfyfnXYJ2zNqWnzOfCb1Abq6lH8ti0syQszA==} peerDependencies: bare-abort-controller: '*' bare-buffer: '*' @@ -4993,8 +5319,8 @@ packages: bare-events: optional: true - bare-url@2.4.5: - resolution: {integrity: sha512-K+y9xF1tN+CdPu4qWwr0QiK1Al07eFPGYK5M2pDXcmHdMdgC/tT/bpmMe1hrmRHaidKLkXrC+cRNYf3XVDUhSQ==} + bare-url@2.5.2: + resolution: {integrity: sha512-L13PCJzKG8RGvx8V1/DdMi12ERhC3tprr7/8a94BxpmnRsFqxh5XZNdhtMxu5HPkRshYOOWRGY8lDP7ZhpG9Cg==} base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -5003,8 +5329,8 @@ packages: resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} engines: {node: ^4.5.0 || >= 5.9} - baseline-browser-mapping@2.10.43: - resolution: {integrity: sha512-AjYpR78kDWAY3Efj+cDTFH9t9SCoL7OoTp1BOb0mQV7S+6CiLwnWM3FyxhJtdPufDFKzmCSFoUncKjWgJEZTCQ==} + baseline-browser-mapping@2.11.20: + resolution: {integrity: sha512-H0ulySigv6icDJ1F7SjtdCD6PrhTpdYCmP0CactWy1+ekh0AFd0o1Wn5T8b+hnTmdBx19u9yhL6wvCylXMY7zw==} engines: {node: '>=6.0.0'} hasBin: true @@ -5022,9 +5348,9 @@ packages: bcrypt-pbkdf@1.0.2: resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} - beasties@0.4.2: - resolution: {integrity: sha512-NvcGjG/7AVUAfRbvrJmHunDQS9uHnE6Q/7AkaPr8oKE8HjOlpjRG5075z/th2Tmlezk3VlaaS8+X9I1RwHJMQw==} - engines: {node: '>=18.0.0'} + beasties@0.5.4: + resolution: {integrity: sha512-8/lOOjT+PElYCnaUbmhgd3Uad5R1VTQ4Wg0k4rK8bX04m5WEqHNmnlLy3Q/lJ7dk25XA+72gayzc/skTfKKpcA==} + engines: {node: '>=20.19.0'} before-after-hook@4.0.0: resolution: {integrity: sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==} @@ -5074,6 +5400,10 @@ packages: boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + boolbase@2.0.0: + resolution: {integrity: sha512-DkVaaQHymRhpYEYo9x1oo7Q7B0Y6KJUsjm3c9eTyFDby4MHLBTwZ6ZDWBel5zrYxj1WsZgC5oLpiz+93MluXeA==} + engines: {node: '>=20.19.0'} + bottleneck@2.19.5: resolution: {integrity: sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==} @@ -5084,15 +5414,15 @@ packages: resolution: {integrity: sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==} engines: {node: '>=10'} - brace-expansion@1.1.16: - resolution: {integrity: sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==} + brace-expansion@1.1.18: + resolution: {integrity: sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==} - brace-expansion@2.1.2: - resolution: {integrity: sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==} + brace-expansion@2.1.4: + resolution: {integrity: sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==} - brace-expansion@5.0.7: - resolution: {integrity: sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==} - engines: {node: 18 || 20 || >=22} + brace-expansion@5.0.9: + resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==} + engines: {node: 20 || >=22} braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} @@ -5101,8 +5431,8 @@ packages: browser-stdout@1.3.1: resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} - browserslist@4.28.6: - resolution: {integrity: sha512-FQBYNK15VMslhLHpA7+n+n1GOlF1kId2xcCg7/j95f24AOF6VDYMNH4mFxF7KuaTdv627faazpOAjFzMrfJOUw==} + browserslist@4.28.8: + resolution: {integrity: sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -5182,8 +5512,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001806: - resolution: {integrity: sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==} + caniuse-lite@1.0.30001810: + resolution: {integrity: sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==} caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} @@ -5214,6 +5544,10 @@ packages: resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + chalk@6.0.0: + resolution: {integrity: sha512-2uNTXIuTTxk7ciZgAU1BQcgnchcG0xXnrs6jzkQfj9SsRa9M2s5zE8WT96hS6KmG4MzWHSrvH43DF1m4XRkrFg==} + engines: {node: '>=22'} + char-regex@1.0.2: resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} engines: {node: '>=10'} @@ -5241,10 +5575,6 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} - chokidar@4.0.3: - resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} - engines: {node: '>= 14.16.0'} - chokidar@5.0.0: resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} engines: {node: '>= 20.19.0'} @@ -5256,6 +5586,10 @@ packages: resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} engines: {node: '>=18'} + chrome-remote-interface@0.33.3: + resolution: {integrity: sha512-zNnn0prUL86Teru6UCAZ1yU1XeXljHl3gj7OrfPcarEfU62OUU4IujDPdTDW3dAWwRqN3ZMG/Chhkh2gPL/wiw==} + hasBin: true + ci-info@2.0.0: resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} @@ -5263,8 +5597,8 @@ packages: resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} engines: {node: '>=8'} - cjs-module-lexer@2.2.0: - resolution: {integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==} + cjs-module-lexer@2.2.1: + resolution: {integrity: sha512-Ca8swihM+/4yKecYHY52kgJd300hi2lADU/a1RxNTRe+RJ9jvqQlESpbz9DnG9mowez8qwXHB8qYdIUw9e+F5Q==} cjson@0.3.3: resolution: {integrity: sha512-yKNcXi/Mvi5kb1uK0sahubYiyfUO2EUgOp4NcY9+8NX5Xmc+4yeNogZuLFkpLBBj7/QI9MjRUIuXrV9XOw5kVg==} @@ -5317,6 +5651,10 @@ packages: resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==} engines: {node: '>=20'} + cli-truncate@6.1.1: + resolution: {integrity: sha512-06p9vyLahLa4zkGcgsGxU6iEkSOiuI4fhCH6Emhe2lPAcoUv73n72DnODsnHA+5wwXGnV0n9M9/qOQJSjYhFhw==} + engines: {node: '>=22'} + cli-width@4.1.0: resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} engines: {node: '>= 12'} @@ -5371,8 +5709,8 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - color-name@2.1.0: - resolution: {integrity: sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==} + color-name@2.1.1: + resolution: {integrity: sha512-p2FdgwVx1a9yWBHP2wI0VgShkDpgN4kZISkxdNipGBJWpa5G6b04OINlVWCyJj0JmfvcPrgqt95E9k8yvaOJFg==} engines: {node: '>=12.20'} color-string@2.1.4: @@ -5390,6 +5728,9 @@ packages: colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + colorjs.io@0.7.1: + resolution: {integrity: sha512-LY7OHnJZxHwT5UlzNa9bbhHHDbzB6yE5+3MIPwJEQKRvSCt/T4G7epsj+9j2BExUIIfXFIJGsIXUKdfrK9Q5tA==} + colors@1.4.0: resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==} engines: {node: '>=0.1.90'} @@ -5417,6 +5758,9 @@ packages: resolution: {integrity: sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg==} engines: {node: '>=22.12.0'} + commander@2.11.0: + resolution: {integrity: sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==} + commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} @@ -5499,10 +5843,14 @@ packages: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} - content-type@2.0.0: - resolution: {integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==} + content-type@2.1.0: + resolution: {integrity: sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==} engines: {node: '>=18'} + content-type@3.0.0: + resolution: {integrity: sha512-AIi5H6p0xk5uknXcN3/rmhP8jgp69OfSe/JuKiQAFprJ7UGw7mwj7m4XcmDzlrnJDG+cGpphAINGdU3g3g7kDw==} + engines: {node: '>=22'} + conventional-changelog-angular@8.3.1: resolution: {integrity: sha512-6gfI3otXK5Ph5DfCOI1dblr+kN3FAm5a97hYoQkqNZxOaYa5WKfXH+AnpsmS+iUH2mgVC2Cg2Qw9m5OKcmNrIg==} engines: {node: '>=18'} @@ -5564,8 +5912,8 @@ packages: engines: {node: '>=18'} hasBin: true - conventional-changelog-writer@9.2.0: - resolution: {integrity: sha512-eACD5BaAQCYjeI3RExkCZopNaaIuXzCP4kaAb2lEFXcGa/KOuxJfj8v/SnjhvF6377pYn0A2Gji+6GhwUK8rEA==} + conventional-changelog-writer@9.2.1: + resolution: {integrity: sha512-StlYSmW3wLedRaqohJMpP3YuWiAqtgD0/cpsai9frdDkXv7rxj0hRbpJrubPYvJxJsjplONsOobEQnPuS9UgCg==} engines: {node: '>=22'} hasBin: true @@ -5573,8 +5921,8 @@ packages: resolution: {integrity: sha512-tuUH8H/19VjtD9Ig7l6TQRh+Z0Yt0NZ6w/cCkkyzUbGQTnUEmKfGtkC9gGfVgCfOL1Rzno5NgNF4KY8vR+Jo3w==} engines: {node: '>=18'} - conventional-changelog@8.1.0: - resolution: {integrity: sha512-idt1JK+3+Nt7gqH/d/sEYWdDeR+5XPov/jssmFN6XxmYSRlonTWSDWhWUPkmm0zbwYjtVdt+4My5aiPkKyvocw==} + conventional-changelog@8.1.3: + resolution: {integrity: sha512-fOMwLCxm46znJKPB08jLxl1FD8SOZOQHktlzCVhvhhVUfq0KgQSryoYXsRRHs1aRlZPR1/QK5wztnY8sBNC2AA==} engines: {node: '>=22'} hasBin: true @@ -5591,8 +5939,8 @@ packages: engines: {node: '>=18'} hasBin: true - conventional-commits-parser@7.1.0: - resolution: {integrity: sha512-DPp6hkUjvwIivxbkrTiLXeRswNv1A/4GFA2X6scXma0AMa9632V3TwxmrlkUIEtUktiM3Ln+RrSH2xlP3/jUTw==} + conventional-commits-parser@7.1.2: + resolution: {integrity: sha512-O+x4N2yH+ijvqWlIyTHsXTAP+algNWgGbjY2duCe8w2vUMvUB95cLRslCPfTMQyLAKlet3bhZTdu6ozn4M+QJQ==} engines: {node: '>=22'} hasBin: true @@ -5672,8 +6020,9 @@ packages: css-select@5.2.2: resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} - css-select@6.0.0: - resolution: {integrity: sha512-rZZVSLle8v0+EY8QAkDWrKhpgt6SA5OtHsgBnsj6ZaLb5dmDVOWUDtQitd9ydxxvEjhewNudS6eTVU7uOyzvXw==} + css-select@7.0.0: + resolution: {integrity: sha512-snmjEVXy+1LnwXdxhYvTMj1d9tOh4HxkA1YmoayVBeeyR2C14Pum7fcxJIm4SswYspVy866eYNwlH6xC3/VH5g==} + engines: {node: '>=20.19.0'} css-tree@3.2.1: resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} @@ -5683,9 +6032,9 @@ packages: resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} engines: {node: '>= 6'} - css-what@7.0.0: - resolution: {integrity: sha512-wD5oz5xibMOPHzy13CyGmogB3phdvcDaB5t0W/Nr5Z2O/agcB8YwOz6e2Lsp10pNDzBoDO9nVa3RGs/2BttpHQ==} - engines: {node: '>= 6'} + css-what@8.0.0: + resolution: {integrity: sha512-DH0Bqq3DNp5tdOReuNyAA+Ev4Y2GS5FMbZpeTLP6C4CDi0h5nL0BmUPChXw3o/qbHLDWHl49sbNqQVY7bMSDdw==} + engines: {node: '>=20.19.0'} cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} @@ -5702,9 +6051,9 @@ packages: custom-event@1.0.1: resolution: {integrity: sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==} - cypress@15.18.1: - resolution: {integrity: sha512-JtkTVtUE2lvLYgZCaug+Uai0H9IqsJirlBO49c87QwG0bJUGvAUVBz1EJve0b0oaYP244Ew9M0BkrHpcqkYxmw==} - engines: {node: ^20.1.0 || ^22.0.0 || >=24.0.0} + cypress@16.0.0: + resolution: {integrity: sha512-/H3zsayGwIGboFIiLWaXxy6ADmCdWy5QjjDBZgslCvjIgYAf1DkZerwAM7wXMPSpfpQ4w+lGjFlmwneRBpg27g==} + engines: {node: ^22.0.0 || ^24.0.0 || >=26.0.0} hasBin: true cytoscape-cose-bilkent@4.1.0: @@ -5717,8 +6066,8 @@ packages: peerDependencies: cytoscape: ^3.2.0 - cytoscape@3.34.0: - resolution: {integrity: sha512-62rNSrioXw93uliKFBwjukeQyeWwH2PqDrTac31r2P6464u3AUvTk0xS4LVvT251g7IgkFunrI48ZEZGjywSOg==} + cytoscape@3.34.2: + resolution: {integrity: sha512-Cm2jaj1X/PBNlzV9yH8zcfGOxO7U+CJ/+mxSBVPSchLaugdp4jtlGx5qaHtPRZ6tgiZ5P+o1XoRfJA+ba6KM3g==} engines: {node: '>=0.10'} d3-array@2.12.1: @@ -5899,8 +6248,8 @@ packages: resolution: {integrity: sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==} engines: {node: '>=4.0'} - dayjs@1.11.21: - resolution: {integrity: sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==} + dayjs@1.11.23: + resolution: {integrity: sha512-QDTCU0M0MxR3hQfnlDJfwekQiaanm1ubOD231u73WBckQ/fsamwRLiE2GBz6D3a/xF1NgfiDLJjXBa1hYOYTtQ==} debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} @@ -5949,10 +6298,6 @@ packages: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} - decamelize@4.0.0: - resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} - engines: {node: '>=10'} - decimal.js@10.6.0: resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} @@ -5986,8 +6331,8 @@ packages: resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} engines: {node: '>=18'} - default-browser@5.5.0: - resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==} + default-browser@5.5.1: + resolution: {integrity: sha512-m1pAzaJgZ/gssEqlOhJkPJp8Xly7QyW6xcrkUa2KKcDeDSEMP7X8xipU3snUcfisTQx0w1AGae+9UtJSfVnXGw==} engines: {node: '>=18'} defaults@1.0.4: @@ -6061,10 +6406,6 @@ packages: resolution: {integrity: sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==} engines: {node: '>=0.3.1'} - diff@7.0.0: - resolution: {integrity: sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==} - engines: {node: '>=0.3.1'} - diff@9.0.0: resolution: {integrity: sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==} engines: {node: '>=0.3.1'} @@ -6081,23 +6422,48 @@ packages: dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + dom-serializer@3.1.1: + resolution: {integrity: sha512-4MEa38/QexBob6gFNwu+EGdWvhJ1OKuNwdYY3Y3NyeWDQfnGeDYQUDfIRzWu5B5gsv03so2Uxd28YC6zrsx3Lw==} + engines: {node: '>=20.19.0'} + domelementtype@2.3.0: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + domelementtype@3.0.0: + resolution: {integrity: sha512-umCQid3jKbDmVjx8jGaW7uUykm4DEUeyV21hPxNMo2nV955DhUThwqyOIDtreepP31hl84X7G5U9ZfsWvIB3Pg==} + engines: {node: '>=20.19.0'} + domhandler@5.0.3: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} - dompurify@3.4.12: - resolution: {integrity: sha512-zQvGet8Z2sWbQhCmfFz/T5QWH2oBmjnqK3qvOjaqaNLrLEF912WamU+ohnTp0TCep/MFVHpdJuCZEdFOdTnEFg==} + domhandler@6.0.1: + resolution: {integrity: sha512-gYzvtM72ZtxQO0T048kd6HWSbbGCNOUwcnfQ01cqIJ4X2IYKFFHZ5mKvrQETcFXxsRObZulDaKmy//R7TPtsBg==} + engines: {node: '>=20.19.0'} + + dompurify@3.4.14: + resolution: {integrity: sha512-dVoH9z+MY+C9IilgGCk3YfFqjLi3fChm2OiKJMzh6axrJ5qwxqWaZamgmHrpv22CN/KdbZJuGEGgfQoL00LTdg==} domutils@3.2.2: resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + domutils@4.0.2: + resolution: {integrity: sha512-qI4JLRKnSzqFqr7hAlS5xQDusBCjKSEG4t4+7aNrIQMHBcsC2TGEhuyABJdYkgSewL57PNLYEiibY2iPKhKpaA==} + engines: {node: '>=20.19.0'} + dot-prop@5.3.0: resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} engines: {node: '>=8'} + dts-resolver@3.0.0: + resolution: {integrity: sha512-1T1f+z+4tl9XD+m+0HBgWoL/nm0bOIffyWaUuUSBlFg/86IWvfx+wjNaO/ybU0AJzG9/Mi5hBUgGV6zCmWEN7Q==} + engines: {node: ^22.18.0 || >=24.0.0} + peerDependencies: + oxc-resolver: '>=11.0.0' + peerDependenciesMeta: + oxc-resolver: + optional: true + dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -6133,8 +6499,8 @@ packages: engines: {node: '>=0.12.18'} hasBin: true - electron-to-chromium@1.5.389: - resolution: {integrity: sha512-cEto7aeOqBfU1D+c5py5pE+ooscKE75JifxLBdFUZsqAxRS6y7kebtxAZvICszSl05gPjYHDTjY+lXpyGvpJbg==} + electron-to-chromium@1.5.417: + resolution: {integrity: sha512-4T+DTDWuMPM4aHlHwWdAVCVWwp7LDilnhzkj+c/Lbj91XSQrLuOmZSLtS9Q4iIqjlPUbPOnC624zDVVHCHaolQ==} emittery@0.13.1: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} @@ -6235,8 +6601,8 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - es-module-lexer@2.3.1: - resolution: {integrity: sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==} + es-module-lexer@2.3.2: + resolution: {integrity: sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==} es-object-atoms@1.1.2: resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} @@ -6250,8 +6616,8 @@ packages: resolution: {integrity: sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==} engines: {node: '>= 0.4'} - es-toolkit@1.49.0: - resolution: {integrity: sha512-G5iZ6Pc/FNRY/soKZHC+TxGDD83rHUDXxzaWhGCX44vAv/tMs56WMusnm/KMNK+luUPsgA9U28cGr4RDlSzL2g==} + es-toolkit@1.52.0: + resolution: {integrity: sha512-XTNEJQh1tY1ZJVcf6ayP/2n4ZPyaHlW2FWs7xvw5ddPuhUVjLD3olQVQS7kf58JbAB48iL0uL/jerTrjtV3lDA==} es6-promise@4.2.8: resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} @@ -6262,8 +6628,8 @@ packages: esbuild-plugin-umd-wrapper@3.0.0: resolution: {integrity: sha512-Ht3jrO7r8oF8FgPIhMnfNQvYLHhz2QA1ggPqfBhoVq0VfYNczqJ6nwQ4PhO5UvrUymn+Q0Nc50xpiDbxI+KR2Q==} - esbuild@0.28.1: - resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} + esbuild@0.28.2: + resolution: {integrity: sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==} engines: {node: '>=18'} hasBin: true @@ -6286,10 +6652,6 @@ packages: resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} engines: {node: '>=8'} - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - escodegen@2.1.0: resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} engines: {node: '>=6.0'} @@ -6344,8 +6706,8 @@ packages: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} - eventsource-parser@3.1.0: - resolution: {integrity: sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==} + eventsource-parser@3.1.1: + resolution: {integrity: sha512-EKN1vKAMcZ8MlYMpaNuxN6R9yakzH6uajHcHVTqWJzvu5pWw9DyhbP35HH8MVBQ+dZjAfDxk+A8NiR9KWaXiyQ==} engines: {node: '>=18.0.0'} eventsource@3.0.7: @@ -6399,8 +6761,8 @@ packages: exponential-backoff@3.1.3: resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==} - express-rate-limit@8.5.2: - resolution: {integrity: sha512-5Kb34ipNX694DH48vN9irak1Qx30nb0PLYHXfJgw4YEjiC3ZEmZJhwOp+VfiCYwFzvFTdB9QkArYS5kXa2cx2A==} + express-rate-limit@8.7.0: + resolution: {integrity: sha512-hOwV7WOxXfjRpAM1DSJWZDXx3GhplwD8IfwuwvogD8i1Qnkgosw/H45s4ZnFAUHDAhPjlY9hLBvJhKmGMyY26g==} engines: {node: '>= 16'} peerDependencies: express: '>= 4.11' @@ -6446,18 +6808,21 @@ packages: fast-string-width@3.0.2: resolution: {integrity: sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==} - fast-uri@3.1.3: - resolution: {integrity: sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg==} + fast-uri@3.1.6: + resolution: {integrity: sha512-7Ical1vFEMr0onbVzEDIreM22I4khW+fzyQPwvAFWBp1iwdshSZRsL4jjRvPG9JP1uiqMHRto+YU6R2/CzDz5Q==} fast-wrap-ansi@0.2.2: resolution: {integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==} + fastdom@1.0.12: + resolution: {integrity: sha512-LB+xjSTEbjHE1cWsxu+tN2Xqr1kpi+V9aADI7sVM5ZMaXyYGPHULQMzpJMYqOTULK/73pUkWVzzObFRBkPr+hg==} + fastest-levenshtein@1.0.16: resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} engines: {node: '>= 4.9.1'} - fastq@1.20.1: - resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + fastq@1.20.3: + resolution: {integrity: sha512-XKv5nnLs6nLF71NgiKJLIZFLkPyIEuOselLG7ujZnGrRfQK8HpvY+WqKhAJUAdLomwVHErVS4LfxFlPq0/FTAw==} faye-websocket@0.11.4: resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==} @@ -6528,24 +6893,20 @@ packages: resolution: {integrity: sha512-OFRzsL6ZMHz5s0JrsEr+TpdGNCtrVtnuG3x1yzGNiQHT0yaDnXAj8V/lWcpJVrnoDpcwXcASxAZYbuXda2Y82A==} engines: {node: '>= 10.13.0'} - firebase-tools@15.23.0: - resolution: {integrity: sha512-YIu1w84GiJAoQfCDBvrK77Qnu19sh00YufGvrWLc9kus9p8j5NkFOGfSpIAiEHu5VliTZUqBhqDwA/i7fuN0GQ==} + firebase-tools@15.28.2: + resolution: {integrity: sha512-oC4qfRyY+voiNGR3JHmpfZ68SSNl4QjrLS625bvflxDnvWN1PumDSGWYkfZjs1XIosceSDHM7x5cGzBMxswi5w==} engines: {node: '>=20.0.0 || >=22.0.0 || >=24.0.0'} hasBin: true - firebase@12.16.0: - resolution: {integrity: sha512-CNw6hFBdONkzF8UGLDx/RDRY9gVa5VmJNHd7qi4gdmA3ZuLkuOrhmWefB2l+FN+OxFpN77Itq7aO6zlTi780ag==} + firebase@12.18.0: + resolution: {integrity: sha512-XaL6tlE5Xd20ZDhckqOMIw+JJTET+wTdeZPxQ7ihc42oxRb7kWUyn/j1LO5V9dH1xq8Rv5R71Pv1fBCdIkt9Rw==} flagged-respawn@2.0.0: resolution: {integrity: sha512-Gq/a6YCi8zexmGHMuJwahTGzXlAZAOsbCVKduWXC6TlLCjjFRlExMJc4GC2NYPYZ0r/brw9P7CpRgQmlPVeOoA==} engines: {node: '>= 10.13.0'} - flat@5.0.2: - resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} - hasBin: true - - flatted@3.4.2: - resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} + flatted@3.4.4: + resolution: {integrity: sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==} fn.name@1.1.0: resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} @@ -6617,8 +6978,8 @@ packages: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} - fs-extra@11.3.6: - resolution: {integrity: sha512-w8ZNZr2mKIc7qeNaQ9AVPT1+iFaI+Avd4xudVOvdDJ8VytREi1Ft5Ih7hd9jjehod8vAM5GMsfQ/TpPf4EyoEA==} + fs-extra@11.4.0: + resolution: {integrity: sha512-EQsFzMUJkCKGr1ePqlYADkIUmHW1s3ZXr5Yqy6wbGrfUCphpl2maM/kyOIRA2HpP3AaFQTZXD4ldjek+nccddA==} engines: {node: '>=14.14'} fs-extra@8.1.0: @@ -6663,8 +7024,8 @@ packages: resolution: {integrity: sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==} engines: {node: '>=18'} - gaxios@7.2.0: - resolution: {integrity: sha512-CUVb4wcYe+771XevyH6HtGmXFAGGKkIC3kswAP8Z1JCe0j80JMaTPZH930DWFrvo0atjh18Arc0pEyUCWa5bfg==} + gaxios@7.3.1: + resolution: {integrity: sha512-kB3rzJV7d9juLZh8/56QTXCwQfxyhdOMdyYk1HdQKFtF8TJTDTZQJtixWIwXdE9Jji91mC41DUNpjleo4L4eAQ==} engines: {node: '>=18'} gcp-metadata@6.1.1: @@ -6675,8 +7036,8 @@ packages: resolution: {integrity: sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==} engines: {node: '>=18'} - gcp-metadata@8.1.3: - resolution: {integrity: sha512-ziTrzUhhpL9Zk5k0HHzgP/KIpWDJT0VMBC/ynt/QIBvTW+UUcSivQRl6VlwTf/EilDxtSWklHoRsKy1c4k+59w==} + gcp-metadata@8.1.4: + resolution: {integrity: sha512-iJ9KMsiu+xKtNRX0PmGLSaIU3bUBAyzWTyqKemKPzNPsmmsBCQYmlNg+brEbES7IHSXtdVwzBPzx1vz3FAaipw==} engines: {node: '>=18'} generator-function@2.0.1: @@ -6722,8 +7083,12 @@ packages: resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} - get-tsconfig@4.14.0: - resolution: {integrity: sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==} + get-tsconfig@4.14.3: + resolution: {integrity: sha512-++QEw4DIY7WGoukz+/+A/8dGYPT9l9yIadnmSgZ8Rjr3YVSVDipQSO9CdnJo9ePqFqUUqh+wk9uIaoiAwsiPkA==} + + get-tsconfig@5.0.0-beta.6: + resolution: {integrity: sha512-X6fBC0pmImC70gvX2zm56go9hx0MyoGVdG0tUCkg/D+Xnh5TJsOZ7iDbOdI3PvmtrDxnu1YdDufpK2QJX1Meqw==} + engines: {node: '>=20.20.0'} get-uri@6.0.5: resolution: {integrity: sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==} @@ -6820,16 +7185,16 @@ packages: resolution: {integrity: sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w==} engines: {node: '>=18'} - google-auth-library@10.9.0: - resolution: {integrity: sha512-xtvUqvINPhTaBm7nXqlYPcrMHJPm1lCNdSovxnKKhTm+4JsvQ+KGVYJViLoH9Yxu8w+T0Qv5HubzYT9BLrppJg==} + google-auth-library@10.9.1: + resolution: {integrity: sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw==} engines: {node: '>=18'} google-auth-library@9.15.1: resolution: {integrity: sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==} engines: {node: '>=14'} - google-gax@5.0.7: - resolution: {integrity: sha512-EhiqaWWJ+9h7sCcKJTsoo6tMcjokVHhWsbSuWCnZJT4vIBP3y4mAoFLnt9SzgkVZeq24ZsFaArr06nnYYku2yA==} + google-gax@5.0.8: + resolution: {integrity: sha512-M4vpZcXQIC1gqIVGQ7eaU3jXQA6zecStyTXu514TYfThlgSurYJOxHZo9fzU6hAgwPWvuEynAVHWyaIk80VeEA==} engines: {node: '>=18'} google-logging-utils@0.0.2: @@ -6840,13 +7205,13 @@ packages: resolution: {integrity: sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==} engines: {node: '>=14'} - google-logging-utils@1.1.4: - resolution: {integrity: sha512-LXxE6ND+JHhDPYtPFt3oeWrjxFPrnRZCZ4At6lpbi1ZDSAN7bmGET9s53vvARbxT93p+xpeDUbc/nCR4C+7vcw==} - engines: {node: '>=14'} + google-logging-utils@1.2.0: + resolution: {integrity: sha512-WE9av4wKDZgRjBwgVUabocx8T6/7o3Ca1Fat46FXDhXVAFibzNadedcOXrdgd1Kzmk8tsk/9ZH89Wyf/SqeZ3A==} + engines: {node: '>=18'} - googleapis-common@8.0.2: - resolution: {integrity: sha512-5MXeQzIZaqCH7B+HJWqhQm946VARpZep6acbWSr/fcgF2cQANq7allgX+i/G0EqF0WyUxB277gtWMzRYHMl9tg==} - engines: {node: '>=18.0.0'} + googleapis-common@8.0.3: + resolution: {integrity: sha512-7g1yzQKx0mmNTjiK0H9dJ8eqKqDBveES9vLHeg5neb3BMQy/d1oQefIMhIpOVT8a+f+LOcixMEdRbFIW/cQUJw==} + engines: {node: '>=18'} gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} @@ -6868,11 +7233,9 @@ packages: resolution: {integrity: sha512-Chq1s4CY7jmh8gO2qvLIJyfCDIN+EHLFW/9iShnp1z8FjBQMoodWP1kDC36VAMXXIvAjj4ARa7ntfAV2BrjsbA==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} - grpc-gcp@1.0.1: - resolution: {integrity: sha512-06r73IoGaAIpzT+DRPnw7V5BXvZ5mjy1OcKqSPX+ZHOgbLxT+lJfz8IN83z/sbA3t55ZX88MfDaaCjDGdveVIA==} + grpc-gcp@1.1.1: + resolution: {integrity: sha512-I3GNn9ONy5Vrm6XdjgOu7296DnN9vudnjv7dXKW2jAogfS20YMYZAzfZNkJUMgdpQTtLJ9t+DQCzYgGBpdYuwA==} engines: {node: '>=12'} - peerDependencies: - protobufjs: '*' gtoken@7.1.0: resolution: {integrity: sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==} @@ -6985,8 +7348,8 @@ packages: resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} engines: {node: '>=0.10.0'} - hono@4.12.30: - resolution: {integrity: sha512-emn+JoJjrN9YTpRDS5it/UI2SO9BAE37T6I3d963RxcZ81G9A4pr2SZTEiiaiKbzx+NKRg5BZ89fCL7gCJCUog==} + hono@4.13.5: + resolution: {integrity: sha512-O6+/eCYRkzzzy0rPWwKLiGBR1nFuUPZynnwjxN1MBA62NNqbT0wQEzQyK2gSO5yDIDB336sXQleAhOHrzlYyKw==} engines: {node: '>=16.9.0'} hosted-git-info@10.1.1: @@ -7025,6 +7388,10 @@ packages: htmlparser2@10.1.0: resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==} + htmlparser2@12.0.0: + resolution: {integrity: sha512-Tz7u1i95/g2x2jz81+x0FBVhBhY5aRTvD3tXXdFaljuNdzDLJ8UGNRrTcj2cgQvAg3iW/h77Fz15nLW0L0CrZw==} + engines: {node: '>=20.19.0'} + http-errors@2.0.1: resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} @@ -7096,15 +7463,10 @@ packages: ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - ignore@7.0.6: - resolution: {integrity: sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==} + ignore@7.0.7: + resolution: {integrity: sha512-dML0wP6oak21rsNYCJpJB6O1BJIEwNpGrTw0URPfAk4hm0e3pRfCtzkfB6olBcXcVlU2rouCyz7lCyRB0OMVCA==} engines: {node: '>= 4'} - image-size@0.5.5: - resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} - engines: {node: '>=0.10.0'} - hasBin: true - immediate@3.0.6: resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} @@ -7148,8 +7510,8 @@ packages: injection-js@2.6.1: resolution: {integrity: sha512-dbR5bdhi7TWDoCye9cByZqeg/gAfamm8Vu3G1KZOTYkOif8WkuM8CD0oeDPtZYMzT5YH76JAFB7bkmyY9OJi2A==} - install-artifact-from-github@1.7.0: - resolution: {integrity: sha512-qAb91yAKVF9rFY4rVP21ZtYUyCScxAFt9udwzVWNLBE1pQcdQeB2gd1HlNPcQNYCzCDvJ/QJQPuWQ6aTmSlU8g==} + install-artifact-from-github@1.8.0: + resolution: {integrity: sha512-EA861BGTOO91yuymA5V6Sx//J5471NBpMHnVZJetquqOYknm4zz25Y2tk/f74ggxerqtd8nfBrn9eaR0oxReEA==} engines: {node: '>=18'} hasBin: true @@ -7168,8 +7530,8 @@ packages: resolution: {integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==} engines: {node: '>=10.13.0'} - ip-address@10.2.0: - resolution: {integrity: sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==} + ip-address@10.7.0: + resolution: {integrity: sha512-BGFsyJd5mpXp3rK6jIdADLNgpJUK1jnjzvYF8lK+VyDab9JAmqN0YOKDdP17HlgKb2+ehPgDc8EtnRLbGCAMhA==} engines: {node: '>= 12'} ip-regex@2.1.0: @@ -7336,12 +7698,8 @@ packages: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} - is-plain-obj@2.1.0: - resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} - engines: {node: '>=8'} - - is-plain-object@5.0.0: - resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} + is-plain-object@5.1.0: + resolution: {integrity: sha512-bUi/yjmtKYcRVUtWRGr0UA6xEFh2I6zWUwMrUXB3s7bmYCaZ8a+0ZsTRkrawh/mzlSD1Y0Ph8bp/U+TvBpWDNw==} engines: {node: '>=0.10.0'} is-potential-custom-element-name@1.0.1: @@ -7697,8 +8055,8 @@ packages: join-path@1.1.1: resolution: {integrity: sha512-jnt9OC34sLXMLJ6YfPQ2ZEKrR9mB5ZbSnQb4LPaOx1c5rTzxpR33L18jjp0r75mGGTJmsil3qwN1B5IBeTnSSA==} - jose@6.2.3: - resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==} + jose@6.2.10: + resolution: {integrity: sha512-iiW7J9qRFlGxvCOIBDBDxFePQSn7ZMAnrYGhrrOo6siO/MIqwfyilLR27pkfDgUk+raLuzADS8A3S/KLBisc0g==} js-tokens@10.0.0: resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} @@ -7706,12 +8064,16 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@3.15.0: - resolution: {integrity: sha512-ttBQIIQPDeLjpPOohtUdXuXUVoA2uIB6fEH9HyJ7234s5mBJ5wTx20njxplLZQgLaOfpmPQA7X2t5AX6tIPbog==} + js-yaml@3.15.2: + resolution: {integrity: sha512-6EuL879VkRA+1Cz578mKMiKvjPNEuk6+r1JaFzoSWejZmtf7xWbIyw1e3KkxlkzTIt9Taw6JBhEppG7utc1P+w==} hasBin: true - js-yaml@4.3.0: - resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==} + js-yaml@4.3.2: + resolution: {integrity: sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==} + hasBin: true + + js-yaml@5.4.1: + resolution: {integrity: sha512-28R/k+NAjeuf7+CKlTxWZVExJGwVVLwY06DgEnOMz2gEpfNkDcD7QvyiVPT0xy0XXhU8vHsd4Ot42OOPdJG7dQ==} hasBin: true jsbn@0.1.1: @@ -7726,11 +8088,11 @@ packages: canvas: optional: true - jsdom@29.1.1: - resolution: {integrity: sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24.0.0} + jsdom@30.0.1: + resolution: {integrity: sha512-52v7mUVUfNQVYYqE1lcdaymWL0njO7lTLUog6ZvW2U5KsbiLk/GnZlVJ+qx0xfNJZ6Gn+KSpPNE52vurbxZwrA==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} peerDependencies: - canvas: ^3.0.0 + canvas: ^3.2.3 peerDependenciesMeta: canvas: optional: true @@ -7768,8 +8130,8 @@ packages: json-stringify-safe@5.0.1: resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} - json-with-bigint@3.5.10: - resolution: {integrity: sha512-Vcx+JVNEBts/xfcoCS69sKrOhOk/3TVlvlT+XzUOefVKnnrbYSCKpDCm10pohsJFtsJVYnwa/cXRZ4eElzaM6w==} + json-with-bigint@3.5.12: + resolution: {integrity: sha512-uwbF/wSSuOgC7qqlq27Xp5B6a2MHVug3t0idZdTqu0JnlFvgJuH7ju+KAk/J06C7GfhoYy2gnb9wz2INqcne7w==} json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} @@ -7816,10 +8178,10 @@ packages: karma-firefox-launcher@2.1.3: resolution: {integrity: sha512-LMM2bseebLbYjODBOVt7TCPP9OI2vZIXCavIXhkO9m+10Uj5l7u/SKoeRmYx8FYHTVGZSpk6peX+3BMHC1WwNw==} - karma-jasmine-html-reporter@2.2.0: - resolution: {integrity: sha512-J0laEC43Oy2RdR5V5R3bqmdo7yRIYySq6XHKbA+e5iSAgLjhR1oICLGeSREPlJXpeyNcdJf3J17YcdhD0mRssQ==} + karma-jasmine-html-reporter@2.3.0: + resolution: {integrity: sha512-iFDjVpcWHnupRoJfnjuAeNF68sAGk+7RfceCzm33HHYNV6OgBa6EC1nPgJUFM+tVDHLlQ5NhgcTKz7AbdrV3AQ==} peerDependencies: - jasmine-core: ^4.0.0 || ^5.0.0 || ^6.0.0 + jasmine-core: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 karma: ^6.0.0 karma-jasmine: ^5.0.0 @@ -7868,8 +8230,8 @@ packages: resolution: {integrity: sha512-DpMa59o5uGUWWjruMp71e6knmwKU3jRBBn1kjuLWN9EeIOxNeSAwvHf03WIl8g/ZMR2oSQC9ej3yeLBwdDc/pg==} engines: {node: '>=10.13.0'} - less@4.6.7: - resolution: {integrity: sha512-o3UxHBPPVY1HtCXx15/z1NlknQiWyafRNbtLEv+6xFaDRI2g2xPKIH43do9dSwt8bGLTsjNSaifa48N3d6odsQ==} + less@4.9.0: + resolution: {integrity: sha512-umRhrCH7fCi8Uj2RcwKjJdvUORTjeWqkdKx0LbcZvjIwsAVsnIAGcxHaqowPeBFBjQuWOeC/bve0AlpFzF/+SQ==} engines: {node: '>=18'} hasBin: true @@ -7890,78 +8252,78 @@ packages: resolution: {integrity: sha512-wwLXMbuxSF8gMvubFcFRp56lkFV69twvbU5vDPbaw+Q+/rF8j0HKjGbIdlSi+LuJm9jf7k9PB+nTxnsLMPcv2Q==} engines: {node: '>=10.13.0'} - lightningcss-android-arm64@1.32.0: - resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + lightningcss-android-arm64@1.33.0: + resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [android] - lightningcss-darwin-arm64@1.32.0: - resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + lightningcss-darwin-arm64@1.33.0: + resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] - lightningcss-darwin-x64@1.32.0: - resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + lightningcss-darwin-x64@1.33.0: + resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] - lightningcss-freebsd-x64@1.32.0: - resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + lightningcss-freebsd-x64@1.33.0: + resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] - lightningcss-linux-arm-gnueabihf@1.32.0: - resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + lightningcss-linux-arm-gnueabihf@1.33.0: + resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] - lightningcss-linux-arm64-gnu@1.32.0: - resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + lightningcss-linux-arm64-gnu@1.33.0: + resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] libc: [glibc] - lightningcss-linux-arm64-musl@1.32.0: - resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + lightningcss-linux-arm64-musl@1.33.0: + resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] libc: [musl] - lightningcss-linux-x64-gnu@1.32.0: - resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + lightningcss-linux-x64-gnu@1.33.0: + resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] libc: [glibc] - lightningcss-linux-x64-musl@1.32.0: - resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + lightningcss-linux-x64-musl@1.33.0: + resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] libc: [musl] - lightningcss-win32-arm64-msvc@1.32.0: - resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + lightningcss-win32-arm64-msvc@1.33.0: + resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] - lightningcss-win32-x64-msvc@1.32.0: - resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + lightningcss-win32-x64-msvc@1.33.0: + resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] - lightningcss@1.32.0: - resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + lightningcss@1.33.0: + resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} engines: {node: '>= 12.0.0'} lilconfig@3.1.3: @@ -7974,8 +8336,8 @@ packages: linkify-it@5.0.2: resolution: {integrity: sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==} - listr2@10.2.2: - resolution: {integrity: sha512-JtNtbZj8q5BnDMR7trpwvwk3RIrANtIVzEUm8w7amp6xelLgyuq+4WZoTH913XaQAoH/cNdYhaNzBPA2U3xbDw==} + listr2@11.1.0: + resolution: {integrity: sha512-xsuczF6mWkEo/E80QHaEokQzKmTy7m80KcLRnkUt9wrcePres2w7dbQi5zOsWtDUg8Dac4gPFyu4EJ/IvKwTOg==} engines: {node: '>=22.13.0'} listr2@9.0.5: @@ -8024,6 +8386,9 @@ packages: lodash.isstring@4.0.1: resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + lodash.once@4.1.1: resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} @@ -8052,6 +8417,10 @@ packages: resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} engines: {node: '>=18'} + log-update@8.0.0: + resolution: {integrity: sha512-lddSgOt3bPASrylL54ZSpy8nBHns+vBVSoILlVOx+dei300pnLRN958rj/EdlVLKuWlSESU3qdnDZdAI7FXYGg==} + engines: {node: '>=22'} + log4js@6.9.1: resolution: {integrity: sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==} engines: {node: '>=8.0'} @@ -8091,6 +8460,12 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + magic-string@1.2.3: + resolution: {integrity: sha512-Bpb0W2TbLKOZ7vJnOUnVRGq3WL2p+ISV29M6hYPL1AFCpyKZpdr5ytiXoTSSxRVhg8YW7f65+6gbG8WG6PCa/g==} + + magic-string@1.4.1: + resolution: {integrity: sha512-8lyCu36ErXR0J9uaGKlKQoiLZKmtI63YGLE8G2o9jyRPdr4X47LusSOwgOJOzcVtp81fTAAjxR7BwKz682Jhow==} + make-dir@3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} @@ -8113,8 +8488,8 @@ packages: resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} engines: {node: '>=0.10.0'} - markdown-it@14.3.0: - resolution: {integrity: sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw==} + markdown-it@14.3.1: + resolution: {integrity: sha512-4Ej49aYTDFIQ+uBkfX8GBvJGccoARxxPep+7aWTs55ozbjQJpW9M26Fe53vnGgvLeVzva/amzjQQaQu9w0vMhA==} hasBin: true marked-terminal@7.3.0: @@ -8133,13 +8508,8 @@ packages: engines: {node: '>= 20'} hasBin: true - marked@18.0.5: - resolution: {integrity: sha512-S6GcvALHg6K4ohtu4E7x0a1AqhAjp6cV8KhLSyN9qVapnzJkusVBxZRcIU9AeYsbe6P1hKDusSbEOzGyyuce6w==} - engines: {node: '>= 20'} - hasBin: true - - marked@18.0.6: - resolution: {integrity: sha512-MrV5puXBfuiy6wl6DLaq3BtIJQAJToAd5zt/ZKhRfGRAuFPALE7/4Y7jnxRQoEgK/pBgurGqLyAuRgZ2xOjr6w==} + marked@18.0.11: + resolution: {integrity: sha512-HnslJfsZkRPBDJRHvVtAaWlZHEpSu7u8LgQuJCELjRKuWR+hpq4A7sLq3p8HaI9ypVoXDXxV34CsQJEe1+J5Aw==} engines: {node: '>= 20'} hasBin: true @@ -8153,15 +8523,15 @@ packages: mdn-data@2.27.1: resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} - mdurl@2.0.0: - resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + mdurl@2.1.0: + resolution: {integrity: sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg==} media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} - media-typer@1.1.0: - resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} + media-typer@1.1.1: + resolution: {integrity: sha512-yz3xRaG20c6/BOzvYoDaGtPmGscs7YivItZEEqe6GbwNfHuxu9YNmvnEkMzKldAGY4/80pRcQRZSEnhquk9XuQ==} engines: {node: '>= 0.8'} memoizeasync@1.1.0: @@ -8185,8 +8555,8 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - mermaid@11.16.0: - resolution: {integrity: sha512-Zvm3kbstgdpvIJPPItlL7fppIZ3kibvc1oZIGxdvk9t6UFz6flv+Jw7FtRGKwfcI8OckmH04LqG6LlS6X4B1pA==} + mermaid@11.17.2: + resolution: {integrity: sha512-V6K3C8EBdEsPFZXSKMJe6ppQOENxuHARr9GvHX4hh47lAbhMRD9qf4oEK7LoaRQxULMa80/qt5gHO73aCleBBg==} methods@1.1.2: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} @@ -8249,8 +8619,8 @@ packages: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} engines: {node: '>=10'} - minimatch@10.2.5: - resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + minimatch@10.2.6: + resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} engines: {node: 18 || 20 || >=22} minimatch@3.1.5: @@ -8295,9 +8665,9 @@ packages: engines: {node: '>=10'} hasBin: true - mocha@11.7.6: - resolution: {integrity: sha512-nS9xOGbw2I3cjCpxwZAEJ9xK9lmJ08vEkQvLtz4du9ZrF9UrjRpeJGiIgl2Z+Qs++pmB4ecDe48Fwsh+j+j7xA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + mocha@12.0.0: + resolution: {integrity: sha512-NYNh5IFt6WYqm9bi4601m7vix8MZdXC0DwS4gY6WhXO2RgJWhivhISVmq1oklCif18OSI9l+vx5Mdm5oh1XGiQ==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true mock-require@3.0.3: @@ -8307,8 +8677,8 @@ packages: moo@0.5.3: resolution: {integrity: sha512-m2fmM2dDm7GZQsY7KK2cme8agi+AAljILjQnof7p1ZMDe6dQ4bdnSMx0cPppudoeNv5hEFQirN6u+O4fDE0IWA==} - morgan@1.11.0: - resolution: {integrity: sha512-zSkVu3t18r39pw4ixfBKvfZi3y2UOqr7d4WYwcj3m8nXpEQK4rPO6GLzs/CExoRgmX3y9EjmmcXqv6jq0SK46g==} + morgan@1.12.0: + resolution: {integrity: sha512-OHpTRQwn2ezasILW8iKe+Yww1XsfWsZIpUOLF7RDb2g5GwO3trPaRwi7+8BDiJ7HFx2Kg2mfUdCBcVhwYlOz2g==} engines: {node: '>= 0.8.0'} mrmime@2.0.1: @@ -8356,8 +8726,8 @@ packages: nan@2.28.0: resolution: {integrity: sha512-fTsDz99OTq2sVePhGdp4qQhggZFtKr64ZNVyVajRKtMOkJxYekplBh577PiJB12v/D3s2E5cGtOI45LWp6rnLQ==} - nanoid@3.3.16: - resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} + nanoid@3.3.18: + resolution: {integrity: sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -8376,6 +8746,11 @@ packages: resolution: {integrity: sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==} hasBin: true + needle@2.9.1: + resolution: {integrity: sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==} + engines: {node: '>= 4.4.x'} + hasBin: true + needle@3.5.0: resolution: {integrity: sha512-jaQyPKKk2YokHrEg+vFDYxXIHTCBgiZwSHOoVx/8V3GIBS8/VN6NdVRmg8q1ERtPkMvmOvebsgga4sAj5hls/w==} engines: {node: '>= 4.4.x'} @@ -8389,9 +8764,9 @@ packages: resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} engines: {node: '>= 0.6'} - negotiator@1.0.0: - resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} - engines: {node: '>= 0.6'} + negotiator@1.1.0: + resolution: {integrity: sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==} + engines: {node: '>=18'} neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} @@ -8400,12 +8775,12 @@ packages: resolution: {integrity: sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA==} engines: {node: '>= 0.4.0'} - ng-packagr@22.1.0-next.3: - resolution: {integrity: sha512-wl36HBl2TCU2O4JOl4iGeKALBtkX1yaiW/GEnzYiTLuQQqlNSuhUWFFl9Y/nzrcnjKlcJkg2CoKdF+PSu8amfg==} + ng-packagr@22.2.0-next.5: + resolution: {integrity: sha512-fZixAT5MGDlxZnPISy1ml22DeOFVMwt3Ym/6l/VwzuAlj1K0YVJNgxxRQs+iX/qqDzcXjyVD+CQAAwAq5pQo3Q==} engines: {node: ^22.22.3 || ^24.15.0 || >=26.0.0} hasBin: true peerDependencies: - '@angular/compiler-cli': ^22.1.0-next + '@angular/compiler-cli': ^22.2.0-next tailwindcss: ^2.0.0 || ^3.0.0 || ^4.0.0 tslib: ^2.3.0 typescript: '>=6.0 <6.1' @@ -8413,8 +8788,8 @@ packages: tailwindcss: optional: true - ngx-flamegraph@0.1.1: - resolution: {integrity: sha512-BTyyOnPDXW0Xi5iOd+H03atdiCNdnYNzpkNJ4iqTrkYGJnOnzaMEzdlaN9Jt3Qpjcs3oyvUoJvD85xZnZpzTyQ==} + ngx-flamegraph@0.2.0: + resolution: {integrity: sha512-qupUnKsftllyS1MMnI3rsegmW8XFs6bLYz7dRU84x0+FAykikR9c3ZAcjwYYbghv2PAIv4Ltw7kB9mwkbWbs/w==} peerDependencies: '@angular/common': ^20.0.0 '@angular/core': ^20.0.0 @@ -8427,12 +8802,12 @@ packages: '@angular/core': '>=17.3.0' rxjs: '>=7.0.0' - nock@14.0.16: - resolution: {integrity: sha512-8r4KEc6nT1D/fdLD/R1BO1CPaVEL8o40u/guFRJlXabN7vr3RmMqyjsY5Krt0nMwhsOAwXQ/mtN5vy5Jh3aErg==} + nock@14.0.17: + resolution: {integrity: sha512-EjRr1weMa4ALQX35AgZTEnP+weJJjlW1KGDiNM2IQC2069YDHas4f4B4UUYR+TTLyKWxJvOz2wObDKQs/LNreA==} engines: {node: '>=18.20.0 <20 || >=20.12.1'} - node-abi@3.94.0: - resolution: {integrity: sha512-W5ZNO5KRPB5TkYmGVD9F6YqhsglXJzE6etpbmT+f6EQElhiX/UTG551cnsRGvLG3fyZEg9HwaDmNmj5nwJ4z9g==} + node-abi@3.96.0: + resolution: {integrity: sha512-rebQ/lz7i0EkoLzUVSrKRzA69zMkwLp95kKMWoMDkkM00Suxz0D7zEQPwRml5fQum24mj7bPvmlgLAmu2JCiYg==} engines: {node: '>=10'} node-addon-api@4.3.0: @@ -8474,16 +8849,16 @@ packages: resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} hasBin: true - node-gyp@13.0.1: - resolution: {integrity: sha512-piOr0S10qy5THB+q5BdqkoOx65XL/tjTMUAit3vciPNp+snTOBnGunWH1Rz7XZUxf2T9uFrfT/Ty4+aC3yPeyg==} + node-gyp@13.0.2: + resolution: {integrity: sha512-SXTvw3PxznpowYhJSOD9mVQBgDaCTWXffX+wQZsQ7PbcTV86TsXCUcSZhHnskFQvrvn/OdSzJPMsptT2pIj9ww==} engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} hasBin: true node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - node-releases@2.0.51: - resolution: {integrity: sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==} + node-releases@2.0.54: + resolution: {integrity: sha512-YHs7BmmcsdAI5Ozuf8JZo6PT0mv2GIWC9vMfvUC3dp65M8hn7Ux8CPL+2oBI7juNuj9d0ndhTcznq2ODBps9cQ==} engines: {node: '>=18'} node-sarif-builder@3.4.0: @@ -8522,8 +8897,12 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - nwsapi@2.2.24: - resolution: {integrity: sha512-7YRhZ3jS45LwmSCT4b2sVFHt/WuovaktDU07QrtOBY2PXskss5a9jfmR9jptyumwXST+rFjrmppMY1KT/yn35A==} + nth-check@3.0.1: + resolution: {integrity: sha512-GX0gsdbGVCgnRgbeGaubfjpBXyYRWOOCVeYh08bSQvDZqxz5ndXs1OTfAt/h36G1xvI94YIspsI0sVFqAV9+RQ==} + engines: {node: '>=20.19.0'} + + nwsapi@2.2.27: + resolution: {integrity: sha512-gQPNF78qebCQ6tvVFBYrvJdBNOrYZm90ZlXgpIFm06p6qHDHq/XC4TnJftN6OMbxVE0UTBAoRgcsDeJBBooITw==} oauth-sign@0.9.0: resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==} @@ -8556,8 +8935,8 @@ packages: resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} engines: {node: '>=0.10.0'} - obug@2.1.3: - resolution: {integrity: sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==} + obug@2.1.4: + resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==} engines: {node: '>=12.20.0'} on-finished@2.3.0: @@ -8632,10 +9011,14 @@ packages: outvariant@1.4.3: resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==} - own-keys@1.0.1: - resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + own-keys@1.0.2: + resolution: {integrity: sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg==} engines: {node: '>= 0.4'} + oxc-parser@0.149.0: + resolution: {integrity: sha512-iuirONeHJBp6dFuuZKvkCfFvBiF0uFmojIQooGtazR9+GvcwoayGMtal1+cvDUnEw2k435GBish01HOn5iyVqQ==} + engines: {node: ^20.19.0 || >=22.12.0} + p-defer@3.0.0: resolution: {integrity: sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==} engines: {node: '>=8'} @@ -8660,8 +9043,8 @@ packages: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} - p-map@7.0.5: - resolution: {integrity: sha512-e8vJF4XdVkzqqSHguEMz41mQO1wKwxKm5ENrUJQUu9kLDCtn83cxbyHZcszr4QC5zEA7WffRRC4gsTecC7J9oA==} + p-map@7.0.7: + resolution: {integrity: sha512-VaWRu2i4FJNRtiRWCuuQRgfQ1B7a6+gMSrO+3j0EQi/k0ULfS9kosRxGoiqwzIjZTDI02tGfk5mXXltLg6QtfQ==} engines: {node: '>=18'} p-queue@6.6.2: @@ -8672,9 +9055,9 @@ packages: resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} engines: {node: '>=8'} - p-throttle@7.0.0: - resolution: {integrity: sha512-aio0v+S0QVkH1O+9x4dHtD4dgCExACcL+3EtNaGqC01GBudS9ijMuUsmN8OVScyV4OOp0jqdLShZFuSlbL/AsA==} - engines: {node: '>=18'} + p-throttle@8.1.0: + resolution: {integrity: sha512-c1wmXavsHZIC4g1OLhOsafK6jZSAeMo0Ap3yivj59PUcCkpacy5YgWdgIp/dB4vp1JZrfBSsPCR0YuADB+ENLQ==} + engines: {node: '>=20'} p-timeout@3.2.0: resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} @@ -8695,8 +9078,8 @@ packages: package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - package-manager-detector@1.7.0: - resolution: {integrity: sha512-xg1eHpwYL/D/HEdWw2goFZP6vV0FH7W+PZ5rFkGjdIDLtxq7EkzBUeT3m+lndYCt8wKbmofUu1MUdMCXkCk9ZQ==} + package-manager-detector@1.8.0: + resolution: {integrity: sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==} pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} @@ -8808,9 +9191,6 @@ packages: resolution: {integrity: sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==} engines: {node: '>=18'} - pathe@2.0.3: - resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - pegjs@0.10.0: resolution: {integrity: sha512-qI5+oFNEGi3L5HAxDwN2LA4Gg7irF70Zs25edhjld9QemOgp0CbvMtbFcMvFtEo1OityPrcCzkQFB8JP/hxgow==} engines: {node: '>=0.10'} @@ -8840,15 +9220,15 @@ packages: peerDependencies: pg: '>=8.0' - pg-protocol@1.15.0: - resolution: {integrity: sha512-cq9sECI5s0+uPUXjbz8ioyPJni6RzsRib0US67i5IoTZKw8fNeYlVE7u8F4dG7vEJJtc5wdD1K189lCCUwqWTQ==} + pg-protocol@1.16.0: + resolution: {integrity: sha512-sILXutLVjCLjcDuOmvhX5e2Z4cS5qG/6Bu3VkpFwdf/633ElGLpEh9bgmuI5I4sqKqkifQiGyiCcx1HdtrK7tg==} pg-types@2.2.0: resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} engines: {node: '>=4'} - pg@8.22.0: - resolution: {integrity: sha512-8wih1vVIBMxoUM2oB4soJsD9tDnDpLv4OXBJ+EJzFsvycD+lfyIreC2gGHq78f8jbLLt+bvlPTFdFZfJkOuzAA==} + pg@8.23.0: + resolution: {integrity: sha512-Ip2EQCngowJLGOfCwkFhPXU7/ljlhn6Rxlmy4XYfL2Y+vyRM59+8uR2xqRWKdYmbXmxCFOAmKxBuSUCdF34qLg==} engines: {node: '>= 16.0.0'} peerDependencies: pg-native: '>=3.0.1' @@ -8866,8 +9246,8 @@ packages: resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} engines: {node: '>=8.6'} - picomatch@4.0.5: - resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + picomatch@4.0.7: + resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==} engines: {node: '>=12'} pify@2.3.0: @@ -8886,8 +9266,8 @@ packages: resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} engines: {node: '>= 6'} - piscina@5.2.0: - resolution: {integrity: sha512-DszUCKeVN/5G5QKo6jAVHL8fmKnkJvQ0ACiVgY7YGCq3TUB2oznAOayvZPIAdEThvhczkXR+qm3IHsNXpFCYfA==} + piscina@5.3.2: + resolution: {integrity: sha512-vv7l/mM7B9WgrhDaudIqv1x6v4LOBRYYmpWGdWushhpbCmVHp11sUB2v4hj1CAeTGXVxuZFz6xOU1RalAiPKfQ==} engines: {node: '>=20.x'} pkce-challenge@5.0.1: @@ -8902,9 +9282,9 @@ packages: resolution: {integrity: sha512-4peoBq4Wks0riS0z8741NVv+/8IiTvqnZAr8QGgtdifrtpdXbNw/FxRS1l6NFqm4EMzuS0EDqNNx4XGaz8cuyQ==} engines: {node: '>=18'} - playwright-core@1.61.1: - resolution: {integrity: sha512-h7Qlt6m4REp25qvIdvbDtVmD4LqVXfpRxhORv9L0jzETM05p4fuPJ3dKyuSXQxDSbXnmS79HAgi9589lGSpLkg==} - engines: {node: '>=18'} + playwright-core@1.62.1: + resolution: {integrity: sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==} + engines: {node: '>=20'} hasBin: true plugin-error@2.0.1: @@ -8984,8 +9364,8 @@ packages: postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.5.20: - resolution: {integrity: sha512-lW616l85ucIQL+FocMmL7pQFPqBmwejrCMg+iPxyImlrANNJG9NHq/RkyCZopDhd8C3LA03PHRJDjkbGu8vvug==} + postcss@8.5.26: + resolution: {integrity: sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==} engines: {node: ^10 || ^12 || >=14} postgres-array@2.0.0: @@ -9009,8 +9389,8 @@ packages: peerDependencies: preact: '>=10 || >= 11.0.0-0' - preact@10.29.7: - resolution: {integrity: sha512-DCHYrK/B10yUD3ZjLfhZ3WIE/9Vf9VFUODcRE2dRomTYDpJk6z6L9wecSfhfE6M9ZTHUdyQkoC46arIDhEV84Q==} + preact@10.29.8: + resolution: {integrity: sha512-ej2aVZ+vZ8WO7tvlQWRM9N63A0KzF9q4mWJfDUHgYaIofWY9hu74QdnQrjoPMmZi2/nZ5gN0bJCQF49xQqx09Q==} peerDependencies: preact-render-to-string: '>=5' peerDependenciesMeta: @@ -9023,8 +9403,8 @@ packages: deprecated: No longer maintained. Please contact the author of the relevant native addon; alternatives are available. hasBin: true - prettier@3.9.5: - resolution: {integrity: sha512-/FVl766LpUfB5vXgCYOYa0MeV/441Ia99AeICQIQFTY/Nw0roZwULcXpku5i1/m5kt/baz+s4Zogspd839HSMg==} + prettier@3.9.6: + resolution: {integrity: sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==} engines: {node: '>=14'} hasBin: true @@ -9036,6 +9416,9 @@ packages: resolution: {integrity: sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + probe-image-size@7.4.0: + resolution: {integrity: sha512-cdEprVtZxV+awMde9X+4jILBFYh4CARxVrQaMl4wY4YcPWbul9jntXrIW95NInBDyJwcVUP3U0T6yukN8rMBaQ==} + proc-log@7.0.0: resolution: {integrity: sha512-FYgfaA69XZ93zaXLoMNQ+ViDXGGBgR8aLh03txzcFhV+9xOXx7+8DLCULrKKpR9+GsH9ZfHm82aSUPpozX0Ztg==} engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} @@ -9068,8 +9451,8 @@ packages: resolution: {integrity: sha512-E1sbAYg3aEbXrq0n1ojJkRHQJGE1kaE/O6GLA94y8rnJBfgvOPTOd1b9hOceQK1FFZI9qMh1vBERCyO2ifubcw==} engines: {node: '>=18'} - protobufjs@7.6.5: - resolution: {integrity: sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw==} + protobufjs@7.6.6: + resolution: {integrity: sha512-dYDWdjSl5RNb7SgPxGQcRU+GtvP7s2fpkrY0r432PcOIaZ0/rBcxEZnQN67iJhFuQiVw754JDoPruPCNdGsbjg==} engines: {node: '>=12.0.0'} protractor@7.0.0: @@ -9150,6 +9533,10 @@ packages: resolution: {integrity: sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==} engines: {node: '>=0.6'} + qs@6.16.0: + resolution: {integrity: sha512-h6fhOIaRrID2CbEY2fqs+7t+UXZo+MLAnU5gRIq85uFtdiUPCdsApMlHhXogKVM4HM2DVbIjGNTTYH2OcmP1vA==} + engines: {node: '>=0.6'} + qs@6.5.5: resolution: {integrity: sha512-mzR4sElr1bfCaPJe7m8ilJ6ZXdDaGoObcYR0ZHSsktM/Lt21MVHj5De30GQH2eiZ1qGRTO7LCAzQsUeXTNexWQ==} engines: {node: '>=0.6'} @@ -9164,9 +9551,6 @@ packages: resolution: {integrity: sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==} engines: {node: '>=0.12'} - randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} @@ -9190,21 +9574,22 @@ packages: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true - re2@1.26.0: - resolution: {integrity: sha512-QTEfFp0nu1eT/HKKZC+2BKM9Lb8uqprGkcHhro9r3giiKS+1SnNZBZ1m7C7Axi/VR1YGXiu3mp35UA53yHAuNw==} + re2@1.26.1: + resolution: {integrity: sha512-oi79a4h6EO3PAwNsDMWgeCcsRGQEUa52DIgOiFTZGDEZocEXG9h+oXy0qZqndo47huUeJuVWSoOJIEhOupqOcg==} engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} - re2js@0.4.3: - resolution: {integrity: sha512-EuNmh7jurhHEE8Ge/lBo9JuMLb3qf866Xjjfyovw3wPc7+hlqDkZq4LwhrCQMEI+ARWfrKrHozEndzlpNT0WDg==} + re2js@2.8.6: + resolution: {integrity: sha512-xLgQil4kIUCrAzVk9fRSkxkFNwmygLFjVxXrLc65aE1F0+Zsb8rxumFBy4XKyvgMCTL6kilDq3EZ0piE2dP/Dg==} + engines: {node: '>=18.0.0'} react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - react-is@19.2.7: - resolution: {integrity: sha512-kZFnouyVv7eP/Phmrlo9FK+zcAdriZJvzxXHF1Sl1P377WSGe2G/JxVolhTrB/jeV47lKImhNUsijjHAAbcl/A==} + react-is@19.2.8: + resolution: {integrity: sha512-s5un28nYxKJw5gvUHyW5PCC28CvBqLu9r3cWgzHT4Vo/5fqqkFcdRYsGcKf50WMPpjjFZS5d76fn3YCo2njKwQ==} - read-cache@1.0.0: - resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + read-cache@1.0.2: + resolution: {integrity: sha512-/peqiBB/n07gQGLsWaHho3WfvUyRscw0gYTsEFMhrIe/nWLkYaf5SbKYjGYqtRV3aPwykJgF2VEMo1ac4bnsGA==} read-package-up@11.0.0: resolution: {integrity: sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==} @@ -9236,12 +9621,8 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} - readdirp@4.1.2: - resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} - engines: {node: '>= 14.18.0'} - - readdirp@5.0.0: - resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} + readdirp@5.1.1: + resolution: {integrity: sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==} engines: {node: '>= 20.19.0'} rechoir@0.8.0: @@ -9345,8 +9726,8 @@ packages: resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} engines: {node: '>=0.12'} - retry-request@8.0.3: - resolution: {integrity: sha512-qqoc4kkGgP9cmQDWELlOpAmfgJOg0Yi7MT82ZjiPWu451ayju4itwomjM4/dBEliify8C1b3tSaeCOldugtwPQ==} + retry-request@8.0.4: + resolution: {integrity: sha512-pI6/7eabUYkZxamkOq0g0uMxKLLGnjzhefY+vL8bVXag5rto4OU2YBTPytWLuHH7aEKD6fn7kJycQfid0Mwnkw==} engines: {node: '>=18'} retry@0.13.1: @@ -9377,17 +9758,40 @@ packages: robust-predicates@3.0.3: resolution: {integrity: sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==} - rolldown@1.1.5: - resolution: {integrity: sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==} + rolldown-plugin-dts@0.28.4: + resolution: {integrity: sha512-yNg16bsWNk1MQ0Pkf3bAPFoZRqSWtxhiTHxKKHCoTZIwwyWerA5pX1MOogb1mjjwusVN2/kd4pK08iQ8M8hFIw==} + engines: {node: ^22.18.0 || ^24.11.0 || >=26.0.0} + peerDependencies: + '@typescript/native-preview': '*' + '@volar/typescript': ~2.4.0 + rolldown: ^1.2.0 + typescript: ^5.0.0 || ^6.0.0 || ~7.0.0 + vue-tsc: ~3.2.0 || ~3.3.0 + peerDependenciesMeta: + '@typescript/native-preview': + optional: true + '@volar/typescript': + optional: true + typescript: + optional: true + vue-tsc: + optional: true + + rolldown@1.2.8: + resolution: {integrity: sha512-Z67nTmhZe7anqnM/EjI392w5i/ANUinjip7QYsOyN37oayduxt3ksdX0hf5OOamkAd53BiIHfbfSzfUmzKFQqQ==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true - rollup-plugin-dts@6.4.1: - resolution: {integrity: sha512-l//F3Zf7ID5GoOfLfD8kroBjQKEKpy1qfhtAdnpibFZMffPaylrg1CoDC2vGkPeTeyxUe4bVFCln2EFuL7IGGg==} + rollup-plugin-dts@6.5.1: + resolution: {integrity: sha512-jODTXp3H7MK/Ur/ErtsrQ0G1GvaCmc3du+y5pNrdBMf6d7HlL2Nd/N6TkEr+f75CkUj01zEoEd7y2elH0eHi1Q==} engines: {node: '>=20'} peerDependencies: - rollup: ^3.29.4 || ^4 - typescript: ^4.5 || ^5.0 || ^6.0 + '@typescript/typescript6': ^6 + rollup: ^3 || ^4 + typescript: ^4.5 || ^5 || ^6 || ^7 + peerDependenciesMeta: + '@typescript/typescript6': + optional: true rollup-plugin-sourcemaps2@0.5.8: resolution: {integrity: sha512-c5BfiVbKAmaz+RoEhFF44Tg/X2QoLxEB8F7wS/eNWDJF/NKxi0SF7srN3Dg0RUnIcYLyCOwscket5Mr3BImMbg==} @@ -9399,8 +9803,8 @@ packages: '@types/node': optional: true - rollup@4.62.2: - resolution: {integrity: sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==} + rollup@4.63.0: + resolution: {integrity: sha512-T5vnZ2y4QqC3/4P+w2+JO+Q/OVdnPsv4XcSYJYMEn0R9/jjl5AgLwO9LAZMzP2lN71O6pypn91rB7lDstUkfrQ==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -9441,27 +9845,266 @@ packages: resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} engines: {node: '>= 0.4'} - safe-regex-test@1.1.0: - resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} - engines: {node: '>= 0.4'} + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sass-embedded-all-unknown@1.104.0: + resolution: {integrity: sha512-+S5We++QAg0/wXeVstn4kaZQNZiHi/1FHFsuVRu6Qns/9+YH6aIExg5e8dE+ceNpnYIZUpoK3mdBJoxJhirReQ==} + cpu: ['!arm', '!arm64', '!riscv64', '!x64'] + + sass-embedded-all-unknown@1.104.1: + resolution: {integrity: sha512-toyMCyUKkT6DsYlHuKZGjd8T6WltaW4TGX07F7HnF4tNJM5m/8VaVsd74zrq3QSPqGE9JjxIDK4NrNc/QY9pkA==} + cpu: ['!arm', '!arm64', '!riscv64', '!x64'] + + sass-embedded-android-arm64@1.104.0: + resolution: {integrity: sha512-Trknl/A+KTTGRsPWrKaVIF/uq468iTqZzXWMEK/e707bqnbodYvWBBkA7uOM1wtnJQIrepeYSp/CIQJnFr95EQ==} + engines: {node: '>=14.0.0'} + cpu: [arm64] + os: [android] + + sass-embedded-android-arm64@1.104.1: + resolution: {integrity: sha512-yW3BVW4YFpN2vu2cVQ+Pz5JrRTvoIz36aCdo+J/Mo1A9gEN8eVPV/AL7aeZ803YdKgIitd3qw3pY4wpmT6TXNg==} + engines: {node: '>=14.0.0'} + cpu: [arm64] + os: [android] + + sass-embedded-android-arm@1.104.0: + resolution: {integrity: sha512-yojf6KAo4EKbXVzzy4FkYJAez+qzj6NV2inEzsQQxvNfKxfX9INtC6u8UNwSjXL40M9vzAH03lygutq9zmhTCg==} + engines: {node: '>=14.0.0'} + cpu: [arm] + os: [android] + + sass-embedded-android-arm@1.104.1: + resolution: {integrity: sha512-g/XPAJYAzSSQZFP4xCdGD0HLKB4mf24cJ/+5Nls8rMool3jNkBv9+AFO4EV0b+RxN8rLcEsMccH1CR64yIFYcQ==} + engines: {node: '>=14.0.0'} + cpu: [arm] + os: [android] + + sass-embedded-android-riscv64@1.104.0: + resolution: {integrity: sha512-UPR1U/qsTzIikl/DAmZn/11oPrz4DrnrbWANB7WGwz3AtYvLZeixEiVj8Yo2jNy6749zPD09Pyo352io8Y2Mxw==} + engines: {node: '>=14.0.0'} + cpu: [riscv64] + os: [android] + + sass-embedded-android-riscv64@1.104.1: + resolution: {integrity: sha512-ZYY8oMKQS7Q/6FBoC8w3T16O3MucDe3xv8iKym41Nht5uvLCGGpm4fC4OF5nlv7wQkJv8oactYddGG3Wd0Rqkg==} + engines: {node: '>=14.0.0'} + cpu: [riscv64] + os: [android] + + sass-embedded-android-x64@1.104.0: + resolution: {integrity: sha512-NebAKvwfj4a7EbOf9LAzgo4f/uO1xFJbIoebzW8bmqdjeIMSAwJvFToIizxjDuOsIJ9M6AaADxwvDxgm8JTq+w==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [android] + + sass-embedded-android-x64@1.104.1: + resolution: {integrity: sha512-5WZKC4lSfjMIjzZdQUlYQUAV+UiatBhD8w28U7cYLLj4/dMgEPOBd4g3VMv0BwpgH2JOaycMS42dXq29W2bcDg==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [android] + + sass-embedded-darwin-arm64@1.104.0: + resolution: {integrity: sha512-DYxsoOtA90/LabvQiFs/UVo6jrPbIlIvelSC0B9fxlB051ZBpEFnWamjLV2Xncp48E63voWTYGKpLlsHsi7clg==} + engines: {node: '>=14.0.0'} + cpu: [arm64] + os: [darwin] + + sass-embedded-darwin-arm64@1.104.1: + resolution: {integrity: sha512-oatuHzn0NsEg0d9Dcze6CuWUPvuETtMxRK4cv0eRAg7p6R0vHnv5GZRyWG6gEy3nc/ha/L+GtTasWVU82f4jrQ==} + engines: {node: '>=14.0.0'} + cpu: [arm64] + os: [darwin] + + sass-embedded-darwin-x64@1.104.0: + resolution: {integrity: sha512-zozGKOnR3mnlBqKhzfGH8ZqjPphaDzE5Zjx+H/IOb/ruR/KApTvYkRdi9Eq7OQvSJwL/EHYiyT2jgHaqQulOWw==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [darwin] + + sass-embedded-darwin-x64@1.104.1: + resolution: {integrity: sha512-gql/5sHGzUTVwuHfM3QLCDeb6NYwen+LLj22gz81C2NKHF/4nUtDyh4N+fURWdT7J0/EhtMOd0+FLML3sGNP7g==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [darwin] + + sass-embedded-linux-arm64@1.104.0: + resolution: {integrity: sha512-2TWOQodxIbwcp9fS01FCUbO2c8bnsdOgUCLB7aZDAhm6ZAkEL8GNIAyKxSMkVIjxndMqNHsG2UtCR2++03DQ+Q==} + engines: {node: '>=14.0.0'} + cpu: [arm64] + os: [linux] + libc: glibc + + sass-embedded-linux-arm64@1.104.1: + resolution: {integrity: sha512-sVWUKXNTu8sP3X95Df0xo/t49Ce5IseTIMqXHxhFBKVmx7gf7kBWNLK0wH5ym+4khc+B5nNJPgq4IxpelG8tMQ==} + engines: {node: '>=14.0.0'} + cpu: [arm64] + os: [linux] + libc: glibc + + sass-embedded-linux-arm@1.104.0: + resolution: {integrity: sha512-RX4t5jBlYtGrZwpuc1mtD3lzGuat+jyPidyN5hD5DURV7q39y4IampzopVJ9fvNZqsiGElYWnKyRJA49Q4xk7w==} + engines: {node: '>=14.0.0'} + cpu: [arm] + os: [linux] + libc: glibc + + sass-embedded-linux-arm@1.104.1: + resolution: {integrity: sha512-WfmshPJOp9vUKxgp8wZ2ncaKBbyrlW9J51M2aUQHWECjMNxTULnGOHWSmD7FViXv4zwn1Co5FIFQUipW7RCxtA==} + engines: {node: '>=14.0.0'} + cpu: [arm] + os: [linux] + libc: glibc + + sass-embedded-linux-musl-arm64@1.104.0: + resolution: {integrity: sha512-NPcl0Cw9QXdGzYgjtLZD9MU3Mmr+N31R+Wa+hbbmlNwg1yghbF/bWrpE96oixrQivtCsY1yh9cONl6d+9NrS6Q==} + engines: {node: '>=14.0.0'} + cpu: [arm64] + os: [linux] + libc: musl + + sass-embedded-linux-musl-arm64@1.104.1: + resolution: {integrity: sha512-H7b+LzZ/w8pwNExInM8HDHraqvxCMdUc5ZRGU/aSJJhZ9HjeRKBjF3GxaisVHnx7o18j1l4VQ5cLBL9tTmNzZw==} + engines: {node: '>=14.0.0'} + cpu: [arm64] + os: [linux] + libc: musl + + sass-embedded-linux-musl-arm@1.104.0: + resolution: {integrity: sha512-KjXKRY/1TDCNbRg/Htq4puzf5etQ9eFXG83O/328Km/1x2FuQMCmD+pSFTqQrj2LskZ8if+NYZJb3CQ1wzF0Pw==} + engines: {node: '>=14.0.0'} + cpu: [arm] + os: [linux] + libc: musl + + sass-embedded-linux-musl-arm@1.104.1: + resolution: {integrity: sha512-k0cQ/CxBzFVYiQEObg6CpF6CUglkdEhi/DZgZXQbwC27kbGGY+fatmIs/cFPJL2z1ulACwoAr86RQUFzYvw5eg==} + engines: {node: '>=14.0.0'} + cpu: [arm] + os: [linux] + libc: musl + + sass-embedded-linux-musl-riscv64@1.104.0: + resolution: {integrity: sha512-/1JR6G1AfGs/paJk5nemuJmg7pOUgwXlz/WW2NhSDRHBgZnb6Zy6yMpkSHoienAOJSBGUmKceT03dQ/4b409CA==} + engines: {node: '>=14.0.0'} + cpu: [riscv64] + os: [linux] + libc: musl + + sass-embedded-linux-musl-riscv64@1.104.1: + resolution: {integrity: sha512-9DYdn4wfrkidjxJVtEd2iCx8HKdZe+uF82GDmrYEZhgu4NjVE6a4fQyW7OLwzn3erZMHKBaObBOH1d37DnXI1A==} + engines: {node: '>=14.0.0'} + cpu: [riscv64] + os: [linux] + libc: musl + + sass-embedded-linux-musl-x64@1.104.0: + resolution: {integrity: sha512-5wVjkPR74JdsoH9+NSKV7UCPAdMTxNoayZdu7B9PnmNkOJMRE5O8Jb2oJ3JXgSH/kcGXJ6Vl6dL8/EPLBAKkcg==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [linux] + libc: musl + + sass-embedded-linux-musl-x64@1.104.1: + resolution: {integrity: sha512-5xz+nAr01b6yaRdrGVgE7lNvm1lGFjwNdUvnz+teidvHCbD5oTcbhrRVrnDoLHHvq5n3Jve9TzWaaHhezaEfHA==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [linux] + libc: musl + + sass-embedded-linux-riscv64@1.104.0: + resolution: {integrity: sha512-Bq9xrONn23cyv5bdSuLm0RG1dcKl+lFQRc1k1UlncI2B2gqb6/OdakEa4Gv2HAmo+O6iOtK39lG9XT1ivTIoww==} + engines: {node: '>=14.0.0'} + cpu: [riscv64] + os: [linux] + libc: glibc + + sass-embedded-linux-riscv64@1.104.1: + resolution: {integrity: sha512-oWryPJWTXK5adtlz/FD7wd2kS4I0CEgp6mWLUVb4oMFURMLz9bA9fO87D7lc4SV++lds7T51PU1kykCbOvNHMg==} + engines: {node: '>=14.0.0'} + cpu: [riscv64] + os: [linux] + libc: glibc + + sass-embedded-linux-x64@1.104.0: + resolution: {integrity: sha512-xznKQzFnNVNq+GiXPmBXIHLL2rlIoekDxE8HXNKgxXX6bn4fByuHApCmj5Uz+MpVOB154EYCbErztyoEcmnb9Q==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [linux] + libc: glibc + + sass-embedded-linux-x64@1.104.1: + resolution: {integrity: sha512-j/sX/yKTx/wJKepC5/ISlR6kPeSuHKThf76D2za5i2VnbHg0MN19jQq3WMorowR3kRghqt6azs3awogG+e7IRA==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [linux] + libc: glibc + + sass-embedded-unknown-all@1.104.0: + resolution: {integrity: sha512-0+zhxrAt9PIsdWEVTe5Wgo+gtYdlyv0ASuuAEXT4e9w2yNArUqZ9Gez4Jn8EmtbF7x9uuZxPWbdnq9z65gCH7g==} + os: ['!android', '!darwin', '!linux', '!win32'] + + sass-embedded-unknown-all@1.104.1: + resolution: {integrity: sha512-RaMsYZB5mRioL4qhoI7T5mmNb2OunakbPTJW2cuu3MeIULnGoxo7Wd5QKFxeQvF7sSQL57RuaQ+q9pH+/pQ9Fg==} + os: ['!android', '!darwin', '!linux', '!win32'] + + sass-embedded-win32-arm64@1.104.0: + resolution: {integrity: sha512-b8dKmgdgmTx0rSBLNPqLQiq4r/SDau0/3we7MG/8ULMneMSl2OoVttN2ilKSz993lqQu8FJSjx5fEjLSeXVaiA==} + engines: {node: '>=14.0.0'} + cpu: [arm64] + os: [win32] + + sass-embedded-win32-arm64@1.104.1: + resolution: {integrity: sha512-fS6DL7lcnTPclqGLF4xRt8egZlFY9cU23d57ufbWqaUbCFu9JTu0+8qB4jMxfx1la6byi3GoSTfbnNOLfWv8sw==} + engines: {node: '>=14.0.0'} + cpu: [arm64] + os: [win32] + + sass-embedded-win32-x64@1.104.0: + resolution: {integrity: sha512-tVL4NZKUo0+fIO2sT9V1DnBOo9wUbkRoic/NbVBThQdCjl07dn7PKW+ISSnY0EwQhCxdulMDek/JZT7c46vTCA==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [win32] + + sass-embedded-win32-x64@1.104.1: + resolution: {integrity: sha512-/c4N2A93Ckms6DuRFVftKYISuI1tyC8gmlVJ8WaWFzgCBN/Swq2rARJIBUNeuxlmxjmYXfd3+2f/u887K63wbA==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [win32] + + sass-embedded@1.104.0: + resolution: {integrity: sha512-AW1ZaKM/o4t137+FNe9zkMFWAZlw+EbWuHopVbP0yc0vpvlYj8NqxgKKSsSqODZVgGON2FzKeFMJJHR+tXNzqA==} + engines: {node: '>=20.19.0'} + hasBin: true - safe-stable-stringify@2.5.0: - resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} - engines: {node: '>=10'} + sass-embedded@1.104.1: + resolution: {integrity: sha512-7LxbtPJ1MWKVbhzOnGx1sHTkHTcHVJ9hbgVsU29p/8gY1VeXt19fcJFr5xsx2f6zfrrR3FeOcYMt0uYDLAxpgw==} + engines: {node: '>=20.19.0'} + hasBin: true - safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + sass@1.104.0: + resolution: {integrity: sha512-btHMApW2bgolvClhRW8AlQJzgI9lUB3pPSofBQQT+E46GWvf9o0TVQ13SYv5riWZVFyPN+JNz3TKW9XhBlc10w==} + engines: {node: '>=20.19.0'} + hasBin: true - sass@1.101.0: - resolution: {integrity: sha512-OL3GoQyoUdDt843DpVmDO6y2k1sc5IhUDSpu8XucEI+35neq5QivZ1iuegnpraEVTJXlQGK1gl27zKcTLEPbQw==} + sass@1.104.1: + resolution: {integrity: sha512-yDA+1aIG3EHgN4V/BvuhCvu61FF6hEd4e+9DxikUm9U0CAGuvdIZ/UYy7qbOxjhbbWQraoyLlMuzdRGOSV5Bmw==} engines: {node: '>=20.19.0'} hasBin: true saucelabs@1.5.0: resolution: {integrity: sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==} - sax@1.6.0: - resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} + sax@1.6.1: + resolution: {integrity: sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==} engines: {node: '>=11.0.0'} saxes@6.0.0: @@ -9516,8 +10159,9 @@ packages: seq@0.3.5: resolution: {integrity: sha512-sisY2Ln1fj43KBkRtXkesnRHYNdswIkIibvNe/0UKm2GZxjMbqmccpiatoKr/k2qX5VKiLU8xm+tz/74LAho4g==} - serialize-javascript@6.0.2: - resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} + serialize-javascript@7.1.1: + resolution: {integrity: sha512-k3CMsaIvvdSwm8oLB4MXSl0wH2/cwlH7xGcnRd2DaeRmBkbzYmyT8j0tsX60DwD1eRwHTpNpH8ljKu9oUT1MeQ==} + engines: {node: '>=20.0.0'} serve-static@1.16.3: resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==} @@ -9556,8 +10200,8 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - shiki@4.3.1: - resolution: {integrity: sha512-oR+qDVi2OjX1tmDpyv+3KviX01KzO6Af+0NNnKnsp9491UEGz2YpxTuJboS/6VhYpTdqzmuJBuiTlrAWWJAssw==} + shiki@4.4.3: + resolution: {integrity: sha512-Mb/GvXPHBAXdgGIcnfU5L3ldpn1XcxrGkPHwqgRx17/I2XRfqlFKk2vGkHWINn1kdXvzJZeuO3is6I9KLPFm0g==} engines: {node: '>=20'} side-channel-list@1.0.1: @@ -9620,6 +10264,10 @@ packages: resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==} engines: {node: '>=20'} + slice-ansi@9.0.0: + resolution: {integrity: sha512-SO/3iYL5S3W57LLEniscOGPZgOqZUPCx6d3dB+52B80yJ0XstzsC/eV8gnA4tM3MHDrKz+OCFSLNjswdSC+/bA==} + engines: {node: '>=22'} + smart-buffer@4.2.0: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} @@ -9627,8 +10275,8 @@ packages: socket.io-adapter@2.5.8: resolution: {integrity: sha512-6Oy52pbg+kvdCVvjcN+FnY7BvxZ7cIHNScbvztT/It5d0vbwoJoVZmF2gjJmnV0/4WlXRfG15zc45ySk9Ah8bw==} - socket.io-parser@4.2.6: - resolution: {integrity: sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==} + socket.io-parser@4.2.7: + resolution: {integrity: sha512-IH/iSeO9T6gz1KkFleGDWkG9N3dl4jXVYUtMhIqH10Md0ttMer8nUNWiP1DKuNrybD2xBrixLJdCC9J6ECoYkg==} engines: {node: '>=10.0.0'} socket.io@4.8.3: @@ -9664,10 +10312,6 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} - source-map@0.7.6: - resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} - engines: {node: '>= 12'} - source-map@0.8.0: resolution: {integrity: sha512-d8EqvL+k/SOXCreS/SUzg2ciyHqBBLcN/yuRjFsbvVhHTE2pgei7oAhmPM7kWFbkX6OSMQfUq4KbkF3au9lhYQ==} engines: {node: '>= 12'} @@ -9765,6 +10409,9 @@ packages: stream-json@1.9.1: resolution: {integrity: sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==} + stream-parser@0.3.1: + resolution: {integrity: sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ==} + stream-shift@1.0.3: resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==} @@ -9772,12 +10419,15 @@ packages: resolution: {integrity: sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==} engines: {node: '>=8.0'} - streamx@2.28.0: - resolution: {integrity: sha512-1Yowhzjf0ivGMrTIkY9hav5TxobO9qIVqUE41fiCGMGgc3CLlf4MY+9AHmZqBWgDTue0fY9zWjYFVyf6Diuobw==} + streamx@2.28.1: + resolution: {integrity: sha512-zEzXb0s5Cds7tqMH6rhZ05lcJydCWiQPEwiNngVqzsxCc962vLY4Uw+mW7od8kDH258k2Uz/JrOkdIAAhSh9VA==} strict-event-emitter@0.5.1: resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==} + strictdom@1.0.1: + resolution: {integrity: sha512-cEmp9QeXXRmjj/rVp9oyiqcvyocWab/HaoN4+bwFeZ7QzykJD6L3yD4v12K1x0tHpqRqVpJevN3gW7kyM39Bqg==} + string-length@4.0.2: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} engines: {node: '>=10'} @@ -9847,6 +10497,10 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + strip-json-comments@5.0.3: + resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==} + engines: {node: '>=14.16'} + structured-source@4.0.0: resolution: {integrity: sha512-qGzRFNJDjFieQkl/sVOI2dUjHKRyL9dAJi2gCPGJLbJHBIkyOHxjuocpIEfbLioX+qSJpvbYdT49/YCdMznKxA==} @@ -9869,9 +10523,9 @@ packages: engines: {node: 20 || 22 || 24} hasBin: true - supports-color@10.2.2: - resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==} - engines: {node: '>=18'} + supports-color@11.0.0: + resolution: {integrity: sha512-/zyImLdxhdygBIaVX0xTlQhKaCDLCrm665aqHk8xqK/Pa6k61fL6gwQGQq1k31yNyz6x55PppQgF2DMyPQa5xw==} + engines: {node: '>=22'} supports-color@2.0.0: resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} @@ -9903,13 +10557,21 @@ packages: symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + sync-child-process@1.0.2: + resolution: {integrity: sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==} + engines: {node: '>=16.0.0'} + + sync-message-port@1.2.0: + resolution: {integrity: sha512-gAQ9qrUN/UCypHtGFbbe7Rc/f9bzO88IwrG8TDo/aMKAApKyD6E3W4Cm0EfhfBb6Z6SKt59tTCTfD+n1xmAvMg==} + engines: {node: '>=16.0.0'} + synckit@0.11.13: resolution: {integrity: sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg==} engines: {node: ^14.18.0 || >=16.0.0} - systeminformation@5.31.16: - resolution: {integrity: sha512-37NsFaeaqwYxanLgdJAGWj8OXIRgvSBsDXGhlC0uUoHyl9nf4HrNsZjqtQ9Gc99bj9FQpffzYccPVuQ6gpjfqg==} - engines: {node: '>=8.0.0'} + systeminformation@5.33.6: + resolution: {integrity: sha512-hMOQG/eRUzuopuYGGdl8ntkau0nEC7fOaRoTUg1RSr2GTQIk2VNa76DA0+ApajkGfzmcgAupgIP/vt+jtoe5EA==} + engines: {node: '>=10.0.0'} os: [darwin, linux, win32, freebsd, openbsd, netbsd, sunos, android] hasBin: true @@ -9932,18 +10594,18 @@ packages: resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} engines: {node: '>=6'} - tar-stream@3.2.0: - resolution: {integrity: sha512-ojzvCvVaNp6aOTFmG7jaRD0meowIAuPc3cMMhSgKiVWws1GyHbGd/xvnyuRKcKlMpt3qvxx6r0hreCNITP9hIg==} + tar-stream@3.2.1: + resolution: {integrity: sha512-nqsEO8zLZJvrOMdEwkA0QdCLFbetHMn95Zqu4fKwX+hkaTWJPZZOrxx/PwtxoK0MMGQmBQNRW3CPs8IFYQz4cQ==} - tar@7.5.20: - resolution: {integrity: sha512-9FcyK4PA6+WbzlTM9WhQm6vB5W7cP7dUiPsv1g7YDwEQnQ1CGpK3MGlKk/ITVWMk05kHZuBhmVhiv8LZoy/PFQ==} + tar@7.5.22: + resolution: {integrity: sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==} engines: {node: '>=18'} tcp-port-used@1.0.3: resolution: {integrity: sha512-4CEQ3qRJYo+mtEbJ+OoQu3dF4TDkwaO3RDVC4UzP5cpAOIUWwuwPjD7sdxDFFqsMUjsXVVYBMlg/boAaloThMA==} - teeny-request@10.1.3: - resolution: {integrity: sha512-5yDliI1uWkYPo7W+Zvrxg6YmoWuj5iC5EydewqrRTvc68nyMTZhlPPlLg6cptUGfbQAb+N9XDPDPzF6N081lug==} + teeny-request@10.1.4: + resolution: {integrity: sha512-R1Cg4Vu0UULeDfHL/kjABLaTW++9yD/B6n2g48y5dJ04hsEaxcfmAqbNDzNsbqAYJyIpZafjklLG9YxRu9uzOg==} engines: {node: '>=18'} teex@1.0.1: @@ -9986,33 +10648,30 @@ packages: through2@4.0.2: resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} - tinybench@2.9.0: - resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + tinybench@6.1.4: + resolution: {integrity: sha512-9APumHG7r4yOk4X4WlkmE71aZcv1gvin1czO3OQ1U9iJcFA5Ja/ygyb0vPOVHTthFozUYs8CLoLUlM8grb2lTQ==} + engines: {node: '>=20.0.0'} - tinyexec@1.2.4: - resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} + tinyexec@1.3.0: + resolution: {integrity: sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==} engines: {node: '>=18'} tinyglobby@0.2.17: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} - tinyrainbow@3.1.0: - resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} - engines: {node: '>=14.0.0'} - tldts-core@6.1.86: resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} - tldts-core@7.4.8: - resolution: {integrity: sha512-c1P7u0EhACHj7lPy4MJm8iTFEU8+nB0LCtddH0fhP7noaVoXAqafMtOOeX+ulpuPBqnrRgRhw494RICT3mbhnw==} + tldts-core@7.4.11: + resolution: {integrity: sha512-CW3WN2rIIE/Of21mulhgnGOwoDyEFNygyIBOONSdyAuSATgMMUCpLeUlB+E8sAwA5xRV9hYPl+kyZ9citHCaKg==} tldts@6.1.86: resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} hasBin: true - tldts@7.4.8: - resolution: {integrity: sha512-htwgN/8KRB3z3vnC0BOETVh2m499g5GmyTK9Wq5JBLX3FNz6tSBveAd+fQhzy9hkjif8vy2jwDMR1sGhLtZl2A==} + tldts@7.4.11: + resolution: {integrity: sha512-aBiNayCfTQxuIJBm06M+xR14cYaYlDlSXZbgsnKzKNxDKUVq7KFwTjwBSsb7m9Y5xO8WfPnBc63WaYFMTGlvqw==} hasBin: true tmp@0.0.30: @@ -10151,8 +10810,8 @@ packages: peerDependencies: typescript: '>=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev' - tsx@4.23.1: - resolution: {integrity: sha512-GQHnkIfxyx1wYCOS/wonik5MVRZU9hi1TEZmzGZSCJB1y9YgoZ8H6itNE/u4suE+yLmOzuE4E5S4TZ/ZX2wcWQ==} + tsx@4.23.13: + resolution: {integrity: sha512-BL5MGkRln6aDYhb0xbQlEAGw743BaZYWdbWtdJOBriYJboKgUUYCadFp2/FpBBZquBC/ezNBn7wMMPx7FDZUDw==} engines: {node: '>=18.0.0'} hasBin: true @@ -10268,19 +10927,19 @@ packages: undici-types@7.18.2: resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} - undici-types@7.28.0: - resolution: {integrity: sha512-LJAfY+2w6HGeT8d8J1wNQsUGUEGio6NWWpwdwurQe4f6oojzCFuGLizl1KSve4irsTxyLly1QhEeE6iapdaIvQ==} + undici-types@8.10.0: + resolution: {integrity: sha512-ibvdovq3nCFs8Msrd95BW+zUOq+aOVbT+wpHUoPWhztbHEoPc6oof51iFDB6Es8lTKvNvVW9jNSAB8dwrKTMGg==} - undici@6.27.0: - resolution: {integrity: sha512-YmfV3YnEDzXRC5lZ2jWtWWHKGUm1zIt8AhesR1tens+HTNv+YZlN/dp6G727LOvMJ8xjP9Be7Y2Sdr96LDm+pg==} + undici@6.28.0: + resolution: {integrity: sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==} engines: {node: '>=18.17'} - undici@7.28.0: - resolution: {integrity: sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==} + undici@7.29.0: + resolution: {integrity: sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==} engines: {node: '>=20.18.1'} - undici@8.7.0: - resolution: {integrity: sha512-N7iQtfyLhIMOFgQubvmLV26svHpO0bqKnAiWotTQCVKCmWrcGbBotPuW1x+xwYZ2VHdSTVUfPQQnlEt1/LouTQ==} + undici@8.10.0: + resolution: {integrity: sha512-HvltHd7avK13QIw/oLe4qoOLyoVSoafqJ2jYOrtMRBkbYT31eiBQ8O0ehRKZiEZCMEyLFQNIADpgCWC5fALvYQ==} engines: {node: '>=22.19.0'} unicode-emoji-modifier-base@1.0.0: @@ -10350,8 +11009,8 @@ packages: resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} engines: {node: '>=8'} - update-browserslist-db@1.2.3: - resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + update-browserslist-db@1.3.2: + resolution: {integrity: sha512-UQ+MSxlhRm1bzjhU+DcuXfjFO1FzNtqhK5+9Yvlp90ItDLk5vT932A0rFu619nf7RVS+Y/VeaUW1jaRDqZ8VJw==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -10383,8 +11042,8 @@ packages: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} - uuid@14.0.1: - resolution: {integrity: sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==} + uuid@14.0.2: + resolution: {integrity: sha512-xZe/16rV4aa+HGSOCiY2YeLT1OybRLrrkL/Rqaq7p7GMVXjFh+6wN4oMYgjFmnSnhY8t6Xpdl2l9qmnHYuMHwQ==} hasBin: true uuid@3.4.0: @@ -10422,6 +11081,9 @@ packages: resolution: {integrity: sha512-aeVK81SIuT6aMJfNo9Vte8Dw0/FZINGBV8BfCraGtqVxIeLAEhJyoWs8SmvRVmXfGss2PmmOwZCuBPbZR+IYWg==} engines: {node: '>= 10.13.0'} + varint@6.0.0: + resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==} + vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -10456,13 +11118,13 @@ packages: resolution: {integrity: sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA==} engines: {node: '>=10.13.0'} - vite@8.1.4: - resolution: {integrity: sha512-bTT9PsdWO+MQMNG9ZXIP/qM9wGh37DFxTV/sPq9cFpHr3w4jkgef032PkAL9jAqhk3Nz8NQw3O8n6/xFkqO4QQ==} + vite@8.2.2: + resolution: {integrity: sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: '@types/node': ^20.19.0 || >=22.12.0 - '@vitejs/devtools': ^0.3.0 + '@vitejs/devtools': ^0.4.0 || ^0.5.0 esbuild: ^0.27.0 || ^0.28.0 jiti: '>=1.21.0' less: ^4.0.0 @@ -10499,22 +11161,23 @@ packages: yaml: optional: true - vitest@4.1.10: - resolution: {integrity: sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==} - engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + vitest@5.0.0: + resolution: {integrity: sha512-gpsMNoRhMjMktVxPtstOH4/PJuPyovVaMDr4oDilXaGH1EcqM2OE96SoHT2VIQ6fTGtTjqmHDrEu2X9RQiXf8Q==} + engines: {node: ^22.12.0 || ^24.0.0 || >=26.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@opentelemetry/api': ^1.9.0 - '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.1.10 - '@vitest/browser-preview': 4.1.10 - '@vitest/browser-webdriverio': 4.1.10 - '@vitest/coverage-istanbul': 4.1.10 - '@vitest/coverage-v8': 4.1.10 - '@vitest/ui': 4.1.10 + '@types/node': ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 5.0.0 + '@vitest/browser-preview': 5.0.0 + '@vitest/browser-webdriverio': ^5.0.0-beta.5 || >=5.0.0 + '@vitest/coverage-istanbul': 5.0.0 + '@vitest/coverage-v8': 5.0.0 + '@vitest/ui': 5.0.0 happy-dom: '*' jsdom: '*' + vite: ^6.4.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: '@edge-runtime/vm': optional: true @@ -10560,14 +11223,14 @@ packages: vscode-languageserver-protocol@3.17.5: resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==} - vscode-languageserver-textdocument@1.0.12: - resolution: {integrity: sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==} + vscode-languageserver-textdocument@1.0.14: + resolution: {integrity: sha512-EQyqJMi552E4ZTf46izQ4Fj6XquqxCySR3J5ZSD1SisMf6RfpeOWHxGBE8Gr6V0/3GHIGdAzDn8F8+1nTGCnoQ==} vscode-languageserver-types@3.17.5: resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==} - vscode-languageserver-types@3.18.0: - resolution: {integrity: sha512-8TsGPNMIMiiBdkORgRSvLjuiEIiAFtO+KssmYWxQ+uSVvlf7RjK8YKCOjPzZ+YA04jXEV7+7LvkSmHkhpNS99g==} + vscode-languageserver-types@3.18.3: + resolution: {integrity: sha512-XIlzJ7Qp/jzSI1ds7/FwPAWrPeTZA7pAtlW4hdJ1J6xXWJL6dR9QYnDhJOdLzdKhUQ5Mm6mvUMw+3DcOQQasPw==} vscode-languageserver@9.0.1: resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==} @@ -10583,8 +11246,8 @@ packages: resolution: {integrity: sha512-Wg6Pz+ePAT1O+F/A1Fc4wS5vY2X+HNtgN4qMdL+65NLQYd1/zdDWH4fhwsLjX8wTzeXkMy49Cr4ZqWTJ7VnVxg==} hasBin: true - vscode-uri@3.1.0: - resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} + vscode-uri@3.2.0: + resolution: {integrity: sha512-m2gXo3bn0G1kT9InzMf07fTbqMbGtyckj3bH5ktLO+1Ssv+yiATZ4dhwaQv9UZWxJh6E9IFGnQyjgWVDWVBDrg==} w3c-keyname@2.2.8: resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} @@ -10600,10 +11263,6 @@ packages: walker@1.0.8: resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} - watchpack@2.5.2: - resolution: {integrity: sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg==} - engines: {node: '>=10.13.0'} - wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} @@ -10678,6 +11337,10 @@ packages: resolution: {integrity: sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + whatwg-url@17.1.0: + resolution: {integrity: sha512-3GeworPmc2ZfEEHP7lEbUfBX/L75wdEsi0rLNhXcXxnoN5jyq0SL5gCy06SGW2cyTIZdTvWIDQNQoza++vKeaw==} + engines: {node: ^22.14.0 || >=24.0.0} + whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} @@ -10739,11 +11402,11 @@ packages: wordwrap@1.0.0: resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - workerpool@9.3.4: - resolution: {integrity: sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==} + workerpool@10.0.3: + resolution: {integrity: sha512-6z2Iis68Wqth93/G/wJP9u+R3O+d2XTlgWChGCwuT1qLbBsOYueGRZuJ++v3mtDP5KjYdy+WzvWC+VWETSVXJA==} - wrap-ansi@10.0.0: - resolution: {integrity: sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ==} + wrap-ansi@10.0.1: + resolution: {integrity: sha512-M0N4xzyzosiIok3svYlEo1sdLZts/8FPgYH/GPC3wvlmPoRvnoManGMrE54waYj3tISA8w6lsdesfVv67qSr8Q==} engines: {node: '>=20'} wrap-ansi@6.2.0: @@ -10772,8 +11435,8 @@ packages: resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - ws@7.5.11: - resolution: {integrity: sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA==} + ws@7.5.13: + resolution: {integrity: sha512-rsKI6xDBFVf4r/x8XyChGK04QR/XHroxs/jUcoWvtEZM8TPU/X/uIY9B1CsSzYws9ZJb/6bbBu7dPhFW00CAoA==} engines: {node: '>=8.3.0'} peerDependencies: bufferutil: ^4.0.1 @@ -10784,8 +11447,8 @@ packages: utf-8-validate: optional: true - ws@8.21.0: - resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} + ws@8.21.3: + resolution: {integrity: sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -10838,6 +11501,9 @@ packages: xvfb@0.4.0: resolution: {integrity: sha512-g55AbjcBL4Bztfn7kiUrR0ne8mMUsFODDJ+HFGf5OuHJqKKccpExX2Qgn7VF2eImw1eoh6+riXHser1J4agrFA==} + xxhash-wasm@1.1.0: + resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==} + y18n@4.0.3: resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} @@ -10860,6 +11526,11 @@ packages: engines: {node: '>= 14.6'} hasBin: true + yaml@2.9.1: + resolution: {integrity: sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==} + engines: {node: '>= 14.6'} + hasBin: true + yargs-parser@18.1.3: resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} engines: {node: '>=6'} @@ -10876,10 +11547,6 @@ packages: resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} engines: {node: ^20.19.0 || ^22.12.0 || >=23} - yargs-unparser@2.0.0: - resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} - engines: {node: '>=10'} - yargs@15.4.1: resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} engines: {node: '>=8'} @@ -10892,8 +11559,8 @@ packages: resolution: {integrity: sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==} engines: {node: '>=12'} - yargs@18.0.0: - resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} + yargs@18.1.0: + resolution: {integrity: sha512-2rAgRKu54VsHkqI0/tYkmluGXHD4KW7yZoycuqDQ15QOTnc2VVfy0nN/1eMhnQLO00A+dwtK20xuCnc1YGeUyg==} engines: {node: ^20.19.0 || ^22.12.0 || >=23} yauzl@3.4.0: @@ -10915,10 +11582,19 @@ packages: resolution: {integrity: sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==} engines: {node: '>=18'} - yoctocolors@2.1.2: - resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} + yoctocolors@2.2.0: + resolution: {integrity: sha512-xYqdZFUK/VYazNl/oCDYN+3WloWQwMfZxBoiNt6qNyk+xfOdi598muWE42rNZFp1kNOiqW936q5RhUdnpqElSg==} engines: {node: '>=18'} + yuku-ast@0.9.3: + resolution: {integrity: sha512-Kt0PXlPCXdKF1fWFTl7N3DaxsVk6DHF8VAXHJMkwPtJnWYgbx20pYgGSweuC/86mIM7k1NUITQ4JffgOLUWTCw==} + + yuku-codegen@0.9.3: + resolution: {integrity: sha512-7oTWwetHiMSyrVPFb8089lBBqkU1gaeQZyumNBJ0t5hocMQRaWhnMeSXTz7J1xm/rcw9+ePsajORdZbub2C35w==} + + yuku-parser@0.9.3: + resolution: {integrity: sha512-96wPoHnwaXfkZv7UIOUkDb+s7ZH8lv8Qtg+MxdvHUV1LFa5jV9iKOaams1942YQt+krFQrWiD6lSg2ermv5kHA==} + zip-stream@6.0.1: resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==} engines: {node: '>= 14'} @@ -10928,8 +11604,11 @@ packages: peerDependencies: zod: ^3.25.28 || ^4 - zod@4.4.3: - resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} + zod@4.5.4: + resolution: {integrity: sha512-sC95tT5iHHH9gtpj6A81kh+NEaRAUFN+qlUPDUbRfOMvNf5QCBqsb3WgvnpVtK5Y+4UfA6KqufotuTvMGiTlsA==} + + zod@4.6.5: + resolution: {integrity: sha512-v5l/aFXZQeai4awLbOpSoHecE9UiMrnfx75tEXLjNonXVARxQ5mOeipTjROUchszUNCqnE+hqAMujRsRHsut2Q==} zone.js@0.16.2: resolution: {integrity: sha512-Eky7p2Z1Ig3NnbfodSPoARCjKBSTFMnE/ACsP1L/XJEfY4SdOFce19BsUCWVwL6K5ABZFy5J3bjcMWffX+YM3Q==} @@ -10951,192 +11630,108 @@ snapshots: '@actions/github@9.1.1': dependencies: '@actions/http-client': 3.0.2 - '@octokit/core': 7.0.6 - '@octokit/plugin-paginate-rest': 14.0.0(@octokit/core@7.0.6) - '@octokit/plugin-rest-endpoint-methods': 17.0.0(@octokit/core@7.0.6) - '@octokit/request': 10.0.11 - '@octokit/request-error': 7.1.0 - undici: 6.27.0 + '@octokit/core': 7.0.8 + '@octokit/plugin-paginate-rest': 14.0.0(@octokit/core@7.0.8) + '@octokit/plugin-rest-endpoint-methods': 17.0.0(@octokit/core@7.0.8) + '@octokit/request': 10.0.16 + '@octokit/request-error': 7.1.2 + undici: 6.28.0 '@actions/http-client@3.0.2': dependencies: tunnel: 0.0.6 - undici: 6.27.0 + undici: 6.28.0 '@actions/http-client@4.0.1': dependencies: tunnel: 0.0.6 - undici: 6.27.0 + undici: 6.28.0 '@actions/io@3.0.2': {} - '@algolia/abtesting@1.21.2': - dependencies: - '@algolia/client-common': 5.55.2 - '@algolia/requester-browser-xhr': 5.55.2 - '@algolia/requester-fetch': 5.55.2 - '@algolia/requester-node-http': 5.55.2 - - '@algolia/abtesting@1.22.0': - dependencies: - '@algolia/client-common': 5.56.0 - '@algolia/requester-browser-xhr': 5.56.0 - '@algolia/requester-fetch': 5.56.0 - '@algolia/requester-node-http': 5.56.0 - - '@algolia/client-abtesting@5.55.2': - dependencies: - '@algolia/client-common': 5.55.2 - '@algolia/requester-browser-xhr': 5.55.2 - '@algolia/requester-fetch': 5.55.2 - '@algolia/requester-node-http': 5.55.2 - - '@algolia/client-abtesting@5.56.0': - dependencies: - '@algolia/client-common': 5.56.0 - '@algolia/requester-browser-xhr': 5.56.0 - '@algolia/requester-fetch': 5.56.0 - '@algolia/requester-node-http': 5.56.0 - - '@algolia/client-analytics@5.55.2': - dependencies: - '@algolia/client-common': 5.55.2 - '@algolia/requester-browser-xhr': 5.55.2 - '@algolia/requester-fetch': 5.55.2 - '@algolia/requester-node-http': 5.55.2 - - '@algolia/client-analytics@5.56.0': - dependencies: - '@algolia/client-common': 5.56.0 - '@algolia/requester-browser-xhr': 5.56.0 - '@algolia/requester-fetch': 5.56.0 - '@algolia/requester-node-http': 5.56.0 - - '@algolia/client-common@5.55.2': {} - - '@algolia/client-common@5.56.0': {} - - '@algolia/client-insights@5.55.2': + '@algolia/abtesting@1.23.0': dependencies: - '@algolia/client-common': 5.55.2 - '@algolia/requester-browser-xhr': 5.55.2 - '@algolia/requester-fetch': 5.55.2 - '@algolia/requester-node-http': 5.55.2 + '@algolia/client-common': 5.57.0 + '@algolia/requester-browser-xhr': 5.57.0 + '@algolia/requester-fetch': 5.57.0 + '@algolia/requester-node-http': 5.57.0 - '@algolia/client-insights@5.56.0': + '@algolia/client-abtesting@5.57.0': dependencies: - '@algolia/client-common': 5.56.0 - '@algolia/requester-browser-xhr': 5.56.0 - '@algolia/requester-fetch': 5.56.0 - '@algolia/requester-node-http': 5.56.0 + '@algolia/client-common': 5.57.0 + '@algolia/requester-browser-xhr': 5.57.0 + '@algolia/requester-fetch': 5.57.0 + '@algolia/requester-node-http': 5.57.0 - '@algolia/client-personalization@5.55.2': + '@algolia/client-analytics@5.57.0': dependencies: - '@algolia/client-common': 5.55.2 - '@algolia/requester-browser-xhr': 5.55.2 - '@algolia/requester-fetch': 5.55.2 - '@algolia/requester-node-http': 5.55.2 + '@algolia/client-common': 5.57.0 + '@algolia/requester-browser-xhr': 5.57.0 + '@algolia/requester-fetch': 5.57.0 + '@algolia/requester-node-http': 5.57.0 - '@algolia/client-personalization@5.56.0': - dependencies: - '@algolia/client-common': 5.56.0 - '@algolia/requester-browser-xhr': 5.56.0 - '@algolia/requester-fetch': 5.56.0 - '@algolia/requester-node-http': 5.56.0 - - '@algolia/client-query-suggestions@5.55.2': - dependencies: - '@algolia/client-common': 5.55.2 - '@algolia/requester-browser-xhr': 5.55.2 - '@algolia/requester-fetch': 5.55.2 - '@algolia/requester-node-http': 5.55.2 - - '@algolia/client-query-suggestions@5.56.0': - dependencies: - '@algolia/client-common': 5.56.0 - '@algolia/requester-browser-xhr': 5.56.0 - '@algolia/requester-fetch': 5.56.0 - '@algolia/requester-node-http': 5.56.0 - - '@algolia/client-search@5.55.2': - dependencies: - '@algolia/client-common': 5.55.2 - '@algolia/requester-browser-xhr': 5.55.2 - '@algolia/requester-fetch': 5.55.2 - '@algolia/requester-node-http': 5.55.2 - - '@algolia/client-search@5.56.0': - dependencies: - '@algolia/client-common': 5.56.0 - '@algolia/requester-browser-xhr': 5.56.0 - '@algolia/requester-fetch': 5.56.0 - '@algolia/requester-node-http': 5.56.0 - - '@algolia/ingestion@1.55.2': - dependencies: - '@algolia/client-common': 5.55.2 - '@algolia/requester-browser-xhr': 5.55.2 - '@algolia/requester-fetch': 5.55.2 - '@algolia/requester-node-http': 5.55.2 - - '@algolia/ingestion@1.56.0': - dependencies: - '@algolia/client-common': 5.56.0 - '@algolia/requester-browser-xhr': 5.56.0 - '@algolia/requester-fetch': 5.56.0 - '@algolia/requester-node-http': 5.56.0 + '@algolia/client-common@5.57.0': {} - '@algolia/monitoring@1.55.2': + '@algolia/client-insights@5.57.0': dependencies: - '@algolia/client-common': 5.55.2 - '@algolia/requester-browser-xhr': 5.55.2 - '@algolia/requester-fetch': 5.55.2 - '@algolia/requester-node-http': 5.55.2 + '@algolia/client-common': 5.57.0 + '@algolia/requester-browser-xhr': 5.57.0 + '@algolia/requester-fetch': 5.57.0 + '@algolia/requester-node-http': 5.57.0 - '@algolia/monitoring@1.56.0': + '@algolia/client-personalization@5.57.0': dependencies: - '@algolia/client-common': 5.56.0 - '@algolia/requester-browser-xhr': 5.56.0 - '@algolia/requester-fetch': 5.56.0 - '@algolia/requester-node-http': 5.56.0 + '@algolia/client-common': 5.57.0 + '@algolia/requester-browser-xhr': 5.57.0 + '@algolia/requester-fetch': 5.57.0 + '@algolia/requester-node-http': 5.57.0 - '@algolia/recommend@5.55.2': + '@algolia/client-query-suggestions@5.57.0': dependencies: - '@algolia/client-common': 5.55.2 - '@algolia/requester-browser-xhr': 5.55.2 - '@algolia/requester-fetch': 5.55.2 - '@algolia/requester-node-http': 5.55.2 + '@algolia/client-common': 5.57.0 + '@algolia/requester-browser-xhr': 5.57.0 + '@algolia/requester-fetch': 5.57.0 + '@algolia/requester-node-http': 5.57.0 - '@algolia/recommend@5.56.0': + '@algolia/client-search@5.57.0': dependencies: - '@algolia/client-common': 5.56.0 - '@algolia/requester-browser-xhr': 5.56.0 - '@algolia/requester-fetch': 5.56.0 - '@algolia/requester-node-http': 5.56.0 + '@algolia/client-common': 5.57.0 + '@algolia/requester-browser-xhr': 5.57.0 + '@algolia/requester-fetch': 5.57.0 + '@algolia/requester-node-http': 5.57.0 - '@algolia/requester-browser-xhr@5.55.2': + '@algolia/ingestion@1.57.0': dependencies: - '@algolia/client-common': 5.55.2 + '@algolia/client-common': 5.57.0 + '@algolia/requester-browser-xhr': 5.57.0 + '@algolia/requester-fetch': 5.57.0 + '@algolia/requester-node-http': 5.57.0 - '@algolia/requester-browser-xhr@5.56.0': + '@algolia/monitoring@1.57.0': dependencies: - '@algolia/client-common': 5.56.0 + '@algolia/client-common': 5.57.0 + '@algolia/requester-browser-xhr': 5.57.0 + '@algolia/requester-fetch': 5.57.0 + '@algolia/requester-node-http': 5.57.0 - '@algolia/requester-fetch@5.55.2': + '@algolia/recommend@5.57.0': dependencies: - '@algolia/client-common': 5.55.2 + '@algolia/client-common': 5.57.0 + '@algolia/requester-browser-xhr': 5.57.0 + '@algolia/requester-fetch': 5.57.0 + '@algolia/requester-node-http': 5.57.0 - '@algolia/requester-fetch@5.56.0': + '@algolia/requester-browser-xhr@5.57.0': dependencies: - '@algolia/client-common': 5.56.0 + '@algolia/client-common': 5.57.0 - '@algolia/requester-node-http@5.55.2': + '@algolia/requester-fetch@5.57.0': dependencies: - '@algolia/client-common': 5.55.2 + '@algolia/client-common': 5.57.0 - '@algolia/requester-node-http@5.56.0': + '@algolia/requester-node-http@5.57.0': dependencies: - '@algolia/client-common': 5.56.0 + '@algolia/client-common': 5.57.0 '@alloc/quick-lru@5.2.0': {} @@ -11145,94 +11740,94 @@ snapshots: '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 - '@angular-devkit/architect@0.2201.0-next.4(chokidar@5.0.0)': + '@angular-devkit/architect@0.2202.0-next.7(chokidar@5.0.0)': dependencies: - '@angular-devkit/core': 22.1.0-next.4(chokidar@5.0.0) + '@angular-devkit/core': 22.2.0-next.7(chokidar@5.0.0) rxjs: 7.8.2 transitivePeerDependencies: - chokidar - '@angular-devkit/core@22.1.0-next.4(chokidar@5.0.0)': + '@angular-devkit/core@22.2.0-next.7(chokidar@5.0.0)': dependencies: ajv: 8.20.0 ajv-formats: 3.0.1 jsonc-parser: 3.3.1 - picomatch: 4.0.5 + picomatch: 4.0.7 rxjs: 7.8.2 - source-map: 0.7.6 + source-map: 0.8.0 optionalDependencies: chokidar: 5.0.0 - '@angular-devkit/schematics@22.1.0-next.4(chokidar@5.0.0)': + '@angular-devkit/schematics@22.2.0-next.7(chokidar@5.0.0)': dependencies: - '@angular-devkit/core': 22.1.0-next.4(chokidar@5.0.0) + '@angular-devkit/core': 22.2.0-next.7(chokidar@5.0.0) jsonc-parser: 3.3.1 - magic-string: 0.30.21 + magic-string: 1.2.3 ora: 9.4.1 rxjs: 7.8.2 transitivePeerDependencies: - chokidar - '@angular/aria@22.1.0-next.4(@angular/cdk@22.1.0-next.4(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2))(@angular/core@packages+core)': + '@angular/aria@22.2.0-next.5(@angular/cdk@22.2.0-next.5(@angular/common@packages+common)(@angular/core@packages+core)(@angular/forms@packages+forms)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2))(@angular/core@packages+core)': dependencies: - '@angular/cdk': 22.1.0-next.4(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2) + '@angular/cdk': 22.2.0-next.5(@angular/common@packages+common)(@angular/core@packages+core)(@angular/forms@packages+forms)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2) '@angular/core': link:packages/core tslib: 2.8.1 - '@angular/build@22.1.0-next.4(048f5165d9cdcac2cb54b2d790f738e3)': + '@angular/build@22.2.0-next.7(2acce862f67dc28f299e38c6f24193ce)': dependencies: '@ampproject/remapping': 2.3.0 - '@angular-devkit/architect': 0.2201.0-next.4(chokidar@5.0.0) + '@angular-devkit/architect': 0.2202.0-next.7(chokidar@5.0.0) '@angular/compiler': link:packages/compiler '@angular/compiler-cli': link:packages/compiler-cli '@babel/core': 8.0.1 - '@babel/helper-annotate-as-pure': 8.0.0 - '@babel/helper-split-export-declaration': 7.24.7 - '@inquirer/confirm': 6.1.1(@types/node@20.19.43) - '@vitejs/plugin-basic-ssl': 2.3.0(vite@8.1.4(@types/node@20.19.43)(esbuild@0.28.1)(jiti@1.21.7)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0)) - beasties: 0.4.2 - browserslist: 4.28.6 - esbuild: 0.28.1 - https-proxy-agent: 9.1.0(supports-color@8.1.1) + '@inquirer/confirm': 6.3.2(@types/node@24.13.3) + '@parcel/watcher': 2.6.0 + '@vitejs/plugin-basic-ssl': 2.3.0(vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.1)(sass@1.104.1)(tsx@4.23.13)(yaml@2.9.1)) + beasties: 0.5.4 + browserslist: 4.28.8 + chokidar: 5.0.0 + esbuild: 0.28.2 + https-proxy-agent: 9.1.0(supports-color@11.0.0) jsonc-parser: 3.3.1 - listr2: 10.2.2 - magic-string: 0.30.21 + listr2: 11.1.0 + magic-string: 1.2.3 mrmime: 2.0.1 + oxc-parser: 0.149.0 parse5-html-rewriting-stream: 8.0.1 - picomatch: 4.0.5 - piscina: 5.2.0 - rolldown: 1.1.5 - sass: 1.101.0 + picomatch: 4.0.7 + piscina: 5.3.2 + rolldown: 1.2.8 + sass: 1.104.0 + sass-embedded: 1.104.0 semver: 7.8.5 source-map-support: 0.5.21 tinyglobby: 0.2.17 tslib: 2.8.1 typescript: 6.0.3 - vite: 8.1.4(@types/node@20.19.43)(esbuild@0.28.1)(jiti@1.21.7)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0) - watchpack: 2.5.2 + vite: 8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.0)(sass@1.104.0)(tsx@4.23.13)(yaml@2.9.1) + xxhash-wasm: 1.1.0 optionalDependencies: '@angular/core': link:packages/core '@angular/localize': link:packages/localize '@angular/platform-browser': link:packages/platform-browser '@angular/platform-server': link:packages/platform-server '@angular/service-worker': link:packages/service-worker - '@angular/ssr': 22.1.0-next.4(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-server@packages+platform-server)(@angular/router@packages+router) - istanbul-lib-instrument: 6.0.3(supports-color@10.2.2) - karma: 6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6) - less: 4.6.7 + '@angular/ssr': 22.2.0-next.7(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-server@packages+platform-server)(@angular/router@packages+router) + istanbul-lib-instrument: 6.0.3(supports-color@11.0.0) + karma: 6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6) + less: 4.9.0(supports-color@11.0.0) lmdb: 3.5.6 - ng-packagr: 22.1.0-next.3(@angular/compiler-cli@packages+compiler-cli)(tailwindcss@3.4.19(tsx@4.23.1)(yaml@2.9.0))(tslib@2.8.1)(typescript@6.0.3) - postcss: 8.5.20 - rollup: 4.62.2 - tailwindcss: 3.4.19(tsx@4.23.1)(yaml@2.9.0) - vitest: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@20.19.43)(esbuild@0.28.1)(jiti@1.21.7)(jsdom@29.1.1)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0) + ng-packagr: 22.2.0-next.5(@angular/compiler-cli@packages+compiler-cli)(supports-color@11.0.0)(tailwindcss@3.4.19(tsx@4.23.13)(yaml@2.9.1))(tslib@2.8.1)(typescript@6.0.3) + postcss: 8.5.26 + rollup: 4.63.0 + tailwindcss: 3.4.19(tsx@4.23.13)(yaml@2.9.1) + vitest: 5.0.0(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(jsdom@30.0.1)(vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.1)(sass@1.104.1)(tsx@4.23.13)(yaml@2.9.1)) transitivePeerDependencies: - '@types/node' - '@vitejs/devtools' - - chokidar - jiti - kerberos - - sass-embedded - stylus - sugarss - supports-color @@ -11240,60 +11835,60 @@ snapshots: - tsx - yaml - '@angular/build@22.1.0-next.4(0b1055752a55c13ecb546c4fb1e33e8f)': + '@angular/build@22.2.0-next.7(e7ab0a794307bcb845f8633d1b339c6e)': dependencies: '@ampproject/remapping': 2.3.0 - '@angular-devkit/architect': 0.2201.0-next.4(chokidar@5.0.0) + '@angular-devkit/architect': 0.2202.0-next.7(chokidar@5.0.0) '@angular/compiler': link:packages/compiler '@angular/compiler-cli': link:packages/compiler-cli '@babel/core': 8.0.1 - '@babel/helper-annotate-as-pure': 8.0.0 - '@babel/helper-split-export-declaration': 7.24.7 - '@inquirer/confirm': 6.1.1(@types/node@24.13.3) - '@vitejs/plugin-basic-ssl': 2.3.0(vite@8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(jiti@1.21.7)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0)) - beasties: 0.4.2 - browserslist: 4.28.6 - esbuild: 0.28.1 - https-proxy-agent: 9.1.0(supports-color@10.2.2) + '@inquirer/confirm': 6.3.2(@types/node@20.19.43) + '@parcel/watcher': 2.6.0 + '@vitejs/plugin-basic-ssl': 2.3.0(vite@8.2.2(@types/node@20.19.43)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.1)(sass@1.104.1)(tsx@4.23.13)(yaml@2.9.1)) + beasties: 0.5.4 + browserslist: 4.28.8 + chokidar: 5.0.0 + esbuild: 0.28.2 + https-proxy-agent: 9.1.0(supports-color@11.0.0) jsonc-parser: 3.3.1 - listr2: 10.2.2 - magic-string: 0.30.21 + listr2: 11.1.0 + magic-string: 1.2.3 mrmime: 2.0.1 + oxc-parser: 0.149.0 parse5-html-rewriting-stream: 8.0.1 - picomatch: 4.0.5 - piscina: 5.2.0 - rolldown: 1.1.5 - sass: 1.101.0 + picomatch: 4.0.7 + piscina: 5.3.2 + rolldown: 1.2.8 + sass: 1.104.0 + sass-embedded: 1.104.0 semver: 7.8.5 source-map-support: 0.5.21 tinyglobby: 0.2.17 tslib: 2.8.1 typescript: 6.0.3 - vite: 8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(jiti@1.21.7)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0) - watchpack: 2.5.2 + vite: 8.2.2(@types/node@20.19.43)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.0)(sass@1.104.0)(tsx@4.23.13)(yaml@2.9.1) + xxhash-wasm: 1.1.0 optionalDependencies: '@angular/core': link:packages/core '@angular/localize': link:packages/localize '@angular/platform-browser': link:packages/platform-browser '@angular/platform-server': link:packages/platform-server '@angular/service-worker': link:packages/service-worker - '@angular/ssr': 22.1.0-next.4(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-server@packages+platform-server)(@angular/router@packages+router) - istanbul-lib-instrument: 6.0.3(supports-color@10.2.2) - karma: 6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6) - less: 4.6.7 + '@angular/ssr': 22.2.0-next.7(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-server@packages+platform-server)(@angular/router@packages+router) + istanbul-lib-instrument: 6.0.3(supports-color@11.0.0) + karma: 6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6) + less: 4.9.0(supports-color@11.0.0) lmdb: 3.5.6 - ng-packagr: 22.1.0-next.3(@angular/compiler-cli@packages+compiler-cli)(tailwindcss@3.4.19(tsx@4.23.1)(yaml@2.9.0))(tslib@2.8.1)(typescript@6.0.3) - postcss: 8.5.20 - rollup: 4.62.2 - tailwindcss: 3.4.19(tsx@4.23.1)(yaml@2.9.0) - vitest: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.1)(jiti@1.21.7)(jsdom@29.1.1)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0) + ng-packagr: 22.2.0-next.5(@angular/compiler-cli@packages+compiler-cli)(supports-color@11.0.0)(tailwindcss@3.4.19(tsx@4.23.13)(yaml@2.9.1))(tslib@2.8.1)(typescript@6.0.3) + postcss: 8.5.26 + rollup: 4.63.0 + tailwindcss: 3.4.19(tsx@4.23.13)(yaml@2.9.1) + vitest: 5.0.0(@opentelemetry/api@1.9.1)(@types/node@20.19.43)(jsdom@30.0.1)(vite@8.2.2(@types/node@20.19.43)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.1)(sass@1.104.1)(tsx@4.23.13)(yaml@2.9.1)) transitivePeerDependencies: - '@types/node' - '@vitejs/devtools' - - chokidar - jiti - kerberos - - sass-embedded - stylus - sugarss - supports-color @@ -11301,62 +11896,57 @@ snapshots: - tsx - yaml - '@angular/cdk@22.1.0-next.4(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2)': + '@angular/cdk@22.2.0-next.5(@angular/common@packages+common)(@angular/core@packages+core)(@angular/forms@packages+forms)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2)': dependencies: '@angular/common': link:packages/common '@angular/core': link:packages/core + '@angular/forms': link:packages/forms '@angular/platform-browser': link:packages/platform-browser parse5: 8.0.1 rxjs: 7.8.2 tslib: 2.8.1 - '@angular/cli@22.1.0-next.4(@cfworker/json-schema@4.1.1)(@types/node@20.19.43)(chokidar@5.0.0)(supports-color@10.2.2)': + '@angular/cli@22.2.0-next.7(@types/node@20.19.43)(chokidar@5.0.0)': dependencies: - '@angular-devkit/architect': 0.2201.0-next.4(chokidar@5.0.0) - '@angular-devkit/core': 22.1.0-next.4(chokidar@5.0.0) - '@angular-devkit/schematics': 22.1.0-next.4(chokidar@5.0.0) - '@inquirer/prompts': 8.5.2(@types/node@20.19.43) - '@listr2/prompt-adapter-inquirer': 4.2.4(@inquirer/prompts@8.5.2(@types/node@20.19.43))(@types/node@20.19.43)(listr2@10.2.2) - '@modelcontextprotocol/sdk': 1.29.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2) - '@schematics/angular': 22.1.0-next.4(chokidar@5.0.0) - algoliasearch: 5.55.2 + '@angular-devkit/architect': 0.2202.0-next.7(chokidar@5.0.0) + '@angular-devkit/core': 22.2.0-next.7(chokidar@5.0.0) + '@angular-devkit/schematics': 22.2.0-next.7(chokidar@5.0.0) + '@inquirer/prompts': 8.7.2(@types/node@20.19.43) + '@listr2/prompt-adapter-inquirer': 4.2.7(@inquirer/prompts@8.7.2(@types/node@20.19.43))(@types/node@20.19.43)(listr2@11.1.0) + '@modelcontextprotocol/server': 2.0.0 + '@schematics/angular': 22.2.0-next.7(chokidar@5.0.0) jsonc-parser: 3.3.1 - listr2: 10.2.2 + listr2: 11.1.0 npm-package-arg: 14.0.0 parse5-html-rewriting-stream: 8.0.1 semver: 7.8.5 - yargs: 18.0.0 - zod: 4.4.3 + yargs: 18.1.0 + zod: 4.5.4 transitivePeerDependencies: - - '@cfworker/json-schema' - '@types/node' - chokidar - - supports-color - '@angular/cli@22.1.0-next.4(@cfworker/json-schema@4.1.1)(@types/node@24.13.3)(chokidar@5.0.0)(supports-color@10.2.2)': + '@angular/cli@22.2.0-next.7(@types/node@24.13.3)(chokidar@5.0.0)': dependencies: - '@angular-devkit/architect': 0.2201.0-next.4(chokidar@5.0.0) - '@angular-devkit/core': 22.1.0-next.4(chokidar@5.0.0) - '@angular-devkit/schematics': 22.1.0-next.4(chokidar@5.0.0) - '@inquirer/prompts': 8.5.2(@types/node@24.13.3) - '@listr2/prompt-adapter-inquirer': 4.2.4(@inquirer/prompts@8.5.2(@types/node@20.19.43))(@types/node@24.13.3)(listr2@10.2.2) - '@modelcontextprotocol/sdk': 1.29.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2) - '@schematics/angular': 22.1.0-next.4(chokidar@5.0.0) - algoliasearch: 5.55.2 + '@angular-devkit/architect': 0.2202.0-next.7(chokidar@5.0.0) + '@angular-devkit/core': 22.2.0-next.7(chokidar@5.0.0) + '@angular-devkit/schematics': 22.2.0-next.7(chokidar@5.0.0) + '@inquirer/prompts': 8.7.2(@types/node@24.13.3) + '@listr2/prompt-adapter-inquirer': 4.2.7(@inquirer/prompts@8.7.2(@types/node@24.13.3))(@types/node@24.13.3)(listr2@11.1.0) + '@modelcontextprotocol/server': 2.0.0 + '@schematics/angular': 22.2.0-next.7(chokidar@5.0.0) jsonc-parser: 3.3.1 - listr2: 10.2.2 + listr2: 11.1.0 npm-package-arg: 14.0.0 parse5-html-rewriting-stream: 8.0.1 semver: 7.8.5 - yargs: 18.0.0 - zod: 4.4.3 + yargs: 18.1.0 + zod: 4.5.4 transitivePeerDependencies: - - '@cfworker/json-schema' - '@types/node' - chokidar - - supports-color - '@angular/core@22.1.0-next.5(@angular/compiler@packages+compiler)': + '@angular/core@22.2.0-next.4(@angular/compiler@packages+compiler)': dependencies: rxjs: 7.8.2 tslib: 2.8.1 @@ -11364,11 +11954,11 @@ snapshots: optionalDependencies: '@angular/compiler': link:packages/compiler - '@angular/domino@https://codeload.github.com/angular/domino/tar.gz/f88e5aa49cf2804d7c2df22ef1640eb4ec43dd56': {} + '@angular/domino@https://codeload.github.com/angular/domino/tar.gz/4d97473116d000e3fd4d6f75ec98cbd67576fa6f': {} - '@angular/material@22.1.0-next.4(@angular/cdk@22.1.0-next.4(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2))(@angular/common@packages+common)(@angular/core@packages+core)(@angular/forms@packages+forms)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2)': + '@angular/material@22.2.0-next.5(@angular/cdk@22.2.0-next.5(@angular/common@packages+common)(@angular/core@packages+core)(@angular/forms@packages+forms)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2))(@angular/common@packages+common)(@angular/core@packages+core)(@angular/forms@packages+forms)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2)': dependencies: - '@angular/cdk': 22.1.0-next.4(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2) + '@angular/cdk': 22.2.0-next.5(@angular/common@packages+common)(@angular/core@packages+core)(@angular/forms@packages+forms)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2) '@angular/common': link:packages/common '@angular/core': link:packages/core '@angular/forms': link:packages/forms @@ -11376,24 +11966,24 @@ snapshots: rxjs: 7.8.2 tslib: 2.8.1 - '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/7a67d5221a9efec2b69b102759d04223a3fc8552(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2))': + '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/c3d7ed184d71d390d3eacff85f4b2b3f16b82660(@modelcontextprotocol/sdk@1.30.0(supports-color@11.0.0))': dependencies: '@actions/core': 3.0.1 - '@conventional-changelog/git-client': 3.1.0(conventional-commits-filter@6.0.1)(conventional-commits-parser@7.1.0) - '@google-cloud/spanner': 8.0.0(supports-color@10.2.2) - '@google/genai': 2.12.0(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2))(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) - '@inquirer/prompts': 8.5.2(@types/node@24.13.3) - '@inquirer/type': 4.0.7(@types/node@24.13.3) - '@octokit/auth-app': 8.2.0 - '@octokit/core': 7.0.6 - '@octokit/graphql': 9.0.3 + '@conventional-changelog/git-client': 3.1.2(conventional-commits-filter@6.0.1)(conventional-commits-parser@7.1.2) + '@google-cloud/spanner': 8.0.0(supports-color@11.0.0) + '@google/genai': 2.20.0(@modelcontextprotocol/sdk@1.30.0(supports-color@11.0.0))(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6) + '@inquirer/prompts': 8.7.0(@types/node@24.13.3) + '@inquirer/type': 4.1.0(@types/node@24.13.3) + '@octokit/auth-app': 8.3.1 + '@octokit/core': 7.0.8 + '@octokit/graphql': 9.0.5 '@octokit/graphql-schema': 15.26.1 - '@octokit/openapi-types': 27.0.0 - '@octokit/plugin-paginate-rest': 14.0.0(@octokit/core@7.0.6) - '@octokit/plugin-rest-endpoint-methods': 17.0.0(@octokit/core@7.0.6) - '@octokit/request-error': 7.1.0 + '@octokit/openapi-types': 28.0.0 + '@octokit/plugin-paginate-rest': 15.0.0(@octokit/core@7.0.8) + '@octokit/plugin-rest-endpoint-methods': 18.0.0(@octokit/core@7.0.8) + '@octokit/request-error': 7.1.2 '@octokit/rest': 22.0.1 - '@octokit/types': 16.0.0 + '@octokit/types': 17.0.0 '@pnpm/dependency-path': 1001.1.10 '@types/cli-progress': 3.11.6 '@types/ejs': 3.1.5 @@ -11401,7 +11991,7 @@ snapshots: '@types/folder-hash': 4.0.4 '@types/jasmine': 6.0.0 '@types/node': 24.13.3 - '@types/semver': 7.7.1 + '@types/semver': 7.8.0 '@types/which': 3.0.4 '@types/yargs': 17.0.35 '@types/yarnpkg__lockfile': 1.1.9 @@ -11409,53 +11999,54 @@ snapshots: bufferutil: 4.1.0 cli-progress: 3.12.0 conventional-commits-filter: 6.0.1 - conventional-commits-parser: 7.1.0 + conventional-commits-parser: 7.1.2 ejs: 6.0.1 encoding: 0.1.13 fast-glob: 3.3.3 - firebase: 12.16.0 - folder-hash: 4.1.3(supports-color@10.2.2) + firebase: 12.18.0 + folder-hash: 4.1.3(supports-color@11.0.0) jasmine: 6.3.0 jasmine-core: 6.3.0 jasmine-reporters: 2.5.2 jsonc-parser: 3.3.1 - minimatch: 10.2.5 + minimatch: 10.2.6 multimatch: 8.0.0 - nock: 14.0.16 + nock: 14.0.17 semver: 7.8.5 - supports-color: 10.2.2 - tsx: 4.23.1 + supports-color: 11.0.0 + tsx: 4.23.13 typed-graphqlify: 3.1.6 typescript: 6.0.3 utf-8-validate: 6.0.6 which: 7.0.0 yaml: 2.9.0 - yargs: 18.0.0 - zod: 4.4.3 + yargs: 18.1.0 + zod: 4.6.5 transitivePeerDependencies: - '@modelcontextprotocol/sdk' - '@react-native-async-storage/async-storage' - '@angular/ssr@22.1.0-next.4(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-server@packages+platform-server)(@angular/router@packages+router)': + '@angular/ssr@22.2.0-next.7(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-server@packages+platform-server)(@angular/router@packages+router)': dependencies: '@angular/common': link:packages/common '@angular/core': link:packages/core '@angular/router': link:packages/router + beasties: 0.5.4 tslib: 2.8.1 optionalDependencies: '@angular/platform-server': link:packages/platform-server '@antfu/install-pkg@1.1.0': dependencies: - package-manager-detector: 1.7.0 - tinyexec: 1.2.4 + package-manager-detector: 1.8.0 + tinyexec: 1.3.0 '@apidevtools/json-schema-ref-parser@9.1.2': dependencies: '@jsdevtools/ono': 7.1.3 '@types/json-schema': 7.0.15 call-me-maybe: 1.0.2 - js-yaml: 4.3.0 + js-yaml: 4.3.2 '@apphosting/common@0.0.8': {} @@ -11467,25 +12058,20 @@ snapshots: '@csstools/css-tokenizer': 3.0.4 lru-cache: 10.4.3 - '@asamuzakjp/css-color@5.1.11': + '@asamuzakjp/css-color@6.0.7': dependencies: - '@asamuzakjp/generational-cache': 1.0.1 - '@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - '@csstools/css-color-parser': 4.1.9(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-calc': 3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-color-parser': 4.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) '@csstools/css-tokenizer': 4.0.0 + lru-cache: 11.5.2 - '@asamuzakjp/dom-selector@7.1.1': + '@asamuzakjp/dom-selector@8.3.2': dependencies: - '@asamuzakjp/generational-cache': 1.0.1 - '@asamuzakjp/nwsapi': 2.3.9 bidi-js: 1.0.3 css-tree: 3.2.1 is-potential-custom-element-name: 1.0.1 - - '@asamuzakjp/generational-cache@1.0.1': {} - - '@asamuzakjp/nwsapi@2.3.9': {} + lru-cache: 11.5.2 '@azu/format-text@1.0.2': {} @@ -11493,86 +12079,91 @@ snapshots: dependencies: '@azu/format-text': 1.0.2 - '@azure/abort-controller@2.1.2': + '@azure/abort-controller@2.2.0': dependencies: tslib: 2.8.1 - '@azure/core-auth@1.10.1(supports-color@10.2.2)': + '@azure/core-auth@1.11.0(supports-color@11.0.0)': dependencies: - '@azure/abort-controller': 2.1.2 - '@azure/core-util': 1.13.1(supports-color@10.2.2) + '@azure/abort-controller': 2.2.0 + '@azure/core-util': 1.14.0(supports-color@11.0.0) tslib: 2.8.1 transitivePeerDependencies: - supports-color - '@azure/core-client@1.10.2(supports-color@10.2.2)': + '@azure/core-client@1.11.0(supports-color@11.0.0)': dependencies: - '@azure/abort-controller': 2.1.2 - '@azure/core-auth': 1.10.1(supports-color@10.2.2) - '@azure/core-rest-pipeline': 1.24.0(supports-color@10.2.2) - '@azure/core-tracing': 1.3.1 - '@azure/core-util': 1.13.1(supports-color@10.2.2) - '@azure/logger': 1.3.0(supports-color@10.2.2) + '@azure/abort-controller': 2.2.0 + '@azure/core-auth': 1.11.0(supports-color@11.0.0) + '@azure/core-rest-pipeline': 1.25.0(supports-color@11.0.0) + '@azure/core-tracing': 1.4.0 + '@azure/core-util': 1.14.0(supports-color@11.0.0) + '@azure/logger': 1.4.0(supports-color@11.0.0) tslib: 2.8.1 transitivePeerDependencies: - supports-color - '@azure/core-rest-pipeline@1.24.0(supports-color@10.2.2)': + '@azure/core-process@1.0.0': {} + + '@azure/core-rest-pipeline@1.25.0(supports-color@11.0.0)': dependencies: - '@azure/abort-controller': 2.1.2 - '@azure/core-auth': 1.10.1(supports-color@10.2.2) - '@azure/core-tracing': 1.3.1 - '@azure/core-util': 1.13.1(supports-color@10.2.2) - '@azure/logger': 1.3.0(supports-color@10.2.2) - '@typespec/ts-http-runtime': 0.3.6(supports-color@10.2.2) + '@azure/abort-controller': 2.2.0 + '@azure/core-auth': 1.11.0(supports-color@11.0.0) + '@azure/core-tracing': 1.4.0 + '@azure/core-util': 1.14.0(supports-color@11.0.0) + '@azure/logger': 1.4.0(supports-color@11.0.0) + '@typespec/ts-http-runtime': 0.3.8(supports-color@11.0.0) tslib: 2.8.1 transitivePeerDependencies: - supports-color - '@azure/core-tracing@1.3.1': + '@azure/core-tracing@1.4.0': dependencies: tslib: 2.8.1 - '@azure/core-util@1.13.1(supports-color@10.2.2)': + '@azure/core-util@1.14.0(supports-color@11.0.0)': dependencies: - '@azure/abort-controller': 2.1.2 - '@typespec/ts-http-runtime': 0.3.6(supports-color@10.2.2) + '@azure/abort-controller': 2.2.0 + '@typespec/ts-http-runtime': 0.3.8(supports-color@11.0.0) tslib: 2.8.1 transitivePeerDependencies: - supports-color - '@azure/identity@4.13.1(supports-color@10.2.2)': - dependencies: - '@azure/abort-controller': 2.1.2 - '@azure/core-auth': 1.10.1(supports-color@10.2.2) - '@azure/core-client': 1.10.2(supports-color@10.2.2) - '@azure/core-rest-pipeline': 1.24.0(supports-color@10.2.2) - '@azure/core-tracing': 1.3.1 - '@azure/core-util': 1.13.1(supports-color@10.2.2) - '@azure/logger': 1.3.0(supports-color@10.2.2) - '@azure/msal-browser': 5.17.0 - '@azure/msal-node': 5.4.0 + '@azure/identity@4.13.2(supports-color@11.0.0)': + dependencies: + '@azure/abort-controller': 2.2.0 + '@azure/core-auth': 1.11.0(supports-color@11.0.0) + '@azure/core-client': 1.11.0(supports-color@11.0.0) + '@azure/core-process': 1.0.0 + '@azure/core-rest-pipeline': 1.25.0(supports-color@11.0.0) + '@azure/core-tracing': 1.4.0 + '@azure/core-util': 1.14.0(supports-color@11.0.0) + '@azure/logger': 1.4.0(supports-color@11.0.0) + '@azure/msal-browser': 5.20.0 + '@azure/msal-node': 5.6.0 open: 10.2.0 tslib: 2.8.1 transitivePeerDependencies: - supports-color - '@azure/logger@1.3.0(supports-color@10.2.2)': + '@azure/logger@1.4.0(supports-color@11.0.0)': dependencies: - '@typespec/ts-http-runtime': 0.3.6(supports-color@10.2.2) + '@typespec/ts-http-runtime': 0.3.8(supports-color@11.0.0) tslib: 2.8.1 transitivePeerDependencies: - supports-color - '@azure/msal-browser@5.17.0': + '@azure/msal-browser@5.20.0': dependencies: - '@azure/msal-common': 16.11.1 + '@azure/msal-common': 16.14.0 - '@azure/msal-common@16.11.1': {} + '@azure/msal-common@16.13.0': {} - '@azure/msal-node@5.4.0': + '@azure/msal-common@16.14.0': {} + + '@azure/msal-node@5.6.0': dependencies: - '@azure/msal-common': 16.11.1 + '@azure/msal-common': 16.13.0 jsonwebtoken: 9.0.3 '@babel/cli@8.0.4(@babel/core@8.0.1)': @@ -11600,20 +12191,20 @@ snapshots: '@babel/compat-data@8.0.0': {} - '@babel/core@7.29.7(supports-color@10.2.2)': + '@babel/core@7.29.7(supports-color@11.0.0)': dependencies: '@babel/code-frame': 7.29.7 - '@babel/generator': 7.29.7 + '@babel/generator': 7.29.8 '@babel/helper-compilation-targets': 7.29.7 - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@11.0.0))(supports-color@11.0.0) '@babel/helpers': 7.29.7 - '@babel/parser': 7.29.7 + '@babel/parser': 7.29.8 '@babel/template': 7.29.7 - '@babel/traverse': 7.29.7(supports-color@10.2.2) - '@babel/types': 7.29.7 + '@babel/traverse': 7.29.8(supports-color@11.0.0) + '@babel/types': 7.29.8 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -11636,13 +12227,13 @@ snapshots: gensync: 1.0.0-beta.2 import-meta-resolve: 4.2.0 json5: 2.2.3 - obug: 2.1.3 + obug: 2.1.4 semver: 7.8.5 - '@babel/generator@7.29.7': + '@babel/generator@7.29.8': dependencies: - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 @@ -11656,15 +12247,11 @@ snapshots: '@types/jsesc': 2.5.1 jsesc: 3.1.0 - '@babel/helper-annotate-as-pure@8.0.0': - dependencies: - '@babel/types': 8.0.4 - '@babel/helper-compilation-targets@7.29.7': dependencies: '@babel/compat-data': 7.29.7 '@babel/helper-validator-option': 7.29.7 - browserslist: 4.28.6 + browserslist: 4.28.8 lru-cache: 5.1.1 semver: 6.3.1 @@ -11672,7 +12259,7 @@ snapshots: dependencies: '@babel/compat-data': 8.0.0 '@babel/helper-validator-option': 8.0.0 - browserslist: 4.28.6 + browserslist: 4.28.8 lru-cache: 11.5.2 semver: 7.8.5 @@ -11680,39 +12267,24 @@ snapshots: '@babel/helper-globals@8.0.0': {} - '@babel/helper-module-imports@7.29.7(supports-color@10.2.2)': + '@babel/helper-module-imports@7.29.7(supports-color@11.0.0)': dependencies: - '@babel/traverse': 7.29.7(supports-color@10.2.2) - '@babel/types': 7.29.7 + '@babel/traverse': 7.29.8(supports-color@11.0.0) + '@babel/types': 7.29.8 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)': + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7(supports-color@11.0.0))(supports-color@11.0.0)': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/helper-module-imports': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@11.0.0) + '@babel/helper-module-imports': 7.29.7(supports-color@11.0.0) '@babel/helper-validator-identifier': 7.29.7 - '@babel/traverse': 7.29.7(supports-color@10.2.2) + '@babel/traverse': 7.29.8(supports-color@11.0.0) transitivePeerDependencies: - supports-color '@babel/helper-plugin-utils@7.29.7': {} - '@babel/helper-plugin-utils@8.0.1(@babel/core@8.0.1)': - dependencies: - '@babel/core': 8.0.1 - - '@babel/helper-remap-async-to-generator@8.0.1(@babel/core@8.0.1)': - dependencies: - '@babel/core': 8.0.1 - '@babel/helper-annotate-as-pure': 8.0.0 - '@babel/helper-wrap-function': 8.0.0 - '@babel/traverse': 8.0.4 - - '@babel/helper-split-export-declaration@7.24.7': - dependencies: - '@babel/types': 7.29.7 - '@babel/helper-string-parser@7.29.7': {} '@babel/helper-string-parser@8.0.0': {} @@ -11725,127 +12297,114 @@ snapshots: '@babel/helper-validator-option@8.0.0': {} - '@babel/helper-wrap-function@8.0.0': - dependencies: - '@babel/template': 8.0.0 - '@babel/traverse': 8.0.4 - '@babel/types': 8.0.4 - '@babel/helpers@7.29.7': dependencies: '@babel/template': 7.29.7 - '@babel/types': 7.29.7 + '@babel/types': 7.29.8 '@babel/helpers@8.0.0': dependencies: '@babel/template': 8.0.0 '@babel/types': 8.0.4 - '@babel/parser@7.29.7': + '@babel/parser@7.29.8': dependencies: - '@babel/types': 7.29.7 + '@babel/types': 7.29.8 '@babel/parser@8.0.4': dependencies: '@babel/types': 8.0.4 - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.29.7(supports-color@11.0.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@11.0.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.29.7(supports-color@11.0.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@11.0.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.29.7(supports-color@11.0.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@11.0.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.29.7(supports-color@11.0.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@11.0.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-import-attributes@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-import-attributes@7.29.7(@babel/core@7.29.7(supports-color@11.0.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@11.0.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.29.7(supports-color@11.0.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@11.0.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.29.7(supports-color@11.0.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@11.0.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-jsx@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-jsx@7.29.7(@babel/core@7.29.7(supports-color@11.0.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@11.0.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.29.7(supports-color@11.0.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@11.0.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.29.7(supports-color@11.0.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@11.0.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.29.7(supports-color@11.0.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@11.0.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.29.7(supports-color@11.0.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@11.0.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.29.7(supports-color@11.0.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@11.0.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.29.7(supports-color@11.0.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@11.0.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.29.7(supports-color@11.0.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@11.0.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.29.7(supports-color@11.0.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@11.0.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-syntax-typescript@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))': + '@babel/plugin-syntax-typescript@7.29.7(@babel/core@7.29.7(supports-color@11.0.0))': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@11.0.0) '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-async-generator-functions@8.0.1(@babel/core@8.0.1)': - dependencies: - '@babel/core': 8.0.1 - '@babel/helper-plugin-utils': 8.0.1(@babel/core@8.0.1) - '@babel/helper-remap-async-to-generator': 8.0.1(@babel/core@8.0.1) - '@babel/traverse': 8.0.4 - '@babel/template@7.29.7': dependencies: '@babel/code-frame': 7.29.7 - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 '@babel/template@8.0.0': dependencies: @@ -11853,15 +12412,15 @@ snapshots: '@babel/parser': 8.0.4 '@babel/types': 8.0.4 - '@babel/traverse@7.29.7(supports-color@10.2.2)': + '@babel/traverse@7.29.8(supports-color@11.0.0)': dependencies: '@babel/code-frame': 7.29.7 - '@babel/generator': 7.29.7 + '@babel/generator': 7.29.8 '@babel/helper-globals': 7.29.7 - '@babel/parser': 7.29.7 + '@babel/parser': 7.29.8 '@babel/template': 7.29.7 - '@babel/types': 7.29.7 - debug: 4.4.3(supports-color@10.2.2) + '@babel/types': 7.29.8 + debug: 4.4.3(supports-color@11.0.0) transitivePeerDependencies: - supports-color @@ -11873,9 +12432,9 @@ snapshots: '@babel/parser': 8.0.4 '@babel/template': 8.0.0 '@babel/types': 8.0.4 - obug: 2.1.3 + obug: 2.1.4 - '@babel/types@7.29.7': + '@babel/types@7.29.8': dependencies: '@babel/helper-string-parser': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 @@ -11899,7 +12458,7 @@ snapshots: dependencies: css-tree: 3.2.1 - '@cfworker/json-schema@4.1.1': {} + '@bufbuild/protobuf@2.14.1': {} '@chevrotain/types@11.1.2': {} @@ -11907,19 +12466,19 @@ snapshots: dependencies: '@codemirror/language': 6.12.4 '@codemirror/state': 6.7.1 - '@codemirror/view': 6.43.6 + '@codemirror/view': 6.43.9 '@lezer/common': 1.5.2 - '@codemirror/commands@6.10.4': + '@codemirror/commands@6.11.0': dependencies: '@codemirror/language': 6.12.4 '@codemirror/state': 6.7.1 - '@codemirror/view': 6.43.6 + '@codemirror/view': 6.43.9 '@lezer/common': 1.5.2 '@codemirror/lang-angular@0.1.4': dependencies: - '@codemirror/lang-html': 6.4.11 + '@codemirror/lang-html': 6.4.12 '@codemirror/lang-javascript': 6.2.5 '@codemirror/language': 6.12.4 '@lezer/common': 1.5.2 @@ -11932,18 +12491,18 @@ snapshots: '@codemirror/language': 6.12.4 '@codemirror/state': 6.7.1 '@lezer/common': 1.5.2 - '@lezer/css': 1.3.4 + '@lezer/css': 1.3.6 - '@codemirror/lang-html@6.4.11': + '@codemirror/lang-html@6.4.12': dependencies: '@codemirror/autocomplete': 6.20.3 '@codemirror/lang-css': 6.3.1 '@codemirror/lang-javascript': 6.2.5 '@codemirror/language': 6.12.4 '@codemirror/state': 6.7.1 - '@codemirror/view': 6.43.6 + '@codemirror/view': 6.43.9 '@lezer/common': 1.5.2 - '@lezer/css': 1.3.4 + '@lezer/css': 1.3.6 '@lezer/html': 1.3.13 '@codemirror/lang-javascript@6.2.5': @@ -11952,7 +12511,7 @@ snapshots: '@codemirror/language': 6.12.4 '@codemirror/lint': 6.9.7 '@codemirror/state': 6.7.1 - '@codemirror/view': 6.43.6 + '@codemirror/view': 6.43.9 '@lezer/common': 1.5.2 '@lezer/javascript': 1.5.4 @@ -11967,7 +12526,7 @@ snapshots: '@codemirror/language@6.12.4': dependencies: '@codemirror/state': 6.7.1 - '@codemirror/view': 6.43.6 + '@codemirror/view': 6.43.9 '@lezer/common': 1.5.2 '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.10 @@ -11976,20 +12535,20 @@ snapshots: '@codemirror/lint@6.9.7': dependencies: '@codemirror/state': 6.7.1 - '@codemirror/view': 6.43.6 + '@codemirror/view': 6.43.9 crelt: 1.0.7 '@codemirror/search@6.7.1': dependencies: '@codemirror/state': 6.7.1 - '@codemirror/view': 6.43.6 + '@codemirror/view': 6.43.9 crelt: 1.0.7 '@codemirror/state@6.7.1': dependencies: - '@marijn/find-cluster-break': 1.0.3 + '@marijn/find-cluster-break': 1.0.4 - '@codemirror/view@6.43.6': + '@codemirror/view@6.43.9': dependencies: '@codemirror/state': 6.7.1 crelt: 1.0.7 @@ -12000,24 +12559,25 @@ snapshots: '@colors/colors@1.6.0': {} - '@conventional-changelog/git-client@2.7.0(conventional-commits-parser@6.4.0)': + '@conventional-changelog/git-client@2.7.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0)': dependencies: '@simple-libs/child-process-utils': 1.0.2 '@simple-libs/stream-utils': 1.2.0 semver: 7.8.5 optionalDependencies: + conventional-commits-filter: 5.0.0 conventional-commits-parser: 6.4.0 - '@conventional-changelog/git-client@3.1.0(conventional-commits-filter@6.0.1)(conventional-commits-parser@7.1.0)': + '@conventional-changelog/git-client@3.1.2(conventional-commits-filter@6.0.1)(conventional-commits-parser@7.1.2)': dependencies: '@simple-libs/child-process-utils': 2.0.0 '@simple-libs/stream-utils': 2.0.0 semver: 7.8.5 optionalDependencies: conventional-commits-filter: 6.0.1 - conventional-commits-parser: 7.1.0 + conventional-commits-parser: 7.1.2 - '@conventional-changelog/template@1.2.1': {} + '@conventional-changelog/template@1.4.0': {} '@cspotcode/source-map-support@0.8.1': dependencies: @@ -12025,14 +12585,14 @@ snapshots: '@csstools/color-helpers@5.1.0': {} - '@csstools/color-helpers@6.1.0': {} + '@csstools/color-helpers@6.1.1': {} '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': dependencies: '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - '@csstools/css-calc@3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + '@csstools/css-calc@3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': dependencies: '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) '@csstools/css-tokenizer': 4.0.0 @@ -12044,10 +12604,10 @@ snapshots: '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - '@csstools/css-color-parser@4.1.9(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + '@csstools/css-color-parser@4.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': dependencies: - '@csstools/color-helpers': 6.1.0 - '@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/color-helpers': 6.1.1 + '@csstools/css-calc': 3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) '@csstools/css-tokenizer': 4.0.0 @@ -12059,7 +12619,7 @@ snapshots: dependencies: '@csstools/css-tokenizer': 4.0.0 - '@csstools/css-syntax-patches-for-csstree@1.1.6(css-tree@3.2.1)': + '@csstools/css-syntax-patches-for-csstree@1.1.10(css-tree@3.2.1)': optionalDependencies: css-tree: 3.2.1 @@ -12082,7 +12642,7 @@ snapshots: json-stringify-safe: 5.0.1 mime-types: 2.1.35 performance-now: 2.1.0 - qs: 6.15.3 + qs: 6.16.0 safe-buffer: 5.2.1 tough-cookie: 5.1.2 tunnel-agent: 0.6.0 @@ -12114,486 +12674,467 @@ snapshots: tslib: 2.8.1 optional: true - '@emnapi/core@1.11.1': - dependencies: - '@emnapi/wasi-threads': 1.2.2 - tslib: 2.8.1 - optional: true - '@emnapi/runtime@1.10.0': dependencies: tslib: 2.8.1 optional: true - '@emnapi/runtime@1.11.1': - dependencies: - tslib: 2.8.1 - optional: true - '@emnapi/wasi-threads@1.2.1': dependencies: tslib: 2.8.1 optional: true - '@emnapi/wasi-threads@1.2.2': - dependencies: - tslib: 2.8.1 - optional: true - - '@esbuild/aix-ppc64@0.28.1': + '@esbuild/aix-ppc64@0.28.2': optional: true - '@esbuild/android-arm64@0.28.1': + '@esbuild/android-arm64@0.28.2': optional: true - '@esbuild/android-arm@0.28.1': + '@esbuild/android-arm@0.28.2': optional: true - '@esbuild/android-x64@0.28.1': + '@esbuild/android-x64@0.28.2': optional: true - '@esbuild/darwin-arm64@0.28.1': + '@esbuild/darwin-arm64@0.28.2': optional: true - '@esbuild/darwin-x64@0.28.1': + '@esbuild/darwin-x64@0.28.2': optional: true - '@esbuild/freebsd-arm64@0.28.1': + '@esbuild/freebsd-arm64@0.28.2': optional: true - '@esbuild/freebsd-x64@0.28.1': + '@esbuild/freebsd-x64@0.28.2': optional: true - '@esbuild/linux-arm64@0.28.1': + '@esbuild/linux-arm64@0.28.2': optional: true - '@esbuild/linux-arm@0.28.1': + '@esbuild/linux-arm@0.28.2': optional: true - '@esbuild/linux-ia32@0.28.1': + '@esbuild/linux-ia32@0.28.2': optional: true - '@esbuild/linux-loong64@0.28.1': + '@esbuild/linux-loong64@0.28.2': optional: true - '@esbuild/linux-mips64el@0.28.1': + '@esbuild/linux-mips64el@0.28.2': optional: true - '@esbuild/linux-ppc64@0.28.1': + '@esbuild/linux-ppc64@0.28.2': optional: true - '@esbuild/linux-riscv64@0.28.1': + '@esbuild/linux-riscv64@0.28.2': optional: true - '@esbuild/linux-s390x@0.28.1': + '@esbuild/linux-s390x@0.28.2': optional: true - '@esbuild/linux-x64@0.28.1': + '@esbuild/linux-x64@0.28.2': optional: true - '@esbuild/netbsd-arm64@0.28.1': + '@esbuild/netbsd-arm64@0.28.2': optional: true - '@esbuild/netbsd-x64@0.28.1': + '@esbuild/netbsd-x64@0.28.2': optional: true - '@esbuild/openbsd-arm64@0.28.1': + '@esbuild/openbsd-arm64@0.28.2': optional: true - '@esbuild/openbsd-x64@0.28.1': + '@esbuild/openbsd-x64@0.28.2': optional: true - '@esbuild/openharmony-arm64@0.28.1': + '@esbuild/openharmony-arm64@0.28.2': optional: true - '@esbuild/sunos-x64@0.28.1': + '@esbuild/sunos-x64@0.28.2': optional: true - '@esbuild/win32-arm64@0.28.1': + '@esbuild/win32-arm64@0.28.2': optional: true - '@esbuild/win32-ia32@0.28.1': + '@esbuild/win32-ia32@0.28.2': optional: true - '@esbuild/win32-x64@0.28.1': + '@esbuild/win32-x64@0.28.2': optional: true '@exodus/bytes@1.15.1': {} '@externs/nodejs@1.5.0': {} - '@firebase/ai@2.13.1(@firebase/app-types@0.9.5)(@firebase/app@0.15.1)': + '@firebase/ai@2.15.0(@firebase/app-types@0.9.6)(@firebase/app@0.16.1)': dependencies: - '@firebase/app': 0.15.1 - '@firebase/app-check-interop-types': 0.3.4 - '@firebase/app-types': 0.9.5 - '@firebase/component': 0.7.3 - '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.1 + '@firebase/app-check-interop-types': 0.3.5 + '@firebase/app-types': 0.9.6 + '@firebase/component': 0.7.5 + '@firebase/logger': 0.5.2 + '@firebase/util': 1.15.3 tslib: 2.8.1 - '@firebase/analytics-compat@0.2.28(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1)': + '@firebase/analytics-compat@0.2.30(@firebase/app-compat@0.5.17)(@firebase/app@0.16.1)': dependencies: - '@firebase/analytics': 0.10.22(@firebase/app@0.15.1) - '@firebase/analytics-types': 0.8.4 - '@firebase/app-compat': 0.5.15 - '@firebase/component': 0.7.3 - '@firebase/util': 1.15.1 + '@firebase/analytics': 0.10.24(@firebase/app@0.16.1) + '@firebase/analytics-types': 0.8.5 + '@firebase/app': 0.16.1 + '@firebase/app-compat': 0.5.17 + '@firebase/component': 0.7.5 + '@firebase/util': 1.15.3 tslib: 2.8.1 - transitivePeerDependencies: - - '@firebase/app' - '@firebase/analytics-types@0.8.4': {} + '@firebase/analytics-types@0.8.5': {} - '@firebase/analytics@0.10.22(@firebase/app@0.15.1)': + '@firebase/analytics@0.10.24(@firebase/app@0.16.1)': dependencies: - '@firebase/app': 0.15.1 - '@firebase/component': 0.7.3 - '@firebase/installations': 0.6.22(@firebase/app@0.15.1) - '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.1 + '@firebase/component': 0.7.5 + '@firebase/installations': 0.6.24(@firebase/app@0.16.1) + '@firebase/logger': 0.5.2 + '@firebase/util': 1.15.3 tslib: 2.8.1 - '@firebase/app-check-compat@0.4.5(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1)': + '@firebase/app-check-compat@0.4.7(@firebase/app-compat@0.5.17)(@firebase/app@0.16.1)': dependencies: - '@firebase/app-check': 0.12.0(@firebase/app@0.15.1) - '@firebase/app-check-types': 0.5.4 - '@firebase/app-compat': 0.5.15 - '@firebase/component': 0.7.3 - '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.1 + '@firebase/app-check': 0.13.1(@firebase/app@0.16.1) + '@firebase/app-check-types': 0.5.5 + '@firebase/app-compat': 0.5.17 + '@firebase/component': 0.7.5 + '@firebase/logger': 0.5.2 + '@firebase/util': 1.15.3 tslib: 2.8.1 - transitivePeerDependencies: - - '@firebase/app' - '@firebase/app-check-interop-types@0.3.4': {} + '@firebase/app-check-interop-types@0.3.5': {} - '@firebase/app-check-types@0.5.4': {} + '@firebase/app-check-types@0.5.5': {} - '@firebase/app-check@0.12.0(@firebase/app@0.15.1)': + '@firebase/app-check@0.13.1(@firebase/app@0.16.1)': dependencies: - '@firebase/app': 0.15.1 - '@firebase/component': 0.7.3 - '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.1 + '@firebase/component': 0.7.5 + '@firebase/logger': 0.5.2 + '@firebase/util': 1.15.3 tslib: 2.8.1 - '@firebase/app-compat@0.5.15': + '@firebase/app-compat@0.5.17': dependencies: - '@firebase/app': 0.15.1 - '@firebase/component': 0.7.3 - '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.1 + '@firebase/component': 0.7.5 + '@firebase/logger': 0.5.2 + '@firebase/util': 1.15.3 tslib: 2.8.1 - '@firebase/app-types@0.9.5': + '@firebase/app-types@0.9.6': dependencies: - '@firebase/logger': 0.5.1 + '@firebase/logger': 0.5.2 - '@firebase/app@0.15.1': + '@firebase/app@0.16.1': dependencies: - '@firebase/component': 0.7.3 - '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/component': 0.7.5 + '@firebase/logger': 0.5.2 + '@firebase/util': 1.15.3 idb: 7.1.1 tslib: 2.8.1 - '@firebase/auth-compat@0.6.8(@firebase/app-compat@0.5.15)(@firebase/app-types@0.9.5)(@firebase/app@0.15.1)': + '@firebase/auth-compat@0.6.10(@firebase/app-compat@0.5.17)(@firebase/app-types@0.9.6)(@firebase/app@0.16.1)': dependencies: - '@firebase/app-compat': 0.5.15 - '@firebase/auth': 1.13.3(@firebase/app@0.15.1) - '@firebase/auth-types': 0.13.1(@firebase/app-types@0.9.5)(@firebase/util@1.15.1) - '@firebase/component': 0.7.3 - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.1 + '@firebase/app-compat': 0.5.17 + '@firebase/auth': 1.13.5(@firebase/app@0.16.1) + '@firebase/auth-types': 0.13.2(@firebase/app-types@0.9.6)(@firebase/util@1.15.3) + '@firebase/component': 0.7.5 + '@firebase/util': 1.15.3 tslib: 2.8.1 transitivePeerDependencies: - - '@firebase/app' - '@firebase/app-types' - '@react-native-async-storage/async-storage' - '@firebase/auth-interop-types@0.2.5': {} + '@firebase/auth-interop-types@0.2.6': {} - '@firebase/auth-types@0.13.1(@firebase/app-types@0.9.5)(@firebase/util@1.15.1)': + '@firebase/auth-types@0.13.2(@firebase/app-types@0.9.6)(@firebase/util@1.15.3)': dependencies: - '@firebase/app-types': 0.9.5 - '@firebase/util': 1.15.1 + '@firebase/app-types': 0.9.6 + '@firebase/util': 1.15.3 - '@firebase/auth@1.13.3(@firebase/app@0.15.1)': + '@firebase/auth@1.13.5(@firebase/app@0.16.1)': dependencies: - '@firebase/app': 0.15.1 - '@firebase/component': 0.7.3 - '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.1 + '@firebase/component': 0.7.5 + '@firebase/logger': 0.5.2 + '@firebase/util': 1.15.3 tslib: 2.8.1 - '@firebase/component@0.7.3': + '@firebase/component@0.7.5': dependencies: - '@firebase/util': 1.15.1 + '@firebase/util': 1.15.3 tslib: 2.8.1 - '@firebase/data-connect@0.7.1(@firebase/app@0.15.1)': + '@firebase/data-connect@0.7.4(@firebase/app@0.16.1)': dependencies: - '@firebase/app': 0.15.1 - '@firebase/auth-interop-types': 0.2.5 - '@firebase/component': 0.7.3 - '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.1 + '@firebase/auth-interop-types': 0.2.6 + '@firebase/component': 0.7.5 + '@firebase/logger': 0.5.2 + '@firebase/util': 1.15.3 tslib: 2.8.1 - '@firebase/database-compat@2.1.4': + '@firebase/database-compat@2.1.7(@firebase/app-compat@0.5.17)(@firebase/app@0.16.1)': dependencies: - '@firebase/component': 0.7.3 - '@firebase/database': 1.1.3 - '@firebase/database-types': 1.0.20 - '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/component': 0.7.5 + '@firebase/database': 1.1.5 + '@firebase/database-types': 1.0.22 + '@firebase/logger': 0.5.2 + '@firebase/util': 1.15.3 tslib: 2.8.1 + optionalDependencies: + '@firebase/app': 0.16.1 + '@firebase/app-compat': 0.5.17 - '@firebase/database-types@1.0.20': + '@firebase/database-types@1.0.22': dependencies: - '@firebase/app-types': 0.9.5 - '@firebase/util': 1.15.1 + '@firebase/app-types': 0.9.6 + '@firebase/util': 1.15.3 - '@firebase/database@1.1.3': + '@firebase/database@1.1.5': dependencies: - '@firebase/app-check-interop-types': 0.3.4 - '@firebase/auth-interop-types': 0.2.5 - '@firebase/component': 0.7.3 - '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/app-check-interop-types': 0.3.5 + '@firebase/auth-interop-types': 0.2.6 + '@firebase/component': 0.7.5 + '@firebase/logger': 0.5.2 + '@firebase/util': 1.15.3 faye-websocket: 0.11.4 tslib: 2.8.1 - '@firebase/firestore-compat@0.4.11(@firebase/app-compat@0.5.15)(@firebase/app-types@0.9.5)(@firebase/app@0.15.1)': + '@firebase/firestore-compat@0.4.13(@firebase/app-compat@0.5.17)(@firebase/app-types@0.9.6)(@firebase/app@0.16.1)': dependencies: - '@firebase/app-compat': 0.5.15 - '@firebase/component': 0.7.3 - '@firebase/firestore': 4.16.0(@firebase/app@0.15.1) - '@firebase/firestore-types': 3.0.4(@firebase/app-types@0.9.5)(@firebase/util@1.15.1) - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.1 + '@firebase/app-compat': 0.5.17 + '@firebase/component': 0.7.5 + '@firebase/firestore': 4.17.1(@firebase/app@0.16.1) + '@firebase/firestore-types': 3.0.5(@firebase/app-types@0.9.6)(@firebase/util@1.15.3) + '@firebase/util': 1.15.3 tslib: 2.8.1 transitivePeerDependencies: - - '@firebase/app' - '@firebase/app-types' - '@firebase/firestore-types@3.0.4(@firebase/app-types@0.9.5)(@firebase/util@1.15.1)': + '@firebase/firestore-types@3.0.5(@firebase/app-types@0.9.6)(@firebase/util@1.15.3)': dependencies: - '@firebase/app-types': 0.9.5 - '@firebase/util': 1.15.1 + '@firebase/app-types': 0.9.6 + '@firebase/util': 1.15.3 - '@firebase/firestore@4.16.0(@firebase/app@0.15.1)': + '@firebase/firestore@4.17.1(@firebase/app@0.16.1)': dependencies: - '@firebase/app': 0.15.1 - '@firebase/component': 0.7.3 - '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 - '@firebase/webchannel-wrapper': 1.0.6 + '@firebase/app': 0.16.1 + '@firebase/component': 0.7.5 + '@firebase/logger': 0.5.2 + '@firebase/util': 1.15.3 + '@firebase/webchannel-wrapper': 1.0.7 '@grpc/grpc-js': 1.9.16 '@grpc/proto-loader': 0.7.15 - re2js: 0.4.3 + re2js: 2.8.6 tslib: 2.8.1 - '@firebase/functions-compat@0.4.5(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1)': + '@firebase/functions-compat@0.5.0(@firebase/app-compat@0.5.17)(@firebase/app@0.16.1)': dependencies: - '@firebase/app-compat': 0.5.15 - '@firebase/component': 0.7.3 - '@firebase/functions': 0.13.5(@firebase/app@0.15.1) - '@firebase/functions-types': 0.6.4 - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.1 + '@firebase/app-compat': 0.5.17 + '@firebase/component': 0.7.5 + '@firebase/functions': 0.14.0(@firebase/app@0.16.1) + '@firebase/functions-types': 0.6.5 + '@firebase/util': 1.15.3 tslib: 2.8.1 - transitivePeerDependencies: - - '@firebase/app' - '@firebase/functions-types@0.6.4': {} + '@firebase/functions-types@0.6.5': {} - '@firebase/functions@0.13.5(@firebase/app@0.15.1)': + '@firebase/functions@0.14.0(@firebase/app@0.16.1)': dependencies: - '@firebase/app': 0.15.1 - '@firebase/app-check-interop-types': 0.3.4 - '@firebase/auth-interop-types': 0.2.5 - '@firebase/component': 0.7.3 - '@firebase/messaging-interop-types': 0.2.5 - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.1 + '@firebase/app-check-interop-types': 0.3.5 + '@firebase/auth-interop-types': 0.2.6 + '@firebase/component': 0.7.5 + '@firebase/messaging-interop-types': 0.2.6 + '@firebase/util': 1.15.3 tslib: 2.8.1 - '@firebase/installations-compat@0.2.22(@firebase/app-compat@0.5.15)(@firebase/app-types@0.9.5)(@firebase/app@0.15.1)': + '@firebase/installations-compat@0.2.24(@firebase/app-compat@0.5.17)(@firebase/app-types@0.9.6)(@firebase/app@0.16.1)': dependencies: - '@firebase/app-compat': 0.5.15 - '@firebase/component': 0.7.3 - '@firebase/installations': 0.6.22(@firebase/app@0.15.1) - '@firebase/installations-types': 0.5.4(@firebase/app-types@0.9.5) - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.1 + '@firebase/app-compat': 0.5.17 + '@firebase/component': 0.7.5 + '@firebase/installations': 0.6.24(@firebase/app@0.16.1) + '@firebase/installations-types': 0.5.5(@firebase/app-types@0.9.6) + '@firebase/util': 1.15.3 tslib: 2.8.1 transitivePeerDependencies: - - '@firebase/app' - '@firebase/app-types' - '@firebase/installations-types@0.5.4(@firebase/app-types@0.9.5)': + '@firebase/installations-types@0.5.5(@firebase/app-types@0.9.6)': dependencies: - '@firebase/app-types': 0.9.5 + '@firebase/app-types': 0.9.6 - '@firebase/installations@0.6.22(@firebase/app@0.15.1)': + '@firebase/installations@0.6.24(@firebase/app@0.16.1)': dependencies: - '@firebase/app': 0.15.1 - '@firebase/component': 0.7.3 - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.1 + '@firebase/component': 0.7.5 + '@firebase/util': 1.15.3 idb: 7.1.1 tslib: 2.8.1 - '@firebase/logger@0.5.1': + '@firebase/logger@0.5.2': dependencies: tslib: 2.8.1 - '@firebase/messaging-compat@0.2.27(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1)': + '@firebase/messaging-compat@0.2.29(@firebase/app-compat@0.5.17)(@firebase/app@0.16.1)': dependencies: - '@firebase/app-compat': 0.5.15 - '@firebase/component': 0.7.3 - '@firebase/messaging': 0.13.0(@firebase/app@0.15.1) - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.1 + '@firebase/app-compat': 0.5.17 + '@firebase/component': 0.7.5 + '@firebase/messaging': 0.13.2(@firebase/app@0.16.1) + '@firebase/util': 1.15.3 tslib: 2.8.1 - transitivePeerDependencies: - - '@firebase/app' - '@firebase/messaging-interop-types@0.2.5': {} + '@firebase/messaging-interop-types@0.2.6': {} - '@firebase/messaging@0.13.0(@firebase/app@0.15.1)': + '@firebase/messaging@0.13.2(@firebase/app@0.16.1)': dependencies: - '@firebase/app': 0.15.1 - '@firebase/component': 0.7.3 - '@firebase/installations': 0.6.22(@firebase/app@0.15.1) - '@firebase/messaging-interop-types': 0.2.5 - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.1 + '@firebase/component': 0.7.5 + '@firebase/installations': 0.6.24(@firebase/app@0.16.1) + '@firebase/messaging-interop-types': 0.2.6 + '@firebase/util': 1.15.3 idb: 7.1.1 tslib: 2.8.1 - '@firebase/performance-compat@0.2.25(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1)': + '@firebase/performance-compat@0.2.27(@firebase/app-compat@0.5.17)(@firebase/app@0.16.1)': dependencies: - '@firebase/app-compat': 0.5.15 - '@firebase/component': 0.7.3 - '@firebase/logger': 0.5.1 - '@firebase/performance': 0.7.12(@firebase/app@0.15.1) - '@firebase/performance-types': 0.2.4 - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.1 + '@firebase/app-compat': 0.5.17 + '@firebase/component': 0.7.5 + '@firebase/logger': 0.5.2 + '@firebase/performance': 0.7.14(@firebase/app@0.16.1) + '@firebase/performance-types': 0.2.5 + '@firebase/util': 1.15.3 tslib: 2.8.1 - transitivePeerDependencies: - - '@firebase/app' - '@firebase/performance-types@0.2.4': {} + '@firebase/performance-types@0.2.5': {} - '@firebase/performance@0.7.12(@firebase/app@0.15.1)': + '@firebase/performance@0.7.14(@firebase/app@0.16.1)': dependencies: - '@firebase/app': 0.15.1 - '@firebase/component': 0.7.3 - '@firebase/installations': 0.6.22(@firebase/app@0.15.1) - '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.1 + '@firebase/component': 0.7.5 + '@firebase/installations': 0.6.24(@firebase/app@0.16.1) + '@firebase/logger': 0.5.2 + '@firebase/util': 1.15.3 tslib: 2.8.1 web-vitals: 4.2.4 - '@firebase/remote-config-compat@0.2.27(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1)': + '@firebase/remote-config-compat@0.2.29(@firebase/app-compat@0.5.17)(@firebase/app@0.16.1)': dependencies: - '@firebase/app-compat': 0.5.15 - '@firebase/component': 0.7.3 - '@firebase/logger': 0.5.1 - '@firebase/remote-config': 0.9.0(@firebase/app@0.15.1) - '@firebase/remote-config-types': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.1 + '@firebase/app-compat': 0.5.17 + '@firebase/component': 0.7.5 + '@firebase/logger': 0.5.2 + '@firebase/remote-config': 0.9.2(@firebase/app@0.16.1) + '@firebase/remote-config-types': 0.5.2 + '@firebase/util': 1.15.3 tslib: 2.8.1 - transitivePeerDependencies: - - '@firebase/app' - '@firebase/remote-config-types@0.5.1': {} + '@firebase/remote-config-types@0.5.2': {} - '@firebase/remote-config@0.9.0(@firebase/app@0.15.1)': + '@firebase/remote-config@0.9.2(@firebase/app@0.16.1)': dependencies: - '@firebase/app': 0.15.1 - '@firebase/component': 0.7.3 - '@firebase/installations': 0.6.22(@firebase/app@0.15.1) - '@firebase/logger': 0.5.1 - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.1 + '@firebase/component': 0.7.5 + '@firebase/installations': 0.6.24(@firebase/app@0.16.1) + '@firebase/logger': 0.5.2 + '@firebase/util': 1.15.3 tslib: 2.8.1 - '@firebase/storage-compat@0.4.3(@firebase/app-compat@0.5.15)(@firebase/app-types@0.9.5)(@firebase/app@0.15.1)': + '@firebase/storage-compat@0.4.5(@firebase/app-compat@0.5.17)(@firebase/app-types@0.9.6)(@firebase/app@0.16.1)': dependencies: - '@firebase/app-compat': 0.5.15 - '@firebase/component': 0.7.3 - '@firebase/storage': 0.14.3(@firebase/app@0.15.1) - '@firebase/storage-types': 0.8.4(@firebase/app-types@0.9.5)(@firebase/util@1.15.1) - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.1 + '@firebase/app-compat': 0.5.17 + '@firebase/component': 0.7.5 + '@firebase/storage': 0.14.5(@firebase/app@0.16.1) + '@firebase/storage-types': 0.8.5(@firebase/app-types@0.9.6)(@firebase/util@1.15.3) + '@firebase/util': 1.15.3 tslib: 2.8.1 transitivePeerDependencies: - - '@firebase/app' - '@firebase/app-types' - '@firebase/storage-types@0.8.4(@firebase/app-types@0.9.5)(@firebase/util@1.15.1)': + '@firebase/storage-types@0.8.5(@firebase/app-types@0.9.6)(@firebase/util@1.15.3)': dependencies: - '@firebase/app-types': 0.9.5 - '@firebase/util': 1.15.1 + '@firebase/app-types': 0.9.6 + '@firebase/util': 1.15.3 - '@firebase/storage@0.14.3(@firebase/app@0.15.1)': + '@firebase/storage@0.14.5(@firebase/app@0.16.1)': dependencies: - '@firebase/app': 0.15.1 - '@firebase/component': 0.7.3 - '@firebase/util': 1.15.1 + '@firebase/app': 0.16.1 + '@firebase/component': 0.7.5 + '@firebase/util': 1.15.3 tslib: 2.8.1 - '@firebase/util@1.15.1': + '@firebase/util@1.15.3': dependencies: tslib: 2.8.1 - '@firebase/webchannel-wrapper@1.0.6': {} + '@firebase/webchannel-wrapper@1.0.7': {} - '@google-cloud/cloud-sql-connector@1.11.2(supports-color@10.2.2)': + '@google-cloud/cloud-sql-connector@1.11.3(supports-color@11.0.0)': dependencies: - '@googleapis/sqladmin': 37.0.0(supports-color@10.2.2) - gaxios: 7.2.0(supports-color@10.2.2) - google-auth-library: 10.9.0(supports-color@10.2.2) - p-throttle: 7.0.0 + '@googleapis/sqladmin': 37.0.0(supports-color@11.0.0) + gaxios: 7.3.1(supports-color@11.0.0) + google-auth-library: 10.9.1(supports-color@11.0.0) + p-throttle: 8.1.0 transitivePeerDependencies: - supports-color - '@google-cloud/common@6.0.1(supports-color@10.2.2)': + '@google-cloud/common@6.1.0(supports-color@11.0.0)': dependencies: '@google-cloud/projectify': 4.0.0 '@google-cloud/promisify': 4.1.0 arrify: 2.0.1 duplexify: 4.1.3 extend: 3.0.2 - google-auth-library: 10.9.0(supports-color@10.2.2) + google-auth-library: 10.9.1(supports-color@11.0.0) html-entities: 2.6.0 - retry-request: 8.0.3(supports-color@10.2.2) - teeny-request: 10.1.3(supports-color@10.2.2) + retry-request: 8.0.4(supports-color@11.0.0) + teeny-request: 10.1.4(supports-color@11.0.0) transitivePeerDependencies: - supports-color - '@google-cloud/paginator@6.0.2': + '@google-cloud/paginator@6.1.0': dependencies: extend: 3.0.2 - '@google-cloud/precise-date@5.1.0': {} + '@google-cloud/precise-date@5.2.0': {} '@google-cloud/projectify@4.0.0': {} - '@google-cloud/projectify@5.1.0': {} + '@google-cloud/projectify@5.2.0': {} '@google-cloud/promisify@4.1.0': {} '@google-cloud/promisify@5.1.0': {} - '@google-cloud/pubsub@5.3.1(supports-color@10.2.2)': + '@google-cloud/pubsub@5.3.1(supports-color@11.0.0)': dependencies: - '@google-cloud/paginator': 6.0.2 - '@google-cloud/precise-date': 5.1.0 - '@google-cloud/projectify': 5.1.0 + '@google-cloud/paginator': 6.1.0 + '@google-cloud/precise-date': 5.2.0 + '@google-cloud/projectify': 5.2.0 '@google-cloud/promisify': 5.1.0 '@opentelemetry/api': 1.9.1 '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.39.0 arrify: 2.0.1 extend: 3.0.2 - google-auth-library: 10.9.0(supports-color@10.2.2) - google-gax: 5.0.7(supports-color@10.2.2) - google-logging-utils: 1.1.4 + google-auth-library: 10.9.1(supports-color@11.0.0) + google-gax: 5.0.8(supports-color@11.0.0) + google-logging-utils: 1.2.0 heap-js: 2.7.1 is-stream-ended: 0.1.4 lodash.snakecase: 4.1.1 @@ -12602,16 +13143,16 @@ snapshots: transitivePeerDependencies: - supports-color - '@google-cloud/spanner@8.0.0(supports-color@10.2.2)': + '@google-cloud/spanner@8.0.0(supports-color@11.0.0)': dependencies: - '@google-cloud/common': 6.0.1(supports-color@10.2.2) - '@google-cloud/precise-date': 5.1.0 - '@google-cloud/projectify': 5.1.0 + '@google-cloud/common': 6.1.0(supports-color@11.0.0) + '@google-cloud/precise-date': 5.2.0 + '@google-cloud/projectify': 5.2.0 '@google-cloud/promisify': 5.1.0 '@grpc/proto-loader': 0.7.15 '@opentelemetry/api': 1.9.1 - '@opentelemetry/context-async-hooks': 2.9.0(@opentelemetry/api@1.9.1) - '@opentelemetry/core': 2.9.0(@opentelemetry/api@1.9.1) + '@opentelemetry/context-async-hooks': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/core': 2.10.0(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.43.0 '@types/big.js': 6.2.2 '@types/stack-trace': 0.0.33 @@ -12620,39 +13161,39 @@ snapshots: duplexify: 4.1.3 events-intercept: 2.0.0 extend: 3.0.2 - google-auth-library: 10.9.0(supports-color@10.2.2) - google-gax: 5.0.7(supports-color@10.2.2) - grpc-gcp: 1.0.1(protobufjs@7.6.5) + google-auth-library: 10.9.1(supports-color@11.0.0) + google-gax: 5.0.8(supports-color@11.0.0) + grpc-gcp: 1.1.1 is: 3.3.2 lodash.snakecase: 4.1.1 merge-stream: 2.0.0 p-queue: 6.6.2 - protobufjs: 7.6.5 - retry-request: 8.0.3(supports-color@10.2.2) + protobufjs: 7.6.6 + retry-request: 8.0.4(supports-color@11.0.0) split-array-stream: 2.0.0 stack-trace: 0.0.10 stream-events: 1.0.5 - teeny-request: 10.1.3(supports-color@10.2.2) + teeny-request: 10.1.4(supports-color@11.0.0) through2: 4.0.2 transitivePeerDependencies: - supports-color - '@google/genai@2.12.0(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2))(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6)': + '@google/genai@2.20.0(@modelcontextprotocol/sdk@1.30.0(supports-color@11.0.0))(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6)': dependencies: - google-auth-library: 10.9.0(supports-color@10.2.2) + google-auth-library: 10.9.1(supports-color@11.0.0) p-retry: 4.6.2 - protobufjs: 7.6.5 - ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) + protobufjs: 7.6.6 + ws: 8.21.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) optionalDependencies: - '@modelcontextprotocol/sdk': 1.29.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2) + '@modelcontextprotocol/sdk': 1.30.0(supports-color@11.0.0) transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - '@googleapis/sqladmin@37.0.0(supports-color@10.2.2)': + '@googleapis/sqladmin@37.0.0(supports-color@11.0.0)': dependencies: - googleapis-common: 8.0.2(supports-color@10.2.2) + googleapis-common: 8.0.3(supports-color@11.0.0) transitivePeerDependencies: - supports-color @@ -12670,14 +13211,14 @@ snapshots: dependencies: lodash.camelcase: 4.3.0 long: 5.3.2 - protobufjs: 7.6.5 + protobufjs: 7.6.6 yargs: 17.7.3 '@grpc/proto-loader@0.8.1': dependencies: lodash.camelcase: 4.3.0 long: 5.3.2 - protobufjs: 7.6.5 + protobufjs: 7.6.6 yargs: 17.7.3 '@gulpjs/messages@1.1.0': {} @@ -12689,9 +13230,9 @@ snapshots: '@harperfast/extended-iterable@1.0.3': optional: true - '@hono/node-server@1.19.14(hono@4.12.30)': + '@hono/node-server@2.1.1(hono@4.13.5)': dependencies: - hono: 4.12.30 + hono: 4.13.5 '@hutson/parse-repository-url@5.0.0': {} @@ -12707,6 +13248,8 @@ snapshots: '@inquirer/ansi@2.0.7': {} + '@inquirer/ansi@2.0.8': {} + '@inquirer/checkbox@4.3.2(@types/node@20.19.43)': dependencies: '@inquirer/ansi': 1.0.2 @@ -12717,21 +13260,39 @@ snapshots: optionalDependencies: '@types/node': 20.19.43 - '@inquirer/checkbox@5.2.1(@types/node@20.19.43)': + '@inquirer/checkbox@5.2.3(@types/node@20.19.43)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/core': 11.2.1(@types/node@20.19.43) - '@inquirer/figures': 2.0.7 - '@inquirer/type': 4.0.7(@types/node@20.19.43) + '@inquirer/core': 12.0.1(@types/node@20.19.43) + '@inquirer/figures': 2.0.8 + '@inquirer/type': 4.1.0(@types/node@20.19.43) optionalDependencies: '@types/node': 20.19.43 - '@inquirer/checkbox@5.2.1(@types/node@24.13.3)': + '@inquirer/checkbox@5.2.3(@types/node@24.13.3)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/core': 11.2.1(@types/node@24.13.3) - '@inquirer/figures': 2.0.7 - '@inquirer/type': 4.0.7(@types/node@24.13.3) + '@inquirer/core': 12.0.1(@types/node@24.13.3) + '@inquirer/figures': 2.0.8 + '@inquirer/type': 4.1.0(@types/node@24.13.3) + optionalDependencies: + '@types/node': 24.13.3 + + '@inquirer/checkbox@5.2.5(@types/node@20.19.43)': + dependencies: + '@inquirer/ansi': 2.0.8 + '@inquirer/core': 12.0.3(@types/node@20.19.43) + '@inquirer/figures': 2.0.9 + '@inquirer/type': 4.1.1(@types/node@20.19.43) + optionalDependencies: + '@types/node': 20.19.43 + + '@inquirer/checkbox@5.2.5(@types/node@24.13.3)': + dependencies: + '@inquirer/ansi': 2.0.8 + '@inquirer/core': 12.0.3(@types/node@24.13.3) + '@inquirer/figures': 2.0.9 + '@inquirer/type': 4.1.1(@types/node@24.13.3) optionalDependencies: '@types/node': 24.13.3 @@ -12742,17 +13303,31 @@ snapshots: optionalDependencies: '@types/node': 20.19.43 - '@inquirer/confirm@6.1.1(@types/node@20.19.43)': + '@inquirer/confirm@6.3.0(@types/node@20.19.43)': + dependencies: + '@inquirer/core': 12.0.1(@types/node@20.19.43) + '@inquirer/type': 4.1.0(@types/node@20.19.43) + optionalDependencies: + '@types/node': 20.19.43 + + '@inquirer/confirm@6.3.0(@types/node@24.13.3)': dependencies: - '@inquirer/core': 11.2.1(@types/node@20.19.43) - '@inquirer/type': 4.0.7(@types/node@20.19.43) + '@inquirer/core': 12.0.1(@types/node@24.13.3) + '@inquirer/type': 4.1.0(@types/node@24.13.3) + optionalDependencies: + '@types/node': 24.13.3 + + '@inquirer/confirm@6.3.2(@types/node@20.19.43)': + dependencies: + '@inquirer/core': 12.0.3(@types/node@20.19.43) + '@inquirer/type': 4.1.1(@types/node@20.19.43) optionalDependencies: '@types/node': 20.19.43 - '@inquirer/confirm@6.1.1(@types/node@24.13.3)': + '@inquirer/confirm@6.3.2(@types/node@24.13.3)': dependencies: - '@inquirer/core': 11.2.1(@types/node@24.13.3) - '@inquirer/type': 4.0.7(@types/node@24.13.3) + '@inquirer/core': 12.0.3(@types/node@24.13.3) + '@inquirer/type': 4.1.1(@types/node@24.13.3) optionalDependencies: '@types/node': 24.13.3 @@ -12769,11 +13344,11 @@ snapshots: optionalDependencies: '@types/node': 20.19.43 - '@inquirer/core@11.2.1(@types/node@20.19.43)': + '@inquirer/core@12.0.1(@types/node@20.19.43)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/figures': 2.0.7 - '@inquirer/type': 4.0.7(@types/node@20.19.43) + '@inquirer/figures': 2.0.8 + '@inquirer/type': 4.1.1(@types/node@20.19.43) cli-width: 4.1.0 fast-wrap-ansi: 0.2.2 mute-stream: 3.0.0 @@ -12781,11 +13356,35 @@ snapshots: optionalDependencies: '@types/node': 20.19.43 - '@inquirer/core@11.2.1(@types/node@24.13.3)': + '@inquirer/core@12.0.1(@types/node@24.13.3)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/figures': 2.0.7 - '@inquirer/type': 4.0.7(@types/node@24.13.3) + '@inquirer/figures': 2.0.8 + '@inquirer/type': 4.1.1(@types/node@24.13.3) + cli-width: 4.1.0 + fast-wrap-ansi: 0.2.2 + mute-stream: 3.0.0 + signal-exit: 4.1.0 + optionalDependencies: + '@types/node': 24.13.3 + + '@inquirer/core@12.0.3(@types/node@20.19.43)': + dependencies: + '@inquirer/ansi': 2.0.8 + '@inquirer/figures': 2.0.9 + '@inquirer/type': 4.1.1(@types/node@20.19.43) + cli-width: 4.1.0 + fast-wrap-ansi: 0.2.2 + mute-stream: 3.0.0 + signal-exit: 4.1.0 + optionalDependencies: + '@types/node': 20.19.43 + + '@inquirer/core@12.0.3(@types/node@24.13.3)': + dependencies: + '@inquirer/ansi': 2.0.8 + '@inquirer/figures': 2.0.9 + '@inquirer/type': 4.1.1(@types/node@24.13.3) cli-width: 4.1.0 fast-wrap-ansi: 0.2.2 mute-stream: 3.0.0 @@ -12801,19 +13400,35 @@ snapshots: optionalDependencies: '@types/node': 20.19.43 - '@inquirer/editor@5.2.2(@types/node@20.19.43)': + '@inquirer/editor@5.3.1(@types/node@20.19.43)': + dependencies: + '@inquirer/core': 12.0.1(@types/node@20.19.43) + '@inquirer/external-editor': 3.0.4(@types/node@20.19.43) + '@inquirer/type': 4.1.0(@types/node@20.19.43) + optionalDependencies: + '@types/node': 20.19.43 + + '@inquirer/editor@5.3.1(@types/node@24.13.3)': dependencies: - '@inquirer/core': 11.2.1(@types/node@20.19.43) - '@inquirer/external-editor': 3.0.3(@types/node@20.19.43) - '@inquirer/type': 4.0.7(@types/node@20.19.43) + '@inquirer/core': 12.0.1(@types/node@24.13.3) + '@inquirer/external-editor': 3.0.4(@types/node@24.13.3) + '@inquirer/type': 4.1.0(@types/node@24.13.3) + optionalDependencies: + '@types/node': 24.13.3 + + '@inquirer/editor@5.3.3(@types/node@20.19.43)': + dependencies: + '@inquirer/core': 12.0.3(@types/node@20.19.43) + '@inquirer/external-editor': 3.0.5(@types/node@20.19.43) + '@inquirer/type': 4.1.1(@types/node@20.19.43) optionalDependencies: '@types/node': 20.19.43 - '@inquirer/editor@5.2.2(@types/node@24.13.3)': + '@inquirer/editor@5.3.3(@types/node@24.13.3)': dependencies: - '@inquirer/core': 11.2.1(@types/node@24.13.3) - '@inquirer/external-editor': 3.0.3(@types/node@24.13.3) - '@inquirer/type': 4.0.7(@types/node@24.13.3) + '@inquirer/core': 12.0.3(@types/node@24.13.3) + '@inquirer/external-editor': 3.0.5(@types/node@24.13.3) + '@inquirer/type': 4.1.1(@types/node@24.13.3) optionalDependencies: '@types/node': 24.13.3 @@ -12825,17 +13440,31 @@ snapshots: optionalDependencies: '@types/node': 20.19.43 - '@inquirer/expand@5.1.1(@types/node@20.19.43)': + '@inquirer/expand@5.1.3(@types/node@20.19.43)': + dependencies: + '@inquirer/core': 12.0.1(@types/node@20.19.43) + '@inquirer/type': 4.1.0(@types/node@20.19.43) + optionalDependencies: + '@types/node': 20.19.43 + + '@inquirer/expand@5.1.3(@types/node@24.13.3)': dependencies: - '@inquirer/core': 11.2.1(@types/node@20.19.43) - '@inquirer/type': 4.0.7(@types/node@20.19.43) + '@inquirer/core': 12.0.1(@types/node@24.13.3) + '@inquirer/type': 4.1.0(@types/node@24.13.3) + optionalDependencies: + '@types/node': 24.13.3 + + '@inquirer/expand@5.1.5(@types/node@20.19.43)': + dependencies: + '@inquirer/core': 12.0.3(@types/node@20.19.43) + '@inquirer/type': 4.1.1(@types/node@20.19.43) optionalDependencies: '@types/node': 20.19.43 - '@inquirer/expand@5.1.1(@types/node@24.13.3)': + '@inquirer/expand@5.1.5(@types/node@24.13.3)': dependencies: - '@inquirer/core': 11.2.1(@types/node@24.13.3) - '@inquirer/type': 4.0.7(@types/node@24.13.3) + '@inquirer/core': 12.0.3(@types/node@24.13.3) + '@inquirer/type': 4.1.1(@types/node@24.13.3) optionalDependencies: '@types/node': 24.13.3 @@ -12846,14 +13475,28 @@ snapshots: optionalDependencies: '@types/node': 20.19.43 - '@inquirer/external-editor@3.0.3(@types/node@20.19.43)': + '@inquirer/external-editor@3.0.4(@types/node@20.19.43)': + dependencies: + chardet: 2.2.0 + iconv-lite: 0.7.3 + optionalDependencies: + '@types/node': 20.19.43 + + '@inquirer/external-editor@3.0.4(@types/node@24.13.3)': + dependencies: + chardet: 2.2.0 + iconv-lite: 0.7.3 + optionalDependencies: + '@types/node': 24.13.3 + + '@inquirer/external-editor@3.0.5(@types/node@20.19.43)': dependencies: chardet: 2.2.0 iconv-lite: 0.7.3 optionalDependencies: '@types/node': 20.19.43 - '@inquirer/external-editor@3.0.3(@types/node@24.13.3)': + '@inquirer/external-editor@3.0.5(@types/node@24.13.3)': dependencies: chardet: 2.2.0 iconv-lite: 0.7.3 @@ -12862,7 +13505,9 @@ snapshots: '@inquirer/figures@1.0.15': {} - '@inquirer/figures@2.0.7': {} + '@inquirer/figures@2.0.8': {} + + '@inquirer/figures@2.0.9': {} '@inquirer/input@4.3.1(@types/node@20.19.43)': dependencies: @@ -12871,17 +13516,31 @@ snapshots: optionalDependencies: '@types/node': 20.19.43 - '@inquirer/input@5.1.2(@types/node@20.19.43)': + '@inquirer/input@5.1.4(@types/node@20.19.43)': + dependencies: + '@inquirer/core': 12.0.1(@types/node@20.19.43) + '@inquirer/type': 4.1.0(@types/node@20.19.43) + optionalDependencies: + '@types/node': 20.19.43 + + '@inquirer/input@5.1.4(@types/node@24.13.3)': + dependencies: + '@inquirer/core': 12.0.1(@types/node@24.13.3) + '@inquirer/type': 4.1.0(@types/node@24.13.3) + optionalDependencies: + '@types/node': 24.13.3 + + '@inquirer/input@5.1.6(@types/node@20.19.43)': dependencies: - '@inquirer/core': 11.2.1(@types/node@20.19.43) - '@inquirer/type': 4.0.7(@types/node@20.19.43) + '@inquirer/core': 12.0.3(@types/node@20.19.43) + '@inquirer/type': 4.1.1(@types/node@20.19.43) optionalDependencies: '@types/node': 20.19.43 - '@inquirer/input@5.1.2(@types/node@24.13.3)': + '@inquirer/input@5.1.6(@types/node@24.13.3)': dependencies: - '@inquirer/core': 11.2.1(@types/node@24.13.3) - '@inquirer/type': 4.0.7(@types/node@24.13.3) + '@inquirer/core': 12.0.3(@types/node@24.13.3) + '@inquirer/type': 4.1.1(@types/node@24.13.3) optionalDependencies: '@types/node': 24.13.3 @@ -12892,17 +13551,31 @@ snapshots: optionalDependencies: '@types/node': 20.19.43 - '@inquirer/number@4.1.1(@types/node@20.19.43)': + '@inquirer/number@4.2.1(@types/node@20.19.43)': + dependencies: + '@inquirer/core': 12.0.1(@types/node@20.19.43) + '@inquirer/type': 4.1.0(@types/node@20.19.43) + optionalDependencies: + '@types/node': 20.19.43 + + '@inquirer/number@4.2.1(@types/node@24.13.3)': + dependencies: + '@inquirer/core': 12.0.1(@types/node@24.13.3) + '@inquirer/type': 4.1.0(@types/node@24.13.3) + optionalDependencies: + '@types/node': 24.13.3 + + '@inquirer/number@4.2.3(@types/node@20.19.43)': dependencies: - '@inquirer/core': 11.2.1(@types/node@20.19.43) - '@inquirer/type': 4.0.7(@types/node@20.19.43) + '@inquirer/core': 12.0.3(@types/node@20.19.43) + '@inquirer/type': 4.1.1(@types/node@20.19.43) optionalDependencies: '@types/node': 20.19.43 - '@inquirer/number@4.1.1(@types/node@24.13.3)': + '@inquirer/number@4.2.3(@types/node@24.13.3)': dependencies: - '@inquirer/core': 11.2.1(@types/node@24.13.3) - '@inquirer/type': 4.0.7(@types/node@24.13.3) + '@inquirer/core': 12.0.3(@types/node@24.13.3) + '@inquirer/type': 4.1.1(@types/node@24.13.3) optionalDependencies: '@types/node': 24.13.3 @@ -12914,19 +13587,35 @@ snapshots: optionalDependencies: '@types/node': 20.19.43 - '@inquirer/password@5.1.1(@types/node@20.19.43)': + '@inquirer/password@5.2.0(@types/node@20.19.43)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/core': 11.2.1(@types/node@20.19.43) - '@inquirer/type': 4.0.7(@types/node@20.19.43) + '@inquirer/core': 12.0.1(@types/node@20.19.43) + '@inquirer/type': 4.1.0(@types/node@20.19.43) optionalDependencies: '@types/node': 20.19.43 - '@inquirer/password@5.1.1(@types/node@24.13.3)': + '@inquirer/password@5.2.0(@types/node@24.13.3)': dependencies: '@inquirer/ansi': 2.0.7 - '@inquirer/core': 11.2.1(@types/node@24.13.3) - '@inquirer/type': 4.0.7(@types/node@24.13.3) + '@inquirer/core': 12.0.1(@types/node@24.13.3) + '@inquirer/type': 4.1.0(@types/node@24.13.3) + optionalDependencies: + '@types/node': 24.13.3 + + '@inquirer/password@5.2.2(@types/node@20.19.43)': + dependencies: + '@inquirer/ansi': 2.0.8 + '@inquirer/core': 12.0.3(@types/node@20.19.43) + '@inquirer/type': 4.1.1(@types/node@20.19.43) + optionalDependencies: + '@types/node': 20.19.43 + + '@inquirer/password@5.2.2(@types/node@24.13.3)': + dependencies: + '@inquirer/ansi': 2.0.8 + '@inquirer/core': 12.0.3(@types/node@24.13.3) + '@inquirer/type': 4.1.1(@types/node@24.13.3) optionalDependencies: '@types/node': 24.13.3 @@ -12945,33 +13634,63 @@ snapshots: optionalDependencies: '@types/node': 20.19.43 - '@inquirer/prompts@8.5.2(@types/node@20.19.43)': - dependencies: - '@inquirer/checkbox': 5.2.1(@types/node@20.19.43) - '@inquirer/confirm': 6.1.1(@types/node@20.19.43) - '@inquirer/editor': 5.2.2(@types/node@20.19.43) - '@inquirer/expand': 5.1.1(@types/node@20.19.43) - '@inquirer/input': 5.1.2(@types/node@20.19.43) - '@inquirer/number': 4.1.1(@types/node@20.19.43) - '@inquirer/password': 5.1.1(@types/node@20.19.43) - '@inquirer/rawlist': 5.3.1(@types/node@20.19.43) - '@inquirer/search': 4.2.1(@types/node@20.19.43) - '@inquirer/select': 5.2.1(@types/node@20.19.43) + '@inquirer/prompts@8.7.0(@types/node@20.19.43)': + dependencies: + '@inquirer/checkbox': 5.2.3(@types/node@20.19.43) + '@inquirer/confirm': 6.3.0(@types/node@20.19.43) + '@inquirer/editor': 5.3.1(@types/node@20.19.43) + '@inquirer/expand': 5.1.3(@types/node@20.19.43) + '@inquirer/input': 5.1.4(@types/node@20.19.43) + '@inquirer/number': 4.2.1(@types/node@20.19.43) + '@inquirer/password': 5.2.0(@types/node@20.19.43) + '@inquirer/rawlist': 5.3.3(@types/node@20.19.43) + '@inquirer/search': 4.3.1(@types/node@20.19.43) + '@inquirer/select': 5.2.3(@types/node@20.19.43) + optionalDependencies: + '@types/node': 20.19.43 + + '@inquirer/prompts@8.7.0(@types/node@24.13.3)': + dependencies: + '@inquirer/checkbox': 5.2.3(@types/node@24.13.3) + '@inquirer/confirm': 6.3.0(@types/node@24.13.3) + '@inquirer/editor': 5.3.1(@types/node@24.13.3) + '@inquirer/expand': 5.1.3(@types/node@24.13.3) + '@inquirer/input': 5.1.4(@types/node@24.13.3) + '@inquirer/number': 4.2.1(@types/node@24.13.3) + '@inquirer/password': 5.2.0(@types/node@24.13.3) + '@inquirer/rawlist': 5.3.3(@types/node@24.13.3) + '@inquirer/search': 4.3.1(@types/node@24.13.3) + '@inquirer/select': 5.2.3(@types/node@24.13.3) + optionalDependencies: + '@types/node': 24.13.3 + + '@inquirer/prompts@8.7.2(@types/node@20.19.43)': + dependencies: + '@inquirer/checkbox': 5.2.5(@types/node@20.19.43) + '@inquirer/confirm': 6.3.2(@types/node@20.19.43) + '@inquirer/editor': 5.3.3(@types/node@20.19.43) + '@inquirer/expand': 5.1.5(@types/node@20.19.43) + '@inquirer/input': 5.1.6(@types/node@20.19.43) + '@inquirer/number': 4.2.3(@types/node@20.19.43) + '@inquirer/password': 5.2.2(@types/node@20.19.43) + '@inquirer/rawlist': 5.3.5(@types/node@20.19.43) + '@inquirer/search': 4.3.3(@types/node@20.19.43) + '@inquirer/select': 5.2.5(@types/node@20.19.43) optionalDependencies: '@types/node': 20.19.43 - '@inquirer/prompts@8.5.2(@types/node@24.13.3)': - dependencies: - '@inquirer/checkbox': 5.2.1(@types/node@24.13.3) - '@inquirer/confirm': 6.1.1(@types/node@24.13.3) - '@inquirer/editor': 5.2.2(@types/node@24.13.3) - '@inquirer/expand': 5.1.1(@types/node@24.13.3) - '@inquirer/input': 5.1.2(@types/node@24.13.3) - '@inquirer/number': 4.1.1(@types/node@24.13.3) - '@inquirer/password': 5.1.1(@types/node@24.13.3) - '@inquirer/rawlist': 5.3.1(@types/node@24.13.3) - '@inquirer/search': 4.2.1(@types/node@24.13.3) - '@inquirer/select': 5.2.1(@types/node@24.13.3) + '@inquirer/prompts@8.7.2(@types/node@24.13.3)': + dependencies: + '@inquirer/checkbox': 5.2.5(@types/node@24.13.3) + '@inquirer/confirm': 6.3.2(@types/node@24.13.3) + '@inquirer/editor': 5.3.3(@types/node@24.13.3) + '@inquirer/expand': 5.1.5(@types/node@24.13.3) + '@inquirer/input': 5.1.6(@types/node@24.13.3) + '@inquirer/number': 4.2.3(@types/node@24.13.3) + '@inquirer/password': 5.2.2(@types/node@24.13.3) + '@inquirer/rawlist': 5.3.5(@types/node@24.13.3) + '@inquirer/search': 4.3.3(@types/node@24.13.3) + '@inquirer/select': 5.2.5(@types/node@24.13.3) optionalDependencies: '@types/node': 24.13.3 @@ -12983,17 +13702,31 @@ snapshots: optionalDependencies: '@types/node': 20.19.43 - '@inquirer/rawlist@5.3.1(@types/node@20.19.43)': + '@inquirer/rawlist@5.3.3(@types/node@20.19.43)': + dependencies: + '@inquirer/core': 12.0.1(@types/node@20.19.43) + '@inquirer/type': 4.1.0(@types/node@20.19.43) + optionalDependencies: + '@types/node': 20.19.43 + + '@inquirer/rawlist@5.3.3(@types/node@24.13.3)': + dependencies: + '@inquirer/core': 12.0.1(@types/node@24.13.3) + '@inquirer/type': 4.1.0(@types/node@24.13.3) + optionalDependencies: + '@types/node': 24.13.3 + + '@inquirer/rawlist@5.3.5(@types/node@20.19.43)': dependencies: - '@inquirer/core': 11.2.1(@types/node@20.19.43) - '@inquirer/type': 4.0.7(@types/node@20.19.43) + '@inquirer/core': 12.0.3(@types/node@20.19.43) + '@inquirer/type': 4.1.1(@types/node@20.19.43) optionalDependencies: '@types/node': 20.19.43 - '@inquirer/rawlist@5.3.1(@types/node@24.13.3)': + '@inquirer/rawlist@5.3.5(@types/node@24.13.3)': dependencies: - '@inquirer/core': 11.2.1(@types/node@24.13.3) - '@inquirer/type': 4.0.7(@types/node@24.13.3) + '@inquirer/core': 12.0.3(@types/node@24.13.3) + '@inquirer/type': 4.1.1(@types/node@24.13.3) optionalDependencies: '@types/node': 24.13.3 @@ -13006,19 +13739,35 @@ snapshots: optionalDependencies: '@types/node': 20.19.43 - '@inquirer/search@4.2.1(@types/node@20.19.43)': + '@inquirer/search@4.3.1(@types/node@20.19.43)': + dependencies: + '@inquirer/core': 12.0.1(@types/node@20.19.43) + '@inquirer/figures': 2.0.8 + '@inquirer/type': 4.1.0(@types/node@20.19.43) + optionalDependencies: + '@types/node': 20.19.43 + + '@inquirer/search@4.3.1(@types/node@24.13.3)': + dependencies: + '@inquirer/core': 12.0.1(@types/node@24.13.3) + '@inquirer/figures': 2.0.8 + '@inquirer/type': 4.1.0(@types/node@24.13.3) + optionalDependencies: + '@types/node': 24.13.3 + + '@inquirer/search@4.3.3(@types/node@20.19.43)': dependencies: - '@inquirer/core': 11.2.1(@types/node@20.19.43) - '@inquirer/figures': 2.0.7 - '@inquirer/type': 4.0.7(@types/node@20.19.43) + '@inquirer/core': 12.0.3(@types/node@20.19.43) + '@inquirer/figures': 2.0.9 + '@inquirer/type': 4.1.1(@types/node@20.19.43) optionalDependencies: '@types/node': 20.19.43 - '@inquirer/search@4.2.1(@types/node@24.13.3)': + '@inquirer/search@4.3.3(@types/node@24.13.3)': dependencies: - '@inquirer/core': 11.2.1(@types/node@24.13.3) - '@inquirer/figures': 2.0.7 - '@inquirer/type': 4.0.7(@types/node@24.13.3) + '@inquirer/core': 12.0.3(@types/node@24.13.3) + '@inquirer/figures': 2.0.9 + '@inquirer/type': 4.1.1(@types/node@24.13.3) optionalDependencies: '@types/node': 24.13.3 @@ -13032,21 +13781,39 @@ snapshots: optionalDependencies: '@types/node': 20.19.43 - '@inquirer/select@5.2.1(@types/node@20.19.43)': + '@inquirer/select@5.2.3(@types/node@20.19.43)': + dependencies: + '@inquirer/ansi': 2.0.7 + '@inquirer/core': 12.0.1(@types/node@20.19.43) + '@inquirer/figures': 2.0.8 + '@inquirer/type': 4.1.0(@types/node@20.19.43) + optionalDependencies: + '@types/node': 20.19.43 + + '@inquirer/select@5.2.3(@types/node@24.13.3)': + dependencies: + '@inquirer/ansi': 2.0.7 + '@inquirer/core': 12.0.1(@types/node@24.13.3) + '@inquirer/figures': 2.0.8 + '@inquirer/type': 4.1.0(@types/node@24.13.3) + optionalDependencies: + '@types/node': 24.13.3 + + '@inquirer/select@5.2.5(@types/node@20.19.43)': dependencies: - '@inquirer/ansi': 2.0.7 - '@inquirer/core': 11.2.1(@types/node@20.19.43) - '@inquirer/figures': 2.0.7 - '@inquirer/type': 4.0.7(@types/node@20.19.43) + '@inquirer/ansi': 2.0.8 + '@inquirer/core': 12.0.3(@types/node@20.19.43) + '@inquirer/figures': 2.0.9 + '@inquirer/type': 4.1.1(@types/node@20.19.43) optionalDependencies: '@types/node': 20.19.43 - '@inquirer/select@5.2.1(@types/node@24.13.3)': + '@inquirer/select@5.2.5(@types/node@24.13.3)': dependencies: - '@inquirer/ansi': 2.0.7 - '@inquirer/core': 11.2.1(@types/node@24.13.3) - '@inquirer/figures': 2.0.7 - '@inquirer/type': 4.0.7(@types/node@24.13.3) + '@inquirer/ansi': 2.0.8 + '@inquirer/core': 12.0.3(@types/node@24.13.3) + '@inquirer/figures': 2.0.9 + '@inquirer/type': 4.1.1(@types/node@24.13.3) optionalDependencies: '@types/node': 24.13.3 @@ -13054,11 +13821,19 @@ snapshots: optionalDependencies: '@types/node': 20.19.43 - '@inquirer/type@4.0.7(@types/node@20.19.43)': + '@inquirer/type@4.1.0(@types/node@20.19.43)': + optionalDependencies: + '@types/node': 20.19.43 + + '@inquirer/type@4.1.0(@types/node@24.13.3)': + optionalDependencies: + '@types/node': 24.13.3 + + '@inquirer/type@4.1.1(@types/node@20.19.43)': optionalDependencies: '@types/node': 20.19.43 - '@inquirer/type@4.0.7(@types/node@24.13.3)': + '@inquirer/type@4.1.1(@types/node@24.13.3)': optionalDependencies: '@types/node': 24.13.3 @@ -13082,12 +13857,12 @@ snapshots: camelcase: 5.3.1 find-up: 4.1.0 get-package-type: 0.1.0 - js-yaml: 3.15.0 + js-yaml: 3.15.2 resolve-from: 5.0.0 '@istanbuljs/schema@0.1.6': {} - '@jasminejs/reporters@1.0.0': {} + '@jasminejs/reporters@1.1.0': {} '@jest/console@30.4.1': dependencies: @@ -13098,13 +13873,13 @@ snapshots: jest-util: 30.4.1 slash: 3.0.0 - '@jest/core@30.4.2(supports-color@10.2.2)(ts-node@10.9.2(@types/node@24.13.3)(typescript@6.0.3))': + '@jest/core@30.4.2(supports-color@11.0.0)(ts-node@10.9.2(@types/node@24.13.3)(typescript@6.0.3))': dependencies: '@jest/console': 30.4.1 '@jest/pattern': 30.4.0 - '@jest/reporters': 30.4.1(supports-color@8.1.1) + '@jest/reporters': 30.4.1(supports-color@11.0.0) '@jest/test-result': 30.4.1 - '@jest/transform': 30.4.1(supports-color@10.2.2) + '@jest/transform': 30.4.1(supports-color@11.0.0) '@jest/types': 30.4.1 '@types/node': 24.13.3 ansi-escapes: 4.3.2 @@ -13114,15 +13889,15 @@ snapshots: fast-json-stable-stringify: 2.1.0 graceful-fs: 4.2.11 jest-changed-files: 30.4.1 - jest-config: 30.4.2(@types/node@24.13.3)(supports-color@10.2.2)(ts-node@10.9.2(@types/node@24.13.3)(typescript@6.0.3)) + jest-config: 30.4.2(@types/node@24.13.3)(supports-color@11.0.0)(ts-node@10.9.2(@types/node@24.13.3)(typescript@6.0.3)) jest-haste-map: 30.4.1 jest-message-util: 30.4.1 jest-regex-util: 30.4.0 jest-resolve: 30.4.1 - jest-resolve-dependencies: 30.4.2(supports-color@10.2.2) - jest-runner: 30.4.2(supports-color@10.2.2) - jest-runtime: 30.4.2(supports-color@10.2.2) - jest-snapshot: 30.4.1(supports-color@10.2.2) + jest-resolve-dependencies: 30.4.2(supports-color@11.0.0) + jest-runner: 30.4.2(supports-color@11.0.0) + jest-runtime: 30.4.2(supports-color@11.0.0) + jest-snapshot: 30.4.1(supports-color@11.0.0) jest-util: 30.4.1 jest-validate: 30.4.1 jest-watcher: 30.4.1 @@ -13136,7 +13911,7 @@ snapshots: '@jest/diff-sequences@30.4.0': {} - '@jest/environment-jsdom-abstract@30.4.1(jsdom@26.1.0(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6))': + '@jest/environment-jsdom-abstract@30.4.1(jsdom@26.1.0(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6))': dependencies: '@jest/environment': 30.4.1 '@jest/fake-timers': 30.4.1 @@ -13145,7 +13920,7 @@ snapshots: '@types/node': 24.13.3 jest-mock: 30.4.1 jest-util: 30.4.1 - jsdom: 26.1.0(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) + jsdom: 26.1.0(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6) '@jest/environment@30.4.1': dependencies: @@ -13158,10 +13933,10 @@ snapshots: dependencies: '@jest/get-type': 30.1.0 - '@jest/expect@30.4.1(supports-color@10.2.2)': + '@jest/expect@30.4.1(supports-color@11.0.0)': dependencies: expect: 30.4.1 - jest-snapshot: 30.4.1(supports-color@10.2.2) + jest-snapshot: 30.4.1(supports-color@11.0.0) transitivePeerDependencies: - supports-color @@ -13176,10 +13951,10 @@ snapshots: '@jest/get-type@30.1.0': {} - '@jest/globals@30.4.1(supports-color@10.2.2)': + '@jest/globals@30.4.1(supports-color@11.0.0)': dependencies: '@jest/environment': 30.4.1 - '@jest/expect': 30.4.1(supports-color@10.2.2) + '@jest/expect': 30.4.1(supports-color@11.0.0) '@jest/types': 30.4.1 jest-mock: 30.4.1 transitivePeerDependencies: @@ -13190,12 +13965,12 @@ snapshots: '@types/node': 24.13.3 jest-regex-util: 30.4.0 - '@jest/reporters@30.4.1(supports-color@8.1.1)': + '@jest/reporters@30.4.1(supports-color@11.0.0)': dependencies: '@bcoe/v8-coverage': 0.2.3 '@jest/console': 30.4.1 '@jest/test-result': 30.4.1 - '@jest/transform': 30.4.1(supports-color@10.2.2) + '@jest/transform': 30.4.1(supports-color@11.0.0) '@jest/types': 30.4.1 '@jridgewell/trace-mapping': 0.3.31 '@types/node': 24.13.3 @@ -13205,9 +13980,9 @@ snapshots: glob: 10.5.0 graceful-fs: 4.2.11 istanbul-lib-coverage: 3.2.2 - istanbul-lib-instrument: 6.0.3(supports-color@10.2.2) + istanbul-lib-instrument: 6.0.3(supports-color@11.0.0) istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 5.0.6(supports-color@8.1.1) + istanbul-lib-source-maps: 5.0.6(supports-color@11.0.0) istanbul-reports: 3.2.0 jest-message-util: 30.4.1 jest-util: 30.4.1 @@ -13249,12 +14024,12 @@ snapshots: jest-haste-map: 30.4.1 slash: 3.0.0 - '@jest/transform@30.4.1(supports-color@10.2.2)': + '@jest/transform@30.4.1(supports-color@11.0.0)': dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@11.0.0) '@jest/types': 30.4.1 '@jridgewell/trace-mapping': 0.3.31 - babel-plugin-istanbul: 7.0.1(supports-color@10.2.2) + babel-plugin-istanbul: 7.0.1(supports-color@11.0.0) chalk: 4.1.2 convert-source-map: 2.0.0 fast-json-stable-stringify: 2.1.0 @@ -13280,7 +14055,7 @@ snapshots: '@jridgewell/gen-mapping@0.3.13': dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/sourcemap-codec': 1.6.0 '@jridgewell/trace-mapping': 0.3.31 '@jridgewell/remapping@2.3.5': @@ -13290,17 +14065,17 @@ snapshots: '@jridgewell/resolve-uri@3.1.2': {} - '@jridgewell/sourcemap-codec@1.5.5': {} + '@jridgewell/sourcemap-codec@1.6.0': {} '@jridgewell/trace-mapping@0.3.31': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/sourcemap-codec': 1.6.0 '@jridgewell/trace-mapping@0.3.9': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/sourcemap-codec': 1.6.0 '@js-sdsl/ordered-map@4.4.2': {} @@ -13308,7 +14083,7 @@ snapshots: '@lezer/common@1.5.2': {} - '@lezer/css@1.3.4': + '@lezer/css@1.3.6': dependencies: '@lezer/common': 1.5.2 '@lezer/highlight': 1.2.3 @@ -13340,19 +14115,19 @@ snapshots: '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.10 - '@listr2/prompt-adapter-inquirer@4.2.4(@inquirer/prompts@8.5.2(@types/node@20.19.43))(@types/node@20.19.43)(listr2@10.2.2)': + '@listr2/prompt-adapter-inquirer@4.2.7(@inquirer/prompts@8.7.2(@types/node@20.19.43))(@types/node@20.19.43)(listr2@11.1.0)': dependencies: - '@inquirer/prompts': 8.5.2(@types/node@20.19.43) - '@inquirer/type': 4.0.7(@types/node@20.19.43) - listr2: 10.2.2 + '@inquirer/prompts': 8.7.2(@types/node@20.19.43) + '@inquirer/type': 4.1.1(@types/node@20.19.43) + listr2: 11.1.0 transitivePeerDependencies: - '@types/node' - '@listr2/prompt-adapter-inquirer@4.2.4(@inquirer/prompts@8.5.2(@types/node@20.19.43))(@types/node@24.13.3)(listr2@10.2.2)': + '@listr2/prompt-adapter-inquirer@4.2.7(@inquirer/prompts@8.7.2(@types/node@24.13.3))(@types/node@24.13.3)(listr2@11.1.0)': dependencies: - '@inquirer/prompts': 8.5.2(@types/node@20.19.43) - '@inquirer/type': 4.0.7(@types/node@24.13.3) - listr2: 10.2.2 + '@inquirer/prompts': 8.7.2(@types/node@24.13.3) + '@inquirer/type': 4.1.1(@types/node@24.13.3) + listr2: 11.1.0 transitivePeerDependencies: - '@types/node' @@ -13377,44 +14152,52 @@ snapshots: '@lmdb/lmdb-win32-x64@3.5.6': optional: true - '@marijn/find-cluster-break@1.0.3': {} + '@marijn/find-cluster-break@1.0.4': {} - '@mcp-b/webmcp-polyfill@4.0.0': + '@mcp-b/webmcp-polyfill@5.1.0': dependencies: - '@cfworker/json-schema': 4.1.1 - '@mcp-b/webmcp-types': 4.0.0 + '@mcp-b/webmcp-types': 5.1.0 '@standard-schema/spec': 1.1.0 - '@mcp-b/webmcp-types@4.0.0': {} + '@mcp-b/webmcp-types@5.1.0': + dependencies: + '@modelcontextprotocol/server': 2.0.0 - '@mermaid-js/parser@1.2.0': + '@mermaid-js/parser@1.2.1': dependencies: '@chevrotain/types': 11.1.2 - '@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2)': + '@modelcontextprotocol/core@2.0.0': + dependencies: + zod: 4.6.5 + + '@modelcontextprotocol/sdk@1.30.0(supports-color@11.0.0)': dependencies: - '@hono/node-server': 1.19.14(hono@4.12.30) + '@hono/node-server': 2.1.1(hono@4.13.5) ajv: 8.20.0 ajv-formats: 3.0.1 content-type: 1.0.5 cors: 2.8.6 cross-spawn: 7.0.6 eventsource: 3.0.7 - eventsource-parser: 3.1.0 - express: 5.2.1(supports-color@10.2.2) - express-rate-limit: 8.5.2(express@5.2.1(supports-color@10.2.2)) - hono: 4.12.30 - jose: 6.2.3 + eventsource-parser: 3.1.1 + express: 5.2.1(supports-color@11.0.0) + express-rate-limit: 8.7.0(express@5.2.1(supports-color@11.0.0))(supports-color@11.0.0) + hono: 4.13.5 + jose: 6.2.10 json-schema-typed: 8.0.2 pkce-challenge: 5.0.1 raw-body: 3.0.2 - zod: 4.4.3 - zod-to-json-schema: 3.25.2(zod@4.4.3) - optionalDependencies: - '@cfworker/json-schema': 4.1.1 + zod: 4.6.5 + zod-to-json-schema: 3.25.2(zod@4.6.5) transitivePeerDependencies: - supports-color + '@modelcontextprotocol/server@2.0.0': + dependencies: + '@modelcontextprotocol/core': 2.0.0 + zod: 4.5.4 + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4': optional: true @@ -13442,6 +14225,9 @@ snapshots: outvariant: 1.4.3 strict-event-emitter: 0.5.1 + '@napi-rs/lzma-linux-x64-gnu@1.5.1': + optional: true + '@napi-rs/nice-android-arm-eabi@1.1.1': optional: true @@ -13514,20 +14300,13 @@ snapshots: '@napi-rs/nice-win32-x64-msvc': 1.1.1 optional: true - '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + '@napi-rs/wasm-runtime@1.2.3(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': dependencies: '@emnapi/core': 1.10.0 '@emnapi/runtime': 1.10.0 '@tybys/wasm-util': 0.10.3 optional: true - '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': - dependencies: - '@emnapi/core': 1.11.1 - '@emnapi/runtime': 1.11.1 - '@tybys/wasm-util': 0.10.3 - optional: true - '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -13538,57 +14317,57 @@ snapshots: '@nodelib/fs.walk@1.2.8': dependencies: '@nodelib/fs.scandir': 2.1.5 - fastq: 1.20.1 + fastq: 1.20.3 - '@octokit/auth-app@8.2.0': + '@octokit/auth-app@8.3.1': dependencies: - '@octokit/auth-oauth-app': 9.0.3 - '@octokit/auth-oauth-user': 6.0.2 - '@octokit/request': 10.0.11 - '@octokit/request-error': 7.1.0 - '@octokit/types': 16.0.0 + '@octokit/auth-oauth-app': 9.0.5 + '@octokit/auth-oauth-user': 6.0.4 + '@octokit/request': 10.0.16 + '@octokit/request-error': 7.1.2 + '@octokit/types': 18.0.0 toad-cache: 3.7.4 universal-github-app-jwt: 2.2.2 universal-user-agent: 7.0.3 - '@octokit/auth-oauth-app@9.0.3': + '@octokit/auth-oauth-app@9.0.5': dependencies: - '@octokit/auth-oauth-device': 8.0.3 - '@octokit/auth-oauth-user': 6.0.2 - '@octokit/request': 10.0.11 - '@octokit/types': 16.0.0 + '@octokit/auth-oauth-device': 8.0.5 + '@octokit/auth-oauth-user': 6.0.4 + '@octokit/request': 10.0.16 + '@octokit/types': 18.0.0 universal-user-agent: 7.0.3 - '@octokit/auth-oauth-device@8.0.3': + '@octokit/auth-oauth-device@8.0.5': dependencies: - '@octokit/oauth-methods': 6.0.2 - '@octokit/request': 10.0.11 - '@octokit/types': 16.0.0 + '@octokit/oauth-methods': 6.0.5 + '@octokit/request': 10.0.16 + '@octokit/types': 18.0.0 universal-user-agent: 7.0.3 - '@octokit/auth-oauth-user@6.0.2': + '@octokit/auth-oauth-user@6.0.4': dependencies: - '@octokit/auth-oauth-device': 8.0.3 - '@octokit/oauth-methods': 6.0.2 - '@octokit/request': 10.0.11 - '@octokit/types': 16.0.0 + '@octokit/auth-oauth-device': 8.0.5 + '@octokit/oauth-methods': 6.0.5 + '@octokit/request': 10.0.16 + '@octokit/types': 18.0.0 universal-user-agent: 7.0.3 '@octokit/auth-token@6.0.0': {} - '@octokit/core@7.0.6': + '@octokit/core@7.0.8': dependencies: '@octokit/auth-token': 6.0.0 - '@octokit/graphql': 9.0.3 - '@octokit/request': 10.0.11 - '@octokit/request-error': 7.1.0 - '@octokit/types': 16.0.0 + '@octokit/graphql': 9.0.5 + '@octokit/request': 10.0.16 + '@octokit/request-error': 7.1.2 + '@octokit/types': 18.0.0 before-after-hook: 4.0.0 universal-user-agent: 7.0.3 - '@octokit/endpoint@11.0.3': + '@octokit/endpoint@11.0.5': dependencies: - '@octokit/types': 16.0.0 + '@octokit/types': 18.0.0 universal-user-agent: 7.0.3 '@octokit/graphql-schema@15.26.1': @@ -13596,61 +14375,83 @@ snapshots: graphql: 16.14.2 graphql-tag: 2.12.7(graphql@16.14.2) - '@octokit/graphql@9.0.3': + '@octokit/graphql@9.0.5': dependencies: - '@octokit/request': 10.0.11 - '@octokit/types': 16.0.0 + '@octokit/request': 10.0.16 + '@octokit/types': 18.0.0 universal-user-agent: 7.0.3 '@octokit/oauth-authorization-url@8.0.0': {} - '@octokit/oauth-methods@6.0.2': + '@octokit/oauth-methods@6.0.5': dependencies: '@octokit/oauth-authorization-url': 8.0.0 - '@octokit/request': 10.0.11 - '@octokit/request-error': 7.1.0 - '@octokit/types': 16.0.0 + '@octokit/request': 10.0.16 + '@octokit/request-error': 7.1.2 + '@octokit/types': 18.0.0 '@octokit/openapi-types@27.0.0': {} - '@octokit/plugin-paginate-rest@14.0.0(@octokit/core@7.0.6)': + '@octokit/openapi-types@28.0.0': {} + + '@octokit/openapi-types@29.0.1': {} + + '@octokit/plugin-paginate-rest@14.0.0(@octokit/core@7.0.8)': dependencies: - '@octokit/core': 7.0.6 + '@octokit/core': 7.0.8 '@octokit/types': 16.0.0 - '@octokit/plugin-request-log@6.0.0(@octokit/core@7.0.6)': + '@octokit/plugin-paginate-rest@15.0.0(@octokit/core@7.0.8)': dependencies: - '@octokit/core': 7.0.6 + '@octokit/core': 7.0.8 + '@octokit/types': 17.0.0 - '@octokit/plugin-rest-endpoint-methods@17.0.0(@octokit/core@7.0.6)': + '@octokit/plugin-request-log@6.0.0(@octokit/core@7.0.8)': dependencies: - '@octokit/core': 7.0.6 - '@octokit/types': 16.0.0 + '@octokit/core': 7.0.8 - '@octokit/request-error@7.1.0': + '@octokit/plugin-rest-endpoint-methods@17.0.0(@octokit/core@7.0.8)': dependencies: + '@octokit/core': 7.0.8 '@octokit/types': 16.0.0 - '@octokit/request@10.0.11': + '@octokit/plugin-rest-endpoint-methods@18.0.0(@octokit/core@7.0.8)': dependencies: - '@octokit/endpoint': 11.0.3 - '@octokit/request-error': 7.1.0 - '@octokit/types': 16.0.0 - content-type: 2.0.0 - json-with-bigint: 3.5.10 + '@octokit/core': 7.0.8 + '@octokit/types': 17.0.0 + + '@octokit/request-error@7.1.2': + dependencies: + '@octokit/types': 18.0.0 + + '@octokit/request@10.0.16': + dependencies: + '@octokit/endpoint': 11.0.5 + '@octokit/request-error': 7.1.2 + '@octokit/types': 18.0.0 + content-type: 3.0.0 + json-with-bigint: 3.5.12 universal-user-agent: 7.0.3 '@octokit/rest@22.0.1': dependencies: - '@octokit/core': 7.0.6 - '@octokit/plugin-paginate-rest': 14.0.0(@octokit/core@7.0.6) - '@octokit/plugin-request-log': 6.0.0(@octokit/core@7.0.6) - '@octokit/plugin-rest-endpoint-methods': 17.0.0(@octokit/core@7.0.6) + '@octokit/core': 7.0.8 + '@octokit/plugin-paginate-rest': 14.0.0(@octokit/core@7.0.8) + '@octokit/plugin-request-log': 6.0.0(@octokit/core@7.0.8) + '@octokit/plugin-rest-endpoint-methods': 17.0.0(@octokit/core@7.0.8) '@octokit/types@16.0.0': dependencies: '@octokit/openapi-types': 27.0.0 + '@octokit/types@17.0.0': + dependencies: + '@octokit/openapi-types': 28.0.0 + + '@octokit/types@18.0.0': + dependencies: + '@octokit/openapi-types': 29.0.1 + '@open-draft/deferred-promise@2.2.0': {} '@open-draft/logger@0.3.0': @@ -13662,7 +14463,7 @@ snapshots: '@opentelemetry/api@1.9.1': {} - '@opentelemetry/context-async-hooks@2.9.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/context-async-hooks@2.10.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 @@ -13671,7 +14472,7 @@ snapshots: '@opentelemetry/api': 1.9.1 '@opentelemetry/semantic-conventions': 1.28.0 - '@opentelemetry/core@2.9.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 '@opentelemetry/semantic-conventions': 1.43.0 @@ -13682,68 +14483,120 @@ snapshots: '@opentelemetry/semantic-conventions@1.43.0': {} - '@oxc-project/types@0.139.0': {} + '@oxc-parser/binding-android-arm-eabi@0.149.0': + optional: true + + '@oxc-parser/binding-android-arm64@0.149.0': + optional: true + + '@oxc-parser/binding-darwin-arm64@0.149.0': + optional: true + + '@oxc-parser/binding-darwin-x64@0.149.0': + optional: true + + '@oxc-parser/binding-freebsd-x64@0.149.0': + optional: true + + '@oxc-parser/binding-linux-arm-gnueabihf@0.149.0': + optional: true + + '@oxc-parser/binding-linux-arm-musleabihf@0.149.0': + optional: true + + '@oxc-parser/binding-linux-arm64-gnu@0.149.0': + optional: true + + '@oxc-parser/binding-linux-arm64-musl@0.149.0': + optional: true + + '@oxc-parser/binding-linux-ppc64-gnu@0.149.0': + optional: true + + '@oxc-parser/binding-linux-riscv64-gnu@0.149.0': + optional: true + + '@oxc-parser/binding-linux-riscv64-musl@0.149.0': + optional: true + + '@oxc-parser/binding-linux-s390x-gnu@0.149.0': + optional: true + + '@oxc-parser/binding-linux-x64-gnu@0.149.0': + optional: true + + '@oxc-parser/binding-linux-x64-musl@0.149.0': + optional: true + + '@oxc-parser/binding-openharmony-arm64@0.149.0': + optional: true + + '@oxc-parser/binding-win32-arm64-msvc@0.149.0': + optional: true + + '@oxc-parser/binding-win32-ia32-msvc@0.149.0': + optional: true - '@parcel/watcher-android-arm64@2.5.6': + '@oxc-parser/binding-win32-x64-msvc@0.149.0': optional: true - '@parcel/watcher-darwin-arm64@2.5.6': + '@oxc-project/types@0.149.0': {} + + '@parcel/watcher-android-arm64@2.6.0': optional: true - '@parcel/watcher-darwin-x64@2.5.6': + '@parcel/watcher-darwin-arm64@2.6.0': optional: true - '@parcel/watcher-freebsd-x64@2.5.6': + '@parcel/watcher-darwin-x64@2.6.0': optional: true - '@parcel/watcher-linux-arm-glibc@2.5.6': + '@parcel/watcher-freebsd-x64@2.6.0': optional: true - '@parcel/watcher-linux-arm-musl@2.5.6': + '@parcel/watcher-linux-arm-glibc@2.6.0': optional: true - '@parcel/watcher-linux-arm64-glibc@2.5.6': + '@parcel/watcher-linux-arm-musl@2.6.0': optional: true - '@parcel/watcher-linux-arm64-musl@2.5.6': + '@parcel/watcher-linux-arm64-glibc@2.6.0': optional: true - '@parcel/watcher-linux-x64-glibc@2.5.6': + '@parcel/watcher-linux-arm64-musl@2.6.0': optional: true - '@parcel/watcher-linux-x64-musl@2.5.6': + '@parcel/watcher-linux-x64-glibc@2.6.0': optional: true - '@parcel/watcher-win32-arm64@2.5.6': + '@parcel/watcher-linux-x64-musl@2.6.0': optional: true - '@parcel/watcher-win32-ia32@2.5.6': + '@parcel/watcher-win32-arm64@2.6.0': optional: true - '@parcel/watcher-win32-x64@2.5.6': + '@parcel/watcher-win32-x64@2.6.0': optional: true - '@parcel/watcher@2.5.6': + '@parcel/watcher@2.6.0': dependencies: detect-libc: 2.1.2 is-glob: 4.0.3 node-addon-api: 7.1.1 - picomatch: 4.0.5 + picomatch: 4.0.7 optionalDependencies: - '@parcel/watcher-android-arm64': 2.5.6 - '@parcel/watcher-darwin-arm64': 2.5.6 - '@parcel/watcher-darwin-x64': 2.5.6 - '@parcel/watcher-freebsd-x64': 2.5.6 - '@parcel/watcher-linux-arm-glibc': 2.5.6 - '@parcel/watcher-linux-arm-musl': 2.5.6 - '@parcel/watcher-linux-arm64-glibc': 2.5.6 - '@parcel/watcher-linux-arm64-musl': 2.5.6 - '@parcel/watcher-linux-x64-glibc': 2.5.6 - '@parcel/watcher-linux-x64-musl': 2.5.6 - '@parcel/watcher-win32-arm64': 2.5.6 - '@parcel/watcher-win32-ia32': 2.5.6 - '@parcel/watcher-win32-x64': 2.5.6 - optional: true + '@parcel/watcher-android-arm64': 2.6.0 + '@parcel/watcher-darwin-arm64': 2.6.0 + '@parcel/watcher-darwin-x64': 2.6.0 + '@parcel/watcher-freebsd-x64': 2.6.0 + '@parcel/watcher-linux-arm-glibc': 2.6.0 + '@parcel/watcher-linux-arm-musl': 2.6.0 + '@parcel/watcher-linux-arm64-glibc': 2.6.0 + '@parcel/watcher-linux-arm64-musl': 2.6.0 + '@parcel/watcher-linux-x64-glibc': 2.6.0 + '@parcel/watcher-linux-x64-musl': 2.6.0 + '@parcel/watcher-win32-arm64': 2.6.0 + '@parcel/watcher-win32-x64': 2.6.0 '@pkgjs/parseargs@0.11.0': optional: true @@ -13802,179 +14655,164 @@ snapshots: '@protobufjs/utf8@1.1.2': {} - '@rolldown/binding-android-arm64@1.1.5': + '@rolldown/binding-android-arm-eabi@1.2.8': optional: true - '@rolldown/binding-darwin-arm64@1.1.5': + '@rolldown/binding-android-arm64@1.2.8': optional: true - '@rolldown/binding-darwin-x64@1.1.5': + '@rolldown/binding-darwin-arm64@1.2.8': optional: true - '@rolldown/binding-freebsd-x64@1.1.5': + '@rolldown/binding-darwin-x64@1.2.8': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.1.5': + '@rolldown/binding-freebsd-x64@1.2.8': optional: true - '@rolldown/binding-linux-arm64-gnu@1.1.5': + '@rolldown/binding-linux-arm-gnueabihf@1.2.8': optional: true - '@rolldown/binding-linux-arm64-musl@1.1.5': + '@rolldown/binding-linux-arm64-gnu@1.2.8': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.1.5': + '@rolldown/binding-linux-arm64-musl@1.2.8': optional: true - '@rolldown/binding-linux-s390x-gnu@1.1.5': + '@rolldown/binding-linux-ppc64-gnu@1.2.8': optional: true - '@rolldown/binding-linux-x64-gnu@1.1.5': + '@rolldown/binding-linux-s390x-gnu@1.2.8': optional: true - '@rolldown/binding-linux-x64-musl@1.1.5': + '@rolldown/binding-linux-x64-gnu@1.2.8': optional: true - '@rolldown/binding-openharmony-arm64@1.1.5': + '@rolldown/binding-linux-x64-musl@1.2.8': optional: true - '@rolldown/binding-wasm32-wasi@1.1.5': - dependencies: - '@emnapi/core': 1.11.1 - '@emnapi/runtime': 1.11.1 - '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + '@rolldown/binding-openharmony-arm64@1.2.8': optional: true - '@rolldown/binding-win32-arm64-msvc@1.1.5': + '@rolldown/binding-win32-arm64-msvc@1.2.8': optional: true - '@rolldown/binding-win32-x64-msvc@1.1.5': + '@rolldown/binding-win32-x64-msvc@1.2.8': optional: true '@rolldown/pluginutils@1.0.1': {} - '@rollup/plugin-commonjs@29.0.3(rollup@4.62.2)': + '@rollup/plugin-commonjs@29.0.3(rollup@4.63.0)': dependencies: - '@rollup/pluginutils': 5.4.0(rollup@4.62.2) + '@rollup/pluginutils': 5.4.0(rollup@4.63.0) commondir: 1.0.1 estree-walker: 2.0.2 - fdir: 6.5.0(picomatch@4.0.5) + fdir: 6.5.0(picomatch@4.0.7) is-reference: 1.2.1 magic-string: 0.30.21 - picomatch: 4.0.5 - optionalDependencies: - rollup: 4.62.2 - - '@rollup/plugin-json@6.1.0(rollup@4.62.2)': - dependencies: - '@rollup/pluginutils': 5.4.0(rollup@4.62.2) + picomatch: 4.0.7 optionalDependencies: - rollup: 4.62.2 + rollup: 4.63.0 - '@rollup/plugin-node-resolve@16.0.3(rollup@4.62.2)': + '@rollup/plugin-node-resolve@16.0.3(rollup@4.63.0)': dependencies: - '@rollup/pluginutils': 5.4.0(rollup@4.62.2) + '@rollup/pluginutils': 5.4.0(rollup@4.63.0) '@types/resolve': 1.20.2 deepmerge: 4.3.1 is-module: 1.0.0 resolve: 1.22.12 optionalDependencies: - rollup: 4.62.2 + rollup: 4.63.0 - '@rollup/pluginutils@5.4.0(rollup@4.62.2)': + '@rollup/pluginutils@5.4.0(rollup@4.63.0)': dependencies: '@types/estree': 1.0.9 estree-walker: 2.0.2 - picomatch: 4.0.5 + picomatch: 4.0.7 optionalDependencies: - rollup: 4.62.2 + rollup: 4.63.0 - '@rollup/rollup-android-arm-eabi@4.62.2': + '@rollup/rollup-android-arm-eabi@4.63.0': optional: true - '@rollup/rollup-android-arm64@4.62.2': + '@rollup/rollup-android-arm64@4.63.0': optional: true - '@rollup/rollup-darwin-arm64@4.62.2': + '@rollup/rollup-darwin-arm64@4.63.0': optional: true - '@rollup/rollup-darwin-x64@4.62.2': + '@rollup/rollup-darwin-x64@4.63.0': optional: true - '@rollup/rollup-freebsd-arm64@4.62.2': + '@rollup/rollup-freebsd-arm64@4.63.0': optional: true - '@rollup/rollup-freebsd-x64@4.62.2': + '@rollup/rollup-freebsd-x64@4.63.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.62.2': + '@rollup/rollup-linux-arm-gnueabihf@4.63.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.62.2': + '@rollup/rollup-linux-arm-musleabihf@4.63.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.62.2': + '@rollup/rollup-linux-arm64-gnu@4.63.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.62.2': + '@rollup/rollup-linux-arm64-musl@4.63.0': optional: true - '@rollup/rollup-linux-loong64-gnu@4.62.2': + '@rollup/rollup-linux-loong64-gnu@4.63.0': optional: true - '@rollup/rollup-linux-loong64-musl@4.62.2': + '@rollup/rollup-linux-loong64-musl@4.63.0': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.62.2': + '@rollup/rollup-linux-ppc64-gnu@4.63.0': optional: true - '@rollup/rollup-linux-ppc64-musl@4.62.2': + '@rollup/rollup-linux-ppc64-musl@4.63.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.62.2': + '@rollup/rollup-linux-riscv64-gnu@4.63.0': optional: true - '@rollup/rollup-linux-riscv64-musl@4.62.2': + '@rollup/rollup-linux-riscv64-musl@4.63.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.62.2': + '@rollup/rollup-linux-s390x-gnu@4.63.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.62.2': + '@rollup/rollup-linux-x64-gnu@4.63.0': optional: true - '@rollup/rollup-linux-x64-musl@4.62.2': + '@rollup/rollup-linux-x64-musl@4.63.0': optional: true - '@rollup/rollup-openbsd-x64@4.62.2': + '@rollup/rollup-openbsd-x64@4.63.0': optional: true - '@rollup/rollup-openharmony-arm64@4.62.2': + '@rollup/rollup-openharmony-arm64@4.63.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.62.2': + '@rollup/rollup-win32-arm64-msvc@4.63.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.62.2': + '@rollup/rollup-win32-ia32-msvc@4.63.0': optional: true - '@rollup/rollup-win32-x64-gnu@4.62.2': + '@rollup/rollup-win32-x64-gnu@4.63.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.62.2': + '@rollup/rollup-win32-x64-msvc@4.63.0': optional: true - '@rollup/wasm-node@4.62.2': - dependencies: - '@types/estree': 1.0.9 - optionalDependencies: - fsevents: 2.3.3 - - '@schematics/angular@22.1.0-next.4(chokidar@5.0.0)': + '@schematics/angular@22.2.0-next.7(chokidar@5.0.0)': dependencies: - '@angular-devkit/core': 22.1.0-next.4(chokidar@5.0.0) - '@angular-devkit/schematics': 22.1.0-next.4(chokidar@5.0.0) + '@angular-devkit/core': 22.2.0-next.7(chokidar@5.0.0) + '@angular-devkit/schematics': 22.2.0-next.7(chokidar@5.0.0) jsonc-parser: 3.3.1 + oxc-parser: 0.149.0 typescript: 6.0.3 transitivePeerDependencies: - chokidar @@ -13983,35 +14821,35 @@ snapshots: dependencies: '@secretlint/types': 10.2.2 - '@secretlint/config-loader@10.2.2(supports-color@10.2.2)': + '@secretlint/config-loader@10.2.2(supports-color@11.0.0)': dependencies: '@secretlint/profiler': 10.2.2 '@secretlint/resolver': 10.2.2 '@secretlint/types': 10.2.2 ajv: 8.20.0 - debug: 4.4.3(supports-color@10.2.2) - rc-config-loader: 4.1.4(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) + rc-config-loader: 4.1.4(supports-color@11.0.0) transitivePeerDependencies: - supports-color - '@secretlint/core@10.2.2(supports-color@10.2.2)': + '@secretlint/core@10.2.2(supports-color@11.0.0)': dependencies: '@secretlint/profiler': 10.2.2 '@secretlint/types': 10.2.2 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) structured-source: 4.0.0 transitivePeerDependencies: - supports-color - '@secretlint/formatter@10.2.2(supports-color@10.2.2)': + '@secretlint/formatter@10.2.2(supports-color@11.0.0)': dependencies: '@secretlint/resolver': 10.2.2 '@secretlint/types': 10.2.2 - '@textlint/linter-formatter': 15.7.1(supports-color@10.2.2) - '@textlint/module-interop': 15.7.1 - '@textlint/types': 15.7.1 + '@textlint/linter-formatter': 15.8.0(supports-color@11.0.0) + '@textlint/module-interop': 15.8.0 + '@textlint/types': 15.8.0 chalk: 5.6.2 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) pluralize: 8.0.0 strip-ansi: 7.2.0 table: 6.9.0 @@ -14019,16 +14857,16 @@ snapshots: transitivePeerDependencies: - supports-color - '@secretlint/node@10.2.2(supports-color@10.2.2)': + '@secretlint/node@10.2.2(supports-color@11.0.0)': dependencies: - '@secretlint/config-loader': 10.2.2(supports-color@10.2.2) - '@secretlint/core': 10.2.2(supports-color@10.2.2) - '@secretlint/formatter': 10.2.2(supports-color@10.2.2) + '@secretlint/config-loader': 10.2.2(supports-color@11.0.0) + '@secretlint/core': 10.2.2(supports-color@11.0.0) + '@secretlint/formatter': 10.2.2(supports-color@11.0.0) '@secretlint/profiler': 10.2.2 '@secretlint/source-creator': 10.2.2 '@secretlint/types': 10.2.2 - debug: 4.4.3(supports-color@10.2.2) - p-map: 7.0.5 + debug: 4.4.3(supports-color@11.0.0) + p-map: 7.0.7 transitivePeerDependencies: - supports-color @@ -14053,40 +14891,40 @@ snapshots: '@secretlint/types@10.2.2': {} - '@shikijs/core@4.3.1': + '@shikijs/core@4.4.3': dependencies: - '@shikijs/primitive': 4.3.1 - '@shikijs/types': 4.3.1 + '@shikijs/primitive': 4.4.3 + '@shikijs/types': 4.4.3 '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.5 hast-util-to-html: 9.0.5 - '@shikijs/engine-javascript@4.3.1': + '@shikijs/engine-javascript@4.4.3': dependencies: - '@shikijs/types': 4.3.1 + '@shikijs/types': 4.4.3 '@shikijs/vscode-textmate': 10.0.2 oniguruma-to-es: 4.3.6 - '@shikijs/engine-oniguruma@4.3.1': + '@shikijs/engine-oniguruma@4.4.3': dependencies: - '@shikijs/types': 4.3.1 + '@shikijs/types': 4.4.3 '@shikijs/vscode-textmate': 10.0.2 - '@shikijs/langs@4.3.1': + '@shikijs/langs@4.4.3': dependencies: - '@shikijs/types': 4.3.1 + '@shikijs/types': 4.4.3 - '@shikijs/primitive@4.3.1': + '@shikijs/primitive@4.4.3': dependencies: - '@shikijs/types': 4.3.1 + '@shikijs/types': 4.4.3 '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.5 - '@shikijs/themes@4.3.1': + '@shikijs/themes@4.4.3': dependencies: - '@shikijs/types': 4.3.1 + '@shikijs/types': 4.4.3 - '@shikijs/types@4.3.1': + '@shikijs/types@4.4.3': dependencies: '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.5 @@ -14137,18 +14975,17 @@ snapshots: '@standard-schema/spec@1.1.0': {} - '@textlint/ast-node-types@15.7.1': {} + '@textlint/ast-node-types@15.8.0': {} - '@textlint/linter-formatter@15.7.1(supports-color@10.2.2)': + '@textlint/linter-formatter@15.8.0(supports-color@11.0.0)': dependencies: '@azu/format-text': 1.0.2 '@azu/style-format': 1.0.1 - '@textlint/module-interop': 15.7.1 - '@textlint/resolver': 15.7.1 - '@textlint/types': 15.7.1 - chalk: 4.1.2 - debug: 4.4.3(supports-color@10.2.2) - js-yaml: 4.3.0 + '@textlint/module-interop': 15.8.0 + '@textlint/resolver': 15.8.0 + '@textlint/types': 15.8.0 + debug: 4.4.3(supports-color@11.0.0) + js-yaml: 4.3.2 lodash: 4.18.1 pluralize: 2.0.0 string-width: 4.2.3 @@ -14158,17 +14995,17 @@ snapshots: transitivePeerDependencies: - supports-color - '@textlint/module-interop@15.7.1': {} + '@textlint/module-interop@15.8.0': {} - '@textlint/resolver@15.7.1': {} + '@textlint/resolver@15.8.0': {} - '@textlint/types@15.7.1': + '@textlint/types@15.8.0': dependencies: - '@textlint/ast-node-types': 15.7.1 + '@textlint/ast-node-types': 15.8.0 '@tootallnate/quickjs-emscripten@0.23.0': {} - '@tsconfig/node10@1.0.12': {} + '@tsconfig/node10@1.0.13': {} '@tsconfig/node12@1.0.11': {} @@ -14189,24 +15026,24 @@ snapshots: '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 '@types/babel__generator': 7.27.0 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.28.0 '@types/babel__generator@7.27.0': dependencies: - '@babel/types': 7.29.7 + '@babel/types': 7.29.8 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 '@types/babel__traverse@7.28.0': dependencies: - '@babel/types': 7.29.7 + '@babel/types': 7.29.8 '@types/big.js@6.2.2': {} @@ -14215,7 +15052,7 @@ snapshots: '@types/deep-eql': 4.0.2 assertion-error: 2.0.1 - '@types/chrome@0.2.2': + '@types/chrome@0.2.7': dependencies: '@types/filesystem': 0.0.36 '@types/har-format': 1.2.16 @@ -14273,7 +15110,7 @@ snapshots: '@types/d3-format@3.0.4': {} - '@types/d3-geo@3.1.0': + '@types/d3-geo@3.1.1': dependencies: '@types/geojson': 7946.0.16 @@ -14299,7 +15136,7 @@ snapshots: '@types/d3-selection@3.0.11': {} - '@types/d3-shape@3.1.8': + '@types/d3-shape@3.2.0': dependencies: '@types/d3-path': 3.1.1 @@ -14334,7 +15171,7 @@ snapshots: '@types/d3-fetch': 3.0.7 '@types/d3-force': 3.0.10 '@types/d3-format': 3.0.4 - '@types/d3-geo': 3.1.0 + '@types/d3-geo': 3.1.1 '@types/d3-hierarchy': 3.1.7 '@types/d3-interpolate': 3.0.4 '@types/d3-path': 3.1.1 @@ -14344,7 +15181,7 @@ snapshots: '@types/d3-scale': 4.0.9 '@types/d3-scale-chromatic': 3.1.0 '@types/d3-selection': 3.0.11 - '@types/d3-shape': 3.1.8 + '@types/d3-shape': 3.2.0 '@types/d3-time': 3.0.4 '@types/d3-time-format': 4.0.3 '@types/d3-timer': 3.0.2 @@ -14411,12 +15248,12 @@ snapshots: '@types/tough-cookie': 4.0.5 parse5: 7.3.0 - '@types/jsdom@28.0.3': + '@types/jsdom@30.0.0': dependencies: '@types/node': 24.13.3 '@types/tough-cookie': 4.0.5 parse5: 8.0.1 - undici-types: 7.28.0 + undici-types: 8.10.0 '@types/jsesc@2.5.1': {} @@ -14451,7 +15288,7 @@ snapshots: '@types/selenium-webdriver@3.0.7': {} - '@types/semver@7.7.1': {} + '@types/semver@7.8.0': {} '@types/sinonjs__fake-timers@8.1.1': {} @@ -14474,7 +15311,7 @@ snapshots: '@types/unist@3.0.3': {} - '@types/vscode@1.125.0': {} + '@types/vscode@1.134.0': {} '@types/which@3.0.4': {} @@ -14490,22 +15327,22 @@ snapshots: '@types/yarnpkg__lockfile@1.1.9': {} - '@typescript/vfs@1.6.4(supports-color@8.1.1)(typescript@6.0.3)': + '@typescript/vfs@1.6.4(supports-color@11.0.0)(typescript@6.0.3)': dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3(supports-color@11.0.0) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typespec/ts-http-runtime@0.3.6(supports-color@10.2.2)': + '@typespec/ts-http-runtime@0.3.8(supports-color@11.0.0)': dependencies: - http-proxy-agent: 7.0.2(supports-color@10.2.2) - https-proxy-agent: 7.0.6(supports-color@10.2.2) + http-proxy-agent: 7.0.2(supports-color@11.0.0) + https-proxy-agent: 7.0.6(supports-color@11.0.0) tslib: 2.8.1 transitivePeerDependencies: - supports-color - '@ungap/structured-clone@1.3.3': {} + '@ungap/structured-clone@1.4.0': {} '@unrs/resolver-binding-android-arm-eabi@1.12.2': optional: true @@ -14565,7 +15402,7 @@ snapshots: dependencies: '@emnapi/core': 1.10.0 '@emnapi/runtime': 1.10.0 - '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + '@napi-rs/wasm-runtime': 1.2.3(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) optional: true '@unrs/resolver-binding-win32-arm64-msvc@1.12.2': @@ -14582,70 +15419,41 @@ snapshots: d3-selection: 3.0.0 d3-transition: 3.0.1(d3-selection@3.0.0) - '@vitejs/plugin-basic-ssl@2.3.0(vite@8.1.4(@types/node@20.19.43)(esbuild@0.28.1)(jiti@1.21.7)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0))': - dependencies: - vite: 8.1.4(@types/node@20.19.43)(esbuild@0.28.1)(jiti@1.21.7)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0) - - '@vitejs/plugin-basic-ssl@2.3.0(vite@8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(jiti@1.21.7)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0))': + '@vitejs/plugin-basic-ssl@2.3.0(vite@8.2.2(@types/node@20.19.43)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.1)(sass@1.104.1)(tsx@4.23.13)(yaml@2.9.1))': dependencies: - vite: 8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(jiti@1.21.7)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0) + vite: 8.2.2(@types/node@20.19.43)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.1)(sass@1.104.1)(tsx@4.23.13)(yaml@2.9.1) - '@vitest/expect@4.1.10': + '@vitejs/plugin-basic-ssl@2.3.0(vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.1)(sass@1.104.1)(tsx@4.23.13)(yaml@2.9.1))': dependencies: - '@standard-schema/spec': 1.1.0 - '@types/chai': 5.2.3 - '@vitest/spy': 4.1.10 - '@vitest/utils': 4.1.10 - chai: 6.2.2 - tinyrainbow: 3.1.0 + vite: 8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.1)(sass@1.104.1)(tsx@4.23.13)(yaml@2.9.1) - '@vitest/mocker@4.1.10(vite@8.1.4(@types/node@20.19.43)(esbuild@0.28.1)(jiti@1.21.7)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0))': + '@vitest/mocker@5.0.0(vite@8.2.2(@types/node@20.19.43)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.1)(sass@1.104.1)(tsx@4.23.13)(yaml@2.9.1))': dependencies: - '@vitest/spy': 4.1.10 + '@jridgewell/trace-mapping': 0.3.31 + '@vitest/spy': 5.0.0 estree-walker: 3.0.3 - magic-string: 0.30.21 + magic-string: 1.4.1 optionalDependencies: - vite: 8.1.4(@types/node@20.19.43)(esbuild@0.28.1)(jiti@1.21.7)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0) + vite: 8.2.2(@types/node@20.19.43)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.1)(sass@1.104.1)(tsx@4.23.13)(yaml@2.9.1) optional: true - '@vitest/mocker@4.1.10(vite@8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(jiti@1.21.7)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0))': + '@vitest/mocker@5.0.0(vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.1)(sass@1.104.1)(tsx@4.23.13)(yaml@2.9.1))': dependencies: - '@vitest/spy': 4.1.10 + '@jridgewell/trace-mapping': 0.3.31 + '@vitest/spy': 5.0.0 estree-walker: 3.0.3 - magic-string: 0.30.21 + magic-string: 1.4.1 optionalDependencies: - vite: 8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(jiti@1.21.7)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0) - - '@vitest/pretty-format@4.1.10': - dependencies: - tinyrainbow: 3.1.0 - - '@vitest/runner@4.1.10': - dependencies: - '@vitest/utils': 4.1.10 - pathe: 2.0.3 - - '@vitest/snapshot@4.1.10': - dependencies: - '@vitest/pretty-format': 4.1.10 - '@vitest/utils': 4.1.10 - magic-string: 0.30.21 - pathe: 2.0.3 - - '@vitest/spy@4.1.10': {} + vite: 8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.1)(sass@1.104.1)(tsx@4.23.13)(yaml@2.9.1) - '@vitest/utils@4.1.10': - dependencies: - '@vitest/pretty-format': 4.1.10 - convert-source-map: 2.0.0 - tinyrainbow: 3.1.0 + '@vitest/spy@5.0.0': {} '@vscode/l10n@0.0.18': {} - '@vscode/test-electron@3.0.0(supports-color@10.2.2)': + '@vscode/test-electron@3.1.0(supports-color@11.0.0)': dependencies: - http-proxy-agent: 7.0.2(supports-color@10.2.2) - https-proxy-agent: 7.0.6(supports-color@10.2.2) + http-proxy-agent: 7.0.2(supports-color@11.0.0) + https-proxy-agent: 7.0.6(supports-color@11.0.0) jszip: 3.10.1 ora: 8.2.0 semver: 7.8.5 @@ -14679,7 +15487,7 @@ snapshots: '@vscode/vsce-sign-win32-x64@2.0.6': optional: true - '@vscode/vsce-sign@2.0.9': + '@vscode/vsce-sign@2.1.0': optionalDependencies: '@vscode/vsce-sign-alpine-arm64': 2.0.6 '@vscode/vsce-sign-alpine-x64': 2.0.6 @@ -14691,14 +15499,14 @@ snapshots: '@vscode/vsce-sign-win32-arm64': 2.0.6 '@vscode/vsce-sign-win32-x64': 2.0.6 - '@vscode/vsce@3.9.2(supports-color@10.2.2)': + '@vscode/vsce@3.9.2(supports-color@11.0.0)': dependencies: - '@azure/identity': 4.13.1(supports-color@10.2.2) - '@secretlint/node': 10.2.2(supports-color@10.2.2) + '@azure/identity': 4.13.2(supports-color@11.0.0) + '@secretlint/node': 10.2.2(supports-color@11.0.0) '@secretlint/secretlint-formatter-sarif': 10.2.2 '@secretlint/secretlint-rule-no-dotenv': 10.2.2 '@secretlint/secretlint-rule-preset-recommend': 10.2.2 - '@vscode/vsce-sign': 2.0.9 + '@vscode/vsce-sign': 2.1.0 azure-devops-node-api: 12.5.0 chalk: 4.1.2 cheerio: 1.2.0 @@ -14709,12 +15517,12 @@ snapshots: hosted-git-info: 4.1.0 jsonc-parser: 3.3.1 leven: 3.1.0 - markdown-it: 14.3.0 + markdown-it: 14.3.1 mime: 1.6.0 - minimatch: 10.2.5 + minimatch: 10.2.6 parse-semver: 1.1.1 read: 1.0.7 - secretlint: 10.2.2(supports-color@10.2.2) + secretlint: 10.2.2(supports-color@11.0.0) semver: 7.8.5 tmp: 0.2.7 typed-rest-client: 1.8.11 @@ -14729,7 +15537,7 @@ snapshots: '@webcontainer/api@1.6.4': {} - '@xmldom/xmldom@0.8.13': {} + '@xmldom/xmldom@0.8.15': {} '@xterm/addon-fit@0.11.0': {} @@ -14737,6 +15545,80 @@ snapshots: '@yarnpkg/lockfile@1.1.0': {} + '@yuku-codegen/binding-android-arm64@0.9.3': + optional: true + + '@yuku-codegen/binding-darwin-arm64@0.9.3': + optional: true + + '@yuku-codegen/binding-darwin-x64@0.9.3': + optional: true + + '@yuku-codegen/binding-freebsd-x64@0.9.3': + optional: true + + '@yuku-codegen/binding-linux-arm-gnu@0.9.3': + optional: true + + '@yuku-codegen/binding-linux-arm-musl@0.9.3': + optional: true + + '@yuku-codegen/binding-linux-arm64-gnu@0.9.3': + optional: true + + '@yuku-codegen/binding-linux-arm64-musl@0.9.3': + optional: true + + '@yuku-codegen/binding-linux-x64-gnu@0.9.3': + optional: true + + '@yuku-codegen/binding-linux-x64-musl@0.9.3': + optional: true + + '@yuku-codegen/binding-win32-arm64@0.9.3': + optional: true + + '@yuku-codegen/binding-win32-x64@0.9.3': + optional: true + + '@yuku-parser/binding-android-arm64@0.9.3': + optional: true + + '@yuku-parser/binding-darwin-arm64@0.9.3': + optional: true + + '@yuku-parser/binding-darwin-x64@0.9.3': + optional: true + + '@yuku-parser/binding-freebsd-x64@0.9.3': + optional: true + + '@yuku-parser/binding-linux-arm-gnu@0.9.3': + optional: true + + '@yuku-parser/binding-linux-arm-musl@0.9.3': + optional: true + + '@yuku-parser/binding-linux-arm64-gnu@0.9.3': + optional: true + + '@yuku-parser/binding-linux-arm64-musl@0.9.3': + optional: true + + '@yuku-parser/binding-linux-x64-gnu@0.9.3': + optional: true + + '@yuku-parser/binding-linux-x64-musl@0.9.3': + optional: true + + '@yuku-parser/binding-win32-arm64@0.9.3': + optional: true + + '@yuku-parser/binding-win32-x64@0.9.3': + optional: true + + '@yuku-toolchain/types@0.9.3': {} + abbrev@5.0.0: optional: true @@ -14752,13 +15634,13 @@ snapshots: accepts@2.0.0: dependencies: mime-types: 3.0.2 - negotiator: 1.0.0 + negotiator: 1.1.0 acorn-walk@8.3.5: dependencies: - acorn: 8.17.0 + acorn: 8.18.0 - acorn@8.17.0: {} + acorn@8.18.0: {} add-stream@1.0.0: {} @@ -14792,43 +15674,26 @@ snapshots: ajv@8.20.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.3 + fast-uri: 3.1.6 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - algoliasearch@5.55.2: - dependencies: - '@algolia/abtesting': 1.21.2 - '@algolia/client-abtesting': 5.55.2 - '@algolia/client-analytics': 5.55.2 - '@algolia/client-common': 5.55.2 - '@algolia/client-insights': 5.55.2 - '@algolia/client-personalization': 5.55.2 - '@algolia/client-query-suggestions': 5.55.2 - '@algolia/client-search': 5.55.2 - '@algolia/ingestion': 1.55.2 - '@algolia/monitoring': 1.55.2 - '@algolia/recommend': 5.55.2 - '@algolia/requester-browser-xhr': 5.55.2 - '@algolia/requester-fetch': 5.55.2 - '@algolia/requester-node-http': 5.55.2 - - algoliasearch@5.56.0: - dependencies: - '@algolia/abtesting': 1.22.0 - '@algolia/client-abtesting': 5.56.0 - '@algolia/client-analytics': 5.56.0 - '@algolia/client-common': 5.56.0 - '@algolia/client-insights': 5.56.0 - '@algolia/client-personalization': 5.56.0 - '@algolia/client-query-suggestions': 5.56.0 - '@algolia/client-search': 5.56.0 - '@algolia/ingestion': 1.56.0 - '@algolia/monitoring': 1.56.0 - '@algolia/recommend': 5.56.0 - '@algolia/requester-browser-xhr': 5.56.0 - '@algolia/requester-fetch': 5.56.0 - '@algolia/requester-node-http': 5.56.0 + algoliasearch@5.57.0: + dependencies: + '@algolia/abtesting': 1.23.0 + '@algolia/client-abtesting': 5.57.0 + '@algolia/client-analytics': 5.57.0 + '@algolia/client-common': 5.57.0 + '@algolia/client-insights': 5.57.0 + '@algolia/client-personalization': 5.57.0 + '@algolia/client-query-suggestions': 5.57.0 + '@algolia/client-search': 5.57.0 + '@algolia/ingestion': 1.57.0 + '@algolia/monitoring': 1.57.0 + '@algolia/recommend': 5.57.0 + '@algolia/requester-browser-xhr': 5.57.0 + '@algolia/requester-fetch': 5.57.0 + '@algolia/requester-node-http': 5.57.0 angular-mocks@1.5.11: {} @@ -14873,7 +15738,7 @@ snapshots: ansi-regex@5.0.1: {} - ansi-regex@6.2.2: {} + ansi-regex@6.3.0: {} ansi-styles@2.2.1: {} @@ -14898,7 +15763,7 @@ snapshots: normalize-path: 3.0.0 picomatch: 2.3.2 - arch@2.2.0: {} + arch@3.0.0: {} archiver-utils@5.0.2: dependencies: @@ -14917,7 +15782,7 @@ snapshots: buffer-crc32: 1.0.0 readable-stream: 4.7.0 readdir-glob: 1.1.3 - tar-stream: 3.2.0 + tar-stream: 3.2.1 zip-stream: 6.0.1 transitivePeerDependencies: - bare-abort-controller @@ -15013,13 +15878,13 @@ snapshots: at-least-node@1.0.0: {} - autoprefixer@10.5.4(postcss@8.5.20): + autoprefixer@10.5.4(postcss@8.5.26): dependencies: - browserslist: 4.28.6 - caniuse-lite: 1.0.30001806 + browserslist: 4.28.8 + caniuse-lite: 1.0.30001810 fraction.js: 5.3.4 picocolors: 1.1.1 - postcss: 8.5.20 + postcss: 8.5.26 postcss-value-parser: 4.2.0 available-typed-arrays@1.0.7: @@ -15037,25 +15902,25 @@ snapshots: b4a@1.8.1: {} - babel-jest@30.4.1(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2): + babel-jest@30.4.1(@babel/core@7.29.7(supports-color@11.0.0))(supports-color@11.0.0): dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@jest/transform': 30.4.1(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@11.0.0) + '@jest/transform': 30.4.1(supports-color@11.0.0) '@types/babel__core': 7.20.5 - babel-plugin-istanbul: 7.0.1(supports-color@10.2.2) - babel-preset-jest: 30.4.0(@babel/core@7.29.7(supports-color@10.2.2)) + babel-plugin-istanbul: 7.0.1(supports-color@11.0.0) + babel-preset-jest: 30.4.0(@babel/core@7.29.7(supports-color@11.0.0)) chalk: 4.1.2 graceful-fs: 4.2.11 slash: 3.0.0 transitivePeerDependencies: - supports-color - babel-plugin-istanbul@7.0.1(supports-color@10.2.2): + babel-plugin-istanbul@7.0.1(supports-color@11.0.0): dependencies: '@babel/helper-plugin-utils': 7.29.7 '@istanbuljs/load-nyc-config': 1.1.0 '@istanbuljs/schema': 0.1.6 - istanbul-lib-instrument: 6.0.3(supports-color@10.2.2) + istanbul-lib-instrument: 6.0.3(supports-color@11.0.0) test-exclude: 6.0.0 transitivePeerDependencies: - supports-color @@ -15064,30 +15929,30 @@ snapshots: dependencies: '@types/babel__core': 7.20.5 - babel-preset-current-node-syntax@1.2.0(@babel/core@7.29.7(supports-color@10.2.2)): - dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-import-attributes': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.29.7(supports-color@10.2.2)) - - babel-preset-jest@30.4.0(@babel/core@7.29.7(supports-color@10.2.2)): - dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + babel-preset-current-node-syntax@1.2.0(@babel/core@7.29.7(supports-color@11.0.0)): + dependencies: + '@babel/core': 7.29.7(supports-color@11.0.0) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.29.7(supports-color@11.0.0)) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.29.7(supports-color@11.0.0)) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.29.7(supports-color@11.0.0)) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.29.7(supports-color@11.0.0)) + '@babel/plugin-syntax-import-attributes': 7.29.7(@babel/core@7.29.7(supports-color@11.0.0)) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.29.7(supports-color@11.0.0)) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.29.7(supports-color@11.0.0)) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.29.7(supports-color@11.0.0)) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.7(supports-color@11.0.0)) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.29.7(supports-color@11.0.0)) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.29.7(supports-color@11.0.0)) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.29.7(supports-color@11.0.0)) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.7(supports-color@11.0.0)) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.29.7(supports-color@11.0.0)) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.29.7(supports-color@11.0.0)) + + babel-preset-jest@30.4.0(@babel/core@7.29.7(supports-color@11.0.0)): + dependencies: + '@babel/core': 7.29.7(supports-color@11.0.0) babel-plugin-jest-hoist: 30.4.0 - babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.7(supports-color@10.2.2)) + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.7(supports-color@11.0.0)) bach@2.0.1: dependencies: @@ -15099,14 +15964,14 @@ snapshots: balanced-match@4.0.4: {} - bare-events@2.9.1: {} + bare-events@2.9.2: {} - bare-fs@4.7.4: + bare-fs@4.8.1: dependencies: - bare-events: 2.9.1 + bare-events: 2.9.2 bare-path: 3.1.1 - bare-stream: 2.13.3(bare-events@2.9.1) - bare-url: 2.4.5 + bare-stream: 2.13.4(bare-events@2.9.2) + bare-url: 2.5.2 fast-fifo: 1.3.2 transitivePeerDependencies: - bare-abort-controller @@ -15114,17 +15979,17 @@ snapshots: bare-path@3.1.1: {} - bare-stream@2.13.3(bare-events@2.9.1): + bare-stream@2.13.4(bare-events@2.9.2): dependencies: b4a: 1.8.1 - streamx: 2.28.0 + streamx: 2.28.1 teex: 1.0.1 optionalDependencies: - bare-events: 2.9.1 + bare-events: 2.9.2 transitivePeerDependencies: - react-native-b4a - bare-url@2.4.5: + bare-url@2.5.2: dependencies: bare-path: 3.1.1 @@ -15132,7 +15997,7 @@ snapshots: base64id@2.0.0: {} - baseline-browser-mapping@2.10.43: {} + baseline-browser-mapping@2.11.20: {} basic-auth-connect@1.1.0: dependencies: @@ -15148,17 +16013,17 @@ snapshots: dependencies: tweetnacl: 0.14.5 - beasties@0.4.2: + beasties@0.5.4: dependencies: - css-select: 6.0.0 - css-what: 7.0.0 - dom-serializer: 2.0.0 - domhandler: 5.0.3 - htmlparser2: 10.1.0 + css-select: 7.0.0 + css-what: 8.0.0 + dom-serializer: 3.1.1 + domhandler: 6.0.1 + htmlparser2: 12.0.0 picocolors: 1.1.1 - postcss: 8.5.20 + postcss: 8.5.26 postcss-media-query-parser: 0.2.3 - postcss-safe-parser: 7.0.1(postcss@8.5.20) + postcss-safe-parser: 7.0.1(postcss@8.5.26) before-after-hook@4.0.0: {} @@ -15196,11 +16061,11 @@ snapshots: bluebird@3.7.2: {} - body-parser@1.20.6(supports-color@10.2.2): + body-parser@1.20.6(supports-color@11.0.0): dependencies: bytes: 3.1.2 content-type: 1.0.5 - debug: 2.6.9(supports-color@10.2.2) + debug: 2.6.9(supports-color@11.0.0) depd: 2.0.0 destroy: 1.2.0 http-errors: 2.0.1 @@ -15213,15 +16078,15 @@ snapshots: transitivePeerDependencies: - supports-color - body-parser@2.3.0(supports-color@10.2.2): + body-parser@2.3.0(supports-color@11.0.0): dependencies: bytes: 3.1.2 - content-type: 2.0.0 - debug: 4.4.3(supports-color@10.2.2) + content-type: 2.1.0 + debug: 4.4.3(supports-color@11.0.0) http-errors: 2.0.1 iconv-lite: 0.7.3 on-finished: 2.4.1 - qs: 6.15.3 + qs: 6.16.0 raw-body: 3.0.2 type-is: 2.1.0 transitivePeerDependencies: @@ -15229,6 +16094,8 @@ snapshots: boolbase@1.0.0: {} + boolbase@2.0.0: {} + bottleneck@2.19.5: {} boundary@2.0.0: {} @@ -15244,16 +16111,16 @@ snapshots: widest-line: 3.1.0 wrap-ansi: 7.0.0 - brace-expansion@1.1.16: + brace-expansion@1.1.18: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - brace-expansion@2.1.2: + brace-expansion@2.1.4: dependencies: balanced-match: 1.0.2 - brace-expansion@5.0.7: + brace-expansion@5.0.9: dependencies: balanced-match: 4.0.4 @@ -15263,17 +16130,17 @@ snapshots: browser-stdout@1.3.1: {} - browserslist@4.28.6: + browserslist@4.28.8: dependencies: - baseline-browser-mapping: 2.10.43 - caniuse-lite: 1.0.30001806 - electron-to-chromium: 1.5.389 - node-releases: 2.0.51 - update-browserslist-db: 1.2.3(browserslist@4.28.6) + baseline-browser-mapping: 2.11.20 + caniuse-lite: 1.0.30001810 + electron-to-chromium: 1.5.417 + node-releases: 2.0.54 + update-browserslist-db: 1.3.2(browserslist@4.28.8) - browserstack@1.6.1(supports-color@8.1.1): + browserstack@1.6.1(supports-color@11.0.0): dependencies: - https-proxy-agent: 2.2.4(supports-color@8.1.1) + https-proxy-agent: 2.2.4(supports-color@11.0.0) transitivePeerDependencies: - supports-color @@ -15340,7 +16207,7 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001806: {} + caniuse-lite@1.0.30001810: {} caseless@0.12.0: {} @@ -15373,6 +16240,8 @@ snapshots: chalk@5.6.2: {} + chalk@6.0.0: {} + char-regex@1.0.2: {} character-entities-html4@2.1.0: {} @@ -15409,7 +16278,7 @@ snapshots: parse5: 7.3.0 parse5-htmlparser2-tree-adapter: 7.1.0 parse5-parser-stream: 7.1.2 - undici: 7.28.0 + undici: 7.29.0 whatwg-mimetype: 4.0.0 chokidar@3.6.0: @@ -15424,24 +16293,28 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - chokidar@4.0.3: - dependencies: - readdirp: 4.1.2 - chokidar@5.0.0: dependencies: - readdirp: 5.0.0 + readdirp: 5.1.1 chownr@1.1.4: optional: true chownr@3.0.0: {} + chrome-remote-interface@0.33.3(bufferutil@4.1.0): + dependencies: + commander: 2.11.0 + ws: 7.5.13(bufferutil@4.1.0) + transitivePeerDependencies: + - bufferutil + - utf-8-validate + ci-info@2.0.0: {} ci-info@4.4.0: {} - cjs-module-lexer@2.2.0: {} + cjs-module-lexer@2.2.1: {} cjson@0.3.3: dependencies: @@ -15449,7 +16322,7 @@ snapshots: cldr@8.0.0: dependencies: - '@xmldom/xmldom': 0.8.13 + '@xmldom/xmldom': 0.8.15 escodegen: 2.1.0 esprima: 4.0.1 memoizeasync: 1.1.0 @@ -15505,6 +16378,11 @@ snapshots: slice-ansi: 8.0.0 string-width: 8.2.2 + cli-truncate@6.1.1: + dependencies: + slice-ansi: 9.0.0 + string-width: 8.2.2 + cli-width@4.1.0: {} cliui@6.0.0: @@ -15551,17 +16429,17 @@ snapshots: color-convert@3.1.3: dependencies: - color-name: 2.1.0 + color-name: 2.1.1 color-name@1.1.3: {} color-name@1.1.4: {} - color-name@2.1.0: {} + color-name@2.1.1: {} color-string@2.1.4: dependencies: - color-name: 2.1.0 + color-name: 2.1.1 color-support@1.1.3: {} @@ -15572,6 +16450,8 @@ snapshots: colorette@2.0.20: {} + colorjs.io@0.7.1: {} + colors@1.4.0: optional: true @@ -15589,6 +16469,8 @@ snapshots: commander@15.0.0: {} + commander@2.11.0: {} + commander@2.20.3: {} commander@4.1.1: {} @@ -15626,11 +16508,11 @@ snapshots: dependencies: mime-db: 1.54.0 - compression@1.8.1(supports-color@10.2.2): + compression@1.8.1(supports-color@11.0.0): dependencies: bytes: 3.1.2 compressible: 2.0.18 - debug: 2.6.9(supports-color@10.2.2) + debug: 2.6.9(supports-color@11.0.0) negotiator: 0.6.4 on-headers: 1.1.0 safe-buffer: 5.2.1 @@ -15661,10 +16543,10 @@ snapshots: write-file-atomic: 3.0.3 xdg-basedir: 4.0.0 - connect@3.7.0(supports-color@10.2.2): + connect@3.7.0(supports-color@11.0.0): dependencies: - debug: 2.6.9(supports-color@10.2.2) - finalhandler: 1.1.2(supports-color@10.2.2) + debug: 2.6.9(supports-color@11.0.0) + finalhandler: 1.1.2(supports-color@11.0.0) parseurl: 1.3.3 utils-merge: 1.0.1 transitivePeerDependencies: @@ -15678,7 +16560,9 @@ snapshots: content-type@1.0.5: {} - content-type@2.0.0: {} + content-type@2.1.0: {} + + content-type@3.0.0: {} conventional-changelog-angular@8.3.1: dependencies: @@ -15692,14 +16576,14 @@ snapshots: dependencies: compare-func: 2.0.0 - conventional-changelog-core@8.0.0: + conventional-changelog-core@8.0.0(conventional-commits-filter@5.0.0): dependencies: '@hutson/parse-repository-url': 5.0.0 add-stream: 1.0.0 conventional-changelog-writer: 8.4.0 conventional-commits-parser: 6.4.0 - git-raw-commits: 5.0.1(conventional-commits-parser@6.4.0) - git-semver-tags: 8.0.1(conventional-commits-parser@6.4.0) + git-raw-commits: 5.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0) + git-semver-tags: 8.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0) hosted-git-info: 7.0.2 normalize-package-data: 6.0.2 read-package-up: 11.0.0 @@ -15731,21 +16615,21 @@ snapshots: meow: 13.2.0 semver: 7.8.5 - conventional-changelog-writer@9.2.0: + conventional-changelog-writer@9.2.1: dependencies: - '@conventional-changelog/template': 1.2.1 + '@conventional-changelog/template': 1.4.0 '@simple-libs/stream-utils': 2.0.0 argue-cli: 3.1.0 conventional-commits-filter: 6.0.1 semver: 7.8.5 - conventional-changelog@6.0.0: + conventional-changelog@6.0.0(conventional-commits-filter@5.0.0): dependencies: conventional-changelog-angular: 8.3.1 conventional-changelog-atom: 5.1.0 conventional-changelog-codemirror: 5.1.0 conventional-changelog-conventionalcommits: 8.0.0 - conventional-changelog-core: 8.0.0 + conventional-changelog-core: 8.0.0(conventional-commits-filter@5.0.0) conventional-changelog-ember: 5.1.0 conventional-changelog-eslint: 6.1.0 conventional-changelog-express: 5.1.0 @@ -15755,18 +16639,17 @@ snapshots: transitivePeerDependencies: - conventional-commits-filter - conventional-changelog@8.1.0(conventional-commits-filter@6.0.1): + conventional-changelog@8.1.3: dependencies: - '@conventional-changelog/git-client': 3.1.0(conventional-commits-filter@6.0.1)(conventional-commits-parser@7.1.0) + '@conventional-changelog/git-client': 3.1.2(conventional-commits-filter@6.0.1)(conventional-commits-parser@7.1.2) '@simple-libs/hosted-git-info': 2.0.0 '@simple-libs/normalize-package-data': 1.0.0 argue-cli: 3.1.0 conventional-changelog-preset-loader: 6.0.1 - conventional-changelog-writer: 9.2.0 - conventional-commits-parser: 7.1.0 + conventional-changelog-writer: 9.2.1 + conventional-commits-filter: 6.0.1 + conventional-commits-parser: 7.1.2 fd-package-json: 2.0.0 - transitivePeerDependencies: - - conventional-commits-filter conventional-commits-filter@5.0.0: {} @@ -15777,7 +16660,7 @@ snapshots: '@simple-libs/stream-utils': 1.2.0 meow: 13.2.0 - conventional-commits-parser@7.1.0: + conventional-commits-parser@7.1.2: dependencies: '@simple-libs/stream-utils': 2.0.0 argue-cli: 3.1.0 @@ -15799,7 +16682,7 @@ snapshots: copy-props@4.0.0: dependencies: each-props: 3.0.0 - is-plain-object: 5.0.0 + is-plain-object: 5.1.0 core-util-is@1.0.2: {} @@ -15851,13 +16734,13 @@ snapshots: domutils: 3.2.2 nth-check: 2.1.1 - css-select@6.0.0: + css-select@7.0.0: dependencies: - boolbase: 1.0.0 - css-what: 7.0.0 - domhandler: 5.0.3 - domutils: 3.2.2 - nth-check: 2.1.1 + boolbase: 2.0.0 + css-what: 8.0.0 + domhandler: 6.0.1 + domutils: 4.0.2 + nth-check: 3.0.1 css-tree@3.2.1: dependencies: @@ -15866,7 +16749,7 @@ snapshots: css-what@6.2.2: {} - css-what@7.0.0: {} + css-what@8.0.0: {} cssesc@3.0.0: {} @@ -15879,24 +16762,25 @@ snapshots: custom-event@1.0.1: {} - cypress@15.18.1: + cypress@16.0.0(bufferutil@4.1.0): dependencies: '@cypress/request': 4.0.1 '@cypress/xvfb': 1.2.4(supports-color@8.1.1) '@types/sinonjs__fake-timers': 8.1.1 '@types/sizzle': 2.3.10 '@types/tmp': 0.2.6 - arch: 2.2.0 + arch: 3.0.0 blob-util: 2.0.2 bluebird: 3.7.2 buffer: 5.7.1 cachedir: 2.4.0 chalk: 4.1.2 + chrome-remote-interface: 0.33.3(bufferutil@4.1.0) ci-info: 4.4.0 cli-table3: 0.6.1 commander: 6.2.1 common-tags: 1.8.2 - dayjs: 1.11.21 + dayjs: 1.11.23 debug: 4.4.3(supports-color@8.1.1) eventemitter2: 6.4.7 execa: 4.1.0 @@ -15914,24 +16798,26 @@ snapshots: proxy-from-env: 1.0.0 request-progress: 3.0.0 supports-color: 8.1.1 - systeminformation: 5.31.16 + systeminformation: 5.33.6 tmp: 0.2.7 tree-kill: 1.2.2 - tslib: 1.14.1 untildify: 4.0.0 yauzl: 3.4.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate - cytoscape-cose-bilkent@4.1.0(cytoscape@3.34.0): + cytoscape-cose-bilkent@4.1.0(cytoscape@3.34.2): dependencies: cose-base: 1.0.3 - cytoscape: 3.34.0 + cytoscape: 3.34.2 - cytoscape-fcose@2.2.0(cytoscape@3.34.0): + cytoscape-fcose@2.2.0(cytoscape@3.34.2): dependencies: cose-base: 2.2.0 - cytoscape: 3.34.0 + cytoscape: 3.34.2 - cytoscape@3.34.0: {} + cytoscape@3.34.2: {} d3-array@2.12.1: dependencies: @@ -16145,19 +17031,19 @@ snapshots: date-format@4.0.14: {} - dayjs@1.11.21: {} + dayjs@1.11.23: {} - debug@2.6.9(supports-color@10.2.2): + debug@2.6.9(supports-color@11.0.0): dependencies: ms: 2.0.0 optionalDependencies: - supports-color: 10.2.2 + supports-color: 11.0.0 - debug@3.2.7(supports-color@10.2.2): + debug@3.2.7(supports-color@11.0.0): dependencies: ms: 2.1.3 optionalDependencies: - supports-color: 10.2.2 + supports-color: 11.0.0 debug@3.2.7(supports-color@8.1.1): dependencies: @@ -16165,23 +17051,23 @@ snapshots: optionalDependencies: supports-color: 8.1.1 - debug@4.3.1(supports-color@10.2.2): + debug@4.3.1(supports-color@11.0.0): dependencies: ms: 2.1.2 optionalDependencies: - supports-color: 10.2.2 + supports-color: 11.0.0 - debug@4.4.0(supports-color@10.2.2): + debug@4.4.0(supports-color@11.0.0): dependencies: ms: 2.1.3 optionalDependencies: - supports-color: 10.2.2 + supports-color: 11.0.0 - debug@4.4.3(supports-color@10.2.2): + debug@4.4.3(supports-color@11.0.0): dependencies: ms: 2.1.3 optionalDependencies: - supports-color: 10.2.2 + supports-color: 11.0.0 debug@4.4.3(supports-color@8.1.1): dependencies: @@ -16191,8 +17077,6 @@ snapshots: decamelize@1.2.0: {} - decamelize@4.0.0: {} - decimal.js@10.6.0: {} decompress-response@6.0.0: @@ -16212,7 +17096,7 @@ snapshots: default-browser-id@5.0.1: {} - default-browser@5.5.0: + default-browser@5.5.1: dependencies: bundle-name: 4.1.0 default-browser-id: 5.0.1 @@ -16281,8 +17165,6 @@ snapshots: diff@4.0.4: {} - diff@7.0.0: {} - diff@9.0.0: {} discontinuous-range@1.0.0: {} @@ -16302,13 +17184,25 @@ snapshots: domhandler: 5.0.3 entities: 4.5.0 + dom-serializer@3.1.1: + dependencies: + domelementtype: 3.0.0 + domhandler: 6.0.1 + entities: 8.0.0 + domelementtype@2.3.0: {} + domelementtype@3.0.0: {} + domhandler@5.0.3: dependencies: domelementtype: 2.3.0 - dompurify@3.4.12: + domhandler@6.0.1: + dependencies: + domelementtype: 3.0.0 + + dompurify@3.4.14: optionalDependencies: '@types/trusted-types': 2.0.7 @@ -16318,10 +17212,18 @@ snapshots: domelementtype: 2.3.0 domhandler: 5.0.3 + domutils@4.0.2: + dependencies: + dom-serializer: 3.1.1 + domelementtype: 3.0.0 + domhandler: 6.0.1 + dot-prop@5.3.0: dependencies: is-obj: 2.0.0 + dts-resolver@3.0.0: {} + dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -16344,7 +17246,7 @@ snapshots: each-props@3.0.0: dependencies: - is-plain-object: 5.0.0 + is-plain-object: 5.1.0 object.defaults: 1.1.0 eastasianwidth@0.2.0: {} @@ -16366,7 +17268,7 @@ snapshots: ejs@6.0.1: {} - electron-to-chromium@1.5.389: {} + electron-to-chromium@1.5.417: {} emittery@0.13.1: {} @@ -16401,7 +17303,7 @@ snapshots: engine.io-parser@5.2.3: {} - engine.io@6.6.9(bufferutil@4.1.0)(supports-color@8.1.1)(utf-8-validate@6.0.6): + engine.io@6.6.9(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6): dependencies: '@types/cors': 2.8.19 '@types/node': 24.13.3 @@ -16410,9 +17312,9 @@ snapshots: base64id: 2.0.0 cookie: 0.7.2 cors: 2.8.6 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3(supports-color@11.0.0) engine.io-parser: 5.2.3 - ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) + ws: 8.21.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) transitivePeerDependencies: - bufferutil - supports-color @@ -16494,7 +17396,7 @@ snapshots: object-inspect: 1.13.4 object-keys: 1.1.1 object.assign: 4.1.7 - own-keys: 1.0.1 + own-keys: 1.0.2 regexp.prototype.flags: 1.5.4 safe-array-concat: 1.1.4 safe-push-apply: 1.0.0 @@ -16515,7 +17417,7 @@ snapshots: es-errors@1.3.0: {} - es-module-lexer@2.3.1: {} + es-module-lexer@2.3.2: {} es-object-atoms@1.1.2: dependencies: @@ -16537,7 +17439,7 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 - es-toolkit@1.49.0: {} + es-toolkit@1.52.0: {} es6-promise@4.2.8: {} @@ -16547,34 +17449,34 @@ snapshots: esbuild-plugin-umd-wrapper@3.0.0: {} - esbuild@0.28.1: + esbuild@0.28.2: optionalDependencies: - '@esbuild/aix-ppc64': 0.28.1 - '@esbuild/android-arm': 0.28.1 - '@esbuild/android-arm64': 0.28.1 - '@esbuild/android-x64': 0.28.1 - '@esbuild/darwin-arm64': 0.28.1 - '@esbuild/darwin-x64': 0.28.1 - '@esbuild/freebsd-arm64': 0.28.1 - '@esbuild/freebsd-x64': 0.28.1 - '@esbuild/linux-arm': 0.28.1 - '@esbuild/linux-arm64': 0.28.1 - '@esbuild/linux-ia32': 0.28.1 - '@esbuild/linux-loong64': 0.28.1 - '@esbuild/linux-mips64el': 0.28.1 - '@esbuild/linux-ppc64': 0.28.1 - '@esbuild/linux-riscv64': 0.28.1 - '@esbuild/linux-s390x': 0.28.1 - '@esbuild/linux-x64': 0.28.1 - '@esbuild/netbsd-arm64': 0.28.1 - '@esbuild/netbsd-x64': 0.28.1 - '@esbuild/openbsd-arm64': 0.28.1 - '@esbuild/openbsd-x64': 0.28.1 - '@esbuild/openharmony-arm64': 0.28.1 - '@esbuild/sunos-x64': 0.28.1 - '@esbuild/win32-arm64': 0.28.1 - '@esbuild/win32-ia32': 0.28.1 - '@esbuild/win32-x64': 0.28.1 + '@esbuild/aix-ppc64': 0.28.2 + '@esbuild/android-arm': 0.28.2 + '@esbuild/android-arm64': 0.28.2 + '@esbuild/android-x64': 0.28.2 + '@esbuild/darwin-arm64': 0.28.2 + '@esbuild/darwin-x64': 0.28.2 + '@esbuild/freebsd-arm64': 0.28.2 + '@esbuild/freebsd-x64': 0.28.2 + '@esbuild/linux-arm': 0.28.2 + '@esbuild/linux-arm64': 0.28.2 + '@esbuild/linux-ia32': 0.28.2 + '@esbuild/linux-loong64': 0.28.2 + '@esbuild/linux-mips64el': 0.28.2 + '@esbuild/linux-ppc64': 0.28.2 + '@esbuild/linux-riscv64': 0.28.2 + '@esbuild/linux-s390x': 0.28.2 + '@esbuild/linux-x64': 0.28.2 + '@esbuild/netbsd-arm64': 0.28.2 + '@esbuild/netbsd-x64': 0.28.2 + '@esbuild/openbsd-arm64': 0.28.2 + '@esbuild/openbsd-x64': 0.28.2 + '@esbuild/openharmony-arm64': 0.28.2 + '@esbuild/sunos-x64': 0.28.2 + '@esbuild/win32-arm64': 0.28.2 + '@esbuild/win32-ia32': 0.28.2 + '@esbuild/win32-x64': 0.28.2 escalade@3.2.0: {} @@ -16586,8 +17488,6 @@ snapshots: escape-string-regexp@2.0.0: {} - escape-string-regexp@4.0.0: {} - escodegen@2.1.0: dependencies: esprima: 4.0.1 @@ -16624,17 +17524,17 @@ snapshots: events-universal@1.0.1: dependencies: - bare-events: 2.9.1 + bare-events: 2.9.2 transitivePeerDependencies: - bare-abort-controller events@3.3.0: {} - eventsource-parser@3.1.0: {} + eventsource-parser@3.1.1: {} eventsource@3.0.7: dependencies: - eventsource-parser: 3.1.0 + eventsource-parser: 3.1.1 execa@4.1.0: dependencies: @@ -16664,18 +17564,18 @@ snapshots: dependencies: pify: 2.3.0 - exegesis-express@4.0.0(supports-color@10.2.2): + exegesis-express@4.0.0(supports-color@11.0.0): dependencies: - exegesis: 4.3.0(supports-color@10.2.2) + exegesis: 4.3.0(supports-color@11.0.0) transitivePeerDependencies: - supports-color - exegesis@4.3.0(supports-color@10.2.2): + exegesis@4.3.0(supports-color@11.0.0): dependencies: '@apidevtools/json-schema-ref-parser': 9.1.2 ajv: 8.20.0 ajv-formats: 2.1.1(ajv@8.20.0) - body-parser: 1.20.6(supports-color@10.2.2) + body-parser: 1.20.6(supports-color@11.0.0) content-type: 1.0.5 deep-freeze: 0.0.1 events-listener: 1.1.0 @@ -16685,7 +17585,7 @@ snapshots: lodash: 4.18.1 openapi3-ts: 3.2.0 promise-breaker: 6.0.0 - qs: 6.15.3 + qs: 6.16.0 raw-body: 2.5.3 semver: 7.8.5 transitivePeerDependencies: @@ -16716,26 +17616,29 @@ snapshots: exponential-backoff@3.1.3: optional: true - express-rate-limit@8.5.2(express@5.2.1(supports-color@10.2.2)): + express-rate-limit@8.7.0(express@5.2.1(supports-color@11.0.0))(supports-color@11.0.0): dependencies: - express: 5.2.1(supports-color@10.2.2) - ip-address: 10.2.0 + debug: 4.4.3(supports-color@11.0.0) + express: 5.2.1(supports-color@11.0.0) + ip-address: 10.7.0 + transitivePeerDependencies: + - supports-color - express@4.22.2(supports-color@10.2.2): + express@4.22.2(supports-color@11.0.0): dependencies: accepts: 1.3.8 array-flatten: 1.1.1 - body-parser: 1.20.6(supports-color@10.2.2) + body-parser: 1.20.6(supports-color@11.0.0) content-disposition: 0.5.4 content-type: 1.0.5 cookie: 0.7.2 cookie-signature: 1.0.7 - debug: 2.6.9(supports-color@10.2.2) + debug: 2.6.9(supports-color@11.0.0) depd: 2.0.0 encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 - finalhandler: 1.3.2(supports-color@10.2.2) + finalhandler: 1.3.2(supports-color@11.0.0) fresh: 0.5.2 http-errors: 2.0.1 merge-descriptors: 1.0.3 @@ -16747,8 +17650,8 @@ snapshots: qs: 6.15.3 range-parser: 1.2.1 safe-buffer: 5.2.1 - send: 0.19.2(supports-color@10.2.2) - serve-static: 1.16.3(supports-color@10.2.2) + send: 0.19.2(supports-color@11.0.0) + serve-static: 1.16.3(supports-color@11.0.0) setprototypeof: 1.2.0 statuses: 2.0.2 type-is: 1.6.18 @@ -16757,20 +17660,20 @@ snapshots: transitivePeerDependencies: - supports-color - express@5.2.1(supports-color@10.2.2): + express@5.2.1(supports-color@11.0.0): dependencies: accepts: 2.0.0 - body-parser: 2.3.0(supports-color@10.2.2) + body-parser: 2.3.0(supports-color@11.0.0) content-disposition: 1.1.0 content-type: 1.0.5 cookie: 0.7.2 cookie-signature: 1.2.2 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) depd: 2.0.0 encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 - finalhandler: 2.1.1(supports-color@10.2.2) + finalhandler: 2.1.1(supports-color@11.0.0) fresh: 2.0.0 http-errors: 2.0.1 merge-descriptors: 2.0.0 @@ -16779,11 +17682,11 @@ snapshots: once: 1.4.0 parseurl: 1.3.3 proxy-addr: 2.0.7 - qs: 6.15.3 + qs: 6.16.0 range-parser: 1.3.0 - router: 2.2.0(supports-color@10.2.2) - send: 1.2.1(supports-color@10.2.2) - serve-static: 2.2.1(supports-color@10.2.2) + router: 2.2.0(supports-color@11.0.0) + send: 1.2.1(supports-color@11.0.0) + serve-static: 2.2.1(supports-color@11.0.0) statuses: 2.0.2 type-is: 2.1.0 vary: 1.1.2 @@ -16822,15 +17725,19 @@ snapshots: dependencies: fast-string-truncated-width: 3.0.3 - fast-uri@3.1.3: {} + fast-uri@3.1.6: {} fast-wrap-ansi@0.2.2: dependencies: fast-string-width: 3.0.2 + fastdom@1.0.12: + dependencies: + strictdom: 1.0.1 + fastest-levenshtein@1.0.16: {} - fastq@1.20.1: + fastq@1.20.3: dependencies: reusify: 1.1.0 @@ -16846,9 +17753,9 @@ snapshots: dependencies: walk-up-path: 4.0.0 - fdir@6.5.0(picomatch@4.0.5): + fdir@6.5.0(picomatch@4.0.7): optionalDependencies: - picomatch: 4.0.5 + picomatch: 4.0.7 fecha@4.2.3: {} @@ -16863,9 +17770,9 @@ snapshots: dependencies: to-regex-range: 5.0.1 - finalhandler@1.1.2(supports-color@10.2.2): + finalhandler@1.1.2(supports-color@11.0.0): dependencies: - debug: 2.6.9(supports-color@10.2.2) + debug: 2.6.9(supports-color@11.0.0) encodeurl: 1.0.2 escape-html: 1.0.3 on-finished: 2.3.0 @@ -16875,9 +17782,9 @@ snapshots: transitivePeerDependencies: - supports-color - finalhandler@1.3.2(supports-color@10.2.2): + finalhandler@1.3.2(supports-color@11.0.0): dependencies: - debug: 2.6.9(supports-color@10.2.2) + debug: 2.6.9(supports-color@11.0.0) encodeurl: 2.0.0 escape-html: 1.0.3 on-finished: 2.4.1 @@ -16887,9 +17794,9 @@ snapshots: transitivePeerDependencies: - supports-color - finalhandler@2.1.1(supports-color@10.2.2): + finalhandler@2.1.1(supports-color@11.0.0): dependencies: - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) encodeurl: 2.0.0 escape-html: 1.0.3 on-finished: 2.4.1 @@ -16925,26 +17832,26 @@ snapshots: fined@2.0.0: dependencies: expand-tilde: 2.0.2 - is-plain-object: 5.0.0 + is-plain-object: 5.1.0 object.defaults: 1.1.0 object.pick: 1.3.0 parse-filepath: 1.0.2 - firebase-tools@15.23.0(@cfworker/json-schema@4.1.1)(@types/node@20.19.43)(bufferutil@4.1.0)(encoding@0.1.13)(supports-color@10.2.2): + firebase-tools@15.28.2(@types/node@20.19.43)(bufferutil@4.1.0)(encoding@0.1.13)(supports-color@11.0.0): dependencies: '@apphosting/common': 0.0.8 '@electric-sql/pglite': 0.3.16 '@electric-sql/pglite-tools': 0.2.21(@electric-sql/pglite@0.3.16) - '@google-cloud/cloud-sql-connector': 1.11.2(supports-color@10.2.2) - '@google-cloud/pubsub': 5.3.1(supports-color@10.2.2) + '@google-cloud/cloud-sql-connector': 1.11.3(supports-color@11.0.0) + '@google-cloud/pubsub': 5.3.1(supports-color@11.0.0) '@inquirer/prompts': 7.10.1(@types/node@20.19.43) - '@modelcontextprotocol/sdk': 1.29.0(@cfworker/json-schema@4.1.1)(supports-color@10.2.2) + '@modelcontextprotocol/sdk': 1.30.0(supports-color@11.0.0) abort-controller: 3.0.0 ajv: 8.20.0 ajv-formats: 3.0.1 archiver: 7.0.1 async-lock: 1.4.1 - body-parser: 1.20.6(supports-color@10.2.2) + body-parser: 1.20.6(supports-color@11.0.0) chokidar: 3.6.0 cjson: 0.3.3 cli-table3: 0.6.5 @@ -16955,17 +17862,17 @@ snapshots: cross-env: 7.0.3 cross-spawn: 7.0.6 csv-parse: 5.6.0 - exegesis: 4.3.0(supports-color@10.2.2) - exegesis-express: 4.0.0(supports-color@10.2.2) - express: 4.22.2(supports-color@10.2.2) + exegesis: 4.3.0(supports-color@11.0.0) + exegesis-express: 4.0.0(supports-color@11.0.0) + express: 4.22.2(supports-color@11.0.0) form-data: 4.0.6 fs-extra: 10.1.0 fuzzy: 0.1.3 - gaxios: 6.7.1(encoding@0.1.13)(supports-color@10.2.2) + gaxios: 6.7.1(encoding@0.1.13)(supports-color@11.0.0) glob: 10.5.0 - google-auth-library: 9.15.1(encoding@0.1.13)(supports-color@10.2.2) - ignore: 7.0.6 - js-yaml: 4.3.0 + google-auth-library: 9.15.1(encoding@0.1.13)(supports-color@11.0.0) + ignore: 7.0.7 + js-yaml: 4.3.2 jsonwebtoken: 9.0.3 libsodium-wrappers: 0.7.16 lodash: 4.18.1 @@ -16974,34 +17881,34 @@ snapshots: marked-terminal: 7.3.0(marked@13.0.3) mime: 2.6.0 minimatch: 3.1.5 - morgan: 1.11.0(supports-color@10.2.2) + morgan: 1.12.0(supports-color@11.0.0) node-fetch: 2.7.0(encoding@0.1.13) open: 6.4.0 ora: 5.4.1 - pg: 8.22.0 + pg: 8.23.0 pg-gateway: 0.3.0-beta.4 pglite-2: '@electric-sql/pglite@0.2.17' - portfinder: 1.0.38(supports-color@8.1.1) + portfinder: 1.0.38(supports-color@11.0.0) progress: 2.0.3 - proxy-agent: 6.5.0(supports-color@10.2.2) + proxy-agent: 6.5.0(supports-color@11.0.0) retry: 0.13.1 semver: 7.8.5 sql-formatter: 15.8.2 stream-chain: 2.2.5 stream-json: 1.9.1 - superstatic: 10.0.0(encoding@0.1.13)(supports-color@10.2.2) - tar: 7.5.20 - tcp-port-used: 1.0.3(supports-color@10.2.2) + superstatic: 10.0.0(encoding@0.1.13)(supports-color@11.0.0) + tar: 7.5.22 + tcp-port-used: 1.0.3(supports-color@11.0.0) tmp: 0.2.7 triple-beam: 1.4.1 - undici: 6.27.0 - universal-analytics: 0.5.4(supports-color@8.1.1) + undici: 6.28.0 + universal-analytics: 0.5.4(supports-color@11.0.0) update-notifier-cjs: 5.1.7(encoding@0.1.13) winston: 3.19.0 winston-transport: 4.9.0 - ws: 7.5.11(bufferutil@4.1.0) + ws: 8.21.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) yaml: 2.9.0 - zod: 4.4.3 + zod: 4.5.4 transitivePeerDependencies: - '@cfworker/json-schema' - '@types/node' @@ -17014,57 +17921,55 @@ snapshots: - supports-color - utf-8-validate - firebase@12.16.0: - dependencies: - '@firebase/ai': 2.13.1(@firebase/app-types@0.9.5)(@firebase/app@0.15.1) - '@firebase/analytics': 0.10.22(@firebase/app@0.15.1) - '@firebase/analytics-compat': 0.2.28(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1) - '@firebase/app': 0.15.1 - '@firebase/app-check': 0.12.0(@firebase/app@0.15.1) - '@firebase/app-check-compat': 0.4.5(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1) - '@firebase/app-compat': 0.5.15 - '@firebase/app-types': 0.9.5 - '@firebase/auth': 1.13.3(@firebase/app@0.15.1) - '@firebase/auth-compat': 0.6.8(@firebase/app-compat@0.5.15)(@firebase/app-types@0.9.5)(@firebase/app@0.15.1) - '@firebase/data-connect': 0.7.1(@firebase/app@0.15.1) - '@firebase/database': 1.1.3 - '@firebase/database-compat': 2.1.4 - '@firebase/firestore': 4.16.0(@firebase/app@0.15.1) - '@firebase/firestore-compat': 0.4.11(@firebase/app-compat@0.5.15)(@firebase/app-types@0.9.5)(@firebase/app@0.15.1) - '@firebase/functions': 0.13.5(@firebase/app@0.15.1) - '@firebase/functions-compat': 0.4.5(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1) - '@firebase/installations': 0.6.22(@firebase/app@0.15.1) - '@firebase/installations-compat': 0.2.22(@firebase/app-compat@0.5.15)(@firebase/app-types@0.9.5)(@firebase/app@0.15.1) - '@firebase/messaging': 0.13.0(@firebase/app@0.15.1) - '@firebase/messaging-compat': 0.2.27(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1) - '@firebase/performance': 0.7.12(@firebase/app@0.15.1) - '@firebase/performance-compat': 0.2.25(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1) - '@firebase/remote-config': 0.9.0(@firebase/app@0.15.1) - '@firebase/remote-config-compat': 0.2.27(@firebase/app-compat@0.5.15)(@firebase/app@0.15.1) - '@firebase/storage': 0.14.3(@firebase/app@0.15.1) - '@firebase/storage-compat': 0.4.3(@firebase/app-compat@0.5.15)(@firebase/app-types@0.9.5)(@firebase/app@0.15.1) - '@firebase/util': 1.15.1 + firebase@12.18.0: + dependencies: + '@firebase/ai': 2.15.0(@firebase/app-types@0.9.6)(@firebase/app@0.16.1) + '@firebase/analytics': 0.10.24(@firebase/app@0.16.1) + '@firebase/analytics-compat': 0.2.30(@firebase/app-compat@0.5.17)(@firebase/app@0.16.1) + '@firebase/app': 0.16.1 + '@firebase/app-check': 0.13.1(@firebase/app@0.16.1) + '@firebase/app-check-compat': 0.4.7(@firebase/app-compat@0.5.17)(@firebase/app@0.16.1) + '@firebase/app-compat': 0.5.17 + '@firebase/app-types': 0.9.6 + '@firebase/auth': 1.13.5(@firebase/app@0.16.1) + '@firebase/auth-compat': 0.6.10(@firebase/app-compat@0.5.17)(@firebase/app-types@0.9.6)(@firebase/app@0.16.1) + '@firebase/data-connect': 0.7.4(@firebase/app@0.16.1) + '@firebase/database': 1.1.5 + '@firebase/database-compat': 2.1.7(@firebase/app-compat@0.5.17)(@firebase/app@0.16.1) + '@firebase/firestore': 4.17.1(@firebase/app@0.16.1) + '@firebase/firestore-compat': 0.4.13(@firebase/app-compat@0.5.17)(@firebase/app-types@0.9.6)(@firebase/app@0.16.1) + '@firebase/functions': 0.14.0(@firebase/app@0.16.1) + '@firebase/functions-compat': 0.5.0(@firebase/app-compat@0.5.17)(@firebase/app@0.16.1) + '@firebase/installations': 0.6.24(@firebase/app@0.16.1) + '@firebase/installations-compat': 0.2.24(@firebase/app-compat@0.5.17)(@firebase/app-types@0.9.6)(@firebase/app@0.16.1) + '@firebase/messaging': 0.13.2(@firebase/app@0.16.1) + '@firebase/messaging-compat': 0.2.29(@firebase/app-compat@0.5.17)(@firebase/app@0.16.1) + '@firebase/performance': 0.7.14(@firebase/app@0.16.1) + '@firebase/performance-compat': 0.2.27(@firebase/app-compat@0.5.17)(@firebase/app@0.16.1) + '@firebase/remote-config': 0.9.2(@firebase/app@0.16.1) + '@firebase/remote-config-compat': 0.2.29(@firebase/app-compat@0.5.17)(@firebase/app@0.16.1) + '@firebase/storage': 0.14.5(@firebase/app@0.16.1) + '@firebase/storage-compat': 0.4.5(@firebase/app-compat@0.5.17)(@firebase/app-types@0.9.6)(@firebase/app@0.16.1) + '@firebase/util': 1.15.3 transitivePeerDependencies: - '@react-native-async-storage/async-storage' flagged-respawn@2.0.0: {} - flat@5.0.2: {} - - flatted@3.4.2: {} + flatted@3.4.4: {} fn.name@1.1.0: {} - folder-hash@4.1.3(supports-color@10.2.2): + folder-hash@4.1.3(supports-color@11.0.0): dependencies: - debug: 4.4.0(supports-color@10.2.2) + debug: 4.4.0(supports-color@11.0.0) minimatch: 7.4.9 transitivePeerDependencies: - supports-color - follow-redirects@1.16.0(debug@4.4.3(supports-color@10.2.2)): + follow-redirects@1.16.0(debug@4.4.3(supports-color@11.0.0)): optionalDependencies: - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) for-each@0.3.5: dependencies: @@ -17118,7 +18023,7 @@ snapshots: jsonfile: 6.2.1 universalify: 2.0.1 - fs-extra@11.3.6: + fs-extra@11.4.0: dependencies: graceful-fs: 4.2.11 jsonfile: 6.2.1 @@ -17140,7 +18045,7 @@ snapshots: fs-mkdirp-stream@2.0.1: dependencies: graceful-fs: 4.2.11 - streamx: 2.28.0 + streamx: 2.28.1 transitivePeerDependencies: - bare-abort-controller - react-native-b4a @@ -17168,10 +18073,10 @@ snapshots: fuzzy@0.1.3: {} - gaxios@6.7.1(encoding@0.1.13)(supports-color@10.2.2): + gaxios@6.7.1(encoding@0.1.13)(supports-color@11.0.0): dependencies: extend: 3.0.2 - https-proxy-agent: 7.0.6(supports-color@10.2.2) + https-proxy-agent: 7.0.6(supports-color@11.0.0) is-stream: 2.0.1 node-fetch: 2.7.0(encoding@0.1.13) uuid: 9.0.1 @@ -17179,43 +18084,43 @@ snapshots: - encoding - supports-color - gaxios@7.1.3(supports-color@10.2.2): + gaxios@7.1.3(supports-color@11.0.0): dependencies: extend: 3.0.2 - https-proxy-agent: 7.0.6(supports-color@10.2.2) + https-proxy-agent: 7.0.6(supports-color@11.0.0) node-fetch: 3.3.2 rimraf: 5.0.10 transitivePeerDependencies: - supports-color - gaxios@7.2.0(supports-color@10.2.2): + gaxios@7.3.1(supports-color@11.0.0): dependencies: extend: 3.0.2 - https-proxy-agent: 7.0.6(supports-color@10.2.2) + https-proxy-agent: 7.0.6(supports-color@11.0.0) node-fetch: 3.3.2 transitivePeerDependencies: - supports-color - gcp-metadata@6.1.1(encoding@0.1.13)(supports-color@10.2.2): + gcp-metadata@6.1.1(encoding@0.1.13)(supports-color@11.0.0): dependencies: - gaxios: 6.7.1(encoding@0.1.13)(supports-color@10.2.2) + gaxios: 6.7.1(encoding@0.1.13)(supports-color@11.0.0) google-logging-utils: 0.0.2 json-bigint: 1.0.0 transitivePeerDependencies: - encoding - supports-color - gcp-metadata@8.1.2(supports-color@10.2.2): + gcp-metadata@8.1.2(supports-color@11.0.0): dependencies: - gaxios: 7.2.0(supports-color@10.2.2) + gaxios: 7.3.1(supports-color@11.0.0) google-logging-utils: 1.1.3 json-bigint: 1.0.0 transitivePeerDependencies: - supports-color - gcp-metadata@8.1.3(supports-color@10.2.2): + gcp-metadata@8.1.4(supports-color@11.0.0): dependencies: - gaxios: 7.1.3(supports-color@10.2.2) + gaxios: 7.1.3(supports-color@11.0.0) google-logging-utils: 1.1.3 json-bigint: 1.0.0 transitivePeerDependencies: @@ -17263,15 +18168,19 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.3.0 - get-tsconfig@4.14.0: + get-tsconfig@4.14.3: + dependencies: + resolve-pkg-maps: 1.0.0 + + get-tsconfig@5.0.0-beta.6: dependencies: resolve-pkg-maps: 1.0.0 - get-uri@6.0.5(supports-color@8.1.1): + get-uri@6.0.5(supports-color@11.0.0): dependencies: basic-ftp: 5.3.1 data-uri-to-buffer: 6.0.2 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3(supports-color@11.0.0) transitivePeerDependencies: - supports-color @@ -17279,17 +18188,17 @@ snapshots: dependencies: assert-plus: 1.0.0 - git-raw-commits@5.0.1(conventional-commits-parser@6.4.0): + git-raw-commits@5.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0): dependencies: - '@conventional-changelog/git-client': 2.7.0(conventional-commits-parser@6.4.0) + '@conventional-changelog/git-client': 2.7.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0) meow: 13.2.0 transitivePeerDependencies: - conventional-commits-filter - conventional-commits-parser - git-semver-tags@8.0.1(conventional-commits-parser@6.4.0): + git-semver-tags@8.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0): dependencies: - '@conventional-changelog/git-client': 2.7.0(conventional-commits-parser@6.4.0) + '@conventional-changelog/git-client': 2.7.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.4.0) meow: 13.2.0 transitivePeerDependencies: - conventional-commits-filter @@ -17318,12 +18227,12 @@ snapshots: dependencies: '@gulpjs/to-absolute-glob': 4.0.0 anymatch: 3.1.3 - fastq: 1.20.1 + fastq: 1.20.3 glob-parent: 6.0.2 is-glob: 4.0.3 is-negated-glob: 1.0.0 normalize-path: 3.0.0 - streamx: 2.28.0 + streamx: 2.28.1 transitivePeerDependencies: - bare-abort-controller - react-native-b4a @@ -17346,14 +18255,14 @@ snapshots: dependencies: foreground-child: 3.3.1 jackspeak: 4.2.3 - minimatch: 10.2.5 + minimatch: 10.2.6 minipass: 7.1.3 package-json-from-dist: 1.0.1 path-scurry: 2.0.2 glob@13.0.6: dependencies: - minimatch: 10.2.5 + minimatch: 10.2.6 minipass: 7.1.3 path-scurry: 2.0.2 @@ -17393,7 +18302,7 @@ snapshots: dependencies: '@sindresorhus/merge-streams': 2.3.0 fast-glob: 3.3.3 - ignore: 7.0.6 + ignore: 7.0.7 path-type: 6.0.0 slash: 5.1.0 unicorn-magic: 0.3.0 @@ -17411,53 +18320,53 @@ snapshots: dependencies: sparkles: 2.1.0 - google-auth-library@10.5.0(supports-color@10.2.2): + google-auth-library@10.5.0(supports-color@11.0.0): dependencies: base64-js: 1.5.1 ecdsa-sig-formatter: 1.0.11 - gaxios: 7.2.0(supports-color@10.2.2) - gcp-metadata: 8.1.3(supports-color@10.2.2) - google-logging-utils: 1.1.4 - gtoken: 8.0.0(supports-color@10.2.2) + gaxios: 7.3.1(supports-color@11.0.0) + gcp-metadata: 8.1.4(supports-color@11.0.0) + google-logging-utils: 1.2.0 + gtoken: 8.0.0(supports-color@11.0.0) jws: 4.0.1 transitivePeerDependencies: - supports-color - google-auth-library@10.9.0(supports-color@10.2.2): + google-auth-library@10.9.1(supports-color@11.0.0): dependencies: base64-js: 1.5.1 ecdsa-sig-formatter: 1.0.11 - gaxios: 7.2.0(supports-color@10.2.2) - gcp-metadata: 8.1.2(supports-color@10.2.2) + gaxios: 7.3.1(supports-color@11.0.0) + gcp-metadata: 8.1.2(supports-color@11.0.0) google-logging-utils: 1.1.3 jws: 4.0.1 transitivePeerDependencies: - supports-color - google-auth-library@9.15.1(encoding@0.1.13)(supports-color@10.2.2): + google-auth-library@9.15.1(encoding@0.1.13)(supports-color@11.0.0): dependencies: base64-js: 1.5.1 ecdsa-sig-formatter: 1.0.11 - gaxios: 6.7.1(encoding@0.1.13)(supports-color@10.2.2) - gcp-metadata: 6.1.1(encoding@0.1.13)(supports-color@10.2.2) - gtoken: 7.1.0(encoding@0.1.13)(supports-color@10.2.2) + gaxios: 6.7.1(encoding@0.1.13)(supports-color@11.0.0) + gcp-metadata: 6.1.1(encoding@0.1.13)(supports-color@11.0.0) + gtoken: 7.1.0(encoding@0.1.13)(supports-color@11.0.0) jws: 4.0.1 transitivePeerDependencies: - encoding - supports-color - google-gax@5.0.7(supports-color@10.2.2): + google-gax@5.0.8(supports-color@11.0.0): dependencies: '@grpc/grpc-js': 1.14.4 '@grpc/proto-loader': 0.8.1 duplexify: 4.1.3 - google-auth-library: 10.5.0(supports-color@10.2.2) + google-auth-library: 10.5.0(supports-color@11.0.0) google-logging-utils: 1.1.3 node-fetch: 3.3.2 object-hash: 3.0.0 proto3-json-serializer: 3.0.4 - protobufjs: 7.6.5 - retry-request: 8.0.3(supports-color@10.2.2) + protobufjs: 7.6.6 + retry-request: 8.0.4(supports-color@11.0.0) rimraf: 5.0.10 transitivePeerDependencies: - supports-color @@ -17466,15 +18375,15 @@ snapshots: google-logging-utils@1.1.3: {} - google-logging-utils@1.1.4: {} + google-logging-utils@1.2.0: {} - googleapis-common@8.0.2(supports-color@10.2.2): + googleapis-common@8.0.3(supports-color@11.0.0): dependencies: extend: 3.0.2 - gaxios: 7.1.3(supports-color@10.2.2) - google-auth-library: 10.5.0(supports-color@10.2.2) + gaxios: 7.1.3(supports-color@11.0.0) + google-auth-library: 10.5.0(supports-color@11.0.0) google-logging-utils: 1.1.3 - qs: 6.15.3 + qs: 6.16.0 url-template: 2.0.8 transitivePeerDependencies: - supports-color @@ -17492,22 +18401,22 @@ snapshots: graphql@16.14.2: {} - grpc-gcp@1.0.1(protobufjs@7.6.5): + grpc-gcp@1.1.1: dependencies: '@grpc/grpc-js': 1.14.4 - protobufjs: 7.6.5 + protobufjs: 7.6.6 - gtoken@7.1.0(encoding@0.1.13)(supports-color@10.2.2): + gtoken@7.1.0(encoding@0.1.13)(supports-color@11.0.0): dependencies: - gaxios: 6.7.1(encoding@0.1.13)(supports-color@10.2.2) + gaxios: 6.7.1(encoding@0.1.13)(supports-color@11.0.0) jws: 4.0.1 transitivePeerDependencies: - encoding - supports-color - gtoken@8.0.0(supports-color@10.2.2): + gtoken@8.0.0(supports-color@11.0.0): dependencies: - gaxios: 7.2.0(supports-color@10.2.2) + gaxios: 7.3.1(supports-color@11.0.0) jws: 4.0.1 transitivePeerDependencies: - supports-color @@ -17527,11 +18436,11 @@ snapshots: v8flags: 4.0.1 yargs: 16.2.2 - gulp-conventional-changelog@5.0.0: + gulp-conventional-changelog@5.0.0(conventional-commits-filter@5.0.0): dependencies: add-stream: 1.0.0 concat-stream: 2.0.0 - conventional-changelog: 6.0.0 + conventional-changelog: 6.0.0(conventional-commits-filter@5.0.0) fancy-log: 2.0.0 plugin-error: 2.0.1 transitivePeerDependencies: @@ -17636,7 +18545,7 @@ snapshots: dependencies: parse-passwd: 1.0.0 - hono@4.12.30: {} + hono@4.13.5: {} hosted-git-info@10.1.1: dependencies: @@ -17677,6 +18586,13 @@ snapshots: domutils: 3.2.2 entities: 7.0.1 + htmlparser2@12.0.0: + dependencies: + domelementtype: 3.0.0 + domhandler: 6.0.1 + domutils: 4.0.2 + entities: 8.0.0 + http-errors@2.0.1: dependencies: depd: 2.0.0 @@ -17687,33 +18603,33 @@ snapshots: http-parser-js@0.5.10: {} - http-proxy-agent@7.0.2(supports-color@10.2.2): + http-proxy-agent@7.0.2(supports-color@11.0.0): dependencies: agent-base: 7.1.4 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) transitivePeerDependencies: - supports-color - http-proxy@1.18.1(debug@4.4.3(supports-color@10.2.2)): + http-proxy@1.18.1(debug@4.4.3(supports-color@11.0.0)): dependencies: eventemitter3: 4.0.7 - follow-redirects: 1.16.0(debug@4.4.3(supports-color@10.2.2)) + follow-redirects: 1.16.0(debug@4.4.3(supports-color@11.0.0)) requires-port: 1.0.0 transitivePeerDependencies: - debug - http-server@14.1.1(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2): + http-server@14.1.1(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0): dependencies: basic-auth: 2.0.1 chalk: 4.1.2 corser: 2.0.1 he: 1.2.0 html-encoding-sniffer: 3.0.0 - http-proxy: 1.18.1(debug@4.4.3(supports-color@10.2.2)) + http-proxy: 1.18.1(debug@4.4.3(supports-color@11.0.0)) mime: 1.6.0 minimist: 1.2.8 opener: 1.5.2 - portfinder: 1.0.38(supports-color@10.2.2) + portfinder: 1.0.38(supports-color@11.0.0) secure-compare: 3.0.1 union: 0.5.0 url-join: 4.0.1 @@ -17733,40 +18649,24 @@ snapshots: jsprim: 2.0.2 sshpk: 1.18.0 - https-proxy-agent@2.2.4(supports-color@10.2.2): - dependencies: - agent-base: 4.3.0 - debug: 3.2.7(supports-color@10.2.2) - transitivePeerDependencies: - - supports-color - - https-proxy-agent@2.2.4(supports-color@8.1.1): + https-proxy-agent@2.2.4(supports-color@11.0.0): dependencies: agent-base: 4.3.0 - debug: 3.2.7(supports-color@8.1.1) + debug: 3.2.7(supports-color@11.0.0) transitivePeerDependencies: - supports-color - https-proxy-agent@7.0.6(supports-color@10.2.2): + https-proxy-agent@7.0.6(supports-color@11.0.0): dependencies: agent-base: 7.1.4 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) transitivePeerDependencies: - supports-color - https-proxy-agent@9.1.0(supports-color@10.2.2): + https-proxy-agent@9.1.0(supports-color@11.0.0): dependencies: agent-base: 9.0.0 - debug: 4.4.3(supports-color@10.2.2) - proxy-agent-negotiate: 1.1.0 - transitivePeerDependencies: - - kerberos - - supports-color - - https-proxy-agent@9.1.0(supports-color@8.1.1): - dependencies: - agent-base: 9.0.0 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3(supports-color@11.0.0) proxy-agent-negotiate: 1.1.0 transitivePeerDependencies: - kerberos @@ -17794,10 +18694,7 @@ snapshots: ieee754@1.2.1: {} - ignore@7.0.6: {} - - image-size@0.5.5: - optional: true + ignore@7.0.7: {} immediate@3.0.6: {} @@ -17831,7 +18728,7 @@ snapshots: dependencies: tslib: 2.8.1 - install-artifact-from-github@1.7.0: + install-artifact-from-github@1.8.0: optional: true internal-slot@1.1.0: @@ -17846,7 +18743,7 @@ snapshots: interpret@3.1.1: {} - ip-address@10.2.0: {} + ip-address@10.7.0: {} ip-regex@2.1.0: {} @@ -17987,9 +18884,7 @@ snapshots: is-path-inside@3.0.3: {} - is-plain-obj@2.1.0: {} - - is-plain-object@5.0.0: {} + is-plain-object@5.1.0: {} is-potential-custom-element-name@1.0.1: {} @@ -18111,20 +19006,20 @@ snapshots: istanbul-lib-coverage@3.2.2: {} - istanbul-lib-instrument@5.2.1(supports-color@10.2.2): + istanbul-lib-instrument@5.2.1(supports-color@11.0.0): dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/parser': 7.29.7 + '@babel/core': 7.29.7(supports-color@11.0.0) + '@babel/parser': 7.29.8 '@istanbuljs/schema': 0.1.6 istanbul-lib-coverage: 3.2.2 semver: 6.3.1 transitivePeerDependencies: - supports-color - istanbul-lib-instrument@6.0.3(supports-color@10.2.2): + istanbul-lib-instrument@6.0.3(supports-color@11.0.0): dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/parser': 7.29.7 + '@babel/core': 7.29.7(supports-color@11.0.0) + '@babel/parser': 7.29.8 '@istanbuljs/schema': 0.1.6 istanbul-lib-coverage: 3.2.2 semver: 7.8.5 @@ -18137,26 +19032,18 @@ snapshots: make-dir: 4.0.0 supports-color: 7.2.0 - istanbul-lib-source-maps@4.0.1(supports-color@10.2.2): - dependencies: - debug: 4.4.3(supports-color@10.2.2) - istanbul-lib-coverage: 3.2.2 - source-map: 0.6.1 - transitivePeerDependencies: - - supports-color - - istanbul-lib-source-maps@4.0.1(supports-color@8.1.1): + istanbul-lib-source-maps@4.0.1(supports-color@11.0.0): dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3(supports-color@11.0.0) istanbul-lib-coverage: 3.2.2 source-map: 0.6.1 transitivePeerDependencies: - supports-color - istanbul-lib-source-maps@5.0.6(supports-color@8.1.1): + istanbul-lib-source-maps@5.0.6(supports-color@11.0.0): dependencies: '@jridgewell/trace-mapping': 0.3.31 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3(supports-color@11.0.0) istanbul-lib-coverage: 3.2.2 transitivePeerDependencies: - supports-color @@ -18190,7 +19077,7 @@ snapshots: jasmine-reporters@2.5.2: dependencies: - '@xmldom/xmldom': 0.8.13 + '@xmldom/xmldom': 0.8.15 mkdirp: 1.0.4 jasmine@2.8.0: @@ -18201,7 +19088,7 @@ snapshots: jasmine@6.3.0: dependencies: - '@jasminejs/reporters': 1.0.0 + '@jasminejs/reporters': 1.1.0 glob: 13.0.6 jasmine-core: 6.3.0 @@ -18213,10 +19100,10 @@ snapshots: jest-util: 30.4.1 p-limit: 3.1.0 - jest-circus@30.4.2(supports-color@10.2.2): + jest-circus@30.4.2(supports-color@11.0.0): dependencies: '@jest/environment': 30.4.1 - '@jest/expect': 30.4.1(supports-color@10.2.2) + '@jest/expect': 30.4.1(supports-color@11.0.0) '@jest/test-result': 30.4.1 '@jest/types': 30.4.1 '@types/node': 24.13.3 @@ -18227,8 +19114,8 @@ snapshots: jest-each: 30.4.1 jest-matcher-utils: 30.4.1 jest-message-util: 30.4.1 - jest-runtime: 30.4.2(supports-color@10.2.2) - jest-snapshot: 30.4.1(supports-color@10.2.2) + jest-runtime: 30.4.2(supports-color@11.0.0) + jest-snapshot: 30.4.1(supports-color@11.0.0) jest-util: 30.4.1 p-limit: 3.1.0 pretty-format: 30.4.1 @@ -18239,15 +19126,15 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@30.4.2(@types/node@24.13.3)(supports-color@10.2.2)(ts-node@10.9.2(@types/node@24.13.3)(typescript@6.0.3)): + jest-cli@30.4.2(@types/node@24.13.3)(supports-color@11.0.0)(ts-node@10.9.2(@types/node@24.13.3)(typescript@6.0.3)): dependencies: - '@jest/core': 30.4.2(supports-color@10.2.2)(ts-node@10.9.2(@types/node@24.13.3)(typescript@6.0.3)) + '@jest/core': 30.4.2(supports-color@11.0.0)(ts-node@10.9.2(@types/node@24.13.3)(typescript@6.0.3)) '@jest/test-result': 30.4.1 '@jest/types': 30.4.1 chalk: 4.1.2 exit-x: 0.2.2 import-local: 3.2.0 - jest-config: 30.4.2(@types/node@24.13.3)(supports-color@10.2.2)(ts-node@10.9.2(@types/node@24.13.3)(typescript@6.0.3)) + jest-config: 30.4.2(@types/node@24.13.3)(supports-color@11.0.0)(ts-node@10.9.2(@types/node@24.13.3)(typescript@6.0.3)) jest-util: 30.4.1 jest-validate: 30.4.1 yargs: 17.7.3 @@ -18258,25 +19145,25 @@ snapshots: - supports-color - ts-node - jest-config@30.4.2(@types/node@24.13.3)(supports-color@10.2.2)(ts-node@10.9.2(@types/node@24.13.3)(typescript@6.0.3)): + jest-config@30.4.2(@types/node@24.13.3)(supports-color@11.0.0)(ts-node@10.9.2(@types/node@24.13.3)(typescript@6.0.3)): dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/core': 7.29.7(supports-color@11.0.0) '@jest/get-type': 30.1.0 '@jest/pattern': 30.4.0 '@jest/test-sequencer': 30.4.1 '@jest/types': 30.4.1 - babel-jest: 30.4.1(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) + babel-jest: 30.4.1(@babel/core@7.29.7(supports-color@11.0.0))(supports-color@11.0.0) chalk: 4.1.2 ci-info: 4.4.0 deepmerge: 4.3.1 glob: 10.5.0 graceful-fs: 4.2.11 - jest-circus: 30.4.2(supports-color@10.2.2) + jest-circus: 30.4.2(supports-color@11.0.0) jest-docblock: 30.4.0 jest-environment-node: 30.4.1 jest-regex-util: 30.4.0 jest-resolve: 30.4.1 - jest-runner: 30.4.2(supports-color@10.2.2) + jest-runner: 30.4.2(supports-color@11.0.0) jest-util: 30.4.1 jest-validate: 30.4.1 parse-json: 5.2.0 @@ -18309,11 +19196,11 @@ snapshots: jest-util: 30.4.1 pretty-format: 30.4.1 - jest-environment-jsdom@30.4.1(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6): + jest-environment-jsdom@30.4.1(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6): dependencies: '@jest/environment': 30.4.1 - '@jest/environment-jsdom-abstract': 30.4.1(jsdom@26.1.0(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6)) - jsdom: 26.1.0(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) + '@jest/environment-jsdom-abstract': 30.4.1(jsdom@26.1.0(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6)) + jsdom: 26.1.0(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6) transitivePeerDependencies: - bufferutil - supports-color @@ -18339,7 +19226,7 @@ snapshots: jest-regex-util: 30.4.0 jest-util: 30.4.1 jest-worker: 30.4.1 - picomatch: 4.0.5 + picomatch: 4.0.7 walker: 1.0.8 optionalDependencies: fsevents: 2.3.3 @@ -18364,7 +19251,7 @@ snapshots: chalk: 4.1.2 graceful-fs: 4.2.11 jest-util: 30.4.1 - picomatch: 4.0.5 + picomatch: 4.0.7 pretty-format: 30.4.1 slash: 3.0.0 stack-utils: 2.0.6 @@ -18381,10 +19268,10 @@ snapshots: jest-regex-util@30.4.0: {} - jest-resolve-dependencies@30.4.2(supports-color@10.2.2): + jest-resolve-dependencies@30.4.2(supports-color@11.0.0): dependencies: jest-regex-util: 30.4.0 - jest-snapshot: 30.4.1(supports-color@10.2.2) + jest-snapshot: 30.4.1(supports-color@11.0.0) transitivePeerDependencies: - supports-color @@ -18399,12 +19286,12 @@ snapshots: slash: 3.0.0 unrs-resolver: 1.12.2 - jest-runner@30.4.2(supports-color@10.2.2): + jest-runner@30.4.2(supports-color@11.0.0): dependencies: '@jest/console': 30.4.1 '@jest/environment': 30.4.1 '@jest/test-result': 30.4.1 - '@jest/transform': 30.4.1(supports-color@10.2.2) + '@jest/transform': 30.4.1(supports-color@11.0.0) '@jest/types': 30.4.1 '@types/node': 24.13.3 chalk: 4.1.2 @@ -18417,7 +19304,7 @@ snapshots: jest-leak-detector: 30.4.1 jest-message-util: 30.4.1 jest-resolve: 30.4.1 - jest-runtime: 30.4.2(supports-color@10.2.2) + jest-runtime: 30.4.2(supports-color@11.0.0) jest-util: 30.4.1 jest-watcher: 30.4.1 jest-worker: 30.4.1 @@ -18426,18 +19313,18 @@ snapshots: transitivePeerDependencies: - supports-color - jest-runtime@30.4.2(supports-color@10.2.2): + jest-runtime@30.4.2(supports-color@11.0.0): dependencies: '@jest/environment': 30.4.1 '@jest/fake-timers': 30.4.1 - '@jest/globals': 30.4.1(supports-color@10.2.2) + '@jest/globals': 30.4.1(supports-color@11.0.0) '@jest/source-map': 30.0.1 '@jest/test-result': 30.4.1 - '@jest/transform': 30.4.1(supports-color@10.2.2) + '@jest/transform': 30.4.1(supports-color@11.0.0) '@jest/types': 30.4.1 '@types/node': 24.13.3 chalk: 4.1.2 - cjs-module-lexer: 2.2.0 + cjs-module-lexer: 2.2.1 collect-v8-coverage: 1.0.3 glob: 10.5.0 graceful-fs: 4.2.11 @@ -18446,26 +19333,26 @@ snapshots: jest-mock: 30.4.1 jest-regex-util: 30.4.0 jest-resolve: 30.4.1 - jest-snapshot: 30.4.1(supports-color@10.2.2) + jest-snapshot: 30.4.1(supports-color@11.0.0) jest-util: 30.4.1 slash: 3.0.0 strip-bom: 4.0.0 transitivePeerDependencies: - supports-color - jest-snapshot@30.4.1(supports-color@10.2.2): + jest-snapshot@30.4.1(supports-color@11.0.0): dependencies: - '@babel/core': 7.29.7(supports-color@10.2.2) - '@babel/generator': 7.29.7 - '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/plugin-syntax-typescript': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2)) - '@babel/types': 7.29.7 + '@babel/core': 7.29.7(supports-color@11.0.0) + '@babel/generator': 7.29.8 + '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7(supports-color@11.0.0)) + '@babel/plugin-syntax-typescript': 7.29.7(@babel/core@7.29.7(supports-color@11.0.0)) + '@babel/types': 7.29.8 '@jest/expect-utils': 30.4.1 '@jest/get-type': 30.1.0 '@jest/snapshot-utils': 30.4.1 - '@jest/transform': 30.4.1(supports-color@10.2.2) + '@jest/transform': 30.4.1(supports-color@11.0.0) '@jest/types': 30.4.1 - babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.7(supports-color@10.2.2)) + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.7(supports-color@11.0.0)) chalk: 4.1.2 expect: 30.4.1 graceful-fs: 4.2.11 @@ -18486,7 +19373,7 @@ snapshots: chalk: 4.1.2 ci-info: 4.4.0 graceful-fs: 4.2.11 - picomatch: 4.0.5 + picomatch: 4.0.7 jest-validate@30.4.1: dependencies: @@ -18511,17 +19398,17 @@ snapshots: jest-worker@30.4.1: dependencies: '@types/node': 24.13.3 - '@ungap/structured-clone': 1.3.3 + '@ungap/structured-clone': 1.4.0 jest-util: 30.4.1 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@30.4.2(@types/node@24.13.3)(supports-color@10.2.2)(ts-node@10.9.2(@types/node@24.13.3)(typescript@6.0.3)): + jest@30.4.2(@types/node@24.13.3)(supports-color@11.0.0)(ts-node@10.9.2(@types/node@24.13.3)(typescript@6.0.3)): dependencies: - '@jest/core': 30.4.2(supports-color@10.2.2)(ts-node@10.9.2(@types/node@24.13.3)(typescript@6.0.3)) + '@jest/core': 30.4.2(supports-color@11.0.0)(ts-node@10.9.2(@types/node@24.13.3)(typescript@6.0.3)) '@jest/types': 30.4.1 import-local: 3.2.0 - jest-cli: 30.4.2(@types/node@24.13.3)(supports-color@10.2.2)(ts-node@10.9.2(@types/node@24.13.3)(typescript@6.0.3)) + jest-cli: 30.4.2(@types/node@24.13.3)(supports-color@11.0.0)(ts-node@10.9.2(@types/node@24.13.3)(typescript@6.0.3)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -18539,33 +19426,37 @@ snapshots: url-join: 0.0.1 valid-url: 1.0.9 - jose@6.2.3: {} + jose@6.2.10: {} js-tokens@10.0.0: {} js-tokens@4.0.0: {} - js-yaml@3.15.0: + js-yaml@3.15.2: dependencies: argparse: 1.0.10 esprima: 4.0.1 - js-yaml@4.3.0: + js-yaml@4.3.2: + dependencies: + argparse: 2.0.1 + + js-yaml@5.4.1: dependencies: argparse: 2.0.1 jsbn@0.1.1: {} - jsdom@26.1.0(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6): + jsdom@26.1.0(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6): dependencies: cssstyle: 4.6.0 data-urls: 5.0.0 decimal.js: 10.6.0 html-encoding-sniffer: 4.0.0 - http-proxy-agent: 7.0.2(supports-color@10.2.2) - https-proxy-agent: 7.0.6(supports-color@10.2.2) + http-proxy-agent: 7.0.2(supports-color@11.0.0) + https-proxy-agent: 7.0.6(supports-color@11.0.0) is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.24 + nwsapi: 2.2.27 parse5: 7.3.0 rrweb-cssom: 0.8.0 saxes: 6.0.0 @@ -18576,19 +19467,19 @@ snapshots: whatwg-encoding: 3.1.1 whatwg-mimetype: 4.0.0 whatwg-url: 14.2.0 - ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) + ws: 8.21.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) xml-name-validator: 5.0.0 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - jsdom@29.1.1: + jsdom@30.0.1: dependencies: - '@asamuzakjp/css-color': 5.1.11 - '@asamuzakjp/dom-selector': 7.1.1 + '@asamuzakjp/css-color': 6.0.7 + '@asamuzakjp/dom-selector': 8.3.2 '@bramus/specificity': 2.4.2 - '@csstools/css-syntax-patches-for-csstree': 1.1.6(css-tree@3.2.1) + '@csstools/css-syntax-patches-for-csstree': 1.1.10(css-tree@3.2.1) '@exodus/bytes': 1.15.1 css-tree: 3.2.1 data-urls: 7.0.0 @@ -18600,11 +19491,11 @@ snapshots: saxes: 6.0.0 symbol-tree: 3.2.4 tough-cookie: 6.0.2 - undici: 7.28.0 + undici: 8.10.0 w3c-xmlserializer: 5.0.0 webidl-conversions: 8.0.1 whatwg-mimetype: 5.0.0 - whatwg-url: 16.0.1 + whatwg-url: 17.1.0 xml-name-validator: 5.0.0 transitivePeerDependencies: - '@noble/hashes' @@ -18633,7 +19524,7 @@ snapshots: json-stringify-safe@5.0.1: {} - json-with-bigint@3.5.10: {} + json-with-bigint@3.5.12: {} json5@2.2.3: {} @@ -18698,23 +19589,12 @@ snapshots: dependencies: which: 1.3.1 - karma-coverage@2.2.1(supports-color@10.2.2): - dependencies: - istanbul-lib-coverage: 3.2.2 - istanbul-lib-instrument: 5.2.1(supports-color@10.2.2) - istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 4.0.1(supports-color@10.2.2) - istanbul-reports: 3.2.0 - minimatch: 3.1.5 - transitivePeerDependencies: - - supports-color - - karma-coverage@2.2.1(supports-color@8.1.1): + karma-coverage@2.2.1(supports-color@11.0.0): dependencies: istanbul-lib-coverage: 3.2.2 - istanbul-lib-instrument: 5.2.1(supports-color@10.2.2) + istanbul-lib-instrument: 5.2.1(supports-color@11.0.0) istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 4.0.1(supports-color@8.1.1) + istanbul-lib-source-maps: 4.0.1(supports-color@11.0.0) istanbul-reports: 3.2.0 minimatch: 3.1.5 transitivePeerDependencies: @@ -18725,43 +19605,43 @@ snapshots: is-wsl: 2.2.0 which: 3.0.1 - karma-jasmine-html-reporter@2.2.0(jasmine-core@6.3.0)(karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6)))(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6)): + karma-jasmine-html-reporter@2.3.0(jasmine-core@6.3.0)(karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)))(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)): dependencies: jasmine-core: 6.3.0 - karma: 6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6) - karma-jasmine: 5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6)) + karma: 6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6) + karma-jasmine: 5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)) - karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6)): + karma-jasmine@5.1.0(karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)): dependencies: jasmine-core: 4.6.1 - karma: 6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6) + karma: 6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6) karma-sourcemap-loader@0.4.0: dependencies: graceful-fs: 4.2.11 - karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@10.2.2))(supports-color@10.2.2)(utf-8-validate@6.0.6): + karma@6.4.4(bufferutil@4.1.0)(debug@4.4.3(supports-color@11.0.0))(supports-color@11.0.0)(utf-8-validate@6.0.6): dependencies: '@colors/colors': 1.5.0 - body-parser: 1.20.6(supports-color@10.2.2) + body-parser: 1.20.6(supports-color@11.0.0) braces: 3.0.3 chokidar: 3.6.0 - connect: 3.7.0(supports-color@10.2.2) + connect: 3.7.0(supports-color@11.0.0) di: 0.0.1 dom-serialize: 2.2.1 glob: 7.2.3 graceful-fs: 4.2.11 - http-proxy: 1.18.1(debug@4.4.3(supports-color@10.2.2)) + http-proxy: 1.18.1(debug@4.4.3(supports-color@11.0.0)) isbinaryfile: 4.0.10 lodash: 4.18.1 - log4js: 6.9.1(supports-color@8.1.1) + log4js: 6.9.1(supports-color@11.0.0) mime: 2.6.0 minimatch: 3.1.5 mkdirp: 0.5.6 qjobs: 1.2.0 range-parser: 1.3.0 rimraf: 3.0.2 - socket.io: 4.8.3(bufferutil@4.1.0)(supports-color@8.1.1)(utf-8-validate@6.0.6) + socket.io: 4.8.3(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6) source-map: 0.6.1 tmp: 0.2.7 ua-parser-js: 0.7.41 @@ -18798,18 +19678,20 @@ snapshots: lead@4.0.0: {} - less@4.6.7: + less@4.9.0(supports-color@11.0.0): dependencies: copy-anything: 3.0.5 parse-node-version: 1.0.1 optionalDependencies: errno: 0.1.8 graceful-fs: 4.2.11 - image-size: 0.5.5 make-dir: 5.1.0 mime: 1.6.0 needle: 3.5.0 + probe-image-size: 7.4.0(supports-color@11.0.0) source-map: 0.6.1 + transitivePeerDependencies: + - supports-color leven@3.1.0: {} @@ -18829,58 +19711,58 @@ snapshots: findup-sync: 5.0.0 fined: 2.0.0 flagged-respawn: 2.0.0 - is-plain-object: 5.0.0 + is-plain-object: 5.1.0 rechoir: 0.8.0 resolve: 1.22.12 - lightningcss-android-arm64@1.32.0: + lightningcss-android-arm64@1.33.0: optional: true - lightningcss-darwin-arm64@1.32.0: + lightningcss-darwin-arm64@1.33.0: optional: true - lightningcss-darwin-x64@1.32.0: + lightningcss-darwin-x64@1.33.0: optional: true - lightningcss-freebsd-x64@1.32.0: + lightningcss-freebsd-x64@1.33.0: optional: true - lightningcss-linux-arm-gnueabihf@1.32.0: + lightningcss-linux-arm-gnueabihf@1.33.0: optional: true - lightningcss-linux-arm64-gnu@1.32.0: + lightningcss-linux-arm64-gnu@1.33.0: optional: true - lightningcss-linux-arm64-musl@1.32.0: + lightningcss-linux-arm64-musl@1.33.0: optional: true - lightningcss-linux-x64-gnu@1.32.0: + lightningcss-linux-x64-gnu@1.33.0: optional: true - lightningcss-linux-x64-musl@1.32.0: + lightningcss-linux-x64-musl@1.33.0: optional: true - lightningcss-win32-arm64-msvc@1.32.0: + lightningcss-win32-arm64-msvc@1.33.0: optional: true - lightningcss-win32-x64-msvc@1.32.0: + lightningcss-win32-x64-msvc@1.33.0: optional: true - lightningcss@1.32.0: + lightningcss@1.33.0: dependencies: detect-libc: 2.1.2 optionalDependencies: - lightningcss-android-arm64: 1.32.0 - lightningcss-darwin-arm64: 1.32.0 - lightningcss-darwin-x64: 1.32.0 - lightningcss-freebsd-x64: 1.32.0 - lightningcss-linux-arm-gnueabihf: 1.32.0 - lightningcss-linux-arm64-gnu: 1.32.0 - lightningcss-linux-arm64-musl: 1.32.0 - lightningcss-linux-x64-gnu: 1.32.0 - lightningcss-linux-x64-musl: 1.32.0 - lightningcss-win32-arm64-msvc: 1.32.0 - lightningcss-win32-x64-msvc: 1.32.0 + lightningcss-android-arm64: 1.33.0 + lightningcss-darwin-arm64: 1.33.0 + lightningcss-darwin-x64: 1.33.0 + lightningcss-freebsd-x64: 1.33.0 + lightningcss-linux-arm-gnueabihf: 1.33.0 + lightningcss-linux-arm64-gnu: 1.33.0 + lightningcss-linux-arm64-musl: 1.33.0 + lightningcss-linux-x64-gnu: 1.33.0 + lightningcss-linux-x64-musl: 1.33.0 + lightningcss-win32-arm64-msvc: 1.33.0 + lightningcss-win32-x64-msvc: 1.33.0 lilconfig@3.1.3: {} @@ -18890,13 +19772,11 @@ snapshots: dependencies: uc.micro: 2.1.0 - listr2@10.2.2: + listr2@11.1.0: dependencies: - cli-truncate: 5.2.0 - eventemitter3: 5.0.4 - log-update: 6.1.0 - rfdc: 1.4.1 - wrap-ansi: 10.0.0 + cli-truncate: 6.1.1 + log-update: 8.0.0 + wrap-ansi: 10.0.1 listr2@9.0.5: dependencies: @@ -18955,6 +19835,9 @@ snapshots: lodash.isstring@4.0.1: {} + lodash.merge@4.6.2: + optional: true + lodash.once@4.1.1: {} lodash.snakecase@4.1.1: {} @@ -18976,7 +19859,7 @@ snapshots: log-symbols@7.0.1: dependencies: is-unicode-supported: 2.1.0 - yoctocolors: 2.1.2 + yoctocolors: 2.2.0 log-update@6.1.0: dependencies: @@ -18986,13 +19869,22 @@ snapshots: strip-ansi: 7.2.0 wrap-ansi: 9.0.2 - log4js@6.9.1(supports-color@8.1.1): + log-update@8.0.0: + dependencies: + ansi-escapes: 7.3.0 + cli-cursor: 5.0.0 + slice-ansi: 9.0.0 + string-width: 8.2.2 + strip-ansi: 7.2.0 + wrap-ansi: 10.0.1 + + log4js@6.9.1(supports-color@11.0.0): dependencies: date-format: 4.0.14 - debug: 4.4.3(supports-color@8.1.1) - flatted: 3.4.2 + debug: 4.4.3(supports-color@11.0.0) + flatted: 3.4.4 rfdc: 1.4.1 - streamroller: 3.1.5(supports-color@8.1.1) + streamroller: 3.1.5(supports-color@11.0.0) transitivePeerDependencies: - supports-color @@ -19027,7 +19919,15 @@ snapshots: magic-string@0.30.21: dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/sourcemap-codec': 1.6.0 + + magic-string@1.2.3: + dependencies: + '@jridgewell/sourcemap-codec': 1.6.0 + + magic-string@1.4.1: + dependencies: + '@jridgewell/sourcemap-codec': 1.6.0 make-dir@3.1.0: dependencies: @@ -19048,19 +19948,19 @@ snapshots: map-cache@0.2.2: {} - markdown-it@14.3.0: + markdown-it@14.3.1: dependencies: argparse: 2.0.1 entities: 4.5.0 linkify-it: 5.0.2 - mdurl: 2.0.0 + mdurl: 2.1.0 punycode.js: 2.3.1 uc.micro: 2.1.0 marked-terminal@7.3.0(marked@13.0.3): dependencies: ansi-escapes: 7.3.0 - ansi-regex: 6.2.2 + ansi-regex: 6.3.0 chalk: 5.6.2 cli-highlight: 2.1.11 cli-table3: 0.6.5 @@ -19072,9 +19972,7 @@ snapshots: marked@16.4.2: {} - marked@18.0.5: {} - - marked@18.0.6: {} + marked@18.0.11: {} math-intrinsics@1.1.0: {} @@ -19082,7 +19980,7 @@ snapshots: dependencies: '@types/hast': 3.0.5 '@types/mdast': 4.0.4 - '@ungap/structured-clone': 1.3.3 + '@ungap/structured-clone': 1.4.0 devlop: 1.1.0 micromark-util-sanitize-uri: 2.0.1 trim-lines: 3.0.1 @@ -19092,11 +19990,11 @@ snapshots: mdn-data@2.27.1: {} - mdurl@2.0.0: {} + mdurl@2.1.0: {} media-typer@0.3.0: {} - media-typer@1.1.0: {} + media-typer@1.1.1: {} memoizeasync@1.1.0: dependencies: @@ -19113,29 +20011,30 @@ snapshots: merge2@1.4.1: {} - mermaid@11.16.0: + mermaid@11.17.2: dependencies: '@braintree/sanitize-url': 7.1.2 '@iconify/utils': 3.1.4 - '@mermaid-js/parser': 1.2.0 + '@mermaid-js/parser': 1.2.1 '@types/d3': 7.4.3 '@upsetjs/venn.js': 2.0.0 - cytoscape: 3.34.0 - cytoscape-cose-bilkent: 4.1.0(cytoscape@3.34.0) - cytoscape-fcose: 2.2.0(cytoscape@3.34.0) + cytoscape: 3.34.2 + cytoscape-cose-bilkent: 4.1.0(cytoscape@3.34.2) + cytoscape-fcose: 2.2.0(cytoscape@3.34.2) d3: 7.9.0 d3-sankey: 0.12.3 dagre-d3-es: 7.0.14 - dayjs: 1.11.21 - dompurify: 3.4.12 - es-toolkit: 1.49.0 + dayjs: 1.11.23 + dompurify: 3.4.14 + es-toolkit: 1.52.0 + fastdom: 1.0.12 katex: 0.16.47 khroma: 2.1.0 marked: 16.4.2 roughjs: 4.6.6 stylis: 4.4.0 ts-dedent: 2.3.0 - uuid: 14.0.1 + uuid: 14.0.2 methods@1.1.2: {} @@ -19184,29 +20083,29 @@ snapshots: mimic-response@3.1.0: optional: true - minimatch@10.2.5: + minimatch@10.2.6: dependencies: - brace-expansion: 5.0.7 + brace-expansion: 5.0.9 minimatch@3.1.5: dependencies: - brace-expansion: 1.1.16 + brace-expansion: 1.1.18 minimatch@5.1.9: dependencies: - brace-expansion: 2.1.2 + brace-expansion: 2.1.4 minimatch@6.2.3: dependencies: - brace-expansion: 2.1.2 + brace-expansion: 2.1.4 minimatch@7.4.9: dependencies: - brace-expansion: 2.1.2 + brace-expansion: 2.1.4 minimatch@9.0.9: dependencies: - brace-expansion: 2.1.2 + brace-expansion: 2.1.4 minimist@1.2.8: {} @@ -19225,29 +20124,24 @@ snapshots: mkdirp@1.0.4: {} - mocha@11.7.6: + mocha@12.0.0: dependencies: browser-stdout: 1.3.1 - chokidar: 4.0.3 + chokidar: 5.0.0 debug: 4.4.3(supports-color@8.1.1) - diff: 7.0.0 - escape-string-regexp: 4.0.0 + diff: 9.0.0 find-up: 5.0.0 - glob: 10.5.0 - he: 1.2.0 + glob: 13.0.6 is-path-inside: 3.0.3 - js-yaml: 4.3.0 - log-symbols: 4.1.0 - minimatch: 9.0.9 + is-unicode-supported: 0.1.0 + js-yaml: 5.4.1 + minimatch: 10.2.6 ms: 2.1.3 picocolors: 1.1.1 - serialize-javascript: 6.0.2 - strip-json-comments: 3.1.1 + serialize-javascript: 7.1.1 + strip-json-comments: 5.0.3 supports-color: 8.1.1 - workerpool: 9.3.4 - yargs: 17.7.3 - yargs-parser: 21.1.1 - yargs-unparser: 2.0.0 + workerpool: 10.0.3 mock-require@3.0.3: dependencies: @@ -19256,10 +20150,10 @@ snapshots: moo@0.5.3: {} - morgan@1.11.0(supports-color@10.2.2): + morgan@1.12.0(supports-color@11.0.0): dependencies: basic-auth: 2.0.1 - debug: 2.6.9(supports-color@10.2.2) + debug: 2.6.9(supports-color@11.0.0) depd: 2.0.0 on-finished: 2.4.1 on-headers: 1.1.0 @@ -19295,7 +20189,7 @@ snapshots: dependencies: array-differ: 4.0.0 array-union: 3.0.1 - minimatch: 10.2.5 + minimatch: 10.2.6 mute-stdout@2.0.0: {} @@ -19314,7 +20208,7 @@ snapshots: nan@2.28.0: optional: true - nanoid@3.3.16: {} + nanoid@3.3.18: {} napi-build-utils@2.0.0: optional: true @@ -19330,72 +20224,87 @@ snapshots: railroad-diagrams: 1.0.0 randexp: 0.4.6 + needle@2.9.1(supports-color@11.0.0): + dependencies: + debug: 3.2.7(supports-color@11.0.0) + iconv-lite: 0.4.24 + sax: 1.6.1 + transitivePeerDependencies: + - supports-color + optional: true + needle@3.5.0: dependencies: iconv-lite: 0.6.3 - sax: 1.6.0 + sax: 1.6.1 optional: true negotiator@0.6.3: {} negotiator@0.6.4: {} - negotiator@1.0.0: {} + negotiator@1.1.0: + dependencies: + content-type: 2.1.0 neo-async@2.6.2: {} netmask@2.1.1: {} - ng-packagr@22.1.0-next.3(@angular/compiler-cli@packages+compiler-cli)(tailwindcss@3.4.19(tsx@4.23.1)(yaml@2.9.0))(tslib@2.8.1)(typescript@6.0.3): + ng-packagr@22.2.0-next.5(@angular/compiler-cli@packages+compiler-cli)(supports-color@11.0.0)(tailwindcss@3.4.19(tsx@4.23.13)(yaml@2.9.1))(tslib@2.8.1)(typescript@6.0.3): dependencies: '@ampproject/remapping': 2.3.0 '@angular/compiler-cli': link:packages/compiler-cli - '@rollup/plugin-json': 6.1.0(rollup@4.62.2) - '@rollup/wasm-node': 4.62.2 ajv: 8.20.0 - browserslist: 4.28.6 + browserslist: 4.28.8 chokidar: 5.0.0 commander: 15.0.0 dependency-graph: 1.0.0 - esbuild: 0.28.1 + esbuild: 0.28.2 find-cache-directory: 6.0.0 injection-js: 2.6.1 jsonc-parser: 3.3.1 - less: 4.6.7 + less: 4.9.0(supports-color@11.0.0) ora: 9.4.1 - piscina: 5.2.0 - postcss: 8.5.20 - rollup-plugin-dts: 6.4.1(rollup@4.62.2)(typescript@6.0.3) + postcss: 8.5.26 + rolldown: 1.2.8 + rolldown-plugin-dts: 0.28.4(rolldown@1.2.8)(typescript@6.0.3) rxjs: 7.8.2 - sass: 1.101.0 + sass: 1.104.1 + sass-embedded: 1.104.1 tinyglobby: 0.2.17 tslib: 2.8.1 typescript: 6.0.3 optionalDependencies: - rollup: 4.62.2 - tailwindcss: 3.4.19(tsx@4.23.1)(yaml@2.9.0) + tailwindcss: 3.4.19(tsx@4.23.13)(yaml@2.9.1) + transitivePeerDependencies: + - '@typescript/native-preview' + - '@volar/typescript' + - oxc-resolver + - supports-color + - vue-tsc - ngx-flamegraph@0.1.1(@angular/common@packages+common)(@angular/core@packages+core): + ngx-flamegraph@0.2.0(@angular/common@packages+common)(@angular/core@packages+core): dependencies: '@angular/common': link:packages/common '@angular/core': link:packages/core tslib: 2.8.1 - ngx-progressbar@14.0.0(@angular/cdk@22.1.0-next.4(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2))(@angular/common@packages+common)(@angular/core@packages+core)(rxjs@7.8.2): + ngx-progressbar@14.0.0(@angular/cdk@22.2.0-next.5(@angular/common@packages+common)(@angular/core@packages+core)(@angular/forms@packages+forms)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2))(@angular/common@packages+common)(@angular/core@packages+core)(rxjs@7.8.2): dependencies: - '@angular/cdk': 22.1.0-next.4(@angular/common@packages+common)(@angular/core@packages+core)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2) + '@angular/cdk': 22.2.0-next.5(@angular/common@packages+common)(@angular/core@packages+core)(@angular/forms@packages+forms)(@angular/platform-browser@packages+platform-browser)(rxjs@7.8.2) '@angular/common': link:packages/common '@angular/core': link:packages/core rxjs: 7.8.2 tslib: 2.8.1 - nock@14.0.16: + nock@14.0.17: dependencies: '@mswjs/interceptors': 0.41.9 json-stringify-safe: 5.0.1 propagate: 2.0.1 - node-abi@3.94.0: + node-abi@3.96.0: dependencies: semver: 7.8.5 optional: true @@ -19406,8 +20315,7 @@ snapshots: node-addon-api@6.1.0: optional: true - node-addon-api@7.1.1: - optional: true + node-addon-api@7.1.1: {} node-domexception@1.0.0: {} @@ -19437,7 +20345,7 @@ snapshots: node-gyp-build@4.8.4: {} - node-gyp@13.0.1: + node-gyp@13.0.2: dependencies: env-paths: 2.2.1 exponential-backoff: 3.1.3 @@ -19445,20 +20353,20 @@ snapshots: nopt: 10.0.1 proc-log: 7.0.0 semver: 7.8.5 - tar: 7.5.20 + tar: 7.5.22 tinyglobby: 0.2.17 - undici: 8.7.0 + undici: 8.10.0 which: 7.0.0 optional: true node-int64@0.4.0: {} - node-releases@2.0.51: {} + node-releases@2.0.54: {} node-sarif-builder@3.4.0: dependencies: '@types/sarif': 2.1.7 - fs-extra: 11.3.6 + fs-extra: 11.4.0 nopt@10.0.1: dependencies: @@ -19496,7 +20404,11 @@ snapshots: dependencies: boolbase: 1.0.0 - nwsapi@2.2.24: {} + nth-check@3.0.1: + dependencies: + boolbase: 2.0.0 + + nwsapi@2.2.27: {} oauth-sign@0.9.0: {} @@ -19528,7 +20440,7 @@ snapshots: dependencies: isobject: 3.0.1 - obug@2.1.3: {} + obug@2.1.4: {} on-finished@2.3.0: dependencies: @@ -19566,7 +20478,7 @@ snapshots: open@10.2.0: dependencies: - default-browser: 5.5.0 + default-browser: 5.5.1 define-lazy-prop: 3.0.0 is-inside-container: 1.0.0 wsl-utils: 0.1.0 @@ -19577,7 +20489,7 @@ snapshots: openapi3-ts@3.2.0: dependencies: - yaml: 2.9.0 + yaml: 2.9.1 opener@1.5.2: {} @@ -19625,12 +20537,37 @@ snapshots: outvariant@1.4.3: {} - own-keys@1.0.1: + own-keys@1.0.2: dependencies: + call-bound: 1.0.4 get-intrinsic: 1.3.0 object-keys: 1.1.1 safe-push-apply: 1.0.0 + oxc-parser@0.149.0: + dependencies: + '@oxc-project/types': 0.149.0 + optionalDependencies: + '@oxc-parser/binding-android-arm-eabi': 0.149.0 + '@oxc-parser/binding-android-arm64': 0.149.0 + '@oxc-parser/binding-darwin-arm64': 0.149.0 + '@oxc-parser/binding-darwin-x64': 0.149.0 + '@oxc-parser/binding-freebsd-x64': 0.149.0 + '@oxc-parser/binding-linux-arm-gnueabihf': 0.149.0 + '@oxc-parser/binding-linux-arm-musleabihf': 0.149.0 + '@oxc-parser/binding-linux-arm64-gnu': 0.149.0 + '@oxc-parser/binding-linux-arm64-musl': 0.149.0 + '@oxc-parser/binding-linux-ppc64-gnu': 0.149.0 + '@oxc-parser/binding-linux-riscv64-gnu': 0.149.0 + '@oxc-parser/binding-linux-riscv64-musl': 0.149.0 + '@oxc-parser/binding-linux-s390x-gnu': 0.149.0 + '@oxc-parser/binding-linux-x64-gnu': 0.149.0 + '@oxc-parser/binding-linux-x64-musl': 0.149.0 + '@oxc-parser/binding-openharmony-arm64': 0.149.0 + '@oxc-parser/binding-win32-arm64-msvc': 0.149.0 + '@oxc-parser/binding-win32-ia32-msvc': 0.149.0 + '@oxc-parser/binding-win32-x64-msvc': 0.149.0 + p-defer@3.0.0: {} p-finally@1.0.0: {} @@ -19651,7 +20588,7 @@ snapshots: dependencies: p-limit: 3.1.0 - p-map@7.0.5: {} + p-map@7.0.7: {} p-queue@6.6.2: dependencies: @@ -19663,7 +20600,7 @@ snapshots: '@types/retry': 0.12.0 retry: 0.13.1 - p-throttle@7.0.0: {} + p-throttle@8.1.0: {} p-timeout@3.2.0: dependencies: @@ -19671,16 +20608,16 @@ snapshots: p-try@2.2.0: {} - pac-proxy-agent@7.2.0(supports-color@10.2.2): + pac-proxy-agent@7.2.0(supports-color@11.0.0): dependencies: '@tootallnate/quickjs-emscripten': 0.23.0 agent-base: 7.1.4 - debug: 4.4.3(supports-color@8.1.1) - get-uri: 6.0.5(supports-color@8.1.1) - http-proxy-agent: 7.0.2(supports-color@10.2.2) - https-proxy-agent: 7.0.6(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) + get-uri: 6.0.5(supports-color@11.0.0) + http-proxy-agent: 7.0.2(supports-color@11.0.0) + https-proxy-agent: 7.0.6(supports-color@11.0.0) pac-resolver: 7.0.1 - socks-proxy-agent: 8.0.5(supports-color@10.2.2) + socks-proxy-agent: 8.0.5(supports-color@11.0.0) transitivePeerDependencies: - supports-color @@ -19691,7 +20628,7 @@ snapshots: package-json-from-dist@1.0.1: {} - package-manager-detector@1.7.0: {} + package-manager-detector@1.8.0: {} pako@1.0.11: {} @@ -19799,8 +20736,6 @@ snapshots: path-type@6.0.0: {} - pathe@2.0.3: {} - pegjs@0.10.0: {} pend@1.2.0: {} @@ -19816,11 +20751,11 @@ snapshots: pg-int8@1.0.1: {} - pg-pool@3.14.0(pg@8.22.0): + pg-pool@3.14.0(pg@8.23.0): dependencies: - pg: 8.22.0 + pg: 8.23.0 - pg-protocol@1.15.0: {} + pg-protocol@1.16.0: {} pg-types@2.2.0: dependencies: @@ -19830,11 +20765,11 @@ snapshots: postgres-date: 1.0.7 postgres-interval: 1.2.0 - pg@8.22.0: + pg@8.23.0: dependencies: pg-connection-string: 2.14.0 - pg-pool: 3.14.0(pg@8.22.0) - pg-protocol: 1.15.0 + pg-pool: 3.14.0(pg@8.23.0) + pg-protocol: 1.16.0 pg-types: 2.2.0 pgpass: 1.0.5 optionalDependencies: @@ -19848,7 +20783,7 @@ snapshots: picomatch@2.3.2: {} - picomatch@4.0.5: {} + picomatch@4.0.7: {} pify@2.3.0: {} @@ -19860,7 +20795,7 @@ snapshots: pirates@4.0.7: {} - piscina@5.2.0: + piscina@5.3.2: optionalDependencies: '@napi-rs/nice': 1.1.1 @@ -19874,7 +20809,7 @@ snapshots: dependencies: find-up-simple: 1.0.1 - playwright-core@1.61.1: {} + playwright-core@1.62.1: {} plugin-error@2.0.1: dependencies: @@ -19891,53 +20826,46 @@ snapshots: path-data-parser: 0.1.0 points-on-curve: 0.2.0 - portfinder@1.0.38(supports-color@10.2.2): - dependencies: - async: 3.2.6 - debug: 4.4.3(supports-color@10.2.2) - transitivePeerDependencies: - - supports-color - - portfinder@1.0.38(supports-color@8.1.1): + portfinder@1.0.38(supports-color@11.0.0): dependencies: async: 3.2.6 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3(supports-color@11.0.0) transitivePeerDependencies: - supports-color possible-typed-array-names@1.1.0: {} - postcss-import@15.1.0(postcss@8.5.20): + postcss-import@15.1.0(postcss@8.5.26): dependencies: - postcss: 8.5.20 + postcss: 8.5.26 postcss-value-parser: 4.2.0 - read-cache: 1.0.0 + read-cache: 1.0.2 resolve: 1.22.12 - postcss-js@4.1.0(postcss@8.5.20): + postcss-js@4.1.0(postcss@8.5.26): dependencies: camelcase-css: 2.0.1 - postcss: 8.5.20 + postcss: 8.5.26 - postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.20)(tsx@4.23.1)(yaml@2.9.0): + postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.26)(tsx@4.23.13)(yaml@2.9.1): dependencies: lilconfig: 3.1.3 optionalDependencies: jiti: 1.21.7 - postcss: 8.5.20 - tsx: 4.23.1 - yaml: 2.9.0 + postcss: 8.5.26 + tsx: 4.23.13 + yaml: 2.9.1 postcss-media-query-parser@0.2.3: {} - postcss-nested@6.2.0(postcss@8.5.20): + postcss-nested@6.2.0(postcss@8.5.26): dependencies: - postcss: 8.5.20 + postcss: 8.5.26 postcss-selector-parser: 6.1.4 - postcss-safe-parser@7.0.1(postcss@8.5.20): + postcss-safe-parser@7.0.1(postcss@8.5.26): dependencies: - postcss: 8.5.20 + postcss: 8.5.26 postcss-selector-parser@6.1.4: dependencies: @@ -19946,9 +20874,9 @@ snapshots: postcss-value-parser@4.2.0: {} - postcss@8.5.20: + postcss@8.5.26: dependencies: - nanoid: 3.3.16 + nanoid: 3.3.18 picocolors: 1.1.1 source-map-js: 1.2.1 @@ -19962,13 +20890,13 @@ snapshots: dependencies: xtend: 4.0.2 - preact-render-to-string@6.7.0(preact@10.29.7): + preact-render-to-string@6.7.0(preact@10.29.8): dependencies: - preact: 10.29.7(preact-render-to-string@6.7.0) + preact: 10.29.8(preact-render-to-string@6.7.0) - preact@10.29.7(preact-render-to-string@6.7.0): + preact@10.29.8(preact-render-to-string@6.7.0): optionalDependencies: - preact-render-to-string: 6.7.0(preact@10.29.7) + preact-render-to-string: 6.7.0(preact@10.29.8) prebuild-install@7.1.3: dependencies: @@ -19978,7 +20906,7 @@ snapshots: minimist: 1.2.8 mkdirp-classic: 0.5.3 napi-build-utils: 2.0.0 - node-abi: 3.94.0 + node-abi: 3.96.0 pump: 3.0.4 rc: 1.2.8 simple-get: 4.0.1 @@ -19986,7 +20914,7 @@ snapshots: tunnel-agent: 0.6.0 optional: true - prettier@3.9.5: {} + prettier@3.9.6: {} pretty-bytes@5.6.0: {} @@ -19995,7 +20923,16 @@ snapshots: '@jest/schemas': 30.4.1 ansi-styles: 5.2.0 react-is-18: react-is@18.3.1 - react-is-19: react-is@19.2.7 + react-is-19: react-is@19.2.8 + + probe-image-size@7.4.0(supports-color@11.0.0): + dependencies: + lodash.merge: 4.6.2 + needle: 2.9.1(supports-color@11.0.0) + stream-parser: 0.3.1(supports-color@11.0.0) + transitivePeerDependencies: + - supports-color + optional: true proc-log@7.0.0: {} @@ -20015,9 +20952,9 @@ snapshots: proto3-json-serializer@3.0.4: dependencies: - protobufjs: 7.6.5 + protobufjs: 7.6.6 - protobufjs@7.6.5: + protobufjs@7.6.6: dependencies: '@protobufjs/aspromise': 1.1.2 '@protobufjs/base64': 1.1.2 @@ -20031,18 +20968,18 @@ snapshots: '@types/node': 24.13.3 long: 5.3.2 - protractor@7.0.0(supports-color@10.2.2): + protractor@7.0.0(supports-color@11.0.0): dependencies: '@types/q': 0.0.32 '@types/selenium-webdriver': 3.0.7 blocking-proxy: 1.0.1 - browserstack: 1.6.1(supports-color@8.1.1) + browserstack: 1.6.1(supports-color@11.0.0) chalk: 1.1.3 glob: 7.2.3 jasmine: 2.8.0 jasminewd2: 2.2.0 q: 1.4.1 - saucelabs: 1.5.0(supports-color@10.2.2) + saucelabs: 1.5.0(supports-color@11.0.0) selenium-webdriver: 3.6.0 source-map-support: 0.4.18 webdriver-js-extender: 2.1.0 @@ -20058,16 +20995,16 @@ snapshots: proxy-agent-negotiate@1.1.0: {} - proxy-agent@6.5.0(supports-color@10.2.2): + proxy-agent@6.5.0(supports-color@11.0.0): dependencies: agent-base: 7.1.4 - debug: 4.4.3(supports-color@8.1.1) - http-proxy-agent: 7.0.2(supports-color@10.2.2) - https-proxy-agent: 7.0.6(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) + http-proxy-agent: 7.0.2(supports-color@11.0.0) + https-proxy-agent: 7.0.6(supports-color@11.0.0) lru-cache: 7.18.3 - pac-proxy-agent: 7.2.0(supports-color@10.2.2) + pac-proxy-agent: 7.2.0(supports-color@11.0.0) proxy-from-env: 1.1.0 - socks-proxy-agent: 8.0.5(supports-color@10.2.2) + socks-proxy-agent: 8.0.5(supports-color@11.0.0) transitivePeerDependencies: - supports-color @@ -20119,6 +21056,11 @@ snapshots: es-define-property: 1.0.1 side-channel: 1.1.1 + qs@6.16.0: + dependencies: + es-define-property: 1.0.1 + side-channel: 1.1.1 + qs@6.5.5: {} queue-microtask@1.2.3: {} @@ -20130,10 +21072,6 @@ snapshots: discontinuous-range: 1.0.0 ret: 0.1.15 - randombytes@2.1.0: - dependencies: - safe-buffer: 5.2.1 - range-parser@1.2.1: {} range-parser@1.3.0: {} @@ -20152,10 +21090,10 @@ snapshots: iconv-lite: 0.7.3 unpipe: 1.0.0 - rc-config-loader@4.1.4(supports-color@10.2.2): + rc-config-loader@4.1.4(supports-color@11.0.0): dependencies: - debug: 4.4.3(supports-color@10.2.2) - js-yaml: 4.3.0 + debug: 4.4.3(supports-color@11.0.0) + js-yaml: 4.3.2 json5: 2.2.3 require-from-string: 2.0.2 transitivePeerDependencies: @@ -20168,22 +21106,20 @@ snapshots: minimist: 1.2.8 strip-json-comments: 2.0.1 - re2@1.26.0: + re2@1.26.1: dependencies: - install-artifact-from-github: 1.7.0 + install-artifact-from-github: 1.8.0 nan: 2.28.0 - node-gyp: 13.0.1 + node-gyp: 13.0.2 optional: true - re2js@0.4.3: {} + re2js@2.8.6: {} react-is@18.3.1: {} - react-is@19.2.7: {} + react-is@19.2.8: {} - read-cache@1.0.0: - dependencies: - pify: 2.3.0 + read-cache@1.0.2: {} read-package-up@11.0.0: dependencies: @@ -20235,9 +21171,7 @@ snapshots: dependencies: picomatch: 2.3.2 - readdirp@4.1.2: {} - - readdirp@5.0.0: {} + readdirp@5.1.1: {} rechoir@0.8.0: dependencies: @@ -20360,10 +21294,10 @@ snapshots: ret@0.1.15: {} - retry-request@8.0.3(supports-color@10.2.2): + retry-request@8.0.4(supports-color@11.0.0): dependencies: extend: 3.0.2 - teeny-request: 10.1.3(supports-color@10.2.2) + teeny-request: 10.1.4(supports-color@11.0.0) transitivePeerDependencies: - supports-color @@ -20387,74 +21321,89 @@ snapshots: robust-predicates@3.0.3: {} - rolldown@1.1.5: + rolldown-plugin-dts@0.28.4(rolldown@1.2.8)(typescript@6.0.3): dependencies: - '@oxc-project/types': 0.139.0 + dts-resolver: 3.0.0 + get-tsconfig: 5.0.0-beta.6 + obug: 2.1.4 + rolldown: 1.2.8 + yuku-ast: 0.9.3 + yuku-codegen: 0.9.3 + yuku-parser: 0.9.3 + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - oxc-resolver + + rolldown@1.2.8: + dependencies: + '@oxc-project/types': 0.149.0 '@rolldown/pluginutils': 1.0.1 optionalDependencies: - '@rolldown/binding-android-arm64': 1.1.5 - '@rolldown/binding-darwin-arm64': 1.1.5 - '@rolldown/binding-darwin-x64': 1.1.5 - '@rolldown/binding-freebsd-x64': 1.1.5 - '@rolldown/binding-linux-arm-gnueabihf': 1.1.5 - '@rolldown/binding-linux-arm64-gnu': 1.1.5 - '@rolldown/binding-linux-arm64-musl': 1.1.5 - '@rolldown/binding-linux-ppc64-gnu': 1.1.5 - '@rolldown/binding-linux-s390x-gnu': 1.1.5 - '@rolldown/binding-linux-x64-gnu': 1.1.5 - '@rolldown/binding-linux-x64-musl': 1.1.5 - '@rolldown/binding-openharmony-arm64': 1.1.5 - '@rolldown/binding-wasm32-wasi': 1.1.5 - '@rolldown/binding-win32-arm64-msvc': 1.1.5 - '@rolldown/binding-win32-x64-msvc': 1.1.5 - - rollup-plugin-dts@6.4.1(rollup@4.62.2)(typescript@6.0.3): + '@rolldown/binding-android-arm-eabi': 1.2.8 + '@rolldown/binding-android-arm64': 1.2.8 + '@rolldown/binding-darwin-arm64': 1.2.8 + '@rolldown/binding-darwin-x64': 1.2.8 + '@rolldown/binding-freebsd-x64': 1.2.8 + '@rolldown/binding-linux-arm-gnueabihf': 1.2.8 + '@rolldown/binding-linux-arm64-gnu': 1.2.8 + '@rolldown/binding-linux-arm64-musl': 1.2.8 + '@rolldown/binding-linux-ppc64-gnu': 1.2.8 + '@rolldown/binding-linux-s390x-gnu': 1.2.8 + '@rolldown/binding-linux-x64-gnu': 1.2.8 + '@rolldown/binding-linux-x64-musl': 1.2.8 + '@rolldown/binding-openharmony-arm64': 1.2.8 + '@rolldown/binding-win32-arm64-msvc': 1.2.8 + '@rolldown/binding-win32-x64-msvc': 1.2.8 + + rollup-plugin-dts@6.5.1(rollup@4.63.0)(typescript@6.0.3): dependencies: '@jridgewell/remapping': 2.3.5 - '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/sourcemap-codec': 1.6.0 convert-source-map: 2.0.0 magic-string: 0.30.21 - rollup: 4.62.2 + rollup: 4.63.0 typescript: 6.0.3 optionalDependencies: - '@babel/code-frame': 7.29.7 + '@babel/code-frame': 8.0.0 - rollup-plugin-sourcemaps2@0.5.8(@types/node@20.19.43)(rollup@4.62.2): + rollup-plugin-sourcemaps2@0.5.8(@types/node@20.19.43)(rollup@4.63.0): dependencies: - '@rollup/pluginutils': 5.4.0(rollup@4.62.2) - rollup: 4.62.2 + '@rollup/pluginutils': 5.4.0(rollup@4.63.0) + rollup: 4.63.0 optionalDependencies: '@types/node': 20.19.43 - rollup@4.62.2: + rollup@4.63.0: dependencies: '@types/estree': 1.0.9 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.62.2 - '@rollup/rollup-android-arm64': 4.62.2 - '@rollup/rollup-darwin-arm64': 4.62.2 - '@rollup/rollup-darwin-x64': 4.62.2 - '@rollup/rollup-freebsd-arm64': 4.62.2 - '@rollup/rollup-freebsd-x64': 4.62.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.62.2 - '@rollup/rollup-linux-arm-musleabihf': 4.62.2 - '@rollup/rollup-linux-arm64-gnu': 4.62.2 - '@rollup/rollup-linux-arm64-musl': 4.62.2 - '@rollup/rollup-linux-loong64-gnu': 4.62.2 - '@rollup/rollup-linux-loong64-musl': 4.62.2 - '@rollup/rollup-linux-ppc64-gnu': 4.62.2 - '@rollup/rollup-linux-ppc64-musl': 4.62.2 - '@rollup/rollup-linux-riscv64-gnu': 4.62.2 - '@rollup/rollup-linux-riscv64-musl': 4.62.2 - '@rollup/rollup-linux-s390x-gnu': 4.62.2 - '@rollup/rollup-linux-x64-gnu': 4.62.2 - '@rollup/rollup-linux-x64-musl': 4.62.2 - '@rollup/rollup-openbsd-x64': 4.62.2 - '@rollup/rollup-openharmony-arm64': 4.62.2 - '@rollup/rollup-win32-arm64-msvc': 4.62.2 - '@rollup/rollup-win32-ia32-msvc': 4.62.2 - '@rollup/rollup-win32-x64-gnu': 4.62.2 - '@rollup/rollup-win32-x64-msvc': 4.62.2 + '@napi-rs/lzma-linux-x64-gnu': 1.5.1 + '@rollup/rollup-android-arm-eabi': 4.63.0 + '@rollup/rollup-android-arm64': 4.63.0 + '@rollup/rollup-darwin-arm64': 4.63.0 + '@rollup/rollup-darwin-x64': 4.63.0 + '@rollup/rollup-freebsd-arm64': 4.63.0 + '@rollup/rollup-freebsd-x64': 4.63.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.63.0 + '@rollup/rollup-linux-arm-musleabihf': 4.63.0 + '@rollup/rollup-linux-arm64-gnu': 4.63.0 + '@rollup/rollup-linux-arm64-musl': 4.63.0 + '@rollup/rollup-linux-loong64-gnu': 4.63.0 + '@rollup/rollup-linux-loong64-musl': 4.63.0 + '@rollup/rollup-linux-ppc64-gnu': 4.63.0 + '@rollup/rollup-linux-ppc64-musl': 4.63.0 + '@rollup/rollup-linux-riscv64-gnu': 4.63.0 + '@rollup/rollup-linux-riscv64-musl': 4.63.0 + '@rollup/rollup-linux-s390x-gnu': 4.63.0 + '@rollup/rollup-linux-x64-gnu': 4.63.0 + '@rollup/rollup-linux-x64-musl': 4.63.0 + '@rollup/rollup-openbsd-x64': 4.63.0 + '@rollup/rollup-openharmony-arm64': 4.63.0 + '@rollup/rollup-win32-arm64-msvc': 4.63.0 + '@rollup/rollup-win32-ia32-msvc': 4.63.0 + '@rollup/rollup-win32-x64-gnu': 4.63.0 + '@rollup/rollup-win32-x64-msvc': 4.63.0 fsevents: 2.3.3 roughjs@4.6.6: @@ -20464,9 +21413,9 @@ snapshots: points-on-curve: 0.2.0 points-on-path: 0.2.1 - router@2.2.0(supports-color@10.2.2): + router@2.2.0(supports-color@11.0.0): dependencies: - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) depd: 2.0.0 is-promise: 4.0.0 parseurl: 1.3.3 @@ -20515,33 +21464,215 @@ snapshots: safer-buffer@2.1.2: {} - sass@1.101.0: + sass-embedded-all-unknown@1.104.0: + dependencies: + sass: 1.104.0 + optional: true + + sass-embedded-all-unknown@1.104.1: + dependencies: + sass: 1.104.1 + optional: true + + sass-embedded-android-arm64@1.104.0: + optional: true + + sass-embedded-android-arm64@1.104.1: + optional: true + + sass-embedded-android-arm@1.104.0: + optional: true + + sass-embedded-android-arm@1.104.1: + optional: true + + sass-embedded-android-riscv64@1.104.0: + optional: true + + sass-embedded-android-riscv64@1.104.1: + optional: true + + sass-embedded-android-x64@1.104.0: + optional: true + + sass-embedded-android-x64@1.104.1: + optional: true + + sass-embedded-darwin-arm64@1.104.0: + optional: true + + sass-embedded-darwin-arm64@1.104.1: + optional: true + + sass-embedded-darwin-x64@1.104.0: + optional: true + + sass-embedded-darwin-x64@1.104.1: + optional: true + + sass-embedded-linux-arm64@1.104.0: + optional: true + + sass-embedded-linux-arm64@1.104.1: + optional: true + + sass-embedded-linux-arm@1.104.0: + optional: true + + sass-embedded-linux-arm@1.104.1: + optional: true + + sass-embedded-linux-musl-arm64@1.104.0: + optional: true + + sass-embedded-linux-musl-arm64@1.104.1: + optional: true + + sass-embedded-linux-musl-arm@1.104.0: + optional: true + + sass-embedded-linux-musl-arm@1.104.1: + optional: true + + sass-embedded-linux-musl-riscv64@1.104.0: + optional: true + + sass-embedded-linux-musl-riscv64@1.104.1: + optional: true + + sass-embedded-linux-musl-x64@1.104.0: + optional: true + + sass-embedded-linux-musl-x64@1.104.1: + optional: true + + sass-embedded-linux-riscv64@1.104.0: + optional: true + + sass-embedded-linux-riscv64@1.104.1: + optional: true + + sass-embedded-linux-x64@1.104.0: + optional: true + + sass-embedded-linux-x64@1.104.1: + optional: true + + sass-embedded-unknown-all@1.104.0: + dependencies: + sass: 1.104.0 + optional: true + + sass-embedded-unknown-all@1.104.1: + dependencies: + sass: 1.104.1 + optional: true + + sass-embedded-win32-arm64@1.104.0: + optional: true + + sass-embedded-win32-arm64@1.104.1: + optional: true + + sass-embedded-win32-x64@1.104.0: + optional: true + + sass-embedded-win32-x64@1.104.1: + optional: true + + sass-embedded@1.104.0: + dependencies: + '@bufbuild/protobuf': 2.14.1 + colorjs.io: 0.7.1 + immutable: 5.1.9 + rxjs: 7.8.2 + supports-color: 8.1.1 + sync-child-process: 1.0.2 + varint: 6.0.0 + optionalDependencies: + sass-embedded-all-unknown: 1.104.0 + sass-embedded-android-arm: 1.104.0 + sass-embedded-android-arm64: 1.104.0 + sass-embedded-android-riscv64: 1.104.0 + sass-embedded-android-x64: 1.104.0 + sass-embedded-darwin-arm64: 1.104.0 + sass-embedded-darwin-x64: 1.104.0 + sass-embedded-linux-arm: 1.104.0 + sass-embedded-linux-arm64: 1.104.0 + sass-embedded-linux-musl-arm: 1.104.0 + sass-embedded-linux-musl-arm64: 1.104.0 + sass-embedded-linux-musl-riscv64: 1.104.0 + sass-embedded-linux-musl-x64: 1.104.0 + sass-embedded-linux-riscv64: 1.104.0 + sass-embedded-linux-x64: 1.104.0 + sass-embedded-unknown-all: 1.104.0 + sass-embedded-win32-arm64: 1.104.0 + sass-embedded-win32-x64: 1.104.0 + + sass-embedded@1.104.1: + dependencies: + '@bufbuild/protobuf': 2.14.1 + colorjs.io: 0.7.1 + immutable: 5.1.9 + rxjs: 7.8.2 + supports-color: 8.1.1 + sync-child-process: 1.0.2 + varint: 6.0.0 + optionalDependencies: + sass-embedded-all-unknown: 1.104.1 + sass-embedded-android-arm: 1.104.1 + sass-embedded-android-arm64: 1.104.1 + sass-embedded-android-riscv64: 1.104.1 + sass-embedded-android-x64: 1.104.1 + sass-embedded-darwin-arm64: 1.104.1 + sass-embedded-darwin-x64: 1.104.1 + sass-embedded-linux-arm: 1.104.1 + sass-embedded-linux-arm64: 1.104.1 + sass-embedded-linux-musl-arm: 1.104.1 + sass-embedded-linux-musl-arm64: 1.104.1 + sass-embedded-linux-musl-riscv64: 1.104.1 + sass-embedded-linux-musl-x64: 1.104.1 + sass-embedded-linux-riscv64: 1.104.1 + sass-embedded-linux-x64: 1.104.1 + sass-embedded-unknown-all: 1.104.1 + sass-embedded-win32-arm64: 1.104.1 + sass-embedded-win32-x64: 1.104.1 + + sass@1.104.0: + dependencies: + chokidar: 5.0.0 + immutable: 5.1.9 + source-map-js: 1.2.1 + optionalDependencies: + '@parcel/watcher': 2.6.0 + + sass@1.104.1: dependencies: chokidar: 5.0.0 immutable: 5.1.9 source-map-js: 1.2.1 optionalDependencies: - '@parcel/watcher': 2.5.6 + '@parcel/watcher': 2.6.0 - saucelabs@1.5.0(supports-color@10.2.2): + saucelabs@1.5.0(supports-color@11.0.0): dependencies: - https-proxy-agent: 2.2.4(supports-color@10.2.2) + https-proxy-agent: 2.2.4(supports-color@11.0.0) transitivePeerDependencies: - supports-color - sax@1.6.0: {} + sax@1.6.1: {} saxes@6.0.0: dependencies: xmlchars: 2.2.0 - secretlint@10.2.2(supports-color@10.2.2): + secretlint@10.2.2(supports-color@11.0.0): dependencies: '@secretlint/config-creator': 10.2.2 - '@secretlint/formatter': 10.2.2(supports-color@10.2.2) - '@secretlint/node': 10.2.2(supports-color@10.2.2) + '@secretlint/formatter': 10.2.2(supports-color@11.0.0) + '@secretlint/node': 10.2.2(supports-color@11.0.0) '@secretlint/profiler': 10.2.2 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3(supports-color@11.0.0) globby: 14.1.0 read-pkg: 9.0.1 transitivePeerDependencies: @@ -20577,9 +21708,9 @@ snapshots: semver@7.8.5: {} - send@0.19.2(supports-color@10.2.2): + send@0.19.2(supports-color@11.0.0): dependencies: - debug: 2.6.9(supports-color@10.2.2) + debug: 2.6.9(supports-color@11.0.0) depd: 2.0.0 destroy: 1.2.0 encodeurl: 2.0.0 @@ -20595,9 +21726,9 @@ snapshots: transitivePeerDependencies: - supports-color - send@1.2.1(supports-color@10.2.2): + send@1.2.1(supports-color@11.0.0): dependencies: - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 @@ -20616,25 +21747,23 @@ snapshots: chainsaw: 0.0.9 hashish: 0.0.4 - serialize-javascript@6.0.2: - dependencies: - randombytes: 2.1.0 + serialize-javascript@7.1.1: {} - serve-static@1.16.3(supports-color@10.2.2): + serve-static@1.16.3(supports-color@11.0.0): dependencies: encodeurl: 2.0.0 escape-html: 1.0.3 parseurl: 1.3.3 - send: 0.19.2(supports-color@10.2.2) + send: 0.19.2(supports-color@11.0.0) transitivePeerDependencies: - supports-color - serve-static@2.2.1(supports-color@10.2.2): + serve-static@2.2.1(supports-color@11.0.0): dependencies: encodeurl: 2.0.0 escape-html: 1.0.3 parseurl: 1.3.3 - send: 1.2.1(supports-color@10.2.2) + send: 1.2.1(supports-color@11.0.0) transitivePeerDependencies: - supports-color @@ -20672,14 +21801,14 @@ snapshots: shebang-regex@3.0.0: {} - shiki@4.3.1: + shiki@4.4.3: dependencies: - '@shikijs/core': 4.3.1 - '@shikijs/engine-javascript': 4.3.1 - '@shikijs/engine-oniguruma': 4.3.1 - '@shikijs/langs': 4.3.1 - '@shikijs/themes': 4.3.1 - '@shikijs/types': 4.3.1 + '@shikijs/core': 4.4.3 + '@shikijs/engine-javascript': 4.4.3 + '@shikijs/engine-oniguruma': 4.4.3 + '@shikijs/langs': 4.4.3 + '@shikijs/themes': 4.4.3 + '@shikijs/types': 4.4.3 '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.5 @@ -20756,49 +21885,54 @@ snapshots: ansi-styles: 6.2.3 is-fullwidth-code-point: 5.1.0 + slice-ansi@9.0.0: + dependencies: + ansi-styles: 6.2.3 + is-fullwidth-code-point: 5.1.0 + smart-buffer@4.2.0: {} - socket.io-adapter@2.5.8(bufferutil@4.1.0)(supports-color@8.1.1)(utf-8-validate@6.0.6): + socket.io-adapter@2.5.8(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6): dependencies: - debug: 4.4.3(supports-color@8.1.1) - ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) + debug: 4.4.3(supports-color@11.0.0) + ws: 8.21.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - socket.io-parser@4.2.6(supports-color@8.1.1): + socket.io-parser@4.2.7(supports-color@11.0.0): dependencies: '@socket.io/component-emitter': 3.1.2 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3(supports-color@11.0.0) transitivePeerDependencies: - supports-color - socket.io@4.8.3(bufferutil@4.1.0)(supports-color@8.1.1)(utf-8-validate@6.0.6): + socket.io@4.8.3(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6): dependencies: accepts: 1.3.8 base64id: 2.0.0 cors: 2.8.6 - debug: 4.4.3(supports-color@8.1.1) - engine.io: 6.6.9(bufferutil@4.1.0)(supports-color@8.1.1)(utf-8-validate@6.0.6) - socket.io-adapter: 2.5.8(bufferutil@4.1.0)(supports-color@8.1.1)(utf-8-validate@6.0.6) - socket.io-parser: 4.2.6(supports-color@8.1.1) + debug: 4.4.3(supports-color@11.0.0) + engine.io: 6.6.9(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6) + socket.io-adapter: 2.5.8(bufferutil@4.1.0)(supports-color@11.0.0)(utf-8-validate@6.0.6) + socket.io-parser: 4.2.7(supports-color@11.0.0) transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - socks-proxy-agent@8.0.5(supports-color@10.2.2): + socks-proxy-agent@8.0.5(supports-color@11.0.0): dependencies: agent-base: 7.1.4 - debug: 4.4.3(supports-color@10.2.2) + debug: 4.4.3(supports-color@11.0.0) socks: 2.8.9 transitivePeerDependencies: - supports-color socks@2.8.9: dependencies: - ip-address: 10.2.0 + ip-address: 10.7.0 smart-buffer: 4.2.0 source-map-js@1.2.1: {} @@ -20821,8 +21955,6 @@ snapshots: source-map@0.6.1: {} - source-map@0.7.6: {} - source-map@0.8.0: {} space-separated-tokens@2.0.2: {} @@ -20904,7 +22036,7 @@ snapshots: stream-composer@1.0.2: dependencies: - streamx: 2.28.0 + streamx: 2.28.1 transitivePeerDependencies: - bare-abort-controller - react-native-b4a @@ -20919,17 +22051,24 @@ snapshots: dependencies: stream-chain: 2.2.5 + stream-parser@0.3.1(supports-color@11.0.0): + dependencies: + debug: 2.6.9(supports-color@11.0.0) + transitivePeerDependencies: + - supports-color + optional: true + stream-shift@1.0.3: {} - streamroller@3.1.5(supports-color@8.1.1): + streamroller@3.1.5(supports-color@11.0.0): dependencies: date-format: 4.0.14 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3(supports-color@11.0.0) fs-extra: 8.1.0 transitivePeerDependencies: - supports-color - streamx@2.28.0: + streamx@2.28.1: dependencies: events-universal: 1.0.1 fast-fifo: 1.3.2 @@ -20940,6 +22079,8 @@ snapshots: strict-event-emitter@0.5.1: {} + strictdom@1.0.1: {} + string-length@4.0.2: dependencies: char-regex: 1.0.2 @@ -21015,7 +22156,7 @@ snapshots: strip-ansi@7.2.0: dependencies: - ansi-regex: 6.2.2 + ansi-regex: 6.3.0 strip-bom@4.0.0: {} @@ -21025,6 +22166,8 @@ snapshots: strip-json-comments@3.1.1: {} + strip-json-comments@5.0.3: {} + structured-source@4.0.0: dependencies: boundary: 2.0.0 @@ -21045,12 +22188,12 @@ snapshots: tinyglobby: 0.2.17 ts-interface-checker: 0.1.13 - superstatic@10.0.0(encoding@0.1.13)(supports-color@10.2.2): + superstatic@10.0.0(encoding@0.1.13)(supports-color@11.0.0): dependencies: basic-auth-connect: 1.1.0 commander: 10.0.1 - compression: 1.8.1(supports-color@10.2.2) - connect: 3.7.0(supports-color@10.2.2) + compression: 1.8.1(supports-color@11.0.0) + connect: 3.7.0(supports-color@11.0.0) destroy: 1.2.0 glob-slasher: 1.0.1 is-url: 1.2.4 @@ -21058,19 +22201,19 @@ snapshots: lodash: 4.18.1 mime-types: 2.1.35 minimatch: 6.2.3 - morgan: 1.11.0(supports-color@10.2.2) + morgan: 1.12.0(supports-color@11.0.0) on-finished: 2.4.1 on-headers: 1.1.0 path-to-regexp: 1.9.0 - router: 2.2.0(supports-color@10.2.2) + router: 2.2.0(supports-color@11.0.0) update-notifier-cjs: 5.1.7(encoding@0.1.13) optionalDependencies: - re2: 1.26.0 + re2: 1.26.1 transitivePeerDependencies: - encoding - supports-color - supports-color@10.2.2: {} + supports-color@11.0.0: {} supports-color@2.0.0: {} @@ -21099,11 +22242,17 @@ snapshots: symbol-tree@3.2.4: {} + sync-child-process@1.0.2: + dependencies: + sync-message-port: 1.2.0 + + sync-message-port@1.2.0: {} + synckit@0.11.13: dependencies: '@pkgr/core': 0.3.6 - systeminformation@5.31.16: {} + systeminformation@5.33.6: {} systemjs@6.15.1: {} @@ -21115,7 +22264,7 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 - tailwindcss@3.4.19(tsx@4.23.1)(yaml@2.9.0): + tailwindcss@3.4.19(tsx@4.23.13)(yaml@2.9.1): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -21131,11 +22280,11 @@ snapshots: normalize-path: 3.0.0 object-hash: 3.0.0 picocolors: 1.1.1 - postcss: 8.5.20 - postcss-import: 15.1.0(postcss@8.5.20) - postcss-js: 4.1.0(postcss@8.5.20) - postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.20)(tsx@4.23.1)(yaml@2.9.0) - postcss-nested: 6.2.0(postcss@8.5.20) + postcss: 8.5.26 + postcss-import: 15.1.0(postcss@8.5.26) + postcss-js: 4.1.0(postcss@8.5.26) + postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.26)(tsx@4.23.13)(yaml@2.9.1) + postcss-nested: 6.2.0(postcss@8.5.26) postcss-selector-parser: 6.1.4 resolve: 1.22.12 sucrase: 3.35.1 @@ -21160,18 +22309,18 @@ snapshots: readable-stream: 3.6.2 optional: true - tar-stream@3.2.0: + tar-stream@3.2.1: dependencies: b4a: 1.8.1 - bare-fs: 4.7.4 + bare-fs: 4.8.1 fast-fifo: 1.3.2 - streamx: 2.28.0 + streamx: 2.28.1 transitivePeerDependencies: - bare-abort-controller - bare-buffer - react-native-b4a - tar@7.5.20: + tar@7.5.22: dependencies: '@isaacs/fs-minipass': 4.0.1 chownr: 3.0.0 @@ -21179,17 +22328,17 @@ snapshots: minizlib: 3.1.0 yallist: 5.0.0 - tcp-port-used@1.0.3(supports-color@10.2.2): + tcp-port-used@1.0.3(supports-color@11.0.0): dependencies: - debug: 4.3.1(supports-color@10.2.2) + debug: 4.3.1(supports-color@11.0.0) is2: 2.0.1 transitivePeerDependencies: - supports-color - teeny-request@10.1.3(supports-color@10.2.2): + teeny-request@10.1.4(supports-color@11.0.0): dependencies: - http-proxy-agent: 7.0.2(supports-color@10.2.2) - https-proxy-agent: 7.0.6(supports-color@10.2.2) + http-proxy-agent: 7.0.2(supports-color@11.0.0) + https-proxy-agent: 7.0.6(supports-color@11.0.0) node-fetch: 3.3.2 stream-events: 1.0.5 transitivePeerDependencies: @@ -21197,7 +22346,7 @@ snapshots: teex@1.0.1: dependencies: - streamx: 2.28.0 + streamx: 2.28.1 transitivePeerDependencies: - bare-abort-controller - react-native-b4a @@ -21246,28 +22395,26 @@ snapshots: dependencies: readable-stream: 3.6.2 - tinybench@2.9.0: {} + tinybench@6.1.4: {} - tinyexec@1.2.4: {} + tinyexec@1.3.0: {} tinyglobby@0.2.17: dependencies: - fdir: 6.5.0(picomatch@4.0.5) - picomatch: 4.0.5 - - tinyrainbow@3.1.0: {} + fdir: 6.5.0(picomatch@4.0.7) + picomatch: 4.0.7 tldts-core@6.1.86: {} - tldts-core@7.4.8: {} + tldts-core@7.4.11: {} tldts@6.1.86: dependencies: tldts-core: 6.1.86 - tldts@7.4.8: + tldts@7.4.11: dependencies: - tldts-core: 7.4.8 + tldts-core: 7.4.11 tmp@0.0.30: dependencies: @@ -21283,7 +22430,7 @@ snapshots: to-through@3.0.0: dependencies: - streamx: 2.28.0 + streamx: 2.28.1 transitivePeerDependencies: - bare-abort-controller - react-native-b4a @@ -21307,7 +22454,7 @@ snapshots: tough-cookie@6.0.2: dependencies: - tldts: 7.4.8 + tldts: 7.4.11 toxic@1.0.1: dependencies: @@ -21344,12 +22491,12 @@ snapshots: ts-node@10.9.2(@types/node@20.19.43)(typescript@6.0.3): dependencies: '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.12 + '@tsconfig/node10': 1.0.13 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 '@types/node': 20.19.43 - acorn: 8.17.0 + acorn: 8.18.0 acorn-walk: 8.3.5 arg: 4.1.3 create-require: 1.1.1 @@ -21362,12 +22509,12 @@ snapshots: ts-node@10.9.2(@types/node@24.13.3)(typescript@6.0.3): dependencies: '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.12 + '@tsconfig/node10': 1.0.13 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 '@types/node': 24.13.3 - acorn: 8.17.0 + acorn: 8.18.0 acorn-walk: 8.3.5 arg: 4.1.3 create-require: 1.1.1 @@ -21382,7 +22529,7 @@ snapshots: dependencies: '@bazel/bazelisk': 1.28.1 glob: 11.1.0 - minimatch: 10.2.5 + minimatch: 10.2.6 typescript: 6.0.3 tslib@1.14.1: {} @@ -21402,7 +22549,7 @@ snapshots: commander: 2.20.3 diff: 4.0.4 glob: 7.2.3 - js-yaml: 3.15.0 + js-yaml: 3.15.2 minimatch: 3.1.5 mkdirp: 0.5.6 resolve: 1.22.12 @@ -21418,9 +22565,9 @@ snapshots: tslib: 1.14.1 typescript: 6.0.3 - tsx@4.23.1: + tsx@4.23.13: dependencies: - esbuild: 0.28.1 + esbuild: 0.28.2 optionalDependencies: fsevents: 2.3.3 @@ -21449,8 +22596,8 @@ snapshots: type-is@2.1.0: dependencies: - content-type: 2.0.0 - media-typer: 1.1.0 + content-type: 2.1.0 + media-typer: 1.1.1 mime-types: 3.0.2 typed-array-buffer@1.0.3: @@ -21490,7 +22637,7 @@ snapshots: typed-rest-client@1.8.11: dependencies: - qs: 6.15.3 + qs: 6.16.0 tunnel: 0.0.6 underscore: 1.13.8 @@ -21544,14 +22691,13 @@ snapshots: undici-types@7.18.2: {} - undici-types@7.28.0: {} + undici-types@8.10.0: {} - undici@6.27.0: {} + undici@6.28.0: {} - undici@7.28.0: {} + undici@7.29.0: {} - undici@8.7.0: - optional: true + undici@8.10.0: {} unicode-emoji-modifier-base@1.0.0: {} @@ -21563,7 +22709,7 @@ snapshots: union@0.5.0: dependencies: - qs: 6.15.3 + qs: 6.16.0 unique-string@2.0.0: dependencies: @@ -21592,10 +22738,10 @@ snapshots: unist-util-is: 6.0.1 unist-util-visit-parents: 6.0.2 - universal-analytics@0.5.4(supports-color@8.1.1): + universal-analytics@0.5.4(supports-color@11.0.0): dependencies: - debug: 4.4.3(supports-color@8.1.1) - uuid: 14.0.1 + debug: 4.4.3(supports-color@11.0.0) + uuid: 14.0.2 transitivePeerDependencies: - supports-color @@ -21638,9 +22784,9 @@ snapshots: untildify@4.0.0: {} - update-browserslist-db@1.2.3(browserslist@4.28.6): + update-browserslist-db@1.3.2(browserslist@4.28.8): dependencies: - browserslist: 4.28.6 + browserslist: 4.28.8 escalade: 3.2.0 picocolors: 1.1.1 @@ -21683,7 +22829,7 @@ snapshots: utils-merge@1.0.1: {} - uuid@14.0.1: {} + uuid@14.0.2: {} uuid@3.4.0: {} @@ -21710,6 +22856,8 @@ snapshots: value-or-function@4.0.0: {} + varint@6.0.0: {} + vary@1.1.2: {} verror@1.10.0: @@ -21749,7 +22897,7 @@ snapshots: normalize-path: 3.0.0 resolve-options: 2.0.0 stream-composer: 1.0.2 - streamx: 2.28.0 + streamx: 2.28.1 to-through: 3.0.0 value-or-function: 4.0.0 vinyl: 3.0.1 @@ -21763,7 +22911,7 @@ snapshots: convert-source-map: 2.0.0 graceful-fs: 4.2.11 now-and-later: 3.0.0 - streamx: 2.28.0 + streamx: 2.28.1 vinyl: 3.0.1 vinyl-contents: 2.0.0 transitivePeerDependencies: @@ -21780,136 +22928,140 @@ snapshots: - bare-abort-controller - react-native-b4a - vite@8.1.4(@types/node@20.19.43)(esbuild@0.28.1)(jiti@1.21.7)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0): + vite@8.2.2(@types/node@20.19.43)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.0)(sass@1.104.0)(tsx@4.23.13)(yaml@2.9.1): dependencies: - lightningcss: 1.32.0 - picomatch: 4.0.5 - postcss: 8.5.20 - rolldown: 1.1.5 + lightningcss: 1.33.0 + picomatch: 4.0.7 + postcss: 8.5.26 + rolldown: 1.2.8 tinyglobby: 0.2.17 optionalDependencies: '@types/node': 20.19.43 - esbuild: 0.28.1 + esbuild: 0.28.2 fsevents: 2.3.3 jiti: 1.21.7 - less: 4.6.7 - sass: 1.101.0 - tsx: 4.23.1 - yaml: 2.9.0 - - vite@8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(jiti@1.21.7)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0): - dependencies: - lightningcss: 1.32.0 - picomatch: 4.0.5 - postcss: 8.5.20 - rolldown: 1.1.5 + less: 4.9.0(supports-color@11.0.0) + sass: 1.104.0 + sass-embedded: 1.104.0 + tsx: 4.23.13 + yaml: 2.9.1 + + vite@8.2.2(@types/node@20.19.43)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.1)(sass@1.104.1)(tsx@4.23.13)(yaml@2.9.1): + dependencies: + lightningcss: 1.33.0 + picomatch: 4.0.7 + postcss: 8.5.26 + rolldown: 1.2.8 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 20.19.43 + esbuild: 0.28.2 + fsevents: 2.3.3 + jiti: 1.21.7 + less: 4.9.0(supports-color@11.0.0) + sass: 1.104.1 + sass-embedded: 1.104.1 + tsx: 4.23.13 + yaml: 2.9.1 + + vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.0)(sass@1.104.0)(tsx@4.23.13)(yaml@2.9.1): + dependencies: + lightningcss: 1.33.0 + picomatch: 4.0.7 + postcss: 8.5.26 + rolldown: 1.2.8 tinyglobby: 0.2.17 optionalDependencies: '@types/node': 24.13.3 - esbuild: 0.28.1 + esbuild: 0.28.2 fsevents: 2.3.3 jiti: 1.21.7 - less: 4.6.7 - sass: 1.101.0 - tsx: 4.23.1 - yaml: 2.9.0 + less: 4.9.0(supports-color@11.0.0) + sass: 1.104.0 + sass-embedded: 1.104.0 + tsx: 4.23.13 + yaml: 2.9.1 + + vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.1)(sass@1.104.1)(tsx@4.23.13)(yaml@2.9.1): + dependencies: + lightningcss: 1.33.0 + picomatch: 4.0.7 + postcss: 8.5.26 + rolldown: 1.2.8 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 24.13.3 + esbuild: 0.28.2 + fsevents: 2.3.3 + jiti: 1.21.7 + less: 4.9.0(supports-color@11.0.0) + sass: 1.104.1 + sass-embedded: 1.104.1 + tsx: 4.23.13 + yaml: 2.9.1 - vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@20.19.43)(esbuild@0.28.1)(jiti@1.21.7)(jsdom@29.1.1)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0): + vitest@5.0.0(@opentelemetry/api@1.9.1)(@types/node@20.19.43)(jsdom@30.0.1)(vite@8.2.2(@types/node@20.19.43)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.1)(sass@1.104.1)(tsx@4.23.13)(yaml@2.9.1)): dependencies: - '@vitest/expect': 4.1.10 - '@vitest/mocker': 4.1.10(vite@8.1.4(@types/node@20.19.43)(esbuild@0.28.1)(jiti@1.21.7)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0)) - '@vitest/pretty-format': 4.1.10 - '@vitest/runner': 4.1.10 - '@vitest/snapshot': 4.1.10 - '@vitest/spy': 4.1.10 - '@vitest/utils': 4.1.10 - es-module-lexer: 2.3.1 + '@types/chai': 5.2.3 + '@vitest/mocker': 5.0.0(vite@8.2.2(@types/node@20.19.43)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.1)(sass@1.104.1)(tsx@4.23.13)(yaml@2.9.1)) + chai: 6.2.2 + es-module-lexer: 2.3.2 expect-type: 1.4.0 - magic-string: 0.30.21 - obug: 2.1.3 - pathe: 2.0.3 - picomatch: 4.0.5 + magic-string: 1.4.1 + obug: 2.1.4 + picomatch: 4.0.7 std-env: 4.2.0 - tinybench: 2.9.0 - tinyexec: 1.2.4 + tinybench: 6.1.4 + tinyexec: 1.3.0 tinyglobby: 0.2.17 - tinyrainbow: 3.1.0 - vite: 8.1.4(@types/node@20.19.43)(esbuild@0.28.1)(jiti@1.21.7)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0) + vite: 8.2.2(@types/node@20.19.43)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.1)(sass@1.104.1)(tsx@4.23.13)(yaml@2.9.1) why-is-node-running: 2.3.0 optionalDependencies: '@opentelemetry/api': 1.9.1 '@types/node': 20.19.43 - jsdom: 29.1.1 + jsdom: 30.0.1 transitivePeerDependencies: - - '@vitejs/devtools' - - esbuild - - jiti - - less - msw - - sass - - sass-embedded - - stylus - - sugarss - - terser - - tsx - - yaml optional: true - vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(esbuild@0.28.1)(jiti@1.21.7)(jsdom@29.1.1)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0): + vitest@5.0.0(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(jsdom@30.0.1)(vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.1)(sass@1.104.1)(tsx@4.23.13)(yaml@2.9.1)): dependencies: - '@vitest/expect': 4.1.10 - '@vitest/mocker': 4.1.10(vite@8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(jiti@1.21.7)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0)) - '@vitest/pretty-format': 4.1.10 - '@vitest/runner': 4.1.10 - '@vitest/snapshot': 4.1.10 - '@vitest/spy': 4.1.10 - '@vitest/utils': 4.1.10 - es-module-lexer: 2.3.1 + '@types/chai': 5.2.3 + '@vitest/mocker': 5.0.0(vite@8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.1)(sass@1.104.1)(tsx@4.23.13)(yaml@2.9.1)) + chai: 6.2.2 + es-module-lexer: 2.3.2 expect-type: 1.4.0 - magic-string: 0.30.21 - obug: 2.1.3 - pathe: 2.0.3 - picomatch: 4.0.5 + magic-string: 1.4.1 + obug: 2.1.4 + picomatch: 4.0.7 std-env: 4.2.0 - tinybench: 2.9.0 - tinyexec: 1.2.4 + tinybench: 6.1.4 + tinyexec: 1.3.0 tinyglobby: 0.2.17 - tinyrainbow: 3.1.0 - vite: 8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(jiti@1.21.7)(less@4.6.7)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0) + vite: 8.2.2(@types/node@24.13.3)(esbuild@0.28.2)(jiti@1.21.7)(less@4.9.0(supports-color@11.0.0))(sass-embedded@1.104.1)(sass@1.104.1)(tsx@4.23.13)(yaml@2.9.1) why-is-node-running: 2.3.0 optionalDependencies: '@opentelemetry/api': 1.9.1 '@types/node': 24.13.3 - jsdom: 29.1.1 + jsdom: 30.0.1 transitivePeerDependencies: - - '@vitejs/devtools' - - esbuild - - jiti - - less - msw - - sass - - sass-embedded - - stylus - - sugarss - - terser - - tsx - - yaml void-elements@2.0.1: {} vscode-css-languageservice@6.3.10: dependencies: '@vscode/l10n': 0.0.18 - vscode-languageserver-textdocument: 1.0.12 + vscode-languageserver-textdocument: 1.0.14 vscode-languageserver-types: 3.17.5 - vscode-uri: 3.1.0 + vscode-uri: 3.2.0 vscode-html-languageservice@5.6.2: dependencies: '@vscode/l10n': 0.0.18 - vscode-languageserver-textdocument: 1.0.12 - vscode-languageserver-types: 3.18.0 - vscode-uri: 3.1.0 + vscode-languageserver-textdocument: 1.0.14 + vscode-languageserver-types: 3.18.3 + vscode-uri: 3.2.0 vscode-jsonrpc@8.2.0: {} @@ -21924,11 +23076,11 @@ snapshots: vscode-jsonrpc: 8.2.0 vscode-languageserver-types: 3.17.5 - vscode-languageserver-textdocument@1.0.12: {} + vscode-languageserver-textdocument@1.0.14: {} vscode-languageserver-types@3.17.5: {} - vscode-languageserver-types@3.18.0: {} + vscode-languageserver-types@3.18.3: {} vscode-languageserver@9.0.1: dependencies: @@ -21948,7 +23100,7 @@ snapshots: vscode-oniguruma: 1.7.0 vscode-textmate: 7.0.4 - vscode-uri@3.1.0: {} + vscode-uri@3.2.0: {} w3c-keyname@2.2.8: {} @@ -21962,10 +23114,6 @@ snapshots: dependencies: makeerror: 1.0.12 - watchpack@2.5.2: - dependencies: - graceful-fs: 4.2.11 - wcwidth@1.0.1: dependencies: defaults: 1.0.4 @@ -22041,6 +23189,14 @@ snapshots: transitivePeerDependencies: - '@noble/hashes' + whatwg-url@17.1.0: + dependencies: + '@exodus/bytes': 1.15.1 + tr46: 6.0.0 + webidl-conversions: 8.0.1 + transitivePeerDependencies: + - '@noble/hashes' + whatwg-url@5.0.0: dependencies: tr46: 0.0.3 @@ -22136,13 +23292,12 @@ snapshots: wordwrap@1.0.0: {} - workerpool@9.3.4: {} + workerpool@10.0.3: {} - wrap-ansi@10.0.0: + wrap-ansi@10.0.1: dependencies: ansi-styles: 6.2.3 string-width: 8.2.2 - strip-ansi: 7.2.0 wrap-ansi@6.2.0: dependencies: @@ -22182,11 +23337,11 @@ snapshots: imurmurhash: 0.1.4 signal-exit: 4.1.0 - ws@7.5.11(bufferutil@4.1.0): + ws@7.5.13(bufferutil@4.1.0): optionalDependencies: bufferutil: 4.1.0 - ws@8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6): + ws@8.21.3(bufferutil@4.1.0)(utf-8-validate@6.0.6): optionalDependencies: bufferutil: 4.1.0 utf-8-validate: 6.0.6 @@ -22203,12 +23358,12 @@ snapshots: xml2js@0.4.23: dependencies: - sax: 1.6.0 + sax: 1.6.1 xmlbuilder: 11.0.1 xml2js@0.5.0: dependencies: - sax: 1.6.0 + sax: 1.6.1 xmlbuilder: 11.0.1 xmlbuilder@11.0.1: {} @@ -22223,6 +23378,8 @@ snapshots: optionalDependencies: sleep: 6.1.0 + xxhash-wasm@1.1.0: {} + y18n@4.0.3: {} y18n@5.0.8: {} @@ -22235,6 +23392,8 @@ snapshots: yaml@2.9.0: {} + yaml@2.9.1: {} + yargs-parser@18.1.3: dependencies: camelcase: 5.3.1 @@ -22246,13 +23405,6 @@ snapshots: yargs-parser@22.0.0: {} - yargs-unparser@2.0.0: - dependencies: - camelcase: 6.3.0 - decamelize: 4.0.0 - flat: 5.0.2 - is-plain-obj: 2.1.0 - yargs@15.4.1: dependencies: cliui: 6.0.0 @@ -22287,12 +23439,12 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 - yargs@18.0.0: + yargs@18.1.0: dependencies: cliui: 9.0.1 escalade: 3.2.0 get-caller-file: 2.0.5 - string-width: 7.2.0 + string-width: 8.2.2 y18n: 5.0.8 yargs-parser: 22.0.0 @@ -22310,7 +23462,46 @@ snapshots: yoctocolors-cjs@2.1.3: {} - yoctocolors@2.1.2: {} + yoctocolors@2.2.0: {} + + yuku-ast@0.9.3: + dependencies: + '@yuku-toolchain/types': 0.9.3 + + yuku-codegen@0.9.3: + dependencies: + '@yuku-toolchain/types': 0.9.3 + optionalDependencies: + '@yuku-codegen/binding-android-arm64': 0.9.3 + '@yuku-codegen/binding-darwin-arm64': 0.9.3 + '@yuku-codegen/binding-darwin-x64': 0.9.3 + '@yuku-codegen/binding-freebsd-x64': 0.9.3 + '@yuku-codegen/binding-linux-arm-gnu': 0.9.3 + '@yuku-codegen/binding-linux-arm-musl': 0.9.3 + '@yuku-codegen/binding-linux-arm64-gnu': 0.9.3 + '@yuku-codegen/binding-linux-arm64-musl': 0.9.3 + '@yuku-codegen/binding-linux-x64-gnu': 0.9.3 + '@yuku-codegen/binding-linux-x64-musl': 0.9.3 + '@yuku-codegen/binding-win32-arm64': 0.9.3 + '@yuku-codegen/binding-win32-x64': 0.9.3 + + yuku-parser@0.9.3: + dependencies: + '@yuku-toolchain/types': 0.9.3 + yuku-ast: 0.9.3 + optionalDependencies: + '@yuku-parser/binding-android-arm64': 0.9.3 + '@yuku-parser/binding-darwin-arm64': 0.9.3 + '@yuku-parser/binding-darwin-x64': 0.9.3 + '@yuku-parser/binding-freebsd-x64': 0.9.3 + '@yuku-parser/binding-linux-arm-gnu': 0.9.3 + '@yuku-parser/binding-linux-arm-musl': 0.9.3 + '@yuku-parser/binding-linux-arm64-gnu': 0.9.3 + '@yuku-parser/binding-linux-arm64-musl': 0.9.3 + '@yuku-parser/binding-linux-x64-gnu': 0.9.3 + '@yuku-parser/binding-linux-x64-musl': 0.9.3 + '@yuku-parser/binding-win32-arm64': 0.9.3 + '@yuku-parser/binding-win32-x64': 0.9.3 zip-stream@6.0.1: dependencies: @@ -22318,11 +23509,13 @@ snapshots: compress-commons: 6.0.2 readable-stream: 4.7.0 - zod-to-json-schema@3.25.2(zod@4.4.3): + zod-to-json-schema@3.25.2(zod@4.6.5): dependencies: - zod: 4.4.3 + zod: 4.6.5 + + zod@4.5.4: {} - zod@4.4.3: {} + zod@4.6.5: {} zone.js@0.16.2: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 34b585e15cc7..a4aa1ead189a 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -88,8 +88,5 @@ hoist: false # to rely on peer dependency placeholders substituted via Bazel. autoInstallPeers: false -# Avoid prompting for confirmation when pnpm determines node_modules needs to be purged. -confirmModulesPurge: false - # Workaround as the default 'install' causes problems during `pnpm ng-dev pr merge` as the lockfile is updated. verifyDepsBeforeRun: warn diff --git a/renovate.json b/renovate.json index 6b178edc01aa..dbb8a238c562 100644 --- a/renovate.json +++ b/renovate.json @@ -1,7 +1,7 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": ["github>angular/dev-infra//renovate-presets/default.json5"], - "baseBranchPatterns": ["main", "22.0.x"], + "baseBranchPatterns": ["main", "22.1.x"], "ignoreDeps": [ "@types/selenium-webdriver", "angular-1.5", diff --git a/scripts/tsconfig.json b/scripts/tsconfig.json index fb0e817869cb..1abe14af3861 100644 --- a/scripts/tsconfig.json +++ b/scripts/tsconfig.json @@ -5,7 +5,6 @@ "lib": ["es2020"], "module": "Node16", "types": ["node"], - "strict": true, "noEmit": true, "skipLibCheck": true, "esModuleInterop": true, diff --git a/skills/dev-skills/README.md b/skills/dev-skills/README.md index c3576e848b8f..789e6a324fd0 100644 --- a/skills/dev-skills/README.md +++ b/skills/dev-skills/README.md @@ -4,7 +4,7 @@ The Angular skills are designed to help coding agents create applications aligne ## Available Skills -- **`angular-developer`**: Generates Angular code and provides architectural guidance. Useful for creating components, services, or obtaining best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling, testing, or CLI tooling. +- **`angular-developer`**: Generates Angular code and provides architectural guidance. Useful for creating components, services, HTTP communication, or obtaining best practices on reactivity (signals, linkedSignal, resource, httpResource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling, testing, or CLI tooling. - **`angular-new-app`**: Creates a new Angular app using the Angular CLI. Provides important guidelines for effectively setting up and structuring a modern Angular application. ## Using Agent Skills diff --git a/skills/dev-skills/angular-developer/SKILL.md b/skills/dev-skills/angular-developer/SKILL.md index 2c8a3a69398e..b0bf5689448c 100644 --- a/skills/dev-skills/angular-developer/SKILL.md +++ b/skills/dev-skills/angular-developer/SKILL.md @@ -1,6 +1,6 @@ --- name: angular-developer -description: Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling. +description: Generates Angular code and provides architectural guidance. Trigger when creating projects, components, services, or HTTP communication, or for best practices on reactivity (signals, linkedSignal, resource, httpResource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, naming conventions, or CLI tooling. license: MIT metadata: author: Copyright 2026 Google LLC @@ -20,7 +20,7 @@ metadata: If no guidelines are provided by the user, here are some default rules to follow when creating a new Angular project: 1. Use the latest stable version of Angular unless the user specifies otherwise. -2. Use Signals Forms for form management in new projects (available in Angular v21 and newer) [Find out more](references/signal-forms.md). +2. Use Signal Forms for form management in new projects (stable in Angular v22 and newer) [Find out more](references/signal-forms.md). **Execution Rules for `ng new`:** When asked to create a new Angular project, you must determine the correct execution command by following these strict steps: @@ -45,10 +45,11 @@ When asked to create a new Angular project, you must determine the correct execu When working with Angular components, consult the following references based on the task: -- **Fundamentals**: Anatomy, metadata, core concepts, and template control flow (@if, @for, @switch). Read [components.md](references/components.md) +- **Fundamentals**: Anatomy, metadata, core concepts, self-closing tags, and template control flow (@if, @for, @switch). Read [components.md](references/components.md) - **Inputs**: Signal-based inputs, transforms, and model inputs. Read [inputs.md](references/inputs.md) - **Outputs**: Signal-based outputs and custom event best practices. Read [outputs.md](references/outputs.md) - **Host Elements**: Host bindings and attribute injection. Read [host-elements.md](references/host-elements.md) +- **Naming Conventions**: Modern Angular v20+ naming style ("Intent over Role") for files, components, services, directives, pipes, and models. Read [naming-conventions.md](references/naming-conventions.md) If you require deeper documentation not found in the references above, read the documentation at `https://angular.dev/guide/components`. @@ -61,11 +62,17 @@ When managing state and data reactivity, use Angular Signals and consult the fol - **Async Reactivity (`resource`)**: Fetching asynchronous data directly into signal state. Read [resource.md](references/resource.md) - **Side Effects (`effect`)**: Logging, third-party DOM manipulation (`afterRenderEffect`), and when NOT to use effects. Read [effects.md](references/effects.md) +## HTTP Communication + +When communicating with backend services, use Angular HTTP APIs and consult the following reference: + +- **HTTP Client and Resources**: `provideHttpClient`, `HttpClient`, interceptors, and `httpResource`. Read [http-client.md](references/http-client.md) + ## Forms In most cases for new apps, **prefer signal forms**. When making a forms decision, analyze the project and consider the following guidelines: -- If the application is using v21 or newer and this is a new form, **prefer signal forms**. +- If the application is using v22 or newer and this is a new form, **prefer Signal Forms**. - For older applications or when working with existing forms, use the appropriate form type that matches the applications current form strategy. - **Signal Forms**: Use signals for form state management. Read [signal-forms.md](references/signal-forms.md) diff --git a/skills/dev-skills/angular-developer/references/angular-aria.md b/skills/dev-skills/angular-developer/references/angular-aria.md index 4241a2576a7c..6c618a8b335a 100644 --- a/skills/dev-skills/angular-developer/references/angular-aria.md +++ b/skills/dev-skills/angular-developer/references/angular-aria.md @@ -17,7 +17,7 @@ Common ARIA attributes to target in CSS: --- -**CRITICAL**: Before using this package, it must be installed via the package manager. Confirm that it has been installed in the project. Use `npm install @angular/aria` to install if necessary. +**CRITICAL**: Before using this package, confirm that `@angular/aria` is installed. If necessary, install it using the package manager configured for the project. ## 1. Accordion @@ -331,9 +331,25 @@ Groups related controls (like text formatting). ```html
-
- - +
+ +
``` diff --git a/skills/dev-skills/angular-developer/references/components.md b/skills/dev-skills/angular-developer/references/components.md index 829a46d80020..4b2c031d3a05 100644 --- a/skills/dev-skills/angular-developer/references/components.md +++ b/skills/dev-skills/angular-developer/references/components.md @@ -48,6 +48,24 @@ To use a component, add it to the `imports` array of the consuming component and export class App {} ``` +### Self-Closing Tags + +Angular supports self-closing tags for custom components. + +**Rule:** Always use self-closing tags when a component does not contain projected content or child nodes: + +```html + + + + + + + + + +``` + ## Template Control Flow Angular uses built-in blocks for conditional rendering and loops. diff --git a/skills/dev-skills/angular-developer/references/creating-services.md b/skills/dev-skills/angular-developer/references/creating-services.md index 00ba49a48045..92b5a757e39c 100644 --- a/skills/dev-skills/angular-developer/references/creating-services.md +++ b/skills/dev-skills/angular-developer/references/creating-services.md @@ -10,21 +10,20 @@ You can generate a service using the Angular CLI: ng generate service my-data ``` -Or you can manually create a TypeScript class and decorate it with `@Service()`. +Or you can manually create a TypeScript class and decorate it with `@Service()`. For reactive state management, store data in a private `signal()` and expose it publicly via `.asReadonly()`: ```ts -import {Service} from '@angular/core'; +import {Service, signal} from '@angular/core'; @Service() export class BasicDataStore { - private data: string[] = []; + private readonly dataSignal = signal([]); - addData(item: string): void { - this.data.push(item); - } + // Expose state as a read-only signal to prevent direct external mutation + readonly data = this.dataSignal.asReadonly(); - getData(): string[] { - return [...this.data]; + addData(item: string): void { + this.dataSignal.update((items) => [...items, item]); } } ``` @@ -39,7 +38,7 @@ Using `@Service` is the recommended approach for most services. It tells Angular #### The `autoProvided` option -If you don't want to create a singleton of your service, you can set `@Service({autoProvided: false})` and declare the service a `providers` array. +If you don't want to create a singleton of your service, you can set `@Service({autoProvided: false})` and declare the service in a `providers` array. ## Injecting a Service @@ -55,36 +54,33 @@ import {BasicDataStore} from './basic-data-store.service'; selector: 'app-example', template: `
-

Data items: {{ dataStore.getData().length }}

+

Data items: {{ dataStore.data().length }}

`, }) export class Example { // Inject the service as a class field - dataStore = inject(BasicDataStore); + readonly dataStore = inject(BasicDataStore); } ``` ### Injecting into Another Service -Services can inject other services in the exact same way. +Services can inject other services in the exact same way. Use `computed()` to derive values from injected services reactively: ```ts -import {Injectable, inject} from '@angular/core'; +import {Service, computed, inject, signal} from '@angular/core'; import {AdvancedDataStore} from './advanced-data-store.service'; @Service() -export class BasicDataStore { +export class CombinedDataStore { // Injecting another service - private advancedDataStore = inject(AdvancedDataStore); - - private data: string[] = []; + private readonly advancedDataStore = inject(AdvancedDataStore); + private readonly dataSignal = signal([]); - getData(): string[] { - // Combine data from this service and the injected service - return [...this.data, ...this.advancedDataStore.getData()]; - } + // Combine reactive state from this service and the injected service + readonly allData = computed(() => [...this.dataSignal(), ...this.advancedDataStore.data()]); } ``` diff --git a/skills/dev-skills/angular-developer/references/define-routes.md b/skills/dev-skills/angular-developer/references/define-routes.md index e36bdf068185..72552038ac82 100644 --- a/skills/dev-skills/angular-developer/references/define-routes.md +++ b/skills/dev-skills/angular-developer/references/define-routes.md @@ -38,6 +38,24 @@ Use `redirectTo` to point one path to another. { path: 'blog', component: Blog }, ``` +### Conditional Redirects + +Pass a function to `redirectTo` to apply logic when redirecting. + +```ts +{ + path: 'restaurant/:location/menu', + redirectTo: ({ params }) => { + const base = `/restaurant/${params['location']}/menu`; + const hour = new Date().getHours(); + + if (hour < 11) return `${base}/breakfast`; + if (hour < 17) return `${base}/lunch`; + return `${base}/dinner`; + }, +}, +``` + ## Page Titles Associate titles with routes for accessibility. Titles can be static or dynamic (via `ResolveFn` or a custom `TitleStrategy`). diff --git a/skills/dev-skills/angular-developer/references/effects.md b/skills/dev-skills/angular-developer/references/effects.md index 1175b1199ad9..cff11a510750 100644 --- a/skills/dev-skills/angular-developer/references/effects.md +++ b/skills/dev-skills/angular-developer/references/effects.md @@ -55,7 +55,7 @@ import { Component, afterRenderEffect, viewChild, ElementRef } from '@angular/co @Component({...}) export class Chart { - canvas = viewChild.required('canvas'); + canvas = viewChild.required>('canvas'); constructor() { afterRenderEffect({ @@ -63,10 +63,10 @@ export class Chart { earlyRead: () => { return this.canvas().nativeElement.getBoundingClientRect().width; }, - // 2. Write to the DOM (receives the result of the previous phase) + // 2. Write to the DOM (receives the previous phase result as a Signal) write: (width) => { // NEVER read from the DOM in the write phase. - setupChart(this.canvas().nativeElement, width); + setupChart(this.canvas().nativeElement, width()); } }); } diff --git a/skills/dev-skills/angular-developer/references/environment-configuration.md b/skills/dev-skills/angular-developer/references/environment-configuration.md index 311e935c78ac..8276df200aaa 100644 --- a/skills/dev-skills/angular-developer/references/environment-configuration.md +++ b/skills/dev-skills/angular-developer/references/environment-configuration.md @@ -81,10 +81,15 @@ Load the configuration before the application starts: ```ts import {Service, inject} from '@angular/core'; import {HttpClient} from '@angular/common/http'; +import {tap} from 'rxjs'; + +interface AppConfig { + apiUrl: string; +} @Service() export class AppConfigService { - private config!: {apiUrl: string}; + private config!: AppConfig; private readonly http = inject(HttpClient); diff --git a/skills/dev-skills/angular-developer/references/http-client.md b/skills/dev-skills/angular-developer/references/http-client.md new file mode 100644 index 000000000000..430639ff3bf1 --- /dev/null +++ b/skills/dev-skills/angular-developer/references/http-client.md @@ -0,0 +1,108 @@ +# HTTP communication with `HttpClient` and `httpResource` + +Use Angular's HTTP APIs for backend communication so requests participate in dependency injection, interceptors, transfer cache, and security features. + +## Setup + +In Angular v21 and later, `HttpClient` is available for injection by default. Add `provideHttpClient(...)` only when an app needs to configure HTTP features for a specific injector: + +```ts +import {provideHttpClient, withInterceptors} from '@angular/common/http'; + +export const appConfig = { + providers: [provideHttpClient(withInterceptors([authInterceptor]))], +}; +``` + +- `HttpClient` uses the fetch backend by default. +- Use `withXhr()` only when upload progress events are required. Do not use `withXhr()` for server-side rendering. +- Use `provideHttpClient(...)` for feature configuration such as interceptors, XSRF options, XHR, or parent-request delegation. +- Calling `provideHttpClient()` with no features is not required for basic HTTP requests, but it configures the default HTTP feature set for that injector, including Angular's XSRF interceptor. +- Prefer `provideHttpClient(...)` over `HttpClientModule` for feature configuration, especially with multiple injectors. +- Use `withRequestsMadeViaParent()` when a child injector should add interceptors while still delegating to the parent HTTP chain. + +## `HttpClient` + +Encapsulate backend calls in injectable services, not components: + +```ts +import {HttpClient} from '@angular/common/http'; +import {Service, inject} from '@angular/core'; + +@Service() +export class UserService { + private readonly http = inject(HttpClient); + + getUser(id: string) { + return this.http.get(`/api/users/${id}`); + } +} +``` + +Important rules: + +- `HttpClient` requests are cold `Observable`s. No request is sent until the `Observable` is subscribed to. Multiple subscriptions send multiple backend requests. +- Subscribe to mutation requests (`post`, `put`, `patch`, `delete`) so they execute. +- The generic type parameter is a type assertion only. Validate unknown backend data at runtime when the shape is not trusted. +- Use literal values for `responseType` and `observe`; if options are extracted, write values like `responseType: 'text' as const`. +- `HttpHeaders` and `HttpParams` are immutable; use the returned instance from `.set()` or `.append()`. +- Fetch options such as `timeout`, `cache`, `priority`, `mode`, `redirect`, `credentials`, `keepalive`, `referrer`, `referrerPolicy`, and `integrity` are supported where the backend supports them. `withCredentials: true` overrides `credentials`. +- Handle failures through `HttpErrorResponse`. Network and timeout failures use status `0`; backend failures use the server status code. +- Prefer the `async` pipe or `toSignal` for component reads so subscriptions are cleaned up. + +## Interceptors + +Prefer functional interceptors configured with `withInterceptors`. + +```ts +import { + HttpHandlerFn, + HttpRequest, + provideHttpClient, + withInterceptors, +} from '@angular/common/http'; + +export function authInterceptor(req: HttpRequest, next: HttpHandlerFn) { + return next(req.clone({setHeaders: {Authorization: 'Bearer token'}})); +} + +export const appConfig = { + providers: [provideHttpClient(withInterceptors([authInterceptor]))], +}; +``` + +- Interceptors run in the order listed. +- Request and response objects are mostly immutable; clone before changing them. +- Request and response bodies are not deeply immutable. Avoid in-place body mutation because retries can run the same interceptor again. +- Use `inject()` inside functional interceptors for services. +- Use `HttpContextToken` for per-request metadata that interceptors need but the backend should not receive. +- Use DI-based interceptors only for existing code, and enable them with `withInterceptorsFromDi()`. + +## Security + +- `HttpClient` strips the XSSI prefix from JSON responses when present. +- `provideHttpClient()` configures XSRF protection by default for mutating relative and same-origin requests. It reads the `XSRF-TOKEN` cookie and sends the `X-XSRF-TOKEN` header. +- The backend must set the XSRF cookie and verify the header. Customize names with `withXsrfConfiguration(...)`; disable only deliberately with `withNoXsrfProtection()`. + +## `httpResource` + +Use `httpResource` to create an asynchronous derivation that fetches data over HTTP and exposes the result as reactive signals. + +```ts +import {httpResource} from '@angular/common/http'; +import {input} from '@angular/core'; + +export class UserProfile { + readonly userId = input.required(); + readonly user = httpResource(() => `/api/users/${this.userId()}`); +} +``` + +- `httpResource` is eager. It sends a request when its reactive request computation runs, not when an `Observable` is subscribed. +- When a dependency changes, it cancels the pending request and sends the next one. +- Return `undefined` from the request function to skip a backend request. +- Prefer `httpResource` for reads. Use `HttpClient` directly for mutations such as `POST`, `PUT`, `PATCH`, and `DELETE`. +- Guard `value()` reads with `hasValue()`; reading `value()` while the resource is in an error state throws. +- Use `httpResource.text`, `httpResource.blob`, or `httpResource.arrayBuffer` for non-JSON responses. +- Use the `parse` option to validate or transform responses with a runtime schema. +- Read `headers()`, `statusCode()`, and `progress()` when response metadata or download progress is needed. Set `reportProgress: true` for progress events. diff --git a/skills/dev-skills/angular-developer/references/loading-strategies.md b/skills/dev-skills/angular-developer/references/loading-strategies.md index 848bff124593..f4d269f90891 100644 --- a/skills/dev-skills/angular-developer/references/loading-strategies.md +++ b/skills/dev-skills/angular-developer/references/loading-strategies.md @@ -24,7 +24,7 @@ Use `loadComponent` to fetch the component on demand. ```ts { path: 'admin', - loadComponent: () => import('./admin/admin.component').then(m => m.AdminComponent)`, + loadComponent: () => import('./admin').then(m => m.Admin), } ``` @@ -39,6 +39,8 @@ Use `loadChildren` to fetch a set of routes. } ``` +Return the `import()` promise directly only when the loaded file uses a `default` export. + ## Injection Context and Lazy Loading Loader functions run within the **injection context** of the current route. This allows you to call `inject()` to make context-aware loading decisions. diff --git a/skills/dev-skills/angular-developer/references/mcp.md b/skills/dev-skills/angular-developer/references/mcp.md index 54460876913f..f0649f1d3bc9 100644 --- a/skills/dev-skills/angular-developer/references/mcp.md +++ b/skills/dev-skills/angular-developer/references/mcp.md @@ -9,24 +9,15 @@ When the MCP server is enabled, AI agents have access to the following tools: | Name | Description | | :-------------------------- | :-------------------------------------------------------------------------------------------------------- | | `ai_tutor` | Launches an interactive AI-powered Angular tutor. | +| `devserver.start` | Asynchronously starts a dev server (`ng serve`). Returns immediately. | +| `devserver.stop` | Stops the dev server. | +| `devserver.wait_for_build` | Returns the logs of the most recent build in a running dev server. | | `get_best_practices` | Retrieves the Angular Best Practices Guide (crucial for standalone components, typed forms, etc.). | | `list_projects` | Lists all applications and libraries in the workspace by reading `angular.json`. | | `onpush_zoneless_migration` | Analyzes code and provides a plan to migrate it to `OnPush` change detection (prerequisite for zoneless). | +| `run_target` | Executes a configured target. | | `search_documentation` | Searches the official documentation at `https://angular.dev`. | -## Experimental Tools - -Some tools must be enabled explicitly using the `--experimental-tool` (or `-E`) flag. - -| Name | Description | -| :------------------------- | :-------------------------------------------------------------------- | -| `build` | Performs a one-off build using `ng build`. | -| `devserver.start` | Asynchronously starts a dev server (`ng serve`). Returns immediately. | -| `devserver.stop` | Stops the dev server. | -| `devserver.wait_for_build` | Returns the logs of the most recent build in a running dev server. | -| `e2e` | Executes end-to-end tests. | -| `test` | Runs the project's unit tests. | - ## Configuration To use the MCP server, you configure your host environment (IDE or CLI) to run `npx @angular/cli mcp`. @@ -97,10 +88,9 @@ You can pass arguments to the MCP server in the `args` array of your configurati - `--read-only`: Only registers tools that do not modify the project. - `--local-only`: Only registers tools that do not require an internet connection. -- `--experimental-tool` (`-E`): Enables specific experimental tools (e.g., `-E build`, `-E devserver`). -Example for read-only mode with experimental tools enabled: +Example for read-only mode: ```json -"args": ["-y", "@angular/cli", "mcp", "--read-only", "-E", "build", "-E", "test"] +"args": ["-y", "@angular/cli", "mcp", "--read-only"] ``` diff --git a/skills/dev-skills/angular-developer/references/naming-conventions.md b/skills/dev-skills/angular-developer/references/naming-conventions.md new file mode 100644 index 000000000000..c0c1fcb84e29 --- /dev/null +++ b/skills/dev-skills/angular-developer/references/naming-conventions.md @@ -0,0 +1,76 @@ +# Angular Naming Conventions (Angular v20+ Style Guide) + +This skill enforces Angular naming conventions for components, services, directives, pipes, and models. While it promotes the modern **"Intent over Role"** philosophy introduced in Angular v20, **it must respect existing project configurations first**. + +--- + +## Core Principles + +1. **Prioritize Existing Conventions**: Before generating or refactoring files, check the existing project files, `angular.json` configuration, and ESLint rules. **Do not force suffixless naming on projects that rely on standard suffixes.** +2. **Remove Role Suffixes (Modern Projects Only)**: In projects configured for "Intent over Role" or newly bootstrapped v20+ projects, filenames no longer include functional extensions like `.component.ts`, `.service.ts`, or `.directive.ts`. Corresponding TypeScript classes drop suffixes like `Component`, `Service`, or `Directive`. +3. **Intent/Purpose-Based Naming**: When suffixless naming is active, name files and classes based on their specific domain, responsibility, or business purpose (e.g., `-data`, `-store`, `-api`, or `-formatter`). +4. **Folder Location as Context**: Lean on folder hierarchy (`core/`, `features/`, `shared/`) and IDE capabilities to identify the technical role of files, rather than encoding that context within the file name. +5. **Interface/Model Exception**: Interfaces and data models still retain the `.model.ts` suffix to clearly declare type contracts. + +--- + +## Recommended Project Structure & Naming Rules + +### 1. File/Identifier Matching & Consistency + +- **Hyphens in Filenames**: Continue using kebab-case (hyphens) to separate words in filenames (e.g., `product-list.ts`). +- **Identifier Matching**: Filenames must align directly with the primary TypeScript class/identifier (e.g., `product-list.ts` contains `class ProductList`). +- **Unified Filenames**: If using split template or style files, keep names identical to the main TypeScript file: + - `product-list.ts` + - `product-list.html` + - `product-list.css` +- **Test Files**: Continue to use the same base name with the `.spec.ts` suffix (e.g., `product-list.spec.ts` for `product-list.ts`). + +### 2. Core Directory (Application Foundation) + +Houses singleton services, global state, and system-wide models. + +- **Services (Logic/State)**: + - _Old_: `auth.service.ts` (Class: `AuthService`) + - _New_: `auth.ts` (Class: `AuthService`) + - _Alternative (Intent-specific)_: Use descriptive domain-purpose suffixes like `[domain]-data.ts`, `[domain]-store.ts`, or `[domain]-data-client.ts` (e.g., `auth-data.ts` / `AuthData`, `user-data-client.ts` / `UserDataClient`). +- **Models**: Retain the `.model.ts` suffix for data shapes. + - _Example_: `user.model.ts` (Interface: `User`) + +### 3. Features Directory (Domain Business Logic) + +Organize files into feature-specific folders containing components, local services, and routes related to that domain. + +- **Main Feature Component**: Name the main feature component after the route or feature itself. + - _Example_: `features/profile/profile.ts` (Class: `Profile`) +- **Feature Sub-Components**: Name sub-components based on their display or functional role. + - _Example_: `features/profile/components/profile-header.ts` (Class: `ProfileHeader`) + - _Example_: `features/projects/components/project-card.ts` (Class: `ProjectCard`) +- **Feature Services**: Name feature services based on feature-specific data or state needs. + - _Example_: `features/projects/projects-data.ts` (Class: `ProjectsData`) + +### 4. Shared Directory (Reusable UI Toolkit) + +Store pure, presentational elements and helpers with zero business logic in a shared folder. + +- **Shared Components**: Name shared components based on their reusable UI role. + - _Example_: `shared/components/button/button.ts` (Class: `Button`) + - _Example_: `shared/components/spinner/spinner.ts` (Class: `Spinner`) +- **Shared Pipes**: Name shared pipes according to their formatting purpose. + - _Example_: `shared/pipes/format-date.ts` (Class: `FormatDate`) +- **Shared Directives**: Name directives according to the behavior they attach to elements. + - _Old_: `highlight.directive.ts` (Class: `HighlightDirective`) + - _New_: `highlight.ts` (Class: `Highlight`) + +--- + +## Best Practices & Coexistence Rules + +- **How to Determine the Style in Use**: + 1. Inspect adjacent files in the target directory (do they end in `.component.ts` or `.ts`?). + 2. Check `angular.json` for custom schematics options that might configure suffix behaviors. + 3. If unsure, use the traditional role suffix style (`.component.ts`, `.service.ts`) as it is the safest default in the Angular ecosystem. +- **Avoid Namespace Collisions**: Without role suffixes, files like `user.ts` (component) and `user.model.ts` (model) can collide if they both declare a class/interface named `User`. + - To prevent this use more specific, intent-based names for components (e.g. `class UserProfile` in `user-profile.ts` or `class UserDetail` in `user-detail.ts`) while keeping the simple domain name for the interface (`interface User` in `user.model.ts`). +- **Consistency Check**: Do not mix old suffix styles and new suffixless styles in the same feature folder or module. Keep existing legacy code as-is unless migrating the entire module to the modern structure. +- **Lean on the IDE**: Rely on modern IDE code navigation (e.g., "Go to Definition" or fuzzy searches for class names like `AuthData` or `ProfileHeader`) and file type icons rather than visual scan of suffix strings. diff --git a/skills/dev-skills/angular-developer/references/pipes.md b/skills/dev-skills/angular-developer/references/pipes.md index f3b50fb93a27..a3182a29a450 100644 --- a/skills/dev-skills/angular-developer/references/pipes.md +++ b/skills/dev-skills/angular-developer/references/pipes.md @@ -54,10 +54,10 @@ export class KebabCasePipe implements PipeTransform { ```ts // formatter.service.ts — import the function, NOT the pipe -import {Injectable} from '@angular/core'; +import {Service} from '@angular/core'; import {toKebabCase} from './kebab-case'; -@Injectable({providedIn: 'root'}) +@Service() export class FormatterService { toSlug(title: string): string { return toKebabCase(title); @@ -80,10 +80,10 @@ Inject `LOCALE_ID` to get the current locale and pass it to the function. ```ts // CORRECT — use formatNumber instead of injecting DecimalPipe -import {Injectable, LOCALE_ID, inject} from '@angular/core'; +import {Service, LOCALE_ID, inject} from '@angular/core'; import {formatNumber} from '@angular/common'; -@Injectable({providedIn: 'root'}) +@Service() export class PriceService { private locale = inject(LOCALE_ID); @@ -95,10 +95,10 @@ export class PriceService { ```ts // WRONG — do not inject pipe classes -import {Injectable} from '@angular/core'; +import {Service, inject} from '@angular/core'; import {DecimalPipe} from '@angular/common'; -@Injectable({providedIn: 'root'}) +@Service() export class PriceService { // ❌ DecimalPipe is not designed to be injected private pipe = inject(DecimalPipe); diff --git a/skills/dev-skills/angular-developer/references/router-testing.md b/skills/dev-skills/angular-developer/references/router-testing.md index 35328e41e427..9f6665e760c6 100644 --- a/skills/dev-skills/angular-developer/references/router-testing.md +++ b/skills/dev-skills/angular-developer/references/router-testing.md @@ -12,7 +12,7 @@ The `RouterTestingHarness` is the primary tool for testing routing scenarios. Yo ```ts import {TestBed} from '@angular/core/testing'; -import {provideRouter} from '@angular/router'; +import {provideRouter, Router} from '@angular/router'; import {RouterTestingHarness} from '@angular/router/testing'; import {Dashboard} from './dashboard.component'; import {HeroDetail} from './hero-detail.component'; @@ -41,7 +41,7 @@ describe('Dashboard Component Routing', () => { ### Key Concepts 1. **`provideRouter([...])`**: Provide a test-specific routing configuration. This should include the routes necessary for the component-under-test to function correctly. -2. **`RouterTestingHarness.create()`**: Asynchronously creates and initializes the harness and performs an initial navigation to the root URL (`/`). +2. **`RouterTestingHarness.create(initialUrl?)`**: Asynchronously creates the harness and optionally performs an initial navigation. ## Writing Router Tests @@ -62,13 +62,14 @@ it('should navigate to a hero detail when a hero is selected', async () => { await harness.fixture.whenStable(); // 2. Assert on the URL - expect(harness.router.url).toEqual('/heroes/42'); + const router = TestBed.inject(Router); + expect(router.url).toEqual('/heroes/42'); // 3. Get the activated component after navigation - const heroDetail = await harness.getHarness(HeroDetail); + const heroDetail = harness.routeDebugElement?.componentInstance as HeroDetail; // 4. Assert on the state of the new component - expect(await heroDetail.componentInstance.hero.name).toBe('Test Hero'); + expect(heroDetail.hero.name).toBe('Test Hero'); }); it('should get the activated component directly', async () => { @@ -82,6 +83,6 @@ it('should get the activated component directly', async () => { ### Best Practices - **Navigate with the Harness:** Always use `harness.navigateByUrl()` to simulate navigation. This method returns a promise that resolves with the instance of the activated component. -- **Access the Router State:** Use `harness.router` to access the live router instance and assert on its state (e.g., `harness.router.url`). -- **Get Activated Components:** Use `harness.getHarness(ComponentType)` to get an instance of a component harness for the currently activated routed component, or `harness.routeDebugElement` to get the `DebugElement`. +- **Access the Router State:** Inject `Router` from `TestBed` to inspect the live router state. +- **Get Activated Components:** Use the component returned by `navigateByUrl(url, ComponentType)`. After application-driven navigation, read `harness.routeDebugElement?.componentInstance`. - **Wait for Stability:** After performing an action that causes navigation, always `await harness.fixture.whenStable()` to ensure the routing is complete before making assertions. diff --git a/tools/bazel/protractor_test.bzl b/tools/bazel/protractor_test.bzl deleted file mode 100644 index b893121d2fd2..000000000000 --- a/tools/bazel/protractor_test.bzl +++ /dev/null @@ -1,27 +0,0 @@ -load("@devinfra//bazel/spec-bundling:index.bzl", _spec_bundle = "spec_bundle") -load("@rules_browsers//protractor_test:index.bzl", _protractor_test = "protractor_test") - -def protractor_web_test_suite(name, deps, **kwargs): - _spec_bundle( - name = "%s_bundle" % name, - deps = deps, - external = ["protractor", "selenium-webdriver"], - ) - - _protractor_test( - name = name, - deps = [":%s_bundle" % name], - extra_config = { - "useAllAngular2AppRoots": True, - "allScriptsTimeout": 120000, - "getPageTimeout": 120000, - "jasmineNodeOpts": { - "defaultTimeoutInterval": 120000, - }, - }, - data = [ - "//:node_modules/protractor", - "//:node_modules/selenium-webdriver", - ], - **kwargs - ) diff --git a/tools/bazel/webdriver_test.bzl b/tools/bazel/webdriver_test.bzl new file mode 100644 index 000000000000..43075bafe601 --- /dev/null +++ b/tools/bazel/webdriver_test.bzl @@ -0,0 +1,51 @@ +load("@devinfra//bazel/spec-bundling:index.bzl", "spec_bundle") +load("@rules_browsers//server_test:index.bzl", "server_test") +load("//tools/bazel:jasmine_test.bzl", "jasmine_test") + +def webdriver_test(name, deps, server, tags = [], data = [], external = [], **kwargs): + spec_bundle( + name = "%s_bundle" % name, + deps = deps, + external = ["selenium-webdriver"] + external, + platform = "node", + config = { + "banner": { + "js": """import {createRequire as __cjsCompatRequire} from 'module'; + const require = __cjsCompatRequire(import.meta.url); + const __filename = import.meta.filename; + const __dirname = import.meta.dirname;""", + }, + "target": ["ES2022"], + "format": "esm", + }, + ) + + jasmine_test( + name = "%s_jasmine_test" % name, + tags = tags + ["manual"], + data = data + [ + ":%s_bundle" % name, + "@rules_browsers//browsers/chromium", + "//:node_modules/selenium-webdriver", + ], + env = { + "CHROME_HEADLESS_BIN": "$(CHROME-HEADLESS-SHELL)", + "CHROMEDRIVER": "$(CHROMEDRIVER)", + }, + toolchains = ["@rules_browsers//browsers/chromium:toolchain_alias"], + **kwargs + ) + + server_test( + name = "%s_chromium" % name, + server = server, + test = ":%s_jasmine_test" % name, + tags = tags + ["e2e"], + ) + + native.test_suite( + name = name, + tests = [ + ":%s_chromium" % name, + ], + ) diff --git a/tools/defaults.bzl b/tools/defaults.bzl index a9dff43be7df..f78ee5c07199 100644 --- a/tools/defaults.bzl +++ b/tools/defaults.bzl @@ -14,9 +14,9 @@ load("//tools/bazel:esbuild.bzl", _esbuild = "esbuild", _esbuild_checked_in = "e load("//tools/bazel:jasmine_test.bzl", _angular_jasmine_test = "angular_jasmine_test", _jasmine_test = "jasmine_test", _zone_compatible_jasmine_test = "zone_compatible_jasmine_test", _zoneless_jasmine_test = "zoneless_jasmine_test") load("//tools/bazel:js_defs.bzl", _js_binary = "js_binary", _js_run_binary = "js_run_binary", _js_test = "js_test") load("//tools/bazel:npm_packages.bzl", _ng_package = "ng_package", _npm_package = "npm_package") -load("//tools/bazel:protractor_test.bzl", _protractor_web_test_suite = "protractor_web_test_suite") load("//tools/bazel:tsec.bzl", _tsec_test = "tsec_test") load("//tools/bazel:web_test.bzl", _ng_web_test_suite = "ng_web_test_suite", _web_test = "web_test", _zoneless_web_test_suite = "zoneless_web_test_suite") +load("//tools/bazel:webdriver_test.bzl", _webdriver_test = "webdriver_test") extract_types = _extract_types esbuild = _esbuild @@ -36,7 +36,7 @@ web_test = _web_test sass_binary = _sass_binary sass_library = _sass_library npm_sass_library = _npm_sass_library -protractor_web_test_suite = _protractor_web_test_suite +webdriver_test = _webdriver_test esbuild_checked_in = _esbuild_checked_in http_server = _http_server api_golden_test = _api_golden_test diff --git a/tools/gulp-tasks/changelog-zonejs.js b/tools/gulp-tasks/changelog-zonejs.js index 2c8853e0865c..2c7020a61813 100644 --- a/tools/gulp-tasks/changelog-zonejs.js +++ b/tools/gulp-tasks/changelog-zonejs.js @@ -19,15 +19,20 @@ module.exports = (gulp) => () => { conventionalChangelog( { preset: 'angular', + tagPrefix: 'zone.js-', }, {linkCompare: true, previousTag: ptag, currentTag: tag, version: version}, { - // Ignore commits that have a different scope than `zone.js`. - extendedRegexp: true, - grep: '^((feat|fix|perf)\\(zone\\.js\\)|revert:.*\\(zone\\.js\\))', from: ptag, to: 'HEAD', }, + undefined, + { + transform: (commit) => { + if (commit.scope !== 'zone.js') return undefined; + return commit; + }, + }, ), ) .pipe(gulp.dest('./packages/zone.js/')); diff --git a/tools/manual_api_docs/blocks/boundary.md b/tools/manual_api_docs/blocks/boundary.md new file mode 100644 index 000000000000..a41315092c36 --- /dev/null +++ b/tools/manual_api_docs/blocks/boundary.md @@ -0,0 +1,34 @@ +IMPORTANT: The `@boundary` block is in [developer preview](reference/releases#developer-preview). It's ready for you to try, but it may change before it is stable. + +The `@boundary` block is a control flow mechanism that lets you intercept and handle rendering errors in templates. + +## Syntax + +```angular-html +@boundary { + +} @error { + +} +``` + +## Description + +The `@boundary` block encapsulates its content and catches any errors that occur during the initial render or subsequent change detection cycles of its child views. If an error is caught, the framework stops rendering the main view and instead renders the fallback UI provided in the `@error` block. + +IMPORTANT: Wrapping `` in a `@boundary` does not catch errors from projected content. See [Content projection with error boundaries](guide/templates/error-boundaries#content-projection). + +You can capture the error object by declaring a variable in the `@error` block, for example `@error (let err)`. + +You can use multiple `@error` blocks with `when` clauses to conditionally render different fallbacks based on the error type, with a final fallback `@error` block at the end. You can also access a `$reset` function to attempt re-rendering the boundary content. + +```angular-html +@boundary { + +} @error (let err; retry = $reset; when isNetworkError(err)) { + + +} @error { + +} +``` diff --git a/tools/manual_api_docs/blocks/defer.md b/tools/manual_api_docs/blocks/defer.md index 11e54a5d9808..92d212d7acc5 100644 --- a/tools/manual_api_docs/blocks/defer.md +++ b/tools/manual_api_docs/blocks/defer.md @@ -1,4 +1,4 @@ -A type of [block](api/core/@defer) that can be used to defer load the JavaScript for components, +The `@defer` block can be used to lazy load components, directives and pipes used inside a component template. ## Syntax diff --git a/tools/manual_api_docs/blocks/let.md b/tools/manual_api_docs/blocks/let.md index cb76226d0598..fc1a2e35e0bf 100644 --- a/tools/manual_api_docs/blocks/let.md +++ b/tools/manual_api_docs/blocks/let.md @@ -2,6 +2,7 @@ ## Syntax + ```angular-html @let name = user.name; @let data = data$ | async; @@ -10,7 +11,7 @@ ## Description `@let` declarations are similar to [JavaScript's `let`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let) and -their values can be any valid Angular expression. The expressions will be re-evaluated everytime the template is executed. +their values can be any valid Angular expression. The expressions will be re-evaluated every time the template is executed. Similarly to JavaScript variables, variables declared with `@let`, can be used: @@ -21,12 +22,12 @@ Similarly to JavaScript variables, variables declared with `@let`, can be used: @let user = user$ | async; @if (user) { -

Hello, {{user.name}}

- +

Hello, {{ user.name }}

+
    @for (snack of user.favoriteSnacks; track snack.id) { -
  • {{snack.name}}
  • +
  • {{ snack.name }}
  • }
diff --git a/tools/manual_api_docs/blocks/switch.md b/tools/manual_api_docs/blocks/switch.md index ca1967797306..7b925ca724a2 100644 --- a/tools/manual_api_docs/blocks/switch.md +++ b/tools/manual_api_docs/blocks/switch.md @@ -67,7 +67,7 @@ When the switched expression is nested within a union, you must explicitly speci template: ` @switch (state.mode) { @case ('show') { - {{ state.menu }}; + {{ state.menu }} } @case ('hide') {} @default never; diff --git a/tools/manual_api_docs/elements/ng-template.md b/tools/manual_api_docs/elements/ng-template.md index 00f70f9368c8..2ecca662a008 100644 --- a/tools/manual_api_docs/elements/ng-template.md +++ b/tools/manual_api_docs/elements/ng-template.md @@ -43,7 +43,7 @@ method `createEmbeddedView()`. ### Template Variables `` elements can be referenced in templates -using [standard template variables](guide/templates/variables#template-reference-variables#how-angular-assigns-values-to-template-variables). +using [standard template variables](guide/templates/variables#assigning-values-to-template-reference-variables). _This is how `` elements are used as `ngIf` else clauses._ diff --git a/tools/symbol-extractor/symbol_extractor_spec/tsconfig.json b/tools/symbol-extractor/symbol_extractor_spec/tsconfig.json index c12cbba737a9..f784437349db 100644 --- a/tools/symbol-extractor/symbol_extractor_spec/tsconfig.json +++ b/tools/symbol-extractor/symbol_extractor_spec/tsconfig.json @@ -1,6 +1,5 @@ { "compilerOptions": { - "strict": true, "module": "ESNext", "target": "ES2022", "sourceMap": true, diff --git a/tools/tsconfig.json b/tools/tsconfig.json index c317a66e241f..df1625aef348 100644 --- a/tools/tsconfig.json +++ b/tools/tsconfig.json @@ -1,6 +1,5 @@ { "compilerOptions": { - "strict": true, "skipLibCheck": true, "declaration": true, "esModuleInterop": true, diff --git a/tslint.json b/tslint.json index c7046a12df1e..2ddbd7e2b178 100644 --- a/tslint.json +++ b/tslint.json @@ -20,7 +20,6 @@ "typescript/lib/tsserverlibrary", "typescript", "minimist", - "magic-string", "semver", "yargs", "glob", @@ -74,6 +73,10 @@ { "name": ["performance", "mark"], "message": "`performance` methods aren't not fully supported in all environments like JSDOM and Cloudflare workers. Use 'performanceMark' from '@angular/core' instead." + }, + { + "name": ["*", "hasOwnProperty"], + "message": "Use `Object.hasOwn` instead." } ] }, diff --git a/vscode-ng-language-service/CHANGELOG.md b/vscode-ng-language-service/CHANGELOG.md index 89aee36c10c1..b51eb31fff92 100644 --- a/vscode-ng-language-service/CHANGELOG.md +++ b/vscode-ng-language-service/CHANGELOG.md @@ -1,3 +1,11 @@ +## 22.1.0 (2026-08-12) + +- fix(language-service): account for strictTemplates being enabled by default ([a99fb915c0](https://github.com/angular/angular/commit/a99fb915c09b352ac67f24e71af84cda30bcbf3e)) +- feat(language-service): Typecheck templates which would require inline typecheck blocks (#68454) ([4f9c824dd9](https://github.com/angular/angular/commit/4f9c824dd9ec4462d29ed07b5e7916be86c19e84)) +- feat(language-service): compile non-exported classes if standalone (#68454) ([7f0265e43a](https://github.com/angular/angular/commit/7f0265e43ab9f6b1ab9ad0ae84e70a40db417417)) + + + ## 22.0.1 (2026-06-11) - fix(vscode-extension): resolve relative workspace tsdk paths to absolute ([f6695b0eb2](https://github.com/angular/angular/commit/f6695b0eb26e70a92579666396a5ff417b8874ff)) diff --git a/vscode-ng-language-service/client/src/client.ts b/vscode-ng-language-service/client/src/client.ts index c934b0b5665f..d42cbf282469 100644 --- a/vscode-ng-language-service/client/src/client.ts +++ b/vscode-ng-language-service/client/src/client.ts @@ -26,12 +26,8 @@ import { } from '../../common/requests'; import {NodeModule, resolve, Version} from '../../common/resolver'; -import { - isInsideStringLiteral, - isNotTypescriptOrSupportedDecoratorField, - isNotTypescriptOrSupportedDecoratorRange, -} from './embedded_support'; import {OpenJsDocLinkCommandId} from '../../common/initialize'; +import {isInsideStringLiteral, isNotTypescriptOrSupportedDecoratorField} from './embedded_support'; interface GetTcbResponse { uri: vscode.Uri; @@ -290,14 +286,17 @@ export class AngularLanguageClient implements vscode.Disposable { return null; } - // For TypeScript files, only request Angular inlay hints when the - // visible range intersects supported decorator fields (e.g. inline - // template/style metadata). This matches the guarding strategy used - // by other Angular LSP features and avoids work on unsupported TS regions. - if (!isNotTypescriptOrSupportedDecoratorRange(document, range)) { + if ( + document.languageId === 'typescript' && + !document.getText().includes('@angular/core') + ) { return null; } + // For TypeScript files, we always request Angular inlay hints. + // The server is responsible for filtering hints that do not intersect + // with the requested span and unsupported TS regions. + return next(document, range, token); }, }, @@ -666,7 +665,7 @@ export class AngularLanguageClient implements vscode.Disposable { if (isApproved === undefined) { // Prompt the user asynchronously, without blocking current server initialization - this.promptForTsdkApproval(workspaceTsdk, stateKey); + this.promptForTsdkApproval(stateKey); } // Fall back to globalValue (or bundled) while waiting for approval or if rejected @@ -676,12 +675,12 @@ export class AngularLanguageClient implements vscode.Disposable { return jsTsTsdkInspect?.globalValue?.trim() ?? tsTsdkInspect?.globalValue?.trim() ?? ''; } - private async promptForTsdkApproval(workspaceTsdk: string, stateKey: string): Promise { + private async promptForTsdkApproval(stateKey: string): Promise { const allowOption = 'Allow'; const disallowOption = 'Disallow'; const choice = await vscode.window.showWarningMessage( - `This workspace configures a custom TypeScript compiler path (${workspaceTsdk}) via 'js/ts.tsdk.path' or 'typescript.tsdk'. ` + + `This workspace configures a custom TypeScript compiler path via 'js/ts.tsdk.path' or 'typescript.tsdk'. ` + `Do you want to allow the Angular Language Service to load the TypeScript compiler from this path?`, allowOption, disallowOption, diff --git a/vscode-ng-language-service/client/src/commands.ts b/vscode-ng-language-service/client/src/commands.ts index aa3f71c27cfd..d56cbfad5555 100644 --- a/vscode-ng-language-service/client/src/commands.ts +++ b/vscode-ng-language-service/client/src/commands.ts @@ -182,17 +182,20 @@ function goToTemplateForComponent(ngClient: AngularLanguageClient): Command { /** * Proxy command for opening links in jsdoc comments. * - * This is needed to avoid incorrectly rewriting uris. + * This is needed to avoid VS Code incorrectly rewriting file names. */ function openJsDocLinkCommand(): Command { return { id: OpenJsDocLinkCommandId, isTextEditorCommand: false, async execute(args) { - if (!args?.file) { + if (typeof args?.file !== 'string' || args.file.length === 0) { return; } - const uri = vscode.Uri.parse(args.file); + // Command URI arguments are untrusted. This value is a filesystem path, so use `Uri.file` + // to prevent URI schemes from selecting another VS Code resource provider. + // https://code.visualstudio.com/api/references/vscode-api#Uri.file + const uri = vscode.Uri.file(args.file); const document = await vscode.workspace.openTextDocument(uri); return await vscode.window.showTextDocument(document, { selection: new vscode.Range( diff --git a/vscode-ng-language-service/client/src/embedded_support.ts b/vscode-ng-language-service/client/src/embedded_support.ts index aacf868b4f7c..eae3b7fb3d71 100644 --- a/vscode-ng-language-service/client/src/embedded_support.ts +++ b/vscode-ng-language-service/client/src/embedded_support.ts @@ -11,11 +11,14 @@ import * as vscode from 'vscode'; const ANGULAR_PROPERTY_ASSIGNMENTS = new Set([ 'template', 'templateUrl', + 'styles', 'styleUrls', 'styleUrl', 'host', ]); +const ANGULAR_HOST_BINDING_DECORATORS = new Set(['HostBinding', 'HostListener']); + /** * Determines if the position is inside a decorator * property that supports language service features. @@ -27,10 +30,11 @@ export function isNotTypescriptOrSupportedDecoratorField( if (document.languageId !== 'typescript') { return true; } - return isPropertyAssignmentToStringOrStringInArray( + return isInsideAngularStringLiteral( document.getText(), document.offsetAt(position), ANGULAR_PROPERTY_ASSIGNMENTS, + ANGULAR_HOST_BINDING_DECORATORS, ); } @@ -65,27 +69,21 @@ export function isInsideStringLiteral( return true; } const offset = document.offsetAt(position); - const scanner = ts.createScanner(ts.ScriptTarget.ESNext, true /* skipTrivia */); - scanner.setText(document.getText()); + const {scanner, scan} = createTemplateAwareScanner(document.getText()); - let token: ts.SyntaxKind = scanner.scan(); + let token: ts.SyntaxKind = scan(); while (token !== ts.SyntaxKind.EndOfFileToken && scanner.getStartPos() < offset) { - const isStringToken = - token === ts.SyntaxKind.StringLiteral || - token === ts.SyntaxKind.NoSubstitutionTemplateLiteral; - const isCursorInToken = - scanner.getStartPos() <= offset && - scanner.getStartPos() + scanner.getTokenText().length >= offset; - if (isCursorInToken && isStringToken) { + if (isStringToken(token) && isCursorInToken(scanner, offset)) { return true; } - token = scanner.scan(); + token = scan(); } return false; } /** - * Basic scanner to determine if we're inside a string of a property with one of the given names. + * Basic scanner to determine if we're inside a string of a property with one of the given names, + * or inside a string argument of a decorator with one of the given names. * * This scanner is not currently robust or perfect but provides us with an accurate answer _most_ of * the time. @@ -95,24 +93,32 @@ export function isInsideStringLiteral( * `@Component` or `{styleUrls: [someFunction('stringL¦iteral')]}`, the @angular/language-service * will always give us the correct answer. This helper gives us a quick win for optimizing the * number of requests we send to the server. - * - * TODO(atscott): tagged templates don't work: #1872 / - * https://github.com/Microsoft/TypeScript/issues/20055 */ -function isPropertyAssignmentToStringOrStringInArray( +function isInsideAngularStringLiteral( documentText: string, offset: number, propertyAssignmentNames: Set, + decoratorNames: Set, ): boolean { - const scanner = ts.createScanner(ts.ScriptTarget.ESNext, true /* skipTrivia */); - scanner.setText(documentText); + const {scanner, scan} = createTemplateAwareScanner(documentText); - let token: ts.SyntaxKind = scanner.scan(); + let token: ts.SyntaxKind = scan(); let lastToken: ts.SyntaxKind | undefined; let lastTokenText: string | undefined; + let secondLastToken: ts.SyntaxKind | undefined; let unclosedBraces = 0; let unclosedBrackets = 0; + let unclosedParens = 0; let propertyAssignmentContext = false; + // Nesting depth at which the current property assignment context was entered. The context ends + // at the first terminator found at that same depth, i.e. the one that ends the assignment's + // initializer rather than one nested inside of it. + let contextBraces = 0; + let contextBrackets = 0; + let decoratorContext = false; + // Parenthesis depth at which the current decorator context was entered. The context ends at the + // closing parenthesis of the decorator call. + let contextParens = 0; while (token !== ts.SyntaxKind.EndOfFileToken && scanner.getStartPos() < offset) { if ( lastToken === ts.SyntaxKind.Identifier && @@ -121,36 +127,64 @@ function isPropertyAssignmentToStringOrStringInArray( propertyAssignmentNames.has(lastTokenText) ) { propertyAssignmentContext = true; - token = scanner.scan(); + contextBraces = unclosedBraces; + contextBrackets = unclosedBrackets; + token = scan(); continue; } - if (unclosedBraces === 0 && unclosedBrackets === 0 && isPropertyAssignmentTerminator(token)) { + if ( + propertyAssignmentContext && + unclosedBraces === contextBraces && + unclosedBrackets === contextBrackets && + isPropertyAssignmentTerminator(token) + ) { propertyAssignmentContext = false; } + if ( + secondLastToken === ts.SyntaxKind.AtToken && + lastToken === ts.SyntaxKind.Identifier && + lastTokenText !== undefined && + token === ts.SyntaxKind.OpenParenToken && + decoratorNames.has(lastTokenText) + ) { + decoratorContext = true; + contextParens = unclosedParens; + } + if ( + decoratorContext && + token === ts.SyntaxKind.CloseParenToken && + unclosedParens === contextParens + 1 + ) { + decoratorContext = false; + } + if (token === ts.SyntaxKind.OpenBracketToken) { unclosedBrackets++; } else if (token === ts.SyntaxKind.OpenBraceToken) { unclosedBraces++; + } else if (token === ts.SyntaxKind.OpenParenToken) { + unclosedParens++; } else if (token === ts.SyntaxKind.CloseBracketToken) { unclosedBrackets--; } else if (token === ts.SyntaxKind.CloseBraceToken) { unclosedBraces--; + } else if (token === ts.SyntaxKind.CloseParenToken) { + unclosedParens--; } - const isStringToken = - token === ts.SyntaxKind.StringLiteral || - token === ts.SyntaxKind.NoSubstitutionTemplateLiteral; - const isCursorInToken = - scanner.getStartPos() <= offset && - scanner.getStartPos() + scanner.getTokenText().length >= offset; - if (propertyAssignmentContext && isCursorInToken && isStringToken) { + if ( + (propertyAssignmentContext || decoratorContext) && + isStringToken(token) && + isCursorInToken(scanner, offset) + ) { return true; } lastTokenText = scanner.getTokenText(); + secondLastToken = lastToken; lastToken = token; - token = scanner.scan(); + token = scan(); } return false; @@ -164,3 +198,62 @@ function isPropertyAssignmentTerminator(token: ts.SyntaxKind) { token === ts.SyntaxKind.CloseBraceToken ); } + +function isStringToken(token: ts.SyntaxKind): boolean { + return ( + token === ts.SyntaxKind.StringLiteral || token === ts.SyntaxKind.NoSubstitutionTemplateLiteral + ); +} + +function isCursorInToken(scanner: ts.Scanner, offset: number): boolean { + return ( + scanner.getStartPos() <= offset && + scanner.getStartPos() + scanner.getTokenText().length >= offset + ); +} + +/** + * Creates a `ts.Scanner` for the given text along with a `scan` function that, unlike + * `ts.Scanner#scan`, handles template literals with substitutions correctly. + * + * The scanner has no notion of template substitutions on its own: it reports the `}` closing a + * `${...}` substitution as a plain `CloseBraceToken` and then treats the remainder of the template + * literal as the beginning of a new one, mis-scanning everything that follows it (see #65494). Just + * like the TypeScript parser, the returned `scan` function re-scans such braces as template + * continuations (`TemplateMiddle`/`TemplateTail`) instead. + */ +function createTemplateAwareScanner(text: string): { + scanner: ts.Scanner; + scan: () => ts.SyntaxKind; +} { + const scanner = ts.createScanner(ts.ScriptTarget.ESNext, true /* skipTrivia */); + scanner.setText(text); + + // Brace depth at which each currently open template substitution started, innermost last. + const substitutionDepths: number[] = []; + let braceDepth = 0; + + const scan = (): ts.SyntaxKind => { + let token = scanner.scan(); + if (token === ts.SyntaxKind.OpenBraceToken) { + braceDepth++; + } else if (token === ts.SyntaxKind.CloseBraceToken) { + if ( + substitutionDepths.length > 0 && + braceDepth === substitutionDepths[substitutionDepths.length - 1] + ) { + // This brace closes a template substitution rather than a block or object literal. + substitutionDepths.pop(); + token = scanner.reScanTemplateToken(false /* isTaggedTemplate */); + } else { + braceDepth--; + } + } + if (token === ts.SyntaxKind.TemplateHead || token === ts.SyntaxKind.TemplateMiddle) { + substitutionDepths.push(braceDepth); + } + return token; + }; + + return {scanner, scan}; +} diff --git a/vscode-ng-language-service/client/src/tests/embedded_support_spec.ts b/vscode-ng-language-service/client/src/tests/embedded_support_spec.ts index d24da813aef5..9586977daca7 100644 --- a/vscode-ng-language-service/client/src/tests/embedded_support_spec.ts +++ b/vscode-ng-language-service/client/src/tests/embedded_support_spec.ts @@ -9,6 +9,7 @@ import type * as vscode from 'vscode'; import {DocumentUri, TextDocument} from 'vscode-languageserver-textdocument'; import { + isInsideStringLiteral, isNotTypescriptOrSupportedDecoratorField, isNotTypescriptOrSupportedDecoratorRange, } from '../embedded_support'; @@ -90,6 +91,144 @@ describe('embedded language support', () => { false, ); }); + + it('inside styles declared before template', () => { + test( + `const foo = {styles: ['h1 { col¦or: red; }'], template: '
'}`, + isNotTypescriptOrSupportedDecoratorField, + true, + ); + }); + + it('inside a string of another property after template', () => { + test( + `const foo = {template: '
', selector: 'app¦-root'}`, + isNotTypescriptOrSupportedDecoratorField, + false, + ); + }); + + it('inside a string in the class body after a template in the decorator', () => { + test( + `@Component({template: '
'}) + export class AppComponent { + private property = 'd¦oe'; + }`, + isNotTypescriptOrSupportedDecoratorField, + false, + ); + }); + + it('inside a string of a nested host property', () => { + test( + `const foo = {host: {'[class.foo]': 'is¦Foo'}, selector: 'app-root'}`, + isNotTypescriptOrSupportedDecoratorField, + true, + ); + }); + + it('inside a @HostListener decorator string', () => { + test( + `@Component({template: '
'}) + export class AppComponent { + @HostListener('cl¦ick', ['$event']) onClick(event: Event) {} + }`, + isNotTypescriptOrSupportedDecoratorField, + true, + ); + }); + + it('inside a @HostBinding decorator string of a directive without template', () => { + test( + `@Directive({selector: '[foo]'}) + export class FooDirective { + @HostBinding('class.f¦oo') isFoo = true; + }`, + isNotTypescriptOrSupportedDecoratorField, + true, + ); + }); + + it('inside a string after a @HostListener decorator', () => { + test( + `@Component({template: '
'}) + export class AppComponent { + @HostListener('click', ['$event']) onClick(event: Event) { + console.log('cli¦cked'); + } + }`, + isNotTypescriptOrSupportedDecoratorField, + false, + ); + }); + + it('inside a string argument of a plain function call named like a decorator', () => { + test(`HostListener('cl¦ick');`, isNotTypescriptOrSupportedDecoratorField, false); + }); + + it('after a template literal with substitutions', () => { + test( + `@Component({template: \`\`}) + export class AppComponent { + private property = 'doe'; + private method(): void { + console.log(\`\${this.property}\`); + this.¦ + } + }`, + isNotTypescriptOrSupportedDecoratorField, + false, + ); + }); + + it('after a template literal with nested braces in a substitution', () => { + test( + `@Component({template: \`\`}) + export class AppComponent { + private method(): void { + console.log(\`\${{a: 1}.a} and \${[1, 2].map((x) => { return x; })}\`); + this.¦ + } + }`, + isNotTypescriptOrSupportedDecoratorField, + false, + ); + }); + + it('inside a template literal template with substitutions', () => { + test( + `const foo = {template: \`
\${value}\`}`, + isNotTypescriptOrSupportedDecoratorField, + false, + ); + }); + + it('inside a template literal template after a template literal with substitutions', () => { + test( + `const prefix = \`\${getPrefix()}-\`; + const foo = {template: \`
¦
\`}`, + isNotTypescriptOrSupportedDecoratorField, + true, + ); + }); + }); + + describe('isInsideStringLiteral', () => { + it('inside a string literal', () => { + test(`const foo = 'ba¦r';`, isInsideStringLiteral, true); + }); + + it('outside of a string literal', () => { + test(`const foo = 'bar'; const baz = 1¦;`, isInsideStringLiteral, false); + }); + + it('after a template literal with substitutions', () => { + test(`const foo = \`\${bar}\`; const baz = 1¦;`, isInsideStringLiteral, false); + }); + + it('inside a string literal after a template literal with substitutions', () => { + test(`const foo = \`\${bar}\`; const baz = 'qu¦x';`, isInsideStringLiteral, true); + }); }); describe('isNotTypescriptOrSupportedDecoratorRange', () => { diff --git a/vscode-ng-language-service/integration/e2e/helper.ts b/vscode-ng-language-service/integration/e2e/helper.ts index 883cd8f380d4..9242e4e073c1 100644 --- a/vscode-ng-language-service/integration/e2e/helper.ts +++ b/vscode-ng-language-service/integration/e2e/helper.ts @@ -1,13 +1,20 @@ import {setTimeout} from 'node:timers/promises'; import * as vscode from 'vscode'; -import {APP_COMPONENT, FOO_TEMPLATE} from '../test_constants'; +import { + APP_COMPONENT, + FOO_TEMPLATE, + INLAY_HINTS_COMPONENT, + INLAY_HINTS_EXTERNAL_TEMPLATE, +} from '../test_constants'; export const COMPLETION_COMMAND = 'vscode.executeCompletionItemProvider'; export const HOVER_COMMAND = 'vscode.executeHoverProvider'; export const DEFINITION_COMMAND = 'vscode.executeDefinitionProvider'; export const APP_COMPONENT_URI = vscode.Uri.file(APP_COMPONENT); export const FOO_TEMPLATE_URI = vscode.Uri.file(FOO_TEMPLATE); +export const INLAY_HINTS_COMPONENT_URI = vscode.Uri.file(INLAY_HINTS_COMPONENT); +export const INLAY_HINTS_EXTERNAL_TEMPLATE_URI = vscode.Uri.file(INLAY_HINTS_EXTERNAL_TEMPLATE); export async function activate(uri: vscode.Uri): Promise { await vscode.window.showTextDocument(uri); diff --git a/vscode-ng-language-service/integration/e2e/inlay_hints_spec.ts b/vscode-ng-language-service/integration/e2e/inlay_hints_spec.ts new file mode 100644 index 000000000000..87611b6d3e93 --- /dev/null +++ b/vscode-ng-language-service/integration/e2e/inlay_hints_spec.ts @@ -0,0 +1,93 @@ +import * as vscode from 'vscode'; +import {activate, INLAY_HINTS_COMPONENT_URI, INLAY_HINTS_EXTERNAL_TEMPLATE_URI} from './helper'; + +const INLAY_HINT_COMMAND = 'vscode.executeInlayHintProvider'; + +describe('Angular LS inlay hints', () => { + let previousForLoopVariableTypes: boolean | undefined; + let previousEditorInlayHintsEnabled: string | boolean | undefined; + + beforeAll(async () => { + const angularConfig = vscode.workspace.getConfiguration('angular'); + previousForLoopVariableTypes = angularConfig.get( + 'inlayHints.variableTypes.forLoopVariableTypes', + ); + await angularConfig.update( + 'inlayHints.variableTypes.forLoopVariableTypes', + true, + vscode.ConfigurationTarget.Workspace, + ); + + const editorConfig = vscode.workspace.getConfiguration('editor'); + previousEditorInlayHintsEnabled = editorConfig.get('inlayHints.enabled'); + await editorConfig.update('inlayHints.enabled', 'on', vscode.ConfigurationTarget.Workspace); + }); + + afterAll(async () => { + const angularConfig = vscode.workspace.getConfiguration('angular'); + await angularConfig.update( + 'inlayHints.variableTypes.forLoopVariableTypes', + previousForLoopVariableTypes, + vscode.ConfigurationTarget.Workspace, + ); + + const editorConfig = vscode.workspace.getConfiguration('editor'); + await editorConfig.update( + 'inlayHints.enabled', + previousEditorInlayHintsEnabled, + vscode.ConfigurationTarget.Workspace, + ); + }); + + it('should return an Angular-specific inlay hint for inline template', async () => { + await activate(INLAY_HINTS_COMPONENT_URI); + + const inlineDocument = await vscode.workspace.openTextDocument(INLAY_HINTS_COMPONENT_URI); + const inlineRange = new vscode.Range( + new vscode.Position(0, 0), + inlineDocument.lineAt(inlineDocument.lineCount - 1).range.end, + ); + const hints = await vscode.commands.executeCommand( + INLAY_HINT_COMMAND, + INLAY_HINTS_COMPONENT_URI, + inlineRange, + ); + + expect(hints).toBeDefined(); + expect(hints!.length).toBeGreaterThan(0); + + const hasNumberHint = hints!.some((hint) => { + const label = + typeof hint.label === 'string' ? hint.label : hint.label.map((l) => l.value).join(''); + return label.includes(': number'); + }); + expect(hasNumberHint).toBeTrue(); + }); + + it('should return an Angular-specific inlay hint for external template', async () => { + await activate(INLAY_HINTS_EXTERNAL_TEMPLATE_URI); + + const externalDocument = await vscode.workspace.openTextDocument( + INLAY_HINTS_EXTERNAL_TEMPLATE_URI, + ); + const externalRange = new vscode.Range( + new vscode.Position(0, 0), + externalDocument.lineAt(externalDocument.lineCount - 1).range.end, + ); + const hints = await vscode.commands.executeCommand( + INLAY_HINT_COMMAND, + INLAY_HINTS_EXTERNAL_TEMPLATE_URI, + externalRange, + ); + + expect(hints).toBeDefined(); + expect(hints!.length).toBeGreaterThan(0); + + const hasNumberHint = hints!.some((hint) => { + const label = + typeof hint.label === 'string' ? hint.label : hint.label.map((l) => l.value).join(''); + return label.includes(': number'); + }); + expect(hasNumberHint).toBeTrue(); + }); +}); diff --git a/vscode-ng-language-service/integration/lsp/ivy_spec.ts b/vscode-ng-language-service/integration/lsp/ivy_spec.ts index a8f9e614a5a3..6eae1718f02f 100644 --- a/vscode-ng-language-service/integration/lsp/ivy_spec.ts +++ b/vscode-ng-language-service/integration/lsp/ivy_spec.ts @@ -251,6 +251,39 @@ export class AppComponent { expect(response).toContain({startLine: 7, endLine: 8}); }); + it('provides folding ranges for inline templates with interpolated strings', async () => { + openTextDocument( + client, + APP_COMPONENT, + ` +import {Component, EventEmitter, Input, Output} from '@angular/core'; + +const suffix = '!'; + +@Component({ + selector: 'my-app', + template: \` +
+ + Hello \${suffix} + +
\`, +}) +export class AppComponent { + name = 'Angular'; +}`, + ); + const response = (await client.sendRequest(lsp.FoldingRangeRequest.type, { + textDocument: { + uri: APP_COMPONENT_URI, + }, + })) as lsp.FoldingRange[]; + expect(Array.isArray(response)).toBe(true); + expect(response.length).toEqual(2); + expect(response).toContain({startLine: 8, endLine: 11}); + expect(response).toContain({startLine: 9, endLine: 10}); + }); + it('provides folding ranges for control flow', async () => { openTextDocument( client, @@ -2420,7 +2453,7 @@ export class AppComponent { 'changes': { [APP_COMPONENT_MODULE_URI]: [ { - 'newText': '\nimport { BarComponent } from "./bar.component";', + 'newText': "\nimport { BarComponent } from './bar.component';", 'range': { // Line numbers adjusted for HighlightDirective import 'start': {'line': 6, 'character': 57}, diff --git a/vscode-ng-language-service/integration/project/app/inlay_hints.component.ts b/vscode-ng-language-service/integration/project/app/inlay_hints.component.ts new file mode 100644 index 000000000000..5700c29a1391 --- /dev/null +++ b/vscode-ng-language-service/integration/project/app/inlay_hints.component.ts @@ -0,0 +1,9 @@ +import {Component} from '@angular/core'; + +@Component({ + selector: 'inlay-hints', + template: `@for (item of [1, 2, 3]; track item) { + {{ item }} + }`, +}) +export class InlayHintsComponent {} diff --git a/vscode-ng-language-service/integration/project/app/inlay_hints_external.component.html b/vscode-ng-language-service/integration/project/app/inlay_hints_external.component.html new file mode 100644 index 000000000000..bef0f22339d2 --- /dev/null +++ b/vscode-ng-language-service/integration/project/app/inlay_hints_external.component.html @@ -0,0 +1,3 @@ +@for (item of [1, 2, 3]; track item) { + {{ item }} +} diff --git a/vscode-ng-language-service/integration/project/app/inlay_hints_external.component.ts b/vscode-ng-language-service/integration/project/app/inlay_hints_external.component.ts new file mode 100644 index 000000000000..0d3fa3fb74c9 --- /dev/null +++ b/vscode-ng-language-service/integration/project/app/inlay_hints_external.component.ts @@ -0,0 +1,7 @@ +import {Component} from '@angular/core'; + +@Component({ + selector: 'inlay-hints-external', + templateUrl: './inlay_hints_external.component.html', +}) +export class InlayHintsExternalComponent {} diff --git a/vscode-ng-language-service/integration/project/libs/post/package.json b/vscode-ng-language-service/integration/project/libs/post/package.json index 0b14cc125a54..793a2d9b1460 100644 --- a/vscode-ng-language-service/integration/project/libs/post/package.json +++ b/vscode-ng-language-service/integration/project/libs/post/package.json @@ -2,7 +2,7 @@ "name": "post", "version": "0.0.1", "peerDependencies": { - "@angular/core": "^22.1.0-next" + "@angular/core": "^22.2.0-next" }, "dependencies": { "tslib": "^2.3.0" diff --git a/vscode-ng-language-service/integration/project/package.json b/vscode-ng-language-service/integration/project/package.json index 253904eca5ac..caa791724aab 100644 --- a/vscode-ng-language-service/integration/project/package.json +++ b/vscode-ng-language-service/integration/project/package.json @@ -9,7 +9,7 @@ "rxjs": "7.8.2" }, "devDependencies": { - "ng-packagr": "22.1.0-next.3", + "ng-packagr": "22.2.0-next.5", "typescript": "6.0.3" }, "scripts": { diff --git a/vscode-ng-language-service/integration/project/tsconfig.json b/vscode-ng-language-service/integration/project/tsconfig.json index 6c611a1ce8d3..7cddc8659247 100644 --- a/vscode-ng-language-service/integration/project/tsconfig.json +++ b/vscode-ng-language-service/integration/project/tsconfig.json @@ -3,7 +3,6 @@ "moduleResolution": "bundler", "experimentalDecorators": true, "target": "es2015", - "strict": true, "typeRoots": ["node_modules/@types"], "paths": { "post": ["./dist/post"] diff --git a/vscode-ng-language-service/integration/test_constants.ts b/vscode-ng-language-service/integration/test_constants.ts index 38174ff69e73..2e0c5786b02e 100644 --- a/vscode-ng-language-service/integration/test_constants.ts +++ b/vscode-ng-language-service/integration/test_constants.ts @@ -30,4 +30,12 @@ export const FOO_TEMPLATE = join(PROJECT_PATH, 'app', 'foo.component.html'); export const FOO_TEMPLATE_URI = pathToFileURL(FOO_TEMPLATE).href; export const FOO_COMPONENT = join(PROJECT_PATH, 'app', 'foo.component.ts'); export const FOO_COMPONENT_URI = pathToFileURL(FOO_COMPONENT).href; +export const INLAY_HINTS_COMPONENT = join(PROJECT_PATH, 'app', 'inlay_hints.component.ts'); +export const INLAY_HINTS_COMPONENT_URI = pathToFileURL(INLAY_HINTS_COMPONENT).href; +export const INLAY_HINTS_EXTERNAL_TEMPLATE = join( + PROJECT_PATH, + 'app', + 'inlay_hints_external.component.html', +); +export const INLAY_HINTS_EXTERNAL_TEMPLATE_URI = pathToFileURL(INLAY_HINTS_EXTERNAL_TEMPLATE).href; export const TSCONFIG = join(PROJECT_PATH, 'tsconfig.json'); diff --git a/vscode-ng-language-service/package.json b/vscode-ng-language-service/package.json index c0132fa0460d..935bac59d029 100644 --- a/vscode-ng-language-service/package.json +++ b/vscode-ng-language-service/package.json @@ -2,7 +2,7 @@ "name": "ng-template", "displayName": "Angular Language Service", "description": "Editor services for Angular templates", - "version": "22.0.0-rc.0", + "version": "22.1.0", "private": true, "publisher": "Angular", "icon": "angular.png", @@ -415,7 +415,7 @@ "@types/jasmine-reporters": "~2.5.3", "@types/node": "^24.5.2", "@types/vscode": "^1.74.3", - "@vscode/test-electron": "~3.0.0", + "@vscode/test-electron": "~3.1.0", "@vscode/vsce": "~3.9.0", "jasmine": "6.3.0", "jasmine-core": "6.3.0", @@ -425,9 +425,9 @@ "vscode-languageclient": "9.0.1", "vscode-languageserver": "9.0.1", "vscode-languageserver-protocol": "3.17.5", - "vscode-languageserver-textdocument": "1.0.12", + "vscode-languageserver-textdocument": "1.0.14", "vscode-tmgrammar-test": "0.1.3", - "vscode-uri": "3.1.0", + "vscode-uri": "3.2.0", "xvfb": "^0.4.0" }, "repository": { diff --git a/vscode-ng-language-service/server/package.json b/vscode-ng-language-service/server/package.json index d506a6efdd59..acc72d2fcdae 100644 --- a/vscode-ng-language-service/server/package.json +++ b/vscode-ng-language-service/server/package.json @@ -25,7 +25,7 @@ "vscode-html-languageservice": "5.6.2", "vscode-css-languageservice": "6.3.10", "vscode-languageserver": "9.0.1", - "vscode-languageserver-textdocument": "^1.0.12", - "vscode-uri": "3.1.0" + "vscode-languageserver-textdocument": "1.0.14", + "vscode-uri": "3.2.0" } } diff --git a/vscode-ng-language-service/server/src/embedded_support.ts b/vscode-ng-language-service/server/src/embedded_support.ts index 1e14bec83b8f..d5a1e8145de1 100644 --- a/vscode-ng-language-service/server/src/embedded_support.ts +++ b/vscode-ng-language-service/server/src/embedded_support.ts @@ -38,6 +38,21 @@ export function getHTMLVirtualContent(sf: ts.SourceFile): string { content.slice(0, region.getStart(sf) + 1) + documentText.slice(region.getStart(sf) + 1, region.getEnd() - 1) + content.slice(region.getEnd() - 1); + + // Template literals may contain `${...}` substitutions, which are not part of the template + // text. Blank them out (preserving line breaks) so the HTML language service only sees the + // static parts of the template. + if (ts.isTemplateExpression(region)) { + let substitutionStart = region.head.end - 2; // position of the `${` + for (const span of region.templateSpans) { + const substitutionEnd = span.literal.getStart(sf) + 1; // position after the `}` + content = + content.slice(0, substitutionStart) + + documentText.slice(substitutionStart, substitutionEnd).replace(/[^\n]/g, ' ') + + content.slice(substitutionEnd); + substitutionStart = span.literal.end - 2; + } + } } return content; } @@ -95,7 +110,12 @@ function isAssignmentToPropertyWithName(node: ts.Node, propertyName: 'styles' | } function isInlineTemplateNode(node: ts.Node) { - return ts.isStringLiteralLike(node) ? isAssignmentToPropertyWithName(node, 'template') : false; + // Unlike styles, templates are also matched when written as a template literal with + // `${...}` substitutions. The substitutions themselves are blanked out when the virtual + // document is constructed. + return ts.isStringLiteralLike(node) || ts.isTemplateExpression(node) + ? isAssignmentToPropertyWithName(node, 'template') + : false; } /** diff --git a/vscode-ng-language-service/server/src/session.ts b/vscode-ng-language-service/server/src/session.ts index 4c4adff1a931..394998c4e623 100644 --- a/vscode-ng-language-service/server/src/session.ts +++ b/vscode-ng-language-service/server/src/session.ts @@ -535,7 +535,21 @@ export class Session { // If they are already part of a ConfiguredProject then the following is // not needed. if (!project || project.projectKind !== ts.server.ProjectKind.Configured) { - const {configFileName} = this.projectService.openClientFile(scriptInfo.fileName); + let {configFileName} = this.projectService.openClientFile(scriptInfo.fileName); + if (configFileName === undefined && isExternalTemplate(scriptInfo.fileName)) { + // When an external template loses its configured project after it was opened (e.g. + // because the corresponding component file was closed and the project graph was updated), + // the same best-effort used in `onDidOpenTextDocument` is needed here. + if (this.loadProjectForExternalTemplate(scriptInfo.fileName)) { + ({configFileName} = this.projectService.openClientFile(scriptInfo.fileName)); + } + if (configFileName === undefined) { + const componentProject = this.attachToComponentProject(scriptInfo); + if (componentProject) { + return componentProject; + } + } + } if (!configFileName) { // Failed to find a config file. There is nothing we could do. this.error(`No config file for ${scriptInfo.fileName}`); @@ -552,6 +566,49 @@ export class Session { return project; } + /** + * In a composite/solution-style project with references, TypeScript will _not_ open a project + * for an HTML file unless the file is explicitly included in the files/includes list. This is + * quite unlikely to be the case for HTML files. As a best-effort to fix this, we attempt to open + * a TS file with the same name so that its project is loaded. Most of the time, this is going to + * be the component file for the external template. + * https://github.com/angular/vscode-ng-language-service/issues/2149 + * + * Returns whether the component file was opened, i.e. whether the config lookup for the template + * is worth retrying. + */ + private loadProjectForExternalTemplate(templatePath: string): boolean { + const maybeComponentTsPath = componentPathForTemplate(templatePath); + if ( + this.projectService.openFiles.has(this.projectService.toPath(maybeComponentTsPath)) || + // Non-component HTML files (e.g. `src/index.html`) have no sibling `.ts`; skip the + // open/close so we don't walk directory trees looking for a config that can't exist. + !this.host.fileExists(maybeComponentTsPath) + ) { + return false; + } + this.projectService.openClientFile(maybeComponentTsPath); + this.projectService.closeClientFile(maybeComponentTsPath); + return true; + } + + /** + * Attaches an external template to the configured project of its component. Needed because + * `openClientFile` does not repeat the config lookup for a file that is already open, so it can + * still report no config file even though the component's project has since been loaded. + */ + private attachToComponentProject(scriptInfo: ts.server.ScriptInfo): ts.server.Project | null { + const componentProject = this.projectService + .getScriptInfo(componentPathForTemplate(scriptInfo.fileName)) + ?.containingProjects.find(isConfiguredProject); + if (!componentProject) { + return null; + } + scriptInfo.detachAllProjects(); + scriptInfo.attachToProject(componentProject); + return componentProject; + } + private onDidOpenTextDocument(params: lsp.DidOpenTextDocumentParams) { const {uri, languageId, text} = params.textDocument; const filePath = uriToFilePath(uri); @@ -568,19 +625,16 @@ export class Session { // buffer in the user's editor which has not been saved to disk. // See https://github.com/angular/vscode-ng-language-service/issues/632 let result = this.projectService.openClientFile(filePath, text, scriptKind); - // If the first opened file is an HTML file and the project is a composite/solution-style - // project with references, TypeScript will _not_ open a project unless the file is explicitly - // included in the files/includes list. This is quite unlikely to be the case for HTML files. - // As a best-effort to fix this, we attempt to open a TS file with the same name. Most of the - // time, this is going to be the component file for the external template. - // https://github.com/angular/vscode-ng-language-service/issues/2149 if (result.configFileName === undefined && languageId === LanguageId.HTML) { - const maybeComponentTsPath = filePath.replace(/\.html$/, '.ts'); - if (!this.projectService.openFiles.has(this.projectService.toPath(maybeComponentTsPath))) { - this.projectService.openClientFile(maybeComponentTsPath); - this.projectService.closeClientFile(maybeComponentTsPath); + if (this.loadProjectForExternalTemplate(filePath)) { result = this.projectService.openClientFile(filePath, text, scriptKind); } + if (result.configFileName === undefined) { + const scriptInfo = this.projectService.getScriptInfo(filePath); + if (scriptInfo) { + this.attachToComponentProject(scriptInfo); + } + } } const {configFileName, configFileErrors} = result; @@ -790,3 +844,7 @@ function isTypeScriptFile(path: string): boolean { function isExternalTemplate(path: string): boolean { return !isTypeScriptFile(path); } + +function componentPathForTemplate(templatePath: string): string { + return templatePath.replace(/\.html$/, '.ts'); +} diff --git a/vscode-ng-language-service/server/src/tests/embedded_support_spec.ts b/vscode-ng-language-service/server/src/tests/embedded_support_spec.ts index 5888251463d2..ae1901596ded 100644 --- a/vscode-ng-language-service/server/src/tests/embedded_support_spec.ts +++ b/vscode-ng-language-service/server/src/tests/embedded_support_spec.ts @@ -39,6 +39,27 @@ describe('server embedded support', () => { ); }); + it('handles template literals with substitutions', () => { + assertEmbeddedHTMLContent( + '@Component({template: `

${abc}

`}) export class MyCmp', + '

', + ); + }); + + it('handles template literals with multiple substitutions', () => { + assertEmbeddedHTMLContent( + '@Component({template: `

${a}b${c}

`})', + '

b

', + ); + }); + + it('preserves line breaks inside template literal substitutions', () => { + assertEmbeddedHTMLContent( + '@Component({template: `

${a +\nb}

`})', + '

\n

', + ); + }); + it('works as expected for CRLF', () => { assertEmbeddedHTMLContent( `@Component({template: 'abc123'})\r\nexport class MyComponent {}`, diff --git a/vscode-ng-language-service/syntaxes/inline-styles.json b/vscode-ng-language-service/syntaxes/inline-styles.json index 01c1a89ed118..a82bc2a383e8 100644 --- a/vscode-ng-language-service/syntaxes/inline-styles.json +++ b/vscode-ng-language-service/syntaxes/inline-styles.json @@ -75,7 +75,7 @@ ] }, "style": { - "begin": "\\s*([`|'|\"])", + "begin": "\\s*([`'\"])", "beginCaptures": { "1": { "name": "string" @@ -89,6 +89,10 @@ }, "contentName": "source.css.scss", "patterns": [ + { + "match": "\\\\[\\s\\S]", + "name": "constant.character.escape.ts" + }, { "include": "source.css.scss" } diff --git a/vscode-ng-language-service/syntaxes/inline-template.json b/vscode-ng-language-service/syntaxes/inline-template.json index 74a82d736ad3..6757e55e600d 100644 --- a/vscode-ng-language-service/syntaxes/inline-template.json +++ b/vscode-ng-language-service/syntaxes/inline-template.json @@ -50,7 +50,7 @@ ] }, "ngTemplate": { - "begin": "\\G\\s*([`|'|\"])", + "begin": "\\G\\s*([`'\"])", "beginCaptures": { "1": { "name": "string" @@ -64,6 +64,10 @@ }, "contentName": "text.html.derivative", "patterns": [ + { + "match": "\\\\[\\s\\S]", + "name": "constant.character.escape.ts" + }, { "include": "text.html.derivative" }, diff --git a/vscode-ng-language-service/syntaxes/src/inline-styles.ts b/vscode-ng-language-service/syntaxes/src/inline-styles.ts index 9e0bbd09917b..8acee371120d 100644 --- a/vscode-ng-language-service/syntaxes/src/inline-styles.ts +++ b/vscode-ng-language-service/syntaxes/src/inline-styles.ts @@ -44,13 +44,18 @@ export const InlineStyles: GrammarDefinition = { }, style: { - begin: /\s*([`|'|"])/, + begin: /\s*([`'"])/, beginCaptures: {1: {name: 'string'}}, // @ts-ignore end: /\1/, endCaptures: {0: {name: 'string'}}, contentName: 'source.css.scss', - patterns: [{include: 'source.css.scss'}], + patterns: [ + // Consume escape sequences first so that an escaped delimiter (e.g. \`) + // does not terminate the style string prematurely. + {match: /\\[\s\S]/, name: 'constant.character.escape.ts'}, + {include: 'source.css.scss'}, + ], }, }, }; diff --git a/vscode-ng-language-service/syntaxes/src/inline-template.ts b/vscode-ng-language-service/syntaxes/src/inline-template.ts index 915d53413b1a..176dba43a8b0 100644 --- a/vscode-ng-language-service/syntaxes/src/inline-template.ts +++ b/vscode-ng-language-service/syntaxes/src/inline-template.ts @@ -32,13 +32,19 @@ export const InlineTemplate: GrammarDefinition = { }, ngTemplate: { - begin: /\G\s*([`|'|"])/, + begin: /\G\s*([`'"])/, beginCaptures: {1: {name: 'string'}}, // @ts-ignore end: /\1/, endCaptures: {0: {name: 'string'}}, contentName: 'text.html.derivative', - patterns: [{include: 'text.html.derivative'}, {include: 'template.ng'}], + patterns: [ + // Consume escape sequences first so that an escaped delimiter (e.g. \`) + // does not terminate the template string prematurely. + {match: /\\[\s\S]/, name: 'constant.character.escape.ts'}, + {include: 'text.html.derivative'}, + {include: 'template.ng'}, + ], }, }, }; diff --git a/vscode-ng-language-service/syntaxes/src/template-blocks.ts b/vscode-ng-language-service/syntaxes/src/template-blocks.ts index a8b5f74cc2f8..d090b3319d61 100644 --- a/vscode-ng-language-service/syntaxes/src/template-blocks.ts +++ b/vscode-ng-language-service/syntaxes/src/template-blocks.ts @@ -19,7 +19,8 @@ export const TemplateBlocks: GrammarDefinition = { }, block: { - begin: /(@)(if|else if|else|defer|placeholder|loading|error|switch|for|empty)(?:\s*)/, + begin: + /(@)(if|else if|else|defer|placeholder|loading|error|switch|for|empty|boundary)(?:\s*)/, beginCaptures: { 1: { patterns: [{include: '#transition'}], diff --git a/vscode-ng-language-service/syntaxes/template-blocks.json b/vscode-ng-language-service/syntaxes/template-blocks.json index 55b5bb8888c5..05e094a13b13 100644 --- a/vscode-ng-language-service/syntaxes/template-blocks.json +++ b/vscode-ng-language-service/syntaxes/template-blocks.json @@ -12,7 +12,7 @@ "name": "keyword.control.block.transition.ng" }, "block": { - "begin": "(@)(if|else if|else|defer|placeholder|loading|error|switch|for|empty)(?:\\s*)", + "begin": "(@)(if|else if|else|defer|placeholder|loading|error|switch|for|empty|boundary)(?:\\s*)", "beginCaptures": { "1": { "patterns": [ diff --git a/vscode-ng-language-service/syntaxes/test/data/inline-styles.ts b/vscode-ng-language-service/syntaxes/test/data/inline-styles.ts index 54faa890bbda..9ef5b2907fbc 100644 --- a/vscode-ng-language-service/syntaxes/test/data/inline-styles.ts +++ b/vscode-ng-language-service/syntaxes/test/data/inline-styles.ts @@ -22,5 +22,9 @@ styles: `.example { width: 100px; }` , styles: ".example { width: 100px; }" , styles: '.example { width: 100px; }' , + +//// Escaped delimiter tests + styles: [ `.example::before { content: '\`'; }` ], + styles: [ '.example::before { content: "\'"; }' ], }) export class TMComponent{} diff --git a/vscode-ng-language-service/syntaxes/test/data/inline-styles.ts.snap b/vscode-ng-language-service/syntaxes/test/data/inline-styles.ts.snap index 3e1a8bf47b07..e6a574ab0431 100644 --- a/vscode-ng-language-service/syntaxes/test/data/inline-styles.ts.snap +++ b/vscode-ng-language-service/syntaxes/test/data/inline-styles.ts.snap @@ -150,6 +150,39 @@ # ^ inline-styles.ng string # ^ inline-styles.ng # ^^ inline-styles.ng +> +>//// Escaped delimiter tests +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inline-styles.ng +> styles: [ `.example::before { content: '\`'; }` ], +#^^ inline-styles.ng +# ^^^^^^ inline-styles.ng meta.object-literal.key.ts +# ^ inline-styles.ng meta.object-literal.key.ts punctuation.separator.key-value.ts +# ^ inline-styles.ng +# ^ inline-styles.ng meta.array.literal.ts meta.brace.square.ts +# ^ inline-styles.ng +# ^ inline-styles.ng string +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inline-styles.ng source.css.scss +# ^^ inline-styles.ng source.css.scss constant.character.escape.ts +# ^^^^ inline-styles.ng source.css.scss +# ^ inline-styles.ng string +# ^ inline-styles.ng +# ^ inline-styles.ng meta.array.literal.ts meta.brace.square.ts +# ^^ inline-styles.ng +> styles: [ '.example::before { content: "\'"; }' ], +#^^ inline-styles.ng +# ^^^^^^ inline-styles.ng meta.object-literal.key.ts +# ^ inline-styles.ng meta.object-literal.key.ts punctuation.separator.key-value.ts +# ^ inline-styles.ng +# ^ inline-styles.ng meta.array.literal.ts meta.brace.square.ts +# ^ inline-styles.ng +# ^ inline-styles.ng string +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inline-styles.ng source.css.scss +# ^^ inline-styles.ng source.css.scss constant.character.escape.ts +# ^^^^ inline-styles.ng source.css.scss +# ^ inline-styles.ng string +# ^ inline-styles.ng +# ^ inline-styles.ng meta.array.literal.ts meta.brace.square.ts +# ^^ inline-styles.ng >}) #^^^ inline-styles.ng >export class TMComponent{} diff --git a/vscode-ng-language-service/syntaxes/test/data/inline-template.ts b/vscode-ng-language-service/syntaxes/test/data/inline-template.ts index c900bf2458cb..75c92574f786 100644 --- a/vscode-ng-language-service/syntaxes/test/data/inline-template.ts +++ b/vscode-ng-language-service/syntaxes/test/data/inline-template.ts @@ -30,3 +30,17 @@ export class TMComponent{} template: '{{property}}', }) export class TMComponent{} + +/* Escaped delimiter tests */ +@Component({ + //// Escaped backtick test + template: ``, + + //// Escaped quote tests + template: '
Hello
', + template: "
Hello
", + + //// Escaped backslash before the closing delimiter + template: `
backslash \\
`, +}) +export class TMComponent{} diff --git a/vscode-ng-language-service/syntaxes/test/data/inline-template.ts.snap b/vscode-ng-language-service/syntaxes/test/data/inline-template.ts.snap index 131c015cc219..e766e9d6b8ce 100644 --- a/vscode-ng-language-service/syntaxes/test/data/inline-template.ts.snap +++ b/vscode-ng-language-service/syntaxes/test/data/inline-template.ts.snap @@ -117,4 +117,69 @@ #^^^ inline-template.ng >export class TMComponent{} #^^^^^^^^^^^^^^^^^^^^^^^^^^^ inline-template.ng +> +>/* Escaped delimiter tests */ +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inline-template.ng +>@Component({ +#^^^^^^^^^^^^^ inline-template.ng +> //// Escaped backtick test +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inline-template.ng +> template: ``, +#^^ inline-template.ng +# ^^^^^^^^ inline-template.ng meta.object-literal.key.ts +# ^ inline-template.ng meta.object-literal.key.ts punctuation.separator.key-value.ts +# ^ inline-template.ng +# ^ inline-template.ng string +# ^^^^^^^^^^^^^^^ inline-template.ng text.html.derivative +# ^^ inline-template.ng text.html.derivative constant.character.escape.ts +# ^^^^ inline-template.ng text.html.derivative +# ^^ inline-template.ng text.html.derivative constant.character.escape.ts +# ^^^^^^^^^^^^^^^^ inline-template.ng text.html.derivative +# ^ inline-template.ng string +# ^^ inline-template.ng +> +> //// Escaped quote tests +#^^^^^^^^^^^^^^^^^^^^^^^^^^^ inline-template.ng +> template: '
Hello
', +#^^ inline-template.ng +# ^^^^^^^^ inline-template.ng meta.object-literal.key.ts +# ^ inline-template.ng meta.object-literal.key.ts punctuation.separator.key-value.ts +# ^ inline-template.ng +# ^ inline-template.ng string +# ^^^^^^^^^^^^^^ inline-template.ng text.html.derivative +# ^^ inline-template.ng text.html.derivative constant.character.escape.ts +# ^^^^^^^^^^^^^^ inline-template.ng text.html.derivative +# ^ inline-template.ng string +# ^^ inline-template.ng +> template: "
Hello
", +#^^ inline-template.ng +# ^^^^^^^^ inline-template.ng meta.object-literal.key.ts +# ^ inline-template.ng meta.object-literal.key.ts punctuation.separator.key-value.ts +# ^ inline-template.ng +# ^ inline-template.ng string +# ^^^^^^^^^^^ inline-template.ng text.html.derivative +# ^^ inline-template.ng text.html.derivative constant.character.escape.ts +# ^^^^^^ inline-template.ng text.html.derivative +# ^^ inline-template.ng text.html.derivative constant.character.escape.ts +# ^^^^^^^^^^^^ inline-template.ng text.html.derivative +# ^ inline-template.ng string +# ^^ inline-template.ng +> +> //// Escaped backslash before the closing delimiter +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inline-template.ng +> template: `
backslash \\
`, +#^^ inline-template.ng +# ^^^^^^^^ inline-template.ng meta.object-literal.key.ts +# ^ inline-template.ng meta.object-literal.key.ts punctuation.separator.key-value.ts +# ^ inline-template.ng +# ^ inline-template.ng string +# ^^^^^^^^^^^^^^^ inline-template.ng text.html.derivative +# ^^ inline-template.ng text.html.derivative constant.character.escape.ts +# ^^^^^^ inline-template.ng text.html.derivative +# ^ inline-template.ng string +# ^^ inline-template.ng +>}) +#^^^ inline-template.ng +>export class TMComponent{} +#^^^^^^^^^^^^^^^^^^^^^^^^^^^ inline-template.ng > \ No newline at end of file diff --git a/vscode-ng-language-service/syntaxes/test/data/template-blocks.html b/vscode-ng-language-service/syntaxes/test/data/template-blocks.html index 628a4b0eb26a..182d76673b28 100644 --- a/vscode-ng-language-service/syntaxes/test/data/template-blocks.html +++ b/vscode-ng-language-service/syntaxes/test/data/template-blocks.html @@ -6,6 +6,10 @@ } +@boundary { + +} + @switch (a) { @case(0) @case (1) { {{getCase1()}} diff --git a/vscode-ng-language-service/syntaxes/test/data/template-blocks.html.snap b/vscode-ng-language-service/syntaxes/test/data/template-blocks.html.snap index 0de100e6d501..2c5a5ccd4721 100644 --- a/vscode-ng-language-service/syntaxes/test/data/template-blocks.html.snap +++ b/vscode-ng-language-service/syntaxes/test/data/template-blocks.html.snap @@ -27,6 +27,16 @@ >} #^ template.blocks.ng control.block.ng punctuation.definition.block.ts > +>@boundary { +#^ template.blocks.ng control.block.ng keyword.control.block.transition.ng +# ^^^^^^^^ template.blocks.ng control.block.ng keyword.control.block.kind.ng +# ^ template.blocks.ng control.block.ng +# ^ template.blocks.ng control.block.ng punctuation.definition.block.ts +> +#^^^^^^^^^^^^ template.blocks.ng control.block.ng control.block.body.ng +>} +#^ template.blocks.ng control.block.ng punctuation.definition.block.ts +> >@switch (a) { #^ template.blocks.ng control.block.ng keyword.control.block.transition.ng # ^^^^^^ template.blocks.ng control.block.ng keyword.control.block.kind.ng diff --git a/vscode-ng-language-service/tools/release.mts b/vscode-ng-language-service/tools/release.mts index b6ee5bbfef62..08996747d8ce 100644 --- a/vscode-ng-language-service/tools/release.mts +++ b/vscode-ng-language-service/tools/release.mts @@ -42,9 +42,6 @@ const packageJsonPath = 'vscode-ng-language-service/package.json'; /** The path to the `CHANGELOG.md` file for the extension. */ const changelogPath = 'vscode-ng-language-service/CHANGELOG.md'; -/** The remote URL for the angular/angular repository. */ -const angularRepoRemote = 'https://github.com/angular/angular.git'; - /** * The prefix for all release commits created by this script. This is used to filter commits when * determining the last release. @@ -81,8 +78,14 @@ async function main(): Promise { throw new Error(`Cannot release from non releasable branch ${branchToReleaseFrom}.`); } + const upstreamRemote = await getUpstreamRemoteName(); + const forkRemote = await getForkRemoteName(); + + console.log(chalk.blue(`Using upstream remote: ${upstreamRemote}`)); + console.log(chalk.blue(`Using fork remote: ${forkRemote}`)); + console.log(chalk.blue(`Releasing from ${branchToReleaseFrom}.`)); - await exec(`git fetch ${angularRepoRemote} ${branchToReleaseFrom} --tags`); + await exec(`git fetch ${upstreamRemote} ${branchToReleaseFrom} --tags`); const currentVersion = await getCurrentVersion(); const newVersion = await getNewVersion(currentVersion); @@ -93,21 +96,20 @@ async function main(): Promise { await installDependencies(); await buildExtension(); - const forkRemote = await getForkRemoteName(); await prepareReleasePullRequest( releaseBranch, `${releaseCommitPrefix}${newVersion}`, [packageJsonPath, changelogPath], forkRemote, ); - await waitForPRToBeMergedAndTag(newVersion, branchToReleaseFrom); + await waitForPRToBeMergedAndTag(newVersion, branchToReleaseFrom, upstreamRemote); await publishExtension(); await createGithubRelease(newVersion, changelog); if (branchToReleaseFrom !== 'main') { - await cherryPickChangelog(changelog, newVersion, forkRemote); + await cherryPickChangelog(changelog, newVersion, forkRemote, upstreamRemote); } console.log(chalk.green('VSCode extension release process complete!')); @@ -321,14 +323,16 @@ async function updatingPackageJsonVersion(newVersion: string): Promise { * This function prompts the user to confirm that the release PR has been merged. Once confirmed, * it fetches the latest changes from the upstream repository, finds the SHA of the merged release * commit, and then creates a Git tag with the format `vsix-` on that commit. Finally, - * it pushes the new tag to the origin. + * it pushes the new tag to the upstream repository. * * @param newVersion The new version number used to create the Git tag. * @param branchToReleaseFrom The branch that the release PR was merged into. + * @param upstreamRemote The remote name or URL used for the upstream repository. */ async function waitForPRToBeMergedAndTag( newVersion: string, branchToReleaseFrom: string, + upstreamRemote: string, ): Promise { console.log( chalk.yellow(` @@ -346,13 +350,14 @@ Once you press Enter, the process will tag and publish automatically. message: 'Press Enter once the release PR has been merged.', }); - await exec(`git fetch ${angularRepoRemote} ${branchToReleaseFrom}`); + await exec(`git fetch ${upstreamRemote} ${branchToReleaseFrom}`); const mergedCommitSha = await getLastReleaseSha(newVersion); console.log(chalk.green(`Tagging the commit: ${mergedCommitSha}`)); const tagName = getTagName(newVersion); await exec(`git tag ${tagName} ${mergedCommitSha}`); - await exec(`git push ${angularRepoRemote} tag ${tagName}`); + const pushTarget = await getPushTarget(upstreamRemote); + await exec(`git push ${pushTarget} tag ${tagName}`); console.log(chalk.green('Release tag pushed to origin.')); } @@ -381,7 +386,9 @@ async function buildExtension(): Promise { console.log(chalk.blue('Building VSCode extension...')); await execAndStream('pnpm', ['bazel', 'clean']); await execAndStream('pnpm', [ - 'pnpm --filter=ng-template run package', + '--filter=ng-template', + 'run', + 'package', ...additionBazelReleaseArgs, ]); @@ -414,8 +421,7 @@ async function createGithubRelease(version: string, changelog: string): Promise< 'Authorization': `Bearer ${token}`, 'X-GitHub-Api-Version': '2022-11-28', }; - const {owner, repo} = getRepoDetails(angularRepoRemote); - const githubReleasesApiUrl = `https://api.github.com/repos/${owner}/${repo}/releases`; + const githubReleasesApiUrl = 'https://api.github.com/repos/angular/angular/releases'; const response = await fetch(githubReleasesApiUrl, { method: 'POST', @@ -512,16 +518,19 @@ async function publishExtension(): Promise { * * @param changelog The changelog content to add. * @param newVersion The new version number. + * @param forkRemote The remote name for the fork repository. + * @param upstreamRemote The remote name or URL for the upstream repository. */ async function cherryPickChangelog( changelog: string, newVersion: string, forkRemote: string, + upstreamRemote: string, ): Promise { console.log(chalk.blue('Cherry-picking changelog to main...')); await exec(`git stash`); - await exec(`git fetch ${angularRepoRemote} main`); + await exec(`git fetch ${upstreamRemote} main`); const cherryPickBranch = `vscode-changelog-cherry-pick${newVersion}`; await exec(`git branch -D ${cherryPickBranch}`).catch(() => {}); await exec(`git checkout -b ${cherryPickBranch} FETCH_HEAD`); @@ -572,6 +581,24 @@ function execAndStream(command: string, args: string[], options: SpawnOptions = }); } +/** + * Gets all configured Git remotes as a map from remote name to remote URL. + * + * @returns A promise that resolves to a map of remote names to their URLs. + */ +async function getRemotes(): Promise> { + const {stdout} = await exec('git remote -v'); + const remotes = new Map(); + for (const line of stdout.split('\n')) { + const parts = line.split(/\s+/); + if (parts.length >= 2) { + const [name, url] = parts; + remotes.set(name, url); + } + } + return remotes; +} + /** * Gets the owner and repo name from a remote URL. * @@ -582,8 +609,8 @@ function getRepoDetails(remoteUrl: string): {owner: string; repo: string} { const match = remoteUrl.trim().match(/github\.com[/:]([\w-]+)\/([\w-]+)/); return { - owner: match ? match[1] : 'angular', - repo: match ? match[2] : 'angular', + owner: match ? match[1].toLowerCase() : 'angular', + repo: match ? match[2].toLowerCase() : 'angular', }; } @@ -631,6 +658,44 @@ function getTagName(version: string): string { return `${tagPrefix}${version}`; } +/** + * Gets the remote name or authenticated URL for the upstream angular repository (angular/angular). + * + * It checks existing configured remotes: + * - If any remote points to angular/angular, uses that remote. + * - If no remote points to angular/angular, falls back to an authenticated HTTPS URL using GITHUB_TOKEN. + * + * @returns The remote name or URL to use for upstream. + */ +async function getUpstreamRemoteName(): Promise { + const remotes = await getRemotes(); + for (const [name, url] of remotes) { + const details = getRepoDetails(url); + if (details.owner === 'angular' && details.repo === 'angular') { + return name; + } + } + + const token = ensureGithubToken(); + return `https://${token}@github.com/angular/angular.git`; +} + +/** + * Determines the target to push to for the upstream repository. + * If the remote URL is HTTPS without embedded credentials, it injects GITHUB_TOKEN to avoid interactive login prompts. + */ +async function getPushTarget(upstreamRemote: string): Promise { + const remotes = await getRemotes(); + const remoteUrl = remotes.get(upstreamRemote) ?? upstreamRemote; + + if (remoteUrl.startsWith('git@') || remoteUrl.startsWith('ssh://')) { + return upstreamRemote; + } + + const token = ensureGithubToken(); + return `https://${token}@github.com/angular/angular.git`; +} + /** * Gets the name of the remote to use as the user's fork. * @@ -642,15 +707,7 @@ function getTagName(version: string): string { * @returns The name of the remote to use. */ async function getForkRemoteName(): Promise { - const {stdout} = await exec('git remote -v'); - const remotes = new Map(); - for (const line of stdout.split('\n')) { - const parts = line.split(/\s+/); - if (parts.length >= 2) { - const [name, url] = parts; - remotes.set(name, url); - } - } + const remotes = await getRemotes(); const candidates: string[] = []; for (const [name, url] of remotes) { @@ -661,8 +718,6 @@ async function getForkRemoteName(): Promise { // If origin is a candidate, we prefer it appropriately IF it's likely the user's fork. // The check `getRepoDetails(url).owner !== 'angular'` already filters out upstream. - // So if `origin` is in candidates, it's safe to use? - // User wanted: "If origin exists and is a candidate ... return 'origin'". if (candidates.includes('origin')) { return 'origin'; } diff --git a/vscode-ng-language-service/tools/tsconfig.json b/vscode-ng-language-service/tools/tsconfig.json index 9b2421b70537..744838ed95a6 100644 --- a/vscode-ng-language-service/tools/tsconfig.json +++ b/vscode-ng-language-service/tools/tsconfig.json @@ -4,7 +4,6 @@ "module": "node16", "moduleResolution": "node16", "types": ["node"], - "strict": true, "esModuleInterop": true, "skipLibCheck": true } diff --git a/vscode-ng-language-service/tsconfig.json b/vscode-ng-language-service/tsconfig.json index c16efe42acdb..5562c88f0656 100644 --- a/vscode-ng-language-service/tsconfig.json +++ b/vscode-ng-language-service/tsconfig.json @@ -1,11 +1,11 @@ { "compilerOptions": { + "stableTypeOrdering": true, "target": "es2017", "module": "commonjs", "moduleResolution": "node", "types": ["node"], "sourceMap": true, - "strict": true, "esModuleInterop": true, "declaration": true, "skipLibCheck": true