@appfunnel-dev/sdk 2.0.0-canary.5 → 2.0.0-canary.8
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 +1 -1
- package/dist/{capabilities-7_hy5f5G.d.cts → capabilities-CsnkVwna.d.cts} +34 -1
- package/dist/{capabilities-7_hy5f5G.d.ts → capabilities-CsnkVwna.d.ts} +34 -1
- package/dist/{checkout-7Dy6IedP.d.ts → checkout-3PkKwPd7.d.ts} +14 -14
- package/dist/{checkout-Dz8cGkB_.d.cts → checkout-Cg20l53c.d.cts} +14 -14
- package/dist/{chunk-VAOR77NW.cjs → chunk-FY3TMSRU.cjs} +7 -7
- package/dist/{chunk-VAOR77NW.cjs.map → chunk-FY3TMSRU.cjs.map} +1 -1
- package/dist/{chunk-CFFMZYPE.js → chunk-PWXMQGO6.js} +3 -3
- package/dist/{chunk-CFFMZYPE.js.map → chunk-PWXMQGO6.js.map} +1 -1
- package/dist/{chunk-TNLRQPVY.js → chunk-RVJLR4RS.js} +36 -8
- package/dist/chunk-RVJLR4RS.js.map +1 -0
- package/dist/{chunk-QMAZGLGV.cjs → chunk-RY3LOSVZ.cjs} +37 -7
- package/dist/chunk-RY3LOSVZ.cjs.map +1 -0
- package/dist/{chunk-AXXG3ODP.js → chunk-VW2HVPR4.js} +63 -90
- package/dist/chunk-VW2HVPR4.js.map +1 -0
- package/dist/{chunk-G44BUG6G.cjs → chunk-Y4YNJ2EX.cjs} +65 -93
- package/dist/chunk-Y4YNJ2EX.cjs.map +1 -0
- package/dist/driver-paddle.cjs +22 -22
- package/dist/driver-paddle.d.cts +2 -2
- package/dist/driver-paddle.d.ts +2 -2
- package/dist/driver-paddle.js +2 -2
- package/dist/driver-stripe.cjs +264 -212
- package/dist/driver-stripe.cjs.map +1 -1
- package/dist/driver-stripe.d.cts +19 -3
- package/dist/driver-stripe.d.ts +19 -3
- package/dist/driver-stripe.js +244 -193
- package/dist/driver-stripe.js.map +1 -1
- package/dist/index.cjs +310 -134
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -25
- package/dist/index.d.ts +25 -25
- package/dist/index.js +262 -82
- package/dist/index.js.map +1 -1
- package/dist/{manifest-Dl7faaKe.d.cts → manifest-B3Tdab0M.d.cts} +157 -85
- package/dist/{manifest-Dl7faaKe.d.ts → manifest-B3Tdab0M.d.ts} +157 -85
- package/dist/manifest-entry.cjs +118 -49
- package/dist/manifest-entry.cjs.map +1 -1
- package/dist/manifest-entry.d.cts +12 -29
- package/dist/manifest-entry.d.ts +12 -29
- package/dist/manifest-entry.js +79 -14
- package/dist/manifest-entry.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-AXXG3ODP.js.map +0 -1
- package/dist/chunk-G44BUG6G.cjs.map +0 -1
- package/dist/chunk-QMAZGLGV.cjs.map +0 -1
- package/dist/chunk-TNLRQPVY.js.map +0 -1
package/dist/manifest-entry.cjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
3
|
+
var chunkY4YNJ2EX_cjs = require('./chunk-Y4YNJ2EX.cjs');
|
|
4
|
+
var chunkRY3LOSVZ_cjs = require('./chunk-RY3LOSVZ.cjs');
|
|
5
5
|
require('./chunk-EMMSS5I5.cjs');
|
|
6
6
|
|
|
7
|
-
// src/manifest/
|
|
7
|
+
// src/manifest/offering-refs.ts
|
|
8
8
|
function mask(src) {
|
|
9
9
|
const out = src.split("");
|
|
10
10
|
const n = src.length;
|
|
@@ -60,7 +60,28 @@ function skipWs(masked, i) {
|
|
|
60
60
|
while (i < masked.length && (masked[i] === " " || masked[i] === " " || masked[i] === "\n" || masked[i] === "\r")) i++;
|
|
61
61
|
return i;
|
|
62
62
|
}
|
|
63
|
-
function
|
|
63
|
+
function tagAttrEnd(masked, from) {
|
|
64
|
+
let depth = 0;
|
|
65
|
+
for (let i = from; i < masked.length; i++) {
|
|
66
|
+
const c = masked[i];
|
|
67
|
+
if (c === "{") depth++;
|
|
68
|
+
else if (c === "}") {
|
|
69
|
+
if (depth > 0) depth--;
|
|
70
|
+
} else if (c === ">" && depth === 0) return i;
|
|
71
|
+
}
|
|
72
|
+
return masked.length;
|
|
73
|
+
}
|
|
74
|
+
function readAttr(src, masked, start, end, name) {
|
|
75
|
+
const re = new RegExp(`\\b${name}\\s*=\\s*`, "g");
|
|
76
|
+
re.lastIndex = start;
|
|
77
|
+
const m = re.exec(masked);
|
|
78
|
+
if (!m || m.index >= end) return null;
|
|
79
|
+
const at = m.index + m[0].length;
|
|
80
|
+
if (masked[at] === "{") return { dynamic: true };
|
|
81
|
+
const lit = literalAt(src, masked, at);
|
|
82
|
+
return lit !== null ? { value: lit } : { dynamic: true };
|
|
83
|
+
}
|
|
84
|
+
function scanOfferingRefs(files) {
|
|
64
85
|
const seen = /* @__PURE__ */ new Set();
|
|
65
86
|
const order = [];
|
|
66
87
|
let dynamic = false;
|
|
@@ -70,11 +91,28 @@ function scanProductRefs(files) {
|
|
|
70
91
|
order.push(v);
|
|
71
92
|
}
|
|
72
93
|
};
|
|
94
|
+
const surfaceSeen = /* @__PURE__ */ new Set();
|
|
95
|
+
const surfaces = [];
|
|
96
|
+
const kindSeen = /* @__PURE__ */ new Set();
|
|
97
|
+
const upsellKinds = [];
|
|
98
|
+
let checkoutDynamic = false;
|
|
99
|
+
const addSurface = (v) => {
|
|
100
|
+
if (v && !surfaceSeen.has(v)) {
|
|
101
|
+
surfaceSeen.add(v);
|
|
102
|
+
surfaces.push(v);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
const addKind = (v) => {
|
|
106
|
+
if (v && !kindSeen.has(v)) {
|
|
107
|
+
kindSeen.add(v);
|
|
108
|
+
upsellKinds.push(v);
|
|
109
|
+
}
|
|
110
|
+
};
|
|
73
111
|
for (const [path, source] of Object.entries(files)) {
|
|
74
112
|
if (!/\.(tsx|jsx|ts|js)$/.test(path)) continue;
|
|
75
113
|
const masked = mask(source);
|
|
76
|
-
for (const m of masked.matchAll(/\
|
|
77
|
-
const plural = source.slice(m.index, m.index +
|
|
114
|
+
for (const m of masked.matchAll(/\buseOfferings?\s*\(/g)) {
|
|
115
|
+
const plural = source.slice(m.index, m.index + 12) === "useOfferings";
|
|
78
116
|
const j = skipWs(masked, m.index + m[0].length);
|
|
79
117
|
if (masked[j] === ")") {
|
|
80
118
|
if (plural) dynamic = true;
|
|
@@ -84,14 +122,36 @@ function scanProductRefs(files) {
|
|
|
84
122
|
if (lit !== null) add(lit);
|
|
85
123
|
else dynamic = true;
|
|
86
124
|
}
|
|
87
|
-
for (const m of masked.matchAll(/<(?:Checkout|Upsell)\b[^>]*?\
|
|
125
|
+
for (const m of masked.matchAll(/<(?:Checkout|Upsell)\b[^>]*?\boffering\s*=\s*/g)) {
|
|
88
126
|
const j = m.index + m[0].length;
|
|
89
127
|
const lit = literalAt(source, masked, j);
|
|
90
128
|
if (lit !== null) add(lit);
|
|
91
129
|
else if (masked[j] === "{") dynamic = true;
|
|
92
130
|
}
|
|
131
|
+
for (const m of masked.matchAll(/<(Checkout|Upsell)\b/g)) {
|
|
132
|
+
const comp = m[1];
|
|
133
|
+
const tagStart = m.index + m[0].length;
|
|
134
|
+
const tagEnd = tagAttrEnd(masked, tagStart);
|
|
135
|
+
const attr = (name) => readAttr(source, masked, tagStart, tagEnd, name);
|
|
136
|
+
const fallback = attr("fallback");
|
|
137
|
+
if (fallback?.value) addSurface(fallback.value);
|
|
138
|
+
else if (fallback?.dynamic) checkoutDynamic = true;
|
|
139
|
+
const recovery = attr("recoverySurface");
|
|
140
|
+
if (recovery?.value) addSurface(recovery.value);
|
|
141
|
+
else if (recovery?.dynamic) checkoutDynamic = true;
|
|
142
|
+
if (comp === "Checkout") {
|
|
143
|
+
const surface = attr("surface");
|
|
144
|
+
if (surface?.value) addSurface(surface.value);
|
|
145
|
+
else if (surface?.dynamic) checkoutDynamic = true;
|
|
146
|
+
} else {
|
|
147
|
+
const kind = attr("kind");
|
|
148
|
+
if (kind?.value) addKind(kind.value);
|
|
149
|
+
else if (kind?.dynamic) checkoutDynamic = true;
|
|
150
|
+
else addKind("subscription");
|
|
151
|
+
}
|
|
152
|
+
}
|
|
93
153
|
}
|
|
94
|
-
return { slots: order, dynamic };
|
|
154
|
+
return { slots: order, dynamic, checkout: { surfaces, upsellKinds, dynamic: checkoutDynamic } };
|
|
95
155
|
}
|
|
96
156
|
|
|
97
157
|
// src/flow/scaffold.ts
|
|
@@ -102,7 +162,7 @@ var DRIVERS = {
|
|
|
102
162
|
stripe: { name: "stripeCheckoutDriver", sub: "driver-stripe" },
|
|
103
163
|
paddle: { name: "paddleCheckoutDriver", sub: "driver-paddle" }
|
|
104
164
|
};
|
|
105
|
-
var HEADER = "// GENERATED by
|
|
165
|
+
var HEADER = "// GENERATED by Appfunnel \u2014 do not edit. Built from funnel.ts + the pages/ folder.\n";
|
|
106
166
|
function generateMount(opts) {
|
|
107
167
|
const p = opts.importPrefix ?? "./";
|
|
108
168
|
const driver = opts.checkout ? DRIVERS[opts.checkout] : null;
|
|
@@ -112,7 +172,9 @@ function generateMount(opts) {
|
|
|
112
172
|
driver && `import { ${driver.name} } from '@appfunnel-dev/sdk/${driver.sub}'`,
|
|
113
173
|
`import { config } from '${p}funnel'`,
|
|
114
174
|
opts.hasLayout && `import Layout from '${p}layout'`,
|
|
115
|
-
...locales.map(
|
|
175
|
+
...locales.map(
|
|
176
|
+
(loc) => `import ${msgId(loc)} from '${p}messages/${loc}.json'`
|
|
177
|
+
)
|
|
116
178
|
].filter(Boolean).join("\n");
|
|
117
179
|
const loaders = opts.pageKeys.map(
|
|
118
180
|
(k) => ` ${JSON.stringify(k)}: () => import(${JSON.stringify(`${p}pages/${k}`)}),`
|
|
@@ -133,8 +195,10 @@ const loaders: Record<string, () => Promise<unknown>> = {
|
|
|
133
195
|
${loaders}
|
|
134
196
|
}
|
|
135
197
|
|
|
136
|
-
// Flow pages come from funnel.ts (order + meta + routing).
|
|
137
|
-
//
|
|
198
|
+
// Flow pages come from funnel.ts (order + meta + routing). A \`@variant\` page MAY also be declared
|
|
199
|
+
// there (with its \`@\` key) to carry its OWN optional routing (\`next\`) \u2014 it still collapses out of
|
|
200
|
+
// the linear flow by the \`@\` marker, but its meta rides along here. Any page file NOT declared is an
|
|
201
|
+
// off-flow \`@variant\` with no own routing, appended with empty meta so it's still loadable.
|
|
138
202
|
const decls = config.pages ?? []
|
|
139
203
|
const flowKeys = new Set(decls.map((d) => d.key))
|
|
140
204
|
export const pages: RuntimePage[] = [
|
|
@@ -180,7 +244,8 @@ import { tree, pages, type MountOpts } from './mount'
|
|
|
180
244
|
export const manifest = compileManifest({
|
|
181
245
|
funnel: config,
|
|
182
246
|
pages: pages.map((pg) => ({ key: pg.key, meta: pg.meta })),
|
|
183
|
-
|
|
247
|
+
offeringRefs: ${JSON.stringify(opts.offeringRefs ?? [])},
|
|
248
|
+
checkoutRefs: ${JSON.stringify(opts.checkoutRefs ?? { surfaces: [], upsellKinds: [], dynamic: false })},
|
|
184
249
|
})
|
|
185
250
|
|
|
186
251
|
export async function ssr(opts: MountOpts): Promise<string> {
|
|
@@ -204,124 +269,128 @@ if (el) createRoot(el).render(tree(${JSON.stringify(opts.data)}))
|
|
|
204
269
|
|
|
205
270
|
Object.defineProperty(exports, "assignVariant", {
|
|
206
271
|
enumerable: true,
|
|
207
|
-
get: function () { return
|
|
272
|
+
get: function () { return chunkY4YNJ2EX_cjs.assignVariant; }
|
|
208
273
|
});
|
|
209
274
|
Object.defineProperty(exports, "bucketingSeed", {
|
|
210
275
|
enumerable: true,
|
|
211
|
-
get: function () { return
|
|
276
|
+
get: function () { return chunkY4YNJ2EX_cjs.bucketingSeed; }
|
|
212
277
|
});
|
|
213
278
|
Object.defineProperty(exports, "buildCatalog", {
|
|
214
279
|
enumerable: true,
|
|
215
|
-
get: function () { return
|
|
280
|
+
get: function () { return chunkY4YNJ2EX_cjs.buildCatalog; }
|
|
216
281
|
});
|
|
217
282
|
Object.defineProperty(exports, "compileManifest", {
|
|
218
283
|
enumerable: true,
|
|
219
|
-
get: function () { return
|
|
284
|
+
get: function () { return chunkY4YNJ2EX_cjs.compileManifest; }
|
|
220
285
|
});
|
|
221
286
|
Object.defineProperty(exports, "currencyExponent", {
|
|
222
287
|
enumerable: true,
|
|
223
|
-
get: function () { return
|
|
288
|
+
get: function () { return chunkY4YNJ2EX_cjs.currencyExponent; }
|
|
224
289
|
});
|
|
225
290
|
Object.defineProperty(exports, "defineFunnel", {
|
|
226
291
|
enumerable: true,
|
|
227
|
-
get: function () { return
|
|
292
|
+
get: function () { return chunkY4YNJ2EX_cjs.defineFunnel; }
|
|
228
293
|
});
|
|
229
294
|
Object.defineProperty(exports, "entryGuard", {
|
|
230
295
|
enumerable: true,
|
|
231
|
-
get: function () { return
|
|
296
|
+
get: function () { return chunkY4YNJ2EX_cjs.entryGuard; }
|
|
232
297
|
});
|
|
233
298
|
Object.defineProperty(exports, "evaluateCondition", {
|
|
234
299
|
enumerable: true,
|
|
235
|
-
get: function () { return
|
|
300
|
+
get: function () { return chunkY4YNJ2EX_cjs.evaluateCondition; }
|
|
236
301
|
});
|
|
237
302
|
Object.defineProperty(exports, "formatMoney", {
|
|
238
303
|
enumerable: true,
|
|
239
|
-
get: function () { return
|
|
304
|
+
get: function () { return chunkY4YNJ2EX_cjs.formatMoney; }
|
|
240
305
|
});
|
|
241
|
-
Object.defineProperty(exports, "
|
|
306
|
+
Object.defineProperty(exports, "formatOffering", {
|
|
242
307
|
enumerable: true,
|
|
243
|
-
get: function () { return
|
|
308
|
+
get: function () { return chunkY4YNJ2EX_cjs.formatOffering; }
|
|
244
309
|
});
|
|
245
310
|
Object.defineProperty(exports, "funnelCatalogKeys", {
|
|
246
311
|
enumerable: true,
|
|
247
|
-
get: function () { return
|
|
312
|
+
get: function () { return chunkY4YNJ2EX_cjs.funnelCatalogKeys; }
|
|
248
313
|
});
|
|
249
314
|
Object.defineProperty(exports, "isRtl", {
|
|
250
315
|
enumerable: true,
|
|
251
|
-
get: function () { return
|
|
316
|
+
get: function () { return chunkY4YNJ2EX_cjs.isRtl; }
|
|
252
317
|
});
|
|
253
318
|
Object.defineProperty(exports, "isVariantKey", {
|
|
254
319
|
enumerable: true,
|
|
255
|
-
get: function () { return
|
|
320
|
+
get: function () { return chunkY4YNJ2EX_cjs.isVariantKey; }
|
|
256
321
|
});
|
|
257
|
-
Object.defineProperty(exports, "
|
|
322
|
+
Object.defineProperty(exports, "normalizeOfferings", {
|
|
258
323
|
enumerable: true,
|
|
259
|
-
get: function () { return
|
|
324
|
+
get: function () { return chunkY4YNJ2EX_cjs.normalizeOfferings; }
|
|
260
325
|
});
|
|
261
326
|
Object.defineProperty(exports, "pageMeta", {
|
|
262
327
|
enumerable: true,
|
|
263
|
-
get: function () { return
|
|
328
|
+
get: function () { return chunkY4YNJ2EX_cjs.pageMeta; }
|
|
264
329
|
});
|
|
265
330
|
Object.defineProperty(exports, "parseSlotKey", {
|
|
266
331
|
enumerable: true,
|
|
267
|
-
get: function () { return
|
|
332
|
+
get: function () { return chunkY4YNJ2EX_cjs.parseSlotKey; }
|
|
268
333
|
});
|
|
269
334
|
Object.defineProperty(exports, "resolveLocale", {
|
|
270
335
|
enumerable: true,
|
|
271
|
-
get: function () { return
|
|
272
|
-
});
|
|
273
|
-
Object.defineProperty(exports, "resolveProduct", {
|
|
274
|
-
enumerable: true,
|
|
275
|
-
get: function () { return chunkG44BUG6G_cjs.resolveProduct; }
|
|
336
|
+
get: function () { return chunkY4YNJ2EX_cjs.resolveLocale; }
|
|
276
337
|
});
|
|
277
|
-
Object.defineProperty(exports, "
|
|
338
|
+
Object.defineProperty(exports, "resolveOffering", {
|
|
278
339
|
enumerable: true,
|
|
279
|
-
get: function () { return
|
|
340
|
+
get: function () { return chunkY4YNJ2EX_cjs.resolveOffering; }
|
|
280
341
|
});
|
|
281
342
|
Object.defineProperty(exports, "weightsOf", {
|
|
282
343
|
enumerable: true,
|
|
283
|
-
get: function () { return
|
|
344
|
+
get: function () { return chunkY4YNJ2EX_cjs.weightsOf; }
|
|
284
345
|
});
|
|
285
346
|
Object.defineProperty(exports, "INLINE_SURFACES", {
|
|
286
347
|
enumerable: true,
|
|
287
|
-
get: function () { return
|
|
348
|
+
get: function () { return chunkRY3LOSVZ_cjs.INLINE_SURFACES; }
|
|
288
349
|
});
|
|
289
350
|
Object.defineProperty(exports, "PROVIDER_PROFILES", {
|
|
290
351
|
enumerable: true,
|
|
291
|
-
get: function () { return
|
|
352
|
+
get: function () { return chunkRY3LOSVZ_cjs.PROVIDER_PROFILES; }
|
|
292
353
|
});
|
|
293
354
|
Object.defineProperty(exports, "checkoutError", {
|
|
294
355
|
enumerable: true,
|
|
295
|
-
get: function () { return
|
|
356
|
+
get: function () { return chunkRY3LOSVZ_cjs.checkoutError; }
|
|
296
357
|
});
|
|
297
358
|
Object.defineProperty(exports, "isInlineSurface", {
|
|
298
359
|
enumerable: true,
|
|
299
|
-
get: function () { return
|
|
360
|
+
get: function () { return chunkRY3LOSVZ_cjs.isInlineSurface; }
|
|
300
361
|
});
|
|
301
362
|
Object.defineProperty(exports, "isMerchantOfRecord", {
|
|
302
363
|
enumerable: true,
|
|
303
|
-
get: function () { return
|
|
364
|
+
get: function () { return chunkRY3LOSVZ_cjs.isMerchantOfRecord; }
|
|
304
365
|
});
|
|
305
366
|
Object.defineProperty(exports, "isOrchestrator", {
|
|
306
367
|
enumerable: true,
|
|
307
|
-
get: function () { return
|
|
368
|
+
get: function () { return chunkRY3LOSVZ_cjs.isOrchestrator; }
|
|
308
369
|
});
|
|
309
370
|
Object.defineProperty(exports, "surfacesFor", {
|
|
310
371
|
enumerable: true,
|
|
311
|
-
get: function () { return
|
|
372
|
+
get: function () { return chunkRY3LOSVZ_cjs.surfacesFor; }
|
|
373
|
+
});
|
|
374
|
+
Object.defineProperty(exports, "trialShapesFor", {
|
|
375
|
+
enumerable: true,
|
|
376
|
+
get: function () { return chunkRY3LOSVZ_cjs.trialShapesFor; }
|
|
312
377
|
});
|
|
313
378
|
Object.defineProperty(exports, "validateCheckout", {
|
|
314
379
|
enumerable: true,
|
|
315
|
-
get: function () { return
|
|
380
|
+
get: function () { return chunkRY3LOSVZ_cjs.validateCheckout; }
|
|
381
|
+
});
|
|
382
|
+
Object.defineProperty(exports, "validateTrial", {
|
|
383
|
+
enumerable: true,
|
|
384
|
+
get: function () { return chunkRY3LOSVZ_cjs.validateTrial; }
|
|
316
385
|
});
|
|
317
386
|
Object.defineProperty(exports, "validateUpsell", {
|
|
318
387
|
enumerable: true,
|
|
319
|
-
get: function () { return
|
|
388
|
+
get: function () { return chunkRY3LOSVZ_cjs.validateUpsell; }
|
|
320
389
|
});
|
|
321
390
|
exports.generateDevEntry = generateDevEntry;
|
|
322
391
|
exports.generateEntryClient = generateEntryClient;
|
|
323
392
|
exports.generateEntryServer = generateEntryServer;
|
|
324
393
|
exports.generateMount = generateMount;
|
|
325
|
-
exports.
|
|
394
|
+
exports.scanOfferingRefs = scanOfferingRefs;
|
|
326
395
|
//# sourceMappingURL=manifest-entry.cjs.map
|
|
327
396
|
//# sourceMappingURL=manifest-entry.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/manifest/product-refs.ts","../src/flow/scaffold.ts"],"names":[],"mappings":"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","file":"manifest-entry.cjs","sourcesContent":["/**\n * Pure, React-free page scan: find which product SLOTS a funnel's pages reference — the first\n * string-literal arg of `useProduct(...)` and the `product` prop of `<Checkout>` / `<Upsell>`.\n * Ships via `@appfunnel-dev/sdk/manifest` so the BUILD, the EDITOR, and the AI all run the SAME\n * check. The result feeds `compileManifest({ productRefs })`, which flags references to slots the\n * funnel doesn't declare (unknown) or hasn't assigned a catalog product to (unassigned).\n *\n * Non-literal args (`useProduct(selectedId)`, `product={expr}`) and the `useProducts()` wildcard are\n * DYNAMIC — they can't be statically enumerated, so they're reported via `dynamic` and never turned\n * into a hard error (validation relaxes when a funnel is dynamic). Mirrors the mask-then-read\n * discipline the funnel.ts code-mods use, so a `useProduct('x')` inside a comment or string literal\n * can't false-positive.\n */\n\nexport interface ProductRefScan {\n /** Concrete slot names referenced by LITERAL args, deduped, in first-seen order. */\n slots: string[]\n /** True if any ref is a non-literal arg or a `useProducts()` wildcard (not statically enumerable). */\n dynamic: boolean\n}\n\n/** Blank comment + string/template CONTENTS (keep quote delimiters + length) so scans don't fire inside them. */\nfunction mask(src: string): string {\n const out = src.split('')\n const n = src.length\n let i = 0\n while (i < n) {\n const c = src[i]\n const d = src[i + 1]\n if (c === '/' && d === '/') {\n while (i < n && src[i] !== '\\n') { out[i] = ' '; i++ }\n } else if (c === '/' && d === '*') {\n out[i] = ' '; out[i + 1] = ' '; i += 2\n while (i < n) {\n if (src[i] === '*' && src[i + 1] === '/') { out[i] = ' '; out[i + 1] = ' '; i += 2; break }\n if (src[i] !== '\\n') out[i] = ' '\n i++\n }\n } else if (c === \"'\" || c === '\"' || c === '`') {\n i++\n while (i < n && src[i] !== c) {\n if (src[i] === '\\\\') { out[i] = ' '; i++; if (i < n && src[i] !== '\\n') out[i] = ' '; i++; continue }\n if (src[i] !== '\\n') out[i] = ' '\n i++\n }\n i++ // closing delimiter (kept)\n } else i++\n }\n return out.join('')\n}\n\n/** A quoted string literal starting at `open` (a quote char in the MASK). Value read from the ORIGINAL. */\nfunction literalAt(src: string, masked: string, open: number): string | null {\n const q = masked[open]\n if (q !== \"'\" && q !== '\"' && q !== '`') return null\n const close = masked.indexOf(q, open + 1)\n if (close === -1) return null\n return src.slice(open + 1, close)\n}\n\n/** Advance past whitespace in `masked` from `i`. */\nfunction skipWs(masked: string, i: number): number {\n while (i < masked.length && (masked[i] === ' ' || masked[i] === '\\t' || masked[i] === '\\n' || masked[i] === '\\r')) i++\n return i\n}\n\nexport function scanProductRefs(files: Record<string, string>): ProductRefScan {\n const seen = new Set<string>()\n const order: string[] = []\n let dynamic = false\n const add = (v: string) => { if (v && !seen.has(v)) { seen.add(v); order.push(v) } }\n\n for (const [path, source] of Object.entries(files)) {\n if (!/\\.(tsx|jsx|ts|js)$/.test(path)) continue\n const masked = mask(source)\n\n // useProduct( … ) / useProducts( … ) — positions on the MASK (a call inside a string won't match).\n for (const m of masked.matchAll(/\\buseProducts?\\s*\\(/g)) {\n const plural = source.slice(m.index!, m.index! + 11) === 'useProducts'\n const j = skipWs(masked, m.index! + m[0].length)\n if (masked[j] === ')') { if (plural) dynamic = true; continue } // useProducts() = whole-catalog wildcard\n const lit = literalAt(source, masked, j)\n if (lit !== null) add(lit)\n else dynamic = true // useProduct(variable) — can't resolve statically\n }\n\n // <Checkout product=\"…\"> / <Upsell product=\"…\"> — the `product` attribute value.\n for (const m of masked.matchAll(/<(?:Checkout|Upsell)\\b[^>]*?\\bproduct\\s*=\\s*/g)) {\n const j = m.index! + m[0].length\n const lit = literalAt(source, masked, j)\n if (lit !== null) add(lit)\n else if (masked[j] === '{') dynamic = true // product={expr}\n }\n }\n return { slots: order, dynamic }\n}\n","/**\n * Source generators for the funnel build \"machinery\" authors no longer write. `funnel.ts` (the\n * spine: id, responses, products, checkout, and the page list + declarative routing) plus the\n * `pages/` folder are the ONLY authored source. The build (renderer/builder) and the CLI dev server\n * call these to synthesize:\n * - `mount.tsx` — code-split page loaders + `createFunnelTree`\n * - `entry.client.tsx` — hydrate the SSR'd markup from injected data\n * - `entry.server.tsx` — `ssr()` + the compiled `manifest`\n *\n * All string templates, zero runtime deps — this module lives in the pure `@appfunnel-dev/sdk/\n * manifest` entry so tooling imports it without the funnel runtime.\n */\n\nexport interface ScaffoldOptions {\n\t/** Page component keys = `pages/<key>.tsx` filenames (base flow pages AND `@variant` pages). */\n\tpageKeys: string[]\n\t/** Import prefix to reach the funnel root: `'./'` at the root (build), `'../../'` in a subdir (CLI dev). */\n\timportPrefix?: string\n\t/** Whether a `layout.tsx` exists to wrap the pages. */\n\thasLayout?: boolean\n\t/** Whether a `styles.css` exists (client entry imports it). */\n\thasStyles?: boolean\n\t/** Checkout provider from `config.checkout` — wires the driver; omit for none. */\n\tcheckout?: 'stripe' | 'paddle' | null\n\t/** Locales with a `messages/<locale>.json` catalog to bake into the mount (so `t()` resolves at render). */\n\tmessageLocales?: string[]\n\t/** Slot names the pages reference (from `scanProductRefs`), baked into the manifest for validation. */\n\tproductRefs?: string[]\n}\n\n/** A safe JS identifier for a message-catalog import (`en` → `msg_en`, `pt-BR` → `msg_pt_BR`). */\nfunction msgId(locale: string): string {\n\treturn 'msg_' + locale.replace(/[^a-zA-Z0-9]/g, '_')\n}\n\nconst DRIVERS = {\n\tstripe: { name: 'stripeCheckoutDriver', sub: 'driver-stripe' },\n\tpaddle: { name: 'paddleCheckoutDriver', sub: 'driver-paddle' },\n} as const\n\nconst HEADER = '// GENERATED by AppFunnel — do not edit. Built from funnel.ts + the pages/ folder.\\n'\n\n/** `mount.tsx` — the code-split loaders + tree, derived from `config.pages` and the `pages/` files. */\nexport function generateMount(opts: ScaffoldOptions): string {\n\tconst p = opts.importPrefix ?? './'\n\tconst driver = opts.checkout ? DRIVERS[opts.checkout] : null\n\n\tconst locales = opts.messageLocales ?? []\n\tconst imports = [\n\t\t`import { createFunnelTree, type MountOpts, type RuntimePage } from '@appfunnel-dev/sdk'`,\n\t\tdriver && `import { ${driver.name} } from '@appfunnel-dev/sdk/${driver.sub}'`,\n\t\t`import { config } from '${p}funnel'`,\n\t\topts.hasLayout && `import Layout from '${p}layout'`,\n\t\t...locales.map((loc) => `import ${msgId(loc)} from '${p}messages/${loc}.json'`),\n\t]\n\t\t.filter(Boolean)\n\t\t.join('\\n')\n\n\t// A static import() per page file so Vite emits one code-split chunk each.\n\tconst loaders = opts.pageKeys\n\t\t.map(\n\t\t\t(k) => `\\t${JSON.stringify(k)}: () => import(${JSON.stringify(`${p}pages/${k}`)}),`\n\t\t)\n\t\t.join('\\n')\n\n\tconst treeArgs = [\n\t\t'config',\n\t\t'pages',\n\t\topts.hasLayout && 'layout: Layout',\n\t\tdriver && `checkoutDriver: ${driver.name}`,\n\t\tlocales.length > 0 && 'messages',\n\t]\n\t\t.filter(Boolean)\n\t\t.join(', ')\n\n\t// The baked message catalog: locale → messages/<locale>.json (so `t()` resolves at render).\n\tconst messagesConst =\n\t\tlocales.length > 0\n\t\t\t? `\\nconst messages = { ${locales.map((loc) => `${JSON.stringify(loc)}: ${msgId(loc)}`).join(', ')} }\\n`\n\t\t\t: ''\n\n\treturn `${HEADER}${imports}\n\nconst loaders: Record<string, () => Promise<unknown>> = {\n${loaders}\n}\n\n// Flow pages come from funnel.ts (order + meta + routing). Any remaining page file is an off-flow\n// \\`@variant\\` page (wired by experiment records at render time), appended so it's loadable.\nconst decls = config.pages ?? []\nconst flowKeys = new Set(decls.map((d) => d.key))\nexport const pages: RuntimePage[] = [\n\t...decls.map((d) => ({ key: d.key, meta: d, load: loaders[d.key] })),\n\t...Object.keys(loaders)\n\t\t.filter((k) => !flowKeys.has(k))\n\t\t.map((k) => ({ key: k, meta: {}, load: loaders[k] })),\n] as RuntimePage[]\n${messagesConst}\nexport const tree = createFunnelTree({ ${treeArgs} })\n\nexport type { MountOpts }\n`\n}\n\n/** `entry.client.tsx` — hydrate the SSR'd markup from the injected `#__af_data`. */\nexport function generateEntryClient(opts: Pick<ScaffoldOptions, 'importPrefix' | 'hasStyles'>): string {\n\tconst p = opts.importPrefix ?? './'\n\tconst styles = opts.hasStyles ? `import '${p}styles.css'\\n` : ''\n\treturn `${HEADER}${styles}import { hydrateRoot } from 'react-dom/client'\nimport { tree, type MountOpts } from './mount'\n\nconst dataEl = document.getElementById('__af_data')\nconst data = (dataEl?.textContent ? JSON.parse(dataEl.textContent) : {}) as MountOpts & {\n\tinitialKey?: string | null\n}\nconst root = document.getElementById('root')\n// FLASH-FREE HYDRATION (SSR-isolation Option B): always DEFER sessionValues on the client. The\n// markup we hydrate against is DEFAULT-state (build-time prerendered, or an SSR render with empty\n// sessionValues), so seeding the store with defaults for the first render is a byte-clean match —\n// no hydration mismatch. The visitor's saved answers (data.sessionValues, present on the \"tail\"\n// path) are then applied post-hydration, popping into already-visible controls with no empty\n// flash. On the cold path sessionValues is absent, so deferring is a no-op (identical output).\nif (root) hydrateRoot(root, tree({ ...data, initialKey: data.initialKey ?? undefined, deferSessionValues: true }))\n`\n}\n\n/** `entry.server.tsx` — `ssr(opts)` HTML + the compiled `manifest` (read by the build). */\nexport function generateEntryServer(opts: Pick<ScaffoldOptions, 'importPrefix' | 'productRefs'>): string {\n\tconst p = opts.importPrefix ?? './'\n\treturn `${HEADER}import { renderToReadableStream } from 'react-dom/server.browser'\nimport { compileManifest } from '@appfunnel-dev/sdk'\nimport { config } from '${p}funnel'\nimport { tree, pages, type MountOpts } from './mount'\n\nexport const manifest = compileManifest({\n\tfunnel: config,\n\tpages: pages.map((pg) => ({ key: pg.key, meta: pg.meta })),\n\tproductRefs: ${JSON.stringify(opts.productRefs ?? [])},\n})\n\nexport async function ssr(opts: MountOpts): Promise<string> {\n\tconst stream = await renderToReadableStream(tree(opts))\n\tawait stream.allReady\n\treturn await new Response(stream).text()\n}\n`\n}\n\n/** Client-only dev entry (createRoot, no SSR) — for the CLI `dev` server. */\nexport function generateDevEntry(\n\topts: Pick<ScaffoldOptions, 'importPrefix' | 'hasStyles'> & { data: unknown }\n): string {\n\tconst p = opts.importPrefix ?? './'\n\tconst styles = opts.hasStyles ? `import '${p}styles.css'\\n` : ''\n\treturn `${HEADER}${styles}import { createRoot } from 'react-dom/client'\nimport { tree } from './mount'\n\nconst el = document.getElementById('root')\nif (el) createRoot(el).render(tree(${JSON.stringify(opts.data)}))\n`\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/manifest/offering-refs.ts","../src/flow/scaffold.ts"],"names":[],"mappings":"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","file":"manifest-entry.cjs","sourcesContent":["/**\n * Pure, React-free page scan: find which offering SLOTS a funnel's pages reference — the first\n * string-literal arg of `useOffering(...)` and the `offering` prop of `<Checkout>` / `<Upsell>`.\n * Ships via `@appfunnel-dev/sdk/manifest` so the BUILD, the EDITOR, and the AI all run the SAME\n * check. The result feeds `compileManifest({ offeringRefs })`, which flags references to slots the\n * funnel doesn't declare (unknown) or hasn't assigned a catalog charge key to (unassigned).\n *\n * Non-literal args (`useOffering(selectedId)`, `offering={expr}`) and the `useOfferings()` wildcard are\n * DYNAMIC — they can't be statically enumerated, so they're reported via `dynamic` and never turned\n * into a hard error (validation relaxes when a funnel is dynamic). Mirrors the mask-then-read\n * discipline the funnel.ts code-mods use, so a `useOffering('x')` inside a comment or string literal\n * can't false-positive.\n */\n\nexport interface OfferingRefScan {\n /** Concrete slot names referenced by LITERAL args, deduped, in first-seen order. */\n slots: string[]\n /** True if any ref is a non-literal arg or a `useOfferings()` wildcard (not statically enumerable). */\n dynamic: boolean\n /**\n * Checkout-SURFACE usage the pages express — feeds the publish (provider × surface) capability\n * gate. Absent-field back-compat: a manifest compiled before this existed simply omits it, and\n * the gate skips (no false blocks). See {@link CheckoutUsageScan}.\n */\n checkout: CheckoutUsageScan\n}\n\n/**\n * What the pages ask the checkout to DO, statically — the surfaces they mount and the off-session\n * upsell kinds they charge. Literal values only; a computed value (`surface={expr}`) sets\n * {@link dynamic} so the publish gate WARNS instead of hard-failing (it can't enumerate it).\n */\nexport interface CheckoutUsageScan {\n /**\n * Purchase SURFACES the pages request, deduped in first-seen order. Captures every literal\n * `<Checkout surface=\"…\">` plus the on-session re-collect surfaces `<Checkout|Upsell fallback=\"…\">`\n * and `recoverySurface=\"…\"` (a fallback re-collects a card → it IS a purchase surface the provider\n * must support). Validated with `validateCheckout(provider, surface)`.\n */\n surfaces: string[]\n /**\n * Off-session upsell KINDS from `<Upsell kind=\"…\">`, deduped. A `<Upsell>` with no `kind` attr\n * defaults to `'subscription'` (mirrors the runtime default), so an unadorned `<Upsell>` records\n * `'subscription'`. Validated with `validateUpsell(provider, paywallSurface, kind)`.\n */\n upsellKinds: string[]\n /** True if any surface/kind was a non-literal (computed) value → the gate WARNS, never blocks, on it. */\n dynamic: boolean\n}\n\n/** Blank comment + string/template CONTENTS (keep quote delimiters + length) so scans don't fire inside them. */\nfunction mask(src: string): string {\n const out = src.split('')\n const n = src.length\n let i = 0\n while (i < n) {\n const c = src[i]\n const d = src[i + 1]\n if (c === '/' && d === '/') {\n while (i < n && src[i] !== '\\n') { out[i] = ' '; i++ }\n } else if (c === '/' && d === '*') {\n out[i] = ' '; out[i + 1] = ' '; i += 2\n while (i < n) {\n if (src[i] === '*' && src[i + 1] === '/') { out[i] = ' '; out[i + 1] = ' '; i += 2; break }\n if (src[i] !== '\\n') out[i] = ' '\n i++\n }\n } else if (c === \"'\" || c === '\"' || c === '`') {\n i++\n while (i < n && src[i] !== c) {\n if (src[i] === '\\\\') { out[i] = ' '; i++; if (i < n && src[i] !== '\\n') out[i] = ' '; i++; continue }\n if (src[i] !== '\\n') out[i] = ' '\n i++\n }\n i++ // closing delimiter (kept)\n } else i++\n }\n return out.join('')\n}\n\n/** A quoted string literal starting at `open` (a quote char in the MASK). Value read from the ORIGINAL. */\nfunction literalAt(src: string, masked: string, open: number): string | null {\n const q = masked[open]\n if (q !== \"'\" && q !== '\"' && q !== '`') return null\n const close = masked.indexOf(q, open + 1)\n if (close === -1) return null\n return src.slice(open + 1, close)\n}\n\n/** Advance past whitespace in `masked` from `i`. */\nfunction skipWs(masked: string, i: number): number {\n while (i < masked.length && (masked[i] === ' ' || masked[i] === '\\t' || masked[i] === '\\n' || masked[i] === '\\r')) i++\n return i\n}\n\n/**\n * Index of the `>` that closes the opening tag begun at `from` (the char after `<Checkout`). Tracks\n * brace depth so a `surface={a > b}` attribute expression doesn't end the tag early; `>` at depth 0\n * closes it (covers `/>` too — the `/` is at depth 0 and we stop at `>`). Returns end-of-string if\n * the tag never closes (masked never fires a value scan past it).\n */\nfunction tagAttrEnd(masked: string, from: number): number {\n let depth = 0\n for (let i = from; i < masked.length; i++) {\n const c = masked[i]\n if (c === '{') depth++\n else if (c === '}') { if (depth > 0) depth-- }\n else if (c === '>' && depth === 0) return i\n }\n return masked.length\n}\n\n/**\n * Read a JSX attribute `name` inside the opening-tag span `[start, end)`: returns its literal value,\n * `{ dynamic: true }` for a `{expr}` value, or null when the attribute is absent. Positions are on\n * the MASK; the value is read from the ORIGINAL (so a string-literal value survives masking).\n */\nfunction readAttr(\n src: string,\n masked: string,\n start: number,\n end: number,\n name: string,\n): { value?: string; dynamic?: boolean } | null {\n const re = new RegExp(`\\\\b${name}\\\\s*=\\\\s*`, 'g')\n re.lastIndex = start\n const m = re.exec(masked)\n if (!m || m.index >= end) return null\n const at = m.index + m[0].length\n if (masked[at] === '{') return { dynamic: true }\n const lit = literalAt(src, masked, at)\n return lit !== null ? { value: lit } : { dynamic: true }\n}\n\nexport function scanOfferingRefs(files: Record<string, string>): OfferingRefScan {\n const seen = new Set<string>()\n const order: string[] = []\n let dynamic = false\n const add = (v: string) => { if (v && !seen.has(v)) { seen.add(v); order.push(v) } }\n\n // Checkout-surface usage (separate dynamic flag: a computed SURFACE relaxes the capability gate,\n // independent of whether an OFFERING ref is computed).\n const surfaceSeen = new Set<string>()\n const surfaces: string[] = []\n const kindSeen = new Set<string>()\n const upsellKinds: string[] = []\n let checkoutDynamic = false\n const addSurface = (v: string) => { if (v && !surfaceSeen.has(v)) { surfaceSeen.add(v); surfaces.push(v) } }\n const addKind = (v: string) => { if (v && !kindSeen.has(v)) { kindSeen.add(v); upsellKinds.push(v) } }\n\n for (const [path, source] of Object.entries(files)) {\n if (!/\\.(tsx|jsx|ts|js)$/.test(path)) continue\n const masked = mask(source)\n\n // useOffering( … ) / useOfferings( … ) — positions on the MASK (a call inside a string won't match).\n for (const m of masked.matchAll(/\\buseOfferings?\\s*\\(/g)) {\n const plural = source.slice(m.index!, m.index! + 12) === 'useOfferings'\n const j = skipWs(masked, m.index! + m[0].length)\n if (masked[j] === ')') { if (plural) dynamic = true; continue } // useOfferings() = whole-catalog wildcard\n const lit = literalAt(source, masked, j)\n if (lit !== null) add(lit)\n else dynamic = true // useOffering(variable) — can't resolve statically\n }\n\n // <Checkout offering=\"…\"> / <Upsell offering=\"…\"> — the `offering` attribute value.\n for (const m of masked.matchAll(/<(?:Checkout|Upsell)\\b[^>]*?\\boffering\\s*=\\s*/g)) {\n const j = m.index! + m[0].length\n const lit = literalAt(source, masked, j)\n if (lit !== null) add(lit)\n else if (masked[j] === '{') dynamic = true // offering={expr}\n }\n\n // <Checkout …> / <Upsell …> checkout-SURFACE usage. Parse each opening tag's attribute span so\n // attribute order doesn't matter and a `>` inside a `{expr}` value can't truncate it.\n for (const m of masked.matchAll(/<(Checkout|Upsell)\\b/g)) {\n const comp = m[1]\n const tagStart = m.index! + m[0].length\n const tagEnd = tagAttrEnd(masked, tagStart)\n const attr = (name: string) => readAttr(source, masked, tagStart, tagEnd, name)\n // A fallback / recoverySurface re-collects a card ON-SESSION → it's a purchase surface too.\n const fallback = attr('fallback')\n if (fallback?.value) addSurface(fallback.value)\n else if (fallback?.dynamic) checkoutDynamic = true\n const recovery = attr('recoverySurface')\n if (recovery?.value) addSurface(recovery.value)\n else if (recovery?.dynamic) checkoutDynamic = true\n\n if (comp === 'Checkout') {\n const surface = attr('surface')\n if (surface?.value) addSurface(surface.value)\n else if (surface?.dynamic) checkoutDynamic = true\n } else {\n // <Upsell>: off-session; `kind` defaults to 'subscription' when the attr is absent.\n const kind = attr('kind')\n if (kind?.value) addKind(kind.value)\n else if (kind?.dynamic) checkoutDynamic = true\n else addKind('subscription')\n }\n }\n }\n return { slots: order, dynamic, checkout: { surfaces, upsellKinds, dynamic: checkoutDynamic } }\n}\n","/**\n * Source generators for the funnel build \"machinery\" authors no longer write. `funnel.ts` (the\n * spine: id, responses, offerings, checkout, and the page list + declarative routing) plus the\n * `pages/` folder are the ONLY authored source. The build (renderer/builder) and the CLI dev server\n * call these to synthesize:\n * - `mount.tsx` — code-split page loaders + `createFunnelTree`\n * - `entry.client.tsx` — hydrate the SSR'd markup from injected data\n * - `entry.server.tsx` — `ssr()` + the compiled `manifest`\n *\n * All string templates, zero runtime deps — this module lives in the pure `@appfunnel-dev/sdk/\n * manifest` entry so tooling imports it without the funnel runtime.\n */\n\nimport type { CheckoutUsageScan } from '../manifest/offering-refs'\n\nexport interface ScaffoldOptions {\n\t/** Page component keys = `pages/<key>.tsx` filenames (base flow pages AND `@variant` pages). */\n\tpageKeys: string[]\n\t/** Import prefix to reach the funnel root: `'./'` at the root (build), `'../../'` in a subdir (CLI dev). */\n\timportPrefix?: string\n\t/** Whether a `layout.tsx` exists to wrap the pages. */\n\thasLayout?: boolean\n\t/** Whether a `styles.css` exists (client entry imports it). */\n\thasStyles?: boolean\n\t/** Checkout provider from `config.checkout` — wires the driver; omit for none. */\n\tcheckout?: 'stripe' | 'paddle' | null\n\t/** Locales with a `messages/<locale>.json` catalog to bake into the mount (so `t()` resolves at render). */\n\tmessageLocales?: string[]\n\t/** Slot names the pages reference (from `scanOfferingRefs`), baked into the manifest for validation. */\n\tofferingRefs?: string[]\n\t/** Checkout-surface usage the pages express (from `scanOfferingRefs(...).checkout`), baked into the manifest for the publish capability gate. */\n\tcheckoutRefs?: CheckoutUsageScan\n}\n\n/** A safe JS identifier for a message-catalog import (`en` → `msg_en`, `pt-BR` → `msg_pt_BR`). */\nfunction msgId(locale: string): string {\n\treturn 'msg_' + locale.replace(/[^a-zA-Z0-9]/g, '_')\n}\n\nconst DRIVERS = {\n\tstripe: { name: 'stripeCheckoutDriver', sub: 'driver-stripe' },\n\tpaddle: { name: 'paddleCheckoutDriver', sub: 'driver-paddle' },\n} as const\n\nconst HEADER =\n\t'// GENERATED by Appfunnel — do not edit. Built from funnel.ts + the pages/ folder.\\n'\n\n/** `mount.tsx` — the code-split loaders + tree, derived from `config.pages` and the `pages/` files. */\nexport function generateMount(opts: ScaffoldOptions): string {\n\tconst p = opts.importPrefix ?? './'\n\tconst driver = opts.checkout ? DRIVERS[opts.checkout] : null\n\n\tconst locales = opts.messageLocales ?? []\n\tconst imports = [\n\t\t`import { createFunnelTree, type MountOpts, type RuntimePage } from '@appfunnel-dev/sdk'`,\n\t\tdriver &&\n\t\t\t`import { ${driver.name} } from '@appfunnel-dev/sdk/${driver.sub}'`,\n\t\t`import { config } from '${p}funnel'`,\n\t\topts.hasLayout && `import Layout from '${p}layout'`,\n\t\t...locales.map(\n\t\t\t(loc) => `import ${msgId(loc)} from '${p}messages/${loc}.json'`\n\t\t),\n\t]\n\t\t.filter(Boolean)\n\t\t.join('\\n')\n\n\t// A static import() per page file so Vite emits one code-split chunk each.\n\tconst loaders = opts.pageKeys\n\t\t.map(\n\t\t\t(k) =>\n\t\t\t\t`\\t${JSON.stringify(k)}: () => import(${JSON.stringify(`${p}pages/${k}`)}),`\n\t\t)\n\t\t.join('\\n')\n\n\tconst treeArgs = [\n\t\t'config',\n\t\t'pages',\n\t\topts.hasLayout && 'layout: Layout',\n\t\tdriver && `checkoutDriver: ${driver.name}`,\n\t\tlocales.length > 0 && 'messages',\n\t]\n\t\t.filter(Boolean)\n\t\t.join(', ')\n\n\t// The baked message catalog: locale → messages/<locale>.json (so `t()` resolves at render).\n\tconst messagesConst =\n\t\tlocales.length > 0\n\t\t\t? `\\nconst messages = { ${locales.map((loc) => `${JSON.stringify(loc)}: ${msgId(loc)}`).join(', ')} }\\n`\n\t\t\t: ''\n\n\treturn `${HEADER}${imports}\n\nconst loaders: Record<string, () => Promise<unknown>> = {\n${loaders}\n}\n\n// Flow pages come from funnel.ts (order + meta + routing). A \\`@variant\\` page MAY also be declared\n// there (with its \\`@\\` key) to carry its OWN optional routing (\\`next\\`) — it still collapses out of\n// the linear flow by the \\`@\\` marker, but its meta rides along here. Any page file NOT declared is an\n// off-flow \\`@variant\\` with no own routing, appended with empty meta so it's still loadable.\nconst decls = config.pages ?? []\nconst flowKeys = new Set(decls.map((d) => d.key))\nexport const pages: RuntimePage[] = [\n\t...decls.map((d) => ({ key: d.key, meta: d, load: loaders[d.key] })),\n\t...Object.keys(loaders)\n\t\t.filter((k) => !flowKeys.has(k))\n\t\t.map((k) => ({ key: k, meta: {}, load: loaders[k] })),\n] as RuntimePage[]\n${messagesConst}\nexport const tree = createFunnelTree({ ${treeArgs} })\n\nexport type { MountOpts }\n`\n}\n\n/** `entry.client.tsx` — hydrate the SSR'd markup from the injected `#__af_data`. */\nexport function generateEntryClient(\n\topts: Pick<ScaffoldOptions, 'importPrefix' | 'hasStyles'>\n): string {\n\tconst p = opts.importPrefix ?? './'\n\tconst styles = opts.hasStyles ? `import '${p}styles.css'\\n` : ''\n\treturn `${HEADER}${styles}import { hydrateRoot } from 'react-dom/client'\nimport { tree, type MountOpts } from './mount'\n\nconst dataEl = document.getElementById('__af_data')\nconst data = (dataEl?.textContent ? JSON.parse(dataEl.textContent) : {}) as MountOpts & {\n\tinitialKey?: string | null\n}\nconst root = document.getElementById('root')\n// FLASH-FREE HYDRATION (SSR-isolation Option B): always DEFER sessionValues on the client. The\n// markup we hydrate against is DEFAULT-state (build-time prerendered, or an SSR render with empty\n// sessionValues), so seeding the store with defaults for the first render is a byte-clean match —\n// no hydration mismatch. The visitor's saved answers (data.sessionValues, present on the \"tail\"\n// path) are then applied post-hydration, popping into already-visible controls with no empty\n// flash. On the cold path sessionValues is absent, so deferring is a no-op (identical output).\nif (root) hydrateRoot(root, tree({ ...data, initialKey: data.initialKey ?? undefined, deferSessionValues: true }))\n`\n}\n\n/** `entry.server.tsx` — `ssr(opts)` HTML + the compiled `manifest` (read by the build). */\nexport function generateEntryServer(\n\topts: Pick<ScaffoldOptions, 'importPrefix' | 'offeringRefs' | 'checkoutRefs'>\n): string {\n\tconst p = opts.importPrefix ?? './'\n\treturn `${HEADER}import { renderToReadableStream } from 'react-dom/server.browser'\nimport { compileManifest } from '@appfunnel-dev/sdk'\nimport { config } from '${p}funnel'\nimport { tree, pages, type MountOpts } from './mount'\n\nexport const manifest = compileManifest({\n\tfunnel: config,\n\tpages: pages.map((pg) => ({ key: pg.key, meta: pg.meta })),\n\tofferingRefs: ${JSON.stringify(opts.offeringRefs ?? [])},\n\tcheckoutRefs: ${JSON.stringify(opts.checkoutRefs ?? { surfaces: [], upsellKinds: [], dynamic: false })},\n})\n\nexport async function ssr(opts: MountOpts): Promise<string> {\n\tconst stream = await renderToReadableStream(tree(opts))\n\tawait stream.allReady\n\treturn await new Response(stream).text()\n}\n`\n}\n\n/** Client-only dev entry (createRoot, no SSR) — for the CLI `dev` server. */\nexport function generateDevEntry(\n\topts: Pick<ScaffoldOptions, 'importPrefix' | 'hasStyles'> & {\n\t\tdata: unknown\n\t}\n): string {\n\tconst p = opts.importPrefix ?? './'\n\tconst styles = opts.hasStyles ? `import '${p}styles.css'\\n` : ''\n\treturn `${HEADER}${styles}import { createRoot } from 'react-dom/client'\nimport { tree } from './mount'\n\nconst el = document.getElementById('root')\nif (el) createRoot(el).render(tree(${JSON.stringify(opts.data)}))\n`\n}\n"]}
|
|
@@ -1,32 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { af as CheckoutUsageScan } from './manifest-B3Tdab0M.cjs';
|
|
2
|
+
export { h as CompileInput, i as Condition, j as ConditionOp, E as EdgeCondition, l as ExperimentArm, n as FlowPage, c as FunnelDefinition, o as FunnelLocales, p as FunnelManifest, ag as FunnelPage, b as FunnelSnapshot, G as Gate, q as Interval, M as ManifestEdge, r as ManifestPage, s as ManifestValidation, t as Money, O as Offering, e as OfferingInput, ah as OfferingRefScan, ai as OfferingSlot, P as PageMeta, v as PageType, w as Predicate, x as ResolvedOffering, y as Route, R as RuntimeExperiment, H as assignVariant, J as bucketingSeed, N as buildCatalog, Q as compileManifest, T as currencyExponent, W as defineFunnel, Y as entryGuard, Z as evaluateCondition, a1 as formatMoney, a2 as formatOffering, aj as funnelCatalogKeys, a4 as isRtl, a5 as isVariantKey, ak as normalizeOfferings, a8 as pageMeta, a9 as parseSlotKey, ac as resolveLocale, ad as resolveOffering, al as scanOfferingRefs, am as weightsOf } from './manifest-B3Tdab0M.cjs';
|
|
3
|
+
import { C as CheckoutError, b as CheckoutIntent, U as UpsellKind, d as CheckoutSurface } from './capabilities-CsnkVwna.cjs';
|
|
4
|
+
export { a as CheckoutErrorCategory, c as CheckoutProvider, I as INLINE_SURFACES, O as OffSessionReliability, P as PROVIDER_PROFILES, e as ProviderProfile, S as SurfaceCapability, T as TrialShape, V as ValidationResult, f as checkoutError, i as isInlineSurface, g as isMerchantOfRecord, h as isOrchestrator, s as surfacesFor, t as trialShapesFor, v as validateCheckout, k as validateTrial, j as validateUpsell } from './capabilities-CsnkVwna.cjs';
|
|
4
5
|
import 'react';
|
|
5
6
|
|
|
6
|
-
/**
|
|
7
|
-
* Pure, React-free page scan: find which product SLOTS a funnel's pages reference — the first
|
|
8
|
-
* string-literal arg of `useProduct(...)` and the `product` prop of `<Checkout>` / `<Upsell>`.
|
|
9
|
-
* Ships via `@appfunnel-dev/sdk/manifest` so the BUILD, the EDITOR, and the AI all run the SAME
|
|
10
|
-
* check. The result feeds `compileManifest({ productRefs })`, which flags references to slots the
|
|
11
|
-
* funnel doesn't declare (unknown) or hasn't assigned a catalog product to (unassigned).
|
|
12
|
-
*
|
|
13
|
-
* Non-literal args (`useProduct(selectedId)`, `product={expr}`) and the `useProducts()` wildcard are
|
|
14
|
-
* DYNAMIC — they can't be statically enumerated, so they're reported via `dynamic` and never turned
|
|
15
|
-
* into a hard error (validation relaxes when a funnel is dynamic). Mirrors the mask-then-read
|
|
16
|
-
* discipline the funnel.ts code-mods use, so a `useProduct('x')` inside a comment or string literal
|
|
17
|
-
* can't false-positive.
|
|
18
|
-
*/
|
|
19
|
-
interface ProductRefScan {
|
|
20
|
-
/** Concrete slot names referenced by LITERAL args, deduped, in first-seen order. */
|
|
21
|
-
slots: string[];
|
|
22
|
-
/** True if any ref is a non-literal arg or a `useProducts()` wildcard (not statically enumerable). */
|
|
23
|
-
dynamic: boolean;
|
|
24
|
-
}
|
|
25
|
-
declare function scanProductRefs(files: Record<string, string>): ProductRefScan;
|
|
26
|
-
|
|
27
7
|
/**
|
|
28
8
|
* Source generators for the funnel build "machinery" authors no longer write. `funnel.ts` (the
|
|
29
|
-
* spine: id, responses,
|
|
9
|
+
* spine: id, responses, offerings, checkout, and the page list + declarative routing) plus the
|
|
30
10
|
* `pages/` folder are the ONLY authored source. The build (renderer/builder) and the CLI dev server
|
|
31
11
|
* call these to synthesize:
|
|
32
12
|
* - `mount.tsx` — code-split page loaders + `createFunnelTree`
|
|
@@ -36,6 +16,7 @@ declare function scanProductRefs(files: Record<string, string>): ProductRefScan;
|
|
|
36
16
|
* All string templates, zero runtime deps — this module lives in the pure `@appfunnel-dev/sdk/
|
|
37
17
|
* manifest` entry so tooling imports it without the funnel runtime.
|
|
38
18
|
*/
|
|
19
|
+
|
|
39
20
|
interface ScaffoldOptions {
|
|
40
21
|
/** Page component keys = `pages/<key>.tsx` filenames (base flow pages AND `@variant` pages). */
|
|
41
22
|
pageKeys: string[];
|
|
@@ -49,15 +30,17 @@ interface ScaffoldOptions {
|
|
|
49
30
|
checkout?: 'stripe' | 'paddle' | null;
|
|
50
31
|
/** Locales with a `messages/<locale>.json` catalog to bake into the mount (so `t()` resolves at render). */
|
|
51
32
|
messageLocales?: string[];
|
|
52
|
-
/** Slot names the pages reference (from `
|
|
53
|
-
|
|
33
|
+
/** Slot names the pages reference (from `scanOfferingRefs`), baked into the manifest for validation. */
|
|
34
|
+
offeringRefs?: string[];
|
|
35
|
+
/** Checkout-surface usage the pages express (from `scanOfferingRefs(...).checkout`), baked into the manifest for the publish capability gate. */
|
|
36
|
+
checkoutRefs?: CheckoutUsageScan;
|
|
54
37
|
}
|
|
55
38
|
/** `mount.tsx` — the code-split loaders + tree, derived from `config.pages` and the `pages/` files. */
|
|
56
39
|
declare function generateMount(opts: ScaffoldOptions): string;
|
|
57
40
|
/** `entry.client.tsx` — hydrate the SSR'd markup from the injected `#__af_data`. */
|
|
58
41
|
declare function generateEntryClient(opts: Pick<ScaffoldOptions, 'importPrefix' | 'hasStyles'>): string;
|
|
59
42
|
/** `entry.server.tsx` — `ssr(opts)` HTML + the compiled `manifest` (read by the build). */
|
|
60
|
-
declare function generateEntryServer(opts: Pick<ScaffoldOptions, 'importPrefix' | '
|
|
43
|
+
declare function generateEntryServer(opts: Pick<ScaffoldOptions, 'importPrefix' | 'offeringRefs' | 'checkoutRefs'>): string;
|
|
61
44
|
/** Client-only dev entry (createRoot, no SSR) — for the CLI `dev` server. */
|
|
62
45
|
declare function generateDevEntry(opts: Pick<ScaffoldOptions, 'importPrefix' | 'hasStyles'> & {
|
|
63
46
|
data: unknown;
|
|
@@ -206,4 +189,4 @@ interface CheckoutCompleteRequest {
|
|
|
206
189
|
}
|
|
207
190
|
type CheckoutCompleteResponse = StepSettled | StepPending | StepFailed;
|
|
208
191
|
|
|
209
|
-
export { type CheckoutCompleteRequest, type CheckoutCompleteResponse, CheckoutError, CheckoutIntent, type CheckoutSessionRequest, type CheckoutSessionResponse, type CheckoutSettlement, CheckoutSurface,
|
|
192
|
+
export { type CheckoutCompleteRequest, type CheckoutCompleteResponse, CheckoutError, CheckoutIntent, type CheckoutSessionRequest, type CheckoutSessionResponse, type CheckoutSettlement, CheckoutSurface, CheckoutUsageScan, type ScaffoldOptions, type StepClientConfirm, type StepEmbedded, type StepFailed, type StepPending, type StepProviderCheckout, type StepRedirect, type StepSettled, UpsellKind, generateDevEntry, generateEntryClient, generateEntryServer, generateMount };
|
package/dist/manifest-entry.d.ts
CHANGED
|
@@ -1,32 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { af as CheckoutUsageScan } from './manifest-B3Tdab0M.js';
|
|
2
|
+
export { h as CompileInput, i as Condition, j as ConditionOp, E as EdgeCondition, l as ExperimentArm, n as FlowPage, c as FunnelDefinition, o as FunnelLocales, p as FunnelManifest, ag as FunnelPage, b as FunnelSnapshot, G as Gate, q as Interval, M as ManifestEdge, r as ManifestPage, s as ManifestValidation, t as Money, O as Offering, e as OfferingInput, ah as OfferingRefScan, ai as OfferingSlot, P as PageMeta, v as PageType, w as Predicate, x as ResolvedOffering, y as Route, R as RuntimeExperiment, H as assignVariant, J as bucketingSeed, N as buildCatalog, Q as compileManifest, T as currencyExponent, W as defineFunnel, Y as entryGuard, Z as evaluateCondition, a1 as formatMoney, a2 as formatOffering, aj as funnelCatalogKeys, a4 as isRtl, a5 as isVariantKey, ak as normalizeOfferings, a8 as pageMeta, a9 as parseSlotKey, ac as resolveLocale, ad as resolveOffering, al as scanOfferingRefs, am as weightsOf } from './manifest-B3Tdab0M.js';
|
|
3
|
+
import { C as CheckoutError, b as CheckoutIntent, U as UpsellKind, d as CheckoutSurface } from './capabilities-CsnkVwna.js';
|
|
4
|
+
export { a as CheckoutErrorCategory, c as CheckoutProvider, I as INLINE_SURFACES, O as OffSessionReliability, P as PROVIDER_PROFILES, e as ProviderProfile, S as SurfaceCapability, T as TrialShape, V as ValidationResult, f as checkoutError, i as isInlineSurface, g as isMerchantOfRecord, h as isOrchestrator, s as surfacesFor, t as trialShapesFor, v as validateCheckout, k as validateTrial, j as validateUpsell } from './capabilities-CsnkVwna.js';
|
|
4
5
|
import 'react';
|
|
5
6
|
|
|
6
|
-
/**
|
|
7
|
-
* Pure, React-free page scan: find which product SLOTS a funnel's pages reference — the first
|
|
8
|
-
* string-literal arg of `useProduct(...)` and the `product` prop of `<Checkout>` / `<Upsell>`.
|
|
9
|
-
* Ships via `@appfunnel-dev/sdk/manifest` so the BUILD, the EDITOR, and the AI all run the SAME
|
|
10
|
-
* check. The result feeds `compileManifest({ productRefs })`, which flags references to slots the
|
|
11
|
-
* funnel doesn't declare (unknown) or hasn't assigned a catalog product to (unassigned).
|
|
12
|
-
*
|
|
13
|
-
* Non-literal args (`useProduct(selectedId)`, `product={expr}`) and the `useProducts()` wildcard are
|
|
14
|
-
* DYNAMIC — they can't be statically enumerated, so they're reported via `dynamic` and never turned
|
|
15
|
-
* into a hard error (validation relaxes when a funnel is dynamic). Mirrors the mask-then-read
|
|
16
|
-
* discipline the funnel.ts code-mods use, so a `useProduct('x')` inside a comment or string literal
|
|
17
|
-
* can't false-positive.
|
|
18
|
-
*/
|
|
19
|
-
interface ProductRefScan {
|
|
20
|
-
/** Concrete slot names referenced by LITERAL args, deduped, in first-seen order. */
|
|
21
|
-
slots: string[];
|
|
22
|
-
/** True if any ref is a non-literal arg or a `useProducts()` wildcard (not statically enumerable). */
|
|
23
|
-
dynamic: boolean;
|
|
24
|
-
}
|
|
25
|
-
declare function scanProductRefs(files: Record<string, string>): ProductRefScan;
|
|
26
|
-
|
|
27
7
|
/**
|
|
28
8
|
* Source generators for the funnel build "machinery" authors no longer write. `funnel.ts` (the
|
|
29
|
-
* spine: id, responses,
|
|
9
|
+
* spine: id, responses, offerings, checkout, and the page list + declarative routing) plus the
|
|
30
10
|
* `pages/` folder are the ONLY authored source. The build (renderer/builder) and the CLI dev server
|
|
31
11
|
* call these to synthesize:
|
|
32
12
|
* - `mount.tsx` — code-split page loaders + `createFunnelTree`
|
|
@@ -36,6 +16,7 @@ declare function scanProductRefs(files: Record<string, string>): ProductRefScan;
|
|
|
36
16
|
* All string templates, zero runtime deps — this module lives in the pure `@appfunnel-dev/sdk/
|
|
37
17
|
* manifest` entry so tooling imports it without the funnel runtime.
|
|
38
18
|
*/
|
|
19
|
+
|
|
39
20
|
interface ScaffoldOptions {
|
|
40
21
|
/** Page component keys = `pages/<key>.tsx` filenames (base flow pages AND `@variant` pages). */
|
|
41
22
|
pageKeys: string[];
|
|
@@ -49,15 +30,17 @@ interface ScaffoldOptions {
|
|
|
49
30
|
checkout?: 'stripe' | 'paddle' | null;
|
|
50
31
|
/** Locales with a `messages/<locale>.json` catalog to bake into the mount (so `t()` resolves at render). */
|
|
51
32
|
messageLocales?: string[];
|
|
52
|
-
/** Slot names the pages reference (from `
|
|
53
|
-
|
|
33
|
+
/** Slot names the pages reference (from `scanOfferingRefs`), baked into the manifest for validation. */
|
|
34
|
+
offeringRefs?: string[];
|
|
35
|
+
/** Checkout-surface usage the pages express (from `scanOfferingRefs(...).checkout`), baked into the manifest for the publish capability gate. */
|
|
36
|
+
checkoutRefs?: CheckoutUsageScan;
|
|
54
37
|
}
|
|
55
38
|
/** `mount.tsx` — the code-split loaders + tree, derived from `config.pages` and the `pages/` files. */
|
|
56
39
|
declare function generateMount(opts: ScaffoldOptions): string;
|
|
57
40
|
/** `entry.client.tsx` — hydrate the SSR'd markup from the injected `#__af_data`. */
|
|
58
41
|
declare function generateEntryClient(opts: Pick<ScaffoldOptions, 'importPrefix' | 'hasStyles'>): string;
|
|
59
42
|
/** `entry.server.tsx` — `ssr(opts)` HTML + the compiled `manifest` (read by the build). */
|
|
60
|
-
declare function generateEntryServer(opts: Pick<ScaffoldOptions, 'importPrefix' | '
|
|
43
|
+
declare function generateEntryServer(opts: Pick<ScaffoldOptions, 'importPrefix' | 'offeringRefs' | 'checkoutRefs'>): string;
|
|
61
44
|
/** Client-only dev entry (createRoot, no SSR) — for the CLI `dev` server. */
|
|
62
45
|
declare function generateDevEntry(opts: Pick<ScaffoldOptions, 'importPrefix' | 'hasStyles'> & {
|
|
63
46
|
data: unknown;
|
|
@@ -206,4 +189,4 @@ interface CheckoutCompleteRequest {
|
|
|
206
189
|
}
|
|
207
190
|
type CheckoutCompleteResponse = StepSettled | StepPending | StepFailed;
|
|
208
191
|
|
|
209
|
-
export { type CheckoutCompleteRequest, type CheckoutCompleteResponse, CheckoutError, CheckoutIntent, type CheckoutSessionRequest, type CheckoutSessionResponse, type CheckoutSettlement, CheckoutSurface,
|
|
192
|
+
export { type CheckoutCompleteRequest, type CheckoutCompleteResponse, CheckoutError, CheckoutIntent, type CheckoutSessionRequest, type CheckoutSessionResponse, type CheckoutSettlement, CheckoutSurface, CheckoutUsageScan, type ScaffoldOptions, type StepClientConfirm, type StepEmbedded, type StepFailed, type StepPending, type StepProviderCheckout, type StepRedirect, type StepSettled, UpsellKind, generateDevEntry, generateEntryClient, generateEntryServer, generateMount };
|