@syntrologie/runtime-sdk 2.4.0-canary.25 → 2.4.0-canary.26

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/version.d.ts CHANGED
@@ -10,4 +10,4 @@
10
10
  *
11
11
  * @since 2.0.0
12
12
  */
13
- export declare const SDK_VERSION = "2.4.0-canary.25";
13
+ export declare const SDK_VERSION = "2.4.0-canary.26";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syntrologie/runtime-sdk",
3
- "version": "2.4.0-canary.25",
3
+ "version": "2.4.0-canary.26",
4
4
  "description": "Syntrologie Runtime SDK for web experimentation and analytics",
5
5
  "license": "Proprietary",
6
6
  "private": false,
@@ -67,12 +67,12 @@
67
67
  "@floating-ui/dom": "^1.7.5",
68
68
  "@growthbook/growthbook": "~1.6.2",
69
69
  "@growthbook/growthbook-react": "^1.6.4",
70
- "@syntrologie/adapt-chatbot": "2.4.0-canary.25",
71
- "@syntrologie/adapt-content": "2.4.0-canary.25",
72
- "@syntrologie/adapt-faq": "2.4.0-canary.25",
73
- "@syntrologie/adapt-gamification": "2.4.0-canary.25",
74
- "@syntrologie/adapt-nav": "2.4.0-canary.25",
75
- "@syntrologie/adapt-overlays": "2.4.0-canary.25",
70
+ "@syntrologie/adapt-chatbot": "2.4.0-canary.26",
71
+ "@syntrologie/adapt-content": "2.4.0-canary.26",
72
+ "@syntrologie/adapt-faq": "2.4.0-canary.26",
73
+ "@syntrologie/adapt-gamification": "2.4.0-canary.26",
74
+ "@syntrologie/adapt-nav": "2.4.0-canary.26",
75
+ "@syntrologie/adapt-overlays": "2.4.0-canary.26",
76
76
  "lucide-react": "^0.576.0",
77
77
  "posthog-js": "~1.302.2",
78
78
  "zod": "^3.25.76"
@@ -45,11 +45,328 @@
45
45
  "$ref": "#/$defs/launcherConfig",
46
46
  "description": "Launcher button configuration"
47
47
  },
48
- "verificationSteps": {
49
- "type": "array",
50
- "items": {
51
- "type": "string"
52
- }
48
+ "meta": {
49
+ "type": "object",
50
+ "properties": {
51
+ "verificationSteps": {
52
+ "type": "array",
53
+ "items": {
54
+ "anyOf": [
55
+ {
56
+ "type": "string"
57
+ },
58
+ {
59
+ "type": "object",
60
+ "properties": {
61
+ "text": {
62
+ "type": "string"
63
+ },
64
+ "check": {
65
+ "anyOf": [
66
+ {
67
+ "type": "object",
68
+ "properties": {
69
+ "type": {
70
+ "type": "string",
71
+ "const": "page_url"
72
+ },
73
+ "url": {
74
+ "type": "string"
75
+ }
76
+ },
77
+ "required": [
78
+ "type",
79
+ "url"
80
+ ],
81
+ "additionalProperties": false
82
+ },
83
+ {
84
+ "type": "object",
85
+ "properties": {
86
+ "type": {
87
+ "type": "string",
88
+ "const": "route"
89
+ },
90
+ "routeId": {
91
+ "type": "string"
92
+ }
93
+ },
94
+ "required": [
95
+ "type",
96
+ "routeId"
97
+ ],
98
+ "additionalProperties": false
99
+ },
100
+ {
101
+ "type": "object",
102
+ "properties": {
103
+ "type": {
104
+ "type": "string",
105
+ "const": "anchor_visible"
106
+ },
107
+ "anchorId": {
108
+ "type": "string"
109
+ },
110
+ "state": {
111
+ "type": "string",
112
+ "enum": [
113
+ "visible",
114
+ "present",
115
+ "absent"
116
+ ]
117
+ }
118
+ },
119
+ "required": [
120
+ "type",
121
+ "anchorId",
122
+ "state"
123
+ ],
124
+ "additionalProperties": false
125
+ },
126
+ {
127
+ "type": "object",
128
+ "properties": {
129
+ "type": {
130
+ "type": "string",
131
+ "const": "event_occurred"
132
+ },
133
+ "eventName": {
134
+ "type": "string"
135
+ },
136
+ "withinMs": {
137
+ "type": "number"
138
+ }
139
+ },
140
+ "required": [
141
+ "type",
142
+ "eventName"
143
+ ],
144
+ "additionalProperties": false
145
+ },
146
+ {
147
+ "type": "object",
148
+ "properties": {
149
+ "type": {
150
+ "type": "string",
151
+ "const": "state_equals"
152
+ },
153
+ "key": {
154
+ "type": "string"
155
+ },
156
+ "value": {}
157
+ },
158
+ "required": [
159
+ "type",
160
+ "key"
161
+ ],
162
+ "additionalProperties": false
163
+ },
164
+ {
165
+ "type": "object",
166
+ "properties": {
167
+ "type": {
168
+ "type": "string",
169
+ "const": "viewport"
170
+ },
171
+ "minWidth": {
172
+ "type": "number"
173
+ },
174
+ "maxWidth": {
175
+ "type": "number"
176
+ },
177
+ "minHeight": {
178
+ "type": "number"
179
+ },
180
+ "maxHeight": {
181
+ "type": "number"
182
+ }
183
+ },
184
+ "required": [
185
+ "type"
186
+ ],
187
+ "additionalProperties": false
188
+ },
189
+ {
190
+ "type": "object",
191
+ "properties": {
192
+ "type": {
193
+ "type": "string",
194
+ "const": "session_metric"
195
+ },
196
+ "key": {
197
+ "type": "string"
198
+ },
199
+ "operator": {
200
+ "type": "string",
201
+ "enum": [
202
+ "gte",
203
+ "lte",
204
+ "eq",
205
+ "gt",
206
+ "lt"
207
+ ]
208
+ },
209
+ "threshold": {
210
+ "type": "number"
211
+ }
212
+ },
213
+ "required": [
214
+ "type",
215
+ "key",
216
+ "operator",
217
+ "threshold"
218
+ ],
219
+ "additionalProperties": false
220
+ },
221
+ {
222
+ "type": "object",
223
+ "properties": {
224
+ "type": {
225
+ "type": "string",
226
+ "const": "dismissed"
227
+ },
228
+ "key": {
229
+ "type": "string"
230
+ },
231
+ "inverted": {
232
+ "type": "boolean"
233
+ }
234
+ },
235
+ "required": [
236
+ "type",
237
+ "key"
238
+ ],
239
+ "additionalProperties": false
240
+ },
241
+ {
242
+ "type": "object",
243
+ "properties": {
244
+ "type": {
245
+ "type": "string",
246
+ "const": "cooldown_active"
247
+ },
248
+ "key": {
249
+ "type": "string"
250
+ },
251
+ "inverted": {
252
+ "type": "boolean"
253
+ }
254
+ },
255
+ "required": [
256
+ "type",
257
+ "key"
258
+ ],
259
+ "additionalProperties": false
260
+ },
261
+ {
262
+ "type": "object",
263
+ "properties": {
264
+ "type": {
265
+ "type": "string",
266
+ "const": "frequency_limit"
267
+ },
268
+ "key": {
269
+ "type": "string"
270
+ },
271
+ "limit": {
272
+ "type": "number"
273
+ },
274
+ "inverted": {
275
+ "type": "boolean"
276
+ }
277
+ },
278
+ "required": [
279
+ "type",
280
+ "key",
281
+ "limit"
282
+ ],
283
+ "additionalProperties": false
284
+ },
285
+ {
286
+ "type": "object",
287
+ "properties": {
288
+ "type": {
289
+ "type": "string",
290
+ "const": "event_count"
291
+ },
292
+ "key": {
293
+ "type": "string"
294
+ },
295
+ "operator": {
296
+ "type": "string",
297
+ "enum": [
298
+ "gte",
299
+ "lte",
300
+ "eq",
301
+ "gt",
302
+ "lt"
303
+ ]
304
+ },
305
+ "count": {
306
+ "type": "integer",
307
+ "minimum": 0
308
+ },
309
+ "withinMs": {
310
+ "type": "number",
311
+ "exclusiveMinimum": 0
312
+ },
313
+ "counter": {
314
+ "type": "object",
315
+ "properties": {
316
+ "events": {
317
+ "type": "array",
318
+ "items": {
319
+ "type": "string"
320
+ },
321
+ "minItems": 1
322
+ },
323
+ "match": {
324
+ "type": "object",
325
+ "additionalProperties": {
326
+ "type": "object",
327
+ "properties": {
328
+ "equals": {
329
+ "type": [
330
+ "string",
331
+ "number",
332
+ "boolean"
333
+ ]
334
+ },
335
+ "contains": {
336
+ "type": "string"
337
+ }
338
+ },
339
+ "additionalProperties": false
340
+ }
341
+ }
342
+ },
343
+ "required": [
344
+ "events"
345
+ ],
346
+ "additionalProperties": false
347
+ }
348
+ },
349
+ "required": [
350
+ "type",
351
+ "key",
352
+ "operator",
353
+ "count"
354
+ ],
355
+ "additionalProperties": false
356
+ }
357
+ ]
358
+ }
359
+ },
360
+ "required": [
361
+ "text"
362
+ ],
363
+ "additionalProperties": false
364
+ }
365
+ ]
366
+ }
367
+ }
368
+ },
369
+ "additionalProperties": true
53
370
  }
54
371
  },
55
372
  "additionalProperties": false,
@@ -194,6 +194,21 @@ for (const tile of config.tiles ?? []) {
194
194
  );
195
195
  }
196
196
 
197
+ // Celebrate actions without triggerWhen fire on every page load — almost always a mistake.
198
+ // The effect (confetti, etc.) should be scoped to a specific page or user action.
199
+ for (const [i, action] of (config.actions ?? []).entries()) {
200
+ if (action.kind !== 'overlays:celebrate') continue;
201
+ if (action.triggerWhen) continue;
202
+
203
+ const label = action.label ? ` (label: "${action.label}")` : '';
204
+ warnings.push(
205
+ `actions[${i}]${label}: overlays:celebrate has no triggerWhen.\n` +
206
+ ` This fires the "${action.effect ?? 'confetti'}" effect on EVERY page load.\n` +
207
+ ` Add a triggerWhen with a page_url condition to scope it, e.g.:\n` +
208
+ ` "triggerWhen": {"type":"rules","rules":[{"conditions":[{"type":"page_url","url":"**/target-page"}],"value":true}],"default":false}`
209
+ );
210
+ }
211
+
197
212
  // page_url conditions should use ** prefix to match any host, not absolute paths.
198
213
  // "/dashboard/state" won't match "http://localhost:8088/dashboard/state" because
199
214
  // page_url evaluates against the full URL. Use "**/dashboard/state" instead.
@@ -230,3 +245,19 @@ if (warnings.length > 0) {
230
245
  console.warn(`\n\u26A0\uFE0F ${warnings.length} design warning(s):`);
231
246
  for (const w of warnings) console.warn(` - ${w}`);
232
247
  }
248
+
249
+ // --- Display meta info (non-blocking, informational) ---
250
+ const meta = config.meta;
251
+ if (meta) {
252
+ if (meta.name) console.log(`\n\uD83D\uDCCB ${meta.name}`);
253
+ if (meta.description) console.log(` ${meta.description}`);
254
+ if (meta.trigger) console.log(` Trigger: ${meta.trigger}`);
255
+ if (meta.verificationSteps?.length > 0) {
256
+ console.log(`\n\uD83E\uDDEA Verification steps:`);
257
+ for (const [i, step] of meta.verificationSteps.entries()) {
258
+ const text = typeof step === 'string' ? step : step.text;
259
+ const check = typeof step === 'object' && step.check ? ` [auto: ${step.check.type}]` : '';
260
+ console.log(` ${i + 1}. ${text}${check}`);
261
+ }
262
+ }
263
+ }