@altertable/data-app 0.62.0 → 0.64.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 (150) hide show
  1. package/AGENTS.md +4 -34
  2. package/CONTRIBUTING.md +79 -87
  3. package/README.md +14 -38
  4. package/dist/chunks/{contract-ryyf6dme.js → contract-cxr9t12b.js} +2 -5
  5. package/dist/chunks/contract-cxr9t12b.js.map +10 -0
  6. package/dist/chunks/contract-mev09s5v.js.map +2 -2
  7. package/dist/chunks/{contract-xjv197ck.js → contract-mwe7gnmh.js} +8 -8
  8. package/dist/chunks/{contract-xjv197ck.js.map → contract-mwe7gnmh.js.map} +3 -3
  9. package/dist/chunks/{contract-3bnrf5pf.js → contract-tf8c3qpv.js} +11 -3
  10. package/dist/chunks/contract-tf8c3qpv.js.map +11 -0
  11. package/dist/chunks/{contract-farfe948.js → contract-txjy0en2.js} +31 -31
  12. package/dist/chunks/contract-txjy0en2.js.map +10 -0
  13. package/dist/chunks/contract-wz59z8pq.js.map +2 -2
  14. package/dist/chunks/{contract-4vrw9zk9.js → contract-xtxza1fy.js} +69 -60
  15. package/dist/chunks/contract-xtxza1fy.js.map +12 -0
  16. package/dist/chunks/{contract-nt819swq.js → contract-yxbjea23.js} +13 -6
  17. package/dist/chunks/contract-yxbjea23.js.map +12 -0
  18. package/dist/chunks/{contract-rrm7s5zp.js → contract-zr3jd7mr.js} +5 -5
  19. package/dist/chunks/contract-zr3jd7mr.js.map +12 -0
  20. package/dist/client/index.js +7 -8
  21. package/dist/client/index.js.map +1 -1
  22. package/dist/core/appearance.js +4 -2
  23. package/dist/core/appearance.js.map +1 -1
  24. package/dist/core/contract.js +2 -2
  25. package/dist/embed/index.js +9 -11
  26. package/dist/embed/index.js.map +2 -2
  27. package/dist/local.js +7 -31
  28. package/dist/local.js.map +5 -7
  29. package/dist/react/embed/index.js +2 -3
  30. package/dist/react/embed/index.js.map +2 -2
  31. package/dist/react/index.js +5446 -230
  32. package/dist/react/index.js.map +71 -66
  33. package/dist/server.js +7 -31
  34. package/dist/server.js.map +5 -7
  35. package/dist/types/client/data-client.d.ts +33 -0
  36. package/dist/types/client/index.d.ts +5 -41
  37. package/dist/types/client/location.d.ts +4 -6
  38. package/dist/types/client/navigation.d.ts +2 -1
  39. package/dist/types/core/appearance.d.ts +12 -1
  40. package/dist/types/core/bridge.d.ts +2 -8
  41. package/dist/types/core/config.d.ts +3 -2
  42. package/dist/types/core/contract.d.ts +9 -56
  43. package/dist/types/core/format.d.ts +0 -1
  44. package/dist/types/core/messages.d.ts +5 -30
  45. package/dist/types/core/navigation.d.ts +11 -0
  46. package/dist/types/core/operation-types.d.ts +76 -0
  47. package/dist/types/core/operation.d.ts +2 -8
  48. package/dist/types/core/variables.d.ts +2 -2
  49. package/dist/types/embed/host.d.ts +5 -3
  50. package/dist/types/embed/index.d.ts +0 -1
  51. package/dist/types/embed/source.d.ts +2 -9
  52. package/dist/types/react/content.d.ts +3 -3
  53. package/dist/types/react/hooks.d.ts +65 -64
  54. package/dist/types/react/index.d.ts +135 -2
  55. package/dist/types/react/injectStyles.d.ts +7 -0
  56. package/dist/types/react/shellStyles.d.ts +3 -0
  57. package/dist/types/react/styles.d.ts +8 -0
  58. package/dist/types/react/ui/AboutData.d.ts +0 -1
  59. package/dist/types/react/ui/AppFooter.d.ts +0 -1
  60. package/dist/types/react/ui/AppHeader.d.ts +0 -1
  61. package/dist/types/react/ui/AppLayout.d.ts +0 -1
  62. package/dist/types/react/ui/AppScope.d.ts +0 -1
  63. package/dist/types/react/ui/AppToolbar.d.ts +0 -1
  64. package/dist/types/react/ui/Breakdown.d.ts +0 -1
  65. package/dist/types/react/ui/Button.d.ts +0 -1
  66. package/dist/types/react/ui/Checkbox.d.ts +0 -1
  67. package/dist/types/react/ui/Combobox.d.ts +0 -1
  68. package/dist/types/react/ui/ComparisonVisual.d.ts +0 -1
  69. package/dist/types/react/ui/ContentSkeleton.d.ts +2 -5
  70. package/dist/types/react/ui/DataApp.d.ts +2 -2
  71. package/dist/types/react/ui/DataAppSkeleton.d.ts +0 -1
  72. package/dist/types/react/ui/DataBoundary.d.ts +0 -1
  73. package/dist/types/react/ui/DataSection.d.ts +2 -4
  74. package/dist/types/react/ui/DataTable.d.ts +2 -3
  75. package/dist/types/react/ui/DataViewToast.d.ts +0 -1
  76. package/dist/types/react/ui/DataWidget.d.ts +4 -14
  77. package/dist/types/react/ui/DateRangePicker.d.ts +0 -1
  78. package/dist/types/react/ui/DateTimeTooltip.d.ts +0 -1
  79. package/dist/types/react/ui/EmptyState.d.ts +2 -5
  80. package/dist/types/react/ui/GettingStarted.d.ts +0 -1
  81. package/dist/types/react/ui/GlossaryDefinition.d.ts +0 -1
  82. package/dist/types/react/ui/GlossaryExplanation.d.ts +0 -1
  83. package/dist/types/react/ui/GradientScroll.d.ts +0 -1
  84. package/dist/types/react/ui/Grid.d.ts +0 -1
  85. package/dist/types/react/ui/HelpPopover.d.ts +0 -2
  86. package/dist/types/react/ui/Kbd.d.ts +0 -1
  87. package/dist/types/react/ui/LiveControl.d.ts +0 -1
  88. package/dist/types/react/ui/MetricWidget.d.ts +0 -2
  89. package/dist/types/react/ui/PeriodSummary.d.ts +0 -1
  90. package/dist/types/react/ui/PresentStory.d.ts +0 -1
  91. package/dist/types/react/ui/QueryList.d.ts +0 -1
  92. package/dist/types/react/ui/Ranking.d.ts +0 -1
  93. package/dist/types/react/ui/RefreshControl.d.ts +0 -1
  94. package/dist/types/react/ui/RefreshRegion.d.ts +0 -1
  95. package/dist/types/react/ui/RequestHint.d.ts +0 -1
  96. package/dist/types/react/ui/SearchField.d.ts +0 -1
  97. package/dist/types/react/ui/SearchInput.d.ts +0 -1
  98. package/dist/types/react/ui/SearchMatch.d.ts +0 -1
  99. package/dist/types/react/ui/SelectableBarChart.d.ts +0 -1
  100. package/dist/types/react/ui/SelectionMark.d.ts +0 -1
  101. package/dist/types/react/ui/Sheet.d.ts +0 -1
  102. package/dist/types/react/ui/Skeleton.d.ts +0 -1
  103. package/dist/types/react/ui/Stack.d.ts +0 -1
  104. package/dist/types/react/ui/StatusPanel.d.ts +0 -1
  105. package/dist/types/react/ui/TableWidget.d.ts +2 -3
  106. package/dist/types/react/ui/Tabs.d.ts +0 -1
  107. package/dist/types/react/ui/TextContent.d.ts +4 -0
  108. package/dist/types/react/ui/TextWidget.d.ts +19 -0
  109. package/dist/types/react/ui/ThemeSelector.d.ts +0 -1
  110. package/dist/types/react/ui/Tooltip.d.ts +0 -1
  111. package/dist/types/react/ui/UpdatedAt.d.ts +0 -1
  112. package/dist/types/react/ui/VariableBar.d.ts +0 -1
  113. package/dist/types/react/ui/VisualizationWidget.d.ts +5 -13
  114. package/dist/types/react/ui/WidgetDisclosure.d.ts +0 -1
  115. package/dist/types/react/ui/WidgetViewTabs.d.ts +2 -3
  116. package/dist/types/react/ui/data-identifiers.d.ts +0 -1
  117. package/dist/types/react/ui/presentation.d.ts +19 -0
  118. package/dist/types/react/ui/useAppAppearance.d.ts +2 -2
  119. package/dist/types/react/view-controls.d.ts +1 -1
  120. package/dist/types/react/view.d.ts +2 -2
  121. package/dist/worker.js +1 -0
  122. package/docs/app-authoring.md +61 -44
  123. package/docs/client.md +11 -19
  124. package/docs/contract.md +9 -9
  125. package/docs/embed.md +10 -29
  126. package/docs/hosted-apps.md +39 -0
  127. package/docs/local-data-apps.md +14 -0
  128. package/docs/react-embed.md +10 -19
  129. package/docs/react.md +108 -134
  130. package/docs/server-bun.md +4 -6
  131. package/docs/server.md +2 -2
  132. package/docs/worker.md +3 -5
  133. package/examples/starter-data-app/index.tsx +159 -0
  134. package/package.json +16 -10
  135. package/dist/chunks/contract-3bnrf5pf.js.map +0 -10
  136. package/dist/chunks/contract-4vrw9zk9.js.map +0 -12
  137. package/dist/chunks/contract-8q35dcyh.js +0 -9
  138. package/dist/chunks/contract-8q35dcyh.js.map +0 -10
  139. package/dist/chunks/contract-farfe948.js.map +0 -10
  140. package/dist/chunks/contract-nt819swq.js.map +0 -11
  141. package/dist/chunks/contract-rrm7s5zp.js.map +0 -12
  142. package/dist/chunks/contract-ryyf6dme.js.map +0 -10
  143. package/dist/react/index.css +0 -4628
  144. package/dist/react.css.d.ts +0 -1
  145. package/dist/types/react/ui/index.d.ts +0 -131
  146. package/docs/appearance.md +0 -43
  147. package/docs/config.md +0 -21
  148. package/docs/format.md +0 -29
  149. package/docs/react-styles.md +0 -17
  150. package/docs/starter-agent-instructions.md +0 -53
@@ -0,0 +1,11 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/core/navigation.ts", "../src/core/messages.ts"],
4
+ "sourcesContent": [
5
+ "/** App-owned URL state shared by controls, frame adapters, and host navigation. */\nexport type AppLocation = { search: string; hash: string };\nexport type HistoryMode = 'push' | 'replace';\nexport type NavigationUpdate = AppLocation & {\n mode: HistoryMode;\n title?: string;\n};\n\nexport function validLocation(value: unknown): value is AppLocation {\n if (!value || typeof value !== 'object') return false;\n const message = value as { search?: unknown; hash?: unknown };\n return (\n typeof message.search === 'string' &&\n message.search.length <= 16_384 &&\n (message.search === '' || message.search.startsWith('?')) &&\n typeof message.hash === 'string' &&\n message.hash.length <= 4096 &&\n (message.hash === '' || message.hash.startsWith('#'))\n );\n}\n",
6
+ "import type {\n TransportResponse,\n QueryResult,\n OperationContracts,\n DataQueryInput,\n DataQueryBody,\n OutputOf,\n} from '@/src/core/operation-types';\nexport type {\n OperationContracts,\n DataQueryInput,\n DataQueryBody,\n} from '@/src/core/operation-types';\nimport { validLocation, type NavigationUpdate } from '@/src/core/navigation';\nexport type { NavigationUpdate } from '@/src/core/navigation';\n\nexport type MessageContext = { signal: AbortSignal };\nexport type RoutedMessage = { route: string; payload: unknown };\nexport type MessageDispatcher = (\n message: unknown,\n context: MessageContext\n) => Promise<unknown>;\nexport type MessageTransport = (\n message: RoutedMessage,\n signal?: AbortSignal\n) => Promise<unknown>;\nexport type MessageRoute<Input, Output> = {\n input: (value: unknown) => Input;\n output: (value: unknown, input: Input) => Output;\n};\nexport type MessageRoutes = Record<\n string,\n {\n input: (value: unknown) => unknown;\n output: (value: unknown, input: never) => unknown;\n }\n>;\nexport type MessageInput<Route extends MessageRoutes[string]> = ReturnType<\n Route['input']\n>;\nexport type MessageHandlers<Routes extends MessageRoutes> = {\n [Name in keyof Routes]: (\n payload: MessageInput<Routes[Name]>,\n context: MessageContext\n ) =>\n | ReturnType<Routes[Name]['output']>\n | Promise<ReturnType<Routes[Name]['output']>>;\n};\n\n// A bootstrap and its app may bundle independent copies in the same window.\nconst errorBrand = Symbol.for('@altertable/data-app/MessageRoutingError');\n\n/** Only these deliberate, public failures cross the message boundary. Other errors stay private. */\nexport class MessageRoutingError extends Error {\n readonly [errorBrand] = true;\n\n static [Symbol.hasInstance](value: unknown): boolean {\n return (\n value instanceof Error &&\n (value as { [errorBrand]?: unknown })[errorBrand] === true\n );\n }\n\n constructor(\n public readonly code: string,\n message: string,\n public readonly requestId?: string\n ) {\n super(message);\n this.name = 'MessageRoutingError';\n }\n}\n\nexport function defineMessageRoute<Input, Output>(\n route: MessageRoute<Input, Output>\n): MessageRoute<Input, Output> {\n return route;\n}\n\n/** Contracts are shared; handlers are supplied by the host and never belong in the app bundle. */\nexport function createMessageRouter<const Routes extends MessageRoutes>(\n routes: Routes,\n handlers: MessageHandlers<NoInfer<Routes>>\n) {\n const registered = new Map(\n Object.entries(routes).map(([name, contract]) => {\n const handler = handlers[name];\n if (!name || name.length > 256 || typeof handler !== 'function')\n throw new Error(\n 'Each message route requires a handler and a bounded name.'\n );\n\n return [name, { contract, handler }] as const;\n })\n );\n\n async function dispatch(\n value: unknown,\n context: MessageContext\n ): Promise<unknown> {\n if (\n !value ||\n typeof value !== 'object' ||\n typeof (value as RoutedMessage).route !== 'string'\n )\n throw new MessageRoutingError(\n 'invalid_message',\n 'Invalid routed message.'\n );\n const message = value as RoutedMessage;\n const entry = registered.get(message.route);\n if (!entry)\n throw new MessageRoutingError('unknown_route', 'Unknown message route.');\n let payload: unknown;\n try {\n payload = entry.contract.input(message.payload);\n } catch {\n throw new MessageRoutingError(\n 'invalid_payload',\n 'Invalid message payload.'\n );\n }\n context.signal.throwIfAborted();\n let result: unknown;\n try {\n result = await entry.handler(payload as never, context);\n } catch (error) {\n if (context.signal.aborted) throw context.signal.reason;\n if (error instanceof MessageRoutingError) throw error;\n throw new MessageRoutingError(\n 'request_failed',\n 'The message request failed. Retry the request.'\n );\n }\n context.signal.throwIfAborted();\n try {\n return entry.contract.output(result, payload as never);\n } catch (error) {\n if (error instanceof MessageRoutingError) throw error;\n throw new MessageRoutingError(\n 'invalid_response',\n 'Invalid message response.'\n );\n }\n }\n\n return { dispatch };\n}\n\nexport type DataQueryRoute<Operations extends OperationContracts> =\n MessageRoute<DataQueryInput<Operations>, TransportResponse> & {\n operations: Operations | undefined;\n };\nexport type MessageOutput<Route extends MessageRoutes[string], Input> =\n Route extends DataQueryRoute<infer Operations>\n ? Input extends { operation: infer Name extends keyof Operations }\n ? TransportResponse<DataQueryBody<OutputOf<Operations[Name]>>>\n : never\n : ReturnType<Route['output']>;\n\n/** Omit contracts only in generic hosts such as the CLI shell, where Bun validates operations. */\nexport function defineDataQueryRoute<\n Operations extends OperationContracts = OperationContracts,\n>(operations?: Operations): DataQueryRoute<Operations> {\n return {\n operations,\n input(value) {\n if (!value || typeof value !== 'object')\n throw new Error('Invalid query.');\n const request = value as { operation?: unknown; input?: unknown };\n if (\n typeof request.operation !== 'string' ||\n !request.operation ||\n request.operation.length > 256 ||\n request.operation.includes('/')\n )\n throw new Error('Invalid operation.');\n const operation =\n operations && Object.hasOwn(operations, request.operation)\n ? operations[request.operation]\n : undefined;\n if (operations && !operation) throw new Error('Unknown operation.');\n\n return {\n operation: request.operation,\n input: operation ? operation.input(request.input) : request.input,\n } as DataQueryInput<Operations>;\n },\n output(value, input) {\n if (!value || typeof value !== 'object')\n throw new Error('Invalid data response.');\n const response = value as TransportResponse;\n if (\n !Number.isInteger(response.status) ||\n response.status < 100 ||\n response.status > 599 ||\n !response.body ||\n typeof response.body !== 'object' ||\n Array.isArray(response.body)\n )\n throw new Error('Invalid data response.');\n const body = response.body as DataQueryBody<unknown> & {\n error?: { code?: unknown; message?: unknown; requestId?: unknown };\n };\n if (response.status < 200 || response.status >= 300) {\n const failure = body.error;\n throw new MessageRoutingError(\n typeof failure?.code === 'string' ? failure.code : 'request_failed',\n typeof failure?.message === 'string'\n ? failure.message\n : 'Could not load data.',\n typeof failure?.requestId === 'string' ? failure.requestId : undefined\n );\n }\n if (\n !('data' in body) ||\n typeof body.requestId !== 'string' ||\n typeof body.queriedAt !== 'string' ||\n !Array.isArray(body.queryIds) ||\n !body.queryIds.every(id => typeof id === 'string')\n )\n throw new Error('Invalid data envelope.');\n if (\n body.queries !== undefined &&\n (!Array.isArray(body.queries) ||\n !body.queries.every(\n query =>\n query &&\n typeof query === 'object' &&\n typeof query.name === 'string' &&\n typeof query.statement === 'string' &&\n (query.queryId === undefined || typeof query.queryId === 'string')\n ))\n )\n throw new Error('Invalid query evidence.');\n const operation = operations?.[input.operation];\n\n return {\n status: response.status,\n body: {\n ...body,\n data: operation ? operation.output(body.data) : body.data,\n },\n };\n },\n };\n}\n\nexport const navigationUpdateRoute = /* @__PURE__ */ defineMessageRoute({\n input(value: unknown): NavigationUpdate {\n if (!value || typeof value !== 'object')\n throw new Error('Invalid navigation.');\n const input = value as NavigationUpdate;\n if (\n !validLocation(input) ||\n (input.mode !== 'push' && input.mode !== 'replace') ||\n (input.title !== undefined &&\n (typeof input.title !== 'string' || input.title.length > 512))\n )\n throw new Error('Invalid navigation.');\n\n return {\n search: input.search,\n hash: input.hash,\n mode: input.mode,\n ...(input.title === undefined ? {} : { title: input.title }),\n };\n },\n output(value: unknown): null {\n if (value !== null) throw new Error('Invalid navigation response.');\n\n return null;\n },\n});\nexport type SqlQueryInput = { statement: string; limit: number };\n\n/** SQL delivery for browser-owned operations. Hosts must enforce backend access and resource limits. */\nexport const sqlQueryRoute = defineMessageRoute({\n input(value: unknown): SqlQueryInput {\n if (!value || typeof value !== 'object')\n throw new Error('Invalid SQL query.');\n const query = value as { statement?: unknown; limit?: unknown };\n if (\n typeof query.statement !== 'string' ||\n !query.statement.trim() ||\n typeof query.limit !== 'number' ||\n !Number.isSafeInteger(query.limit) ||\n query.limit < 1\n )\n throw new Error('Invalid SQL query.');\n\n return { statement: query.statement, limit: query.limit };\n },\n output(value: unknown, input: SqlQueryInput): QueryResult {\n if (!value || typeof value !== 'object')\n throw new Error('Invalid query result.');\n const result = value as QueryResult;\n if (\n !Array.isArray(result.columns) ||\n !result.columns.every(\n column =>\n column &&\n typeof column.name === 'string' &&\n (column.type === undefined || typeof column.type === 'string')\n ) ||\n !Array.isArray(result.rows) ||\n result.rows.length > input.limit ||\n !result.rows.every(\n row => Array.isArray(row) && row.length === result.columns.length\n ) ||\n (result.queryId !== undefined && typeof result.queryId !== 'string')\n )\n throw new Error('Invalid query result.');\n\n return {\n columns: result.columns,\n rows: result.rows,\n ...(result.queryId === undefined ? {} : { queryId: result.queryId }),\n };\n },\n});\n\nexport const dataAppRoutes = {\n 'data:query': /* @__PURE__ */ defineDataQueryRoute(),\n 'navigation:update': navigationUpdateRoute,\n};\n"
7
+ ],
8
+ "mappings": "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",
9
+ "debugId": "7AD0B2977AA9174364756E2164756E21",
10
+ "names": []
11
+ }
@@ -1,7 +1,3 @@
1
- import {
2
- invariant
3
- } from "./contract-8q35dcyh.js";
4
-
5
1
  // src/core/appearance.ts
6
2
  var defaults = {
7
3
  theme: "light",
@@ -34,38 +30,42 @@ function font(value) {
34
30
  return typeof value === "string" && value.length > 0 && value.length <= 120 && !/[;{}()]/.test(value);
35
31
  }
36
32
  function parseAppearance2(value) {
37
- if (value === undefined)
38
- return {
39
- ...defaults,
40
- chartColors: [...defaults.chartColors],
41
- typography: { ...defaults.typography }
42
- };
43
- invariant(record(value) && Object.keys(value).every((key) => [
44
- "theme",
45
- "baseColor",
46
- "accentColor",
47
- "darkAccentColor",
48
- "chartColors",
49
- "density",
50
- "cornerRadius",
51
- "elevation",
52
- "typography"
53
- ].includes(key)), "Invalid appearance settings.");
54
- const typography = value.typography;
55
- const validFields = (value.theme === undefined || oneOf(value.theme, ["light", "dark", "system"])) && (value.baseColor === undefined || oneOf(value.baseColor, ["neutral", "slate", "warm"])) && (value.accentColor === undefined || color(value.accentColor)) && (value.darkAccentColor === undefined || color(value.darkAccentColor)) && (value.chartColors === undefined || Array.isArray(value.chartColors) && value.chartColors.length >= 1 && value.chartColors.length <= 8 && value.chartColors.every(color)) && (value.density === undefined || oneOf(value.density, ["compact", "comfortable", "spacious"])) && (value.cornerRadius === undefined || oneOf(value.cornerRadius, ["none", "small", "medium", "large"])) && (value.elevation === undefined || oneOf(value.elevation, ["flat", "subtle", "raised"])) && (typography === undefined || record(typography) && Object.keys(typography).every((key) => key === "body" || key === "heading") && (typography.body === undefined || font(typography.body)) && (typography.heading === undefined || font(typography.heading)));
56
- invariant(validFields, "Invalid appearance settings.");
33
+ if (!record(value))
34
+ return normalizeAppearance2();
35
+ const typography = record(value.typography) ? value.typography : {};
36
+ return normalizeAppearance2({
37
+ theme: oneOf(value.theme, ["light", "dark", "system"]) ? value.theme : undefined,
38
+ baseColor: oneOf(value.baseColor, ["neutral", "slate", "warm"]) ? value.baseColor : undefined,
39
+ accentColor: color(value.accentColor) ? value.accentColor : undefined,
40
+ darkAccentColor: color(value.darkAccentColor) ? value.darkAccentColor : undefined,
41
+ chartColors: Array.isArray(value.chartColors) && value.chartColors.length >= 1 && value.chartColors.length <= 8 && value.chartColors.every(color) ? value.chartColors : undefined,
42
+ density: oneOf(value.density, ["compact", "comfortable", "spacious"]) ? value.density : undefined,
43
+ cornerRadius: oneOf(value.cornerRadius, [
44
+ "none",
45
+ "small",
46
+ "medium",
47
+ "large"
48
+ ]) ? value.cornerRadius : undefined,
49
+ elevation: oneOf(value.elevation, ["flat", "subtle", "raised"]) ? value.elevation : undefined,
50
+ typography: {
51
+ body: font(typography.body) ? typography.body : undefined,
52
+ heading: font(typography.heading) ? typography.heading : undefined
53
+ }
54
+ });
55
+ }
56
+ function normalizeAppearance2(value = {}) {
57
57
  return {
58
58
  theme: value.theme ?? defaults.theme,
59
59
  baseColor: value.baseColor ?? defaults.baseColor,
60
60
  accentColor: value.accentColor ?? defaults.accentColor,
61
- darkAccentColor: value.darkAccentColor ?? (value.accentColor === undefined ? defaults.darkAccentColor : undefined),
62
- chartColors: value.chartColors ?? defaults.chartColors,
63
61
  density: value.density ?? defaults.density,
64
62
  cornerRadius: value.cornerRadius ?? defaults.cornerRadius,
65
63
  elevation: value.elevation ?? defaults.elevation,
64
+ darkAccentColor: value.darkAccentColor ?? (value.accentColor === undefined ? defaults.darkAccentColor : undefined),
65
+ chartColors: [...value.chartColors ?? defaults.chartColors],
66
66
  typography: {
67
- body: record(typography) && typeof typography.body === "string" ? typography.body : defaults.typography.body,
68
- heading: record(typography) && typeof typography.heading === "string" ? typography.heading : defaults.typography.heading
67
+ body: value.typography?.body ?? defaults.typography.body,
68
+ heading: value.typography?.heading ?? defaults.typography.heading
69
69
  }
70
70
  };
71
71
  }
@@ -98,7 +98,7 @@ function fontStack(family) {
98
98
  return family === "system" ? "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, ui-sans-serif, sans-serif" : `${JSON.stringify(family)}, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, ui-sans-serif, sans-serif`;
99
99
  }
100
100
  function applyAppearance2(value) {
101
- const settings = parseAppearance2(value);
101
+ const settings = normalizeAppearance2(value);
102
102
  const root = document.documentElement;
103
103
  const preference = window.matchMedia("(prefers-color-scheme: dark)");
104
104
  const [xs, sm, md, lg, xl] = spaces[settings.density];
@@ -183,6 +183,6 @@ function createThemeController2(initialTheme = "light") {
183
183
  };
184
184
  }
185
185
 
186
- export { parseAppearance2, applyAppearance2, createThemeController2 };
186
+ export { parseAppearance2, normalizeAppearance2, applyAppearance2, createThemeController2 };
187
187
 
188
- //# debugId=90CD7598768B570C64756E2164756E21
188
+ //# debugId=E968EAFDC43C9C1764756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/core/appearance.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * Brand settings; parsing is portable, while theme application requires the browser.\n * @module @altertable/data-app/appearance\n */\nexport type Theme = 'light' | 'dark';\nexport type ThemePreference = Theme | 'system';\n\nexport type AppearanceSettings = {\n theme: ThemePreference;\n baseColor: 'neutral' | 'slate' | 'warm';\n accentColor: string;\n darkAccentColor?: string;\n chartColors: string[];\n density: 'compact' | 'comfortable' | 'spacious';\n cornerRadius: 'none' | 'small' | 'medium' | 'large';\n elevation: 'flat' | 'subtle' | 'raised';\n typography: { body: string; heading: string };\n};\n\n/** App-authored overrides; omitted fields use the package defaults. */\nexport type AppearanceOptions = Partial<\n Omit<AppearanceSettings, 'typography'>\n> & { typography?: Partial<AppearanceSettings['typography']> };\n\nexport type ThemeController = {\n getTheme: () => ThemePreference;\n setTheme: (theme: ThemePreference) => void;\n subscribe: (listener: () => void) => () => void;\n};\n\nconst defaults: AppearanceSettings = {\n theme: 'light',\n baseColor: 'neutral',\n accentColor: '#405d47',\n darkAccentColor: '#a6c4ad',\n chartColors: [\n '#285fc0',\n '#a95319',\n '#147862',\n '#7243aa',\n '#aa3958',\n '#475569',\n ],\n density: 'comfortable',\n cornerRadius: 'medium',\n elevation: 'subtle',\n typography: { body: 'system', heading: 'system' },\n};\n\nfunction record(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction oneOf<T extends string>(\n value: unknown,\n options: readonly T[]\n): value is T {\n return typeof value === 'string' && options.includes(value as T);\n}\n\nfunction color(value: unknown): value is string {\n return typeof value === 'string' && /^#[0-9a-fA-F]{6}$/.test(value);\n}\n\nfunction font(value: unknown): value is string {\n return (\n typeof value === 'string' &&\n value.length > 0 &&\n value.length <= 120 &&\n !/[;{}()]/.test(value)\n );\n}\n\n/** Preserve supported external settings and use defaults for invalid fields. */\nexport function parseAppearance(value: unknown): AppearanceSettings {\n if (!record(value)) return normalizeAppearance();\n const typography = record(value.typography) ? value.typography : {};\n\n return normalizeAppearance({\n theme: oneOf(value.theme, ['light', 'dark', 'system'])\n ? value.theme\n : undefined,\n baseColor: oneOf(value.baseColor, ['neutral', 'slate', 'warm'])\n ? value.baseColor\n : undefined,\n accentColor: color(value.accentColor) ? value.accentColor : undefined,\n darkAccentColor: color(value.darkAccentColor)\n ? value.darkAccentColor\n : undefined,\n chartColors:\n Array.isArray(value.chartColors) &&\n value.chartColors.length >= 1 &&\n value.chartColors.length <= 8 &&\n value.chartColors.every(color)\n ? value.chartColors\n : undefined,\n density: oneOf(value.density, ['compact', 'comfortable', 'spacious'])\n ? value.density\n : undefined,\n cornerRadius: oneOf(value.cornerRadius, [\n 'none',\n 'small',\n 'medium',\n 'large',\n ])\n ? value.cornerRadius\n : undefined,\n elevation: oneOf(value.elevation, ['flat', 'subtle', 'raised'])\n ? value.elevation\n : undefined,\n typography: {\n body: font(typography.body) ? typography.body : undefined,\n heading: font(typography.heading) ? typography.heading : undefined,\n },\n });\n}\n\n/** Resolve typed app settings without repeating authoring checks at runtime. */\nexport function normalizeAppearance(\n value: AppearanceOptions = {}\n): AppearanceSettings {\n return {\n theme: value.theme ?? defaults.theme,\n baseColor: value.baseColor ?? defaults.baseColor,\n accentColor: value.accentColor ?? defaults.accentColor,\n density: value.density ?? defaults.density,\n cornerRadius: value.cornerRadius ?? defaults.cornerRadius,\n elevation: value.elevation ?? defaults.elevation,\n darkAccentColor:\n value.darkAccentColor ??\n (value.accentColor === undefined ? defaults.darkAccentColor : undefined),\n chartColors: [...(value.chartColors ?? defaults.chartColors)],\n typography: {\n body: value.typography?.body ?? defaults.typography.body,\n heading: value.typography?.heading ?? defaults.typography.heading,\n },\n };\n}\n\nconst palettes = {\n neutral: {\n light: ['#ffffff', '#ffffff', '#f6f7f7', '#202124', '#687078', '#e3e6e8'],\n dark: ['#151719', '#202326', '#292d31', '#f2f3f4', '#aeb5bc', '#3b4248'],\n },\n slate: {\n light: ['#f8fafc', '#ffffff', '#f1f5f9', '#17212f', '#607083', '#dce3ea'],\n dark: ['#111820', '#1b2530', '#263340', '#f0f4f8', '#a8b5c3', '#3a4857'],\n },\n warm: {\n light: ['#fbfaf8', '#ffffff', '#f5f2ed', '#292723', '#736e66', '#e8e2da'],\n dark: ['#1b1916', '#25221e', '#302c27', '#f5f1eb', '#bcb3a8', '#494239'],\n },\n} as const;\n\nconst spaces = {\n compact: ['4px', '8px', '12px', '18px', '24px'],\n comfortable: ['5px', '10px', '16px', '24px', '32px'],\n spacious: ['6px', '12px', '20px', '30px', '40px'],\n} as const;\n\nconst radii = {\n none: ['0px', '0px', '0px'],\n small: ['4px', '7px', '9px'],\n medium: ['7px', '12px', '16px'],\n large: ['10px', '18px', '24px'],\n} as const;\n\nfunction fontStack(family: string): string {\n return family === 'system'\n ? \"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, ui-sans-serif, sans-serif\"\n : `${JSON.stringify(family)}, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, ui-sans-serif, sans-serif`;\n}\n\n/**\n * Install semantic tokens on the document root, including portaled UI. Returns a cleanup for\n * system-theme listening.\n */\nexport function applyAppearance(value?: AppearanceOptions): () => void {\n const settings = normalizeAppearance(value);\n const root = document.documentElement;\n const preference = window.matchMedia('(prefers-color-scheme: dark)');\n const [xs, sm, md, lg, xl] = spaces[settings.density];\n const [control, surface, overlay] = radii[settings.cornerRadius];\n const tokens: Record<string, string> = {\n '--at-font': fontStack(settings.typography.body),\n '--at-font-heading': fontStack(settings.typography.heading),\n '--at-space-xs': xs,\n '--at-space-sm': sm,\n '--at-space-md': md,\n '--at-space-lg': lg,\n '--at-space-xl': xl,\n '--at-layout-gap': `clamp(${md}, 2.5vw, ${lg})`,\n '--at-radius-control': control,\n '--at-radius-surface': surface,\n '--at-radius-overlay': overlay,\n '--at-shadow-overlay':\n settings.elevation === 'flat'\n ? 'none'\n : settings.elevation === 'raised'\n ? '0 24px 72px rgb(0 0 0 / 24%)'\n : '0 18px 50px rgb(0 0 0 / 16%)',\n '--at-shadow-surface':\n settings.elevation === 'flat'\n ? 'none'\n : settings.elevation === 'raised'\n ? '0 8px 28px rgb(20 28 40 / 10%)'\n : '0 3px 16px rgb(20 28 40 / 5%)',\n };\n\n function applyColors(): void {\n const dark =\n settings.theme === 'dark' ||\n (settings.theme === 'system' && preference.matches);\n const [background, surfaceColor, subtle, text, muted, border] =\n palettes[settings.baseColor][dark ? 'dark' : 'light'];\n const accent = dark\n ? (settings.darkAccentColor ??\n `color-mix(in srgb, ${settings.accentColor} 50%, white)`)\n : settings.accentColor;\n settings.chartColors.forEach((chartColor, index) => {\n tokens[`--at-chart-${index + 1}`] = dark\n ? `color-mix(in srgb, ${chartColor} 60%, white)`\n : chartColor;\n });\n Object.assign(tokens, {\n '--at-background': background,\n '--at-surface': surfaceColor,\n '--at-subtle': subtle,\n '--at-text': text,\n '--at-muted': muted,\n '--at-border': border,\n '--at-accent': accent,\n '--at-focus-color': muted,\n '--at-control-hover-border': `color-mix(in srgb, ${muted} 45%, ${border})`,\n '--at-accent-hover': `color-mix(in srgb, ${accent} 80%, ${dark ? 'white' : 'black'})`,\n '--at-accent-subtle': `color-mix(in srgb, ${accent} ${dark ? 22 : 12}%, ${surfaceColor})`,\n '--at-on-accent': dark ? background : '#ffffff',\n '--at-danger': dark ? '#f97066' : '#b42318',\n '--at-backdrop': dark ? 'rgb(0 0 0 / 55%)' : 'rgb(15 23 30 / 22%)',\n '--at-code-surface': dark ? '#242a31' : '#f4f6f9',\n '--at-code-text': dark ? '#e5e9ef' : '#273242',\n });\n root.style.colorScheme = dark ? 'dark' : 'light';\n for (const [name, token] of Object.entries(tokens))\n root.style.setProperty(name, token);\n }\n applyColors();\n if (settings.theme === 'system')\n preference.addEventListener('change', applyColors);\n\n return () => {\n preference.removeEventListener('change', applyColors);\n };\n}\n\n/** Persist a viewer theme preference. Applying appearance belongs to the UI owner. */\nexport function createThemeController(\n initialTheme: ThemePreference = 'light'\n): ThemeController {\n const storageKey = 'altertable.data-app.theme';\n let theme = initialTheme;\n try {\n const saved = window.localStorage.getItem(storageKey);\n if (oneOf(saved, ['light', 'dark', 'system'])) theme = saved;\n } catch {\n // Storage can be unavailable in private browsing or embedded contexts.\n }\n const listeners = new Set<() => void>();\n\n return {\n getTheme() {\n return theme;\n },\n setTheme(nextTheme) {\n if (nextTheme === theme) return;\n theme = nextTheme;\n try {\n window.localStorage.setItem(storageKey, theme);\n } catch {\n // The selection still applies to this page.\n }\n listeners.forEach(listener => listener());\n },\n subscribe(listener) {\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n },\n };\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "E968EAFDC43C9C1764756E2164756E21",
9
+ "names": []
10
+ }
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/core/config.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * App identity and display scope shared by browser and server.\n * @module @altertable/data-app/config\n * @see https://github.com/altertable-ai/data-app/blob/main/docs/config.md\n */\nexport type DataAppConfig = {\n title: string;\n scope: { organization: string; environment: string };\n appearance: unknown;\n};\n\nexport function dataAppTitle(\n config: Pick<DataAppConfig, 'title' | 'scope'>\n): string {\n return `${config.title} • ${config.scope.organization}/${config.scope.environment} • Altertable app`;\n}\n"
5
+ "/**\n * App identity and display scope shared by browser and server.\n * @module @altertable/data-app/config\n */\nimport type { AppearanceOptions } from '@/src/core/appearance';\n\nexport type DataAppConfig = {\n title: string;\n /** Display labels; scope does not grant data access. */\n scope: { organization: string; environment: string };\n appearance: AppearanceOptions;\n};\n\nexport function dataAppTitle(\n config: Pick<DataAppConfig, 'title' | 'scope'>\n): string {\n return `${config.title} • ${config.scope.organization}/${config.scope.environment} • Altertable app`;\n}\n"
6
6
  ],
7
- "mappings": ";AAWO,SAAS,aAAY,CAC1B,QACQ;AAAA,EACR,OAAO,GAAG,OAAO,WAAW,OAAO,MAAM,gBAAgB,OAAO,MAAM;AAAA;",
7
+ "mappings": ";AAaO,SAAS,aAAY,CAC1B,QACQ;AAAA,EACR,OAAO,GAAG,OAAO,WAAW,OAAO,MAAM,gBAAgB,OAAO,MAAM;AAAA;",
8
8
  "debugId": "B8EA593317DFC02A64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -6,16 +6,76 @@ import {
6
6
  getDataAppTransport2,
7
7
  executeDataOperation,
8
8
  toDataOperationFailure
9
- } from "./contract-xjv197ck.js";
9
+ } from "./contract-mwe7gnmh.js";
10
10
  import {
11
+ PARENT_PARAM
12
+ } from "./contract-cxr9t12b.js";
13
+ import {
14
+ validLocation,
11
15
  MessageRoutingError2,
12
16
  defineDataQueryRoute2,
13
17
  navigationUpdateRoute2
14
- } from "./contract-3bnrf5pf.js";
15
- import {
16
- PARENT_PARAM,
17
- validLocation
18
- } from "./contract-ryyf6dme.js";
18
+ } from "./contract-tf8c3qpv.js";
19
+
20
+ // src/client/data-client.ts
21
+ var dataQueryRoute = defineDataQueryRoute2();
22
+ function createDataClient2(options = {}) {
23
+ if (options.operations)
24
+ return createOperationClient({
25
+ operations: options.operations,
26
+ lakehouse: options.lakehouse
27
+ });
28
+ const http = createHttpTransport2(options);
29
+ const useHttp = options.endpoint !== undefined || options.fetch !== undefined;
30
+ return {
31
+ async query(name, input, { signal } = {}) {
32
+ const transport = options.transport ?? (useHttp ? http : localFrameBridge()?.transport ?? http);
33
+ const response = await transport(name, input, signal);
34
+ const ok = response.status >= 200 && response.status < 300;
35
+ let body;
36
+ try {
37
+ body = dataQueryRoute.output(response, { operation: name, input }).body;
38
+ } catch (error) {
39
+ if (signal?.aborted)
40
+ throw error;
41
+ if (error instanceof MessageRoutingError2)
42
+ throw new DataAppError2(error.message, error.code, error.requestId);
43
+ throw new DataAppError2(ok ? "The data response was invalid." : "Could not load data.", ok ? "invalid_response" : "request_failed");
44
+ }
45
+ return { ...body, input };
46
+ }
47
+ };
48
+ }
49
+ function createOperationClient(options) {
50
+ return {
51
+ async query(name, input, { signal } = {}) {
52
+ signal?.throwIfAborted();
53
+ const requestId = crypto.randomUUID();
54
+ if (!Object.hasOwn(options.operations, name))
55
+ throw new DataAppError2("Unknown data operation.", "not_found", requestId);
56
+ const lakehouse = options.lakehouse ?? (typeof window === "undefined" ? undefined : getDataAppTransport2()?.lakehouse);
57
+ if (!lakehouse)
58
+ throw new DataAppError2("An authorized SQL bridge must be installed first.", "bridge_unavailable", requestId);
59
+ try {
60
+ const { body } = await executeDataOperation(options.operations[name], input, {
61
+ lakehouse,
62
+ signal: signal ?? new AbortController().signal,
63
+ includeSql: true,
64
+ requestId,
65
+ operationName: name
66
+ });
67
+ return { ...body, input };
68
+ } catch (error) {
69
+ if (signal?.aborted)
70
+ throw signal.reason;
71
+ if (error instanceof DataAppError2)
72
+ throw error;
73
+ const failure = toDataOperationFailure(error);
74
+ throw new DataAppError2(failure.message, failure.code, requestId);
75
+ }
76
+ }
77
+ };
78
+ }
19
79
 
20
80
  // src/client/location.ts
21
81
  function createAppLocation(frame, virtual, publish) {
@@ -115,7 +175,7 @@ function attachNavigation(frame, virtual, connection) {
115
175
  messages.request("navigation:update", update).catch(() => {});
116
176
  }
117
177
  function receiveState(state) {
118
- if (!state || typeof state !== "object" || !validLocation(state))
178
+ if (!validLocation(state))
119
179
  return;
120
180
  pendingUpdate = undefined;
121
181
  apply(state);
@@ -187,57 +247,6 @@ function getDataAppNavigation2(frame = window) {
187
247
  return adapter.navigation;
188
248
  }
189
249
 
190
- // src/client/index.ts
191
- var dataQueryRoute = defineDataQueryRoute2();
192
- function createDataClient2(options = {}) {
193
- const http = createHttpTransport2(options);
194
- const useHttp = options.endpoint !== undefined || options.fetch !== undefined;
195
- return {
196
- async query(name, input, { signal } = {}) {
197
- if (options.operations) {
198
- signal?.throwIfAborted();
199
- const requestId = crypto.randomUUID();
200
- if (!Object.hasOwn(options.operations, name))
201
- throw new DataAppError2("Unknown data operation.", "not_found", requestId);
202
- const lakehouse = options.lakehouse ?? (typeof window === "undefined" ? undefined : getDataAppTransport2()?.lakehouse);
203
- if (!lakehouse)
204
- throw new DataAppError2("An authorized SQL bridge must be installed first.", "bridge_unavailable", requestId);
205
- try {
206
- const { body } = await executeDataOperation(options.operations[name], input, {
207
- lakehouse,
208
- signal: signal ?? new AbortController().signal,
209
- includeSql: true,
210
- requestId,
211
- operationName: name
212
- });
213
- return { ...body, input };
214
- } catch (error) {
215
- if (signal?.aborted)
216
- throw signal.reason;
217
- if (error instanceof DataAppError2)
218
- throw error;
219
- const failure = toDataOperationFailure(error);
220
- throw new DataAppError2(failure.message, failure.code, requestId);
221
- }
222
- }
223
- const transport = options.transport ?? (useHttp ? http : localFrameBridge()?.transport ?? http);
224
- const response = await transport(name, input, signal);
225
- const ok = response.status >= 200 && response.status < 300;
226
- let body;
227
- try {
228
- body = dataQueryRoute.output(response, { operation: name, input }).body;
229
- } catch (error) {
230
- if (signal?.aborted)
231
- throw error;
232
- if (error instanceof MessageRoutingError2)
233
- throw new DataAppError2(error.message, error.code, error.requestId);
234
- throw new DataAppError2(ok ? "The data response was invalid." : "Could not load data.", ok ? "invalid_response" : "request_failed");
235
- }
236
- return { ...body, input };
237
- }
238
- };
239
- }
240
-
241
- export { createDataAppNavigation2, getDataAppNavigation2, createDataClient2 };
250
+ export { createDataClient2, createDataAppNavigation2, getDataAppNavigation2 };
242
251
 
243
- //# debugId=A9C5A1657EDE5C5C64756E2164756E21
252
+ //# debugId=B2D2C0A1B4F5737F64756E2164756E21
@@ -0,0 +1,12 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/client/data-client.ts", "../src/client/location.ts", "../src/client/navigation.ts"],
4
+ "sourcesContent": [
5
+ "import { 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. `queries` is present only when SQL disclosure is\n * allowed.\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 = crypto.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 includeSql: true,\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
+ "import { PARENT_PARAM } from '@/src/core/bridge';\nimport { validLocation } from '@/src/core/navigation';\n\nimport type { AppLocation, HistoryMode } from '@/src/core/navigation';\nexport type { AppLocation } from '@/src/core/navigation';\nexport type DataAppLocation = {\n snapshot(): AppLocation;\n subscribe(listener: () => void): () => void;\n update(location: AppLocation, mode?: HistoryMode): void;\n};\n\n/** Opaque sandboxes keep app state in memory; URL frames retain their real URL for HMR. */\nexport function createAppLocation(\n frame: Window,\n virtual: boolean,\n publish: (location: AppLocation, mode: HistoryMode) => void\n) {\n let state: AppLocation = { search: '', hash: '' };\n let disposed = false;\n const listeners = new Set<() => void>();\n\n function notify() {\n for (const listener of listeners) listener();\n }\n\n function snapshot(): AppLocation {\n if (virtual) return state;\n const url = new URL(frame.location.href);\n url.searchParams.delete(PARENT_PARAM);\n if (state.search !== url.search || state.hash !== url.hash)\n state = { search: url.search, hash: url.hash };\n\n return state;\n }\n\n function apply(next: AppLocation) {\n const previous = snapshot();\n if (previous.search === next.search && previous.hash === next.hash) return;\n if (virtual) state = next;\n else {\n const url = new URL(frame.location.href);\n const parent = url.searchParams.get(PARENT_PARAM);\n url.search = next.search;\n if (parent) url.searchParams.set(PARENT_PARAM, parent);\n url.hash = next.hash;\n frame.history.replaceState(null, '', url);\n frame.dispatchEvent(new Event('popstate'));\n }\n if (virtual) notify();\n }\n\n const location: DataAppLocation = {\n snapshot,\n subscribe(listener) {\n listeners.add(listener);\n if (!virtual) frame.addEventListener('popstate', listener);\n\n return () => {\n listeners.delete(listener);\n frame.removeEventListener('popstate', listener);\n };\n },\n update(next, mode = 'replace') {\n if (disposed) return;\n if (!validLocation(next)) throw new Error('Invalid app location.');\n const before = snapshot();\n if (before.search === next.search && before.hash === next.hash) return;\n apply(next);\n publish(next, mode);\n },\n };\n\n function dispose() {\n disposed = true;\n for (const listener of listeners)\n frame.removeEventListener('popstate', listener);\n listeners.clear();\n }\n\n return { location, apply, dispose };\n}\n",
7
+ "import type { AppLocation, HistoryMode } from '@/src/core/navigation';\nimport { createAppLocation, type DataAppLocation } from '@/src/client/location';\nimport { validLocation } from '@/src/core/navigation';\nimport {\n navigationUpdateRoute,\n type NavigationUpdate,\n} from '@/src/core/messages';\nimport { createMessageClient } from '@/src/client/messages';\nimport {\n getDataAppTransport,\n localFrameBridge,\n type IframeTransport,\n} from '@/src/client/iframe';\n\nexport type DataAppNavigation = DataAppLocation & {\n /** Publish URL changes made outside the adapter, including the document title. */\n publish(mode?: HistoryMode): void;\n dispose(): void;\n};\n\n/** Attach app URL behavior to an already authenticated bridge. */\nexport function createDataAppNavigation({\n bridge,\n window: frame = window,\n}: {\n bridge: IframeTransport;\n window?: Window;\n}): DataAppNavigation {\n return attachNavigation(frame, bridge.mode === 'bundle', bridge).navigation;\n}\n\nfunction attachNavigation(\n frame: Window,\n virtual: boolean,\n connection: IframeTransport | Promise<IframeTransport>\n) {\n let disposed = false;\n let unsubscribe: (() => void) | undefined;\n let send: ((update: NavigationUpdate) => void) | undefined;\n let pendingUpdate: NavigationUpdate | undefined;\n const { location, apply, dispose } = createAppLocation(\n frame,\n virtual,\n publish\n );\n\n function publish(location: AppLocation, mode: HistoryMode) {\n const update = { ...location, mode, title: frame.document.title };\n if (send) send(update);\n else pendingUpdate = update;\n }\n\n function attach(bridge: IframeTransport) {\n if (disposed) return;\n unsubscribe?.();\n const messages = createMessageClient(\n { 'navigation:update': navigationUpdateRoute },\n bridge.request\n );\n\n function sendUpdate(update: NavigationUpdate) {\n void messages.request('navigation:update', update).catch(() => {});\n }\n\n function receiveState(state: unknown) {\n if (!validLocation(state)) return;\n pendingUpdate = undefined;\n apply(state);\n }\n\n send = sendUpdate;\n unsubscribe = bridge.subscribe(receiveState);\n receiveState(bridge.snapshot());\n if (pendingUpdate) {\n sendUpdate(pendingUpdate);\n pendingUpdate = undefined;\n }\n }\n\n if ('then' in connection) void connection.then(attach).catch(() => {});\n else attach(connection);\n\n const navigation: DataAppNavigation = {\n ...location,\n publish(mode = 'replace') {\n if (!disposed) publish(location.snapshot(), mode);\n },\n dispose() {\n disposed = true;\n unsubscribe?.();\n dispose();\n send = undefined;\n pendingUpdate = undefined;\n },\n };\n\n return {\n navigation,\n attach,\n isDisposed() {\n return disposed;\n },\n };\n}\n\nconst navigationKey = Symbol.for('altertable.appNavigation');\ntype NavigationWindow = Window & {\n [navigationKey]?: ReturnType<typeof attachNavigation> & {\n bridge?: IframeTransport;\n };\n};\n\n/** URL controls attach navigation on demand; bootstrap and data-only clients do not. */\nexport function getDataAppNavigation(\n frame: Window = window\n): DataAppNavigation | undefined {\n const target = frame as NavigationWindow;\n const bridge = getDataAppTransport(frame);\n const cached = target[navigationKey]?.isDisposed()\n ? undefined\n : target[navigationKey];\n if (cached) {\n if (bridge && cached.bridge !== bridge) {\n cached.attach(bridge);\n cached.bridge = bridge;\n }\n\n return cached.navigation;\n }\n if (bridge) {\n const adapter = attachNavigation(frame, bridge.mode === 'bundle', bridge);\n target[navigationKey] = { bridge, ...adapter };\n\n return adapter.navigation;\n }\n const preview = localFrameBridge(frame);\n if (!preview?.connect) return undefined;\n const connection = preview.connect();\n const adapter = attachNavigation(frame, false, connection);\n const entry = {\n ...adapter,\n bridge: undefined as IframeTransport | undefined,\n };\n target[navigationKey] = entry;\n void connection\n .then(bridge => {\n entry.bridge = bridge;\n })\n .catch(() => {});\n\n return adapter.navigation;\n}\n"
8
+ ],
9
+ "mappings": "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",
10
+ "debugId": "B2D2C0A1B4F5737F64756E2164756E21",
11
+ "names": []
12
+ }
@@ -1,13 +1,16 @@
1
1
  import {
2
2
  formatDateRange2
3
3
  } from "./contract-mev09s5v.js";
4
- import {
5
- invariant
6
- } from "./contract-8q35dcyh.js";
7
4
 
8
5
  // src/core/contract.ts
9
6
  import { parseDate, today } from "@internationalized/date";
10
7
 
8
+ // src/core/invariant.ts
9
+ function invariant(condition, message) {
10
+ if (!condition)
11
+ throw new Error(`Invariant failed: ${message}`);
12
+ }
13
+
11
14
  // src/core/dimension.ts
12
15
  var allSelection = { kind: "all" };
13
16
  function dimensionMemberKey(member) {
@@ -16,7 +19,6 @@ function dimensionMemberKey(member) {
16
19
  function dimensionFilter2(config) {
17
20
  const { key, label, selection, valueType } = config;
18
21
  const options = config.options ?? [];
19
- invariant(!!config.options !== !!config.facet, "Choose fixed options or one facet operation.");
20
22
  const optionKeys = options.map((option) => dimensionMemberKey({ kind: "value", value: option.value }));
21
23
  invariant(!!key && options.length <= 200 && new Set(optionKeys).size === options.length, "Dimension options need a key, at most 200 distinct values.");
22
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.");
@@ -266,11 +268,16 @@ function defineQueryNames2(names) {
266
268
  invariant(values.every((name) => !!name.trim()) && new Set(values).size === values.length, "Query names must be nonempty and unique.");
267
269
  return names;
268
270
  }
271
+ var sourceErrorBrand = Symbol.for("@altertable/data-app/DataSourceError");
269
272
 
270
273
  class DataSourceError2 extends Error {
271
274
  reason;
272
275
  status;
276
+ [sourceErrorBrand] = true;
273
277
  queryName;
278
+ static [Symbol.hasInstance](value) {
279
+ return value instanceof Error && value[sourceErrorBrand] === true;
280
+ }
274
281
  constructor(reason, status) {
275
282
  super(`Data source ${reason}${status ? ` (${status})` : ""}.`);
276
283
  this.reason = reason;
@@ -316,6 +323,6 @@ function connectionCheck2() {
316
323
  });
317
324
  }
318
325
 
319
- export { dimensionMemberKey, dimensionFilter2, parseDimensionSelection2, parseFacetOptions2, dimensionPredicate2, parseEmptyInput2, parseTrue2, previousDateRange2, defineDateRangeContract2, parseDateRangeInput2, parseCount2, parseLabel2, rowsAsRecords2, defineQueryNames2, DataSourceError2, defineOperation2, connectionQueryNames2, connectionCheck2 };
326
+ export { invariant, dimensionMemberKey, dimensionFilter2, parseDimensionSelection2, parseFacetOptions2, dimensionPredicate2, parseEmptyInput2, parseTrue2, previousDateRange2, defineDateRangeContract2, parseDateRangeInput2, parseCount2, parseLabel2, rowsAsRecords2, defineQueryNames2, DataSourceError2, defineOperation2, connectionQueryNames2, connectionCheck2 };
320
327
 
321
- //# debugId=65216D55145AC13D64756E2164756E21
328
+ //# debugId=44D567B58A731E4A64756E2164756E21
@@ -0,0 +1,12 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/core/contract.ts", "../src/core/invariant.ts", "../src/core/dimension.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 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\nexport type OperationQuery<Names extends Readonly<Record<string, string>>> = (\n name: Names[keyof Names],\n statement: string,\n options?: { limit?: number }\n) => Promise<QueryResult>;\n\nexport function defineOperation<\n Input,\n Output,\n const Names extends Readonly<Record<string, string>> = Record<string, never>,\n>(\n operation: Omit<DataOperation<Input, Output>, 'run' | 'queryNames'> & {\n queryNames?: Names;\n run: (\n context: OperationContext & { query: OperationQuery<NoInfer<Names>> },\n input: Input\n ) => Promise<Output>;\n }\n): DataOperation<Input, Output> & { queryNames?: Names } {\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 if (operation.queryNames) defineQueryNames(operation.queryNames);\n for (const input of operation.checks) operation.input(input);\n\n return {\n ...operation,\n run(context, input) {\n function query(\n name: Names[keyof Names],\n statement: string,\n options?: { limit?: number }\n ): Promise<QueryResult> {\n invariant(\n operation.queryNames &&\n Object.values(operation.queryNames).includes(name),\n `Unknown query name: ${name}.`\n );\n\n return context.lakehouse.queryAll(statement, {\n name,\n limit: options?.limit ?? operation.policy.maxQueryRows,\n signal: context.signal,\n });\n }\n\n return operation.run({ ...context, query }, input);\n },\n };\n}\n\nexport const connectionQueryNames = defineQueryNames({\n connection: 'connection-check',\n});\n\n/** Success requires a bounded SQL query; it does not establish access to a particular dataset. */\nexport function connectionCheck(): DataOperation<Record<string, never>, true> {\n return defineOperation({\n input: parseEmptyInput,\n output: parseTrue,\n checks: [{}],\n queryNames: connectionQueryNames,\n policy: { maxQueryRows: 1, maxDurationMs: 15_000, exposeSql: true },\n async run({ query }): Promise<true> {\n await query(\n connectionQueryNames.connection,\n 'SELECT 1 AS connection_check'\n );\n\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",
6
+ "/** Assert an author or data contract while preserving a useful failure message. */\nexport function invariant(\n condition: unknown,\n message: string\n): asserts condition {\n if (!condition) throw new Error(`Invariant failed: ${message}`);\n}\n",
7
+ "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'; 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> = Omit<\n AppVariable<DimensionSelection<T>, 'dimension'>,\n 'options'\n> & {\n label: string;\n selection: 'single' | 'multiple';\n valueType: 'string' | 'number';\n allowMissing: 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 selection: 'single' | 'multiple';\n allowMissing?: 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, selection, 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 = config.maxSelected ?? (selection === 'single' ? 1 : 20);\n invariant(\n Number.isInteger(maxSelected) &&\n maxSelected >= 1 &&\n maxSelected <= 50 &&\n (selection !== '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 !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 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 tokens = JSON.parse(raw);\n if (!Array.isArray(tokens)) return defaultValue;\n const value = {\n kind: 'include' as const,\n members: tokens.map(token =>\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 selection,\n options,\n facet: config.facet,\n allowMissing,\n maxSelected,\n urlKeys: [key],\n defaultValue,\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.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 return `(${clauses.join(' OR ')})`;\n}\n"
8
+ ],
9
+ "mappings": ";;;;;AAKA;;;ACJO,SAAS,SAAS,CACvB,WACA,SACmB;AAAA,EACnB,IAAI,CAAC;AAAA,IAAW,MAAM,IAAI,MAAM,qBAAqB,SAAS;AAAA;;;AC2BhE,IAAM,eAA0C,EAAE,MAAM,MAAM;AAEvD,SAAS,kBAAkB,CAAC,QAAyB;AAAA,EAC1D,OAAO,OAAO,SAAS,YACnB,YACA,SAAS,OAAO,OAAO,SAAS,OAAO;AAAA;AAwBtC,SAAS,gBAA+C,CAC7D,QACsB;AAAA,EACtB,QAAQ,KAAK,OAAO,WAAW,cAAc;AAAA,EAC7C,MAAM,UAAU,OAAO,WAAW,CAAC;AAAA,EACnC,MAAM,aAAa,QAAQ,IAAI,YAC7B,mBAAmB,EAAE,MAAM,SAAS,OAAO,OAAO,MAAM,CAAC,CAC3D;AAAA,EACA,UACE,CAAC,CAAC,OACA,QAAQ,UAAU,OAClB,IAAI,IAAI,UAAU,EAAE,SAAS,QAAQ,QACvC,4DACF;AAAA,EACA,UACE,QAAQ,MACN,YACE,OAAO,OAAO,UAAU,aACxB,CAAC,CAAC,OAAO,MAAM,KAAK,MACnB,OAAO,UAAU,aACf,OAAO,cAAc,OAAO,KAAK,KAAK,OAAO,SAAS,EAC7D,GACA,sEACF;AAAA,EACA,MAAM,UAAU,IAAI,IAAI,UAAU;AAAA,EAClC,MAAM,cAAc,OAAO,gBAAgB,cAAc,WAAW,IAAI;AAAA,EACxE,UACE,OAAO,UAAU,WAAW,KAC1B,eAAe,KACf,eAAe,OACd,cAAc,YAAY,gBAAgB,IAC7C,uCACF;AAAA,EACA,MAAM,eAAe,OAAO,gBAAgB;AAAA,EAC5C,MAAM,eAAe;AAAA,EAErB,SAAS,WAAW,CAAC,QAAqC;AAAA,IACxD,IAAI,OAAO,SAAS;AAAA,MAAW,OAAO;AAAA,IACtC,IAAI,OAAO,SAAS,WAAW,OAAO,OAAO,UAAU;AAAA,MACrD,OAAO;AAAA,IACT,IAAI,CAAC,OAAO;AAAA,MAAO,OAAO,QAAQ,IAAI,mBAAmB,MAAM,CAAC;AAAA,IAEhE,OAAO,OAAO,OAAO,UAAU,WAC3B,OAAO,SAAS,OAAO,KAAK,IAC5B,OAAO,MAAM,UAAU;AAAA;AAAA,EAG7B,SAAS,KAAK,CAAC,OAAuC;AAAA,IACpD,IAAI,CAAC,SAAS,OAAO,UAAU;AAAA,MAAU,OAAO;AAAA,IAChD,IAAI,MAAM,SAAS;AAAA,MAAO,OAAO;AAAA,IACjC,IACE,MAAM,SAAS,aACf,CAAC,MAAM,QAAQ,MAAM,OAAO,KAC5B,CAAC,MAAM,QAAQ,UACf,MAAM,QAAQ,SAAS;AAAA,MAEvB,OAAO;AAAA,IACT,MAAM,MAAM,MAAM,QAAQ,IAAI,kBAAkB;AAAA,IAEhD,OAAO,IAAI,IAAI,GAAG,EAAE,SAAS,IAAI,UAAU,MAAM,QAAQ,MAAM,WAAW;AAAA;AAAA,EAG5E,SAAS,MAAM,CAAC,OAA8B;AAAA,IAC5C,OAAO,MAAM,SAAS,QAClB,OACA,KAAK,UACH,MAAM,QAAQ,IAAI,YAChB,OAAO,SAAS,YAAY,CAAC,GAAG,IAAI,CAAC,KAAK,OAAO,KAAK,CACxD,CACF;AAAA;AAAA,EAGN,SAAS,KAAK,CAAC,KAA2C;AAAA,IACxD,IAAI,QAAQ;AAAA,MAAM,OAAO;AAAA,IACzB,IAAI,IAAI,SAAS;AAAA,MAAM,OAAO;AAAA,IAC9B,IAAI;AAAA,MACF,MAAM,SAAS,KAAK,MAAM,GAAG;AAAA,MAC7B,IAAI,CAAC,MAAM,QAAQ,MAAM;AAAA,QAAG,OAAO;AAAA,MACnC,MAAM,QAAQ;AAAA,QACZ,MAAM;AAAA,QACN,SAAS,OAAO,IAAI,WAClB,MAAM,QAAQ,KAAK,KAAK,MAAM,WAAW,KAAK,MAAM,OAAO,MACvD,EAAE,MAAM,UAAmB,IAC3B,MAAM,QAAQ,KAAK,KAAK,MAAM,WAAW,KAAK,MAAM,OAAO,MACzD,EAAE,MAAM,SAAkB,OAAO,MAAM,GAAQ,IAC/C,EAAE,MAAM,UAAmB,CACnC;AAAA,MACF;AAAA,MAEA,OAAO,MAAM,KAA8B,IACtC,QACD;AAAA,MACJ,MAAM;AAAA,MACN,OAAO;AAAA;AAAA;AAAA,EAIX,OAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO,OAAO;AAAA,IACd;AAAA,IACA;AAAA,IACA,SAAS,CAAC,GAAG;AAAA,IACb;AAAA,IACA,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,IAAI,CAAC,MAAM,OAAO;AAAA,MAChB,OAAO,OAAO,IAAI,MAAM,OAAO,KAAK;AAAA;AAAA,IAEtC,IAAI,CAAC,QAAQ;AAAA,MACX,OAAO,MAAM,OAAO,IAAI,GAAG,CAAC;AAAA;AAAA,IAE9B,KAAK,CAAC,OAAO;AAAA,MACX,OAAO,GAAG,MAAM,OAAO,KAAK,EAAE;AAAA;AAAA,IAEhC,QAAQ,CAAC,OAAO;AAAA,MACd,OAAO,MAAM,SAAS,QAClB,OAAO,MAAM,kBAAkB,MAC/B,MAAM,QACH,IAAI,YACH,OAAO,SAAS,YACZ,YACC,QAAQ,KAAK,YAAU,OAAO,UAAU,OAAO,KAAK,GACjD,SAAS,OAAO,OAAO,KAAK,CACtC,EACC,KAAK,IAAI;AAAA;AAAA,EAEpB;AAAA;AAIK,SAAS,wBAAiD,CAC/D,OACA,QACuB;AAAA,EACvB,UACE,OAAO,MAAM,KAA8B,GAC3C,WAAW,OAAO,kBACpB;AAAA,EAEA,OAAO;AAAA;AAIF,SAAS,kBAA2C,CACzD,OACA,QACsB;AAAA,EACtB,UACE,MAAM,QAAQ,KAAK,KAAK,MAAM,UAAU,KACxC,mCACF;AAAA,EACA,MAAM,UAAgC,CAAC;AAAA,EACvC,MAAM,OAAO,IAAI;AAAA,EACjB,WAAW,QAAQ,OAAO;AAAA,IACxB,UAAU,QAAQ,OAAO,SAAS,UAAU,uBAAuB;AAAA,IACnE,MAAM,SAAS;AAAA,IACf,UACE,OAAO,OAAO,UAAU,OAAO,aAC7B,OAAO,MAAM;AAAA,MACX,MAAM;AAAA,MACN,SAAS,CAAC,EAAE,MAAM,SAAS,OAAO,OAAO,MAAM,CAAC;AAAA,IAClD,CAAC,KACD,OAAO,OAAO,UAAU,YACxB,CAAC,CAAC,OAAO,MAAM,KAAK,KACpB,OAAO,MAAM,UAAU,QACtB,OAAO,UAAU,aACf,OAAO,cAAc,OAAO,KAAK,KAAK,OAAO,SAAS,IAC3D,uBACF;AAAA,IACA,MAAM,KAAK,mBAAmB,EAAE,MAAM,SAAS,OAAO,OAAO,MAAM,CAAC;AAAA,IACpE,UAAU,CAAC,KAAK,IAAI,EAAE,GAAG,yBAAyB;AAAA,IAClD,KAAK,IAAI,EAAE;AAAA,IACX,QAAQ,KAAK,MAAM;AAAA,EACrB;AAAA,EAEA,OAAO;AAAA;AAIF,SAAS,mBAGf,CACC,QACA,WACA,gBACQ;AAAA,EACR,UACE,eAAe,SAAS,MAAM,KAC5B,wDAAwD,KAAK,MAAM,GACrE,2BACF;AAAA,EACA,IAAI,UAAU,SAAS;AAAA,IAAO,OAAO;AAAA,EACrC,UACE,UAAU,QAAQ,SAAS,GAC3B,uCACF;AAAA,EACA,MAAM,SAAS,UAAU,QAAQ,OAC/B,CAAC,WACC,OAAO,SAAS,OACpB;AAAA,EACA,MAAM,UAAU,UAAU,QAAQ,KAAK,YAAU,OAAO,SAAS,SAAS;AAAA,EAC1E,MAAM,WAAW,OAAO,IAAI,GAAG,YAAY;AAAA,IACzC,IAAI,OAAO,UAAU,UAAU;AAAA,MAC7B,UAAU,OAAO,SAAS,KAAK,GAAG,kCAAkC;AAAA,MAEpE,OAAO,OAAO,KAAK;AAAA,IACrB;AAAA,IACA,MAAM,OAAO;AAAA,IACb,SAAS,QAAQ,EAAG,QAAQ,KAAK,QAAQ;AAAA,MACvC,UACE,KAAK,WAAW,KAAK,KAAK,MAAM,KAAK,WAAW,KAAK,MAAM,KAC3D,+CACF;AAAA,IAEF,OAAO,IAAI,KAAK,WAAW,KAAK,IAAI;AAAA,GACrC;AAAA,EACD,MAAM,UAAU;AAAA,IACd,GAAI,SAAS,SAAS,CAAC,GAAG,cAAc,SAAS,KAAK,IAAI,IAAI,IAAI,CAAC;AAAA,IACnE,GAAI,UAAU,CAAC,GAAG,gBAAgB,IAAI,CAAC;AAAA,EACzC;AAAA,EAEA,OAAO,IAAI,QAAQ,KAAK,MAAM;AAAA;;;AFzQzB,SAAS,gBAAe,CAAC,OAAuC;AAAA,EACrE,UACE,OAAO,UAAU,YACf,UAAU,QACV,CAAC,MAAM,QAAQ,KAAK,KACpB,OAAO,KAAK,KAAK,EAAE,WAAW,GAChC,iCACF;AAAA,EAEA,OAAO,CAAC;AAAA;AAGH,SAAS,UAAS,CAAC,OAAsB;AAAA,EAC9C,UAAU,UAAU,MAAM,8BAA8B;AAAA,EAExD,OAAO;AAAA;AAUF,SAAS,kBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,GACiC;AAAA,EACjC,MAAM,QAAQ,UAAU,KAAK;AAAA,EAC7B,MAAM,OAAO,UAAU,GAAG;AAAA,EAC1B,MAAM,QACH,KAAK,OAAO,KAAK,EAAE,QAAQ,IAAI,MAAM,OAAO,KAAK,EAAE,QAAQ,KAC1D,WACF;AAAA,EACF,UAAU,QAAQ,GAAG,uCAAuC;AAAA,EAC5D,MAAM,cAAc,MAAM,SAAS,EAAE,MAAM,EAAE,CAAC;AAAA,EAE9C,OAAO;AAAA,IACL,OAAO,YAAY,SAAS,EAAE,MAAM,OAAO,EAAE,CAAC,EAAE,SAAS;AAAA,IACzD,KAAK,YAAY,SAAS;AAAA,EAC5B;AAAA;AAgBK,SAAS,wBAAuB,CAAC,SAAmC;AAAA,EACzE,UACE,OAAO,UAAU,QAAQ,YAAY,KAAK,QAAQ,eAAe,GACjE,2CACF;AAAA,EACA,IAAI,QAAQ;AAAA,IAAS,UAAU,QAAQ,OAAO;AAAA,EAC9C,IAAI,OAAO,QAAQ,YAAY;AAAA,IAAU,UAAU,QAAQ,OAAO;AAAA,EAClE,MAAM,QAAQ,QAAQ;AAAA,EAEtB,SAAS,MAAM,GAAG;AAAA,IAChB,MAAM,SAAS,MAAM,QAAQ,QAAQ,EAAE,SAAS;AAAA,MAC9C,MAAM,QAAQ,iBAAiB,QAAQ,IAAI;AAAA,IAC7C,CAAC;AAAA,IACD,MAAM,YACJ,OAAO,QAAQ,YAAY,aACvB,QAAQ,QAAQ,IAChB,QAAQ;AAAA,IACd,MAAM,UACJ,aAAa,UAAU,SAAS,EAAE,QAAQ,MAAM,IAAI,IAChD,UAAU,SAAS,EAAE,SAAS,IAC9B,OAAO,SAAS;AAAA,IAEtB,OAAO;AAAA,MACL,SAAS,QAAQ;AAAA,MACjB;AAAA,MACA,cAAc,QAAQ;AAAA,MACtB,UAAU,QAAQ;AAAA,IACpB;AAAA;AAAA,EAGF,SAAS,MAAM,GAAG,OAAO,OAAwC;AAAA,IAC/D,OAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,UAAU,QAAQ;AAAA,IACpB;AAAA;AAAA,EAGF,SAAS,aAAa,CAAC,OAAuB;AAAA,IAC5C,OAAO,GAAG,iBAAgB,KAAK,KAAK,QAAQ;AAAA;AAAA,EAG9C,SAAS,UAAU,CAAC,OAA8C;AAAA,IAChE,MAAM,WAAW,mBAAkB,KAAK;AAAA,IAExC,OAAO,QAAQ,WAAW,SAAS,QAAQ,QAAQ,UAC/C,OACA;AAAA;AAAA,EAGN,SAAS,OAAO,CAAC,OAAgB,UAAU,OAAyB;AAAA,IAClE,MAAM,QAAQ,qBAAoB,OAAO,OAAO,CAAC;AAAA,IACjD,MAAM,WAAW,UAAU,WAAW,KAAK,IAAI;AAAA,IAC/C,UACE,CAAC,WAAW,UACZ,kDACF;AAAA,IAEA,OAAO,EAAE,OAAO,YAAY,SAAS;AAAA;AAAA,EAGvC,SAAS,YAAY,CAAC,OAAkC;AAAA,IACtD,UAAU,SAAS,OAAO,UAAU,UAAU,sBAAsB;AAAA,IACpE,MAAM,QAAQ;AAAA,IACd,MAAM,SAAS,QAAQ,MAAM,OAAO,MAAM,cAAc,IAAI;AAAA,IAC5D,IAAI,MAAM,cAAc,MAAM;AAAA,MAC5B,MAAM,WAAW,qBAAoB,MAAM,YAAY,OAAO,CAAC;AAAA,MAC/D,UACE,SAAS,UAAU,OAAO,YAAY,SACpC,SAAS,QAAQ,OAAO,YAAY,KACtC,sDACF;AAAA,IACF;AAAA,IAEA,OAAO;AAAA;AAAA,EAGT,OAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,KAAK,CAAC,OAAgB;AAAA,MACpB,OAAO,qBAAoB,OAAO,OAAO,CAAC;AAAA;AAAA,IAE5C;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM,EAAE,QAAQ,cAAc;AAAA,EAChC;AAAA;AAMK,SAAS,oBAAmB,CACjC;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,GAEc;AAAA,EAChB,UACE,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,GAC1D,sBACF;AAAA,EACA,QAAQ,OAAO,QAAQ;AAAA,EAEvB,SAAS,GAAG,CAAC,OAAwB;AAAA,IACnC,UACE,OAAO,UAAU,YAAY,sBAAsB,KAAK,KAAK,GAC7D,2BACF;AAAA,IACA,MAAM,YAAY,KAAK,MAAM,GAAG,iBAAiB;AAAA,IACjD,UACE,OAAO,SAAS,SAAS,KACvB,IAAI,KAAK,SAAS,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE,MAAM,OACrD,8BACF;AAAA,IAEA,OAAO;AAAA;AAAA,EAET,MAAM,QAAQ,IAAI,KAAK;AAAA,EACvB,MAAM,OAAO,IAAI,GAAG;AAAA,EACpB,UACE,OAAO,UAAU,YAAY,KAAK,eAAe,GACjD,sCACF;AAAA,EACA,UACE,SAAS,SACN,OAAO,SAAS,WAAa,iBAC7B,YAAY,aAAa,SAAS,IAAI,OAAO,OAC7C,YAAY,aAAa,QAAQ,IAAI,OAAO,IAC/C,gBAAgB,+CAClB;AAAA,EAEA,OAAO,EAAE,OAAwB,IAAmB;AAAA;AAI/C,SAAS,WAAU,CAAC,OAAwB;AAAA,EACjD,MAAM,SACJ,OAAO,UAAU,YAAY,OAAO,UAAU,WAC1C,OAAO,KAAK,IACZ;AAAA,EACN,UACE,OAAO,cAAc,MAAM,KACzB,UAAU,MACT,OAAO,UAAU,YAAY,CAAC,CAAC,MAAM,KAAK,IAC7C,gCACF;AAAA,EAEA,OAAO;AAAA;AAGF,SAAS,WAAU,CAAC,OAAgB,YAAY,KAAa;AAAA,EAClE,UACE,OAAO,UAAU,YAAY,CAAC,CAAC,SAAS,MAAM,UAAU,WACxD,gCACF;AAAA,EAEA,OAAO;AAAA;AAIF,SAAS,cAAa,CAC3B,QACA,iBAC2B;AAAA,EAC3B,MAAM,QAAQ,OAAO,QAAQ,IAAI,YAAU,OAAO,IAAI;AAAA,EACtD,UACE,IAAI,IAAI,KAAK,EAAE,SAAS,MAAM,UAC5B,gBAAgB,MAAM,UAAQ,MAAM,SAAS,IAAI,CAAC,GACpD,uDACF;AAAA,EAEA,OAAO,OAAO,KAAK,IAAI,SAAO;AAAA,IAC5B,UACE,IAAI,WAAW,MAAM,QACrB,uCACF;AAAA,IAEA,OAAO,OAAO,YAAY,MAAM,IAAI,CAAC,MAAM,UAAU,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC;AAAA,GACzE;AAAA;AAGI,SAAS,iBAA4D,CAC1E,OACO;AAAA,EACP,MAAM,SAAS,OAAO,OAAO,KAAK;AAAA,EAClC,UACE,OAAO,MAAM,UAAQ,CAAC,CAAC,KAAK,KAAK,CAAC,KAChC,IAAI,IAAI,MAAM,EAAE,SAAS,OAAO,QAClC,0CACF;AAAA,EAEA,OAAO;AAAA;AAGT,IAAM,mBAAmB,OAAO,IAAI,sCAAsC;AAAA;AAEnE,MAAM,yBAAwB,MAAM;AAAA,EAYvB;AAAA,EAMA;AAAA,GAjBR,oBAAoB;AAAA,EAC9B;AAAA,UAEQ,OAAO,YAAY,CAAC,OAAyB;AAAA,IACnD,OACE,iBAAiB,SAChB,MAA2C,sBAAsB;AAAA;AAAA,EAItE,WAAW,CACO,QAMA,QAChB;AAAA,IACA,MAAM,eAAe,SAAS,SAAS,KAAK,YAAY,KAAK;AAAA,IAR7C;AAAA,IAMA;AAAA,IAGhB,KAAK,OAAO;AAAA;AAEhB;AAQO,SAAS,gBAIf,CACC,WAOuD;AAAA,EACvD,UACE,MAAM,QAAQ,UAAU,MAAM,KAC5B,UAAU,OAAO,SAAS,KAC1B,OAAO,UAAU,UAAU,OAAO,YAAY,KAC9C,UAAU,OAAO,eAAe,KAChC,OAAO,UAAU,UAAU,OAAO,aAAa,KAC/C,UAAU,OAAO,gBAAgB,MAChC,UAAU,OAAO,qBAAqB,aACpC,OAAO,UAAU,UAAU,OAAO,gBAAgB,KACjD,UAAU,OAAO,mBAAmB,IAC1C,8EACF;AAAA,EACA,IAAI,UAAU;AAAA,IAAY,kBAAiB,UAAU,UAAU;AAAA,EAC/D,WAAW,SAAS,UAAU;AAAA,IAAQ,UAAU,MAAM,KAAK;AAAA,EAE3D,OAAO;AAAA,OACF;AAAA,IACH,GAAG,CAAC,SAAS,OAAO;AAAA,MAClB,SAAS,KAAK,CACZ,MACA,WACA,SACsB;AAAA,QACtB,UACE,UAAU,cACR,OAAO,OAAO,UAAU,UAAU,EAAE,SAAS,IAAI,GACnD,uBAAuB,OACzB;AAAA,QAEA,OAAO,QAAQ,UAAU,SAAS,WAAW;AAAA,UAC3C;AAAA,UACA,OAAO,SAAS,SAAS,UAAU,OAAO;AAAA,UAC1C,QAAQ,QAAQ;AAAA,QAClB,CAAC;AAAA;AAAA,MAGH,OAAO,UAAU,IAAI,KAAK,SAAS,MAAM,GAAG,KAAK;AAAA;AAAA,EAErD;AAAA;AAGK,IAAM,wBAAuB,kBAAiB;AAAA,EACnD,YAAY;AACd,CAAC;AAGM,SAAS,gBAAe,GAA+C;AAAA,EAC5E,OAAO,iBAAgB;AAAA,IACrB,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,QAAQ,CAAC,CAAC,CAAC;AAAA,IACX,YAAY;AAAA,IACZ,QAAQ,EAAE,cAAc,GAAG,eAAe,OAAQ,WAAW,KAAK;AAAA,SAC5D,IAAG,GAAG,SAAwB;AAAA,MAClC,MAAM,MACJ,sBAAqB,YACrB,8BACF;AAAA,MAEA,OAAO;AAAA;AAAA,EAEX,CAAC;AAAA;",
10
+ "debugId": "44D567B58A731E4A64756E2164756E21",
11
+ "names": []
12
+ }
@@ -1,6 +1,3 @@
1
- import {
2
- MessageRoutingError2
3
- } from "./contract-3bnrf5pf.js";
4
1
  import {
5
2
  BRIDGE,
6
3
  PARENT_PARAM,
@@ -8,7 +5,10 @@ import {
8
5
  REQUEST_TIMEOUT_MS,
9
6
  isBridgeMessage,
10
7
  validId
11
- } from "./contract-ryyf6dme.js";
8
+ } from "./contract-cxr9t12b.js";
9
+ import {
10
+ MessageRoutingError2
11
+ } from "./contract-tf8c3qpv.js";
12
12
 
13
13
  // src/embed/host.ts
14
14
  function attachDataAppConnection({
@@ -258,4 +258,4 @@ function attachDataAppBridge2(options) {
258
258
 
259
259
  export { attachDataAppBridge2 };
260
260
 
261
- //# debugId=3C364E4A3943864564756E2164756E21
261
+ //# debugId=F23BB728E5A0F78664756E2164756E21