@svgrid/enterprise 2.5.3 → 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 +1 -1
- package/dist/designer/assets/{index-CBYU-KNn.js → index-BF0UH638.js} +3 -3
- package/dist/designer/assets/{src-i309BeJb.js → src-BPJruwB9.js} +1 -1
- 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 -144
- package/src/license.ts +0 -157
- 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,111 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import { evaluatePredicate, evaluateScalar, evaluateChange } from './evaluate'
|
|
3
|
-
import type { ChangeExpr, EvalContext, PredicateExpr, ScalarExpr } from './expression-types'
|
|
4
|
-
|
|
5
|
-
type Row = { price: number; qty: number; name: string; region: string }
|
|
6
|
-
|
|
7
|
-
const row: Row = { price: 120, qty: 3, name: 'Widget', region: 'EU' }
|
|
8
|
-
const ctx = (r: Row, extra: Partial<EvalContext<Row>> = {}): EvalContext<Row> => ({ row: r, ...extra })
|
|
9
|
-
|
|
10
|
-
describe('evaluateScalar', () => {
|
|
11
|
-
it('reads columns, literals and arithmetic', () => {
|
|
12
|
-
const total: ScalarExpr = { kind: 'bin', op: '*', left: { kind: 'col', id: 'price' }, right: { kind: 'col', id: 'qty' } }
|
|
13
|
-
expect(evaluateScalar(total, ctx(row))).toBe(360)
|
|
14
|
-
expect(evaluateScalar({ kind: 'lit', value: 5 }, ctx(row))).toBe(5)
|
|
15
|
-
expect(evaluateScalar({ kind: 'neg', expr: { kind: 'col', id: 'price' } }, ctx(row))).toBe(-120)
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
it('concatenates strings with +', () => {
|
|
19
|
-
const e: ScalarExpr = { kind: 'bin', op: '+', left: { kind: 'col', id: 'name' }, right: { kind: 'lit', value: '!' } }
|
|
20
|
-
expect(evaluateScalar(e, ctx(row))).toBe('Widget!')
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
it('guards divide by zero', () => {
|
|
24
|
-
const e: ScalarExpr = { kind: 'bin', op: '/', left: { kind: 'lit', value: 10 }, right: { kind: 'lit', value: 0 } }
|
|
25
|
-
expect(Number.isNaN(evaluateScalar(e, ctx(row)) as number)).toBe(true)
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
it('runs built-in functions', () => {
|
|
29
|
-
expect(evaluateScalar({ kind: 'func', name: 'ABS', args: [{ kind: 'lit', value: -7 }] }, ctx(row))).toBe(7)
|
|
30
|
-
expect(evaluateScalar({ kind: 'func', name: 'ROUND', args: [{ kind: 'lit', value: 3.14159 }, { kind: 'lit', value: 2 }] }, ctx(row))).toBe(3.14)
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
it('aggregates over the row set in scope', () => {
|
|
34
|
-
const rows: Row[] = [row, { ...row, price: 80 }, { ...row, price: 40 }]
|
|
35
|
-
const sum: ScalarExpr = { kind: 'agg', fn: 'sum', column: 'price' }
|
|
36
|
-
expect(evaluateScalar(sum, ctx(row, { rows }))).toBe(240)
|
|
37
|
-
expect(evaluateScalar({ kind: 'agg', fn: 'avg', column: 'price' }, ctx(row, { rows }))).toBe(80)
|
|
38
|
-
expect(evaluateScalar({ kind: 'agg', fn: 'count', column: 'price' }, ctx(row, { rows }))).toBe(3)
|
|
39
|
-
})
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
describe('evaluatePredicate', () => {
|
|
43
|
-
it('cmp delegates to applyExcelFilter semantics', () => {
|
|
44
|
-
const gt: PredicateExpr = { kind: 'cmp', column: 'price', op: 'greaterThan', value: 100 }
|
|
45
|
-
expect(evaluatePredicate(gt, ctx(row))).toBe(true)
|
|
46
|
-
expect(evaluatePredicate(gt, ctx({ ...row, price: 50 }))).toBe(false)
|
|
47
|
-
|
|
48
|
-
const contains: PredicateExpr = { kind: 'cmp', column: 'name', op: 'contains', value: 'idge' }
|
|
49
|
-
expect(evaluatePredicate(contains, ctx(row))).toBe(true)
|
|
50
|
-
|
|
51
|
-
const inSet: PredicateExpr = { kind: 'cmp', column: 'region', op: 'in', value: ['EU', 'US'] }
|
|
52
|
-
expect(evaluatePredicate(inSet, ctx(row))).toBe(true)
|
|
53
|
-
expect(evaluatePredicate(inSet, ctx({ ...row, region: 'APAC' }))).toBe(false)
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
it('combines with and/or/not', () => {
|
|
57
|
-
const expr: PredicateExpr = {
|
|
58
|
-
kind: 'and',
|
|
59
|
-
parts: [
|
|
60
|
-
{ kind: 'cmp', column: 'price', op: 'greaterThan', value: 100 },
|
|
61
|
-
{ kind: 'not', expr: { kind: 'cmp', column: 'region', op: 'equals', value: 'US' } },
|
|
62
|
-
],
|
|
63
|
-
}
|
|
64
|
-
expect(evaluatePredicate(expr, ctx(row))).toBe(true)
|
|
65
|
-
expect(evaluatePredicate(expr, ctx({ ...row, region: 'US' }))).toBe(false)
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
it('scalarCmp compares cross-column maths', () => {
|
|
69
|
-
// price / qty >= 40 -> 120/3 = 40 -> true
|
|
70
|
-
const expr: PredicateExpr = {
|
|
71
|
-
kind: 'scalarCmp',
|
|
72
|
-
left: { kind: 'bin', op: '/', left: { kind: 'col', id: 'price' }, right: { kind: 'col', id: 'qty' } },
|
|
73
|
-
op: '>=',
|
|
74
|
-
right: { kind: 'lit', value: 40 },
|
|
75
|
-
}
|
|
76
|
-
expect(evaluatePredicate(expr, ctx(row))).toBe(true)
|
|
77
|
-
expect(evaluatePredicate(expr, ctx({ ...row, qty: 4 }))).toBe(false)
|
|
78
|
-
})
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
describe('evaluateChange', () => {
|
|
82
|
-
const change = (e: ChangeExpr, prev: Row, next: Row) => evaluateChange(e, ctx(next, { prev }))
|
|
83
|
-
|
|
84
|
-
it('detects a bare change', () => {
|
|
85
|
-
expect(change({ kind: 'changed', column: 'price' }, row, { ...row, price: 121 })).toBe(true)
|
|
86
|
-
expect(change({ kind: 'changed', column: 'price' }, row, { ...row })).toBe(false)
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
it('returns false with no prior snapshot', () => {
|
|
90
|
-
expect(evaluateChange({ kind: 'changed', column: 'price' }, ctx(row))).toBe(false)
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
it('tests absolute delta', () => {
|
|
94
|
-
const e: ChangeExpr = { kind: 'delta', column: 'price', op: '>', value: 10, abs: true }
|
|
95
|
-
expect(change(e, row, { ...row, price: 140 })).toBe(true)
|
|
96
|
-
expect(change(e, row, { ...row, price: 100 })).toBe(true) // abs of -20
|
|
97
|
-
expect(change(e, row, { ...row, price: 125 })).toBe(false)
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
it('tests percent change', () => {
|
|
101
|
-
const e: ChangeExpr = { kind: 'percentChange', column: 'price', op: '>', value: 5, abs: true }
|
|
102
|
-
expect(change(e, row, { ...row, price: 132 })).toBe(true) // +10%
|
|
103
|
-
expect(change(e, row, { ...row, price: 123 })).toBe(false) // +2.5%
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
it('detects threshold crossing', () => {
|
|
107
|
-
const above: ChangeExpr = { kind: 'crossed', column: 'price', threshold: 130, direction: 'above' }
|
|
108
|
-
expect(change(above, row, { ...row, price: 135 })).toBe(true)
|
|
109
|
-
expect(change(above, { ...row, price: 131 }, { ...row, price: 140 })).toBe(false) // already above
|
|
110
|
-
})
|
|
111
|
-
})
|
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Expression evaluators - pure functions, no DOM. Predicate leaves delegate to
|
|
3
|
-
* the grid's `applyExcelFilter` so operator semantics match the filter row
|
|
4
|
-
* exactly; scalar maths and change detection are handled here.
|
|
5
|
-
*/
|
|
6
|
-
import { applyExcelFilter } from '@svgrid/grid/filtering'
|
|
7
|
-
import type {
|
|
8
|
-
ChangeExpr,
|
|
9
|
-
ComparisonOp,
|
|
10
|
-
EvalContext,
|
|
11
|
-
ExprRow,
|
|
12
|
-
PredicateExpr,
|
|
13
|
-
ScalarExpr,
|
|
14
|
-
} from './expression-types.js'
|
|
15
|
-
|
|
16
|
-
type Scalar = number | string | boolean | null
|
|
17
|
-
|
|
18
|
-
function readValue<TData>(ctx: EvalContext<TData>, row: TData, columnId: string): unknown {
|
|
19
|
-
if (ctx.getValue) return ctx.getValue(row, columnId)
|
|
20
|
-
return (row as Record<string, unknown>)?.[columnId]
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/** Number coercion that returns NaN for blanks/non-numerics (never 0). */
|
|
24
|
-
function num(v: unknown): number {
|
|
25
|
-
if (v == null || v === '') return NaN
|
|
26
|
-
if (typeof v === 'boolean') return v ? 1 : 0
|
|
27
|
-
return Number(v)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/** Loose value equality used by `changed` and `=` on non-numeric operands. */
|
|
31
|
-
function looseEqual(a: unknown, b: unknown): boolean {
|
|
32
|
-
if (a == null && b == null) return true
|
|
33
|
-
const na = num(a)
|
|
34
|
-
const nb = num(b)
|
|
35
|
-
if (Number.isFinite(na) && Number.isFinite(nb)) return na === nb
|
|
36
|
-
return String(a ?? '') === String(b ?? '')
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const BUILTINS: Record<string, (args: Scalar[]) => Scalar> = {
|
|
40
|
-
ABS: (a) => Math.abs(num(a[0])),
|
|
41
|
-
ROUND: (a) => {
|
|
42
|
-
const n = num(a[0])
|
|
43
|
-
const d = a.length > 1 ? num(a[1]) : 0
|
|
44
|
-
const f = 10 ** (Number.isFinite(d) ? d : 0)
|
|
45
|
-
return Math.round(n * f) / f
|
|
46
|
-
},
|
|
47
|
-
FLOOR: (a) => Math.floor(num(a[0])),
|
|
48
|
-
CEIL: (a) => Math.ceil(num(a[0])),
|
|
49
|
-
MIN: (a) => Math.min(...a.map(num)),
|
|
50
|
-
MAX: (a) => Math.max(...a.map(num)),
|
|
51
|
-
IF: (a) => (truthy(a[0] ?? null) ? (a[1] ?? null) : (a[2] ?? null)),
|
|
52
|
-
COALESCE: (a) => a.find((v) => v != null && v !== '') ?? null,
|
|
53
|
-
CONCAT: (a) => a.map((v) => (v == null ? '' : String(v))).join(''),
|
|
54
|
-
LOWER: (a) => String(a[0] ?? '').toLowerCase(),
|
|
55
|
-
UPPER: (a) => String(a[0] ?? '').toUpperCase(),
|
|
56
|
-
LEN: (a) => String(a[0] ?? '').length,
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/** Names of the built-in scalar functions (for editor validation/autocomplete). */
|
|
60
|
-
export const BUILTIN_FUNCTION_NAMES: ReadonlyArray<string> = Object.keys(BUILTINS)
|
|
61
|
-
|
|
62
|
-
/** Whether `name` (any case) is a known built-in scalar function. */
|
|
63
|
-
export function isBuiltinFunction(name: string): boolean {
|
|
64
|
-
return name.toUpperCase() in BUILTINS
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function truthy(v: Scalar): boolean {
|
|
68
|
-
if (typeof v === 'boolean') return v
|
|
69
|
-
if (v == null || v === '') return false
|
|
70
|
-
const n = num(v)
|
|
71
|
-
return Number.isFinite(n) ? n !== 0 : true
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/** Evaluate a scalar expression to a single value. */
|
|
75
|
-
export function evaluateScalar<TData = ExprRow>(
|
|
76
|
-
expr: ScalarExpr,
|
|
77
|
-
ctx: EvalContext<TData>,
|
|
78
|
-
): Scalar {
|
|
79
|
-
switch (expr.kind) {
|
|
80
|
-
case 'lit':
|
|
81
|
-
return expr.value
|
|
82
|
-
case 'col':
|
|
83
|
-
return (readValue(ctx, ctx.row, expr.id) ?? null) as Scalar
|
|
84
|
-
case 'neg':
|
|
85
|
-
return -num(evaluateScalar(expr.expr, ctx))
|
|
86
|
-
case 'bin': {
|
|
87
|
-
const l = evaluateScalar(expr.left, ctx)
|
|
88
|
-
const r = evaluateScalar(expr.right, ctx)
|
|
89
|
-
if (expr.op === '+') {
|
|
90
|
-
const ln = num(l)
|
|
91
|
-
const rn = num(r)
|
|
92
|
-
if (Number.isFinite(ln) && Number.isFinite(rn)) return ln + rn
|
|
93
|
-
return String(l ?? '') + String(r ?? '')
|
|
94
|
-
}
|
|
95
|
-
const a = num(l)
|
|
96
|
-
const b = num(r)
|
|
97
|
-
switch (expr.op) {
|
|
98
|
-
case '-':
|
|
99
|
-
return a - b
|
|
100
|
-
case '*':
|
|
101
|
-
return a * b
|
|
102
|
-
case '/':
|
|
103
|
-
return b === 0 ? NaN : a / b
|
|
104
|
-
case '%':
|
|
105
|
-
return b === 0 ? NaN : a % b
|
|
106
|
-
// Rules are authored at runtime, so an operator outside the union can
|
|
107
|
-
// arrive from parsed JSON. Without this the switch falls out of its
|
|
108
|
-
// case and into `case 'agg'`, reading agg fields off a binary node.
|
|
109
|
-
default:
|
|
110
|
-
return null
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
case 'agg': {
|
|
114
|
-
const rows = ctx.rows ?? [ctx.row]
|
|
115
|
-
if (expr.fn === 'count') return rows.length
|
|
116
|
-
const nums: number[] = []
|
|
117
|
-
for (const row of rows) {
|
|
118
|
-
const n = num(readValue(ctx, row, expr.column))
|
|
119
|
-
if (Number.isFinite(n)) nums.push(n)
|
|
120
|
-
}
|
|
121
|
-
if (nums.length === 0) return expr.fn === 'sum' ? 0 : null
|
|
122
|
-
switch (expr.fn) {
|
|
123
|
-
case 'sum':
|
|
124
|
-
return nums.reduce((s, n) => s + n, 0)
|
|
125
|
-
case 'avg':
|
|
126
|
-
return nums.reduce((s, n) => s + n, 0) / nums.length
|
|
127
|
-
case 'min':
|
|
128
|
-
return Math.min(...nums)
|
|
129
|
-
case 'max':
|
|
130
|
-
return Math.max(...nums)
|
|
131
|
-
// Same here: falling through to `case 'func'` would call
|
|
132
|
-
// `expr.name.toUpperCase()` on an agg node and throw.
|
|
133
|
-
default:
|
|
134
|
-
return null
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
case 'func': {
|
|
138
|
-
const name = expr.name.toUpperCase()
|
|
139
|
-
const args = expr.args.map((a) => evaluateScalar(a, ctx))
|
|
140
|
-
const fn = ctx.functions?.[name] ?? BUILTINS[name]
|
|
141
|
-
return fn ? fn(args) : null
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
function compareScalar(a: Scalar, op: ComparisonOp, b: Scalar): boolean {
|
|
147
|
-
switch (op) {
|
|
148
|
-
case '=':
|
|
149
|
-
return looseEqual(a, b)
|
|
150
|
-
case '!=':
|
|
151
|
-
return !looseEqual(a, b)
|
|
152
|
-
}
|
|
153
|
-
const na = num(a)
|
|
154
|
-
const nb = num(b)
|
|
155
|
-
const numeric = Number.isFinite(na) && Number.isFinite(nb)
|
|
156
|
-
const x: number | string = numeric ? na : String(a ?? '')
|
|
157
|
-
const y: number | string = numeric ? nb : String(b ?? '')
|
|
158
|
-
switch (op) {
|
|
159
|
-
case '>':
|
|
160
|
-
return x > y
|
|
161
|
-
case '<':
|
|
162
|
-
return x < y
|
|
163
|
-
case '>=':
|
|
164
|
-
return x >= y
|
|
165
|
-
case '<=':
|
|
166
|
-
return x <= y
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/** Evaluate a predicate expression to a boolean for the context's row. */
|
|
171
|
-
export function evaluatePredicate<TData = ExprRow>(
|
|
172
|
-
expr: PredicateExpr,
|
|
173
|
-
ctx: EvalContext<TData>,
|
|
174
|
-
): boolean {
|
|
175
|
-
switch (expr.kind) {
|
|
176
|
-
case 'const':
|
|
177
|
-
return expr.value
|
|
178
|
-
case 'and':
|
|
179
|
-
return expr.parts.every((p) => evaluatePredicate(p, ctx))
|
|
180
|
-
case 'or':
|
|
181
|
-
return expr.parts.some((p) => evaluatePredicate(p, ctx))
|
|
182
|
-
case 'not':
|
|
183
|
-
return !evaluatePredicate(expr.expr, ctx)
|
|
184
|
-
case 'cmp':
|
|
185
|
-
return applyExcelFilter(
|
|
186
|
-
readValue(ctx, ctx.row, expr.column),
|
|
187
|
-
{ id: expr.column, operator: expr.op, value: expr.value, valueTo: expr.valueTo },
|
|
188
|
-
{ locale: ctx.locale },
|
|
189
|
-
) as boolean
|
|
190
|
-
case 'scalarCmp':
|
|
191
|
-
return compareScalar(
|
|
192
|
-
evaluateScalar(expr.left, ctx),
|
|
193
|
-
expr.op,
|
|
194
|
-
evaluateScalar(expr.right, ctx),
|
|
195
|
-
)
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Evaluate a change expression - true when the value moved between `ctx.prev`
|
|
201
|
-
* and `ctx.row` in the way the expression describes. Returns false when there
|
|
202
|
-
* is no prior snapshot (nothing has changed yet).
|
|
203
|
-
*/
|
|
204
|
-
export function evaluateChange<TData = ExprRow>(
|
|
205
|
-
expr: ChangeExpr,
|
|
206
|
-
ctx: EvalContext<TData>,
|
|
207
|
-
): boolean {
|
|
208
|
-
if (ctx.prev == null) return false
|
|
209
|
-
const next = readValue(ctx, ctx.row, expr.column)
|
|
210
|
-
const prev = readValue(ctx, ctx.prev, expr.column)
|
|
211
|
-
switch (expr.kind) {
|
|
212
|
-
case 'changed':
|
|
213
|
-
return !looseEqual(prev, next)
|
|
214
|
-
case 'delta': {
|
|
215
|
-
const p = num(prev)
|
|
216
|
-
const n = num(next)
|
|
217
|
-
if (!Number.isFinite(p) || !Number.isFinite(n)) return false
|
|
218
|
-
const d = expr.abs ? Math.abs(n - p) : n - p
|
|
219
|
-
return compareScalar(d, expr.op, expr.value)
|
|
220
|
-
}
|
|
221
|
-
case 'percentChange': {
|
|
222
|
-
const p = num(prev)
|
|
223
|
-
const n = num(next)
|
|
224
|
-
if (!Number.isFinite(p) || !Number.isFinite(n) || p === 0) return false
|
|
225
|
-
const pc = ((n - p) / Math.abs(p)) * 100
|
|
226
|
-
return compareScalar(expr.abs ? Math.abs(pc) : pc, expr.op, expr.value)
|
|
227
|
-
}
|
|
228
|
-
case 'crossed': {
|
|
229
|
-
const p = num(prev)
|
|
230
|
-
const n = num(next)
|
|
231
|
-
if (!Number.isFinite(p) || !Number.isFinite(n)) return false
|
|
232
|
-
return expr.direction === 'above'
|
|
233
|
-
? p < expr.threshold && n >= expr.threshold
|
|
234
|
-
: p > expr.threshold && n <= expr.threshold
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Column metadata for the expression layer - the small, self-contained operator
|
|
3
|
-
* catalogue the editor draws from, plus name <-> id resolution for the
|
|
4
|
-
* `[Bracketed Name]` reference syntax.
|
|
5
|
-
*
|
|
6
|
-
* The operator set mirrors the grid's own filter row (text / number / date),
|
|
7
|
-
* so an expression's operators line up with what a user already knows from the
|
|
8
|
-
* column menu. We keep a local copy rather than importing the grid's internal
|
|
9
|
-
* `filter-operators` module (which is not part of the public surface).
|
|
10
|
-
*/
|
|
11
|
-
import type { ExcelFilterOperator } from '@svgrid/grid'
|
|
12
|
-
|
|
13
|
-
/** Coarse value type used to decide which operators a column offers. */
|
|
14
|
-
export type ExprColumnType = 'text' | 'number' | 'date' | 'datetime' | 'boolean'
|
|
15
|
-
|
|
16
|
-
/** A column as the expression layer sees it. */
|
|
17
|
-
export type ExprColumn = {
|
|
18
|
-
/** Canonical id (the field key stored in the AST). */
|
|
19
|
-
id: string
|
|
20
|
-
/** Human label; also the token used inside `[Bracketed Name]` references. */
|
|
21
|
-
name?: string
|
|
22
|
-
type?: ExprColumnType
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/** One operator entry: its label and which column types it applies to. */
|
|
26
|
-
export type OperatorMeta = {
|
|
27
|
-
value: ExcelFilterOperator
|
|
28
|
-
label: string
|
|
29
|
-
types: ReadonlyArray<ExprColumnType>
|
|
30
|
-
/** No value input (acts on emptiness alone). */
|
|
31
|
-
valueless?: boolean
|
|
32
|
-
/** Multi-value set membership (renders a token/chip input). */
|
|
33
|
-
set?: boolean
|
|
34
|
-
/** Needs a second value (`valueTo`). */
|
|
35
|
-
range?: boolean
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const TEXT: ExprColumnType[] = ['text']
|
|
39
|
-
const NUM: ExprColumnType[] = ['number']
|
|
40
|
-
const DATES: ExprColumnType[] = ['date', 'datetime']
|
|
41
|
-
const ALL: ExprColumnType[] = ['text', 'number', 'date', 'datetime', 'boolean']
|
|
42
|
-
|
|
43
|
-
/** The full operator catalogue, ordered as the editor should present it. */
|
|
44
|
-
export const OPERATORS: ReadonlyArray<OperatorMeta> = [
|
|
45
|
-
{ value: 'equals', label: 'Equals', types: ALL },
|
|
46
|
-
{ value: 'notEquals', label: 'Not equals', types: ALL },
|
|
47
|
-
{ value: 'contains', label: 'Contains', types: TEXT },
|
|
48
|
-
{ value: 'notContains', label: 'Not contains', types: TEXT },
|
|
49
|
-
{ value: 'startsWith', label: 'Starts with', types: TEXT },
|
|
50
|
-
{ value: 'endsWith', label: 'Ends with', types: TEXT },
|
|
51
|
-
{ value: 'regex', label: 'Matches regex', types: TEXT },
|
|
52
|
-
{ value: 'greaterThan', label: 'Greater than', types: [...NUM, ...DATES] },
|
|
53
|
-
{ value: 'lessThan', label: 'Less than', types: [...NUM, ...DATES] },
|
|
54
|
-
{ value: 'between', label: 'Between', types: [...NUM, ...DATES], range: true },
|
|
55
|
-
{ value: 'in', label: 'In', types: ['text', 'number'], set: true },
|
|
56
|
-
{ value: 'notIn', label: 'Not in', types: ['text', 'number'], set: true },
|
|
57
|
-
{ value: 'isBlank', label: 'Is blank', types: ALL, valueless: true },
|
|
58
|
-
{ value: 'isNotBlank', label: 'Is not blank', types: ALL, valueless: true },
|
|
59
|
-
]
|
|
60
|
-
|
|
61
|
-
const BY_VALUE = new Map<ExcelFilterOperator, OperatorMeta>(
|
|
62
|
-
OPERATORS.map((op) => [op.value, op]),
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
/** Metadata for one operator (falls back to a plain `equals`). */
|
|
66
|
-
export function operatorMeta(op: ExcelFilterOperator): OperatorMeta {
|
|
67
|
-
return BY_VALUE.get(op) ?? { value: 'equals', label: 'Equals', types: ALL }
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/** Operators valid for a column type (defaults to the text set). */
|
|
71
|
-
export function operatorsForType(type: ExprColumnType | undefined): OperatorMeta[] {
|
|
72
|
-
const t = type ?? 'text'
|
|
73
|
-
return OPERATORS.filter((op) => op.types.includes(t))
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/** Whether an operator needs no value input. */
|
|
77
|
-
export function isValueless(op: ExcelFilterOperator): boolean {
|
|
78
|
-
return operatorMeta(op).valueless === true
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/** Whether an operator takes a multi-value token list. */
|
|
82
|
-
export function isSetOperator(op: ExcelFilterOperator): boolean {
|
|
83
|
-
return operatorMeta(op).set === true
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/** Whether an operator needs a second (`valueTo`) value. */
|
|
87
|
-
export function isRangeOperator(op: ExcelFilterOperator): boolean {
|
|
88
|
-
return operatorMeta(op).range === true
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/** Look a column up by its canonical id. */
|
|
92
|
-
export function columnById(
|
|
93
|
-
columns: ReadonlyArray<ExprColumn>,
|
|
94
|
-
id: string,
|
|
95
|
-
): ExprColumn | undefined {
|
|
96
|
-
return columns.find((c) => c.id === id)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Resolve a reference (as written in an expression) to a column id. A reference
|
|
101
|
-
* matches a column id first, then a column name (case-insensitive) - so both
|
|
102
|
-
* `price` and `[Unit Price]` resolve. Returns the raw ref unchanged when
|
|
103
|
-
* nothing matches, leaving `validateExpression` to flag it.
|
|
104
|
-
*/
|
|
105
|
-
export function resolveColumnRef(
|
|
106
|
-
columns: ReadonlyArray<ExprColumn>,
|
|
107
|
-
ref: string,
|
|
108
|
-
): string {
|
|
109
|
-
if (columnById(columns, ref)) return ref
|
|
110
|
-
const lc = ref.toLowerCase()
|
|
111
|
-
const byName = columns.find((c) => (c.name ?? '').toLowerCase() === lc)
|
|
112
|
-
return byName ? byName.id : ref
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/** The display label for a column id (its name, or the id itself). */
|
|
116
|
-
export function columnLabel(
|
|
117
|
-
columns: ReadonlyArray<ExprColumn>,
|
|
118
|
-
id: string,
|
|
119
|
-
): string {
|
|
120
|
-
return columnById(columns, id)?.name ?? id
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* How a column id should be written inside an expression: `[Name]` when the
|
|
125
|
-
* label has spaces or non-word characters, otherwise the bare id.
|
|
126
|
-
*/
|
|
127
|
-
export function columnRefText(
|
|
128
|
-
columns: ReadonlyArray<ExprColumn>,
|
|
129
|
-
id: string,
|
|
130
|
-
): string {
|
|
131
|
-
const label = columnLabel(columns, id)
|
|
132
|
-
return /^[A-Za-z_$][\w$]*$/.test(label) ? label : `[${label}]`
|
|
133
|
-
}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Expression / query language - the model layer.
|
|
3
|
-
*
|
|
4
|
-
* A tiny, dependency-free expression language that end users author through the
|
|
5
|
-
* grid UI. It is the connective tissue behind the Alert Rules engine (and, in
|
|
6
|
-
* time, styled columns and calculated columns): one predicate/scalar/change
|
|
7
|
-
* model, evaluated the same way everywhere.
|
|
8
|
-
*
|
|
9
|
-
* The canonical, persisted form is a JSON AST (the types below) - no parser on
|
|
10
|
-
* the hot path. A light tokenizer/parser (`parse.ts`) is offered only for the
|
|
11
|
-
* editor's free-text mode; the structured builder writes the AST directly.
|
|
12
|
-
*
|
|
13
|
-
* Leaf comparisons delegate to the grid's own `applyExcelFilter`, so a rule's
|
|
14
|
-
* "greater than" is byte-for-byte the grid filter's "greater than".
|
|
15
|
-
*/
|
|
16
|
-
import type { ExcelFilterOperator } from '@svgrid/grid'
|
|
17
|
-
|
|
18
|
-
/** Symbolic comparison operators used by `scalarCmp` (general value compare). */
|
|
19
|
-
export type ComparisonOp = '=' | '!=' | '>' | '<' | '>=' | '<='
|
|
20
|
-
|
|
21
|
-
/** Arithmetic operators for `bin` scalar nodes. */
|
|
22
|
-
export type ArithmeticOp = '+' | '-' | '*' | '/' | '%'
|
|
23
|
-
|
|
24
|
-
/** Column aggregate reducers (evaluated over the row set in scope). */
|
|
25
|
-
export type AggFn = 'sum' | 'avg' | 'min' | 'max' | 'count'
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* A scalar expression - evaluates to a single value (number / string /
|
|
29
|
-
* boolean / null) for a given row (and, for aggregates, the row set).
|
|
30
|
-
*/
|
|
31
|
-
export type ScalarExpr =
|
|
32
|
-
| { kind: 'col'; id: string }
|
|
33
|
-
| { kind: 'lit'; value: string | number | boolean | null }
|
|
34
|
-
| { kind: 'neg'; expr: ScalarExpr }
|
|
35
|
-
| { kind: 'bin'; op: ArithmeticOp; left: ScalarExpr; right: ScalarExpr }
|
|
36
|
-
| { kind: 'agg'; fn: AggFn; column: string }
|
|
37
|
-
| { kind: 'func'; name: string; args: ScalarExpr[] }
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* A boolean (predicate) expression - the thing an alert rule / filter needs.
|
|
41
|
-
*
|
|
42
|
-
* - `cmp` maps straight onto the grid's `applyExcelFilter` (text/set/range ops).
|
|
43
|
-
* - `scalarCmp` compares two scalar expressions with a symbolic operator, so
|
|
44
|
-
* cross-column maths (`[filled] / [target] >= 0.9`) is expressible.
|
|
45
|
-
*/
|
|
46
|
-
export type PredicateExpr =
|
|
47
|
-
| { kind: 'and'; parts: PredicateExpr[] }
|
|
48
|
-
| { kind: 'or'; parts: PredicateExpr[] }
|
|
49
|
-
| { kind: 'not'; expr: PredicateExpr }
|
|
50
|
-
| { kind: 'cmp'; column: string; op: ExcelFilterOperator; value?: unknown; valueTo?: unknown }
|
|
51
|
-
| { kind: 'scalarCmp'; left: ScalarExpr; op: ComparisonOp; right: ScalarExpr }
|
|
52
|
-
| { kind: 'const'; value: boolean }
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* A change (observable) expression - true when a value moves between the
|
|
56
|
-
* previous and current snapshot of a row. Powers "relative change" alerts.
|
|
57
|
-
*/
|
|
58
|
-
export type ChangeExpr =
|
|
59
|
-
| { kind: 'changed'; column: string }
|
|
60
|
-
| { kind: 'delta'; column: string; op: ComparisonOp; value: number; abs?: boolean }
|
|
61
|
-
| { kind: 'percentChange'; column: string; op: ComparisonOp; value: number; abs?: boolean }
|
|
62
|
-
| { kind: 'crossed'; column: string; threshold: number; direction: 'above' | 'below' }
|
|
63
|
-
|
|
64
|
-
/** The shape the evaluator reads rows as (a plain field bag by default). */
|
|
65
|
-
export type ExprRow = Record<string, unknown>
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Everything the evaluator needs for one evaluation. `getValue` lets a caller
|
|
69
|
-
* resolve a column id to a value when it is not a plain `row[id]` field;
|
|
70
|
-
* `functions` injects extra scalar functions (e.g. delegate to HyperFormula).
|
|
71
|
-
*/
|
|
72
|
-
export type EvalContext<TData = ExprRow> = {
|
|
73
|
-
row: TData
|
|
74
|
-
/** Prior snapshot of the same row - required by `ChangeExpr`. */
|
|
75
|
-
prev?: TData
|
|
76
|
-
/** The row set in scope - required by aggregates. Defaults to `[row]`. */
|
|
77
|
-
rows?: ReadonlyArray<TData>
|
|
78
|
-
/** Resolve a column id to its cell value. Defaults to `row[id]`. */
|
|
79
|
-
getValue?: (row: TData, columnId: string) => unknown
|
|
80
|
-
/** BCP-47 locale(s) threaded into `applyExcelFilter` for text folding. */
|
|
81
|
-
locale?: string | ReadonlyArray<string>
|
|
82
|
-
/** Extra scalar functions by upper-case name, merged over the builtins. */
|
|
83
|
-
functions?: Record<string, (args: Array<number | string | boolean | null>) => number | string | boolean | null>
|
|
84
|
-
}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import {
|
|
3
|
-
ExpressionParseError,
|
|
4
|
-
collectColumnRefs,
|
|
5
|
-
parsePredicate,
|
|
6
|
-
stringifyPredicate,
|
|
7
|
-
validateExpression,
|
|
8
|
-
} from './parse'
|
|
9
|
-
import { evaluatePredicate } from './evaluate'
|
|
10
|
-
import type { ExprColumn } from './expression-columns'
|
|
11
|
-
import type { PredicateExpr } from './expression-types'
|
|
12
|
-
|
|
13
|
-
const columns: ExprColumn[] = [
|
|
14
|
-
{ id: 'price', name: 'Unit Price', type: 'number' },
|
|
15
|
-
{ id: 'qty', name: 'Qty', type: 'number' },
|
|
16
|
-
{ id: 'name', name: 'Name', type: 'text' },
|
|
17
|
-
{ id: 'region', name: 'Region', type: 'text' },
|
|
18
|
-
]
|
|
19
|
-
|
|
20
|
-
describe('parsePredicate', () => {
|
|
21
|
-
it('parses a col-vs-literal comparison into a cmp node (grid-filter semantics)', () => {
|
|
22
|
-
const e = parsePredicate('price > 100', columns)
|
|
23
|
-
expect(e).toEqual({ kind: 'cmp', column: 'price', op: 'greaterThan', value: 100 })
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
it('resolves [Bracketed Name] references to ids', () => {
|
|
27
|
-
const e = parsePredicate('[Unit Price] >= 50', columns) as Extract<PredicateExpr, { kind: 'scalarCmp' }>
|
|
28
|
-
// >= has no cmp equivalent, so it becomes a scalarCmp over the resolved column id
|
|
29
|
-
expect(e.kind).toBe('scalarCmp')
|
|
30
|
-
expect(e.left).toEqual({ kind: 'col', id: 'price' })
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
it('parses keyword text/set/range operators', () => {
|
|
34
|
-
expect(parsePredicate('name CONTAINS "wid"', columns)).toEqual({ kind: 'cmp', column: 'name', op: 'contains', value: 'wid' })
|
|
35
|
-
expect(parsePredicate('region IN ("EU", "US")', columns)).toEqual({ kind: 'cmp', column: 'region', op: 'in', value: ['EU', 'US'] })
|
|
36
|
-
expect(parsePredicate('price BETWEEN 10 AND 20', columns)).toEqual({ kind: 'cmp', column: 'price', op: 'between', value: 10, valueTo: 20 })
|
|
37
|
-
expect(parsePredicate('name ISBLANK', columns)).toEqual({ kind: 'cmp', column: 'name', op: 'isBlank' })
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
it('honours AND/OR/NOT precedence and grouping', () => {
|
|
41
|
-
const e = parsePredicate('price > 100 AND (region = "EU" OR region = "US")', columns) as Extract<PredicateExpr, { kind: 'and' }>
|
|
42
|
-
expect(e.kind).toBe('and')
|
|
43
|
-
expect(e.parts[1]!.kind).toBe('or')
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
it('parses cross-column scalar maths', () => {
|
|
47
|
-
const e = parsePredicate('price / qty >= 40', columns) as Extract<PredicateExpr, { kind: 'scalarCmp' }>
|
|
48
|
-
expect(e.kind).toBe('scalarCmp')
|
|
49
|
-
expect(e.op).toBe('>=')
|
|
50
|
-
expect(e.left).toEqual({ kind: 'bin', op: '/', left: { kind: 'col', id: 'price' }, right: { kind: 'col', id: 'qty' } })
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
it('throws a positioned error on a syntax problem', () => {
|
|
54
|
-
expect(() => parsePredicate('price >', columns)).toThrow(ExpressionParseError)
|
|
55
|
-
try {
|
|
56
|
-
parsePredicate('price @ 5', columns)
|
|
57
|
-
} catch (err) {
|
|
58
|
-
expect(err).toBeInstanceOf(ExpressionParseError)
|
|
59
|
-
expect((err as ExpressionParseError).pos).toBeGreaterThan(0)
|
|
60
|
-
}
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
it('parsed expressions evaluate correctly end to end', () => {
|
|
64
|
-
const e = parsePredicate('price > 100 AND region = "EU"', columns)
|
|
65
|
-
expect(evaluatePredicate(e, { row: { price: 120, region: 'EU' } })).toBe(true)
|
|
66
|
-
expect(evaluatePredicate(e, { row: { price: 120, region: 'US' } })).toBe(false)
|
|
67
|
-
})
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
describe('stringifyPredicate', () => {
|
|
71
|
-
it('round-trips through parse for the common forms', () => {
|
|
72
|
-
for (const src of [
|
|
73
|
-
'price > 100',
|
|
74
|
-
'name CONTAINS "wid"',
|
|
75
|
-
'region IN ("EU", "US")',
|
|
76
|
-
'price BETWEEN 10 AND 20',
|
|
77
|
-
'name ISBLANK',
|
|
78
|
-
]) {
|
|
79
|
-
const ast = parsePredicate(src, columns)
|
|
80
|
-
const back = stringifyPredicate(ast, columns)
|
|
81
|
-
expect(stringifyPredicate(parsePredicate(back, columns), columns)).toBe(back)
|
|
82
|
-
}
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
it('writes [bracketed] names when a label has spaces', () => {
|
|
86
|
-
const ast = parsePredicate('price > 100', columns)
|
|
87
|
-
expect(stringifyPredicate(ast, columns)).toBe('[Unit Price] > 100')
|
|
88
|
-
})
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
describe('validateExpression + collectColumnRefs', () => {
|
|
92
|
-
it('collects every referenced column id', () => {
|
|
93
|
-
const ast = parsePredicate('price / qty >= 40 AND region = "EU"', columns)
|
|
94
|
-
expect(collectColumnRefs(ast).sort()).toEqual(['price', 'qty', 'region'])
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
it('flags unknown columns and functions', () => {
|
|
98
|
-
const ast = parsePredicate('bogus > 5', columns)
|
|
99
|
-
expect(validateExpression(ast, columns)).toContain('Unknown column "bogus"')
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
it('passes a sound expression', () => {
|
|
103
|
-
const ast = parsePredicate('price > 100', columns)
|
|
104
|
-
expect(validateExpression(ast, columns)).toEqual([])
|
|
105
|
-
})
|
|
106
|
-
})
|