@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.
@@ -2,7 +2,7 @@
2
2
  import * as React from "react";
3
3
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
4
4
 
5
- //#region src/customer-app/logger.ts
5
+ //#region src/custom-app/logger.ts
6
6
  let activeLogger = createConsoleLogger();
7
7
  /** Replace the global logger. Pass `null` to silence everything. */
8
8
  function setOxyAppLogger(logger) {
@@ -42,9 +42,9 @@ function silentLogger() {
42
42
  }
43
43
 
44
44
  //#endregion
45
- //#region src/customer-app/errors.ts
45
+ //#region src/custom-app/errors.ts
46
46
  /**
47
- * Error thrown by all customer-app hooks when an API call returns a
47
+ * Error thrown by all custom-app hooks when an API call returns a
48
48
  * non-2xx response. Carries the structured `code` + `hint` the server
49
49
  * emits so bundle UIs can render an actionable message instead of
50
50
  * "404: { ...json... }".
@@ -91,12 +91,12 @@ async function apiErrorFromResponse(resp) {
91
91
  }
92
92
  const ARCH_DOC = "internal-docs/customer-apps.md";
93
93
  /** Interpret a thrown error as a structured report for UI display. */
94
- function interpretCustomerAppError(err) {
94
+ function interpretCustomAppError(err) {
95
95
  const message = err instanceof Error ? err.message : String(err);
96
96
  if (/Failed to load oxy-app\.json.*HTTP 404/.test(message)) return {
97
97
  title: "Manifest not found",
98
98
  message,
99
- hint: "The bundle is being served, but oxy-app.json was not. Check that public/oxy-app.json is committed in the customer-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/.",
99
+ 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/.",
100
100
  docs: ARCH_DOC
101
101
  };
102
102
  if (/Failed to load oxy-app\.json/.test(message)) return {
@@ -132,7 +132,7 @@ function interpretCustomerAppError(err) {
132
132
  if (/^403:.*SELECT.*WITH/im.test(message)) return {
133
133
  title: "Query rejected — read-only endpoint",
134
134
  message,
135
- hint: "This proxy only runs SELECT or WITH queries. Mutations (INSERT/UPDATE/DELETE/DROP) are not allowed from customer-app bundles.",
135
+ hint: "This proxy only runs SELECT or WITH queries. Mutations (INSERT/UPDATE/DELETE/DROP) are not allowed from custom-app bundles.",
136
136
  docs: ARCH_DOC
137
137
  };
138
138
  if (/^403:/m.test(message)) return {
@@ -168,7 +168,7 @@ function interpretCustomerAppError(err) {
168
168
  if (/Unexpected token '<'|<!doctype/i.test(message)) return {
169
169
  title: "Fetched HTML where JSON was expected",
170
170
  message,
171
- 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 customer-app row is served at.",
171
+ 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.",
172
172
  docs: ARCH_DOC
173
173
  };
174
174
  return {
@@ -180,7 +180,7 @@ function interpretCustomerAppError(err) {
180
180
  }
181
181
 
182
182
  //#endregion
183
- //#region src/customer-app/inject.ts
183
+ //#region src/custom-app/inject.ts
184
184
  /**
185
185
  * Read the runtime app-config oxy injected at serve time. Returns
186
186
  * `undefined` outside the browser or when the global isn't set
@@ -193,18 +193,18 @@ function readInjectedAppConfig() {
193
193
  }
194
194
 
195
195
  //#endregion
196
- //#region src/customer-app/manifest.ts
196
+ //#region src/custom-app/manifest.ts
197
197
  let cached = null;
198
198
  /**
199
199
  * Load + validate the manifest. Cached after the first call so callers
200
200
  * can invoke this from every component without coordinating.
201
201
  */
202
- function loadCustomerAppManifest(options = {}) {
202
+ function loadCustomAppManifest(options = {}) {
203
203
  if (!cached) cached = fetchAndValidate(options);
204
204
  return cached;
205
205
  }
206
206
  /** For tests: reset the cache between runs. */
207
- function _resetCustomerAppManifestCacheForTest() {
207
+ function _resetCustomAppManifestCacheForTest() {
208
208
  cached = null;
209
209
  }
210
210
  async function fetchAndValidate(options) {
@@ -226,7 +226,7 @@ async function fetchAndValidate(options) {
226
226
  status: res.status,
227
227
  statusText: res.statusText
228
228
  });
229
- throw new Error(`Failed to load oxy-app.json from ${manifestUrl} (HTTP ${res.status}). The customer-app repo must commit this file alongside the bundle.`);
229
+ 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.`);
230
230
  }
231
231
  const manifest = validateManifest(await res.json(), manifestUrl);
232
232
  const resolved = {
@@ -291,7 +291,7 @@ const FUNCTION_NAME_RE = /^[a-z][a-z0-9-]{0,63}$/;
291
291
  /**
292
292
  * Validate the optional `functions` map. Each key is a function name;
293
293
  * each value declares how the function is invoked. Mirrors the
294
- * server-side validation in `customer_apps_publish.rs` so a bad
294
+ * server-side validation in `custom_apps_publish.rs` so a bad
295
295
  * manifest fails at build, not at publish.
296
296
  */
297
297
  function validateFunctions(raw) {
@@ -369,7 +369,7 @@ function isRecord(v) {
369
369
  }
370
370
 
371
371
  //#endregion
372
- //#region src/customer-app/function-invoke.ts
372
+ //#region src/custom-app/function-invoke.ts
373
373
  const inflight$1 = /* @__PURE__ */ new Map();
374
374
  /**
375
375
  * Dedup key for an invocation: function name + its (stable-serialized) body,
@@ -395,7 +395,7 @@ function sharedFunctionInvoke(key, run) {
395
395
  }
396
396
 
397
397
  //#endregion
398
- //#region src/customer-app/function-sse.ts
398
+ //#region src/custom-app/function-sse.ts
399
399
  /**
400
400
  * Read a `text/event-stream` function response to completion. Resolves with the
401
401
  * decoded result + captured logs, or rejects (with `.logs` attached) on an
@@ -452,7 +452,7 @@ async function readFunctionSseStream(resp) {
452
452
  }
453
453
 
454
454
  //#endregion
455
- //#region src/customer-app/interpolate.ts
455
+ //#region src/custom-app/interpolate.ts
456
456
  /**
457
457
  * Interpolate `{{ params.X }}` and `{{ params.X | sqlquote }}` placeholders
458
458
  * in a SQL template.
@@ -481,7 +481,7 @@ function interpolateSqlParams(sql, params) {
481
481
  }
482
482
 
483
483
  //#endregion
484
- //#region src/customer-app/markdown.ts
484
+ //#region src/custom-app/markdown.ts
485
485
  /**
486
486
  * Allowlist for `[text](url)` href values in agent-emitted markdown.
487
487
  * Markdown comes from an LLM, which sits across an external trust
@@ -557,7 +557,7 @@ function isTableStart(lines, idx) {
557
557
  }
558
558
 
559
559
  //#endregion
560
- //#region src/customer-app/query-cache.ts
560
+ //#region src/custom-app/query-cache.ts
561
561
  const SWR_TTL_MS = 3e4;
562
562
  const inflight = /* @__PURE__ */ new Map();
563
563
  const cache = /* @__PURE__ */ new Map();
@@ -601,28 +601,48 @@ async function sharedQuery(fetcher, projectId, sql, db, opts = {}) {
601
601
  }
602
602
 
603
603
  //#endregion
604
- //#region src/customer-app/react.tsx
604
+ //#region src/custom-app/react.tsx
605
605
  function defaultFetcher(input, init) {
606
606
  return fetch(input, {
607
607
  credentials: "include",
608
608
  ...init
609
609
  });
610
610
  }
611
+ /**
612
+ * Resolve relative ("/…") request paths against `backendUrl` so the SDK's API
613
+ * calls reach a cross-origin oxy backend instead of the app's own origin.
614
+ *
615
+ * This is what lets a standalone dev app (e.g. served on `localhost:3005`)
616
+ * drive the wired shell — `shell-context`, Ask Oxygen agent asks, events —
617
+ * against oxy on another origin (`localhost:3000`) WITHOUT a same-origin dev
618
+ * proxy. The target origin must permit the app's origin (oxy's main `/api`
619
+ * allows configured dev origins + `credentials`); the external data API is a
620
+ * separate, wildcard-CORS surface.
621
+ *
622
+ * Opt-in: when `backendUrl` is unset the base fetcher is returned unchanged, so
623
+ * apps served same-origin by oxy keep their existing relative-URL behaviour.
624
+ * Absolute URLs and non-string inputs pass through untouched (no double-prefix).
625
+ */
626
+ function withBackendBase(base, backendUrl) {
627
+ if (!backendUrl) return base;
628
+ const origin = backendUrl.replace(/\/+$/, "");
629
+ return (input, init) => base(typeof input === "string" && input.startsWith("/") ? origin + input : input, init);
630
+ }
611
631
  const OxyAppContext = React.createContext(void 0);
612
632
  /**
613
633
  * Top-level provider. Loads the manifest once on mount; children only
614
634
  * render after the manifest is ready (or the error fallback fires).
615
635
  */
616
636
  function OxyAppProvider(props) {
617
- const { manifestOptions, fallback, errorFallback, fetcher: fetcherProp, children } = props;
618
- const fetcher = fetcherProp ?? defaultFetcher;
637
+ const { manifestOptions, fallback, errorFallback, fetcher: fetcherProp, backendUrl, children } = props;
638
+ const fetcher = React.useMemo(() => withBackendBase(fetcherProp ?? defaultFetcher, backendUrl), [fetcherProp, backendUrl]);
619
639
  const [state, setState] = React.useState({
620
640
  status: "loading",
621
641
  fetcher
622
642
  });
623
643
  React.useEffect(() => {
624
644
  let cancelled = false;
625
- loadCustomerAppManifest(manifestOptions).then((resolved) => {
645
+ loadCustomAppManifest(manifestOptions).then((resolved) => {
626
646
  if (!cancelled) setState({
627
647
  status: "ready",
628
648
  resolved,
@@ -631,7 +651,7 @@ function OxyAppProvider(props) {
631
651
  }).catch((e) => {
632
652
  if (!cancelled) setState({
633
653
  status: "error",
634
- error: interpretCustomerAppError(e),
654
+ error: interpretCustomAppError(e),
635
655
  fetcher
636
656
  });
637
657
  });
@@ -733,7 +753,7 @@ function useOxyApp() {
733
753
  }
734
754
  /**
735
755
  * Execute an ad-hoc SQL query against the project linked to this
736
- * customer app. The query is specified inline by the caller; no
756
+ * custom app. The query is specified inline by the caller; no
737
757
  * manifest declaration is involved.
738
758
  *
739
759
  * Re-runs whenever `input` or enabled `params` change. Use the
@@ -2234,5 +2254,5 @@ const styles = {
2234
2254
  };
2235
2255
 
2236
2256
  //#endregion
2237
- export { interpretCustomerAppError as _, useFunction as a, useQuery as c, useTrackEvent as d, _resetCustomerAppManifestCacheForTest as f, apiErrorFromResponse as g, OxyApiError as h, useAgentRun as i, useResolvedManifest as l, readInjectedAppConfig as m, OxyAppProvider as n, useOxyApp as o, loadCustomerAppManifest as p, OxyChat as r, useProcedureRun as s, OxyAnswer as t, useSemanticQuery as u, getOxyAppLogger as v, setOxyAppLogger as y };
2238
- //# sourceMappingURL=react-DArzs6_l.mjs.map
2257
+ 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 };
2258
+ //# sourceMappingURL=react-5HGW_0oy.mjs.map