@funnelsgrove/runtime 0.1.44 → 0.1.45

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 CHANGED
@@ -2,60 +2,65 @@
2
2
 
3
3
  Shared funnel runtime contracts and helpers.
4
4
 
5
- ## Build And Publish
5
+ Read this file before editing shared funnel mechanics. Deeper runtime behavior is
6
+ documented in [`docs/product-specs/funnel-template-runtime.md`](../../docs/product-specs/funnel-template-runtime.md).
6
7
 
7
- - Build distributable output with `npm run build --workspace @funnelsgrove/runtime`.
8
- - Publish from the repo root with `npm publish --workspace @funnelsgrove/runtime --access public`.
9
- - Local repo installs still resolve this package through npm workspaces when another workspace depends on version `0.1.1`.
10
- - The build normalizes generated relative ESM imports to explicit `.js` files for published package consumers.
8
+ ## Owns funnel mechanics
9
+
10
+ `@funnelsgrove/runtime` owns the reusable mechanics that every generated or published funnel depends on: manifests, routing, env resolution, funnel state, preview/runtime detection, and generic runtime UI. Funnels bring their own copy, visual design, billing catalog, and step JSX.
11
11
 
12
12
  ## Use This Package For
13
13
 
14
14
  - manifest types and validation
15
15
  - route resolution and entry-point handling
16
+ - runtime mode and public env/config resolution
16
17
  - experiment assignment helpers
17
18
  - preview-bridge parsing and preview/runtime detection
18
19
  - published theme contract and CSS variable helpers
19
- - funnel context, base controls, and reusable runtime UI primitives
20
- - subscription handoff and subscription management screens whose copy stays funnel-local
20
+ - funnel context, flow controller, and generic runtime UI primitives
21
+ - funnel-scoped state/storage helpers
21
22
  - browser-safe API client helpers used by funnels
22
- - a shared test-mode developer info box for funnel-local preview tooling
23
-
24
- ## Responsibilities
25
-
26
- - keep funnel mechanics consistent across every funnel
27
- - expose stable contracts for routing, previews, and step identity
28
- - avoid funnel-specific copy, visual design, or billing plan catalogs
29
-
30
- ## What Belongs Here
31
-
32
- - reusable runtime helpers that any funnel can use
33
- - shared browser/event/storage helpers tied to funnel behavior
34
- - funnel-scoped paywall state helpers that keep runtime-owned storage keys under `fg_...`
35
- - hosted-path navigation helpers so static previews keep their `/published/f/...` or `/catalog/...` prefix
36
- - generic context and base component primitives
37
- - safe local-only fallbacks when no real SDK publishable key is configured
38
- - shared preview-checkout publishable key fallback used by paywalls when only the seed placeholder is configured
39
- - default runtime config values for API/bootstrap wiring
40
- - env-backed support email rendering for shared subscription management screens
41
- - full-step subscription management surfaces that avoid exposing an outer page background rim
42
- - subscription handoff link rendering for iOS, Android, and desktop/web fallbacks from runtime env
43
- - subscription handoff browser-only values are resolved after mount so published success routes hydrate without text mismatches
44
- - public subscription summaries with provider plan and period metadata for funnel-local management screens
45
- - a bottom-right `RuntimeDevInfoBox` that funnels can mount in test mode to inspect public runtime config with one canonical env/config name per row, copy the current funnel user id/email, switch to live mode, and clear funnel-scoped paywall state
23
+ - subscription handoff and subscription management screens whose copy stays funnel-local
24
+ - test-mode developer info surfaces for funnel preview tooling
25
+
26
+ ## Do Not Use This Package For
27
+
28
+ - funnel-specific step JSX
29
+ - brand/theme assets
30
+ - billing catalog data
31
+ - analytics transport
32
+ - Stripe checkout UI
33
+ - funnel-specific developer widget copy
34
+ - direct provider SDK calls
35
+
36
+ ## Public Surfaces
37
+
38
+ - `config/*`: manifest, theme, font, env, and builder-preview contracts.
39
+ - `runtime/*`: flow, routing, attribution, feature flags, preview bridge, URL attributes, and manifest validation.
40
+ - `services/*`: API client, runtime mode, public env, project env, logger, and funnel state helpers.
41
+ - `components/*`: generic runtime context, subscription handoff/management, editor panel, dev info, and base controls.
42
+ - `content/*` and `steps/types`: shared step content and taxonomy contracts.
46
43
 
47
44
  ## Storage Conventions
48
45
 
49
46
  - runtime user ids stay funnel-scoped under `funnel:<funnelId>:user-id`
50
47
  - runtime-generated user ids use the `u_` prefix
51
48
  - paywall state is stored through runtime helpers under `fg_state:<funnelId>`
52
- - developer reset controls should clear paywall state through `clearPaywallStateValue`, including any funnel-provided legacy keys
49
+ - developer reset controls should clear paywall state through `clearPaywallStateValue`, including funnel-provided compatibility keys when a live funnel still needs them
53
50
 
54
- ## What Does Not Belong Here
51
+ ## Engineering Rules
55
52
 
56
- - funnel-specific step JSX
57
- - brand/theme assets
58
- - billing catalog data
59
- - analytics SDK transport
60
- - Stripe checkout UI
61
- - funnel-specific developer widget copy, config extras, or legacy storage keys
53
+ - Do not import `@funnelsgrove/payments` or `@funnelsgrove/analytics` here for checkout or transport orchestration.
54
+ - Runtime UI must be generic and copy-injectable.
55
+ - Browser-only values must resolve after mount when SSR hydration can be affected.
56
+ - Keep env mapping centralized in `config/env.config.ts`.
57
+
58
+ ## Build, Test, Publish
59
+
60
+ ```bash
61
+ npm run test:run --workspace @funnelsgrove/runtime
62
+ npm run build --workspace @funnelsgrove/runtime
63
+ npm publish --workspace @funnelsgrove/runtime --access public
64
+ ```
65
+
66
+ The build normalizes generated relative ESM imports to explicit `.js` files for published package consumers.
package/dist/index.js CHANGED
@@ -1,10 +1,13 @@
1
+ // Shared config contracts.
1
2
  export * from './config/builder-preview.protocol.js';
2
3
  export * from './config/env.config.js';
3
4
  export * from './config/funnel.manifest.types.js';
4
5
  export * from './config/funnel.experiments.types.js';
5
6
  export * from './config/funnel-theme.js';
6
7
  export * from './config/font-config.js';
8
+ // Structured content contracts.
7
9
  export * from './content/step-content.js';
10
+ // Runtime mechanics.
8
11
  export * from './runtime/experiment-assignment.js';
9
12
  export * from './runtime/browser-helpers.js';
10
13
  export * from './runtime/funnel-flow.js';
@@ -20,6 +23,7 @@ export * from './runtime/route-resolver.js';
20
23
  export * from './runtime/subscription-handoff.js';
21
24
  export * from './runtime/url-user-attributes.js';
22
25
  export * from './runtime/use-url-user-attributes-sync.js';
26
+ // Browser-safe services.
23
27
  export * from './services/api.service.js';
24
28
  export * from './services/funnel-state.service.js';
25
29
  export * from './services/logger.js';
@@ -28,6 +32,7 @@ export * from './services/project-env.js';
28
32
  export * from './services/public-env.js';
29
33
  export * from './services/runtime-api.config.js';
30
34
  export * from './services/runtime-mode.service.js';
35
+ // SDK and generic runtime UI.
31
36
  export * from './sdk/userAnswers.js';
32
37
  export * from './components/FunnelContext.js';
33
38
  export * from './components/FunnelEditorPanel.js';
@@ -1,5 +1,6 @@
1
1
  import type { PostHog } from 'posthog-js';
2
2
  export declare const POSTHOG_FEATURE_FLAG_READY_TIMEOUT_MS = 2500;
3
+ export declare const POSTHOG_SCOPED_FLAG_RELOAD_RETRY_MS = 300;
3
4
  type BootstrapConfig = {
4
5
  apiKey: string;
5
6
  apiHost: string;
@@ -3,6 +3,7 @@ import { runtimePublicConfig } from '../services/public-env.js';
3
3
  let initialized = false;
4
4
  let readyPromise = null;
5
5
  export const POSTHOG_FEATURE_FLAG_READY_TIMEOUT_MS = 2500;
6
+ export const POSTHOG_SCOPED_FLAG_RELOAD_RETRY_MS = 300;
6
7
  const STORED_PERSON_PROPERTIES_KEY = '$stored_person_properties';
7
8
  const buildFlagScopeProperties = (config) => {
8
9
  var _a, _b;
@@ -84,7 +85,17 @@ export const bootstrapPostHog = (config) => {
84
85
  bootstrap: { distinctID: config.distinctId },
85
86
  loaded: () => {
86
87
  let unsubscribe = null;
87
- unsubscribe = posthog.onFeatureFlags(() => {
88
+ let scopedReloadRetried = false;
89
+ unsubscribe = posthog.onFeatureFlags((flags) => {
90
+ if (Object.keys(scopeProperties).length > 0 &&
91
+ flags.length === 0 &&
92
+ !scopedReloadRetried) {
93
+ scopedReloadRetried = true;
94
+ setTimeout(() => {
95
+ posthog.reloadFeatureFlags();
96
+ }, POSTHOG_SCOPED_FLAG_RELOAD_RETRY_MS);
97
+ return;
98
+ }
88
99
  unsubscribe === null || unsubscribe === void 0 ? void 0 : unsubscribe();
89
100
  markReady();
90
101
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@funnelsgrove/runtime",
3
- "version": "0.1.44",
3
+ "version": "0.1.45",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "main": "./dist/index.js",