@syntrologie/runtime-sdk 2.2.0-canary.9 → 2.2.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 +2 -1
- package/dist/actions/types.d.ts +7 -0
- package/dist/antiFlicker.d.ts +2 -0
- package/dist/{chunk-UEAP7WOK.js → chunk-V4MDQX67.js} +468 -112
- package/dist/chunk-V4MDQX67.js.map +7 -0
- package/dist/configFetcher.d.ts +3 -1
- package/dist/context/ContextManager.d.ts +4 -0
- package/dist/diagnostics/service-worker-check.d.ts +23 -0
- package/dist/editorLoader.d.ts +8 -2
- package/dist/index.d.ts +3 -0
- package/dist/index.js +22 -4
- package/dist/index.js.map +2 -2
- package/dist/integrations/gtm-bridge.d.ts +36 -0
- package/dist/navigation/NavigationMonitor.d.ts +45 -0
- package/dist/overlays/runtime/utils/AnchorWatcher.d.ts +22 -0
- package/dist/overlays/types.d.ts +2 -0
- package/dist/react.js +1 -1
- package/dist/runtime.d.ts +3 -0
- package/dist/smart-canvas.esm.js +44 -44
- package/dist/smart-canvas.esm.js.map +4 -4
- package/dist/smart-canvas.js +12771 -21496
- package/dist/smart-canvas.js.map +4 -4
- package/dist/smart-canvas.min.js +44 -44
- package/dist/smart-canvas.min.js.map +4 -4
- package/dist/telemetry/adapters/posthog.d.ts +19 -0
- package/dist/telemetry/consent.d.ts +62 -0
- package/dist/version.d.ts +1 -1
- package/dist/widgets/WidgetRegistry.d.ts +10 -0
- package/package.json +11 -7
- package/scripts/syntroReactPlugin.mjs +113 -0
- package/dist/chunk-UEAP7WOK.js.map +0 -7
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* and use the TelemetryClient interface.
|
|
6
6
|
*/
|
|
7
7
|
import type { PostHog, Properties } from 'posthog-js';
|
|
8
|
+
import type { ConsentGate } from '../consent';
|
|
8
9
|
import type { CanvasSurface, TelemetryClient } from '../types';
|
|
9
10
|
export interface PostHogAdapterOptions {
|
|
10
11
|
/**
|
|
@@ -58,6 +59,18 @@ export interface PostHogAdapterOptions {
|
|
|
58
59
|
* Used to feed events into the EventBus for runtime decisions.
|
|
59
60
|
*/
|
|
60
61
|
onCapture?: (eventName: string, properties?: Record<string, unknown>) => void;
|
|
62
|
+
/**
|
|
63
|
+
* Consent gate for GDPR compliance.
|
|
64
|
+
* When provided with requireExplicitConsent, PostHog initialization is
|
|
65
|
+
* deferred until consent is granted.
|
|
66
|
+
*/
|
|
67
|
+
consent?: ConsentGate;
|
|
68
|
+
/**
|
|
69
|
+
* Require explicit consent before initializing PostHog.
|
|
70
|
+
* When true, PostHog will not init until consent.grant() is called.
|
|
71
|
+
* @default false
|
|
72
|
+
*/
|
|
73
|
+
requireExplicitConsent?: boolean;
|
|
61
74
|
}
|
|
62
75
|
interface CanvasAnalyticsPayload extends Properties {
|
|
63
76
|
rectangleId?: string;
|
|
@@ -71,7 +84,13 @@ export declare class PostHogAdapter implements TelemetryClient {
|
|
|
71
84
|
private client?;
|
|
72
85
|
private featureFlagsCallback?;
|
|
73
86
|
private captureCallback?;
|
|
87
|
+
private consentUnsub?;
|
|
74
88
|
constructor(options?: PostHogAdapterOptions);
|
|
89
|
+
/**
|
|
90
|
+
* Initialize the PostHog client. Called immediately (no consent gate)
|
|
91
|
+
* or deferred (when consent gate grants).
|
|
92
|
+
*/
|
|
93
|
+
private initPostHog;
|
|
75
94
|
/**
|
|
76
95
|
* Get all feature flags from PostHog.
|
|
77
96
|
* Used to extract segment membership flags (in_segment_*).
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ConsentGate - GDPR-compliant consent management for telemetry.
|
|
3
|
+
*
|
|
4
|
+
* Gates PostHog (and any future telemetry provider) initialization on
|
|
5
|
+
* user consent status. Supports:
|
|
6
|
+
* - Explicit consent requirement (opt-in model)
|
|
7
|
+
* - GTM Consent Mode v2 integration (reads analytics_storage from dataLayer)
|
|
8
|
+
* - Programmatic grant/deny API for host page consent banners
|
|
9
|
+
*
|
|
10
|
+
* The ConsentGate lives in the runtime (not the PostHog adapter) because
|
|
11
|
+
* consent is provider-agnostic — if we switch from PostHog to Segment or
|
|
12
|
+
* another provider, consent logic should not change.
|
|
13
|
+
*/
|
|
14
|
+
export type ConsentStatus = 'granted' | 'denied' | 'pending';
|
|
15
|
+
export interface ConsentConfig {
|
|
16
|
+
/** Initial consent status. Default: 'pending' */
|
|
17
|
+
initialStatus?: ConsentStatus;
|
|
18
|
+
/** If true, telemetry is blocked until grant() is called. Default: false */
|
|
19
|
+
requireExplicitConsent?: boolean;
|
|
20
|
+
/** Read consent state from GTM's window.dataLayer consent events. Default: false */
|
|
21
|
+
readFromGtmConsentMode?: boolean;
|
|
22
|
+
/** Called whenever consent status changes. */
|
|
23
|
+
onConsentChange?: (status: ConsentStatus) => void;
|
|
24
|
+
}
|
|
25
|
+
type ConsentListener = (status: ConsentStatus) => void;
|
|
26
|
+
export declare class ConsentGate {
|
|
27
|
+
private status;
|
|
28
|
+
private listeners;
|
|
29
|
+
private configCallback?;
|
|
30
|
+
private gtmEnabled;
|
|
31
|
+
private destroyed;
|
|
32
|
+
constructor(config?: ConsentConfig);
|
|
33
|
+
/**
|
|
34
|
+
* Grant consent — enables telemetry collection.
|
|
35
|
+
*/
|
|
36
|
+
grant(): void;
|
|
37
|
+
/**
|
|
38
|
+
* Deny consent — disables telemetry collection.
|
|
39
|
+
*/
|
|
40
|
+
deny(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Get the current consent status.
|
|
43
|
+
*/
|
|
44
|
+
getStatus(): ConsentStatus;
|
|
45
|
+
/**
|
|
46
|
+
* Subscribe to consent status changes.
|
|
47
|
+
* Returns an unsubscribe function.
|
|
48
|
+
*/
|
|
49
|
+
subscribe(listener: ConsentListener): () => void;
|
|
50
|
+
/**
|
|
51
|
+
* Poll GTM's dataLayer for consent state.
|
|
52
|
+
* Scans for the most recent consent update event with analytics_storage.
|
|
53
|
+
*/
|
|
54
|
+
pollGtmConsent(): void;
|
|
55
|
+
/**
|
|
56
|
+
* Clean up listeners and stop responding to changes.
|
|
57
|
+
*/
|
|
58
|
+
destroy(): void;
|
|
59
|
+
private setStatus;
|
|
60
|
+
private notify;
|
|
61
|
+
}
|
|
62
|
+
export {};
|
package/dist/version.d.ts
CHANGED
|
@@ -68,11 +68,16 @@ export interface MountedWidgetHandle {
|
|
|
68
68
|
* Allows apps to register custom widgets that can be rendered via
|
|
69
69
|
* mountWidget actions or directly through the Surfaces system.
|
|
70
70
|
*/
|
|
71
|
+
export type WidgetRegistryListener = (event: {
|
|
72
|
+
type: 'registered' | 'unregistered';
|
|
73
|
+
widgetId: string;
|
|
74
|
+
}) => void;
|
|
71
75
|
export declare class WidgetRegistry {
|
|
72
76
|
private widgets;
|
|
73
77
|
private mountedWidgets;
|
|
74
78
|
private mountIdCounter;
|
|
75
79
|
private runtimeRef?;
|
|
80
|
+
private listeners;
|
|
76
81
|
/**
|
|
77
82
|
* Bind a runtime reference so it can be injected into widget mount() calls.
|
|
78
83
|
* Uses `unknown` to avoid circular imports (WidgetRegistry ← runtime.ts).
|
|
@@ -133,6 +138,11 @@ export declare class WidgetRegistry {
|
|
|
133
138
|
* Get all widgets from a specific source.
|
|
134
139
|
*/
|
|
135
140
|
getBySource(source: string): WidgetRegistration[];
|
|
141
|
+
/**
|
|
142
|
+
* Subscribe to widget registration changes.
|
|
143
|
+
*/
|
|
144
|
+
subscribe(callback: WidgetRegistryListener): () => void;
|
|
145
|
+
private notify;
|
|
136
146
|
/**
|
|
137
147
|
* Clean up all mounted widgets.
|
|
138
148
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@syntrologie/runtime-sdk",
|
|
3
|
-
"version": "2.2.0
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Syntrologie Runtime SDK for web experimentation and analytics",
|
|
5
5
|
"license": "Proprietary",
|
|
6
6
|
"private": false,
|
|
@@ -35,12 +35,16 @@
|
|
|
35
35
|
"./cdn": {
|
|
36
36
|
"import": "./dist/smart-canvas.esm.js",
|
|
37
37
|
"require": "./dist/smart-canvas.js"
|
|
38
|
+
},
|
|
39
|
+
"./build-plugin": {
|
|
40
|
+
"import": "./scripts/syntroReactPlugin.mjs"
|
|
38
41
|
}
|
|
39
42
|
},
|
|
40
43
|
"files": [
|
|
41
44
|
"dist",
|
|
42
45
|
"schema",
|
|
43
46
|
"scripts/validate-config.mjs",
|
|
47
|
+
"scripts/syntroReactPlugin.mjs",
|
|
44
48
|
"CAPABILITIES.md"
|
|
45
49
|
],
|
|
46
50
|
"scripts": {
|
|
@@ -63,12 +67,12 @@
|
|
|
63
67
|
"@floating-ui/dom": "^1.7.5",
|
|
64
68
|
"@growthbook/growthbook": "~1.6.2",
|
|
65
69
|
"@growthbook/growthbook-react": "^1.6.4",
|
|
66
|
-
"@syntrologie/adapt-chatbot": "2.2.0
|
|
67
|
-
"@syntrologie/adapt-content": "2.2.0
|
|
68
|
-
"@syntrologie/adapt-faq": "2.2.0
|
|
69
|
-
"@syntrologie/adapt-gamification": "2.2.0
|
|
70
|
-
"@syntrologie/adapt-nav": "2.2.0
|
|
71
|
-
"@syntrologie/adapt-overlays": "2.2.0
|
|
70
|
+
"@syntrologie/adapt-chatbot": "2.2.0",
|
|
71
|
+
"@syntrologie/adapt-content": "2.2.0",
|
|
72
|
+
"@syntrologie/adapt-faq": "2.2.0",
|
|
73
|
+
"@syntrologie/adapt-gamification": "2.2.0",
|
|
74
|
+
"@syntrologie/adapt-nav": "2.2.0",
|
|
75
|
+
"@syntrologie/adapt-overlays": "2.2.0",
|
|
72
76
|
"posthog-js": "~1.302.2",
|
|
73
77
|
"zod": "^3.25.76"
|
|
74
78
|
},
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* syntroReactPlugin — esbuild plugin for shared React via SynOS
|
|
3
|
+
*
|
|
4
|
+
* Replaces `import { useState } from 'react'` (and react-dom, jsx-runtime)
|
|
5
|
+
* with lazy wrappers that resolve to SynOS.React / SynOS.ReactDOM at call
|
|
6
|
+
* time. This means:
|
|
7
|
+
* - Adaptive modules load and self-register without React being available
|
|
8
|
+
* - React resolves when components actually render
|
|
9
|
+
* - The runtime SDK sets SynOS.React at module scope before any render
|
|
10
|
+
*
|
|
11
|
+
* Used by: build-cdn.js, build-adaptives-only.js, editor-sdk/build.js
|
|
12
|
+
*/
|
|
13
|
+
export const syntroReactPlugin = {
|
|
14
|
+
name: 'syntro-react',
|
|
15
|
+
setup(build) {
|
|
16
|
+
build.onResolve({ filter: /^react(-dom)?(\/.*)?$/ }, (args) => ({
|
|
17
|
+
path: args.path,
|
|
18
|
+
namespace: 'syntro-react',
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
build.onLoad({ filter: /.*/, namespace: 'syntro-react' }, (args) => {
|
|
22
|
+
if (args.path === 'react/jsx-runtime' || args.path === 'react/jsx-dev-runtime') {
|
|
23
|
+
return {
|
|
24
|
+
contents: `
|
|
25
|
+
function _R() {
|
|
26
|
+
return (typeof SynOS !== 'undefined' && SynOS.React) || {};
|
|
27
|
+
}
|
|
28
|
+
function _jsx(type, props, key) {
|
|
29
|
+
var R = _R();
|
|
30
|
+
var p = props || {};
|
|
31
|
+
var c = p.children;
|
|
32
|
+
delete p.children;
|
|
33
|
+
if (key !== undefined) p.key = key;
|
|
34
|
+
return Array.isArray(c)
|
|
35
|
+
? R.createElement.apply(null, [type, p].concat(c))
|
|
36
|
+
: c !== undefined
|
|
37
|
+
? R.createElement(type, p, c)
|
|
38
|
+
: R.createElement(type, p);
|
|
39
|
+
}
|
|
40
|
+
export var jsx = _jsx;
|
|
41
|
+
export var jsxs = _jsx;
|
|
42
|
+
export var Fragment = _R().Fragment;
|
|
43
|
+
`,
|
|
44
|
+
loader: 'js',
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (args.path === 'react') {
|
|
48
|
+
// Hooks and creation APIs are lazy function wrappers — they resolve
|
|
49
|
+
// SynOS.React at call time (during render), not at module load.
|
|
50
|
+
//
|
|
51
|
+
// Component types (Fragment, Suspense, etc.) are resolved at module
|
|
52
|
+
// evaluation via _R(). This is fine because the runtime SDK always
|
|
53
|
+
// loads before adaptive modules evaluate, so SynOS.React is set.
|
|
54
|
+
// ES module named exports can't be truly lazy (no getter support).
|
|
55
|
+
return {
|
|
56
|
+
contents: `
|
|
57
|
+
function _R() {
|
|
58
|
+
return (typeof SynOS !== 'undefined' && SynOS.React) || {};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Default export — lazy proxy for React.* access
|
|
62
|
+
export default new Proxy({}, { get: function(_, k) { return _R()[k]; } });
|
|
63
|
+
|
|
64
|
+
// Hooks — lazy function wrappers (resolve at call time)
|
|
65
|
+
export function useState() { return _R().useState.apply(null, arguments); }
|
|
66
|
+
export function useEffect() { return _R().useEffect.apply(null, arguments); }
|
|
67
|
+
export function useMemo() { return _R().useMemo.apply(null, arguments); }
|
|
68
|
+
export function useCallback() { return _R().useCallback.apply(null, arguments); }
|
|
69
|
+
export function useRef() { return _R().useRef.apply(null, arguments); }
|
|
70
|
+
export function useContext() { return _R().useContext.apply(null, arguments); }
|
|
71
|
+
export function useReducer() { return _R().useReducer.apply(null, arguments); }
|
|
72
|
+
export function useLayoutEffect() { return _R().useLayoutEffect.apply(null, arguments); }
|
|
73
|
+
export function useId() { return _R().useId.apply(null, arguments); }
|
|
74
|
+
|
|
75
|
+
// Creation APIs — lazy function wrappers
|
|
76
|
+
export function createElement() { return _R().createElement.apply(null, arguments); }
|
|
77
|
+
export function createContext() { return _R().createContext.apply(null, arguments); }
|
|
78
|
+
export function forwardRef() { return _R().forwardRef.apply(null, arguments); }
|
|
79
|
+
export function memo() { return _R().memo.apply(null, arguments); }
|
|
80
|
+
export function lazy() { return _R().lazy.apply(null, arguments); }
|
|
81
|
+
export function isValidElement() { return _R().isValidElement.apply(null, arguments); }
|
|
82
|
+
export function cloneElement() { return _R().cloneElement.apply(null, arguments); }
|
|
83
|
+
|
|
84
|
+
// Component types — resolved at module eval (runtime loads first)
|
|
85
|
+
var _r = _R();
|
|
86
|
+
export var Fragment = _r.Fragment;
|
|
87
|
+
export var Suspense = _r.Suspense;
|
|
88
|
+
export var Children = _r.Children;
|
|
89
|
+
export var Component = _r.Component;
|
|
90
|
+
export var PureComponent = _r.PureComponent;
|
|
91
|
+
`,
|
|
92
|
+
loader: 'js',
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
if (args.path === 'react-dom' || args.path.startsWith('react-dom/')) {
|
|
96
|
+
return {
|
|
97
|
+
contents: `
|
|
98
|
+
function _RD() {
|
|
99
|
+
return (typeof SynOS !== 'undefined' && SynOS.ReactDOM) || {};
|
|
100
|
+
}
|
|
101
|
+
export default new Proxy({}, { get: function(_, k) { return _RD()[k]; } });
|
|
102
|
+
export function createRoot() { return _RD().createRoot.apply(null, arguments); }
|
|
103
|
+
export function hydrateRoot() { return _RD().hydrateRoot.apply(null, arguments); }
|
|
104
|
+
export function createPortal() { return _RD().createPortal.apply(null, arguments); }
|
|
105
|
+
export function flushSync() { return _RD().flushSync.apply(null, arguments); }
|
|
106
|
+
`,
|
|
107
|
+
loader: 'js',
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
return { contents: 'export default {};', loader: 'js' };
|
|
111
|
+
});
|
|
112
|
+
},
|
|
113
|
+
};
|