@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
package/src/scheduling.ts
DELETED
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Scheduling - client-side, cron-driven automation for grid actions.
|
|
3
|
-
*
|
|
4
|
-
* Two everyday jobs that normally need a backend job runner - "email me this
|
|
5
|
-
* report every weekday at 17:30" and "remind the desk at 09:00 to reconcile" -
|
|
6
|
-
* are, in a long-lived data app, just a timer plus an action you already have:
|
|
7
|
-
* an export (`api.exportCsv` / `@svgrid/enterprise` Excel/PDF) or an alert
|
|
8
|
-
* (`toast`). This module supplies the missing middle: a pure cron matcher and a
|
|
9
|
-
* small runtime that fires your callback when a schedule comes due.
|
|
10
|
-
*
|
|
11
|
-
* Everything here is pure and injectable (`now`), so the matching logic is
|
|
12
|
-
* unit-testable without wall-clock flakiness, and the render/app layer just
|
|
13
|
-
* wires `onFire` to whatever action it wants.
|
|
14
|
-
*
|
|
15
|
-
* ```ts
|
|
16
|
-
* import { createScheduler } from '@svgrid/enterprise'
|
|
17
|
-
* import { toast } from '@svgrid/grid'
|
|
18
|
-
*
|
|
19
|
-
* const scheduler = createScheduler({
|
|
20
|
-
* schedules: [
|
|
21
|
-
* { id: 'eod', name: 'End-of-day CSV', cron: '30 17 * * 1-5' },
|
|
22
|
-
* { id: 'standup', name: 'Stand-up reminder', cron: '0 9 * * *' },
|
|
23
|
-
* ],
|
|
24
|
-
* onFire(schedule) {
|
|
25
|
-
* if (schedule.id === 'eod') api.exportCsv({ filename: 'eod' })
|
|
26
|
-
* else toast.info(`${schedule.name}`)
|
|
27
|
-
* },
|
|
28
|
-
* })
|
|
29
|
-
* scheduler.start() // stop() on teardown
|
|
30
|
-
* ```
|
|
31
|
-
*
|
|
32
|
-
* Caveat, by design: schedules run entirely in the browser tab, so the app has
|
|
33
|
-
* to be open when a schedule is due. Pair with a server job for guaranteed
|
|
34
|
-
* delivery; use this for the far more common "the dashboard is always up on the
|
|
35
|
-
* wall" case where a backend cron is overkill.
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
|
-
/** A field in the range [min, max] that a parsed cron sub-expression matches. */
|
|
39
|
-
type CronField = { min: number; max: number; match: (n: number) => boolean }
|
|
40
|
-
|
|
41
|
-
export type Schedule = {
|
|
42
|
-
/** Stable id - used to dedupe fires and to key your `onFire` switch. */
|
|
43
|
-
id: string
|
|
44
|
-
/** Human label shown in a schedules panel / toast. */
|
|
45
|
-
name?: string
|
|
46
|
-
/**
|
|
47
|
-
* Recurring trigger: a standard 5-field cron expression
|
|
48
|
-
* `"minute hour day-of-month month day-of-week"`. Ignored when `runAt` is set.
|
|
49
|
-
* Supports `*`, lists (`1,15`), ranges (`1-5`), and steps (`*/15`, `9-17/2`).
|
|
50
|
-
* Day-of-week is `0-6` with Sunday `0` (`7` also accepted for Sunday).
|
|
51
|
-
*/
|
|
52
|
-
cron?: string
|
|
53
|
-
/**
|
|
54
|
-
* One-off trigger: an ISO datetime string. Fires a single time when the
|
|
55
|
-
* wall clock reaches that minute, then never again. Takes precedence over
|
|
56
|
-
* `cron` when both are present.
|
|
57
|
-
*/
|
|
58
|
-
runAt?: string
|
|
59
|
-
/** Set `false` to keep the definition but stop it firing. Default `true`. */
|
|
60
|
-
enabled?: boolean
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const RANGES = {
|
|
64
|
-
minute: [0, 59],
|
|
65
|
-
hour: [0, 23],
|
|
66
|
-
dom: [1, 31],
|
|
67
|
-
month: [1, 12],
|
|
68
|
-
dow: [0, 6],
|
|
69
|
-
} as const
|
|
70
|
-
|
|
71
|
-
/** Parse one cron field (e.g. `*/15`, `1-5`, `0,30`) into a matcher. */
|
|
72
|
-
function parseField(raw: string, min: number, max: number): CronField {
|
|
73
|
-
const allowed = new Set<number>()
|
|
74
|
-
for (const part of raw.split(',')) {
|
|
75
|
-
const [rangePart, stepPart] = part.split('/')
|
|
76
|
-
const step = stepPart ? parseInt(stepPart, 10) : 1
|
|
77
|
-
if (!Number.isFinite(step) || step < 1) {
|
|
78
|
-
throw new Error(`Invalid cron step in "${raw}"`)
|
|
79
|
-
}
|
|
80
|
-
let lo: number
|
|
81
|
-
let hi: number
|
|
82
|
-
if (rangePart === '*' || rangePart === '') {
|
|
83
|
-
lo = min
|
|
84
|
-
hi = max
|
|
85
|
-
} else if (rangePart!.includes('-')) {
|
|
86
|
-
const [a, b] = rangePart!.split('-')
|
|
87
|
-
lo = parseInt(a!, 10)
|
|
88
|
-
hi = parseInt(b!, 10)
|
|
89
|
-
} else {
|
|
90
|
-
lo = parseInt(rangePart!, 10)
|
|
91
|
-
hi = lo
|
|
92
|
-
}
|
|
93
|
-
if (!Number.isFinite(lo) || !Number.isFinite(hi)) {
|
|
94
|
-
throw new Error(`Invalid cron field "${raw}"`)
|
|
95
|
-
}
|
|
96
|
-
for (let n = lo; n <= hi; n += step) {
|
|
97
|
-
if (n >= min && n <= max) allowed.add(n)
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
return { min, max, match: (n) => allowed.has(n) }
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
type ParsedCron = {
|
|
104
|
-
minute: CronField
|
|
105
|
-
hour: CronField
|
|
106
|
-
dom: CronField
|
|
107
|
-
month: CronField
|
|
108
|
-
dow: CronField
|
|
109
|
-
/** True when BOTH day-of-month and day-of-week are restricted (not `*`). */
|
|
110
|
-
domAndDowRestricted: boolean
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Parse a 5-field cron expression. Throws on the wrong field count or an
|
|
115
|
-
* unparseable field, so a bad schedule surfaces at setup, not silently at 3am.
|
|
116
|
-
*/
|
|
117
|
-
export function parseCron(expr: string): ParsedCron {
|
|
118
|
-
const fields = expr.trim().split(/\s+/)
|
|
119
|
-
if (fields.length !== 5) {
|
|
120
|
-
throw new Error(
|
|
121
|
-
`Cron needs 5 fields "min hour dom month dow", got ${fields.length}: "${expr}"`,
|
|
122
|
-
)
|
|
123
|
-
}
|
|
124
|
-
const [min, hour, dom, month, dow] = fields
|
|
125
|
-
// Day-of-week 7 is an alias for Sunday (0); normalize before parsing.
|
|
126
|
-
const dowNorm = dow!.replace(/7/g, '0')
|
|
127
|
-
return {
|
|
128
|
-
minute: parseField(min!, ...RANGES.minute),
|
|
129
|
-
hour: parseField(hour!, ...RANGES.hour),
|
|
130
|
-
dom: parseField(dom!, ...RANGES.dom),
|
|
131
|
-
month: parseField(month!, ...RANGES.month),
|
|
132
|
-
dow: parseField(dowNorm, ...RANGES.dow),
|
|
133
|
-
domAndDowRestricted: dom !== '*' && dow !== '*',
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/** Whether a parsed cron matches a specific `Date` to the minute. */
|
|
138
|
-
export function cronMatchesParsed(parsed: ParsedCron, date: Date): boolean {
|
|
139
|
-
if (!parsed.minute.match(date.getMinutes())) return false
|
|
140
|
-
if (!parsed.hour.match(date.getHours())) return false
|
|
141
|
-
if (!parsed.month.match(date.getMonth() + 1)) return false
|
|
142
|
-
const domOk = parsed.dom.match(date.getDate())
|
|
143
|
-
const dowOk = parsed.dow.match(date.getDay())
|
|
144
|
-
// Standard cron semantics: when both day fields are restricted the match is
|
|
145
|
-
// the UNION (fires if either matches); otherwise plain AND.
|
|
146
|
-
return parsed.domAndDowRestricted ? domOk || dowOk : domOk && dowOk
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/** Whether a cron expression matches a `Date` to the minute. */
|
|
150
|
-
export function cronMatches(expr: string, date: Date): boolean {
|
|
151
|
-
return cronMatchesParsed(parseCron(expr), date)
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/** Two dates fall in the same wall-clock minute. */
|
|
155
|
-
function sameMinute(a: Date, b: Date): boolean {
|
|
156
|
-
return (
|
|
157
|
-
a.getFullYear() === b.getFullYear() &&
|
|
158
|
-
a.getMonth() === b.getMonth() &&
|
|
159
|
-
a.getDate() === b.getDate() &&
|
|
160
|
-
a.getHours() === b.getHours() &&
|
|
161
|
-
a.getMinutes() === b.getMinutes()
|
|
162
|
-
)
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/** Whether a schedule is due to fire during the minute containing `date`. */
|
|
166
|
-
export function isScheduleDue(schedule: Schedule, date: Date): boolean {
|
|
167
|
-
if (schedule.enabled === false) return false
|
|
168
|
-
if (schedule.runAt) {
|
|
169
|
-
const at = new Date(schedule.runAt)
|
|
170
|
-
return !Number.isNaN(at.getTime()) && sameMinute(at, date)
|
|
171
|
-
}
|
|
172
|
-
if (schedule.cron) return cronMatches(schedule.cron, date)
|
|
173
|
-
return false
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* The next `Date` (to the minute) at or after `from` that `schedule` fires,
|
|
178
|
-
* or `null` if it never will again (past one-off, or no match within a year).
|
|
179
|
-
* Handy for a "next run" column in a schedules panel.
|
|
180
|
-
*/
|
|
181
|
-
export function nextRun(schedule: Schedule, from: Date): Date | null {
|
|
182
|
-
if (schedule.enabled === false) return null
|
|
183
|
-
if (schedule.runAt) {
|
|
184
|
-
const at = new Date(schedule.runAt)
|
|
185
|
-
if (Number.isNaN(at.getTime())) return null
|
|
186
|
-
// Compare at minute granularity - a runAt in the current minute is "now".
|
|
187
|
-
const floor = new Date(from)
|
|
188
|
-
floor.setSeconds(0, 0)
|
|
189
|
-
return at.getTime() >= floor.getTime() ? at : null
|
|
190
|
-
}
|
|
191
|
-
if (!schedule.cron) return null
|
|
192
|
-
const parsed = parseCron(schedule.cron)
|
|
193
|
-
const cursor = new Date(from)
|
|
194
|
-
cursor.setSeconds(0, 0)
|
|
195
|
-
// Scan minute-by-minute for up to ~366 days (527040 minutes).
|
|
196
|
-
for (let i = 0; i < 527_040; i += 1) {
|
|
197
|
-
if (cronMatchesParsed(parsed, cursor)) return new Date(cursor)
|
|
198
|
-
cursor.setMinutes(cursor.getMinutes() + 1)
|
|
199
|
-
}
|
|
200
|
-
return null
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
export type SchedulerOptions = {
|
|
204
|
-
/** The schedules to run. Read once per tick, so you may mutate the array. */
|
|
205
|
-
schedules: ReadonlyArray<Schedule>
|
|
206
|
-
/** Called when a schedule comes due. Receives the schedule + the fire time. */
|
|
207
|
-
onFire: (schedule: Schedule, firedAt: Date) => void
|
|
208
|
-
/**
|
|
209
|
-
* Clock source, injectable for tests. Default `() => new Date()`.
|
|
210
|
-
*/
|
|
211
|
-
now?: () => Date
|
|
212
|
-
/**
|
|
213
|
-
* How often to check, in ms. Default 30_000 (twice a minute) so a fire is
|
|
214
|
-
* never more than ~30s late; per-minute dedupe keeps it firing once.
|
|
215
|
-
*/
|
|
216
|
-
intervalMs?: number
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
export type Scheduler = {
|
|
220
|
-
/** Begin ticking. No-op if already started. */
|
|
221
|
-
start: () => void
|
|
222
|
-
/** Stop ticking and clear the timer. */
|
|
223
|
-
stop: () => void
|
|
224
|
-
/**
|
|
225
|
-
* Run one check against `at` (default now) and fire anything due. Exposed for
|
|
226
|
-
* tests and for a "run due now" button; the internal tick calls this too.
|
|
227
|
-
*/
|
|
228
|
-
tick: (at?: Date) => void
|
|
229
|
-
/** Upcoming fire time per schedule id, from `at` (default now). */
|
|
230
|
-
upcoming: (at?: Date) => Array<{ id: string; at: Date | null }>
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* A client-side scheduler: ticks on an interval, fires `onFire` for every
|
|
235
|
-
* schedule due in the current minute, and guarantees at most one fire per
|
|
236
|
-
* schedule per minute (and exactly one, ever, for a one-off).
|
|
237
|
-
*/
|
|
238
|
-
export function createScheduler(options: SchedulerOptions): Scheduler {
|
|
239
|
-
const now = options.now ?? (() => new Date())
|
|
240
|
-
const intervalMs = options.intervalMs ?? 30_000
|
|
241
|
-
// Per-schedule guard: the minute-key we last fired, so a twice-a-minute tick
|
|
242
|
-
// (or a manual tick) never double-fires the same minute. One-offs are marked
|
|
243
|
-
// done so they never fire again even across minutes.
|
|
244
|
-
const lastFiredKey = new Map<string, string>()
|
|
245
|
-
const oneOffDone = new Set<string>()
|
|
246
|
-
let timer: ReturnType<typeof setInterval> | null = null
|
|
247
|
-
|
|
248
|
-
const minuteKey = (d: Date) =>
|
|
249
|
-
`${d.getFullYear()}-${d.getMonth()}-${d.getDate()}-${d.getHours()}-${d.getMinutes()}`
|
|
250
|
-
|
|
251
|
-
function tick(at: Date = now()): void {
|
|
252
|
-
const key = minuteKey(at)
|
|
253
|
-
for (const schedule of options.schedules) {
|
|
254
|
-
if (schedule.enabled === false) continue
|
|
255
|
-
const oneOff = !!schedule.runAt
|
|
256
|
-
if (oneOff && oneOffDone.has(schedule.id)) continue
|
|
257
|
-
if (lastFiredKey.get(schedule.id) === key) continue
|
|
258
|
-
if (!isScheduleDue(schedule, at)) continue
|
|
259
|
-
lastFiredKey.set(schedule.id, key)
|
|
260
|
-
if (oneOff) oneOffDone.add(schedule.id)
|
|
261
|
-
options.onFire(schedule, at)
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
return {
|
|
266
|
-
start() {
|
|
267
|
-
if (timer != null) return
|
|
268
|
-
timer = setInterval(() => tick(), intervalMs)
|
|
269
|
-
},
|
|
270
|
-
stop() {
|
|
271
|
-
if (timer != null) {
|
|
272
|
-
clearInterval(timer)
|
|
273
|
-
timer = null
|
|
274
|
-
}
|
|
275
|
-
},
|
|
276
|
-
tick,
|
|
277
|
-
upcoming(at: Date = now()) {
|
|
278
|
-
return options.schedules.map((s) => ({ id: s.id, at: nextRun(s, at) }))
|
|
279
|
-
},
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/** A few common cron expressions, for docs, presets, and pickers. */
|
|
284
|
-
export const CRON_PRESETS: ReadonlyArray<{ label: string; cron: string }> = [
|
|
285
|
-
{ label: 'Every minute', cron: '* * * * *' },
|
|
286
|
-
{ label: 'Every 15 minutes', cron: '*/15 * * * *' },
|
|
287
|
-
{ label: 'Hourly, on the hour', cron: '0 * * * *' },
|
|
288
|
-
{ label: 'Every weekday at 09:00', cron: '0 9 * * 1-5' },
|
|
289
|
-
{ label: 'Weekdays at 17:30', cron: '30 17 * * 1-5' },
|
|
290
|
-
{ label: 'Daily at midnight', cron: '0 0 * * *' },
|
|
291
|
-
{ label: 'Monday mornings at 08:00', cron: '0 8 * * 1' },
|
|
292
|
-
{ label: 'First of the month at 06:00', cron: '0 6 1 * *' },
|
|
293
|
-
]
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import type { EntitySchema } from './schema'
|
|
3
|
-
import {
|
|
4
|
-
addField,
|
|
5
|
-
blankField,
|
|
6
|
-
isSchemaValid,
|
|
7
|
-
moveField,
|
|
8
|
-
removeField,
|
|
9
|
-
sampleRows,
|
|
10
|
-
updateField,
|
|
11
|
-
validateSchema,
|
|
12
|
-
} from './schema-designer'
|
|
13
|
-
|
|
14
|
-
function base(): EntitySchema {
|
|
15
|
-
return {
|
|
16
|
-
name: 'customers',
|
|
17
|
-
idField: 'id',
|
|
18
|
-
fields: [
|
|
19
|
-
{ field: 'id', type: 'text', primaryKey: true, readonly: true },
|
|
20
|
-
{ field: 'name', type: 'text' },
|
|
21
|
-
{ field: 'tier', type: 'enum', options: [{ value: 'free', label: 'Free' }] },
|
|
22
|
-
],
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
describe('blankField / addField', () => {
|
|
27
|
-
it('adds a uniquely named blank field', () => {
|
|
28
|
-
const s = addField(base())
|
|
29
|
-
expect(s.fields).toHaveLength(4)
|
|
30
|
-
const added = s.fields[3]!
|
|
31
|
-
expect(added.type).toBe('text')
|
|
32
|
-
expect(base().fields.map((f) => f.field)).not.toContain(added.field)
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
it('avoids name collisions', () => {
|
|
36
|
-
const s: EntitySchema = { name: 't', fields: [{ field: 'field1', type: 'text' }] }
|
|
37
|
-
expect(blankField(s).field).not.toBe('field1')
|
|
38
|
-
})
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
describe('removeField', () => {
|
|
42
|
-
it('removes and clears idField if it pointed there', () => {
|
|
43
|
-
const s = removeField(base(), 'id')
|
|
44
|
-
expect(s.fields.map((f) => f.field)).toEqual(['name', 'tier'])
|
|
45
|
-
expect(s.idField).toBeUndefined()
|
|
46
|
-
})
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
describe('updateField', () => {
|
|
50
|
-
it('patches a field', () => {
|
|
51
|
-
const s = updateField(base(), 'name', { label: 'Full Name', required: true })
|
|
52
|
-
const f = s.fields.find((x) => x.field === 'name')!
|
|
53
|
-
expect(f.label).toBe('Full Name')
|
|
54
|
-
expect(f.required).toBe(true)
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
it('enforces a single primary key', () => {
|
|
58
|
-
const s = updateField(base(), 'name', { primaryKey: true })
|
|
59
|
-
expect(s.fields.find((f) => f.field === 'id')!.primaryKey).toBe(false)
|
|
60
|
-
expect(s.fields.find((f) => f.field === 'name')!.primaryKey).toBe(true)
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
it('drops options when a field leaves the enum type', () => {
|
|
64
|
-
const s = updateField(base(), 'tier', { type: 'text' })
|
|
65
|
-
expect(s.fields.find((f) => f.field === 'tier')!.options).toBeUndefined()
|
|
66
|
-
})
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
describe('moveField', () => {
|
|
70
|
-
it('reorders and is a no-op at the ends', () => {
|
|
71
|
-
expect(moveField(base(), 'name', -1).fields.map((f) => f.field)).toEqual(['name', 'id', 'tier'])
|
|
72
|
-
expect(moveField(base(), 'id', -1).fields.map((f) => f.field)).toEqual(['id', 'name', 'tier'])
|
|
73
|
-
})
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
describe('validateSchema', () => {
|
|
77
|
-
it('is clean for a well-formed schema', () => {
|
|
78
|
-
expect(validateSchema(base())).toEqual([])
|
|
79
|
-
expect(isSchemaValid(base())).toBe(true)
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
it('errors on duplicate names', () => {
|
|
83
|
-
const s: EntitySchema = {
|
|
84
|
-
name: 't',
|
|
85
|
-
idField: 'id',
|
|
86
|
-
fields: [{ field: 'id', type: 'text' }, { field: 'id', type: 'number' }],
|
|
87
|
-
}
|
|
88
|
-
expect(validateSchema(s).some((i) => i.level === 'error' && /Duplicate/.test(i.message))).toBe(true)
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
it('errors when no primary key resolves', () => {
|
|
92
|
-
const s: EntitySchema = { name: 't', fields: [{ field: 'x', type: 'text' }] }
|
|
93
|
-
expect(isSchemaValid(s)).toBe(false)
|
|
94
|
-
expect(validateSchema(s).some((i) => /primary key/.test(i.message))).toBe(true)
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
it('warns on an enum with no options and an incomplete relation', () => {
|
|
98
|
-
const s: EntitySchema = {
|
|
99
|
-
name: 't',
|
|
100
|
-
idField: 'id',
|
|
101
|
-
fields: [
|
|
102
|
-
{ field: 'id', type: 'text', primaryKey: true },
|
|
103
|
-
{ field: 'k', type: 'enum' },
|
|
104
|
-
{ field: 'r', type: 'relation' },
|
|
105
|
-
],
|
|
106
|
-
}
|
|
107
|
-
const warnings = validateSchema(s).filter((i) => i.level === 'warning')
|
|
108
|
-
expect(warnings.map((w) => w.field).sort()).toEqual(['k', 'r'])
|
|
109
|
-
})
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
describe('sampleRows', () => {
|
|
113
|
-
it('produces deterministic, type-appropriate sample data', () => {
|
|
114
|
-
const rows = sampleRows(base(), 2)
|
|
115
|
-
expect(rows).toHaveLength(2)
|
|
116
|
-
expect(rows[0]!.tier).toBe('free') // first enum option
|
|
117
|
-
expect(typeof rows[0]!.name).toBe('string')
|
|
118
|
-
// deterministic: same input, same output
|
|
119
|
-
expect(sampleRows(base(), 2)).toEqual(rows)
|
|
120
|
-
})
|
|
121
|
-
})
|
package/src/schema-designer.ts
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Schema-designer logic. The testable core behind `SvSchemaDesigner.svelte`:
|
|
3
|
-
* immutable operations that edit an `EntitySchema` (add / remove / reorder /
|
|
4
|
-
* retype fields, set the primary key), validation of the schema being designed,
|
|
5
|
-
* and sample-row generation for the live grid preview.
|
|
6
|
-
*
|
|
7
|
-
* Pure (no Svelte, no DOM), mirroring the pivot-designer / edit-panel split.
|
|
8
|
-
* Every mutation returns a NEW schema so Svelte reactivity and undo stay simple.
|
|
9
|
-
*/
|
|
10
|
-
import type { EntityField, EntityFieldType, EntitySchema } from './schema'
|
|
11
|
-
import { resolveIdField } from './schema'
|
|
12
|
-
import { generateRows } from './studio/sample-data'
|
|
13
|
-
|
|
14
|
-
/** All field types the designer offers, in menu order. */
|
|
15
|
-
export const FIELD_TYPES: ReadonlyArray<EntityFieldType> = [
|
|
16
|
-
'text',
|
|
17
|
-
'number',
|
|
18
|
-
'boolean',
|
|
19
|
-
'date',
|
|
20
|
-
'dateString',
|
|
21
|
-
'datetime',
|
|
22
|
-
'enum',
|
|
23
|
-
'relation',
|
|
24
|
-
'json',
|
|
25
|
-
]
|
|
26
|
-
|
|
27
|
-
/** A fresh field with a name unique within the schema. */
|
|
28
|
-
export function blankField(schema: EntitySchema): EntityField {
|
|
29
|
-
const taken = new Set(schema.fields.map((f) => f.field))
|
|
30
|
-
let n = schema.fields.length + 1
|
|
31
|
-
let name = `field${n}`
|
|
32
|
-
while (taken.has(name)) name = `field${++n}`
|
|
33
|
-
return { field: name, type: 'text' }
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/** Append a field (a blank one when none is given). */
|
|
37
|
-
export function addField(schema: EntitySchema, field?: EntityField): EntitySchema {
|
|
38
|
-
return { ...schema, fields: [...schema.fields, field ?? blankField(schema)] }
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/** Remove a field by name. Clears `idField` if it pointed at the removed field. */
|
|
42
|
-
export function removeField(schema: EntitySchema, fieldName: string): EntitySchema {
|
|
43
|
-
const fields = schema.fields.filter((f) => f.field !== fieldName)
|
|
44
|
-
const idField = schema.idField === fieldName ? undefined : schema.idField
|
|
45
|
-
return { ...schema, fields, idField }
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Patch a field by name. Setting `primaryKey: true` clears it on every other
|
|
50
|
-
* field (a schema has at most one). Switching `type` drops now-irrelevant
|
|
51
|
-
* `options` (leaving enum) / `relation` (leaving relation).
|
|
52
|
-
*/
|
|
53
|
-
export function updateField(
|
|
54
|
-
schema: EntitySchema,
|
|
55
|
-
fieldName: string,
|
|
56
|
-
patch: Partial<EntityField>,
|
|
57
|
-
): EntitySchema {
|
|
58
|
-
const makesPrimary = patch.primaryKey === true
|
|
59
|
-
const fields = schema.fields.map((f) => {
|
|
60
|
-
if (f.field !== fieldName) {
|
|
61
|
-
return makesPrimary && f.primaryKey ? { ...f, primaryKey: false } : f
|
|
62
|
-
}
|
|
63
|
-
const next: EntityField = { ...f, ...patch }
|
|
64
|
-
if (patch.type && patch.type !== f.type) {
|
|
65
|
-
if (patch.type !== 'enum') delete next.options
|
|
66
|
-
if (patch.type !== 'relation') delete next.relation
|
|
67
|
-
}
|
|
68
|
-
return next
|
|
69
|
-
})
|
|
70
|
-
return { ...schema, fields }
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/** Move a field one slot up (`-1`) or down (`+1`). No-op at the ends. */
|
|
74
|
-
export function moveField(schema: EntitySchema, fieldName: string, dir: -1 | 1): EntitySchema {
|
|
75
|
-
const i = schema.fields.findIndex((f) => f.field === fieldName)
|
|
76
|
-
const j = i + dir
|
|
77
|
-
if (i < 0 || j < 0 || j >= schema.fields.length) return schema
|
|
78
|
-
const fields = [...schema.fields]
|
|
79
|
-
const a = fields[i]!
|
|
80
|
-
const b = fields[j]!
|
|
81
|
-
fields[i] = b
|
|
82
|
-
fields[j] = a
|
|
83
|
-
return { ...schema, fields }
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export type SchemaIssueLevel = 'error' | 'warning'
|
|
87
|
-
export type SchemaIssue = { level: SchemaIssueLevel; message: string; field?: string }
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Validate the schema under construction. Errors block code generation;
|
|
91
|
-
* warnings are advisory. Covers: at least one field, unique field names, a
|
|
92
|
-
* resolvable primary key, enums with options, and complete relations.
|
|
93
|
-
*/
|
|
94
|
-
export function validateSchema(schema: EntitySchema): SchemaIssue[] {
|
|
95
|
-
const issues: SchemaIssue[] = []
|
|
96
|
-
|
|
97
|
-
if (schema.fields.length === 0) {
|
|
98
|
-
issues.push({ level: 'error', message: 'Add at least one field.' })
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const seen = new Set<string>()
|
|
102
|
-
for (const f of schema.fields) {
|
|
103
|
-
if (!f.field.trim()) {
|
|
104
|
-
issues.push({ level: 'error', message: 'A field has an empty name.' })
|
|
105
|
-
} else if (seen.has(f.field)) {
|
|
106
|
-
issues.push({ level: 'error', message: `Duplicate field name "${f.field}".`, field: f.field })
|
|
107
|
-
}
|
|
108
|
-
seen.add(f.field)
|
|
109
|
-
|
|
110
|
-
if (f.type === 'enum' && (!f.options || f.options.length === 0)) {
|
|
111
|
-
issues.push({ level: 'warning', message: `Enum "${f.field}" has no options.`, field: f.field })
|
|
112
|
-
}
|
|
113
|
-
if (f.type === 'relation' && (!f.relation?.entity || !f.relation?.labelField)) {
|
|
114
|
-
issues.push({
|
|
115
|
-
level: 'warning',
|
|
116
|
-
message: `Relation "${f.field}" needs a related entity and label field.`,
|
|
117
|
-
field: f.field,
|
|
118
|
-
})
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
try {
|
|
123
|
-
resolveIdField(schema)
|
|
124
|
-
} catch {
|
|
125
|
-
issues.push({
|
|
126
|
-
level: 'error',
|
|
127
|
-
message: 'No primary key: flag a field as primary key, set idField, or name a field "id".',
|
|
128
|
-
})
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return issues
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/** True when the schema has no error-level issues (warnings are allowed). */
|
|
135
|
-
export function isSchemaValid(schema: EntitySchema): boolean {
|
|
136
|
-
return !validateSchema(schema).some((i) => i.level === 'error')
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/** Deterministic, realistic sample rows for the designer's grid preview. */
|
|
140
|
-
export function sampleRows(schema: EntitySchema, count = 3): Array<Record<string, unknown>> {
|
|
141
|
-
return generateRows(schema.fields, count)
|
|
142
|
-
}
|