@syntrologie/runtime-sdk 2.10.0 → 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/dist/react.js CHANGED
@@ -1,9 +1,10 @@
1
1
  import {
2
2
  Syntro
3
- } from "./chunk-OIDBMIRB.js";
4
- import "./chunk-R5DNAIRI.js";
5
- import "./chunk-XDYJ64IN.js";
6
- import "./chunk-BU4Z6PD7.js";
3
+ } from "./chunk-H3FAYTUV.js";
4
+ import "./chunk-NBFQGKSV.js";
5
+ import "./chunk-37TTQRH5.js";
6
+ import "./chunk-Q77NT67W.js";
7
+ import "./chunk-JMHRHAEL.js";
7
8
 
8
9
  // src/react.tsx
9
10
  import { createContext, useContext, useEffect, useRef, useState } from "react";
package/dist/react.js.map CHANGED
@@ -2,6 +2,6 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/react.tsx"],
4
4
  "sourcesContent": ["/**\n * React bindings for the Syntro SDK.\n *\n * Usage:\n * ```tsx\n * import { SyntroProvider, useSyntro } from '@syntrologie/runtime-sdk/react';\n *\n * function App() {\n * return (\n * <SyntroProvider token=\"syn_xxx\">\n * <MyApp />\n * </SyntroProvider>\n * );\n * }\n *\n * function MyComponent() {\n * const { canvas, experiments, telemetry, isReady } = useSyntro();\n * // ...\n * }\n * ```\n */\nimport { createContext, type ReactNode, useContext, useEffect, useRef, useState } from 'react';\n\nimport type { SmartCanvasHandle } from './api';\nimport { Syntro, type SyntroInitOptions, type SyntroInitResult } from './bootstrap';\nimport type { ExperimentClient } from './experiments/types';\nimport type { TelemetryClient } from './telemetry/types';\n\nexport interface SyntroContextValue {\n /** The SmartCanvas handle */\n canvas: SmartCanvasHandle | null;\n /** The experiment client */\n experiments: ExperimentClient | null;\n /** The telemetry client */\n telemetry: TelemetryClient | null;\n /** Whether the SDK has finished initializing */\n isReady: boolean;\n /** Any error that occurred during initialization */\n error: Error | null;\n}\n\nconst SyntroContext = createContext<SyntroContextValue | null>(null);\n\n// Global tracking to handle React Strict Mode double-mounting\nlet globalInitPromise: Promise<SyntroInitResult> | null = null;\nlet globalInitToken: string | null = null;\n\nexport interface SyntroProviderProps {\n /**\n * The Syntro token containing all credentials.\n */\n token: string;\n\n /**\n * Optional canvas configuration overrides.\n */\n canvasOptions?: SyntroInitOptions['canvas'];\n\n /**\n * Custom config fetcher to override the default experiment-based fetcher.\n * Use this for local development or when bypassing the experiment server.\n */\n fetcher?: SyntroInitOptions['fetcher'];\n\n /**\n * Children to render.\n */\n children: ReactNode;\n\n /**\n * Called when initialization completes.\n */\n onReady?: (result: SyntroInitResult) => void;\n\n /**\n * Called when initialization fails.\n */\n onError?: (error: Error) => void;\n}\n\n/**\n * Provider component that initializes the Syntro SDK.\n *\n * Place this at the root of your app or at the top of any subtree\n * that needs access to the SDK.\n */\nexport function SyntroProvider({\n token,\n canvasOptions,\n fetcher,\n children,\n onReady,\n onError,\n}: SyntroProviderProps) {\n const [state, setState] = useState<SyntroContextValue>({\n canvas: null,\n experiments: null,\n telemetry: null,\n isReady: false,\n error: null,\n });\n\n const initRef = useRef(false);\n const handleRef = useRef<SmartCanvasHandle | null>(null);\n\n useEffect(() => {\n if (!token) return;\n\n // Reuse existing init if same token (handles React Strict Mode remounts)\n if (globalInitPromise && globalInitToken === token) {\n globalInitPromise.then((result) => {\n handleRef.current = result.canvas;\n setState({\n canvas: result.canvas,\n experiments: result.experiments ?? null,\n telemetry: result.telemetry ?? null,\n isReady: true,\n error: null,\n });\n });\n return;\n }\n\n // Prevent double init\n if (initRef.current) return;\n initRef.current = true;\n\n globalInitToken = token;\n globalInitPromise = Syntro.init({ token, canvas: canvasOptions, fetcher });\n\n globalInitPromise\n .then((result) => {\n handleRef.current = result.canvas;\n setState({\n canvas: result.canvas,\n experiments: result.experiments ?? null,\n telemetry: result.telemetry ?? null,\n isReady: true,\n error: null,\n });\n onReady?.(result);\n })\n .catch((err) => {\n const error = err instanceof Error ? err : new Error(String(err));\n setState((prev) => ({ ...prev, error, isReady: true }));\n onError?.(error);\n // Clear global state on error so retry is possible\n globalInitPromise = null;\n globalInitToken = null;\n });\n\n // Don't destroy on unmount in dev mode - React Strict Mode will remount\n // The canvas persists and will be reused on remount\n }, [token, canvasOptions, fetcher, onError, onReady]);\n\n return <SyntroContext.Provider value={state}>{children}</SyntroContext.Provider>;\n}\n\n/**\n * Hook to access the Syntro SDK.\n *\n * Must be used within a SyntroProvider.\n *\n * @returns The SDK context containing canvas, experiments, telemetry, and status\n */\nexport function useSyntro(): SyntroContextValue {\n const context = useContext(SyntroContext);\n if (!context) {\n throw new Error('useSyntro must be used within a SyntroProvider');\n }\n return context;\n}\n\n/**\n * Hook to check if the SDK is ready.\n *\n * Shorthand for `useSyntro().isReady`.\n */\nexport function useSyntroReady(): boolean {\n return useSyntro().isReady;\n}\n\n/**\n * Hook to access the experiment client.\n *\n * @returns The experiment client, or null if not configured\n */\nexport function useSyntroExperiments(): ExperimentClient | null {\n return useSyntro().experiments;\n}\n\n/**\n * Hook to access the telemetry client.\n *\n * @returns The telemetry client, or null if not configured\n */\nexport function useSyntroTelemetry(): TelemetryClient | null {\n return useSyntro().telemetry;\n}\n\n/**\n * Hook to access the canvas handle.\n *\n * @returns The canvas handle, or null if not ready\n */\nexport function useSyntroCanvas(): SmartCanvasHandle | null {\n return useSyntro().canvas;\n}\n"],
5
- "mappings": ";;;;;;;;AAqBA,SAAS,eAA+B,YAAY,WAAW,QAAQ,gBAAgB;AAsI9E;AAlHT,IAAM,gBAAgB,cAAyC,IAAI;AAGnE,IAAI,oBAAsD;AAC1D,IAAI,kBAAiC;AAyC9B,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAwB;AACtB,QAAM,CAAC,OAAO,QAAQ,IAAI,SAA6B;AAAA,IACrD,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,WAAW;AAAA,IACX,SAAS;AAAA,IACT,OAAO;AAAA,EACT,CAAC;AAED,QAAM,UAAU,OAAO,KAAK;AAC5B,QAAM,YAAY,OAAiC,IAAI;AAEvD,YAAU,MAAM;AACd,QAAI,CAAC,MAAO;AAGZ,QAAI,qBAAqB,oBAAoB,OAAO;AAClD,wBAAkB,KAAK,CAAC,WAAW;AA9GzC;AA+GQ,kBAAU,UAAU,OAAO;AAC3B,iBAAS;AAAA,UACP,QAAQ,OAAO;AAAA,UACf,cAAa,YAAO,gBAAP,YAAsB;AAAA,UACnC,YAAW,YAAO,cAAP,YAAoB;AAAA,UAC/B,SAAS;AAAA,UACT,OAAO;AAAA,QACT,CAAC;AAAA,MACH,CAAC;AACD;AAAA,IACF;AAGA,QAAI,QAAQ,QAAS;AACrB,YAAQ,UAAU;AAElB,sBAAkB;AAClB,wBAAoB,OAAO,KAAK,EAAE,OAAO,QAAQ,eAAe,QAAQ,CAAC;AAEzE,sBACG,KAAK,CAAC,WAAW;AAnIxB;AAoIQ,gBAAU,UAAU,OAAO;AAC3B,eAAS;AAAA,QACP,QAAQ,OAAO;AAAA,QACf,cAAa,YAAO,gBAAP,YAAsB;AAAA,QACnC,YAAW,YAAO,cAAP,YAAoB;AAAA,QAC/B,SAAS;AAAA,QACT,OAAO;AAAA,MACT,CAAC;AACD,yCAAU;AAAA,IACZ,CAAC,EACA,MAAM,CAAC,QAAQ;AACd,YAAM,QAAQ,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAChE,eAAS,CAAC,UAAU,EAAE,GAAG,MAAM,OAAO,SAAS,KAAK,EAAE;AACtD,yCAAU;AAEV,0BAAoB;AACpB,wBAAkB;AAAA,IACpB,CAAC;AAAA,EAIL,GAAG,CAAC,OAAO,eAAe,SAAS,SAAS,OAAO,CAAC;AAEpD,SAAO,oBAAC,cAAc,UAAd,EAAuB,OAAO,OAAQ,UAAS;AACzD;AASO,SAAS,YAAgC;AAC9C,QAAM,UAAU,WAAW,aAAa;AACxC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AACA,SAAO;AACT;AAOO,SAAS,iBAA0B;AACxC,SAAO,UAAU,EAAE;AACrB;AAOO,SAAS,uBAAgD;AAC9D,SAAO,UAAU,EAAE;AACrB;AAOO,SAAS,qBAA6C;AAC3D,SAAO,UAAU,EAAE;AACrB;AAOO,SAAS,kBAA4C;AAC1D,SAAO,UAAU,EAAE;AACrB;",
5
+ "mappings": ";;;;;;;;;AAqBA,SAAS,eAA+B,YAAY,WAAW,QAAQ,gBAAgB;AAsI9E;AAlHT,IAAM,gBAAgB,cAAyC,IAAI;AAGnE,IAAI,oBAAsD;AAC1D,IAAI,kBAAiC;AAyC9B,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAwB;AACtB,QAAM,CAAC,OAAO,QAAQ,IAAI,SAA6B;AAAA,IACrD,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,WAAW;AAAA,IACX,SAAS;AAAA,IACT,OAAO;AAAA,EACT,CAAC;AAED,QAAM,UAAU,OAAO,KAAK;AAC5B,QAAM,YAAY,OAAiC,IAAI;AAEvD,YAAU,MAAM;AACd,QAAI,CAAC,MAAO;AAGZ,QAAI,qBAAqB,oBAAoB,OAAO;AAClD,wBAAkB,KAAK,CAAC,WAAW;AA9GzC;AA+GQ,kBAAU,UAAU,OAAO;AAC3B,iBAAS;AAAA,UACP,QAAQ,OAAO;AAAA,UACf,cAAa,YAAO,gBAAP,YAAsB;AAAA,UACnC,YAAW,YAAO,cAAP,YAAoB;AAAA,UAC/B,SAAS;AAAA,UACT,OAAO;AAAA,QACT,CAAC;AAAA,MACH,CAAC;AACD;AAAA,IACF;AAGA,QAAI,QAAQ,QAAS;AACrB,YAAQ,UAAU;AAElB,sBAAkB;AAClB,wBAAoB,OAAO,KAAK,EAAE,OAAO,QAAQ,eAAe,QAAQ,CAAC;AAEzE,sBACG,KAAK,CAAC,WAAW;AAnIxB;AAoIQ,gBAAU,UAAU,OAAO;AAC3B,eAAS;AAAA,QACP,QAAQ,OAAO;AAAA,QACf,cAAa,YAAO,gBAAP,YAAsB;AAAA,QACnC,YAAW,YAAO,cAAP,YAAoB;AAAA,QAC/B,SAAS;AAAA,QACT,OAAO;AAAA,MACT,CAAC;AACD,yCAAU;AAAA,IACZ,CAAC,EACA,MAAM,CAAC,QAAQ;AACd,YAAM,QAAQ,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAChE,eAAS,CAAC,UAAU,EAAE,GAAG,MAAM,OAAO,SAAS,KAAK,EAAE;AACtD,yCAAU;AAEV,0BAAoB;AACpB,wBAAkB;AAAA,IACpB,CAAC;AAAA,EAIL,GAAG,CAAC,OAAO,eAAe,SAAS,SAAS,OAAO,CAAC;AAEpD,SAAO,oBAAC,cAAc,UAAd,EAAuB,OAAO,OAAQ,UAAS;AACzD;AASO,SAAS,YAAgC;AAC9C,QAAM,UAAU,WAAW,aAAa;AACxC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AACA,SAAO;AACT;AAOO,SAAS,iBAA0B;AACxC,SAAO,UAAU,EAAE;AACrB;AAOO,SAAS,uBAAgD;AAC9D,SAAO,UAAU,EAAE;AACrB;AAOO,SAAS,qBAA6C;AAC3D,SAAO,UAAU,EAAE;AACrB;AAOO,SAAS,kBAA4C;AAC1D,SAAO,UAAU,EAAE;AACrB;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,32 @@
1
+ import "./chunk-JMHRHAEL.js";
2
+
3
+ // src/telemetry/replayMirror.ts
4
+ function setupReplayMirror(options) {
5
+ const { posthogHost, mirrorEndpoint, sessionIdHeader = "X-Syntro-Session-Id" } = options;
6
+ const recordingPath = `${posthogHost}/s/`;
7
+ const originalFetch = globalThis.fetch.bind(globalThis);
8
+ globalThis.fetch = (input, init) => {
9
+ var _a;
10
+ const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
11
+ const result = originalFetch(input, init);
12
+ if (url.startsWith(recordingPath)) {
13
+ originalFetch(mirrorEndpoint, {
14
+ method: (_a = init == null ? void 0 : init.method) != null ? _a : "POST",
15
+ body: init == null ? void 0 : init.body,
16
+ headers: {
17
+ ...init == null ? void 0 : init.headers,
18
+ [sessionIdHeader]: "syntro-session"
19
+ }
20
+ }).catch(() => {
21
+ });
22
+ }
23
+ return result;
24
+ };
25
+ return () => {
26
+ globalThis.fetch = originalFetch;
27
+ };
28
+ }
29
+ export {
30
+ setupReplayMirror
31
+ };
32
+ //# sourceMappingURL=replayMirror-QZ3GQ527.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/telemetry/replayMirror.ts"],
4
+ "sourcesContent": ["interface ReplayMirrorOptions {\n posthogHost: string;\n mirrorEndpoint: string;\n sessionIdHeader?: string;\n}\n\nexport function setupReplayMirror(options: ReplayMirrorOptions): () => void {\n const { posthogHost, mirrorEndpoint, sessionIdHeader = 'X-Syntro-Session-Id' } = options;\n const recordingPath = `${posthogHost}/s/`;\n const originalFetch = globalThis.fetch.bind(globalThis);\n\n globalThis.fetch = (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;\n\n const result = originalFetch(input, init);\n\n if (url.startsWith(recordingPath)) {\n originalFetch(mirrorEndpoint, {\n method: init?.method ?? 'POST',\n body: init?.body,\n headers: {\n ...(init?.headers as Record<string, string>),\n [sessionIdHeader]: 'syntro-session',\n },\n }).catch(() => {\n // Silently ignore mirror failures\n });\n }\n\n return result;\n };\n\n return () => {\n globalThis.fetch = originalFetch;\n };\n}\n"],
5
+ "mappings": ";;;AAMO,SAAS,kBAAkB,SAA0C;AAC1E,QAAM,EAAE,aAAa,gBAAgB,kBAAkB,sBAAsB,IAAI;AACjF,QAAM,gBAAgB,GAAG,WAAW;AACpC,QAAM,gBAAgB,WAAW,MAAM,KAAK,UAAU;AAEtD,aAAW,QAAQ,CAAC,OAA0B,SAA0C;AAX1F;AAYI,UAAM,MAAM,OAAO,UAAU,WAAW,QAAQ,iBAAiB,MAAM,MAAM,OAAO,MAAM;AAE1F,UAAM,SAAS,cAAc,OAAO,IAAI;AAExC,QAAI,IAAI,WAAW,aAAa,GAAG;AACjC,oBAAc,gBAAgB;AAAA,QAC5B,SAAQ,kCAAM,WAAN,YAAgB;AAAA,QACxB,MAAM,6BAAM;AAAA,QACZ,SAAS;AAAA,UACP,GAAI,6BAAM;AAAA,UACV,CAAC,eAAe,GAAG;AAAA,QACrB;AAAA,MACF,CAAC,EAAE,MAAM,MAAM;AAAA,MAEf,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAEA,SAAO,MAAM;AACX,eAAW,QAAQ;AAAA,EACrB;AACF;",
6
+ "names": []
7
+ }