@altertable/data-app 0.59.1 → 0.62.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 (71) hide show
  1. package/AGENTS.md +5 -3
  2. package/CONTRIBUTING.md +16 -4
  3. package/README.md +20 -14
  4. package/dist/chunks/{contract-jksbmt5q.js → contract-3bnrf5pf.js} +27 -5
  5. package/dist/chunks/contract-3bnrf5pf.js.map +10 -0
  6. package/dist/chunks/{contract-tkkc28tg.js → contract-4vrw9zk9.js} +43 -13
  7. package/dist/chunks/contract-4vrw9zk9.js.map +12 -0
  8. package/dist/chunks/{contract-14vxdcrs.js → contract-farfe948.js} +17 -21
  9. package/dist/chunks/contract-farfe948.js.map +10 -0
  10. package/dist/chunks/contract-nt819swq.js.map +1 -1
  11. package/dist/chunks/{contract-tqrf3ykr.js → contract-rrm7s5zp.js} +61 -32
  12. package/dist/chunks/contract-rrm7s5zp.js.map +12 -0
  13. package/dist/chunks/{contract-mb5nfzwg.js → contract-xjv197ck.js} +178 -31
  14. package/dist/chunks/contract-xjv197ck.js.map +13 -0
  15. package/dist/client/index.js +6 -4
  16. package/dist/client/index.js.map +1 -1
  17. package/dist/core/appearance.js +1 -1
  18. package/dist/core/contract.js +5 -3
  19. package/dist/core/contract.js.map +1 -1
  20. package/dist/embed/index.js +42 -8
  21. package/dist/embed/index.js.map +5 -4
  22. package/dist/local.js +191 -79
  23. package/dist/local.js.map +8 -7
  24. package/dist/react/embed/index.js +84 -99
  25. package/dist/react/embed/index.js.map +4 -5
  26. package/dist/react/index.css +156 -6
  27. package/dist/react/index.js +313 -152
  28. package/dist/react/index.js.map +17 -13
  29. package/dist/server.js +172 -76
  30. package/dist/server.js.map +7 -6
  31. package/dist/types/client/iframe.d.ts +14 -0
  32. package/dist/types/client/index.d.ts +19 -13
  33. package/dist/types/core/appearance.d.ts +7 -6
  34. package/dist/types/core/contract.d.ts +3 -3
  35. package/dist/types/core/messages.d.ts +9 -3
  36. package/dist/types/core/operation.d.ts +27 -0
  37. package/dist/types/core/presentation.d.ts +7 -0
  38. package/dist/types/embed/bridge.d.ts +12 -0
  39. package/dist/types/embed/host.d.ts +10 -3
  40. package/dist/types/embed/index.d.ts +7 -4
  41. package/dist/types/embed/{shell.d.ts → source.d.ts} +5 -4
  42. package/dist/types/embed/sql.d.ts +4 -0
  43. package/dist/types/react/embed/bridge.d.ts +19 -10
  44. package/dist/types/react/embed/index.d.ts +0 -2
  45. package/dist/types/react/ui/DataAppSkeleton.d.ts +8 -0
  46. package/dist/types/react/ui/SearchInput.d.ts +1 -1
  47. package/dist/types/react/ui/index.d.ts +2 -0
  48. package/dist/types/react/ui/useAppAppearance.d.ts +3 -0
  49. package/dist/types/react/ui/useDataAppPresentation.d.ts +3 -0
  50. package/dist/types/react/view-controls.d.ts +1 -1
  51. package/dist/{bootstrap.js → worker.js} +161 -29
  52. package/docs/app-authoring.md +24 -4
  53. package/docs/appearance.md +21 -8
  54. package/docs/client.md +40 -3
  55. package/docs/contract.md +9 -7
  56. package/docs/embed.md +114 -19
  57. package/docs/react-embed.md +84 -24
  58. package/docs/react.md +51 -0
  59. package/docs/releasing.md +5 -0
  60. package/docs/server-bun.md +5 -0
  61. package/docs/starter-agent-instructions.md +4 -2
  62. package/docs/worker.md +57 -0
  63. package/package.json +9 -5
  64. package/dist/chunks/contract-14vxdcrs.js.map +0 -10
  65. package/dist/chunks/contract-jksbmt5q.js.map +0 -10
  66. package/dist/chunks/contract-mb5nfzwg.js.map +0 -12
  67. package/dist/chunks/contract-tkkc28tg.js.map +0 -12
  68. package/dist/chunks/contract-tqrf3ykr.js.map +0 -11
  69. package/dist/types/embed/standalone.d.ts +0 -1
  70. package/dist/types/react/embed/shell.d.ts +0 -10
  71. package/docs/bootstrap.md +0 -76
@@ -1,7 +1,11 @@
1
1
  import {
2
2
  MessageRoutingError2,
3
- defineDataQueryRoute2
4
- } from "./contract-jksbmt5q.js";
3
+ defineDataQueryRoute2,
4
+ sqlQueryRoute2
5
+ } from "./contract-3bnrf5pf.js";
6
+ import {
7
+ DataSourceError2
8
+ } from "./contract-nt819swq.js";
5
9
  import {
6
10
  BRIDGE,
7
11
  PARENT_PARAM,
@@ -78,6 +82,11 @@ function createMessageClient2(routes, transport) {
78
82
  }
79
83
 
80
84
  // src/client/iframe.ts
85
+ function rethrowDataMessageError(error) {
86
+ if (error instanceof MessageRoutingError2)
87
+ throw new DataAppError2(error.message, error.code, error.requestId);
88
+ throw error;
89
+ }
81
90
  function createIframeTransport2({
82
91
  parentOrigin,
83
92
  window: frame = window,
@@ -106,20 +115,20 @@ function createIframeTransport2({
106
115
  if (event.origin !== parentOrigin || event.source !== frame.parent || !isBridgeMessage(event.data))
107
116
  return;
108
117
  const message = event.data;
109
- if (message.type === "connect") {
118
+ if (message.type === "bridge:connect") {
110
119
  if (mode === "bundle") {
111
120
  if (!validId(message.token))
112
121
  return;
113
122
  token = message.token;
114
123
  }
115
- send({ type: "ready" });
124
+ send({ type: "bridge:ready" });
116
125
  return;
117
126
  }
118
127
  if (mode === "bundle" && (!token || message.token !== token))
119
128
  return;
120
129
  if (message.documentId !== documentId)
121
130
  return;
122
- if (message.type === "initialize" && validId(message.sessionId)) {
131
+ if (message.type === "bridge:initialize" && validId(message.sessionId)) {
123
132
  if (sessionId && sessionId !== message.sessionId) {
124
133
  for (const entry of pending.values())
125
134
  entry.reject(new DataAppError2("The preview reconnected. Retry the request.", "bridge_reset"));
@@ -131,16 +140,16 @@ function createIframeTransport2({
131
140
  entry.start();
132
141
  receiveState(message.state);
133
142
  if (mode === "url")
134
- send({ type: "runtime.ready" });
143
+ send({ type: "runtime:ready" });
135
144
  return;
136
145
  }
137
146
  if (!sessionId || message.sessionId !== sessionId)
138
147
  return;
139
- if (message.type === "state") {
148
+ if (message.type === "state:update") {
140
149
  receiveState(message.state);
141
150
  return;
142
151
  }
143
- if (message.type === "script.load" && mode === "bundle" && typeof message.javascript === "string") {
152
+ if (message.type === "script:load" && mode === "bundle" && typeof message.javascript === "string") {
144
153
  loadScript?.(message.javascript);
145
154
  return;
146
155
  }
@@ -149,9 +158,9 @@ function createIframeTransport2({
149
158
  const entry = pending.get(message.id);
150
159
  if (!entry)
151
160
  return;
152
- if (message.type === "result" && "response" in message) {
161
+ if (message.type === "bridge:result" && "response" in message) {
153
162
  entry.resolve(message.response);
154
- } else if (message.type === "error" && typeof message.code === "string" && typeof message.message === "string") {
163
+ } else if (message.type === "bridge:error" && typeof message.code === "string" && typeof message.message === "string") {
155
164
  entry.reject(new MessageRoutingError2(message.code, message.message, typeof message.requestId === "string" ? message.requestId : undefined));
156
165
  }
157
166
  }
@@ -173,13 +182,13 @@ function createIframeTransport2({
173
182
  }
174
183
  function abort() {
175
184
  if (sent)
176
- send({ type: "cancel", id });
185
+ send({ type: "bridge:cancel", id });
177
186
  cleanup();
178
187
  reject(signal?.reason);
179
188
  }
180
189
  const timer = setTimeout(() => {
181
190
  if (sent)
182
- send({ type: "cancel", id });
191
+ send({ type: "bridge:cancel", id });
183
192
  cleanup();
184
193
  reject(new DataAppError2(sessionId ? "The data request timed out." : "The preview shell is unavailable. Reload the preview.", sessionId ? "timeout" : "bridge_unavailable"));
185
194
  }, timeoutMs);
@@ -189,7 +198,7 @@ function createIframeTransport2({
189
198
  return;
190
199
  try {
191
200
  send({
192
- type: "request",
201
+ type: "bridge:request",
193
202
  id,
194
203
  route: message.route,
195
204
  payload: message.payload
@@ -214,28 +223,22 @@ function createIframeTransport2({
214
223
  if (sessionId)
215
224
  entry.start();
216
225
  else
217
- send({ type: "ready" });
226
+ send({ type: "bridge:ready" });
218
227
  });
219
228
  }
220
- const messages = createMessageClient2({ "data.query": defineDataQueryRoute2() }, requestMessage);
221
- async function queryData(operation, input, signal) {
222
- try {
223
- return await messages.request("data.query", { operation, input }, { signal });
224
- } catch (error) {
225
- if (error instanceof MessageRoutingError2)
226
- throw new DataAppError2(error.message, error.code, error.requestId);
227
- throw error;
228
- }
229
+ const messages = createMessageClient2({ "data:query": defineDataQueryRoute2(), "data:sql": sqlQueryRoute2 }, requestMessage);
230
+ function queryOperation(operation, input, signal) {
231
+ return messages.request("data:query", { operation, input }, { signal }).catch(rethrowDataMessageError);
229
232
  }
230
233
  function disconnect() {
231
- send({ type: "disconnect" });
234
+ send({ type: "bridge:disconnect" });
232
235
  sessionId = undefined;
233
236
  for (const entry of pending.values())
234
237
  entry.reject(new DataAppError2("The preview has closed.", "bridge_closed"));
235
238
  }
236
239
  function resume(event) {
237
240
  if (event.persisted)
238
- send({ type: "ready" });
241
+ send({ type: "bridge:ready" });
239
242
  }
240
243
  function dispose() {
241
244
  if (disposed)
@@ -250,10 +253,15 @@ function createIframeTransport2({
250
253
  frame.addEventListener("pagehide", disconnect);
251
254
  frame.addEventListener("pageshow", resume);
252
255
  if (mode === "url")
253
- send({ type: "ready" });
256
+ send({ type: "bridge:ready" });
254
257
  return {
255
258
  request: requestMessage,
256
- transport: queryData,
259
+ transport: queryOperation,
260
+ lakehouse: {
261
+ queryAll(statement, { limit, signal }) {
262
+ return messages.request("data:sql", { statement, limit }, { signal }).catch(rethrowDataMessageError);
263
+ }
264
+ },
257
265
  dispose,
258
266
  mode,
259
267
  snapshot() {
@@ -266,10 +274,10 @@ function createIframeTransport2({
266
274
  };
267
275
  },
268
276
  ready() {
269
- send({ type: "runtime.ready" });
277
+ send({ type: "runtime:ready" });
270
278
  },
271
279
  fail() {
272
- send({ type: "runtime.error" });
280
+ send({ type: "runtime:error" });
273
281
  }
274
282
  };
275
283
  }
@@ -370,6 +378,145 @@ function getDataAppTransport2(frame = window) {
370
378
  return frame[installedKey];
371
379
  }
372
380
 
373
- export { DataAppError2, createHttpTransport2, createMessageClient2, createIframeTransport2, localFrameBridge, installDataAppTransport2, getDataAppTransport2 };
381
+ // src/core/operation.ts
382
+ async function executeDataOperation(operation, value, {
383
+ operationName,
384
+ lakehouse,
385
+ signal: requestSignal,
386
+ includeSql,
387
+ requestId
388
+ }) {
389
+ requestSignal.throwIfAborted();
390
+ let input;
391
+ try {
392
+ input = operation.input(value);
393
+ } catch {
394
+ throw new OperationInputError;
395
+ }
396
+ const signal = AbortSignal.any([
397
+ requestSignal,
398
+ AbortSignal.timeout(operation.policy.maxDurationMs)
399
+ ]);
400
+ const execution = createOperationLakehouse(operation, lakehouse, signal, operationName);
401
+ try {
402
+ const output = await runOperation(operation, input, {
403
+ lakehouse: execution.lakehouse,
404
+ signal
405
+ });
406
+ const body = {
407
+ data: operation.output(output),
408
+ requestId,
409
+ queriedAt: new Date().toISOString(),
410
+ queryIds: execution.queryIds,
411
+ ...operation.policy.exposeSql && includeSql ? { queries: execution.queries } : {}
412
+ };
413
+ const serializedBody = JSON.stringify(body);
414
+ const responseBytes = new TextEncoder().encode(serializedBody).byteLength;
415
+ if (responseBytes > (operation.policy.maxResponseBytes ?? 1e6))
416
+ throw new Error("Response exceeds byte limit.");
417
+ return { body, serializedBody };
418
+ } catch (error) {
419
+ if (signal.aborted && !(error instanceof DataSourceError2))
420
+ throw new OperationTimeoutError;
421
+ throw error;
422
+ }
423
+ }
424
+ function createOperationLakehouse(operation, source, signal, operationName) {
425
+ const queryIds = [];
426
+ const queries = [];
427
+ const lakehouse = {
428
+ async queryAll(statement, options) {
429
+ if (!Number.isInteger(options.limit) || options.limit < 1)
430
+ throw new Error("Query needs a positive row limit.");
431
+ if (operation.queryNames && !Object.values(operation.queryNames).includes(options.name ?? ""))
432
+ throw new Error(`Query name is not registered for operation ${operationName}.`);
433
+ const query = {
434
+ name: options.name ?? `Query ${queries.length + 1}`,
435
+ statement
436
+ };
437
+ queries.push(query);
438
+ const limit = Math.min(options.limit, operation.policy.maxQueryRows);
439
+ let result;
440
+ try {
441
+ result = await source.queryAll(statement, {
442
+ limit,
443
+ signal: AbortSignal.any([signal, options.signal])
444
+ });
445
+ } catch (error) {
446
+ if (error instanceof DataSourceError2)
447
+ error.queryName = query.name;
448
+ throw error;
449
+ }
450
+ if (result.rows.length > limit)
451
+ throw new Error("Result exceeds row limit.");
452
+ if (result.queryId) {
453
+ query.queryId = result.queryId;
454
+ queryIds.push(result.queryId);
455
+ }
456
+ return result;
457
+ }
458
+ };
459
+ return { lakehouse, queries, queryIds };
460
+ }
461
+ async function runOperation(operation, input, { lakehouse, signal }) {
462
+ let abort;
463
+ try {
464
+ signal.throwIfAborted();
465
+ const cancelled = new Promise((_, reject) => {
466
+ function rejectAborted() {
467
+ reject(new Error("Request aborted."));
468
+ }
469
+ abort = rejectAborted;
470
+ signal.addEventListener("abort", rejectAborted, { once: true });
471
+ if (signal.aborted)
472
+ rejectAborted();
473
+ });
474
+ return await Promise.race([
475
+ cancelled,
476
+ Promise.resolve().then(() => {
477
+ signal.throwIfAborted();
478
+ return operation.run({ lakehouse, signal }, input);
479
+ })
480
+ ]);
481
+ } finally {
482
+ if (abort)
483
+ signal.removeEventListener("abort", abort);
484
+ }
485
+ }
486
+
487
+ class OperationTimeoutError extends Error {
488
+ }
489
+
490
+ class OperationInputError extends Error {
491
+ }
492
+ var sourceErrorMessages = {
493
+ unauthorized: "This app could not authenticate its data connection. Contact the app owner.",
494
+ forbidden: "This app cannot access the requested data. Contact the app owner.",
495
+ rate_limited: "The lakehouse is busy. Wait a moment and retry.",
496
+ query_rejected: "A lakehouse query was rejected. Check the app's data operation.",
497
+ unavailable: "The lakehouse is unavailable. Check the connection and retry."
498
+ };
499
+ function toDataOperationFailure(error, aborted = false) {
500
+ if (error instanceof OperationInputError)
501
+ return {
502
+ status: 400,
503
+ code: "invalid_input",
504
+ message: "Check this operation's inputs."
505
+ };
506
+ if (error instanceof DataSourceError2)
507
+ return {
508
+ status: error.reason === "rate_limited" ? 429 : 502,
509
+ code: `source_${error.reason}`,
510
+ message: sourceErrorMessages[error.reason]
511
+ };
512
+ const timedOut = aborted || error instanceof OperationTimeoutError;
513
+ return {
514
+ status: timedOut ? 504 : 502,
515
+ code: timedOut ? "timeout" : "query_failed",
516
+ message: timedOut ? "The data request timed out." : "The data request failed."
517
+ };
518
+ }
519
+
520
+ export { DataAppError2, createHttpTransport2, createMessageClient2, createIframeTransport2, localFrameBridge, installDataAppTransport2, getDataAppTransport2, executeDataOperation, toDataOperationFailure };
374
521
 
375
- //# debugId=CBF217D545192BD464756E2164756E21
522
+ //# debugId=A5D6917EB066FFF364756E2164756E21
@@ -0,0 +1,13 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/client/transport.ts", "../src/client/messages.ts", "../src/client/iframe.ts", "../src/core/operation.ts"],
4
+ "sourcesContent": [
5
+ "import type { TransportResponse } from '@/src/core/bridge';\n\nexport type DataTransport = (\n operation: string,\n input: unknown,\n signal?: AbortSignal\n) => Promise<TransportResponse>;\n\n// A bootstrap and its app may bundle independent copies in the same window.\nconst errorBrand = Symbol.for('@altertable/data-app/DataAppError');\n\nexport class DataAppError 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 message: string,\n public readonly code: string,\n public readonly requestId?: string\n ) {\n super(message);\n this.name = 'DataAppError';\n }\n}\n\nexport function createHttpTransport({\n endpoint = '/api/data',\n fetch: request = globalThis.fetch,\n}: {\n endpoint?: string;\n fetch?: typeof fetch;\n} = {}): DataTransport {\n async function requestData(\n operation: string,\n input: unknown,\n signal?: AbortSignal\n ): Promise<TransportResponse> {\n const response = await request(\n `${endpoint.replace(/\\/$/, '')}/${encodeURIComponent(operation)}`,\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(input),\n signal,\n }\n );\n try {\n return { status: response.status, body: await response.json() };\n } catch (error) {\n if (signal?.aborted) throw error;\n throw new DataAppError(\n response.ok ? 'The data response was invalid.' : 'Could not load data.',\n response.ok ? 'invalid_response' : 'request_failed'\n );\n }\n }\n\n return requestData;\n}\n",
6
+ "import {\n MessageRoutingError,\n type MessageInput,\n type MessageOutput,\n type MessageRoutes,\n type MessageTransport,\n} from '@/src/core/messages';\n\n/** Both ends validate using the same contracts; the transport owns delivery and cancellation. */\nexport function createMessageClient<const Routes extends MessageRoutes>(\n routes: Routes,\n transport: MessageTransport\n) {\n return {\n async request<\n Name extends keyof Routes & string,\n const Input extends MessageInput<NoInfer<Routes[Name]>>,\n >(\n route: Name,\n payload: Input,\n { signal }: { signal?: AbortSignal } = {}\n ): Promise<MessageOutput<Routes[Name], Input>> {\n signal?.throwIfAborted();\n if (!Object.hasOwn(routes, route))\n throw new MessageRoutingError(\n 'unknown_route',\n 'Unknown message route.'\n );\n const contract = routes[route]!;\n let input: unknown;\n try {\n input = contract.input(payload);\n } catch {\n throw new MessageRoutingError(\n 'invalid_payload',\n 'Invalid message payload.'\n );\n }\n const response = await transport({ route, payload: input }, signal);\n signal?.throwIfAborted();\n try {\n return contract.output(response, input as never) as MessageOutput<\n Routes[Name],\n Input\n >;\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}\n",
7
+ "import {\n BRIDGE,\n PARENT_PARAM,\n MAX_PENDING,\n REQUEST_TIMEOUT_MS,\n isBridgeMessage,\n validId,\n type BridgeMessage,\n type TransportResponse,\n} from '@/src/core/bridge';\nimport {\n defineDataQueryRoute,\n sqlQueryRoute,\n MessageRoutingError,\n type RoutedMessage,\n} from '@/src/core/messages';\nimport type { Lakehouse } from '@/src/core/contract';\nimport { createMessageClient } from '@/src/client/messages';\nimport { DataAppError } from '@/src/client/transport';\n\ntype Pending = {\n start: () => void;\n reject: (error: unknown) => void;\n resolve: (value: unknown) => void;\n};\n\n/** Data clients expose one error type for HTTP and message delivery. */\nfunction rethrowDataMessageError(error: unknown): never {\n if (error instanceof MessageRoutingError)\n throw new DataAppError(error.message, error.code, error.requestId);\n throw error;\n}\n\n/** One bridge per document, shared by all clients and retained across module hot replacement. */\nexport function createIframeTransport({\n parentOrigin,\n window: frame = window,\n timeoutMs = REQUEST_TIMEOUT_MS,\n mode = 'url',\n loadScript,\n}: {\n parentOrigin: string;\n window?: Window;\n timeoutMs?: number;\n mode?: 'url' | 'bundle';\n loadScript?: (javascript: string) => void;\n}) {\n if (new URL(parentOrigin).origin !== parentOrigin)\n throw new Error('Expected an exact parent origin.');\n const documentId = crypto.randomUUID();\n let token: string | undefined;\n let sessionId: string | undefined;\n let disposed = false;\n const pending = new Map<string, Pending>();\n let hostState: unknown;\n const stateListeners = new Set<(state: unknown) => void>();\n\n function send(message: Partial<BridgeMessage>) {\n frame.parent.postMessage(\n { channel: BRIDGE, version: 1, documentId, sessionId, token, ...message },\n parentOrigin\n );\n }\n\n function receiveState(state: unknown) {\n hostState = state;\n for (const listener of stateListeners) listener(state);\n }\n\n function receive(event: MessageEvent) {\n if (\n event.origin !== parentOrigin ||\n event.source !== frame.parent ||\n !isBridgeMessage(event.data)\n )\n return;\n const message = event.data;\n if (message.type === 'bridge:connect') {\n if (mode === 'bundle') {\n if (!validId(message.token)) return;\n token = message.token;\n }\n send({ type: 'bridge:ready' });\n\n return;\n }\n if (mode === 'bundle' && (!token || message.token !== token)) return;\n if (message.documentId !== documentId) return;\n if (message.type === 'bridge:initialize' && validId(message.sessionId)) {\n if (sessionId && sessionId !== message.sessionId) {\n for (const entry of pending.values())\n entry.reject(\n new DataAppError(\n 'The preview reconnected. Retry the request.',\n 'bridge_reset'\n )\n );\n }\n const first = !sessionId;\n sessionId = message.sessionId;\n if (first) for (const entry of pending.values()) entry.start();\n receiveState(message.state);\n if (mode === 'url') send({ type: 'runtime:ready' });\n\n return;\n }\n if (!sessionId || message.sessionId !== sessionId) return;\n if (message.type === 'state:update') {\n receiveState(message.state);\n\n return;\n }\n if (\n message.type === 'script:load' &&\n mode === 'bundle' &&\n typeof message.javascript === 'string'\n ) {\n loadScript?.(message.javascript);\n\n return;\n }\n if (typeof message.id !== 'string') return;\n const entry = pending.get(message.id);\n if (!entry) return;\n if (message.type === 'bridge:result' && 'response' in message) {\n entry.resolve(message.response);\n } else if (\n message.type === 'bridge:error' &&\n typeof message.code === 'string' &&\n typeof message.message === 'string'\n ) {\n entry.reject(\n new MessageRoutingError(\n message.code,\n message.message,\n typeof message.requestId === 'string' ? message.requestId : undefined\n )\n );\n }\n }\n\n frame.addEventListener('message', receive);\n\n function requestMessage(\n message: RoutedMessage,\n signal?: AbortSignal\n ): Promise<unknown> {\n return new Promise((resolve, reject) => {\n if (disposed)\n return reject(\n new DataAppError('The preview has closed.', 'bridge_closed')\n );\n if (signal?.aborted) return reject(signal.reason);\n if (pending.size >= MAX_PENDING)\n return reject(\n new DataAppError('Too many pending data requests.', 'bridge_busy')\n );\n const id = crypto.randomUUID();\n let sent = false;\n\n function cleanup() {\n clearTimeout(timer);\n signal?.removeEventListener('abort', abort);\n pending.delete(id);\n }\n\n function abort() {\n if (sent) send({ type: 'bridge:cancel', id });\n cleanup();\n reject(signal?.reason);\n }\n\n const timer = setTimeout(() => {\n if (sent) send({ type: 'bridge:cancel', id });\n cleanup();\n reject(\n new DataAppError(\n sessionId\n ? 'The data request timed out.'\n : 'The preview shell is unavailable. Reload the preview.',\n sessionId ? 'timeout' : 'bridge_unavailable'\n )\n );\n }, timeoutMs);\n const entry: Pending = {\n start() {\n if (sent) return;\n try {\n send({\n type: 'bridge:request',\n id,\n route: message.route,\n payload: message.payload,\n });\n sent = true;\n } catch {\n cleanup();\n reject(\n new DataAppError(\n 'The message payload could not be sent.',\n 'invalid_payload'\n )\n );\n }\n },\n resolve(value) {\n cleanup();\n resolve(value);\n },\n reject(error) {\n cleanup();\n reject(error);\n },\n };\n pending.set(id, entry);\n signal?.addEventListener('abort', abort, { once: true });\n if (sessionId) entry.start();\n else send({ type: 'bridge:ready' });\n });\n }\n\n const messages = createMessageClient(\n { 'data:query': defineDataQueryRoute(), 'data:sql': sqlQueryRoute },\n requestMessage\n );\n\n function queryOperation(\n operation: string,\n input: unknown,\n signal?: AbortSignal\n ): Promise<TransportResponse> {\n return messages\n .request('data:query', { operation, input }, { signal })\n .catch(rethrowDataMessageError);\n }\n\n function disconnect() {\n send({ type: 'bridge:disconnect' });\n sessionId = undefined;\n for (const entry of pending.values())\n entry.reject(\n new DataAppError('The preview has closed.', 'bridge_closed')\n );\n }\n\n function resume(event: PageTransitionEvent) {\n if (event.persisted) send({ type: 'bridge:ready' });\n }\n\n function dispose() {\n if (disposed) return;\n disconnect();\n disposed = true;\n frame.removeEventListener('message', receive);\n frame.removeEventListener('pagehide', disconnect);\n frame.removeEventListener('pageshow', resume);\n stateListeners.clear();\n }\n\n frame.addEventListener('pagehide', disconnect);\n frame.addEventListener('pageshow', resume);\n if (mode === 'url') send({ type: 'bridge:ready' });\n\n return {\n request: requestMessage,\n transport: queryOperation,\n lakehouse: {\n queryAll(statement, { limit, signal }) {\n return messages\n .request('data:sql', { statement, limit }, { signal })\n .catch(rethrowDataMessageError);\n },\n } satisfies Lakehouse,\n dispose,\n mode,\n snapshot() {\n return hostState;\n },\n subscribe(listener: (state: unknown) => void) {\n stateListeners.add(listener);\n\n return () => {\n stateListeners.delete(listener);\n };\n },\n ready() {\n send({ type: 'runtime:ready' });\n },\n fail() {\n send({ type: 'runtime:error' });\n },\n };\n}\n\nexport type IframeTransport = ReturnType<typeof createIframeTransport>;\n\nconst bridgeKey = Symbol.for('altertable.localFrameBridge');\nconst installedKey = Symbol.for('altertable.installedTransport');\ntype LocalBridge = Pick<\n ReturnType<typeof createIframeTransport>,\n 'transport'\n> & { connect?: () => Promise<ReturnType<typeof createIframeTransport>> };\ntype FrameWindow = Window & {\n [bridgeKey]?: LocalBridge;\n [installedKey]?: ReturnType<typeof createIframeTransport>;\n};\n\n/** The URL opts into local preview; only same-origin server configuration establishes trust. */\nexport function localFrameBridge(window?: Window): LocalBridge | undefined {\n const activeWindow =\n window ??\n (typeof globalThis.window === 'undefined' ? undefined : globalThis.window);\n if (!activeWindow) return undefined;\n const frame = activeWindow as FrameWindow;\n if (frame[bridgeKey]) return frame[bridgeKey];\n const parentOrigin =\n new URL(frame.location.href).searchParams.get(PARENT_PARAM) ?? '';\n if (!parentOrigin) return undefined;\n\n async function connect(parentOrigin: string) {\n try {\n const response = await frame.fetch('/__altertable/parent', {\n signal: AbortSignal.timeout(5000),\n });\n const config = (await response.json()) as { origin?: unknown };\n if (\n !response.ok ||\n config.origin !== parentOrigin ||\n frame.parent === frame\n )\n throw new Error('Invalid local parent configuration.');\n // Another owner can install a trusted bridge while configuration is pending.\n if (frame[installedKey]) return frame[installedKey];\n if (frame[bridgeKey] !== proxy)\n throw new Error('Preview transport owner changed.');\n const bridge = createIframeTransport({ parentOrigin, window: frame });\n frame[bridgeKey] = bridge;\n frame[installedKey] = bridge;\n\n return bridge;\n } catch {\n throw new DataAppError(\n 'The preview shell could not be verified. Open the URL printed by altertable app dev.',\n 'bridge_unavailable'\n );\n }\n }\n\n let connection: Promise<ReturnType<typeof createIframeTransport>> | undefined;\n\n function getConnection() {\n const installed = frame[installedKey];\n if (installed) return Promise.resolve(installed);\n if (!connection) {\n const attempt = connect(parentOrigin);\n connection = attempt;\n // Clear only this failed attempt; retained proxy references can explicitly retry.\n void attempt.catch(() => {\n if (connection === attempt) connection = undefined;\n });\n }\n\n return connection;\n }\n\n const proxy: LocalBridge = {\n async transport(operation, input, signal) {\n signal?.throwIfAborted();\n const attempt = getConnection();\n let abort: (() => void) | undefined;\n try {\n const bridge = signal\n ? await Promise.race([\n attempt,\n new Promise<never>((_, reject) => {\n const requestSignal = signal;\n\n function handleAbort() {\n reject(requestSignal.reason);\n }\n\n abort = handleAbort;\n requestSignal.addEventListener('abort', handleAbort, {\n once: true,\n });\n }),\n ])\n : await attempt;\n signal?.throwIfAborted();\n\n return bridge.transport(operation, input, signal);\n } finally {\n if (abort) signal?.removeEventListener('abort', abort);\n }\n },\n connect: getConnection,\n };\n frame[bridgeKey] = proxy;\n // Static mounting still verifies eagerly, without an unhandled rejection.\n void getConnection().catch(() => {});\n\n return proxy;\n}\n\n/** Install an explicitly trusted transport for hosted apps and their URL-backed controls. */\nexport function installDataAppTransport(\n bridge: ReturnType<typeof createIframeTransport>,\n frame: Window = window\n) {\n const target = frame as FrameWindow;\n if (target[installedKey])\n throw new Error('A data app transport is already installed.');\n target[bridgeKey] = bridge;\n target[installedKey] = bridge;\n\n return () => {\n if (target[bridgeKey] === bridge) delete target[bridgeKey];\n if (target[installedKey] === bridge) delete target[installedKey];\n bridge.dispose();\n };\n}\n\n/** The bootstrap installs this before executing app code. URL apps can install an explicit connection. */\nexport function getDataAppTransport(frame: Window = window) {\n return (frame as FrameWindow)[installedKey];\n}\n",
8
+ "import {\n DataSourceError,\n type DataOperations,\n type DisclosedQuery,\n type Lakehouse,\n type OperationContext,\n} from '@/src/core/contract';\n\ntype Operation = DataOperations[string];\ntype OperationExecutionOptions = {\n operationName: string;\n lakehouse: Lakehouse;\n signal: AbortSignal;\n /** Include query evidence in the response; this does not keep browser-owned SQL private. */\n includeSql: boolean;\n requestId: string;\n};\n\n/** Shared operation execution. Adapters own authorization, delivery, and public errors. */\nexport async function executeDataOperation(\n operation: Operation,\n value: unknown,\n {\n operationName,\n lakehouse,\n signal: requestSignal,\n includeSql,\n requestId,\n }: OperationExecutionOptions\n) {\n requestSignal.throwIfAborted();\n let input: unknown;\n try {\n input = operation.input(value);\n } catch {\n throw new OperationInputError();\n }\n\n const signal = AbortSignal.any([\n requestSignal,\n AbortSignal.timeout(operation.policy.maxDurationMs),\n ]);\n const execution = createOperationLakehouse(\n operation,\n lakehouse,\n signal,\n operationName\n );\n try {\n const output = await runOperation(operation, input, {\n lakehouse: execution.lakehouse,\n signal,\n });\n const body = {\n data: operation.output(output),\n requestId,\n queriedAt: new Date().toISOString(),\n queryIds: execution.queryIds,\n ...(operation.policy.exposeSql && includeSql\n ? { queries: execution.queries }\n : {}),\n };\n const serializedBody = JSON.stringify(body);\n const responseBytes = new TextEncoder().encode(serializedBody).byteLength;\n if (responseBytes > (operation.policy.maxResponseBytes ?? 1_000_000))\n throw new Error('Response exceeds byte limit.');\n\n return { body, serializedBody };\n } catch (error) {\n if (signal.aborted && !(error instanceof DataSourceError))\n throw new OperationTimeoutError();\n throw error;\n }\n}\n\n/** Query evidence follows statement invocation order; query IDs retain completion order. */\nfunction createOperationLakehouse(\n operation: Operation,\n source: Lakehouse,\n signal: AbortSignal,\n operationName: string\n) {\n const queryIds: string[] = [];\n const queries: DisclosedQuery[] = [];\n const lakehouse: Lakehouse = {\n async queryAll(statement, options) {\n if (!Number.isInteger(options.limit) || options.limit < 1)\n throw new Error('Query needs a positive row limit.');\n if (\n operation.queryNames &&\n !Object.values(operation.queryNames).includes(options.name ?? '')\n )\n throw new Error(\n `Query name is not registered for operation ${operationName}.`\n );\n const query: DisclosedQuery = {\n name: options.name ?? `Query ${queries.length + 1}`,\n statement,\n };\n queries.push(query);\n const limit = Math.min(options.limit, operation.policy.maxQueryRows);\n let result;\n try {\n result = await source.queryAll(statement, {\n limit,\n signal: AbortSignal.any([signal, options.signal]),\n });\n } catch (error) {\n if (error instanceof DataSourceError) error.queryName = query.name;\n throw error;\n }\n if (result.rows.length > limit)\n throw new Error('Result exceeds row limit.');\n if (result.queryId) {\n query.queryId = result.queryId;\n queryIds.push(result.queryId);\n }\n\n return result;\n },\n };\n\n return { lakehouse, queries, queryIds };\n}\n\n/** Settle cancellation even when operation code or its lakehouse ignores the signal. */\nasync function runOperation(\n operation: Operation,\n input: unknown,\n { lakehouse, signal }: OperationContext\n) {\n let abort: (() => void) | undefined;\n try {\n signal.throwIfAborted();\n const cancelled = new Promise<never>((_, reject) => {\n function rejectAborted() {\n reject(new Error('Request aborted.'));\n }\n abort = rejectAborted;\n signal.addEventListener('abort', rejectAborted, { once: true });\n if (signal.aborted) rejectAborted();\n });\n\n return await Promise.race([\n cancelled,\n Promise.resolve().then(() => {\n signal.throwIfAborted();\n\n return operation.run({ lakehouse, signal }, input as never);\n }),\n ]);\n } finally {\n if (abort) signal.removeEventListener('abort', abort);\n }\n}\n\nclass OperationTimeoutError extends Error {}\n\nclass OperationInputError extends Error {}\n\nconst sourceErrorMessages = {\n unauthorized:\n 'This app could not authenticate its data connection. Contact the app owner.',\n forbidden:\n 'This app cannot access the requested data. Contact the app owner.',\n rate_limited: 'The lakehouse is busy. Wait a moment and retry.',\n query_rejected:\n \"A lakehouse query was rejected. Check the app's data operation.\",\n unavailable: 'The lakehouse is unavailable. Check the connection and retry.',\n};\n\nexport function toDataOperationFailure(error: unknown, aborted = false) {\n if (error instanceof OperationInputError)\n return {\n status: 400,\n code: 'invalid_input',\n message: \"Check this operation's inputs.\",\n };\n if (error instanceof DataSourceError)\n return {\n status: error.reason === 'rate_limited' ? 429 : 502,\n code: `source_${error.reason}`,\n message: sourceErrorMessages[error.reason],\n };\n const timedOut = aborted || error instanceof OperationTimeoutError;\n return {\n status: timedOut ? 504 : 502,\n code: timedOut ? 'timeout' : 'query_failed',\n message: timedOut\n ? 'The data request timed out.'\n : 'The data request failed.',\n };\n}\n"
9
+ ],
10
+ "mappings": ";;;;;;;;;;;;;;;;;;AASA,IAAM,aAAa,OAAO,IAAI,mCAAmC;AAAA;AAE1D,MAAM,sBAAqB,MAAM;AAAA,EAYpB;AAAA,EACA;AAAA,GAZR,cAAc;AAAA,UAEhB,OAAO,YAAY,CAAC,OAAyB;AAAA,IACnD,OACE,iBAAiB,SAChB,MAAqC,gBAAgB;AAAA;AAAA,EAI1D,WAAW,CACT,SACgB,MACA,WAChB;AAAA,IACA,MAAM,OAAO;AAAA,IAHG;AAAA,IACA;AAAA,IAGhB,KAAK,OAAO;AAAA;AAEhB;AAEO,SAAS,oBAAmB;AAAA,EACjC,WAAW;AAAA,EACX,OAAO,UAAU,WAAW;AAAA,IAI1B,CAAC,GAAkB;AAAA,EACrB,eAAe,WAAW,CACxB,WACA,OACA,QAC4B;AAAA,IAC5B,MAAM,WAAW,MAAM,QACrB,GAAG,SAAS,QAAQ,OAAO,EAAE,KAAK,mBAAmB,SAAS,KAC9D;AAAA,MACE,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,KAAK;AAAA,MAC1B;AAAA,IACF,CACF;AAAA,IACA,IAAI;AAAA,MACF,OAAO,EAAE,QAAQ,SAAS,QAAQ,MAAM,MAAM,SAAS,KAAK,EAAE;AAAA,MAC9D,OAAO,OAAO;AAAA,MACd,IAAI,QAAQ;AAAA,QAAS,MAAM;AAAA,MAC3B,MAAM,IAAI,cACR,SAAS,KAAK,mCAAmC,wBACjD,SAAS,KAAK,qBAAqB,gBACrC;AAAA;AAAA;AAAA,EAIJ,OAAO;AAAA;;;ACtDF,SAAS,oBAAuD,CACrE,QACA,WACA;AAAA,EACA,OAAO;AAAA,SACC,QAGL,CACC,OACA,WACE,WAAqC,CAAC,GACK;AAAA,MAC7C,QAAQ,eAAe;AAAA,MACvB,IAAI,CAAC,OAAO,OAAO,QAAQ,KAAK;AAAA,QAC9B,MAAM,IAAI,qBACR,iBACA,wBACF;AAAA,MACF,MAAM,WAAW,OAAO;AAAA,MACxB,IAAI;AAAA,MACJ,IAAI;AAAA,QACF,QAAQ,SAAS,MAAM,OAAO;AAAA,QAC9B,MAAM;AAAA,QACN,MAAM,IAAI,qBACR,mBACA,0BACF;AAAA;AAAA,MAEF,MAAM,WAAW,MAAM,UAAU,EAAE,OAAO,SAAS,MAAM,GAAG,MAAM;AAAA,MAClE,QAAQ,eAAe;AAAA,MACvB,IAAI;AAAA,QACF,OAAO,SAAS,OAAO,UAAU,KAAc;AAAA,QAI/C,OAAO,OAAO;AAAA,QACd,IAAI,iBAAiB;AAAA,UAAqB,MAAM;AAAA,QAChD,MAAM,IAAI,qBACR,oBACA,2BACF;AAAA;AAAA;AAAA,EAGN;AAAA;;;AC1BF,SAAS,uBAAuB,CAAC,OAAuB;AAAA,EACtD,IAAI,iBAAiB;AAAA,IACnB,MAAM,IAAI,cAAa,MAAM,SAAS,MAAM,MAAM,MAAM,SAAS;AAAA,EACnE,MAAM;AAAA;AAID,SAAS,sBAAqB;AAAA,EACnC;AAAA,EACA,QAAQ,QAAQ;AAAA,EAChB,YAAY;AAAA,EACZ,OAAO;AAAA,EACP;AAAA,GAOC;AAAA,EACD,IAAI,IAAI,IAAI,YAAY,EAAE,WAAW;AAAA,IACnC,MAAM,IAAI,MAAM,kCAAkC;AAAA,EACpD,MAAM,aAAa,OAAO,WAAW;AAAA,EACrC,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI,WAAW;AAAA,EACf,MAAM,UAAU,IAAI;AAAA,EACpB,IAAI;AAAA,EACJ,MAAM,iBAAiB,IAAI;AAAA,EAE3B,SAAS,IAAI,CAAC,SAAiC;AAAA,IAC7C,MAAM,OAAO,YACX,EAAE,SAAS,QAAQ,SAAS,GAAG,YAAY,WAAW,UAAU,QAAQ,GACxE,YACF;AAAA;AAAA,EAGF,SAAS,YAAY,CAAC,OAAgB;AAAA,IACpC,YAAY;AAAA,IACZ,WAAW,YAAY;AAAA,MAAgB,SAAS,KAAK;AAAA;AAAA,EAGvD,SAAS,OAAO,CAAC,OAAqB;AAAA,IACpC,IACE,MAAM,WAAW,gBACjB,MAAM,WAAW,MAAM,UACvB,CAAC,gBAAgB,MAAM,IAAI;AAAA,MAE3B;AAAA,IACF,MAAM,UAAU,MAAM;AAAA,IACtB,IAAI,QAAQ,SAAS,kBAAkB;AAAA,MACrC,IAAI,SAAS,UAAU;AAAA,QACrB,IAAI,CAAC,QAAQ,QAAQ,KAAK;AAAA,UAAG;AAAA,QAC7B,QAAQ,QAAQ;AAAA,MAClB;AAAA,MACA,KAAK,EAAE,MAAM,eAAe,CAAC;AAAA,MAE7B;AAAA,IACF;AAAA,IACA,IAAI,SAAS,aAAa,CAAC,SAAS,QAAQ,UAAU;AAAA,MAAQ;AAAA,IAC9D,IAAI,QAAQ,eAAe;AAAA,MAAY;AAAA,IACvC,IAAI,QAAQ,SAAS,uBAAuB,QAAQ,QAAQ,SAAS,GAAG;AAAA,MACtE,IAAI,aAAa,cAAc,QAAQ,WAAW;AAAA,QAChD,WAAW,SAAS,QAAQ,OAAO;AAAA,UACjC,MAAM,OACJ,IAAI,cACF,+CACA,cACF,CACF;AAAA,MACJ;AAAA,MACA,MAAM,QAAQ,CAAC;AAAA,MACf,YAAY,QAAQ;AAAA,MACpB,IAAI;AAAA,QAAO,WAAW,SAAS,QAAQ,OAAO;AAAA,UAAG,MAAM,MAAM;AAAA,MAC7D,aAAa,QAAQ,KAAK;AAAA,MAC1B,IAAI,SAAS;AAAA,QAAO,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAAA,MAElD;AAAA,IACF;AAAA,IACA,IAAI,CAAC,aAAa,QAAQ,cAAc;AAAA,MAAW;AAAA,IACnD,IAAI,QAAQ,SAAS,gBAAgB;AAAA,MACnC,aAAa,QAAQ,KAAK;AAAA,MAE1B;AAAA,IACF;AAAA,IACA,IACE,QAAQ,SAAS,iBACjB,SAAS,YACT,OAAO,QAAQ,eAAe,UAC9B;AAAA,MACA,aAAa,QAAQ,UAAU;AAAA,MAE/B;AAAA,IACF;AAAA,IACA,IAAI,OAAO,QAAQ,OAAO;AAAA,MAAU;AAAA,IACpC,MAAM,QAAQ,QAAQ,IAAI,QAAQ,EAAE;AAAA,IACpC,IAAI,CAAC;AAAA,MAAO;AAAA,IACZ,IAAI,QAAQ,SAAS,mBAAmB,cAAc,SAAS;AAAA,MAC7D,MAAM,QAAQ,QAAQ,QAAQ;AAAA,IAChC,EAAO,SACL,QAAQ,SAAS,kBACjB,OAAO,QAAQ,SAAS,YACxB,OAAO,QAAQ,YAAY,UAC3B;AAAA,MACA,MAAM,OACJ,IAAI,qBACF,QAAQ,MACR,QAAQ,SACR,OAAO,QAAQ,cAAc,WAAW,QAAQ,YAAY,SAC9D,CACF;AAAA,IACF;AAAA;AAAA,EAGF,MAAM,iBAAiB,WAAW,OAAO;AAAA,EAEzC,SAAS,cAAc,CACrB,SACA,QACkB;AAAA,IAClB,OAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AAAA,MACtC,IAAI;AAAA,QACF,OAAO,OACL,IAAI,cAAa,2BAA2B,eAAe,CAC7D;AAAA,MACF,IAAI,QAAQ;AAAA,QAAS,OAAO,OAAO,OAAO,MAAM;AAAA,MAChD,IAAI,QAAQ,QAAQ;AAAA,QAClB,OAAO,OACL,IAAI,cAAa,mCAAmC,aAAa,CACnE;AAAA,MACF,MAAM,KAAK,OAAO,WAAW;AAAA,MAC7B,IAAI,OAAO;AAAA,MAEX,SAAS,OAAO,GAAG;AAAA,QACjB,aAAa,KAAK;AAAA,QAClB,QAAQ,oBAAoB,SAAS,KAAK;AAAA,QAC1C,QAAQ,OAAO,EAAE;AAAA;AAAA,MAGnB,SAAS,KAAK,GAAG;AAAA,QACf,IAAI;AAAA,UAAM,KAAK,EAAE,MAAM,iBAAiB,GAAG,CAAC;AAAA,QAC5C,QAAQ;AAAA,QACR,OAAO,QAAQ,MAAM;AAAA;AAAA,MAGvB,MAAM,QAAQ,WAAW,MAAM;AAAA,QAC7B,IAAI;AAAA,UAAM,KAAK,EAAE,MAAM,iBAAiB,GAAG,CAAC;AAAA,QAC5C,QAAQ;AAAA,QACR,OACE,IAAI,cACF,YACI,gCACA,yDACJ,YAAY,YAAY,oBAC1B,CACF;AAAA,SACC,SAAS;AAAA,MACZ,MAAM,QAAiB;AAAA,QACrB,KAAK,GAAG;AAAA,UACN,IAAI;AAAA,YAAM;AAAA,UACV,IAAI;AAAA,YACF,KAAK;AAAA,cACH,MAAM;AAAA,cACN;AAAA,cACA,OAAO,QAAQ;AAAA,cACf,SAAS,QAAQ;AAAA,YACnB,CAAC;AAAA,YACD,OAAO;AAAA,YACP,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,OACE,IAAI,cACF,0CACA,iBACF,CACF;AAAA;AAAA;AAAA,QAGJ,OAAO,CAAC,OAAO;AAAA,UACb,QAAQ;AAAA,UACR,QAAQ,KAAK;AAAA;AAAA,QAEf,MAAM,CAAC,OAAO;AAAA,UACZ,QAAQ;AAAA,UACR,OAAO,KAAK;AAAA;AAAA,MAEhB;AAAA,MACA,QAAQ,IAAI,IAAI,KAAK;AAAA,MACrB,QAAQ,iBAAiB,SAAS,OAAO,EAAE,MAAM,KAAK,CAAC;AAAA,MACvD,IAAI;AAAA,QAAW,MAAM,MAAM;AAAA,MACtB;AAAA,aAAK,EAAE,MAAM,eAAe,CAAC;AAAA,KACnC;AAAA;AAAA,EAGH,MAAM,WAAW,qBACf,EAAE,cAAc,sBAAqB,GAAG,YAAY,eAAc,GAClE,cACF;AAAA,EAEA,SAAS,cAAc,CACrB,WACA,OACA,QAC4B;AAAA,IAC5B,OAAO,SACJ,QAAQ,cAAc,EAAE,WAAW,MAAM,GAAG,EAAE,OAAO,CAAC,EACtD,MAAM,uBAAuB;AAAA;AAAA,EAGlC,SAAS,UAAU,GAAG;AAAA,IACpB,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAAA,IAClC,YAAY;AAAA,IACZ,WAAW,SAAS,QAAQ,OAAO;AAAA,MACjC,MAAM,OACJ,IAAI,cAAa,2BAA2B,eAAe,CAC7D;AAAA;AAAA,EAGJ,SAAS,MAAM,CAAC,OAA4B;AAAA,IAC1C,IAAI,MAAM;AAAA,MAAW,KAAK,EAAE,MAAM,eAAe,CAAC;AAAA;AAAA,EAGpD,SAAS,OAAO,GAAG;AAAA,IACjB,IAAI;AAAA,MAAU;AAAA,IACd,WAAW;AAAA,IACX,WAAW;AAAA,IACX,MAAM,oBAAoB,WAAW,OAAO;AAAA,IAC5C,MAAM,oBAAoB,YAAY,UAAU;AAAA,IAChD,MAAM,oBAAoB,YAAY,MAAM;AAAA,IAC5C,eAAe,MAAM;AAAA;AAAA,EAGvB,MAAM,iBAAiB,YAAY,UAAU;AAAA,EAC7C,MAAM,iBAAiB,YAAY,MAAM;AAAA,EACzC,IAAI,SAAS;AAAA,IAAO,KAAK,EAAE,MAAM,eAAe,CAAC;AAAA,EAEjD,OAAO;AAAA,IACL,SAAS;AAAA,IACT,WAAW;AAAA,IACX,WAAW;AAAA,MACT,QAAQ,CAAC,aAAa,OAAO,UAAU;AAAA,QACrC,OAAO,SACJ,QAAQ,YAAY,EAAE,WAAW,MAAM,GAAG,EAAE,OAAO,CAAC,EACpD,MAAM,uBAAuB;AAAA;AAAA,IAEpC;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,GAAG;AAAA,MACT,OAAO;AAAA;AAAA,IAET,SAAS,CAAC,UAAoC;AAAA,MAC5C,eAAe,IAAI,QAAQ;AAAA,MAE3B,OAAO,MAAM;AAAA,QACX,eAAe,OAAO,QAAQ;AAAA;AAAA;AAAA,IAGlC,KAAK,GAAG;AAAA,MACN,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAAA;AAAA,IAEhC,IAAI,GAAG;AAAA,MACL,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAAA;AAAA,EAElC;AAAA;AAKF,IAAM,YAAY,OAAO,IAAI,6BAA6B;AAC1D,IAAM,eAAe,OAAO,IAAI,+BAA+B;AAWxD,SAAS,gBAAgB,CAAC,SAA0C;AAAA,EACzE,MAAM,eACJ,YACC,OAAO,WAAW,WAAW,cAAc,YAAY,WAAW;AAAA,EACrE,IAAI,CAAC;AAAA,IAAc;AAAA,EACnB,MAAM,QAAQ;AAAA,EACd,IAAI,MAAM;AAAA,IAAY,OAAO,MAAM;AAAA,EACnC,MAAM,eACJ,IAAI,IAAI,MAAM,SAAS,IAAI,EAAE,aAAa,IAAI,YAAY,KAAK;AAAA,EACjE,IAAI,CAAC;AAAA,IAAc;AAAA,EAEnB,eAAe,OAAO,CAAC,cAAsB;AAAA,IAC3C,IAAI;AAAA,MACF,MAAM,WAAW,MAAM,MAAM,MAAM,wBAAwB;AAAA,QACzD,QAAQ,YAAY,QAAQ,IAAI;AAAA,MAClC,CAAC;AAAA,MACD,MAAM,SAAU,MAAM,SAAS,KAAK;AAAA,MACpC,IACE,CAAC,SAAS,MACV,OAAO,WAAW,gBAClB,MAAM,WAAW;AAAA,QAEjB,MAAM,IAAI,MAAM,qCAAqC;AAAA,MAEvD,IAAI,MAAM;AAAA,QAAe,OAAO,MAAM;AAAA,MACtC,IAAI,MAAM,eAAe;AAAA,QACvB,MAAM,IAAI,MAAM,kCAAkC;AAAA,MACpD,MAAM,SAAS,uBAAsB,EAAE,cAAc,QAAQ,MAAM,CAAC;AAAA,MACpE,MAAM,aAAa;AAAA,MACnB,MAAM,gBAAgB;AAAA,MAEtB,OAAO;AAAA,MACP,MAAM;AAAA,MACN,MAAM,IAAI,cACR,wFACA,oBACF;AAAA;AAAA;AAAA,EAIJ,IAAI;AAAA,EAEJ,SAAS,aAAa,GAAG;AAAA,IACvB,MAAM,YAAY,MAAM;AAAA,IACxB,IAAI;AAAA,MAAW,OAAO,QAAQ,QAAQ,SAAS;AAAA,IAC/C,IAAI,CAAC,YAAY;AAAA,MACf,MAAM,UAAU,QAAQ,YAAY;AAAA,MACpC,aAAa;AAAA,MAER,QAAQ,MAAM,MAAM;AAAA,QACvB,IAAI,eAAe;AAAA,UAAS,aAAa;AAAA,OAC1C;AAAA,IACH;AAAA,IAEA,OAAO;AAAA;AAAA,EAGT,MAAM,QAAqB;AAAA,SACnB,UAAS,CAAC,WAAW,OAAO,QAAQ;AAAA,MACxC,QAAQ,eAAe;AAAA,MACvB,MAAM,UAAU,cAAc;AAAA,MAC9B,IAAI;AAAA,MACJ,IAAI;AAAA,QACF,MAAM,SAAS,SACX,MAAM,QAAQ,KAAK;AAAA,UACjB;AAAA,UACA,IAAI,QAAe,CAAC,GAAG,WAAW;AAAA,YAChC,MAAM,gBAAgB;AAAA,YAEtB,SAAS,WAAW,GAAG;AAAA,cACrB,OAAO,cAAc,MAAM;AAAA;AAAA,YAG7B,QAAQ;AAAA,YACR,cAAc,iBAAiB,SAAS,aAAa;AAAA,cACnD,MAAM;AAAA,YACR,CAAC;AAAA,WACF;AAAA,QACH,CAAC,IACD,MAAM;AAAA,QACV,QAAQ,eAAe;AAAA,QAEvB,OAAO,OAAO,UAAU,WAAW,OAAO,MAAM;AAAA,gBAChD;AAAA,QACA,IAAI;AAAA,UAAO,QAAQ,oBAAoB,SAAS,KAAK;AAAA;AAAA;AAAA,IAGzD,SAAS;AAAA,EACX;AAAA,EACA,MAAM,aAAa;AAAA,EAEd,cAAc,EAAE,MAAM,MAAM,EAAE;AAAA,EAEnC,OAAO;AAAA;AAIF,SAAS,wBAAuB,CACrC,QACA,QAAgB,QAChB;AAAA,EACA,MAAM,SAAS;AAAA,EACf,IAAI,OAAO;AAAA,IACT,MAAM,IAAI,MAAM,4CAA4C;AAAA,EAC9D,OAAO,aAAa;AAAA,EACpB,OAAO,gBAAgB;AAAA,EAEvB,OAAO,MAAM;AAAA,IACX,IAAI,OAAO,eAAe;AAAA,MAAQ,OAAO,OAAO;AAAA,IAChD,IAAI,OAAO,kBAAkB;AAAA,MAAQ,OAAO,OAAO;AAAA,IACnD,OAAO,QAAQ;AAAA;AAAA;AAKZ,SAAS,oBAAmB,CAAC,QAAgB,QAAQ;AAAA,EAC1D,OAAQ,MAAsB;AAAA;;;ACrZhC,eAAsB,oBAAoB,CACxC,WACA;AAAA,EAEE;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,GAEF;AAAA,EACA,cAAc,eAAe;AAAA,EAC7B,IAAI;AAAA,EACJ,IAAI;AAAA,IACF,QAAQ,UAAU,MAAM,KAAK;AAAA,IAC7B,MAAM;AAAA,IACN,MAAM,IAAI;AAAA;AAAA,EAGZ,MAAM,SAAS,YAAY,IAAI;AAAA,IAC7B;AAAA,IACA,YAAY,QAAQ,UAAU,OAAO,aAAa;AAAA,EACpD,CAAC;AAAA,EACD,MAAM,YAAY,yBAChB,WACA,WACA,QACA,aACF;AAAA,EACA,IAAI;AAAA,IACF,MAAM,SAAS,MAAM,aAAa,WAAW,OAAO;AAAA,MAClD,WAAW,UAAU;AAAA,MACrB;AAAA,IACF,CAAC;AAAA,IACD,MAAM,OAAO;AAAA,MACX,MAAM,UAAU,OAAO,MAAM;AAAA,MAC7B;AAAA,MACA,WAAW,IAAI,KAAK,EAAE,YAAY;AAAA,MAClC,UAAU,UAAU;AAAA,SAChB,UAAU,OAAO,aAAa,aAC9B,EAAE,SAAS,UAAU,QAAQ,IAC7B,CAAC;AAAA,IACP;AAAA,IACA,MAAM,iBAAiB,KAAK,UAAU,IAAI;AAAA,IAC1C,MAAM,gBAAgB,IAAI,YAAY,EAAE,OAAO,cAAc,EAAE;AAAA,IAC/D,IAAI,iBAAiB,UAAU,OAAO,oBAAoB;AAAA,MACxD,MAAM,IAAI,MAAM,8BAA8B;AAAA,IAEhD,OAAO,EAAE,MAAM,eAAe;AAAA,IAC9B,OAAO,OAAO;AAAA,IACd,IAAI,OAAO,WAAW,EAAE,iBAAiB;AAAA,MACvC,MAAM,IAAI;AAAA,IACZ,MAAM;AAAA;AAAA;AAKV,SAAS,wBAAwB,CAC/B,WACA,QACA,QACA,eACA;AAAA,EACA,MAAM,WAAqB,CAAC;AAAA,EAC5B,MAAM,UAA4B,CAAC;AAAA,EACnC,MAAM,YAAuB;AAAA,SACrB,SAAQ,CAAC,WAAW,SAAS;AAAA,MACjC,IAAI,CAAC,OAAO,UAAU,QAAQ,KAAK,KAAK,QAAQ,QAAQ;AAAA,QACtD,MAAM,IAAI,MAAM,mCAAmC;AAAA,MACrD,IACE,UAAU,cACV,CAAC,OAAO,OAAO,UAAU,UAAU,EAAE,SAAS,QAAQ,QAAQ,EAAE;AAAA,QAEhE,MAAM,IAAI,MACR,8CAA8C,gBAChD;AAAA,MACF,MAAM,QAAwB;AAAA,QAC5B,MAAM,QAAQ,QAAQ,SAAS,QAAQ,SAAS;AAAA,QAChD;AAAA,MACF;AAAA,MACA,QAAQ,KAAK,KAAK;AAAA,MAClB,MAAM,QAAQ,KAAK,IAAI,QAAQ,OAAO,UAAU,OAAO,YAAY;AAAA,MACnE,IAAI;AAAA,MACJ,IAAI;AAAA,QACF,SAAS,MAAM,OAAO,SAAS,WAAW;AAAA,UACxC;AAAA,UACA,QAAQ,YAAY,IAAI,CAAC,QAAQ,QAAQ,MAAM,CAAC;AAAA,QAClD,CAAC;AAAA,QACD,OAAO,OAAO;AAAA,QACd,IAAI,iBAAiB;AAAA,UAAiB,MAAM,YAAY,MAAM;AAAA,QAC9D,MAAM;AAAA;AAAA,MAER,IAAI,OAAO,KAAK,SAAS;AAAA,QACvB,MAAM,IAAI,MAAM,2BAA2B;AAAA,MAC7C,IAAI,OAAO,SAAS;AAAA,QAClB,MAAM,UAAU,OAAO;AAAA,QACvB,SAAS,KAAK,OAAO,OAAO;AAAA,MAC9B;AAAA,MAEA,OAAO;AAAA;AAAA,EAEX;AAAA,EAEA,OAAO,EAAE,WAAW,SAAS,SAAS;AAAA;AAIxC,eAAe,YAAY,CACzB,WACA,SACE,WAAW,UACb;AAAA,EACA,IAAI;AAAA,EACJ,IAAI;AAAA,IACF,OAAO,eAAe;AAAA,IACtB,MAAM,YAAY,IAAI,QAAe,CAAC,GAAG,WAAW;AAAA,MAClD,SAAS,aAAa,GAAG;AAAA,QACvB,OAAO,IAAI,MAAM,kBAAkB,CAAC;AAAA;AAAA,MAEtC,QAAQ;AAAA,MACR,OAAO,iBAAiB,SAAS,eAAe,EAAE,MAAM,KAAK,CAAC;AAAA,MAC9D,IAAI,OAAO;AAAA,QAAS,cAAc;AAAA,KACnC;AAAA,IAED,OAAO,MAAM,QAAQ,KAAK;AAAA,MACxB;AAAA,MACA,QAAQ,QAAQ,EAAE,KAAK,MAAM;AAAA,QAC3B,OAAO,eAAe;AAAA,QAEtB,OAAO,UAAU,IAAI,EAAE,WAAW,OAAO,GAAG,KAAc;AAAA,OAC3D;AAAA,IACH,CAAC;AAAA,YACD;AAAA,IACA,IAAI;AAAA,MAAO,OAAO,oBAAoB,SAAS,KAAK;AAAA;AAAA;AAAA;AAIxD,MAAM,8BAA8B,MAAM;AAAC;AAAA;AAE3C,MAAM,4BAA4B,MAAM;AAAC;AAEzC,IAAM,sBAAsB;AAAA,EAC1B,cACE;AAAA,EACF,WACE;AAAA,EACF,cAAc;AAAA,EACd,gBACE;AAAA,EACF,aAAa;AACf;AAEO,SAAS,sBAAsB,CAAC,OAAgB,UAAU,OAAO;AAAA,EACtE,IAAI,iBAAiB;AAAA,IACnB,OAAO;AAAA,MACL,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,EACF,IAAI,iBAAiB;AAAA,IACnB,OAAO;AAAA,MACL,QAAQ,MAAM,WAAW,iBAAiB,MAAM;AAAA,MAChD,MAAM,UAAU,MAAM;AAAA,MACtB,SAAS,oBAAoB,MAAM;AAAA,IACrC;AAAA,EACF,MAAM,WAAW,WAAW,iBAAiB;AAAA,EAC7C,OAAO;AAAA,IACL,QAAQ,WAAW,MAAM;AAAA,IACzB,MAAM,WAAW,YAAY;AAAA,IAC7B,SAAS,WACL,gCACA;AAAA,EACN;AAAA;",
11
+ "debugId": "A5D6917EB066FFF364756E2164756E21",
12
+ "names": []
13
+ }
@@ -2,7 +2,7 @@ import {
2
2
  createDataAppNavigation2,
3
3
  getDataAppNavigation2,
4
4
  createDataClient2
5
- } from "../chunks/contract-tkkc28tg.js";
5
+ } from "../chunks/contract-4vrw9zk9.js";
6
6
  import {
7
7
  DataAppError2,
8
8
  createHttpTransport2,
@@ -10,8 +10,10 @@ import {
10
10
  createIframeTransport2,
11
11
  installDataAppTransport2,
12
12
  getDataAppTransport2
13
- } from "../chunks/contract-mb5nfzwg.js";
14
- import"../chunks/contract-jksbmt5q.js";
13
+ } from "../chunks/contract-xjv197ck.js";
14
+ import"../chunks/contract-nt819swq.js";
15
+ import"../chunks/contract-mev09s5v.js";
16
+ import"../chunks/contract-3bnrf5pf.js";
15
17
  export {
16
18
  DataAppError2 as DataAppError,
17
19
  createDataAppNavigation2 as createDataAppNavigation,
@@ -24,4 +26,4 @@ export {
24
26
  installDataAppTransport2 as installDataAppTransport
25
27
  };
26
28
 
27
- //# debugId=43A567C4125F87CC64756E2164756E21
29
+ //# debugId=8C4A11AD957CE63364756E2164756E21
@@ -4,6 +4,6 @@
4
4
  "sourcesContent": [
5
5
  ],
6
6
  "mappings": "",
7
- "debugId": "43A567C4125F87CC64756E2164756E21",
7
+ "debugId": "8C4A11AD957CE63364756E2164756E21",
8
8
  "names": []
9
9
  }
@@ -2,7 +2,7 @@ import {
2
2
  parseAppearance2,
3
3
  applyAppearance2,
4
4
  createThemeController2
5
- } from "../chunks/contract-14vxdcrs.js";
5
+ } from "../chunks/contract-farfe948.js";
6
6
  export {
7
7
  applyAppearance2 as applyAppearance,
8
8
  createThemeController2 as createThemeController,
@@ -24,8 +24,9 @@ import {
24
24
  createMessageRouter2,
25
25
  defineDataQueryRoute2,
26
26
  navigationUpdateRoute2,
27
+ sqlQueryRoute2,
27
28
  dataAppRoutes2
28
- } from "../chunks/contract-jksbmt5q.js";
29
+ } from "../chunks/contract-3bnrf5pf.js";
29
30
  export {
30
31
  DataSourceError2 as DataSourceError,
31
32
  MessageRoutingError2 as MessageRoutingError,
@@ -49,7 +50,8 @@ export {
49
50
  parseLabel2 as parseLabel,
50
51
  parseTrue2 as parseTrue,
51
52
  previousDateRange2 as previousDateRange,
52
- rowsAsRecords2 as rowsAsRecords
53
+ rowsAsRecords2 as rowsAsRecords,
54
+ sqlQueryRoute2 as sqlQueryRoute
53
55
  };
54
56
 
55
- //# debugId=2AD65EB8F0F2F7AD64756E2164756E21
57
+ //# debugId=7902CE650ED22CFA64756E2164756E21
@@ -4,6 +4,6 @@
4
4
  "sourcesContent": [
5
5
  ],
6
6
  "mappings": "",
7
- "debugId": "2AD65EB8F0F2F7AD64756E2164756E21",
7
+ "debugId": "7902CE650ED22CFA64756E2164756E21",
8
8
  "names": []
9
9
  }
@@ -1,12 +1,17 @@
1
- import"../chunks/contract-jksbmt5q.js";
1
+ import {
2
+ MessageRoutingError2,
3
+ sqlQueryRoute2
4
+ } from "../chunks/contract-3bnrf5pf.js";
2
5
  import {
3
6
  createIframeTransport2,
4
- installDataAppTransport2
5
- } from "../chunks/contract-mb5nfzwg.js";
7
+ installDataAppTransport2,
8
+ toDataOperationFailure
9
+ } from "../chunks/contract-xjv197ck.js";
10
+ import"../chunks/contract-mev09s5v.js";
11
+ import"../chunks/contract-nt819swq.js";
6
12
  import {
7
- attachDataAppBridge2,
8
- attachDataAppShell2
9
- } from "../chunks/contract-tqrf3ykr.js";
13
+ attachDataAppBridge2
14
+ } from "../chunks/contract-rrm7s5zp.js";
10
15
  import {
11
16
  PARENT_PARAM
12
17
  } from "../chunks/contract-ryyf6dme.js";
@@ -81,11 +86,40 @@ function createNavigationHandler({
81
86
  }
82
87
  return navigate;
83
88
  }
89
+ // src/embed/sql.ts
90
+ function createSqlQueryHandler(authorize) {
91
+ async function handleSqlQuery(input, context) {
92
+ const requestId = crypto.randomUUID();
93
+ context.signal.throwIfAborted();
94
+ let lakehouse;
95
+ try {
96
+ lakehouse = await authorize(input, context);
97
+ } catch {
98
+ context.signal.throwIfAborted();
99
+ throw new MessageRoutingError2("forbidden", "You cannot run this query.", requestId);
100
+ }
101
+ context.signal.throwIfAborted();
102
+ try {
103
+ return await lakehouse.queryAll(input.statement, {
104
+ limit: input.limit,
105
+ signal: context.signal
106
+ });
107
+ } catch (error) {
108
+ context.signal.throwIfAborted();
109
+ if (error instanceof MessageRoutingError2)
110
+ throw error;
111
+ const failure = toDataOperationFailure(error);
112
+ throw new MessageRoutingError2(failure.code, failure.message, requestId);
113
+ }
114
+ }
115
+ return handleSqlQuery;
116
+ }
84
117
  export {
85
118
  attachDataAppBridge2 as attachDataAppBridge,
86
- attachDataAppShell2 as attachDataAppShell,
87
119
  createNavigationHandler,
120
+ createSqlQueryHandler,
121
+ sqlQueryRoute2 as sqlQueryRoute,
88
122
  startDataAppBootstrap
89
123
  };
90
124
 
91
- //# debugId=1E61B2F0590BD55F64756E2164756E21
125
+ //# debugId=10E8E3B80241E0BC64756E2164756E21
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/embed/bootstrap.ts", "../src/embed/navigation.ts"],
3
+ "sources": ["../src/embed/bootstrap.ts", "../src/embed/navigation.ts", "../src/embed/sql.ts"],
4
4
  "sourcesContent": [
5
5
  "import {\n createIframeTransport,\n installDataAppTransport,\n} from '@/src/client/iframe';\n\n/** Run from a trusted bootstrap page in an allow-scripts-only iframe. CSP can prohibit network access. */\nexport function startDataAppBootstrap({\n parentOrigin,\n window: frame = window,\n}: {\n parentOrigin: string;\n window?: Window;\n}) {\n let loaded: string | undefined;\n let failed = false;\n const bridge = createIframeTransport({\n parentOrigin,\n window: frame,\n mode: 'bundle',\n loadScript(javascript) {\n if (loaded !== undefined) {\n if (javascript === loaded) {\n if (failed) bridge.fail();\n else bridge.ready();\n } else bridge.fail();\n\n return;\n }\n loaded = javascript;\n try {\n const script = frame.document.createElement('script');\n script.textContent = javascript;\n frame.document.body.append(script);\n if (!failed) bridge.ready();\n } catch {\n reportError();\n }\n },\n });\n\n function reportError() {\n failed = true;\n bridge.fail();\n }\n\n frame.addEventListener('error', reportError);\n frame.addEventListener('unhandledrejection', reportError);\n const uninstall = installDataAppTransport(bridge, frame);\n\n return () => {\n frame.removeEventListener('error', reportError);\n frame.removeEventListener('unhandledrejection', reportError);\n uninstall();\n };\n}\n",
6
- "import { PARENT_PARAM } from '@/src/core/bridge';\nimport type { NavigationUpdate } from '@/src/core/messages';\n\n/** Override this handler for framework routers. Reserved host parameters survive app navigation. */\nexport function createNavigationHandler({\n window: host = window,\n reservedSearchParams = [],\n}: {\n window?: Window;\n reservedSearchParams?: readonly string[];\n} = {}) {\n function navigate(input: NavigationUpdate): null {\n const previous = new URL(host.location.href);\n const url = new URL(previous);\n url.search = input.search;\n url.searchParams.delete(PARENT_PARAM);\n for (const name of reservedSearchParams) {\n url.searchParams.delete(name);\n for (const value of previous.searchParams.getAll(name))\n url.searchParams.append(name, value);\n }\n url.hash = input.hash;\n if (url.href !== host.location.href)\n host.history[input.mode === 'push' ? 'pushState' : 'replaceState'](\n null,\n '',\n url\n );\n if (input.title !== undefined) host.document.title = input.title;\n\n return null;\n }\n\n return navigate;\n}\n"
6
+ "import { PARENT_PARAM } from '@/src/core/bridge';\nimport type { NavigationUpdate } from '@/src/core/messages';\n\n/** Override this handler for framework routers. Reserved host parameters survive app navigation. */\nexport function createNavigationHandler({\n window: host = window,\n reservedSearchParams = [],\n}: {\n window?: Window;\n reservedSearchParams?: readonly string[];\n} = {}) {\n function navigate(input: NavigationUpdate): null {\n const previous = new URL(host.location.href);\n const url = new URL(previous);\n url.search = input.search;\n url.searchParams.delete(PARENT_PARAM);\n for (const name of reservedSearchParams) {\n url.searchParams.delete(name);\n for (const value of previous.searchParams.getAll(name))\n url.searchParams.append(name, value);\n }\n url.hash = input.hash;\n if (url.href !== host.location.href)\n host.history[input.mode === 'push' ? 'pushState' : 'replaceState'](\n null,\n '',\n url\n );\n if (input.title !== undefined) host.document.title = input.title;\n\n return null;\n }\n\n return navigate;\n}\n",
7
+ "import type { Lakehouse } from '@/src/core/contract';\nimport { toDataOperationFailure } from '@/src/core/operation';\nimport {\n MessageRoutingError,\n type MessageContext,\n type SqlQueryInput,\n} from '@/src/core/messages';\n\n/** Authorize every SQL request and supply a backend that independently enforces access and query limits. */\nexport function createSqlQueryHandler(\n authorize: (\n query: SqlQueryInput,\n context: MessageContext\n ) => Promise<Lakehouse>\n) {\n async function handleSqlQuery(input: SqlQueryInput, context: MessageContext) {\n const requestId = crypto.randomUUID();\n context.signal.throwIfAborted();\n let lakehouse: Lakehouse;\n try {\n lakehouse = await authorize(input, context);\n } catch {\n context.signal.throwIfAborted();\n throw new MessageRoutingError(\n 'forbidden',\n 'You cannot run this query.',\n requestId\n );\n }\n context.signal.throwIfAborted();\n try {\n return await lakehouse.queryAll(input.statement, {\n limit: input.limit,\n signal: context.signal,\n });\n } catch (error) {\n context.signal.throwIfAborted();\n if (error instanceof MessageRoutingError) throw error;\n const failure = toDataOperationFailure(error);\n throw new MessageRoutingError(failure.code, failure.message, requestId);\n }\n }\n\n return handleSqlQuery;\n}\n"
7
8
  ],
8
- "mappings": ";;;;;;;;;;;;;AAMO,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA,QAAQ,QAAQ;AAAA,GAIf;AAAA,EACD,IAAI;AAAA,EACJ,IAAI,SAAS;AAAA,EACb,MAAM,SAAS,uBAAsB;AAAA,IACnC;AAAA,IACA,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,UAAU,CAAC,YAAY;AAAA,MACrB,IAAI,WAAW,WAAW;AAAA,QACxB,IAAI,eAAe,QAAQ;AAAA,UACzB,IAAI;AAAA,YAAQ,OAAO,KAAK;AAAA,UACnB;AAAA,mBAAO,MAAM;AAAA,QACpB,EAAO;AAAA,iBAAO,KAAK;AAAA,QAEnB;AAAA,MACF;AAAA,MACA,SAAS;AAAA,MACT,IAAI;AAAA,QACF,MAAM,SAAS,MAAM,SAAS,cAAc,QAAQ;AAAA,QACpD,OAAO,cAAc;AAAA,QACrB,MAAM,SAAS,KAAK,OAAO,MAAM;AAAA,QACjC,IAAI,CAAC;AAAA,UAAQ,OAAO,MAAM;AAAA,QAC1B,MAAM;AAAA,QACN,YAAY;AAAA;AAAA;AAAA,EAGlB,CAAC;AAAA,EAED,SAAS,WAAW,GAAG;AAAA,IACrB,SAAS;AAAA,IACT,OAAO,KAAK;AAAA;AAAA,EAGd,MAAM,iBAAiB,SAAS,WAAW;AAAA,EAC3C,MAAM,iBAAiB,sBAAsB,WAAW;AAAA,EACxD,MAAM,YAAY,yBAAwB,QAAQ,KAAK;AAAA,EAEvD,OAAO,MAAM;AAAA,IACX,MAAM,oBAAoB,SAAS,WAAW;AAAA,IAC9C,MAAM,oBAAoB,sBAAsB,WAAW;AAAA,IAC3D,UAAU;AAAA;AAAA;;AChDP,SAAS,uBAAuB;AAAA,EACrC,QAAQ,OAAO;AAAA,EACf,uBAAuB,CAAC;AAAA,IAItB,CAAC,GAAG;AAAA,EACN,SAAS,QAAQ,CAAC,OAA+B;AAAA,IAC/C,MAAM,WAAW,IAAI,IAAI,KAAK,SAAS,IAAI;AAAA,IAC3C,MAAM,MAAM,IAAI,IAAI,QAAQ;AAAA,IAC5B,IAAI,SAAS,MAAM;AAAA,IACnB,IAAI,aAAa,OAAO,YAAY;AAAA,IACpC,WAAW,QAAQ,sBAAsB;AAAA,MACvC,IAAI,aAAa,OAAO,IAAI;AAAA,MAC5B,WAAW,SAAS,SAAS,aAAa,OAAO,IAAI;AAAA,QACnD,IAAI,aAAa,OAAO,MAAM,KAAK;AAAA,IACvC;AAAA,IACA,IAAI,OAAO,MAAM;AAAA,IACjB,IAAI,IAAI,SAAS,KAAK,SAAS;AAAA,MAC7B,KAAK,QAAQ,MAAM,SAAS,SAAS,cAAc,gBACjD,MACA,IACA,GACF;AAAA,IACF,IAAI,MAAM,UAAU;AAAA,MAAW,KAAK,SAAS,QAAQ,MAAM;AAAA,IAE3D,OAAO;AAAA;AAAA,EAGT,OAAO;AAAA;",
9
- "debugId": "1E61B2F0590BD55F64756E2164756E21",
9
+ "mappings": "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",
10
+ "debugId": "10E8E3B80241E0BC64756E2164756E21",
10
11
  "names": []
11
12
  }