@svgrid/enterprise 2.5.2 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/SvAlertRuleEditor.svelte.d.ts +13 -0
- package/dist/SvAlertsManager.svelte.d.ts +14 -0
- package/dist/SvAlertsPanel.svelte.d.ts +9 -0
- package/dist/SvAuthGate.svelte.d.ts +22 -0
- package/dist/SvBoard.svelte.d.ts +35 -0
- package/dist/SvExportMenu.svelte.d.ts +61 -0
- package/dist/SvExpressionEditor.svelte.d.ts +12 -0
- package/dist/SvFileInput.svelte.d.ts +20 -0
- package/dist/SvGridAlerts.svelte.d.ts +77 -0
- package/dist/SvGridBoard.svelte.d.ts +30 -0
- package/dist/SvGridEditPanel.svelte.d.ts +73 -0
- package/dist/SvGridMasterDetail.svelte.d.ts +49 -0
- package/dist/SvGridScheduler.svelte.d.ts +30 -0
- package/dist/SvImportDialog.svelte.d.ts +88 -0
- package/dist/SvLookupInput.svelte.d.ts +21 -0
- package/dist/SvPivotDesigner.svelte.d.ts +176 -0
- package/dist/SvRecordDetail.svelte.d.ts +58 -0
- package/dist/SvSchedule.svelte.d.ts +29 -0
- package/dist/SvSchemaChart.svelte.d.ts +61 -0
- package/dist/SvSchemaDashboard.svelte.d.ts +46 -0
- package/dist/alerts/alert-engine-attach.d.ts +79 -0
- package/dist/alerts/alert-engine-attach.js +106 -0
- package/dist/alerts/alert-engine.d.ts +42 -0
- package/dist/alerts/alert-engine.js +196 -0
- package/dist/alerts/alert-formats.d.ts +26 -0
- package/dist/alerts/alert-formats.js +58 -0
- package/dist/alerts/alert-observer.d.ts +54 -0
- package/dist/alerts/alert-observer.js +156 -0
- package/dist/alerts/alert-scheduler.d.ts +30 -0
- package/dist/alerts/alert-scheduler.js +54 -0
- package/dist/alerts/alert-storage.d.ts +31 -0
- package/dist/alerts/alert-storage.js +92 -0
- package/dist/alerts/alert-store.svelte.d.ts +24 -0
- package/dist/alerts/alert-store.svelte.js +69 -0
- package/dist/alerts/alert-types.d.ts +86 -0
- package/dist/alerts/alert-types.js +1 -0
- package/dist/alerts.d.ts +2 -0
- package/{src/alerts.ts → dist/alerts.js} +9 -9
- package/dist/board.d.ts +7 -0
- package/{src/board.ts → dist/board.js} +13 -14
- package/dist/cdn/svgrid-enterprise.svelte-external.js +2987 -2981
- package/dist/designer/assets/{index-CM5xvaOy.js → index-BF0UH638.js} +3 -3
- package/dist/designer/assets/{src-D-ET9Mmo.js → src-BPJruwB9.js} +184 -184
- package/dist/designer/index.html +2 -2
- package/dist/edit-panel.d.ts +105 -0
- package/dist/edit-panel.js +350 -0
- package/dist/export-conditional.d.ts +31 -0
- package/dist/export-conditional.js +65 -0
- package/dist/export-ooxml.d.ts +93 -0
- package/dist/export-ooxml.js +385 -0
- package/dist/export-pdf.d.ts +107 -0
- package/dist/export-pdf.js +144 -0
- package/dist/export-print.d.ts +55 -0
- package/dist/export-print.js +91 -0
- package/{src/export-serialize.ts → dist/export-serialize.d.ts} +11 -24
- package/dist/export-serialize.js +11 -0
- package/dist/export-xls.d.ts +26 -0
- package/dist/export-xls.js +157 -0
- package/dist/export.d.ts +323 -0
- package/dist/export.js +1021 -0
- package/dist/expressions/evaluate.d.ts +17 -0
- package/dist/expressions/evaluate.js +214 -0
- package/dist/expressions/expression-columns.d.ts +61 -0
- package/dist/expressions/expression-columns.js +72 -0
- package/dist/expressions/expression-types.d.ts +125 -0
- package/dist/expressions/expression-types.js +1 -0
- package/dist/expressions/parse.d.ts +25 -0
- package/dist/expressions/parse.js +537 -0
- package/dist/import.d.ts +232 -0
- package/dist/import.js +846 -0
- package/dist/index.d.ts +66 -0
- package/dist/index.js +91 -0
- package/dist/install.d.ts +70 -0
- package/dist/install.js +61 -0
- package/dist/license-core.d.ts +37 -0
- package/dist/license-core.js +81 -0
- package/dist/license.d.ts +30 -0
- package/dist/license.js +139 -0
- package/dist/master-detail.d.ts +23 -0
- package/dist/master-detail.js +35 -0
- package/dist/node/studio.js +1 -1
- package/dist/pivot-chart.d.ts +28 -0
- package/dist/pivot-chart.js +71 -0
- package/dist/pivot-designer.d.ts +69 -0
- package/dist/pivot-designer.js +38 -0
- package/dist/pivot-enable.d.ts +6 -0
- package/{src/pivot-enable.ts → dist/pivot-enable.js} +13 -18
- package/dist/pivot.d.ts +111 -0
- package/dist/pivot.js +353 -0
- package/dist/print.d.ts +33 -0
- package/dist/print.js +61 -0
- package/dist/revoked.d.ts +1 -0
- package/{src/revoked.ts → dist/revoked.js} +5 -6
- package/dist/scheduler-assignments.d.ts +64 -0
- package/dist/scheduler-assignments.js +92 -0
- package/dist/scheduler-axis.d.ts +81 -0
- package/dist/scheduler-axis.js +180 -0
- package/{src/scheduler-booking.ts → dist/scheduler-booking.d.ts} +10 -43
- package/dist/scheduler-booking.js +50 -0
- package/dist/scheduler-config.d.ts +177 -0
- package/dist/scheduler-config.js +1 -0
- package/dist/scheduler-dependencies.d.ts +89 -0
- package/dist/scheduler-dependencies.js +179 -0
- package/dist/scheduler-freebusy.d.ts +19 -0
- package/{src/scheduler-freebusy.ts → dist/scheduler-freebusy.js} +9 -19
- package/{src/scheduler-heatmap.ts → dist/scheduler-heatmap.d.ts} +12 -35
- package/dist/scheduler-heatmap.js +41 -0
- package/dist/scheduler-resource-tree.d.ts +48 -0
- package/dist/scheduler-resource-tree.js +78 -0
- package/dist/scheduler-slots.d.ts +37 -0
- package/dist/scheduler-slots.js +80 -0
- package/dist/scheduler-summary.d.ts +41 -0
- package/dist/scheduler-summary.js +54 -0
- package/dist/scheduler.d.ts +7 -0
- package/{src/scheduler.ts → dist/scheduler.js} +13 -14
- package/dist/scheduling.d.ts +132 -0
- package/dist/scheduling.js +228 -0
- package/dist/schema-designer.d.ts +42 -0
- package/dist/schema-designer.js +117 -0
- package/dist/schema.d.ts +369 -0
- package/dist/schema.js +216 -0
- package/dist/smart-shim.d.ts +62 -0
- package/dist/smart-shim.js +34 -0
- package/dist/sources/aggregate.d.ts +43 -0
- package/dist/sources/aggregate.js +60 -0
- package/dist/sources/auth-supabase.d.ts +69 -0
- package/dist/sources/auth-supabase.js +39 -0
- package/dist/sources/dashboard.d.ts +65 -0
- package/dist/sources/dashboard.js +95 -0
- package/dist/sources/field-inference.d.ts +23 -0
- package/dist/sources/field-inference.js +52 -0
- package/dist/sources/filters.d.ts +35 -0
- package/dist/sources/filters.js +52 -0
- package/dist/sources/index.d.ts +18 -0
- package/dist/sources/index.js +18 -0
- package/dist/sources/introspect-supabase.d.ts +30 -0
- package/dist/sources/introspect-supabase.js +134 -0
- package/dist/sources/realtime-supabase.d.ts +37 -0
- package/dist/sources/realtime-supabase.js +52 -0
- package/dist/sources/relation-lookup.d.ts +50 -0
- package/dist/sources/relation-lookup.js +77 -0
- package/dist/sources/rest-adapters.d.ts +48 -0
- package/dist/sources/rest-adapters.js +85 -0
- package/dist/sources/rest.d.ts +38 -0
- package/dist/sources/rest.js +86 -0
- package/dist/sources/schema-from-columns.d.ts +37 -0
- package/dist/sources/schema-from-columns.js +48 -0
- package/dist/sources/supabase.d.ts +33 -0
- package/dist/sources/supabase.js +74 -0
- package/dist/sources/with-entity-rules.d.ts +25 -0
- package/dist/sources/with-entity-rules.js +47 -0
- package/dist/sources/with-relation-labels.d.ts +26 -0
- package/dist/sources/with-relation-labels.js +38 -0
- package/dist/staged-editing.d.ts +85 -0
- package/dist/staged-editing.js +0 -0
- package/dist/studio/bug-report.d.ts +61 -0
- package/dist/studio/bug-report.js +126 -0
- package/dist/studio/cli.d.ts +56 -0
- package/dist/studio/cli.js +70 -0
- package/dist/studio/copilot-core.d.ts +22 -0
- package/{src/studio/copilot-core.ts → dist/studio/copilot-core.js} +34 -38
- package/dist/studio/csv.d.ts +36 -0
- package/dist/studio/csv.js +173 -0
- package/dist/studio/db-connect-string.d.ts +45 -0
- package/dist/studio/db-connect-string.js +113 -0
- package/dist/studio/deploy-cli.d.ts +35 -0
- package/dist/studio/deploy-cli.js +81 -0
- package/dist/studio/emit-project.d.ts +77 -0
- package/dist/studio/emit-project.js +5389 -0
- package/dist/studio/emit-schema.d.ts +110 -0
- package/dist/studio/emit-schema.js +1128 -0
- package/dist/studio/index.d.ts +35 -0
- package/dist/studio/index.js +38 -0
- package/dist/studio/init-flow.d.ts +58 -0
- package/dist/studio/init-flow.js +451 -0
- package/dist/studio/introspect-db.d.ts +47 -0
- package/dist/studio/introspect-db.js +255 -0
- package/dist/studio/introspect-openapi.d.ts +19 -0
- package/dist/studio/introspect-openapi.js +244 -0
- package/dist/studio/introspect-prisma.d.ts +25 -0
- package/dist/studio/introspect-prisma.js +164 -0
- package/dist/studio/introspect.d.ts +35 -0
- package/dist/studio/introspect.js +306 -0
- package/dist/studio/project.d.ts +1327 -0
- package/dist/studio/project.js +1798 -0
- package/dist/studio/sample-data.d.ts +19 -0
- package/dist/studio/sample-data.js +207 -0
- package/dist/studio/samples/ats.d.ts +2 -0
- package/dist/studio/samples/ats.js +194 -0
- package/dist/studio/samples/clinic.d.ts +2 -0
- package/dist/studio/samples/clinic.js +171 -0
- package/dist/studio/samples/crm.d.ts +2 -0
- package/dist/studio/samples/crm.js +280 -0
- package/dist/studio/samples/datasets.d.ts +38 -0
- package/dist/studio/samples/datasets.js +296 -0
- package/dist/studio/samples/ecommerce.d.ts +2 -0
- package/dist/studio/samples/ecommerce.js +178 -0
- package/dist/studio/samples/events.d.ts +2 -0
- package/dist/studio/samples/events.js +192 -0
- package/dist/studio/samples/fleet.d.ts +2 -0
- package/dist/studio/samples/fleet.js +203 -0
- package/dist/studio/samples/gym.d.ts +2 -0
- package/dist/studio/samples/gym.js +205 -0
- package/dist/studio/samples/hr.d.ts +2 -0
- package/dist/studio/samples/hr.js +186 -0
- package/dist/studio/samples/index.d.ts +13 -0
- package/dist/studio/samples/index.js +44 -0
- package/dist/studio/samples/insurance.d.ts +2 -0
- package/dist/studio/samples/insurance.js +220 -0
- package/dist/studio/samples/inventory.d.ts +2 -0
- package/dist/studio/samples/inventory.js +204 -0
- package/dist/studio/samples/invoicing.d.ts +2 -0
- package/dist/studio/samples/invoicing.js +154 -0
- package/dist/studio/samples/library.d.ts +2 -0
- package/dist/studio/samples/library.js +171 -0
- package/dist/studio/samples/live-data.d.ts +5 -0
- package/dist/studio/samples/live-data.js +261 -0
- package/dist/studio/samples/projects.d.ts +2 -0
- package/dist/studio/samples/projects.js +203 -0
- package/dist/studio/samples/realestate.d.ts +2 -0
- package/dist/studio/samples/realestate.js +187 -0
- package/dist/studio/samples/restaurant.d.ts +2 -0
- package/dist/studio/samples/restaurant.js +180 -0
- package/dist/studio/samples/school.d.ts +2 -0
- package/dist/studio/samples/school.js +188 -0
- package/dist/studio/samples/shared.d.ts +142 -0
- package/dist/studio/samples/shared.js +164 -0
- package/dist/studio/samples/starter.d.ts +4 -0
- package/dist/studio/samples/starter.js +237 -0
- package/dist/studio/samples/subscriptions.d.ts +2 -0
- package/dist/studio/samples/subscriptions.js +175 -0
- package/dist/studio/samples/support.d.ts +2 -0
- package/dist/studio/samples/support.js +209 -0
- package/dist/studio/scaffold-app.d.ts +22 -0
- package/{src/studio/scaffold-app.ts → dist/studio/scaffold-app.js} +45 -63
- package/dist/studio/scaffold.d.ts +63 -0
- package/dist/studio/scaffold.js +346 -0
- package/dist/studio/screen-suites.d.ts +193 -0
- package/dist/studio/screen-suites.js +297 -0
- package/dist/studio/themes.d.ts +34 -0
- package/dist/studio/themes.js +41 -0
- package/dist/studio/ui-components.d.ts +89 -0
- package/dist/studio/ui-components.generated.d.ts +29 -0
- package/dist/studio/ui-components.generated.js +7139 -0
- package/dist/studio/ui-components.js +673 -0
- package/dist/studio/user-error.d.ts +23 -0
- package/{src/studio/user-error.ts → dist/studio/user-error.js} +10 -13
- package/dist/studio/verify.d.ts +34 -0
- package/dist/studio/verify.js +47 -0
- package/dist/sveltekit/in-memory.d.ts +14 -0
- package/dist/sveltekit/in-memory.js +113 -0
- package/dist/sveltekit/index.d.ts +6 -0
- package/dist/sveltekit/index.js +5 -0
- package/dist/sveltekit/query-plan.d.ts +44 -0
- package/dist/sveltekit/query-plan.js +76 -0
- package/dist/sveltekit/sql-source.d.ts +47 -0
- package/dist/sveltekit/sql-source.js +106 -0
- package/dist/sveltekit/sql.d.ts +48 -0
- package/dist/sveltekit/sql.js +73 -0
- package/dist/sveltekit/transport.d.ts +209 -0
- package/dist/sveltekit/transport.js +219 -0
- package/{src/sveltekit/types.ts → dist/sveltekit/types.d.ts} +8 -11
- package/dist/sveltekit/types.js +1 -0
- package/dist/upgrade-prompt.d.ts +16 -0
- package/dist/upgrade-prompt.js +141 -0
- package/dist/version.d.ts +13 -0
- package/{src/version.ts → dist/version.js} +1 -1
- package/dist/watermark.d.ts +2 -0
- package/dist/watermark.js +146 -0
- package/package.json +26 -24
- package/src/SvBoard.dom.test.ts +0 -67
- package/src/SvGridAlerts.dom.test.ts +0 -113
- package/src/SvGridEditPanel.dom.test.ts +0 -320
- package/src/SvRecordDetail.dom.test.ts +0 -137
- package/src/SvSchedule.dom.test.ts +0 -57
- package/src/ai-export-pdf.dom.test.ts +0 -77
- package/src/ai-export-xlsx.dom.test.ts +0 -90
- package/src/ai-export.dom.test.ts +0 -114
- package/src/alerts/alert-engine-attach.ts +0 -165
- package/src/alerts/alert-engine.test.ts +0 -135
- package/src/alerts/alert-engine.ts +0 -260
- package/src/alerts/alert-formats.test.ts +0 -87
- package/src/alerts/alert-formats.ts +0 -77
- package/src/alerts/alert-observer.test.ts +0 -189
- package/src/alerts/alert-observer.ts +0 -208
- package/src/alerts/alert-scheduler.ts +0 -96
- package/src/alerts/alert-storage.test.ts +0 -54
- package/src/alerts/alert-storage.ts +0 -116
- package/src/alerts/alert-store.svelte.ts +0 -80
- package/src/alerts/alert-types.ts +0 -94
- package/src/board.dom.test.ts +0 -941
- package/src/edit-panel.test.ts +0 -322
- package/src/edit-panel.ts +0 -379
- package/src/export-conditional.test.ts +0 -60
- package/src/export-conditional.ts +0 -94
- package/src/export-ooxml.test.ts +0 -152
- package/src/export-ooxml.ts +0 -489
- package/src/export-pdf.test.ts +0 -138
- package/src/export-pdf.ts +0 -245
- package/src/export-print.test.ts +0 -66
- package/src/export-print.ts +0 -132
- package/src/export-serialize.test.ts +0 -56
- package/src/export-xls.ts +0 -199
- package/src/export-xlsx-roundtrip.test.ts +0 -120
- package/src/export-xlsx.test.ts +0 -150
- package/src/export.test.ts +0 -349
- package/src/export.ts +0 -1464
- package/src/expressions/evaluate.test.ts +0 -111
- package/src/expressions/evaluate.ts +0 -237
- package/src/expressions/expression-columns.ts +0 -133
- package/src/expressions/expression-types.ts +0 -84
- package/src/expressions/parse.test.ts +0 -106
- package/src/expressions/parse.ts +0 -610
- package/src/import-automap.test.ts +0 -131
- package/src/import-hardening.test.ts +0 -158
- package/src/import.test.ts +0 -415
- package/src/import.ts +0 -1044
- package/src/index.ts +0 -569
- package/src/install.ts +0 -154
- package/src/license-core.test.ts +0 -23
- package/src/license-core.ts +0 -107
- package/src/license-expiry.test.ts +0 -127
- package/src/license.ts +0 -137
- package/src/master-detail.test.ts +0 -61
- package/src/master-detail.ts +0 -42
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/_metadata.json +0 -178
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/attachments-ZrPsKxob.js +0 -3875
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/attachments-ZrPsKxob.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/constants-ACqvWGE2.js +0 -21
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/constants-ACqvWGE2.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/dev-D3w5jt92.js +0 -1938
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/dev-D3w5jt92.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/events-CC2V3H0y.js +0 -205
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/events-CC2V3H0y.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/flags-BXP37tAa.js +0 -18
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/flags-BXP37tAa.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/hydration-DwubnU5b.js +0 -264
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/hydration-DwubnU5b.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/legacy-client-hD7f6PUz.js +0 -697
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/legacy-client-hD7f6PUz.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte.js +0 -134
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_animate.js +0 -55
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_animate.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_attachments.js +0 -2
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_compiler.js +0 -46843
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_compiler.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_easing.js +0 -237
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_easing.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_events.js +0 -2
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal.js +0 -4
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_client.js +0 -7
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_disclose-version.js +0 -4
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_disclose-version.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_async.js +0 -5
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_async.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_legacy.js +0 -5
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_legacy.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_tracing.js +0 -5
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_tracing.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_server.js +0 -6
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_legacy.js +0 -83
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_legacy.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_motion.js +0 -559
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_motion.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity.js +0 -24
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity_window.js +0 -122
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity_window.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_server.js +0 -2
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_store.js +0 -89
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_store.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_transition.js +0 -241
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_transition.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-DBx1SCN6.js +0 -4938
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-DBx1SCN6.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-gjfpSTFS.js +0 -495
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-gjfpSTFS.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/validate-DKoOKg8S.js +0 -190
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/validate-DKoOKg8S.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/version-C0MiR7eR.js +0 -8
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/version-C0MiR7eR.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/warnings-B6Y7P0Q-.js +0 -138
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/warnings-B6Y7P0Q-.js.map +0 -1
- package/src/pivot-chart.test.ts +0 -86
- package/src/pivot-chart.ts +0 -112
- package/src/pivot-designer.ts +0 -101
- package/src/pivot.test.ts +0 -335
- package/src/pivot.ts +0 -578
- package/src/print.ts +0 -107
- package/src/scheduler-assignments.test.ts +0 -97
- package/src/scheduler-assignments.ts +0 -134
- package/src/scheduler-axis.test.ts +0 -108
- package/src/scheduler-axis.ts +0 -238
- package/src/scheduler-booking.test.ts +0 -57
- package/src/scheduler-config.ts +0 -179
- package/src/scheduler-dependencies.test.ts +0 -155
- package/src/scheduler-dependencies.ts +0 -223
- package/src/scheduler-freebusy.test.ts +0 -41
- package/src/scheduler-heatmap.test.ts +0 -39
- package/src/scheduler-resource-tree.test.ts +0 -84
- package/src/scheduler-resource-tree.ts +0 -107
- package/src/scheduler-slots.test.ts +0 -53
- package/src/scheduler-slots.ts +0 -94
- package/src/scheduler-summary.test.ts +0 -47
- package/src/scheduler-summary.ts +0 -81
- package/src/scheduling.test.ts +0 -194
- package/src/scheduling.ts +0 -293
- package/src/schema-designer.test.ts +0 -121
- package/src/schema-designer.ts +0 -142
- package/src/schema.test.ts +0 -268
- package/src/schema.ts +0 -562
- package/src/smart-shim.ts +0 -107
- package/src/sources/aggregate.test.ts +0 -79
- package/src/sources/aggregate.ts +0 -102
- package/src/sources/auth-supabase.test.ts +0 -80
- package/src/sources/auth-supabase.ts +0 -87
- package/src/sources/dashboard.kpi.test.ts +0 -50
- package/src/sources/dashboard.test.ts +0 -61
- package/src/sources/dashboard.ts +0 -136
- package/src/sources/field-inference.test.ts +0 -60
- package/src/sources/field-inference.ts +0 -63
- package/src/sources/filters.test.ts +0 -58
- package/src/sources/filters.ts +0 -70
- package/src/sources/index.ts +0 -67
- package/src/sources/introspect-supabase.test.ts +0 -112
- package/src/sources/introspect-supabase.ts +0 -139
- package/src/sources/realtime-supabase.test.ts +0 -93
- package/src/sources/realtime-supabase.ts +0 -99
- package/src/sources/relation-lookup.test.ts +0 -99
- package/src/sources/relation-lookup.ts +0 -128
- package/src/sources/rest-adapters.test.ts +0 -95
- package/src/sources/rest-adapters.ts +0 -120
- package/src/sources/rest.test.ts +0 -104
- package/src/sources/rest.ts +0 -129
- package/src/sources/schema-from-columns.test.ts +0 -106
- package/src/sources/schema-from-columns.ts +0 -88
- package/src/sources/supabase.test.ts +0 -110
- package/src/sources/supabase.ts +0 -99
- package/src/sources/with-entity-rules.test.ts +0 -104
- package/src/sources/with-entity-rules.ts +0 -78
- package/src/sources/with-relation-labels.test.ts +0 -75
- package/src/sources/with-relation-labels.ts +0 -73
- package/src/staged-editing.ts +0 -0
- package/src/studio/bug-report.test.ts +0 -101
- package/src/studio/bug-report.ts +0 -165
- package/src/studio/cli.test.ts +0 -187
- package/src/studio/cli.ts +0 -117
- package/src/studio/copilot-core.test.ts +0 -45
- package/src/studio/csv.test.ts +0 -90
- package/src/studio/csv.ts +0 -165
- package/src/studio/db-connect-string.test.ts +0 -94
- package/src/studio/db-connect-string.ts +0 -128
- package/src/studio/deploy-cli.test.ts +0 -56
- package/src/studio/deploy-cli.ts +0 -100
- package/src/studio/emit-project.test.ts +0 -3324
- package/src/studio/emit-project.ts +0 -5377
- package/src/studio/emit-schema.test.ts +0 -111
- package/src/studio/emit-schema.ts +0 -1181
- package/src/studio/index.ts +0 -380
- package/src/studio/init-flow.test.ts +0 -514
- package/src/studio/init-flow.ts +0 -556
- package/src/studio/introspect-db.test.ts +0 -186
- package/src/studio/introspect-db.ts +0 -312
- package/src/studio/introspect-openapi.test.ts +0 -84
- package/src/studio/introspect-openapi.ts +0 -252
- package/src/studio/introspect-prisma.test.ts +0 -99
- package/src/studio/introspect-prisma.ts +0 -175
- package/src/studio/introspect.test.ts +0 -172
- package/src/studio/introspect.ts +0 -310
- package/src/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/_svelte_metadata.json +0 -1
- package/src/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/package.json +0 -3
- package/src/studio/pipeline.test.ts +0 -42
- package/src/studio/project-robust.test.ts +0 -157
- package/src/studio/project.test.ts +0 -929
- package/src/studio/project.ts +0 -2394
- package/src/studio/sample-data.test.ts +0 -58
- package/src/studio/sample-data.ts +0 -203
- package/src/studio/samples/ats.ts +0 -202
- package/src/studio/samples/clinic.ts +0 -179
- package/src/studio/samples/crm.ts +0 -291
- package/src/studio/samples/datasets.test.ts +0 -84
- package/src/studio/samples/datasets.ts +0 -340
- package/src/studio/samples/ecommerce.ts +0 -187
- package/src/studio/samples/events.ts +0 -201
- package/src/studio/samples/fleet.ts +0 -213
- package/src/studio/samples/gym.ts +0 -215
- package/src/studio/samples/hr.ts +0 -195
- package/src/studio/samples/index.ts +0 -55
- package/src/studio/samples/insurance.ts +0 -229
- package/src/studio/samples/inventory.ts +0 -213
- package/src/studio/samples/invoicing.ts +0 -162
- package/src/studio/samples/library.ts +0 -180
- package/src/studio/samples/live-data.test.ts +0 -99
- package/src/studio/samples/live-data.ts +0 -306
- package/src/studio/samples/projects.ts +0 -212
- package/src/studio/samples/realestate.ts +0 -196
- package/src/studio/samples/restaurant.ts +0 -189
- package/src/studio/samples/samples.test.ts +0 -304
- package/src/studio/samples/school.ts +0 -197
- package/src/studio/samples/seed-floor.test.ts +0 -25
- package/src/studio/samples/shared.ts +0 -237
- package/src/studio/samples/starter.ts +0 -251
- package/src/studio/samples/subscriptions.ts +0 -183
- package/src/studio/samples/support.ts +0 -216
- package/src/studio/scaffold-app.test.ts +0 -91
- package/src/studio/scaffold.test.ts +0 -192
- package/src/studio/scaffold.ts +0 -390
- package/src/studio/screen-suites.test.ts +0 -269
- package/src/studio/screen-suites.ts +0 -448
- package/src/studio/themes.ts +0 -62
- package/src/studio/ui-components-surface.test.ts +0 -185
- package/src/studio/ui-components.generated.ts +0 -7154
- package/src/studio/ui-components.ts +0 -742
- package/src/studio/verify.test.ts +0 -47
- package/src/studio/verify.ts +0 -79
- package/src/sveltekit/in-memory.test.ts +0 -104
- package/src/sveltekit/in-memory.ts +0 -129
- package/src/sveltekit/index.ts +0 -24
- package/src/sveltekit/query-plan.test.ts +0 -109
- package/src/sveltekit/query-plan.ts +0 -125
- package/src/sveltekit/sql-source.test.ts +0 -198
- package/src/sveltekit/sql-source.ts +0 -171
- package/src/sveltekit/sql.test.ts +0 -80
- package/src/sveltekit/sql.ts +0 -131
- package/src/sveltekit/transport-scope.test.ts +0 -125
- package/src/sveltekit/transport.test.ts +0 -201
- package/src/sveltekit/transport.ts +0 -373
- package/src/upgrade-prompt.test.ts +0 -71
- package/src/upgrade-prompt.ts +0 -162
- package/src/version.test.ts +0 -17
- package/src/watermark.test.ts +0 -97
- package/src/watermark.ts +0 -156
- /package/{src → dist}/SvAlertRuleEditor.svelte +0 -0
- /package/{src → dist}/SvAlertsManager.svelte +0 -0
- /package/{src → dist}/SvAlertsPanel.svelte +0 -0
- /package/{src → dist}/SvAuthGate.svelte +0 -0
- /package/{src → dist}/SvBoard.svelte +0 -0
- /package/{src → dist}/SvExportMenu.svelte +0 -0
- /package/{src → dist}/SvExpressionEditor.svelte +0 -0
- /package/{src → dist}/SvFileInput.svelte +0 -0
- /package/{src → dist}/SvGridAlerts.svelte +0 -0
- /package/{src → dist}/SvGridBoard.svelte +0 -0
- /package/{src → dist}/SvGridEditPanel.svelte +0 -0
- /package/{src → dist}/SvGridMasterDetail.svelte +0 -0
- /package/{src → dist}/SvGridScheduler.svelte +0 -0
- /package/{src → dist}/SvImportDialog.svelte +0 -0
- /package/{src → dist}/SvLookupInput.svelte +0 -0
- /package/{src → dist}/SvPivotDesigner.svelte +0 -0
- /package/{src → dist}/SvRecordDetail.svelte +0 -0
- /package/{src → dist}/SvSchedule.svelte +0 -0
- /package/{src → dist}/SvSchemaChart.svelte +0 -0
- /package/{src → dist}/SvSchemaDashboard.svelte +0 -0
- /package/{src → dist}/pdfmake-shims.d.ts +0 -0
- /package/{src → dist}/smart.export.d.ts +0 -0
- /package/{src → dist}/smart.export.js +0 -0
- /package/{src → dist}/studio/HANDLERS-DESIGN.md +0 -0
- /package/{src → dist/studio}/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/_svelte_metadata.json +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/_metadata.json +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/attachments-BOv1rBKp.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/attachments-BOv1rBKp.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/constants-B9vgIdCd.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/constants-B9vgIdCd.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/dev-T1qbW_qD.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/dev-T1qbW_qD.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/events-Bo11SfVK.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/events-Bo11SfVK.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/flags-X7D4vfrZ.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/flags-X7D4vfrZ.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/hydration-oyUje5i1.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/hydration-oyUje5i1.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/legacy-client-DeSQgSFm.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/legacy-client-DeSQgSFm.js.map +0 -0
- /package/{src → dist/studio}/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/package.json +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_animate.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_animate.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_attachments.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_compiler.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_compiler.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_easing.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_easing.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_events.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_client.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_disclose-version.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_disclose-version.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_async.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_async.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_legacy.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_legacy.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_tracing.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_tracing.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_server.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_legacy.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_legacy.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_motion.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_motion.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity_window.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity_window.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_server.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_store.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_store.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_transition.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_transition.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-BbWyXNk1.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-BbWyXNk1.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-DI_fC7vt.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-DI_fC7vt.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/validate-Dyr3lQv9.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/validate-Dyr3lQv9.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/version-_9FHH-LF.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/version-_9FHH-LF.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/warnings-CUbSPnyP.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/warnings-CUbSPnyP.js.map +0 -0
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* createSupabaseRealtime - live updates for a Studio screen via Supabase
|
|
3
|
-
* Realtime (Postgres change streams). Subscribe to a table's INSERT / UPDATE /
|
|
4
|
-
* DELETE events and react - typically by refreshing the current page so the grid
|
|
5
|
-
* stays in sync with the database, no polling.
|
|
6
|
-
*
|
|
7
|
-
* const live = createSupabaseRealtime({
|
|
8
|
-
* client, table: 'customers',
|
|
9
|
-
* debounceMs: 200,
|
|
10
|
-
* onChange: () => controller.refresh(), // re-fetch the current page
|
|
11
|
-
* })
|
|
12
|
-
* // later: live.unsubscribe()
|
|
13
|
-
*
|
|
14
|
-
* You bring the same `supabase-js` client used for reads (BYO, no dependency).
|
|
15
|
-
* Because the server model is paged, the correct default is to `refresh()` on a
|
|
16
|
-
* change - that respects the active sort / filter / page. Use `debounceMs` to
|
|
17
|
-
* coalesce bursts into a single refetch. For per-row effects (e.g. flashing a
|
|
18
|
-
* changed row) read the normalized event passed to `onChange`.
|
|
19
|
-
*/
|
|
20
|
-
import { nudgeEnterprise } from '../license'
|
|
21
|
-
|
|
22
|
-
/** A normalized change event. `new` is the row after the change (INSERT/UPDATE); `old` its prior identity (UPDATE/DELETE). */
|
|
23
|
-
export type RealtimeChange<TData> = {
|
|
24
|
-
type: 'INSERT' | 'UPDATE' | 'DELETE'
|
|
25
|
-
new: TData | null
|
|
26
|
-
old: Partial<TData> | null
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/** The slice of a `supabase-js` client + channel this needs. */
|
|
30
|
-
export type RealtimeChannelLike = {
|
|
31
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
32
|
-
on(type: 'postgres_changes', filter: Record<string, unknown>, cb: (payload: any) => void): RealtimeChannelLike
|
|
33
|
-
subscribe(cb?: (status: string) => void): RealtimeChannelLike
|
|
34
|
-
}
|
|
35
|
-
export type SupabaseRealtimeClientLike = {
|
|
36
|
-
channel(name: string): RealtimeChannelLike
|
|
37
|
-
removeChannel(channel: RealtimeChannelLike): void
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export type SupabaseRealtimeConfig<TData> = {
|
|
41
|
-
client: SupabaseRealtimeClientLike
|
|
42
|
-
table: string
|
|
43
|
-
/** Postgres schema. Default `'public'`. */
|
|
44
|
-
schema?: string
|
|
45
|
-
/** Only these events. Default `'*'` (all). */
|
|
46
|
-
event?: 'INSERT' | 'UPDATE' | 'DELETE' | '*'
|
|
47
|
-
/** PostgREST-style row filter, e.g. `'tier=eq.pro'`. */
|
|
48
|
-
filter?: string
|
|
49
|
-
/** Unique channel name. Default `svgrid:{schema}:{table}`. */
|
|
50
|
-
channelName?: string
|
|
51
|
-
/** Coalesce bursts: call `onChange` at most once per this window (trailing). */
|
|
52
|
-
debounceMs?: number
|
|
53
|
-
/** Called for each change (or the last of a debounced burst). */
|
|
54
|
-
onChange: (change: RealtimeChange<TData>) => void
|
|
55
|
-
/** Subscription status callback (`SUBSCRIBED`, `CHANNEL_ERROR`, ...). */
|
|
56
|
-
onStatus?: (status: string) => void
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export type SupabaseRealtimeHandle = { unsubscribe(): void }
|
|
60
|
-
|
|
61
|
-
export function createSupabaseRealtime<TData = Record<string, unknown>>(
|
|
62
|
-
config: SupabaseRealtimeConfig<TData>,
|
|
63
|
-
): SupabaseRealtimeHandle {
|
|
64
|
-
nudgeEnterprise('Studio') // soft-gate; never blocks
|
|
65
|
-
const schema = config.schema ?? 'public'
|
|
66
|
-
const channelName = config.channelName ?? `svgrid:${schema}:${config.table}`
|
|
67
|
-
|
|
68
|
-
let timer: ReturnType<typeof setTimeout> | undefined
|
|
69
|
-
const emit = (change: RealtimeChange<TData>) => {
|
|
70
|
-
if (!config.debounceMs) {
|
|
71
|
-
config.onChange(change)
|
|
72
|
-
return
|
|
73
|
-
}
|
|
74
|
-
if (timer) clearTimeout(timer)
|
|
75
|
-
timer = setTimeout(() => config.onChange(change), config.debounceMs)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const channel = config.client
|
|
79
|
-
.channel(channelName)
|
|
80
|
-
.on(
|
|
81
|
-
'postgres_changes',
|
|
82
|
-
{ event: config.event ?? '*', schema, table: config.table, ...(config.filter ? { filter: config.filter } : {}) },
|
|
83
|
-
(payload) => {
|
|
84
|
-
emit({
|
|
85
|
-
type: payload.eventType,
|
|
86
|
-
new: (payload.new ?? null) as TData | null,
|
|
87
|
-
old: (payload.old ?? null) as Partial<TData> | null,
|
|
88
|
-
})
|
|
89
|
-
},
|
|
90
|
-
)
|
|
91
|
-
.subscribe(config.onStatus)
|
|
92
|
-
|
|
93
|
-
return {
|
|
94
|
-
unsubscribe() {
|
|
95
|
-
if (timer) clearTimeout(timer)
|
|
96
|
-
config.client.removeChannel(channel)
|
|
97
|
-
},
|
|
98
|
-
}
|
|
99
|
-
}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from 'vitest'
|
|
2
|
-
import type { ServerRequest } from '@svgrid/grid'
|
|
3
|
-
import type { EntitySchema } from '../schema'
|
|
4
|
-
import { createRelationLookup } from './relation-lookup'
|
|
5
|
-
|
|
6
|
-
type Company = { id: number; name: string }
|
|
7
|
-
|
|
8
|
-
const companies: Company[] = [
|
|
9
|
-
{ id: 1, name: 'Acme Inc' },
|
|
10
|
-
{ id: 2, name: 'Globex' },
|
|
11
|
-
{ id: 3, name: 'Initech' },
|
|
12
|
-
]
|
|
13
|
-
|
|
14
|
-
const schema: EntitySchema<Company> = {
|
|
15
|
-
name: 'companies',
|
|
16
|
-
idField: 'id',
|
|
17
|
-
fields: [
|
|
18
|
-
{ field: 'id', type: 'number', primaryKey: true },
|
|
19
|
-
{ field: 'name', type: 'text' },
|
|
20
|
-
],
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/** Minimal getRows over the array: honors global search + an equals filter on id. */
|
|
24
|
-
function source() {
|
|
25
|
-
const getRows = vi.fn(async (req: ServerRequest) => {
|
|
26
|
-
let rows = companies
|
|
27
|
-
const g = req.filterModel.global?.toLowerCase()
|
|
28
|
-
if (g) rows = rows.filter((c) => c.name.toLowerCase().includes(g))
|
|
29
|
-
const idCol = req.filterModel.columns?.id
|
|
30
|
-
if (idCol?.selectedValues) rows = rows.filter((c) => idCol.selectedValues!.includes(String(c.id)))
|
|
31
|
-
else if (idCol) rows = rows.filter((c) => String(c.id) === idCol.value)
|
|
32
|
-
return { rows: rows.slice(req.startRow, req.endRow), rowCount: rows.length }
|
|
33
|
-
})
|
|
34
|
-
return { getRows }
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
describe('createRelationLookup', () => {
|
|
38
|
-
it('searches and maps rows to { value, label }', async () => {
|
|
39
|
-
const lookup = createRelationLookup({ source: source(), schema, labelField: 'name' })
|
|
40
|
-
expect(await lookup.search('in')).toEqual([
|
|
41
|
-
{ value: '1', label: 'Acme Inc', row: { id: 1, name: 'Acme Inc' } },
|
|
42
|
-
{ value: '3', label: 'Initech', row: { id: 3, name: 'Initech' } },
|
|
43
|
-
])
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
it('returns a full page for an empty query', async () => {
|
|
47
|
-
const lookup = createRelationLookup({ source: source(), schema, labelField: 'name' })
|
|
48
|
-
expect((await lookup.search('')).map((o) => o.label)).toEqual(['Acme Inc', 'Globex', 'Initech'])
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
it('resolves a stored key to its label', async () => {
|
|
52
|
-
const lookup = createRelationLookup({ source: source(), schema, labelField: 'name' })
|
|
53
|
-
expect(await lookup.labelFor(2)).toBe('Globex')
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
it('caches labels seen during search (no extra getRows for labelFor)', async () => {
|
|
57
|
-
const src = source()
|
|
58
|
-
const lookup = createRelationLookup({ source: src, schema, labelField: 'name' })
|
|
59
|
-
await lookup.search('acme') // caches value 1 -> Acme Inc
|
|
60
|
-
src.getRows.mockClear()
|
|
61
|
-
expect(await lookup.labelFor(1)).toBe('Acme Inc')
|
|
62
|
-
expect(src.getRows).not.toHaveBeenCalled()
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
it('returns null for an empty value and the key itself when unresolved', async () => {
|
|
66
|
-
const lookup = createRelationLookup({ source: source(), schema, labelField: 'name' })
|
|
67
|
-
expect(await lookup.labelFor('')).toBeNull()
|
|
68
|
-
expect(await lookup.labelFor(999)).toBe('999')
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
it('honors an explicit valueField over the schema id', async () => {
|
|
72
|
-
const lookup = createRelationLookup({ source: source(), labelField: 'name', valueField: 'name' })
|
|
73
|
-
const opts = await lookup.search('glob')
|
|
74
|
-
expect(opts[0]).toMatchObject({ value: 'Globex', label: 'Globex' })
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
describe('labelsFor (batch)', () => {
|
|
78
|
-
it('resolves many keys in a single request (no N+1), deduping', async () => {
|
|
79
|
-
const src = source()
|
|
80
|
-
const lookup = createRelationLookup({ source: src, schema, labelField: 'name' })
|
|
81
|
-
const map = await lookup.labelsFor([1, 2, 2, 3, null, ''])
|
|
82
|
-
expect(map.get('1')).toBe('Acme Inc')
|
|
83
|
-
expect(map.get('2')).toBe('Globex')
|
|
84
|
-
expect(map.get('3')).toBe('Initech')
|
|
85
|
-
expect(src.getRows).toHaveBeenCalledTimes(1) // one query for all misses
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
it('serves cached keys without a request, and maps unresolved keys to themselves', async () => {
|
|
89
|
-
const src = source()
|
|
90
|
-
const lookup = createRelationLookup({ source: src, schema, labelField: 'name' })
|
|
91
|
-
await lookup.labelsFor([1]) // warm the cache
|
|
92
|
-
src.getRows.mockClear()
|
|
93
|
-
const map = await lookup.labelsFor([1, 999])
|
|
94
|
-
expect(map.get('1')).toBe('Acme Inc') // cached
|
|
95
|
-
expect(map.get('999')).toBe('999') // unresolved -> itself
|
|
96
|
-
expect(src.getRows).toHaveBeenCalledTimes(1) // only the miss (999)
|
|
97
|
-
})
|
|
98
|
-
})
|
|
99
|
-
})
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* createRelationLookup - powers a foreign-key "lookup" field: search the related
|
|
3
|
-
* entity for options, and resolve a stored key back to its human label. It runs
|
|
4
|
-
* over the SAME `ServerDataSource` contract as everything else, so the related
|
|
5
|
-
* options can come from Supabase, REST, SQL, or in-memory - whatever backs the
|
|
6
|
-
* related table.
|
|
7
|
-
*
|
|
8
|
-
* const companyLookup = createRelationLookup({
|
|
9
|
-
* source: companiesSource, // the related entity's ServerDataSource
|
|
10
|
-
* schema: companiesSchema, // resolves the related primary key
|
|
11
|
-
* labelField: 'name', // what the user sees
|
|
12
|
-
* })
|
|
13
|
-
* await companyLookup.search('acme') // -> [{ value: '12', label: 'Acme Inc' }, ...]
|
|
14
|
-
* await companyLookup.labelFor('12') // -> 'Acme Inc'
|
|
15
|
-
*
|
|
16
|
-
* Pass it to `<SvGridEditPanel lookups={{ companyId: companyLookup }} />` and the
|
|
17
|
-
* `companyId` relation field renders a searchable picker instead of a raw input.
|
|
18
|
-
*/
|
|
19
|
-
import type { RowData, ServerDataSource, ServerRequest } from '@svgrid/grid'
|
|
20
|
-
import { resolveIdField, type EntitySchema } from '../schema'
|
|
21
|
-
|
|
22
|
-
export type RelationOption = { value: string; label: string; row: RowData }
|
|
23
|
-
|
|
24
|
-
export type RelationLookup = {
|
|
25
|
-
/** Search the related entity (global search); returns a page of options. */
|
|
26
|
-
search(query: string): Promise<RelationOption[]>
|
|
27
|
-
/** Resolve a stored key to its label (cached). Returns the key itself if not found. */
|
|
28
|
-
labelFor(value: unknown): Promise<string | null>
|
|
29
|
-
/**
|
|
30
|
-
* Resolve many keys at once (cached), fetching only the misses in a SINGLE
|
|
31
|
-
* request (a set / `IN` filter) - avoids the N+1 of calling `labelFor` per
|
|
32
|
-
* row. Returns a `value -> label` map (unresolved keys map to themselves).
|
|
33
|
-
*/
|
|
34
|
-
labelsFor(values: ReadonlyArray<unknown>): Promise<Map<string, string>>
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export type RelationLookupConfig<TRelated extends RowData> = {
|
|
38
|
-
/** The related entity's read source (only `getRows` is used). */
|
|
39
|
-
source: Pick<ServerDataSource<TRelated>, 'getRows'>
|
|
40
|
-
/** Field on the related row shown to the user. */
|
|
41
|
-
labelField: string
|
|
42
|
-
/** Related primary-key field. Default: resolved from `schema`, else `'id'`. */
|
|
43
|
-
valueField?: string
|
|
44
|
-
/** Related schema, used to resolve the key when `valueField` is omitted. */
|
|
45
|
-
schema?: EntitySchema<TRelated>
|
|
46
|
-
/** Options fetched per search. Default 20. */
|
|
47
|
-
pageSize?: number
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function createRelationLookup<TRelated extends RowData>(
|
|
51
|
-
config: RelationLookupConfig<TRelated>,
|
|
52
|
-
): RelationLookup {
|
|
53
|
-
const pageSize = config.pageSize ?? 20
|
|
54
|
-
const valueField = config.valueField ?? (config.schema ? resolveIdField(config.schema) : 'id')
|
|
55
|
-
const { labelField, source } = config
|
|
56
|
-
const cache = new Map<string, string>() // value -> label
|
|
57
|
-
|
|
58
|
-
const toOption = (row: RowData): RelationOption => {
|
|
59
|
-
const value = String(row[valueField] ?? '')
|
|
60
|
-
const label = String(row[labelField] ?? value)
|
|
61
|
-
cache.set(value, label)
|
|
62
|
-
return { value, label, row }
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const request = (over: Partial<ServerRequest>): ServerRequest => ({
|
|
66
|
-
startRow: 0,
|
|
67
|
-
endRow: pageSize,
|
|
68
|
-
pageIndex: 0,
|
|
69
|
-
pageSize,
|
|
70
|
-
sortModel: [],
|
|
71
|
-
filterModel: {},
|
|
72
|
-
...over,
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
return {
|
|
76
|
-
async search(query: string): Promise<RelationOption[]> {
|
|
77
|
-
const term = query.trim()
|
|
78
|
-
const { rows } = await source.getRows(request({ filterModel: term ? { global: term } : {} }))
|
|
79
|
-
return rows.map((r) => toOption(r as RowData))
|
|
80
|
-
},
|
|
81
|
-
|
|
82
|
-
async labelFor(value: unknown): Promise<string | null> {
|
|
83
|
-
if (value == null || value === '') return null
|
|
84
|
-
const key = String(value)
|
|
85
|
-
const cached = cache.get(key)
|
|
86
|
-
if (cached != null) return cached
|
|
87
|
-
const { rows } = await source.getRows(
|
|
88
|
-
request({
|
|
89
|
-
endRow: 1,
|
|
90
|
-
pageSize: 1,
|
|
91
|
-
filterModel: { columns: { [valueField]: { operator: 'equals', value: key } } },
|
|
92
|
-
}),
|
|
93
|
-
)
|
|
94
|
-
const row = rows[0] as RowData | undefined
|
|
95
|
-
return row ? toOption(row).label : key
|
|
96
|
-
},
|
|
97
|
-
|
|
98
|
-
async labelsFor(values: ReadonlyArray<unknown>): Promise<Map<string, string>> {
|
|
99
|
-
const result = new Map<string, string>()
|
|
100
|
-
const missing: string[] = []
|
|
101
|
-
for (const v of values) {
|
|
102
|
-
if (v == null || v === '') continue
|
|
103
|
-
const key = String(v)
|
|
104
|
-
if (result.has(key)) continue
|
|
105
|
-
const cached = cache.get(key)
|
|
106
|
-
if (cached != null) result.set(key, cached)
|
|
107
|
-
else if (!missing.includes(key)) missing.push(key)
|
|
108
|
-
}
|
|
109
|
-
if (missing.length > 0) {
|
|
110
|
-
// One request for every miss: a set (`IN`) filter on the key field.
|
|
111
|
-
const { rows } = await source.getRows(
|
|
112
|
-
request({
|
|
113
|
-
endRow: missing.length,
|
|
114
|
-
pageSize: missing.length,
|
|
115
|
-
filterModel: { columns: { [valueField]: { operator: 'in', value: '', selectedValues: missing } } },
|
|
116
|
-
}),
|
|
117
|
-
)
|
|
118
|
-
for (const row of rows) {
|
|
119
|
-
const opt = toOption(row as RowData)
|
|
120
|
-
result.set(opt.value, opt.label)
|
|
121
|
-
}
|
|
122
|
-
// Anything still unresolved maps to the key itself.
|
|
123
|
-
for (const key of missing) if (!result.has(key)) result.set(key, key)
|
|
124
|
-
}
|
|
125
|
-
return result
|
|
126
|
-
},
|
|
127
|
-
}
|
|
128
|
-
}
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import type { ServerRequest } from '@svgrid/grid'
|
|
3
|
-
import { createRestDataSource } from './rest'
|
|
4
|
-
import { offsetLimitAdapter, dummyJsonAdapter, jsonServerAdapter } from './rest-adapters'
|
|
5
|
-
|
|
6
|
-
type Row = { id: string; name: string }
|
|
7
|
-
|
|
8
|
-
function jsonResponse(body: unknown, opts: { status?: number; headers?: Record<string, string> } = {}) {
|
|
9
|
-
const status = opts.status ?? 200
|
|
10
|
-
const headers = opts.headers ?? {}
|
|
11
|
-
return {
|
|
12
|
-
ok: status >= 200 && status < 300,
|
|
13
|
-
status,
|
|
14
|
-
statusText: 'OK',
|
|
15
|
-
headers: { get: (k: string) => headers[k.toLowerCase()] ?? null },
|
|
16
|
-
json: async () => body,
|
|
17
|
-
} as unknown as Response
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function mockFetch(handler: (url: string) => Response) {
|
|
21
|
-
const calls: string[] = []
|
|
22
|
-
const fetch = (async (url: string | URL) => {
|
|
23
|
-
calls.push(String(url))
|
|
24
|
-
return handler(String(url))
|
|
25
|
-
}) as unknown as typeof globalThis.fetch
|
|
26
|
-
return { fetch, calls }
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const req = (p: Partial<ServerRequest>): ServerRequest => ({
|
|
30
|
-
startRow: 0, endRow: 10, pageIndex: 0, pageSize: 10, sortModel: [], filterModel: {}, ...p,
|
|
31
|
-
})
|
|
32
|
-
const paramsOf = (url: string) => new URLSearchParams(url.split('?')[1])
|
|
33
|
-
|
|
34
|
-
describe('dummyJsonAdapter', () => {
|
|
35
|
-
it('maps paging to skip/limit, sort to sortBy/order, and reads products/total', async () => {
|
|
36
|
-
const { fetch, calls } = mockFetch(() =>
|
|
37
|
-
jsonResponse({ products: [{ id: '1', name: 'Phone' }], total: 194, skip: 20, limit: 10 }),
|
|
38
|
-
)
|
|
39
|
-
const src = createRestDataSource<Row>({ url: 'https://dummyjson.com/products', fetch, ...dummyJsonAdapter<Row>() })
|
|
40
|
-
const out = await src.getRows(req({ startRow: 20, endRow: 30, sortModel: [{ id: 'price', desc: true }] }))
|
|
41
|
-
const p = paramsOf(calls[0]!)
|
|
42
|
-
expect(p.get('skip')).toBe('20')
|
|
43
|
-
expect(p.get('limit')).toBe('10')
|
|
44
|
-
expect(p.get('sortBy')).toBe('price')
|
|
45
|
-
expect(p.get('order')).toBe('desc')
|
|
46
|
-
expect(out).toEqual({ rows: [{ id: '1', name: 'Phone' }], rowCount: 194 })
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
it('reads a non-default collection key (e.g. users)', async () => {
|
|
50
|
-
const { fetch } = mockFetch(() => jsonResponse({ users: [{ id: '7', name: 'Ada' }], total: 30 }))
|
|
51
|
-
const src = createRestDataSource<Row>({ url: 'https://dummyjson.com/users', fetch, ...dummyJsonAdapter<Row>('users') })
|
|
52
|
-
expect(await src.getRows(req({}))).toEqual({ rows: [{ id: '7', name: 'Ada' }], rowCount: 30 })
|
|
53
|
-
})
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
describe('jsonServerAdapter', () => {
|
|
57
|
-
it('maps paging to _start/_limit, multi-sort to _sort/_order, total from X-Total-Count', async () => {
|
|
58
|
-
const { fetch, calls } = mockFetch(() =>
|
|
59
|
-
jsonResponse([{ id: '1', name: 'Ada' }], { headers: { 'x-total-count': '240' } }),
|
|
60
|
-
)
|
|
61
|
-
const src = createRestDataSource<Row>({ url: 'https://x.test/posts', fetch, ...jsonServerAdapter<Row>() })
|
|
62
|
-
const out = await src.getRows(
|
|
63
|
-
req({ startRow: 0, endRow: 25, sortModel: [{ id: 'title', desc: false }, { id: 'views', desc: true }] }),
|
|
64
|
-
)
|
|
65
|
-
const p = paramsOf(calls[0]!)
|
|
66
|
-
expect(p.get('_start')).toBe('0')
|
|
67
|
-
expect(p.get('_limit')).toBe('25')
|
|
68
|
-
expect(p.get('_sort')).toBe('title,views')
|
|
69
|
-
expect(p.get('_order')).toBe('asc,desc')
|
|
70
|
-
expect(out).toEqual({ rows: [{ id: '1', name: 'Ada' }], rowCount: 240 })
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
it('falls back to array length when no X-Total-Count header', async () => {
|
|
74
|
-
const { fetch } = mockFetch(() => jsonResponse([{ id: '1', name: 'A' }, { id: '2', name: 'B' }]))
|
|
75
|
-
const src = createRestDataSource<Row>({ url: 'https://x.test/posts', fetch, ...jsonServerAdapter<Row>() })
|
|
76
|
-
expect((await src.getRows(req({}))).rowCount).toBe(2)
|
|
77
|
-
})
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
describe('offsetLimitAdapter', () => {
|
|
81
|
-
it('is fully configurable and sends the search term under the named param', async () => {
|
|
82
|
-
const { fetch, calls } = mockFetch(() => jsonResponse({ data: [{ id: '1', name: 'x' }], count: 3 }))
|
|
83
|
-
const src = createRestDataSource<Row>({
|
|
84
|
-
url: 'https://x.test/items',
|
|
85
|
-
fetch,
|
|
86
|
-
...offsetLimitAdapter<Row>({ offsetParam: 'from', limitParam: 'size', searchParam: 'q', rowsKey: 'data', totalKey: 'count' }),
|
|
87
|
-
})
|
|
88
|
-
const out = await src.getRows(req({ startRow: 5, endRow: 15, filterModel: { global: 'ada', columns: {} } }))
|
|
89
|
-
const p = paramsOf(calls[0]!)
|
|
90
|
-
expect(p.get('from')).toBe('5')
|
|
91
|
-
expect(p.get('size')).toBe('10')
|
|
92
|
-
expect(p.get('q')).toBe('ada')
|
|
93
|
-
expect(out).toEqual({ rows: [{ id: '1', name: 'x' }], rowCount: 3 })
|
|
94
|
-
})
|
|
95
|
-
})
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Wire-format adapters for `createRestDataSource`. A public / third-party API
|
|
3
|
-
* rarely speaks our default `offset&limit&sort` dialect - it uses `skip`, or
|
|
4
|
-
* `page`, or `_start`, and wraps its rows under `products` / `data` / a bare
|
|
5
|
-
* array with an `X-Total-Count` header. An adapter is just the `{ buildQuery,
|
|
6
|
-
* parse }` pair that teaches the REST source that dialect:
|
|
7
|
-
*
|
|
8
|
-
* createRestDataSource({ url: 'https://dummyjson.com/products',
|
|
9
|
-
* ...dummyJsonAdapter() })
|
|
10
|
-
*
|
|
11
|
-
* `offsetLimitAdapter` is the configurable base; `dummyJsonAdapter` and
|
|
12
|
-
* `jsonServerAdapter` are ready-made presets for two very common shapes.
|
|
13
|
-
*/
|
|
14
|
-
import type { RowData, ServerRequest, ServerResult } from '@svgrid/grid'
|
|
15
|
-
import type { RestDataSourceConfig } from './rest'
|
|
16
|
-
import { normalizeFilters } from './filters'
|
|
17
|
-
|
|
18
|
-
/** The parts of a REST config that describe a backend's wire format. */
|
|
19
|
-
export type RestAdapter<TData extends RowData> = Required<
|
|
20
|
-
Pick<RestDataSourceConfig<TData>, 'buildQuery' | 'parse'>
|
|
21
|
-
>
|
|
22
|
-
|
|
23
|
-
const pick = (body: unknown, keys: string[]): unknown => {
|
|
24
|
-
const b = (body ?? {}) as Record<string, unknown>
|
|
25
|
-
for (const k of keys) if (b[k] != null) return b[k]
|
|
26
|
-
return undefined
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export type OffsetLimitOptions = {
|
|
30
|
-
/** Query param for the first-row offset (default `offset`). */
|
|
31
|
-
offsetParam?: string
|
|
32
|
-
/** Query param for the page size (default `limit`). */
|
|
33
|
-
limitParam?: string
|
|
34
|
-
/** If set, single-column sort emits `<sortByParam>=<col>` + `<orderParam>=asc|desc`. */
|
|
35
|
-
sortByParam?: string
|
|
36
|
-
orderParam?: string
|
|
37
|
-
/** If set, the global search term is sent as `<searchParam>=<term>`. */
|
|
38
|
-
searchParam?: string
|
|
39
|
-
/** Response key holding the row array (tried in order; falls back to `data`/`rows`/`items`). */
|
|
40
|
-
rowsKey?: string
|
|
41
|
-
/** Response key holding the total count (tried in order; falls back to `total`/`count`). */
|
|
42
|
-
totalKey?: string
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* The `?offset=..&limit=..` family (Supabase-ish REST, DummyJSON with `skip`,
|
|
47
|
-
* many hand-rolled APIs). Configure the param names + response keys once.
|
|
48
|
-
*/
|
|
49
|
-
export function offsetLimitAdapter<TData extends RowData>(opts: OffsetLimitOptions = {}): RestAdapter<TData> {
|
|
50
|
-
const offsetParam = opts.offsetParam ?? 'offset'
|
|
51
|
-
const limitParam = opts.limitParam ?? 'limit'
|
|
52
|
-
const rowsKeys = [opts.rowsKey, 'data', 'rows', 'items'].filter(Boolean) as string[]
|
|
53
|
-
const totalKeys = [opts.totalKey, 'total', 'count', 'rowCount'].filter(Boolean) as string[]
|
|
54
|
-
return {
|
|
55
|
-
buildQuery(request: ServerRequest): Record<string, string> {
|
|
56
|
-
const params: Record<string, string> = {
|
|
57
|
-
[offsetParam]: String(request.startRow),
|
|
58
|
-
[limitParam]: String(request.endRow - request.startRow),
|
|
59
|
-
}
|
|
60
|
-
const first = request.sortModel[0]
|
|
61
|
-
if (opts.sortByParam && first) {
|
|
62
|
-
params[opts.sortByParam] = first.id
|
|
63
|
-
if (opts.orderParam) params[opts.orderParam] = first.desc ? 'desc' : 'asc'
|
|
64
|
-
}
|
|
65
|
-
if (opts.searchParam) {
|
|
66
|
-
const { search } = normalizeFilters(request.filterModel)
|
|
67
|
-
if (search) params[opts.searchParam] = search
|
|
68
|
-
}
|
|
69
|
-
return params
|
|
70
|
-
},
|
|
71
|
-
parse(body: unknown): ServerResult<TData> {
|
|
72
|
-
const rows = (pick(body, rowsKeys) ?? []) as TData[]
|
|
73
|
-
const total = pick(body, totalKeys)
|
|
74
|
-
return { rows, rowCount: total != null ? Number(total) : rows.length }
|
|
75
|
-
},
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* DummyJSON (`https://dummyjson.com/<collection>`): `skip`/`limit` paging,
|
|
81
|
-
* `sortBy`/`order` sort, rows under `products`* + a `total` field.
|
|
82
|
-
* (*`rowsKey` defaults to `products`; pass one for `users`, `posts`, etc.)
|
|
83
|
-
*/
|
|
84
|
-
export function dummyJsonAdapter<TData extends RowData>(rowsKey = 'products'): RestAdapter<TData> {
|
|
85
|
-
return offsetLimitAdapter<TData>({
|
|
86
|
-
offsetParam: 'skip',
|
|
87
|
-
limitParam: 'limit',
|
|
88
|
-
sortByParam: 'sortBy',
|
|
89
|
-
orderParam: 'order',
|
|
90
|
-
rowsKey,
|
|
91
|
-
totalKey: 'total',
|
|
92
|
-
})
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* `json-server` / JSONPlaceholder: `_start`/`_limit` paging, `_sort`/`_order`
|
|
97
|
-
* multi-column sort, a bare JSON array with the total in `X-Total-Count`.
|
|
98
|
-
*/
|
|
99
|
-
export function jsonServerAdapter<TData extends RowData>(): RestAdapter<TData> {
|
|
100
|
-
return {
|
|
101
|
-
buildQuery(request: ServerRequest): Record<string, string> {
|
|
102
|
-
const params: Record<string, string> = {
|
|
103
|
-
_start: String(request.startRow),
|
|
104
|
-
_limit: String(request.endRow - request.startRow),
|
|
105
|
-
}
|
|
106
|
-
if (request.sortModel.length) {
|
|
107
|
-
params._sort = request.sortModel.map((s) => s.id).join(',')
|
|
108
|
-
params._order = request.sortModel.map((s) => (s.desc ? 'desc' : 'asc')).join(',')
|
|
109
|
-
}
|
|
110
|
-
const { search } = normalizeFilters(request.filterModel)
|
|
111
|
-
if (search) params.q = search
|
|
112
|
-
return params
|
|
113
|
-
},
|
|
114
|
-
parse(body: unknown, response: Response): ServerResult<TData> {
|
|
115
|
-
const rows = Array.isArray(body) ? (body as TData[]) : []
|
|
116
|
-
const header = response.headers.get('x-total-count')
|
|
117
|
-
return { rows, rowCount: header != null ? Number(header) : rows.length }
|
|
118
|
-
},
|
|
119
|
-
}
|
|
120
|
-
}
|
package/src/sources/rest.test.ts
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import type { ServerRequest } from '@svgrid/grid'
|
|
3
|
-
import { createRestDataSource } from './rest'
|
|
4
|
-
|
|
5
|
-
type Row = { id: string; name: string }
|
|
6
|
-
|
|
7
|
-
function jsonResponse(body: unknown, opts: { status?: number; headers?: Record<string, string> } = {}) {
|
|
8
|
-
const status = opts.status ?? 200
|
|
9
|
-
const headers = opts.headers ?? {}
|
|
10
|
-
return {
|
|
11
|
-
ok: status >= 200 && status < 300,
|
|
12
|
-
status,
|
|
13
|
-
statusText: 'OK',
|
|
14
|
-
headers: { get: (k: string) => headers[k.toLowerCase()] ?? null },
|
|
15
|
-
json: async () => body,
|
|
16
|
-
} as unknown as Response
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function mockFetch(handler: (url: string, init?: RequestInit) => Response) {
|
|
20
|
-
const calls: Array<{ url: string; init?: RequestInit }> = []
|
|
21
|
-
const fetch = (async (url: string | URL, init?: RequestInit) => {
|
|
22
|
-
calls.push({ url: String(url), init })
|
|
23
|
-
return handler(String(url), init)
|
|
24
|
-
}) as unknown as typeof globalThis.fetch
|
|
25
|
-
return { fetch, calls }
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const req = (p: Partial<ServerRequest>): ServerRequest => ({
|
|
29
|
-
startRow: 0, endRow: 10, pageIndex: 0, pageSize: 10, sortModel: [], filterModel: {}, ...p,
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
describe('createRestDataSource reads', () => {
|
|
33
|
-
it('builds the default query and parses an object response', async () => {
|
|
34
|
-
const { fetch, calls } = mockFetch(() => jsonResponse({ rows: [{ id: '1', name: 'Ada' }], rowCount: 5 }))
|
|
35
|
-
const src = createRestDataSource<Row>({ url: '/api/customers', fetch })
|
|
36
|
-
const out = await src.getRows(
|
|
37
|
-
req({
|
|
38
|
-
sortModel: [{ id: 'mrr', desc: true }, { id: 'name', desc: false }],
|
|
39
|
-
filterModel: { global: 'ada', columns: { name: { operator: 'contains', value: 'a' } } },
|
|
40
|
-
}),
|
|
41
|
-
)
|
|
42
|
-
const usp = new URLSearchParams(calls[0]!.url.split('?')[1])
|
|
43
|
-
expect(usp.get('offset')).toBe('0')
|
|
44
|
-
expect(usp.get('limit')).toBe('10')
|
|
45
|
-
expect(usp.get('sort')).toBe('-mrr,name')
|
|
46
|
-
expect(usp.get('search')).toBe('ada')
|
|
47
|
-
expect(usp.get('name')).toBe('contains:a')
|
|
48
|
-
expect(out).toEqual({ rows: [{ id: '1', name: 'Ada' }], rowCount: 5 })
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
it('merges static `query` params into every read (built paging wins on conflict)', async () => {
|
|
52
|
-
const { fetch, calls } = mockFetch(() => jsonResponse({ rows: [], rowCount: 0 }))
|
|
53
|
-
const src = createRestDataSource<Row>({ url: '/api/customers', fetch, query: { region: 'eu', limit: 'IGNORED' } })
|
|
54
|
-
await src.getRows(req({}))
|
|
55
|
-
const usp = new URLSearchParams(calls[0]!.url.split('?')[1])
|
|
56
|
-
expect(usp.get('region')).toBe('eu') // static param sent on every read
|
|
57
|
-
expect(usp.get('limit')).toBe('10') // the built paging limit wins over a static one
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
it('reads the total from Content-Range for an array body', async () => {
|
|
61
|
-
const { fetch } = mockFetch(() => jsonResponse([{ id: '1', name: 'Ada' }], { headers: { 'content-range': '0-0/240' } }))
|
|
62
|
-
const src = createRestDataSource<Row>({ url: '/api/customers', fetch })
|
|
63
|
-
const out = await src.getRows(req({}))
|
|
64
|
-
expect(out).toEqual({ rows: [{ id: '1', name: 'Ada' }], rowCount: 240 })
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
it('throws on a non-ok response', async () => {
|
|
68
|
-
const { fetch } = mockFetch(() => jsonResponse({}, { status: 500 }))
|
|
69
|
-
const src = createRestDataSource<Row>({ url: '/api/customers', fetch })
|
|
70
|
-
await expect(src.getRows(req({}))).rejects.toThrow(/500/)
|
|
71
|
-
})
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
describe('createRestDataSource writes', () => {
|
|
75
|
-
it('POSTs to the collection to create', async () => {
|
|
76
|
-
const { fetch, calls } = mockFetch(() => jsonResponse({ id: '9', name: 'New' }))
|
|
77
|
-
const src = createRestDataSource<Row>({ url: '/api/customers', fetch })
|
|
78
|
-
const row = await src.createRow({ name: 'New' })
|
|
79
|
-
expect(calls[0]!.url).toBe('/api/customers')
|
|
80
|
-
expect(calls[0]!.init?.method).toBe('POST')
|
|
81
|
-
expect(JSON.parse(String(calls[0]!.init?.body))).toEqual({ name: 'New' })
|
|
82
|
-
expect(row).toEqual({ id: '9', name: 'New' })
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
it('PATCHes /{id} to update and DELETEs /{id}', async () => {
|
|
86
|
-
const { fetch, calls } = mockFetch((_url, init) =>
|
|
87
|
-
init?.method === 'DELETE' ? jsonResponse(undefined, { status: 204 }) : jsonResponse({ id: '5', name: 'X' }),
|
|
88
|
-
)
|
|
89
|
-
const src = createRestDataSource<Row>({ url: '/api/customers', fetch })
|
|
90
|
-
await src.updateRow('5', { name: 'X' })
|
|
91
|
-
await src.deleteRow('7')
|
|
92
|
-
expect(calls[0]).toMatchObject({ url: '/api/customers/5' })
|
|
93
|
-
expect(calls[0]!.init?.method).toBe('PATCH')
|
|
94
|
-
expect(calls[1]!).toMatchObject({ url: '/api/customers/7' })
|
|
95
|
-
expect(calls[1]!.init?.method).toBe('DELETE')
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
it('applies custom headers', async () => {
|
|
99
|
-
const { fetch, calls } = mockFetch(() => jsonResponse({ rows: [], rowCount: 0 }))
|
|
100
|
-
const src = createRestDataSource<Row>({ url: '/api/x', fetch, headers: { authorization: 'Bearer t' } })
|
|
101
|
-
await src.getRows(req({}))
|
|
102
|
-
expect((calls[0]!.init?.headers as Record<string, string>).authorization).toBe('Bearer t')
|
|
103
|
-
})
|
|
104
|
-
})
|