@xeonr/renderer-sdk 1.1.0 → 1.5.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.
@@ -1,5 +1,60 @@
1
- import { useState, useRef, useEffect, useMemo } from 'react';
1
+ import { useState, useEffect, useMemo } from 'react';
2
2
  import { RendererClient } from '../client.js';
3
+ // One RendererClient per page. Multiple `useRendererClient()` calls
4
+ // (different components subscribing to the same state) all share the
5
+ // singleton — previously each call spawned its own client, which
6
+ // caused duplicate `window.error` / `unhandledrejection` listeners
7
+ // (so every crash got reported N times), duplicate `uplim:ready`
8
+ // pings, and state divergence between instances.
9
+ //
10
+ // Page lifetime: the iframe is full-reloaded for HMR / test, so the
11
+ // module-level singleton lives exactly as long as it should. SDK-level
12
+ // HMR (developer working on the SDK in monorepo, hot-replacing this
13
+ // module) is handled via `import.meta.hot.dispose` at the bottom of
14
+ // the file.
15
+ let sharedClient = null;
16
+ let sharedClientOptionsKey = null;
17
+ function optionsKey(options) {
18
+ if (!options)
19
+ return '';
20
+ // Stable order so { a, b } and { b, a } produce the same key. Used
21
+ // only for the dev-mode mismatch warning — never for behavior.
22
+ const entries = Object.entries(options).sort(([a], [b]) => a.localeCompare(b));
23
+ return JSON.stringify(entries);
24
+ }
25
+ function getSharedClient(options) {
26
+ if (sharedClient) {
27
+ const key = optionsKey(options);
28
+ // Best-effort dev nudge: if a later mount passes different
29
+ // options than the first one, those options are silently
30
+ // ignored. Only flag when keys differ AND the later caller
31
+ // passed non-empty options (passing nothing is the common
32
+ // case for downstream subscribers).
33
+ if (key && sharedClientOptionsKey !== null && key !== sharedClientOptionsKey) {
34
+ // eslint-disable-next-line no-console
35
+ console.warn('[uplim] useRendererClient called with different options after first call; ' +
36
+ 'later options are ignored (the client is a per-page singleton).');
37
+ }
38
+ return sharedClient;
39
+ }
40
+ sharedClient = new RendererClient(options);
41
+ sharedClientOptionsKey = optionsKey(options);
42
+ return sharedClient;
43
+ }
44
+ // SDK-dev HMR cleanup: when this module is hot-replaced (e.g. someone
45
+ // editing the SDK with the renderer harness running), detach the old
46
+ // client's listeners before the new module evaluates. Prod / non-HMR
47
+ // builds skip the entire block — `import.meta.hot` is undefined.
48
+ const maybeHot = import.meta.hot;
49
+ if (maybeHot) {
50
+ maybeHot.dispose(() => {
51
+ if (sharedClient) {
52
+ sharedClient.destroy();
53
+ sharedClient = null;
54
+ sharedClientOptionsKey = null;
55
+ }
56
+ });
57
+ }
3
58
  /**
4
59
  * Apply the host's theme to the renderer document. Two distinct effects:
5
60
  *
@@ -42,22 +97,23 @@ function applyThemeToDocument(theme) {
42
97
  * ```
43
98
  */
44
99
  export function useRendererClient(options) {
45
- const clientRef = useRef(null);
46
- // Lazy-init the client (only once)
47
- if (clientRef.current === null) {
48
- clientRef.current = new RendererClient(options);
49
- }
50
- const client = clientRef.current;
51
- const [connected, setConnected] = useState(false);
52
- const [scope, setScope] = useState(null);
53
- const [renderingType, setRenderingType] = useState(null);
54
- const [token, setToken] = useState(null);
55
- const [tokenExpiresAt, setTokenExpiresAt] = useState(null);
56
- const [theme, setTheme] = useState('light');
57
- const [config, setConfig] = useState(null);
58
- const [entrypoint, setEntrypoint] = useState(null);
59
- const [apiBaseUrl, setApiBaseUrl] = useState(null);
60
- const [path, setPath] = useState('/');
100
+ const client = getSharedClient(options);
101
+ // Initial state read directly from the client handles late
102
+ // subscribers (a second `useRendererClient` mount that happens
103
+ // after init has already fired). Without this, the late mount
104
+ // would sit at `connected: false` forever because onInit only
105
+ // fires for NEW init events, not for already-received state.
106
+ const [connected, setConnected] = useState(() => client.isConnected());
107
+ const [scope, setScope] = useState(() => client.getScope());
108
+ const [renderingType, setRenderingType] = useState(() => client.getRenderingType());
109
+ const [token, setToken] = useState(() => client.getToken());
110
+ const [tokenExpiresAt, setTokenExpiresAt] = useState(() => client.getTokenExpiresAt());
111
+ const [theme, setTheme] = useState(() => client.getTheme());
112
+ const [config, setConfig] = useState(() => client.getConfig());
113
+ const [entrypoint, setEntrypoint] = useState(() => client.getEntrypoint());
114
+ const [apiBaseUrl, setApiBaseUrl] = useState(() => client.getApiBaseUrl());
115
+ const [resource, setResource] = useState(() => client.getResource());
116
+ const [path, setPath] = useState(() => client.getPath());
61
117
  useEffect(() => {
62
118
  const unsubInit = client.onInit((payload) => {
63
119
  setConnected(true);
@@ -69,6 +125,7 @@ export function useRendererClient(options) {
69
125
  setConfig(payload.config);
70
126
  setEntrypoint(payload.entrypoint);
71
127
  setApiBaseUrl(payload.apiBaseUrl);
128
+ setResource(payload.resource ?? null);
72
129
  setPath(client.getPath());
73
130
  applyThemeToDocument(payload.theme);
74
131
  });
@@ -88,13 +145,20 @@ export function useRendererClient(options) {
88
145
  unsubTheme();
89
146
  unsubToken();
90
147
  unsubNavigate();
91
- client.destroy();
148
+ // NB: do NOT destroy() here — the client is a per-page
149
+ // singleton, not a per-component instance. Component
150
+ // unmounts (route changes / strict-mode double-mount /
151
+ // React render-time tearing) shouldn't kill the shared
152
+ // state. The iframe full-reload tears the singleton down
153
+ // implicitly when the page goes away; SDK-level HMR is
154
+ // handled by import.meta.hot.dispose at the top of file.
92
155
  };
93
156
  }, [client]);
94
157
  const methods = useMemo(() => ({
95
158
  openUpload: (uploadId) => client.openUpload(uploadId),
96
159
  requestToken: () => client.requestToken(),
97
160
  close: () => client.close(),
161
+ markReady: () => client.signalReady(),
98
162
  apiAdapter: client.getApiAdapter(),
99
163
  }), [client]);
100
164
  return {
@@ -107,6 +171,7 @@ export function useRendererClient(options) {
107
171
  config,
108
172
  entrypoint,
109
173
  apiBaseUrl,
174
+ resource,
110
175
  path,
111
176
  client,
112
177
  ...methods,
@@ -1 +1 @@
1
- {"version":3,"file":"useRendererClient.js","sourceRoot":"","sources":["../../src/react/useRendererClient.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useRendererClient.js","sourceRoot":"","sources":["../../src/react/useRendererClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Hook for surfacing async failures to `<RendererErrorBoundary>` (and from
3
+ * there to the host's crash overlay + telemetry).
4
+ *
5
+ * Renderers shouldn't render their own "Upload not found" / "Failed to
6
+ * load" inline UI — those are still crashes from a telemetry standpoint,
7
+ * and the host already owns a polished overlay with reload + fallback
8
+ * actions. This hook lets a renderer take an error caught in an async
9
+ * context (fetch `.catch()`, useEffect cleanup, etc.) and route it to
10
+ * the host instead of rendering a half-broken inline state.
11
+ *
12
+ * Pattern:
13
+ *
14
+ * ```tsx
15
+ * const reportFatal = useReportFatalError();
16
+ * useEffect(() => {
17
+ * client.getUpload(...).catch(reportFatal);
18
+ * }, []);
19
+ * ```
20
+ *
21
+ * Mechanics: we keep an error in component state. When set, the *next*
22
+ * render throws it — React's error-handling pipeline catches the throw
23
+ * and bubbles to the nearest boundary. From there
24
+ * `RendererErrorBoundary.componentDidCatch` reports the crash to the
25
+ * host and renders nothing, and the host overlay (Reload / Copy /
26
+ * Fallback) takes over the visible iframe area.
27
+ *
28
+ * Why state-then-throw rather than a direct `throw err`? You can't
29
+ * throw to React from async code — React only sees throws that happen
30
+ * during render or in event handlers. Routing through state ensures
31
+ * the throw lands inside the render phase.
32
+ *
33
+ * The returned callback is stable across renders so it's safe to drop
34
+ * straight into a `.catch()`.
35
+ */
36
+ export declare function useReportFatalError(): (err: unknown) => void;
37
+ //# sourceMappingURL=useReportFatalError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useReportFatalError.d.ts","sourceRoot":"","sources":["../../src/react/useReportFatalError.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,mBAAmB,IAAI,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAiC5D"}
@@ -0,0 +1,71 @@
1
+ import { useCallback, useState } from 'react';
2
+ /**
3
+ * Hook for surfacing async failures to `<RendererErrorBoundary>` (and from
4
+ * there to the host's crash overlay + telemetry).
5
+ *
6
+ * Renderers shouldn't render their own "Upload not found" / "Failed to
7
+ * load" inline UI — those are still crashes from a telemetry standpoint,
8
+ * and the host already owns a polished overlay with reload + fallback
9
+ * actions. This hook lets a renderer take an error caught in an async
10
+ * context (fetch `.catch()`, useEffect cleanup, etc.) and route it to
11
+ * the host instead of rendering a half-broken inline state.
12
+ *
13
+ * Pattern:
14
+ *
15
+ * ```tsx
16
+ * const reportFatal = useReportFatalError();
17
+ * useEffect(() => {
18
+ * client.getUpload(...).catch(reportFatal);
19
+ * }, []);
20
+ * ```
21
+ *
22
+ * Mechanics: we keep an error in component state. When set, the *next*
23
+ * render throws it — React's error-handling pipeline catches the throw
24
+ * and bubbles to the nearest boundary. From there
25
+ * `RendererErrorBoundary.componentDidCatch` reports the crash to the
26
+ * host and renders nothing, and the host overlay (Reload / Copy /
27
+ * Fallback) takes over the visible iframe area.
28
+ *
29
+ * Why state-then-throw rather than a direct `throw err`? You can't
30
+ * throw to React from async code — React only sees throws that happen
31
+ * during render or in event handlers. Routing through state ensures
32
+ * the throw lands inside the render phase.
33
+ *
34
+ * The returned callback is stable across renders so it's safe to drop
35
+ * straight into a `.catch()`.
36
+ */
37
+ export function useReportFatalError() {
38
+ // Generic state slot — we never read the value, only use the
39
+ // updater. We narrow to `never` so TypeScript stops us from
40
+ // accidentally using it as data anywhere.
41
+ const [, setState] = useState();
42
+ return useCallback((err) => {
43
+ // Functional updater throws — React invokes it during the next
44
+ // render attempt, which puts the throw inside the render phase
45
+ // where boundaries can see it.
46
+ setState(() => {
47
+ if (err instanceof Error) {
48
+ throw err;
49
+ }
50
+ // Wrap non-Error throws so the boundary always sees a real
51
+ // Error instance with a meaningful .name / .message. Without
52
+ // this, `client.reportCrash` would synthesise a generic
53
+ // 'UnknownError' which loses the original payload's shape.
54
+ if (typeof err === 'string') {
55
+ throw new Error(err);
56
+ }
57
+ if (err && typeof err === 'object' && 'message' in err && typeof err.message === 'string') {
58
+ const wrapped = new Error(err.message);
59
+ if ('name' in err && typeof err.name === 'string') {
60
+ wrapped.name = err.name;
61
+ }
62
+ if ('stack' in err && typeof err.stack === 'string') {
63
+ wrapped.stack = err.stack;
64
+ }
65
+ throw wrapped;
66
+ }
67
+ throw new Error('Unknown renderer error');
68
+ });
69
+ }, []);
70
+ }
71
+ //# sourceMappingURL=useReportFatalError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useReportFatalError.js","sourceRoot":"","sources":["../../src/react/useReportFatalError.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,UAAU,mBAAmB;IAClC,6DAA6D;IAC7D,4DAA4D;IAC5D,0CAA0C;IAC1C,MAAM,CAAC,EAAE,QAAQ,CAAC,GAAG,QAAQ,EAAS,CAAC;IACvC,OAAO,WAAW,CAAC,CAAC,GAAY,EAAE,EAAE;QACnC,+DAA+D;QAC/D,+DAA+D;QAC/D,+BAA+B;QAC/B,QAAQ,CAAC,GAAG,EAAE;YACb,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;gBAC1B,MAAM,GAAG,CAAC;YACX,CAAC;YACD,2DAA2D;YAC3D,6DAA6D;YAC7D,wDAAwD;YACxD,2DAA2D;YAC3D,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;gBAC7B,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;YACtB,CAAC;YACD,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,SAAS,IAAI,GAAG,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;gBAC3F,MAAM,OAAO,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBACvC,IAAI,MAAM,IAAI,GAAG,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACnD,OAAO,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;gBACzB,CAAC;gBACD,IAAI,OAAO,IAAI,GAAG,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;oBACrD,OAAO,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;gBAC3B,CAAC;gBACD,MAAM,OAAO,CAAC;YACf,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;AACR,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { type Upload, type Folder } from '@xeonr/uploads-protocol/uplim/api/v1/uploads_pb';
2
+ import { type Bucket } from '@xeonr/uploads-protocol/uplim/api/v1/buckets_pb';
3
+ import type { RendererApiAdapter, RendererScope } from './types.js';
4
+ /**
5
+ * Best-effort decoder for the host's pre-loaded `resource` field. The
6
+ * host serialises via `toJson(UploadSchema, …)`/etc and posts the JSON
7
+ * across the iframe boundary, so we run it back through `fromJson` to
8
+ * land at a real Message instance with the right prototype methods.
9
+ *
10
+ * Returns null on any failure (schema mismatch, missing fields, etc.)
11
+ * so callers fall through to a fresh fetch.
12
+ */
13
+ export declare function decodeUploadResource(value: unknown): Upload | null;
14
+ export declare function decodeFolderResource(value: unknown): Folder | null;
15
+ export declare function decodeBucketResource(value: unknown): Bucket | null;
16
+ /**
17
+ * Fetch the upload for the current scope via the API. Caller already
18
+ * narrowed the scope; we just translate to the BucketUploadsService
19
+ * RPC. Throws when the API returns no upload (treated as a not-found
20
+ * by the renderer).
21
+ */
22
+ export declare function fetchUpload(scope: RendererScope, apiAdapter: RendererApiAdapter): Promise<Upload>;
23
+ export declare function fetchFolder(scope: RendererScope, apiAdapter: RendererApiAdapter): Promise<Folder>;
24
+ export declare function fetchBucket(scope: RendererScope, apiAdapter: RendererApiAdapter): Promise<Bucket>;
25
+ //# sourceMappingURL=resources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"AAaA,OAAO,EAKN,KAAK,MAAM,EACX,KAAK,MAAM,EACX,MAAM,iDAAiD,CAAC;AACzD,OAAO,EAGN,KAAK,MAAM,EACX,MAAM,iDAAiD,CAAC;AAEzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEpE;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAOlE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAOlE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAOlE;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAChC,KAAK,EAAE,aAAa,EACpB,UAAU,EAAE,kBAAkB,GAC5B,OAAO,CAAC,MAAM,CAAC,CAWjB;AAED,wBAAsB,WAAW,CAChC,KAAK,EAAE,aAAa,EACpB,UAAU,EAAE,kBAAkB,GAC5B,OAAO,CAAC,MAAM,CAAC,CAgBjB;AAED,wBAAsB,WAAW,CAChC,KAAK,EAAE,aAAa,EACpB,UAAU,EAAE,kBAAkB,GAC5B,OAAO,CAAC,MAAM,CAAC,CAOjB"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Typed resource accessors that read from the host-seeded `resource`
3
+ * cache first and fall back to a real API call when the cache is
4
+ * absent or stale.
5
+ *
6
+ * Lives in its own file so the imports against `@xeonr/uploads-protocol`
7
+ * and `@xeonr/uploads-sdk` are kept out of `client.ts`. Those packages
8
+ * are declared as optional peer dependencies — a renderer that never
9
+ * calls `getUpload()` / `getFolder()` / `getBucket()` doesn't need to
10
+ * install them. The fetch helpers throw at call time when the deps are
11
+ * missing.
12
+ */
13
+ import { fromJson } from '@bufbuild/protobuf';
14
+ import { BucketUploadsService, BucketFoldersService, UploadSchema, FolderSchema, } from '@xeonr/uploads-protocol/uplim/api/v1/uploads_pb';
15
+ import { BucketsService, BucketSchema, } from '@xeonr/uploads-protocol/uplim/api/v1/buckets_pb';
16
+ import { getUploadClientWithEnv } from '@xeonr/uploads-sdk/api/base';
17
+ /**
18
+ * Best-effort decoder for the host's pre-loaded `resource` field. The
19
+ * host serialises via `toJson(UploadSchema, …)`/etc and posts the JSON
20
+ * across the iframe boundary, so we run it back through `fromJson` to
21
+ * land at a real Message instance with the right prototype methods.
22
+ *
23
+ * Returns null on any failure (schema mismatch, missing fields, etc.)
24
+ * so callers fall through to a fresh fetch.
25
+ */
26
+ export function decodeUploadResource(value) {
27
+ if (!value || typeof value !== 'object')
28
+ return null;
29
+ try {
30
+ return fromJson(UploadSchema, value);
31
+ }
32
+ catch {
33
+ return null;
34
+ }
35
+ }
36
+ export function decodeFolderResource(value) {
37
+ if (!value || typeof value !== 'object')
38
+ return null;
39
+ try {
40
+ return fromJson(FolderSchema, value);
41
+ }
42
+ catch {
43
+ return null;
44
+ }
45
+ }
46
+ export function decodeBucketResource(value) {
47
+ if (!value || typeof value !== 'object')
48
+ return null;
49
+ try {
50
+ return fromJson(BucketSchema, value);
51
+ }
52
+ catch {
53
+ return null;
54
+ }
55
+ }
56
+ /**
57
+ * Fetch the upload for the current scope via the API. Caller already
58
+ * narrowed the scope; we just translate to the BucketUploadsService
59
+ * RPC. Throws when the API returns no upload (treated as a not-found
60
+ * by the renderer).
61
+ */
62
+ export async function fetchUpload(scope, apiAdapter) {
63
+ if (scope.type !== 'upload') {
64
+ throw new Error('fetchUpload requires an upload-typed scope');
65
+ }
66
+ const client = getUploadClientWithEnv(BucketUploadsService, apiAdapter);
67
+ const res = await client.getUpload({
68
+ bucketRef: { type: { case: 'bucketId', value: scope.bucketId } },
69
+ uploadRef: { type: { case: 'uploadId', value: scope.uploadId } },
70
+ });
71
+ if (!res.upload)
72
+ throw new Error('Upload not found');
73
+ return res.upload;
74
+ }
75
+ export async function fetchFolder(scope, apiAdapter) {
76
+ // Folder scopes ('folder' or 'virtual-file' with a folderId) carry
77
+ // the identifier; everything else is a misuse.
78
+ let folderId;
79
+ if (scope.type === 'folder')
80
+ folderId = scope.folderId;
81
+ else if (scope.type === 'virtual-file')
82
+ folderId = scope.folderId;
83
+ if (!folderId) {
84
+ throw new Error('fetchFolder requires a folder-typed scope with a folderId');
85
+ }
86
+ const client = getUploadClientWithEnv(BucketFoldersService, apiAdapter);
87
+ const res = await client.getFolder({
88
+ bucketRef: { type: { case: 'bucketId', value: scope.bucketId } },
89
+ folderRef: { type: { case: 'folderId', value: folderId } },
90
+ });
91
+ if (!res.folder)
92
+ throw new Error('Folder not found');
93
+ return res.folder;
94
+ }
95
+ export async function fetchBucket(scope, apiAdapter) {
96
+ const client = getUploadClientWithEnv(BucketsService, apiAdapter);
97
+ const res = await client.getBucket({
98
+ bucketRef: { type: { case: 'bucketId', value: scope.bucketId } },
99
+ });
100
+ if (!res.bucket)
101
+ throw new Error('Bucket not found');
102
+ return res.bucket;
103
+ }
104
+ //# sourceMappingURL=resources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.js","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -32,6 +32,25 @@ export interface RendererConfig {
32
32
  * republished without bumping the archive). Bounded to 64 chars.
33
33
  */
34
34
  buildHash?: string;
35
+ /**
36
+ * When true, the SDK holds `uplim:ack` until the renderer explicitly
37
+ * calls `markReady()` from `useRendererClient()`. The host's loading
38
+ * overlay stays visible until that signal arrives, so the user
39
+ * never sees a blank canvas between bridge ack and the renderer's
40
+ * first paint.
41
+ *
42
+ * Leave unset (or `false`) for fast renderers where the gap is
43
+ * invisible — that's the right default and lowest-friction pattern
44
+ * (image, code, plain markdown). Set `true` when the renderer takes
45
+ * perceptible time to settle (large file fetch, video decode,
46
+ * multi-page paginate) and the blank-canvas flash is noticeable.
47
+ *
48
+ * The SDK auto-acks after 30s (configurable via
49
+ * `RendererClientOptions.readyTimeoutMs`) and logs a warning if
50
+ * `markReady()` never fires — so a forgotten signal can't trap
51
+ * users behind the overlay.
52
+ */
53
+ deferReady?: boolean;
35
54
  }
36
55
  export type RendererPermission = 'createFolder' | 'openUpload';
37
56
  /**
@@ -98,5 +117,23 @@ export interface InitPayload {
98
117
  config: RendererConfig;
99
118
  /** Initial hash path to navigate to, derived from the host URL fragment. */
100
119
  initialPath?: string;
120
+ /**
121
+ * Pre-loaded resource snapshot the host already had on hand when it
122
+ * mounted the iframe — typically the `Upload` proto (in its JSON
123
+ * encoding) for upload-scoped renderers, or `Folder` for folder
124
+ * scopes. Renderers can consume this directly to avoid an extra
125
+ * GetUpload / GetFolder round trip on first paint.
126
+ *
127
+ * Shape is intentionally loose (`unknown`) because the SDK is
128
+ * deliberately decoupled from the @xeonr/uploads-protocol types —
129
+ * renderers cast to the proto JSON type (e.g. `UploadJson`) on use.
130
+ * Treat as advisory: if absent or stale, fall back to a fresh fetch.
131
+ *
132
+ * Stays in sync via the existing `resource_url`-style fetches that
133
+ * the renderer triggers when the host posts an updated init (e.g.
134
+ * after edit / replace flows). For now hosts only populate the
135
+ * field for upload-typed scopes; future hosts may extend.
136
+ */
137
+ resource?: unknown;
101
138
  }
102
139
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,OAAO,EAAE,CAAC,CAAC;IACX,uDAAuD;IACvD,WAAW,CAAC,EAAE,kBAAkB,EAAE,CAAC;IACnC,OAAO,CAAC,EAAE;QACT,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,cAAc,CAAC,EAAE,OAAO,CAAC;KACzB,CAAC;IACF;;;;;;;;;;OAUG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,kBAAkB,GAC3B,cAAc,GACd,YAAY,CAAC;AAEhB;;;GAGG;AACH,MAAM,MAAM,aAAa,GACtB,mBAAmB,GACnB,mBAAmB,GACnB,mBAAmB,GACnB,wBAAwB,CAAC;AAE5B,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IACxC,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACb;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GACtB,iBAAiB,GACjB,iBAAiB,GACjB,eAAe,CAAC;AAEnB;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC3C,uBAAuB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACnE,sBAAsB,CAAC,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;CAC5C;AAED,0DAA0D;AAC1D,MAAM,WAAW,WAAW;IAC3B,wBAAwB;IACxB,OAAO,EAAE,CAAC,CAAC;IACX,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,cAAc,EAAE,MAAM,CAAC;IACvB,0BAA0B;IAC1B,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC;IACxB,mCAAmC;IACnC,UAAU,EAAE,WAAW,GAAG,QAAQ,CAAC;IACnC,+CAA+C;IAC/C,KAAK,EAAE,aAAa,CAAC;IACrB,4DAA4D;IAC5D,aAAa,EAAE,aAAa,CAAC;IAC7B,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,MAAM,EAAE,cAAc,CAAC;IACvB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,OAAO,EAAE,CAAC,CAAC;IACX,uDAAuD;IACvD,WAAW,CAAC,EAAE,kBAAkB,EAAE,CAAC;IACnC,OAAO,CAAC,EAAE;QACT,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,cAAc,CAAC,EAAE,OAAO,CAAC;KACzB,CAAC;IACF;;;;;;;;;;OAUG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;;;;;;;OAiBG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,MAAM,kBAAkB,GAC3B,cAAc,GACd,YAAY,CAAC;AAEhB;;;GAGG;AACH,MAAM,MAAM,aAAa,GACtB,mBAAmB,GACnB,mBAAmB,GACnB,mBAAmB,GACnB,wBAAwB,CAAC;AAE5B,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IACxC,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACb;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GACtB,iBAAiB,GACjB,iBAAiB,GACjB,eAAe,CAAC;AAEnB;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC3C,uBAAuB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACnE,sBAAsB,CAAC,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;CAC5C;AAED,0DAA0D;AAC1D,MAAM,WAAW,WAAW;IAC3B,wBAAwB;IACxB,OAAO,EAAE,CAAC,CAAC;IACX,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,cAAc,EAAE,MAAM,CAAC;IACvB,0BAA0B;IAC1B,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC;IACxB,mCAAmC;IACnC,UAAU,EAAE,WAAW,GAAG,QAAQ,CAAC;IACnC,+CAA+C;IAC/C,KAAK,EAAE,aAAa,CAAC;IACrB,4DAA4D;IAC5D,aAAa,EAAE,aAAa,CAAC;IAC7B,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,MAAM,EAAE,cAAc,CAAC;IACvB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;;;;;;;;;;OAgBG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xeonr/renderer-sdk",
3
- "version": "1.1.0",
3
+ "version": "1.5.0",
4
4
  "type": "module",
5
5
  "license": "ISC",
6
6
  "description": "SDK for building custom renderers for upl.im integrations",
@@ -30,7 +30,10 @@
30
30
  },
31
31
  "peerDependencies": {
32
32
  "react": ">=18.0.0",
33
- "react-dom": ">=18.0.0"
33
+ "react-dom": ">=18.0.0",
34
+ "@bufbuild/protobuf": ">=2.0.0",
35
+ "@xeonr/uploads-protocol": "*",
36
+ "@xeonr/uploads-sdk": "*"
34
37
  },
35
38
  "peerDependenciesMeta": {
36
39
  "react": {
@@ -38,14 +41,26 @@
38
41
  },
39
42
  "react-dom": {
40
43
  "optional": true
44
+ },
45
+ "@bufbuild/protobuf": {
46
+ "optional": true
47
+ },
48
+ "@xeonr/uploads-protocol": {
49
+ "optional": true
50
+ },
51
+ "@xeonr/uploads-sdk": {
52
+ "optional": true
41
53
  }
42
54
  },
43
55
  "devDependencies": {
44
56
  "@types/react": "^19.0.0",
45
57
  "@types/react-dom": "^19.0.0",
58
+ "@bufbuild/protobuf": "^2.0.0",
46
59
  "react": "^19.0.0",
47
60
  "react-dom": "^19.0.0",
48
- "typescript": "^5.8.3"
61
+ "typescript": "^5.8.3",
62
+ "@xeonr/uploads-protocol": "1.0.6",
63
+ "@xeonr/uploads-sdk": "1.0.6"
49
64
  },
50
65
  "scripts": {
51
66
  "build": "tsc"