@oxy-hq/sdk 2.8.0 → 2.10.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.
@@ -64,6 +64,25 @@ interface OxyAppFunctionManifest {
64
64
  email?: {
65
65
  send?: boolean;
66
66
  };
67
+ /**
68
+ * Capability for `ctx.oltp` — read/write the app's OWN per-org OLTP schema on
69
+ * the managed Postgres tenant (fail-closed: omit → every `ctx.oltp` call
70
+ * rejected). A pure GATE: the target schema is derived from the app's own slug
71
+ * host-side (`oltp-bookings` → `app_oltp_bookings`), never named here, so a
72
+ * manifest cannot point `ctx.oltp` at another app's schema. The resolved role
73
+ * has DML rights on that one schema and nothing else — reaching neither another
74
+ * app's data nor the analyst-visible `raw_*` schemas. The store must be
75
+ * provisioned first (ask whoever operates the org).
76
+ *
77
+ * NOTE: this shape is `{ enabled }`, not the earlier `{ writer }` — an app
78
+ * had no business naming its own writer (that was the cross-app hole). A
79
+ * manifest still carrying `"oltp": { "writer": "…" }` deserializes to
80
+ * `enabled: undefined` → **disabled**, and `ctx.oltp` then reports the
81
+ * capability as missing. Switch it to `{ "enabled": true }`.
82
+ */
83
+ oltp?: {
84
+ enabled?: boolean;
85
+ };
67
86
  /**
68
87
  * Retry policy for **background** runs (a `schedule` fire or a manual job
69
88
  * trigger). Omit → a job run is attempted once. Route (HTTP) invocations are
@@ -130,6 +149,93 @@ interface OxyAppManifest {
130
149
  agent?: string;
131
150
  suggestedQuestions?: string[];
132
151
  };
152
+ /**
153
+ * Optional app-level storage policy. Distinct from the per-function
154
+ * `storage: { read, write }` capability: those gate what one function may
155
+ * call, while this governs the app's whole asset silo, which every function
156
+ * shares.
157
+ */
158
+ storage?: OxyAppStorageManifest;
159
+ /**
160
+ * Browser-runtime performance opt-outs. Both features below are **on by
161
+ * default** — an app that says nothing gets them — so this block exists only
162
+ * to turn one off.
163
+ *
164
+ * Read by the platform at **publish time** (like {@link OxyAppStorageManifest})
165
+ * rather than by this loader, so the field is documented here but not
166
+ * round-tripped through the dev-time manifest fetch.
167
+ */
168
+ performance?: OxyAppPerformanceManifest;
169
+ /**
170
+ * Opt out of the platform's automatic, zero-config usage instrumentation:
171
+ * SPA pageviews, Core Web Vitals, engagement time, and uncaught-error counts,
172
+ * posted to `<base>/__oxy/beacon` by the runtime Oxy injects into every served
173
+ * page. `false` silences the **client** runtime only — the server still
174
+ * records one view row per HTML navigation (that floor is not opt-out-able),
175
+ * so the Activity tab never goes dark, it just loses the in-page detail.
176
+ *
177
+ * Distinct from `useTrackEvent` (your own named events): those are additive and
178
+ * always on. This governs only the events the platform sends on your behalf.
179
+ *
180
+ * Honored at publish time (see {@link performance} for why it is not
181
+ * round-tripped here). Default: `true`.
182
+ */
183
+ analytics?: boolean;
184
+ }
185
+ /** Browser-runtime performance opt-outs — the `performance` block in `oxy-app.json`. */
186
+ interface OxyAppPerformanceManifest {
187
+ /**
188
+ * Opt out of the platform service worker Oxy registers at `<base>/__oxy/sw.js`.
189
+ * It precaches your build's entry assets and serves content-hashed files
190
+ * cache-first, so a repeat load of a published app is near-instant.
191
+ *
192
+ * Set `false` only if your app ships its own service worker (two workers
193
+ * cannot both control the same scope) or genuinely must never be cached.
194
+ * There is nothing to configure to opt *in* — a normal build is precached
195
+ * automatically, and a bundle that inlines everything into one HTML file
196
+ * simply has nothing to precache, which is fine. Default: `true`.
197
+ */
198
+ serviceWorker?: boolean;
199
+ }
200
+ /** How long assets under a given prefix are kept. */
201
+ interface OxyAppRetentionRule {
202
+ /**
203
+ * Key prefix inside your silo, as you write it — `"tmp/"`, `"generated/"`.
204
+ * The `customer-app-storage/<app_id>/` part is implicit.
205
+ */
206
+ prefix: string;
207
+ /**
208
+ * One of the five supported classes. `null` (or omitted) pins the prefix to
209
+ * "keep forever", which is how you protect it from a broader sibling rule.
210
+ *
211
+ * The set is closed on purpose — each class is one bucket-wide S3 lifecycle
212
+ * rule, so an arbitrary duration can't be honoured. An unrecognized value is
213
+ * ignored with a warning and the prefix simply doesn't expire.
214
+ */
215
+ expireAfter?: "1d" | "7d" | "30d" | "90d" | "365d" | null;
216
+ }
217
+ /** App-level `storage` block in `oxy-app.json`. */
218
+ interface OxyAppStorageManifest {
219
+ /**
220
+ * Retention rules for the asset silo. **Longest matching prefix wins**; a key
221
+ * matching no rule is kept forever.
222
+ *
223
+ * Expiry is enforced by S3 lifecycle rules on an object tag, so it is
224
+ * approximate (evaluated daily, not on the hour) and applies from the time an
225
+ * object was written. Editing a rule does not retag assets already stored —
226
+ * new writes pick up the new class.
227
+ *
228
+ * ```jsonc
229
+ * "storage": {
230
+ * "retention": [
231
+ * { "prefix": "tmp/", "expireAfter": "1d" },
232
+ * { "prefix": "generated/", "expireAfter": "90d" },
233
+ * { "prefix": "uploads/", "expireAfter": null } // keep forever
234
+ * ]
235
+ * }
236
+ * ```
237
+ */
238
+ retention?: OxyAppRetentionRule[];
133
239
  }
134
240
  /**
135
241
  * Manifest + runtime-injected identity needed to call oxy. Callers
@@ -223,6 +329,27 @@ interface FunctionLog {
223
329
  level: string;
224
330
  message: string;
225
331
  }
332
+ /** A successful function result plus the logs captured during the run. */
333
+ interface FunctionResult<Data> {
334
+ value: Data;
335
+ logs: FunctionLog[];
336
+ }
337
+ /**
338
+ * An error carries the logs captured before the throw, so the app can show them.
339
+ *
340
+ * `status` is the HTTP status the FUNCTION returned, present when the function
341
+ * ran and answered a non-2xx. It is absent when the run itself failed (an
342
+ * `event: error` frame — a crash, a timeout, a cancellation), because there was
343
+ * no response to have a status.
344
+ *
345
+ * `body` is the parsed payload the function returned with that status, so a
346
+ * caller can read `{ error: "…" }` without re-parsing the message.
347
+ */
348
+ type FunctionError = Error & {
349
+ logs?: FunctionLog[];
350
+ status?: number;
351
+ body?: unknown;
352
+ };
226
353
  //#endregion
227
354
  //#region src/custom-app/react.d.ts
228
355
  /**
@@ -422,7 +549,7 @@ interface UseSemanticQueryResult<Row = Record<string, unknown>> {
422
549
  refetch: () => void;
423
550
  }
424
551
  /**
425
- * Run a semantic-layer query against the project's `.view.yml` /
552
+ * Run a semantic-model query against the project's `.view.yml` /
426
553
  * `.topic.yml` definitions. The server compiles to SQL and executes
427
554
  * through the same connector path as `useQuery`, so result shape
428
555
  * matches.
@@ -657,5 +784,5 @@ interface OxyChatProps {
657
784
  */
658
785
  declare function OxyChat(props: OxyChatProps): React.JSX.Element;
659
786
  //#endregion
660
- export { UseSemanticQueryOpts as A, CustomAppErrorReport as B, UseProcedureRunInput as C, UseQueryOpts as D, UseQueryInput as E, useProcedureRun as F, OxyAppFunctionManifest as G, apiErrorFromResponse as H, useQuery as I, _resetCustomAppManifestCacheForTest as J, OxyAppManifest as K, useResolvedManifest as L, useAgentRun as M, useFunction as N, UseQueryResult as O, useOxyApp as P, useSemanticQuery as R, UseFunctionResult as S, UseProcedureRunResult as T, interpretCustomAppError as U, OxyApiError as V, LoadManifestOptions as W, loadCustomAppManifest as Y, SemanticFilter as _, AppFetcher as a, UseAgentRunInput as b, OxyAppProvider as c, OxyChatProps as d, ProcedureProgress as f, SemanticDateRangeOp as g, SemanticArrayOp as h, AgentSqlArtifact as i, UseSemanticQueryResult as j, UseSemanticQueryInput as k, OxyAppProviderProps as l, ProcedureRunState as m, AgentRunEvent as n, OxyAnswer as o, ProcedureResult as p, ResolvedCustomAppManifest as q, AgentRunState as r, OxyAnswerProps as s, AgentArtifact as t, OxyChat as u, SemanticScalarOp as v, UseProcedureRunOpts as w, UseAgentRunResult as x, SemanticTimeDimension as y, useTrackEvent as z };
661
- //# sourceMappingURL=react-kHG5gkd-.d.mts.map
787
+ export { loadCustomAppManifest as $, UseSemanticQueryOpts as A, FunctionError as B, UseProcedureRunInput as C, UseQueryOpts as D, UseQueryInput as E, useProcedureRun as F, apiErrorFromResponse as G, FunctionResult as H, useQuery as I, OxyAppFunctionManifest as J, interpretCustomAppError as K, useResolvedManifest as L, useAgentRun as M, useFunction as N, UseQueryResult as O, useOxyApp as P, _resetCustomAppManifestCacheForTest as Q, useSemanticQuery as R, UseFunctionResult as S, UseProcedureRunResult as T, CustomAppErrorReport as U, FunctionLog as V, OxyApiError as W, OxyAppPerformanceManifest as X, OxyAppManifest as Y, ResolvedCustomAppManifest as Z, SemanticFilter as _, AppFetcher as a, UseAgentRunInput as b, OxyAppProvider as c, OxyChatProps as d, ProcedureProgress as f, SemanticDateRangeOp as g, SemanticArrayOp as h, AgentSqlArtifact as i, UseSemanticQueryResult as j, UseSemanticQueryInput as k, OxyAppProviderProps as l, ProcedureRunState as m, AgentRunEvent as n, OxyAnswer as o, ProcedureResult as p, LoadManifestOptions as q, AgentRunState as r, OxyAnswerProps as s, AgentArtifact as t, OxyChat as u, SemanticScalarOp as v, UseProcedureRunOpts as w, UseAgentRunResult as x, SemanticTimeDimension as y, useTrackEvent as z };
788
+ //# sourceMappingURL=react-BGUzRMxq.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-BGUzRMxq.d.cts","names":[],"sources":["../src/custom-app/manifest.ts","../src/custom-app/errors.ts","../src/custom-app/function-sse.ts","../src/custom-app/react.tsx"],"mappings":"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"}
@@ -64,6 +64,25 @@ interface OxyAppFunctionManifest {
64
64
  email?: {
65
65
  send?: boolean;
66
66
  };
67
+ /**
68
+ * Capability for `ctx.oltp` — read/write the app's OWN per-org OLTP schema on
69
+ * the managed Postgres tenant (fail-closed: omit → every `ctx.oltp` call
70
+ * rejected). A pure GATE: the target schema is derived from the app's own slug
71
+ * host-side (`oltp-bookings` → `app_oltp_bookings`), never named here, so a
72
+ * manifest cannot point `ctx.oltp` at another app's schema. The resolved role
73
+ * has DML rights on that one schema and nothing else — reaching neither another
74
+ * app's data nor the analyst-visible `raw_*` schemas. The store must be
75
+ * provisioned first (ask whoever operates the org).
76
+ *
77
+ * NOTE: this shape is `{ enabled }`, not the earlier `{ writer }` — an app
78
+ * had no business naming its own writer (that was the cross-app hole). A
79
+ * manifest still carrying `"oltp": { "writer": "…" }` deserializes to
80
+ * `enabled: undefined` → **disabled**, and `ctx.oltp` then reports the
81
+ * capability as missing. Switch it to `{ "enabled": true }`.
82
+ */
83
+ oltp?: {
84
+ enabled?: boolean;
85
+ };
67
86
  /**
68
87
  * Retry policy for **background** runs (a `schedule` fire or a manual job
69
88
  * trigger). Omit → a job run is attempted once. Route (HTTP) invocations are
@@ -130,6 +149,93 @@ interface OxyAppManifest {
130
149
  agent?: string;
131
150
  suggestedQuestions?: string[];
132
151
  };
152
+ /**
153
+ * Optional app-level storage policy. Distinct from the per-function
154
+ * `storage: { read, write }` capability: those gate what one function may
155
+ * call, while this governs the app's whole asset silo, which every function
156
+ * shares.
157
+ */
158
+ storage?: OxyAppStorageManifest;
159
+ /**
160
+ * Browser-runtime performance opt-outs. Both features below are **on by
161
+ * default** — an app that says nothing gets them — so this block exists only
162
+ * to turn one off.
163
+ *
164
+ * Read by the platform at **publish time** (like {@link OxyAppStorageManifest})
165
+ * rather than by this loader, so the field is documented here but not
166
+ * round-tripped through the dev-time manifest fetch.
167
+ */
168
+ performance?: OxyAppPerformanceManifest;
169
+ /**
170
+ * Opt out of the platform's automatic, zero-config usage instrumentation:
171
+ * SPA pageviews, Core Web Vitals, engagement time, and uncaught-error counts,
172
+ * posted to `<base>/__oxy/beacon` by the runtime Oxy injects into every served
173
+ * page. `false` silences the **client** runtime only — the server still
174
+ * records one view row per HTML navigation (that floor is not opt-out-able),
175
+ * so the Activity tab never goes dark, it just loses the in-page detail.
176
+ *
177
+ * Distinct from `useTrackEvent` (your own named events): those are additive and
178
+ * always on. This governs only the events the platform sends on your behalf.
179
+ *
180
+ * Honored at publish time (see {@link performance} for why it is not
181
+ * round-tripped here). Default: `true`.
182
+ */
183
+ analytics?: boolean;
184
+ }
185
+ /** Browser-runtime performance opt-outs — the `performance` block in `oxy-app.json`. */
186
+ interface OxyAppPerformanceManifest {
187
+ /**
188
+ * Opt out of the platform service worker Oxy registers at `<base>/__oxy/sw.js`.
189
+ * It precaches your build's entry assets and serves content-hashed files
190
+ * cache-first, so a repeat load of a published app is near-instant.
191
+ *
192
+ * Set `false` only if your app ships its own service worker (two workers
193
+ * cannot both control the same scope) or genuinely must never be cached.
194
+ * There is nothing to configure to opt *in* — a normal build is precached
195
+ * automatically, and a bundle that inlines everything into one HTML file
196
+ * simply has nothing to precache, which is fine. Default: `true`.
197
+ */
198
+ serviceWorker?: boolean;
199
+ }
200
+ /** How long assets under a given prefix are kept. */
201
+ interface OxyAppRetentionRule {
202
+ /**
203
+ * Key prefix inside your silo, as you write it — `"tmp/"`, `"generated/"`.
204
+ * The `customer-app-storage/<app_id>/` part is implicit.
205
+ */
206
+ prefix: string;
207
+ /**
208
+ * One of the five supported classes. `null` (or omitted) pins the prefix to
209
+ * "keep forever", which is how you protect it from a broader sibling rule.
210
+ *
211
+ * The set is closed on purpose — each class is one bucket-wide S3 lifecycle
212
+ * rule, so an arbitrary duration can't be honoured. An unrecognized value is
213
+ * ignored with a warning and the prefix simply doesn't expire.
214
+ */
215
+ expireAfter?: "1d" | "7d" | "30d" | "90d" | "365d" | null;
216
+ }
217
+ /** App-level `storage` block in `oxy-app.json`. */
218
+ interface OxyAppStorageManifest {
219
+ /**
220
+ * Retention rules for the asset silo. **Longest matching prefix wins**; a key
221
+ * matching no rule is kept forever.
222
+ *
223
+ * Expiry is enforced by S3 lifecycle rules on an object tag, so it is
224
+ * approximate (evaluated daily, not on the hour) and applies from the time an
225
+ * object was written. Editing a rule does not retag assets already stored —
226
+ * new writes pick up the new class.
227
+ *
228
+ * ```jsonc
229
+ * "storage": {
230
+ * "retention": [
231
+ * { "prefix": "tmp/", "expireAfter": "1d" },
232
+ * { "prefix": "generated/", "expireAfter": "90d" },
233
+ * { "prefix": "uploads/", "expireAfter": null } // keep forever
234
+ * ]
235
+ * }
236
+ * ```
237
+ */
238
+ retention?: OxyAppRetentionRule[];
133
239
  }
134
240
  /**
135
241
  * Manifest + runtime-injected identity needed to call oxy. Callers
@@ -223,6 +329,27 @@ interface FunctionLog {
223
329
  level: string;
224
330
  message: string;
225
331
  }
332
+ /** A successful function result plus the logs captured during the run. */
333
+ interface FunctionResult<Data> {
334
+ value: Data;
335
+ logs: FunctionLog[];
336
+ }
337
+ /**
338
+ * An error carries the logs captured before the throw, so the app can show them.
339
+ *
340
+ * `status` is the HTTP status the FUNCTION returned, present when the function
341
+ * ran and answered a non-2xx. It is absent when the run itself failed (an
342
+ * `event: error` frame — a crash, a timeout, a cancellation), because there was
343
+ * no response to have a status.
344
+ *
345
+ * `body` is the parsed payload the function returned with that status, so a
346
+ * caller can read `{ error: "…" }` without re-parsing the message.
347
+ */
348
+ type FunctionError = Error & {
349
+ logs?: FunctionLog[];
350
+ status?: number;
351
+ body?: unknown;
352
+ };
226
353
  //#endregion
227
354
  //#region src/custom-app/react.d.ts
228
355
  /**
@@ -422,7 +549,7 @@ interface UseSemanticQueryResult<Row = Record<string, unknown>> {
422
549
  refetch: () => void;
423
550
  }
424
551
  /**
425
- * Run a semantic-layer query against the project's `.view.yml` /
552
+ * Run a semantic-model query against the project's `.view.yml` /
426
553
  * `.topic.yml` definitions. The server compiles to SQL and executes
427
554
  * through the same connector path as `useQuery`, so result shape
428
555
  * matches.
@@ -657,5 +784,5 @@ interface OxyChatProps {
657
784
  */
658
785
  declare function OxyChat(props: OxyChatProps): React.JSX.Element;
659
786
  //#endregion
660
- export { UseSemanticQueryOpts as A, CustomAppErrorReport as B, UseProcedureRunInput as C, UseQueryOpts as D, UseQueryInput as E, useProcedureRun as F, OxyAppFunctionManifest as G, apiErrorFromResponse as H, useQuery as I, _resetCustomAppManifestCacheForTest as J, OxyAppManifest as K, useResolvedManifest as L, useAgentRun as M, useFunction as N, UseQueryResult as O, useOxyApp as P, useSemanticQuery as R, UseFunctionResult as S, UseProcedureRunResult as T, interpretCustomAppError as U, OxyApiError as V, LoadManifestOptions as W, loadCustomAppManifest as Y, SemanticFilter as _, AppFetcher as a, UseAgentRunInput as b, OxyAppProvider as c, OxyChatProps as d, ProcedureProgress as f, SemanticDateRangeOp as g, SemanticArrayOp as h, AgentSqlArtifact as i, UseSemanticQueryResult as j, UseSemanticQueryInput as k, OxyAppProviderProps as l, ProcedureRunState as m, AgentRunEvent as n, OxyAnswer as o, ProcedureResult as p, ResolvedCustomAppManifest as q, AgentRunState as r, OxyAnswerProps as s, AgentArtifact as t, OxyChat as u, SemanticScalarOp as v, UseProcedureRunOpts as w, UseAgentRunResult as x, SemanticTimeDimension as y, useTrackEvent as z };
661
- //# sourceMappingURL=react-kHG5gkd-.d.cts.map
787
+ export { loadCustomAppManifest as $, UseSemanticQueryOpts as A, FunctionError as B, UseProcedureRunInput as C, UseQueryOpts as D, UseQueryInput as E, useProcedureRun as F, apiErrorFromResponse as G, FunctionResult as H, useQuery as I, OxyAppFunctionManifest as J, interpretCustomAppError as K, useResolvedManifest as L, useAgentRun as M, useFunction as N, UseQueryResult as O, useOxyApp as P, _resetCustomAppManifestCacheForTest as Q, useSemanticQuery as R, UseFunctionResult as S, UseProcedureRunResult as T, CustomAppErrorReport as U, FunctionLog as V, OxyApiError as W, OxyAppPerformanceManifest as X, OxyAppManifest as Y, ResolvedCustomAppManifest as Z, SemanticFilter as _, AppFetcher as a, UseAgentRunInput as b, OxyAppProvider as c, OxyChatProps as d, ProcedureProgress as f, SemanticDateRangeOp as g, SemanticArrayOp as h, AgentSqlArtifact as i, UseSemanticQueryResult as j, UseSemanticQueryInput as k, OxyAppProviderProps as l, ProcedureRunState as m, AgentRunEvent as n, OxyAnswer as o, ProcedureResult as p, LoadManifestOptions as q, AgentRunState as r, OxyAnswerProps as s, AgentArtifact as t, OxyChat as u, SemanticScalarOp as v, UseProcedureRunOpts as w, UseAgentRunResult as x, SemanticTimeDimension as y, useTrackEvent as z };
788
+ //# sourceMappingURL=react-BGUzRMxq.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-BGUzRMxq.d.mts","names":[],"sources":["../src/custom-app/manifest.ts","../src/custom-app/errors.ts","../src/custom-app/function-sse.ts","../src/custom-app/react.tsx"],"mappings":"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"}
@@ -20,7 +20,7 @@ var __copyProps = (to, from, except, desc) => {
20
20
  }
21
21
  return to;
22
22
  };
23
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
24
24
  value: mod,
25
25
  enumerable: true
26
26
  }) : target, mod));
@@ -59,9 +59,7 @@ function createConsoleLogger() {
59
59
  case "warn":
60
60
  console.warn(...args);
61
61
  break;
62
- case "error":
63
- console.error(...args);
64
- break;
62
+ case "error": console.error(...args);
65
63
  }
66
64
  } };
67
65
  }
@@ -302,6 +300,7 @@ function validateManifest(raw, url) {
302
300
  if (raw.schemaVersion !== 2) throw new Error(`oxy-app.json: schemaVersion must be 2 (got ${JSON.stringify(raw.schemaVersion)}). v1 manifests are no longer supported — upgrade to the identity-only shape.`);
303
301
  if (raw.products !== void 0 || raw.writers !== void 0) throw new Error(`oxy-app.json is schemaVersion 2 (identity-only); \`products\` and \`writers\` are no longer supported`);
304
302
  if (typeof raw.slug !== "string" || !raw.slug.trim()) throw new Error("oxy-app.json: `slug` is required and must be a non-empty string");
303
+ if (!isValidSlug(raw.slug)) throw new Error(`oxy-app.json: \`slug\` ${JSON.stringify(raw.slug)} is invalid — use 1–63 lowercase letters, digits and single hyphens (no leading/trailing/double hyphen, no underscore)`);
305
304
  return {
306
305
  schemaVersion: 2,
307
306
  name: typeof raw.name === "string" ? raw.name : void 0,
@@ -315,12 +314,21 @@ function validateManifest(raw, url) {
315
314
  } : void 0
316
315
  };
317
316
  }
317
+ const SLUG_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/;
318
+ function isValidSlug(s) {
319
+ return s.length <= 63 && SLUG_RE.test(s);
320
+ }
318
321
  const FUNCTION_NAME_RE = /^[a-z][a-z0-9-]{0,63}$/;
319
322
  /**
320
- * Validate the optional `functions` map. Each key is a function name;
321
- * each value declares how the function is invoked. Mirrors the
322
- * server-side validation in `custom_apps_publish.rs` so a bad
323
- * manifest fails at build, not at publish.
323
+ * Validate the optional `functions` map. Each key is a function name; each value
324
+ * declares how the function is invoked. Mirrors the server-side function-name
325
+ * rule enforced at publish in `custom_apps_publish.rs` — `is_valid_function_name`,
326
+ * checked in `record_functions` before any row is written.
327
+ *
328
+ * This runs at manifest LOAD (app boot / `pnpm dev`), not at `oxy build` — the
329
+ * build-time gate is the vite plugin's `validateManifest`, which now checks
330
+ * function names too. `oxy publish` also validates them locally before esbuild,
331
+ * so a bad name fails before the upload regardless.
324
332
  */
325
333
  function validateFunctions(raw) {
326
334
  if (!isRecord(raw)) throw new Error("oxy-app.json: `functions` must be an object keyed by function name");
@@ -449,11 +457,24 @@ async function readFunctionSseStream(resp) {
449
457
  });
450
458
  } catch {}
451
459
  else if (event === "data") dataPayload = data;
452
- else if (event === "done") return {
453
- done: true,
454
- value: dataPayload ? JSON.parse(dataPayload) : null
455
- };
456
- else if (event === "error") {
460
+ else if (event === "done") {
461
+ const parsed = dataPayload ? JSON.parse(dataPayload) : null;
462
+ const meta = data ? JSON.parse(data) : {};
463
+ const status = typeof meta.status === "number" ? meta.status : 200;
464
+ if (status < 200 || status >= 300) {
465
+ const payload = parsed;
466
+ const err = new Error(String(payload?.message ?? payload?.error ?? `function returned ${status}`));
467
+ err.name = "FunctionStatusError";
468
+ err.status = status;
469
+ err.body = parsed;
470
+ err.logs = logs;
471
+ throw err;
472
+ }
473
+ return {
474
+ done: true,
475
+ value: parsed
476
+ };
477
+ } else if (event === "error") {
457
478
  const payload = data ? JSON.parse(data) : {};
458
479
  const err = new Error(payload.message || payload.error || "function invocation failed");
459
480
  err.name = payload.error || "FunctionError";
@@ -943,7 +964,7 @@ function useFunction(name) {
943
964
  };
944
965
  }
945
966
  /**
946
- * Run a semantic-layer query against the project's `.view.yml` /
967
+ * Run a semantic-model query against the project's `.view.yml` /
947
968
  * `.topic.yml` definitions. The server compiles to SQL and executes
948
969
  * through the same connector path as `useQuery`, so result shape
949
970
  * matches.
@@ -1043,7 +1064,7 @@ function useSemanticQuery(input, opts = {}) {
1043
1064
  }
1044
1065
  const PROCEDURE_POLL_MS = 2e3;
1045
1066
  const PROCEDURE_BACKOFF_MS = 5e3;
1046
- const PROCEDURE_MAX_WAIT_MS = 3600 * 1e3;
1067
+ const PROCEDURE_MAX_WAIT_MS = 36e5;
1047
1068
  /**
1048
1069
  * @beta Long-running procedure runner. The wire shape works end-to-end
1049
1070
  * (start → poll → cancel; runs survive server restarts via the
@@ -1521,9 +1542,7 @@ async function consumeSseStream(opts) {
1521
1542
  case "event":
1522
1543
  currentEvent = value;
1523
1544
  break;
1524
- case "data":
1525
- currentData.push(value);
1526
- break;
1545
+ case "data": currentData.push(value);
1527
1546
  }
1528
1547
  }
1529
1548
  }
@@ -1850,7 +1869,8 @@ function ErrorBlock(props) {
1850
1869
  });
1851
1870
  }
1852
1871
  function MarkdownText(props) {
1853
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: react.useMemo(() => parseMarkdown(props.text), [props.text]) });
1872
+ const blocks = react.useMemo(() => parseMarkdown(props.text), [props.text]);
1873
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: blocks });
1854
1874
  }
1855
1875
  function parseMarkdown(text) {
1856
1876
  const lines = text.replace(/\r\n/g, "\n").split("\n");
@@ -1935,10 +1955,14 @@ function parseMarkdown(text) {
1935
1955
  }
1936
1956
  return blocks.map((b, idx) => {
1937
1957
  switch (b.kind) {
1938
- case "h": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(`h${b.level}`, {
1939
- style: b.level === 1 ? styles.h1 : b.level === 2 ? styles.h2 : styles.h3,
1940
- children: renderInline(b.text)
1941
- }, idx);
1958
+ case "h": {
1959
+ const Tag = `h${b.level}`;
1960
+ const headingStyle = b.level === 1 ? styles.h1 : b.level === 2 ? styles.h2 : styles.h3;
1961
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Tag, {
1962
+ style: headingStyle,
1963
+ children: renderInline(b.text)
1964
+ }, idx);
1965
+ }
1942
1966
  case "code": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
1943
1967
  style: styles.codeBlock,
1944
1968
  "data-lang": b.lang || void 0,
@@ -2407,4 +2431,4 @@ Object.defineProperty(exports, 'useTrackEvent', {
2407
2431
  return useTrackEvent;
2408
2432
  }
2409
2433
  });
2410
- //# sourceMappingURL=react-BFFCK4VM.cjs.map
2434
+ //# sourceMappingURL=react-Cas_DVKe.cjs.map