@lightdash/query-sdk 1.95.1 → 1.97.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/deliveryRender.d.ts +44 -0
- package/dist/deliveryRender.js +97 -0
- package/dist/features.js +6 -0
- package/dist/generated/sdkVersion.d.ts +1 -1
- package/dist/generated/sdkVersion.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -0
- package/dist/postMessageTransport.d.ts +4 -0
- package/dist/postMessageTransport.js +4 -0
- package/package.json +2 -2
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delivery-render flag: the host rides `deliveryRender: true` on its
|
|
3
|
+
* `lightdash:sdk:ready` message during delivery/preview capture renders
|
|
4
|
+
* (absent on interactive loads). Apps gate all-tab data mounting on it.
|
|
5
|
+
*/
|
|
6
|
+
export type DeliveryRenderStore = {
|
|
7
|
+
getValue: () => boolean;
|
|
8
|
+
setValue: (next: boolean) => void;
|
|
9
|
+
subscribe: (listener: () => void) => () => void;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Minimal external store: synchronous reads for useSyncExternalStore.
|
|
13
|
+
* Exported for tests — app code uses `useDeliveryRender`.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createDeliveryRenderStore(): DeliveryRenderStore;
|
|
16
|
+
/**
|
|
17
|
+
* Listen for the flag riding on the host's `lightdash:sdk:ready`. Called by
|
|
18
|
+
* `createPostMessageTransport()`; a no-op outside the browser (SSR/tests that
|
|
19
|
+
* never create a postMessage transport keep the default `false`). One
|
|
20
|
+
* listener per bundle — re-mounting replaces the previous listener rather
|
|
21
|
+
* than stacking.
|
|
22
|
+
*/
|
|
23
|
+
export declare function mountDeliveryRender(targetWindow: Window): () => void;
|
|
24
|
+
/**
|
|
25
|
+
* True inside delivery/preview capture renders. Gate DATA fetching on this —
|
|
26
|
+
* mount every tab's/slide's data hooks and show only the active one — never
|
|
27
|
+
* mount all tabs unconditionally on interactive loads.
|
|
28
|
+
*
|
|
29
|
+
* const deliveryRender = useDeliveryRender();
|
|
30
|
+
* return (deliveryRender || activeTab === 'summary') && <SummaryTabData />;
|
|
31
|
+
*/
|
|
32
|
+
export declare function useDeliveryRender(): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Non-hook accessor for event handlers and other post-boot code. Do NOT call
|
|
35
|
+
* at module init: the flag arrives from the host after the iframe loads, so
|
|
36
|
+
* a read before then always returns false. Components should use the hook,
|
|
37
|
+
* which re-renders when the flag arrives.
|
|
38
|
+
*/
|
|
39
|
+
export declare function isDeliveryRender(): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Test-only seam: drops the listener and the shared store so the next mount
|
|
42
|
+
* re-reads the default `false`.
|
|
43
|
+
*/
|
|
44
|
+
export declare function resetDeliveryRenderState(): void;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delivery-render flag: the host rides `deliveryRender: true` on its
|
|
3
|
+
* `lightdash:sdk:ready` message during delivery/preview capture renders
|
|
4
|
+
* (absent on interactive loads). Apps gate all-tab data mounting on it.
|
|
5
|
+
*/
|
|
6
|
+
import { useSyncExternalStore } from 'react';
|
|
7
|
+
const SDK_READY_MESSAGE = 'lightdash:sdk:ready';
|
|
8
|
+
/**
|
|
9
|
+
* Minimal external store: synchronous reads for useSyncExternalStore.
|
|
10
|
+
* Exported for tests — app code uses `useDeliveryRender`.
|
|
11
|
+
*/
|
|
12
|
+
export function createDeliveryRenderStore() {
|
|
13
|
+
let value = false;
|
|
14
|
+
const listeners = new Set();
|
|
15
|
+
return {
|
|
16
|
+
getValue: () => value,
|
|
17
|
+
setValue: (next) => {
|
|
18
|
+
if (next === value)
|
|
19
|
+
return;
|
|
20
|
+
value = next;
|
|
21
|
+
listeners.forEach((listener) => listener());
|
|
22
|
+
},
|
|
23
|
+
subscribe: (listener) => {
|
|
24
|
+
listeners.add(listener);
|
|
25
|
+
return () => {
|
|
26
|
+
listeners.delete(listener);
|
|
27
|
+
};
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
// Lazily created so tests (and SSR) never touch window at import time.
|
|
32
|
+
let sharedStore = null;
|
|
33
|
+
function getSharedStore() {
|
|
34
|
+
if (sharedStore === null) {
|
|
35
|
+
sharedStore = createDeliveryRenderStore();
|
|
36
|
+
}
|
|
37
|
+
return sharedStore;
|
|
38
|
+
}
|
|
39
|
+
let activeCleanup = null;
|
|
40
|
+
/**
|
|
41
|
+
* Listen for the flag riding on the host's `lightdash:sdk:ready`. Called by
|
|
42
|
+
* `createPostMessageTransport()`; a no-op outside the browser (SSR/tests that
|
|
43
|
+
* never create a postMessage transport keep the default `false`). One
|
|
44
|
+
* listener per bundle — re-mounting replaces the previous listener rather
|
|
45
|
+
* than stacking.
|
|
46
|
+
*/
|
|
47
|
+
export function mountDeliveryRender(targetWindow) {
|
|
48
|
+
if (typeof window === 'undefined')
|
|
49
|
+
return () => { };
|
|
50
|
+
const store = getSharedStore();
|
|
51
|
+
const handler = (event) => {
|
|
52
|
+
if (event.source !== targetWindow)
|
|
53
|
+
return;
|
|
54
|
+
const data = event.data;
|
|
55
|
+
if (data?.type !== SDK_READY_MESSAGE)
|
|
56
|
+
return;
|
|
57
|
+
store.setValue(data.deliveryRender === true);
|
|
58
|
+
};
|
|
59
|
+
activeCleanup?.();
|
|
60
|
+
window.addEventListener('message', handler);
|
|
61
|
+
const cleanup = () => {
|
|
62
|
+
window.removeEventListener('message', handler);
|
|
63
|
+
if (activeCleanup === cleanup)
|
|
64
|
+
activeCleanup = null;
|
|
65
|
+
};
|
|
66
|
+
activeCleanup = cleanup;
|
|
67
|
+
return cleanup;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* True inside delivery/preview capture renders. Gate DATA fetching on this —
|
|
71
|
+
* mount every tab's/slide's data hooks and show only the active one — never
|
|
72
|
+
* mount all tabs unconditionally on interactive loads.
|
|
73
|
+
*
|
|
74
|
+
* const deliveryRender = useDeliveryRender();
|
|
75
|
+
* return (deliveryRender || activeTab === 'summary') && <SummaryTabData />;
|
|
76
|
+
*/
|
|
77
|
+
export function useDeliveryRender() {
|
|
78
|
+
const store = getSharedStore();
|
|
79
|
+
return useSyncExternalStore(store.subscribe, store.getValue, () => false);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Non-hook accessor for event handlers and other post-boot code. Do NOT call
|
|
83
|
+
* at module init: the flag arrives from the host after the iframe loads, so
|
|
84
|
+
* a read before then always returns false. Components should use the hook,
|
|
85
|
+
* which re-renders when the flag arrives.
|
|
86
|
+
*/
|
|
87
|
+
export function isDeliveryRender() {
|
|
88
|
+
return getSharedStore().getValue();
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Test-only seam: drops the listener and the shared store so the next mount
|
|
92
|
+
* re-reads the default `false`.
|
|
93
|
+
*/
|
|
94
|
+
export function resetDeliveryRenderState() {
|
|
95
|
+
activeCleanup?.();
|
|
96
|
+
sharedStore = null;
|
|
97
|
+
}
|
package/dist/features.js
CHANGED
|
@@ -77,6 +77,12 @@ export const SDK_FEATURES = [
|
|
|
77
77
|
description: "Match the light or dark mode of the viewer's Lightdash (or embed) instead of a fixed theme, and restyle live when they switch.",
|
|
78
78
|
wiring: 'Keep complete light tokens in :root and dark tokens in .dark, remove any fixed dark class from the app shell, and use useColorScheme() only for colours that cannot be expressed in CSS.',
|
|
79
79
|
},
|
|
80
|
+
{
|
|
81
|
+
key: 'delivery-render',
|
|
82
|
+
label: 'Full data in scheduled deliveries',
|
|
83
|
+
description: "Scheduled deliveries and their preview render every tab or slide's data, not just the one currently visible.",
|
|
84
|
+
wiring: "Gate tab/slide content so DATA components for all tabs mount when useDeliveryRender() is true — tabs switch what's shown, not what's fetched. Never mount all tabs unconditionally.",
|
|
85
|
+
},
|
|
80
86
|
];
|
|
81
87
|
export const SDK_FEATURE_KEYS = SDK_FEATURES.map((f) => f.key);
|
|
82
88
|
export const SDK_MANIFEST_MESSAGE_TYPE = 'lightdash:sdk:manifest';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "1.
|
|
1
|
+
export declare const SDK_VERSION = "1.97.0";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by scripts/generateSdkVersion.mjs (prebuild) — do not edit.
|
|
2
|
-
export const SDK_VERSION = '1.
|
|
2
|
+
export const SDK_VERSION = '1.97.0';
|
package/dist/index.d.ts
CHANGED
|
@@ -18,5 +18,6 @@ export { VizContextProvider, useVizContext, getFormatted, getRaw, } from './vizC
|
|
|
18
18
|
export type { VizContext, VizContextCell, VizContextOptionValue, VizContextRow, DataAppVizContextMessage, VizContextRequestMessage, } from './vizContext';
|
|
19
19
|
export { useColorScheme } from './colorScheme';
|
|
20
20
|
export type { HostColorScheme, HostColorSchemeMessage, HostColorSchemeRequestMessage, } from './colorScheme';
|
|
21
|
+
export { isDeliveryRender, useDeliveryRender } from './deliveryRender';
|
|
21
22
|
export { useUrlState } from './urlState';
|
|
22
23
|
export type { SdkUrlStateChangeMessage, UrlStateMap } from './urlState';
|
package/dist/index.js
CHANGED
|
@@ -22,5 +22,8 @@ export { exportToSheets } from './exportToSheets';
|
|
|
22
22
|
export { VizContextProvider, useVizContext, getFormatted, getRaw, } from './vizContext';
|
|
23
23
|
// Host light/dark mode (seeded from the iframe URL, updated by the host)
|
|
24
24
|
export { useColorScheme } from './colorScheme';
|
|
25
|
+
// Delivery/preview capture flag (true when the host is capturing this render
|
|
26
|
+
// for a scheduled delivery or its preview, not an interactive load)
|
|
27
|
+
export { isDeliveryRender, useDeliveryRender } from './deliveryRender';
|
|
25
28
|
// Shareable URL state (seeded from and written back to the host page URL)
|
|
26
29
|
export { useUrlState } from './urlState';
|
|
@@ -26,6 +26,10 @@ export type SdkFetchResponse = {
|
|
|
26
26
|
};
|
|
27
27
|
export type SdkReadyMessage = {
|
|
28
28
|
type: 'lightdash:sdk:ready';
|
|
29
|
+
/** True when the host is capturing this render for a scheduled delivery
|
|
30
|
+
* or its preview. Absent (never `false`) on ordinary interactive loads —
|
|
31
|
+
* see `deliveryRender.ts`'s `useDeliveryRender()`. */
|
|
32
|
+
deliveryRender?: boolean;
|
|
29
33
|
};
|
|
30
34
|
export type SdkScreenshotRequest = {
|
|
31
35
|
type: 'lightdash:sdk:screenshot-request';
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* mapping) stays in the SDK's apiTransport.
|
|
10
10
|
*/
|
|
11
11
|
import { createApiTransport } from './apiTransport';
|
|
12
|
+
import { mountDeliveryRender } from './deliveryRender';
|
|
12
13
|
import { announceSdkManifest } from './manifest';
|
|
13
14
|
const DEFAULT_TIMEOUT_MS = 120000;
|
|
14
15
|
const READY_TIMEOUT_MS = 10000;
|
|
@@ -172,6 +173,9 @@ function createPostMessageExternalFetch(config) {
|
|
|
172
173
|
export function createPostMessageTransport(config) {
|
|
173
174
|
// Report this bundle's SDK capabilities so the host can offer upgrades.
|
|
174
175
|
announceSdkManifest(config.targetWindow);
|
|
176
|
+
// Listen for the delivery/preview capture flag riding on the same
|
|
177
|
+
// `lightdash:sdk:ready` handshake — see `useDeliveryRender()`.
|
|
178
|
+
mountDeliveryRender(config.targetWindow);
|
|
175
179
|
const adapter = createPostMessageFetchAdapter({
|
|
176
180
|
targetWindow: config.targetWindow,
|
|
177
181
|
timeoutMs: config.timeoutMs,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lightdash/query-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.97.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "SDK for building custom data apps against the Lightdash semantic layer",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"jsdom": "26.1.0",
|
|
35
35
|
"typescript": "7.0.2",
|
|
36
36
|
"vitest": "4.1.6",
|
|
37
|
-
"@lightdash/common": "1.
|
|
37
|
+
"@lightdash/common": "1.97.0"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
40
|
"prebuild": "node ./scripts/generateSdkVersion.mjs",
|