@appfunnel-dev/sdk 2.0.0-canary.4 → 2.0.0-canary.7
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/{checkout-Dz8cGkB_.d.cts → checkout-CMEdxpgo.d.cts} +13 -13
- package/dist/{checkout-7Dy6IedP.d.ts → checkout-D1NUPv4p.d.ts} +13 -13
- package/dist/{chunk-AKO6XKXP.js → chunk-7YQLPPPG.js} +66 -91
- package/dist/chunk-7YQLPPPG.js.map +1 -0
- package/dist/{chunk-JSRKA375.cjs → chunk-BPOAWI4G.cjs} +68 -94
- package/dist/chunk-BPOAWI4G.cjs.map +1 -0
- package/dist/{chunk-M6U3FNRW.js → chunk-CFFMZYPE.js} +3 -3
- package/dist/{chunk-M6U3FNRW.js.map → chunk-CFFMZYPE.js.map} +1 -1
- package/dist/chunk-EMMSS5I5.cjs +37 -0
- package/dist/chunk-EMMSS5I5.cjs.map +1 -0
- package/dist/chunk-G3PMV62Z.js +33 -0
- package/dist/chunk-G3PMV62Z.js.map +1 -0
- package/dist/{chunk-LJYLGLFS.cjs → chunk-QMAZGLGV.cjs} +2 -35
- package/dist/chunk-QMAZGLGV.cjs.map +1 -0
- package/dist/{chunk-YY375F2B.js → chunk-TNLRQPVY.js} +3 -33
- package/dist/chunk-TNLRQPVY.js.map +1 -0
- package/dist/{chunk-CY4VBSMX.cjs → chunk-VAOR77NW.cjs} +7 -7
- package/dist/{chunk-CY4VBSMX.cjs.map → chunk-VAOR77NW.cjs.map} +1 -1
- package/dist/chunk-WYUDL4FI.cjs +8 -0
- package/dist/chunk-WYUDL4FI.cjs.map +1 -0
- package/dist/chunk-ZZJG4EYL.js +6 -0
- package/dist/chunk-ZZJG4EYL.js.map +1 -0
- package/dist/driver-paddle.cjs +23 -22
- package/dist/driver-paddle.cjs.map +1 -1
- package/dist/driver-paddle.d.cts +1 -1
- package/dist/driver-paddle.d.ts +1 -1
- package/dist/driver-paddle.js +3 -2
- package/dist/driver-paddle.js.map +1 -1
- package/dist/driver-stripe.cjs +277 -224
- package/dist/driver-stripe.cjs.map +1 -1
- package/dist/driver-stripe.d.cts +18 -2
- package/dist/driver-stripe.d.ts +18 -2
- package/dist/driver-stripe.js +244 -192
- package/dist/driver-stripe.js.map +1 -1
- package/dist/index.cjs +750 -150
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +151 -90
- package/dist/index.d.ts +151 -90
- package/dist/index.js +702 -98
- package/dist/index.js.map +1 -1
- package/dist/{manifest-Cr2y1op6.d.cts → manifest-CMe8yVkr.d.cts} +131 -88
- package/dist/{manifest-Cr2y1op6.d.ts → manifest-CMe8yVkr.d.ts} +131 -88
- package/dist/manifest-entry.cjs +62 -47
- package/dist/manifest-entry.cjs.map +1 -1
- package/dist/manifest-entry.d.cts +15 -15
- package/dist/manifest-entry.d.ts +15 -15
- package/dist/manifest-entry.js +25 -14
- package/dist/manifest-entry.js.map +1 -1
- package/dist/protocol.cjs +13 -0
- package/dist/protocol.cjs.map +1 -0
- package/dist/protocol.d.cts +182 -0
- package/dist/protocol.d.ts +182 -0
- package/dist/protocol.js +4 -0
- package/dist/protocol.js.map +1 -0
- package/package.json +14 -2
- package/dist/chunk-AKO6XKXP.js.map +0 -1
- package/dist/chunk-JSRKA375.cjs.map +0 -1
- package/dist/chunk-LJYLGLFS.cjs.map +0 -1
- package/dist/chunk-YY375F2B.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, ComponentType, ButtonHTMLAttributes } from 'react';
|
|
3
|
-
import { V as VariableValue, a as VariableConfig, A as Acquisition,
|
|
4
|
-
export { B as BrowserContext,
|
|
5
|
-
import {
|
|
6
|
-
|
|
3
|
+
import { V as VariableValue, a as VariableConfig, A as Acquisition, O as Offering, D as Direction, F as FunnelContext, R as RuntimeExperiment, b as FunnelSnapshot, c as FunnelDefinition, d as buildContext, e as OfferingInput, P as PageMeta, f as PageContext } from './manifest-CMe8yVkr.cjs';
|
|
4
|
+
export { B as BrowserContext, g as BuildContextOptions, C as ClickIdContext, h as CompileInput, i as Condition, j as ConditionOp, k as DeviceContext, E as EdgeCondition, l as ExperimentArm, m as ExperimentResolution, n as FlowPage, o as FunnelLocales, p as FunnelManifest, G as Gate, I as IdentityContext, q as Interval, L as LocaleContext, M as ManifestEdge, r as ManifestPage, s as ManifestValidation, t as Money, u as OsContext, v as PageType, w as Predicate, x as ResolvedOffering, y as Route, S as SessionContext, z as SystemContext, U as UtmContext, H as assignVariant, J as bucketingSeed, K as buildAcquisition, N as buildCatalog, Q as compileManifest, T as currencyExponent, W as defineFunnel, X as definePage, Y as entryGuard, Z as evaluateCondition, _ as evaluateGate, $ as expectedPathLength, a0 as fnv1a, a1 as formatMoney, a2 as formatOffering, a3 as hashToUnit, a4 as isRtl, a5 as isVariantKey, a6 as nextPage, a7 as outgoingKeys, a8 as pageMeta, a9 as parseSlotKey, aa as pickByWeight, ab as resolveExperiments, ac as resolveLocale, ad as resolveOffering, ae as resolveRoute } from './manifest-CMe8yVkr.cjs';
|
|
5
|
+
import { NavSnapshot } from './protocol.cjs';
|
|
6
|
+
import { a as CheckoutDriver, C as CheckoutDriverContext } from './checkout-CMEdxpgo.cjs';
|
|
7
|
+
export { b as Checkout, c as CheckoutCallbacks, d as CheckoutHandle, e as CheckoutProps, f as CheckoutRequest, g as CheckoutResult, h as CheckoutResume, i as CheckoutStatus, F as FailureModalProps, j as FailureRoute, M as MockDriverOptions, O as OnFailedMap, U as Upsell, k as UpsellProps, l as UseCheckoutOptions, m as createMockDriver, n as driverWithEmail, u as useCheckout } from './checkout-CMEdxpgo.cjs';
|
|
7
8
|
import { ToasterProps } from 'sonner';
|
|
8
9
|
export { ToasterProps, toast } from 'sonner';
|
|
9
10
|
export { C as CheckoutError, a as CheckoutErrorCategory, b as CheckoutIntent, c as CheckoutProvider, d as CheckoutSurface, I as INLINE_SURFACES, O as OffSessionReliability, P as PROVIDER_PROFILES, e as ProviderProfile, S as SurfaceCapability, U as UpsellKind, V as ValidationResult, f as checkoutError, i as isInlineSurface, g as isMerchantOfRecord, h as isOrchestrator, s as surfacesFor, v as validateCheckout, j as validateUpsell } from './capabilities-7_hy5f5G.cjs';
|
|
@@ -187,30 +188,123 @@ declare function useTracker(): {
|
|
|
187
188
|
};
|
|
188
189
|
|
|
189
190
|
/**
|
|
190
|
-
*
|
|
191
|
+
* The **`window.appfunnel` event bus** — the client-side integration surface
|
|
192
|
+
* (port of v0 `admin/lib/funnel/utils/appfunnelRuntime.ts`).
|
|
193
|
+
*
|
|
194
|
+
* Every taxonomy event the runtime emits is mirrored here, so on-page pixels and
|
|
195
|
+
* custom scripts integrate by **subscribing** — `window.appfunnel.on('purchase.complete', …)`
|
|
196
|
+
* — instead of the funnel hand-injecting pixel config per page. The pre-built pixel
|
|
197
|
+
* loaders (Meta/TikTok/GTM/Clarity) are just subscribers; CAPI stays the server-side
|
|
198
|
+
* default (this is the *client* sink of the same events). See doc 08 §3.
|
|
199
|
+
*
|
|
200
|
+
* Two deliberate properties vs. v0:
|
|
201
|
+
* - **Replay history** (`events`): async pixels load *after* `funnel.start`/`page.view`
|
|
202
|
+
* fire, so a late subscriber would miss them. The bus keeps a bounded history a
|
|
203
|
+
* subscriber can replay (the GTM `dataLayer` trick) — no lost events.
|
|
204
|
+
* - **Subscribe + read + drive.** The window surface exposes `on`/`off`/`events` + read
|
|
205
|
+
* getters, and — resolving the deferred bus-control-scope decision (doc 08 §3/§4) —
|
|
206
|
+
* **flow control**: `goTo`/`goNext`/`goPrevious` + a `navigation()` snapshot, so a host
|
|
207
|
+
* page (the live editor, or an author's own external nav UI) can drive the funnel. It
|
|
208
|
+
* still has **no `emit`** (third-party code can't forge taxonomy events) and no
|
|
209
|
+
* `setVariable` (state stays funnel-owned). Flow control is a no-op (warns once) until a
|
|
210
|
+
* `<FunnelView>` mounts and registers itself via {@link FunnelBus.registerNavigation}.
|
|
211
|
+
*/
|
|
212
|
+
|
|
213
|
+
/** Read accessors the bus exposes — wired to the funnel's store + context. */
|
|
214
|
+
interface BusAccessors {
|
|
215
|
+
getVariable: (key: string) => unknown;
|
|
216
|
+
getVariables: () => Record<string, unknown>;
|
|
217
|
+
getCurrentPageId: () => string | null;
|
|
218
|
+
getCustomerId: () => string | null;
|
|
219
|
+
getVisitorId: () => string | null;
|
|
220
|
+
}
|
|
221
|
+
interface BusEvent {
|
|
222
|
+
event: string;
|
|
223
|
+
data: unknown;
|
|
224
|
+
/** Epoch ms the event was emitted (for ordering / replay). */
|
|
225
|
+
ts: number;
|
|
226
|
+
}
|
|
227
|
+
type Listener = (data: unknown) => void;
|
|
228
|
+
/** The flow-control seam a mounted `<FunnelView>` registers into the bus (SDK-internal). */
|
|
229
|
+
interface NavigationControl {
|
|
230
|
+
/** Jump to a page key. Returns `false` if the key isn't a real page (no navigation happened). */
|
|
231
|
+
goTo(pageKey: string): boolean;
|
|
232
|
+
goNext(): void;
|
|
233
|
+
goPrevious(): void;
|
|
234
|
+
snapshot(): NavSnapshot | null;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* The public `window.appfunnel` surface — subscribe + read + drive the flow. It never
|
|
238
|
+
* exposes `emit` (no forged events) or `setVariable` (state stays funnel-owned).
|
|
239
|
+
*/
|
|
240
|
+
interface AppfunnelBusApi extends BusAccessors {
|
|
241
|
+
/** Subscribe to an event (or `'*'` for all). Returns an unsubscribe fn. */
|
|
242
|
+
on(event: string, cb: Listener): () => void;
|
|
243
|
+
off(event: string, cb: Listener): void;
|
|
244
|
+
/** Bounded replay history — read past events, then `on()` for future ones. */
|
|
245
|
+
readonly events: BusEvent[];
|
|
246
|
+
/** Jump the flow to a page key. Returns `false` for an unknown key (or before the flow mounts). */
|
|
247
|
+
goTo(pageKey: string): boolean;
|
|
248
|
+
/** Advance via the current page's `next` predicate (else the linear next). */
|
|
249
|
+
goNext(): void;
|
|
250
|
+
/** Step back to the previous page in flow history. */
|
|
251
|
+
goPrevious(): void;
|
|
252
|
+
/** The current flow snapshot, or `null` before a `<FunnelView>` mounts. */
|
|
253
|
+
navigation(): NavSnapshot | null;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* The internal bus: the public {@link AppfunnelBusApi} plus `emit` (SDK-only) and
|
|
257
|
+
* `now` injection. The SDK holds this; only {@link AppfunnelBusApi} reaches `window`.
|
|
258
|
+
*/
|
|
259
|
+
interface FunnelBus extends AppfunnelBusApi {
|
|
260
|
+
emit(event: string, data?: unknown): void;
|
|
261
|
+
/** SDK-only: a mounted `<FunnelView>` registers its flow control; returns an unregister fn. */
|
|
262
|
+
registerNavigation(nav: NavigationControl): () => void;
|
|
263
|
+
}
|
|
264
|
+
/** Create a bus over the given read accessors. `now` is injectable for tests. */
|
|
265
|
+
declare function createBus(accessors: BusAccessors, now?: () => number): FunnelBus;
|
|
266
|
+
/**
|
|
267
|
+
* Wrap a {@link Tracker} so every emitted taxonomy event is mirrored to the bus
|
|
268
|
+
* (the client sink). `identify()` also surfaces a `user.registered` to the bus, so
|
|
269
|
+
* pixels see registration. The server sink (the inner tracker → CAPI) is untouched.
|
|
270
|
+
*/
|
|
271
|
+
declare function withBus(tracker: Tracker, bus: FunnelBus): Tracker;
|
|
272
|
+
declare global {
|
|
273
|
+
interface Window {
|
|
274
|
+
appfunnel?: AppfunnelBusApi;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Attach the bus's public surface to `window.appfunnel` (client-side only).
|
|
279
|
+
* Returns a detach fn for unmount. No-op under SSR.
|
|
280
|
+
*/
|
|
281
|
+
declare function attachBus(bus: FunnelBus): () => void;
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* v2 `offerings` — the **read-only** offering catalog.
|
|
191
285
|
*
|
|
192
|
-
* **
|
|
286
|
+
* **Appfunnel does not manage currency.** Multi-currency is entirely the payment
|
|
193
287
|
* provider's job: the provider (or its preview API) resolves the visitor's price,
|
|
194
|
-
* and we receive a single resolved `{ amount, currency }` per
|
|
288
|
+
* and we receive a single resolved `{ amount, currency }` per offering. No FX, no
|
|
195
289
|
* currency selection, no conversion on our side. (FX appears only for frozen-USD
|
|
196
290
|
* *reporting*, never display — phase-3 §3.6b.) A provider that doesn't localize
|
|
197
291
|
* simply gives one currency.
|
|
198
292
|
*
|
|
199
|
-
* Our only job is **display**: pick the
|
|
293
|
+
* Our only job is **display**: pick the offering by logical id and **format** its
|
|
200
294
|
* amount. Formatting happens at read time in the funnel's **active locale** (so
|
|
201
295
|
* switching language reformats `kr 79,00` ⇄ `$9.99`), while the **currency** is
|
|
202
296
|
* whatever the provider resolved. Currency selection is the platform's; the
|
|
203
|
-
* authoring funnel only ever names
|
|
297
|
+
* authoring funnel only ever names an offering id.
|
|
204
298
|
*
|
|
205
299
|
* The math itself (resolve/format/exponents) is pure and lives in {@link ./money}
|
|
206
300
|
* so the server/tooling entry can use it without React — this module re-exports
|
|
207
301
|
* it and adds the React wiring (provider + hooks).
|
|
208
302
|
*/
|
|
209
303
|
|
|
210
|
-
/** `
|
|
211
|
-
declare function
|
|
212
|
-
/** `
|
|
213
|
-
declare function
|
|
304
|
+
/** `useOffering('monthly')` — one offering, formatted in the active locale. */
|
|
305
|
+
declare function useOffering(id: string | undefined): Offering | undefined;
|
|
306
|
+
/** `useOfferings()` — every offering, formatted in the active locale, in order. */
|
|
307
|
+
declare function useOfferings(): Offering[];
|
|
214
308
|
|
|
215
309
|
/**
|
|
216
310
|
* v2 localization — translated **text** (prices already localize via `Intl` in
|
|
@@ -340,12 +434,21 @@ interface FunnelProviderProps {
|
|
|
340
434
|
config?: FunnelDefinition;
|
|
341
435
|
/** Server / session-restored values overriding declared defaults. */
|
|
342
436
|
sessionValues?: Record<string, VariableValue>;
|
|
437
|
+
/**
|
|
438
|
+
* FLASH-FREE HYDRATION (SSR-isolation Option B): when true, the store is seeded with
|
|
439
|
+
* DEFAULTS only for the initial (hydration) render — matching the build-time-prerendered
|
|
440
|
+
* DEFAULT-state markup — and `sessionValues` are applied as a POST-hydration state update in
|
|
441
|
+
* a mount effect (`store.setMany`), so a returning visitor's saved answers pop into
|
|
442
|
+
* already-visible controls without an empty-shell flash or a hydration mismatch. Off (the
|
|
443
|
+
* default) preserves the original behavior: `sessionValues` seed the store at construction
|
|
444
|
+
* (used by SSR itself and by non-prerendered mounts). The client entry sets this to true. */
|
|
445
|
+
deferSessionValues?: boolean;
|
|
343
446
|
/** The platform tracker; defaults to a silent console tracker (tests/dev). */
|
|
344
447
|
tracker?: Tracker;
|
|
345
448
|
/** Computed-context seed (funnel id, test/live mode, server-hydrated utm/session). */
|
|
346
449
|
context?: Parameters<typeof buildContext>[0];
|
|
347
|
-
/**
|
|
348
|
-
|
|
450
|
+
/** Offerings with their provider-resolved price (`{ amount, currency }`). */
|
|
451
|
+
offerings?: OfferingInput[];
|
|
349
452
|
/** Live page-level experiment records, platform/DB-sourced (not authored in funnel code). */
|
|
350
453
|
experiments?: RuntimeExperiment[];
|
|
351
454
|
/** The platform checkout driver; defaults to a mock that resolves successfully. */
|
|
@@ -364,7 +467,7 @@ interface FunnelProviderProps {
|
|
|
364
467
|
* Mounts a funnel: builds the writable {@link VariableStore} + the read-only
|
|
365
468
|
* {@link FunnelContext} (once) and provides the runtime to the tree via hooks.
|
|
366
469
|
*/
|
|
367
|
-
declare function FunnelProvider({ config, sessionValues, tracker, context: contextOpts,
|
|
470
|
+
declare function FunnelProvider({ config, sessionValues, deferSessionValues, tracker, context: contextOpts, offerings, experiments, checkout, messages, locale: localeOverride, toaster, store, children, }: FunnelProviderProps): ReactNode;
|
|
368
471
|
/**
|
|
369
472
|
* The imperative handle. Does **not** subscribe — use it in event handlers and
|
|
370
473
|
* effects (`useFunnel().responses.set({...})`). For reactive reads use the hooks.
|
|
@@ -477,9 +580,20 @@ declare function useExperiment(id: string): string | undefined;
|
|
|
477
580
|
*
|
|
478
581
|
* Must live inside `<FunnelProvider>`.
|
|
479
582
|
*/
|
|
480
|
-
declare function FunnelView({ pages, initialKey, layout, fallback, prefetch: prefetchMode, onNavigate, }: {
|
|
583
|
+
declare function FunnelView({ pages, initialKey, trustInitialKey, layout, fallback, prefetch: prefetchMode, onNavigate, }: {
|
|
481
584
|
pages: RuntimePage[];
|
|
482
585
|
initialKey?: string;
|
|
586
|
+
/**
|
|
587
|
+
* FLASH-FREE HYDRATION (SSR-isolation Option B, FIX 1): honor `initialKey` VERBATIM as the entry
|
|
588
|
+
* page, WITHOUT re-evaluating its entry `guard` on the client. The SERVER already resolved the
|
|
589
|
+
* true entry — either by evaluating a declarative guard to pick the prerendered target-vs-bounce,
|
|
590
|
+
* or by running the real guard inside the fallback SSR render — and threaded the resolved key
|
|
591
|
+
* here. With `deferSessionValues` on, the client's initial snapshot is EMPTY (saved answers arrive
|
|
592
|
+
* post-hydration), so re-running the guard here would wrongly bounce a qualified visitor and
|
|
593
|
+
* mismatch the server markup. Set by the client entry (via createFunnelTree) alongside
|
|
594
|
+
* `deferSessionValues`; the guard still protects in-funnel navigation and non-deferred mounts.
|
|
595
|
+
*/
|
|
596
|
+
trustInitialKey?: boolean;
|
|
483
597
|
layout?: ComponentType<{
|
|
484
598
|
children: ReactNode;
|
|
485
599
|
}>;
|
|
@@ -524,8 +638,8 @@ declare function useAssets(): Record<string, string>;
|
|
|
524
638
|
declare function useAsset(name: string): string | undefined;
|
|
525
639
|
/** What the renderer injects when mounting a funnel build (SSR and hydration). */
|
|
526
640
|
interface MountOpts {
|
|
527
|
-
/** Platform-resolved
|
|
528
|
-
|
|
641
|
+
/** Platform-resolved offering prices (one currency per visitor). */
|
|
642
|
+
offerings?: OfferingInput[];
|
|
529
643
|
/** Explicit locale override (URL/param/geo); wins over the detected device locale. */
|
|
530
644
|
locale?: string;
|
|
531
645
|
mode?: 'test' | 'live';
|
|
@@ -567,6 +681,23 @@ interface MountOpts {
|
|
|
567
681
|
/** The server-resolved session id backing `sessionValues` — seeds the tracker (fallback)
|
|
568
682
|
* and `context.session.id`. */
|
|
569
683
|
sessionId?: string | null;
|
|
684
|
+
/** Mount the cross-origin {@link EmbedBridge} — the Funnel Embed API (flow snapshot + goTo/goNext/
|
|
685
|
+
* goPrevious + screenshot, over the versioned wire protocol). Set ONLY by preview surfaces (the live
|
|
686
|
+
* editor + the sealed `/preview/<buildId>` build); a live prod funnel leaves it off so it can't be
|
|
687
|
+
* driven / can't leak its flow state to an embedder. */
|
|
688
|
+
embed?: boolean;
|
|
689
|
+
/** FLASH-FREE HYDRATION (SSR-isolation Option B): set by the CLIENT entry only. The initial
|
|
690
|
+
* render is seeded with DEFAULTS (matching the build-time default-state prerender it hydrates
|
|
691
|
+
* against), then `sessionValues` are applied post-hydration via `store.setMany` — a returning
|
|
692
|
+
* visitor's saved answers pop into already-visible controls, no empty flash, no mismatch. Unset
|
|
693
|
+
* on SSR (the server render must bake sessionValues into the markup, the original behavior). */
|
|
694
|
+
deferSessionValues?: boolean;
|
|
695
|
+
/** SSR-isolation Option B, FIX 1: render `initialKey` VERBATIM without evaluating its entry guard.
|
|
696
|
+
* Set by the build-time PRERENDER stage so a guarded page (paywall/upsell) prerenders its OWN
|
|
697
|
+
* default-state markup (the renderer decides target-vs-bounce at serve time by evaluating the
|
|
698
|
+
* guard against the visitor's session). Defaults to `deferSessionValues` (the client trusts the
|
|
699
|
+
* server-resolved key); the prerender sets it true explicitly while leaving sessionValues baked. */
|
|
700
|
+
trustInitialKey?: boolean;
|
|
570
701
|
}
|
|
571
702
|
/**
|
|
572
703
|
* The shape a funnel build's `mount.tsx` module must export — the named,
|
|
@@ -758,76 +889,6 @@ type ModalProps = OverlayCommon;
|
|
|
758
889
|
/** A centered dialog. Auto-binds to its `defineModal` — `<Modal>…`. */
|
|
759
890
|
declare function Modal(props: ModalProps): ReactNode;
|
|
760
891
|
|
|
761
|
-
/**
|
|
762
|
-
* The **`window.appfunnel` event bus** — the client-side integration surface
|
|
763
|
-
* (port of v0 `admin/lib/funnel/utils/appfunnelRuntime.ts`).
|
|
764
|
-
*
|
|
765
|
-
* Every taxonomy event the runtime emits is mirrored here, so on-page pixels and
|
|
766
|
-
* custom scripts integrate by **subscribing** — `window.appfunnel.on('purchase.complete', …)`
|
|
767
|
-
* — instead of the funnel hand-injecting pixel config per page. The pre-built pixel
|
|
768
|
-
* loaders (Meta/TikTok/GTM/Clarity) are just subscribers; CAPI stays the server-side
|
|
769
|
-
* default (this is the *client* sink of the same events). See doc 08 §3.
|
|
770
|
-
*
|
|
771
|
-
* Two deliberate properties vs. v0:
|
|
772
|
-
* - **Replay history** (`events`): async pixels load *after* `funnel.start`/`page.view`
|
|
773
|
-
* fire, so a late subscriber would miss them. The bus keeps a bounded history a
|
|
774
|
-
* subscriber can replay (the GTM `dataLayer` trick) — no lost events.
|
|
775
|
-
* - **Subscribe + read only.** The window surface exposes `on`/`off`/`events` + read
|
|
776
|
-
* getters; it has **no `emit`** (third-party code can't forge events) and **no
|
|
777
|
-
* mutating actions** (`setVariable`/navigation) — the funnel can't be driven through
|
|
778
|
-
* it. (v0's full-control Custom-JS API is deferred pending the bus-control-scope
|
|
779
|
-
* decision; doc 08 §3 + §4.)
|
|
780
|
-
*/
|
|
781
|
-
|
|
782
|
-
/** Read accessors the bus exposes — wired to the funnel's store + context. */
|
|
783
|
-
interface BusAccessors {
|
|
784
|
-
getVariable: (key: string) => unknown;
|
|
785
|
-
getVariables: () => Record<string, unknown>;
|
|
786
|
-
getCurrentPageId: () => string | null;
|
|
787
|
-
getCustomerId: () => string | null;
|
|
788
|
-
getVisitorId: () => string | null;
|
|
789
|
-
}
|
|
790
|
-
interface BusEvent {
|
|
791
|
-
event: string;
|
|
792
|
-
data: unknown;
|
|
793
|
-
/** Epoch ms the event was emitted (for ordering / replay). */
|
|
794
|
-
ts: number;
|
|
795
|
-
}
|
|
796
|
-
type Listener = (data: unknown) => void;
|
|
797
|
-
/** The public `window.appfunnel` surface — subscribe + read, never emit or mutate. */
|
|
798
|
-
interface AppFunnelBusApi extends BusAccessors {
|
|
799
|
-
/** Subscribe to an event (or `'*'` for all). Returns an unsubscribe fn. */
|
|
800
|
-
on(event: string, cb: Listener): () => void;
|
|
801
|
-
off(event: string, cb: Listener): void;
|
|
802
|
-
/** Bounded replay history — read past events, then `on()` for future ones. */
|
|
803
|
-
readonly events: BusEvent[];
|
|
804
|
-
}
|
|
805
|
-
/**
|
|
806
|
-
* The internal bus: the public {@link AppFunnelBusApi} plus `emit` (SDK-only) and
|
|
807
|
-
* `now` injection. The SDK holds this; only {@link AppFunnelBusApi} reaches `window`.
|
|
808
|
-
*/
|
|
809
|
-
interface FunnelBus extends AppFunnelBusApi {
|
|
810
|
-
emit(event: string, data?: unknown): void;
|
|
811
|
-
}
|
|
812
|
-
/** Create a bus over the given read accessors. `now` is injectable for tests. */
|
|
813
|
-
declare function createBus(accessors: BusAccessors, now?: () => number): FunnelBus;
|
|
814
|
-
/**
|
|
815
|
-
* Wrap a {@link Tracker} so every emitted taxonomy event is mirrored to the bus
|
|
816
|
-
* (the client sink). `identify()` also surfaces a `user.registered` to the bus, so
|
|
817
|
-
* pixels see registration. The server sink (the inner tracker → CAPI) is untouched.
|
|
818
|
-
*/
|
|
819
|
-
declare function withBus(tracker: Tracker, bus: FunnelBus): Tracker;
|
|
820
|
-
declare global {
|
|
821
|
-
interface Window {
|
|
822
|
-
appfunnel?: AppFunnelBusApi;
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
/**
|
|
826
|
-
* Attach the bus's public surface to `window.appfunnel` (client-side only).
|
|
827
|
-
* Returns a detach fn for unmount. No-op under SSR.
|
|
828
|
-
*/
|
|
829
|
-
declare function attachBus(bus: FunnelBus): () => void;
|
|
830
|
-
|
|
831
892
|
/**
|
|
832
893
|
* The **event catalog** — the single source of truth for *which* events exist and
|
|
833
894
|
* how each is routed (analytics vs. integrations vs. runtime-only). Pairs with the
|
|
@@ -1021,4 +1082,4 @@ interface ScriptProps {
|
|
|
1021
1082
|
*/
|
|
1022
1083
|
declare function Script({ src, strategy, id, async, defer, nonce, attributes, onLoad, onError, }: ScriptProps): null;
|
|
1023
1084
|
|
|
1024
|
-
export { Acquisition, type
|
|
1085
|
+
export { Acquisition, type AppfunnelBusApi, AssetsContext, AssetsProvider, Back, type BackProps, type BusAccessors, type BusEvent, type CatalogEvent, CheckoutDriver, CheckoutDriverContext, Choice, type ChoiceOption, type ChoiceProps, type CreateFunnelTreeInput, Direction, EVENT_CATALOG, type EventMeta, type EventSource, type Formatters, type Funnel, type FunnelBus, FunnelContext, FunnelDefinition, type FunnelEventDataMap, FunnelProvider, type FunnelProviderProps, FunnelSnapshot, FunnelToaster, FunnelView, type KnownFunnelEvent, type MessageCatalog, Modal, type ModalHandler, type ModalHocProps, type ModalProps, type ModalState, type MountModule, type MountOpts, Namespace, type NavigationState, Next, type NextProps, Offering, OfferingInput, PageContext, PageMeta, type PageModule, type PlatformTrackingConfig, type PluralCategory, RuntimeExperiment, type RuntimePage, Script, type ScriptProps, Sheet, type SheetProps, type SheetSide, type TFunction, type Tracker, type Translation, VariableStore, attachBus, buildContext, createBus, createConsoleTracker, createFunnelStore, createFunnelTree, createPlatformTracker, defineModal, hideModal, integrationEvents, isIntegrationEvent, isTrackableEvent, newEventId, registerModal, removeModal, showModal, unregisterModal, useActiveLocale, useAsset, useAssets, useClickIds, useContextValue, useData, useDevice, useExperiment, useField, useFunnel, useLocale, useModal, useNavigation, useOffering, useOfferings, usePage, useResponse, useSystem, useTracker, useTranslation, useUserAttribute, useUtm, withBus };
|