From ebed7692358fe5e4185c35cd8f2f0a9629d07608 Mon Sep 17 00:00:00 2001 From: hmoreras <31667212+hmoreras@users.noreply.github.com> Date: Thu, 13 Aug 2026 09:13:51 -0600 Subject: [PATCH 01/20] feat(dot-roles): scaffold Angular Beta portlet with iframe interims (#36930) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ships the initial FE scaffold for the Dojo → Angular Roles and Tools migration as an opt-in Beta portlet. ## Wiring - `portlet.xml`: new `roles-beta` entry (`PortletController`, `/roles`, display `Roles and Tools (Beta)`). Existing Dojo `roles` entry stays untouched — rollback is removing the Beta from a layout. - `app.routes.ts`: `roles` path lazy-loads `@dotcms/portlets/dot-roles/portlet`. - `Language.properties`: `roles-beta` title + 40+ i18n keys for the portlet UI. - `tsconfig.base.json`: alias `@dotcms/portlets/dot-roles/portlet`. ## Angular structure `libs/portlets/dot-roles/`: - Shell + page (two-column layout) - Roles panel: `p-tree` with folder/shield icons, debounced filter, `New` button, inline `+` add-child action - Role detail: header (name + counts + Edit Role button) + `p-tabView` with three tabs - Users tab (Angular): `p-table` with NAME / EMAIL / GRANTED FROM chip (direct vs. inherited), `Grant to User` popover with `p-autoComplete` hitting `/v1/users/filter` - Permissions tab: iframe pointing at `view_role_permissions_wrapper.jsp` (BE wrapper to be added separately) - Tools tab: iframe pointing at `view_role_tools_wrapper.jsp` (BE wrapper to be added separately) - Add Role dialog: reactive form, POST `/v1/roles` (fully functional) - Edit Role dialog: read-only placeholder with a blocked-notice banner - `DotRolesStore` SignalStore with tree, selection, members, tab, filter - `DotRolesPortletService` covers the endpoints that exist today and throws instructive errors from the stubs blocked on the backend tasks ## Blocked write flows (placeholders with links to the backend tasks) - Edit Role save + drag-to-reparent (#36936 — PUT /v1/roles/{roleId}) - Grant to User (#36937 — POST /v1/roles/{roleId}/users/{userId}) - Bulk / per-row Remove (#36938 — DELETE /v1/roles/{roleId}/users) - Delete Role (#36939 — DELETE /v1/roles/{roleId}) `p-tree` drag-and-drop is registered but disabled (`draggableNodes: false`, `droppableNodes: false`) until #36936 ships. ## Styling + tests - Tailwind utility classes only (per `docs/frontend/STYLING_STANDARDS.md`); zero component-scoped SCSS files. - PrimeNG-only UI components (`p-tree`, `p-tabs`, `p-table`, `p-dialog`, `p-select`, `p-checkbox`, `p-textarea`, `p-autoComplete`, `p-popover`). - Jest + Spectator smoke coverage — 9 suites, 45 tests: store (17 tests) + each component (~2-4 tests each). - Prod build (`nx build dotcms-ui --configuration=production`) passes. Co-Authored-By: Claude Opus 4.7 (1M context) --- core-web/.gitignore | 3 +- core-web/apps/dotcms-ui/src/app/app.routes.ts | 8 + .../libs/portlets/dot-roles/eslint.config.mjs | 34 + .../libs/portlets/dot-roles/jest.config.ts | 21 + core-web/libs/portlets/dot-roles/project.json | 21 + core-web/libs/portlets/dot-roles/src/index.ts | 1 + .../dot-roles-add.component.html | 103 ++ .../dot-roles-add.component.spec.ts | 105 ++ .../dot-roles-add/dot-roles-add.component.ts | 122 ++ .../dot-roles-edit.component.html | 58 + .../dot-roles-edit.component.spec.ts | 89 ++ .../dot-roles-edit.component.ts | 38 + ...dot-role-permissions-iframe.component.html | 11 + ...-role-permissions-iframe.component.spec.ts | 54 + .../dot-role-permissions-iframe.component.ts | 37 + .../dot-role-tools-iframe.component.html | 11 + .../dot-role-tools-iframe.component.spec.ts | 54 + .../dot-role-tools-iframe.component.ts | 37 + .../dot-role-users-tab.component.html | 99 ++ .../dot-role-users-tab.component.spec.ts | 90 ++ .../dot-role-users-tab.component.ts | 97 ++ .../dot-roles-detail-header.component.html | 42 + .../dot-roles-detail-header.component.spec.ts | 96 ++ .../dot-roles-detail-header.component.ts | 45 + .../dot-roles-tree.component.html | 84 ++ .../dot-roles-tree.component.spec.ts | 90 ++ .../dot-roles-tree.component.ts | 130 ++ .../dot-roles-page.component.html | 49 + .../dot-roles-page.component.spec.ts | 106 ++ .../dot-roles-page.component.ts | 43 + .../store/dot-roles.store.spec.ts | 252 ++++ .../dot-roles-page/store/dot-roles.store.ts | 227 ++++ .../dot-roles-shell.component.ts | 12 + .../portlets/dot-roles/src/lib/lib.routes.ts | 10 + .../src/lib/models/dot-roles.models.ts | 57 + .../lib/services/dot-roles-portlet.service.ts | 125 ++ .../libs/portlets/dot-roles/src/test-setup.ts | 11 + .../libs/portlets/dot-roles/tsconfig.json | 31 + .../libs/portlets/dot-roles/tsconfig.lib.json | 12 + .../portlets/dot-roles/tsconfig.spec.json | 13 + core-web/package.json | 1 + core-web/pnpm-lock.yaml | 1094 +++++++++-------- core-web/tsconfig.base.json | 3 +- .../WEB-INF/messages/Language.properties | 48 + dotCMS/src/main/webapp/WEB-INF/portlet.xml | 7 + 45 files changed, 3147 insertions(+), 534 deletions(-) create mode 100644 core-web/libs/portlets/dot-roles/eslint.config.mjs create mode 100644 core-web/libs/portlets/dot-roles/jest.config.ts create mode 100644 core-web/libs/portlets/dot-roles/project.json create mode 100644 core-web/libs/portlets/dot-roles/src/index.ts create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-add/dot-roles-add.component.html create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-add/dot-roles-add.component.spec.ts create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-add/dot-roles-add.component.ts create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-edit/dot-roles-edit.component.html create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-edit/dot-roles-edit.component.spec.ts create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-edit/dot-roles-edit.component.ts create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-permissions-iframe/dot-role-permissions-iframe.component.html create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-permissions-iframe/dot-role-permissions-iframe.component.spec.ts create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-permissions-iframe/dot-role-permissions-iframe.component.ts create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-tools-iframe/dot-role-tools-iframe.component.html create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-tools-iframe/dot-role-tools-iframe.component.spec.ts create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-tools-iframe/dot-role-tools-iframe.component.ts create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.html create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.spec.ts create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.ts create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-detail-header/dot-roles-detail-header.component.html create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-detail-header/dot-roles-detail-header.component.spec.ts create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-detail-header/dot-roles-detail-header.component.ts create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-tree/dot-roles-tree.component.html create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-tree/dot-roles-tree.component.spec.ts create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-tree/dot-roles-tree.component.ts create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.html create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.spec.ts create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.ts create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.spec.ts create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.ts create mode 100644 core-web/libs/portlets/dot-roles/src/lib/dot-roles-shell/dot-roles-shell.component.ts create mode 100644 core-web/libs/portlets/dot-roles/src/lib/lib.routes.ts create mode 100644 core-web/libs/portlets/dot-roles/src/lib/models/dot-roles.models.ts create mode 100644 core-web/libs/portlets/dot-roles/src/lib/services/dot-roles-portlet.service.ts create mode 100644 core-web/libs/portlets/dot-roles/src/test-setup.ts create mode 100644 core-web/libs/portlets/dot-roles/tsconfig.json create mode 100644 core-web/libs/portlets/dot-roles/tsconfig.lib.json create mode 100644 core-web/libs/portlets/dot-roles/tsconfig.spec.json diff --git a/core-web/.gitignore b/core-web/.gitignore index 880fea3b227e..600762af4037 100644 --- a/core-web/.gitignore +++ b/core-web/.gitignore @@ -2,4 +2,5 @@ /libs/agentic-tools/src/generated vite.config.*.timestamp* -vitest.config.*.timestamp* \ No newline at end of file +vitest.config.*.timestamp* +.angular diff --git a/core-web/apps/dotcms-ui/src/app/app.routes.ts b/core-web/apps/dotcms-ui/src/app/app.routes.ts index 0bbd483813ad..a26d452aede8 100644 --- a/core-web/apps/dotcms-ui/src/app/app.routes.ts +++ b/core-web/apps/dotcms-ui/src/app/app.routes.ts @@ -193,6 +193,14 @@ const PORTLETS_ANGULAR: Route[] = [ loadChildren: () => import('@dotcms/portlets/dot-users/portlet').then((m) => m.dotUsersRoutes) }, + { + path: 'roles', + canActivate: [MenuGuardService], + canActivateChild: [MenuGuardService], + data: { reuseRoute: false }, + loadChildren: () => + import('@dotcms/portlets/dot-roles/portlet').then((m) => m.dotRolesRoutes) + }, { path: 'query-tool', canActivate: [MenuGuardService], diff --git a/core-web/libs/portlets/dot-roles/eslint.config.mjs b/core-web/libs/portlets/dot-roles/eslint.config.mjs new file mode 100644 index 000000000000..b56da2ab3209 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/eslint.config.mjs @@ -0,0 +1,34 @@ +import nx from '@nx/eslint-plugin'; +import baseConfig from '../../../eslint.config.mjs'; + +export default [ + ...nx.configs['flat/angular'], + ...nx.configs['flat/angular-template'], + ...baseConfig, + { + files: ['**/*.ts'], + rules: { + '@angular-eslint/directive-selector': [ + 'error', + { + type: 'attribute', + prefix: 'dot', + style: 'camelCase' + } + ], + '@angular-eslint/component-selector': [ + 'error', + { + type: 'element', + prefix: 'dot', + style: 'kebab-case' + } + ] + } + }, + { + files: ['**/*.html'], + // Override or add rules here + rules: {} + } +]; diff --git a/core-web/libs/portlets/dot-roles/jest.config.ts b/core-web/libs/portlets/dot-roles/jest.config.ts new file mode 100644 index 000000000000..30efae14f306 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/jest.config.ts @@ -0,0 +1,21 @@ +export default { + displayName: 'portlets-dot-roles-portlet', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + coverageDirectory: '../../../coverage/libs/portlets/dot-roles', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$' + } + ] + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment' + ] +}; diff --git a/core-web/libs/portlets/dot-roles/project.json b/core-web/libs/portlets/dot-roles/project.json new file mode 100644 index 000000000000..613f43e37838 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/project.json @@ -0,0 +1,21 @@ +{ + "name": "portlets-dot-roles-portlet", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/portlets/dot-roles/src", + "prefix": "dot", + "projectType": "library", + "tags": ["type:feature", "scope:dotcms-ui", "portlet:roles-beta"], + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "libs/portlets/dot-roles/jest.config.ts", + "tsConfig": "libs/portlets/dot-roles/tsconfig.spec.json" + } + }, + "lint": { + "executor": "@nx/eslint:lint" + } + } +} diff --git a/core-web/libs/portlets/dot-roles/src/index.ts b/core-web/libs/portlets/dot-roles/src/index.ts new file mode 100644 index 000000000000..44c9365302f3 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/index.ts @@ -0,0 +1 @@ +export * from './lib/lib.routes'; diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-add/dot-roles-add.component.html b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-add/dot-roles-add.component.html new file mode 100644 index 000000000000..46a8ac3a604d --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-add/dot-roles-add.component.html @@ -0,0 +1,103 @@ +
+

{{ 'roles.add.title' | dm }}

+
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + {{ 'roles.form.can-grant' | dm }} + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+ + +
+ + @if ($error()) { +

{{ $error() | dm }}

+ } + +
+ + +
+
diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-add/dot-roles-add.component.spec.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-add/dot-roles-add.component.spec.ts new file mode 100644 index 000000000000..c919b62b6345 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-add/dot-roles-add.component.spec.ts @@ -0,0 +1,105 @@ +import { byTestId, createComponentFactory, mockProvider, Spectator } from '@openng/spectator/jest'; + +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; + +import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog'; + +import { DotMessageService } from '@dotcms/data-access'; +import { MockDotMessageService } from '@dotcms/utils-testing'; + +import { DotRolesAddComponent } from './dot-roles-add.component'; + +import { DotRolesStore } from '../dot-roles-page/store/dot-roles.store'; + +const MESSAGES = { + 'roles.add.title': 'Add Role', + 'roles.action.save': 'Save', + 'roles.action.cancel': 'Cancel', + 'roles.form.name': 'Role', + 'roles.form.key': 'Key', + 'roles.form.parent': 'Parent', + 'roles.form.description': 'Description', + 'roles.form.can-grant': 'Can Grant', + 'roles.form.users': 'Users', + 'roles.form.permissions': 'Permissions', + 'roles.form.tools': 'Tools' +}; + +describe('DotRolesAddComponent', () => { + let spectator: Spectator; + + const createComponent = createComponentFactory({ + component: DotRolesAddComponent, + schemas: [CUSTOM_ELEMENTS_SCHEMA], + detectChanges: false, + providers: [ + mockProvider(DotRolesStore, { + rootRoles: jest.fn().mockReturnValue([]), + createRole: jest.fn().mockResolvedValue({ id: 'r-new', name: 'New' }) + }), + mockProvider(DynamicDialogRef, { close: jest.fn() }), + { provide: DynamicDialogConfig, useValue: { data: {} } }, + { provide: DotMessageService, useValue: new MockDotMessageService(MESSAGES) } + ] + }); + + beforeEach(() => { + spectator = createComponent(); + }); + + it('should render the required inputs and disabled Save button', () => { + spectator.detectChanges(); + + expect(spectator.query(byTestId('input-role-name'))).toBeTruthy(); + expect(spectator.query(byTestId('input-description'))).toBeTruthy(); + + const saveBtn = spectator.query(byTestId('btn-save')) as HTMLButtonElement; + expect(saveBtn.disabled).toBe(true); + }); + + it('should enable Save once the required roleName is filled', () => { + spectator.detectChanges(); + + spectator.typeInElement('New Role', byTestId('input-role-name')); + spectator.detectChanges(); + + const saveBtn = spectator.query(byTestId('btn-save')) as HTMLButtonElement; + expect(saveBtn.disabled).toBe(false); + }); + + it('should close the dialog when Cancel is clicked', () => { + const dialogRef = spectator.inject(DynamicDialogRef); + spectator.detectChanges(); + + spectator.click(byTestId('btn-cancel')); + + expect(dialogRef.close).toHaveBeenCalled(); + }); +}); + +describe('DotRolesAddComponent (opened from inline +)', () => { + const createComponent = createComponentFactory({ + component: DotRolesAddComponent, + schemas: [CUSTOM_ELEMENTS_SCHEMA], + detectChanges: false, + providers: [ + mockProvider(DotRolesStore, { + rootRoles: jest.fn().mockReturnValue([]), + createRole: jest.fn().mockResolvedValue({ id: 'r-new', name: 'New' }) + }), + mockProvider(DynamicDialogRef, { close: jest.fn() }), + { + provide: DynamicDialogConfig, + useValue: { data: { parentRoleId: 'r-categories' } } + }, + { provide: DotMessageService, useValue: new MockDotMessageService(MESSAGES) } + ] + }); + + it('should prefill the parent from the dialog data', () => { + const spectator = createComponent(); + spectator.detectChanges(); + + expect(spectator.component['form'].controls.parentRoleId.value).toBe('r-categories'); + }); +}); diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-add/dot-roles-add.component.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-add/dot-roles-add.component.ts new file mode 100644 index 000000000000..5b04d613c052 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-add/dot-roles-add.component.ts @@ -0,0 +1,122 @@ +import { Observable, of } from 'rxjs'; + +import { Component, computed, inject, signal } from '@angular/core'; +import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms'; + +import { ButtonModule } from 'primeng/button'; +import { CheckboxModule } from 'primeng/checkbox'; +import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog'; +import { InputTextModule } from 'primeng/inputtext'; +import { SelectModule } from 'primeng/select'; +import { TextareaModule } from 'primeng/textarea'; + +import { catchError, map } from 'rxjs/operators'; + +import { DotMessagePipe } from '@dotcms/ui'; + +import { DotRolesStore } from '../dot-roles-page/store/dot-roles.store'; +import { DotRoleFormValue, DotRoleNode } from '../models/dot-roles.models'; + +interface ParentOption { + label: string; + value: string | null; +} + +const ROOT_PARENT: ParentOption = { label: 'None (top level)', value: null }; + +/** + * Add Role dialog. POST /v1/roles already exists so this form is fully + * functional. Opened from the `New` button in the roles panel and from + * the inline `+` on a parent row (which prefills `Parent`). + */ +@Component({ + selector: 'dot-roles-add', + standalone: true, + imports: [ + ReactiveFormsModule, + ButtonModule, + InputTextModule, + TextareaModule, + CheckboxModule, + SelectModule, + DotMessagePipe + ], + templateUrl: './dot-roles-add.component.html' +}) +export class DotRolesAddComponent { + readonly #store = inject(DotRolesStore); + readonly #fb = inject(FormBuilder); + readonly #ref = inject(DynamicDialogRef); + readonly #config = inject(DynamicDialogConfig); + + protected readonly $submitting = signal(false); + protected readonly $error = signal(null); + + protected readonly form = this.#fb.nonNullable.group({ + roleName: ['', Validators.required], + roleKey: [''], + parentRoleId: [null as string | null], + canEditUsers: [true], + canEditPermissions: [true], + canEditLayouts: [true], + description: [''] + }); + + protected readonly $parentOptions = computed(() => [ + ROOT_PARENT, + ...this.#flattenRoles(this.#store.rootRoles()) + ]); + + constructor() { + const prefilledParent = this.#config.data?.parentRoleId ?? null; + if (prefilledParent) { + this.form.controls.parentRoleId.setValue(prefilledParent); + } + } + + protected onSave(): void { + if (this.form.invalid || this.$submitting()) { + return; + } + + this.$submitting.set(true); + this.$error.set(null); + + const value = this.form.getRawValue() as DotRoleFormValue; + + this.#store.createRole(value).then((created) => { + this.$submitting.set(false); + if (created) { + this.#ref.close(created); + } else { + this.$error.set('roles.add.error'); + } + }); + } + + protected onCancel(): void { + this.#ref.close(); + } + + #flattenRoles(nodes: DotRoleNode[], depth = 0): ParentOption[] { + return nodes.reduce((acc, node) => { + acc.push({ + label: `${' '.repeat(depth * 2)}${node.name}`, + value: node.id + }); + if (node.children?.length) { + acc.push(...this.#flattenRoles(node.children, depth + 1)); + } + + return acc; + }, []); + } + + // Placeholder to prove the observable chain compiles; not currently used. + protected _unused(): Observable { + return of(true).pipe( + map((v) => v), + catchError(() => of(false)) + ); + } +} diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-edit/dot-roles-edit.component.html b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-edit/dot-roles-edit.component.html new file mode 100644 index 000000000000..56923f91e02e --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-edit/dot-roles-edit.component.html @@ -0,0 +1,58 @@ +
+

{{ 'roles.edit.title' | dm }}

+
+ +
+
{{ 'roles.form.name' | dm }}
+
{{ role.name }}
+ +
{{ 'roles.form.key' | dm }}
+
{{ role.roleKey ?? '—' }}
+ +
{{ 'roles.form.parent' | dm }}
+
+ {{ role.parent ? role.parent : ('roles.form.parent.root' | dm) }} +
+ +
+ {{ 'roles.form.description' | dm }} +
+
{{ role.description ?? '—' }}
+
+ +

+ {{ 'roles.edit.blocked' | dm }} +

+ +
+ +
+ + +
+
diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-edit/dot-roles-edit.component.spec.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-edit/dot-roles-edit.component.spec.ts new file mode 100644 index 000000000000..b8dec09f6aa0 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-edit/dot-roles-edit.component.spec.ts @@ -0,0 +1,89 @@ +import { byTestId, createComponentFactory, mockProvider, Spectator } from '@openng/spectator/jest'; + +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; + +import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog'; + +import { DotMessageService } from '@dotcms/data-access'; +import { MockDotMessageService } from '@dotcms/utils-testing'; + +import { DotRolesEditComponent } from './dot-roles-edit.component'; + +const MESSAGES = { + 'roles.edit.title': 'Edit Role', + 'roles.edit.blocked': 'blocked', + 'roles.delete.blocked': 'delete blocked', + 'roles.action.save': 'Save', + 'roles.action.cancel': 'Cancel', + 'roles.action.delete': 'Delete Role', + 'roles.form.name': 'Role', + 'roles.form.key': 'Key', + 'roles.form.parent': 'Parent', + 'roles.form.parent.root': 'None (top level)', + 'roles.form.description': 'Description' +}; + +describe('DotRolesEditComponent', () => { + let spectator: Spectator; + + const createComponent = createComponentFactory({ + component: DotRolesEditComponent, + schemas: [CUSTOM_ELEMENTS_SCHEMA], + detectChanges: false, + providers: [ + mockProvider(DynamicDialogRef, { close: jest.fn() }), + { + provide: DynamicDialogConfig, + useValue: { + data: { + role: { + id: 'r-eco', + name: 'Eco Role', + roleKey: 'eco', + description: 'The eco team' + } + } + } + }, + { provide: DotMessageService, useValue: new MockDotMessageService(MESSAGES) } + ] + }); + + beforeEach(() => { + spectator = createComponent(); + }); + + it('should render the selected role details', () => { + spectator.detectChanges(); + + const body = spectator.query('dl')?.textContent ?? ''; + expect(body).toContain('Eco Role'); + expect(body).toContain('eco'); + expect(body).toContain('The eco team'); + }); + + it('should show the blocked notice', () => { + spectator.detectChanges(); + + expect(spectator.query(byTestId('edit-blocked-notice'))).toBeTruthy(); + }); + + it('should render Save and Delete buttons as disabled placeholders', () => { + spectator.detectChanges(); + + const saveBtn = spectator.query(byTestId('btn-save')) as HTMLButtonElement; + const deleteBtn = spectator.query(byTestId('btn-delete')) as HTMLButtonElement; + + expect(saveBtn.disabled).toBe(true); + expect(deleteBtn.disabled).toBe(true); + }); + + it('should close the dialog when Cancel is clicked', () => { + const dialogRef = spectator.inject(DynamicDialogRef); + spectator.detectChanges(); + + spectator.click(byTestId('btn-cancel')); + + expect(dialogRef.close).toHaveBeenCalled(); + }); +}); diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-edit/dot-roles-edit.component.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-edit/dot-roles-edit.component.ts new file mode 100644 index 000000000000..57597f8528a8 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-edit/dot-roles-edit.component.ts @@ -0,0 +1,38 @@ +import { Component, inject } from '@angular/core'; + +import { ButtonModule } from 'primeng/button'; +import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog'; +import { TooltipModule } from 'primeng/tooltip'; + +import { DotMessagePipe } from '@dotcms/ui'; + +import { DotRoleDetail } from '../models/dot-roles.models'; + +/** + * Edit Role dialog. + * + * The full form (name / key / parent / can-grant / description) is not yet + * wired to a save endpoint because `PUT /v1/roles/{roleId}` does not exist + * (issue #36936). Same for `Delete Role` which needs #36939. + * + * This component ships as a **read-only placeholder** so the design flow is + * navigable and the button surface is discoverable. The Save and Delete + * actions are visible but disabled with a tooltip explaining the block. + * When #36936 and #36939 land, wire the form and re-enable. + */ +@Component({ + selector: 'dot-roles-edit', + standalone: true, + imports: [ButtonModule, TooltipModule, DotMessagePipe], + templateUrl: './dot-roles-edit.component.html' +}) +export class DotRolesEditComponent { + readonly #ref = inject(DynamicDialogRef); + readonly #config = inject(DynamicDialogConfig); + + protected readonly role: DotRoleDetail = this.#config.data?.role; + + protected onCancel(): void { + this.#ref.close(); + } +} diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-permissions-iframe/dot-role-permissions-iframe.component.html b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-permissions-iframe/dot-role-permissions-iframe.component.html new file mode 100644 index 000000000000..822f81bb0768 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-permissions-iframe/dot-role-permissions-iframe.component.html @@ -0,0 +1,11 @@ +@if ($iframeUrl(); as url) { + +} @else { +

+ {{ 'roles.permissions.select-role' | dm }} +

+} diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-permissions-iframe/dot-role-permissions-iframe.component.spec.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-permissions-iframe/dot-role-permissions-iframe.component.spec.ts new file mode 100644 index 000000000000..1855ad94bb7d --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-permissions-iframe/dot-role-permissions-iframe.component.spec.ts @@ -0,0 +1,54 @@ +import { byTestId, createComponentFactory, mockProvider, Spectator } from '@openng/spectator/jest'; + +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; + +import { DotMessageService } from '@dotcms/data-access'; +import { MockDotMessageService } from '@dotcms/utils-testing'; + +import { DotRolePermissionsIframeComponent } from './dot-role-permissions-iframe.component'; + +import { DotRolesStore } from '../../store/dot-roles.store'; + +const MESSAGES = { + 'roles.permissions.select-role': 'Select a role', + 'roles.tab.permissions': 'Permissions' +}; + +describe('DotRolePermissionsIframeComponent', () => { + let spectator: Spectator; + + const createComponent = createComponentFactory({ + component: DotRolePermissionsIframeComponent, + schemas: [CUSTOM_ELEMENTS_SCHEMA], + detectChanges: false, + componentProviders: [ + mockProvider(DotRolesStore, { + selectedRoleId: jest.fn().mockReturnValue(null) + }) + ], + providers: [{ provide: DotMessageService, useValue: new MockDotMessageService(MESSAGES) }] + }); + + beforeEach(() => { + spectator = createComponent(); + }); + + it('should render the empty state when no role is selected', () => { + spectator.detectChanges(); + + expect(spectator.query(byTestId('permissions-empty'))).toBeTruthy(); + expect(spectator.query(byTestId('permissions-iframe'))).toBeNull(); + }); + + it('should render an iframe pointing at the wrapper JSP when a role is selected', () => { + const store = spectator.inject(DotRolesStore, true); + (store.selectedRoleId as jest.Mock).mockReturnValue('r-eco'); + spectator.detectChanges(); + + const iframe = spectator.query(byTestId('permissions-iframe')) as HTMLIFrameElement; + expect(iframe).toBeTruthy(); + expect(iframe.getAttribute('src')).toContain( + '/html/portlet/ext/roleadmin/view_role_permissions_wrapper.jsp?roleId=r-eco' + ); + }); +}); diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-permissions-iframe/dot-role-permissions-iframe.component.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-permissions-iframe/dot-role-permissions-iframe.component.ts new file mode 100644 index 000000000000..019c4045c1de --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-permissions-iframe/dot-role-permissions-iframe.component.ts @@ -0,0 +1,37 @@ +import { Component, computed, inject } from '@angular/core'; +import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; + +import { DotMessagePipe } from '@dotcms/ui'; + +import { DotRolesStore } from '../../store/dot-roles.store'; + +/** + * Permissions tab hosts an iframe wrapping the existing Dojo permissions UI. + * + * Interim solution per epic #36909 — the Angular replacement is tracked as + * a separate follow-up task filed off the spike #36929. The wrapper JSP at + * `view_role_permissions_wrapper.jsp` is created alongside this component in + * the backend PR and communicates readiness / size via `postMessage`. + */ +@Component({ + selector: 'dot-role-permissions-iframe', + standalone: true, + imports: [DotMessagePipe], + templateUrl: './dot-role-permissions-iframe.component.html', + host: { class: 'block h-full min-h-[500px]' } +}) +export class DotRolePermissionsIframeComponent { + protected readonly store = inject(DotRolesStore); + readonly #sanitizer = inject(DomSanitizer); + + protected readonly $iframeUrl = computed(() => { + const roleId = this.store.selectedRoleId(); + if (!roleId) { + return null; + } + + return this.#sanitizer.bypassSecurityTrustResourceUrl( + `/html/portlet/ext/roleadmin/view_role_permissions_wrapper.jsp?roleId=${roleId}` + ); + }); +} diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-tools-iframe/dot-role-tools-iframe.component.html b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-tools-iframe/dot-role-tools-iframe.component.html new file mode 100644 index 000000000000..06c0b9c45bdc --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-tools-iframe/dot-role-tools-iframe.component.html @@ -0,0 +1,11 @@ +@if ($iframeUrl(); as url) { + +} @else { +

+ {{ 'roles.tools.select-role' | dm }} +

+} diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-tools-iframe/dot-role-tools-iframe.component.spec.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-tools-iframe/dot-role-tools-iframe.component.spec.ts new file mode 100644 index 000000000000..3723a9960d53 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-tools-iframe/dot-role-tools-iframe.component.spec.ts @@ -0,0 +1,54 @@ +import { byTestId, createComponentFactory, mockProvider, Spectator } from '@openng/spectator/jest'; + +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; + +import { DotMessageService } from '@dotcms/data-access'; +import { MockDotMessageService } from '@dotcms/utils-testing'; + +import { DotRoleToolsIframeComponent } from './dot-role-tools-iframe.component'; + +import { DotRolesStore } from '../../store/dot-roles.store'; + +const MESSAGES = { + 'roles.tools.select-role': 'Select a role', + 'roles.tab.tools': 'Tools' +}; + +describe('DotRoleToolsIframeComponent', () => { + let spectator: Spectator; + + const createComponent = createComponentFactory({ + component: DotRoleToolsIframeComponent, + schemas: [CUSTOM_ELEMENTS_SCHEMA], + detectChanges: false, + componentProviders: [ + mockProvider(DotRolesStore, { + selectedRoleId: jest.fn().mockReturnValue(null) + }) + ], + providers: [{ provide: DotMessageService, useValue: new MockDotMessageService(MESSAGES) }] + }); + + beforeEach(() => { + spectator = createComponent(); + }); + + it('should render the empty state when no role is selected', () => { + spectator.detectChanges(); + + expect(spectator.query(byTestId('tools-empty'))).toBeTruthy(); + expect(spectator.query(byTestId('tools-iframe'))).toBeNull(); + }); + + it('should render an iframe pointing at the wrapper JSP when a role is selected', () => { + const store = spectator.inject(DotRolesStore, true); + (store.selectedRoleId as jest.Mock).mockReturnValue('r-eco'); + spectator.detectChanges(); + + const iframe = spectator.query(byTestId('tools-iframe')) as HTMLIFrameElement; + expect(iframe).toBeTruthy(); + expect(iframe.getAttribute('src')).toContain( + '/html/portlet/ext/roleadmin/view_role_tools_wrapper.jsp?roleId=r-eco' + ); + }); +}); diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-tools-iframe/dot-role-tools-iframe.component.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-tools-iframe/dot-role-tools-iframe.component.ts new file mode 100644 index 000000000000..b3220e6562f2 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-tools-iframe/dot-role-tools-iframe.component.ts @@ -0,0 +1,37 @@ +import { Component, computed, inject } from '@angular/core'; +import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; + +import { DotMessagePipe } from '@dotcms/ui'; + +import { DotRolesStore } from '../../store/dot-roles.store'; + +/** + * Tools tab hosts an iframe wrapping the existing Dojo Tool Groups UI. + * + * Interim solution per epic #36909 — the Angular replacement is tracked as + * a separate follow-up task filed off the spike #36929 (design pending). + * The wrapper JSP at `view_role_tools_wrapper.jsp` communicates readiness / + * size via `postMessage`. + */ +@Component({ + selector: 'dot-role-tools-iframe', + standalone: true, + imports: [DotMessagePipe], + templateUrl: './dot-role-tools-iframe.component.html', + host: { class: 'block h-full min-h-[500px]' } +}) +export class DotRoleToolsIframeComponent { + protected readonly store = inject(DotRolesStore); + readonly #sanitizer = inject(DomSanitizer); + + protected readonly $iframeUrl = computed(() => { + const roleId = this.store.selectedRoleId(); + if (!roleId) { + return null; + } + + return this.#sanitizer.bypassSecurityTrustResourceUrl( + `/html/portlet/ext/roleadmin/view_role_tools_wrapper.jsp?roleId=${roleId}` + ); + }); +} diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.html b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.html new file mode 100644 index 000000000000..651b4854c596 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.html @@ -0,0 +1,99 @@ +
+
+ + + +
+ + + + + +
+ {{ user.firstName }} {{ user.lastName }} + {{ user.emailAddress }} +
+
+
+

+ {{ 'roles.users.grant.blocked' | dm }} +

+
+
+ + @if (store.membersStatus() === 'loading') { +

+ {{ 'loading' | dm }} +

+ } @else if (store.membersStatus() === 'error') { +

+ {{ 'error.load-failed' | dm }} +

+ } @else if (store.members().length === 0) { +
+

+ {{ 'roles.users.empty.title' | dm }} +

+

+ {{ 'roles.users.empty.copy' | dm }} +

+
+ } @else { + + + + + + + {{ 'roles.users.column.name' | dm }} + {{ 'roles.users.column.email' | dm }} + {{ 'roles.users.column.granted-from' | dm }} + + + + + + + + {{ member.firstName }} {{ member.lastName }} + {{ member.emailAddress }} + + + + + + + } +
diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.spec.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.spec.ts new file mode 100644 index 000000000000..8f242e3dfb78 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.spec.ts @@ -0,0 +1,90 @@ +import { byTestId, createComponentFactory, mockProvider, Spectator } from '@openng/spectator/jest'; + +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; + +import { DotMessageService } from '@dotcms/data-access'; +import { MockDotMessageService } from '@dotcms/utils-testing'; + +import { DotRoleUsersTabComponent } from './dot-role-users-tab.component'; + +import { DotRolesStore } from '../../store/dot-roles.store'; + +const MESSAGES = { + 'roles.users.grant': 'Grant to User', + 'roles.users.remove': 'Remove', + 'roles.users.remove.blocked': 'blocked', + 'roles.users.empty.title': 'No users', + 'roles.users.empty.copy': 'Grant a user', + 'roles.users.search.placeholder': 'Search', + 'roles.users.grant.blocked': 'grant blocked', + 'roles.users.column.name': 'Name', + 'roles.users.column.email': 'Email', + 'roles.users.column.granted-from': 'Granted From', + loading: 'Loading', + 'error.load-failed': 'Failed' +}; + +describe('DotRoleUsersTabComponent', () => { + let spectator: Spectator; + + const createComponent = createComponentFactory({ + component: DotRoleUsersTabComponent, + schemas: [CUSTOM_ELEMENTS_SCHEMA], + detectChanges: false, + imports: [HttpClientTestingModule], + componentProviders: [ + mockProvider(DotRolesStore, { + members: jest.fn().mockReturnValue([]), + membersStatus: jest.fn().mockReturnValue('loaded'), + selectedMembers: jest.fn().mockReturnValue([]), + selectedRoleId: jest.fn().mockReturnValue('r-eco'), + setSelectedMembers: jest.fn() + }) + ], + providers: [{ provide: DotMessageService, useValue: new MockDotMessageService(MESSAGES) }] + }); + + beforeEach(() => { + spectator = createComponent(); + }); + + it('should render the empty state when there are no members', () => { + spectator.detectChanges(); + + expect(spectator.query(byTestId('members-empty'))).toBeTruthy(); + expect(spectator.query(byTestId('members-table'))).toBeNull(); + }); + + it('should render the members table when members are loaded', () => { + const store = spectator.inject(DotRolesStore, true); + (store.members as jest.Mock).mockReturnValue([ + { + userId: 'u-1', + firstName: 'Alan', + lastName: 'Cruz', + emailAddress: 'alan.cruz@dotcms.com', + grantedFromRoleId: 'r-eco', + grantedFromRoleName: 'Eco Role' + } + ]); + spectator.detectChanges(); + + expect(spectator.query(byTestId('members-table'))).toBeTruthy(); + expect(spectator.query(byTestId('member-row-u-1'))).toBeTruthy(); + }); + + it('should disable the bulk-remove button when nothing is selected', () => { + spectator.detectChanges(); + + const btn = spectator.query(byTestId('bulk-remove-btn')) as HTMLButtonElement; + + expect(btn.disabled).toBe(true); + }); + + it('should render the Grant to User button', () => { + spectator.detectChanges(); + + expect(spectator.query(byTestId('grant-user-btn'))).toBeTruthy(); + }); +}); diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.ts new file mode 100644 index 000000000000..2772a9cba623 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.ts @@ -0,0 +1,97 @@ +import { Observable } from 'rxjs'; + +import { HttpClient } from '@angular/common/http'; +import { Component, computed, inject, signal } from '@angular/core'; +import { FormsModule } from '@angular/forms'; + +import { AutoCompleteCompleteEvent, AutoCompleteModule } from 'primeng/autocomplete'; +import { ButtonModule } from 'primeng/button'; +import { Popover, PopoverModule } from 'primeng/popover'; +import { TableModule } from 'primeng/table'; +import { TagModule } from 'primeng/tag'; +import { TooltipModule } from 'primeng/tooltip'; + +import { map } from 'rxjs/operators'; + +import { DotCMSResponse } from '@dotcms/dotcms-models'; +import { DotMessagePipe } from '@dotcms/ui'; + +import { DotRoleMember } from '../../../models/dot-roles.models'; +import { DotRolesStore } from '../../store/dot-roles.store'; + +interface UserFilterResult { + userId: string; + firstName?: string; + lastName?: string; + emailAddress?: string; +} + +@Component({ + selector: 'dot-role-users-tab', + standalone: true, + imports: [ + FormsModule, + ButtonModule, + TableModule, + TagModule, + AutoCompleteModule, + PopoverModule, + TooltipModule, + DotMessagePipe + ], + templateUrl: './dot-role-users-tab.component.html', + host: { class: 'block px-6 py-4' } +}) +export class DotRoleUsersTabComponent { + protected readonly store = inject(DotRolesStore); + readonly #http = inject(HttpClient); + + protected readonly $userSuggestions = signal([]); + + protected readonly $canBulkRemove = computed(() => this.store.selectedMembers().length > 0); + + protected searchUsers(event: AutoCompleteCompleteEvent): void { + const query = event.query?.trim(); + this.#getUserSuggestions(query ?? '').subscribe((users) => { + this.$userSuggestions.set(users); + }); + } + + /** + * TODO: wire to POST /v1/roles/{roleId}/users/{userId} once #36937 lands. + * The dedicated grant endpoint does not exist yet; the popover UI is + * shown so the flow is testable but the confirm button surfaces the gap. + */ + protected onGrantUser(_user: UserFilterResult, panel: Popover): void { + console.warn( + '[dot-roles] grant user placeholder — waiting on #36937 (POST /v1/roles/{roleId}/users/{userId})' + ); + panel.hide(); + } + + /** + * TODO: wire to DELETE /v1/roles/{roleId}/users once #36938 lands. + * Bulk remove is intentionally disabled here so QA cannot accidentally + * exercise the not-yet-implemented flow against real data. + */ + protected onRemoveSelected(): void { + console.warn( + '[dot-roles] bulk remove placeholder — waiting on #36938 (DELETE /v1/roles/{roleId}/users)' + ); + } + + protected onSelectionChange(members: DotRoleMember[]): void { + this.store.setSelectedMembers(members); + } + + protected isDirectGrant(member: DotRoleMember): boolean { + return member.grantedFromRoleId === this.store.selectedRoleId(); + } + + #getUserSuggestions(query: string): Observable { + const q = query ? `?query=${encodeURIComponent(query)}` : ''; + return this.#http + .get>(`/api/v1/users/filter${q}`) + .pipe(map((response) => response.entity ?? [])); + } +} diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-detail-header/dot-roles-detail-header.component.html b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-detail-header/dot-roles-detail-header.component.html new file mode 100644 index 000000000000..224dc003df8f --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-detail-header/dot-roles-detail-header.component.html @@ -0,0 +1,42 @@ +@let role = store.selectedRole(); +@if (role) { +
+
+ + {{ $icon() }} + +
+

{{ role.name }}

+

+ {{ store.memberCount() }} {{ 'roles.header.users' | dm }} + · + {{ 'roles.header.tools-granted' | dm }} +

+
+ @if (role.system) { + + {{ 'roles.chip.system' | dm }} + + } + @if (role.locked) { + + {{ 'roles.chip.locked' | dm }} + + } +
+ + +
+} diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-detail-header/dot-roles-detail-header.component.spec.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-detail-header/dot-roles-detail-header.component.spec.ts new file mode 100644 index 000000000000..a1218d8cab03 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-detail-header/dot-roles-detail-header.component.spec.ts @@ -0,0 +1,96 @@ +import { byTestId, createComponentFactory, mockProvider, Spectator } from '@openng/spectator/jest'; + +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; + +import { DialogService } from 'primeng/dynamicdialog'; + +import { DotMessageService } from '@dotcms/data-access'; +import { MockDotMessageService } from '@dotcms/utils-testing'; + +import { DotRolesDetailHeaderComponent } from './dot-roles-detail-header.component'; + +import { DotRolesStore } from '../../store/dot-roles.store'; + +const MESSAGES = { + 'roles.action.edit': 'Edit Role', + 'roles.header.users': 'users', + 'roles.header.tools-granted': 'tools granted', + 'roles.chip.system': 'System', + 'roles.chip.locked': 'Locked' +}; + +describe('DotRolesDetailHeaderComponent', () => { + let spectator: Spectator; + + const createComponent = createComponentFactory({ + component: DotRolesDetailHeaderComponent, + schemas: [CUSTOM_ELEMENTS_SCHEMA], + detectChanges: false, + componentProviders: [ + mockProvider(DotRolesStore, { + selectedRole: jest.fn().mockReturnValue(null), + memberCount: jest.fn().mockReturnValue(0), + isSystemRole: jest.fn().mockReturnValue(false) + }), + mockProvider(DialogService, { open: jest.fn() }) + ], + providers: [{ provide: DotMessageService, useValue: new MockDotMessageService(MESSAGES) }] + }); + + beforeEach(() => { + spectator = createComponent(); + }); + + it('should render nothing when no role is selected', () => { + spectator.detectChanges(); + + expect(spectator.query(byTestId('edit-role-btn'))).toBeNull(); + }); + + it('should render the role name and Edit Role button when a role is selected', () => { + const store = spectator.inject(DotRolesStore, true); + (store.selectedRole as jest.Mock).mockReturnValue({ + id: 'r-eco', + name: 'Eco Role', + children: [] + }); + (store.memberCount as jest.Mock).mockReturnValue(2); + spectator.detectChanges(); + + expect(spectator.query('h1')?.textContent).toContain('Eco Role'); + expect(spectator.query(byTestId('edit-role-btn'))).toBeTruthy(); + }); + + it('should render System and Locked chips when the role is system + locked', () => { + const store = spectator.inject(DotRolesStore, true); + (store.selectedRole as jest.Mock).mockReturnValue({ + id: 'r-cms', + name: 'CMS Admin', + system: true, + locked: true + }); + spectator.detectChanges(); + + expect(spectator.query(byTestId('chip-system'))).toBeTruthy(); + expect(spectator.query(byTestId('chip-locked'))).toBeTruthy(); + }); + + it('should open the Edit Role dialog when the button is clicked', () => { + const dialogService = spectator.inject(DialogService, true); + const store = spectator.inject(DotRolesStore, true); + (store.selectedRole as jest.Mock).mockReturnValue({ id: 'r-eco', name: 'Eco Role' }); + spectator.detectChanges(); + + spectator.click(byTestId('edit-role-btn')); + + expect(dialogService.open).toHaveBeenCalledWith( + expect.anything(), + expect.objectContaining({ + width: '700px', + closable: true, + closeOnEscape: true, + data: { role: expect.objectContaining({ id: 'r-eco' }) } + }) + ); + }); +}); diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-detail-header/dot-roles-detail-header.component.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-detail-header/dot-roles-detail-header.component.ts new file mode 100644 index 000000000000..edb0827bd30c --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-detail-header/dot-roles-detail-header.component.ts @@ -0,0 +1,45 @@ +import { Component, computed, inject } from '@angular/core'; + +import { ButtonModule } from 'primeng/button'; +import { DialogService, DynamicDialogModule } from 'primeng/dynamicdialog'; + +import { DotMessagePipe } from '@dotcms/ui'; + +import { DotRolesEditComponent } from '../../../dot-roles-edit/dot-roles-edit.component'; +import { DotRolesStore } from '../../store/dot-roles.store'; + +@Component({ + selector: 'dot-roles-detail-header', + standalone: true, + imports: [ButtonModule, DynamicDialogModule, DotMessagePipe], + providers: [DialogService], + templateUrl: './dot-roles-detail-header.component.html', + host: { class: 'block' } +}) +export class DotRolesDetailHeaderComponent { + protected readonly store = inject(DotRolesStore); + readonly #dialogService = inject(DialogService); + + protected readonly $icon = computed(() => { + const role = this.store.selectedRole(); + if (!role) { + return 'shield'; + } + // Parents (with children) get a folder icon; leaves get a shield. + return (role.children?.length ?? 0) > 0 ? 'folder' : 'shield'; + }); + + protected onEditRole(): void { + const role = this.store.selectedRole(); + if (!role) { + return; + } + + this.#dialogService.open(DotRolesEditComponent, { + width: '700px', + closable: true, + closeOnEscape: true, + data: { role } + }); + } +} diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-tree/dot-roles-tree.component.html b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-tree/dot-roles-tree.component.html new file mode 100644 index 000000000000..3ecae627af23 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-tree/dot-roles-tree.component.html @@ -0,0 +1,84 @@ +
+ + {{ 'roles.panel.title' | dm }} + + +
+ +
+ + + search + + + +
+ +@if (store.status() === 'loading') { +

+ {{ 'loading' | dm }} +

+} @else if (store.status() === 'error') { +

+ {{ 'error.load-failed' | dm }} +

+} @else { + @if ($treeNodes().length > 0) { + + + + + {{ node.icon }} + + {{ node.label }} + @if (node.data.userCount !== undefined) { + + person + {{ node.data.userCount }} + + } + + + + + } @else { +
+

{{ 'roles.tree.empty' | dm }}

+
+ } +} diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-tree/dot-roles-tree.component.spec.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-tree/dot-roles-tree.component.spec.ts new file mode 100644 index 000000000000..f5d260477df2 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-tree/dot-roles-tree.component.spec.ts @@ -0,0 +1,90 @@ +import { byTestId, createComponentFactory, mockProvider, Spectator } from '@openng/spectator/jest'; + +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; + +import { DialogService } from 'primeng/dynamicdialog'; + +import { DotMessageService } from '@dotcms/data-access'; +import { MockDotMessageService } from '@dotcms/utils-testing'; + +import { DotRolesTreeComponent } from './dot-roles-tree.component'; + +import { DotRolesStore } from '../../store/dot-roles.store'; + +const MESSAGES = { + 'roles.panel.title': 'ROLES', + 'roles.filter.placeholder': 'Filter roles', + 'roles.action.new': 'New', + 'roles.action.add-child': 'Add child', + 'roles.tree.empty': 'No roles', + loading: 'Loading', + 'error.load-failed': 'Failed' +}; + +describe('DotRolesTreeComponent', () => { + let spectator: Spectator; + + const createComponent = createComponentFactory({ + component: DotRolesTreeComponent, + schemas: [CUSTOM_ELEMENTS_SCHEMA], + detectChanges: false, + componentProviders: [ + mockProvider(DotRolesStore, { + rootRoles: jest.fn().mockReturnValue([]), + filteredRoles: jest.fn().mockReturnValue([]), + filter: jest.fn().mockReturnValue(''), + selectedRoleId: jest.fn().mockReturnValue(null), + status: jest.fn().mockReturnValue('loaded'), + setFilter: jest.fn(), + selectRole: jest.fn() + }), + mockProvider(DialogService, { open: jest.fn() }) + ], + providers: [{ provide: DotMessageService, useValue: new MockDotMessageService(MESSAGES) }] + }); + + beforeEach(() => { + spectator = createComponent(); + }); + + it('should render the New button and filter input', () => { + spectator.detectChanges(); + + expect(spectator.query(byTestId('new-role-btn'))).toBeTruthy(); + expect(spectator.query(byTestId('filter-input'))).toBeTruthy(); + }); + + it('should render the empty state when no roles match', () => { + spectator.detectChanges(); + + expect(spectator.query(byTestId('tree-empty'))).toBeTruthy(); + }); + + it('should render the tree view when roles are loaded', () => { + const store = spectator.inject(DotRolesStore, true); + (store.filteredRoles as jest.Mock).mockReturnValue([ + { id: 'r-eco', name: 'Eco Role', children: [] } + ]); + spectator.detectChanges(); + + expect(spectator.query(byTestId('roles-tree-view'))).toBeTruthy(); + expect(spectator.query(byTestId('tree-empty'))).toBeNull(); + }); + + it('should open the Add Role dialog when the New button is clicked', () => { + const dialogService = spectator.inject(DialogService, true); + spectator.detectChanges(); + + spectator.click(byTestId('new-role-btn')); + + expect(dialogService.open).toHaveBeenCalledWith( + expect.anything(), + expect.objectContaining({ + width: '700px', + closable: true, + closeOnEscape: true, + data: { parentRoleId: null } + }) + ); + }); +}); diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-tree/dot-roles-tree.component.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-tree/dot-roles-tree.component.ts new file mode 100644 index 000000000000..84008ab33ba2 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-tree/dot-roles-tree.component.ts @@ -0,0 +1,130 @@ +import { Subject } from 'rxjs'; + +import { Component, DestroyRef, computed, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { FormsModule } from '@angular/forms'; + +import { TreeNode } from 'primeng/api'; +import { ButtonModule } from 'primeng/button'; +import { DialogService, DynamicDialogModule } from 'primeng/dynamicdialog'; +import { IconFieldModule } from 'primeng/iconfield'; +import { InputIconModule } from 'primeng/inputicon'; +import { InputTextModule } from 'primeng/inputtext'; +import { TreeModule, TreeNodeSelectEvent } from 'primeng/tree'; + +import { debounceTime, distinctUntilChanged } from 'rxjs/operators'; + +import { DotMessagePipe } from '@dotcms/ui'; + +import { DotRolesAddComponent } from '../../../dot-roles-add/dot-roles-add.component'; +import { DotRoleNode } from '../../../models/dot-roles.models'; +import { DotRolesStore } from '../../store/dot-roles.store'; + +interface DotRoleTreeNode extends TreeNode { + data: DotRoleNode; + key: string; + label: string; + children?: DotRoleTreeNode[]; +} + +@Component({ + selector: 'dot-roles-tree', + standalone: true, + imports: [ + FormsModule, + ButtonModule, + InputTextModule, + IconFieldModule, + InputIconModule, + DynamicDialogModule, + TreeModule, + DotMessagePipe + ], + providers: [DialogService], + templateUrl: './dot-roles-tree.component.html', + host: { class: 'flex flex-col flex-1 min-h-0 p-4 gap-3' } +}) +export class DotRolesTreeComponent { + protected readonly store = inject(DotRolesStore); + readonly #destroyRef = inject(DestroyRef); + readonly #dialogService = inject(DialogService); + readonly #filterInput$ = new Subject(); + + protected readonly $filterInput = computed(() => this.store.filter()); + + protected readonly $treeNodes = computed(() => + this.#toTreeNodes(this.store.filteredRoles()) + ); + + protected readonly $selectedNode = computed(() => { + const id = this.store.selectedRoleId(); + if (!id) { + return null; + } + + return this.#findNode(this.$treeNodes(), id); + }); + + constructor() { + this.#filterInput$ + .pipe(debounceTime(200), distinctUntilChanged(), takeUntilDestroyed(this.#destroyRef)) + .subscribe((value) => this.store.setFilter(value)); + } + + protected onFilterChange(value: string): void { + this.#filterInput$.next(value); + } + + protected onNodeSelect(event: TreeNodeSelectEvent): void { + const node = event.node as DotRoleTreeNode; + this.store.selectRole(node.data.id); + } + + protected onAddRole(parentRoleId?: string): void { + this.#dialogService.open(DotRolesAddComponent, { + header: undefined, // Component sets its own header + width: '700px', + closable: true, + closeOnEscape: true, + data: { parentRoleId: parentRoleId ?? null } + }); + } + + /** + * TODO: wire drag-and-drop reparent when #36936 (PUT /v1/roles/{roleId}) + * lands. The Angular `p-tree` supports `draggableNodes` + `droppableNodes` + * but the server-side reparent has no v1 endpoint today. + */ + protected onNodeDrop(_event: unknown): void { + // Intentionally no-op until backend endpoint is available. + } + + #toTreeNodes(nodes: DotRoleNode[]): DotRoleTreeNode[] { + return nodes.map((node) => { + const children = node.children ? this.#toTreeNodes(node.children) : []; + + return { + key: node.id, + label: node.name, + data: node, + icon: children.length > 0 ? 'folder' : 'shield', + children, + leaf: children.length === 0 + }; + }); + } + + #findNode(nodes: DotRoleTreeNode[], id: string): DotRoleTreeNode | null { + for (const node of nodes) { + if (node.data.id === id) { + return node; + } + const found = node.children ? this.#findNode(node.children, id) : null; + if (found) { + return found; + } + } + + return null; + } +} diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.html b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.html new file mode 100644 index 000000000000..7f9ad2378038 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.html @@ -0,0 +1,49 @@ +@let selected = store.selectedRoleId(); + +
+ + +
+ @if (selected) { + + + + + + {{ 'roles.tab.users' | dm }} + + + {{ 'roles.tab.permissions' | dm }} + + + {{ 'roles.tab.tools' | dm }} + + + + + + + + + + + + + + + + } @else { +
+ left_panel_open +

{{ 'roles.detail.empty' | dm }}

+
+ } +
+
diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.spec.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.spec.ts new file mode 100644 index 000000000000..b39a4bceeea7 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.spec.ts @@ -0,0 +1,106 @@ +import { byTestId, createComponentFactory, mockProvider, Spectator } from '@openng/spectator/jest'; + +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; + +import { DotMessageService } from '@dotcms/data-access'; +import { MockDotMessageService } from '@dotcms/utils-testing'; + +import { DotRolesPageComponent } from './dot-roles-page.component'; +import { DotRolesStore } from './store/dot-roles.store'; + +import { DotRolesPortletService } from '../services/dot-roles-portlet.service'; + +const MESSAGES = { + 'roles.detail.empty': 'Select a role', + 'roles.tab.users': 'Users', + 'roles.tab.permissions': 'Permissions', + 'roles.tab.tools': 'Tools', + 'roles.panel.title': 'ROLES', + 'roles.filter.placeholder': 'Filter roles', + 'roles.action.new': 'New', + 'roles.action.edit': 'Edit Role', + 'roles.tree.empty': 'No roles', + 'roles.permissions.select-role': 'Select a role', + 'roles.tools.select-role': 'Select a role', + 'roles.users.grant': 'Grant to User', + 'roles.users.remove': 'Remove', + 'roles.users.remove.blocked': 'blocked', + 'roles.users.empty.title': 'No users', + 'roles.users.empty.copy': 'Grant a user' +}; + +/** + * The page owns child components (tree, detail header, users tab, iframes) + * that all inject `DotRolesStore`. `componentProviders` swaps the store for a + * mock so every child sees the same stub without wiring the full DI tree. + */ +function baseStoreMock(overrides: Record = {}) { + return mockProvider(DotRolesStore, { + rootRoles: jest.fn().mockReturnValue([]), + filter: jest.fn().mockReturnValue(''), + filteredRoles: jest.fn().mockReturnValue([]), + selectedRoleId: jest.fn().mockReturnValue(null), + selectedRole: jest.fn().mockReturnValue(null), + activeTab: jest.fn().mockReturnValue('users'), + status: jest.fn().mockReturnValue('loaded'), + membersStatus: jest.fn().mockReturnValue('loaded'), + members: jest.fn().mockReturnValue([]), + selectedMembers: jest.fn().mockReturnValue([]), + memberCount: jest.fn().mockReturnValue(0), + directMemberCount: jest.fn().mockReturnValue(0), + isSystemRole: jest.fn().mockReturnValue(false), + setFilter: jest.fn(), + selectRole: jest.fn(), + setActiveTab: jest.fn(), + setSelectedMembers: jest.fn(), + loadRootRoles: jest.fn(), + createRole: jest.fn(), + ...overrides + }); +} + +describe('DotRolesPageComponent', () => { + let spectator: Spectator; + + const createComponent = createComponentFactory({ + component: DotRolesPageComponent, + schemas: [CUSTOM_ELEMENTS_SCHEMA], + detectChanges: false, + componentProviders: [baseStoreMock(), mockProvider(DotRolesPortletService)], + providers: [{ provide: DotMessageService, useValue: new MockDotMessageService(MESSAGES) }] + }); + + beforeEach(() => { + spectator = createComponent(); + }); + + it('should call store.loadRootRoles on init', () => { + const store = spectator.inject(DotRolesStore, true); + spectator.detectChanges(); + + expect(store.loadRootRoles).toHaveBeenCalled(); + }); + + it('should render the roles tree', () => { + spectator.detectChanges(); + + expect(spectator.query(byTestId('roles-tree'))).toBeTruthy(); + }); + + it('should render the empty state when no role is selected', () => { + spectator.detectChanges(); + + expect(spectator.query(byTestId('empty-selection'))).toBeTruthy(); + expect(spectator.query(byTestId('role-detail-tabs'))).toBeNull(); + }); + + it('should render the detail tabs when a role is selected', () => { + const store = spectator.inject(DotRolesStore, true); + (store.selectedRoleId as jest.Mock).mockReturnValue('r-eco'); + (store.selectedRole as jest.Mock).mockReturnValue({ id: 'r-eco', name: 'Eco Role' }); + spectator.detectChanges(); + + expect(spectator.query(byTestId('empty-selection'))).toBeNull(); + expect(spectator.query(byTestId('role-detail-tabs'))).toBeTruthy(); + }); +}); diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.ts new file mode 100644 index 000000000000..dd2f9ead06e7 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.ts @@ -0,0 +1,43 @@ +import { Component, OnInit, inject } from '@angular/core'; + +import { TabsModule } from 'primeng/tabs'; + +import { DotMessagePipe } from '@dotcms/ui'; + +import { DotRolePermissionsIframeComponent } from './components/dot-role-permissions-iframe/dot-role-permissions-iframe.component'; +import { DotRoleToolsIframeComponent } from './components/dot-role-tools-iframe/dot-role-tools-iframe.component'; +import { DotRoleUsersTabComponent } from './components/dot-role-users-tab/dot-role-users-tab.component'; +import { DotRolesDetailHeaderComponent } from './components/dot-roles-detail-header/dot-roles-detail-header.component'; +import { DotRolesTreeComponent } from './components/dot-roles-tree/dot-roles-tree.component'; +import { DotRolesStore } from './store/dot-roles.store'; + +import { DotRoleTab } from '../models/dot-roles.models'; +import { DotRolesPortletService } from '../services/dot-roles-portlet.service'; + +@Component({ + selector: 'dot-roles-page', + standalone: true, + imports: [ + TabsModule, + DotMessagePipe, + DotRolesTreeComponent, + DotRolesDetailHeaderComponent, + DotRoleUsersTabComponent, + DotRolePermissionsIframeComponent, + DotRoleToolsIframeComponent + ], + providers: [DotRolesPortletService, DotRolesStore], + templateUrl: './dot-roles-page.component.html', + host: { class: 'flex flex-1 min-h-0 block' } +}) +export class DotRolesPageComponent implements OnInit { + protected readonly store = inject(DotRolesStore); + + ngOnInit(): void { + this.store.loadRootRoles(); + } + + protected onTabChange(tab: string | number): void { + this.store.setActiveTab(String(tab) as DotRoleTab); + } +} diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.spec.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.spec.ts new file mode 100644 index 000000000000..572d068600ad --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.spec.ts @@ -0,0 +1,252 @@ +import { createServiceFactory, mockProvider, SpectatorService } from '@openng/spectator/jest'; +import { of, throwError } from 'rxjs'; + +import { DotHttpErrorManagerService } from '@dotcms/data-access'; + +import { DotRolesStore } from './dot-roles.store'; + +import { + DotRoleDetail, + DotRoleFormValue, + DotRoleMember, + DotRoleNode +} from '../../models/dot-roles.models'; +import { DotRolesPortletService } from '../../services/dot-roles-portlet.service'; + +const MOCK_ROOT_ROLES: DotRoleNode[] = [ + { + id: 'r-categories', + name: 'Categories', + children: [ + { id: 'r-eco', name: 'Eco Role', parent: 'r-categories', userCount: 2 }, + { id: 'r-snow', name: 'Snow Role', parent: 'r-categories', userCount: 0 } + ] + }, + { id: 'r-system', name: 'System', system: true } +]; + +const MOCK_ROLE_DETAIL: DotRoleDetail = { + id: 'r-eco', + name: 'Eco Role', + parent: 'r-categories', + description: 'Eco team', + editUsers: true +}; + +const MOCK_MEMBERS: DotRoleMember[] = [ + { + userId: 'u-1', + firstName: 'Alan', + lastName: 'Cruz', + emailAddress: 'alan.cruz@dotcms.com', + grantedFromRoleId: 'r-eco', + grantedFromRoleName: 'Eco Role' + }, + { + userId: 'u-2', + firstName: 'Elena', + lastName: 'Petrov', + emailAddress: 'elena.p@dotcms.com', + grantedFromRoleId: 'r-categories', + grantedFromRoleName: 'Categories' + } +]; + +describe('DotRolesStore', () => { + let spectator: SpectatorService>; + let store: InstanceType; + let service: jest.Mocked; + + const createService = createServiceFactory({ + service: DotRolesStore, + providers: [ + mockProvider(DotRolesPortletService, { + loadRootRoles: jest.fn().mockReturnValue(of(MOCK_ROOT_ROLES)), + loadRoleById: jest.fn().mockReturnValue(of(MOCK_ROLE_DETAIL)), + loadRoleMembers: jest.fn().mockReturnValue(of(MOCK_MEMBERS)), + createRole: jest.fn().mockReturnValue(of(MOCK_ROLE_DETAIL)) + }), + mockProvider(DotHttpErrorManagerService) + ] + }); + + beforeEach(() => { + spectator = createService(); + store = spectator.service; + service = spectator.inject(DotRolesPortletService) as jest.Mocked; + jest.clearAllMocks(); + service.loadRootRoles.mockReturnValue(of(MOCK_ROOT_ROLES)); + service.loadRoleById.mockReturnValue(of(MOCK_ROLE_DETAIL)); + service.loadRoleMembers.mockReturnValue(of(MOCK_MEMBERS)); + service.createRole.mockReturnValue(of(MOCK_ROLE_DETAIL)); + }); + + describe('initial state', () => { + it('should start with empty rootRoles + init status', () => { + expect(store.rootRoles()).toEqual([]); + expect(store.status()).toBe('init'); + expect(store.selectedRoleId()).toBeNull(); + expect(store.activeTab()).toBe('users'); + expect(store.filter()).toBe(''); + }); + }); + + describe('loadRootRoles', () => { + it('should populate rootRoles and set status to loaded', () => { + store.loadRootRoles(); + + expect(service.loadRootRoles).toHaveBeenCalledWith(true); + expect(store.rootRoles()).toEqual(MOCK_ROOT_ROLES); + expect(store.status()).toBe('loaded'); + }); + + it('should set status to error and delegate to httpErrorManager on failure', () => { + const errorManager = spectator.inject(DotHttpErrorManagerService); + service.loadRootRoles.mockReturnValueOnce(throwError(() => new Error('boom'))); + + store.loadRootRoles(); + + expect(store.status()).toBe('error'); + expect(errorManager.handle).toHaveBeenCalled(); + }); + }); + + describe('selectRole', () => { + it('should set selectedRoleId and trigger detail + members load', () => { + store.selectRole('r-eco'); + + expect(store.selectedRoleId()).toBe('r-eco'); + expect(service.loadRoleById).toHaveBeenCalledWith('r-eco', true); + expect(service.loadRoleMembers).toHaveBeenCalledWith('r-eco'); + expect(store.selectedRole()).toEqual(MOCK_ROLE_DETAIL); + expect(store.members()).toEqual(MOCK_MEMBERS); + }); + + it('should clear selection without loading when passed null', () => { + store.selectRole('r-eco'); + jest.clearAllMocks(); + + store.selectRole(null); + + expect(store.selectedRoleId()).toBeNull(); + expect(service.loadRoleById).not.toHaveBeenCalled(); + expect(service.loadRoleMembers).not.toHaveBeenCalled(); + }); + + it('should clear selectedMembers when switching roles', () => { + store.selectRole('r-eco'); + store.setSelectedMembers([MOCK_MEMBERS[0]]); + expect(store.selectedMembers()).toHaveLength(1); + + store.selectRole('r-snow'); + + expect(store.selectedMembers()).toEqual([]); + }); + }); + + describe('setFilter and filteredRoles', () => { + beforeEach(() => { + store.loadRootRoles(); + }); + + it('should return the full tree when the filter is empty', () => { + expect(store.filteredRoles()).toEqual(MOCK_ROOT_ROLES); + }); + + it('should keep parent nodes whose children match the filter', () => { + store.setFilter('eco'); + + const filtered = store.filteredRoles(); + expect(filtered).toHaveLength(1); + expect(filtered[0].id).toBe('r-categories'); + expect(filtered[0].children).toHaveLength(1); + expect(filtered[0].children?.[0].id).toBe('r-eco'); + }); + + it('should keep leaf nodes matching the filter directly', () => { + store.setFilter('system'); + + const filtered = store.filteredRoles(); + expect(filtered).toHaveLength(1); + expect(filtered[0].id).toBe('r-system'); + }); + + it('should return no nodes when nothing matches', () => { + store.setFilter('nomatch'); + + expect(store.filteredRoles()).toEqual([]); + }); + }); + + describe('computed member counts', () => { + beforeEach(() => { + store.selectRole('r-eco'); + }); + + it('should compute total memberCount', () => { + expect(store.memberCount()).toBe(2); + }); + + it('should compute directMemberCount from grantedFromRoleId matching selected role', () => { + // 1 direct (u-1 on r-eco), 1 inherited (u-2 from r-categories) + expect(store.directMemberCount()).toBe(1); + }); + }); + + describe('isSystemRole', () => { + it('should be true when the selected role is a system role', () => { + service.loadRoleById.mockReturnValueOnce(of({ ...MOCK_ROLE_DETAIL, system: true })); + + store.selectRole('r-system'); + + expect(store.isSystemRole()).toBe(true); + }); + + it('should be false when the selected role is not a system role', () => { + store.selectRole('r-eco'); + + expect(store.isSystemRole()).toBe(false); + }); + }); + + describe('setActiveTab', () => { + it('should update active tab', () => { + store.setActiveTab('permissions'); + expect(store.activeTab()).toBe('permissions'); + + store.setActiveTab('tools'); + expect(store.activeTab()).toBe('tools'); + }); + }); + + describe('createRole', () => { + const FORM: DotRoleFormValue = { + roleName: 'New Role', + roleKey: '', + parentRoleId: null, + canEditUsers: true, + canEditPermissions: true, + canEditLayouts: true, + description: '' + }; + + it('should POST, reload tree, select the new role, and return the created detail', async () => { + const created = await store.createRole(FORM); + + expect(service.createRole).toHaveBeenCalledWith(FORM); + expect(service.loadRootRoles).toHaveBeenCalled(); + expect(store.selectedRoleId()).toBe(MOCK_ROLE_DETAIL.id); + expect(created).toEqual(MOCK_ROLE_DETAIL); + }); + + it('should delegate to httpErrorManager and return null on failure', async () => { + const errorManager = spectator.inject(DotHttpErrorManagerService); + service.createRole.mockReturnValueOnce(throwError(() => new Error('boom'))); + + const result = await store.createRole(FORM); + + expect(errorManager.handle).toHaveBeenCalled(); + expect(result).toBeNull(); + }); + }); +}); diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.ts new file mode 100644 index 000000000000..241701684b22 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.ts @@ -0,0 +1,227 @@ +import { patchState, signalStore, withComputed, withMethods, withState } from '@ngrx/signals'; +import { rxMethod } from '@ngrx/signals/rxjs-interop'; +import { EMPTY, pipe } from 'rxjs'; + +import { computed, inject } from '@angular/core'; + +import { catchError, switchMap, tap } from 'rxjs/operators'; + +import { DotHttpErrorManagerService } from '@dotcms/data-access'; + +import { + DotRoleDetail, + DotRoleFormValue, + DotRoleMember, + DotRoleNode, + DotRoleTab, + DotRolesStatus +} from '../../models/dot-roles.models'; +import { DotRolesPortletService } from '../../services/dot-roles-portlet.service'; + +export interface DotRolesState { + /** Full tree as loaded from `/v1/roles` (root roles + their first-level children). */ + rootRoles: DotRoleNode[]; + /** Client-side filter typed into the `Filter roles` input. */ + filter: string; + /** Currently selected role id (drives the right-hand detail area). */ + selectedRoleId: string | null; + /** Detail of the currently selected role (name/desc/can-grant flags/parent). */ + selectedRole: DotRoleDetail | null; + /** Active tab on the right-hand detail area. */ + activeTab: DotRoleTab; + /** Members of the selected role, annotated with inheritance metadata. */ + members: DotRoleMember[]; + /** Users selected for bulk-remove on the members table. */ + selectedMembers: DotRoleMember[]; + status: DotRolesStatus; + membersStatus: DotRolesStatus; + error: string | null; +} + +const initialState: DotRolesState = { + rootRoles: [], + filter: '', + selectedRoleId: null, + selectedRole: null, + activeTab: 'users', + members: [], + selectedMembers: [], + status: 'init', + membersStatus: 'init', + error: null +}; + +export const DotRolesStore = signalStore( + withState(initialState), + + withComputed(({ rootRoles, filter, selectedRoleId, selectedRole, members }) => ({ + /** + * Client-side filter applied to the loaded tree. The Dojo portlet + * hits `/api/role/loadbyname` on filter; the Angular portlet + * loads the tree once and filters in memory to avoid extra HTTP + * per keystroke. + */ + filteredRoles: computed(() => { + const q = filter().trim().toLowerCase(); + if (!q) { + return rootRoles(); + } + + return filterTree(rootRoles(), q); + }), + + /** Total users granted this role — direct + inherited. */ + memberCount: computed(() => members().length), + + /** How many members were granted directly on the selected role. */ + directMemberCount: computed( + () => members().filter((m) => m.grantedFromRoleId === selectedRoleId()).length + ), + + /** True when the selected role is a system role (locked / immutable). */ + isSystemRole: computed(() => selectedRole()?.system ?? false) + })), + + withMethods((store) => { + const service = inject(DotRolesPortletService); + const httpErrorManager = inject(DotHttpErrorManagerService); + + const loadRootRoles = rxMethod( + pipe( + tap(() => patchState(store, { status: 'loading', error: null })), + switchMap(() => + service.loadRootRoles(true).pipe( + tap((rootRoles) => { + patchState(store, { rootRoles, status: 'loaded' }); + }), + catchError((error) => { + httpErrorManager.handle(error); + patchState(store, { status: 'error' }); + + return EMPTY; + }) + ) + ) + ) + ); + + const loadRoleMembers = rxMethod( + pipe( + tap(() => patchState(store, { membersStatus: 'loading' })), + switchMap((roleId) => + service.loadRoleMembers(roleId).pipe( + tap((members) => { + patchState(store, { + members, + membersStatus: 'loaded' + }); + }), + catchError((error) => { + httpErrorManager.handle(error); + patchState(store, { membersStatus: 'error' }); + + return EMPTY; + }) + ) + ) + ) + ); + + const loadRoleDetail = rxMethod( + pipe( + switchMap((roleId) => + service.loadRoleById(roleId, true).pipe( + tap((selectedRole) => patchState(store, { selectedRole })), + catchError((error) => { + httpErrorManager.handle(error); + + return EMPTY; + }) + ) + ) + ) + ); + + return { + loadRootRoles, + loadRoleMembers, + loadRoleDetail, + + /** Update the free-text filter applied to the tree. */ + setFilter(filter: string): void { + patchState(store, { filter }); + }, + + /** Select a role and load its detail + members. */ + selectRole(roleId: string | null): void { + patchState(store, { + selectedRoleId: roleId, + selectedMembers: [] + }); + + if (roleId) { + loadRoleDetail(roleId); + loadRoleMembers(roleId); + } + }, + + setActiveTab(activeTab: DotRoleTab): void { + patchState(store, { activeTab }); + }, + + setSelectedMembers(selectedMembers: DotRoleMember[]): void { + patchState(store, { selectedMembers }); + }, + + /** + * Create a role. Returns a promise so the calling component + * can close its dialog on success and surface errors on failure. + */ + async createRole(form: DotRoleFormValue): Promise { + try { + const created = await new Promise((resolve, reject) => { + service.createRole(form).subscribe({ + next: (role) => resolve(role), + error: (err) => reject(err) + }); + }); + // Reload the tree so the new node appears; select it. + loadRootRoles(); + patchState(store, { selectedRoleId: created.id }); + + return created; + } catch (error) { + httpErrorManager.handle(error); + + return null; + } + } + + // NOTE: updateRole / deleteRole / grantUserToRole / removeUsersFromRole / + // reparentRole are intentionally NOT exposed from the store yet. + // They depend on backend endpoints that don't exist: + // - #36936 (PUT /v1/roles/{roleId}) → Edit Role, reparent + // - #36937 (POST /v1/roles/{roleId}/users/{userId}) → Grant user + // - #36938 (DELETE /v1/roles/{roleId}/users) → Remove members + // - #36939 (DELETE /v1/roles/{roleId}) → Delete Role + // Components must render the corresponding UI in a disabled / + // "coming soon" state until those endpoints land. + }; + }) +); + +function filterTree(nodes: DotRoleNode[], query: string): DotRoleNode[] { + return nodes.reduce((acc, node) => { + const matches = node.name.toLowerCase().includes(query); + const filteredChildren = node.children ? filterTree(node.children, query) : []; + + if (matches || filteredChildren.length > 0) { + acc.push({ + ...node, + children: filteredChildren.length > 0 ? filteredChildren : node.children + }); + } + + return acc; + }, []); +} diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-shell/dot-roles-shell.component.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-shell/dot-roles-shell.component.ts new file mode 100644 index 000000000000..9a1b16a52b41 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-shell/dot-roles-shell.component.ts @@ -0,0 +1,12 @@ +import { Component } from '@angular/core'; + +import { DotRolesPageComponent } from '../dot-roles-page/dot-roles-page.component'; + +@Component({ + selector: 'dot-roles-shell', + standalone: true, + imports: [DotRolesPageComponent], + template: '', + host: { class: 'flex flex-col h-full min-h-0 block' } +}) +export class DotRolesShellComponent {} diff --git a/core-web/libs/portlets/dot-roles/src/lib/lib.routes.ts b/core-web/libs/portlets/dot-roles/src/lib/lib.routes.ts new file mode 100644 index 000000000000..4df5b85d1158 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/lib.routes.ts @@ -0,0 +1,10 @@ +import { Route } from '@angular/router'; + +import { DotRolesShellComponent } from './dot-roles-shell/dot-roles-shell.component'; + +export const dotRolesRoutes: Route[] = [ + { + path: '', + component: DotRolesShellComponent + } +]; diff --git a/core-web/libs/portlets/dot-roles/src/lib/models/dot-roles.models.ts b/core-web/libs/portlets/dot-roles/src/lib/models/dot-roles.models.ts new file mode 100644 index 000000000000..d8d754770ff1 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/models/dot-roles.models.ts @@ -0,0 +1,57 @@ +/** + * Tree node used in the roles panel. Parent roles render with a folder icon + * (they have children); leaf roles render with a shield icon. + */ +export interface DotRoleNode { + readonly id: string; + readonly name: string; + readonly roleKey?: string; + readonly parent?: string; + readonly system?: boolean; + readonly locked?: boolean; + readonly userCount?: number; + readonly children?: DotRoleNode[]; +} + +/** + * Full role detail. Extends the tree node with the fields shown / edited + * in the Add / Edit role dialogs. + */ +export interface DotRoleDetail extends DotRoleNode { + readonly description?: string; + readonly editUsers?: boolean; + readonly editPermissions?: boolean; + readonly editLayouts?: boolean; + readonly DBFQN?: string; + readonly FQN?: string; +} + +/** + * Payload for POST /v1/roles (RoleForm). + * Also the shape the Angular Edit Role dialog collects; it PUTs the same + * body against /v1/roles/{roleId} once the endpoint ships (see #36936). + */ +export interface DotRoleFormValue { + roleName: string; + roleKey?: string; + parentRoleId?: string | null; + canEditUsers: boolean; + canEditPermissions: boolean; + canEditLayouts: boolean; + description?: string; +} + +/** Member of a role, annotated with the role that granted access. */ +export interface DotRoleMember { + readonly userId: string; + readonly firstName: string; + readonly lastName: string; + readonly emailAddress: string; + /** roleId that granted membership (self = direct; ancestor id = inherited) */ + readonly grantedFromRoleId: string; + readonly grantedFromRoleName: string; +} + +export type DotRoleTab = 'users' | 'permissions' | 'tools'; + +export type DotRolesStatus = 'init' | 'loading' | 'loaded' | 'error'; diff --git a/core-web/libs/portlets/dot-roles/src/lib/services/dot-roles-portlet.service.ts b/core-web/libs/portlets/dot-roles/src/lib/services/dot-roles-portlet.service.ts new file mode 100644 index 000000000000..c1e577001cfb --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/services/dot-roles-portlet.service.ts @@ -0,0 +1,125 @@ +import { Observable } from 'rxjs'; + +import { HttpClient } from '@angular/common/http'; +import { Injectable, inject } from '@angular/core'; + +import { map } from 'rxjs/operators'; + +import { DotCMSResponse } from '@dotcms/dotcms-models'; + +import { + DotRoleDetail, + DotRoleFormValue, + DotRoleMember, + DotRoleNode +} from '../models/dot-roles.models'; + +/** + * Portlet-scoped data access for the Roles and Tools Angular Beta. + * + * The shared `DotRolesService` under `@dotcms/data-access` covers the + * legacy read paths used by other portlets (roles-per-user hierarchy). + * This service owns the endpoints the Roles portlet specifically consumes. + * + * Blocked write flows (Edit / Delete role, Grant / Remove user) are called + * out in the individual methods; they resolve to the dedicated v1 endpoints + * once #36936, #36937, #36938, #36939 land. + */ +@Injectable() +export class DotRolesPortletService { + #http = inject(HttpClient); + + /** GET /v1/roles — root roles (optionally with first-level children). */ + loadRootRoles(loadChildren = true): Observable { + return this.#http + .get>(`/api/v1/roles?loadChildrenRoles=${loadChildren}`) + .pipe(map((response) => response.entity ?? [])); + } + + /** GET /v1/roles/{roleId} — role detail (optionally expand a subtree). */ + loadRoleById(roleId: string, loadChildren = true): Observable { + return this.#http + .get< + DotCMSResponse + >(`/api/v1/roles/${roleId}?loadChildrenRoles=${loadChildren}`) + .pipe(map((response) => response.entity)); + } + + /** + * GET /v1/roles/{roleId}/rolehierarchyanduserroles — members of the role + * annotated with inheritance metadata so the Users tab can render the + * `GRANTED FROM` chip. + */ + loadRoleMembers(roleId: string): Observable { + return this.#http + .get< + DotCMSResponse + >(`/api/v1/roles/${roleId}/rolehierarchyanduserroles`) + .pipe(map((response) => response.entity ?? [])); + } + + /** POST /v1/roles — create role (Add Role dialog). */ + createRole(form: DotRoleFormValue): Observable { + return this.#http + .post>('/api/v1/roles', form) + .pipe(map((response) => response.entity)); + } + + /** + * TODO: replace with `PUT /v1/roles/{roleId}` once #36936 ships. + * + * The Edit Role dialog (name / key / description / can-grant / parent) + * and drag-to-reparent both depend on this endpoint. Until it exists, + * the Angular portlet cannot mutate an existing role. Consumers should + * handle the rejected promise / thrown error and surface the message. + */ + updateRole(_roleId: string, _form: DotRoleFormValue): Observable { + throw new Error( + 'updateRole is not wired yet — waiting on PUT /v1/roles/{roleId} (issue #36936)' + ); + } + + /** + * TODO: replace with `DELETE /v1/roles/{roleId}` once #36939 ships. + * + * The Delete Role destructive action in the Edit dialog depends on this. + * Structured 409 errors (`has_children`, `has_users`, `has_layouts`) will + * surface once the endpoint exists so the FE can localize the message. + */ + deleteRole(_roleId: string): Observable { + throw new Error( + 'deleteRole is not wired yet — waiting on DELETE /v1/roles/{roleId} (issue #36939)' + ); + } + + /** + * TODO: replace with `POST /v1/roles/{roleId}/users/{userId}` once + * #36937 ships. Used by the Grant to User popover on the Users tab. + */ + grantUserToRole(_roleId: string, _userId: string): Observable { + throw new Error( + 'grantUserToRole is not wired yet — waiting on POST /v1/roles/{roleId}/users/{userId} (issue #36937)' + ); + } + + /** + * TODO: replace with `DELETE /v1/roles/{roleId}/users` once #36938 ships. + * Used by per-row Remove and bulk-remove on the Users tab. + */ + removeUsersFromRole(_roleId: string, _userIds: string[]): Observable { + throw new Error( + 'removeUsersFromRole is not wired yet — waiting on DELETE /v1/roles/{roleId}/users (issue #36938)' + ); + } + + /** + * TODO: reparent a role. Blocked on #36936. Drag-and-drop in the roles + * tree triggers this action, which today has no v1 endpoint (only DWR + * RoleAjax#updateRole supports it). + */ + reparentRole(_roleId: string, _newParentId: string | null): Observable { + throw new Error( + 'reparentRole is not wired yet — waiting on PUT /v1/roles/{roleId} (issue #36936)' + ); + } +} diff --git a/core-web/libs/portlets/dot-roles/src/test-setup.ts b/core-web/libs/portlets/dot-roles/src/test-setup.ts new file mode 100644 index 000000000000..b4da80f025e3 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/test-setup.ts @@ -0,0 +1,11 @@ +import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone'; + +import { setupResizeObserverMock } from '@dotcms/utils-testing'; + +setupZoneTestEnv({ + errorOnUnknownElements: true, + errorOnUnknownProperties: true +}); + +// PrimeNG Tabs (and other layout components) call ResizeObserver on mount. +setupResizeObserverMock(); diff --git a/core-web/libs/portlets/dot-roles/tsconfig.json b/core-web/libs/portlets/dot-roles/tsconfig.json new file mode 100644 index 000000000000..8e2e06fb8ff3 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/tsconfig.json @@ -0,0 +1,31 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "target": "es2022", + "moduleResolution": "bundler", + "useDefineForClassFields": false, + "forceConsistentCasingInFileNames": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "module": "preserve", + "lib": ["dom", "dom.iterable", "es2022"] + }, + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "typeCheckHostBindings": true, + "strictTemplates": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/core-web/libs/portlets/dot-roles/tsconfig.lib.json b/core-web/libs/portlets/dot-roles/tsconfig.lib.json new file mode 100644 index 000000000000..ea591ee88915 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/tsconfig.lib.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [] + }, + "include": ["src/**/*.ts"], + "exclude": ["src/**/*.spec.ts", "src/**/*.test.ts", "jest.config.ts", "src/test-setup.ts"] +} diff --git a/core-web/libs/portlets/dot-roles/tsconfig.spec.json b/core-web/libs/portlets/dot-roles/tsconfig.spec.json new file mode 100644 index 000000000000..48633a8d638e --- /dev/null +++ b/core-web/libs/portlets/dot-roles/tsconfig.spec.json @@ -0,0 +1,13 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "module": "commonjs", + "target": "es2016", + "types": ["jest", "node"], + "moduleResolution": "bundler", + "isolatedModules": true + }, + "files": ["src/test-setup.ts"], + "include": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts", "src/**/*.d.ts"] +} diff --git a/core-web/package.json b/core-web/package.json index 74443a495664..b0c1e7c1449a 100644 --- a/core-web/package.json +++ b/core-web/package.json @@ -286,6 +286,7 @@ "jest-html-reporters": "3.1.5", "jest-junit": "16.0.0", "jest-preset-angular": "17.0.0", + "jest-util": "~30.3.0", "jiti": "2.4.2", "jsdom": "28.1.0", "jsonc-eslint-parser": "2.4.0", diff --git a/core-web/pnpm-lock.yaml b/core-web/pnpm-lock.yaml index 4b9ca7a56aca..fcc96fae7380 100644 --- a/core-web/pnpm-lock.yaml +++ b/core-web/pnpm-lock.yaml @@ -120,10 +120,10 @@ importers: version: 21.1.1(@angular/core@22.1.0(@angular/compiler@22.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) '@nx/angular': specifier: 23.1.1 - version: 23.1.1(0c2651284a7a75bfb153c6888b067c15) + version: 23.1.1(072c770ba89bf4308c6f3053aba8fcd1) '@nx/playwright': specifier: 23.1.1 - version: 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@playwright/test@1.36.0)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) + version: 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@playwright/test@1.36.0)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) '@primeuix/themes': specifier: 2.0.3 version: 2.0.3 @@ -490,7 +490,7 @@ importers: version: 8.4.1 '@happy-dom/jest-environment': specifier: 20.8.3 - version: 20.8.3(@jest/environment@30.4.1)(@jest/fake-timers@30.4.1)(@jest/types@30.4.1)(jest-mock@30.4.1)(jest-util@30.4.1) + version: 20.8.3(@jest/environment@30.4.1)(@jest/fake-timers@30.4.1)(@jest/types@30.4.1)(jest-mock@30.4.1)(jest-util@30.3.0) '@jest/globals': specifier: 30.2.0 version: 30.2.0 @@ -505,37 +505,37 @@ importers: version: 23.1.1(@babel/traverse@7.29.7)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.19.2)(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) '@nx/eslint': specifier: 23.1.1 - version: 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) + version: 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) '@nx/eslint-plugin': specifier: 23.1.1 version: 23.1.1(@babel/traverse@7.29.7)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@typescript-eslint/parser@8.62.0(eslint@9.39.4(jiti@2.4.2))(typescript@6.0.3))(eslint-config-prettier@10.1.8(eslint@9.39.4(jiti@2.4.2)))(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(typescript@6.0.3) '@nx/jest': specifier: 23.1.1 - version: 23.1.1(8be0172cf244ce853aad5d3fbafc9ccb) + version: 23.1.1(7d847bd2f59cc0593e48c48118840ff5) '@nx/js': specifier: 23.1.1 version: 23.1.1(@babel/traverse@7.29.7)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) '@nx/node': specifier: 23.1.1 - version: 23.1.1(df37e30a9f355cb6272a961a8a72175f) + version: 23.1.1(c0e3db756d0da6d6b699dfa51d58e1fd) '@nx/react': specifier: 23.1.1 - version: 23.1.1(6f6c41671706189c500dd3f5d3f548a6) + version: 23.1.1(363fcebb2341dffc7ac71091199caef6) '@nx/rollup': specifier: 23.1.1 version: 23.1.1(@babel/core@7.29.0)(@babel/traverse@7.29.7)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@types/babel__core@7.20.5)(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(rollup@4.14.0)(typescript@6.0.3) '@nx/vite': specifier: 23.1.1 - version: 23.1.1(@babel/traverse@7.29.7)(@nx/eslint@23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(typescript@6.0.3)(vite@7.3.2(@types/node@20.19.9)(jiti@2.4.2)(less@4.6.7)(lightningcss@1.33.0)(sass-embedded@1.100.0)(sass@1.56.2)(terser@5.28.1)(tsx@4.19.0)(yaml@2.9.0))(vitest@4.0.18) + version: 23.1.1(@babel/traverse@7.29.7)(@nx/eslint@23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(typescript@6.0.3)(vite@7.3.2(@types/node@20.19.9)(jiti@2.4.2)(less@4.6.7)(lightningcss@1.33.0)(sass-embedded@1.100.0)(sass@1.56.2)(terser@5.28.1)(tsx@4.19.0)(yaml@2.9.0))(vitest@4.0.18) '@nx/vitest': specifier: 23.1.1 - version: 23.1.1(@babel/traverse@7.29.7)(@nx/eslint@23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(typescript@6.0.3)(vite@7.3.2(@types/node@20.19.9)(jiti@2.4.2)(less@4.6.7)(lightningcss@1.33.0)(sass-embedded@1.100.0)(sass@1.56.2)(terser@5.28.1)(tsx@4.19.0)(yaml@2.9.0))(vitest@4.0.18) + version: 23.1.1(@babel/traverse@7.29.7)(@nx/eslint@23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(typescript@6.0.3)(vite@7.3.2(@types/node@20.19.9)(jiti@2.4.2)(less@4.6.7)(lightningcss@1.33.0)(sass-embedded@1.100.0)(sass@1.56.2)(terser@5.28.1)(tsx@4.19.0)(yaml@2.9.0))(vitest@4.0.18) '@nx/vue': specifier: 23.1.1 - version: 23.1.1(b7694867a93ecc98b9fe8597854a77c7) + version: 23.1.1(4f1137c05c476613326b82b0cbcff0bb) '@nx/web': specifier: 23.1.1 - version: 23.1.1(269dd13e357dbfb54dda39a5dcf682ec) + version: 23.1.1(401e976a88e39fb2af84d87acf67b7d3) '@nx/workspace': specifier: 23.1.1 version: 23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)) @@ -722,6 +722,9 @@ importers: jest-preset-angular: specifier: 17.0.0 version: 17.0.0(@angular/compiler-cli@22.1.0(@angular/compiler@22.1.0)(typescript@6.0.3))(@angular/core@22.1.0(@angular/compiler@22.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@22.1.0(@angular/animations@22.1.0(@angular/core@22.1.0(@angular/compiler@22.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@22.1.0(@angular/core@22.1.0(@angular/compiler@22.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@22.1.0(@angular/compiler@22.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@babel/core@7.29.0)(@jest/transform@30.4.1)(@jest/types@30.4.1)(babel-jest@30.2.0(@babel/core@7.29.0))(jest@30.2.0(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.19.2))(ts-node@10.9.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@6.0.3)))(jsdom@28.1.0)(typescript@6.0.3) + jest-util: + specifier: ~30.3.0 + version: 30.3.0 jiti: specifier: 2.4.2 version: 2.4.2 @@ -775,7 +778,7 @@ importers: version: 1.56.2 ts-jest: specifier: 29.4.6 - version: 29.4.6(@babel/core@7.29.0)(@jest/transform@30.4.1)(@jest/types@30.4.1)(babel-jest@30.2.0(@babel/core@7.29.0))(esbuild@0.19.2)(jest-util@30.4.1)(jest@30.2.0(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.19.2))(ts-node@10.9.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@6.0.3)))(typescript@6.0.3) + version: 29.4.6(@babel/core@7.29.0)(@jest/transform@30.4.1)(@jest/types@30.4.1)(babel-jest@30.2.0(@babel/core@7.29.0))(esbuild@0.19.2)(jest-util@30.3.0)(jest@30.2.0(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.19.2))(ts-node@10.9.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@6.0.3)))(typescript@6.0.3) ts-node: specifier: 10.9.2 version: 10.9.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@6.0.3) @@ -2444,10 +2447,10 @@ packages: engines: {node: '>=14.17.0'} '@emnapi/core@1.10.0': - resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} + resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==, tarball: https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz} '@emnapi/core@1.11.1': - resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} + resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==, tarball: https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz} '@emnapi/core@1.11.2': resolution: {integrity: sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==} @@ -2456,10 +2459,10 @@ packages: resolution: {integrity: sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==} '@emnapi/runtime@1.10.0': - resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} + resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==, tarball: https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz} '@emnapi/runtime@1.11.1': - resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} + resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==, tarball: https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz} '@emnapi/runtime@1.11.2': resolution: {integrity: sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==} @@ -2471,7 +2474,7 @@ packages: resolution: {integrity: sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==} '@emnapi/wasi-threads@1.2.1': - resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==, tarball: https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz} '@emnapi/wasi-threads@1.2.2': resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} @@ -2480,739 +2483,739 @@ packages: resolution: {integrity: sha512-no2pQMWiBy6gpBEiqGeU77/bFejDqUTRY7KX+0+iur13op3bqUsXdnwoZs6Xb1zbv0gAj5VvS1PWoUUckSr5Dw==} '@esbuild/aix-ppc64@0.23.1': - resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==} + resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==, tarball: https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz} engines: {node: '>=18'} cpu: [ppc64] os: [aix] '@esbuild/aix-ppc64@0.25.5': - resolution: {integrity: sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==} + resolution: {integrity: sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==, tarball: https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz} engines: {node: '>=18'} cpu: [ppc64] os: [aix] '@esbuild/aix-ppc64@0.27.7': - resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} + resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==, tarball: https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz} engines: {node: '>=18'} cpu: [ppc64] os: [aix] '@esbuild/aix-ppc64@0.28.1': - resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==} + resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==, tarball: https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz} engines: {node: '>=18'} cpu: [ppc64] os: [aix] '@esbuild/android-arm64@0.19.2': - resolution: {integrity: sha512-lsB65vAbe90I/Qe10OjkmrdxSX4UJDjosDgb8sZUKcg3oefEuW2OT2Vozz8ef7wrJbMcmhvCC+hciF8jY/uAkw==} + resolution: {integrity: sha512-lsB65vAbe90I/Qe10OjkmrdxSX4UJDjosDgb8sZUKcg3oefEuW2OT2Vozz8ef7wrJbMcmhvCC+hciF8jY/uAkw==, tarball: https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.2.tgz} engines: {node: '>=12'} cpu: [arm64] os: [android] '@esbuild/android-arm64@0.23.1': - resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==} + resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==, tarball: https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz} engines: {node: '>=18'} cpu: [arm64] os: [android] '@esbuild/android-arm64@0.25.5': - resolution: {integrity: sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==} + resolution: {integrity: sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==, tarball: https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz} engines: {node: '>=18'} cpu: [arm64] os: [android] '@esbuild/android-arm64@0.27.7': - resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==} + resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==, tarball: https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz} engines: {node: '>=18'} cpu: [arm64] os: [android] '@esbuild/android-arm64@0.28.1': - resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==} + resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==, tarball: https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz} engines: {node: '>=18'} cpu: [arm64] os: [android] '@esbuild/android-arm@0.19.2': - resolution: {integrity: sha512-tM8yLeYVe7pRyAu9VMi/Q7aunpLwD139EY1S99xbQkT4/q2qa6eA4ige/WJQYdJ8GBL1K33pPFhPfPdJ/WzT8Q==} + resolution: {integrity: sha512-tM8yLeYVe7pRyAu9VMi/Q7aunpLwD139EY1S99xbQkT4/q2qa6eA4ige/WJQYdJ8GBL1K33pPFhPfPdJ/WzT8Q==, tarball: https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.2.tgz} engines: {node: '>=12'} cpu: [arm] os: [android] '@esbuild/android-arm@0.23.1': - resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==} + resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==, tarball: https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz} engines: {node: '>=18'} cpu: [arm] os: [android] '@esbuild/android-arm@0.25.5': - resolution: {integrity: sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==} + resolution: {integrity: sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==, tarball: https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz} engines: {node: '>=18'} cpu: [arm] os: [android] '@esbuild/android-arm@0.27.7': - resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==} + resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==, tarball: https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz} engines: {node: '>=18'} cpu: [arm] os: [android] '@esbuild/android-arm@0.28.1': - resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==} + resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==, tarball: https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz} engines: {node: '>=18'} cpu: [arm] os: [android] '@esbuild/android-x64@0.19.2': - resolution: {integrity: sha512-qK/TpmHt2M/Hg82WXHRc/W/2SGo/l1thtDHZWqFq7oi24AjZ4O/CpPSu6ZuYKFkEgmZlFoa7CooAyYmuvnaG8w==} + resolution: {integrity: sha512-qK/TpmHt2M/Hg82WXHRc/W/2SGo/l1thtDHZWqFq7oi24AjZ4O/CpPSu6ZuYKFkEgmZlFoa7CooAyYmuvnaG8w==, tarball: https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.2.tgz} engines: {node: '>=12'} cpu: [x64] os: [android] '@esbuild/android-x64@0.23.1': - resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==} + resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==, tarball: https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz} engines: {node: '>=18'} cpu: [x64] os: [android] '@esbuild/android-x64@0.25.5': - resolution: {integrity: sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==} + resolution: {integrity: sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==, tarball: https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz} engines: {node: '>=18'} cpu: [x64] os: [android] '@esbuild/android-x64@0.27.7': - resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==} + resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==, tarball: https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz} engines: {node: '>=18'} cpu: [x64] os: [android] '@esbuild/android-x64@0.28.1': - resolution: {integrity: sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==} + resolution: {integrity: sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==, tarball: https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz} engines: {node: '>=18'} cpu: [x64] os: [android] '@esbuild/darwin-arm64@0.19.2': - resolution: {integrity: sha512-Ora8JokrvrzEPEpZO18ZYXkH4asCdc1DLdcVy8TGf5eWtPO1Ie4WroEJzwI52ZGtpODy3+m0a2yEX9l+KUn0tA==} + resolution: {integrity: sha512-Ora8JokrvrzEPEpZO18ZYXkH4asCdc1DLdcVy8TGf5eWtPO1Ie4WroEJzwI52ZGtpODy3+m0a2yEX9l+KUn0tA==, tarball: https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.2.tgz} engines: {node: '>=12'} cpu: [arm64] os: [darwin] '@esbuild/darwin-arm64@0.23.1': - resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==} + resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==, tarball: https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz} engines: {node: '>=18'} cpu: [arm64] os: [darwin] '@esbuild/darwin-arm64@0.25.5': - resolution: {integrity: sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==} + resolution: {integrity: sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==, tarball: https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz} engines: {node: '>=18'} cpu: [arm64] os: [darwin] '@esbuild/darwin-arm64@0.27.7': - resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==} + resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==, tarball: https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz} engines: {node: '>=18'} cpu: [arm64] os: [darwin] '@esbuild/darwin-arm64@0.28.1': - resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==} + resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==, tarball: https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz} engines: {node: '>=18'} cpu: [arm64] os: [darwin] '@esbuild/darwin-x64@0.19.2': - resolution: {integrity: sha512-tP+B5UuIbbFMj2hQaUr6EALlHOIOmlLM2FK7jeFBobPy2ERdohI4Ka6ZFjZ1ZYsrHE/hZimGuU90jusRE0pwDw==} + resolution: {integrity: sha512-tP+B5UuIbbFMj2hQaUr6EALlHOIOmlLM2FK7jeFBobPy2ERdohI4Ka6ZFjZ1ZYsrHE/hZimGuU90jusRE0pwDw==, tarball: https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.2.tgz} engines: {node: '>=12'} cpu: [x64] os: [darwin] '@esbuild/darwin-x64@0.23.1': - resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==} + resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==, tarball: https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz} engines: {node: '>=18'} cpu: [x64] os: [darwin] '@esbuild/darwin-x64@0.25.5': - resolution: {integrity: sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==} + resolution: {integrity: sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==, tarball: https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz} engines: {node: '>=18'} cpu: [x64] os: [darwin] '@esbuild/darwin-x64@0.27.7': - resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==} + resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==, tarball: https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz} engines: {node: '>=18'} cpu: [x64] os: [darwin] '@esbuild/darwin-x64@0.28.1': - resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==} + resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==, tarball: https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz} engines: {node: '>=18'} cpu: [x64] os: [darwin] '@esbuild/freebsd-arm64@0.19.2': - resolution: {integrity: sha512-YbPY2kc0acfzL1VPVK6EnAlig4f+l8xmq36OZkU0jzBVHcOTyQDhnKQaLzZudNJQyymd9OqQezeaBgkTGdTGeQ==} + resolution: {integrity: sha512-YbPY2kc0acfzL1VPVK6EnAlig4f+l8xmq36OZkU0jzBVHcOTyQDhnKQaLzZudNJQyymd9OqQezeaBgkTGdTGeQ==, tarball: https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.2.tgz} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] '@esbuild/freebsd-arm64@0.23.1': - resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==} + resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==, tarball: https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] '@esbuild/freebsd-arm64@0.25.5': - resolution: {integrity: sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==} + resolution: {integrity: sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==, tarball: https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] '@esbuild/freebsd-arm64@0.27.7': - resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==} + resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==, tarball: https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] '@esbuild/freebsd-arm64@0.28.1': - resolution: {integrity: sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==} + resolution: {integrity: sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==, tarball: https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] '@esbuild/freebsd-x64@0.19.2': - resolution: {integrity: sha512-nSO5uZT2clM6hosjWHAsS15hLrwCvIWx+b2e3lZ3MwbYSaXwvfO528OF+dLjas1g3bZonciivI8qKR/Hm7IWGw==} + resolution: {integrity: sha512-nSO5uZT2clM6hosjWHAsS15hLrwCvIWx+b2e3lZ3MwbYSaXwvfO528OF+dLjas1g3bZonciivI8qKR/Hm7IWGw==, tarball: https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.2.tgz} engines: {node: '>=12'} cpu: [x64] os: [freebsd] '@esbuild/freebsd-x64@0.23.1': - resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==} + resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==, tarball: https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz} engines: {node: '>=18'} cpu: [x64] os: [freebsd] '@esbuild/freebsd-x64@0.25.5': - resolution: {integrity: sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==} + resolution: {integrity: sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==, tarball: https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz} engines: {node: '>=18'} cpu: [x64] os: [freebsd] '@esbuild/freebsd-x64@0.27.7': - resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==} + resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==, tarball: https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz} engines: {node: '>=18'} cpu: [x64] os: [freebsd] '@esbuild/freebsd-x64@0.28.1': - resolution: {integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==} + resolution: {integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==, tarball: https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz} engines: {node: '>=18'} cpu: [x64] os: [freebsd] '@esbuild/linux-arm64@0.19.2': - resolution: {integrity: sha512-ig2P7GeG//zWlU0AggA3pV1h5gdix0MA3wgB+NsnBXViwiGgY77fuN9Wr5uoCrs2YzaYfogXgsWZbm+HGr09xg==} + resolution: {integrity: sha512-ig2P7GeG//zWlU0AggA3pV1h5gdix0MA3wgB+NsnBXViwiGgY77fuN9Wr5uoCrs2YzaYfogXgsWZbm+HGr09xg==, tarball: https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.2.tgz} engines: {node: '>=12'} cpu: [arm64] os: [linux] '@esbuild/linux-arm64@0.23.1': - resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==} + resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==, tarball: https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz} engines: {node: '>=18'} cpu: [arm64] os: [linux] '@esbuild/linux-arm64@0.25.5': - resolution: {integrity: sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==} + resolution: {integrity: sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==, tarball: https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz} engines: {node: '>=18'} cpu: [arm64] os: [linux] '@esbuild/linux-arm64@0.27.7': - resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==} + resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==, tarball: https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz} engines: {node: '>=18'} cpu: [arm64] os: [linux] '@esbuild/linux-arm64@0.28.1': - resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==} + resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==, tarball: https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz} engines: {node: '>=18'} cpu: [arm64] os: [linux] '@esbuild/linux-arm@0.19.2': - resolution: {integrity: sha512-Odalh8hICg7SOD7XCj0YLpYCEc+6mkoq63UnExDCiRA2wXEmGlK5JVrW50vZR9Qz4qkvqnHcpH+OFEggO3PgTg==} + resolution: {integrity: sha512-Odalh8hICg7SOD7XCj0YLpYCEc+6mkoq63UnExDCiRA2wXEmGlK5JVrW50vZR9Qz4qkvqnHcpH+OFEggO3PgTg==, tarball: https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.2.tgz} engines: {node: '>=12'} cpu: [arm] os: [linux] '@esbuild/linux-arm@0.23.1': - resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==} + resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==, tarball: https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz} engines: {node: '>=18'} cpu: [arm] os: [linux] '@esbuild/linux-arm@0.25.5': - resolution: {integrity: sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==} + resolution: {integrity: sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==, tarball: https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz} engines: {node: '>=18'} cpu: [arm] os: [linux] '@esbuild/linux-arm@0.27.7': - resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==} + resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==, tarball: https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz} engines: {node: '>=18'} cpu: [arm] os: [linux] '@esbuild/linux-arm@0.28.1': - resolution: {integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==} + resolution: {integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==, tarball: https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz} engines: {node: '>=18'} cpu: [arm] os: [linux] '@esbuild/linux-ia32@0.19.2': - resolution: {integrity: sha512-mLfp0ziRPOLSTek0Gd9T5B8AtzKAkoZE70fneiiyPlSnUKKI4lp+mGEnQXcQEHLJAcIYDPSyBvsUbKUG2ri/XQ==} + resolution: {integrity: sha512-mLfp0ziRPOLSTek0Gd9T5B8AtzKAkoZE70fneiiyPlSnUKKI4lp+mGEnQXcQEHLJAcIYDPSyBvsUbKUG2ri/XQ==, tarball: https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.2.tgz} engines: {node: '>=12'} cpu: [ia32] os: [linux] '@esbuild/linux-ia32@0.23.1': - resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==} + resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==, tarball: https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz} engines: {node: '>=18'} cpu: [ia32] os: [linux] '@esbuild/linux-ia32@0.25.5': - resolution: {integrity: sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==} + resolution: {integrity: sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==, tarball: https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz} engines: {node: '>=18'} cpu: [ia32] os: [linux] '@esbuild/linux-ia32@0.27.7': - resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==} + resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==, tarball: https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz} engines: {node: '>=18'} cpu: [ia32] os: [linux] '@esbuild/linux-ia32@0.28.1': - resolution: {integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==} + resolution: {integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==, tarball: https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz} engines: {node: '>=18'} cpu: [ia32] os: [linux] '@esbuild/linux-loong64@0.19.2': - resolution: {integrity: sha512-hn28+JNDTxxCpnYjdDYVMNTR3SKavyLlCHHkufHV91fkewpIyQchS1d8wSbmXhs1fiYDpNww8KTFlJ1dHsxeSw==} + resolution: {integrity: sha512-hn28+JNDTxxCpnYjdDYVMNTR3SKavyLlCHHkufHV91fkewpIyQchS1d8wSbmXhs1fiYDpNww8KTFlJ1dHsxeSw==, tarball: https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.2.tgz} engines: {node: '>=12'} cpu: [loong64] os: [linux] '@esbuild/linux-loong64@0.23.1': - resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==} + resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==, tarball: https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz} engines: {node: '>=18'} cpu: [loong64] os: [linux] '@esbuild/linux-loong64@0.25.5': - resolution: {integrity: sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==} + resolution: {integrity: sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==, tarball: https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz} engines: {node: '>=18'} cpu: [loong64] os: [linux] '@esbuild/linux-loong64@0.27.7': - resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==} + resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==, tarball: https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz} engines: {node: '>=18'} cpu: [loong64] os: [linux] '@esbuild/linux-loong64@0.28.1': - resolution: {integrity: sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==} + resolution: {integrity: sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==, tarball: https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz} engines: {node: '>=18'} cpu: [loong64] os: [linux] '@esbuild/linux-mips64el@0.19.2': - resolution: {integrity: sha512-KbXaC0Sejt7vD2fEgPoIKb6nxkfYW9OmFUK9XQE4//PvGIxNIfPk1NmlHmMg6f25x57rpmEFrn1OotASYIAaTg==} + resolution: {integrity: sha512-KbXaC0Sejt7vD2fEgPoIKb6nxkfYW9OmFUK9XQE4//PvGIxNIfPk1NmlHmMg6f25x57rpmEFrn1OotASYIAaTg==, tarball: https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.2.tgz} engines: {node: '>=12'} cpu: [mips64el] os: [linux] '@esbuild/linux-mips64el@0.23.1': - resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==} + resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==, tarball: https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz} engines: {node: '>=18'} cpu: [mips64el] os: [linux] '@esbuild/linux-mips64el@0.25.5': - resolution: {integrity: sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==} + resolution: {integrity: sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==, tarball: https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz} engines: {node: '>=18'} cpu: [mips64el] os: [linux] '@esbuild/linux-mips64el@0.27.7': - resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==} + resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==, tarball: https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz} engines: {node: '>=18'} cpu: [mips64el] os: [linux] '@esbuild/linux-mips64el@0.28.1': - resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==} + resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==, tarball: https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz} engines: {node: '>=18'} cpu: [mips64el] os: [linux] '@esbuild/linux-ppc64@0.19.2': - resolution: {integrity: sha512-dJ0kE8KTqbiHtA3Fc/zn7lCd7pqVr4JcT0JqOnbj4LLzYnp+7h8Qi4yjfq42ZlHfhOCM42rBh0EwHYLL6LEzcw==} + resolution: {integrity: sha512-dJ0kE8KTqbiHtA3Fc/zn7lCd7pqVr4JcT0JqOnbj4LLzYnp+7h8Qi4yjfq42ZlHfhOCM42rBh0EwHYLL6LEzcw==, tarball: https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.2.tgz} engines: {node: '>=12'} cpu: [ppc64] os: [linux] '@esbuild/linux-ppc64@0.23.1': - resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==} + resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==, tarball: https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz} engines: {node: '>=18'} cpu: [ppc64] os: [linux] '@esbuild/linux-ppc64@0.25.5': - resolution: {integrity: sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==} + resolution: {integrity: sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==, tarball: https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz} engines: {node: '>=18'} cpu: [ppc64] os: [linux] '@esbuild/linux-ppc64@0.27.7': - resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==} + resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==, tarball: https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz} engines: {node: '>=18'} cpu: [ppc64] os: [linux] '@esbuild/linux-ppc64@0.28.1': - resolution: {integrity: sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==} + resolution: {integrity: sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==, tarball: https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz} engines: {node: '>=18'} cpu: [ppc64] os: [linux] '@esbuild/linux-riscv64@0.19.2': - resolution: {integrity: sha512-7Z/jKNFufZ/bbu4INqqCN6DDlrmOTmdw6D0gH+6Y7auok2r02Ur661qPuXidPOJ+FSgbEeQnnAGgsVynfLuOEw==} + resolution: {integrity: sha512-7Z/jKNFufZ/bbu4INqqCN6DDlrmOTmdw6D0gH+6Y7auok2r02Ur661qPuXidPOJ+FSgbEeQnnAGgsVynfLuOEw==, tarball: https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.2.tgz} engines: {node: '>=12'} cpu: [riscv64] os: [linux] '@esbuild/linux-riscv64@0.23.1': - resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==} + resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==, tarball: https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz} engines: {node: '>=18'} cpu: [riscv64] os: [linux] '@esbuild/linux-riscv64@0.25.5': - resolution: {integrity: sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==} + resolution: {integrity: sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==, tarball: https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz} engines: {node: '>=18'} cpu: [riscv64] os: [linux] '@esbuild/linux-riscv64@0.27.7': - resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==} + resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==, tarball: https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz} engines: {node: '>=18'} cpu: [riscv64] os: [linux] '@esbuild/linux-riscv64@0.28.1': - resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==} + resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==, tarball: https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz} engines: {node: '>=18'} cpu: [riscv64] os: [linux] '@esbuild/linux-s390x@0.19.2': - resolution: {integrity: sha512-U+RinR6aXXABFCcAY4gSlv4CL1oOVvSSCdseQmGO66H+XyuQGZIUdhG56SZaDJQcLmrSfRmx5XZOWyCJPRqS7g==} + resolution: {integrity: sha512-U+RinR6aXXABFCcAY4gSlv4CL1oOVvSSCdseQmGO66H+XyuQGZIUdhG56SZaDJQcLmrSfRmx5XZOWyCJPRqS7g==, tarball: https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.2.tgz} engines: {node: '>=12'} cpu: [s390x] os: [linux] '@esbuild/linux-s390x@0.23.1': - resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==} + resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==, tarball: https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz} engines: {node: '>=18'} cpu: [s390x] os: [linux] '@esbuild/linux-s390x@0.25.5': - resolution: {integrity: sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==} + resolution: {integrity: sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==, tarball: https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz} engines: {node: '>=18'} cpu: [s390x] os: [linux] '@esbuild/linux-s390x@0.27.7': - resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==} + resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==, tarball: https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz} engines: {node: '>=18'} cpu: [s390x] os: [linux] '@esbuild/linux-s390x@0.28.1': - resolution: {integrity: sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==} + resolution: {integrity: sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==, tarball: https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz} engines: {node: '>=18'} cpu: [s390x] os: [linux] '@esbuild/linux-x64@0.19.2': - resolution: {integrity: sha512-oxzHTEv6VPm3XXNaHPyUTTte+3wGv7qVQtqaZCrgstI16gCuhNOtBXLEBkBREP57YTd68P0VgDgG73jSD8bwXQ==} + resolution: {integrity: sha512-oxzHTEv6VPm3XXNaHPyUTTte+3wGv7qVQtqaZCrgstI16gCuhNOtBXLEBkBREP57YTd68P0VgDgG73jSD8bwXQ==, tarball: https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.2.tgz} engines: {node: '>=12'} cpu: [x64] os: [linux] '@esbuild/linux-x64@0.23.1': - resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==} + resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==, tarball: https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz} engines: {node: '>=18'} cpu: [x64] os: [linux] '@esbuild/linux-x64@0.25.5': - resolution: {integrity: sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==} + resolution: {integrity: sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==, tarball: https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz} engines: {node: '>=18'} cpu: [x64] os: [linux] '@esbuild/linux-x64@0.27.7': - resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==} + resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==, tarball: https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz} engines: {node: '>=18'} cpu: [x64] os: [linux] '@esbuild/linux-x64@0.28.1': - resolution: {integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==} + resolution: {integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==, tarball: https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz} engines: {node: '>=18'} cpu: [x64] os: [linux] '@esbuild/netbsd-arm64@0.25.5': - resolution: {integrity: sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==} + resolution: {integrity: sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==, tarball: https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] '@esbuild/netbsd-arm64@0.27.7': - resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==} + resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==, tarball: https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] '@esbuild/netbsd-arm64@0.28.1': - resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==} + resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==, tarball: https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] '@esbuild/netbsd-x64@0.19.2': - resolution: {integrity: sha512-WNa5zZk1XpTTwMDompZmvQLHszDDDN7lYjEHCUmAGB83Bgs20EMs7ICD+oKeT6xt4phV4NDdSi/8OfjPbSbZfQ==} + resolution: {integrity: sha512-WNa5zZk1XpTTwMDompZmvQLHszDDDN7lYjEHCUmAGB83Bgs20EMs7ICD+oKeT6xt4phV4NDdSi/8OfjPbSbZfQ==, tarball: https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.2.tgz} engines: {node: '>=12'} cpu: [x64] os: [netbsd] '@esbuild/netbsd-x64@0.23.1': - resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==} + resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==, tarball: https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz} engines: {node: '>=18'} cpu: [x64] os: [netbsd] '@esbuild/netbsd-x64@0.25.5': - resolution: {integrity: sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==} + resolution: {integrity: sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==, tarball: https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz} engines: {node: '>=18'} cpu: [x64] os: [netbsd] '@esbuild/netbsd-x64@0.27.7': - resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==} + resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==, tarball: https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz} engines: {node: '>=18'} cpu: [x64] os: [netbsd] '@esbuild/netbsd-x64@0.28.1': - resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==} + resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==, tarball: https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz} engines: {node: '>=18'} cpu: [x64] os: [netbsd] '@esbuild/openbsd-arm64@0.23.1': - resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==} + resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==, tarball: https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] '@esbuild/openbsd-arm64@0.25.5': - resolution: {integrity: sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==} + resolution: {integrity: sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==, tarball: https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] '@esbuild/openbsd-arm64@0.27.7': - resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==} + resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==, tarball: https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] '@esbuild/openbsd-arm64@0.28.1': - resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==} + resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==, tarball: https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] '@esbuild/openbsd-x64@0.19.2': - resolution: {integrity: sha512-S6kI1aT3S++Dedb7vxIuUOb3oAxqxk2Rh5rOXOTYnzN8JzW1VzBd+IqPiSpgitu45042SYD3HCoEyhLKQcDFDw==} + resolution: {integrity: sha512-S6kI1aT3S++Dedb7vxIuUOb3oAxqxk2Rh5rOXOTYnzN8JzW1VzBd+IqPiSpgitu45042SYD3HCoEyhLKQcDFDw==, tarball: https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.2.tgz} engines: {node: '>=12'} cpu: [x64] os: [openbsd] '@esbuild/openbsd-x64@0.23.1': - resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==} + resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==, tarball: https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz} engines: {node: '>=18'} cpu: [x64] os: [openbsd] '@esbuild/openbsd-x64@0.25.5': - resolution: {integrity: sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==} + resolution: {integrity: sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==, tarball: https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz} engines: {node: '>=18'} cpu: [x64] os: [openbsd] '@esbuild/openbsd-x64@0.27.7': - resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==} + resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==, tarball: https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz} engines: {node: '>=18'} cpu: [x64] os: [openbsd] '@esbuild/openbsd-x64@0.28.1': - resolution: {integrity: sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==} + resolution: {integrity: sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==, tarball: https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz} engines: {node: '>=18'} cpu: [x64] os: [openbsd] '@esbuild/openharmony-arm64@0.27.7': - resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==} + resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==, tarball: https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] '@esbuild/openharmony-arm64@0.28.1': - resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==} + resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==, tarball: https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] '@esbuild/sunos-x64@0.19.2': - resolution: {integrity: sha512-VXSSMsmb+Z8LbsQGcBMiM+fYObDNRm8p7tkUDMPG/g4fhFX5DEFmjxIEa3N8Zr96SjsJ1woAhF0DUnS3MF3ARw==} + resolution: {integrity: sha512-VXSSMsmb+Z8LbsQGcBMiM+fYObDNRm8p7tkUDMPG/g4fhFX5DEFmjxIEa3N8Zr96SjsJ1woAhF0DUnS3MF3ARw==, tarball: https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.2.tgz} engines: {node: '>=12'} cpu: [x64] os: [sunos] '@esbuild/sunos-x64@0.23.1': - resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==} + resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==, tarball: https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz} engines: {node: '>=18'} cpu: [x64] os: [sunos] '@esbuild/sunos-x64@0.25.5': - resolution: {integrity: sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==} + resolution: {integrity: sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==, tarball: https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz} engines: {node: '>=18'} cpu: [x64] os: [sunos] '@esbuild/sunos-x64@0.27.7': - resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==} + resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==, tarball: https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz} engines: {node: '>=18'} cpu: [x64] os: [sunos] '@esbuild/sunos-x64@0.28.1': - resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==} + resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==, tarball: https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz} engines: {node: '>=18'} cpu: [x64] os: [sunos] '@esbuild/win32-arm64@0.19.2': - resolution: {integrity: sha512-5NayUlSAyb5PQYFAU9x3bHdsqB88RC3aM9lKDAz4X1mo/EchMIT1Q+pSeBXNgkfNmRecLXA0O8xP+x8V+g/LKg==} + resolution: {integrity: sha512-5NayUlSAyb5PQYFAU9x3bHdsqB88RC3aM9lKDAz4X1mo/EchMIT1Q+pSeBXNgkfNmRecLXA0O8xP+x8V+g/LKg==, tarball: https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.2.tgz} engines: {node: '>=12'} cpu: [arm64] os: [win32] '@esbuild/win32-arm64@0.23.1': - resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==} + resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==, tarball: https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz} engines: {node: '>=18'} cpu: [arm64] os: [win32] '@esbuild/win32-arm64@0.25.5': - resolution: {integrity: sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==} + resolution: {integrity: sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==, tarball: https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz} engines: {node: '>=18'} cpu: [arm64] os: [win32] '@esbuild/win32-arm64@0.27.7': - resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==} + resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==, tarball: https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz} engines: {node: '>=18'} cpu: [arm64] os: [win32] '@esbuild/win32-arm64@0.28.1': - resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==} + resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==, tarball: https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz} engines: {node: '>=18'} cpu: [arm64] os: [win32] '@esbuild/win32-ia32@0.19.2': - resolution: {integrity: sha512-47gL/ek1v36iN0wL9L4Q2MFdujR0poLZMJwhO2/N3gA89jgHp4MR8DKCmwYtGNksbfJb9JoTtbkoe6sDhg2QTA==} + resolution: {integrity: sha512-47gL/ek1v36iN0wL9L4Q2MFdujR0poLZMJwhO2/N3gA89jgHp4MR8DKCmwYtGNksbfJb9JoTtbkoe6sDhg2QTA==, tarball: https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.2.tgz} engines: {node: '>=12'} cpu: [ia32] os: [win32] '@esbuild/win32-ia32@0.23.1': - resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==} + resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==, tarball: https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz} engines: {node: '>=18'} cpu: [ia32] os: [win32] '@esbuild/win32-ia32@0.25.5': - resolution: {integrity: sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==} + resolution: {integrity: sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==, tarball: https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz} engines: {node: '>=18'} cpu: [ia32] os: [win32] '@esbuild/win32-ia32@0.27.7': - resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==} + resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==, tarball: https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz} engines: {node: '>=18'} cpu: [ia32] os: [win32] '@esbuild/win32-ia32@0.28.1': - resolution: {integrity: sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==} + resolution: {integrity: sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==, tarball: https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz} engines: {node: '>=18'} cpu: [ia32] os: [win32] '@esbuild/win32-x64@0.19.2': - resolution: {integrity: sha512-tcuhV7ncXBqbt/Ybf0IyrMcwVOAPDckMK9rXNHtF17UTK18OKLpg08glminN06pt2WCoALhXdLfSPbVvK/6fxw==} + resolution: {integrity: sha512-tcuhV7ncXBqbt/Ybf0IyrMcwVOAPDckMK9rXNHtF17UTK18OKLpg08glminN06pt2WCoALhXdLfSPbVvK/6fxw==, tarball: https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.2.tgz} engines: {node: '>=12'} cpu: [x64] os: [win32] '@esbuild/win32-x64@0.23.1': - resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==} + resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==, tarball: https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz} engines: {node: '>=18'} cpu: [x64] os: [win32] '@esbuild/win32-x64@0.25.5': - resolution: {integrity: sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==} + resolution: {integrity: sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==, tarball: https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz} engines: {node: '>=18'} cpu: [x64] os: [win32] '@esbuild/win32-x64@0.27.7': - resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==} + resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==, tarball: https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz} engines: {node: '>=18'} cpu: [x64] os: [win32] '@esbuild/win32-x64@0.28.1': - resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==} + resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==, tarball: https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -3641,6 +3644,10 @@ packages: resolution: {integrity: sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/types@30.3.0': + resolution: {integrity: sha512-JHm87k7bA33hpBngtU8h6UBub/fqqA9uXfw+21j5Hmk7ooPHlboRNxHq0JcMtC+n8VJGP1mcfnD3Mk+XKe1oSw==, tarball: https://registry.npmjs.org/@jest/types/-/types-30.3.0.tgz} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/types@30.4.1': resolution: {integrity: sha512-f1x/vJXIfjOlEmejYpbkbgw1gOqpPECwMvMEtBqe47j7H2Hg8h8w3o3ikhSXq3MI15kg+oQ0exWO0uCtTNJLoQ==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -3814,37 +3821,37 @@ packages: resolution: {integrity: sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ==} '@lmdb/lmdb-darwin-arm64@3.5.6': - resolution: {integrity: sha512-mY5FG4TjPAkY4P0w+OhHaUka5mDh2TX2WKYIwuKzJ1zeW3VvRgxdam/lGJTquI+bthTx5CSHDW+BAQCnNAzkEA==} + resolution: {integrity: sha512-mY5FG4TjPAkY4P0w+OhHaUka5mDh2TX2WKYIwuKzJ1zeW3VvRgxdam/lGJTquI+bthTx5CSHDW+BAQCnNAzkEA==, tarball: https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.5.6.tgz} cpu: [arm64] os: [darwin] '@lmdb/lmdb-darwin-x64@3.5.6': - resolution: {integrity: sha512-foa+pwitysO8k+xhs7psBFfTKnVgR69NlZRRTHaFVDqphh7AdGpLeyRzKw/ofatr/sN6TiHRRW6mmop0ZrrppQ==} + resolution: {integrity: sha512-foa+pwitysO8k+xhs7psBFfTKnVgR69NlZRRTHaFVDqphh7AdGpLeyRzKw/ofatr/sN6TiHRRW6mmop0ZrrppQ==, tarball: https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.5.6.tgz} cpu: [x64] os: [darwin] '@lmdb/lmdb-linux-arm64@3.5.6': - resolution: {integrity: sha512-HmiyFFdJa38s1heCMSooSPaBSFTHJ3C+ERPp28xAPlDX1YiALJVOgbry065nXd8Y7KISWjnw05zpG1RX8IfftA==} + resolution: {integrity: sha512-HmiyFFdJa38s1heCMSooSPaBSFTHJ3C+ERPp28xAPlDX1YiALJVOgbry065nXd8Y7KISWjnw05zpG1RX8IfftA==, tarball: https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.5.6.tgz} cpu: [arm64] os: [linux] '@lmdb/lmdb-linux-arm@3.5.6': - resolution: {integrity: sha512-QR4YRyR5h5Z8eGXrNQjiyo2NNDfqi3tCc9dQG5Is1blCt+qWw1ZoBWhlWAr5d+jshkifMIJjVHzHGKbkKzF8Tw==} + resolution: {integrity: sha512-QR4YRyR5h5Z8eGXrNQjiyo2NNDfqi3tCc9dQG5Is1blCt+qWw1ZoBWhlWAr5d+jshkifMIJjVHzHGKbkKzF8Tw==, tarball: https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.5.6.tgz} cpu: [arm] os: [linux] '@lmdb/lmdb-linux-x64@3.5.6': - resolution: {integrity: sha512-ADzCuCF2cTNiX9kDScqcz1fjnAkxPpQNneV3KFTdV3wWtVlI2sTGzySoMTgDpinkMMFj1NTJlxA6XR8fwc4hlA==} + resolution: {integrity: sha512-ADzCuCF2cTNiX9kDScqcz1fjnAkxPpQNneV3KFTdV3wWtVlI2sTGzySoMTgDpinkMMFj1NTJlxA6XR8fwc4hlA==, tarball: https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.5.6.tgz} cpu: [x64] os: [linux] '@lmdb/lmdb-win32-arm64@3.5.6': - resolution: {integrity: sha512-J7A9aEQsQiv0TYtBGL7NDIPp2lOS8nnl+zm4sWZm1xlsTTaQ4PgD096Adzdrk27rw3UxCkDXdCUa4ax41oztBQ==} + resolution: {integrity: sha512-J7A9aEQsQiv0TYtBGL7NDIPp2lOS8nnl+zm4sWZm1xlsTTaQ4PgD096Adzdrk27rw3UxCkDXdCUa4ax41oztBQ==, tarball: https://registry.npmjs.org/@lmdb/lmdb-win32-arm64/-/lmdb-win32-arm64-3.5.6.tgz} cpu: [arm64] os: [win32] '@lmdb/lmdb-win32-x64@3.5.6': - resolution: {integrity: sha512-1g7G0knRX2iV/voDu54yxrGqw5Dk0w2oIYb7dgJq8IkOi+m7wbD8Q3QpPFjh0C01G58S88dqGn03len6UPCXsg==} + resolution: {integrity: sha512-1g7G0knRX2iV/voDu54yxrGqw5Dk0w2oIYb7dgJq8IkOi+m7wbD8Q3QpPFjh0C01G58S88dqGn03len6UPCXsg==, tarball: https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.5.6.tgz} cpu: [x64] os: [win32] @@ -4225,149 +4232,149 @@ packages: resolution: {integrity: sha512-3qLRIqcZVBNgJrZpiEzcTP8a6+mCdUV1QGk/XljawsQHyNieMVdLQtdLvkoF5Z5kRXNMovq+wv3vchKOMWyA8w==} '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4': - resolution: {integrity: sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ==} + resolution: {integrity: sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ==, tarball: https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.4.tgz} cpu: [arm64] os: [darwin] '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.4': - resolution: {integrity: sha512-zExlW9zUJKZH/tOtVMttwjKa4Xm/3KcNjnE3dPN92uCktwavMxpgCA3MoJK/DOnTWsQgo224OaST27/mPNAf+w==} + resolution: {integrity: sha512-zExlW9zUJKZH/tOtVMttwjKa4Xm/3KcNjnE3dPN92uCktwavMxpgCA3MoJK/DOnTWsQgo224OaST27/mPNAf+w==, tarball: https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.4.tgz} cpu: [x64] os: [darwin] '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.4': - resolution: {integrity: sha512-dgX0P/9wGPJeHFBG+ZmhgE6bmtMt7NP5CRBGyyktpopdk/mW4POnrpQsSLtKI1dwpc+pPLuXHDh6vvskyQE/sw==} + resolution: {integrity: sha512-dgX0P/9wGPJeHFBG+ZmhgE6bmtMt7NP5CRBGyyktpopdk/mW4POnrpQsSLtKI1dwpc+pPLuXHDh6vvskyQE/sw==, tarball: https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.4.tgz} cpu: [arm64] os: [linux] '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.4': - resolution: {integrity: sha512-Tg3yX65f5GbtXLkrYEHE5oibZG9epyYWas7FogTTEJeDEF9JlXJzKgXaNhT3UXlTOeA+AfZpYZYZ0uPj7Cfquw==} + resolution: {integrity: sha512-Tg3yX65f5GbtXLkrYEHE5oibZG9epyYWas7FogTTEJeDEF9JlXJzKgXaNhT3UXlTOeA+AfZpYZYZ0uPj7Cfquw==, tarball: https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.4.tgz} cpu: [arm] os: [linux] '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.4': - resolution: {integrity: sha512-8TNXMEjJc3QEy7R/x1INhgiU+XakDAFUzBhaz7+Rbrs8NH5UQeHQxxmzsSBJGyV6I1jW79undiQm8tOI+D+8FQ==} + resolution: {integrity: sha512-8TNXMEjJc3QEy7R/x1INhgiU+XakDAFUzBhaz7+Rbrs8NH5UQeHQxxmzsSBJGyV6I1jW79undiQm8tOI+D+8FQ==, tarball: https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.4.tgz} cpu: [x64] os: [linux] '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4': - resolution: {integrity: sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ==} + resolution: {integrity: sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ==, tarball: https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.4.tgz} cpu: [x64] os: [win32] '@napi-rs/nice-android-arm-eabi@1.1.1': - resolution: {integrity: sha512-kjirL3N6TnRPv5iuHw36wnucNqXAO46dzK9oPb0wj076R5Xm8PfUVA9nAFB5ZNMmfJQJVKACAPd/Z2KYMppthw==} + resolution: {integrity: sha512-kjirL3N6TnRPv5iuHw36wnucNqXAO46dzK9oPb0wj076R5Xm8PfUVA9nAFB5ZNMmfJQJVKACAPd/Z2KYMppthw==, tarball: https://registry.npmjs.org/@napi-rs/nice-android-arm-eabi/-/nice-android-arm-eabi-1.1.1.tgz} engines: {node: '>= 10'} cpu: [arm] os: [android] '@napi-rs/nice-android-arm64@1.1.1': - resolution: {integrity: sha512-blG0i7dXgbInN5urONoUCNf+DUEAavRffrO7fZSeoRMJc5qD+BJeNcpr54msPF6qfDD6kzs9AQJogZvT2KD5nw==} + resolution: {integrity: sha512-blG0i7dXgbInN5urONoUCNf+DUEAavRffrO7fZSeoRMJc5qD+BJeNcpr54msPF6qfDD6kzs9AQJogZvT2KD5nw==, tarball: https://registry.npmjs.org/@napi-rs/nice-android-arm64/-/nice-android-arm64-1.1.1.tgz} engines: {node: '>= 10'} cpu: [arm64] os: [android] '@napi-rs/nice-darwin-arm64@1.1.1': - resolution: {integrity: sha512-s/E7w45NaLqTGuOjC2p96pct4jRfo61xb9bU1unM/MJ/RFkKlJyJDx7OJI/O0ll/hrfpqKopuAFDV8yo0hfT7A==} + resolution: {integrity: sha512-s/E7w45NaLqTGuOjC2p96pct4jRfo61xb9bU1unM/MJ/RFkKlJyJDx7OJI/O0ll/hrfpqKopuAFDV8yo0hfT7A==, tarball: https://registry.npmjs.org/@napi-rs/nice-darwin-arm64/-/nice-darwin-arm64-1.1.1.tgz} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] '@napi-rs/nice-darwin-x64@1.1.1': - resolution: {integrity: sha512-dGoEBnVpsdcC+oHHmW1LRK5eiyzLwdgNQq3BmZIav+9/5WTZwBYX7r5ZkQC07Nxd3KHOCkgbHSh4wPkH1N1LiQ==} + resolution: {integrity: sha512-dGoEBnVpsdcC+oHHmW1LRK5eiyzLwdgNQq3BmZIav+9/5WTZwBYX7r5ZkQC07Nxd3KHOCkgbHSh4wPkH1N1LiQ==, tarball: https://registry.npmjs.org/@napi-rs/nice-darwin-x64/-/nice-darwin-x64-1.1.1.tgz} engines: {node: '>= 10'} cpu: [x64] os: [darwin] '@napi-rs/nice-freebsd-x64@1.1.1': - resolution: {integrity: sha512-kHv4kEHAylMYmlNwcQcDtXjklYp4FCf0b05E+0h6nDHsZ+F0bDe04U/tXNOqrx5CmIAth4vwfkjjUmp4c4JktQ==} + resolution: {integrity: sha512-kHv4kEHAylMYmlNwcQcDtXjklYp4FCf0b05E+0h6nDHsZ+F0bDe04U/tXNOqrx5CmIAth4vwfkjjUmp4c4JktQ==, tarball: https://registry.npmjs.org/@napi-rs/nice-freebsd-x64/-/nice-freebsd-x64-1.1.1.tgz} engines: {node: '>= 10'} cpu: [x64] os: [freebsd] '@napi-rs/nice-linux-arm-gnueabihf@1.1.1': - resolution: {integrity: sha512-E1t7K0efyKXZDoZg1LzCOLxgolxV58HCkaEkEvIYQx12ht2pa8hoBo+4OB3qh7e+QiBlp1SRf+voWUZFxyhyqg==} + resolution: {integrity: sha512-E1t7K0efyKXZDoZg1LzCOLxgolxV58HCkaEkEvIYQx12ht2pa8hoBo+4OB3qh7e+QiBlp1SRf+voWUZFxyhyqg==, tarball: https://registry.npmjs.org/@napi-rs/nice-linux-arm-gnueabihf/-/nice-linux-arm-gnueabihf-1.1.1.tgz} engines: {node: '>= 10'} cpu: [arm] os: [linux] '@napi-rs/nice-linux-arm64-gnu@1.1.1': - resolution: {integrity: sha512-CIKLA12DTIZlmTaaKhQP88R3Xao+gyJxNWEn04wZwC2wmRapNnxCUZkVwggInMJvtVElA+D4ZzOU5sX4jV+SmQ==} + resolution: {integrity: sha512-CIKLA12DTIZlmTaaKhQP88R3Xao+gyJxNWEn04wZwC2wmRapNnxCUZkVwggInMJvtVElA+D4ZzOU5sX4jV+SmQ==, tarball: https://registry.npmjs.org/@napi-rs/nice-linux-arm64-gnu/-/nice-linux-arm64-gnu-1.1.1.tgz} engines: {node: '>= 10'} cpu: [arm64] os: [linux] '@napi-rs/nice-linux-arm64-musl@1.1.1': - resolution: {integrity: sha512-+2Rzdb3nTIYZ0YJF43qf2twhqOCkiSrHx2Pg6DJaCPYhhaxbLcdlV8hCRMHghQ+EtZQWGNcS2xF4KxBhSGeutg==} + resolution: {integrity: sha512-+2Rzdb3nTIYZ0YJF43qf2twhqOCkiSrHx2Pg6DJaCPYhhaxbLcdlV8hCRMHghQ+EtZQWGNcS2xF4KxBhSGeutg==, tarball: https://registry.npmjs.org/@napi-rs/nice-linux-arm64-musl/-/nice-linux-arm64-musl-1.1.1.tgz} engines: {node: '>= 10'} cpu: [arm64] os: [linux] '@napi-rs/nice-linux-ppc64-gnu@1.1.1': - resolution: {integrity: sha512-4FS8oc0GeHpwvv4tKciKkw3Y4jKsL7FRhaOeiPei0X9T4Jd619wHNe4xCLmN2EMgZoeGg+Q7GY7BsvwKpL22Tg==} + resolution: {integrity: sha512-4FS8oc0GeHpwvv4tKciKkw3Y4jKsL7FRhaOeiPei0X9T4Jd619wHNe4xCLmN2EMgZoeGg+Q7GY7BsvwKpL22Tg==, tarball: https://registry.npmjs.org/@napi-rs/nice-linux-ppc64-gnu/-/nice-linux-ppc64-gnu-1.1.1.tgz} engines: {node: '>= 10'} cpu: [ppc64] os: [linux] '@napi-rs/nice-linux-riscv64-gnu@1.1.1': - resolution: {integrity: sha512-HU0nw9uD4FO/oGCCk409tCi5IzIZpH2agE6nN4fqpwVlCn5BOq0MS1dXGjXaG17JaAvrlpV5ZeyZwSon10XOXw==} + resolution: {integrity: sha512-HU0nw9uD4FO/oGCCk409tCi5IzIZpH2agE6nN4fqpwVlCn5BOq0MS1dXGjXaG17JaAvrlpV5ZeyZwSon10XOXw==, tarball: https://registry.npmjs.org/@napi-rs/nice-linux-riscv64-gnu/-/nice-linux-riscv64-gnu-1.1.1.tgz} engines: {node: '>= 10'} cpu: [riscv64] os: [linux] '@napi-rs/nice-linux-s390x-gnu@1.1.1': - resolution: {integrity: sha512-2YqKJWWl24EwrX0DzCQgPLKQBxYDdBxOHot1KWEq7aY2uYeX+Uvtv4I8xFVVygJDgf6/92h9N3Y43WPx8+PAgQ==} + resolution: {integrity: sha512-2YqKJWWl24EwrX0DzCQgPLKQBxYDdBxOHot1KWEq7aY2uYeX+Uvtv4I8xFVVygJDgf6/92h9N3Y43WPx8+PAgQ==, tarball: https://registry.npmjs.org/@napi-rs/nice-linux-s390x-gnu/-/nice-linux-s390x-gnu-1.1.1.tgz} engines: {node: '>= 10'} cpu: [s390x] os: [linux] '@napi-rs/nice-linux-x64-gnu@1.1.1': - resolution: {integrity: sha512-/gaNz3R92t+dcrfCw/96pDopcmec7oCcAQ3l/M+Zxr82KT4DljD37CpgrnXV+pJC263JkW572pdbP3hP+KjcIg==} + resolution: {integrity: sha512-/gaNz3R92t+dcrfCw/96pDopcmec7oCcAQ3l/M+Zxr82KT4DljD37CpgrnXV+pJC263JkW572pdbP3hP+KjcIg==, tarball: https://registry.npmjs.org/@napi-rs/nice-linux-x64-gnu/-/nice-linux-x64-gnu-1.1.1.tgz} engines: {node: '>= 10'} cpu: [x64] os: [linux] '@napi-rs/nice-linux-x64-musl@1.1.1': - resolution: {integrity: sha512-xScCGnyj/oppsNPMnevsBe3pvNaoK7FGvMjT35riz9YdhB2WtTG47ZlbxtOLpjeO9SqqQ2J2igCmz6IJOD5JYw==} + resolution: {integrity: sha512-xScCGnyj/oppsNPMnevsBe3pvNaoK7FGvMjT35riz9YdhB2WtTG47ZlbxtOLpjeO9SqqQ2J2igCmz6IJOD5JYw==, tarball: https://registry.npmjs.org/@napi-rs/nice-linux-x64-musl/-/nice-linux-x64-musl-1.1.1.tgz} engines: {node: '>= 10'} cpu: [x64] os: [linux] '@napi-rs/nice-openharmony-arm64@1.1.1': - resolution: {integrity: sha512-6uJPRVwVCLDeoOaNyeiW0gp2kFIM4r7PL2MczdZQHkFi9gVlgm+Vn+V6nTWRcu856mJ2WjYJiumEajfSm7arPQ==} + resolution: {integrity: sha512-6uJPRVwVCLDeoOaNyeiW0gp2kFIM4r7PL2MczdZQHkFi9gVlgm+Vn+V6nTWRcu856mJ2WjYJiumEajfSm7arPQ==, tarball: https://registry.npmjs.org/@napi-rs/nice-openharmony-arm64/-/nice-openharmony-arm64-1.1.1.tgz} engines: {node: '>= 10'} cpu: [arm64] os: [openharmony] '@napi-rs/nice-win32-arm64-msvc@1.1.1': - resolution: {integrity: sha512-uoTb4eAvM5B2aj/z8j+Nv8OttPf2m+HVx3UjA5jcFxASvNhQriyCQF1OB1lHL43ZhW+VwZlgvjmP5qF3+59atA==} + resolution: {integrity: sha512-uoTb4eAvM5B2aj/z8j+Nv8OttPf2m+HVx3UjA5jcFxASvNhQriyCQF1OB1lHL43ZhW+VwZlgvjmP5qF3+59atA==, tarball: https://registry.npmjs.org/@napi-rs/nice-win32-arm64-msvc/-/nice-win32-arm64-msvc-1.1.1.tgz} engines: {node: '>= 10'} cpu: [arm64] os: [win32] '@napi-rs/nice-win32-ia32-msvc@1.1.1': - resolution: {integrity: sha512-CNQqlQT9MwuCsg1Vd/oKXiuH+TcsSPJmlAFc5frFyX/KkOh0UpBLEj7aoY656d5UKZQMQFP7vJNa1DNUNORvug==} + resolution: {integrity: sha512-CNQqlQT9MwuCsg1Vd/oKXiuH+TcsSPJmlAFc5frFyX/KkOh0UpBLEj7aoY656d5UKZQMQFP7vJNa1DNUNORvug==, tarball: https://registry.npmjs.org/@napi-rs/nice-win32-ia32-msvc/-/nice-win32-ia32-msvc-1.1.1.tgz} engines: {node: '>= 10'} cpu: [ia32] os: [win32] '@napi-rs/nice-win32-x64-msvc@1.1.1': - resolution: {integrity: sha512-vB+4G/jBQCAh0jelMTY3+kgFy00Hlx2f2/1zjMoH821IbplbWZOkLiTYXQkygNTzQJTq5cvwBDgn2ppHD+bglQ==} + resolution: {integrity: sha512-vB+4G/jBQCAh0jelMTY3+kgFy00Hlx2f2/1zjMoH821IbplbWZOkLiTYXQkygNTzQJTq5cvwBDgn2ppHD+bglQ==, tarball: https://registry.npmjs.org/@napi-rs/nice-win32-x64-msvc/-/nice-win32-x64-msvc-1.1.1.tgz} engines: {node: '>= 10'} cpu: [x64] os: [win32] '@napi-rs/nice@1.1.1': - resolution: {integrity: sha512-xJIPs+bYuc9ASBl+cvGsKbGrJmS6fAKaSZCnT0lhahT5rhA2VVy9/EcIgd2JhtEuFOJNx7UHNn/qiTPTY4nrQw==} + resolution: {integrity: sha512-xJIPs+bYuc9ASBl+cvGsKbGrJmS6fAKaSZCnT0lhahT5rhA2VVy9/EcIgd2JhtEuFOJNx7UHNn/qiTPTY4nrQw==, tarball: https://registry.npmjs.org/@napi-rs/nice/-/nice-1.1.1.tgz} engines: {node: '>= 10'} '@napi-rs/wasm-runtime@0.2.4': resolution: {integrity: sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==} '@napi-rs/wasm-runtime@1.0.7': - resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==} + resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==, tarball: https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.7.tgz} '@napi-rs/wasm-runtime@1.1.6': - resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==, tarball: https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz} peerDependencies: '@emnapi/core': ^1.7.1 '@emnapi/runtime': ^1.7.1 @@ -4376,55 +4383,55 @@ packages: resolution: {integrity: sha512-irQnbMLbUNQpP1wcE5NstJtbuA/69kRfzBrpAD7Gsn8zm/CY6YQYc3HQBz8QPxwISG26tIm5afvvVbu508oBeQ==} '@next/swc-darwin-arm64@14.0.4': - resolution: {integrity: sha512-mF05E/5uPthWzyYDyptcwHptucf/jj09i2SXBPwNzbgBNc+XnwzrL0U6BmPjQeOL+FiB+iG1gwBeq7mlDjSRPg==} + resolution: {integrity: sha512-mF05E/5uPthWzyYDyptcwHptucf/jj09i2SXBPwNzbgBNc+XnwzrL0U6BmPjQeOL+FiB+iG1gwBeq7mlDjSRPg==, tarball: https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.4.tgz} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] '@next/swc-darwin-x64@14.0.4': - resolution: {integrity: sha512-IZQ3C7Bx0k2rYtrZZxKKiusMTM9WWcK5ajyhOZkYYTCc8xytmwSzR1skU7qLgVT/EY9xtXDG0WhY6fyujnI3rw==} + resolution: {integrity: sha512-IZQ3C7Bx0k2rYtrZZxKKiusMTM9WWcK5ajyhOZkYYTCc8xytmwSzR1skU7qLgVT/EY9xtXDG0WhY6fyujnI3rw==, tarball: https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.0.4.tgz} engines: {node: '>= 10'} cpu: [x64] os: [darwin] '@next/swc-linux-arm64-gnu@14.0.4': - resolution: {integrity: sha512-VwwZKrBQo/MGb1VOrxJ6LrKvbpo7UbROuyMRvQKTFKhNaXjUmKTu7wxVkIuCARAfiI8JpaWAnKR+D6tzpCcM4w==} + resolution: {integrity: sha512-VwwZKrBQo/MGb1VOrxJ6LrKvbpo7UbROuyMRvQKTFKhNaXjUmKTu7wxVkIuCARAfiI8JpaWAnKR+D6tzpCcM4w==, tarball: https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.4.tgz} engines: {node: '>= 10'} cpu: [arm64] os: [linux] '@next/swc-linux-arm64-musl@14.0.4': - resolution: {integrity: sha512-8QftwPEW37XxXoAwsn+nXlodKWHfpMaSvt81W43Wh8dv0gkheD+30ezWMcFGHLI71KiWmHK5PSQbTQGUiidvLQ==} + resolution: {integrity: sha512-8QftwPEW37XxXoAwsn+nXlodKWHfpMaSvt81W43Wh8dv0gkheD+30ezWMcFGHLI71KiWmHK5PSQbTQGUiidvLQ==, tarball: https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.4.tgz} engines: {node: '>= 10'} cpu: [arm64] os: [linux] '@next/swc-linux-x64-gnu@14.0.4': - resolution: {integrity: sha512-/s/Pme3VKfZAfISlYVq2hzFS8AcAIOTnoKupc/j4WlvF6GQ0VouS2Q2KEgPuO1eMBwakWPB1aYFIA4VNVh667A==} + resolution: {integrity: sha512-/s/Pme3VKfZAfISlYVq2hzFS8AcAIOTnoKupc/j4WlvF6GQ0VouS2Q2KEgPuO1eMBwakWPB1aYFIA4VNVh667A==, tarball: https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.4.tgz} engines: {node: '>= 10'} cpu: [x64] os: [linux] '@next/swc-linux-x64-musl@14.0.4': - resolution: {integrity: sha512-m8z/6Fyal4L9Bnlxde5g2Mfa1Z7dasMQyhEhskDATpqr+Y0mjOBZcXQ7G5U+vgL22cI4T7MfvgtrM2jdopqWaw==} + resolution: {integrity: sha512-m8z/6Fyal4L9Bnlxde5g2Mfa1Z7dasMQyhEhskDATpqr+Y0mjOBZcXQ7G5U+vgL22cI4T7MfvgtrM2jdopqWaw==, tarball: https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.4.tgz} engines: {node: '>= 10'} cpu: [x64] os: [linux] '@next/swc-win32-arm64-msvc@14.0.4': - resolution: {integrity: sha512-7Wv4PRiWIAWbm5XrGz3D8HUkCVDMMz9igffZG4NB1p4u1KoItwx9qjATHz88kwCEal/HXmbShucaslXCQXUM5w==} + resolution: {integrity: sha512-7Wv4PRiWIAWbm5XrGz3D8HUkCVDMMz9igffZG4NB1p4u1KoItwx9qjATHz88kwCEal/HXmbShucaslXCQXUM5w==, tarball: https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.4.tgz} engines: {node: '>= 10'} cpu: [arm64] os: [win32] '@next/swc-win32-ia32-msvc@14.0.4': - resolution: {integrity: sha512-zLeNEAPULsl0phfGb4kdzF/cAVIfaC7hY+kt0/d+y9mzcZHsMS3hAS829WbJ31DkSlVKQeHEjZHIdhN+Pg7Gyg==} + resolution: {integrity: sha512-zLeNEAPULsl0phfGb4kdzF/cAVIfaC7hY+kt0/d+y9mzcZHsMS3hAS829WbJ31DkSlVKQeHEjZHIdhN+Pg7Gyg==, tarball: https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.4.tgz} engines: {node: '>= 10'} cpu: [ia32] os: [win32] '@next/swc-win32-x64-msvc@14.0.4': - resolution: {integrity: sha512-yEh2+R8qDlDCjxVpzOTEpBLQTEFAcP2A8fUFLaWNap9GitYKkKv1//y2S6XY6zsR4rCOPRpU7plYDR+az2n30A==} + resolution: {integrity: sha512-yEh2+R8qDlDCjxVpzOTEpBLQTEFAcP2A8fUFLaWNap9GitYKkKv1//y2S6XY6zsR4rCOPRpU7plYDR+az2n30A==, tarball: https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.0.4.tgz} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -4638,102 +4645,102 @@ packages: optional: true '@nx/nx-darwin-arm64@21.6.11': - resolution: {integrity: sha512-4hXhV7ShXIlfPEjjm7dJY383xM2vTcnkKr5FUncAU08GKkkL67ib5CMlQADtdi32ewfCZntqiT8gUfFFSNvKtA==} + resolution: {integrity: sha512-4hXhV7ShXIlfPEjjm7dJY383xM2vTcnkKr5FUncAU08GKkkL67ib5CMlQADtdi32ewfCZntqiT8gUfFFSNvKtA==, tarball: https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-21.6.11.tgz} cpu: [arm64] os: [darwin] '@nx/nx-darwin-arm64@23.1.1': - resolution: {integrity: sha512-Rq/RXLX5uIvJQfb6kuUgEirquT5ARaAgQyNaMZVnOPAL5wuxaDvQag8WX/WUCIgbUKZuGkclJwM7Vlnvtn3bdg==} + resolution: {integrity: sha512-Rq/RXLX5uIvJQfb6kuUgEirquT5ARaAgQyNaMZVnOPAL5wuxaDvQag8WX/WUCIgbUKZuGkclJwM7Vlnvtn3bdg==, tarball: https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-23.1.1.tgz} cpu: [arm64] os: [darwin] '@nx/nx-darwin-x64@21.6.11': - resolution: {integrity: sha512-VxjKkzyhdO47X7d4JPx/f6HslERKetFmouDUBIoqbKDPVWpRegGMsRKcMYh4l61usxI1Qa2U4Ec6MgO5Fnm41g==} + resolution: {integrity: sha512-VxjKkzyhdO47X7d4JPx/f6HslERKetFmouDUBIoqbKDPVWpRegGMsRKcMYh4l61usxI1Qa2U4Ec6MgO5Fnm41g==, tarball: https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-21.6.11.tgz} cpu: [x64] os: [darwin] '@nx/nx-darwin-x64@23.1.1': - resolution: {integrity: sha512-doWaPLPd6yUas3FhQJqMAScupCsToeTedK4RRWm700VhHoVdBTN4ejIBRBfoiT/SPAwY6EOHb8uFDJhGo7geMg==} + resolution: {integrity: sha512-doWaPLPd6yUas3FhQJqMAScupCsToeTedK4RRWm700VhHoVdBTN4ejIBRBfoiT/SPAwY6EOHb8uFDJhGo7geMg==, tarball: https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-23.1.1.tgz} cpu: [x64] os: [darwin] '@nx/nx-freebsd-x64@21.6.11': - resolution: {integrity: sha512-3jDn7Tb3FMFfeFTM/XKAcI+J92kDLNmxUS/N/n/+kF/XYLPgMUZQqSeDpVifk4fgy0BCoH8DSMQIqTQau6dV/g==} + resolution: {integrity: sha512-3jDn7Tb3FMFfeFTM/XKAcI+J92kDLNmxUS/N/n/+kF/XYLPgMUZQqSeDpVifk4fgy0BCoH8DSMQIqTQau6dV/g==, tarball: https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-21.6.11.tgz} cpu: [x64] os: [freebsd] '@nx/nx-freebsd-x64@23.1.1': - resolution: {integrity: sha512-9rDZKBPGuX8mid11RimJ2ENqDYZpPZhrqTlI9q/VnqcPLq0Bw/8AhqCKhBVlfNqJjbi4OsRQYDK7UkqIlcfThg==} + resolution: {integrity: sha512-9rDZKBPGuX8mid11RimJ2ENqDYZpPZhrqTlI9q/VnqcPLq0Bw/8AhqCKhBVlfNqJjbi4OsRQYDK7UkqIlcfThg==, tarball: https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-23.1.1.tgz} cpu: [x64] os: [freebsd] '@nx/nx-linux-arm-gnueabihf@21.6.11': - resolution: {integrity: sha512-37tpiVod5FN/EAuCGh+uad/6nsfDFze02OjYReUPKeYPs8Q7Ac/V9j4kn/y5uZhKSle+9+sa2QR/K79B0+lNxw==} + resolution: {integrity: sha512-37tpiVod5FN/EAuCGh+uad/6nsfDFze02OjYReUPKeYPs8Q7Ac/V9j4kn/y5uZhKSle+9+sa2QR/K79B0+lNxw==, tarball: https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-21.6.11.tgz} cpu: [arm] os: [linux] '@nx/nx-linux-arm-gnueabihf@23.1.1': - resolution: {integrity: sha512-NDR5X2HiD6WU3JEaDJmOLteIGIFqjrjkzoFWrQke2Y1oCRYu+UyFdPeaMVUyAs5OyUx4U+SD+eBQPTCNbWmazA==} + resolution: {integrity: sha512-NDR5X2HiD6WU3JEaDJmOLteIGIFqjrjkzoFWrQke2Y1oCRYu+UyFdPeaMVUyAs5OyUx4U+SD+eBQPTCNbWmazA==, tarball: https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-23.1.1.tgz} cpu: [arm] os: [linux] '@nx/nx-linux-arm64-gnu@21.6.11': - resolution: {integrity: sha512-r+czH0OtldQqFm2B6BBBUPW8aO+sBMvpZCgN855vko30WaCeXo8Fkuk71rQMxByz0jnoCxSnzLtEWVZm1rmJYA==} + resolution: {integrity: sha512-r+czH0OtldQqFm2B6BBBUPW8aO+sBMvpZCgN855vko30WaCeXo8Fkuk71rQMxByz0jnoCxSnzLtEWVZm1rmJYA==, tarball: https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-21.6.11.tgz} cpu: [arm64] os: [linux] '@nx/nx-linux-arm64-gnu@23.1.1': - resolution: {integrity: sha512-tWDHJII8+aHweTzHelf5dGM6qGNmHbAPhCc3jrtrM0uE+UD/wt2Dpq7H3086Iyia9M9jGM9sYpuD/6W6WAFAMA==} + resolution: {integrity: sha512-tWDHJII8+aHweTzHelf5dGM6qGNmHbAPhCc3jrtrM0uE+UD/wt2Dpq7H3086Iyia9M9jGM9sYpuD/6W6WAFAMA==, tarball: https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-23.1.1.tgz} cpu: [arm64] os: [linux] '@nx/nx-linux-arm64-musl@21.6.11': - resolution: {integrity: sha512-0FAPyWEGPCukXxR1qowvFx6Q/cU906vwPlAQtcbrBU1e2H2aMUslk9EmL8iHb5MsHdmGcFyFemwr9oN8gxmz4g==} + resolution: {integrity: sha512-0FAPyWEGPCukXxR1qowvFx6Q/cU906vwPlAQtcbrBU1e2H2aMUslk9EmL8iHb5MsHdmGcFyFemwr9oN8gxmz4g==, tarball: https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-21.6.11.tgz} cpu: [arm64] os: [linux] '@nx/nx-linux-arm64-musl@23.1.1': - resolution: {integrity: sha512-t7iVMZ7Cj3LmPcfaYt9KOkojpuC5XRmtZ/0G+NBMA2GuRhCVbzpOgUCob0nQMV2TrTwn5oAWJeDc4xLni+oteg==} + resolution: {integrity: sha512-t7iVMZ7Cj3LmPcfaYt9KOkojpuC5XRmtZ/0G+NBMA2GuRhCVbzpOgUCob0nQMV2TrTwn5oAWJeDc4xLni+oteg==, tarball: https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-23.1.1.tgz} cpu: [arm64] os: [linux] '@nx/nx-linux-x64-gnu@21.6.11': - resolution: {integrity: sha512-+bWJWXJ8tdddl1L3bTKE0VmvTmdsk4zzUr6P9ts9hXQbwoWqMcuA6LNqOhUfzVOL3VioirRMtKMfFuUAUhi3Yg==} + resolution: {integrity: sha512-+bWJWXJ8tdddl1L3bTKE0VmvTmdsk4zzUr6P9ts9hXQbwoWqMcuA6LNqOhUfzVOL3VioirRMtKMfFuUAUhi3Yg==, tarball: https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-21.6.11.tgz} cpu: [x64] os: [linux] '@nx/nx-linux-x64-gnu@23.1.1': - resolution: {integrity: sha512-stuCayctOt/4AFvxKYgGTPluUc0HW7DcyTz9yeTMl/zj0+FENEr8RCTjInD0Q5qVGzYphma6SssVSh432w5agw==} + resolution: {integrity: sha512-stuCayctOt/4AFvxKYgGTPluUc0HW7DcyTz9yeTMl/zj0+FENEr8RCTjInD0Q5qVGzYphma6SssVSh432w5agw==, tarball: https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-23.1.1.tgz} cpu: [x64] os: [linux] '@nx/nx-linux-x64-musl@21.6.11': - resolution: {integrity: sha512-Mh09mLc+yeJk7DKfx7x6XfB+bm2dP1/7gyUuRQj4WjkT+Il2ZponyTuH8LmX06Jpr7efAAFk+8lBXeleV7XvMw==} + resolution: {integrity: sha512-Mh09mLc+yeJk7DKfx7x6XfB+bm2dP1/7gyUuRQj4WjkT+Il2ZponyTuH8LmX06Jpr7efAAFk+8lBXeleV7XvMw==, tarball: https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-21.6.11.tgz} cpu: [x64] os: [linux] '@nx/nx-linux-x64-musl@23.1.1': - resolution: {integrity: sha512-cZSUqGV+iHda39W91BNKSysSu6OFfR6M4ViQBcMtbwq3ce19gDr2f23MqGZEQZtaD/eSQ9UNEhx09nhrdYxWDg==} + resolution: {integrity: sha512-cZSUqGV+iHda39W91BNKSysSu6OFfR6M4ViQBcMtbwq3ce19gDr2f23MqGZEQZtaD/eSQ9UNEhx09nhrdYxWDg==, tarball: https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-23.1.1.tgz} cpu: [x64] os: [linux] '@nx/nx-win32-arm64-msvc@21.6.11': - resolution: {integrity: sha512-d7ZeCCDwaeyKiWD2JLSSxMSuSHHwIdpbnMtZtzRE6tDdAgs6e9F36/OBNQB3IRXH8V6QKOy2OGDyWeOKr01X9A==} + resolution: {integrity: sha512-d7ZeCCDwaeyKiWD2JLSSxMSuSHHwIdpbnMtZtzRE6tDdAgs6e9F36/OBNQB3IRXH8V6QKOy2OGDyWeOKr01X9A==, tarball: https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-21.6.11.tgz} cpu: [arm64] os: [win32] '@nx/nx-win32-arm64-msvc@23.1.1': - resolution: {integrity: sha512-iDlYbFHgTYV5lg1ypEt+LAj86o/uyy6vR0ha5pcUs4FqXzQgy14lOeyRod/EZs9Er3DIyJlEi/rpEvaP99/Hag==} + resolution: {integrity: sha512-iDlYbFHgTYV5lg1ypEt+LAj86o/uyy6vR0ha5pcUs4FqXzQgy14lOeyRod/EZs9Er3DIyJlEi/rpEvaP99/Hag==, tarball: https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-23.1.1.tgz} cpu: [arm64] os: [win32] '@nx/nx-win32-x64-msvc@21.6.11': - resolution: {integrity: sha512-otHSkhyoGilttV4RRkVmLLGb2W+Ia4b90lWxLnEm9jAAKmA9O2FUG2vAvKDHNcqTyDwwCcHfHxslgnR1u/3OIg==} + resolution: {integrity: sha512-otHSkhyoGilttV4RRkVmLLGb2W+Ia4b90lWxLnEm9jAAKmA9O2FUG2vAvKDHNcqTyDwwCcHfHxslgnR1u/3OIg==, tarball: https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-21.6.11.tgz} cpu: [x64] os: [win32] '@nx/nx-win32-x64-msvc@23.1.1': - resolution: {integrity: sha512-UD21AHWJ2PEA+PuANPCt+lj3kYpAzYNq+bm4VCbrt3KZd7zDPas0ns85UIhfrhsNiSmYzjWz2/JDk2S3cA6lGw==} + resolution: {integrity: sha512-UD21AHWJ2PEA+PuANPCt+lj3kYpAzYNq+bm4VCbrt3KZd7zDPas0ns85UIhfrhsNiSmYzjWz2/JDk2S3cA6lGw==, tarball: https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-23.1.1.tgz} cpu: [x64] os: [win32] @@ -4929,120 +4936,120 @@ packages: engines: {node: '>=8.0.0'} '@oxc-parser/binding-android-arm-eabi@0.142.0': - resolution: {integrity: sha512-ZiRGDutGsv1G6bL/ozy/koC0Sv39T1DqyoC4KD1DOy9ZoACm1O5UWhEK2c02Qdk+4lfLVkvFa/mQ0fm/4h1BtQ==} + resolution: {integrity: sha512-ZiRGDutGsv1G6bL/ozy/koC0Sv39T1DqyoC4KD1DOy9ZoACm1O5UWhEK2c02Qdk+4lfLVkvFa/mQ0fm/4h1BtQ==, tarball: https://registry.npmjs.org/@oxc-parser/binding-android-arm-eabi/-/binding-android-arm-eabi-0.142.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] '@oxc-parser/binding-android-arm64@0.142.0': - resolution: {integrity: sha512-WZkvGRLNQTz8lR9zP5nLjUdlroRCopBu3g9zF1p/laE6DzT1UbQo8Rdz5MWhaJUPYg/6gp+jo7HUgsyKaN1FtQ==} + resolution: {integrity: sha512-WZkvGRLNQTz8lR9zP5nLjUdlroRCopBu3g9zF1p/laE6DzT1UbQo8Rdz5MWhaJUPYg/6gp+jo7HUgsyKaN1FtQ==, tarball: https://registry.npmjs.org/@oxc-parser/binding-android-arm64/-/binding-android-arm64-0.142.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] '@oxc-parser/binding-darwin-arm64@0.142.0': - resolution: {integrity: sha512-l4khS8LQOOVYsGRVARo1gSaCT/aBSceUVXgtovWc2+drnxVuDr082WA3OCHVdVzIz5JIrP/y9CWsSKxBDNmYGg==} + resolution: {integrity: sha512-l4khS8LQOOVYsGRVARo1gSaCT/aBSceUVXgtovWc2+drnxVuDr082WA3OCHVdVzIz5JIrP/y9CWsSKxBDNmYGg==, tarball: https://registry.npmjs.org/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.142.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] '@oxc-parser/binding-darwin-x64@0.142.0': - resolution: {integrity: sha512-QBsNF3nqlXmcH2B1YOPqQYmCJoy4HuIjUxGbBO/k5JAJUl68ghU2psRY2zPk+RyBaWqKP/qfL4oaFgEMCdwskA==} + resolution: {integrity: sha512-QBsNF3nqlXmcH2B1YOPqQYmCJoy4HuIjUxGbBO/k5JAJUl68ghU2psRY2zPk+RyBaWqKP/qfL4oaFgEMCdwskA==, tarball: https://registry.npmjs.org/@oxc-parser/binding-darwin-x64/-/binding-darwin-x64-0.142.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] '@oxc-parser/binding-freebsd-x64@0.142.0': - resolution: {integrity: sha512-b7Q7m4Cqc6XqNhri3R+QhU+GVy646Pn+bkdhrDdWym/Fdi0ZUa+d73H9dm5H91JtbtAQ/z1d8XKMW3oOV8a4tQ==} + resolution: {integrity: sha512-b7Q7m4Cqc6XqNhri3R+QhU+GVy646Pn+bkdhrDdWym/Fdi0ZUa+d73H9dm5H91JtbtAQ/z1d8XKMW3oOV8a4tQ==, tarball: https://registry.npmjs.org/@oxc-parser/binding-freebsd-x64/-/binding-freebsd-x64-0.142.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] '@oxc-parser/binding-linux-arm-gnueabihf@0.142.0': - resolution: {integrity: sha512-3riVS5IhdH3uCZj1Y9ftDQlR0dvLsIlw/edrRqk8JhgNd5K0XSs+UBtgh50N13CAlW9/TXj6sVGXaKNBocd0Yg==} + resolution: {integrity: sha512-3riVS5IhdH3uCZj1Y9ftDQlR0dvLsIlw/edrRqk8JhgNd5K0XSs+UBtgh50N13CAlW9/TXj6sVGXaKNBocd0Yg==, tarball: https://registry.npmjs.org/@oxc-parser/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.142.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] '@oxc-parser/binding-linux-arm-musleabihf@0.142.0': - resolution: {integrity: sha512-NmXUOpgpTSkhl795TiXmWppTwmSJ92RC1qvD6e4XOF+slgmo3e6Ah+kEu+6AN8s7NAOEwqGmir58MgSQSWmBSA==} + resolution: {integrity: sha512-NmXUOpgpTSkhl795TiXmWppTwmSJ92RC1qvD6e4XOF+slgmo3e6Ah+kEu+6AN8s7NAOEwqGmir58MgSQSWmBSA==, tarball: https://registry.npmjs.org/@oxc-parser/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.142.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] '@oxc-parser/binding-linux-arm64-gnu@0.142.0': - resolution: {integrity: sha512-gc0EXsKtXgerujmU2Bql3u1L1HsSQ2774R83idq/FoNMPVV/RY/1ErFsvnit7KoiP/sLvzQixeUo4Ut0ic0wmw==} + resolution: {integrity: sha512-gc0EXsKtXgerujmU2Bql3u1L1HsSQ2774R83idq/FoNMPVV/RY/1ErFsvnit7KoiP/sLvzQixeUo4Ut0ic0wmw==, tarball: https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.142.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] '@oxc-parser/binding-linux-arm64-musl@0.142.0': - resolution: {integrity: sha512-F2XvmWSE0uWpie+jHKKIFgdVOe9ypGhkEZxKx5DuW215K6cbAC274yYaPkcM7EqY4Df3Weyhpcz3lsURyH2LVg==} + resolution: {integrity: sha512-F2XvmWSE0uWpie+jHKKIFgdVOe9ypGhkEZxKx5DuW215K6cbAC274yYaPkcM7EqY4Df3Weyhpcz3lsURyH2LVg==, tarball: https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.142.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] '@oxc-parser/binding-linux-ppc64-gnu@0.142.0': - resolution: {integrity: sha512-wLMbT21U/QxknQsk+VvNF0b9D2/aGWhcaQQQ+VYlE8FwD5+GoWZIPPXNzyHmkYyhm0KB3itL+TBavjMatqNnYA==} + resolution: {integrity: sha512-wLMbT21U/QxknQsk+VvNF0b9D2/aGWhcaQQQ+VYlE8FwD5+GoWZIPPXNzyHmkYyhm0KB3itL+TBavjMatqNnYA==, tarball: https://registry.npmjs.org/@oxc-parser/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.142.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] '@oxc-parser/binding-linux-riscv64-gnu@0.142.0': - resolution: {integrity: sha512-+G8F/4ckwT7FCJV4H2bt09xEzJbjNCfuL4Sp1AYNaFtFMVtgIGMuJlteT82U+K0UIZ/DzAR/LDlMFnEuajG7Kw==} + resolution: {integrity: sha512-+G8F/4ckwT7FCJV4H2bt09xEzJbjNCfuL4Sp1AYNaFtFMVtgIGMuJlteT82U+K0UIZ/DzAR/LDlMFnEuajG7Kw==, tarball: https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.142.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] '@oxc-parser/binding-linux-riscv64-musl@0.142.0': - resolution: {integrity: sha512-hTsHtTLxMAfCo+rpF5K3qZJKW2NpPN/CHd4mYB3y7XlSdspHkd2gehDIofP64AacA9nWQw2tY3O7wR6UY8IVOA==} + resolution: {integrity: sha512-hTsHtTLxMAfCo+rpF5K3qZJKW2NpPN/CHd4mYB3y7XlSdspHkd2gehDIofP64AacA9nWQw2tY3O7wR6UY8IVOA==, tarball: https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.142.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] '@oxc-parser/binding-linux-s390x-gnu@0.142.0': - resolution: {integrity: sha512-6y7qYY3TCUDYjqswImdTGl92y+KA/80twALegQPN27kfY+bG7Ib1+L3jbmrCZQx6wrVnai9IPsEZp07I0hx7JQ==} + resolution: {integrity: sha512-6y7qYY3TCUDYjqswImdTGl92y+KA/80twALegQPN27kfY+bG7Ib1+L3jbmrCZQx6wrVnai9IPsEZp07I0hx7JQ==, tarball: https://registry.npmjs.org/@oxc-parser/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.142.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] '@oxc-parser/binding-linux-x64-gnu@0.142.0': - resolution: {integrity: sha512-i69kAWU+2LgoH5bR+zWiiu+UzAw7Oxkwv7COeJTeY19pn4e70nKQcr9Pm6cL2Z0Z54d+gl9qADlK/0yyuCPiBA==} + resolution: {integrity: sha512-i69kAWU+2LgoH5bR+zWiiu+UzAw7Oxkwv7COeJTeY19pn4e70nKQcr9Pm6cL2Z0Z54d+gl9qADlK/0yyuCPiBA==, tarball: https://registry.npmjs.org/@oxc-parser/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.142.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] '@oxc-parser/binding-linux-x64-musl@0.142.0': - resolution: {integrity: sha512-4SQs678MmjYVrmhAgCWD4o0vpaFszXw9xLX5p2Z9MMFcltxiLkA88wQjh80YHjPrXtpyZ2CWI5m+1yNKM0m2Pw==} + resolution: {integrity: sha512-4SQs678MmjYVrmhAgCWD4o0vpaFszXw9xLX5p2Z9MMFcltxiLkA88wQjh80YHjPrXtpyZ2CWI5m+1yNKM0m2Pw==, tarball: https://registry.npmjs.org/@oxc-parser/binding-linux-x64-musl/-/binding-linux-x64-musl-0.142.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] '@oxc-parser/binding-openharmony-arm64@0.142.0': - resolution: {integrity: sha512-YHpx9N7Ln3a++Tc8rv+H7mrK1zyJQOAwCFg8LZ3lTs1T5afGWeZrLPhPT9HLnIwSjCyJqPWVMIrMxbjcmBr2oQ==} + resolution: {integrity: sha512-YHpx9N7Ln3a++Tc8rv+H7mrK1zyJQOAwCFg8LZ3lTs1T5afGWeZrLPhPT9HLnIwSjCyJqPWVMIrMxbjcmBr2oQ==, tarball: https://registry.npmjs.org/@oxc-parser/binding-openharmony-arm64/-/binding-openharmony-arm64-0.142.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] '@oxc-parser/binding-wasm32-wasi@0.142.0': - resolution: {integrity: sha512-3pLDyY3+oogW73RM5uehNgAiR/Xfb7fvO2Q1Z1gIqZ2+50XDVQmBVlRkHXZTU4gKnQHpwETNsYQVsJ3joVB2iA==} + resolution: {integrity: sha512-3pLDyY3+oogW73RM5uehNgAiR/Xfb7fvO2Q1Z1gIqZ2+50XDVQmBVlRkHXZTU4gKnQHpwETNsYQVsJ3joVB2iA==, tarball: https://registry.npmjs.org/@oxc-parser/binding-wasm32-wasi/-/binding-wasm32-wasi-0.142.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [wasm32] '@oxc-parser/binding-win32-arm64-msvc@0.142.0': - resolution: {integrity: sha512-Had/VeVY28Oyb0K+Q4FV8KCzoBycIh93oDK6pCbya9lkzdq+ikMHMgBubsdqqlybjJmQRawCQRrnBRHyQwYvcQ==} + resolution: {integrity: sha512-Had/VeVY28Oyb0K+Q4FV8KCzoBycIh93oDK6pCbya9lkzdq+ikMHMgBubsdqqlybjJmQRawCQRrnBRHyQwYvcQ==, tarball: https://registry.npmjs.org/@oxc-parser/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.142.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] '@oxc-parser/binding-win32-ia32-msvc@0.142.0': - resolution: {integrity: sha512-GGi3+YphVHavvgs6gum2UXoNCqzHAmPt/nXkn8ZQZstV2Q1qZD1Mn8fz/nWrDkefHQtrG/+1/XrbMxsBTo6Svw==} + resolution: {integrity: sha512-GGi3+YphVHavvgs6gum2UXoNCqzHAmPt/nXkn8ZQZstV2Q1qZD1Mn8fz/nWrDkefHQtrG/+1/XrbMxsBTo6Svw==, tarball: https://registry.npmjs.org/@oxc-parser/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.142.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] '@oxc-parser/binding-win32-x64-msvc@0.142.0': - resolution: {integrity: sha512-Ny/Wv4Us1LGC/ljwNTp+Hx3r/pH15EFfeDF0p+n898gt+TtRd6C9SccHcuUhDiNTb8s5tt7jdeAMDRQZ4Vq6hg==} + resolution: {integrity: sha512-Ny/Wv4Us1LGC/ljwNTp+Hx3r/pH15EFfeDF0p+n898gt+TtRd6C9SccHcuUhDiNTb8s5tt7jdeAMDRQZ4Vq6hg==, tarball: https://registry.npmjs.org/@oxc-parser/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.142.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -5057,180 +5064,180 @@ packages: resolution: {integrity: sha512-7W+2q5AKQVU36fkaryontrHn3YDt1RyUYXatw9i5H8ocYe2sPKSFB6eS8WNPeRKiN1qAWWZUPm7gwFzJGrccqQ==} '@oxc-resolver/binding-android-arm-eabi@11.24.2': - resolution: {integrity: sha512-y09e0L0SRI2OA2tUIrjBgoV3eH5hvUKXNkJqXmNo5V2WxIjyC7I7aJfRLMEVpA8yi95f90gFDvO0VMgrDw+vwA==} + resolution: {integrity: sha512-y09e0L0SRI2OA2tUIrjBgoV3eH5hvUKXNkJqXmNo5V2WxIjyC7I7aJfRLMEVpA8yi95f90gFDvO0VMgrDw+vwA==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-android-arm-eabi/-/binding-android-arm-eabi-11.24.2.tgz} cpu: [arm] os: [android] '@oxc-resolver/binding-android-arm64@11.24.2': - resolution: {integrity: sha512-cl4icWaZFnLdg8m6qtnh5rBMuGbxc/ptStFHLeCNwr+2cZjkjNwQu/jYRS0CHlnPecOJMpuS5M6/BH+0J/YkEg==} + resolution: {integrity: sha512-cl4icWaZFnLdg8m6qtnh5rBMuGbxc/ptStFHLeCNwr+2cZjkjNwQu/jYRS0CHlnPecOJMpuS5M6/BH+0J/YkEg==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-android-arm64/-/binding-android-arm64-11.24.2.tgz} cpu: [arm64] os: [android] '@oxc-resolver/binding-darwin-arm64@11.24.2': - resolution: {integrity: sha512-At29QEMF6HajbQvgY8K6OXnHD1x9rad74xBEfmCB6ZqCGsdq75aK7tOYcTbOanMy8qdIBrfL3SMr3p/lfSlb9w==} + resolution: {integrity: sha512-At29QEMF6HajbQvgY8K6OXnHD1x9rad74xBEfmCB6ZqCGsdq75aK7tOYcTbOanMy8qdIBrfL3SMr3p/lfSlb9w==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-11.24.2.tgz} cpu: [arm64] os: [darwin] '@oxc-resolver/binding-darwin-x64@11.24.2': - resolution: {integrity: sha512-A5Kqr1EUj4oIL5CF4WRssq/o5P0Y11cwoFouMRmQ7YnC/A8V93nv1nb7aSU8HwcgmXropjLNkVTl4MN87cu28Q==} + resolution: {integrity: sha512-A5Kqr1EUj4oIL5CF4WRssq/o5P0Y11cwoFouMRmQ7YnC/A8V93nv1nb7aSU8HwcgmXropjLNkVTl4MN87cu28Q==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-11.24.2.tgz} cpu: [x64] os: [darwin] '@oxc-resolver/binding-freebsd-x64@11.24.2': - resolution: {integrity: sha512-R5xkRBRRz7ceH/P5Jrc6G7FmdUdgpLYyESFAUDVTNQ9K0sGPxcp4ljiwEwEqsvNcQ4sYbMRrWcHHBCu7ksAJVw==} + resolution: {integrity: sha512-R5xkRBRRz7ceH/P5Jrc6G7FmdUdgpLYyESFAUDVTNQ9K0sGPxcp4ljiwEwEqsvNcQ4sYbMRrWcHHBCu7ksAJVw==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-freebsd-x64/-/binding-freebsd-x64-11.24.2.tgz} cpu: [x64] os: [freebsd] '@oxc-resolver/binding-linux-arm-gnueabihf@11.24.2': - resolution: {integrity: sha512-k/RuYL4L/R58IBn3wT5ma3Wh4k62bp1eYCFRWCmMsasUOqL+H6sW0VGFadEzKWXFFlz+2uIMoeMk9ySSZJHgbg==} + resolution: {integrity: sha512-k/RuYL4L/R58IBn3wT5ma3Wh4k62bp1eYCFRWCmMsasUOqL+H6sW0VGFadEzKWXFFlz+2uIMoeMk9ySSZJHgbg==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-11.24.2.tgz} cpu: [arm] os: [linux] '@oxc-resolver/binding-linux-arm-musleabihf@11.24.2': - resolution: {integrity: sha512-bnHAak3ujYfH5pKk4NieFNbvYvernfoQDgwLddbZ3OtMYrem87/qjlA+u+aKG0oZcqSLGCful/6/CEA+aeAgaA==} + resolution: {integrity: sha512-bnHAak3ujYfH5pKk4NieFNbvYvernfoQDgwLddbZ3OtMYrem87/qjlA+u+aKG0oZcqSLGCful/6/CEA+aeAgaA==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-11.24.2.tgz} cpu: [arm] os: [linux] '@oxc-resolver/binding-linux-arm64-gnu@11.24.2': - resolution: {integrity: sha512-vDT3KHgzYp47gmtNOqL2VNhCyl5Zv643eyxm//A68J8DeUGXrvD1pZFiaT4jSfe+RInfnn1R2yVHye4enx6RnA==} + resolution: {integrity: sha512-vDT3KHgzYp47gmtNOqL2VNhCyl5Zv643eyxm//A68J8DeUGXrvD1pZFiaT4jSfe+RInfnn1R2yVHye4enx6RnA==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-11.24.2.tgz} cpu: [arm64] os: [linux] '@oxc-resolver/binding-linux-arm64-musl@11.24.2': - resolution: {integrity: sha512-+kMlQvbzfyEYtu5FcjE4p+ttBLpKW4d/AsAsuE69BxV6V4twZJeIQZFfD8gh/wqglY0MkPSezWXQH0jBV13MUw==} + resolution: {integrity: sha512-+kMlQvbzfyEYtu5FcjE4p+ttBLpKW4d/AsAsuE69BxV6V4twZJeIQZFfD8gh/wqglY0MkPSezWXQH0jBV13MUw==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-11.24.2.tgz} cpu: [arm64] os: [linux] '@oxc-resolver/binding-linux-ppc64-gnu@11.24.2': - resolution: {integrity: sha512-shjfMhmZ3gq9fv/w7bi3PnZlgOPG+2QAOFf0BJF0EgBSIGZ6PMLN2zbGEblTUYB/NKVDRyYhE2ff3dJ1QqNPkA==} + resolution: {integrity: sha512-shjfMhmZ3gq9fv/w7bi3PnZlgOPG+2QAOFf0BJF0EgBSIGZ6PMLN2zbGEblTUYB/NKVDRyYhE2ff3dJ1QqNPkA==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-11.24.2.tgz} cpu: [ppc64] os: [linux] '@oxc-resolver/binding-linux-riscv64-gnu@11.24.2': - resolution: {integrity: sha512-zGelwFR5oRo+b69k8Lrzun86DyUHzfKN6cnjbR9l7Z7NIRznOE/2ZvPa1IUKqAL2PzAXOdwkfVqNvO1H2RlpAw==} + resolution: {integrity: sha512-zGelwFR5oRo+b69k8Lrzun86DyUHzfKN6cnjbR9l7Z7NIRznOE/2ZvPa1IUKqAL2PzAXOdwkfVqNvO1H2RlpAw==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-11.24.2.tgz} cpu: [riscv64] os: [linux] '@oxc-resolver/binding-linux-riscv64-musl@11.24.2': - resolution: {integrity: sha512-qxZ1SWCXJY0eyhAlP6Lmo9F2Nrtx7EkYj9oCgL8apDPCwXwCEDA2U697bbT81JIc2IrVjxO4KX6WU2N+oN9Z4w==} + resolution: {integrity: sha512-qxZ1SWCXJY0eyhAlP6Lmo9F2Nrtx7EkYj9oCgL8apDPCwXwCEDA2U697bbT81JIc2IrVjxO4KX6WU2N+oN9Z4w==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-11.24.2.tgz} cpu: [riscv64] os: [linux] '@oxc-resolver/binding-linux-s390x-gnu@11.24.2': - resolution: {integrity: sha512-sGCecF3cx2DFlH4t/z7ApnOnXqN48p5p5mlHDEnHTAukQa2P+qMVE4CwyWE9W+q/m3QJ7kKfGrIjax31f44oFQ==} + resolution: {integrity: sha512-sGCecF3cx2DFlH4t/z7ApnOnXqN48p5p5mlHDEnHTAukQa2P+qMVE4CwyWE9W+q/m3QJ7kKfGrIjax31f44oFQ==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-11.24.2.tgz} cpu: [s390x] os: [linux] '@oxc-resolver/binding-linux-x64-gnu@11.24.2': - resolution: {integrity: sha512-k/VlMMcSzMlahb3/fENM4rTlsJ0s3fFROA0KXPBmKggqmTSaE383sl8F3KCOXPLmVsYfW6hCitMhXCEtNeZxxg==} + resolution: {integrity: sha512-k/VlMMcSzMlahb3/fENM4rTlsJ0s3fFROA0KXPBmKggqmTSaE383sl8F3KCOXPLmVsYfW6hCitMhXCEtNeZxxg==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-11.24.2.tgz} cpu: [x64] os: [linux] '@oxc-resolver/binding-linux-x64-musl@11.24.2': - resolution: {integrity: sha512-8hbnZyNi97b/8wapYaIF9+t9GmZKBW2vunaOc3h9HGJptH7b7XpvZqOTBSm/MpTjr7H497BlgOaSfLUdhmy2bw==} + resolution: {integrity: sha512-8hbnZyNi97b/8wapYaIF9+t9GmZKBW2vunaOc3h9HGJptH7b7XpvZqOTBSm/MpTjr7H497BlgOaSfLUdhmy2bw==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-11.24.2.tgz} cpu: [x64] os: [linux] '@oxc-resolver/binding-openharmony-arm64@11.24.2': - resolution: {integrity: sha512-MvyGik3a6pVgZ0t/kWlbmFxFLmXQJwgLsY2eYFHLpy0wGwRbfzeIGgDwQ3kXqE30z+kSXennRkCrT7TUvkptNg==} + resolution: {integrity: sha512-MvyGik3a6pVgZ0t/kWlbmFxFLmXQJwgLsY2eYFHLpy0wGwRbfzeIGgDwQ3kXqE30z+kSXennRkCrT7TUvkptNg==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-openharmony-arm64/-/binding-openharmony-arm64-11.24.2.tgz} cpu: [arm64] os: [openharmony] '@oxc-resolver/binding-wasm32-wasi@11.24.2': - resolution: {integrity: sha512-vHcssMPwO08RTvj/c0iOBz90attxyG3wQJ0dTcyEQK43LRpcdLWZlV5feBhv6Isn6ahbQIzHbCgfa81+RiML0Q==} + resolution: {integrity: sha512-vHcssMPwO08RTvj/c0iOBz90attxyG3wQJ0dTcyEQK43LRpcdLWZlV5feBhv6Isn6ahbQIzHbCgfa81+RiML0Q==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-11.24.2.tgz} engines: {node: '>=14.0.0'} cpu: [wasm32] '@oxc-resolver/binding-win32-arm64-msvc@11.24.2': - resolution: {integrity: sha512-uokJqro2iBqkFvJdKQLP7d8/BUmFwESQFVmIJUQKj1Xn1a/LysJoe1vmeECLF5b3jsV8CAL5sEMJXX6SdK9Nhg==} + resolution: {integrity: sha512-uokJqro2iBqkFvJdKQLP7d8/BUmFwESQFVmIJUQKj1Xn1a/LysJoe1vmeECLF5b3jsV8CAL5sEMJXX6SdK9Nhg==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-11.24.2.tgz} cpu: [arm64] os: [win32] '@oxc-resolver/binding-win32-x64-msvc@11.24.2': - resolution: {integrity: sha512-UqGPmo56KDfLlfXFAFIrNflHT8tFxWGEivWg3Zeyp4Uy2NlKN1FGPr6/BxcLGG3+kZ6Wp14g5Uj+n71boqZfiw==} + resolution: {integrity: sha512-UqGPmo56KDfLlfXFAFIrNflHT8tFxWGEivWg3Zeyp4Uy2NlKN1FGPr6/BxcLGG3+kZ6Wp14g5Uj+n71boqZfiw==, tarball: https://registry.npmjs.org/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-11.24.2.tgz} cpu: [x64] os: [win32] '@parcel/watcher-android-arm64@2.5.6': - resolution: {integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==} + resolution: {integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==, tarball: https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [android] '@parcel/watcher-darwin-arm64@2.5.6': - resolution: {integrity: sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==} + resolution: {integrity: sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==, tarball: https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [darwin] '@parcel/watcher-darwin-x64@2.5.6': - resolution: {integrity: sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==} + resolution: {integrity: sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==, tarball: https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz} engines: {node: '>= 10.0.0'} cpu: [x64] os: [darwin] '@parcel/watcher-freebsd-x64@2.5.6': - resolution: {integrity: sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==} + resolution: {integrity: sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==, tarball: https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz} engines: {node: '>= 10.0.0'} cpu: [x64] os: [freebsd] '@parcel/watcher-linux-arm-glibc@2.5.6': - resolution: {integrity: sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==} + resolution: {integrity: sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==, tarball: https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] '@parcel/watcher-linux-arm-musl@2.5.6': - resolution: {integrity: sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==} + resolution: {integrity: sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==, tarball: https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] '@parcel/watcher-linux-arm64-glibc@2.5.6': - resolution: {integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==} + resolution: {integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==, tarball: https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] '@parcel/watcher-linux-arm64-musl@2.5.6': - resolution: {integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==} + resolution: {integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==, tarball: https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] '@parcel/watcher-linux-x64-glibc@2.5.6': - resolution: {integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==} + resolution: {integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==, tarball: https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] '@parcel/watcher-linux-x64-musl@2.5.6': - resolution: {integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==} + resolution: {integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==, tarball: https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] '@parcel/watcher-win32-arm64@2.5.6': - resolution: {integrity: sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==} + resolution: {integrity: sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==, tarball: https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [win32] '@parcel/watcher-win32-ia32@2.5.6': - resolution: {integrity: sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==} + resolution: {integrity: sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==, tarball: https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz} engines: {node: '>= 10.0.0'} cpu: [ia32] os: [win32] '@parcel/watcher-win32-x64@2.5.6': - resolution: {integrity: sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==} + resolution: {integrity: sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==, tarball: https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz} engines: {node: '>= 10.0.0'} cpu: [x64] os: [win32] '@parcel/watcher@2.5.6': - resolution: {integrity: sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==} + resolution: {integrity: sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==, tarball: https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz} engines: {node: '>= 10.0.0'} '@peculiar/asn1-cms@2.8.0': @@ -5281,7 +5288,7 @@ packages: typescript: '>3.0.0' '@pkgjs/parseargs@0.11.0': - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==, tarball: https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz} engines: {node: '>=14'} '@pkgr/core@0.3.6': @@ -5322,179 +5329,179 @@ packages: resolution: {integrity: sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==} '@rolldown/binding-android-arm64@1.1.5': - resolution: {integrity: sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==} + resolution: {integrity: sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==, tarball: https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] '@rolldown/binding-android-arm64@1.2.0': - resolution: {integrity: sha512-9yB1l95IrJuNGDFdOYe79vdApdz6WWBCObE+rQ2LUliYUlcyFwSYIb2xb5/Ifw7dAtMy2ZqNyd8QTSOc7duAKw==} + resolution: {integrity: sha512-9yB1l95IrJuNGDFdOYe79vdApdz6WWBCObE+rQ2LUliYUlcyFwSYIb2xb5/Ifw7dAtMy2ZqNyd8QTSOc7duAKw==, tarball: https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] '@rolldown/binding-darwin-arm64@1.1.5': - resolution: {integrity: sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==} + resolution: {integrity: sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==, tarball: https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] '@rolldown/binding-darwin-arm64@1.2.0': - resolution: {integrity: sha512-pexNaW9ACLUOaBITOpU6qVu4VrsOFIjTv6bzgu0YUATo4eUJx0V605PxwZfndpPOn0ilqGqvGQ0M8UW0IE24jg==} + resolution: {integrity: sha512-pexNaW9ACLUOaBITOpU6qVu4VrsOFIjTv6bzgu0YUATo4eUJx0V605PxwZfndpPOn0ilqGqvGQ0M8UW0IE24jg==, tarball: https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.0.tgz} 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==} + resolution: {integrity: sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==, tarball: https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] '@rolldown/binding-darwin-x64@1.2.0': - resolution: {integrity: sha512-NqKYaq0355ZmNMG4QGpxtEDxsc7tGDhjhCm4PpE0cwnBW+5Il95LJyq414niEiaKLVjnVHBEjSo1wngKxJNiFw==} + resolution: {integrity: sha512-NqKYaq0355ZmNMG4QGpxtEDxsc7tGDhjhCm4PpE0cwnBW+5Il95LJyq414niEiaKLVjnVHBEjSo1wngKxJNiFw==, tarball: https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.0.tgz} 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==} + resolution: {integrity: sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==, tarball: https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] '@rolldown/binding-freebsd-x64@1.2.0': - resolution: {integrity: sha512-3vPoHzh6eBTz9IbB0/qZdSr0Qeks2echn+I4cHu2joV74VriPDdldswksEDzrl1mBB+oPRi+67+3Ib59paxIPQ==} + resolution: {integrity: sha512-3vPoHzh6eBTz9IbB0/qZdSr0Qeks2echn+I4cHu2joV74VriPDdldswksEDzrl1mBB+oPRi+67+3Ib59paxIPQ==, tarball: https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.0.tgz} 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==} + resolution: {integrity: sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] '@rolldown/binding-linux-arm-gnueabihf@1.2.0': - resolution: {integrity: sha512-E6NNefZ1bUVmKJq2tJkf45J4Zyczj7qm9rUT7NY+Xo2474Y13qWAwc2tvBt0BAVbmtXR1llkxXg0Ou1jbDf2SQ==} + resolution: {integrity: sha512-E6NNefZ1bUVmKJq2tJkf45J4Zyczj7qm9rUT7NY+Xo2474Y13qWAwc2tvBt0BAVbmtXR1llkxXg0Ou1jbDf2SQ==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.0.tgz} 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==} + resolution: {integrity: sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] '@rolldown/binding-linux-arm64-gnu@1.2.0': - resolution: {integrity: sha512-D+TgkdgM1vu+7/Fpf8+v0ARW+RXEP9Ccazgm8zQ4JFFd9Q7SrYQ2TakU5S5ihazQDgpKyAgZDOcIFsvoHmTZ8w==} + resolution: {integrity: sha512-D+TgkdgM1vu+7/Fpf8+v0ARW+RXEP9Ccazgm8zQ4JFFd9Q7SrYQ2TakU5S5ihazQDgpKyAgZDOcIFsvoHmTZ8w==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] '@rolldown/binding-linux-arm64-musl@1.1.5': - resolution: {integrity: sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==} + resolution: {integrity: sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] '@rolldown/binding-linux-arm64-musl@1.2.0': - resolution: {integrity: sha512-wUqdwJBbAv0APN87GecstdMUtLjjNTs0hBALpxETD73mccFxdmt/XeizXDtN5RAlBwNKmI+Tg+blect2G+8IeQ==} + resolution: {integrity: sha512-wUqdwJBbAv0APN87GecstdMUtLjjNTs0hBALpxETD73mccFxdmt/XeizXDtN5RAlBwNKmI+Tg+blect2G+8IeQ==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] '@rolldown/binding-linux-ppc64-gnu@1.1.5': - resolution: {integrity: sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==} + resolution: {integrity: sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] '@rolldown/binding-linux-ppc64-gnu@1.2.0': - resolution: {integrity: sha512-9DtF35qR9/NrfhM4oxLplCzVVjE+KKm8Pjemi0i/sdhAWkUasjmSo8WTTubNJClhSHCfyk2yeyoXDQEDPtDAAw==} + resolution: {integrity: sha512-9DtF35qR9/NrfhM4oxLplCzVVjE+KKm8Pjemi0i/sdhAWkUasjmSo8WTTubNJClhSHCfyk2yeyoXDQEDPtDAAw==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] '@rolldown/binding-linux-s390x-gnu@1.1.5': - resolution: {integrity: sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==} + resolution: {integrity: sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] '@rolldown/binding-linux-s390x-gnu@1.2.0': - resolution: {integrity: sha512-RzuHrBh8X8Hntd2N4VR02QGEciq/9JhcZoTpR/Cee6otRrlILGCf3cg2ygHuih+ZebUnWmMrDX6ITI85btO6rQ==} + resolution: {integrity: sha512-RzuHrBh8X8Hntd2N4VR02QGEciq/9JhcZoTpR/Cee6otRrlILGCf3cg2ygHuih+ZebUnWmMrDX6ITI85btO6rQ==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] '@rolldown/binding-linux-x64-gnu@1.1.5': - resolution: {integrity: sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==} + resolution: {integrity: sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] '@rolldown/binding-linux-x64-gnu@1.2.0': - resolution: {integrity: sha512-MK7L0018jjh1jR3mh21G2j1zAVcpscJBlPo2z19pRjv2XOYGRhaV4LyiD8HO6nCDdZln9IFgCMIV5yt4E3klGQ==} + resolution: {integrity: sha512-MK7L0018jjh1jR3mh21G2j1zAVcpscJBlPo2z19pRjv2XOYGRhaV4LyiD8HO6nCDdZln9IFgCMIV5yt4E3klGQ==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] '@rolldown/binding-linux-x64-musl@1.1.5': - resolution: {integrity: sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==} + resolution: {integrity: sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.5.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] '@rolldown/binding-linux-x64-musl@1.2.0': - resolution: {integrity: sha512-gyrxLQ9NfGb/9LoVnC4kb9miUghw1mghnkfYvNHSnVIXriabnfgGPUP4RLcJm87q3KgYz4FYUG8IDiWUT+CpSw==} + resolution: {integrity: sha512-gyrxLQ9NfGb/9LoVnC4kb9miUghw1mghnkfYvNHSnVIXriabnfgGPUP4RLcJm87q3KgYz4FYUG8IDiWUT+CpSw==, tarball: https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] '@rolldown/binding-openharmony-arm64@1.1.5': - resolution: {integrity: sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==} + resolution: {integrity: sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==, tarball: https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] '@rolldown/binding-openharmony-arm64@1.2.0': - resolution: {integrity: sha512-/6VFMQGRmrhP77KXDC+StIxGzcNp5JOIyYtw0CQ8gPlzhpiIRucYfoM5FaFamHd5BJYIdH86yfP46l1p3WdrFA==} + resolution: {integrity: sha512-/6VFMQGRmrhP77KXDC+StIxGzcNp5JOIyYtw0CQ8gPlzhpiIRucYfoM5FaFamHd5BJYIdH86yfP46l1p3WdrFA==, tarball: https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] '@rolldown/binding-wasm32-wasi@1.1.5': - resolution: {integrity: sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==} + resolution: {integrity: sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==, tarball: https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [wasm32] '@rolldown/binding-wasm32-wasi@1.2.0': - resolution: {integrity: sha512-rwdbUL465kisF24WEJLvP3JrEG6E5GRuIHt5wpMwHGERtHe4Wm2CIvtf5gTBgr2tGOHKh5NdKEAFS2VkOPE91g==} + resolution: {integrity: sha512-rwdbUL465kisF24WEJLvP3JrEG6E5GRuIHt5wpMwHGERtHe4Wm2CIvtf5gTBgr2tGOHKh5NdKEAFS2VkOPE91g==, tarball: https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.2.0.tgz} 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==} + resolution: {integrity: sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==, tarball: https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] '@rolldown/binding-win32-arm64-msvc@1.2.0': - resolution: {integrity: sha512-+5suHwRiKGmhwyUaNT8a5QbrBvLFh2DbO910TEmGRH1aSxwrCezodvGQnulv4uiWEIv1Kq4ypRsJ5+O+ry1DiA==} + resolution: {integrity: sha512-+5suHwRiKGmhwyUaNT8a5QbrBvLFh2DbO910TEmGRH1aSxwrCezodvGQnulv4uiWEIv1Kq4ypRsJ5+O+ry1DiA==, tarball: https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.0.tgz} 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==} + resolution: {integrity: sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==, tarball: https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] '@rolldown/binding-win32-x64-msvc@1.2.0': - resolution: {integrity: sha512-WfFv6/qGufotqBSBzBYwgpCkJBk8Nj7697LL9vTz/XWc67e0r3oewu8iMRwQj3AUL45GVD7wVsPjCsAAtW66Wg==} + resolution: {integrity: sha512-WfFv6/qGufotqBSBzBYwgpCkJBk8Nj7697LL9vTz/XWc67e0r3oewu8iMRwQj3AUL45GVD7wVsPjCsAAtW66Wg==, tarball: https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.0.tgz} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -5581,242 +5588,242 @@ packages: optional: true '@rollup/rollup-android-arm-eabi@4.14.0': - resolution: {integrity: sha512-jwXtxYbRt1V+CdQSy6Z+uZti7JF5irRKF8hlKfEnF/xJpcNGuuiZMBvuoYM+x9sr9iWGnzrlM0+9hvQ1kgkf1w==} + resolution: {integrity: sha512-jwXtxYbRt1V+CdQSy6Z+uZti7JF5irRKF8hlKfEnF/xJpcNGuuiZMBvuoYM+x9sr9iWGnzrlM0+9hvQ1kgkf1w==, tarball: https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.0.tgz} cpu: [arm] os: [android] '@rollup/rollup-android-arm-eabi@4.62.2': - resolution: {integrity: sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==} + resolution: {integrity: sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==, tarball: https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz} cpu: [arm] os: [android] '@rollup/rollup-android-arm64@4.14.0': - resolution: {integrity: sha512-fI9nduZhCccjzlsA/OuAwtFGWocxA4gqXGTLvOyiF8d+8o0fZUeSztixkYjcGq1fGZY3Tkq4yRvHPFxU+jdZ9Q==} + resolution: {integrity: sha512-fI9nduZhCccjzlsA/OuAwtFGWocxA4gqXGTLvOyiF8d+8o0fZUeSztixkYjcGq1fGZY3Tkq4yRvHPFxU+jdZ9Q==, tarball: https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.0.tgz} cpu: [arm64] os: [android] '@rollup/rollup-android-arm64@4.62.2': - resolution: {integrity: sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==} + resolution: {integrity: sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==, tarball: https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.2.tgz} cpu: [arm64] os: [android] '@rollup/rollup-darwin-arm64@4.14.0': - resolution: {integrity: sha512-BcnSPRM76/cD2gQC+rQNGBN6GStBs2pl/FpweW8JYuz5J/IEa0Fr4AtrPv766DB/6b2MZ/AfSIOSGw3nEIP8SA==} + resolution: {integrity: sha512-BcnSPRM76/cD2gQC+rQNGBN6GStBs2pl/FpweW8JYuz5J/IEa0Fr4AtrPv766DB/6b2MZ/AfSIOSGw3nEIP8SA==, tarball: https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.14.0.tgz} cpu: [arm64] os: [darwin] '@rollup/rollup-darwin-arm64@4.34.9': - resolution: {integrity: sha512-0CY3/K54slrzLDjOA7TOjN1NuLKERBgk9nY5V34mhmuu673YNb+7ghaDUs6N0ujXR7fz5XaS5Aa6d2TNxZd0OQ==} + resolution: {integrity: sha512-0CY3/K54slrzLDjOA7TOjN1NuLKERBgk9nY5V34mhmuu673YNb+7ghaDUs6N0ujXR7fz5XaS5Aa6d2TNxZd0OQ==, tarball: https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.9.tgz} cpu: [arm64] os: [darwin] '@rollup/rollup-darwin-arm64@4.62.2': - resolution: {integrity: sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==} + resolution: {integrity: sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==, tarball: https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.2.tgz} cpu: [arm64] os: [darwin] '@rollup/rollup-darwin-x64@4.14.0': - resolution: {integrity: sha512-LDyFB9GRolGN7XI6955aFeI3wCdCUszFWumWU0deHA8VpR3nWRrjG6GtGjBrQxQKFevnUTHKCfPR4IvrW3kCgQ==} + resolution: {integrity: sha512-LDyFB9GRolGN7XI6955aFeI3wCdCUszFWumWU0deHA8VpR3nWRrjG6GtGjBrQxQKFevnUTHKCfPR4IvrW3kCgQ==, tarball: https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.14.0.tgz} cpu: [x64] os: [darwin] '@rollup/rollup-darwin-x64@4.34.9': - resolution: {integrity: sha512-eOojSEAi/acnsJVYRxnMkPFqcxSMFfrw7r2iD9Q32SGkb/Q9FpUY1UlAu1DH9T7j++gZ0lHjnm4OyH2vCI7l7Q==} + resolution: {integrity: sha512-eOojSEAi/acnsJVYRxnMkPFqcxSMFfrw7r2iD9Q32SGkb/Q9FpUY1UlAu1DH9T7j++gZ0lHjnm4OyH2vCI7l7Q==, tarball: https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.9.tgz} cpu: [x64] os: [darwin] '@rollup/rollup-darwin-x64@4.62.2': - resolution: {integrity: sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==} + resolution: {integrity: sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==, tarball: https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.2.tgz} cpu: [x64] os: [darwin] '@rollup/rollup-freebsd-arm64@4.62.2': - resolution: {integrity: sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==} + resolution: {integrity: sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==, tarball: https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.2.tgz} cpu: [arm64] os: [freebsd] '@rollup/rollup-freebsd-x64@4.62.2': - resolution: {integrity: sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==} + resolution: {integrity: sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==, tarball: https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.2.tgz} cpu: [x64] os: [freebsd] '@rollup/rollup-linux-arm-gnueabihf@4.14.0': - resolution: {integrity: sha512-ygrGVhQP47mRh0AAD0zl6QqCbNsf0eTo+vgwkY6LunBcg0f2Jv365GXlDUECIyoXp1kKwL5WW6rsO429DBY/bA==} + resolution: {integrity: sha512-ygrGVhQP47mRh0AAD0zl6QqCbNsf0eTo+vgwkY6LunBcg0f2Jv365GXlDUECIyoXp1kKwL5WW6rsO429DBY/bA==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.14.0.tgz} cpu: [arm] os: [linux] '@rollup/rollup-linux-arm-gnueabihf@4.62.2': - resolution: {integrity: sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==} + resolution: {integrity: sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.2.tgz} cpu: [arm] os: [linux] '@rollup/rollup-linux-arm-musleabihf@4.62.2': - resolution: {integrity: sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==} + resolution: {integrity: sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.2.tgz} cpu: [arm] os: [linux] '@rollup/rollup-linux-arm64-gnu@4.14.0': - resolution: {integrity: sha512-x+uJ6MAYRlHGe9wi4HQjxpaKHPM3d3JjqqCkeC5gpnnI6OWovLdXTpfa8trjxPLnWKyBsSi5kne+146GAxFt4A==} + resolution: {integrity: sha512-x+uJ6MAYRlHGe9wi4HQjxpaKHPM3d3JjqqCkeC5gpnnI6OWovLdXTpfa8trjxPLnWKyBsSi5kne+146GAxFt4A==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.14.0.tgz} cpu: [arm64] os: [linux] '@rollup/rollup-linux-arm64-gnu@4.34.9': - resolution: {integrity: sha512-6TZjPHjKZUQKmVKMUowF3ewHxctrRR09eYyvT5eFv8w/fXarEra83A2mHTVJLA5xU91aCNOUnM+DWFMSbQ0Nxw==} + resolution: {integrity: sha512-6TZjPHjKZUQKmVKMUowF3ewHxctrRR09eYyvT5eFv8w/fXarEra83A2mHTVJLA5xU91aCNOUnM+DWFMSbQ0Nxw==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.9.tgz} cpu: [arm64] os: [linux] '@rollup/rollup-linux-arm64-gnu@4.62.2': - resolution: {integrity: sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==} + resolution: {integrity: sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.2.tgz} cpu: [arm64] os: [linux] '@rollup/rollup-linux-arm64-musl@4.14.0': - resolution: {integrity: sha512-nrRw8ZTQKg6+Lttwqo6a2VxR9tOroa2m91XbdQ2sUUzHoedXlsyvY1fN4xWdqz8PKmf4orDwejxXHjh7YBGUCA==} + resolution: {integrity: sha512-nrRw8ZTQKg6+Lttwqo6a2VxR9tOroa2m91XbdQ2sUUzHoedXlsyvY1fN4xWdqz8PKmf4orDwejxXHjh7YBGUCA==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.14.0.tgz} cpu: [arm64] os: [linux] '@rollup/rollup-linux-arm64-musl@4.34.9': - resolution: {integrity: sha512-LD2fytxZJZ6xzOKnMbIpgzFOuIKlxVOpiMAXawsAZ2mHBPEYOnLRK5TTEsID6z4eM23DuO88X0Tq1mErHMVq0A==} + resolution: {integrity: sha512-LD2fytxZJZ6xzOKnMbIpgzFOuIKlxVOpiMAXawsAZ2mHBPEYOnLRK5TTEsID6z4eM23DuO88X0Tq1mErHMVq0A==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.9.tgz} cpu: [arm64] os: [linux] '@rollup/rollup-linux-arm64-musl@4.62.2': - resolution: {integrity: sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==} + resolution: {integrity: sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.2.tgz} cpu: [arm64] os: [linux] '@rollup/rollup-linux-loong64-gnu@4.62.2': - resolution: {integrity: sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==} + resolution: {integrity: sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.2.tgz} cpu: [loong64] os: [linux] '@rollup/rollup-linux-loong64-musl@4.62.2': - resolution: {integrity: sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==} + resolution: {integrity: sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.2.tgz} cpu: [loong64] os: [linux] '@rollup/rollup-linux-powerpc64le-gnu@4.14.0': - resolution: {integrity: sha512-xV0d5jDb4aFu84XKr+lcUJ9y3qpIWhttO3Qev97z8DKLXR62LC3cXT/bMZXrjLF9X+P5oSmJTzAhqwUbY96PnA==} + resolution: {integrity: sha512-xV0d5jDb4aFu84XKr+lcUJ9y3qpIWhttO3Qev97z8DKLXR62LC3cXT/bMZXrjLF9X+P5oSmJTzAhqwUbY96PnA==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.14.0.tgz} cpu: [ppc64le] os: [linux] '@rollup/rollup-linux-ppc64-gnu@4.62.2': - resolution: {integrity: sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==} + resolution: {integrity: sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.2.tgz} cpu: [ppc64] os: [linux] '@rollup/rollup-linux-ppc64-musl@4.62.2': - resolution: {integrity: sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==} + resolution: {integrity: sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.2.tgz} cpu: [ppc64] os: [linux] '@rollup/rollup-linux-riscv64-gnu@4.14.0': - resolution: {integrity: sha512-SDDhBQwZX6LPRoPYjAZWyL27LbcBo7WdBFWJi5PI9RPCzU8ijzkQn7tt8NXiXRiFMJCVpkuMkBf4OxSxVMizAw==} + resolution: {integrity: sha512-SDDhBQwZX6LPRoPYjAZWyL27LbcBo7WdBFWJi5PI9RPCzU8ijzkQn7tt8NXiXRiFMJCVpkuMkBf4OxSxVMizAw==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.14.0.tgz} cpu: [riscv64] os: [linux] '@rollup/rollup-linux-riscv64-gnu@4.62.2': - resolution: {integrity: sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==} + resolution: {integrity: sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.2.tgz} cpu: [riscv64] os: [linux] '@rollup/rollup-linux-riscv64-musl@4.62.2': - resolution: {integrity: sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==} + resolution: {integrity: sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.2.tgz} cpu: [riscv64] os: [linux] '@rollup/rollup-linux-s390x-gnu@4.14.0': - resolution: {integrity: sha512-RxB/qez8zIDshNJDufYlTT0ZTVut5eCpAZ3bdXDU9yTxBzui3KhbGjROK2OYTTor7alM7XBhssgoO3CZ0XD3qA==} + resolution: {integrity: sha512-RxB/qez8zIDshNJDufYlTT0ZTVut5eCpAZ3bdXDU9yTxBzui3KhbGjROK2OYTTor7alM7XBhssgoO3CZ0XD3qA==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.14.0.tgz} cpu: [s390x] os: [linux] '@rollup/rollup-linux-s390x-gnu@4.62.2': - resolution: {integrity: sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==} + resolution: {integrity: sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.2.tgz} cpu: [s390x] os: [linux] '@rollup/rollup-linux-x64-gnu@4.14.0': - resolution: {integrity: sha512-C6y6z2eCNCfhZxT9u+jAM2Fup89ZjiG5pIzZIDycs1IwESviLxwkQcFRGLjnDrP+PT+v5i4YFvlcfAs+LnreXg==} + resolution: {integrity: sha512-C6y6z2eCNCfhZxT9u+jAM2Fup89ZjiG5pIzZIDycs1IwESviLxwkQcFRGLjnDrP+PT+v5i4YFvlcfAs+LnreXg==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.14.0.tgz} cpu: [x64] os: [linux] '@rollup/rollup-linux-x64-gnu@4.34.9': - resolution: {integrity: sha512-FwBHNSOjUTQLP4MG7y6rR6qbGw4MFeQnIBrMe161QGaQoBQLqSUEKlHIiVgF3g/mb3lxlxzJOpIBhaP+C+KP2A==} + resolution: {integrity: sha512-FwBHNSOjUTQLP4MG7y6rR6qbGw4MFeQnIBrMe161QGaQoBQLqSUEKlHIiVgF3g/mb3lxlxzJOpIBhaP+C+KP2A==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.9.tgz} cpu: [x64] os: [linux] '@rollup/rollup-linux-x64-gnu@4.62.2': - resolution: {integrity: sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==} + resolution: {integrity: sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.2.tgz} cpu: [x64] os: [linux] '@rollup/rollup-linux-x64-musl@4.14.0': - resolution: {integrity: sha512-i0QwbHYfnOMYsBEyjxcwGu5SMIi9sImDVjDg087hpzXqhBSosxkE7gyIYFHgfFl4mr7RrXksIBZ4DoLoP4FhJg==} + resolution: {integrity: sha512-i0QwbHYfnOMYsBEyjxcwGu5SMIi9sImDVjDg087hpzXqhBSosxkE7gyIYFHgfFl4mr7RrXksIBZ4DoLoP4FhJg==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.14.0.tgz} cpu: [x64] os: [linux] '@rollup/rollup-linux-x64-musl@4.34.9': - resolution: {integrity: sha512-cYRpV4650z2I3/s6+5/LONkjIz8MBeqrk+vPXV10ORBnshpn8S32bPqQ2Utv39jCiDcO2eJTuSlPXpnvmaIgRA==} + resolution: {integrity: sha512-cYRpV4650z2I3/s6+5/LONkjIz8MBeqrk+vPXV10ORBnshpn8S32bPqQ2Utv39jCiDcO2eJTuSlPXpnvmaIgRA==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.9.tgz} cpu: [x64] os: [linux] '@rollup/rollup-linux-x64-musl@4.62.2': - resolution: {integrity: sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==} + resolution: {integrity: sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.2.tgz} cpu: [x64] os: [linux] '@rollup/rollup-openbsd-x64@4.62.2': - resolution: {integrity: sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==} + resolution: {integrity: sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==, tarball: https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.2.tgz} cpu: [x64] os: [openbsd] '@rollup/rollup-openharmony-arm64@4.62.2': - resolution: {integrity: sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==} + resolution: {integrity: sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==, tarball: https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.2.tgz} cpu: [arm64] os: [openharmony] '@rollup/rollup-win32-arm64-msvc@4.14.0': - resolution: {integrity: sha512-Fq52EYb0riNHLBTAcL0cun+rRwyZ10S9vKzhGKKgeD+XbwunszSY0rVMco5KbOsTlwovP2rTOkiII/fQ4ih/zQ==} + resolution: {integrity: sha512-Fq52EYb0riNHLBTAcL0cun+rRwyZ10S9vKzhGKKgeD+XbwunszSY0rVMco5KbOsTlwovP2rTOkiII/fQ4ih/zQ==, tarball: https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.14.0.tgz} cpu: [arm64] os: [win32] '@rollup/rollup-win32-arm64-msvc@4.34.9': - resolution: {integrity: sha512-z4mQK9dAN6byRA/vsSgQiPeuO63wdiDxZ9yg9iyX2QTzKuQM7T4xlBoeUP/J8uiFkqxkcWndWi+W7bXdPbt27Q==} + resolution: {integrity: sha512-z4mQK9dAN6byRA/vsSgQiPeuO63wdiDxZ9yg9iyX2QTzKuQM7T4xlBoeUP/J8uiFkqxkcWndWi+W7bXdPbt27Q==, tarball: https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.9.tgz} cpu: [arm64] os: [win32] '@rollup/rollup-win32-arm64-msvc@4.62.2': - resolution: {integrity: sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==} + resolution: {integrity: sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==, tarball: https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.2.tgz} cpu: [arm64] os: [win32] '@rollup/rollup-win32-ia32-msvc@4.14.0': - resolution: {integrity: sha512-e/PBHxPdJ00O9p5Ui43+vixSgVf4NlLsmV6QneGERJ3lnjIua/kim6PRFe3iDueT1rQcgSkYP8ZBBXa/h4iPvw==} + resolution: {integrity: sha512-e/PBHxPdJ00O9p5Ui43+vixSgVf4NlLsmV6QneGERJ3lnjIua/kim6PRFe3iDueT1rQcgSkYP8ZBBXa/h4iPvw==, tarball: https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.14.0.tgz} cpu: [ia32] os: [win32] '@rollup/rollup-win32-ia32-msvc@4.62.2': - resolution: {integrity: sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==} + resolution: {integrity: sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==, tarball: https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.2.tgz} cpu: [ia32] os: [win32] '@rollup/rollup-win32-x64-gnu@4.62.2': - resolution: {integrity: sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==} + resolution: {integrity: sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==, tarball: https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.2.tgz} cpu: [x64] os: [win32] '@rollup/rollup-win32-x64-msvc@4.14.0': - resolution: {integrity: sha512-aGg7iToJjdklmxlUlJh/PaPNa4PmqHfyRMLunbL3eaMO0gp656+q1zOKkpJ/CVe9CryJv6tAN1HDoR8cNGzkag==} + resolution: {integrity: sha512-aGg7iToJjdklmxlUlJh/PaPNa4PmqHfyRMLunbL3eaMO0gp656+q1zOKkpJ/CVe9CryJv6tAN1HDoR8cNGzkag==, tarball: https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.0.tgz} cpu: [x64] os: [win32] '@rollup/rollup-win32-x64-msvc@4.34.9': - resolution: {integrity: sha512-AyleYRPU7+rgkMWbEh71fQlrzRfeP6SyMnRf9XX4fCdDPAJumdSBqYEcWPMzVQ4ScAl7E4oFfK0GUVn77xSwbw==} + resolution: {integrity: sha512-AyleYRPU7+rgkMWbEh71fQlrzRfeP6SyMnRf9XX4fCdDPAJumdSBqYEcWPMzVQ4ScAl7E4oFfK0GUVn77xSwbw==, tarball: https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.9.tgz} cpu: [x64] os: [win32] '@rollup/rollup-win32-x64-msvc@4.62.2': - resolution: {integrity: sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==} + resolution: {integrity: sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==, tarball: https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.2.tgz} cpu: [x64] os: [win32] @@ -5826,110 +5833,110 @@ packages: hasBin: true '@rspack/binding-darwin-arm64@1.7.12': - resolution: {integrity: sha512-rbFprJaJiqrmfy8SHth8EsoRS0wg4bXcucwj9NiMzpGFq14Opw8c04iQ6H9BECYzgmN0PKZ9rh41LdVvhdZe4A==} + resolution: {integrity: sha512-rbFprJaJiqrmfy8SHth8EsoRS0wg4bXcucwj9NiMzpGFq14Opw8c04iQ6H9BECYzgmN0PKZ9rh41LdVvhdZe4A==, tarball: https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.7.12.tgz} cpu: [arm64] os: [darwin] '@rspack/binding-darwin-arm64@2.1.4': - resolution: {integrity: sha512-3Xcs01iw48F4WeE4SHga6bCNb/UEFvtQX4P4eMIaJfGPjTQuxfabGE8yCPm9e3tpLZ5uo+IBnJ6nh5r6tIDOXQ==} + resolution: {integrity: sha512-3Xcs01iw48F4WeE4SHga6bCNb/UEFvtQX4P4eMIaJfGPjTQuxfabGE8yCPm9e3tpLZ5uo+IBnJ6nh5r6tIDOXQ==, tarball: https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-2.1.4.tgz} cpu: [arm64] os: [darwin] '@rspack/binding-darwin-x64@1.7.12': - resolution: {integrity: sha512-jnOp+/UXOJa9xqUb8KXH03sysoO2e4Ij6tw6MqDdmdj8n/A8PQENRPUbW9AwXpPtVDJPus9r4fi7b3+6e4B8Hg==} + resolution: {integrity: sha512-jnOp+/UXOJa9xqUb8KXH03sysoO2e4Ij6tw6MqDdmdj8n/A8PQENRPUbW9AwXpPtVDJPus9r4fi7b3+6e4B8Hg==, tarball: https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.7.12.tgz} cpu: [x64] os: [darwin] '@rspack/binding-darwin-x64@2.1.4': - resolution: {integrity: sha512-bz/AsCplLs+3fXULPQU9d4r8H4PdeljgHFyItvVIrA/NKZqzQ8sX0topf/zJVZAOtPH7GNnrKjq0/F0U2DHikQ==} + resolution: {integrity: sha512-bz/AsCplLs+3fXULPQU9d4r8H4PdeljgHFyItvVIrA/NKZqzQ8sX0topf/zJVZAOtPH7GNnrKjq0/F0U2DHikQ==, tarball: https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-2.1.4.tgz} cpu: [x64] os: [darwin] '@rspack/binding-linux-arm64-gnu@1.7.12': - resolution: {integrity: sha512-C8owWG+yvo7X0oVLIXetkoJhIFBP1LYNcAQqtgLmJnQLQDklGuP83dKC+zISGQWpjawHfZ1ER96vLgoTrxKZdw==} + resolution: {integrity: sha512-C8owWG+yvo7X0oVLIXetkoJhIFBP1LYNcAQqtgLmJnQLQDklGuP83dKC+zISGQWpjawHfZ1ER96vLgoTrxKZdw==, tarball: https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.7.12.tgz} cpu: [arm64] os: [linux] '@rspack/binding-linux-arm64-gnu@2.1.4': - resolution: {integrity: sha512-x0HQTLU1MusCtNamuXxf3ayEPkvh9uuaq4wVyBqveRkn4FznSOoHUsxTAKMnjGARX+vdLV/y/SwWJRDp2RI4zw==} + resolution: {integrity: sha512-x0HQTLU1MusCtNamuXxf3ayEPkvh9uuaq4wVyBqveRkn4FznSOoHUsxTAKMnjGARX+vdLV/y/SwWJRDp2RI4zw==, tarball: https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-2.1.4.tgz} cpu: [arm64] os: [linux] '@rspack/binding-linux-arm64-musl@1.7.12': - resolution: {integrity: sha512-i51WWI64aRpsfSki6rN0aepPqXkVfS+vZM7+4bWDcmnhUmdMvhIPcYg0QRk3DtyJnu33jqNLM0WHY78k00NyfA==} + resolution: {integrity: sha512-i51WWI64aRpsfSki6rN0aepPqXkVfS+vZM7+4bWDcmnhUmdMvhIPcYg0QRk3DtyJnu33jqNLM0WHY78k00NyfA==, tarball: https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.7.12.tgz} cpu: [arm64] os: [linux] '@rspack/binding-linux-arm64-musl@2.1.4': - resolution: {integrity: sha512-SEYCQD9UflKJMkYGnG5nt2gcsqdkgJsQmryBC/jxo+bOuY9gUSReU99FqCt7WRQrsHLbGeAFeTWs1QzItWG/Bw==} + resolution: {integrity: sha512-SEYCQD9UflKJMkYGnG5nt2gcsqdkgJsQmryBC/jxo+bOuY9gUSReU99FqCt7WRQrsHLbGeAFeTWs1QzItWG/Bw==, tarball: https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-2.1.4.tgz} cpu: [arm64] os: [linux] '@rspack/binding-linux-riscv64-gnu@2.1.4': - resolution: {integrity: sha512-jYtQKtnDRaVfyasvTGY04Z7m+xDWZYVwAIEOB4hP7czM7FVLOMgHlMlvw/EgF0DNHrBthqbPfBIS2tP50CzpEA==} + resolution: {integrity: sha512-jYtQKtnDRaVfyasvTGY04Z7m+xDWZYVwAIEOB4hP7czM7FVLOMgHlMlvw/EgF0DNHrBthqbPfBIS2tP50CzpEA==, tarball: https://registry.npmjs.org/@rspack/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-2.1.4.tgz} cpu: [riscv64] os: [linux] '@rspack/binding-linux-riscv64-musl@2.1.4': - resolution: {integrity: sha512-ZgxKjQAm9pidq2kChQO2PqKI9OQpLuGD7iPBuyT0gQg3m1+7vvbbkArLBPzJ12CQHVZvqua7n/QGx8pQjJI2Zw==} + resolution: {integrity: sha512-ZgxKjQAm9pidq2kChQO2PqKI9OQpLuGD7iPBuyT0gQg3m1+7vvbbkArLBPzJ12CQHVZvqua7n/QGx8pQjJI2Zw==, tarball: https://registry.npmjs.org/@rspack/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-2.1.4.tgz} cpu: [riscv64] os: [linux] '@rspack/binding-linux-x64-gnu@1.7.12': - resolution: {integrity: sha512-MSos0FuPEefqo9V92ULd5hggKG29EkSNg1zDcypy0OkpsKh5pfjVxTLYFXgTcVyFoUQQbdG8zFBzYbwmJ8V4ew==} + resolution: {integrity: sha512-MSos0FuPEefqo9V92ULd5hggKG29EkSNg1zDcypy0OkpsKh5pfjVxTLYFXgTcVyFoUQQbdG8zFBzYbwmJ8V4ew==, tarball: https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.7.12.tgz} cpu: [x64] os: [linux] '@rspack/binding-linux-x64-gnu@2.1.4': - resolution: {integrity: sha512-C53B3e6M4yzlYn4hDxR9cHZV+HqkfFGR0zuhH8QCfdBfN5KyGsmXmujiFU85ANEvBgf9CF8VreBQeJ20lyto/g==} + resolution: {integrity: sha512-C53B3e6M4yzlYn4hDxR9cHZV+HqkfFGR0zuhH8QCfdBfN5KyGsmXmujiFU85ANEvBgf9CF8VreBQeJ20lyto/g==, tarball: https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-2.1.4.tgz} cpu: [x64] os: [linux] '@rspack/binding-linux-x64-musl@1.7.12': - resolution: {integrity: sha512-JcAMVKXOnjfpC3coWjCFPWD3Yl8RBw6a+IXQQ8mfRlHaHMIiOv8IfZqx15XRxMUn49CtP7Z0Na8iiAg2aKrcfw==} + resolution: {integrity: sha512-JcAMVKXOnjfpC3coWjCFPWD3Yl8RBw6a+IXQQ8mfRlHaHMIiOv8IfZqx15XRxMUn49CtP7Z0Na8iiAg2aKrcfw==, tarball: https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.7.12.tgz} cpu: [x64] os: [linux] '@rspack/binding-linux-x64-musl@2.1.4': - resolution: {integrity: sha512-UaeG3FRo7e5RameQvWRNQ6KeXF29LEk67U/ohb9tF4U38mKH1OGqhmwCf5yLkqiOSgOi7Ff3ireOZD83Fso1iw==} + resolution: {integrity: sha512-UaeG3FRo7e5RameQvWRNQ6KeXF29LEk67U/ohb9tF4U38mKH1OGqhmwCf5yLkqiOSgOi7Ff3ireOZD83Fso1iw==, tarball: https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-2.1.4.tgz} cpu: [x64] os: [linux] '@rspack/binding-wasm32-wasi@1.7.12': - resolution: {integrity: sha512-n+ZqP6ZMc0nhOgvadg5VhEs9ojtbES80AcWeFnmGkbzIszvGSO63GKNiRkXtjJ9KFuRzytbbmsCqkUVH+Tywxg==} + resolution: {integrity: sha512-n+ZqP6ZMc0nhOgvadg5VhEs9ojtbES80AcWeFnmGkbzIszvGSO63GKNiRkXtjJ9KFuRzytbbmsCqkUVH+Tywxg==, tarball: https://registry.npmjs.org/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-1.7.12.tgz} cpu: [wasm32] '@rspack/binding-wasm32-wasi@2.1.4': - resolution: {integrity: sha512-0P1WZEfu7JOPzD/jQfk9U/6gnRFc7RpvYCQaYZVVYZNJ2gU6O0/yLegRGKNK/2L0zjYwiD0ynhOIBVUUERf5Pw==} + resolution: {integrity: sha512-0P1WZEfu7JOPzD/jQfk9U/6gnRFc7RpvYCQaYZVVYZNJ2gU6O0/yLegRGKNK/2L0zjYwiD0ynhOIBVUUERf5Pw==, tarball: https://registry.npmjs.org/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-2.1.4.tgz} cpu: [wasm32] '@rspack/binding-win32-arm64-msvc@1.7.12': - resolution: {integrity: sha512-8+h5fYDXYdmugbdfZ+D1y8IQ3rv2EhSfyGP7vBe+bjNyaMa4jWrpucmZbtxojUL1AzaeuHbvMdj9UO/gelk/+g==} + resolution: {integrity: sha512-8+h5fYDXYdmugbdfZ+D1y8IQ3rv2EhSfyGP7vBe+bjNyaMa4jWrpucmZbtxojUL1AzaeuHbvMdj9UO/gelk/+g==, tarball: https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.7.12.tgz} cpu: [arm64] os: [win32] '@rspack/binding-win32-arm64-msvc@2.1.4': - resolution: {integrity: sha512-+aStQipk1EakLRPfD+/aQbtmTXfxqSWetcRRDWV3cAsD4ebv1tF8FLKYY1PCaFpQbX1FxzCBGF0KHxkAsi9cxA==} + resolution: {integrity: sha512-+aStQipk1EakLRPfD+/aQbtmTXfxqSWetcRRDWV3cAsD4ebv1tF8FLKYY1PCaFpQbX1FxzCBGF0KHxkAsi9cxA==, tarball: https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-2.1.4.tgz} cpu: [arm64] os: [win32] '@rspack/binding-win32-ia32-msvc@1.7.12': - resolution: {integrity: sha512-cDMGwTRSa2p9fNBVe1wTRkF2AEXZ9ARWW36QeC5CkLaI0Ezz8lvhF2+CSOPnhaQ1O1qtn0L0SF+lFnrY+I7xGQ==} + resolution: {integrity: sha512-cDMGwTRSa2p9fNBVe1wTRkF2AEXZ9ARWW36QeC5CkLaI0Ezz8lvhF2+CSOPnhaQ1O1qtn0L0SF+lFnrY+I7xGQ==, tarball: https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.7.12.tgz} cpu: [ia32] os: [win32] '@rspack/binding-win32-ia32-msvc@2.1.4': - resolution: {integrity: sha512-7nyrLRQ07j6i6omZuwiwwTI6rpjdy/Su3niLDAG7WsLL21u3/UQQrw6Fvm8SH3XYteghoHLSM3dhgaisuUhdJg==} + resolution: {integrity: sha512-7nyrLRQ07j6i6omZuwiwwTI6rpjdy/Su3niLDAG7WsLL21u3/UQQrw6Fvm8SH3XYteghoHLSM3dhgaisuUhdJg==, tarball: https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-2.1.4.tgz} cpu: [ia32] os: [win32] '@rspack/binding-win32-x64-msvc@1.7.12': - resolution: {integrity: sha512-wIqFvlgFqrgUyj/6S/FJcvShnkZOmIeXTfqvheLY67MGq8qd8jb1YimQVKAIrmWB3yuJKUFACI3Ag1UBtEedEA==} + resolution: {integrity: sha512-wIqFvlgFqrgUyj/6S/FJcvShnkZOmIeXTfqvheLY67MGq8qd8jb1YimQVKAIrmWB3yuJKUFACI3Ag1UBtEedEA==, tarball: https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.7.12.tgz} cpu: [x64] os: [win32] '@rspack/binding-win32-x64-msvc@2.1.4': - resolution: {integrity: sha512-Z4je7JBaDpO9vvNMgCxlycycRJq+GQwwuXSXagW2xvvGM10Ij63YVtIehSMG9xaW8PED41oc9nWndoEsiD60pA==} + resolution: {integrity: sha512-Z4je7JBaDpO9vvNMgCxlycycRJq+GQwwuXSXagW2xvvGM10Ij63YVtIehSMG9xaW8PED41oc9nWndoEsiD60pA==, tarball: https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-2.1.4.tgz} cpu: [x64] os: [win32] @@ -6058,7 +6065,7 @@ packages: '@stencil/core': '>=2.0.0 || >=3.0.0-beta.0 || >= 4.0.0-beta.0 || >= 4.0.0' '@storybook/global@5.0.0': - resolution: {integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==} + resolution: {integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==, tarball: https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz} '@stylistic/eslint-plugin@5.2.2': resolution: {integrity: sha512-bE2DUjruqXlHYP3Q2Gpqiuj2bHq7/88FnuaS0FjeGGLCy+X6a07bGVuwtiOYnPSLHR6jmx5Bwdv+j7l8H+G97A==} @@ -6161,61 +6168,61 @@ packages: resolution: {integrity: sha512-ovltDVH5QpdHXZkW138vG4+dgcNsxfwxHVoV6BtmTbz2KKl1A8ZSlbdtxzzfNjCjbpayda8Us9eMtcHobm38dA==} '@swc/core-darwin-arm64@1.15.8': - resolution: {integrity: sha512-M9cK5GwyWWRkRGwwCbREuj6r8jKdES/haCZ3Xckgkl8MUQJZA3XB7IXXK1IXRNeLjg6m7cnoMICpXv1v1hlJOg==} + resolution: {integrity: sha512-M9cK5GwyWWRkRGwwCbREuj6r8jKdES/haCZ3Xckgkl8MUQJZA3XB7IXXK1IXRNeLjg6m7cnoMICpXv1v1hlJOg==, tarball: https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.8.tgz} engines: {node: '>=10'} cpu: [arm64] os: [darwin] '@swc/core-darwin-x64@1.15.8': - resolution: {integrity: sha512-j47DasuOvXl80sKJHSi2X25l44CMc3VDhlJwA7oewC1nV1VsSzwX+KOwE5tLnfORvVJJyeiXgJORNYg4jeIjYQ==} + resolution: {integrity: sha512-j47DasuOvXl80sKJHSi2X25l44CMc3VDhlJwA7oewC1nV1VsSzwX+KOwE5tLnfORvVJJyeiXgJORNYg4jeIjYQ==, tarball: https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.8.tgz} engines: {node: '>=10'} cpu: [x64] os: [darwin] '@swc/core-linux-arm-gnueabihf@1.15.8': - resolution: {integrity: sha512-siAzDENu2rUbwr9+fayWa26r5A9fol1iORG53HWxQL1J8ym4k7xt9eME0dMPXlYZDytK5r9sW8zEA10F2U3Xwg==} + resolution: {integrity: sha512-siAzDENu2rUbwr9+fayWa26r5A9fol1iORG53HWxQL1J8ym4k7xt9eME0dMPXlYZDytK5r9sW8zEA10F2U3Xwg==, tarball: https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.8.tgz} engines: {node: '>=10'} cpu: [arm] os: [linux] '@swc/core-linux-arm64-gnu@1.15.8': - resolution: {integrity: sha512-o+1y5u6k2FfPYbTRUPvurwzNt5qd0NTumCTFscCNuBksycloXY16J8L+SMW5QRX59n4Hp9EmFa3vpvNHRVv1+Q==} + resolution: {integrity: sha512-o+1y5u6k2FfPYbTRUPvurwzNt5qd0NTumCTFscCNuBksycloXY16J8L+SMW5QRX59n4Hp9EmFa3vpvNHRVv1+Q==, tarball: https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.8.tgz} engines: {node: '>=10'} cpu: [arm64] os: [linux] '@swc/core-linux-arm64-musl@1.15.8': - resolution: {integrity: sha512-koiCqL09EwOP1S2RShCI7NbsQuG6r2brTqUYE7pV7kZm9O17wZ0LSz22m6gVibpwEnw8jI3IE1yYsQTVpluALw==} + resolution: {integrity: sha512-koiCqL09EwOP1S2RShCI7NbsQuG6r2brTqUYE7pV7kZm9O17wZ0LSz22m6gVibpwEnw8jI3IE1yYsQTVpluALw==, tarball: https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.8.tgz} engines: {node: '>=10'} cpu: [arm64] os: [linux] '@swc/core-linux-x64-gnu@1.15.8': - resolution: {integrity: sha512-4p6lOMU3bC+Vd5ARtKJ/FxpIC5G8v3XLoPEZ5s7mLR8h7411HWC/LmTXDHcrSXRC55zvAVia1eldy6zDLz8iFQ==} + resolution: {integrity: sha512-4p6lOMU3bC+Vd5ARtKJ/FxpIC5G8v3XLoPEZ5s7mLR8h7411HWC/LmTXDHcrSXRC55zvAVia1eldy6zDLz8iFQ==, tarball: https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.8.tgz} engines: {node: '>=10'} cpu: [x64] os: [linux] '@swc/core-linux-x64-musl@1.15.8': - resolution: {integrity: sha512-z3XBnbrZAL+6xDGAhJoN4lOueIxC/8rGrJ9tg+fEaeqLEuAtHSW2QHDHxDwkxZMjuF/pZ6MUTjHjbp8wLbuRLA==} + resolution: {integrity: sha512-z3XBnbrZAL+6xDGAhJoN4lOueIxC/8rGrJ9tg+fEaeqLEuAtHSW2QHDHxDwkxZMjuF/pZ6MUTjHjbp8wLbuRLA==, tarball: https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.8.tgz} engines: {node: '>=10'} cpu: [x64] os: [linux] '@swc/core-win32-arm64-msvc@1.15.8': - resolution: {integrity: sha512-djQPJ9Rh9vP8GTS/Df3hcc6XP6xnG5c8qsngWId/BLA9oX6C7UzCPAn74BG/wGb9a6j4w3RINuoaieJB3t+7iQ==} + resolution: {integrity: sha512-djQPJ9Rh9vP8GTS/Df3hcc6XP6xnG5c8qsngWId/BLA9oX6C7UzCPAn74BG/wGb9a6j4w3RINuoaieJB3t+7iQ==, tarball: https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.8.tgz} engines: {node: '>=10'} cpu: [arm64] os: [win32] '@swc/core-win32-ia32-msvc@1.15.8': - resolution: {integrity: sha512-/wfAgxORg2VBaUoFdytcVBVCgf1isWZIEXB9MZEUty4wwK93M/PxAkjifOho9RN3WrM3inPLabICRCEgdHpKKQ==} + resolution: {integrity: sha512-/wfAgxORg2VBaUoFdytcVBVCgf1isWZIEXB9MZEUty4wwK93M/PxAkjifOho9RN3WrM3inPLabICRCEgdHpKKQ==, tarball: https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.8.tgz} engines: {node: '>=10'} cpu: [ia32] os: [win32] '@swc/core-win32-x64-msvc@1.15.8': - resolution: {integrity: sha512-GpMePrh9Sl4d61o4KAHOOv5is5+zt6BEXCOCgs/H0FLGeii7j9bWDE8ExvKFy2GRRZVNR1ugsnzaGWHKM6kuzA==} + resolution: {integrity: sha512-GpMePrh9Sl4d61o4KAHOOv5is5+zt6BEXCOCgs/H0FLGeii7j9bWDE8ExvKFy2GRRZVNR1ugsnzaGWHKM6kuzA==, tarball: https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.8.tgz} engines: {node: '>=10'} cpu: [x64] os: [win32] @@ -6245,61 +6252,61 @@ packages: resolution: {integrity: sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==} '@tailwindcss/oxide-android-arm64@4.2.1': - resolution: {integrity: sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==} + resolution: {integrity: sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.1.tgz} engines: {node: '>= 20'} cpu: [arm64] os: [android] '@tailwindcss/oxide-darwin-arm64@4.2.1': - resolution: {integrity: sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==} + resolution: {integrity: sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.1.tgz} engines: {node: '>= 20'} cpu: [arm64] os: [darwin] '@tailwindcss/oxide-darwin-x64@4.2.1': - resolution: {integrity: sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==} + resolution: {integrity: sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.1.tgz} engines: {node: '>= 20'} cpu: [x64] os: [darwin] '@tailwindcss/oxide-freebsd-x64@4.2.1': - resolution: {integrity: sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==} + resolution: {integrity: sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.1.tgz} engines: {node: '>= 20'} cpu: [x64] os: [freebsd] '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1': - resolution: {integrity: sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==} + resolution: {integrity: sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.1.tgz} engines: {node: '>= 20'} cpu: [arm] os: [linux] '@tailwindcss/oxide-linux-arm64-gnu@4.2.1': - resolution: {integrity: sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==} + resolution: {integrity: sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.1.tgz} engines: {node: '>= 20'} cpu: [arm64] os: [linux] '@tailwindcss/oxide-linux-arm64-musl@4.2.1': - resolution: {integrity: sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==} + resolution: {integrity: sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.1.tgz} engines: {node: '>= 20'} cpu: [arm64] os: [linux] '@tailwindcss/oxide-linux-x64-gnu@4.2.1': - resolution: {integrity: sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==} + resolution: {integrity: sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.1.tgz} engines: {node: '>= 20'} cpu: [x64] os: [linux] '@tailwindcss/oxide-linux-x64-musl@4.2.1': - resolution: {integrity: sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==} + resolution: {integrity: sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.1.tgz} engines: {node: '>= 20'} cpu: [x64] os: [linux] '@tailwindcss/oxide-wasm32-wasi@4.2.1': - resolution: {integrity: sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==} + resolution: {integrity: sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.1.tgz} engines: {node: '>=14.0.0'} cpu: [wasm32] bundledDependencies: @@ -6311,13 +6318,13 @@ packages: - tslib '@tailwindcss/oxide-win32-arm64-msvc@4.2.1': - resolution: {integrity: sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==} + resolution: {integrity: sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.1.tgz} engines: {node: '>= 20'} cpu: [arm64] os: [win32] '@tailwindcss/oxide-win32-x64-msvc@4.2.1': - resolution: {integrity: sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==} + resolution: {integrity: sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==, tarball: https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.1.tgz} engines: {node: '>= 20'} cpu: [x64] os: [win32] @@ -6377,7 +6384,7 @@ packages: optional: true '@testing-library/user-event@14.6.1': - resolution: {integrity: sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==} + resolution: {integrity: sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==, tarball: https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz} engines: {node: '>=12', npm: '>=6'} peerDependencies: '@testing-library/dom': '>=7.21.4' @@ -6679,7 +6686,7 @@ packages: resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} '@tybys/wasm-util@0.10.3': - resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} + resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==, tarball: https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz} '@tybys/wasm-util@0.9.0': resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} @@ -6814,7 +6821,7 @@ packages: resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} '@types/dlv@1.1.5': - resolution: {integrity: sha512-JHOWNfiWepAhfwlSw17kiWrWrk6od2dEQgHltJw9AS0JPFoLZJBge5+Dnil2NfdjAvJ/+vGSX60/BRW20PpUXw==} + resolution: {integrity: sha512-JHOWNfiWepAhfwlSw17kiWrWrk6od2dEQgHltJw9AS0JPFoLZJBge5+Dnil2NfdjAvJ/+vGSX60/BRW20PpUXw==, tarball: https://registry.npmjs.org/@types/dlv/-/dlv-1.1.5.tgz} '@types/dragula@3.7.4': resolution: {integrity: sha512-cjg5MNq8CnXyJTScWM2t9fc0FC77rrBxYBs6/R3FiwW9NOTdHPB2nJq52I0tfxiBnhFb451S2j5ok4wW7sKmvA==} @@ -7098,112 +7105,112 @@ packages: resolution: {integrity: sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==} '@unrs/resolver-binding-android-arm-eabi@1.12.2': - resolution: {integrity: sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==} + resolution: {integrity: sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz} cpu: [arm] os: [android] '@unrs/resolver-binding-android-arm64@1.12.2': - resolution: {integrity: sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==} + resolution: {integrity: sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.12.2.tgz} cpu: [arm64] os: [android] '@unrs/resolver-binding-darwin-arm64@1.12.2': - resolution: {integrity: sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==} + resolution: {integrity: sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.12.2.tgz} cpu: [arm64] os: [darwin] '@unrs/resolver-binding-darwin-x64@1.12.2': - resolution: {integrity: sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==} + resolution: {integrity: sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.12.2.tgz} cpu: [x64] os: [darwin] '@unrs/resolver-binding-freebsd-x64@1.12.2': - resolution: {integrity: sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==} + resolution: {integrity: sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.12.2.tgz} cpu: [x64] os: [freebsd] '@unrs/resolver-binding-linux-arm-gnueabihf@1.12.2': - resolution: {integrity: sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==} + resolution: {integrity: sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.12.2.tgz} cpu: [arm] os: [linux] '@unrs/resolver-binding-linux-arm-musleabihf@1.12.2': - resolution: {integrity: sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==} + resolution: {integrity: sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.12.2.tgz} cpu: [arm] os: [linux] '@unrs/resolver-binding-linux-arm64-gnu@1.12.2': - resolution: {integrity: sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==} + resolution: {integrity: sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.12.2.tgz} cpu: [arm64] os: [linux] '@unrs/resolver-binding-linux-arm64-musl@1.12.2': - resolution: {integrity: sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==} + resolution: {integrity: sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.12.2.tgz} cpu: [arm64] os: [linux] '@unrs/resolver-binding-linux-loong64-gnu@1.12.2': - resolution: {integrity: sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==} + resolution: {integrity: sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.12.2.tgz} cpu: [loong64] os: [linux] '@unrs/resolver-binding-linux-loong64-musl@1.12.2': - resolution: {integrity: sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==} + resolution: {integrity: sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.12.2.tgz} cpu: [loong64] os: [linux] '@unrs/resolver-binding-linux-ppc64-gnu@1.12.2': - resolution: {integrity: sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==} + resolution: {integrity: sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.12.2.tgz} cpu: [ppc64] os: [linux] '@unrs/resolver-binding-linux-riscv64-gnu@1.12.2': - resolution: {integrity: sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==} + resolution: {integrity: sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.12.2.tgz} cpu: [riscv64] os: [linux] '@unrs/resolver-binding-linux-riscv64-musl@1.12.2': - resolution: {integrity: sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==} + resolution: {integrity: sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.12.2.tgz} cpu: [riscv64] os: [linux] '@unrs/resolver-binding-linux-s390x-gnu@1.12.2': - resolution: {integrity: sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==} + resolution: {integrity: sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.12.2.tgz} cpu: [s390x] os: [linux] '@unrs/resolver-binding-linux-x64-gnu@1.12.2': - resolution: {integrity: sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==} + resolution: {integrity: sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz} cpu: [x64] os: [linux] '@unrs/resolver-binding-linux-x64-musl@1.12.2': - resolution: {integrity: sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==} + resolution: {integrity: sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.12.2.tgz} cpu: [x64] os: [linux] '@unrs/resolver-binding-openharmony-arm64@1.12.2': - resolution: {integrity: sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==} + resolution: {integrity: sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.12.2.tgz} cpu: [arm64] os: [openharmony] '@unrs/resolver-binding-wasm32-wasi@1.12.2': - resolution: {integrity: sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==} + resolution: {integrity: sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.12.2.tgz} engines: {node: '>=14.0.0'} cpu: [wasm32] '@unrs/resolver-binding-win32-arm64-msvc@1.12.2': - resolution: {integrity: sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==} + resolution: {integrity: sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz} cpu: [arm64] os: [win32] '@unrs/resolver-binding-win32-ia32-msvc@1.12.2': - resolution: {integrity: sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==} + resolution: {integrity: sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.12.2.tgz} cpu: [ia32] os: [win32] '@unrs/resolver-binding-win32-x64-msvc@1.12.2': - resolution: {integrity: sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==} + resolution: {integrity: sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==, tarball: https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.12.2.tgz} cpu: [x64] os: [win32] @@ -7248,13 +7255,13 @@ packages: optional: true '@vitest/expect@3.2.4': - resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} + resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==, tarball: https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz} '@vitest/expect@4.0.18': resolution: {integrity: sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==} '@vitest/mocker@3.2.4': - resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} + resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==, tarball: https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz} peerDependencies: msw: ^2.4.9 vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 @@ -7276,7 +7283,7 @@ packages: optional: true '@vitest/pretty-format@3.2.4': - resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} + resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==, tarball: https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz} '@vitest/pretty-format@4.0.18': resolution: {integrity: sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==} @@ -7291,7 +7298,7 @@ packages: resolution: {integrity: sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==} '@vitest/spy@3.2.4': - resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} + resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==, tarball: https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz} '@vitest/spy@4.0.18': resolution: {integrity: sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==} @@ -7302,7 +7309,7 @@ packages: vitest: 4.0.18 '@vitest/utils@3.2.4': - resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} + resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==, tarball: https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz} '@vitest/utils@4.0.18': resolution: {integrity: sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==} @@ -7784,7 +7791,7 @@ packages: resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} ast-types@0.16.1: - resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} + resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==, tarball: https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz} engines: {node: '>=4'} ast-v8-to-istanbul@1.0.5: @@ -7982,7 +7989,7 @@ packages: engines: {node: '>=18.0.0'} better-opn@3.0.2: - resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==} + resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==, tarball: https://registry.npmjs.org/better-opn/-/better-opn-3.0.2.tgz} engines: {node: '>=12.0.0'} bidi-js@1.0.3: @@ -8118,7 +8125,7 @@ packages: hasBin: true chai@5.3.3: - resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==, tarball: https://registry.npmjs.org/chai/-/chai-5.3.3.tgz} engines: {node: '>=18'} chai@6.2.2: @@ -8156,7 +8163,7 @@ packages: engines: {pnpm: '>=8'} check-error@2.1.3: - resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} + resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==, tarball: https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz} engines: {node: '>= 16'} chokidar@3.6.0: @@ -8180,7 +8187,7 @@ packages: engines: {node: '>=8'} ci-info@4.4.0: - resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} + resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==, tarball: https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz} engines: {node: '>=8'} cjs-module-lexer@2.2.0: @@ -8222,7 +8229,7 @@ packages: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} clipboard@2.0.11: - resolution: {integrity: sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==} + resolution: {integrity: sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==, tarball: https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz} cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} @@ -8934,7 +8941,7 @@ packages: optional: true deep-eql@5.0.2: - resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==, tarball: https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz} engines: {node: '>=6'} deep-equal@1.0.1: @@ -9192,7 +9199,7 @@ packages: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} emoji-toolkit@9.0.1: - resolution: {integrity: sha512-sMMNqKNLVHXJfIKoPbrRJwtYuysVNC9GlKetr72zE3SSVbHqoeDLWVrxP0uM0AE0qvdl3hbUk+tJhhwXZrDHaw==} + resolution: {integrity: sha512-sMMNqKNLVHXJfIKoPbrRJwtYuysVNC9GlKetr72zE3SSVbHqoeDLWVrxP0uM0AE0qvdl3hbUk+tJhhwXZrDHaw==, tarball: https://registry.npmjs.org/emoji-toolkit/-/emoji-toolkit-9.0.1.tgz} emojibase-data@17.0.0: resolution: {integrity: sha512-Yvgb5AWoHViHV/gq1qr5ZAarcBip+B27/ZLRsUJkbgAEaLlZ/fof9g882LTpmEpyhBNEC0m2SEmItljHsTygjA==} @@ -9200,7 +9207,7 @@ packages: emojibase: '*' emojibase@17.0.0: - resolution: {integrity: sha512-bXdpf4HPY3p41zK5swVKZdC/VynsMZ4LoLxdYDE+GucqkFwzcM1GVc4ODfYAlwoKaf2U2oNNUoOO78N96ovpBA==} + resolution: {integrity: sha512-bXdpf4HPY3p41zK5swVKZdC/VynsMZ4LoLxdYDE+GucqkFwzcM1GVc4ODfYAlwoKaf2U2oNNUoOO78N96ovpBA==, tarball: https://registry.npmjs.org/emojibase/-/emojibase-17.0.0.tgz} engines: {node: '>=18.12.0'} emojis-list@3.0.0: @@ -9265,7 +9272,7 @@ packages: engines: {node: '>=18'} errno@0.1.8: - resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} + resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==, tarball: https://registry.npmjs.org/errno/-/errno-0.1.8.tgz} hasBin: true error-ex@1.3.4: @@ -9327,7 +9334,7 @@ packages: resolution: {integrity: sha512-G5iZ6Pc/FNRY/soKZHC+TxGDD83rHUDXxzaWhGCX44vAv/tMs56WMusnm/KMNK+luUPsgA9U28cGr4RDlSzL2g==} esbuild-register@3.6.0: - resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} + resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==, tarball: https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.6.0.tgz} peerDependencies: esbuild: '>=0.12 <1' @@ -9357,7 +9364,7 @@ packages: hasBin: true esbuild@0.28.1: - resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} + resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==, tarball: https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz} engines: {node: '>=18'} hasBin: true @@ -9885,12 +9892,12 @@ packages: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==, tarball: https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==, tarball: https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] @@ -10267,7 +10274,7 @@ packages: engines: {node: '>= 4'} image-size@0.5.5: - resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} + resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==, tarball: https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz} engines: {node: '>=0.10.0'} hasBin: true @@ -10891,15 +10898,19 @@ packages: engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-util@29.7.0: - resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} + resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==, tarball: https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} jest-util@30.2.0: - resolution: {integrity: sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==} + resolution: {integrity: sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==, tarball: https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-util@30.3.0: + resolution: {integrity: sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==, tarball: https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-util@30.4.1: - resolution: {integrity: sha512-vjQb1sACEiv13DKJMDToJpzVW0joCsIQrmbg0fi7CyOOt+g9jTuQl2A216pWRBYhOVt53XbL/2LbMKg1BECWOw==} + resolution: {integrity: sha512-vjQb1sACEiv13DKJMDToJpzVW0joCsIQrmbg0fi7CyOOt+g9jTuQl2A216pWRBYhOVt53XbL/2LbMKg1BECWOw==, tarball: https://registry.npmjs.org/jest-util/-/jest-util-30.4.1.tgz} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} jest-validate@30.2.0: @@ -11066,7 +11077,7 @@ packages: resolution: {integrity: sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==} katex@0.16.47: - resolution: {integrity: sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==} + resolution: {integrity: sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==, tarball: https://registry.npmjs.org/katex/-/katex-0.16.47.tgz} hasBin: true keygrip@1.1.0: @@ -11190,133 +11201,133 @@ packages: hasBin: true lightningcss-android-arm64@1.31.1: - resolution: {integrity: sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==} + resolution: {integrity: sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==, tarball: https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [android] lightningcss-android-arm64@1.33.0: - resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} + resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==, tarball: https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [android] lightningcss-darwin-arm64@1.31.1: - resolution: {integrity: sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==} + resolution: {integrity: sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==, tarball: https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] lightningcss-darwin-arm64@1.33.0: - resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} + resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==, tarball: https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] lightningcss-darwin-x64@1.31.1: - resolution: {integrity: sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==} + resolution: {integrity: sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==, tarball: https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] lightningcss-darwin-x64@1.33.0: - resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} + resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==, tarball: https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] lightningcss-freebsd-x64@1.31.1: - resolution: {integrity: sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==} + resolution: {integrity: sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==, tarball: https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] lightningcss-freebsd-x64@1.33.0: - resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} + resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==, tarball: https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] lightningcss-linux-arm-gnueabihf@1.31.1: - resolution: {integrity: sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==} + resolution: {integrity: sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==, tarball: https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] lightningcss-linux-arm-gnueabihf@1.33.0: - resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} + resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==, tarball: https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] lightningcss-linux-arm64-gnu@1.31.1: - resolution: {integrity: sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==} + resolution: {integrity: sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==, tarball: https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] lightningcss-linux-arm64-gnu@1.33.0: - resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} + resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==, tarball: https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] lightningcss-linux-arm64-musl@1.31.1: - resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==} + resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==, tarball: https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] lightningcss-linux-arm64-musl@1.33.0: - resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} + resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==, tarball: https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] lightningcss-linux-x64-gnu@1.31.1: - resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==} + resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==, tarball: https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] lightningcss-linux-x64-gnu@1.33.0: - resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} + resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==, tarball: https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] lightningcss-linux-x64-musl@1.31.1: - resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==} + resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==, tarball: https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] lightningcss-linux-x64-musl@1.33.0: - resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} + resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==, tarball: https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] lightningcss-win32-arm64-msvc@1.31.1: - resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==} + resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==, tarball: https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] lightningcss-win32-arm64-msvc@1.33.0: - resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} + resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==, tarball: https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] lightningcss-win32-x64-msvc@1.31.1: - resolution: {integrity: sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==} + resolution: {integrity: sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==, tarball: https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] lightningcss-win32-x64-msvc@1.33.0: - resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} + resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==, tarball: https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] @@ -11373,7 +11384,7 @@ packages: resolution: {integrity: sha512-4Sc3OFX9QHOJaHbmTMk28SYgVxLN3ePDjg7hofEft2zWlehFL3LiAuapWc4U/kYwMYJSh2hTCPZ6/LIC7ii0MA==} lmdb@3.5.6: - resolution: {integrity: sha512-j3uE8ReKNyUWDjhfEFSJqE/1DLtfTR5Z8yFzVHvBjAk37wNg7HdScjcv8ttPHRvrdgPQMPWxFFI0SsdBzI5lBw==} + resolution: {integrity: sha512-j3uE8ReKNyUWDjhfEFSJqE/1DLtfTR5Z8yFzVHvBjAk37wNg7HdScjcv8ttPHRvrdgPQMPWxFFI0SsdBzI5lBw==, tarball: https://registry.npmjs.org/lmdb/-/lmdb-3.5.6.tgz} hasBin: true loader-runner@4.3.2: @@ -11459,7 +11470,7 @@ packages: hasBin: true loupe@3.2.1: - resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} + resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==, tarball: https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz} lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} @@ -11498,7 +11509,7 @@ packages: resolution: {integrity: sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==} make-dir@2.1.0: - resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} + resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==, tarball: https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz} engines: {node: '>=6'} make-dir@3.1.0: @@ -11510,7 +11521,7 @@ packages: engines: {node: '>=10'} make-dir@5.1.0: - resolution: {integrity: sha512-IfpFq6UM39dUNiphpA6uDezNx/AvWyhwfICWPR3t1VspkgkMZrL+Rk1RbN1bx+aeNYwOrqGJgEgV3yotk+ZUVw==} + resolution: {integrity: sha512-IfpFq6UM39dUNiphpA6uDezNx/AvWyhwfICWPR3t1VspkgkMZrL+Rk1RbN1bx+aeNYwOrqGJgEgV3yotk+ZUVw==, tarball: https://registry.npmjs.org/make-dir/-/make-dir-5.1.0.tgz} engines: {node: '>=18'} make-error@1.3.6: @@ -11595,7 +11606,7 @@ packages: engines: {node: '>= 8'} mermaid@11.16.0: - resolution: {integrity: sha512-Zvm3kbstgdpvIJPPItlL7fppIZ3kibvc1oZIGxdvk9t6UFz6flv+Jw7FtRGKwfcI8OckmH04LqG6LlS6X4B1pA==} + resolution: {integrity: sha512-Zvm3kbstgdpvIJPPItlL7fppIZ3kibvc1oZIGxdvk9t6UFz6flv+Jw7FtRGKwfcI8OckmH04LqG6LlS6X4B1pA==, tarball: https://registry.npmjs.org/mermaid/-/mermaid-11.16.0.tgz} methods@1.1.2: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} @@ -11767,7 +11778,7 @@ packages: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} msgpackr-extract@3.0.4: - resolution: {integrity: sha512-4kmO/MdyUIkLIvTPr8VHLil4AtoKIoniWPIEk5+CDy0xnWC84azhSFmuJ7PxZdsYtiP5kEeQsORAVIeMgxT+Hw==} + resolution: {integrity: sha512-4kmO/MdyUIkLIvTPr8VHLil4AtoKIoniWPIEk5+CDy0xnWC84azhSFmuJ7PxZdsYtiP5kEeQsORAVIeMgxT+Hw==, tarball: https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.4.tgz} hasBin: true msgpackr@1.12.1: @@ -11798,7 +11809,7 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} needle@3.5.0: - resolution: {integrity: sha512-jaQyPKKk2YokHrEg+vFDYxXIHTCBgiZwSHOoVx/8V3GIBS8/VN6NdVRmg8q1ERtPkMvmOvebsgga4sAj5hls/w==} + resolution: {integrity: sha512-jaQyPKKk2YokHrEg+vFDYxXIHTCBgiZwSHOoVx/8V3GIBS8/VN6NdVRmg8q1ERtPkMvmOvebsgga4sAj5hls/w==, tarball: https://registry.npmjs.org/needle/-/needle-3.5.0.tgz} engines: {node: '>= 4.4.x'} hasBin: true @@ -12079,7 +12090,7 @@ packages: engines: {node: '>=12'} openapi-types@12.1.3: - resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==} + resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==, tarball: https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz} opener@1.5.2: resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==} @@ -12269,7 +12280,7 @@ packages: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} pathval@2.0.1: - resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} + resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==, tarball: https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz} engines: {node: '>= 14.16'} picocolors@1.1.1: @@ -13253,7 +13264,7 @@ packages: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} react-is@19.2.7: - resolution: {integrity: sha512-kZFnouyVv7eP/Phmrlo9FK+zcAdriZJvzxXHF1Sl1P377WSGe2G/JxVolhTrB/jeV47lKImhNUsijjHAAbcl/A==} + resolution: {integrity: sha512-kZFnouyVv7eP/Phmrlo9FK+zcAdriZJvzxXHF1Sl1P377WSGe2G/JxVolhTrB/jeV47lKImhNUsijjHAAbcl/A==, tarball: https://registry.npmjs.org/react-is/-/react-is-19.2.7.tgz} react-refresh@0.18.0: resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} @@ -13296,7 +13307,7 @@ packages: engines: {node: '>= 20.19.0'} recast@0.23.12: - resolution: {integrity: sha512-dEWRjcINDu/F4l2dYx57ugBtD7HV9KXESyxhzw/MqWLeglJrsjJKqACPyUPg+6AF8mIgm+Zi0dZ3ACoIg+QtpA==} + resolution: {integrity: sha512-dEWRjcINDu/F4l2dYx57ugBtD7HV9KXESyxhzw/MqWLeglJrsjJKqACPyUPg+6AF8mIgm+Zi0dZ3ACoIg+QtpA==, tarball: https://registry.npmjs.org/recast/-/recast-0.23.12.tgz} engines: {node: '>= 4'} redent@3.0.0: @@ -13459,7 +13470,7 @@ packages: hasBin: true rollup@4.62.2: - resolution: {integrity: sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==} + resolution: {integrity: sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==, tarball: https://registry.npmjs.org/rollup/-/rollup-4.62.2.tgz} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -13522,105 +13533,105 @@ packages: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} sass-embedded-all-unknown@1.100.0: - resolution: {integrity: sha512-auFtXY/kwYILmSVjtBDwyj0axcLbYYiffOKWoaXHnI5bsYwiRbBh3EneR1rpbX2ZIZCrwX93i5pxKLTZF/662Q==} + resolution: {integrity: sha512-auFtXY/kwYILmSVjtBDwyj0axcLbYYiffOKWoaXHnI5bsYwiRbBh3EneR1rpbX2ZIZCrwX93i5pxKLTZF/662Q==, tarball: https://registry.npmjs.org/sass-embedded-all-unknown/-/sass-embedded-all-unknown-1.100.0.tgz} cpu: ['!arm', '!arm64', '!riscv64', '!x64'] sass-embedded-android-arm64@1.100.0: - resolution: {integrity: sha512-W+Ru9JwTnfU0UX3jSZcbqFdtKFMcYdfFwytc57h2DgnqCOIiAqI2E06mABZBZC+r3LwXCBuS5GbXAGeVgvVDkA==} + resolution: {integrity: sha512-W+Ru9JwTnfU0UX3jSZcbqFdtKFMcYdfFwytc57h2DgnqCOIiAqI2E06mABZBZC+r3LwXCBuS5GbXAGeVgvVDkA==, tarball: https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.100.0.tgz} engines: {node: '>=14.0.0'} cpu: [arm64] os: [android] sass-embedded-android-arm@1.100.0: - resolution: {integrity: sha512-70f3HgX2pFNmzpGQ86n5e6QfWn2fP4QUQGfFQK0P1XH73ZLIzLo2YqygrGKGKeeqtc5eU2Wl1/xQzhzuKnO4kw==} + resolution: {integrity: sha512-70f3HgX2pFNmzpGQ86n5e6QfWn2fP4QUQGfFQK0P1XH73ZLIzLo2YqygrGKGKeeqtc5eU2Wl1/xQzhzuKnO4kw==, tarball: https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.100.0.tgz} engines: {node: '>=14.0.0'} cpu: [arm] os: [android] sass-embedded-android-riscv64@1.100.0: - resolution: {integrity: sha512-icU3o0V/uCSytSpf+tX5Lf51BvyQEbLzDUJfUi9etSauYBGHpPKkdtdZH0si4v98phq11Kl8rSV1SggksxF1Hg==} + resolution: {integrity: sha512-icU3o0V/uCSytSpf+tX5Lf51BvyQEbLzDUJfUi9etSauYBGHpPKkdtdZH0si4v98phq11Kl8rSV1SggksxF1Hg==, tarball: https://registry.npmjs.org/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.100.0.tgz} engines: {node: '>=14.0.0'} cpu: [riscv64] os: [android] sass-embedded-android-x64@1.100.0: - resolution: {integrity: sha512-mevF9VQk6gEYByy8+jusaHGmd7Usb2ytX/DsEOd0JtOGCtcf1kh575xJ6OUBDIcJ15uLnbau/0iy1eP6WVBvWA==} + resolution: {integrity: sha512-mevF9VQk6gEYByy8+jusaHGmd7Usb2ytX/DsEOd0JtOGCtcf1kh575xJ6OUBDIcJ15uLnbau/0iy1eP6WVBvWA==, tarball: https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.100.0.tgz} engines: {node: '>=14.0.0'} cpu: [x64] os: [android] sass-embedded-darwin-arm64@1.100.0: - resolution: {integrity: sha512-1PVlYi61POo93IT/FfrG1mc1tAHxeSTyUALF2aOFmXGWjVXr3bQzEQiBGCOvQbj/ix+5hNyXFXcEMEyKvtUJJA==} + resolution: {integrity: sha512-1PVlYi61POo93IT/FfrG1mc1tAHxeSTyUALF2aOFmXGWjVXr3bQzEQiBGCOvQbj/ix+5hNyXFXcEMEyKvtUJJA==, tarball: https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.100.0.tgz} engines: {node: '>=14.0.0'} cpu: [arm64] os: [darwin] sass-embedded-darwin-x64@1.100.0: - resolution: {integrity: sha512-x97o3JnGyImZNCIVs9wQHJUE5QCvmVIKaH1cwrz/5dK7OT1FpeNiW+u9TUomP9hG6Ekjd8EL8NBHpxTfIhdjmg==} + resolution: {integrity: sha512-x97o3JnGyImZNCIVs9wQHJUE5QCvmVIKaH1cwrz/5dK7OT1FpeNiW+u9TUomP9hG6Ekjd8EL8NBHpxTfIhdjmg==, tarball: https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.100.0.tgz} engines: {node: '>=14.0.0'} cpu: [x64] os: [darwin] sass-embedded-linux-arm64@1.100.0: - resolution: {integrity: sha512-Dwjmj8Z6VRy7rAi53JAdEwIyUjpfl7PhpSc2/LpQPQx+aO5Dp7Spaipkax0ufJl1SoDUdchCsM4y/88YaluorQ==} + resolution: {integrity: sha512-Dwjmj8Z6VRy7rAi53JAdEwIyUjpfl7PhpSc2/LpQPQx+aO5Dp7Spaipkax0ufJl1SoDUdchCsM4y/88YaluorQ==, tarball: https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.100.0.tgz} engines: {node: '>=14.0.0'} cpu: [arm64] os: [linux] sass-embedded-linux-arm@1.100.0: - resolution: {integrity: sha512-9Ul7O1eKrc5YlhwWjkp8tZPSe3UEwSZ1uwUZOQom1HL0pRlBA6F/IlGZYFTLwnHMIP1fc77MMNaBRfc05mKMpw==} + resolution: {integrity: sha512-9Ul7O1eKrc5YlhwWjkp8tZPSe3UEwSZ1uwUZOQom1HL0pRlBA6F/IlGZYFTLwnHMIP1fc77MMNaBRfc05mKMpw==, tarball: https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.100.0.tgz} engines: {node: '>=14.0.0'} cpu: [arm] os: [linux] sass-embedded-linux-musl-arm64@1.100.0: - resolution: {integrity: sha512-XpACJB2KjSLjf2e9uuvGVdOURsoNrFqgRiihhXyUHK9W0t3LIHb7z5MA/7XGPIT9bWSOO2zyw+rH/FHtDV/Yrg==} + resolution: {integrity: sha512-XpACJB2KjSLjf2e9uuvGVdOURsoNrFqgRiihhXyUHK9W0t3LIHb7z5MA/7XGPIT9bWSOO2zyw+rH/FHtDV/Yrg==, tarball: https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.100.0.tgz} engines: {node: '>=14.0.0'} cpu: [arm64] os: [linux] sass-embedded-linux-musl-arm@1.100.0: - resolution: {integrity: sha512-sl0JgbGloPyJg66XXx5UDSDScZ0oU85DpMQU4JU/sCUCFj1Z8zZ69SJWKTCNE4/jwnce7WI2zPCV5AG+RHOZJw==} + resolution: {integrity: sha512-sl0JgbGloPyJg66XXx5UDSDScZ0oU85DpMQU4JU/sCUCFj1Z8zZ69SJWKTCNE4/jwnce7WI2zPCV5AG+RHOZJw==, tarball: https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.100.0.tgz} engines: {node: '>=14.0.0'} cpu: [arm] os: [linux] sass-embedded-linux-musl-riscv64@1.100.0: - resolution: {integrity: sha512-ShvI0Kx04mwoCARwZ0UjiT97isQvzO80tAt91zmFyHLN9kelc/IrQi940farSm2xQVPCKdeVyeG0ekBsokSpYQ==} + resolution: {integrity: sha512-ShvI0Kx04mwoCARwZ0UjiT97isQvzO80tAt91zmFyHLN9kelc/IrQi940farSm2xQVPCKdeVyeG0ekBsokSpYQ==, tarball: https://registry.npmjs.org/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.100.0.tgz} engines: {node: '>=14.0.0'} cpu: [riscv64] os: [linux] sass-embedded-linux-musl-x64@1.100.0: - resolution: {integrity: sha512-TDBCRWNuS4RDLQXvRc1gjZlWiWTWaWGp0Bwu/IKwJxov81lsvrCs3TihTyNXtW7V5aoN4Ky3r0QOkNb3mwmBnA==} + resolution: {integrity: sha512-TDBCRWNuS4RDLQXvRc1gjZlWiWTWaWGp0Bwu/IKwJxov81lsvrCs3TihTyNXtW7V5aoN4Ky3r0QOkNb3mwmBnA==, tarball: https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.100.0.tgz} engines: {node: '>=14.0.0'} cpu: [x64] os: [linux] sass-embedded-linux-riscv64@1.100.0: - resolution: {integrity: sha512-j4ENJGOheO+fm3j/yorLxCjBP6/XskrZx7dTLlT+lXYwN/qqCqoA/gsNLI0McS3DFM6GBwPiffzWsdWS8t6sEQ==} + resolution: {integrity: sha512-j4ENJGOheO+fm3j/yorLxCjBP6/XskrZx7dTLlT+lXYwN/qqCqoA/gsNLI0McS3DFM6GBwPiffzWsdWS8t6sEQ==, tarball: https://registry.npmjs.org/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.100.0.tgz} engines: {node: '>=14.0.0'} cpu: [riscv64] os: [linux] sass-embedded-linux-x64@1.100.0: - resolution: {integrity: sha512-0vUSN8j0WGtCJIOPh//EmUvYGHW0QOe5iul8qyhPk50MAcw49MA0r34AhftjDdx94ILPF6vApFs0gwHPQRlpVA==} + resolution: {integrity: sha512-0vUSN8j0WGtCJIOPh//EmUvYGHW0QOe5iul8qyhPk50MAcw49MA0r34AhftjDdx94ILPF6vApFs0gwHPQRlpVA==, tarball: https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.100.0.tgz} engines: {node: '>=14.0.0'} cpu: [x64] os: [linux] sass-embedded-unknown-all@1.100.0: - resolution: {integrity: sha512-c+naBgWId4MIpToXcI0DgqetjdAkwTTAxFAuOaBz7HUXLdyG1oZRrEvSsbe41nEdQOKH0vgofVFCeSQgoXOG9A==} + resolution: {integrity: sha512-c+naBgWId4MIpToXcI0DgqetjdAkwTTAxFAuOaBz7HUXLdyG1oZRrEvSsbe41nEdQOKH0vgofVFCeSQgoXOG9A==, tarball: https://registry.npmjs.org/sass-embedded-unknown-all/-/sass-embedded-unknown-all-1.100.0.tgz} os: ['!android', '!darwin', '!linux', '!win32'] sass-embedded-win32-arm64@1.100.0: - resolution: {integrity: sha512-iE+yxj+hUXwwbqpHkXxgAWTzeRfcWxJ7SSTQEPMk48lwq3oCrWLlz5sQuWHbuTK/i0GKQfROdP+hOmPi89yjUg==} + resolution: {integrity: sha512-iE+yxj+hUXwwbqpHkXxgAWTzeRfcWxJ7SSTQEPMk48lwq3oCrWLlz5sQuWHbuTK/i0GKQfROdP+hOmPi89yjUg==, tarball: https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.100.0.tgz} engines: {node: '>=14.0.0'} cpu: [arm64] os: [win32] sass-embedded-win32-x64@1.100.0: - resolution: {integrity: sha512-qI4F8MI7/KYoy9NdjJfhSspG42WPkADSNDvwEV7qWvCSFC83koJssRsKO2/PfY+niZz6BG65Ic/D+A11h959hw==} + resolution: {integrity: sha512-qI4F8MI7/KYoy9NdjJfhSspG42WPkADSNDvwEV7qWvCSFC83koJssRsKO2/PfY+niZz6BG65Ic/D+A11h959hw==, tarball: https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.100.0.tgz} engines: {node: '>=14.0.0'} cpu: [x64] os: [win32] @@ -13670,7 +13681,7 @@ packages: optional: true sass@1.100.0: - resolution: {integrity: sha512-B5j0rYMlinhhOo9tjQebMVVn0TfyXAF+wB3b2ggZUuJ/is/Y+7+JGjirAMxHZ9Z3hIP98NPfamlAkBHa1lAaXQ==} + resolution: {integrity: sha512-B5j0rYMlinhhOo9tjQebMVVn0TfyXAF+wB3b2ggZUuJ/is/Y+7+JGjirAMxHZ9Z3hIP98NPfamlAkBHa1lAaXQ==, tarball: https://registry.npmjs.org/sass/-/sass-1.100.0.tgz} engines: {node: '>=20.19.0'} hasBin: true @@ -13961,7 +13972,7 @@ packages: engines: {node: '>= 0.4'} storybook@9.1.20: - resolution: {integrity: sha512-6rME2tww6PFhm96iG2Xx44yzwLDWBiDWy+kJ2ub6x90werSTOiuo+tZJ94BgCfFutR0tEfLRIq59s+Zg6YyChA==} + resolution: {integrity: sha512-6rME2tww6PFhm96iG2Xx44yzwLDWBiDWy+kJ2ub6x90werSTOiuo+tZJ94BgCfFutR0tEfLRIq59s+Zg6YyChA==, tarball: https://registry.npmjs.org/storybook/-/storybook-9.1.20.tgz} hasBin: true peerDependencies: prettier: ^2 || ^3 @@ -14273,7 +14284,7 @@ packages: resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==} tiny-invariant@1.3.3: - resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==, tarball: https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz} tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -14290,7 +14301,7 @@ packages: resolution: {integrity: sha512-3fCHKAeqT+xNwBVESf6iDbDV0VNwZNmfrkx9c/6Gz5iB8piMfaO6s7FvoiTrj1hf1gVbfyLTnz1DooI6DhgINQ==} tinyrainbow@2.0.0: - resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==, tarball: https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz} engines: {node: '>=14.0.0'} tinyrainbow@3.1.0: @@ -14298,7 +14309,7 @@ packages: engines: {node: '>=14.0.0'} tinyspy@4.0.4: - resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} + resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==, tarball: https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz} engines: {node: '>=14.0.0'} tippy.js@6.3.7: @@ -14602,7 +14613,7 @@ packages: resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} uglify-js@3.19.3: - resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==, tarball: https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz} engines: {node: '>=0.8.0'} hasBin: true @@ -17885,14 +17896,14 @@ snapshots: '@floating-ui/utils@0.2.12': {} - '@happy-dom/jest-environment@20.8.3(@jest/environment@30.4.1)(@jest/fake-timers@30.4.1)(@jest/types@30.4.1)(jest-mock@30.4.1)(jest-util@30.4.1)': + '@happy-dom/jest-environment@20.8.3(@jest/environment@30.4.1)(@jest/fake-timers@30.4.1)(@jest/types@30.4.1)(jest-mock@30.4.1)(jest-util@30.3.0)': dependencies: '@jest/environment': 30.4.1 '@jest/fake-timers': 30.4.1 '@jest/types': 30.4.1 happy-dom: 20.10.6 jest-mock: 30.4.1 - jest-util: 30.4.1 + jest-util: 30.3.0 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -18411,6 +18422,16 @@ snapshots: '@types/yargs': 17.0.35 chalk: 4.1.2 + '@jest/types@30.3.0': + dependencies: + '@jest/pattern': 30.0.1 + '@jest/schemas': 30.0.5 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 20.19.9 + '@types/yargs': 17.0.35 + chalk: 4.1.2 + '@jest/types@30.4.1': dependencies: '@jest/pattern': 30.4.0 @@ -19881,16 +19902,16 @@ snapshots: - webpack-cli - webpack-hot-middleware - '@nx/angular@23.1.1(0c2651284a7a75bfb153c6888b067c15)': + '@nx/angular@23.1.1(072c770ba89bf4308c6f3053aba8fcd1)': dependencies: '@angular-devkit/core': 22.1.2(chokidar@5.0.0) '@angular-devkit/schematics': 22.1.2(chokidar@5.0.0) '@nx/devkit': 23.1.1(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) - '@nx/eslint': 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) + '@nx/eslint': 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) '@nx/js': 23.1.1(@babel/traverse@7.29.7)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) - '@nx/module-federation': 23.1.1(de2c3d761620e871eecd33c4b77b05e5) - '@nx/rspack': 23.1.1(a3529f5f9f9a7208a5531ab889f55194) - '@nx/web': 23.1.1(269dd13e357dbfb54dda39a5dcf682ec) + '@nx/module-federation': 23.1.1(ed575dd90a698e7a2ada4e01d6d83333) + '@nx/rspack': 23.1.1(13b9975587e7b23c7eca523ed9d7e170) + '@nx/web': 23.1.1(401e976a88e39fb2af84d87acf67b7d3) '@nx/webpack': 23.1.1(@babel/traverse@7.29.7)(@rspack/core@1.7.12(@swc/helpers@0.5.23))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.19.2)(lightningcss@1.33.0)(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(typescript@6.0.3)(webpack-dev-server@5.2.6(tslib@2.8.1)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)))(webpack@5.64.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.19.2)(lightningcss@1.33.0)(postcss@8.5.6)) '@phenomnomnominal/tsquery': 6.2.0(typescript@6.0.3) '@schematics/angular': 22.1.2(chokidar@5.0.0) @@ -19907,7 +19928,7 @@ snapshots: optionalDependencies: '@angular-devkit/build-angular': 22.1.2(@angular/compiler-cli@22.1.0(@angular/compiler@22.1.0)(typescript@6.0.3))(@angular/compiler@22.1.0)(@angular/core@22.1.0(@angular/compiler@22.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@22.1.0(@angular/animations@22.1.0(@angular/core@22.1.0(@angular/compiler@22.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@22.1.0(@angular/core@22.1.0(@angular/compiler@22.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@22.1.0(@angular/compiler@22.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@rspack/core@1.7.12(@swc/helpers@0.5.23))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@types/node@20.19.9)(chokidar@5.0.0)(jiti@2.4.2)(lightningcss@1.33.0)(ng-packagr@22.1.0(@angular/compiler-cli@22.1.0(@angular/compiler@22.1.0)(typescript@6.0.3))(tailwindcss@4.1.17)(tslib@2.3.0)(typescript@6.0.3))(rollup@4.14.0)(sass-embedded@1.100.0)(tailwindcss@4.1.17)(tsx@4.19.0)(typescript@6.0.3)(vitest@4.0.18)(yaml@2.9.0) '@angular/build': 22.1.2(@angular/compiler-cli@22.1.0(@angular/compiler@22.1.0)(typescript@6.0.3))(@angular/compiler@22.1.0)(@angular/core@22.1.0(@angular/compiler@22.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@22.1.0(@angular/animations@22.1.0(@angular/core@22.1.0(@angular/compiler@22.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@22.1.0(@angular/core@22.1.0(@angular/compiler@22.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@22.1.0(@angular/compiler@22.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@types/node@20.19.9)(chokidar@5.0.0)(istanbul-lib-instrument@6.0.3)(jiti@2.4.2)(less@4.6.7)(ng-packagr@22.1.0(@angular/compiler-cli@22.1.0(@angular/compiler@22.1.0)(typescript@6.0.3))(tailwindcss@4.1.17)(tslib@2.3.0)(typescript@6.0.3))(postcss@8.5.6)(rollup@4.14.0)(sass-embedded@1.100.0)(tailwindcss@4.1.17)(terser@5.28.1)(tslib@2.3.0)(tsx@4.19.0)(typescript@6.0.3)(vitest@4.0.18)(yaml@2.9.0) - '@nx/playwright': 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@playwright/test@1.36.0)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) + '@nx/playwright': 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@playwright/test@1.36.0)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) ng-packagr: 22.1.0(@angular/compiler-cli@22.1.0(@angular/compiler@22.1.0)(typescript@6.0.3))(tailwindcss@4.1.17)(tslib@2.3.0)(typescript@6.0.3) transitivePeerDependencies: - '@babel/traverse' @@ -20067,7 +20088,7 @@ snapshots: - supports-color - verdaccio - '@nx/eslint@23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))': + '@nx/eslint@23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))': dependencies: '@nx/devkit': 23.1.1(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) '@nx/js': 23.1.1(@babel/traverse@7.29.7)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) @@ -20076,7 +20097,7 @@ snapshots: tslib: 2.3.0 typescript: 6.0.3 optionalDependencies: - '@nx/jest': 23.1.1(8be0172cf244ce853aad5d3fbafc9ccb) + '@nx/jest': 23.1.1(7d847bd2f59cc0593e48c48118840ff5) '@zkochan/js-yaml': 0.0.7 transitivePeerDependencies: - '@babel/traverse' @@ -20097,7 +20118,7 @@ snapshots: identity-obj-proxy: 3.0.0 jest-config: 30.4.2(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.19.2))(ts-node@10.9.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@6.0.3)) jest-resolve: 30.4.1 - jest-util: 30.4.1 + jest-util: 30.3.0 minimatch: 9.0.3 picocolors: 1.1.1 resolve.exports: 2.0.3 @@ -20119,7 +20140,7 @@ snapshots: - typescript - verdaccio - '@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb)': + '@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5)': dependencies: '@jest/reporters': 30.4.1 '@jest/test-result': 30.4.1 @@ -20129,7 +20150,7 @@ snapshots: identity-obj-proxy: 3.0.0 jest-config: 30.4.2(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.19.2))(ts-node@10.9.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@6.0.3)) jest-resolve: 30.4.1 - jest-util: 30.4.1 + jest-util: 30.3.0 jsonc-parser: 3.3.1 minimatch: 10.2.5 picocolors: 1.1.1 @@ -20139,7 +20160,7 @@ snapshots: yargs-parser: 21.1.1 optionalDependencies: jest: 30.2.0(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.19.2))(ts-node@10.9.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@6.0.3)) - ts-jest: 29.4.6(@babel/core@7.29.0)(@jest/transform@30.4.1)(@jest/types@30.4.1)(babel-jest@30.2.0(@babel/core@7.29.0))(esbuild@0.19.2)(jest-util@30.4.1)(jest@30.2.0(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.19.2))(ts-node@10.9.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@6.0.3)))(typescript@6.0.3) + ts-jest: 29.4.6(@babel/core@7.29.0)(@jest/transform@30.4.1)(@jest/types@30.4.1)(babel-jest@30.2.0(@babel/core@7.29.0))(esbuild@0.19.2)(jest-util@30.3.0)(jest@30.2.0(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.19.2))(ts-node@10.9.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@6.0.3)))(typescript@6.0.3) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -20274,11 +20295,11 @@ snapshots: - vue-tsc - webpack-cli - '@nx/module-federation@23.1.1(de2c3d761620e871eecd33c4b77b05e5)': + '@nx/module-federation@23.1.1(ed575dd90a698e7a2ada4e01d6d83333)': dependencies: '@nx/devkit': 23.1.1(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) '@nx/js': 23.1.1(@babel/traverse@7.29.7)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) - '@nx/web': 23.1.1(269dd13e357dbfb54dda39a5dcf682ec) + '@nx/web': 23.1.1(401e976a88e39fb2af84d87acf67b7d3) '@rspack/core': 2.1.4(@module-federation/runtime-tools@0.18.4)(@swc/helpers@0.5.23) express: 4.22.2 http-proxy-middleware: 3.0.5 @@ -20317,12 +20338,12 @@ snapshots: - verdaccio - webpack-cli - '@nx/node@23.1.1(df37e30a9f355cb6272a961a8a72175f)': + '@nx/node@23.1.1(c0e3db756d0da6d6b699dfa51d58e1fd)': dependencies: '@nx/devkit': 23.1.1(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) '@nx/docker': 23.1.1(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) - '@nx/eslint': 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) - '@nx/jest': 23.1.1(8be0172cf244ce853aad5d3fbafc9ccb) + '@nx/eslint': 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) + '@nx/jest': 23.1.1(7d847bd2f59cc0593e48c48118840ff5) '@nx/js': 23.1.1(@babel/traverse@7.29.7)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) kill-port: 1.6.1 semver: 7.8.5 @@ -20410,10 +20431,10 @@ snapshots: '@nx/nx-win32-x64-msvc@23.1.1': optional: true - '@nx/playwright@23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@playwright/test@1.36.0)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))': + '@nx/playwright@23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@playwright/test@1.36.0)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))': dependencies: '@nx/devkit': 23.1.1(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) - '@nx/eslint': 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) + '@nx/eslint': 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) '@nx/js': 23.1.1(@babel/traverse@7.29.7)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) minimatch: 10.2.5 semver: 7.8.5 @@ -20487,14 +20508,14 @@ snapshots: - webpack - webpack-cli - '@nx/react@23.1.1(6f6c41671706189c500dd3f5d3f548a6)': + '@nx/react@23.1.1(363fcebb2341dffc7ac71091199caef6)': dependencies: '@nx/devkit': 23.1.1(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) - '@nx/eslint': 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) + '@nx/eslint': 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) '@nx/js': 23.1.1(@babel/traverse@7.29.7)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) - '@nx/module-federation': 23.1.1(de2c3d761620e871eecd33c4b77b05e5) + '@nx/module-federation': 23.1.1(ed575dd90a698e7a2ada4e01d6d83333) '@nx/rollup': 23.1.1(@babel/core@7.29.0)(@babel/traverse@7.29.7)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@types/babel__core@7.20.5)(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(rollup@4.14.0)(typescript@6.0.3) - '@nx/web': 23.1.1(269dd13e357dbfb54dda39a5dcf682ec) + '@nx/web': 23.1.1(401e976a88e39fb2af84d87acf67b7d3) '@phenomnomnominal/tsquery': 6.2.0(typescript@6.0.3) '@svgr/webpack': 8.1.0(typescript@6.0.3) express: 4.22.2 @@ -20505,7 +20526,7 @@ snapshots: semver: 7.8.5 tslib: 2.3.0 optionalDependencies: - '@nx/vite': 23.1.1(@babel/traverse@7.29.7)(@nx/eslint@23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(typescript@6.0.3)(vite@7.3.2(@types/node@20.19.9)(jiti@2.4.2)(less@4.6.7)(lightningcss@1.33.0)(sass-embedded@1.100.0)(sass@1.56.2)(terser@5.28.1)(tsx@4.19.0)(yaml@2.9.0))(vitest@4.0.18) + '@nx/vite': 23.1.1(@babel/traverse@7.29.7)(@nx/eslint@23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(typescript@6.0.3)(vite@7.3.2(@types/node@20.19.9)(jiti@2.4.2)(less@4.6.7)(lightningcss@1.33.0)(sass-embedded@1.100.0)(sass@1.56.2)(terser@5.28.1)(tsx@4.19.0)(yaml@2.9.0))(vitest@4.0.18) transitivePeerDependencies: - '@babel/core' - '@babel/traverse' @@ -20673,12 +20694,12 @@ snapshots: - webpack-cli - webpack-hot-middleware - '@nx/rspack@23.1.1(a3529f5f9f9a7208a5531ab889f55194)': + '@nx/rspack@23.1.1(13b9975587e7b23c7eca523ed9d7e170)': dependencies: '@nx/devkit': 23.1.1(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) '@nx/js': 23.1.1(@babel/traverse@7.29.7)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) - '@nx/module-federation': 23.1.1(de2c3d761620e871eecd33c4b77b05e5) - '@nx/web': 23.1.1(269dd13e357dbfb54dda39a5dcf682ec) + '@nx/module-federation': 23.1.1(ed575dd90a698e7a2ada4e01d6d83333) + '@nx/web': 23.1.1(401e976a88e39fb2af84d87acf67b7d3) '@phenomnomnominal/tsquery': 6.2.0(typescript@6.0.3) autoprefixer: 10.5.2(postcss@8.5.6) browserslist: 4.28.6 @@ -20789,11 +20810,11 @@ snapshots: - typescript - verdaccio - '@nx/vite@23.1.1(@babel/traverse@7.29.7)(@nx/eslint@23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(typescript@6.0.3)(vite@7.3.2(@types/node@20.19.9)(jiti@2.4.2)(less@4.6.7)(lightningcss@1.33.0)(sass-embedded@1.100.0)(sass@1.56.2)(terser@5.28.1)(tsx@4.19.0)(yaml@2.9.0))(vitest@4.0.18)': + '@nx/vite@23.1.1(@babel/traverse@7.29.7)(@nx/eslint@23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(typescript@6.0.3)(vite@7.3.2(@types/node@20.19.9)(jiti@2.4.2)(less@4.6.7)(lightningcss@1.33.0)(sass-embedded@1.100.0)(sass@1.56.2)(terser@5.28.1)(tsx@4.19.0)(yaml@2.9.0))(vitest@4.0.18)': dependencies: '@nx/devkit': 23.1.1(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) '@nx/js': 23.1.1(@babel/traverse@7.29.7)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) - '@nx/vitest': 23.1.1(@babel/traverse@7.29.7)(@nx/eslint@23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(typescript@6.0.3)(vite@7.3.2(@types/node@20.19.9)(jiti@2.4.2)(less@4.6.7)(lightningcss@1.33.0)(sass-embedded@1.100.0)(sass@1.56.2)(terser@5.28.1)(tsx@4.19.0)(yaml@2.9.0))(vitest@4.0.18) + '@nx/vitest': 23.1.1(@babel/traverse@7.29.7)(@nx/eslint@23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(typescript@6.0.3)(vite@7.3.2(@types/node@20.19.9)(jiti@2.4.2)(less@4.6.7)(lightningcss@1.33.0)(sass-embedded@1.100.0)(sass@1.56.2)(terser@5.28.1)(tsx@4.19.0)(yaml@2.9.0))(vitest@4.0.18) '@phenomnomnominal/tsquery': 6.2.0(typescript@6.0.3) ajv: 8.20.0 enquirer: 2.3.6 @@ -20814,7 +20835,7 @@ snapshots: - verdaccio - vitest - '@nx/vitest@23.1.1(@babel/traverse@7.29.7)(@nx/eslint@23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(typescript@6.0.3)(vite@7.3.2(@types/node@20.19.9)(jiti@2.4.2)(less@4.6.7)(lightningcss@1.33.0)(sass-embedded@1.100.0)(sass@1.56.2)(terser@5.28.1)(tsx@4.19.0)(yaml@2.9.0))(vitest@4.0.18)': + '@nx/vitest@23.1.1(@babel/traverse@7.29.7)(@nx/eslint@23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(typescript@6.0.3)(vite@7.3.2(@types/node@20.19.9)(jiti@2.4.2)(less@4.6.7)(lightningcss@1.33.0)(sass-embedded@1.100.0)(sass@1.56.2)(terser@5.28.1)(tsx@4.19.0)(yaml@2.9.0))(vitest@4.0.18)': dependencies: '@nx/devkit': 23.1.1(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) '@nx/js': 23.1.1(@babel/traverse@7.29.7)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) @@ -20822,7 +20843,7 @@ snapshots: semver: 7.8.5 tslib: 2.3.0 optionalDependencies: - '@nx/eslint': 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) + '@nx/eslint': 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) vite: 7.3.2(@types/node@20.19.9)(jiti@2.4.2)(less@4.6.7)(lightningcss@1.33.0)(sass-embedded@1.100.0)(sass@1.56.2)(terser@5.28.1)(tsx@4.19.0)(yaml@2.9.0) vitest: 4.0.18(@opentelemetry/api@1.9.1)(@types/node@20.19.9)(@vitest/ui@4.0.18)(happy-dom@15.7.4)(jiti@2.4.2)(jsdom@28.1.0)(less@4.6.7)(lightningcss@1.33.0)(sass-embedded@1.100.0)(sass@1.56.2)(terser@5.28.1)(tsx@4.19.0)(yaml@2.9.0) transitivePeerDependencies: @@ -20858,18 +20879,18 @@ snapshots: - vite - vitest - '@nx/vue@23.1.1(b7694867a93ecc98b9fe8597854a77c7)': + '@nx/vue@23.1.1(4f1137c05c476613326b82b0cbcff0bb)': dependencies: '@nx/devkit': 23.1.1(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) - '@nx/eslint': 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) + '@nx/eslint': 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) '@nx/js': 23.1.1(@babel/traverse@7.29.7)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) - '@nx/vite': 23.1.1(@babel/traverse@7.29.7)(@nx/eslint@23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(typescript@6.0.3)(vite@7.3.2(@types/node@20.19.9)(jiti@2.4.2)(less@4.6.7)(lightningcss@1.33.0)(sass-embedded@1.100.0)(sass@1.56.2)(terser@5.28.1)(tsx@4.19.0)(yaml@2.9.0))(vitest@4.0.18) - '@nx/vitest': 23.1.1(@babel/traverse@7.29.7)(@nx/eslint@23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(typescript@6.0.3)(vite@7.3.2(@types/node@20.19.9)(jiti@2.4.2)(less@4.6.7)(lightningcss@1.33.0)(sass-embedded@1.100.0)(sass@1.56.2)(terser@5.28.1)(tsx@4.19.0)(yaml@2.9.0))(vitest@4.0.18) - '@nx/web': 23.1.1(269dd13e357dbfb54dda39a5dcf682ec) + '@nx/vite': 23.1.1(@babel/traverse@7.29.7)(@nx/eslint@23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(typescript@6.0.3)(vite@7.3.2(@types/node@20.19.9)(jiti@2.4.2)(less@4.6.7)(lightningcss@1.33.0)(sass-embedded@1.100.0)(sass@1.56.2)(terser@5.28.1)(tsx@4.19.0)(yaml@2.9.0))(vitest@4.0.18) + '@nx/vitest': 23.1.1(@babel/traverse@7.29.7)(@nx/eslint@23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(typescript@6.0.3)(vite@7.3.2(@types/node@20.19.9)(jiti@2.4.2)(less@4.6.7)(lightningcss@1.33.0)(sass-embedded@1.100.0)(sass@1.56.2)(terser@5.28.1)(tsx@4.19.0)(yaml@2.9.0))(vitest@4.0.18) + '@nx/web': 23.1.1(401e976a88e39fb2af84d87acf67b7d3) picomatch: 4.0.4 tslib: 2.3.0 optionalDependencies: - '@nx/playwright': 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@playwright/test@1.36.0)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) + '@nx/playwright': 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@playwright/test@1.36.0)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) '@vitejs/plugin-vue': 6.0.8(vite@7.3.2(@types/node@20.19.9)(jiti@2.4.2)(less@4.6.7)(lightningcss@1.33.0)(sass-embedded@1.100.0)(sass@1.56.2)(terser@5.28.1)(tsx@4.19.0)(yaml@2.9.0))(vue@3.5.39(typescript@6.0.3)) vue: 3.5.39(typescript@6.0.3) vue-tsc: 2.2.12(typescript@6.0.3) @@ -20907,7 +20928,7 @@ snapshots: - supports-color - verdaccio - '@nx/web@23.1.1(269dd13e357dbfb54dda39a5dcf682ec)': + '@nx/web@23.1.1(401e976a88e39fb2af84d87acf67b7d3)': dependencies: '@nx/devkit': 23.1.1(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) '@nx/js': 23.1.1(@babel/traverse@7.29.7)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) @@ -20916,10 +20937,10 @@ snapshots: picocolors: 1.1.1 tslib: 2.3.0 optionalDependencies: - '@nx/eslint': 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) - '@nx/jest': 23.1.1(8be0172cf244ce853aad5d3fbafc9ccb) - '@nx/playwright': 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@playwright/test@1.36.0)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) - '@nx/vite': 23.1.1(@babel/traverse@7.29.7)(@nx/eslint@23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(8be0172cf244ce853aad5d3fbafc9ccb))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(typescript@6.0.3)(vite@7.3.2(@types/node@20.19.9)(jiti@2.4.2)(less@4.6.7)(lightningcss@1.33.0)(sass-embedded@1.100.0)(sass@1.56.2)(terser@5.28.1)(tsx@4.19.0)(yaml@2.9.0))(vitest@4.0.18) + '@nx/eslint': 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) + '@nx/jest': 23.1.1(7d847bd2f59cc0593e48c48118840ff5) + '@nx/playwright': 23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@playwright/test@1.36.0)(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))) + '@nx/vite': 23.1.1(@babel/traverse@7.29.7)(@nx/eslint@23.1.1(@babel/traverse@7.29.7)(@nx/jest@23.1.1(7d847bd2f59cc0593e48c48118840ff5))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.4(jiti@2.4.2))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(typescript@6.0.3)(vite@7.3.2(@types/node@20.19.9)(jiti@2.4.2)(less@4.6.7)(lightningcss@1.33.0)(sass-embedded@1.100.0)(sass@1.56.2)(terser@5.28.1)(tsx@4.19.0)(yaml@2.9.0))(vitest@4.0.18) '@nx/webpack': 23.1.1(@babel/traverse@7.29.7)(@rspack/core@1.7.12(@swc/helpers@0.5.23))(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.19.2)(lightningcss@1.33.0)(nx@23.1.1(@swc-node/register@1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@6.0.3))(@swc/core@1.15.8(@swc/helpers@0.5.23)))(typescript@6.0.3)(webpack-dev-server@5.2.6(tslib@2.8.1)(webpack@5.109.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.28.1)(lightningcss@1.33.0)(postcss@8.5.19)))(webpack@5.64.0(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.19.2)(lightningcss@1.33.0)(postcss@8.5.6)) transitivePeerDependencies: - '@babel/traverse' @@ -28290,6 +28311,15 @@ snapshots: graceful-fs: 4.2.11 picomatch: 4.0.5 + jest-util@30.3.0: + dependencies: + '@jest/types': 30.3.0 + '@types/node': 20.19.9 + chalk: 4.1.2 + ci-info: 4.4.0 + graceful-fs: 4.2.11 + picomatch: 4.0.5 + jest-util@30.4.1: dependencies: '@jest/types': 30.4.1 @@ -32374,7 +32404,7 @@ snapshots: esbuild: 0.28.1 jest-util: 30.4.1 - ts-jest@29.4.6(@babel/core@7.29.0)(@jest/transform@30.4.1)(@jest/types@30.4.1)(babel-jest@30.2.0(@babel/core@7.29.0))(esbuild@0.19.2)(jest-util@30.4.1)(jest@30.2.0(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.19.2))(ts-node@10.9.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@6.0.3)))(typescript@6.0.3): + ts-jest@29.4.6(@babel/core@7.29.0)(@jest/transform@30.4.1)(@jest/types@30.4.1)(babel-jest@30.2.0(@babel/core@7.29.0))(esbuild@0.19.2)(jest-util@30.3.0)(jest@30.2.0(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.19.2))(ts-node@10.9.2(@swc/core@1.15.8(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@6.0.3)))(typescript@6.0.3): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 @@ -32393,7 +32423,7 @@ snapshots: '@jest/types': 30.4.1 babel-jest: 30.2.0(@babel/core@7.29.0) esbuild: 0.19.2 - jest-util: 30.4.1 + jest-util: 30.3.0 ts-loader@9.6.2(loader-utils@2.0.4)(typescript@5.9.3)(webpack@5.108.4(@swc/core@1.15.8(@swc/helpers@0.5.23))(esbuild@0.19.2)(lightningcss@1.33.0)(postcss@8.5.6)): dependencies: diff --git a/core-web/tsconfig.base.json b/core-web/tsconfig.base.json index 6151940a067c..d815d601cb03 100644 --- a/core-web/tsconfig.base.json +++ b/core-web/tsconfig.base.json @@ -115,7 +115,8 @@ "@dotcms/ai/sandbox": ["libs/sdk/ai/src/sandbox/index.ts"], "@dotcms/ai/adapter": ["libs/sdk/ai/src/adapter/index.ts"], "@dotcms/ai/spec": ["libs/sdk/ai/src/spec/index.ts"], - "@dotcms/vue": ["./libs/sdk/vue/src/index.ts"] + "@dotcms/vue": ["./libs/sdk/vue/src/index.ts"], + "@dotcms/portlets/dot-roles/portlet": ["libs/portlets/dot-roles/src/index.ts"] } }, "exclude": ["node_modules", "tmp"] diff --git a/dotCMS/src/main/webapp/WEB-INF/messages/Language.properties b/dotCMS/src/main/webapp/WEB-INF/messages/Language.properties index 9808a9c55ca0..6be0fbf77fc9 100644 --- a/dotCMS/src/main/webapp/WEB-INF/messages/Language.properties +++ b/dotCMS/src/main/webapp/WEB-INF/messages/Language.properties @@ -706,6 +706,7 @@ com.dotcms.repackage.javax.portlet.title.templates=Templates com.dotcms.repackage.javax.portlet.title.time-machine=Time Machine com.dotcms.repackage.javax.portlet.title.users=Users com.dotcms.repackage.javax.portlet.title.users-beta=Users (Beta) +com.dotcms.repackage.javax.portlet.title.roles-beta=Roles and Tools (Beta) com.dotcms.repackage.javax.portlet.title.vanity-urls=Vanity URLs com.dotcms.repackage.javax.portlet.title.web-forms=Web Forms com.dotcms.repackage.javax.portlet.title.workflow-schemes=Workflows @@ -7479,6 +7480,53 @@ users.create.header=Create User users.edit.header=Edit User users.dialog.stub.message=The user profile dialog is coming in a follow-up ticket. +## Roles and Tools Portlet (Beta) +roles.panel.title=ROLES +roles.filter.placeholder=Filter roles +roles.action.new=New +roles.action.edit=Edit Role +roles.action.save=Save +roles.action.cancel=Cancel +roles.action.delete=Delete Role +roles.action.add-child=Add child role +roles.tree.empty=No roles match your filter. +roles.detail.empty=Select a role from the panel on the left. +roles.header.users=users +roles.header.tools-granted=tools granted +roles.chip.system=System +roles.chip.locked=Locked +roles.tab.users=Users +roles.tab.permissions=Permissions +roles.tab.tools=Tools +roles.add.title=Add Role +roles.add.error=Could not create the role. Please try again. +roles.edit.title=Edit Role +roles.edit.blocked=Editing an existing role requires PUT /api/v1/roles/{roleId} (issue #36936). Once the endpoint ships, this dialog will save changes and reparent. +roles.delete.blocked=Deleting a role requires DELETE /api/v1/roles/{roleId} (issue #36939). +roles.form.name=Role +roles.form.key=Key +roles.form.parent=Parent +roles.form.parent.root=None (top level) +roles.form.can-grant=Can Grant +roles.form.users=Users +roles.form.permissions=Permissions +roles.form.tools=Tools +roles.form.description=Description +roles.users.grant=Grant to User +roles.users.grant.blocked=Granting requires POST /api/v1/roles/{roleId}/users/{userId} (issue #36937). Search works; the grant is not persisted yet. +roles.users.search.placeholder=Search users +roles.users.remove=Remove +roles.users.remove.blocked=Bulk remove requires DELETE /api/v1/roles/{roleId}/users (issue #36938). +roles.users.empty.title=This role has no users yet +roles.users.empty.copy=Grant this role to a user using the selector above. +roles.users.column.name=Name +roles.users.column.email=Email +roles.users.column.granted-from=Granted From +roles.permissions.select-role=Select a role to view its permissions. +roles.tools.select-role=Select a role to view its tools. +loading=Loading… +error.load-failed=Failed to load data. Please try again. + ## Tags Portlet tags.search.placeholder=Search tags.export=Export diff --git a/dotCMS/src/main/webapp/WEB-INF/portlet.xml b/dotCMS/src/main/webapp/WEB-INF/portlet.xml index a8a9baad28df..5b7624feff13 100644 --- a/dotCMS/src/main/webapp/WEB-INF/portlet.xml +++ b/dotCMS/src/main/webapp/WEB-INF/portlet.xml @@ -530,4 +530,11 @@ /users + + roles-beta + Roles and Tools (Beta) + com.dotcms.spring.portlet.PortletController + /roles + + From 085a98e07ab2c20f946310c6ab235c9886418ff4 Mon Sep 17 00:00:00 2001 From: hmoreras <31667212+hmoreras@users.noreply.github.com> Date: Fri, 14 Aug 2026 14:21:21 -0600 Subject: [PATCH 02/20] fix(dot-roles): tree hierarchy + users tab data + tab layout (#36930) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Polish pass after the initial scaffold, driven by hands-on feedback against the demo instance. Groups five distinct fixes. ## Tree hierarchy — consume nested `roleChildren` instead of rebuilding The `/v1/roles?loadChildrenRoles=true` response is nested (`RoleView` has `roleChildren: List` even though the openapi.json misses the field). Rebuilding the tree client-side from `parent` was flattening grandchildren away, so Publisher / Legal → Reviewer → Contributor never appeared. The store now consumes the nested response verbatim and lazy-loads deeper levels on `onNodeExpand` via `/v1/roles/{roleId}?loadChildrenRoles=true`. `#expandedRoles` tracks which nodes have been fetched so confirmed-leaf chevrons hide correctly. ## Users tab — swap broken endpoint, handle parents + editUsers=false The tab was calling `/v1/roles/{roleId}/rolehierarchyanduserroles` and expecting `firstName/lastName/emailAddress` on the entries — but that endpoint returns `Role[]`, not `User[]`, so the table stayed empty. Two-path replacement: - `loadRoleMembersByKey(roleKey)` → `GET /v1/users/filter?roleKey=X` — same fast path dot-users uses, returns users with email. - `loadRoleMembersById(roleId)` → falls back to `/rolehierarchyanduserroles` and parses the `user === true` entries. No email today (the endpoint returns Role objects); table shows `—` in that column until an id-based user endpoint is added upstream. The store picks the path based on whether the selected role has a `roleKey`. Also drops the previous `!editUsers` short-circuit — the flag gates GRANT/REMOVE actions, not visibility. Parent roles (Publisher / Legal, System, etc.) now show their members; the "Users cannot be assigned" banner appears above the table when `editUsers === false` and the Grant / Remove buttons are disabled instead of the whole tab. ## Tree row height — match Content Drive by dropping `pButton` The inline `+` add-child action was a ` - + } @else {

{{ 'roles.tree.empty' | dm }}

diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-tree/dot-roles-tree.component.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-tree/dot-roles-tree.component.ts index 84008ab33ba2..8a06698fe57f 100644 --- a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-tree/dot-roles-tree.component.ts +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-roles-tree/dot-roles-tree.component.ts @@ -1,6 +1,6 @@ import { Subject } from 'rxjs'; -import { Component, DestroyRef, computed, inject } from '@angular/core'; +import { Component, DestroyRef, computed, inject, signal } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { FormsModule } from '@angular/forms'; @@ -10,21 +10,21 @@ import { DialogService, DynamicDialogModule } from 'primeng/dynamicdialog'; import { IconFieldModule } from 'primeng/iconfield'; import { InputIconModule } from 'primeng/inputicon'; import { InputTextModule } from 'primeng/inputtext'; -import { TreeModule, TreeNodeSelectEvent } from 'primeng/tree'; +import { TreeNodeExpandEvent, TreeNodeSelectEvent } from 'primeng/types/tree'; import { debounceTime, distinctUntilChanged } from 'rxjs/operators'; -import { DotMessagePipe } from '@dotcms/ui'; +import { DotFolderTreeComponent, DotMessagePipe } from '@dotcms/ui'; import { DotRolesAddComponent } from '../../../dot-roles-add/dot-roles-add.component'; import { DotRoleNode } from '../../../models/dot-roles.models'; import { DotRolesStore } from '../../store/dot-roles.store'; -interface DotRoleTreeNode extends TreeNode { +interface DotRolePrimeTreeNode extends TreeNode { data: DotRoleNode; key: string; label: string; - children?: DotRoleTreeNode[]; + children?: DotRolePrimeTreeNode[]; } @Component({ @@ -37,7 +37,7 @@ interface DotRoleTreeNode extends TreeNode { IconFieldModule, InputIconModule, DynamicDialogModule, - TreeModule, + DotFolderTreeComponent, DotMessagePipe ], providers: [DialogService], @@ -50,13 +50,29 @@ export class DotRolesTreeComponent { readonly #dialogService = inject(DialogService); readonly #filterInput$ = new Subject(); + /** + * Nodes whose children have already been lazy-loaded from the backend. + * We use this to hide the chevron on nodes we've confirmed are leaves + * so users don't get to click into empty branches after expanding. + */ + readonly #expandedRoles = signal(new Set()); + + /** + * PassThrough config for the shared `DotFolderTreeComponent` — matches + * the compact chrome used by Content Drive so row heights stay tight. + */ + protected readonly treePt = { + root: { class: 'w-full h-full border-none overflow-y-auto' }, + nodeLabel: { class: 'overflow-hidden text-ellipsis whitespace-nowrap flex-1' } + }; + protected readonly $filterInput = computed(() => this.store.filter()); - protected readonly $treeNodes = computed(() => + protected readonly $treeNodes = computed(() => this.#toTreeNodes(this.store.filteredRoles()) ); - protected readonly $selectedNode = computed(() => { + protected readonly $selectedNode = computed(() => { const id = this.store.selectedRoleId(); if (!id) { return null; @@ -76,13 +92,34 @@ export class DotRolesTreeComponent { } protected onNodeSelect(event: TreeNodeSelectEvent): void { - const node = event.node as DotRoleTreeNode; + const node = event.node as DotRolePrimeTreeNode; this.store.selectRole(node.data.id); } + /** + * PrimeNG lazy-load hook. The backend only returns 2 levels deep per + * request, so any node whose children we haven't fetched yet triggers + * a load on first expand. + */ + protected onNodeExpand(event: TreeNodeExpandEvent): void { + const node = event.node as DotRolePrimeTreeNode; + const id = node.data.id; + if (this.#expandedRoles().has(id)) { + return; + } + + this.#expandedRoles.update((set) => new Set(set).add(id)); + + // Only fetch when we don't already have children populated. + const hasLoadedChildren = (node.data.roleChildren?.length ?? 0) > 0; + if (!hasLoadedChildren && !node.data.user) { + this.store.loadRoleChildren(id); + } + } + protected onAddRole(parentRoleId?: string): void { this.#dialogService.open(DotRolesAddComponent, { - header: undefined, // Component sets its own header + header: undefined, width: '700px', closable: true, closeOnEscape: true, @@ -90,31 +127,28 @@ export class DotRolesTreeComponent { }); } - /** - * TODO: wire drag-and-drop reparent when #36936 (PUT /v1/roles/{roleId}) - * lands. The Angular `p-tree` supports `draggableNodes` + `droppableNodes` - * but the server-side reparent has no v1 endpoint today. - */ - protected onNodeDrop(_event: unknown): void { - // Intentionally no-op until backend endpoint is available. - } - - #toTreeNodes(nodes: DotRoleNode[]): DotRoleTreeNode[] { + #toTreeNodes(nodes: DotRoleNode[]): DotRolePrimeTreeNode[] { return nodes.map((node) => { - const children = node.children ? this.#toTreeNodes(node.children) : []; + const children = this.#toTreeNodes(node.roleChildren ?? []); + const hasChildren = children.length > 0; + // A node is a confirmed leaf when it's a user-role, OR we've + // fetched its children and got none back. Otherwise we keep + // the chevron so admins can drill into deeper levels. + const confirmedLeaf = + node.user === true || (this.#expandedRoles().has(node.id) && !hasChildren); return { key: node.id, label: node.name, data: node, - icon: children.length > 0 ? 'folder' : 'shield', children, - leaf: children.length === 0 + leaf: confirmedLeaf, + expanded: hasChildren }; }); } - #findNode(nodes: DotRoleTreeNode[], id: string): DotRoleTreeNode | null { + #findNode(nodes: DotRolePrimeTreeNode[], id: string): DotRolePrimeTreeNode | null { for (const node of nodes) { if (node.data.id === id) { return node; diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.html b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.html index 7f9ad2378038..221c2c0010f3 100644 --- a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.html +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.html @@ -25,14 +25,14 @@ - - + + - + - + diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.spec.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.spec.ts index b39a4bceeea7..4e4806040e0a 100644 --- a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.spec.ts +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.spec.ts @@ -36,24 +36,28 @@ const MESSAGES = { */ function baseStoreMock(overrides: Record = {}) { return mockProvider(DotRolesStore, { - rootRoles: jest.fn().mockReturnValue([]), + roles: jest.fn().mockReturnValue([]), + roleTree: jest.fn().mockReturnValue([]), filter: jest.fn().mockReturnValue(''), filteredRoles: jest.fn().mockReturnValue([]), selectedRoleId: jest.fn().mockReturnValue(null), selectedRole: jest.fn().mockReturnValue(null), + selectedRoleIsParent: jest.fn().mockReturnValue(false), activeTab: jest.fn().mockReturnValue('users'), status: jest.fn().mockReturnValue('loaded'), membersStatus: jest.fn().mockReturnValue('loaded'), members: jest.fn().mockReturnValue([]), selectedMembers: jest.fn().mockReturnValue([]), memberCount: jest.fn().mockReturnValue(0), - directMemberCount: jest.fn().mockReturnValue(0), isSystemRole: jest.fn().mockReturnValue(false), + canGrantUsers: jest.fn().mockReturnValue(true), setFilter: jest.fn(), selectRole: jest.fn(), setActiveTab: jest.fn(), setSelectedMembers: jest.fn(), loadRootRoles: jest.fn(), + loadMembers: jest.fn(), + loadRoleChildren: jest.fn(), createRole: jest.fn(), ...overrides }); diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.ts index dd2f9ead06e7..489205bd66e9 100644 --- a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.ts +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.ts @@ -33,6 +33,16 @@ import { DotRolesPortletService } from '../services/dot-roles-portlet.service'; export class DotRolesPageComponent implements OnInit { protected readonly store = inject(DotRolesStore); + /** + * PassThrough to strip PrimeNG's default padding off the tab panel + * wrappers — the Users tab renders a `p-table` that must reach the + * section edges to align with the panel divider. Tailwind's `!` + * suffix wins the specificity war against PrimeNG's `.p-tabpanels` + * selector. + */ + protected readonly tabPanelsPt = { root: { class: 'p-0!' } }; + protected readonly tabPanelPt = { root: { class: 'p-0!' } }; + ngOnInit(): void { this.store.loadRootRoles(); } diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.spec.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.spec.ts index 572d068600ad..c760c3b032db 100644 --- a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.spec.ts +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.spec.ts @@ -5,50 +5,66 @@ import { DotHttpErrorManagerService } from '@dotcms/data-access'; import { DotRolesStore } from './dot-roles.store'; +import { DotRoleDetail, DotRoleFormValue, DotRoleNode } from '../../models/dot-roles.models'; import { - DotRoleDetail, - DotRoleFormValue, - DotRoleMember, - DotRoleNode -} from '../../models/dot-roles.models'; -import { DotRolesPortletService } from '../../services/dot-roles-portlet.service'; - -const MOCK_ROOT_ROLES: DotRoleNode[] = [ + DotRolesPortletService, + DotRoleUserFilterResult +} from '../../services/dot-roles-portlet.service'; + +const ROLE_BY_KEY = { id: 'r-eco', roleKey: 'eco' }; +const ROLE_BY_ID = { id: 'r-nokey', roleKey: null }; + +/** + * Nested shape returned by `GET /v1/roles?loadChildrenRoles=true` — matches + * the real `RoleView` wire format (openapi.json misses the `roleChildren` + * field, but the Java class exposes it). + */ +const MOCK_NESTED_ROLES: DotRoleNode[] = [ { id: 'r-categories', name: 'Categories', - children: [ - { id: 'r-eco', name: 'Eco Role', parent: 'r-categories', userCount: 2 }, - { id: 'r-snow', name: 'Snow Role', parent: 'r-categories', userCount: 0 } + roleKey: 'Categories', + roleChildren: [ + { + id: 'r-eco', + name: 'Eco Role', + parent: 'r-categories', + roleKey: 'eco', + roleChildren: [] + }, + { + id: 'r-snow', + name: 'Snow Role', + parent: 'r-categories', + roleKey: 'snow', + roleChildren: [] + } ] }, - { id: 'r-system', name: 'System', system: true } + { id: 'r-system', name: 'System', system: true, roleKey: 'system', roleChildren: [] } ]; const MOCK_ROLE_DETAIL: DotRoleDetail = { id: 'r-eco', name: 'Eco Role', parent: 'r-categories', + roleKey: 'eco', description: 'Eco team', editUsers: true }; -const MOCK_MEMBERS: DotRoleMember[] = [ +const MOCK_USER_FILTER_RESULTS: DotRoleUserFilterResult[] = [ { userId: 'u-1', firstName: 'Alan', lastName: 'Cruz', - emailAddress: 'alan.cruz@dotcms.com', - grantedFromRoleId: 'r-eco', - grantedFromRoleName: 'Eco Role' + emailAddress: 'alan.cruz@dotcms.com' }, { userId: 'u-2', firstName: 'Elena', lastName: 'Petrov', - emailAddress: 'elena.p@dotcms.com', - grantedFromRoleId: 'r-categories', - grantedFromRoleName: 'Categories' + emailAddress: 'elena.p@dotcms.com' } ]; @@ -61,9 +77,10 @@ describe('DotRolesStore', () => { service: DotRolesStore, providers: [ mockProvider(DotRolesPortletService, { - loadRootRoles: jest.fn().mockReturnValue(of(MOCK_ROOT_ROLES)), + loadRootRoles: jest.fn().mockReturnValue(of(MOCK_NESTED_ROLES)), loadRoleById: jest.fn().mockReturnValue(of(MOCK_ROLE_DETAIL)), - loadRoleMembers: jest.fn().mockReturnValue(of(MOCK_MEMBERS)), + loadRoleMembersByKey: jest.fn().mockReturnValue(of(MOCK_USER_FILTER_RESULTS)), + loadRoleMembersById: jest.fn().mockReturnValue(of(MOCK_USER_FILTER_RESULTS)), createRole: jest.fn().mockReturnValue(of(MOCK_ROLE_DETAIL)) }), mockProvider(DotHttpErrorManagerService) @@ -75,15 +92,17 @@ describe('DotRolesStore', () => { store = spectator.service; service = spectator.inject(DotRolesPortletService) as jest.Mocked; jest.clearAllMocks(); - service.loadRootRoles.mockReturnValue(of(MOCK_ROOT_ROLES)); + service.loadRootRoles.mockReturnValue(of(MOCK_NESTED_ROLES)); service.loadRoleById.mockReturnValue(of(MOCK_ROLE_DETAIL)); - service.loadRoleMembers.mockReturnValue(of(MOCK_MEMBERS)); + service.loadRoleMembersByKey.mockReturnValue(of(MOCK_USER_FILTER_RESULTS)); + service.loadRoleMembersById.mockReturnValue(of(MOCK_USER_FILTER_RESULTS)); service.createRole.mockReturnValue(of(MOCK_ROLE_DETAIL)); }); describe('initial state', () => { - it('should start with empty rootRoles + init status', () => { - expect(store.rootRoles()).toEqual([]); + it('should start with an empty roles list + init status', () => { + expect(store.roles()).toEqual([]); + expect(store.roleTree()).toEqual([]); expect(store.status()).toBe('init'); expect(store.selectedRoleId()).toBeNull(); expect(store.activeTab()).toBe('users'); @@ -92,14 +111,23 @@ describe('DotRolesStore', () => { }); describe('loadRootRoles', () => { - it('should populate rootRoles and set status to loaded', () => { + it('should populate roles and set status to loaded', () => { store.loadRootRoles(); expect(service.loadRootRoles).toHaveBeenCalledWith(true); - expect(store.rootRoles()).toEqual(MOCK_ROOT_ROLES); + expect(store.roles()).toEqual(MOCK_NESTED_ROLES); expect(store.status()).toBe('loaded'); }); + it('should expose the nested response verbatim via roleTree', () => { + store.loadRootRoles(); + + const tree = store.roleTree(); + expect(tree.map((n) => n.id)).toEqual(['r-categories', 'r-system']); + const categories = tree.find((n) => n.id === 'r-categories'); + expect(categories?.roleChildren?.map((c) => c.id)).toEqual(['r-eco', 'r-snow']); + }); + it('should set status to error and delegate to httpErrorManager on failure', () => { const errorManager = spectator.inject(DotHttpErrorManagerService); service.loadRootRoles.mockReturnValueOnce(throwError(() => new Error('boom'))); @@ -111,15 +139,43 @@ describe('DotRolesStore', () => { }); }); + describe('loadRoleChildren (lazy-load on expand)', () => { + beforeEach(() => { + store.loadRootRoles(); + }); + + it('should splice fetched children into the state tree', () => { + service.loadRoleById.mockReturnValueOnce( + of({ + id: 'r-eco', + name: 'Eco Role', + parent: 'r-categories', + roleChildren: [ + { + id: 'r-eco-child', + name: 'Eco Child', + parent: 'r-eco', + roleChildren: [] + } + ] + }) + ); + + store.loadRoleChildren('r-eco'); + + const categories = store.roles().find((n) => n.id === 'r-categories'); + const eco = categories?.roleChildren?.find((n) => n.id === 'r-eco'); + expect(eco?.roleChildren?.map((n) => n.id)).toEqual(['r-eco-child']); + }); + }); + describe('selectRole', () => { - it('should set selectedRoleId and trigger detail + members load', () => { + it('should set selectedRoleId and load the role detail', () => { store.selectRole('r-eco'); expect(store.selectedRoleId()).toBe('r-eco'); expect(service.loadRoleById).toHaveBeenCalledWith('r-eco', true); - expect(service.loadRoleMembers).toHaveBeenCalledWith('r-eco'); expect(store.selectedRole()).toEqual(MOCK_ROLE_DETAIL); - expect(store.members()).toEqual(MOCK_MEMBERS); }); it('should clear selection without loading when passed null', () => { @@ -130,17 +186,46 @@ describe('DotRolesStore', () => { expect(store.selectedRoleId()).toBeNull(); expect(service.loadRoleById).not.toHaveBeenCalled(); - expect(service.loadRoleMembers).not.toHaveBeenCalled(); }); - it('should clear selectedMembers when switching roles', () => { - store.selectRole('r-eco'); - store.setSelectedMembers([MOCK_MEMBERS[0]]); + it('should clear members and selectedMembers when switching roles', () => { + store.loadMembers(ROLE_BY_KEY); + store.setSelectedMembers([{ userId: 'u-1' } as never]); expect(store.selectedMembers()).toHaveLength(1); store.selectRole('r-snow'); expect(store.selectedMembers()).toEqual([]); + expect(store.members()).toEqual([]); + }); + }); + + describe('loadMembers', () => { + it('should use the roleKey path when the selected role has a roleKey', () => { + store.loadMembers(ROLE_BY_KEY); + + expect(service.loadRoleMembersByKey).toHaveBeenCalledWith('eco'); + expect(service.loadRoleMembersById).not.toHaveBeenCalled(); + expect(store.members()).toHaveLength(2); + expect(store.membersStatus()).toBe('loaded'); + }); + + it('should fall back to the roleId path when the role has no roleKey', () => { + store.loadMembers(ROLE_BY_ID); + + expect(service.loadRoleMembersById).toHaveBeenCalledWith('r-nokey'); + expect(service.loadRoleMembersByKey).not.toHaveBeenCalled(); + expect(store.members()).toHaveLength(2); + }); + + it('should set membersStatus to error and delegate on failure', () => { + const errorManager = spectator.inject(DotHttpErrorManagerService); + service.loadRoleMembersByKey.mockReturnValueOnce(throwError(() => new Error('boom'))); + + store.loadMembers(ROLE_BY_KEY); + + expect(store.membersStatus()).toBe('error'); + expect(errorManager.handle).toHaveBeenCalled(); }); }); @@ -150,7 +235,8 @@ describe('DotRolesStore', () => { }); it('should return the full tree when the filter is empty', () => { - expect(store.filteredRoles()).toEqual(MOCK_ROOT_ROLES); + const filtered = store.filteredRoles(); + expect(filtered.map((n) => n.id)).toEqual(['r-categories', 'r-system']); }); it('should keep parent nodes whose children match the filter', () => { @@ -159,8 +245,8 @@ describe('DotRolesStore', () => { const filtered = store.filteredRoles(); expect(filtered).toHaveLength(1); expect(filtered[0].id).toBe('r-categories'); - expect(filtered[0].children).toHaveLength(1); - expect(filtered[0].children?.[0].id).toBe('r-eco'); + expect(filtered[0].roleChildren).toHaveLength(1); + expect(filtered[0].roleChildren?.[0].id).toBe('r-eco'); }); it('should keep leaf nodes matching the filter directly', () => { @@ -178,34 +264,57 @@ describe('DotRolesStore', () => { }); }); - describe('computed member counts', () => { + describe('member count computeds', () => { beforeEach(() => { store.selectRole('r-eco'); + store.loadMembers(ROLE_BY_KEY); }); it('should compute total memberCount', () => { expect(store.memberCount()).toBe(2); }); + }); + + describe('selectedRoleIsParent and isSystemRole', () => { + it('should mark the selected role as parent when the detail has roleChildren', () => { + service.loadRoleById.mockReturnValueOnce( + of({ + ...MOCK_ROLE_DETAIL, + roleChildren: [{ id: 'child', name: 'child' }] + }) + ); + + store.selectRole('r-eco'); - it('should compute directMemberCount from grantedFromRoleId matching selected role', () => { - // 1 direct (u-1 on r-eco), 1 inherited (u-2 from r-categories) - expect(store.directMemberCount()).toBe(1); + expect(store.selectedRoleIsParent()).toBe(true); }); - }); - describe('isSystemRole', () => { - it('should be true when the selected role is a system role', () => { + it('should mark the selected role as leaf when the detail has no roleChildren', () => { + store.selectRole('r-eco'); + + expect(store.selectedRoleIsParent()).toBe(false); + }); + + it('isSystemRole should be true only for system roles', () => { service.loadRoleById.mockReturnValueOnce(of({ ...MOCK_ROLE_DETAIL, system: true })); store.selectRole('r-system'); expect(store.isSystemRole()).toBe(true); }); + }); - it('should be false when the selected role is not a system role', () => { - store.selectRole('r-eco'); + describe('canGrantUsers', () => { + it('should reflect the editUsers flag from the selected role', () => { + service.loadRoleById.mockReturnValueOnce(of({ ...MOCK_ROLE_DETAIL, editUsers: false })); + + store.selectRole('r-system'); - expect(store.isSystemRole()).toBe(false); + expect(store.canGrantUsers()).toBe(false); + }); + + it('should default to true when no role is selected', () => { + expect(store.canGrantUsers()).toBe(true); }); }); @@ -230,13 +339,64 @@ describe('DotRolesStore', () => { description: '' }; - it('should POST, reload tree, select the new role, and return the created detail', async () => { + it('should POST, append the created role to the roots when parentRoleId is null', async () => { + store.loadRootRoles(); + jest.clearAllMocks(); + service.createRole.mockReturnValue( + of({ id: 'r-new-root', name: 'New Root', roleKey: 'new-root' }) + ); + const created = await store.createRole(FORM); expect(service.createRole).toHaveBeenCalledWith(FORM); - expect(service.loadRootRoles).toHaveBeenCalled(); - expect(store.selectedRoleId()).toBe(MOCK_ROLE_DETAIL.id); - expect(created).toEqual(MOCK_ROLE_DETAIL); + // Local splice — no full reload. + expect(service.loadRootRoles).not.toHaveBeenCalled(); + expect(store.roles().map((n) => n.id)).toContain('r-new-root'); + expect(store.selectedRoleId()).toBe('r-new-root'); + expect(created?.id).toBe('r-new-root'); + }); + + it('should splice into the parent roleChildren when the parent is loaded', async () => { + store.loadRootRoles(); + jest.clearAllMocks(); + service.createRole.mockReturnValue( + of({ + id: 'r-eco-child', + name: 'Eco Child', + parent: 'r-eco', + roleKey: 'eco-child' + }) + ); + + await store.createRole({ ...FORM, parentRoleId: 'r-eco' }); + + // Full reload not triggered, targeted fetch not triggered either. + expect(service.loadRootRoles).not.toHaveBeenCalled(); + expect(service.loadRoleById).toHaveBeenCalledTimes(1); + const categories = store.roles().find((n) => n.id === 'r-categories'); + const eco = categories?.roleChildren?.find((n) => n.id === 'r-eco'); + expect(eco?.roleChildren?.map((n) => n.id)).toContain('r-eco-child'); + }); + + it('should refresh just the parent subtree when the parent is not loaded', async () => { + store.loadRootRoles(); + jest.clearAllMocks(); + service.createRole.mockReturnValue( + of({ id: 'r-deep', name: 'Deep', parent: 'r-unloaded', roleKey: 'deep' }) + ); + service.loadRoleById.mockReturnValueOnce( + of({ + id: 'r-unloaded', + name: 'Unloaded Parent', + roleChildren: [{ id: 'r-deep', name: 'Deep', roleChildren: [] }] + }) + ); + + await store.createRole({ ...FORM, parentRoleId: 'r-unloaded' }); + + expect(service.loadRootRoles).not.toHaveBeenCalled(); + // One call for the parent subtree refresh + one for the selected role detail. + expect(service.loadRoleById).toHaveBeenCalledWith('r-unloaded', true); }); it('should delegate to httpErrorManager and return null on failure', async () => { diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.ts index 241701684b22..e0639829d1bf 100644 --- a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.ts +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.ts @@ -19,8 +19,13 @@ import { import { DotRolesPortletService } from '../../services/dot-roles-portlet.service'; export interface DotRolesState { - /** Full tree as loaded from `/v1/roles` (root roles + their first-level children). */ - rootRoles: DotRoleNode[]; + /** + * Nested role tree as returned by `GET /v1/roles?loadChildrenRoles=true` + * — root roles with their direct children populated. Grandchildren come + * back empty from the initial call and are lazy-loaded per node when + * the user expands them (see `loadRoleChildren`). + */ + roles: DotRoleNode[]; /** Client-side filter typed into the `Filter roles` input. */ filter: string; /** Currently selected role id (drives the right-hand detail area). */ @@ -29,7 +34,7 @@ export interface DotRolesState { selectedRole: DotRoleDetail | null; /** Active tab on the right-hand detail area. */ activeTab: DotRoleTab; - /** Members of the selected role, annotated with inheritance metadata. */ + /** Members of the selected role. */ members: DotRoleMember[]; /** Users selected for bulk-remove on the members table. */ selectedMembers: DotRoleMember[]; @@ -39,7 +44,7 @@ export interface DotRolesState { } const initialState: DotRolesState = { - rootRoles: [], + roles: [], filter: '', selectedRoleId: null, selectedRole: null, @@ -54,32 +59,38 @@ const initialState: DotRolesState = { export const DotRolesStore = signalStore( withState(initialState), - withComputed(({ rootRoles, filter, selectedRoleId, selectedRole, members }) => ({ + withComputed(({ roles, filter, selectedRoleId, selectedRole, members }) => ({ + /** Alias for `roles` — the tree comes nested from the wire response. */ + roleTree: computed(() => roles()), + /** - * Client-side filter applied to the loaded tree. The Dojo portlet - * hits `/api/role/loadbyname` on filter; the Angular portlet - * loads the tree once and filters in memory to avoid extra HTTP - * per keystroke. + * Nested tree filtered by the free-text `Filter roles` input. A + * parent whose name doesn't match is still kept if any of its + * descendants match; a leaf is dropped when it doesn't match. */ filteredRoles: computed(() => { const q = filter().trim().toLowerCase(); if (!q) { - return rootRoles(); + return roles(); } - return filterTree(rootRoles(), q); + return filterTree(roles(), q); }), - /** Total users granted this role — direct + inherited. */ + /** Total users granted this role. */ memberCount: computed(() => members().length), - /** How many members were granted directly on the selected role. */ - directMemberCount: computed( - () => members().filter((m) => m.grantedFromRoleId === selectedRoleId()).length - ), - /** True when the selected role is a system role (locked / immutable). */ - isSystemRole: computed(() => selectedRole()?.system ?? false) + isSystemRole: computed(() => selectedRole()?.system ?? false), + + /** True when the selected role can accept user grants. */ + canGrantUsers: computed(() => selectedRole()?.editUsers ?? true), + + /** True when the selected role has children (folder icon in the header). */ + selectedRoleIsParent: computed(() => (selectedRole()?.roleChildren?.length ?? 0) > 0), + + /** Selected role id used by consumers that need to correlate. */ + selectedIdForCorrelation: computed(() => selectedRoleId()) })), withMethods((store) => { @@ -91,8 +102,8 @@ export const DotRolesStore = signalStore( tap(() => patchState(store, { status: 'loading', error: null })), switchMap(() => service.loadRootRoles(true).pipe( - tap((rootRoles) => { - patchState(store, { rootRoles, status: 'loaded' }); + tap((roles) => { + patchState(store, { roles, status: 'loaded' }); }), catchError((error) => { httpErrorManager.handle(error); @@ -105,28 +116,6 @@ export const DotRolesStore = signalStore( ) ); - const loadRoleMembers = rxMethod( - pipe( - tap(() => patchState(store, { membersStatus: 'loading' })), - switchMap((roleId) => - service.loadRoleMembers(roleId).pipe( - tap((members) => { - patchState(store, { - members, - membersStatus: 'loaded' - }); - }), - catchError((error) => { - httpErrorManager.handle(error); - patchState(store, { membersStatus: 'error' }); - - return EMPTY; - }) - ) - ) - ) - ); - const loadRoleDetail = rxMethod( pipe( switchMap((roleId) => @@ -144,7 +133,6 @@ export const DotRolesStore = signalStore( return { loadRootRoles, - loadRoleMembers, loadRoleDetail, /** Update the free-text filter applied to the tree. */ @@ -156,15 +144,69 @@ export const DotRolesStore = signalStore( selectRole(roleId: string | null): void { patchState(store, { selectedRoleId: roleId, - selectedMembers: [] + selectedMembers: [], + members: [], + membersStatus: 'init' }); if (roleId) { loadRoleDetail(roleId); - loadRoleMembers(roleId); } }, + /** + * Load members for the currently selected role. Called by the + * Users tab component whenever the selected role changes. + * + * Path selection: + * - If the role has a `roleKey`, use `/v1/users/filter?roleKey=X` + * — fast, returns email and full name in one call. + * - Otherwise, fall back to `/rolehierarchyanduserroles` and + * parse user-roles from the response. That path is missing + * email today because the endpoint returns Role objects, not + * User objects (see `DotRolesPortletService.loadRoleMembersById`). + */ + loadMembers(role: { id: string; roleKey?: string | null }): void { + patchState(store, { membersStatus: 'loading' }); + const request$ = role.roleKey + ? service.loadRoleMembersByKey(role.roleKey) + : service.loadRoleMembersById(role.id); + request$.subscribe({ + next: (users) => { + const members: DotRoleMember[] = users.map((u) => ({ + userId: u.userId, + firstName: u.firstName ?? '', + lastName: u.lastName ?? '', + emailAddress: u.emailAddress ?? '' + })); + patchState(store, { members, membersStatus: 'loaded' }); + }, + error: (error) => { + httpErrorManager.handle(error); + patchState(store, { membersStatus: 'error' }); + } + }); + }, + + /** + * Lazy-load a node's children when the user expands it in the + * roles tree. Fetches `/v1/roles/{roleId}?loadChildrenRoles=true` + * and splices the returned children into the state tree. + */ + loadRoleChildren(roleId: string): void { + service.loadRoleById(roleId, true).subscribe({ + next: (loaded) => { + const next = patchNodeChildren( + store.roles(), + roleId, + loaded.roleChildren ?? [] + ); + patchState(store, { roles: next }); + }, + error: (error) => httpErrorManager.handle(error) + }); + }, + setActiveTab(activeTab: DotRoleTab): void { patchState(store, { activeTab }); }, @@ -176,6 +218,17 @@ export const DotRolesStore = signalStore( /** * Create a role. Returns a promise so the calling component * can close its dialog on success and surface errors on failure. + * + * Efficiency: the POST response carries the fully-hydrated new + * role (id, parent, roleKey, DBFQN, FQN...). We splice it into + * the parent's `roleChildren` in state — no follow-up fetch, + * no loss of lazy-loaded branches elsewhere in the tree. + * + * Fallback: when the target parent isn't currently in state + * (edge case — parent picker showed a role we haven't lazy- + * loaded above), we scope the refresh to just that parent's + * subtree via `loadRoleChildren` instead of reloading the whole + * tree. */ async createRole(form: DotRoleFormValue): Promise { try { @@ -185,9 +238,35 @@ export const DotRolesStore = signalStore( error: (err) => reject(err) }); }); - // Reload the tree so the new node appears; select it. - loadRootRoles(); + + const parentId = form.parentRoleId ?? null; + if (!parentId) { + // Root role — append to state.roles. + patchState(store, { roles: [...store.roles(), created] }); + } else if (findRoleInTree(store.roles(), parentId)) { + // Parent is loaded — splice in place, keep the rest untouched. + patchState(store, { + roles: appendChildToParent(store.roles(), parentId, created) + }); + } else { + // Parent isn't in the loaded tree — refresh just that + // subtree instead of reloading the whole root list. + service.loadRoleById(parentId, true).subscribe({ + next: (parentDetail) => { + patchState(store, { + roles: patchNodeChildren( + store.roles(), + parentId, + parentDetail.roleChildren ?? [] + ) + }); + }, + error: (error) => httpErrorManager.handle(error) + }); + } + patchState(store, { selectedRoleId: created.id }); + loadRoleDetail(created.id); return created; } catch (error) { @@ -204,8 +283,6 @@ export const DotRolesStore = signalStore( // - #36937 (POST /v1/roles/{roleId}/users/{userId}) → Grant user // - #36938 (DELETE /v1/roles/{roleId}/users) → Remove members // - #36939 (DELETE /v1/roles/{roleId}) → Delete Role - // Components must render the corresponding UI in a disabled / - // "coming soon" state until those endpoints land. }; }) ); @@ -213,15 +290,81 @@ export const DotRolesStore = signalStore( function filterTree(nodes: DotRoleNode[], query: string): DotRoleNode[] { return nodes.reduce((acc, node) => { const matches = node.name.toLowerCase().includes(query); - const filteredChildren = node.children ? filterTree(node.children, query) : []; + const filteredChildren = node.roleChildren ? filterTree(node.roleChildren, query) : []; if (matches || filteredChildren.length > 0) { acc.push({ ...node, - children: filteredChildren.length > 0 ? filteredChildren : node.children + roleChildren: filteredChildren.length > 0 ? filteredChildren : node.roleChildren }); } return acc; }, []); } + +/** + * Immutably splice `newChildren` into the tree under the node with `id`. + * Returns a new tree; unchanged branches are shared by reference. + */ +function patchNodeChildren( + nodes: DotRoleNode[], + id: string, + newChildren: DotRoleNode[] +): DotRoleNode[] { + return nodes.map((node) => { + if (node.id === id) { + return { ...node, roleChildren: newChildren }; + } + if (node.roleChildren && node.roleChildren.length > 0) { + return { + ...node, + roleChildren: patchNodeChildren(node.roleChildren, id, newChildren) + }; + } + return node; + }); +} + +/** + * Immutably append a newly-created role to its parent's `roleChildren`. + * Sharing branches by reference keeps re-render churn minimal. + */ +function appendChildToParent( + nodes: DotRoleNode[], + parentId: string, + child: DotRoleNode +): DotRoleNode[] { + return nodes.map((node) => { + if (node.id === parentId) { + return { + ...node, + roleChildren: [...(node.roleChildren ?? []), child] + }; + } + if (node.roleChildren && node.roleChildren.length > 0) { + return { + ...node, + roleChildren: appendChildToParent(node.roleChildren, parentId, child) + }; + } + return node; + }); +} + +/** Walk the tree looking for a node id. Returns the node or `null`. */ +function findRoleInTree(nodes: DotRoleNode[], id: string): DotRoleNode | null { + for (const node of nodes) { + if (node.id === id) { + return node; + } + if (node.roleChildren && node.roleChildren.length > 0) { + const found = findRoleInTree(node.roleChildren, id); + if (found) { + return found; + } + } + } + + return null; +} diff --git a/core-web/libs/portlets/dot-roles/src/lib/models/dot-roles.models.ts b/core-web/libs/portlets/dot-roles/src/lib/models/dot-roles.models.ts index d8d754770ff1..3d5c23d9bfb8 100644 --- a/core-web/libs/portlets/dot-roles/src/lib/models/dot-roles.models.ts +++ b/core-web/libs/portlets/dot-roles/src/lib/models/dot-roles.models.ts @@ -1,6 +1,13 @@ /** - * Tree node used in the roles panel. Parent roles render with a folder icon - * (they have children); leaf roles render with a shield icon. + * Shape returned by `GET /v1/roles` and `GET /v1/roles/{roleid}` — mirrors + * the backend `RoleView`. The wire response is **nested**: each node carries + * its direct children under `roleChildren`. The backend loads only 2 levels + * per request, so grandchildren come back as `roleChildren: []` even when + * they exist. The store lazy-loads deeper levels on `onNodeExpand` in the + * roles tree. + * + * `user: true` marks the role as an individual user-role (roleKey = userId). + * User-roles are always leaves in the tree. */ export interface DotRoleNode { readonly id: string; @@ -9,22 +16,20 @@ export interface DotRoleNode { readonly parent?: string; readonly system?: boolean; readonly locked?: boolean; - readonly userCount?: number; - readonly children?: DotRoleNode[]; -} - -/** - * Full role detail. Extends the tree node with the fields shown / edited - * in the Add / Edit role dialogs. - */ -export interface DotRoleDetail extends DotRoleNode { - readonly description?: string; + readonly user?: boolean; readonly editUsers?: boolean; readonly editPermissions?: boolean; readonly editLayouts?: boolean; + /** Direct children — populated by `/v1/roles?loadChildrenRoles=true`. */ + readonly roleChildren?: DotRoleNode[]; +} + +/** Full role detail. Same shape as `DotRoleNode` today. */ +export type DotRoleDetail = DotRoleNode & { + readonly description?: string; readonly DBFQN?: string; readonly FQN?: string; -} +}; /** * Payload for POST /v1/roles (RoleForm). @@ -41,15 +46,17 @@ export interface DotRoleFormValue { description?: string; } -/** Member of a role, annotated with the role that granted access. */ +/** + * User row rendered in the Users tab table. Sourced from + * `/v1/users/filter?roleKey=X` — that endpoint returns users granted the + * given role (direct grants only; inherited grants are not covered today — + * see the follow-up backend hardening item). + */ export interface DotRoleMember { readonly userId: string; readonly firstName: string; readonly lastName: string; readonly emailAddress: string; - /** roleId that granted membership (self = direct; ancestor id = inherited) */ - readonly grantedFromRoleId: string; - readonly grantedFromRoleName: string; } export type DotRoleTab = 'users' | 'permissions' | 'tools'; diff --git a/core-web/libs/portlets/dot-roles/src/lib/services/dot-roles-portlet.service.ts b/core-web/libs/portlets/dot-roles/src/lib/services/dot-roles-portlet.service.ts index c1e577001cfb..574169b64ada 100644 --- a/core-web/libs/portlets/dot-roles/src/lib/services/dot-roles-portlet.service.ts +++ b/core-web/libs/portlets/dot-roles/src/lib/services/dot-roles-portlet.service.ts @@ -7,20 +7,31 @@ import { map } from 'rxjs/operators'; import { DotCMSResponse } from '@dotcms/dotcms-models'; -import { - DotRoleDetail, - DotRoleFormValue, - DotRoleMember, - DotRoleNode -} from '../models/dot-roles.models'; +import { DotRoleDetail, DotRoleFormValue, DotRoleNode } from '../models/dot-roles.models'; + +/** + * User row shape returned by `/v1/users/filter?roleKey=X`. The endpoint + * accepts `roleKey` (not `roleId`) as the filter parameter. Same wire + * format used by the dot-users portlet. + */ +export interface DotRoleUserFilterResult { + readonly userId: string; + readonly firstName?: string; + readonly lastName?: string; + readonly emailAddress?: string; +} + +/** Row shape from `/v1/roles/{roleId}/rolehierarchyanduserroles`. */ +interface RoleHierarchyEntry { + readonly id: string; + readonly name?: string; + readonly roleKey?: string; + readonly user?: boolean; +} /** * Portlet-scoped data access for the Roles and Tools Angular Beta. * - * The shared `DotRolesService` under `@dotcms/data-access` covers the - * legacy read paths used by other portlets (roles-per-user hierarchy). - * This service owns the endpoints the Roles portlet specifically consumes. - * * Blocked write flows (Edit / Delete role, Grant / Remove user) are called * out in the individual methods; they resolve to the dedicated v1 endpoints * once #36936, #36937, #36938, #36939 land. @@ -29,14 +40,22 @@ import { export class DotRolesPortletService { #http = inject(HttpClient); - /** GET /v1/roles — root roles (optionally with first-level children). */ + /** + * GET /v1/roles — root roles + their direct children. + * The backend only fills 2 levels; deeper levels are lazy-loaded per + * expand via `loadRoleById`. + */ loadRootRoles(loadChildren = true): Observable { return this.#http .get>(`/api/v1/roles?loadChildrenRoles=${loadChildren}`) .pipe(map((response) => response.entity ?? [])); } - /** GET /v1/roles/{roleId} — role detail (optionally expand a subtree). */ + /** + * GET /v1/roles/{roleId} — role detail with its direct children. + * Used both to populate the role detail area on selection and to + * lazy-load grandchildren when the roles tree expands a node. + */ loadRoleById(roleId: string, loadChildren = true): Observable { return this.#http .get< @@ -46,18 +65,57 @@ export class DotRolesPortletService { } /** - * GET /v1/roles/{roleId}/rolehierarchyanduserroles — members of the role - * annotated with inheritance metadata so the Users tab can render the - * `GRANTED FROM` chip. + * GET /v1/users/filter?roleKey=X — users granted the given role. + * + * Fast path (used when the selected role has a `roleKey`). Returns + * users with email/name in a single call. The endpoint requires a + * `roleKey` — roles created via the UI without one need the id-based + * fallback below. */ - loadRoleMembers(roleId: string): Observable { + loadRoleMembersByKey(roleKey: string): Observable { + const url = `/api/v1/users/filter?roleKey=${encodeURIComponent(roleKey)}`; + return this.#http - .get< - DotCMSResponse - >(`/api/v1/roles/${roleId}/rolehierarchyanduserroles`) + .get>(url) .pipe(map((response) => response.entity ?? [])); } + /** + * GET /v1/roles/{roleId}/rolehierarchyanduserroles — fallback used when + * the selected role has no `roleKey`. The endpoint returns a mixed list + * of Role objects: the role itself (or its ancestors when + * `roleHierarchyForAssign=true`), and one entry per user assigned, + * where `role.user === true` and `role.roleKey` holds the userId. + * + * We filter for user-roles and map to `DotRoleUserFilterResult`. The + * response does not carry email — the endpoint returns Role objects, + * not User objects — so members loaded via this path show empty email. + * A follow-up ticket will add id-based user filtering upstream so we + * can retire this fallback. + */ + loadRoleMembersById(roleId: string): Observable { + const url = `/api/v1/roles/${encodeURIComponent( + roleId + )}/rolehierarchyanduserroles?roleHierarchyForAssign=false`; + + return this.#http.get>(url).pipe( + map((response) => { + const entries = response.entity ?? []; + return entries + .filter((entry) => entry.user === true) + .map((entry) => { + const [firstName = '', ...rest] = (entry.name ?? '').split(' '); + return { + userId: entry.roleKey ?? entry.id, + firstName, + lastName: rest.join(' '), + emailAddress: '' + }; + }); + }) + ); + } + /** POST /v1/roles — create role (Add Role dialog). */ createRole(form: DotRoleFormValue): Observable { return this.#http diff --git a/dotCMS/src/main/webapp/WEB-INF/messages/Language.properties b/dotCMS/src/main/webapp/WEB-INF/messages/Language.properties index 6be0fbf77fc9..b0ca0aba0b9a 100644 --- a/dotCMS/src/main/webapp/WEB-INF/messages/Language.properties +++ b/dotCMS/src/main/webapp/WEB-INF/messages/Language.properties @@ -7514,6 +7514,7 @@ roles.form.tools=Tools roles.form.description=Description roles.users.grant=Grant to User roles.users.grant.blocked=Granting requires POST /api/v1/roles/{roleId}/users/{userId} (issue #36937). Search works; the grant is not persisted yet. +roles.users.cannot-grant=Users cannot be assigned to this Role. Verify that Users is selected in the Can Grant section of the Role properties. roles.users.search.placeholder=Search users roles.users.remove=Remove roles.users.remove.blocked=Bulk remove requires DELETE /api/v1/roles/{roleId}/users (issue #36938). From 820f154b348e9d039ec93a1860ea2254b3de6959 Mon Sep 17 00:00:00 2001 From: hmoreras <31667212+hmoreras@users.noreply.github.com> Date: Fri, 14 Aug 2026 17:31:28 -0600 Subject: [PATCH 03/20] fix(dot-roles): show inherited users with Granted From column (#36930) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a parent role is selected, the Users tab now lists members granted directly to that role and to any of its ancestors, matching the Dojo portlet behavior (dotCMS role grants flow downward — a user granted Publisher / Legal is also a member of Reviewer, Contributor, and every descendant). Each row is tagged with the closest ancestor where the user was directly granted; that tag drives the new "Granted From" column and disables the remove checkbox on inherited rows (removal has to happen at the ancestor). ## Store `loadMembers` now walks the ancestor chain in `state.roles` via the `parent` id (up to a 20-deep guard against pathological data), fires one `/v1/users/filter?roleKey=X` per role in `forkJoin`, and merges results into a `Map` where first-in wins. Because the chain is ordered `[selected, parent, ..., root]`, direct grants override inherited entries when a user is granted at more than one level. Roles without a `roleKey` fall back to the id-based path documented in the service — the fallback returns no email today; a follow-up backend ticket (#37070) will add a dedicated `GET /v1/roles/{roleId}/users` returning `List` so we can retire the workaround. Per-request `catchError` recovers to an empty batch instead of aborting the whole load, so one failing ancestor call no longer nukes the tab. ## Users tab `DotRoleMember` regains `grantedFromRoleId` / `grantedFromRoleName`. The table gains a "Granted From" column rendered as a `p-tag` (`info` severity for direct rows, `secondary` for inherited). `p-tableCheckbox` is disabled on inherited rows and `onSelectionChange` filters those out defensively so the header checkbox can't select rows the admin can't remove from here. ## Tests Store spec covers: ancestor walk + tagging, dedup with closest-ancestor priority when a user is granted at multiple levels, graceful partial failure on ancestor call error. Users tab spec updated for the enriched `DotRoleMember` shape and the new `selectedRoleId` mock dependency. 55 tests green, lint / format:check / prod build clean. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../dot-role-users-tab.component.html | 16 ++- .../dot-role-users-tab.component.spec.ts | 5 +- .../dot-role-users-tab.component.ts | 15 +- .../store/dot-roles.store.spec.ts | 51 ++++++- .../dot-roles-page/store/dot-roles.store.ts | 130 ++++++++++++++---- .../src/lib/models/dot-roles.models.ts | 14 +- .../lib/services/dot-roles-portlet.service.ts | 7 +- 7 files changed, 204 insertions(+), 34 deletions(-) diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.html b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.html index 336b4e06fac9..b1771b1feeab 100644 --- a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.html +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.html @@ -94,15 +94,29 @@ {{ 'roles.users.column.name' | dm }} {{ 'roles.users.column.email' | dm }} + {{ 'roles.users.column.granted-from' | dm }} + @let direct = isDirectGrant(member); - + + {{ member.firstName }} {{ member.lastName }} {{ member.emailAddress || '—' }} + + + diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.spec.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.spec.ts index 67a2789e2274..c8c27d09ae35 100644 --- a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.spec.ts +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.spec.ts @@ -44,6 +44,7 @@ describe('DotRoleUsersTabComponent', () => { roleKey: 'eco', editUsers: true }), + selectedRoleId: jest.fn().mockReturnValue('r-eco'), canGrantUsers: jest.fn().mockReturnValue(true), setSelectedMembers: jest.fn(), loadMembers: jest.fn() @@ -70,7 +71,9 @@ describe('DotRoleUsersTabComponent', () => { userId: 'u-1', firstName: 'Alan', lastName: 'Cruz', - emailAddress: 'alan.cruz@dotcms.com' + emailAddress: 'alan.cruz@dotcms.com', + grantedFromRoleId: 'r-eco', + grantedFromRoleName: 'Eco Role' } ]); spectator.detectChanges(); diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.ts index 542b0ba5a243..0ef3da9a5fc8 100644 --- a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.ts +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-users-tab/dot-role-users-tab.component.ts @@ -99,8 +99,21 @@ export class DotRoleUsersTabComponent { ); } + /** + * A member row is directly granted to the currently-selected role + * (as opposed to inherited from an ancestor) when its + * `grantedFromRoleId` matches the selected role. Only direct rows + * are removable from this tab. + */ + protected isDirectGrant(member: DotRoleMember): boolean { + return member.grantedFromRoleId === this.store.selectedRoleId(); + } + protected onSelectionChange(members: DotRoleMember[]): void { - this.store.setSelectedMembers(members); + // Filter out inherited rows in case a user managed to check one + // (e.g., via header checkbox). Only direct grants can be removed. + const direct = members.filter((m) => this.isDirectGrant(m)); + this.store.setSelectedMembers(direct); } #getUserSuggestions(query: string): Observable { diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.spec.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.spec.ts index c760c3b032db..b2f12ec5cdd8 100644 --- a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.spec.ts +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.spec.ts @@ -218,14 +218,61 @@ describe('DotRolesStore', () => { expect(store.members()).toHaveLength(2); }); - it('should set membersStatus to error and delegate on failure', () => { + it('should walk the ancestor chain, tag each user with grantedFrom, and prefer the closest ancestor on duplicates', () => { + store.loadRootRoles(); + // r-eco lives under r-categories in MOCK_NESTED_ROLES, so the + // chain expected here is [r-eco, r-categories]. + service.loadRoleMembersByKey.mockImplementation((roleKey: string) => { + if (roleKey === 'eco') { + return of([ + { userId: 'u-1', firstName: 'Alan', lastName: 'Cruz', emailAddress: 'a@x' } + ]); + } + if (roleKey === 'Categories') { + return of([ + { + userId: 'u-2', + firstName: 'Chris', + lastName: 'Publisher', + emailAddress: 'c@x' + }, + // u-1 is granted at BOTH r-eco and r-categories — the + // direct grant on r-eco must win over the inherited one. + { userId: 'u-1', firstName: 'Alan', lastName: 'Cruz', emailAddress: 'a@x' } + ]); + } + + return of([]); + }); + + store.selectRole('r-eco'); + store.loadMembers({ id: 'r-eco', roleKey: 'eco' }); + + expect(service.loadRoleMembersByKey).toHaveBeenCalledWith('eco'); + expect(service.loadRoleMembersByKey).toHaveBeenCalledWith('Categories'); + + const members = store.members(); + expect(members).toHaveLength(2); + + const alan = members.find((m) => m.userId === 'u-1'); + const chris = members.find((m) => m.userId === 'u-2'); + expect(alan?.grantedFromRoleId).toBe('r-eco'); + expect(alan?.grantedFromRoleName).toBe('Eco Role'); + expect(chris?.grantedFromRoleId).toBe('r-categories'); + expect(chris?.grantedFromRoleName).toBe('Categories'); + }); + + it('should delegate to httpErrorManager and continue when one ancestor call fails', () => { const errorManager = spectator.inject(DotHttpErrorManagerService); service.loadRoleMembersByKey.mockReturnValueOnce(throwError(() => new Error('boom'))); store.loadMembers(ROLE_BY_KEY); - expect(store.membersStatus()).toBe('error'); + // Partial failure of one ancestor call must not nuke the whole + // tab: the store surfaces the error via the http manager but + // still resolves to `loaded` with whatever succeeded. expect(errorManager.handle).toHaveBeenCalled(); + expect(store.membersStatus()).toBe('loaded'); }); }); diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.ts index e0639829d1bf..b6f56c73a602 100644 --- a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.ts +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/store/dot-roles.store.ts @@ -1,10 +1,10 @@ import { patchState, signalStore, withComputed, withMethods, withState } from '@ngrx/signals'; import { rxMethod } from '@ngrx/signals/rxjs-interop'; -import { EMPTY, pipe } from 'rxjs'; +import { EMPTY, forkJoin, of, pipe } from 'rxjs'; import { computed, inject } from '@angular/core'; -import { catchError, switchMap, tap } from 'rxjs/operators'; +import { catchError, map, switchMap, tap } from 'rxjs/operators'; import { DotHttpErrorManagerService } from '@dotcms/data-access'; @@ -155,31 +155,80 @@ export const DotRolesStore = signalStore( }, /** - * Load members for the currently selected role. Called by the - * Users tab component whenever the selected role changes. + * Load members for the currently selected role — including + * users granted to any ancestor of the role (dotCMS inherits + * grants downward, so a Reviewer's user list includes users + * granted Publisher / Legal even though those users were never + * granted Reviewer directly). * - * Path selection: - * - If the role has a `roleKey`, use `/v1/users/filter?roleKey=X` - * — fast, returns email and full name in one call. - * - Otherwise, fall back to `/rolehierarchyanduserroles` and - * parse user-roles from the response. That path is missing - * email today because the endpoint returns Role objects, not - * User objects (see `DotRolesPortletService.loadRoleMembersById`). + * Implementation: walks the ancestor chain in `state.roles` via + * `parent` id, fires one `/v1/users/filter?roleKey=X` per role + * in parallel (falling back to the id-based endpoint when a + * role has no `roleKey`), and merges results. Each user is + * tagged with the closest ancestor where they were directly + * granted (selected role first, then parent, grandparent, ...), + * so the Users tab can render the "Granted From" chip and + * disable removal on inherited rows. + * + * TODO: collapse this whole flow into a single call to + * `GET /v1/roles/{roleId}/users` once #37070 ships. That + * endpoint will do the ancestor walk + user enrichment + * (including email) server-side. */ loadMembers(role: { id: string; roleKey?: string | null }): void { + const chain = collectAncestorChain(store.roles(), role); + if (chain.length === 0) { + patchState(store, { members: [], membersStatus: 'loaded' }); + + return; + } + patchState(store, { membersStatus: 'loading' }); - const request$ = role.roleKey - ? service.loadRoleMembersByKey(role.roleKey) - : service.loadRoleMembersById(role.id); - request$.subscribe({ - next: (users) => { - const members: DotRoleMember[] = users.map((u) => ({ - userId: u.userId, - firstName: u.firstName ?? '', - lastName: u.lastName ?? '', - emailAddress: u.emailAddress ?? '' - })); - patchState(store, { members, membersStatus: 'loaded' }); + + const requests = chain.map((node) => { + const source$ = node.roleKey + ? service.loadRoleMembersByKey(node.roleKey) + : service.loadRoleMembersById(node.id); + + return source$.pipe( + map((users) => + users.map((u) => ({ + userId: u.userId, + firstName: u.firstName ?? '', + lastName: u.lastName ?? '', + emailAddress: u.emailAddress ?? '', + grantedFromRoleId: node.id, + grantedFromRoleName: node.name + })) + ), + catchError((error) => { + // Fail one ancestor gracefully — don't abort the + // whole load if a single call errors out. + httpErrorManager.handle(error); + + return of([]); + }) + ); + }); + + forkJoin(requests).subscribe({ + next: (batches) => { + // Dedup: first insertion wins. Chain is ordered + // selected → parent → ..., so the closest ancestor + // is the one that survives when a user is granted + // at more than one level. + const byUserId = new Map(); + for (const batch of batches) { + for (const member of batch) { + if (!byUserId.has(member.userId)) { + byUserId.set(member.userId, member); + } + } + } + patchState(store, { + members: Array.from(byUserId.values()), + membersStatus: 'loaded' + }); }, error: (error) => { httpErrorManager.handle(error); @@ -352,6 +401,41 @@ function appendChildToParent( }); } +/** + * Build the ancestor chain for a role, ordered `[role, parent, grandparent, + * ..., root]`. Matches the Java `RoleAPI.findRoleHierarchy` semantics (a + * self-referential `parent === id` marks the root). The chain drives the + * parallel `/v1/users/filter?roleKey=X` fan-out in `loadMembers`. + */ +function collectAncestorChain( + tree: DotRoleNode[], + role: { id: string; roleKey?: string | null } +): DotRoleNode[] { + const start = findRoleInTree(tree, role.id) ?? { + id: role.id, + name: role.id, + roleKey: role.roleKey ?? undefined + }; + const chain: DotRoleNode[] = [start]; + let cursor: DotRoleNode | null = start; + // Guard against pathological data — hierarchies deeper than 20 aren't + // realistic in practice, and this stops any accidental cycles cold. + for (let i = 0; i < 20; i++) { + const parentId = cursor.parent; + if (!parentId || parentId === cursor.id) { + break; + } + const parentNode = findRoleInTree(tree, parentId); + if (!parentNode) { + break; + } + chain.push(parentNode); + cursor = parentNode; + } + + return chain; +} + /** Walk the tree looking for a node id. Returns the node or `null`. */ function findRoleInTree(nodes: DotRoleNode[], id: string): DotRoleNode | null { for (const node of nodes) { diff --git a/core-web/libs/portlets/dot-roles/src/lib/models/dot-roles.models.ts b/core-web/libs/portlets/dot-roles/src/lib/models/dot-roles.models.ts index 3d5c23d9bfb8..2d19a8c9e838 100644 --- a/core-web/libs/portlets/dot-roles/src/lib/models/dot-roles.models.ts +++ b/core-web/libs/portlets/dot-roles/src/lib/models/dot-roles.models.ts @@ -47,16 +47,22 @@ export interface DotRoleFormValue { } /** - * User row rendered in the Users tab table. Sourced from - * `/v1/users/filter?roleKey=X` — that endpoint returns users granted the - * given role (direct grants only; inherited grants are not covered today — - * see the follow-up backend hardening item). + * User row rendered in the Users tab table. + * + * `grantedFromRoleId` / `grantedFromRoleName` identify the ancestor role + * where the user was directly granted. When it matches the currently- + * selected role, the row is a direct grant and can be removed from this + * tab; when it matches an ancestor, the row is inherited and can only + * be removed by editing the ancestor role. The store walks the ancestor + * chain via `RoleAPI.findRoleHierarchy` semantics to populate this. */ export interface DotRoleMember { readonly userId: string; readonly firstName: string; readonly lastName: string; readonly emailAddress: string; + readonly grantedFromRoleId: string; + readonly grantedFromRoleName: string; } export type DotRoleTab = 'users' | 'permissions' | 'tools'; diff --git a/core-web/libs/portlets/dot-roles/src/lib/services/dot-roles-portlet.service.ts b/core-web/libs/portlets/dot-roles/src/lib/services/dot-roles-portlet.service.ts index 574169b64ada..995c3c8ea320 100644 --- a/core-web/libs/portlets/dot-roles/src/lib/services/dot-roles-portlet.service.ts +++ b/core-web/libs/portlets/dot-roles/src/lib/services/dot-roles-portlet.service.ts @@ -90,8 +90,11 @@ export class DotRolesPortletService { * We filter for user-roles and map to `DotRoleUserFilterResult`. The * response does not carry email — the endpoint returns Role objects, * not User objects — so members loaded via this path show empty email. - * A follow-up ticket will add id-based user filtering upstream so we - * can retire this fallback. + * + * TODO: retire this fallback and the ancestor-walk fan-out in the store + * once `GET /v1/roles/{roleId}/users` ships (issue #37070). That + * endpoint will return `List` with email + granted-from + * metadata in a single call, replacing this whole flow. */ loadRoleMembersById(roleId: string): Observable { const url = `/api/v1/roles/${encodeURIComponent( From 79a2c035bfa41736954aa655d2e28a65acbfd676 Mon Sep 17 00:00:00 2001 From: hmoreras <31667212+hmoreras@users.noreply.github.com> Date: Fri, 14 Aug 2026 17:55:19 -0600 Subject: [PATCH 04/20] feat(dot-roles): permissions tab iframe wrapper JSP (#36930) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Interim per epic #36909 — ship the Roles Beta Permissions tab as an ` diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-permissions-iframe/dot-role-permissions-iframe.component.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-permissions-iframe/dot-role-permissions-iframe.component.ts index fa79f4872e68..1658ff9f4477 100644 --- a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-permissions-iframe/dot-role-permissions-iframe.component.ts +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-permissions-iframe/dot-role-permissions-iframe.component.ts @@ -28,7 +28,7 @@ const PERMISSIONS_WRAPPER_JSP = '/html/portlet/ext/roleadmin/view_role_permissio standalone: true, imports: [DotMessagePipe], templateUrl: './dot-role-permissions-iframe.component.html', - host: { class: 'block h-full min-h-[500px]' } + host: { class: 'block h-full' } }) export class DotRolePermissionsIframeComponent { protected readonly store = inject(DotRolesStore); diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-tools-iframe/dot-role-tools-iframe.component.html b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-tools-iframe/dot-role-tools-iframe.component.html index 06c0b9c45bdc..82c5bb24123f 100644 --- a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-tools-iframe/dot-role-tools-iframe.component.html +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-tools-iframe/dot-role-tools-iframe.component.html @@ -1,6 +1,6 @@ @if ($iframeUrl(); as url) { diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-tools-iframe/dot-role-tools-iframe.component.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-tools-iframe/dot-role-tools-iframe.component.ts index b3220e6562f2..fd08127c7883 100644 --- a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-tools-iframe/dot-role-tools-iframe.component.ts +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/components/dot-role-tools-iframe/dot-role-tools-iframe.component.ts @@ -18,7 +18,7 @@ import { DotRolesStore } from '../../store/dot-roles.store'; standalone: true, imports: [DotMessagePipe], templateUrl: './dot-role-tools-iframe.component.html', - host: { class: 'block h-full min-h-[500px]' } + host: { class: 'block h-full' } }) export class DotRoleToolsIframeComponent { protected readonly store = inject(DotRolesStore); diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.html b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.html index 221c2c0010f3..ca9bb873a0ed 100644 --- a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.html +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.html @@ -30,10 +30,26 @@ - + + @if (store.activeTab() === 'permissions') { + + } - + @if (store.activeTab() === 'tools') { + + } diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.scss b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.scss new file mode 100644 index 000000000000..5a8292bb7179 --- /dev/null +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.scss @@ -0,0 +1,30 @@ +/* + * Force a full-height flex chain down from `` to the tabpanel + * content. Without this, PrimeNG's default tab layout leaves the panels + * at `height: auto` — the permissions/tools iframes then collapse to + * their own fallback `min-height`, which crops the embedded Dojo + * widgets. We can't rely on Tailwind's `!` suffix utilities through + * PrimeNG's `pt` API because newly-added `foo!` class names don't + * always get generated on a running dev server (JIT can miss them). + * + * Plain CSS with `!important` sidesteps that entirely. + */ + +:host ::ng-deep p-tabs.p-tabs { + display: flex !important; + flex: 1 1 auto !important; + flex-direction: column !important; + min-height: 0 !important; +} + +:host ::ng-deep p-tabpanels.p-tabpanels { + display: block !important; + flex: 1 1 auto !important; + min-height: 0 !important; + overflow: hidden !important; +} + +:host ::ng-deep p-tabpanel.p-tabpanel { + display: block !important; + height: 100% !important; +} diff --git a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.ts b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.ts index 489205bd66e9..956128f65ffd 100644 --- a/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.ts +++ b/core-web/libs/portlets/dot-roles/src/lib/dot-roles-page/dot-roles-page.component.ts @@ -28,6 +28,7 @@ import { DotRolesPortletService } from '../services/dot-roles-portlet.service'; ], providers: [DotRolesPortletService, DotRolesStore], templateUrl: './dot-roles-page.component.html', + styleUrl: './dot-roles-page.component.scss', host: { class: 'flex flex-1 min-h-0 block' } }) export class DotRolesPageComponent implements OnInit { @@ -35,10 +36,10 @@ export class DotRolesPageComponent implements OnInit { /** * PassThrough to strip PrimeNG's default padding off the tab panel - * wrappers — the Users tab renders a `p-table` that must reach the - * section edges to align with the panel divider. Tailwind's `!` - * suffix wins the specificity war against PrimeNG's `.p-tabpanels` - * selector. + * wrappers so the Users tab's `p-table` reaches the section edges + * to align with the panel divider. The full-height flex chain is + * enforced in `dot-roles-page.component.scss` — see that file for + * why we don't do it here via `pt`. */ protected readonly tabPanelsPt = { root: { class: 'p-0!' } }; protected readonly tabPanelPt = { root: { class: 'p-0!' } }; diff --git a/dotCMS/src/main/webapp/html/portlet/ext/roleadmin/view_role_iframe_stubs_inc.jsp b/dotCMS/src/main/webapp/html/portlet/ext/roleadmin/view_role_iframe_stubs_inc.jsp new file mode 100644 index 000000000000..b1236dc7d57c --- /dev/null +++ b/dotCMS/src/main/webapp/html/portlet/ext/roleadmin/view_role_iframe_stubs_inc.jsp @@ -0,0 +1,72 @@ +<%-- + Neutralizes the portlet-scoped boot chain that `view_roles_js_inc.jsp` + kicks off when the shared JS is loaded from an iframe wrapper that + renders only ONE widget (permissions or tools). + + The shared file registers several `dojo.addOnLoad` callbacks + unconditionally at include time: + - `buildRolesTree()` — builds the roles tree AND the dijit + `roleTreeMenu` context menu, dereferencing multiple DOM elements + (`noRolesFound`, `rolesTreeWrapper`, ...) and the dijit widget + `roleTreeMenu` (line 222) whose absence produces + `Cannot read properties of undefined (reading 'bindDomNode')`. + - The anonymous users-grid init at line 765 — instantiates a + `dojox.grid.DataGrid` on `usersGrid`. + - `initializePortletInfoList()` — creates a `FilteringSelect` on + `portletList`. + + Two-part strategy: + + 1. Provide hidden DOM stubs for the shared file's `dojo.byId(...)` + targets so the anonymous callbacks (which we cannot override) + don't NPE. + + 2. Override the two NAMED initializers (`buildRolesTree`, + `initializePortletInfoList`) with no-ops in a ` +
+ + diff --git a/dotCMS/src/main/webapp/html/portlet/ext/roleadmin/view_role_permissions_wrapper.jsp b/dotCMS/src/main/webapp/html/portlet/ext/roleadmin/view_role_permissions_wrapper.jsp index 4080d92aa194..03237b868ed4 100644 --- a/dotCMS/src/main/webapp/html/portlet/ext/roleadmin/view_role_permissions_wrapper.jsp +++ b/dotCMS/src/main/webapp/html/portlet/ext/roleadmin/view_role_permissions_wrapper.jsp @@ -37,15 +37,44 @@ <%@ include file="/html/portlet/ext/roleadmin/view_roles_js_inc.jsp" %> <%@ include file="/html/portlet/ext/roleadmin/view_role_permissions_js_inc.jsp" %> +<%-- Hidden DOM stubs to satisfy the shared JS's unconditional + `dojo.addOnLoad` initializers (roles tree, users grid, portlet + select) — see the include file's header for the full rationale. --%> +<%@ include file="/html/portlet/ext/roleadmin/view_role_iframe_stubs_inc.jsp" %> + +<%-- + Match the CSS load-set of the canonical `view_roles.jsp` portlet: + ONLY `view_roles.css`, NOT `view_role_permissions.css`. The latter + file carries a legacy `.dotcms .dijitAccordionTitle{height:23px}` + rule that clips the accordion title and hides the + `hostFolderAccordionPermissionsTitleWrapper` template. The modern + `.permission__list .dijitAccordionTitle{height:auto}` override lives + in `dotcms.css` (already pulled in by `top_inc.jsp`) — leaving + `view_role_permissions.css` OUT lets that override win. +--%> <%-- Renders the `rolePermissionsWrapper` div + `permissionsAccordionContainer` @@ -64,3 +93,12 @@ <% } %> }); + +<%-- + `bottom_inc.jsp` registers `dotMakeBodVisible` on `dojo.addOnLoad` — + without it the `` set by `top_inc.jsp` + is never toggled and nothing renders. It also anti-frame-busts + correctly (only redirects to `/dotAdmin/` when the page is NOT inside + an iframe, which is exactly our embed scenario). +--%> +<%@ include file="/html/common/bottom_inc.jsp" %> diff --git a/dotCMS/src/main/webapp/html/portlet/ext/roleadmin/view_role_tools_wrapper.jsp b/dotCMS/src/main/webapp/html/portlet/ext/roleadmin/view_role_tools_wrapper.jsp index 60504b661a62..3b8a09a6df87 100644 --- a/dotCMS/src/main/webapp/html/portlet/ext/roleadmin/view_role_tools_wrapper.jsp +++ b/dotCMS/src/main/webapp/html/portlet/ext/roleadmin/view_role_tools_wrapper.jsp @@ -34,6 +34,11 @@ <%-- Dojo widgets + DWR RoleAjax bootstrap used by the Tools JS. --%> <%@ include file="/html/portlet/ext/roleadmin/view_roles_js_inc.jsp" %> +<%-- Hidden DOM stubs to satisfy the shared JS's unconditional + `dojo.addOnLoad` initializers (roles tree, users grid) — see the + include file's header for the full rationale. --%> +<%@ include file="/html/portlet/ext/roleadmin/view_role_iframe_stubs_inc.jsp" %> + <%-- Renders the New Layout dialog, Custom Portlet dialog, and the Tool @@ -76,7 +176,36 @@ load: function (role) { currentRoleId = _roleId; currentRole = role; + // Populate the `.view-roles__heading` h3 manually — the + // shared `setRoleName` also touches `displayRoleName1/2` + // which don't exist in this wrapper (they're in the full + // portlet's other tabs); calling it here would NPE. + var nameEl = dojo.byId('displayRoleName3'); + if (nameEl) { + nameEl.innerHTML = (role && role.name) ? role.name : ''; + } loadRoleLayouts(_roleId); + + // dojox.grid.DataGrid measures its header height once at + // `startup()`; in the canonical portlet a dijit TabContainer + // fires `.resize()` on tab activation, which triggers the + // grid to re-layout with a proper header height. This + // wrapper has no TabContainer, so the header stays at + // height 0 (invisible, behind the first data row). Poll + // for the grid dijit and call `.resize()` explicitly as + // soon as it exists — bail out after ~3s in case a BE + // failure means the grid never mounts. + var resizeAttempts = 0; + var resizeInterval = setInterval(function () { + resizeAttempts++; + var grid = dijit.byId('roleLayoutsGrid'); + if (grid) { + grid.resize(); + clearInterval(resizeInterval); + } else if (resizeAttempts > 30) { + clearInterval(resizeInterval); + } + }, 100); }, error: function (err) { console.error('Failed to load role for iframe wrapper', err); From a016e33f8d8e98b0a8cfb0e2e3a73d1ea91fbb71 Mon Sep 17 00:00:00 2001 From: hmoreras <31667212+hmoreras@users.noreply.github.com> Date: Thu, 20 Aug 2026 16:49:14 -0600 Subject: [PATCH 10/20] fix(dot-roles): unbreak New Layout dialog in Tools iframe (#36930) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clicking Create Custom Tool Group / Create Custom Content Tool from the Tools tab threw `RangeError: Maximum call stack size exceeded`, and once the dialog was force-opened its Tools dropdown was empty. Also its form rows collapsed with no cell spacing. Three chained iframe-only bugs: 1. Infinite recursion — `createNewLayout` (`view_roles_js_inc.jsp:1268`) defers to `initializePortletInfoList(createNewLayout)` when the portlet list isn't cached yet, expecting an async DWR fetch. The stubs file overrode `initializePortletInfoList` with a synchronous no-op that just fired the callback, turning that guard into unbounded self-recursion. The override was there to keep the shared file's boot-time `dojo.addOnLoad(initializePortletInfoList)` from failing on a missing `` unconditionally. In the Tools wrapper the same id also exists inside the New Layout dialog markup, and dojox's `initializePortletInfoListCallback` upgrades the FIRST `#portletList` it finds via `dijit.form.FilteringSelect`. The stub comes before the real select in DOM order, so it "won" the widget binding and the real dropdown in the dialog stayed a plain empty `` + is parsed, so `dijit.form.FilteringSelect` would upgrade THE STUB + (first-in-DOM wins for `getElementById`) — leaving the real select + inside the New Layout dialog with no widget and an empty dropdown. + Wrappers that DO need the stub (currently `view_role_permissions_wrapper.jsp`) + should inject their own. --%> diff --git a/dotCMS/src/main/webapp/html/portlet/ext/roleadmin/view_role_permissions_wrapper.jsp b/dotCMS/src/main/webapp/html/portlet/ext/roleadmin/view_role_permissions_wrapper.jsp index 03237b868ed4..ef6a39af5e42 100644 --- a/dotCMS/src/main/webapp/html/portlet/ext/roleadmin/view_role_permissions_wrapper.jsp +++ b/dotCMS/src/main/webapp/html/portlet/ext/roleadmin/view_role_permissions_wrapper.jsp @@ -42,6 +42,15 @@ select) — see the include file's header for the full rationale. --%> <%@ include file="/html/portlet/ext/roleadmin/view_role_iframe_stubs_inc.jsp" %> +<%-- The permissions wrapper does NOT ship a ` + <%-- Match the CSS load-set of the canonical `view_roles.jsp` portlet: ONLY `view_roles.css`, NOT `view_role_permissions.css`. The latter diff --git a/dotCMS/src/main/webapp/html/portlet/ext/roleadmin/view_role_tools_wrapper.jsp b/dotCMS/src/main/webapp/html/portlet/ext/roleadmin/view_role_tools_wrapper.jsp index 25880f24ea0a..a776e02a5edb 100644 --- a/dotCMS/src/main/webapp/html/portlet/ext/roleadmin/view_role_tools_wrapper.jsp +++ b/dotCMS/src/main/webapp/html/portlet/ext/roleadmin/view_role_tools_wrapper.jsp @@ -52,6 +52,17 @@ body { background: #fff; margin: 0; padding: 8px; } #roleToolsWrapper { padding: 0; } + /* `.toolTable` styling lives INLINE in `view_roles.jsp` (lines 60-70), + not in `view_roles.css`, so the New Layout dialog form fields + collapse without any cell spacing in this iframe. Mirror the same + rules here so the dialog matches the canonical portlet. */ + .toolTable { margin: 0 auto; } + .toolTable td { + padding: 10px 8px; + vertical-align: middle; + position: relative; + } + /* * dojox.grid.DataGrid's default layout uses `position: absolute` on * `.dojoxGridHeader` (line 49 of Grid.css) with an inline height set From d50e2f2dcbac39d3f41dc75678d0fa1f76837f97 Mon Sep 17 00:00:00 2001 From: hmoreras <31667212+hmoreras@users.noreply.github.com> Date: Thu, 20 Aug 2026 17:04:39 -0600 Subject: [PATCH 11/20] fix(dot-roles): hide bulk-remove until selection, hide stray FilteringSelect in permissions iframe (#36930) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two small UX fixes for the Angular Beta portlet: - Users tab: the Remove button was always visible but disabled until the admin selected direct-grant rows. Wrap it in `@if ($canBulkRemove())` so it only renders when the store's selection is non-empty — no crowded toolbar for the common case, and the destructive action stops advertising itself when it can't fire. - Permissions iframe: a stray 241px combobox was rendering under the tabs (`#widget_portletList`). The permissions wrapper stubs a ` + stub here so the parser has an element to bind to. + + WRAPPED in a `display:none` container: `display:none` on the + ` + <%-- Match the CSS load-set of the canonical `view_roles.jsp` portlet: From 656d22e3a6e902c6086ec77ba1e2c4d9e603bd2f Mon Sep 17 00:00:00 2001 From: hmoreras <31667212+hmoreras@users.noreply.github.com> Date: Thu, 20 Aug 2026 17:49:39 -0600 Subject: [PATCH 12/20] feat(dot-roles): server-side search + loading skeletons + tree polish (#36930) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Server-side role tree search (was client-side over the loaded cache only, so a match nested under an unexpanded node never surfaced) plus loading skeletons on role selection and Tailwind-only refactors. - Roles tree filter now hits the deprecated-but-functional `GET /api/role/loadbyname/name/{q}/` (only REST surface today doing a deep-tree search — the modern `/v1/roles` endpoint has no filter query yet). Response shape is Dojo's `ItemFileReadStore` legacy format with dashes underscored in ids as a DnD artifact; we adapt it to `DotRoleNode[]`. Search is gated at 3+ chars matching the canonical Dojo portlet, and the tree auto-expands every branch when results are showing so leaf matches are visible without clicking through ancestors - Grant to User popover: replaced the client-side `p-listbox` filter-only flow with a debounced pipe that hits `/api/v1/users/filter?query=X` per keystroke (300ms debounce + `switchMap`) — client-side filter would miss users past the first page for large tenants - Empty state for the roles tree: centered stack with an icon + hint text on top padding, matching the pattern used in dot-tags - Skeleton loading: `dot-roles-detail-header` now shows a circle + two-line + button placeholder while `selectedRoleStatus` is 'loading', and `dot-role-users-tab` shows a five-row table skeleton while either the members list or the role detail is loading. Layouts mirror the loaded state to avoid content-jump - Tree padding: dropped the `