@oxy-hq/sdk 2.9.1 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +118 -7
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +118 -7
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +3 -3
- package/dist/index.mjs.map +1 -1
- package/dist/{react-DBG6Pfp_.d.mts → react-CLONxcnA.d.cts} +127 -3
- package/dist/react-CLONxcnA.d.cts.map +1 -0
- package/dist/{react-DBG6Pfp_.d.cts → react-CLONxcnA.d.mts} +127 -3
- package/dist/react-CLONxcnA.d.mts.map +1 -0
- package/dist/{react-sACIu6Ea.mjs → react-DqnINwTi.mjs} +45 -14
- package/dist/react-DqnINwTi.mjs.map +1 -0
- package/dist/{react-CDYGAfGA.cjs → react-riTxd9ce.cjs} +45 -14
- package/dist/react-riTxd9ce.cjs.map +1 -0
- package/dist/shell.cjs +1 -1
- package/dist/shell.d.cts +1 -1
- package/dist/shell.d.mts +1 -1
- package/dist/shell.mjs +1 -1
- package/package.json +7 -7
- package/dist/react-CDYGAfGA.cjs.map +0 -1
- package/dist/react-DBG6Pfp_.d.cts.map +0 -1
- package/dist/react-DBG6Pfp_.d.mts.map +0 -1
- package/dist/react-sACIu6Ea.mjs.map +0 -1
|
@@ -64,6 +64,44 @@ interface OxyAppFunctionManifest {
|
|
|
64
64
|
email?: {
|
|
65
65
|
send?: boolean;
|
|
66
66
|
};
|
|
67
|
+
/**
|
|
68
|
+
* Capability for `ctx.org.people()` — the org's people directory, READ-ONLY
|
|
69
|
+
* (fail-closed: omit → the call is rejected before any query).
|
|
70
|
+
*
|
|
71
|
+
* Declare it for a function that has to name a person: an assignee, a roster
|
|
72
|
+
* entry, who submitted something. It answers with a display name and a role.
|
|
73
|
+
*
|
|
74
|
+
* Three things it deliberately is not, so nobody plans around them:
|
|
75
|
+
* it returns **no email and no phone** — naming a colleague is a different
|
|
76
|
+
* need from contacting them off-platform; it returns **no location**, which
|
|
77
|
+
* the platform does not hold for a member; and it does **not include
|
|
78
|
+
* frontline workers**, who hold no org-membership row by design.
|
|
79
|
+
*
|
|
80
|
+
* One flag, not `read`/`write`: there is no write. Editing the directory
|
|
81
|
+
* would put tenant membership behind an app's manifest.
|
|
82
|
+
*/
|
|
83
|
+
org?: {
|
|
84
|
+
read?: boolean;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Capability for `ctx.oltp` — read/write the app's OWN per-org OLTP schema on
|
|
88
|
+
* the managed Postgres tenant (fail-closed: omit → every `ctx.oltp` call
|
|
89
|
+
* rejected). A pure GATE: the target schema is derived from the app's own slug
|
|
90
|
+
* host-side (`oltp-bookings` → `app_oltp_bookings`), never named here, so a
|
|
91
|
+
* manifest cannot point `ctx.oltp` at another app's schema. The resolved role
|
|
92
|
+
* has DML rights on that one schema and nothing else — reaching neither another
|
|
93
|
+
* app's data nor the analyst-visible `raw_*` schemas. The store must be
|
|
94
|
+
* provisioned first (ask whoever operates the org).
|
|
95
|
+
*
|
|
96
|
+
* NOTE: this shape is `{ enabled }`, not the earlier `{ writer }` — an app
|
|
97
|
+
* had no business naming its own writer (that was the cross-app hole). A
|
|
98
|
+
* manifest still carrying `"oltp": { "writer": "…" }` deserializes to
|
|
99
|
+
* `enabled: undefined` → **disabled**, and `ctx.oltp` then reports the
|
|
100
|
+
* capability as missing. Switch it to `{ "enabled": true }`.
|
|
101
|
+
*/
|
|
102
|
+
oltp?: {
|
|
103
|
+
enabled?: boolean;
|
|
104
|
+
};
|
|
67
105
|
/**
|
|
68
106
|
* Retry policy for **background** runs (a `schedule` fire or a manual job
|
|
69
107
|
* trigger). Omit → a job run is attempted once. Route (HTTP) invocations are
|
|
@@ -120,6 +158,25 @@ interface OxyAppManifest {
|
|
|
120
158
|
* static bundle (today's default). See the functions design doc.
|
|
121
159
|
*/
|
|
122
160
|
functions?: Record<string, OxyAppFunctionManifest>;
|
|
161
|
+
/**
|
|
162
|
+
* Schema migrations that ship WITH this bundle and run on promote.
|
|
163
|
+
*
|
|
164
|
+
* `dir` is a directory inside the built bundle holding numbered `.sql` files.
|
|
165
|
+
* The platform runs them in lexical order, **once each, ever**, inside a
|
|
166
|
+
* transaction, as the app's own writer role, and records each one.
|
|
167
|
+
*
|
|
168
|
+
* What changes for the author: you no longer write defensive
|
|
169
|
+
* `IF NOT EXISTS` / idempotent upserts, because re-running is a no-op by
|
|
170
|
+
* construction rather than by your care. And you **may not edit, rename or
|
|
171
|
+
* copy a migration that has already run** — all three fail the promote by
|
|
172
|
+
* name, and the fix is always a new file.
|
|
173
|
+
*
|
|
174
|
+
* The `.sql` files are ordinary bundle files, fetchable over the app's own
|
|
175
|
+
* host: put no secrets in them.
|
|
176
|
+
*/
|
|
177
|
+
migrations?: {
|
|
178
|
+
dir: string;
|
|
179
|
+
};
|
|
123
180
|
/**
|
|
124
181
|
* Optional Ask Oxygen binding (agent ref + composer chips). The
|
|
125
182
|
* platform's registered copy is authoritative (surfaced by
|
|
@@ -137,6 +194,46 @@ interface OxyAppManifest {
|
|
|
137
194
|
* shares.
|
|
138
195
|
*/
|
|
139
196
|
storage?: OxyAppStorageManifest;
|
|
197
|
+
/**
|
|
198
|
+
* Browser-runtime performance opt-outs. Both features below are **on by
|
|
199
|
+
* default** — an app that says nothing gets them — so this block exists only
|
|
200
|
+
* to turn one off.
|
|
201
|
+
*
|
|
202
|
+
* Read by the platform at **publish time** (like {@link OxyAppStorageManifest})
|
|
203
|
+
* rather than by this loader, so the field is documented here but not
|
|
204
|
+
* round-tripped through the dev-time manifest fetch.
|
|
205
|
+
*/
|
|
206
|
+
performance?: OxyAppPerformanceManifest;
|
|
207
|
+
/**
|
|
208
|
+
* Opt out of the platform's automatic, zero-config usage instrumentation:
|
|
209
|
+
* SPA pageviews, Core Web Vitals, engagement time, and uncaught-error counts,
|
|
210
|
+
* posted to `<base>/__oxy/beacon` by the runtime Oxy injects into every served
|
|
211
|
+
* page. `false` silences the **client** runtime only — the server still
|
|
212
|
+
* records one view row per HTML navigation (that floor is not opt-out-able),
|
|
213
|
+
* so the Activity tab never goes dark, it just loses the in-page detail.
|
|
214
|
+
*
|
|
215
|
+
* Distinct from `useTrackEvent` (your own named events): those are additive and
|
|
216
|
+
* always on. This governs only the events the platform sends on your behalf.
|
|
217
|
+
*
|
|
218
|
+
* Honored at publish time (see {@link performance} for why it is not
|
|
219
|
+
* round-tripped here). Default: `true`.
|
|
220
|
+
*/
|
|
221
|
+
analytics?: boolean;
|
|
222
|
+
}
|
|
223
|
+
/** Browser-runtime performance opt-outs — the `performance` block in `oxy-app.json`. */
|
|
224
|
+
interface OxyAppPerformanceManifest {
|
|
225
|
+
/**
|
|
226
|
+
* Opt out of the platform service worker Oxy registers at `<base>/__oxy/sw.js`.
|
|
227
|
+
* It precaches your build's entry assets and serves content-hashed files
|
|
228
|
+
* cache-first, so a repeat load of a published app is near-instant.
|
|
229
|
+
*
|
|
230
|
+
* Set `false` only if your app ships its own service worker (two workers
|
|
231
|
+
* cannot both control the same scope) or genuinely must never be cached.
|
|
232
|
+
* There is nothing to configure to opt *in* — a normal build is precached
|
|
233
|
+
* automatically, and a bundle that inlines everything into one HTML file
|
|
234
|
+
* simply has nothing to precache, which is fine. Default: `true`.
|
|
235
|
+
*/
|
|
236
|
+
serviceWorker?: boolean;
|
|
140
237
|
}
|
|
141
238
|
/** How long assets under a given prefix are kept. */
|
|
142
239
|
interface OxyAppRetentionRule {
|
|
@@ -270,6 +367,27 @@ interface FunctionLog {
|
|
|
270
367
|
level: string;
|
|
271
368
|
message: string;
|
|
272
369
|
}
|
|
370
|
+
/** A successful function result plus the logs captured during the run. */
|
|
371
|
+
interface FunctionResult<Data> {
|
|
372
|
+
value: Data;
|
|
373
|
+
logs: FunctionLog[];
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* An error carries the logs captured before the throw, so the app can show them.
|
|
377
|
+
*
|
|
378
|
+
* `status` is the HTTP status the FUNCTION returned, present when the function
|
|
379
|
+
* ran and answered a non-2xx. It is absent when the run itself failed (an
|
|
380
|
+
* `event: error` frame — a crash, a timeout, a cancellation), because there was
|
|
381
|
+
* no response to have a status.
|
|
382
|
+
*
|
|
383
|
+
* `body` is the parsed payload the function returned with that status, so a
|
|
384
|
+
* caller can read `{ error: "…" }` without re-parsing the message.
|
|
385
|
+
*/
|
|
386
|
+
type FunctionError = Error & {
|
|
387
|
+
logs?: FunctionLog[];
|
|
388
|
+
status?: number;
|
|
389
|
+
body?: unknown;
|
|
390
|
+
};
|
|
273
391
|
//#endregion
|
|
274
392
|
//#region src/custom-app/react.d.ts
|
|
275
393
|
/**
|
|
@@ -340,6 +458,12 @@ declare function useResolvedManifest(): ResolvedCustomAppManifest;
|
|
|
340
458
|
*/
|
|
341
459
|
declare function useOxyApp(): {
|
|
342
460
|
projectId: string | undefined;
|
|
461
|
+
/**
|
|
462
|
+
* The `apps.id` this bundle was served as — from `window.__OXY_APP__`, so
|
|
463
|
+
* it is the platform's word and not the manifest's. Undefined under `pnpm
|
|
464
|
+
* dev` against a manifest with no injected identity.
|
|
465
|
+
*/
|
|
466
|
+
appId: string | undefined;
|
|
343
467
|
appSlug: string | undefined;
|
|
344
468
|
orgSlug: string | undefined;
|
|
345
469
|
fetcher: AppFetcher;
|
|
@@ -469,7 +593,7 @@ interface UseSemanticQueryResult<Row = Record<string, unknown>> {
|
|
|
469
593
|
refetch: () => void;
|
|
470
594
|
}
|
|
471
595
|
/**
|
|
472
|
-
* Run a semantic-
|
|
596
|
+
* Run a semantic-model query against the project's `.view.yml` /
|
|
473
597
|
* `.topic.yml` definitions. The server compiles to SQL and executes
|
|
474
598
|
* through the same connector path as `useQuery`, so result shape
|
|
475
599
|
* matches.
|
|
@@ -704,5 +828,5 @@ interface OxyChatProps {
|
|
|
704
828
|
*/
|
|
705
829
|
declare function OxyChat(props: OxyChatProps): React.JSX.Element;
|
|
706
830
|
//#endregion
|
|
707
|
-
export { UseSemanticQueryOpts as A,
|
|
708
|
-
//# sourceMappingURL=react-
|
|
831
|
+
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 };
|
|
832
|
+
//# sourceMappingURL=react-CLONxcnA.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react-CLONxcnA.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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"}
|
|
@@ -272,6 +272,7 @@ function validateManifest(raw, url) {
|
|
|
272
272
|
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.`);
|
|
273
273
|
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`);
|
|
274
274
|
if (typeof raw.slug !== "string" || !raw.slug.trim()) throw new Error("oxy-app.json: `slug` is required and must be a non-empty string");
|
|
275
|
+
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)`);
|
|
275
276
|
return {
|
|
276
277
|
schemaVersion: 2,
|
|
277
278
|
name: typeof raw.name === "string" ? raw.name : void 0,
|
|
@@ -285,12 +286,21 @@ function validateManifest(raw, url) {
|
|
|
285
286
|
} : void 0
|
|
286
287
|
};
|
|
287
288
|
}
|
|
289
|
+
const SLUG_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
290
|
+
function isValidSlug(s) {
|
|
291
|
+
return s.length <= 63 && SLUG_RE.test(s);
|
|
292
|
+
}
|
|
288
293
|
const FUNCTION_NAME_RE = /^[a-z][a-z0-9-]{0,63}$/;
|
|
289
294
|
/**
|
|
290
|
-
* Validate the optional `functions` map. Each key is a function name;
|
|
291
|
-
*
|
|
292
|
-
*
|
|
293
|
-
*
|
|
295
|
+
* Validate the optional `functions` map. Each key is a function name; each value
|
|
296
|
+
* declares how the function is invoked. Mirrors the server-side function-name
|
|
297
|
+
* rule enforced at publish in `custom_apps_publish.rs` — `is_valid_function_name`,
|
|
298
|
+
* checked in `record_functions` before any row is written.
|
|
299
|
+
*
|
|
300
|
+
* This runs at manifest LOAD (app boot / `pnpm dev`), not at `oxy build` — the
|
|
301
|
+
* build-time gate is the vite plugin's `validateManifest`, which now checks
|
|
302
|
+
* function names too. `oxy publish` also validates them locally before esbuild,
|
|
303
|
+
* so a bad name fails before the upload regardless.
|
|
294
304
|
*/
|
|
295
305
|
function validateFunctions(raw) {
|
|
296
306
|
if (!isRecord(raw)) throw new Error("oxy-app.json: `functions` must be an object keyed by function name");
|
|
@@ -419,11 +429,24 @@ async function readFunctionSseStream(resp) {
|
|
|
419
429
|
});
|
|
420
430
|
} catch {}
|
|
421
431
|
else if (event === "data") dataPayload = data;
|
|
422
|
-
else if (event === "done")
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
432
|
+
else if (event === "done") {
|
|
433
|
+
const parsed = dataPayload ? JSON.parse(dataPayload) : null;
|
|
434
|
+
const meta = data ? JSON.parse(data) : {};
|
|
435
|
+
const status = typeof meta.status === "number" ? meta.status : 200;
|
|
436
|
+
if (status < 200 || status >= 300) {
|
|
437
|
+
const payload = parsed;
|
|
438
|
+
const err = new Error(String(payload?.message ?? payload?.error ?? `function returned ${status}`));
|
|
439
|
+
err.name = "FunctionStatusError";
|
|
440
|
+
err.status = status;
|
|
441
|
+
err.body = parsed;
|
|
442
|
+
err.logs = logs;
|
|
443
|
+
throw err;
|
|
444
|
+
}
|
|
445
|
+
return {
|
|
446
|
+
done: true,
|
|
447
|
+
value: parsed
|
|
448
|
+
};
|
|
449
|
+
} else if (event === "error") {
|
|
427
450
|
const payload = data ? JSON.parse(data) : {};
|
|
428
451
|
const err = new Error(payload.message || payload.error || "function invocation failed");
|
|
429
452
|
err.name = payload.error || "FunctionError";
|
|
@@ -749,6 +772,7 @@ function useOxyApp() {
|
|
|
749
772
|
if (!ctx) throw new Error("useOxyApp must be called inside <OxyAppProvider>");
|
|
750
773
|
return {
|
|
751
774
|
projectId: ctx.resolved?.projectId,
|
|
775
|
+
appId: ctx.resolved?.appId,
|
|
752
776
|
appSlug: ctx.resolved?.appSlug,
|
|
753
777
|
orgSlug: ctx.resolved?.orgSlug,
|
|
754
778
|
fetcher: ctx.fetcher
|
|
@@ -913,7 +937,7 @@ function useFunction(name) {
|
|
|
913
937
|
};
|
|
914
938
|
}
|
|
915
939
|
/**
|
|
916
|
-
* Run a semantic-
|
|
940
|
+
* Run a semantic-model query against the project's `.view.yml` /
|
|
917
941
|
* `.topic.yml` definitions. The server compiles to SQL and executes
|
|
918
942
|
* through the same connector path as `useQuery`, so result shape
|
|
919
943
|
* matches.
|
|
@@ -1535,7 +1559,7 @@ function sleep(ms, signal) {
|
|
|
1535
1559
|
* within-limit events are unaffected.
|
|
1536
1560
|
*/
|
|
1537
1561
|
function useTrackEvent() {
|
|
1538
|
-
const { projectId, fetcher } = useOxyApp();
|
|
1562
|
+
const { projectId, appId, fetcher } = useOxyApp();
|
|
1539
1563
|
const queueRef = React.useRef([]);
|
|
1540
1564
|
const flushTimerRef = React.useRef(null);
|
|
1541
1565
|
const flush = React.useCallback(() => {
|
|
@@ -1546,7 +1570,10 @@ function useTrackEvent() {
|
|
|
1546
1570
|
queueRef.current = [];
|
|
1547
1571
|
for (const evt of batch) {
|
|
1548
1572
|
const url = `/api/customer-apps/${projectId}/events`;
|
|
1549
|
-
const body = JSON.stringify(
|
|
1573
|
+
const body = JSON.stringify(appId ? {
|
|
1574
|
+
...evt,
|
|
1575
|
+
app_id: appId
|
|
1576
|
+
} : evt);
|
|
1550
1577
|
try {
|
|
1551
1578
|
if (typeof navigator !== "undefined" && typeof navigator.sendBeacon === "function" && document.visibilityState === "hidden") navigator.sendBeacon(url, new Blob([body], { type: "application/json" }));
|
|
1552
1579
|
else fetcher(url, {
|
|
@@ -1560,7 +1587,11 @@ function useTrackEvent() {
|
|
|
1560
1587
|
console.warn("[oxy] useTrackEvent enqueue failed:", e);
|
|
1561
1588
|
}
|
|
1562
1589
|
}
|
|
1563
|
-
}, [
|
|
1590
|
+
}, [
|
|
1591
|
+
projectId,
|
|
1592
|
+
fetcher,
|
|
1593
|
+
appId
|
|
1594
|
+
]);
|
|
1564
1595
|
React.useEffect(() => {
|
|
1565
1596
|
if (typeof window === "undefined") return;
|
|
1566
1597
|
const onHide = () => flush();
|
|
@@ -2261,4 +2292,4 @@ const styles = {
|
|
|
2261
2292
|
|
|
2262
2293
|
//#endregion
|
|
2263
2294
|
export { interpretCustomAppError as _, useFunction as a, useQuery as c, useTrackEvent as d, _resetCustomAppManifestCacheForTest as f, apiErrorFromResponse as g, OxyApiError as h, useAgentRun as i, useResolvedManifest as l, readInjectedAppConfig as m, OxyAppProvider as n, useOxyApp as o, loadCustomAppManifest as p, OxyChat as r, useProcedureRun as s, OxyAnswer as t, useSemanticQuery as u, getOxyAppLogger as v, setOxyAppLogger as y };
|
|
2264
|
-
//# sourceMappingURL=react-
|
|
2295
|
+
//# sourceMappingURL=react-DqnINwTi.mjs.map
|