@svgrid/enterprise 2.5.2 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/SvAlertRuleEditor.svelte.d.ts +13 -0
- package/dist/SvAlertsManager.svelte.d.ts +14 -0
- package/dist/SvAlertsPanel.svelte.d.ts +9 -0
- package/dist/SvAuthGate.svelte.d.ts +22 -0
- package/dist/SvBoard.svelte.d.ts +35 -0
- package/dist/SvExportMenu.svelte.d.ts +61 -0
- package/dist/SvExpressionEditor.svelte.d.ts +12 -0
- package/dist/SvFileInput.svelte.d.ts +20 -0
- package/dist/SvGridAlerts.svelte.d.ts +77 -0
- package/dist/SvGridBoard.svelte.d.ts +30 -0
- package/dist/SvGridEditPanel.svelte.d.ts +73 -0
- package/dist/SvGridMasterDetail.svelte.d.ts +49 -0
- package/dist/SvGridScheduler.svelte.d.ts +30 -0
- package/dist/SvImportDialog.svelte.d.ts +88 -0
- package/dist/SvLookupInput.svelte.d.ts +21 -0
- package/dist/SvPivotDesigner.svelte.d.ts +176 -0
- package/dist/SvRecordDetail.svelte.d.ts +58 -0
- package/dist/SvSchedule.svelte.d.ts +29 -0
- package/dist/SvSchemaChart.svelte.d.ts +61 -0
- package/dist/SvSchemaDashboard.svelte.d.ts +46 -0
- package/dist/alerts/alert-engine-attach.d.ts +79 -0
- package/dist/alerts/alert-engine-attach.js +106 -0
- package/dist/alerts/alert-engine.d.ts +42 -0
- package/dist/alerts/alert-engine.js +196 -0
- package/dist/alerts/alert-formats.d.ts +26 -0
- package/dist/alerts/alert-formats.js +58 -0
- package/dist/alerts/alert-observer.d.ts +54 -0
- package/dist/alerts/alert-observer.js +156 -0
- package/dist/alerts/alert-scheduler.d.ts +30 -0
- package/dist/alerts/alert-scheduler.js +54 -0
- package/dist/alerts/alert-storage.d.ts +31 -0
- package/dist/alerts/alert-storage.js +92 -0
- package/dist/alerts/alert-store.svelte.d.ts +24 -0
- package/dist/alerts/alert-store.svelte.js +69 -0
- package/dist/alerts/alert-types.d.ts +86 -0
- package/dist/alerts/alert-types.js +1 -0
- package/dist/alerts.d.ts +2 -0
- package/{src/alerts.ts → dist/alerts.js} +9 -9
- package/dist/board.d.ts +7 -0
- package/{src/board.ts → dist/board.js} +13 -14
- package/dist/cdn/svgrid-enterprise.svelte-external.js +2987 -2981
- package/dist/designer/assets/{index-CM5xvaOy.js → index-BF0UH638.js} +3 -3
- package/dist/designer/assets/{src-D-ET9Mmo.js → src-BPJruwB9.js} +184 -184
- package/dist/designer/index.html +2 -2
- package/dist/edit-panel.d.ts +105 -0
- package/dist/edit-panel.js +350 -0
- package/dist/export-conditional.d.ts +31 -0
- package/dist/export-conditional.js +65 -0
- package/dist/export-ooxml.d.ts +93 -0
- package/dist/export-ooxml.js +385 -0
- package/dist/export-pdf.d.ts +107 -0
- package/dist/export-pdf.js +144 -0
- package/dist/export-print.d.ts +55 -0
- package/dist/export-print.js +91 -0
- package/{src/export-serialize.ts → dist/export-serialize.d.ts} +11 -24
- package/dist/export-serialize.js +11 -0
- package/dist/export-xls.d.ts +26 -0
- package/dist/export-xls.js +157 -0
- package/dist/export.d.ts +323 -0
- package/dist/export.js +1021 -0
- package/dist/expressions/evaluate.d.ts +17 -0
- package/dist/expressions/evaluate.js +214 -0
- package/dist/expressions/expression-columns.d.ts +61 -0
- package/dist/expressions/expression-columns.js +72 -0
- package/dist/expressions/expression-types.d.ts +125 -0
- package/dist/expressions/expression-types.js +1 -0
- package/dist/expressions/parse.d.ts +25 -0
- package/dist/expressions/parse.js +537 -0
- package/dist/import.d.ts +232 -0
- package/dist/import.js +846 -0
- package/dist/index.d.ts +66 -0
- package/dist/index.js +91 -0
- package/dist/install.d.ts +70 -0
- package/dist/install.js +61 -0
- package/dist/license-core.d.ts +37 -0
- package/dist/license-core.js +81 -0
- package/dist/license.d.ts +30 -0
- package/dist/license.js +139 -0
- package/dist/master-detail.d.ts +23 -0
- package/dist/master-detail.js +35 -0
- package/dist/node/studio.js +1 -1
- package/dist/pivot-chart.d.ts +28 -0
- package/dist/pivot-chart.js +71 -0
- package/dist/pivot-designer.d.ts +69 -0
- package/dist/pivot-designer.js +38 -0
- package/dist/pivot-enable.d.ts +6 -0
- package/{src/pivot-enable.ts → dist/pivot-enable.js} +13 -18
- package/dist/pivot.d.ts +111 -0
- package/dist/pivot.js +353 -0
- package/dist/print.d.ts +33 -0
- package/dist/print.js +61 -0
- package/dist/revoked.d.ts +1 -0
- package/{src/revoked.ts → dist/revoked.js} +5 -6
- package/dist/scheduler-assignments.d.ts +64 -0
- package/dist/scheduler-assignments.js +92 -0
- package/dist/scheduler-axis.d.ts +81 -0
- package/dist/scheduler-axis.js +180 -0
- package/{src/scheduler-booking.ts → dist/scheduler-booking.d.ts} +10 -43
- package/dist/scheduler-booking.js +50 -0
- package/dist/scheduler-config.d.ts +177 -0
- package/dist/scheduler-config.js +1 -0
- package/dist/scheduler-dependencies.d.ts +89 -0
- package/dist/scheduler-dependencies.js +179 -0
- package/dist/scheduler-freebusy.d.ts +19 -0
- package/{src/scheduler-freebusy.ts → dist/scheduler-freebusy.js} +9 -19
- package/{src/scheduler-heatmap.ts → dist/scheduler-heatmap.d.ts} +12 -35
- package/dist/scheduler-heatmap.js +41 -0
- package/dist/scheduler-resource-tree.d.ts +48 -0
- package/dist/scheduler-resource-tree.js +78 -0
- package/dist/scheduler-slots.d.ts +37 -0
- package/dist/scheduler-slots.js +80 -0
- package/dist/scheduler-summary.d.ts +41 -0
- package/dist/scheduler-summary.js +54 -0
- package/dist/scheduler.d.ts +7 -0
- package/{src/scheduler.ts → dist/scheduler.js} +13 -14
- package/dist/scheduling.d.ts +132 -0
- package/dist/scheduling.js +228 -0
- package/dist/schema-designer.d.ts +42 -0
- package/dist/schema-designer.js +117 -0
- package/dist/schema.d.ts +369 -0
- package/dist/schema.js +216 -0
- package/dist/smart-shim.d.ts +62 -0
- package/dist/smart-shim.js +34 -0
- package/dist/sources/aggregate.d.ts +43 -0
- package/dist/sources/aggregate.js +60 -0
- package/dist/sources/auth-supabase.d.ts +69 -0
- package/dist/sources/auth-supabase.js +39 -0
- package/dist/sources/dashboard.d.ts +65 -0
- package/dist/sources/dashboard.js +95 -0
- package/dist/sources/field-inference.d.ts +23 -0
- package/dist/sources/field-inference.js +52 -0
- package/dist/sources/filters.d.ts +35 -0
- package/dist/sources/filters.js +52 -0
- package/dist/sources/index.d.ts +18 -0
- package/dist/sources/index.js +18 -0
- package/dist/sources/introspect-supabase.d.ts +30 -0
- package/dist/sources/introspect-supabase.js +134 -0
- package/dist/sources/realtime-supabase.d.ts +37 -0
- package/dist/sources/realtime-supabase.js +52 -0
- package/dist/sources/relation-lookup.d.ts +50 -0
- package/dist/sources/relation-lookup.js +77 -0
- package/dist/sources/rest-adapters.d.ts +48 -0
- package/dist/sources/rest-adapters.js +85 -0
- package/dist/sources/rest.d.ts +38 -0
- package/dist/sources/rest.js +86 -0
- package/dist/sources/schema-from-columns.d.ts +37 -0
- package/dist/sources/schema-from-columns.js +48 -0
- package/dist/sources/supabase.d.ts +33 -0
- package/dist/sources/supabase.js +74 -0
- package/dist/sources/with-entity-rules.d.ts +25 -0
- package/dist/sources/with-entity-rules.js +47 -0
- package/dist/sources/with-relation-labels.d.ts +26 -0
- package/dist/sources/with-relation-labels.js +38 -0
- package/dist/staged-editing.d.ts +85 -0
- package/dist/staged-editing.js +0 -0
- package/dist/studio/bug-report.d.ts +61 -0
- package/dist/studio/bug-report.js +126 -0
- package/dist/studio/cli.d.ts +56 -0
- package/dist/studio/cli.js +70 -0
- package/dist/studio/copilot-core.d.ts +22 -0
- package/{src/studio/copilot-core.ts → dist/studio/copilot-core.js} +34 -38
- package/dist/studio/csv.d.ts +36 -0
- package/dist/studio/csv.js +173 -0
- package/dist/studio/db-connect-string.d.ts +45 -0
- package/dist/studio/db-connect-string.js +113 -0
- package/dist/studio/deploy-cli.d.ts +35 -0
- package/dist/studio/deploy-cli.js +81 -0
- package/dist/studio/emit-project.d.ts +77 -0
- package/dist/studio/emit-project.js +5389 -0
- package/dist/studio/emit-schema.d.ts +110 -0
- package/dist/studio/emit-schema.js +1128 -0
- package/dist/studio/index.d.ts +35 -0
- package/dist/studio/index.js +38 -0
- package/dist/studio/init-flow.d.ts +58 -0
- package/dist/studio/init-flow.js +451 -0
- package/dist/studio/introspect-db.d.ts +47 -0
- package/dist/studio/introspect-db.js +255 -0
- package/dist/studio/introspect-openapi.d.ts +19 -0
- package/dist/studio/introspect-openapi.js +244 -0
- package/dist/studio/introspect-prisma.d.ts +25 -0
- package/dist/studio/introspect-prisma.js +164 -0
- package/dist/studio/introspect.d.ts +35 -0
- package/dist/studio/introspect.js +306 -0
- package/dist/studio/project.d.ts +1327 -0
- package/dist/studio/project.js +1798 -0
- package/dist/studio/sample-data.d.ts +19 -0
- package/dist/studio/sample-data.js +207 -0
- package/dist/studio/samples/ats.d.ts +2 -0
- package/dist/studio/samples/ats.js +194 -0
- package/dist/studio/samples/clinic.d.ts +2 -0
- package/dist/studio/samples/clinic.js +171 -0
- package/dist/studio/samples/crm.d.ts +2 -0
- package/dist/studio/samples/crm.js +280 -0
- package/dist/studio/samples/datasets.d.ts +38 -0
- package/dist/studio/samples/datasets.js +296 -0
- package/dist/studio/samples/ecommerce.d.ts +2 -0
- package/dist/studio/samples/ecommerce.js +178 -0
- package/dist/studio/samples/events.d.ts +2 -0
- package/dist/studio/samples/events.js +192 -0
- package/dist/studio/samples/fleet.d.ts +2 -0
- package/dist/studio/samples/fleet.js +203 -0
- package/dist/studio/samples/gym.d.ts +2 -0
- package/dist/studio/samples/gym.js +205 -0
- package/dist/studio/samples/hr.d.ts +2 -0
- package/dist/studio/samples/hr.js +186 -0
- package/dist/studio/samples/index.d.ts +13 -0
- package/dist/studio/samples/index.js +44 -0
- package/dist/studio/samples/insurance.d.ts +2 -0
- package/dist/studio/samples/insurance.js +220 -0
- package/dist/studio/samples/inventory.d.ts +2 -0
- package/dist/studio/samples/inventory.js +204 -0
- package/dist/studio/samples/invoicing.d.ts +2 -0
- package/dist/studio/samples/invoicing.js +154 -0
- package/dist/studio/samples/library.d.ts +2 -0
- package/dist/studio/samples/library.js +171 -0
- package/dist/studio/samples/live-data.d.ts +5 -0
- package/dist/studio/samples/live-data.js +261 -0
- package/dist/studio/samples/projects.d.ts +2 -0
- package/dist/studio/samples/projects.js +203 -0
- package/dist/studio/samples/realestate.d.ts +2 -0
- package/dist/studio/samples/realestate.js +187 -0
- package/dist/studio/samples/restaurant.d.ts +2 -0
- package/dist/studio/samples/restaurant.js +180 -0
- package/dist/studio/samples/school.d.ts +2 -0
- package/dist/studio/samples/school.js +188 -0
- package/dist/studio/samples/shared.d.ts +142 -0
- package/dist/studio/samples/shared.js +164 -0
- package/dist/studio/samples/starter.d.ts +4 -0
- package/dist/studio/samples/starter.js +237 -0
- package/dist/studio/samples/subscriptions.d.ts +2 -0
- package/dist/studio/samples/subscriptions.js +175 -0
- package/dist/studio/samples/support.d.ts +2 -0
- package/dist/studio/samples/support.js +209 -0
- package/dist/studio/scaffold-app.d.ts +22 -0
- package/{src/studio/scaffold-app.ts → dist/studio/scaffold-app.js} +45 -63
- package/dist/studio/scaffold.d.ts +63 -0
- package/dist/studio/scaffold.js +346 -0
- package/dist/studio/screen-suites.d.ts +193 -0
- package/dist/studio/screen-suites.js +297 -0
- package/dist/studio/themes.d.ts +34 -0
- package/dist/studio/themes.js +41 -0
- package/dist/studio/ui-components.d.ts +89 -0
- package/dist/studio/ui-components.generated.d.ts +29 -0
- package/dist/studio/ui-components.generated.js +7139 -0
- package/dist/studio/ui-components.js +673 -0
- package/dist/studio/user-error.d.ts +23 -0
- package/{src/studio/user-error.ts → dist/studio/user-error.js} +10 -13
- package/dist/studio/verify.d.ts +34 -0
- package/dist/studio/verify.js +47 -0
- package/dist/sveltekit/in-memory.d.ts +14 -0
- package/dist/sveltekit/in-memory.js +113 -0
- package/dist/sveltekit/index.d.ts +6 -0
- package/dist/sveltekit/index.js +5 -0
- package/dist/sveltekit/query-plan.d.ts +44 -0
- package/dist/sveltekit/query-plan.js +76 -0
- package/dist/sveltekit/sql-source.d.ts +47 -0
- package/dist/sveltekit/sql-source.js +106 -0
- package/dist/sveltekit/sql.d.ts +48 -0
- package/dist/sveltekit/sql.js +73 -0
- package/dist/sveltekit/transport.d.ts +209 -0
- package/dist/sveltekit/transport.js +219 -0
- package/{src/sveltekit/types.ts → dist/sveltekit/types.d.ts} +8 -11
- package/dist/sveltekit/types.js +1 -0
- package/dist/upgrade-prompt.d.ts +16 -0
- package/dist/upgrade-prompt.js +141 -0
- package/dist/version.d.ts +13 -0
- package/{src/version.ts → dist/version.js} +1 -1
- package/dist/watermark.d.ts +2 -0
- package/dist/watermark.js +146 -0
- package/package.json +26 -24
- package/src/SvBoard.dom.test.ts +0 -67
- package/src/SvGridAlerts.dom.test.ts +0 -113
- package/src/SvGridEditPanel.dom.test.ts +0 -320
- package/src/SvRecordDetail.dom.test.ts +0 -137
- package/src/SvSchedule.dom.test.ts +0 -57
- package/src/ai-export-pdf.dom.test.ts +0 -77
- package/src/ai-export-xlsx.dom.test.ts +0 -90
- package/src/ai-export.dom.test.ts +0 -114
- package/src/alerts/alert-engine-attach.ts +0 -165
- package/src/alerts/alert-engine.test.ts +0 -135
- package/src/alerts/alert-engine.ts +0 -260
- package/src/alerts/alert-formats.test.ts +0 -87
- package/src/alerts/alert-formats.ts +0 -77
- package/src/alerts/alert-observer.test.ts +0 -189
- package/src/alerts/alert-observer.ts +0 -208
- package/src/alerts/alert-scheduler.ts +0 -96
- package/src/alerts/alert-storage.test.ts +0 -54
- package/src/alerts/alert-storage.ts +0 -116
- package/src/alerts/alert-store.svelte.ts +0 -80
- package/src/alerts/alert-types.ts +0 -94
- package/src/board.dom.test.ts +0 -941
- package/src/edit-panel.test.ts +0 -322
- package/src/edit-panel.ts +0 -379
- package/src/export-conditional.test.ts +0 -60
- package/src/export-conditional.ts +0 -94
- package/src/export-ooxml.test.ts +0 -152
- package/src/export-ooxml.ts +0 -489
- package/src/export-pdf.test.ts +0 -138
- package/src/export-pdf.ts +0 -245
- package/src/export-print.test.ts +0 -66
- package/src/export-print.ts +0 -132
- package/src/export-serialize.test.ts +0 -56
- package/src/export-xls.ts +0 -199
- package/src/export-xlsx-roundtrip.test.ts +0 -120
- package/src/export-xlsx.test.ts +0 -150
- package/src/export.test.ts +0 -349
- package/src/export.ts +0 -1464
- package/src/expressions/evaluate.test.ts +0 -111
- package/src/expressions/evaluate.ts +0 -237
- package/src/expressions/expression-columns.ts +0 -133
- package/src/expressions/expression-types.ts +0 -84
- package/src/expressions/parse.test.ts +0 -106
- package/src/expressions/parse.ts +0 -610
- package/src/import-automap.test.ts +0 -131
- package/src/import-hardening.test.ts +0 -158
- package/src/import.test.ts +0 -415
- package/src/import.ts +0 -1044
- package/src/index.ts +0 -569
- package/src/install.ts +0 -154
- package/src/license-core.test.ts +0 -23
- package/src/license-core.ts +0 -107
- package/src/license-expiry.test.ts +0 -127
- package/src/license.ts +0 -137
- package/src/master-detail.test.ts +0 -61
- package/src/master-detail.ts +0 -42
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/_metadata.json +0 -178
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/attachments-ZrPsKxob.js +0 -3875
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/attachments-ZrPsKxob.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/constants-ACqvWGE2.js +0 -21
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/constants-ACqvWGE2.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/dev-D3w5jt92.js +0 -1938
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/dev-D3w5jt92.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/events-CC2V3H0y.js +0 -205
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/events-CC2V3H0y.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/flags-BXP37tAa.js +0 -18
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/flags-BXP37tAa.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/hydration-DwubnU5b.js +0 -264
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/hydration-DwubnU5b.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/legacy-client-hD7f6PUz.js +0 -697
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/legacy-client-hD7f6PUz.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte.js +0 -134
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_animate.js +0 -55
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_animate.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_attachments.js +0 -2
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_compiler.js +0 -46843
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_compiler.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_easing.js +0 -237
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_easing.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_events.js +0 -2
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal.js +0 -4
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_client.js +0 -7
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_disclose-version.js +0 -4
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_disclose-version.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_async.js +0 -5
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_async.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_legacy.js +0 -5
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_legacy.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_tracing.js +0 -5
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_tracing.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_server.js +0 -6
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_legacy.js +0 -83
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_legacy.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_motion.js +0 -559
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_motion.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity.js +0 -24
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity_window.js +0 -122
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity_window.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_server.js +0 -2
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_store.js +0 -89
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_store.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_transition.js +0 -241
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_transition.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-DBx1SCN6.js +0 -4938
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-DBx1SCN6.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-gjfpSTFS.js +0 -495
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-gjfpSTFS.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/validate-DKoOKg8S.js +0 -190
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/validate-DKoOKg8S.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/version-C0MiR7eR.js +0 -8
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/version-C0MiR7eR.js.map +0 -1
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/warnings-B6Y7P0Q-.js +0 -138
- package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/warnings-B6Y7P0Q-.js.map +0 -1
- package/src/pivot-chart.test.ts +0 -86
- package/src/pivot-chart.ts +0 -112
- package/src/pivot-designer.ts +0 -101
- package/src/pivot.test.ts +0 -335
- package/src/pivot.ts +0 -578
- package/src/print.ts +0 -107
- package/src/scheduler-assignments.test.ts +0 -97
- package/src/scheduler-assignments.ts +0 -134
- package/src/scheduler-axis.test.ts +0 -108
- package/src/scheduler-axis.ts +0 -238
- package/src/scheduler-booking.test.ts +0 -57
- package/src/scheduler-config.ts +0 -179
- package/src/scheduler-dependencies.test.ts +0 -155
- package/src/scheduler-dependencies.ts +0 -223
- package/src/scheduler-freebusy.test.ts +0 -41
- package/src/scheduler-heatmap.test.ts +0 -39
- package/src/scheduler-resource-tree.test.ts +0 -84
- package/src/scheduler-resource-tree.ts +0 -107
- package/src/scheduler-slots.test.ts +0 -53
- package/src/scheduler-slots.ts +0 -94
- package/src/scheduler-summary.test.ts +0 -47
- package/src/scheduler-summary.ts +0 -81
- package/src/scheduling.test.ts +0 -194
- package/src/scheduling.ts +0 -293
- package/src/schema-designer.test.ts +0 -121
- package/src/schema-designer.ts +0 -142
- package/src/schema.test.ts +0 -268
- package/src/schema.ts +0 -562
- package/src/smart-shim.ts +0 -107
- package/src/sources/aggregate.test.ts +0 -79
- package/src/sources/aggregate.ts +0 -102
- package/src/sources/auth-supabase.test.ts +0 -80
- package/src/sources/auth-supabase.ts +0 -87
- package/src/sources/dashboard.kpi.test.ts +0 -50
- package/src/sources/dashboard.test.ts +0 -61
- package/src/sources/dashboard.ts +0 -136
- package/src/sources/field-inference.test.ts +0 -60
- package/src/sources/field-inference.ts +0 -63
- package/src/sources/filters.test.ts +0 -58
- package/src/sources/filters.ts +0 -70
- package/src/sources/index.ts +0 -67
- package/src/sources/introspect-supabase.test.ts +0 -112
- package/src/sources/introspect-supabase.ts +0 -139
- package/src/sources/realtime-supabase.test.ts +0 -93
- package/src/sources/realtime-supabase.ts +0 -99
- package/src/sources/relation-lookup.test.ts +0 -99
- package/src/sources/relation-lookup.ts +0 -128
- package/src/sources/rest-adapters.test.ts +0 -95
- package/src/sources/rest-adapters.ts +0 -120
- package/src/sources/rest.test.ts +0 -104
- package/src/sources/rest.ts +0 -129
- package/src/sources/schema-from-columns.test.ts +0 -106
- package/src/sources/schema-from-columns.ts +0 -88
- package/src/sources/supabase.test.ts +0 -110
- package/src/sources/supabase.ts +0 -99
- package/src/sources/with-entity-rules.test.ts +0 -104
- package/src/sources/with-entity-rules.ts +0 -78
- package/src/sources/with-relation-labels.test.ts +0 -75
- package/src/sources/with-relation-labels.ts +0 -73
- package/src/staged-editing.ts +0 -0
- package/src/studio/bug-report.test.ts +0 -101
- package/src/studio/bug-report.ts +0 -165
- package/src/studio/cli.test.ts +0 -187
- package/src/studio/cli.ts +0 -117
- package/src/studio/copilot-core.test.ts +0 -45
- package/src/studio/csv.test.ts +0 -90
- package/src/studio/csv.ts +0 -165
- package/src/studio/db-connect-string.test.ts +0 -94
- package/src/studio/db-connect-string.ts +0 -128
- package/src/studio/deploy-cli.test.ts +0 -56
- package/src/studio/deploy-cli.ts +0 -100
- package/src/studio/emit-project.test.ts +0 -3324
- package/src/studio/emit-project.ts +0 -5377
- package/src/studio/emit-schema.test.ts +0 -111
- package/src/studio/emit-schema.ts +0 -1181
- package/src/studio/index.ts +0 -380
- package/src/studio/init-flow.test.ts +0 -514
- package/src/studio/init-flow.ts +0 -556
- package/src/studio/introspect-db.test.ts +0 -186
- package/src/studio/introspect-db.ts +0 -312
- package/src/studio/introspect-openapi.test.ts +0 -84
- package/src/studio/introspect-openapi.ts +0 -252
- package/src/studio/introspect-prisma.test.ts +0 -99
- package/src/studio/introspect-prisma.ts +0 -175
- package/src/studio/introspect.test.ts +0 -172
- package/src/studio/introspect.ts +0 -310
- package/src/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/_svelte_metadata.json +0 -1
- package/src/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/package.json +0 -3
- package/src/studio/pipeline.test.ts +0 -42
- package/src/studio/project-robust.test.ts +0 -157
- package/src/studio/project.test.ts +0 -929
- package/src/studio/project.ts +0 -2394
- package/src/studio/sample-data.test.ts +0 -58
- package/src/studio/sample-data.ts +0 -203
- package/src/studio/samples/ats.ts +0 -202
- package/src/studio/samples/clinic.ts +0 -179
- package/src/studio/samples/crm.ts +0 -291
- package/src/studio/samples/datasets.test.ts +0 -84
- package/src/studio/samples/datasets.ts +0 -340
- package/src/studio/samples/ecommerce.ts +0 -187
- package/src/studio/samples/events.ts +0 -201
- package/src/studio/samples/fleet.ts +0 -213
- package/src/studio/samples/gym.ts +0 -215
- package/src/studio/samples/hr.ts +0 -195
- package/src/studio/samples/index.ts +0 -55
- package/src/studio/samples/insurance.ts +0 -229
- package/src/studio/samples/inventory.ts +0 -213
- package/src/studio/samples/invoicing.ts +0 -162
- package/src/studio/samples/library.ts +0 -180
- package/src/studio/samples/live-data.test.ts +0 -99
- package/src/studio/samples/live-data.ts +0 -306
- package/src/studio/samples/projects.ts +0 -212
- package/src/studio/samples/realestate.ts +0 -196
- package/src/studio/samples/restaurant.ts +0 -189
- package/src/studio/samples/samples.test.ts +0 -304
- package/src/studio/samples/school.ts +0 -197
- package/src/studio/samples/seed-floor.test.ts +0 -25
- package/src/studio/samples/shared.ts +0 -237
- package/src/studio/samples/starter.ts +0 -251
- package/src/studio/samples/subscriptions.ts +0 -183
- package/src/studio/samples/support.ts +0 -216
- package/src/studio/scaffold-app.test.ts +0 -91
- package/src/studio/scaffold.test.ts +0 -192
- package/src/studio/scaffold.ts +0 -390
- package/src/studio/screen-suites.test.ts +0 -269
- package/src/studio/screen-suites.ts +0 -448
- package/src/studio/themes.ts +0 -62
- package/src/studio/ui-components-surface.test.ts +0 -185
- package/src/studio/ui-components.generated.ts +0 -7154
- package/src/studio/ui-components.ts +0 -742
- package/src/studio/verify.test.ts +0 -47
- package/src/studio/verify.ts +0 -79
- package/src/sveltekit/in-memory.test.ts +0 -104
- package/src/sveltekit/in-memory.ts +0 -129
- package/src/sveltekit/index.ts +0 -24
- package/src/sveltekit/query-plan.test.ts +0 -109
- package/src/sveltekit/query-plan.ts +0 -125
- package/src/sveltekit/sql-source.test.ts +0 -198
- package/src/sveltekit/sql-source.ts +0 -171
- package/src/sveltekit/sql.test.ts +0 -80
- package/src/sveltekit/sql.ts +0 -131
- package/src/sveltekit/transport-scope.test.ts +0 -125
- package/src/sveltekit/transport.test.ts +0 -201
- package/src/sveltekit/transport.ts +0 -373
- package/src/upgrade-prompt.test.ts +0 -71
- package/src/upgrade-prompt.ts +0 -162
- package/src/version.test.ts +0 -17
- package/src/watermark.test.ts +0 -97
- package/src/watermark.ts +0 -156
- /package/{src → dist}/SvAlertRuleEditor.svelte +0 -0
- /package/{src → dist}/SvAlertsManager.svelte +0 -0
- /package/{src → dist}/SvAlertsPanel.svelte +0 -0
- /package/{src → dist}/SvAuthGate.svelte +0 -0
- /package/{src → dist}/SvBoard.svelte +0 -0
- /package/{src → dist}/SvExportMenu.svelte +0 -0
- /package/{src → dist}/SvExpressionEditor.svelte +0 -0
- /package/{src → dist}/SvFileInput.svelte +0 -0
- /package/{src → dist}/SvGridAlerts.svelte +0 -0
- /package/{src → dist}/SvGridBoard.svelte +0 -0
- /package/{src → dist}/SvGridEditPanel.svelte +0 -0
- /package/{src → dist}/SvGridMasterDetail.svelte +0 -0
- /package/{src → dist}/SvGridScheduler.svelte +0 -0
- /package/{src → dist}/SvImportDialog.svelte +0 -0
- /package/{src → dist}/SvLookupInput.svelte +0 -0
- /package/{src → dist}/SvPivotDesigner.svelte +0 -0
- /package/{src → dist}/SvRecordDetail.svelte +0 -0
- /package/{src → dist}/SvSchedule.svelte +0 -0
- /package/{src → dist}/SvSchemaChart.svelte +0 -0
- /package/{src → dist}/SvSchemaDashboard.svelte +0 -0
- /package/{src → dist}/pdfmake-shims.d.ts +0 -0
- /package/{src → dist}/smart.export.d.ts +0 -0
- /package/{src → dist}/smart.export.js +0 -0
- /package/{src → dist}/studio/HANDLERS-DESIGN.md +0 -0
- /package/{src → dist/studio}/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/_svelte_metadata.json +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/_metadata.json +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/attachments-BOv1rBKp.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/attachments-BOv1rBKp.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/constants-B9vgIdCd.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/constants-B9vgIdCd.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/dev-T1qbW_qD.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/dev-T1qbW_qD.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/events-Bo11SfVK.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/events-Bo11SfVK.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/flags-X7D4vfrZ.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/flags-X7D4vfrZ.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/hydration-oyUje5i1.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/hydration-oyUje5i1.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/legacy-client-DeSQgSFm.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/legacy-client-DeSQgSFm.js.map +0 -0
- /package/{src → dist/studio}/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/package.json +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_animate.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_animate.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_attachments.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_compiler.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_compiler.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_easing.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_easing.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_events.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_client.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_disclose-version.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_disclose-version.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_async.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_async.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_legacy.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_legacy.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_tracing.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_tracing.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_server.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_legacy.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_legacy.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_motion.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_motion.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity_window.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity_window.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_server.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_store.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_store.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_transition.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_transition.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-BbWyXNk1.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-BbWyXNk1.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-DI_fC7vt.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-DI_fC7vt.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/validate-Dyr3lQv9.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/validate-Dyr3lQv9.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/version-_9FHH-LF.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/version-_9FHH-LF.js.map +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/warnings-CUbSPnyP.js +0 -0
- /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/warnings-CUbSPnyP.js.map +0 -0
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The pure alert engine - no DOM, no timers. It turns rules + data snapshots
|
|
3
|
-
* into `AlertEvent`s, with true-edge de-duplication so a `dataChange` rule fires
|
|
4
|
-
* once when a row starts matching (not on every re-evaluation while it keeps
|
|
5
|
-
* matching). The reactive/observing wrapper lives in `alert-engine-attach.ts`.
|
|
6
|
-
*/
|
|
7
|
-
import { evaluateChange, evaluatePredicate } from '../expressions/evaluate'
|
|
8
|
-
import { collectColumnRefs } from '../expressions/parse'
|
|
9
|
-
import type { EvalContext } from '../expressions/expression-types'
|
|
10
|
-
import type { AlertEvent, AlertRule } from './alert-types'
|
|
11
|
-
|
|
12
|
-
export type AlertEngineOptions<TData> = {
|
|
13
|
-
rules: AlertRule[]
|
|
14
|
-
getRowId: (row: TData) => string
|
|
15
|
-
/** Resolve a column id to a value (defaults to `row[id]`). */
|
|
16
|
-
getValue?: (row: TData, columnId: string) => unknown
|
|
17
|
-
locale?: string | ReadonlyArray<string>
|
|
18
|
-
/** Clock for `firedAt` (injectable for deterministic tests). */
|
|
19
|
-
now?: () => number
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export type ValidateEditResult = {
|
|
23
|
-
vetoed: boolean
|
|
24
|
-
events: AlertEvent[]
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export type AlertEngine<TData> = {
|
|
28
|
-
setRules(rules: AlertRule[]): void
|
|
29
|
-
getRules(): AlertRule[]
|
|
30
|
-
/** Full-snapshot pass: fires `dataChange`/`scheduled`/aggregate edges. */
|
|
31
|
-
evaluate(rows: ReadonlyArray<TData>): AlertEvent[]
|
|
32
|
-
/** Prev -> next pass: fires `relativeChange` plus `dataChange` edges. */
|
|
33
|
-
evaluateTransition(prev: ReadonlyArray<TData>, next: ReadonlyArray<TData>): AlertEvent[]
|
|
34
|
-
/** Would editing `(row, columnId) -> nextValue` trip a validation rule? */
|
|
35
|
-
validateEdit(row: TData, columnId: string, nextValue: unknown): ValidateEditResult
|
|
36
|
-
/**
|
|
37
|
-
* True iff some enabled rule reads a row's PREVIOUS value (a `relativeChange`
|
|
38
|
-
* trigger). When false, the observer can skip cloning prev-snapshots entirely
|
|
39
|
-
* - the hot-path saver for `dataChange`/aggregate-only rule sets over big feeds.
|
|
40
|
-
*/
|
|
41
|
-
needsPrev(): boolean
|
|
42
|
-
/** True iff some enabled rule is aggregate-scope (needs the full row set). */
|
|
43
|
-
needsFullSet(): boolean
|
|
44
|
-
/** Forget edge memory so matching rows can fire again. */
|
|
45
|
-
reset(): void
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const AGG_ROW_KEY = '*'
|
|
49
|
-
|
|
50
|
-
/** Fill message-template tokens from the firing context. */
|
|
51
|
-
export function renderTemplate(
|
|
52
|
-
template: string,
|
|
53
|
-
ctx: { rule: AlertRule; row?: Record<string, unknown>; columnId?: string; value?: unknown },
|
|
54
|
-
): string {
|
|
55
|
-
const { rule, row, columnId, value } = ctx
|
|
56
|
-
return template
|
|
57
|
-
.replace(/\{rule\}/g, rule.name)
|
|
58
|
-
.replace(/\{severity\}/g, rule.severity)
|
|
59
|
-
.replace(/\{column\}/g, columnId ?? '')
|
|
60
|
-
.replace(/\{value\}/g, value == null ? '' : String(value))
|
|
61
|
-
.replace(/\{row\.([\w$]+)\}/g, (_m, key: string) => fmt(row?.[key]))
|
|
62
|
-
.replace(/\{([\w$]+)\}/g, (m, key: string) => (row && key in row ? fmt(row[key]) : m))
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function fmt(v: unknown): string {
|
|
66
|
-
return v == null ? '' : String(v)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function defaultMessage(rule: AlertRule): string {
|
|
70
|
-
return rule.name
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export function createAlertEngine<TData = Record<string, unknown>>(
|
|
74
|
-
options: AlertEngineOptions<TData>,
|
|
75
|
-
): AlertEngine<TData> {
|
|
76
|
-
let rules = options.rules
|
|
77
|
-
const getValue = options.getValue
|
|
78
|
-
const now = options.now ?? (() => Date.now())
|
|
79
|
-
// Edge memory: keys currently satisfying a `dataChange`/aggregate predicate.
|
|
80
|
-
const active = new Set<string>()
|
|
81
|
-
|
|
82
|
-
const ctxFor = (row: TData, rows?: ReadonlyArray<TData>, prev?: TData): EvalContext<TData> => ({
|
|
83
|
-
row,
|
|
84
|
-
prev,
|
|
85
|
-
rows,
|
|
86
|
-
getValue,
|
|
87
|
-
locale: options.locale,
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
const val = (row: TData, columnId?: string): unknown =>
|
|
91
|
-
columnId == null
|
|
92
|
-
? undefined
|
|
93
|
-
: getValue
|
|
94
|
-
? getValue(row, columnId)
|
|
95
|
-
: (row as Record<string, unknown>)?.[columnId]
|
|
96
|
-
|
|
97
|
-
// A representative column for the message `{value}`/`{column}` tokens: the
|
|
98
|
-
// rule's explicit target, else the first column its predicate references.
|
|
99
|
-
const primaryColumn = (rule: AlertRule): string | undefined =>
|
|
100
|
-
rule.columns?.[0] ?? collectColumnRefs(rule.predicate)[0]
|
|
101
|
-
|
|
102
|
-
function buildEvent(
|
|
103
|
-
rule: AlertRule,
|
|
104
|
-
opts: { row?: TData; rowId?: string; columnId?: string; value?: unknown },
|
|
105
|
-
): AlertEvent {
|
|
106
|
-
const msgAction = rule.actions.find((a) => a.message)
|
|
107
|
-
const template = msgAction?.message ?? defaultMessage(rule)
|
|
108
|
-
const message = renderTemplate(template, {
|
|
109
|
-
rule,
|
|
110
|
-
row: opts.row as Record<string, unknown> | undefined,
|
|
111
|
-
columnId: opts.columnId,
|
|
112
|
-
value: opts.value,
|
|
113
|
-
})
|
|
114
|
-
return {
|
|
115
|
-
ruleId: rule.id,
|
|
116
|
-
ruleName: rule.name,
|
|
117
|
-
severity: rule.severity,
|
|
118
|
-
scope: rule.scope,
|
|
119
|
-
triggerType: rule.trigger.type,
|
|
120
|
-
rowId: opts.rowId,
|
|
121
|
-
columnId: opts.columnId,
|
|
122
|
-
value: opts.value,
|
|
123
|
-
message,
|
|
124
|
-
actions: rule.actions,
|
|
125
|
-
firedAt: now(),
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/** Aggregate-scope: one edge event when the predicate over all rows flips true. */
|
|
130
|
-
function evaluateAggregate(rule: AlertRule, rows: ReadonlyArray<TData>): AlertEvent[] {
|
|
131
|
-
const key = `${rule.id}::${AGG_ROW_KEY}`
|
|
132
|
-
const first = rows[0]
|
|
133
|
-
const matches = first != null && evaluatePredicate(rule.predicate, ctxFor(first, rows))
|
|
134
|
-
if (matches && !active.has(key)) {
|
|
135
|
-
active.add(key)
|
|
136
|
-
return [buildEvent(rule, {})]
|
|
137
|
-
}
|
|
138
|
-
if (!matches) active.delete(key)
|
|
139
|
-
return []
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/** Row/cell dataChange: edge event when a row newly satisfies the predicate. */
|
|
143
|
-
function evaluateDataChangeRow(
|
|
144
|
-
rule: AlertRule,
|
|
145
|
-
row: TData,
|
|
146
|
-
rows: ReadonlyArray<TData>,
|
|
147
|
-
): AlertEvent[] {
|
|
148
|
-
const id = options.getRowId(row)
|
|
149
|
-
const key = `${rule.id}::${id}`
|
|
150
|
-
const matches = evaluatePredicate(rule.predicate, ctxFor(row, rows))
|
|
151
|
-
if (matches && !active.has(key)) {
|
|
152
|
-
active.add(key)
|
|
153
|
-
const source = primaryColumn(rule)
|
|
154
|
-
// Expose the column on the event only for cell scope; still surface its
|
|
155
|
-
// value for the message tokens regardless of scope.
|
|
156
|
-
const columnId = rule.scope === 'cell' ? source : undefined
|
|
157
|
-
return [buildEvent(rule, { row, rowId: id, columnId, value: val(row, source) })]
|
|
158
|
-
}
|
|
159
|
-
if (!matches) active.delete(key)
|
|
160
|
-
return []
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/** relativeChange: fires whenever the change test holds for a prev->next row. */
|
|
164
|
-
function evaluateRelative(
|
|
165
|
-
rule: AlertRule,
|
|
166
|
-
row: TData,
|
|
167
|
-
prev: TData | undefined,
|
|
168
|
-
rows: ReadonlyArray<TData>,
|
|
169
|
-
): AlertEvent[] {
|
|
170
|
-
if (rule.trigger.type !== 'relativeChange' || prev == null) return []
|
|
171
|
-
const changed = evaluateChange(rule.trigger.expr, ctxFor(row, rows, prev))
|
|
172
|
-
if (!changed) return []
|
|
173
|
-
// Gate on the predicate too, so "price jumped AND price > 100" is expressible.
|
|
174
|
-
if (!evaluatePredicate(rule.predicate, ctxFor(row, rows, prev))) return []
|
|
175
|
-
const columnId = rule.trigger.expr.column
|
|
176
|
-
return [
|
|
177
|
-
buildEvent(rule, {
|
|
178
|
-
row,
|
|
179
|
-
rowId: options.getRowId(row),
|
|
180
|
-
columnId,
|
|
181
|
-
value: val(row, columnId),
|
|
182
|
-
}),
|
|
183
|
-
]
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
function activeRules(): AlertRule[] {
|
|
187
|
-
return rules.filter((r) => r.enabled)
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return {
|
|
191
|
-
setRules(next) {
|
|
192
|
-
rules = next
|
|
193
|
-
},
|
|
194
|
-
getRules() {
|
|
195
|
-
return rules
|
|
196
|
-
},
|
|
197
|
-
needsPrev() {
|
|
198
|
-
return rules.some((r) => r.enabled && r.trigger.type === 'relativeChange')
|
|
199
|
-
},
|
|
200
|
-
needsFullSet() {
|
|
201
|
-
return rules.some((r) => r.enabled && r.scope === 'aggregate')
|
|
202
|
-
},
|
|
203
|
-
reset() {
|
|
204
|
-
active.clear()
|
|
205
|
-
},
|
|
206
|
-
|
|
207
|
-
evaluate(rows) {
|
|
208
|
-
const events: AlertEvent[] = []
|
|
209
|
-
for (const rule of activeRules()) {
|
|
210
|
-
if (rule.scope === 'aggregate') {
|
|
211
|
-
events.push(...evaluateAggregate(rule, rows))
|
|
212
|
-
} else if (rule.trigger.type === 'dataChange' || rule.trigger.type === 'scheduled') {
|
|
213
|
-
for (const row of rows) events.push(...evaluateDataChangeRow(rule, row, rows))
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
return events
|
|
217
|
-
},
|
|
218
|
-
|
|
219
|
-
evaluateTransition(prev, next) {
|
|
220
|
-
const prevById = new Map<string, TData>()
|
|
221
|
-
for (const row of prev) prevById.set(options.getRowId(row), row)
|
|
222
|
-
const events: AlertEvent[] = []
|
|
223
|
-
for (const rule of activeRules()) {
|
|
224
|
-
if (rule.scope === 'aggregate') {
|
|
225
|
-
events.push(...evaluateAggregate(rule, next))
|
|
226
|
-
continue
|
|
227
|
-
}
|
|
228
|
-
for (const row of next) {
|
|
229
|
-
const before = prevById.get(options.getRowId(row))
|
|
230
|
-
if (rule.trigger.type === 'relativeChange') {
|
|
231
|
-
events.push(...evaluateRelative(rule, row, before, next))
|
|
232
|
-
} else if (rule.trigger.type === 'dataChange') {
|
|
233
|
-
events.push(...evaluateDataChangeRow(rule, row, next))
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
return events
|
|
238
|
-
},
|
|
239
|
-
|
|
240
|
-
validateEdit(row, columnId, nextValue) {
|
|
241
|
-
const candidate = { ...(row as Record<string, unknown>), [columnId]: nextValue } as TData
|
|
242
|
-
const events: AlertEvent[] = []
|
|
243
|
-
let vetoed = false
|
|
244
|
-
for (const rule of activeRules()) {
|
|
245
|
-
if (rule.trigger.type !== 'validation') continue
|
|
246
|
-
if (!evaluatePredicate(rule.predicate, ctxFor(candidate))) continue
|
|
247
|
-
events.push(
|
|
248
|
-
buildEvent(rule, {
|
|
249
|
-
row: candidate,
|
|
250
|
-
rowId: options.getRowId(candidate),
|
|
251
|
-
columnId,
|
|
252
|
-
value: nextValue,
|
|
253
|
-
}),
|
|
254
|
-
)
|
|
255
|
-
if (rule.actions.some((a) => a.kind === 'preventEdit')) vetoed = true
|
|
256
|
-
}
|
|
257
|
-
return { vetoed, events }
|
|
258
|
-
},
|
|
259
|
-
}
|
|
260
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import { rulesToConditionalFormats, toConditionalFormats } from './alert-formats'
|
|
3
|
-
import type { AlertEvent, AlertRule } from './alert-types'
|
|
4
|
-
|
|
5
|
-
type Row = { id: string; price: number }
|
|
6
|
-
const getRowId = (r: Row) => r.id
|
|
7
|
-
|
|
8
|
-
const event = (over: Partial<AlertEvent> = {}): AlertEvent => ({
|
|
9
|
-
ruleId: 'r1',
|
|
10
|
-
ruleName: 'High',
|
|
11
|
-
severity: 'warning',
|
|
12
|
-
scope: 'row',
|
|
13
|
-
triggerType: 'dataChange',
|
|
14
|
-
rowId: 'a',
|
|
15
|
-
message: 'hi',
|
|
16
|
-
actions: [{ kind: 'highlight', style: { background: '#fee2e2', color: '#991b1b' } }],
|
|
17
|
-
firedAt: 0,
|
|
18
|
-
...over,
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
describe('toConditionalFormats', () => {
|
|
22
|
-
it('turns a highlight action into a row-matching RuleFormat', () => {
|
|
23
|
-
const formats = toConditionalFormats([event()], getRowId)
|
|
24
|
-
expect(formats).toHaveLength(1)
|
|
25
|
-
const f = formats[0]!
|
|
26
|
-
expect(f.type).toBe('rule')
|
|
27
|
-
if (f.type === 'rule') {
|
|
28
|
-
expect(f.background).toBe('#fee2e2')
|
|
29
|
-
expect(f.color).toBe('#991b1b')
|
|
30
|
-
expect(f.when({ value: 120, row: { id: 'a', price: 120 } })).toBe(true)
|
|
31
|
-
expect(f.when({ value: 80, row: { id: 'b', price: 80 } })).toBe(false)
|
|
32
|
-
}
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
it('scopes to the event column when no explicit columns', () => {
|
|
36
|
-
const formats = toConditionalFormats([event({ columnId: 'price' })], getRowId)
|
|
37
|
-
const f = formats[0]!
|
|
38
|
-
if (f.type === 'rule') expect(f.columns).toEqual(['price'])
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
it('honours explicit action columns', () => {
|
|
42
|
-
const formats = toConditionalFormats(
|
|
43
|
-
[event({ actions: [{ kind: 'badge', columns: ['price', 'id'], style: { background: '#fff' } }] })],
|
|
44
|
-
getRowId,
|
|
45
|
-
)
|
|
46
|
-
const f = formats[0]!
|
|
47
|
-
if (f.type === 'rule') expect(f.columns).toEqual(['price', 'id'])
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
it('ignores toast/log/flash-only events (no styling)', () => {
|
|
51
|
-
expect(toConditionalFormats([event({ actions: [{ kind: 'toast' }, { kind: 'log' }] })], getRowId)).toHaveLength(0)
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
it('skips events without a row id', () => {
|
|
55
|
-
expect(toConditionalFormats([event({ rowId: undefined })], getRowId)).toHaveLength(0)
|
|
56
|
-
})
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
describe('rulesToConditionalFormats', () => {
|
|
60
|
-
const rule = (over: Partial<AlertRule> = {}): AlertRule => ({
|
|
61
|
-
id: 'r1',
|
|
62
|
-
name: 'High',
|
|
63
|
-
enabled: true,
|
|
64
|
-
severity: 'warning',
|
|
65
|
-
scope: 'row',
|
|
66
|
-
predicate: { kind: 'cmp', column: 'price', op: 'greaterThan', value: 100 },
|
|
67
|
-
trigger: { type: 'dataChange' },
|
|
68
|
-
actions: [{ kind: 'highlight', style: { background: '#fee2e2' } }],
|
|
69
|
-
createdAt: 0,
|
|
70
|
-
...over,
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
it('emits one live predicate-driven format per styling rule', () => {
|
|
74
|
-
const formats = rulesToConditionalFormats<Row>([rule()])
|
|
75
|
-
expect(formats).toHaveLength(1)
|
|
76
|
-
const f = formats[0]!
|
|
77
|
-
if (f.type === 'rule') {
|
|
78
|
-
expect(f.when({ value: 0, row: { id: 'a', price: 120 } })).toBe(true)
|
|
79
|
-
expect(f.when({ value: 0, row: { id: 'b', price: 80 } })).toBe(false)
|
|
80
|
-
}
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
it('ignores disabled rules and non-styling rules', () => {
|
|
84
|
-
expect(rulesToConditionalFormats<Row>([rule({ enabled: false })])).toHaveLength(0)
|
|
85
|
-
expect(rulesToConditionalFormats<Row>([rule({ actions: [{ kind: 'toast' }] })])).toHaveLength(0)
|
|
86
|
-
})
|
|
87
|
-
})
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Bridge fired alert events to the grid's conditional-formatting engine. A
|
|
3
|
-
* `badge` / `highlight` action becomes a `RuleFormat` whose `when` matches the
|
|
4
|
-
* row that fired, so `resolveCellFormat` paints it - the same painter the grid
|
|
5
|
-
* already uses for color scales and data bars. No new rendering path.
|
|
6
|
-
*/
|
|
7
|
-
import type { ConditionalFormat } from '@svgrid/grid/format'
|
|
8
|
-
import { evaluatePredicate } from '../expressions/evaluate'
|
|
9
|
-
import type { AlertEvent, AlertRule } from './alert-types'
|
|
10
|
-
|
|
11
|
-
/** Which action kinds paint onto cells. */
|
|
12
|
-
const STYLING_KINDS = new Set(['badge', 'highlight'])
|
|
13
|
-
|
|
14
|
-
export type StylingContext<TData> = {
|
|
15
|
-
getValue?: (row: TData, columnId: string) => unknown
|
|
16
|
-
locale?: string | ReadonlyArray<string>
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Persistent styling: one self-contained `RuleFormat` per enabled rule that has
|
|
21
|
-
* a `badge`/`highlight` action. The format's `when` runs the rule predicate
|
|
22
|
-
* directly, so the styling stays live as data changes (rows light up while they
|
|
23
|
-
* match and clear when they stop) without any row-id bookkeeping. One format
|
|
24
|
-
* per rule keeps the array tiny regardless of row count.
|
|
25
|
-
*/
|
|
26
|
-
export function rulesToConditionalFormats<TData = Record<string, unknown>>(
|
|
27
|
-
rules: ReadonlyArray<AlertRule>,
|
|
28
|
-
ctx: StylingContext<TData> = {},
|
|
29
|
-
): ConditionalFormat<TData>[] {
|
|
30
|
-
const formats: ConditionalFormat<TData>[] = []
|
|
31
|
-
for (const rule of rules) {
|
|
32
|
-
if (!rule.enabled) continue
|
|
33
|
-
for (const action of rule.actions) {
|
|
34
|
-
if (!STYLING_KINDS.has(action.kind)) continue
|
|
35
|
-
const columns = action.columns ?? rule.columns
|
|
36
|
-
const style = action.style ?? {}
|
|
37
|
-
formats.push({
|
|
38
|
-
type: 'rule',
|
|
39
|
-
...(columns ? { columns } : {}),
|
|
40
|
-
when: ({ row }: { value: unknown; row: TData }) =>
|
|
41
|
-
evaluatePredicate(rule.predicate, { row, getValue: ctx.getValue, locale: ctx.locale }),
|
|
42
|
-
...(style.background ? { background: style.background } : {}),
|
|
43
|
-
...(style.color ? { color: style.color } : {}),
|
|
44
|
-
})
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
return formats
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Turn active alert events into conditional formats. Events whose actions only
|
|
52
|
-
* toast/log/flash contribute nothing here. Matching is by row id, so the format
|
|
53
|
-
* follows the row through sort/filter rather than a fixed index.
|
|
54
|
-
*/
|
|
55
|
-
export function toConditionalFormats<TData = Record<string, unknown>>(
|
|
56
|
-
events: ReadonlyArray<AlertEvent>,
|
|
57
|
-
getRowId: (row: TData) => string,
|
|
58
|
-
): ConditionalFormat<TData>[] {
|
|
59
|
-
const formats: ConditionalFormat<TData>[] = []
|
|
60
|
-
for (const event of events) {
|
|
61
|
-
if (event.rowId == null) continue
|
|
62
|
-
const rowId = event.rowId
|
|
63
|
-
for (const action of event.actions) {
|
|
64
|
-
if (!STYLING_KINDS.has(action.kind)) continue
|
|
65
|
-
const columns = action.columns ?? (event.columnId ? [event.columnId] : undefined)
|
|
66
|
-
const style = action.style ?? {}
|
|
67
|
-
formats.push({
|
|
68
|
-
type: 'rule',
|
|
69
|
-
...(columns ? { columns } : {}),
|
|
70
|
-
when: ({ row }: { value: unknown; row: TData }) => getRowId(row) === rowId,
|
|
71
|
-
...(style.background ? { background: style.background } : {}),
|
|
72
|
-
...(style.color ? { color: style.color } : {}),
|
|
73
|
-
})
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return formats
|
|
77
|
-
}
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from 'vitest'
|
|
2
|
-
import { createAlertEngine } from './alert-engine'
|
|
3
|
-
import { createAlertObserver } from './alert-observer'
|
|
4
|
-
import { createAlertScheduler } from './alert-scheduler'
|
|
5
|
-
import type { AlertEvent, AlertRule } from './alert-types'
|
|
6
|
-
|
|
7
|
-
type Row = { id: string; price: number; region: string; status: string }
|
|
8
|
-
|
|
9
|
-
const seedRows = (over: Partial<Row>[] = []): Row[] =>
|
|
10
|
-
[
|
|
11
|
-
{ id: 'a', price: 120, region: 'EU', status: 'open' },
|
|
12
|
-
{ id: 'b', price: 80, region: 'US', status: 'open' },
|
|
13
|
-
].map((r, i) => ({ ...r, ...(over[i] ?? {}) }))
|
|
14
|
-
|
|
15
|
-
const getRowId = (r: Row) => r.id
|
|
16
|
-
|
|
17
|
-
const dataChangeRule: AlertRule = {
|
|
18
|
-
id: 'r1',
|
|
19
|
-
name: 'High price',
|
|
20
|
-
enabled: true,
|
|
21
|
-
severity: 'warning',
|
|
22
|
-
scope: 'row',
|
|
23
|
-
predicate: { kind: 'cmp', column: 'price', op: 'greaterThan', value: 100 },
|
|
24
|
-
trigger: { type: 'dataChange' },
|
|
25
|
-
actions: [{ kind: 'toast', message: '{region} at {value}' }],
|
|
26
|
-
createdAt: 0,
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const relativeRule: AlertRule = {
|
|
30
|
-
id: 'r2',
|
|
31
|
-
name: 'Jumped',
|
|
32
|
-
enabled: true,
|
|
33
|
-
severity: 'info',
|
|
34
|
-
scope: 'row',
|
|
35
|
-
predicate: { kind: 'const', value: true },
|
|
36
|
-
trigger: { type: 'relativeChange', expr: { kind: 'percentChange', column: 'price', op: '>', value: 5, abs: true } },
|
|
37
|
-
actions: [{ kind: 'toast', message: 'moved' }],
|
|
38
|
-
createdAt: 0,
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function harness(rules: AlertRule[]) {
|
|
42
|
-
const engine = createAlertEngine<Row>({ rules, getRowId, now: () => 1000 })
|
|
43
|
-
const events: AlertEvent[] = []
|
|
44
|
-
const observer = createAlertObserver<Row>({
|
|
45
|
-
engine,
|
|
46
|
-
getRowId,
|
|
47
|
-
schedule: 'sync', // deterministic: runs inline
|
|
48
|
-
onEvents: (batch) => events.push(...batch),
|
|
49
|
-
})
|
|
50
|
-
return { engine, observer, events }
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
describe('engine.needsPrev / needsFullSet', () => {
|
|
54
|
-
it('needsPrev is true only when a relativeChange rule is enabled', () => {
|
|
55
|
-
expect(createAlertEngine<Row>({ rules: [dataChangeRule], getRowId }).needsPrev()).toBe(false)
|
|
56
|
-
expect(createAlertEngine<Row>({ rules: [relativeRule], getRowId }).needsPrev()).toBe(true)
|
|
57
|
-
expect(
|
|
58
|
-
createAlertEngine<Row>({ rules: [{ ...relativeRule, enabled: false }], getRowId }).needsPrev(),
|
|
59
|
-
).toBe(false)
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
it('needsFullSet is true only when an aggregate-scope rule is enabled', () => {
|
|
63
|
-
expect(createAlertEngine<Row>({ rules: [dataChangeRule], getRowId }).needsFullSet()).toBe(false)
|
|
64
|
-
const agg: AlertRule = { ...dataChangeRule, id: 'agg', scope: 'aggregate' }
|
|
65
|
-
expect(createAlertEngine<Row>({ rules: [agg], getRowId }).needsFullSet()).toBe(true)
|
|
66
|
-
})
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
describe('createAlertObserver push mode', () => {
|
|
70
|
-
it('seed is silent - pre-existing matches do not fire', () => {
|
|
71
|
-
const { observer, events } = harness([dataChangeRule])
|
|
72
|
-
observer.seed(seedRows()) // 'a' already > 100
|
|
73
|
-
expect(events).toHaveLength(0)
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
it('pushChanged fires only for the rows it is given, once on crossing', () => {
|
|
77
|
-
const { observer, events } = harness([dataChangeRule])
|
|
78
|
-
observer.seed(seedRows([{ price: 90 }])) // 'a' starts below threshold
|
|
79
|
-
// 'b' unchanged and below threshold; push 'a' now crossing.
|
|
80
|
-
observer.pushChanged([{ id: 'a', price: 130, region: 'EU', status: 'open' }])
|
|
81
|
-
expect(events).toHaveLength(1)
|
|
82
|
-
expect(events[0]!.rowId).toBe('a')
|
|
83
|
-
// Pushing it again while it stays above must not re-fire (edge memory).
|
|
84
|
-
observer.pushChanged([{ id: 'a', price: 131, region: 'EU', status: 'open' }])
|
|
85
|
-
expect(events).toHaveLength(1)
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
it('does not evaluate rows that were never pushed', () => {
|
|
89
|
-
const { observer, events } = harness([dataChangeRule])
|
|
90
|
-
observer.seed(seedRows([{ price: 90 }, { price: 95 }])) // both below
|
|
91
|
-
// Only 'b' is pushed, crossing the line; 'a' is untouched.
|
|
92
|
-
observer.pushChanged([{ id: 'b', price: 150, region: 'US', status: 'open' }])
|
|
93
|
-
expect(events).toHaveLength(1)
|
|
94
|
-
expect(events[0]!.rowId).toBe('b')
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
it('relativeChange push sees prev via the maintained snapshot', () => {
|
|
98
|
-
const { observer, events } = harness([relativeRule])
|
|
99
|
-
const start = seedRows()
|
|
100
|
-
observer.seed(start)
|
|
101
|
-
// 'a' 120 -> 140 is +16% -> fires.
|
|
102
|
-
observer.pushChanged([{ id: 'a', price: 140, region: 'EU', status: 'open' }])
|
|
103
|
-
expect(events).toHaveLength(1)
|
|
104
|
-
expect(events[0]!.columnId).toBe('price')
|
|
105
|
-
})
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
describe('createAlertObserver scales O(changed), not O(total)', () => {
|
|
109
|
-
it('a push over a 100k seed touches only the changed rows', () => {
|
|
110
|
-
// Seed 100k rows, then push a handful. The evaluation must not re-scan the
|
|
111
|
-
// whole set - we assert by counting getRowId calls after the seed.
|
|
112
|
-
let calls = 0
|
|
113
|
-
const countingId = (r: Row) => {
|
|
114
|
-
calls++
|
|
115
|
-
return r.id
|
|
116
|
-
}
|
|
117
|
-
const engine = createAlertEngine<Row>({ rules: [dataChangeRule], getRowId: countingId, now: () => 1000 })
|
|
118
|
-
const events: AlertEvent[] = []
|
|
119
|
-
const observer = createAlertObserver<Row>({
|
|
120
|
-
engine,
|
|
121
|
-
getRowId: countingId,
|
|
122
|
-
schedule: 'sync',
|
|
123
|
-
onEvents: (b) => events.push(...b),
|
|
124
|
-
})
|
|
125
|
-
|
|
126
|
-
const big: Row[] = Array.from({ length: 100_000 }, (_, i) => ({
|
|
127
|
-
id: `r${i}`,
|
|
128
|
-
price: 10, // all below the >100 threshold
|
|
129
|
-
region: 'EU',
|
|
130
|
-
status: 'open',
|
|
131
|
-
}))
|
|
132
|
-
observer.seed(big)
|
|
133
|
-
calls = 0 // ignore the one-time seed cost; measure only the push
|
|
134
|
-
|
|
135
|
-
observer.pushChanged([{ id: 'r5', price: 130, region: 'EU', status: 'open' }])
|
|
136
|
-
expect(events).toHaveLength(1)
|
|
137
|
-
expect(events[0]!.rowId).toBe('r5')
|
|
138
|
-
// O(changed): a single changed row costs a bounded handful of id lookups,
|
|
139
|
-
// nowhere near the 100k total.
|
|
140
|
-
expect(calls).toBeLessThan(50)
|
|
141
|
-
})
|
|
142
|
-
})
|
|
143
|
-
|
|
144
|
-
describe('createAlertObserver scan (watch) mode', () => {
|
|
145
|
-
it('index-diffs the array and evaluates only changed rows', () => {
|
|
146
|
-
const { observer, events } = harness([dataChangeRule])
|
|
147
|
-
let data: Row[] = seedRows([{ price: 90 }]) // 'a' below
|
|
148
|
-
observer.scan(() => data) // first scan seeds silently
|
|
149
|
-
expect(events).toHaveLength(0)
|
|
150
|
-
// Immutable replace of 'a' only (Svelte-5 style).
|
|
151
|
-
data = [{ ...data[0]!, price: 130 }, data[1]!]
|
|
152
|
-
observer.scan(() => data)
|
|
153
|
-
expect(events).toHaveLength(1)
|
|
154
|
-
expect(events[0]!.rowId).toBe('a')
|
|
155
|
-
})
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
describe('createScheduler', () => {
|
|
159
|
-
it('sync mode runs immediately', () => {
|
|
160
|
-
const s = createAlertScheduler('sync')
|
|
161
|
-
const fn = vi.fn()
|
|
162
|
-
s.schedule(fn)
|
|
163
|
-
expect(fn).toHaveBeenCalledTimes(1)
|
|
164
|
-
expect(s.pending).toBe(false)
|
|
165
|
-
})
|
|
166
|
-
|
|
167
|
-
it('coalesces multiple schedules and flush runs the latest once', () => {
|
|
168
|
-
const s = createAlertScheduler('raf') // no rAF in node -> setTimeout fallback, but flush is sync
|
|
169
|
-
const a = vi.fn()
|
|
170
|
-
const b = vi.fn()
|
|
171
|
-
s.schedule(a)
|
|
172
|
-
s.schedule(b)
|
|
173
|
-
expect(s.pending).toBe(true)
|
|
174
|
-
s.flush()
|
|
175
|
-
// Latest wins - only the most recent callback runs, exactly once.
|
|
176
|
-
expect(a).not.toHaveBeenCalled()
|
|
177
|
-
expect(b).toHaveBeenCalledTimes(1)
|
|
178
|
-
expect(s.pending).toBe(false)
|
|
179
|
-
})
|
|
180
|
-
|
|
181
|
-
it('cancel drops the pending callback', () => {
|
|
182
|
-
const s = createAlertScheduler('raf')
|
|
183
|
-
const fn = vi.fn()
|
|
184
|
-
s.schedule(fn)
|
|
185
|
-
s.cancel()
|
|
186
|
-
s.flush()
|
|
187
|
-
expect(fn).not.toHaveBeenCalled()
|
|
188
|
-
})
|
|
189
|
-
})
|