feat(04-01): install new deps + scaffold API test harness with Wave-0 RED stubs
- Add react-router@7, @dnd-kit/core, @dnd-kit/sortable, fractional-indexing to PWA - Add fractional-indexing to API (rank generation server-side) - ioredis NOT added (in-memory EventEmitter per RESEARCH Plan 02 justification) - Create apps/api/test/setup.ts with afterEach DB cleanup for list tables - Wire test.setupFiles in apps/api/vitest.config.ts - Add 4 Wave-0 RED stub test files (LIST-01/02/03/04, D-04, D-11, D-07) - All stubs run as todo, not import-error
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
"@hono/oidc-auth": "1.8.3",
|
"@hono/oidc-auth": "1.8.3",
|
||||||
"@hono/zod-validator": "0.8.0",
|
"@hono/zod-validator": "0.8.0",
|
||||||
"drizzle-orm": "0.45.2",
|
"drizzle-orm": "0.45.2",
|
||||||
|
"fractional-indexing": "^3.2.0",
|
||||||
"hono": "4.12.23",
|
"hono": "4.12.23",
|
||||||
"ical.js": "2.2.1",
|
"ical.js": "2.2.1",
|
||||||
"mysql2": "3.22.4",
|
"mysql2": "3.22.4",
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* Wave-0 RED stubs for listEmitter (in-memory EventEmitter fan-out).
|
||||||
|
*
|
||||||
|
* Covers D-04: SSE fan-out MUST be scoped to who can see a list.
|
||||||
|
* These are pure-unit tests — no DB or HTTP server needed.
|
||||||
|
*
|
||||||
|
* Downstream plans implement the actual listEmitter.ts module that these stubs test.
|
||||||
|
*
|
||||||
|
* Run: pnpm --filter @familysync/api test
|
||||||
|
*/
|
||||||
|
|
||||||
|
describe('listEmitter — scoped fan-out correctness (D-04)', () => {
|
||||||
|
it.todo('publishListEvent emits only to subscribers for the matching listId')
|
||||||
|
it.todo('publishListEvent does NOT emit to subscribers for a different listId')
|
||||||
|
it.todo('subscribeListEvents returns an unsubscribe function that stops future events')
|
||||||
|
it.todo('unsubscribed handler is not called after unsubscribe()')
|
||||||
|
it.todo('multiple subscribers for the same listId all receive the event')
|
||||||
|
it.todo('emitter handles 100+ concurrent subscribers without error (D-18 scale check)')
|
||||||
|
})
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* Wave-0 RED stubs for the lists API router.
|
||||||
|
*
|
||||||
|
* These stubs cover LIST-01 through LIST-04 behavior.
|
||||||
|
* Downstream plans (02/03/06) replace the `it.todo` entries with real assertions
|
||||||
|
* once the routes and DB are wired.
|
||||||
|
*
|
||||||
|
* Security focus: T-04-02 — scoped fan-out (private list events must NOT reach non-owner).
|
||||||
|
*
|
||||||
|
* Run: pnpm --filter @familysync/api test
|
||||||
|
*/
|
||||||
|
|
||||||
|
describe('GET /api/lists — LIST-01: returns only accessible lists', () => {
|
||||||
|
it.todo('returns empty array when user has no lists')
|
||||||
|
it.todo('returns lists owned by the current user')
|
||||||
|
it.todo('returns lists shared with the current user via list_shares')
|
||||||
|
it.todo('does NOT return private lists owned by another user')
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('POST /api/lists — LIST-01: create list', () => {
|
||||||
|
it.todo('creates a list and inserts a list_shares row when isShared=true (D-01)')
|
||||||
|
it.todo('creates a private list with no list_shares row when isShared=false')
|
||||||
|
it.todo('rejects a name longer than 255 characters with 422')
|
||||||
|
it.todo('returns 401 when called without a session')
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('PATCH /api/list-items/:id — LIST-02: per-field update', () => {
|
||||||
|
it.todo('updates only the checked field when patch body is { checked: true } (D-08)')
|
||||||
|
it.todo('updates only the text field when patch body is { text: "..." } (D-08)')
|
||||||
|
it.todo('rejects a patch body with more than one field with 422')
|
||||||
|
it.todo('returns 403 when caller does not own or share the parent list (T-04-02)')
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('PATCH /api/list-items/:id rank — LIST-03: fractional reorder', () => {
|
||||||
|
it.todo('updates the rank field to the new fractional-indexing string')
|
||||||
|
it.todo('rejects an empty rank string with 422')
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('SSE scoped fan-out — LIST-04 / T-04-02: private-list event isolation', () => {
|
||||||
|
it.todo('publishListEvent on a private list does NOT emit to a subscriber for a different list')
|
||||||
|
it.todo('publishListEvent on a shared list emits to all subscribers for that list')
|
||||||
|
})
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* Vitest global test setup for apps/api.
|
||||||
|
*
|
||||||
|
* Establishes shared test infrastructure for API tests:
|
||||||
|
* - DB pool access via the existing client.ts (DB_HOST/DB_NAME from env)
|
||||||
|
* - Per-test cleanup for list tables (truncate between tests so state is isolated)
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* This file is referenced in vitest.config.ts via test.setupFiles.
|
||||||
|
* Pure-logic tests (listEmitter, fractional rank) do NOT require DB — the
|
||||||
|
* cleanup function is a no-op when the tables are empty.
|
||||||
|
*
|
||||||
|
* Environment:
|
||||||
|
* Set DB_HOST, DB_USER, DB_PASSWORD, DB_NAME in the test environment.
|
||||||
|
* Tests run against a local MariaDB dev database; production data is never touched.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { afterEach } from 'vitest'
|
||||||
|
import { db } from '../src/db/client.js'
|
||||||
|
import { lists, listItems, listShares } from '../src/db/schema.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Truncate list tables in FK-safe order after each test.
|
||||||
|
* list_items and list_shares have FK to lists; delete children first.
|
||||||
|
* Called automatically via afterEach — no per-test setup needed.
|
||||||
|
*/
|
||||||
|
afterEach(async () => {
|
||||||
|
try {
|
||||||
|
// Delete child rows first to avoid FK constraint violations
|
||||||
|
await db.delete(listItems)
|
||||||
|
await db.delete(listShares)
|
||||||
|
await db.delete(lists)
|
||||||
|
} catch {
|
||||||
|
// DB may not be available in pure-unit test runs (no DB_HOST configured).
|
||||||
|
// Swallow the error — pure-logic tests do not need cleanup.
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -4,5 +4,6 @@ export default defineConfig({
|
|||||||
test: {
|
test: {
|
||||||
environment: 'node',
|
environment: 'node',
|
||||||
globals: true,
|
globals: true,
|
||||||
|
setupFiles: ['./test/setup.ts'],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
"test": "vitest run"
|
"test": "vitest run"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@dnd-kit/core": "^6.3.1",
|
||||||
|
"@dnd-kit/sortable": "^10.0.0",
|
||||||
"@schedule-x/calendar": "4.6.0",
|
"@schedule-x/calendar": "4.6.0",
|
||||||
"@schedule-x/calendar-controls": "4.6.0",
|
"@schedule-x/calendar-controls": "4.6.0",
|
||||||
"@schedule-x/event-modal": "4.6.0",
|
"@schedule-x/event-modal": "4.6.0",
|
||||||
@@ -18,10 +20,12 @@
|
|||||||
"@schedule-x/react": "4.1.0",
|
"@schedule-x/react": "4.1.0",
|
||||||
"@schedule-x/theme-default": "4.6.0",
|
"@schedule-x/theme-default": "4.6.0",
|
||||||
"@tanstack/react-query": "5.101.0",
|
"@tanstack/react-query": "5.101.0",
|
||||||
|
"fractional-indexing": "^3.2.0",
|
||||||
"ical.js": "2.2.1",
|
"ical.js": "2.2.1",
|
||||||
"lucide-react": "1.17.0",
|
"lucide-react": "1.17.0",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
|
"react-router": "^7.17.0",
|
||||||
"temporal-polyfill": "0.3.2",
|
"temporal-polyfill": "0.3.2",
|
||||||
"vite-plugin-pwa": "^1.3.0",
|
"vite-plugin-pwa": "^1.3.0",
|
||||||
"zustand": "5.0.14"
|
"zustand": "5.0.14"
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* Wave-0 RED stubs for useListSSE hook.
|
||||||
|
*
|
||||||
|
* Covers D-11: bounded (capped exponential) backoff before showing the
|
||||||
|
* "disconnected / updates paused" indicator.
|
||||||
|
*
|
||||||
|
* Tests use a mock EventSource that simulates connect/disconnect scenarios.
|
||||||
|
* Downstream plans implement the actual useListSSE.ts hook.
|
||||||
|
*
|
||||||
|
* Run: pnpm --filter @familysync/pwa test
|
||||||
|
*/
|
||||||
|
|
||||||
|
describe('useListSSE — D-11 bounded backoff', () => {
|
||||||
|
it.todo('starts connected when EventSource fires the open event')
|
||||||
|
it.todo('attempts to reconnect with exponential backoff on error')
|
||||||
|
it.todo('stops retrying after the configured max attempts and sets status to disconnected')
|
||||||
|
it.todo('resets backoff counter on successful reconnect')
|
||||||
|
it.todo('calls onMessage callback with parsed event data when a message arrives')
|
||||||
|
it.todo('cleans up EventSource on unmount')
|
||||||
|
})
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* Wave-0 RED stubs for ListDetail component.
|
||||||
|
*
|
||||||
|
* Covers D-07: optimistic update — the editing member's change shows instantly,
|
||||||
|
* then reconciles against the server (rollback on rejection).
|
||||||
|
*
|
||||||
|
* Downstream plans implement the actual ListDetail.tsx component.
|
||||||
|
*
|
||||||
|
* Run: pnpm --filter @familysync/pwa test
|
||||||
|
*/
|
||||||
|
|
||||||
|
describe('ListDetail — D-07 optimistic update + rollback', () => {
|
||||||
|
it.todo('checking an item immediately updates the UI before server responds')
|
||||||
|
it.todo('unchecking an item immediately updates the UI before server responds')
|
||||||
|
it.todo('rolls back the checked state if the server PATCH returns an error')
|
||||||
|
it.todo('adding an item shows it in the list immediately (optimistic insert)')
|
||||||
|
it.todo('removes the optimistically-added item if the server POST returns an error')
|
||||||
|
it.todo('completed items sink to the "completed" section at the bottom (D-05)')
|
||||||
|
})
|
||||||
Generated
+98
-2
@@ -22,6 +22,9 @@ importers:
|
|||||||
drizzle-orm:
|
drizzle-orm:
|
||||||
specifier: 0.45.2
|
specifier: 0.45.2
|
||||||
version: 0.45.2(mysql2@3.22.4(@types/node@22.19.19))
|
version: 0.45.2(mysql2@3.22.4(@types/node@22.19.19))
|
||||||
|
fractional-indexing:
|
||||||
|
specifier: ^3.2.0
|
||||||
|
version: 3.2.0
|
||||||
hono:
|
hono:
|
||||||
specifier: 4.12.23
|
specifier: 4.12.23
|
||||||
version: 4.12.23
|
version: 4.12.23
|
||||||
@@ -59,6 +62,12 @@ importers:
|
|||||||
|
|
||||||
apps/pwa:
|
apps/pwa:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@dnd-kit/core':
|
||||||
|
specifier: ^6.3.1
|
||||||
|
version: 6.3.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
|
||||||
|
'@dnd-kit/sortable':
|
||||||
|
specifier: ^10.0.0
|
||||||
|
version: 10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)
|
||||||
'@schedule-x/calendar':
|
'@schedule-x/calendar':
|
||||||
specifier: 4.6.0
|
specifier: 4.6.0
|
||||||
version: 4.6.0(@preact/signals@2.9.1(preact@10.29.2))(preact@10.29.2)(temporal-polyfill@0.3.2)
|
version: 4.6.0(@preact/signals@2.9.1(preact@10.29.2))(preact@10.29.2)(temporal-polyfill@0.3.2)
|
||||||
@@ -80,6 +89,9 @@ importers:
|
|||||||
'@tanstack/react-query':
|
'@tanstack/react-query':
|
||||||
specifier: 5.101.0
|
specifier: 5.101.0
|
||||||
version: 5.101.0(react@19.2.7)
|
version: 5.101.0(react@19.2.7)
|
||||||
|
fractional-indexing:
|
||||||
|
specifier: ^3.2.0
|
||||||
|
version: 3.2.0
|
||||||
ical.js:
|
ical.js:
|
||||||
specifier: 2.2.1
|
specifier: 2.2.1
|
||||||
version: 2.2.1
|
version: 2.2.1
|
||||||
@@ -92,6 +104,9 @@ importers:
|
|||||||
react-dom:
|
react-dom:
|
||||||
specifier: ^19.0.0
|
specifier: ^19.0.0
|
||||||
version: 19.2.7(react@19.2.7)
|
version: 19.2.7(react@19.2.7)
|
||||||
|
react-router:
|
||||||
|
specifier: ^7.17.0
|
||||||
|
version: 7.17.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
|
||||||
temporal-polyfill:
|
temporal-polyfill:
|
||||||
specifier: 0.3.2
|
specifier: 0.3.2
|
||||||
version: 0.3.2
|
version: 0.3.2
|
||||||
@@ -685,6 +700,28 @@ packages:
|
|||||||
resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==}
|
resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
'@dnd-kit/accessibility@3.1.1':
|
||||||
|
resolution: {integrity: sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>=16.8.0'
|
||||||
|
|
||||||
|
'@dnd-kit/core@6.3.1':
|
||||||
|
resolution: {integrity: sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>=16.8.0'
|
||||||
|
react-dom: '>=16.8.0'
|
||||||
|
|
||||||
|
'@dnd-kit/sortable@10.0.0':
|
||||||
|
resolution: {integrity: sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==}
|
||||||
|
peerDependencies:
|
||||||
|
'@dnd-kit/core': ^6.3.0
|
||||||
|
react: '>=16.8.0'
|
||||||
|
|
||||||
|
'@dnd-kit/utilities@3.2.2':
|
||||||
|
resolution: {integrity: sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>=16.8.0'
|
||||||
|
|
||||||
'@drizzle-team/brocli@0.10.2':
|
'@drizzle-team/brocli@0.10.2':
|
||||||
resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==}
|
resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==}
|
||||||
|
|
||||||
@@ -1773,6 +1810,10 @@ packages:
|
|||||||
convert-source-map@2.0.0:
|
convert-source-map@2.0.0:
|
||||||
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
|
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
|
||||||
|
|
||||||
|
cookie@1.1.1:
|
||||||
|
resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
core-js-compat@3.49.0:
|
core-js-compat@3.49.0:
|
||||||
resolution: {integrity: sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==}
|
resolution: {integrity: sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==}
|
||||||
|
|
||||||
@@ -2057,6 +2098,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
|
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
|
|
||||||
|
fractional-indexing@3.2.0:
|
||||||
|
resolution: {integrity: sha512-PcOxmqwYCW7O2ovKRU8OoQQj2yqTfEB/yeTYk4gPid6dN5ODRfU1hXd9tTVZzax/0NkO7AxpHykvZnT1aYp/BQ==}
|
||||||
|
engines: {node: ^14.13.1 || >=16.0.0}
|
||||||
|
|
||||||
fs-extra@9.1.0:
|
fs-extra@9.1.0:
|
||||||
resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==}
|
resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -2589,6 +2634,16 @@ packages:
|
|||||||
resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==}
|
resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
react-router@7.17.0:
|
||||||
|
resolution: {integrity: sha512-FDELK7rTMlCHO5+reyXsPlmfr7N1F91lPHsWYfMEGQm/KQ+F4JFM8jGoeQDmDvdTs93Fw9aSilH+uKRb4/jXvQ==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>=18'
|
||||||
|
react-dom: '>=18'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
react-dom:
|
||||||
|
optional: true
|
||||||
|
|
||||||
react@19.2.7:
|
react@19.2.7:
|
||||||
resolution: {integrity: sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==}
|
resolution: {integrity: sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -2682,6 +2737,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==}
|
resolution: {integrity: sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==}
|
||||||
engines: {node: '>=20.0.0'}
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
|
set-cookie-parser@2.7.2:
|
||||||
|
resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==}
|
||||||
|
|
||||||
set-function-length@1.2.2:
|
set-function-length@1.2.2:
|
||||||
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
|
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -3880,6 +3938,31 @@ snapshots:
|
|||||||
|
|
||||||
'@csstools/css-tokenizer@3.0.4': {}
|
'@csstools/css-tokenizer@3.0.4': {}
|
||||||
|
|
||||||
|
'@dnd-kit/accessibility@3.1.1(react@19.2.7)':
|
||||||
|
dependencies:
|
||||||
|
react: 19.2.7
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@dnd-kit/core@6.3.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7)':
|
||||||
|
dependencies:
|
||||||
|
'@dnd-kit/accessibility': 3.1.1(react@19.2.7)
|
||||||
|
'@dnd-kit/utilities': 3.2.2(react@19.2.7)
|
||||||
|
react: 19.2.7
|
||||||
|
react-dom: 19.2.7(react@19.2.7)
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@dnd-kit/sortable@10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)':
|
||||||
|
dependencies:
|
||||||
|
'@dnd-kit/core': 6.3.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
|
||||||
|
'@dnd-kit/utilities': 3.2.2(react@19.2.7)
|
||||||
|
react: 19.2.7
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@dnd-kit/utilities@3.2.2(react@19.2.7)':
|
||||||
|
dependencies:
|
||||||
|
react: 19.2.7
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@drizzle-team/brocli@0.10.2': {}
|
'@drizzle-team/brocli@0.10.2': {}
|
||||||
|
|
||||||
'@emnapi/core@1.10.0':
|
'@emnapi/core@1.10.0':
|
||||||
@@ -4660,6 +4743,8 @@ snapshots:
|
|||||||
|
|
||||||
convert-source-map@2.0.0: {}
|
convert-source-map@2.0.0: {}
|
||||||
|
|
||||||
|
cookie@1.1.1: {}
|
||||||
|
|
||||||
core-js-compat@3.49.0:
|
core-js-compat@3.49.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
browserslist: 4.28.2
|
browserslist: 4.28.2
|
||||||
@@ -4959,6 +5044,8 @@ snapshots:
|
|||||||
cross-spawn: 7.0.6
|
cross-spawn: 7.0.6
|
||||||
signal-exit: 4.1.0
|
signal-exit: 4.1.0
|
||||||
|
|
||||||
|
fractional-indexing@3.2.0: {}
|
||||||
|
|
||||||
fs-extra@9.1.0:
|
fs-extra@9.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
at-least-node: 1.0.0
|
at-least-node: 1.0.0
|
||||||
@@ -5459,6 +5546,14 @@ snapshots:
|
|||||||
|
|
||||||
react-refresh@0.17.0: {}
|
react-refresh@0.17.0: {}
|
||||||
|
|
||||||
|
react-router@7.17.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7):
|
||||||
|
dependencies:
|
||||||
|
cookie: 1.1.1
|
||||||
|
react: 19.2.7
|
||||||
|
set-cookie-parser: 2.7.2
|
||||||
|
optionalDependencies:
|
||||||
|
react-dom: 19.2.7(react@19.2.7)
|
||||||
|
|
||||||
react@19.2.7: {}
|
react@19.2.7: {}
|
||||||
|
|
||||||
redent@3.0.0:
|
redent@3.0.0:
|
||||||
@@ -5605,6 +5700,8 @@ snapshots:
|
|||||||
|
|
||||||
serialize-javascript@7.0.5: {}
|
serialize-javascript@7.0.5: {}
|
||||||
|
|
||||||
|
set-cookie-parser@2.7.2: {}
|
||||||
|
|
||||||
set-function-length@1.2.2:
|
set-function-length@1.2.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
define-data-property: 1.1.4
|
define-data-property: 1.1.4
|
||||||
@@ -5805,8 +5902,7 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
tslib@2.8.1:
|
tslib@2.8.1: {}
|
||||||
optional: true
|
|
||||||
|
|
||||||
tsx@4.22.4:
|
tsx@4.22.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
Reference in New Issue
Block a user