@oxy-hq/sdk 2.4.0 → 2.6.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 +1 -1
- package/dist/index.cjs +8 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +206 -10
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +206 -10
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +5 -5
- package/dist/index.mjs.map +1 -1
- package/dist/{react-DArzs6_l.mjs → react-5HGW_0oy.mjs} +46 -26
- package/dist/react-5HGW_0oy.mjs.map +1 -0
- package/dist/{react-B7Blpmt7.cjs → react-BAiiXftp.cjs} +51 -31
- package/dist/react-BAiiXftp.cjs.map +1 -0
- package/dist/{react-BLsczFL4.d.mts → react-DnBdQ8dG.d.cts} +26 -16
- package/dist/react-DnBdQ8dG.d.cts.map +1 -0
- package/dist/{react-BLsczFL4.d.cts → react-DnBdQ8dG.d.mts} +26 -16
- package/dist/react-DnBdQ8dG.d.mts.map +1 -0
- package/dist/shell.cjs +138 -54
- package/dist/shell.cjs.map +1 -1
- package/dist/shell.css +80 -4
- package/dist/shell.d.cts +15 -6
- package/dist/shell.d.cts.map +1 -1
- package/dist/shell.d.mts +15 -6
- package/dist/shell.d.mts.map +1 -1
- package/dist/shell.mjs +138 -54
- package/dist/shell.mjs.map +1 -1
- package/package.json +11 -11
- package/dist/react-B7Blpmt7.cjs.map +0 -1
- package/dist/react-BLsczFL4.d.cts.map +0 -1
- package/dist/react-BLsczFL4.d.mts.map +0 -1
- package/dist/react-DArzs6_l.mjs.map +0 -1
|
@@ -30,7 +30,7 @@ let react = require("react");
|
|
|
30
30
|
react = __toESM(react, 1);
|
|
31
31
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
32
32
|
|
|
33
|
-
//#region src/
|
|
33
|
+
//#region src/custom-app/logger.ts
|
|
34
34
|
let activeLogger = createConsoleLogger();
|
|
35
35
|
/** Replace the global logger. Pass `null` to silence everything. */
|
|
36
36
|
function setOxyAppLogger(logger) {
|
|
@@ -70,9 +70,9 @@ function silentLogger() {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
//#endregion
|
|
73
|
-
//#region src/
|
|
73
|
+
//#region src/custom-app/errors.ts
|
|
74
74
|
/**
|
|
75
|
-
* Error thrown by all
|
|
75
|
+
* Error thrown by all custom-app hooks when an API call returns a
|
|
76
76
|
* non-2xx response. Carries the structured `code` + `hint` the server
|
|
77
77
|
* emits so bundle UIs can render an actionable message instead of
|
|
78
78
|
* "404: { ...json... }".
|
|
@@ -119,12 +119,12 @@ async function apiErrorFromResponse(resp) {
|
|
|
119
119
|
}
|
|
120
120
|
const ARCH_DOC = "internal-docs/customer-apps.md";
|
|
121
121
|
/** Interpret a thrown error as a structured report for UI display. */
|
|
122
|
-
function
|
|
122
|
+
function interpretCustomAppError(err) {
|
|
123
123
|
const message = err instanceof Error ? err.message : String(err);
|
|
124
124
|
if (/Failed to load oxy-app\.json.*HTTP 404/.test(message)) return {
|
|
125
125
|
title: "Manifest not found",
|
|
126
126
|
message,
|
|
127
|
-
hint: "The bundle is being served, but oxy-app.json was not. Check that public/oxy-app.json is committed in the
|
|
127
|
+
hint: "The bundle is being served, but oxy-app.json was not. Check that public/oxy-app.json is committed in the custom-app repo and that the build copied it into the static output. If you're using Next.js, anything under public/ is auto-copied to out/.",
|
|
128
128
|
docs: ARCH_DOC
|
|
129
129
|
};
|
|
130
130
|
if (/Failed to load oxy-app\.json/.test(message)) return {
|
|
@@ -160,7 +160,7 @@ function interpretCustomerAppError(err) {
|
|
|
160
160
|
if (/^403:.*SELECT.*WITH/im.test(message)) return {
|
|
161
161
|
title: "Query rejected — read-only endpoint",
|
|
162
162
|
message,
|
|
163
|
-
hint: "This proxy only runs SELECT or WITH queries. Mutations (INSERT/UPDATE/DELETE/DROP) are not allowed from
|
|
163
|
+
hint: "This proxy only runs SELECT or WITH queries. Mutations (INSERT/UPDATE/DELETE/DROP) are not allowed from custom-app bundles.",
|
|
164
164
|
docs: ARCH_DOC
|
|
165
165
|
};
|
|
166
166
|
if (/^403:/m.test(message)) return {
|
|
@@ -196,7 +196,7 @@ function interpretCustomerAppError(err) {
|
|
|
196
196
|
if (/Unexpected token '<'|<!doctype/i.test(message)) return {
|
|
197
197
|
title: "Fetched HTML where JSON was expected",
|
|
198
198
|
message,
|
|
199
|
-
hint: "Most likely the built bundle is stale — built against an old SDK whose endpoints no longer exist on the server. Rebuild the bundle (vite build) with @oxy-hq/sdk@^2.0.0 and reload. If the bundle is current, check that OXY_APP_BASE_PATH matches the path the
|
|
199
|
+
hint: "Most likely the built bundle is stale — built against an old SDK whose endpoints no longer exist on the server. Rebuild the bundle (vite build) with @oxy-hq/sdk@^2.0.0 and reload. If the bundle is current, check that OXY_APP_BASE_PATH matches the path the custom-app row is served at.",
|
|
200
200
|
docs: ARCH_DOC
|
|
201
201
|
};
|
|
202
202
|
return {
|
|
@@ -208,7 +208,7 @@ function interpretCustomerAppError(err) {
|
|
|
208
208
|
}
|
|
209
209
|
|
|
210
210
|
//#endregion
|
|
211
|
-
//#region src/
|
|
211
|
+
//#region src/custom-app/inject.ts
|
|
212
212
|
/**
|
|
213
213
|
* Read the runtime app-config oxy injected at serve time. Returns
|
|
214
214
|
* `undefined` outside the browser or when the global isn't set
|
|
@@ -221,18 +221,18 @@ function readInjectedAppConfig() {
|
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
//#endregion
|
|
224
|
-
//#region src/
|
|
224
|
+
//#region src/custom-app/manifest.ts
|
|
225
225
|
let cached = null;
|
|
226
226
|
/**
|
|
227
227
|
* Load + validate the manifest. Cached after the first call so callers
|
|
228
228
|
* can invoke this from every component without coordinating.
|
|
229
229
|
*/
|
|
230
|
-
function
|
|
230
|
+
function loadCustomAppManifest(options = {}) {
|
|
231
231
|
if (!cached) cached = fetchAndValidate(options);
|
|
232
232
|
return cached;
|
|
233
233
|
}
|
|
234
234
|
/** For tests: reset the cache between runs. */
|
|
235
|
-
function
|
|
235
|
+
function _resetCustomAppManifestCacheForTest() {
|
|
236
236
|
cached = null;
|
|
237
237
|
}
|
|
238
238
|
async function fetchAndValidate(options) {
|
|
@@ -254,7 +254,7 @@ async function fetchAndValidate(options) {
|
|
|
254
254
|
status: res.status,
|
|
255
255
|
statusText: res.statusText
|
|
256
256
|
});
|
|
257
|
-
throw new Error(`Failed to load oxy-app.json from ${manifestUrl} (HTTP ${res.status}). The
|
|
257
|
+
throw new Error(`Failed to load oxy-app.json from ${manifestUrl} (HTTP ${res.status}). The custom-app repo must commit this file alongside the bundle.`);
|
|
258
258
|
}
|
|
259
259
|
const manifest = validateManifest(await res.json(), manifestUrl);
|
|
260
260
|
const resolved = {
|
|
@@ -319,7 +319,7 @@ const FUNCTION_NAME_RE = /^[a-z][a-z0-9-]{0,63}$/;
|
|
|
319
319
|
/**
|
|
320
320
|
* Validate the optional `functions` map. Each key is a function name;
|
|
321
321
|
* each value declares how the function is invoked. Mirrors the
|
|
322
|
-
* server-side validation in `
|
|
322
|
+
* server-side validation in `custom_apps_publish.rs` so a bad
|
|
323
323
|
* manifest fails at build, not at publish.
|
|
324
324
|
*/
|
|
325
325
|
function validateFunctions(raw) {
|
|
@@ -397,7 +397,7 @@ function isRecord(v) {
|
|
|
397
397
|
}
|
|
398
398
|
|
|
399
399
|
//#endregion
|
|
400
|
-
//#region src/
|
|
400
|
+
//#region src/custom-app/function-invoke.ts
|
|
401
401
|
const inflight$1 = /* @__PURE__ */ new Map();
|
|
402
402
|
/**
|
|
403
403
|
* Dedup key for an invocation: function name + its (stable-serialized) body,
|
|
@@ -423,7 +423,7 @@ function sharedFunctionInvoke(key, run) {
|
|
|
423
423
|
}
|
|
424
424
|
|
|
425
425
|
//#endregion
|
|
426
|
-
//#region src/
|
|
426
|
+
//#region src/custom-app/function-sse.ts
|
|
427
427
|
/**
|
|
428
428
|
* Read a `text/event-stream` function response to completion. Resolves with the
|
|
429
429
|
* decoded result + captured logs, or rejects (with `.logs` attached) on an
|
|
@@ -480,7 +480,7 @@ async function readFunctionSseStream(resp) {
|
|
|
480
480
|
}
|
|
481
481
|
|
|
482
482
|
//#endregion
|
|
483
|
-
//#region src/
|
|
483
|
+
//#region src/custom-app/interpolate.ts
|
|
484
484
|
/**
|
|
485
485
|
* Interpolate `{{ params.X }}` and `{{ params.X | sqlquote }}` placeholders
|
|
486
486
|
* in a SQL template.
|
|
@@ -509,7 +509,7 @@ function interpolateSqlParams(sql, params) {
|
|
|
509
509
|
}
|
|
510
510
|
|
|
511
511
|
//#endregion
|
|
512
|
-
//#region src/
|
|
512
|
+
//#region src/custom-app/markdown.ts
|
|
513
513
|
/**
|
|
514
514
|
* Allowlist for `[text](url)` href values in agent-emitted markdown.
|
|
515
515
|
* Markdown comes from an LLM, which sits across an external trust
|
|
@@ -585,7 +585,7 @@ function isTableStart(lines, idx) {
|
|
|
585
585
|
}
|
|
586
586
|
|
|
587
587
|
//#endregion
|
|
588
|
-
//#region src/
|
|
588
|
+
//#region src/custom-app/query-cache.ts
|
|
589
589
|
const SWR_TTL_MS = 3e4;
|
|
590
590
|
const inflight = /* @__PURE__ */ new Map();
|
|
591
591
|
const cache = /* @__PURE__ */ new Map();
|
|
@@ -629,28 +629,48 @@ async function sharedQuery(fetcher, projectId, sql, db, opts = {}) {
|
|
|
629
629
|
}
|
|
630
630
|
|
|
631
631
|
//#endregion
|
|
632
|
-
//#region src/
|
|
632
|
+
//#region src/custom-app/react.tsx
|
|
633
633
|
function defaultFetcher(input, init) {
|
|
634
634
|
return fetch(input, {
|
|
635
635
|
credentials: "include",
|
|
636
636
|
...init
|
|
637
637
|
});
|
|
638
638
|
}
|
|
639
|
+
/**
|
|
640
|
+
* Resolve relative ("/…") request paths against `backendUrl` so the SDK's API
|
|
641
|
+
* calls reach a cross-origin oxy backend instead of the app's own origin.
|
|
642
|
+
*
|
|
643
|
+
* This is what lets a standalone dev app (e.g. served on `localhost:3005`)
|
|
644
|
+
* drive the wired shell — `shell-context`, Ask Oxygen agent asks, events —
|
|
645
|
+
* against oxy on another origin (`localhost:3000`) WITHOUT a same-origin dev
|
|
646
|
+
* proxy. The target origin must permit the app's origin (oxy's main `/api`
|
|
647
|
+
* allows configured dev origins + `credentials`); the external data API is a
|
|
648
|
+
* separate, wildcard-CORS surface.
|
|
649
|
+
*
|
|
650
|
+
* Opt-in: when `backendUrl` is unset the base fetcher is returned unchanged, so
|
|
651
|
+
* apps served same-origin by oxy keep their existing relative-URL behaviour.
|
|
652
|
+
* Absolute URLs and non-string inputs pass through untouched (no double-prefix).
|
|
653
|
+
*/
|
|
654
|
+
function withBackendBase(base, backendUrl) {
|
|
655
|
+
if (!backendUrl) return base;
|
|
656
|
+
const origin = backendUrl.replace(/\/+$/, "");
|
|
657
|
+
return (input, init) => base(typeof input === "string" && input.startsWith("/") ? origin + input : input, init);
|
|
658
|
+
}
|
|
639
659
|
const OxyAppContext = react.createContext(void 0);
|
|
640
660
|
/**
|
|
641
661
|
* Top-level provider. Loads the manifest once on mount; children only
|
|
642
662
|
* render after the manifest is ready (or the error fallback fires).
|
|
643
663
|
*/
|
|
644
664
|
function OxyAppProvider(props) {
|
|
645
|
-
const { manifestOptions, fallback, errorFallback, fetcher: fetcherProp, children } = props;
|
|
646
|
-
const fetcher = fetcherProp ?? defaultFetcher;
|
|
665
|
+
const { manifestOptions, fallback, errorFallback, fetcher: fetcherProp, backendUrl, children } = props;
|
|
666
|
+
const fetcher = react.useMemo(() => withBackendBase(fetcherProp ?? defaultFetcher, backendUrl), [fetcherProp, backendUrl]);
|
|
647
667
|
const [state, setState] = react.useState({
|
|
648
668
|
status: "loading",
|
|
649
669
|
fetcher
|
|
650
670
|
});
|
|
651
671
|
react.useEffect(() => {
|
|
652
672
|
let cancelled = false;
|
|
653
|
-
|
|
673
|
+
loadCustomAppManifest(manifestOptions).then((resolved) => {
|
|
654
674
|
if (!cancelled) setState({
|
|
655
675
|
status: "ready",
|
|
656
676
|
resolved,
|
|
@@ -659,7 +679,7 @@ function OxyAppProvider(props) {
|
|
|
659
679
|
}).catch((e) => {
|
|
660
680
|
if (!cancelled) setState({
|
|
661
681
|
status: "error",
|
|
662
|
-
error:
|
|
682
|
+
error: interpretCustomAppError(e),
|
|
663
683
|
fetcher
|
|
664
684
|
});
|
|
665
685
|
});
|
|
@@ -761,7 +781,7 @@ function useOxyApp() {
|
|
|
761
781
|
}
|
|
762
782
|
/**
|
|
763
783
|
* Execute an ad-hoc SQL query against the project linked to this
|
|
764
|
-
*
|
|
784
|
+
* custom app. The query is specified inline by the caller; no
|
|
765
785
|
* manifest declaration is involved.
|
|
766
786
|
*
|
|
767
787
|
* Re-runs whenever `input` or enabled `params` change. Use the
|
|
@@ -2292,10 +2312,10 @@ Object.defineProperty(exports, '__toESM', {
|
|
|
2292
2312
|
return __toESM;
|
|
2293
2313
|
}
|
|
2294
2314
|
});
|
|
2295
|
-
Object.defineProperty(exports, '
|
|
2315
|
+
Object.defineProperty(exports, '_resetCustomAppManifestCacheForTest', {
|
|
2296
2316
|
enumerable: true,
|
|
2297
2317
|
get: function () {
|
|
2298
|
-
return
|
|
2318
|
+
return _resetCustomAppManifestCacheForTest;
|
|
2299
2319
|
}
|
|
2300
2320
|
});
|
|
2301
2321
|
Object.defineProperty(exports, 'apiErrorFromResponse', {
|
|
@@ -2310,16 +2330,16 @@ Object.defineProperty(exports, 'getOxyAppLogger', {
|
|
|
2310
2330
|
return getOxyAppLogger;
|
|
2311
2331
|
}
|
|
2312
2332
|
});
|
|
2313
|
-
Object.defineProperty(exports, '
|
|
2333
|
+
Object.defineProperty(exports, 'interpretCustomAppError', {
|
|
2314
2334
|
enumerable: true,
|
|
2315
2335
|
get: function () {
|
|
2316
|
-
return
|
|
2336
|
+
return interpretCustomAppError;
|
|
2317
2337
|
}
|
|
2318
2338
|
});
|
|
2319
|
-
Object.defineProperty(exports, '
|
|
2339
|
+
Object.defineProperty(exports, 'loadCustomAppManifest', {
|
|
2320
2340
|
enumerable: true,
|
|
2321
2341
|
get: function () {
|
|
2322
|
-
return
|
|
2342
|
+
return loadCustomAppManifest;
|
|
2323
2343
|
}
|
|
2324
2344
|
});
|
|
2325
2345
|
Object.defineProperty(exports, 'readInjectedAppConfig', {
|
|
@@ -2382,4 +2402,4 @@ Object.defineProperty(exports, 'useTrackEvent', {
|
|
|
2382
2402
|
return useTrackEvent;
|
|
2383
2403
|
}
|
|
2384
2404
|
});
|
|
2385
|
-
//# sourceMappingURL=react-
|
|
2405
|
+
//# sourceMappingURL=react-BAiiXftp.cjs.map
|