diff --git a/.changeset/olive-pens-draw.md b/.changeset/olive-pens-draw.md new file mode 100644 index 00000000..12b126f7 --- /dev/null +++ b/.changeset/olive-pens-draw.md @@ -0,0 +1,10 @@ +--- +'@tanstack/angular-store': patch +'@tanstack/preact-store': patch +'@tanstack/svelte-store': patch +'@tanstack/react-store': patch +'@tanstack/solid-store': patch +'@tanstack/vue-store': patch +--- + +Fix adapter `shallow` equality for keyless value objects (e.g. Temporal) so updates aren’t skipped. diff --git a/package.json b/package.json index 5af6e0cf..467a5ab0 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "devDependencies": { "@changesets/cli": "^2.29.8", "@eslint-react/eslint-plugin": "^1.53.1", + "@js-temporal/polyfill": "^0.5.1", "@svitejs/changesets-changelog-github-compact": "^1.2.0", "@tanstack/eslint-config": "0.3.3", "@tanstack/typedoc-config": "0.3.1", @@ -60,7 +61,9 @@ "prettier-plugin-svelte": "^3.4.0", "publint": "^0.3.15", "sherif": "^1.9.0", + "temporal-polyfill": "^0.3.0", "tinyglobby": "^0.2.15", + "tsx": "^4.21.0", "typescript": "5.6.3", "typescript50": "npm:typescript@5.0", "typescript51": "npm:typescript@5.1", @@ -79,4 +82,4 @@ "@tanstack/svelte-store": "workspace:*", "@tanstack/vue-store": "workspace:*" } -} +} \ No newline at end of file diff --git a/packages/angular-store/src/index.ts b/packages/angular-store/src/index.ts index 130120a4..bf716889 100644 --- a/packages/angular-store/src/index.ts +++ b/packages/angular-store/src/index.ts @@ -90,6 +90,32 @@ function shallow(objA: T, objB: T) { return true } + /** + * Temporal branding note: + * Temporal types (native or polyfill) define `Symbol.toStringTag` values like + * `"Temporal.PlainDate"` as part of the TC39 Temporal spec, which makes this + * check reliable across realms/polyfills (unlike `instanceof`). + * + * See: + * - https://tc39.es/proposal-temporal/ + * - https://tc39.es/proposal-temporal/docs/plaindate.html + */ + const tagA = getToStringTag(objA) + const tagB = getToStringTag(objB) + const isTemporal = + tagA !== undefined && + tagB !== undefined && + tagA === tagB && + tagA.startsWith('Temporal.') + + if (isTemporal && hasEquals(objA) && hasEquals(objB)) { + try { + return objA.equals(objB) + } catch { + return false + } + } + const keysA = Object.keys(objA) if (keysA.length !== Object.keys(objB).length) { return false @@ -105,3 +131,20 @@ function shallow(objA: T, objB: T) { } return true } + +function hasEquals( + value: TValue, +): value is TValue & { equals: (other: unknown) => boolean } { + return ( + typeof value === 'object' && + value !== null && + 'equals' in (value as object) && + typeof (value as any).equals === 'function' + ) +} + +function getToStringTag(value: unknown): string | undefined { + if (typeof value !== 'object' || value === null) return undefined + const tag = (value as any)[Symbol.toStringTag] + return typeof tag === 'string' ? tag : undefined +} diff --git a/packages/angular-store/tests/index.test.ts b/packages/angular-store/tests/index.test.ts index 17c5e465..0f290e87 100644 --- a/packages/angular-store/tests/index.test.ts +++ b/packages/angular-store/tests/index.test.ts @@ -3,6 +3,7 @@ import { Component, effect } from '@angular/core' import { TestBed } from '@angular/core/testing' import { By } from '@angular/platform-browser' import { Store } from '@tanstack/store' +import { Temporal } from 'temporal-polyfill' import { injectStore } from '../src/index' describe('injectStore', () => { @@ -142,4 +143,52 @@ describe('dataType', () => { debugElement.query(By.css('p#displayStoreVal')).nativeElement.textContent, ).toContain(new Date('2025-03-29T21:06:40.401Z')) }) + + test('temporal change trigger re-render', () => { + const store = new Store({ date: Temporal.PlainDate.from('2025-03-29') }) + + @Component({ + template: ` +
+

{{ storeVal().toString() }}

+ +
+ `, + standalone: true, + }) + class MyCmp { + storeVal = injectStore(store, (state) => state.date) + + constructor() { + effect(() => { + console.log(this.storeVal()) + }) + } + + updateDate() { + store.setState((v) => ({ + ...v, + date: Temporal.PlainDate.from('2025-03-30'), + })) + } + } + + const fixture = TestBed.createComponent(MyCmp) + fixture.detectChanges() + + const debugElement = fixture.debugElement + + expect( + debugElement.query(By.css('p#displayStoreVal')).nativeElement.textContent, + ).toContain('2025-03-29') + + debugElement + .query(By.css('button#updateDate')) + .triggerEventHandler('click', null) + + fixture.detectChanges() + expect( + debugElement.query(By.css('p#displayStoreVal')).nativeElement.textContent, + ).toContain('2025-03-30') + }) }) diff --git a/packages/preact-store/src/index.ts b/packages/preact-store/src/index.ts index 7b2c5bcc..dea75dfc 100644 --- a/packages/preact-store/src/index.ts +++ b/packages/preact-store/src/index.ts @@ -162,6 +162,32 @@ export function shallow(objA: T, objB: T) { return true } + /** + * Temporal branding note: + * Temporal types (native or polyfill) define `Symbol.toStringTag` values like + * `"Temporal.PlainDate"` as part of the TC39 Temporal spec, which makes this + * check reliable across realms/polyfills (unlike `instanceof`). + * + * See: + * - https://tc39.es/proposal-temporal/ + * - https://tc39.es/proposal-temporal/docs/plaindate.html + */ + const tagA = getToStringTag(objA) + const tagB = getToStringTag(objB) + const isTemporal = + tagA !== undefined && + tagB !== undefined && + tagA === tagB && + tagA.startsWith('Temporal.') + + if (isTemporal && hasEquals(objA) && hasEquals(objB)) { + try { + return objA.equals(objB) + } catch { + return false + } + } + const keysA = getOwnKeys(objA) if (keysA.length !== getOwnKeys(objB).length) { return false @@ -169,7 +195,7 @@ export function shallow(objA: T, objB: T) { for (const key of keysA) { if ( - !Object.prototype.hasOwnProperty.call(objB, key as string) || + !Object.prototype.hasOwnProperty.call(objB, key) || !Object.is(objA[key as keyof T], objB[key as keyof T]) ) { return false @@ -178,6 +204,23 @@ export function shallow(objA: T, objB: T) { return true } +function hasEquals( + value: TValue, +): value is TValue & { equals: (other: unknown) => boolean } { + return ( + typeof value === 'object' && + value !== null && + 'equals' in (value as object) && + typeof (value as any).equals === 'function' + ) +} + +function getToStringTag(value: unknown): string | undefined { + if (typeof value !== 'object' || value === null) return undefined + const tag = (value as any)[Symbol.toStringTag] + return typeof tag === 'string' ? tag : undefined +} + function getOwnKeys(obj: object): Array { return (Object.keys(obj) as Array).concat( Object.getOwnPropertySymbols(obj), diff --git a/packages/preact-store/tests/index.test.tsx b/packages/preact-store/tests/index.test.tsx index 06315d51..d5e21e7c 100644 --- a/packages/preact-store/tests/index.test.tsx +++ b/packages/preact-store/tests/index.test.tsx @@ -3,6 +3,7 @@ import { render, waitFor } from '@testing-library/preact' import { Derived, Store } from '@tanstack/store' import { useState } from 'preact/hooks' import { userEvent } from '@testing-library/user-event' +import { Temporal } from 'temporal-polyfill' import { shallow, useStore } from '../src/index' const user = userEvent.setup() @@ -303,4 +304,10 @@ describe('shallow', () => { const objB = new Date('2025-02-10') expect(shallow(objA, objB)).toBe(true) }) + + test('should return false for temporal objects with different values', () => { + const objA = Temporal.PlainDate.from('2025-02-10') + const objB = Temporal.PlainDate.from('2025-02-11') + expect(shallow(objA, objB)).toBe(false) + }) }) diff --git a/packages/react-store/src/index.ts b/packages/react-store/src/index.ts index 21d3a478..cdb7b5df 100644 --- a/packages/react-store/src/index.ts +++ b/packages/react-store/src/index.ts @@ -74,15 +74,41 @@ export function shallow(objA: T, objB: T) { return true } + /** + * Temporal branding note: + * Temporal types (native or polyfill) define `Symbol.toStringTag` values like + * `"Temporal.PlainDate"` as part of the TC39 Temporal spec, which makes this + * check reliable across realms/polyfills (unlike `instanceof`). + * + * See: + * - https://tc39.es/proposal-temporal/ + * - https://tc39.es/proposal-temporal/docs/plaindate.html + */ + const tagA = getToStringTag(objA) + const tagB = getToStringTag(objB) + const isTemporal = + tagA !== undefined && + tagB !== undefined && + tagA === tagB && + tagA.startsWith('Temporal.') + + if (isTemporal && hasEquals(objA) && hasEquals(objB)) { + try { + return objA.equals(objB) + } catch { + return false + } + } + const keysA = getOwnKeys(objA) if (keysA.length !== getOwnKeys(objB).length) { return false } - for (let i = 0; i < keysA.length; i++) { + for (const key of keysA) { if ( - !Object.prototype.hasOwnProperty.call(objB, keysA[i] as string) || - !Object.is(objA[keysA[i] as keyof T], objB[keysA[i] as keyof T]) + !Object.prototype.hasOwnProperty.call(objB, key) || + !Object.is(objA[key as keyof T], objB[key as keyof T]) ) { return false } @@ -90,6 +116,23 @@ export function shallow(objA: T, objB: T) { return true } +function hasEquals( + value: TValue, +): value is TValue & { equals: (other: unknown) => boolean } { + return ( + typeof value === 'object' && + value !== null && + 'equals' in (value as object) && + typeof (value as any).equals === 'function' + ) +} + +function getToStringTag(value: unknown): string | undefined { + if (typeof value !== 'object' || value === null) return undefined + const tag = (value as any)[Symbol.toStringTag] + return typeof tag === 'string' ? tag : undefined +} + function getOwnKeys(obj: object): Array { return (Object.keys(obj) as Array).concat( Object.getOwnPropertySymbols(obj), diff --git a/packages/react-store/tests/index.test.tsx b/packages/react-store/tests/index.test.tsx index 37d1d37c..596a89e8 100644 --- a/packages/react-store/tests/index.test.tsx +++ b/packages/react-store/tests/index.test.tsx @@ -3,6 +3,8 @@ import { render, waitFor } from '@testing-library/react' import { Derived, Store } from '@tanstack/store' import { useState } from 'react' import { userEvent } from '@testing-library/user-event' +import { Temporal as JsTemporal } from '@js-temporal/polyfill' +import { Temporal } from 'temporal-polyfill' import { shallow, useStore } from '../src/index' const user = userEvent.setup() @@ -302,4 +304,16 @@ describe('shallow', () => { const objB = new Date('2025-02-10') expect(shallow(objA, objB)).toBe(true) }) + + test('should return false for temporal objects with different values', () => { + const objA = Temporal.PlainDate.from('2025-02-10') + const objB = Temporal.PlainDate.from('2025-02-11') + expect(shallow(objA, objB)).toBe(false) + }) + + test('supports Temporal from @js-temporal/polyfill', () => { + const objA = JsTemporal.PlainDate.from('2025-02-10') + const objB = JsTemporal.PlainDate.from('2025-02-10') + expect(shallow(objA, objB)).toBe(true) + }) }) diff --git a/packages/solid-store/src/index.tsx b/packages/solid-store/src/index.tsx index 104653b8..0cd26f7d 100644 --- a/packages/solid-store/src/index.tsx +++ b/packages/solid-store/src/index.tsx @@ -81,6 +81,32 @@ export function shallow(objA: T, objB: T) { return true } + /** + * Temporal branding note: + * Temporal types (native or polyfill) define `Symbol.toStringTag` values like + * `"Temporal.PlainDate"` as part of the TC39 Temporal spec, which makes this + * check reliable across realms/polyfills (unlike `instanceof`). + * + * See: + * - https://tc39.es/proposal-temporal/ + * - https://tc39.es/proposal-temporal/docs/plaindate.html + */ + const tagA = getToStringTag(objA) + const tagB = getToStringTag(objB) + const isTemporal = + tagA !== undefined && + tagB !== undefined && + tagA === tagB && + tagA.startsWith('Temporal.') + + if (isTemporal && hasEquals(objA) && hasEquals(objB)) { + try { + return objA.equals(objB) + } catch { + return false + } + } + const keysA = Object.keys(objA) if (keysA.length !== Object.keys(objB).length) { return false @@ -96,3 +122,20 @@ export function shallow(objA: T, objB: T) { } return true } + +function hasEquals( + value: TValue, +): value is TValue & { equals: (other: unknown) => boolean } { + return ( + typeof value === 'object' && + value !== null && + 'equals' in (value as object) && + typeof (value as any).equals === 'function' + ) +} + +function getToStringTag(value: unknown): string | undefined { + if (typeof value !== 'object' || value === null) return undefined + const tag = (value as any)[Symbol.toStringTag] + return typeof tag === 'string' ? tag : undefined +} diff --git a/packages/solid-store/tests/index.test.tsx b/packages/solid-store/tests/index.test.tsx index 2efa725c..a078fe49 100644 --- a/packages/solid-store/tests/index.test.tsx +++ b/packages/solid-store/tests/index.test.tsx @@ -1,7 +1,8 @@ -import { describe, expect, it } from 'vitest' +import { describe, expect, it, test } from 'vitest' import { render, renderHook } from '@solidjs/testing-library' import { Store } from '@tanstack/store' -import { useStore } from '../src/index' +import { Temporal } from 'temporal-polyfill' +import { shallow, useStore } from '../src/index' describe('useStore', () => { it.todo('allows us to select state using a selector', () => { @@ -53,3 +54,11 @@ describe('useStore', () => { expect(result()).toStrictEqual(new Date('2025-03-29T21:06:40.401Z')) }) }) + +describe('shallow', () => { + test('should return false for temporal objects with different values', () => { + const objA = Temporal.PlainDate.from('2025-02-10') + const objB = Temporal.PlainDate.from('2025-02-11') + expect(shallow(objA, objB)).toBe(false) + }) +}) diff --git a/packages/svelte-store/src/index.svelte.ts b/packages/svelte-store/src/index.svelte.ts index 636dd433..c6318d2f 100644 --- a/packages/svelte-store/src/index.svelte.ts +++ b/packages/svelte-store/src/index.svelte.ts @@ -83,18 +83,61 @@ export function shallow(objA: T, objB: T) { return true } + /** + * Temporal branding note: + * Temporal types (native or polyfill) define `Symbol.toStringTag` values like + * `"Temporal.PlainDate"` as part of the TC39 Temporal spec, which makes this + * check reliable across realms/polyfills (unlike `instanceof`). + * + * See: + * - https://tc39.es/proposal-temporal/ + * - https://tc39.es/proposal-temporal/docs/plaindate.html + */ + const tagA = getToStringTag(objA) + const tagB = getToStringTag(objB) + const isTemporal = + tagA !== undefined && + tagB !== undefined && + tagA === tagB && + tagA.startsWith('Temporal.') + + if (isTemporal && hasEquals(objA) && hasEquals(objB)) { + try { + return objA.equals(objB) + } catch { + return false + } + } + const keysA = Object.keys(objA) if (keysA.length !== Object.keys(objB).length) { return false } - for (let i = 0; i < keysA.length; i++) { + for (const key of keysA) { if ( - !Object.prototype.hasOwnProperty.call(objB, keysA[i] as string) || - !Object.is(objA[keysA[i] as keyof T], objB[keysA[i] as keyof T]) + !Object.prototype.hasOwnProperty.call(objB, key) || + !Object.is(objA[key as keyof T], objB[key as keyof T]) ) { return false } } return true } + +function hasEquals( + value: TValue, +): value is TValue & { equals: (other: unknown) => boolean } { + return ( + typeof value === 'object' && + value !== null && + 'equals' in (value as object) && + typeof (value as any).equals === 'function' + ) +} + +function getToStringTag(value: unknown): string | undefined { + if (typeof value !== 'object' || value === null) return undefined + const tag = (value as any)[Symbol.toStringTag] + return typeof tag === 'string' ? tag : undefined +} diff --git a/packages/svelte-store/tests/index.test.ts b/packages/svelte-store/tests/index.test.ts index 24f7a3dd..ab435952 100644 --- a/packages/svelte-store/tests/index.test.ts +++ b/packages/svelte-store/tests/index.test.ts @@ -1,6 +1,7 @@ import { describe, expect, it, test } from 'vitest' import { render, waitFor } from '@testing-library/svelte' import { userEvent } from '@testing-library/user-event' +import { Temporal } from 'temporal-polyfill' import { shallow } from '../src/index.svelte.js' import TestBaseStore from './BaseStore.test.svelte' import TestRerender from './Render.test.svelte' @@ -91,4 +92,10 @@ describe('shallow', () => { const objB = new Date('2025-02-10') expect(shallow(objA, objB)).toBe(true) }) + + test('should return false for temporal objects with different values', () => { + const objA = Temporal.PlainDate.from('2025-02-10') + const objB = Temporal.PlainDate.from('2025-02-11') + expect(shallow(objA, objB)).toBe(false) + }) }) diff --git a/packages/vue-store/src/index.ts b/packages/vue-store/src/index.ts index 6b2ebd0b..9910cd46 100644 --- a/packages/vue-store/src/index.ts +++ b/packages/vue-store/src/index.ts @@ -87,6 +87,32 @@ export function shallow(objA: T, objB: T) { return true } + /** + * Temporal branding note: + * Temporal types (native or polyfill) define `Symbol.toStringTag` values like + * `"Temporal.PlainDate"` as part of the TC39 Temporal spec, which makes this + * check reliable across realms/polyfills (unlike `instanceof`). + * + * See: + * - https://tc39.es/proposal-temporal/ + * - https://tc39.es/proposal-temporal/docs/plaindate.html + */ + const tagA = getToStringTag(objA) + const tagB = getToStringTag(objB) + const isTemporal = + tagA !== undefined && + tagB !== undefined && + tagA === tagB && + tagA.startsWith('Temporal.') + + if (isTemporal && hasEquals(objA) && hasEquals(objB)) { + try { + return objA.equals(objB) + } catch { + return false + } + } + const keysA = Object.keys(objA) if (keysA.length !== Object.keys(objB).length) { return false @@ -102,3 +128,20 @@ export function shallow(objA: T, objB: T) { } return true } + +function hasEquals( + value: TValue, +): value is TValue & { equals: (other: unknown) => boolean } { + return ( + typeof value === 'object' && + value !== null && + 'equals' in (value as object) && + typeof (value as any).equals === 'function' + ) +} + +function getToStringTag(value: unknown): string | undefined { + if (typeof value !== 'object' || value === null) return undefined + const tag = (value as any)[Symbol.toStringTag] + return typeof tag === 'string' ? tag : undefined +} diff --git a/packages/vue-store/tests/index.test.tsx b/packages/vue-store/tests/index.test.tsx index ebdb3f98..832784fb 100644 --- a/packages/vue-store/tests/index.test.tsx +++ b/packages/vue-store/tests/index.test.tsx @@ -4,6 +4,7 @@ import { defineComponent, h } from 'vue-demi' import { render, waitFor } from '@testing-library/vue' import { Store } from '@tanstack/store' import { userEvent } from '@testing-library/user-event' +import { Temporal } from 'temporal-polyfill' import { shallow, useStore } from '../src/index' const user = userEvent.setup() @@ -168,4 +169,10 @@ describe('shallow', () => { const objB = new Date('2025-02-10') expect(shallow(objA, objB)).toBe(true) }) + + test('should return false for temporal objects with different values', () => { + const objA = Temporal.PlainDate.from('2025-02-10') + const objB = Temporal.PlainDate.from('2025-02-11') + expect(shallow(objA, objB)).toBe(false) + }) }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9fe910cf..5fe9b3e0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: '@eslint-react/eslint-plugin': specifier: ^1.53.1 version: 1.53.1(eslint@9.39.2(jiti@2.6.1))(ts-api-utils@2.1.0(typescript@5.6.3))(typescript@5.6.3) + '@js-temporal/polyfill': + specifier: ^0.5.1 + version: 0.5.1 '@svitejs/changesets-changelog-github-compact': specifier: ^1.2.0 version: 1.2.0(encoding@0.1.13) @@ -71,9 +74,15 @@ importers: sherif: specifier: ^1.9.0 version: 1.9.0 + temporal-polyfill: + specifier: ^0.3.0 + version: 0.3.0 tinyglobby: specifier: ^0.2.15 version: 0.2.15 + tsx: + specifier: ^4.21.0 + version: 4.21.0 typescript: specifier: 5.6.3 version: 5.6.3 @@ -2074,6 +2083,10 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@js-temporal/polyfill@0.5.1': + resolution: {integrity: sha512-hloP58zRVCRSpgDxmqCWJNlizAlUgJFqG2ypq79DCvyv9tHjRYMDOcPFjzfl/A1/YxDvRCZz8wvZvmapQnKwFQ==} + engines: {node: '>=12'} + '@jsonjoy.com/base64@1.1.2': resolution: {integrity: sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==} engines: {node: '>=10.0'} @@ -5450,6 +5463,9 @@ packages: resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true + jsbi@4.3.2: + resolution: {integrity: sha512-9fqMSQbhJykSeii05nxKl4m6Eqn2P6rOlYiS+C5Dr/HPIU/7yZxu5qzbs40tgaFORiw2Amd0mirjxatXYMkIew==} + jsdom@25.0.1: resolution: {integrity: sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==} engines: {node: '>=18'} @@ -7183,10 +7199,18 @@ packages: tar@6.2.1: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me tar@7.5.2: resolution: {integrity: sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==} engines: {node: '>=18'} + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me + + temporal-polyfill@0.3.0: + resolution: {integrity: sha512-qNsTkX9K8hi+FHDfHmf22e/OGuXmfBm9RqNismxBrnSmZVJKegQ+HYYXT+R7Ha8F/YSm2Y34vmzD4cxMu2u95g==} + + temporal-spec@0.3.0: + resolution: {integrity: sha512-n+noVpIqz4hYgFSMOSiINNOUOMFtV5cZQNCmmszA6GiVFVRt3G7AqVyhXjhCSmowvQn+NsGn+jMDMKJYHd3bSQ==} term-size@2.2.1: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} @@ -8000,9 +8024,9 @@ snapshots: tree-kill: 1.2.2 tslib: 2.8.1 typescript: 5.6.3 - webpack: 5.98.0(esbuild@0.25.4) + webpack: 5.98.0 webpack-dev-middleware: 7.4.2(webpack@5.98.0(esbuild@0.25.4)) - webpack-dev-server: 5.2.2(webpack@5.98.0(esbuild@0.25.4)) + webpack-dev-server: 5.2.2(webpack@5.98.0) webpack-merge: 6.0.1 webpack-subresource-integrity: 5.1.0(webpack@5.98.0(esbuild@0.25.4)) optionalDependencies: @@ -8164,7 +8188,7 @@ snapshots: '@babel/helper-split-export-declaration': 7.24.7 '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.10) '@inquirer/confirm': 5.1.6(@types/node@24.9.2) - '@vitejs/plugin-basic-ssl': 1.2.0(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(less@4.2.2)(sass@1.85.0)(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.1)) + '@vitejs/plugin-basic-ssl': 1.2.0(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(less@4.4.2)(sass@1.93.3)(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.1)) beasties: 0.3.2 browserslist: 4.27.0 esbuild: 0.25.4 @@ -9903,6 +9927,10 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@js-temporal/polyfill@0.5.1': + dependencies: + jsbi: 4.3.2 + '@jsonjoy.com/base64@1.1.2(tslib@2.8.1)': dependencies: tslib: 2.8.1 @@ -11176,7 +11204,6 @@ snapshots: '@vitejs/plugin-basic-ssl@1.2.0(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(less@4.4.2)(sass@1.93.3)(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.1))': dependencies: vite: 6.4.1(@types/node@24.9.2)(jiti@2.6.1)(less@4.4.2)(sass@1.93.3)(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.1) - optional: true '@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(less@4.4.2)(sass@1.93.3)(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.1))': dependencies: @@ -13684,6 +13711,8 @@ snapshots: dependencies: argparse: 2.0.1 + jsbi@4.3.2: {} + jsdom@25.0.1: dependencies: cssstyle: 4.6.0 @@ -15685,6 +15714,12 @@ snapshots: minizlib: 3.1.0 yallist: 5.0.0 + temporal-polyfill@0.3.0: + dependencies: + temporal-spec: 0.3.0 + + temporal-spec@0.3.0: {} + term-size@2.2.1: {} terser-webpack-plugin@5.3.14(esbuild@0.25.4)(webpack@5.98.0(esbuild@0.25.4)): @@ -15698,6 +15733,15 @@ snapshots: optionalDependencies: esbuild: 0.25.4 + terser-webpack-plugin@5.3.14(webpack@5.98.0(esbuild@0.25.4)): + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + jest-worker: 27.5.1 + schema-utils: 4.3.3 + serialize-javascript: 6.0.2 + terser: 5.39.0 + webpack: 5.98.0 + terser@5.39.0: dependencies: '@jridgewell/source-map': 0.3.11 @@ -16273,6 +16317,17 @@ snapshots: optionalDependencies: webpack: 5.98.0(esbuild@0.25.4) + webpack-dev-middleware@7.4.2(webpack@5.98.0): + dependencies: + colorette: 2.0.20 + memfs: 4.50.0 + mime-types: 2.1.35 + on-finished: 2.4.1 + range-parser: 1.2.1 + schema-utils: 4.3.3 + optionalDependencies: + webpack: 5.98.0 + webpack-dev-server@5.2.2(webpack@5.98.0(esbuild@0.25.4)): dependencies: '@types/bonjour': 3.5.13 @@ -16311,6 +16366,44 @@ snapshots: - supports-color - utf-8-validate + webpack-dev-server@5.2.2(webpack@5.98.0): + dependencies: + '@types/bonjour': 3.5.13 + '@types/connect-history-api-fallback': 1.5.4 + '@types/express': 4.17.25 + '@types/express-serve-static-core': 4.19.7 + '@types/serve-index': 1.9.4 + '@types/serve-static': 1.15.10 + '@types/sockjs': 0.3.36 + '@types/ws': 8.18.1 + ansi-html-community: 0.0.8 + bonjour-service: 1.3.0 + chokidar: 3.6.0 + colorette: 2.0.20 + compression: 1.8.1 + connect-history-api-fallback: 2.0.0 + express: 4.21.2 + graceful-fs: 4.2.11 + http-proxy-middleware: 2.0.9(@types/express@4.17.25) + ipaddr.js: 2.2.0 + launch-editor: 2.12.0 + open: 10.1.0 + p-retry: 6.2.1 + schema-utils: 4.3.3 + selfsigned: 2.4.1 + serve-index: 1.9.1 + sockjs: 0.3.24 + spdy: 4.0.2 + webpack-dev-middleware: 7.4.2(webpack@5.98.0) + ws: 8.18.3 + optionalDependencies: + webpack: 5.98.0 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + webpack-merge@6.0.1: dependencies: clone-deep: 4.0.1 @@ -16327,6 +16420,36 @@ snapshots: webpack-virtual-modules@0.6.2: optional: true + webpack@5.98.0: + dependencies: + '@types/eslint-scope': 3.7.7 + '@types/estree': 1.0.8 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/wasm-edit': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + acorn: 8.15.0 + browserslist: 4.27.0 + chrome-trace-event: 1.0.4 + enhanced-resolve: 5.18.3 + es-module-lexer: 1.7.0 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.1 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 4.3.3 + tapable: 2.3.0 + terser-webpack-plugin: 5.3.14(webpack@5.98.0(esbuild@0.25.4)) + watchpack: 2.4.4 + webpack-sources: 3.3.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + webpack@5.98.0(esbuild@0.25.4): dependencies: '@types/eslint-scope': 3.7.7