@altertable/data-app 0.66.0 → 0.68.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.
Files changed (138) hide show
  1. package/CONTRIBUTING.md +22 -16
  2. package/dist/chunks/{contract-19ckn3n7.js → index-23dktynd.js} +8 -6
  3. package/dist/chunks/index-23dktynd.js.map +10 -0
  4. package/dist/chunks/{contract-rfbakka4.js → index-ag0cgnvq.js} +169 -35
  5. package/dist/chunks/index-ag0cgnvq.js.map +13 -0
  6. package/dist/chunks/index-dq7b35fn.js +307 -0
  7. package/dist/chunks/index-dq7b35fn.js.map +13 -0
  8. package/dist/chunks/{contract-e11m4y7f.js → index-ev2b5aaf.js} +11 -6
  9. package/dist/chunks/{contract-e11m4y7f.js.map → index-ev2b5aaf.js.map} +3 -3
  10. package/dist/chunks/{contract-awa2d5b1.js → index-f5cnbrjz.js} +19 -2
  11. package/dist/chunks/{contract-awa2d5b1.js.map → index-f5cnbrjz.js.map} +4 -3
  12. package/dist/chunks/{contract-havnjmdr.js → index-gvers8jw.js} +2429 -1110
  13. package/dist/chunks/index-gvers8jw.js.map +109 -0
  14. package/dist/chunks/{contract-13j5zb3c.js → index-ktmvs916.js} +8 -7
  15. package/dist/chunks/index-ktmvs916.js.map +13 -0
  16. package/dist/chunks/index-mt93ff2b.js +28 -0
  17. package/dist/chunks/index-mt93ff2b.js.map +10 -0
  18. package/dist/chunks/{contract-tf8c3qpv.js → index-qd5xgx6y.js} +46 -5
  19. package/dist/chunks/index-qd5xgx6y.js.map +13 -0
  20. package/dist/chunks/{contract-pk603qj7.js → index-x69p7cv7.js} +12 -9
  21. package/dist/chunks/index-x69p7cv7.js.map +10 -0
  22. package/dist/client/index.js +6 -6
  23. package/dist/core/appearance.js +1 -1
  24. package/dist/core/config.js +7 -3
  25. package/dist/core/config.js.map +1 -1
  26. package/dist/core/contract.js +14 -6
  27. package/dist/core/contract.js.map +1 -1
  28. package/dist/core/format.js +1 -1
  29. package/dist/embed/index.js +12 -10
  30. package/dist/embed/index.js.map +4 -4
  31. package/dist/index.js +12 -0
  32. package/dist/index.js.map +9 -0
  33. package/dist/local.js +20 -30
  34. package/dist/local.js.map +7 -8
  35. package/dist/react/embed/index.js +1 -1
  36. package/dist/react/embed/index.js.map +2 -2
  37. package/dist/react/index.js +79 -29
  38. package/dist/react/index.js.map +5 -6
  39. package/dist/react/ui/index.js +1702 -177
  40. package/dist/react/ui/index.js.map +20 -9
  41. package/dist/server.js +13 -26
  42. package/dist/server.js.map +6 -7
  43. package/dist/types/client/annotations.d.ts +4 -0
  44. package/dist/types/client/data-client.d.ts +1 -2
  45. package/dist/types/client/iframe.d.ts +4 -2
  46. package/dist/types/core/annotations.d.ts +2 -0
  47. package/dist/types/core/config.d.ts +48 -4
  48. package/dist/types/core/contract.d.ts +20 -12
  49. package/dist/types/core/dimension.d.ts +6 -4
  50. package/dist/types/core/filters.d.ts +44 -0
  51. package/dist/types/core/messages.d.ts +2 -0
  52. package/dist/types/core/operation-types.d.ts +5 -2
  53. package/dist/types/core/operation.d.ts +3 -4
  54. package/dist/types/core/queries.d.ts +16 -0
  55. package/dist/types/core/uuid.d.ts +2 -0
  56. package/dist/types/core/variables.d.ts +32 -13
  57. package/dist/types/embed/runtime-html.d.ts +2 -0
  58. package/dist/types/embed/source.d.ts +2 -1
  59. package/dist/types/index.d.ts +3 -0
  60. package/dist/types/react/annotations/AnnotationBar.d.ts +7 -1
  61. package/dist/types/react/annotations/AnnotationEditor.d.ts +2 -1
  62. package/dist/types/react/annotations/useDataAppAnnotations.d.ts +3 -0
  63. package/dist/types/react/app-context.d.ts +3 -0
  64. package/dist/types/react/index.d.ts +3 -3
  65. package/dist/types/react/mount.d.ts +6 -4
  66. package/dist/types/react/style-contract.d.ts +34 -2
  67. package/dist/types/react/ui/Button.d.ts +3 -3
  68. package/dist/types/react/ui/ChartLegend.d.ts +31 -0
  69. package/dist/types/react/ui/Checkbox.d.ts +15 -4
  70. package/dist/types/react/ui/CheckboxGroup.d.ts +7 -0
  71. package/dist/types/react/ui/{Combobox.d.ts → ChoicePicker.d.ts} +10 -15
  72. package/dist/types/react/ui/ComposedChart.d.ts +41 -0
  73. package/dist/types/react/ui/ComposedChartLegend.d.ts +8 -0
  74. package/dist/types/react/ui/DataAppFrame.d.ts +1 -2
  75. package/dist/types/react/ui/DimensionPicker.d.ts +1 -1
  76. package/dist/types/react/ui/FilterActions.d.ts +10 -0
  77. package/dist/types/react/ui/FilterBar.d.ts +3 -0
  78. package/dist/types/react/ui/FunnelChart.d.ts +20 -0
  79. package/dist/types/react/ui/GettingStarted.d.ts +2 -4
  80. package/dist/types/react/ui/JourneyChart.d.ts +10 -0
  81. package/dist/types/react/ui/Menu.d.ts +12 -0
  82. package/dist/types/react/ui/NumberField.d.ts +27 -0
  83. package/dist/types/react/ui/NumberFilterPicker.d.ts +9 -0
  84. package/dist/types/react/ui/PieChart.d.ts +5 -2
  85. package/dist/types/react/ui/RadioGroup.d.ts +18 -0
  86. package/dist/types/react/ui/RetentionChart.d.ts +27 -0
  87. package/dist/types/react/ui/SearchInput.d.ts +2 -2
  88. package/dist/types/react/ui/Select.d.ts +14 -0
  89. package/dist/types/react/ui/SelectionMark.d.ts +2 -1
  90. package/dist/types/react/ui/TooltipSurface.d.ts +3 -0
  91. package/dist/types/react/ui/chart-data.d.ts +10 -1
  92. package/dist/types/react/ui/chart-primitives.d.ts +22 -0
  93. package/dist/types/react/ui/chartColor.d.ts +1 -0
  94. package/dist/types/react/ui/icons.d.ts +1 -0
  95. package/dist/types/react/ui/index.d.ts +33 -2
  96. package/dist/types/react/ui/journey-flow.d.ts +49 -0
  97. package/dist/types/react/ui/keyboard.d.ts +6 -0
  98. package/dist/types/react/ui/shortcuts.d.ts +7 -0
  99. package/dist/types/react/ui/useAppAppearance.d.ts +1 -1
  100. package/dist/types/react/ui/useSvgId.d.ts +2 -0
  101. package/dist/types/react/ui/variables.d.ts +4 -2
  102. package/dist/types/react/view-controls.d.ts +3 -1
  103. package/dist/types/server/handler.d.ts +4 -4
  104. package/dist/worker.js +21 -738
  105. package/docs/app-authoring.md +15 -1
  106. package/docs/client.md +8 -8
  107. package/docs/contract.md +43 -20
  108. package/docs/data-context.md +8 -6
  109. package/docs/embed.md +10 -2
  110. package/docs/formatting-and-appearance.md +23 -7
  111. package/docs/hosted-apps.md +9 -2
  112. package/docs/layout.md +1 -1
  113. package/docs/react-embed.md +3 -2
  114. package/docs/react.md +4 -3
  115. package/docs/server-bun.md +1 -1
  116. package/docs/server.md +4 -4
  117. package/docs/styling.md +10 -3
  118. package/docs/ui.md +176 -3
  119. package/docs/variables.md +80 -7
  120. package/docs/views.md +4 -8
  121. package/docs/widgets.md +19 -13
  122. package/docs/worker.md +2 -1
  123. package/examples/starter-data-app/index.tsx +34 -32
  124. package/package.json +16 -11
  125. package/dist/chunks/contract-13j5zb3c.js.map +0 -13
  126. package/dist/chunks/contract-19ckn3n7.js.map +0 -10
  127. package/dist/chunks/contract-h8a6f559.js +0 -286
  128. package/dist/chunks/contract-h8a6f559.js.map +0 -12
  129. package/dist/chunks/contract-havnjmdr.js.map +0 -99
  130. package/dist/chunks/contract-pk603qj7.js.map +0 -10
  131. package/dist/chunks/contract-rfbakka4.js.map +0 -13
  132. package/dist/chunks/contract-tf8c3qpv.js.map +0 -11
  133. package/dist/chunks/contract-wz59z8pq.js +0 -8
  134. package/dist/chunks/contract-wz59z8pq.js.map +0 -10
  135. /package/dist/chunks/{contract-m6n8ctfc.js → index-m6n8ctfc.js} +0 -0
  136. /package/dist/chunks/{contract-m6n8ctfc.js.map → index-m6n8ctfc.js.map} +0 -0
  137. /package/dist/chunks/{contract-mev09s5v.js → index-mev09s5v.js} +0 -0
  138. /package/dist/chunks/{contract-mev09s5v.js.map → index-mev09s5v.js.map} +0 -0
package/CONTRIBUTING.md CHANGED
@@ -4,6 +4,7 @@ Use the Bun and Node.js versions in `.bun-version` and `.node-version`.
4
4
 
5
5
  ```fish
6
6
  bun install --frozen-lockfile
7
+ bash scripts/install-test-browser.sh
7
8
  bun run check
8
9
  ```
9
10
 
@@ -36,12 +37,21 @@ fallbacks minimal.
36
37
 
37
38
  ## Verify changes
38
39
 
39
- Tests should tell the package's public usage stories: define an operation,
40
- authorize and query it, compose a view, or embed an app. Exercise published
41
- entries so build and export mistakes are observable. Test private logic in
42
- isolation only when its complexity warrants it, such as cancellation, streaming,
43
- SQL escaping, or authenticated bridge sessions. Avoid tests that repeat trivial
44
- helpers, file layout, or every component prop.
40
+ Write high-level public API tests with Vitest in `tests/public-api`. Define an
41
+ operation, authorize and query it, compose a view, or embed an app through
42
+ `@altertable/data-app/<entry>`. Assert consumer-visible results and errors. Supply
43
+ data and failures through public dependency injection; do not import private
44
+ source, fabricate internal state, or assert implementation details. Prefer queries by role and accessible name, or by label for form fields. Scope
45
+ content assertions to the relevant region, status, alert, or dialog; use text
46
+ queries for prose with no meaningful role. Do not invent ARIA roles for tests.
47
+ Group browser workflows by consumer capability in `apps-*.test.ts`; keep tests
48
+ self-contained and setup local until repetition warrants sharing it.
49
+
50
+ `bun run test` runs the complete suite against the built package. Browser
51
+ workflows launch Chromium through Playwright from Vitest. They use public
52
+ consumer fixtures, an isolated local server, and a fresh browser context per
53
+ test. Build first; run one file with `bun run test tests/public-api/apps-export.test.ts`
54
+ or one workflow with `bun run test -t "workflow name"`.
45
55
 
46
56
  Update the relevant guide when changing public behavior. In documentation prose,
47
57
  write functions as `functionName()` and components as `<ComponentName>`. Keep JSDoc for
@@ -63,10 +73,9 @@ checks. Build before running consumer tests individually.
63
73
  | `bun run check:links` | Validate local files, images, and heading links |
64
74
  | `bun run check:links:external` | Check external URLs (requires network access) |
65
75
  | `bun run format` | Format source and docs |
66
- | `bun run test` | Verify public contracts and complex isolated logic |
67
- | `bun run test:package` | Verify the npm archive as a consumer |
68
- | `bun run test:starter` | Typecheck, lint, and build the starter |
69
- | `bun run test:browser` | Verify browser interactions in Chromium |
76
+ | `bun run test` | Verify high-level public API workflows with Vitest |
77
+ | `bun run check:package` | Verify the npm archive as a consumer |
78
+ | `bun run check:starter` | Typecheck, lint, and build the starter |
70
79
  | `bun run check:workflows` | Validate workflows and shell scripts |
71
80
 
72
81
  Markdown checks cover all authored `.md` files, including `AGENTS.md` and the
@@ -79,18 +88,15 @@ It skips local development URLs and checks reachability without external heading
79
88
  validation. It stays outside required checks because third-party availability and
80
89
  rate limits can cause failures unrelated to a change.
81
90
 
82
- For browser changes, run `bash scripts/install-test-browser.sh` once, then
83
- `bun run test:browser`.
84
-
85
91
  Run `bun run dev` to preview UI examples at `http://127.0.0.1:27418/gallery`
86
92
  and a playground at `/playground` (`dev/playground.tsx`, querying the demo
87
- tables `scripts/dev.ts` seeds). It builds once, then rebuilds `dist` when `src`
93
+ tables from `dev/seed.ts` that `scripts/dev.ts` seeds). It builds once, then rebuilds `dist` when `src`
88
94
  changes; open pages reload on package, fixture, and playground edits. Restart it after changing
89
- `browser-tests/server.ts`; rerun `bun run build` to refresh declarations. Add `?delay=2000` to a host page URL
95
+ `dev/server.ts`; rerun `bun run build` to refresh declarations. Add `?delay=2000` to a host page URL
90
96
  to delay its SQL responses and inspect loading states. It needs Docker: SQL runs
91
97
  against a mocked Altertable API
92
98
  ([altertable-mock](https://github.com/altertable-ai/altertable-mock), DuckDB)
93
- started with Testcontainers and stopped on exit. Browser tests keep fixtures.
99
+ started with Testcontainers and stopped on exit. Public API tests use their own deterministic consumer fixtures.
94
100
 
95
101
  Open the **Widgets** tab (`/gallery?view=widgets`) for one ready example of each
96
102
  composable data display inside `<VisualizationWidget>`. The other tabs cover
@@ -1,17 +1,20 @@
1
1
  import {
2
2
  executeDataOperation,
3
3
  toDataOperationFailure
4
- } from "./contract-pk603qj7.js";
4
+ } from "./index-x69p7cv7.js";
5
5
  import {
6
6
  DataAppError2,
7
7
  createHttpTransport2,
8
8
  localFrameBridge,
9
9
  getDataAppTransport2
10
- } from "./contract-13j5zb3c.js";
10
+ } from "./index-ktmvs916.js";
11
+ import {
12
+ randomUuid
13
+ } from "./index-f5cnbrjz.js";
11
14
  import {
12
15
  MessageRoutingError2,
13
16
  defineDataQueryRoute2
14
- } from "./contract-tf8c3qpv.js";
17
+ } from "./index-qd5xgx6y.js";
15
18
 
16
19
  // src/client/data-client.ts
17
20
  var dataQueryRoute = defineDataQueryRoute2();
@@ -46,7 +49,7 @@ function createOperationClient(options) {
46
49
  return {
47
50
  async query(name, input, { signal } = {}) {
48
51
  signal?.throwIfAborted();
49
- const requestId = crypto.randomUUID();
52
+ const requestId = randomUuid();
50
53
  if (!Object.hasOwn(options.operations, name))
51
54
  throw new DataAppError2("Unknown data operation.", "not_found", requestId);
52
55
  const lakehouse = options.lakehouse ?? (typeof window === "undefined" ? undefined : getDataAppTransport2()?.lakehouse);
@@ -56,7 +59,6 @@ function createOperationClient(options) {
56
59
  const { body } = await executeDataOperation(options.operations[name], input, {
57
60
  lakehouse,
58
61
  signal: signal ?? new AbortController().signal,
59
- includeSql: true,
60
62
  requestId,
61
63
  operationName: name
62
64
  });
@@ -75,4 +77,4 @@ function createOperationClient(options) {
75
77
 
76
78
  export { createDataClient2 };
77
79
 
78
- //# debugId=64AFD24787CC437264756E2164756E21
80
+ //# debugId=F1FFBCC98547BBCD64756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/client/data-client.ts"],
4
+ "sourcesContent": [
5
+ "import { randomUuid } from '@/src/core/uuid';\nimport { createHttpTransport, DataAppError } from '@/src/client/transport';\nimport { getDataAppTransport, localFrameBridge } from '@/src/client/iframe';\nimport {\n executeDataOperation,\n toDataOperationFailure,\n} from '@/src/core/operation';\nimport type { DataOperations, Lakehouse } from '@/src/core/contract';\nimport { defineDataQueryRoute, MessageRoutingError } from '@/src/core/messages';\nimport type { DataTransport } from '@/src/client/transport';\nimport type {\n DataQueryBody,\n InputOf,\n OutputOf,\n} from '@/src/core/operation-types';\nexport type { InputOf, OutputOf } from '@/src/core/operation-types';\n\n/**\n * Parsed operation data and query evidence.\n */\nexport type DataResponse<Output, Input = unknown> = DataQueryBody<Output> & {\n /** The exact browser input that produced this response. */\n input: Input;\n};\n\nexport type DataClient<Operations extends DataOperations> = {\n query<Name extends keyof Operations & string>(\n name: Name,\n input: InputOf<Operations[Name]>,\n options?: { signal?: AbortSignal }\n ): Promise<\n DataResponse<OutputOf<Operations[Name]>, InputOf<Operations[Name]>>\n >;\n};\n\n/** Browser operations and named-operation delivery are mutually exclusive configurations. */\nexport type DataClientOptions<Operations extends DataOperations> =\n | {\n operations: Operations;\n lakehouse?: Lakehouse;\n transport?: never;\n endpoint?: never;\n fetch?: never;\n }\n | {\n operations?: never;\n lakehouse?: never;\n transport?: DataTransport;\n endpoint?: string;\n fetch?: typeof fetch;\n };\n\nconst dataQueryRoute = defineDataQueryRoute();\n\n/** Named HTTP operations, or browser-owned operations executed through an authorized SQL bridge. */\nexport function createDataClient<Operations extends DataOperations>(\n options: DataClientOptions<Operations> = {}\n): DataClient<Operations> {\n if (options.operations)\n return createOperationClient({\n operations: options.operations,\n lakehouse: options.lakehouse,\n });\n const http = createHttpTransport(options);\n const useHttp = options.endpoint !== undefined || options.fetch !== undefined;\n\n return {\n async query(name, input, { signal } = {}) {\n const transport =\n options.transport ??\n (useHttp ? http : (localFrameBridge()?.transport ?? http));\n const response = await transport(name, input, signal);\n const ok = response.status >= 200 && response.status < 300;\n let body: Omit<DataResponse<OutputOf<Operations[typeof name]>>, 'input'>;\n try {\n body = dataQueryRoute.output(response, { operation: name, input })\n .body as typeof body;\n } catch (error) {\n if (signal?.aborted) throw error;\n if (error instanceof MessageRoutingError)\n throw new DataAppError(error.message, error.code, error.requestId);\n throw new DataAppError(\n ok ? 'The data response was invalid.' : 'Could not load data.',\n ok ? 'invalid_response' : 'request_failed'\n );\n }\n\n return { ...body, input };\n },\n };\n}\n\nfunction createOperationClient<Operations extends DataOperations>(options: {\n operations: Operations;\n lakehouse?: Lakehouse;\n}): DataClient<Operations> {\n return {\n async query(name, input, { signal } = {}) {\n signal?.throwIfAborted();\n const requestId = randomUuid();\n if (!Object.hasOwn(options.operations, name))\n throw new DataAppError(\n 'Unknown data operation.',\n 'not_found',\n requestId\n );\n const lakehouse =\n options.lakehouse ??\n (typeof window === 'undefined'\n ? undefined\n : getDataAppTransport()?.lakehouse);\n if (!lakehouse)\n throw new DataAppError(\n 'An authorized SQL bridge must be installed first.',\n 'bridge_unavailable',\n requestId\n );\n\n try {\n const { body } = await executeDataOperation(\n options.operations[name]!,\n input,\n {\n lakehouse,\n signal: signal ?? new AbortController().signal,\n requestId,\n operationName: name,\n }\n );\n\n return { ...body, input } as DataResponse<\n OutputOf<Operations[typeof name]>,\n InputOf<Operations[typeof name]>\n >;\n } catch (error) {\n if (signal?.aborted) throw signal.reason;\n if (error instanceof DataAppError) throw error;\n const failure = toDataOperationFailure(error);\n throw new DataAppError(failure.message, failure.code, requestId);\n }\n },\n };\n}\n"
6
+ ],
7
+ "mappings": ";;;;;;;;;;;;;;;;;;;AAoDA,IAAM,iBAAiB,sBAAqB;AAGrC,SAAS,iBAAmD,CACjE,UAAyC,CAAC,GAClB;AAAA,EACxB,IAAI,QAAQ;AAAA,IACV,OAAO,sBAAsB;AAAA,MAC3B,YAAY,QAAQ;AAAA,MACpB,WAAW,QAAQ;AAAA,IACrB,CAAC;AAAA,EACH,MAAM,OAAO,qBAAoB,OAAO;AAAA,EACxC,MAAM,UAAU,QAAQ,aAAa,aAAa,QAAQ,UAAU;AAAA,EAEpE,OAAO;AAAA,SACC,MAAK,CAAC,MAAM,SAAS,WAAW,CAAC,GAAG;AAAA,MACxC,MAAM,YACJ,QAAQ,cACP,UAAU,OAAQ,iBAAiB,GAAG,aAAa;AAAA,MACtD,MAAM,WAAW,MAAM,UAAU,MAAM,OAAO,MAAM;AAAA,MACpD,MAAM,KAAK,SAAS,UAAU,OAAO,SAAS,SAAS;AAAA,MACvD,IAAI;AAAA,MACJ,IAAI;AAAA,QACF,OAAO,eAAe,OAAO,UAAU,EAAE,WAAW,MAAM,MAAM,CAAC,EAC9D;AAAA,QACH,OAAO,OAAO;AAAA,QACd,IAAI,QAAQ;AAAA,UAAS,MAAM;AAAA,QAC3B,IAAI,iBAAiB;AAAA,UACnB,MAAM,IAAI,cAAa,MAAM,SAAS,MAAM,MAAM,MAAM,SAAS;AAAA,QACnE,MAAM,IAAI,cACR,KAAK,mCAAmC,wBACxC,KAAK,qBAAqB,gBAC5B;AAAA;AAAA,MAGF,OAAO,KAAK,MAAM,MAAM;AAAA;AAAA,EAE5B;AAAA;AAGF,SAAS,qBAAwD,CAAC,SAGvC;AAAA,EACzB,OAAO;AAAA,SACC,MAAK,CAAC,MAAM,SAAS,WAAW,CAAC,GAAG;AAAA,MACxC,QAAQ,eAAe;AAAA,MACvB,MAAM,YAAY,WAAW;AAAA,MAC7B,IAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,IAAI;AAAA,QACzC,MAAM,IAAI,cACR,2BACA,aACA,SACF;AAAA,MACF,MAAM,YACJ,QAAQ,cACP,OAAO,WAAW,cACf,YACA,qBAAoB,GAAG;AAAA,MAC7B,IAAI,CAAC;AAAA,QACH,MAAM,IAAI,cACR,qDACA,sBACA,SACF;AAAA,MAEF,IAAI;AAAA,QACF,QAAQ,SAAS,MAAM,qBACrB,QAAQ,WAAW,OACnB,OACA;AAAA,UACE;AAAA,UACA,QAAQ,UAAU,IAAI,gBAAgB,EAAE;AAAA,UACxC;AAAA,UACA,eAAe;AAAA,QACjB,CACF;AAAA,QAEA,OAAO,KAAK,MAAM,MAAM;AAAA,QAIxB,OAAO,OAAO;AAAA,QACd,IAAI,QAAQ;AAAA,UAAS,MAAM,OAAO;AAAA,QAClC,IAAI,iBAAiB;AAAA,UAAc,MAAM;AAAA,QACzC,MAAM,UAAU,uBAAuB,KAAK;AAAA,QAC5C,MAAM,IAAI,cAAa,QAAQ,SAAS,QAAQ,MAAM,SAAS;AAAA;AAAA;AAAA,EAGrE;AAAA;",
8
+ "debugId": "F1FFBCC98547BBCD64756E2164756E21",
9
+ "names": []
10
+ }
@@ -1,33 +1,30 @@
1
1
  import {
2
2
  formatDateRange2
3
- } from "./contract-mev09s5v.js";
3
+ } from "./index-mev09s5v.js";
4
4
  import {
5
+ invariant,
6
+ snapshotQueries,
7
+ resolveQueryParameters,
5
8
  defineMessageRoute2
6
- } from "./contract-tf8c3qpv.js";
9
+ } from "./index-qd5xgx6y.js";
7
10
 
8
11
  // src/core/contract.ts
9
12
  import { parseDate, today } from "@internationalized/date";
10
13
 
11
- // src/core/invariant.ts
12
- function invariant(condition, message) {
13
- if (!condition)
14
- throw new Error(`Invariant failed: ${message}`);
15
- }
16
-
17
14
  // src/core/dimension.ts
18
15
  var allSelection = { kind: "all" };
19
16
  function dimensionMemberKey(member) {
20
17
  return member.kind === "missing" ? "missing" : `value:${typeof member.value}:${member.value}`;
21
18
  }
22
19
  function dimensionFilter2(config) {
23
- const { key, label, selection, valueType } = config;
20
+ const { key, label, selectionMode, valueType } = config;
24
21
  const options = config.options ?? [];
25
22
  const optionKeys = options.map((option) => dimensionMemberKey({ kind: "value", value: option.value }));
26
23
  invariant(!!key && options.length <= 200 && new Set(optionKeys).size === options.length, "Dimension options need a key, at most 200 distinct values.");
27
24
  invariant(options.every((option) => typeof option.value === valueType && !!option.label.trim() && (option.count === undefined || Number.isSafeInteger(option.count) && option.count >= 0)), "Dimension options need typed values, labels, and nonnegative counts.");
28
25
  const allowed = new Set(optionKeys);
29
- const maxSelected = config.maxSelected ?? (selection === "single" ? 1 : 20);
30
- invariant(Number.isInteger(maxSelected) && maxSelected >= 1 && maxSelected <= 50 && (selection !== "single" || maxSelected === 1), "Dimension selection limit is invalid.");
26
+ const maxSelected = config.maxSelected ?? (selectionMode === "single" ? 1 : 20);
27
+ invariant(Number.isInteger(maxSelected) && maxSelected >= 1 && maxSelected <= 50 && (selectionMode !== "single" || maxSelected === 1), "Dimension selection limit is invalid.");
31
28
  const allowMissing = config.allowMissing ?? false;
32
29
  const defaultValue = allSelection;
33
30
  function validMember(member) {
@@ -44,13 +41,16 @@ function dimensionFilter2(config) {
44
41
  return false;
45
42
  if (value.kind === "all")
46
43
  return true;
47
- if (value.kind !== "include" || !Array.isArray(value.members) || !value.members.length || value.members.length > maxSelected)
44
+ if (value.kind !== "include" && !(config.allowExclusion && value.kind === "exclude") || !Array.isArray(value.members) || !value.members.length || value.members.length > maxSelected)
48
45
  return false;
49
46
  const ids = value.members.map(dimensionMemberKey);
50
47
  return new Set(ids).size === ids.length && value.members.every(validMember);
51
48
  }
52
49
  function encode(value) {
53
- return value.kind === "all" ? null : JSON.stringify(value.members.map((member) => member.kind === "missing" ? ["m"] : ["v", member.value]));
50
+ return value.kind === "all" ? null : JSON.stringify({
51
+ kind: value.kind,
52
+ members: value.members.map((member) => member.kind === "missing" ? ["m"] : ["v", member.value])
53
+ });
54
54
  }
55
55
  function parse(raw) {
56
56
  if (raw === null)
@@ -58,12 +58,13 @@ function dimensionFilter2(config) {
58
58
  if (raw.length > 4096)
59
59
  return defaultValue;
60
60
  try {
61
- const tokens = JSON.parse(raw);
62
- if (!Array.isArray(tokens))
61
+ const parsed = JSON.parse(raw);
62
+ const tokens = Array.isArray(parsed) ? { kind: "include", members: parsed } : parsed;
63
+ if (!tokens || !Array.isArray(tokens.members))
63
64
  return defaultValue;
64
65
  const value = {
65
- kind: "include",
66
- members: tokens.map((token) => Array.isArray(token) && token.length === 1 && token[0] === "m" ? { kind: "missing" } : Array.isArray(token) && token.length === 2 && token[0] === "v" ? { kind: "value", value: token[1] } : { kind: "invalid" })
66
+ kind: tokens.kind,
67
+ members: tokens.members.map((token) => Array.isArray(token) && token.length === 1 && token[0] === "m" ? { kind: "missing" } : Array.isArray(token) && token.length === 2 && token[0] === "v" ? { kind: "value", value: token[1] } : { kind: "invalid" })
67
68
  };
68
69
  return valid(value) ? value : defaultValue;
69
70
  } catch {
@@ -74,13 +75,15 @@ function dimensionFilter2(config) {
74
75
  kind: "dimension",
75
76
  label,
76
77
  valueType,
77
- selection,
78
+ selectionMode,
78
79
  options,
79
80
  facet: config.facet,
80
81
  allowMissing,
82
+ allowExclusion: config.allowExclusion ?? false,
81
83
  maxSelected,
82
84
  urlKeys: [key],
83
85
  defaultValue,
86
+ clearValue: allSelection,
84
87
  history: config.history ?? "push",
85
88
  valid,
86
89
  same(left, right) {
@@ -93,7 +96,7 @@ function dimensionFilter2(config) {
93
96
  return { [key]: encode(value) };
94
97
  },
95
98
  describe(value) {
96
- return value.kind === "all" ? `All ${label.toLocaleLowerCase()}` : value.members.map((member) => member.kind === "missing" ? "Missing" : options.find((option) => option.value === member.value)?.label ?? String(member.value)).join(", ");
99
+ return value.kind === "all" ? `All ${label.toLocaleLowerCase()}` : `${value.kind === "exclude" ? "Exclude: " : ""}${value.members.map((member) => member.kind === "missing" ? "Missing" : options.find((option) => option.value === member.value)?.label ?? String(member.value)).join(", ")}`;
97
100
  }
98
101
  };
99
102
  }
@@ -140,7 +143,8 @@ function dimensionPredicate2(column, selection, allowedColumns) {
140
143
  ...literals.length ? [`${column} IN (${literals.join(", ")})`] : [],
141
144
  ...missing ? [`${column} IS NULL`] : []
142
145
  ];
143
- return `(${clauses.join(" OR ")})`;
146
+ const predicate = `(${clauses.join(" OR ")})`;
147
+ return selection.kind === "exclude" ? missing ? `NOT ${predicate}` : `(${column} IS NULL OR NOT ${predicate})` : predicate;
144
148
  }
145
149
  // src/core/annotations.ts
146
150
  function object(value) {
@@ -280,6 +284,18 @@ var annotationEditorStateRoute2 = /* @__PURE__ */ defineMessageRoute2({
280
284
  return null;
281
285
  }
282
286
  });
287
+ var annotationSendRoute2 = /* @__PURE__ */ defineMessageRoute2({
288
+ input(value) {
289
+ if (value !== null)
290
+ throw new Error("Invalid annotation send request.");
291
+ return null;
292
+ },
293
+ output(value) {
294
+ if (value !== null)
295
+ throw new Error("Invalid annotation response.");
296
+ return null;
297
+ }
298
+ });
283
299
  var annotationUpdateRoute2 = /* @__PURE__ */ defineMessageRoute2({
284
300
  input(value) {
285
301
  const input = object(value);
@@ -316,6 +332,123 @@ function isAnnotationPresentation(value) {
316
332
  return typeof value === "number" && Number.isFinite(value) && value >= 0 && value <= 1;
317
333
  }) && target.region.width > 0 && target.region.height > 0 && target.region.x + target.region.width <= 1.000001 && target.region.y + target.region.height <= 1.000001) && (target.comment === undefined || typeof target.comment === "string" && target.comment.length <= 2000)));
318
334
  }
335
+ // src/core/filters.ts
336
+ var all = { kind: "all" };
337
+ var numberOperatorLabels = {
338
+ eq: "Equals",
339
+ ne: "Does not equal",
340
+ gt: "Greater than",
341
+ gte: "At least",
342
+ lt: "Less than",
343
+ lte: "At most"
344
+ };
345
+ function numberFilter2({
346
+ key,
347
+ label,
348
+ min,
349
+ max,
350
+ defaultValue = all,
351
+ history = "push"
352
+ }) {
353
+ invariant(!!key.trim(), "Numeric filter requires a URL key.");
354
+ invariant((min === undefined || Number.isFinite(min)) && (max === undefined || Number.isFinite(max)) && (min === undefined || max === undefined || min <= max), "Invalid numeric filter bounds.");
355
+ function validNumber(value) {
356
+ return typeof value === "number" && Number.isFinite(value) && (min === undefined || value >= min) && (max === undefined || value <= max);
357
+ }
358
+ function valid(value) {
359
+ if (!value || typeof value !== "object")
360
+ return false;
361
+ if (value.kind === "all")
362
+ return true;
363
+ if (value.kind === "comparison")
364
+ return typeof value.operator === "string" && Object.hasOwn(numberOperatorLabels, value.operator) && validNumber(value.value);
365
+ return value.kind === "range" && (value.min !== undefined || value.max !== undefined) && (value.min === undefined || validNumber(value.min)) && (value.max === undefined || validNumber(value.max)) && (value.min === undefined || value.max === undefined || value.min <= value.max);
366
+ }
367
+ function encode(value) {
368
+ return value.kind === "all" ? null : value.kind === "range" ? JSON.stringify({ kind: "range", min: value.min, max: value.max }) : JSON.stringify({
369
+ kind: "comparison",
370
+ operator: value.operator,
371
+ value: value.value
372
+ });
373
+ }
374
+ invariant(valid(defaultValue), `Invalid default for ${label}.`);
375
+ return {
376
+ kind: "numberFilter",
377
+ label,
378
+ min,
379
+ max,
380
+ defaultValue,
381
+ clearValue: all,
382
+ urlKeys: [key],
383
+ history,
384
+ valid,
385
+ same: (left, right) => encode(left) === encode(right),
386
+ describe(value) {
387
+ return value.kind === "all" ? "Any" : value.kind === "comparison" ? `${numberOperatorLabels[value.operator]} ${value.value}` : value.min === undefined ? `At most ${value.max}` : value.max === undefined ? `At least ${value.min}` : `${value.min}–${value.max}`;
388
+ },
389
+ read(params) {
390
+ const raw = params.get(key);
391
+ if (raw === null)
392
+ return defaultValue;
393
+ if (raw.length > 512)
394
+ return defaultValue;
395
+ try {
396
+ const value = raw === "all" ? all : JSON.parse(raw);
397
+ return valid(value) ? value : defaultValue;
398
+ } catch {
399
+ return defaultValue;
400
+ }
401
+ },
402
+ write(value) {
403
+ return {
404
+ [key]: encode(value) === encode(defaultValue) ? null : value.kind === "all" ? "all" : encode(value)
405
+ };
406
+ }
407
+ };
408
+ }
409
+ function booleanFilter2({
410
+ key,
411
+ label,
412
+ defaultValue = all,
413
+ history = "push"
414
+ }) {
415
+ invariant(!!key.trim(), "Boolean filter requires a URL key.");
416
+ function valid(value) {
417
+ return !!value && typeof value === "object" && (value.kind === "all" || value.kind === "is" && typeof value.value === "boolean");
418
+ }
419
+ function encode(value) {
420
+ return value.kind === "all" ? "all" : String(value.value);
421
+ }
422
+ invariant(valid(defaultValue), `Invalid default for ${label}.`);
423
+ return {
424
+ kind: "booleanFilter",
425
+ label,
426
+ defaultValue,
427
+ clearValue: all,
428
+ urlKeys: [key],
429
+ history,
430
+ valid,
431
+ describe: (value) => value.kind === "all" ? "Any" : value.value ? "Yes" : "No",
432
+ same: (left, right) => encode(left) === encode(right),
433
+ read(params) {
434
+ const raw = params.get(key);
435
+ return raw === "all" ? all : raw === "true" || raw === "false" ? { kind: "is", value: raw === "true" } : defaultValue;
436
+ },
437
+ write(value) {
438
+ return {
439
+ [key]: encode(value) === encode(defaultValue) ? null : encode(value)
440
+ };
441
+ }
442
+ };
443
+ }
444
+ function parseNumberSelection2(value, filter) {
445
+ invariant(filter.valid(value), `Invalid ${filter.label} selection.`);
446
+ return value;
447
+ }
448
+ function parseBooleanSelection2(value, filter) {
449
+ invariant(filter.valid(value), `Invalid ${filter.label} selection.`);
450
+ return value;
451
+ }
319
452
 
320
453
  // src/core/contract.ts
321
454
  function parseEmptyInput2(value) {
@@ -464,42 +597,43 @@ class DataSourceError2 extends Error {
464
597
  }
465
598
  function defineOperation2(operation) {
466
599
  invariant(Array.isArray(operation.checks) && operation.checks.length > 0 && Number.isInteger(operation.policy.maxQueryRows) && operation.policy.maxQueryRows > 0 && Number.isInteger(operation.policy.maxDurationMs) && operation.policy.maxDurationMs > 0 && (operation.policy.maxResponseBytes === undefined || Number.isInteger(operation.policy.maxResponseBytes) && operation.policy.maxResponseBytes > 0), "Each data operation needs check inputs and positive row and duration limits.");
467
- if (operation.queryNames)
468
- defineQueryNames2(operation.queryNames);
600
+ const queries = snapshotQueries(operation.queries);
601
+ const queryNames = Object.fromEntries(Object.keys(queries).map((name) => [name, name]));
469
602
  for (const input of operation.checks)
470
603
  operation.input(input);
471
604
  return {
472
605
  ...operation,
606
+ queryNames,
473
607
  run(context, input) {
474
- function query(name, statement, options) {
475
- invariant(operation.queryNames && Object.values(operation.queryNames).includes(name), `Unknown query name: ${name}.`);
476
- return context.lakehouse.queryAll(statement, {
608
+ function query(name, values = {}, options) {
609
+ invariant(Object.hasOwn(queries, name), `Unknown query name: ${name}.`);
610
+ const definition = queries[name];
611
+ const params = resolveQueryParameters(definition.params, values, context.queryParams ?? {});
612
+ return context.lakehouse.queryAll(definition.statement, {
477
613
  name,
614
+ params,
478
615
  limit: options?.limit ?? operation.policy.maxQueryRows,
479
616
  signal: context.signal
480
617
  });
481
618
  }
482
- return operation.run({ ...context, query }, input);
619
+ return operation.run({ signal: context.signal, query }, input);
483
620
  }
484
621
  };
485
622
  }
486
- var connectionQueryNames2 = defineQueryNames2({
487
- connection: "connection-check"
488
- });
489
- function connectionCheck2() {
623
+ function connectionCheck2(queries) {
490
624
  return defineOperation2({
625
+ queries,
491
626
  input: parseEmptyInput2,
492
627
  output: parseTrue2,
493
628
  checks: [{}],
494
- queryNames: connectionQueryNames2,
495
- policy: { maxQueryRows: 1, maxDurationMs: 15000, exposeSql: true },
629
+ policy: { maxQueryRows: 1, maxDurationMs: 15000 },
496
630
  async run({ query }) {
497
- await query(connectionQueryNames2.connection, "SELECT 1 AS connection_check");
631
+ await query("connection");
498
632
  return true;
499
633
  }
500
634
  });
501
635
  }
502
636
 
503
- export { invariant, dimensionMemberKey, dimensionFilter2, parseDimensionSelection2, parseFacetOptions2, dimensionPredicate2, parseDataAppAnnotationDraft2, annotationDraftRoute2, annotationEditorStateRoute2, annotationUpdateRoute2, annotationModeRoute2, isAnnotationPresentation, parseEmptyInput2, parseTrue2, previousDateRange2, defineDateRangeContract2, parseDateRangeInput2, parseCount2, parseLabel2, rowsAsRecords2, defineQueryNames2, DataSourceError2, defineOperation2, connectionQueryNames2, connectionCheck2 };
637
+ export { dimensionMemberKey, dimensionFilter2, parseDimensionSelection2, parseFacetOptions2, dimensionPredicate2, parseDataAppAnnotationDraft2, annotationDraftRoute2, annotationEditorStateRoute2, annotationSendRoute2, annotationUpdateRoute2, annotationModeRoute2, isAnnotationPresentation, numberOperatorLabels, numberFilter2, booleanFilter2, parseNumberSelection2, parseBooleanSelection2, parseEmptyInput2, parseTrue2, previousDateRange2, defineDateRangeContract2, parseDateRangeInput2, parseCount2, parseLabel2, rowsAsRecords2, defineQueryNames2, DataSourceError2, defineOperation2, connectionCheck2 };
504
638
 
505
- //# debugId=876507C08B805AF964756E2164756E21
639
+ //# debugId=87015EDE1552300964756E2164756E21
@@ -0,0 +1,13 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/core/contract.ts", "../src/core/dimension.ts", "../src/core/annotations.ts", "../src/core/filters.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * Shared operation contracts and input/output validation for browser and server.\n * @module @altertable/data-app/contract\n * @see https://github.com/altertable-ai/data-app/blob/main/docs/contract.md\n */\nimport { parseDate, today } from '@internationalized/date';\nimport { formatDateRange } from '@/src/core/format';\nimport { invariant } from '@/src/core/invariant';\nimport {\n snapshotQueries,\n resolveQueryParameters,\n type QueryDefinitions,\n type QueryParameters,\n type QueryParameterValue,\n} from '@/src/core/queries';\nexport type {\n QueryDefinitions,\n QueryParameters,\n QueryParameterValue,\n} from '@/src/core/queries';\nimport type { DateRange as DateRangeInput } from '@/src/core/date-range';\nimport type {\n QueryResult,\n DataOperation,\n OperationContext,\n} from '@/src/core/operation-types';\nexport type {\n QueryResult,\n DisclosedQuery,\n Lakehouse,\n OperationContext,\n DataOperation,\n DataOperations,\n} from '@/src/core/operation-types';\n\nexport function parseEmptyInput(value: unknown): Record<string, never> {\n invariant(\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n Object.keys(value).length === 0,\n 'This operation takes no inputs.'\n );\n\n return {};\n}\n\nexport function parseTrue(value: unknown): true {\n invariant(value === true, 'Expected a successful check.');\n\n return true;\n}\n\nexport type { DateRange as DateRangeInput } from '@/src/core/date-range';\nexport type DateRangeRequest = {\n range: DateRangeInput;\n comparison: DateRangeInput | null;\n};\n\n/** The immediately preceding, equally long set of calendar days. */\nexport function previousDateRange({\n start,\n end,\n}: DateRangeInput): DateRangeInput {\n const first = parseDate(start);\n const last = parseDate(end);\n const days =\n (last.toDate('UTC').getTime() - first.toDate('UTC').getTime()) /\n 86_400_000 +\n 1;\n invariant(days >= 1, 'Date range must start before it ends.');\n const previousEnd = first.subtract({ days: 1 });\n\n return {\n start: previousEnd.subtract({ days: days - 1 }).toString(),\n end: previousEnd.toString(),\n };\n}\n\nexport type ReportingPeriod =\n | { kind: 'rolling'; amount: number; unit: 'hour' | 'day'; end: string }\n | { kind: 'calendar'; start: string; end: string; timeZone: string };\n\nexport type DateRangeContractOptions = {\n minDate?: string;\n maxDate?: string | (() => string);\n maxRangeDays: number;\n timeZone: string;\n completeDays?: boolean;\n};\n\n/** One source policy for the server parser, URL variable, and displayed reporting period. */\nexport function defineDateRangeContract(options: DateRangeContractOptions) {\n invariant(\n Number.isInteger(options.maxRangeDays) && options.maxRangeDays > 0,\n 'Date range needs a positive maxRangeDays.'\n );\n if (options.minDate) parseDate(options.minDate);\n if (typeof options.maxDate === 'string') parseDate(options.maxDate);\n today(options.timeZone);\n\n function bounds() {\n const latest = today(options.timeZone).subtract({\n days: options.completeDays === false ? 0 : 1,\n });\n const sourceMax =\n typeof options.maxDate === 'function'\n ? options.maxDate()\n : options.maxDate;\n const maxDate =\n sourceMax && parseDate(sourceMax).compare(latest) < 0\n ? parseDate(sourceMax).toString()\n : latest.toString();\n\n return {\n minDate: options.minDate,\n maxDate,\n maxRangeDays: options.maxRangeDays,\n timeZone: options.timeZone,\n };\n }\n\n function period({ start, end }: DateRangeInput): ReportingPeriod {\n return {\n kind: 'calendar',\n start,\n end,\n timeZone: options.timeZone,\n };\n }\n\n function describeInput(input: DateRangeInput) {\n return `${formatDateRange(input)} ${options.timeZone}`;\n }\n\n function comparison(input: DateRangeInput): DateRangeInput | null {\n const previous = previousDateRange(input);\n\n return options.minDate && previous.start < options.minDate\n ? null\n : previous;\n }\n\n function request(value: unknown, compare = false): DateRangeRequest {\n const range = parseDateRangeInput(value, bounds());\n const previous = compare ? comparison(range) : null;\n invariant(\n !compare || previous,\n 'Comparison is outside available source coverage.'\n );\n\n return { range, comparison: previous };\n }\n\n function parseRequest(value: unknown): DateRangeRequest {\n invariant(value && typeof value === 'object', 'Choose a date range.');\n const input = value as Record<string, unknown>;\n const parsed = request(input.range, input.comparison != null);\n if (input.comparison != null) {\n const supplied = parseDateRangeInput(input.comparison, bounds());\n invariant(\n supplied.start === parsed.comparison?.start &&\n supplied.end === parsed.comparison?.end,\n 'Comparison must be the preceding equal-length range.'\n );\n }\n\n return parsed;\n }\n\n return {\n request,\n parseRequest,\n bounds,\n parse(value: unknown) {\n return parseDateRangeInput(value, bounds());\n },\n period,\n comparison,\n describeInput,\n view: { period, describeInput },\n };\n}\n\nexport type DateRangeContract = ReturnType<typeof defineDateRangeContract>;\n\n/** Validate calendar dates and a bounded inclusive range on the server. */\nexport function parseDateRangeInput(\n value: unknown,\n {\n minDate,\n maxDate,\n maxRangeDays,\n }: { minDate?: string; maxDate?: string; maxRangeDays: number }\n): DateRangeInput {\n invariant(\n value && typeof value === 'object' && !Array.isArray(value),\n 'Choose a date range.'\n );\n const { start, end } = value as Record<string, unknown>;\n\n function day(input: unknown): number {\n invariant(\n typeof input === 'string' && /^\\d{4}-\\d{2}-\\d{2}$/.test(input),\n 'Dates must be YYYY-MM-DD.'\n );\n const timestamp = Date.parse(`${input}T00:00:00Z`);\n invariant(\n Number.isFinite(timestamp) &&\n new Date(timestamp).toISOString().slice(0, 10) === input,\n 'Choose valid calendar dates.'\n );\n\n return timestamp;\n }\n const first = day(start);\n const last = day(end);\n invariant(\n Number.isInteger(maxRangeDays) && maxRangeDays > 0,\n 'Maximum range days must be positive.'\n );\n invariant(\n first <= last &&\n (last - first) / 86_400_000 < maxRangeDays &&\n (minDate === undefined || first >= day(minDate)) &&\n (maxDate === undefined || last <= day(maxDate)),\n `Choose up to ${maxRangeDays} days within the available range.`\n );\n\n return { start: start as string, end: end as string };\n}\n\n/** Accepts numeric strings from DuckDB; rejects negative, fractional, and unsafe integers. */\nexport function parseCount(value: unknown): number {\n const number =\n typeof value === 'number' || typeof value === 'string'\n ? Number(value)\n : NaN;\n invariant(\n Number.isSafeInteger(number) &&\n number >= 0 &&\n (typeof value !== 'string' || !!value.trim()),\n 'Invalid count in query result.'\n );\n\n return number;\n}\n\nexport function parseLabel(value: unknown, maxLength = 100): string {\n invariant(\n typeof value === 'string' && !!value && value.length <= maxLength,\n 'Invalid label in query result.'\n );\n\n return value;\n}\n\n/** Rejects missing or duplicate columns and rows whose width differs from the column list. */\nexport function rowsAsRecords(\n result: QueryResult,\n requiredColumns: readonly string[]\n): Record<string, unknown>[] {\n const names = result.columns.map(column => column.name);\n invariant(\n new Set(names).size === names.length &&\n requiredColumns.every(name => names.includes(name)),\n 'Query result columns do not match the expected shape.'\n );\n\n return result.rows.map(row => {\n invariant(\n row.length === names.length,\n 'Query result row has the wrong width.'\n );\n\n return Object.fromEntries(names.map((name, index) => [name, row[index]]));\n });\n}\n\nexport function defineQueryNames<const Names extends Record<string, string>>(\n names: Names\n): Names {\n const values = Object.values(names);\n invariant(\n values.every(name => !!name.trim()) &&\n new Set(values).size === values.length,\n 'Query names must be nonempty and unique.'\n );\n\n return names;\n}\n\nconst sourceErrorBrand = Symbol.for('@altertable/data-app/DataSourceError');\n\nexport class DataSourceError extends Error {\n readonly [sourceErrorBrand] = true;\n queryName?: string;\n\n static [Symbol.hasInstance](value: unknown): boolean {\n return (\n value instanceof Error &&\n (value as { [sourceErrorBrand]?: unknown })[sourceErrorBrand] === true\n );\n }\n\n constructor(\n public readonly reason:\n | 'unauthorized'\n | 'forbidden'\n | 'rate_limited'\n | 'query_rejected'\n | 'unavailable',\n public readonly status?: number\n ) {\n super(`Data source ${reason}${status ? ` (${status})` : ''}.`);\n this.name = 'DataSourceError';\n }\n}\n\ntype RegisteredQueryParameters<\n Queries extends QueryDefinitions,\n Name extends keyof Queries,\n> = keyof Queries[Name]['params'] extends never\n ? Record<string, never>\n : Partial<Record<keyof Queries[Name]['params'], QueryParameterValue>>;\n\nexport type RegisteredQuery<Queries extends QueryDefinitions> = <\n Name extends keyof Queries & string,\n const Params extends object = {},\n>(\n name: Name,\n params?: Params &\n NoInfer<RegisteredQueryParameters<Queries, Name>> &\n NoInfer<\n Record<Exclude<keyof Params, keyof Queries[Name]['params']>, never>\n > &\n NoInfer<Params extends (...args: never[]) => unknown ? never : object>,\n options?: { limit?: number }\n) => Promise<QueryResult>;\n\nexport function defineOperation<\n Input,\n Output,\n const Queries extends QueryDefinitions,\n>(\n operation: Omit<DataOperation<Input, Output>, 'run' | 'queryNames'> & {\n queries: Queries;\n run: (\n context: Pick<OperationContext, 'signal'> & {\n query: RegisteredQuery<NoInfer<Queries>>;\n },\n input: Input\n ) => Promise<Output>;\n }\n): Omit<DataOperation<Input, Output>, 'queryNames'> & {\n queryNames: { readonly [Name in keyof Queries & string]: Name };\n} {\n invariant(\n Array.isArray(operation.checks) &&\n operation.checks.length > 0 &&\n Number.isInteger(operation.policy.maxQueryRows) &&\n operation.policy.maxQueryRows > 0 &&\n Number.isInteger(operation.policy.maxDurationMs) &&\n operation.policy.maxDurationMs > 0 &&\n (operation.policy.maxResponseBytes === undefined ||\n (Number.isInteger(operation.policy.maxResponseBytes) &&\n operation.policy.maxResponseBytes > 0)),\n 'Each data operation needs check inputs and positive row and duration limits.'\n );\n const queries = snapshotQueries(operation.queries);\n const queryNames = Object.fromEntries(\n Object.keys(queries).map(name => [name, name])\n ) as { readonly [Name in keyof Queries & string]: Name };\n for (const input of operation.checks) operation.input(input);\n\n return {\n ...operation,\n queryNames,\n run(context, input) {\n function query(\n name: keyof Queries & string,\n values: Partial<QueryParameters> = {},\n options?: { limit?: number }\n ) {\n invariant(Object.hasOwn(queries, name), `Unknown query name: ${name}.`);\n const definition = queries[name]!;\n const params = resolveQueryParameters(\n definition.params,\n values,\n context.queryParams ?? {}\n );\n return context.lakehouse.queryAll(definition.statement, {\n name,\n params,\n limit: options?.limit ?? operation.policy.maxQueryRows,\n signal: context.signal,\n });\n }\n return operation.run({ signal: context.signal, query }, input);\n },\n };\n}\n\n/** A connectivity probe uses the app's registered connection query. */\nexport function connectionCheck<\n const Queries extends QueryDefinitions & {\n connection: QueryDefinitions[string];\n },\n>(queries: Queries) {\n return defineOperation({\n queries,\n input: parseEmptyInput,\n output: parseTrue,\n checks: [{}],\n policy: { maxQueryRows: 1, maxDurationMs: 15_000 },\n async run({ query }): Promise<true> {\n await query('connection');\n return true;\n },\n });\n}\n\nexport {\n dimensionFilter,\n parseDimensionSelection,\n parseFacetOptions,\n dimensionPredicate,\n} from '@/src/core/dimension';\nexport type {\n DimensionSelection,\n DimensionMember,\n DimensionOption,\n DimensionVariable,\n DimensionFilterOptions,\n} from '@/src/core/dimension';\n\nexport {\n createMessageRouter,\n defineMessageRoute,\n defineDataQueryRoute,\n MessageRoutingError,\n dataAppRoutes,\n navigationUpdateRoute,\n sqlQueryRoute,\n} from '@/src/core/messages';\nexport type {\n MessageContext,\n RoutedMessage,\n MessageDispatcher,\n MessageTransport,\n MessageRoute,\n MessageRoutes,\n MessageInput,\n MessageHandlers,\n MessageOutput,\n OperationContracts,\n DataQueryInput,\n DataQueryBody,\n DataQueryRoute,\n NavigationUpdate,\n SqlQueryInput,\n} from '@/src/core/messages';\nexport type { TransportResponse } from '@/src/core/bridge';\n\nexport {\n annotationDraftRoute,\n annotationModeRoute,\n annotationEditorStateRoute,\n annotationSendRoute,\n annotationUpdateRoute,\n parseDataAppAnnotationDraft,\n} from '@/src/core/annotations';\nexport type {\n DataAppAnnotationDraft,\n DataAppAnnotationPresentation,\n} from '@/src/core/annotations';\n\nexport {\n numberFilter,\n booleanFilter,\n parseNumberSelection,\n parseBooleanSelection,\n} from '@/src/core/filters';\nexport type {\n NumberSelection,\n NumberOperator,\n NumberFilter,\n BooleanSelection,\n BooleanFilter,\n} from '@/src/core/filters';\n",
6
+ "import type { AppVariable, HistoryMode } from '@/src/core/variables';\nimport { invariant } from '@/src/core/invariant';\n\nexport type DimensionValue = string | number;\nexport type DimensionMember<T extends DimensionValue = DimensionValue> =\n | { kind: 'value'; value: T }\n | { kind: 'missing' };\nexport type DimensionSelection<T extends DimensionValue = DimensionValue> =\n | { kind: 'all' }\n | { kind: 'include' | 'exclude'; members: readonly DimensionMember<T>[] };\nexport type DimensionOption<T extends DimensionValue = DimensionValue> = {\n value: T;\n label: string;\n count?: number;\n};\nexport type DimensionVariable<T extends DimensionValue = DimensionValue> =\n AppVariable<DimensionSelection<T>, 'dimension'> & {\n label: string;\n selectionMode: 'single' | 'multiple';\n valueType: 'string' | 'number';\n allowMissing: boolean;\n allowExclusion: boolean;\n maxSelected: number;\n options: readonly DimensionOption<T>[];\n facet?: {\n operation: string;\n input: (values: Record<string, unknown>) => unknown;\n };\n describe: (selection: DimensionSelection<T>) => string;\n };\n\nconst allSelection: DimensionSelection<never> = { kind: 'all' };\n\nexport function dimensionMemberKey(member: DimensionMember) {\n return member.kind === 'missing'\n ? 'missing'\n : `value:${typeof member.value}:${member.value}`;\n}\n\nexport type DimensionFilterOptions<T extends DimensionValue> = {\n key: string;\n label: string;\n valueType: T extends number ? 'number' : 'string';\n selectionMode: 'single' | 'multiple';\n allowMissing?: boolean;\n allowExclusion?: boolean;\n maxSelected?: number;\n history?: HistoryMode;\n} & (\n | { options: readonly DimensionOption<T>[]; facet?: never }\n | {\n /** A bounded operation supplies options and counts; input chooses other filters affecting counts. */\n facet: {\n operation: string;\n input: (values: Record<string, unknown>) => unknown;\n };\n options?: never;\n }\n);\n\n/** A bounded categorical filter. URL tags distinguish missing from literal \"null\". */\nexport function dimensionFilter<const T extends DimensionValue>(\n config: DimensionFilterOptions<T>\n): DimensionVariable<T> {\n const { key, label, selectionMode, valueType } = config;\n const options = config.options ?? [];\n const optionKeys = options.map(option =>\n dimensionMemberKey({ kind: 'value', value: option.value })\n );\n invariant(\n !!key &&\n options.length <= 200 &&\n new Set(optionKeys).size === options.length,\n 'Dimension options need a key, at most 200 distinct values.'\n );\n invariant(\n options.every(\n option =>\n typeof option.value === valueType &&\n !!option.label.trim() &&\n (option.count === undefined ||\n (Number.isSafeInteger(option.count) && option.count >= 0))\n ),\n 'Dimension options need typed values, labels, and nonnegative counts.'\n );\n const allowed = new Set(optionKeys);\n const maxSelected =\n config.maxSelected ?? (selectionMode === 'single' ? 1 : 20);\n invariant(\n Number.isInteger(maxSelected) &&\n maxSelected >= 1 &&\n maxSelected <= 50 &&\n (selectionMode !== 'single' || maxSelected === 1),\n 'Dimension selection limit is invalid.'\n );\n const allowMissing = config.allowMissing ?? false;\n const defaultValue = allSelection;\n\n function validMember(member: DimensionMember<T>): boolean {\n if (member.kind === 'missing') return allowMissing;\n if (member.kind !== 'value' || typeof member.value !== valueType)\n return false;\n if (!config.facet) return allowed.has(dimensionMemberKey(member));\n\n return typeof member.value === 'number'\n ? Number.isFinite(member.value)\n : member.value.length <= 100;\n }\n\n function valid(value: DimensionSelection<T>): boolean {\n if (!value || typeof value !== 'object') return false;\n if (value.kind === 'all') return true;\n if (\n (value.kind !== 'include' &&\n !(config.allowExclusion && value.kind === 'exclude')) ||\n !Array.isArray(value.members) ||\n !value.members.length ||\n value.members.length > maxSelected\n )\n return false;\n const ids = value.members.map(dimensionMemberKey);\n\n return new Set(ids).size === ids.length && value.members.every(validMember);\n }\n\n function encode(value: DimensionSelection<T>) {\n return value.kind === 'all'\n ? null\n : JSON.stringify({\n kind: value.kind,\n members: value.members.map(member =>\n member.kind === 'missing' ? ['m'] : ['v', member.value]\n ),\n });\n }\n\n function parse(raw: string | null): DimensionSelection<T> {\n if (raw === null) return defaultValue;\n if (raw.length > 4096) return defaultValue;\n try {\n const parsed = JSON.parse(raw);\n const tokens = Array.isArray(parsed)\n ? { kind: 'include', members: parsed }\n : parsed;\n if (!tokens || !Array.isArray(tokens.members)) return defaultValue;\n const value = {\n kind: tokens.kind,\n members: tokens.members.map((token: unknown) =>\n Array.isArray(token) && token.length === 1 && token[0] === 'm'\n ? { kind: 'missing' as const }\n : Array.isArray(token) && token.length === 2 && token[0] === 'v'\n ? { kind: 'value' as const, value: token[1] as T }\n : { kind: 'invalid' as const }\n ),\n };\n\n return valid(value as DimensionSelection<T>)\n ? (value as DimensionSelection<T>)\n : defaultValue;\n } catch {\n return defaultValue;\n }\n }\n\n return {\n kind: 'dimension',\n label,\n valueType,\n selectionMode,\n options,\n facet: config.facet,\n allowMissing,\n allowExclusion: config.allowExclusion ?? false,\n maxSelected,\n urlKeys: [key],\n defaultValue,\n clearValue: allSelection,\n history: config.history ?? 'push',\n valid,\n same(left, right) {\n return encode(left) === encode(right);\n },\n read(params) {\n return parse(params.get(key));\n },\n write(value) {\n return { [key]: encode(value) };\n },\n describe(value) {\n return value.kind === 'all'\n ? `All ${label.toLocaleLowerCase()}`\n : `${value.kind === 'exclude' ? 'Exclude: ' : ''}${value.members\n .map(member =>\n member.kind === 'missing'\n ? 'Missing'\n : (options.find(option => option.value === member.value)\n ?.label ?? String(member.value))\n )\n .join(', ')}`;\n },\n };\n}\n\n/** Server-side parser; call from the operation input parser before building SQL. */\nexport function parseDimensionSelection<T extends DimensionValue>(\n value: unknown,\n filter: DimensionVariable<T>\n): DimensionSelection<T> {\n invariant(\n filter.valid(value as DimensionSelection<T>),\n `Invalid ${filter.label} selection.`\n );\n\n return value as DimensionSelection<T>;\n}\n\n/** Validate bounded facet results before showing them in a picker. */\nexport function parseFacetOptions<T extends DimensionValue>(\n value: unknown,\n filter: DimensionVariable<T>\n): DimensionOption<T>[] {\n invariant(\n Array.isArray(value) && value.length <= 200,\n 'Facet options exceed their bound.'\n );\n const options: DimensionOption<T>[] = [];\n const seen = new Set<string>();\n for (const item of value) {\n invariant(item && typeof item === 'object', 'Invalid facet option.');\n const option = item as DimensionOption<T>;\n invariant(\n typeof option.value === filter.valueType &&\n filter.valid({\n kind: 'include',\n members: [{ kind: 'value', value: option.value }],\n }) &&\n typeof option.label === 'string' &&\n !!option.label.trim() &&\n option.label.length <= 100 &&\n (option.count === undefined ||\n (Number.isSafeInteger(option.count) && option.count >= 0)),\n 'Invalid facet option.'\n );\n const id = dimensionMemberKey({ kind: 'value', value: option.value });\n invariant(!seen.has(id), 'Duplicate facet option.');\n seen.add(id);\n options.push(option);\n }\n\n return options;\n}\n\n/** Central SQL literal encoding for transports without bound parameters. Column is an allowlisted identifier. */\nexport function dimensionPredicate<\n T extends DimensionValue,\n const Columns extends readonly string[],\n>(\n column: Columns[number],\n selection: DimensionSelection<T>,\n allowedColumns: Columns\n): string {\n invariant(\n allowedColumns.includes(column) &&\n /^[A-Za-z_][A-Za-z_0-9]*(?:\\.[A-Za-z_][A-Za-z_0-9]*)*$/.test(column),\n 'Invalid dimension column.'\n );\n if (selection.kind === 'all') return '';\n invariant(\n selection.members.length > 0,\n 'Empty dimension inclusion is invalid.'\n );\n const values = selection.members.filter(\n (member): member is Extract<DimensionMember<T>, { kind: 'value' }> =>\n member.kind === 'value'\n );\n const missing = selection.members.some(member => member.kind === 'missing');\n const literals = values.map(({ value }) => {\n if (typeof value === 'number') {\n invariant(Number.isFinite(value), 'Invalid numeric dimension value.');\n\n return String(value);\n }\n const text = value as string;\n for (let index = 0; index < text.length; index++)\n invariant(\n text.charCodeAt(index) >= 32 && text.charCodeAt(index) !== 127,\n 'Invalid control character in dimension value.'\n );\n\n return `'${text.replaceAll(\"'\", \"''\")}'`;\n });\n const clauses = [\n ...(literals.length ? [`${column} IN (${literals.join(', ')})`] : []),\n ...(missing ? [`${column} IS NULL`] : []),\n ];\n\n const predicate = `(${clauses.join(' OR ')})`;\n // Excluding values retains missing records unless missing itself is excluded.\n return selection.kind === 'exclude'\n ? missing\n ? `NOT ${predicate}`\n : `(${column} IS NULL OR NOT ${predicate})`\n : predicate;\n}\n",
7
+ "import { defineMessageRoute } from '@/src/core/messages';\n\nexport type DataAppAnnotationDraft = {\n id: string;\n target: {\n id: string;\n label: string;\n kind: 'widget' | 'element' | 'app';\n text: string;\n queryNames: string[];\n glossaryIds: string[];\n };\n context: {\n search: string;\n hash: string;\n displayedInput?: unknown;\n /** Normalized position within the selected target, stable across scrolling/resizing. */\n anchor?: { x: number; y: number };\n cursor?: { x: number; y: number };\n /** Normalized custom selection rectangle within the iframe document. */\n region?: { x: number; y: number; width: number; height: number };\n screenshot?: {\n mimeType: 'image/png';\n dataUrl: string;\n width: number;\n height: number;\n };\n view?: string;\n viewport: { width: number; height: number };\n rect: { x: number; y: number; width: number; height: number };\n };\n comment: string;\n};\n\nexport type DataAppAnnotationPresentation = {\n enabled: boolean;\n /** When provided, the host owns the mode and renders the annotation trigger. */\n active?: boolean;\n pinsVisible?: boolean;\n showHint?: boolean;\n readOnly?: boolean;\n targets?: {\n id: string;\n targetId: string;\n number: number;\n comment?: string;\n anchor?: { x: number; y: number };\n region?: { x: number; y: number; width: number; height: number };\n }[];\n selectedAnnotationId?: string;\n selectedTargetId?: string;\n selectionId?: string;\n};\n\nfunction object(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value))\n throw new Error('Invalid annotation.');\n return value as Record<string, unknown>;\n}\nfunction text(value: unknown, limit: number, required = false): string {\n if (\n typeof value !== 'string' ||\n value.length > limit ||\n (required && !value.trim())\n )\n throw new Error('Invalid annotation text.');\n return value;\n}\nfunction names(value: unknown): string[] {\n if (!Array.isArray(value) || value.length > 20)\n throw new Error('Invalid annotation references.');\n return value.map(name => text(name, 128, true));\n}\nfunction number(value: unknown, positive = false): number {\n if (\n typeof value !== 'number' ||\n !Number.isFinite(value) ||\n Math.abs(value) > 1_000_000 ||\n (positive && value < 0)\n )\n throw new Error('Invalid annotation geometry.');\n return value;\n}\n\n/** Reconstruct at the boundary; discard extra fields and bound the entire JSON payload. */\nexport function parseDataAppAnnotationDraft(\n value: unknown\n): DataAppAnnotationDraft {\n const input = object(value);\n const target = object(input.target);\n const context = object(input.context);\n const viewport = object(context.viewport);\n const rect = object(context.rect);\n if (\n target.kind !== 'widget' &&\n target.kind !== 'element' &&\n target.kind !== 'app'\n )\n throw new Error('Invalid annotation target.');\n let screenshot: DataAppAnnotationDraft['context']['screenshot'];\n if (context.screenshot !== undefined) {\n const image = object(context.screenshot);\n const dataUrl = text(image.dataUrl, 350_000, true);\n if (\n image.mimeType !== 'image/png' ||\n !/^data:image\\/png;base64,iVBORw0KGgo[A-Za-z0-9+/]*={0,2}$/.test(dataUrl)\n )\n throw new Error('Invalid annotation screenshot.');\n const width = number(image.width, true);\n const height = number(image.height, true);\n if (\n !Number.isInteger(width) ||\n !Number.isInteger(height) ||\n width < 1 ||\n height < 1 ||\n width > 1024 ||\n height > 1024\n )\n throw new Error('Invalid screenshot dimensions.');\n const encoded = dataUrl.slice('data:image/png;base64,'.length);\n if (\n encoded.length % 4 !== 0 ||\n (encoded.length / 4) * 3 -\n (encoded.endsWith('==') ? 2 : encoded.endsWith('=') ? 1 : 0) >\n 262_144\n )\n throw new Error('Screenshot is too large.');\n const header = atob(encoded.slice(0, 44));\n if (header.length < 24 || header.slice(12, 16) !== 'IHDR')\n throw new Error('Invalid PNG header.');\n const bytes = Uint8Array.from(header, character => character.charCodeAt(0));\n const dimensions = new DataView(bytes.buffer);\n if (\n dimensions.getUint32(16) !== width ||\n dimensions.getUint32(20) !== height\n )\n throw new Error('Screenshot dimensions do not match the image.');\n screenshot = { mimeType: 'image/png', dataUrl, width, height };\n }\n let anchor: { x: number; y: number } | undefined;\n if (context.anchor !== undefined) {\n const point = object(context.anchor);\n const x = number(point.x, true);\n const y = number(point.y, true);\n if (x > 1 || y > 1) throw new Error('Invalid annotation anchor.');\n anchor = { x, y };\n }\n let cursor: { x: number; y: number } | undefined;\n if (context.cursor !== undefined) {\n const point = object(context.cursor);\n cursor = { x: number(point.x), y: number(point.y) };\n }\n let region: DataAppAnnotationDraft['context']['region'];\n if (context.region !== undefined) {\n const area = object(context.region);\n region = {\n x: number(area.x, true),\n y: number(area.y, true),\n width: number(area.width, true),\n height: number(area.height, true),\n };\n if (\n target.kind !== 'app' ||\n region.width <= 0 ||\n region.height <= 0 ||\n region.x + region.width > 1.000001 ||\n region.y + region.height > 1.000001\n )\n throw new Error('Invalid annotation selection.');\n }\n const draft: DataAppAnnotationDraft = {\n id: text(input.id, 128, true),\n target: {\n id: text(target.id, 128, true),\n label: text(target.label, 256, true),\n kind: target.kind,\n text: text(target.text, 1024),\n queryNames: names(target.queryNames),\n glossaryIds: names(target.glossaryIds),\n },\n context: {\n ...(anchor ? { anchor } : {}),\n ...(region ? { region } : {}),\n ...(cursor ? { cursor } : {}),\n ...(screenshot ? { screenshot } : {}),\n search: text(context.search, 2048),\n hash: text(context.hash, 1024),\n viewport: {\n width: number(viewport.width, true),\n height: number(viewport.height, true),\n },\n rect: {\n x: number(rect.x),\n y: number(rect.y),\n width: number(rect.width, true),\n height: number(rect.height, true),\n },\n ...(context.view === undefined ? {} : { view: text(context.view, 128) }),\n ...(context.displayedInput === undefined\n ? {}\n : { displayedInput: context.displayedInput }),\n },\n comment: text(input.comment, 2000, true).trim(),\n };\n const json = JSON.stringify({\n ...draft,\n context: { ...draft.context, screenshot: undefined },\n });\n if (new TextEncoder().encode(json).byteLength > 12_000)\n throw new Error('Annotation is too large.');\n return JSON.parse(JSON.stringify(draft)) as DataAppAnnotationDraft;\n}\n\nexport const annotationDraftRoute = /* @__PURE__ */ defineMessageRoute({\n input: parseDataAppAnnotationDraft,\n output(value: unknown): null {\n if (value !== null) throw new Error('Invalid annotation response.');\n return null;\n },\n});\n\nexport const annotationEditorStateRoute = /* @__PURE__ */ defineMessageRoute({\n input(value: unknown): { hasUnsavedChanges: boolean } {\n const input = object(value);\n if (typeof input.hasUnsavedChanges !== 'boolean')\n throw new Error('Invalid annotation editor state.');\n return { hasUnsavedChanges: input.hasUnsavedChanges };\n },\n output(value: unknown): null {\n if (value !== null) throw new Error('Invalid annotation response.');\n return null;\n },\n});\n\n/** Request host-owned batch submission without transferring ownership of drafts. */\nexport const annotationSendRoute = /* @__PURE__ */ defineMessageRoute({\n input(value: unknown): null {\n if (value !== null) throw new Error('Invalid annotation send request.');\n return null;\n },\n output(value: unknown): null {\n if (value !== null) throw new Error('Invalid annotation response.');\n return null;\n },\n});\n\nexport const annotationUpdateRoute = /* @__PURE__ */ defineMessageRoute({\n input(value: unknown): { id: string; comment: string } {\n const input = object(value);\n return {\n id: text(input.id, 128, true),\n comment: text(input.comment, 2000, true).trim(),\n };\n },\n output(value: unknown): null {\n if (value !== null) throw new Error('Invalid annotation response.');\n return null;\n },\n});\n\n/** A controlled shell acknowledges local exits (for example Escape). */\nexport const annotationModeRoute = /* @__PURE__ */ defineMessageRoute({\n input(value: unknown): { active: boolean } {\n const input = object(value);\n if (typeof input.active !== 'boolean')\n throw new Error('Invalid annotation mode.');\n return { active: input.active };\n },\n output(value: unknown): null {\n if (value !== null) throw new Error('Invalid annotation response.');\n return null;\n },\n});\n\nexport function isAnnotationPresentation(\n value: unknown\n): value is DataAppAnnotationPresentation {\n if (!value || typeof value !== 'object') return false;\n const input = value as DataAppAnnotationPresentation;\n return (\n typeof input.enabled === 'boolean' &&\n (input.active === undefined || typeof input.active === 'boolean') &&\n (input.pinsVisible === undefined ||\n typeof input.pinsVisible === 'boolean') &&\n (input.showHint === undefined || typeof input.showHint === 'boolean') &&\n (input.readOnly === undefined || typeof input.readOnly === 'boolean') &&\n (input.selectedAnnotationId === undefined ||\n (typeof input.selectedAnnotationId === 'string' &&\n input.selectedAnnotationId.length <= 128)) &&\n (input.selectionId === undefined ||\n (typeof input.selectionId === 'string' &&\n input.selectionId.length <= 128)) &&\n (input.selectedTargetId === undefined ||\n (typeof input.selectedTargetId === 'string' &&\n input.selectedTargetId.length <= 128)) &&\n (input.targets === undefined ||\n (Array.isArray(input.targets) &&\n input.targets.length <= 50 &&\n input.targets.every(\n target =>\n target &&\n typeof target.id === 'string' &&\n target.id.length <= 128 &&\n typeof target.targetId === 'string' &&\n target.targetId.length <= 128 &&\n Number.isSafeInteger(target.number) &&\n target.number > 0 &&\n (target.anchor === undefined ||\n (typeof target.anchor.x === 'number' &&\n Number.isFinite(target.anchor.x) &&\n target.anchor.x >= 0 &&\n target.anchor.x <= 1 &&\n typeof target.anchor.y === 'number' &&\n Number.isFinite(target.anchor.y) &&\n target.anchor.y >= 0 &&\n target.anchor.y <= 1)) &&\n (target.region === undefined ||\n (typeof target.region === 'object' &&\n target.region !== null &&\n ['x', 'y', 'width', 'height'].every(key => {\n const value = (target.region as Record<string, unknown>)[key];\n return (\n typeof value === 'number' &&\n Number.isFinite(value) &&\n value >= 0 &&\n value <= 1\n );\n }) &&\n target.region.width > 0 &&\n target.region.height > 0 &&\n target.region.x + target.region.width <= 1.000001 &&\n target.region.y + target.region.height <= 1.000001)) &&\n (target.comment === undefined ||\n (typeof target.comment === 'string' &&\n target.comment.length <= 2000))\n )))\n );\n}\n",
8
+ "import { invariant } from '@/src/core/invariant';\nimport type { AppVariable, HistoryMode } from '@/src/core/variables';\n\nexport type NumberOperator = 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte';\nexport type NumberSelection =\n | { kind: 'all' }\n | { kind: 'comparison'; operator: NumberOperator; value: number }\n | { kind: 'range'; min?: number; max?: number };\nexport type BooleanSelection = { kind: 'all' } | { kind: 'is'; value: boolean };\nexport type NumberFilter = AppVariable<NumberSelection, 'numberFilter'> & {\n label: string;\n min?: number;\n max?: number;\n};\nexport type BooleanFilter = AppVariable<BooleanSelection, 'booleanFilter'> & {\n label: string;\n};\n\ntype FilterOptions<Value> = {\n key: string;\n label: string;\n defaultValue?: Value;\n history?: HistoryMode;\n};\nconst all = { kind: 'all' } as const;\nexport const numberOperatorLabels: Record<NumberOperator, string> = {\n eq: 'Equals',\n ne: 'Does not equal',\n gt: 'Greater than',\n gte: 'At least',\n lt: 'Less than',\n lte: 'At most',\n};\n\n/** Exact numeric predicates; range bounds are inclusive and may be open-ended. */\nexport function numberFilter({\n key,\n label,\n min,\n max,\n defaultValue = all,\n history = 'push',\n}: FilterOptions<NumberSelection> & {\n min?: number;\n max?: number;\n}): NumberFilter {\n invariant(!!key.trim(), 'Numeric filter requires a URL key.');\n invariant(\n (min === undefined || Number.isFinite(min)) &&\n (max === undefined || Number.isFinite(max)) &&\n (min === undefined || max === undefined || min <= max),\n 'Invalid numeric filter bounds.'\n );\n function validNumber(value: unknown): value is number {\n return (\n typeof value === 'number' &&\n Number.isFinite(value) &&\n (min === undefined || value >= min) &&\n (max === undefined || value <= max)\n );\n }\n function valid(value: NumberSelection) {\n if (!value || typeof value !== 'object') return false;\n if (value.kind === 'all') return true;\n if (value.kind === 'comparison')\n return (\n typeof value.operator === 'string' &&\n Object.hasOwn(numberOperatorLabels, value.operator) &&\n validNumber(value.value)\n );\n return (\n value.kind === 'range' &&\n (value.min !== undefined || value.max !== undefined) &&\n (value.min === undefined || validNumber(value.min)) &&\n (value.max === undefined || validNumber(value.max)) &&\n (value.min === undefined ||\n value.max === undefined ||\n value.min <= value.max)\n );\n }\n function encode(value: NumberSelection) {\n return value.kind === 'all'\n ? null\n : value.kind === 'range'\n ? JSON.stringify({ kind: 'range', min: value.min, max: value.max })\n : JSON.stringify({\n kind: 'comparison',\n operator: value.operator,\n value: value.value,\n });\n }\n invariant(valid(defaultValue), `Invalid default for ${label}.`);\n return {\n kind: 'numberFilter',\n label,\n min,\n max,\n defaultValue,\n clearValue: all,\n urlKeys: [key],\n history,\n valid,\n same: (left, right) => encode(left) === encode(right),\n describe(value) {\n return value.kind === 'all'\n ? 'Any'\n : value.kind === 'comparison'\n ? `${numberOperatorLabels[value.operator]} ${value.value}`\n : value.min === undefined\n ? `At most ${value.max}`\n : value.max === undefined\n ? `At least ${value.min}`\n : `${value.min}–${value.max}`;\n },\n read(params) {\n const raw = params.get(key);\n if (raw === null) return defaultValue;\n if (raw.length > 512) return defaultValue;\n try {\n const value = raw === 'all' ? all : JSON.parse(raw);\n return valid(value) ? value : defaultValue;\n } catch {\n return defaultValue;\n }\n },\n write(value) {\n return {\n [key]:\n encode(value) === encode(defaultValue)\n ? null\n : value.kind === 'all'\n ? 'all'\n : encode(value),\n };\n },\n };\n}\n\n/** Boolean predicate with a distinct unrestricted state. */\nexport function booleanFilter({\n key,\n label,\n defaultValue = all,\n history = 'push',\n}: FilterOptions<BooleanSelection>): BooleanFilter {\n invariant(!!key.trim(), 'Boolean filter requires a URL key.');\n function valid(value: BooleanSelection) {\n return (\n !!value &&\n typeof value === 'object' &&\n (value.kind === 'all' ||\n (value.kind === 'is' && typeof value.value === 'boolean'))\n );\n }\n function encode(value: BooleanSelection) {\n return value.kind === 'all' ? 'all' : String(value.value);\n }\n invariant(valid(defaultValue), `Invalid default for ${label}.`);\n return {\n kind: 'booleanFilter',\n label,\n defaultValue,\n clearValue: all,\n urlKeys: [key],\n history,\n valid,\n describe: value =>\n value.kind === 'all' ? 'Any' : value.value ? 'Yes' : 'No',\n same: (left, right) => encode(left) === encode(right),\n read(params) {\n const raw = params.get(key);\n return raw === 'all'\n ? all\n : raw === 'true' || raw === 'false'\n ? { kind: 'is', value: raw === 'true' }\n : defaultValue;\n },\n write(value) {\n return {\n [key]: encode(value) === encode(defaultValue) ? null : encode(value),\n };\n },\n };\n}\n\nexport function parseNumberSelection(\n value: unknown,\n filter: NumberFilter\n): NumberSelection {\n invariant(\n filter.valid(value as NumberSelection),\n `Invalid ${filter.label} selection.`\n );\n return value as NumberSelection;\n}\nexport function parseBooleanSelection(\n value: unknown,\n filter: BooleanFilter\n): BooleanSelection {\n invariant(\n filter.valid(value as BooleanSelection),\n `Invalid ${filter.label} selection.`\n );\n return value as BooleanSelection;\n}\n"
9
+ ],
10
+ "mappings": "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",
11
+ "debugId": "87015EDE1552300964756E2164756E21",
12
+ "names": []
13
+ }