@fabricorg/experiments-web-adapters 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,19 @@
1
+ # @fabricorg/experiments-web-adapters
2
+
3
+ Snowplow, GA4, GTM/dataLayer, failure, and Mojito migration adapters for
4
+ `@fabricorg/experiments-web`.
5
+
6
+ ```ts
7
+ import { mojitoCompatibilityAdapter } from '@fabricorg/experiments-web-adapters'
8
+
9
+ const hooks = mojitoCompatibilityAdapter(Mojito.options.storageAdapter)
10
+ await init({ manifestUrl, subjectId, ...hooks })
11
+ ```
12
+
13
+ The bridge maps successful exposure, recipe failure, and activation timeout to
14
+ Mojito's `onExposure`, `onRecipeFailure`, and `onVeilTimeout` callbacks. The
15
+ complete Fabric record remains available on `test.fabric`.
16
+
17
+ Documentation: https://experiments.fabric.pro/docs/reference/web-adapters/
18
+
19
+ MIT
package/dist/index.cjs CHANGED
@@ -107,11 +107,45 @@ function dataLayerFailureAdapter(options = {}) {
107
107
  });
108
108
  };
109
109
  }
110
+ function mojitoTestObject(record, options) {
111
+ var _a, _b, _c, _d, _e;
112
+ return {
113
+ options: {
114
+ id: record.experimentId,
115
+ name: (_b = (_a = options.experimentNames) == null ? void 0 : _a[record.experimentId]) != null ? _b : record.experimentId
116
+ },
117
+ chosenRecipe: {
118
+ id: record.variantKey,
119
+ name: (_e = (_d = (_c = options.variantNames) == null ? void 0 : _c[record.experimentId]) == null ? void 0 : _d[record.variantKey]) != null ? _e : record.variantKey
120
+ },
121
+ subjectId: record.subjectId,
122
+ manifestVersion: record.manifestVersion,
123
+ fabric: record
124
+ };
125
+ }
126
+ function mojitoCompatibilityAdapter(adapter, options = {}) {
127
+ return {
128
+ onExposure(record) {
129
+ var _a;
130
+ if (!record.failure) (_a = adapter.onExposure) == null ? void 0 : _a.call(adapter, mojitoTestObject(record, options));
131
+ },
132
+ onRecipeFailure(record) {
133
+ var _a;
134
+ if (!record.failure) return;
135
+ (_a = adapter.onRecipeFailure) == null ? void 0 : _a.call(adapter, mojitoTestObject(record, options), record.failure.message);
136
+ },
137
+ onActivationFailure(record) {
138
+ var _a;
139
+ (_a = adapter.onVeilTimeout) == null ? void 0 : _a.call(adapter, mojitoTestObject(record, options), record.variantKey);
140
+ }
141
+ };
142
+ }
110
143
 
111
144
  exports.compose = compose;
112
145
  exports.dataLayerAdapter = dataLayerAdapter;
113
146
  exports.dataLayerFailureAdapter = dataLayerFailureAdapter;
114
147
  exports.gaAdapter = gaAdapter;
148
+ exports.mojitoCompatibilityAdapter = mojitoCompatibilityAdapter;
115
149
  exports.snowplowAdapter = snowplowAdapter;
116
150
  exports.snowplowFailureAdapter = snowplowFailureAdapter;
117
151
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":["_a"],"mappings":";;;AAiBO,SAAS,eAAA,CAAgB,OAAA,GAAkC,EAAC,EAAoB;AAjBvF,EAAA,IAAA,EAAA;AAkBE,EAAA,MAAM,MAAA,GAAA,CAAS,EAAA,GAAA,OAAA,CAAQ,MAAA,KAAR,IAAA,GAAA,EAAA,GAAkB,sDAAA;AACjC,EAAA,OAAO,CAAC,MAAA,KAAW;AAnBrB,IAAA,IAAAA,GAAAA;AAoBI,IAAA,MAAM,WACJA,GAAAA,GAAA,OAAA,CAAQ,OAAA,KAAR,IAAA,GAAAA,MAAoB,UAAA,CAA2D,QAAA;AACjF,IAAA,IAAI,CAAC,OAAA,EAAS;AACd,IAAA,OAAA,CAAQ,0BAAA,EAA4B;AAAA,MAClC,KAAA,EAAO;AAAA,QACL,MAAA;AAAA,QACA,IAAA,EAAM;AAAA,UACJ,cAAc,MAAA,CAAO,YAAA;AAAA,UACrB,YAAY,MAAA,CAAO,UAAA;AAAA,UACnB,WAAW,MAAA,CAAO,SAAA;AAAA,UAClB,iBAAiB,MAAA,CAAO,eAAA;AAAA,UACxB,IAAI,MAAA,CAAO,EAAA;AAAA,UACX,SAAS,MAAA,CAAO;AAAA;AAClB;AACF,KACD,CAAA;AAAA,EACH,CAAA;AACF;AAYO,SAAS,SAAA,CAAU,OAAA,GAA4B,EAAC,EAAoB;AAjD3E,EAAA,IAAA,EAAA;AAkDE,EAAA,MAAM,SAAA,GAAA,CAAY,EAAA,GAAA,OAAA,CAAQ,SAAA,KAAR,IAAA,GAAA,EAAA,GAAqB,qBAAA;AACvC,EAAA,OAAO,CAAC,MAAA,KAAW;AAnDrB,IAAA,IAAAA,GAAAA;AAoDI,IAAA,MAAM,QAAOA,GAAAA,GAAA,OAAA,CAAQ,IAAA,KAAR,IAAA,GAAAA,MAAiB,UAAA,CAAuD,IAAA;AACrF,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,IAAA,CAAK,SAAS,SAAA,EAAW;AAAA,MACvB,eAAe,MAAA,CAAO,YAAA;AAAA,MACtB,aAAa,MAAA,CAAO,UAAA;AAAA,MACpB,kBAAkB,MAAA,CAAO;AAAA,KAC1B,CAAA;AAAA,EACH,CAAA;AACF;AAaO,SAAS,gBAAA,CAAiB,OAAA,GAAmC,EAAC,EAAoB;AAzEzF,EAAA,IAAA,EAAA;AA0EE,EAAA,MAAM,SAAA,GAAA,CAAY,EAAA,GAAA,OAAA,CAAQ,SAAA,KAAR,IAAA,GAAA,EAAA,GAAqB,aAAA;AACvC,EAAA,OAAO,CAAC,MAAA,KAAW;AA3ErB,IAAA,IAAAA,GAAAA;AA4EI,IAAA,MAAM,CAAA,GAAI,UAAA;AACV,IAAA,IAAI,CAAC,CAAA,CAAE,SAAA,EAAW,CAAA,CAAE,YAAY,EAAC;AACjC,IAAA,MAAM,MAAKA,GAAAA,GAAA,OAAA,CAAQ,SAAA,KAAR,IAAA,GAAAA,MAAqB,CAAA,CAAE,SAAA;AAClC,IAAA,EAAA,CAAG,IAAA,CAAK;AAAA,MACN,KAAA,EAAO,SAAA;AAAA,MACP,kBAAkB,MAAA,CAAO,YAAA;AAAA,MACzB,gBAAgB,MAAA,CAAO,UAAA;AAAA,MACvB,eAAe,MAAA,CAAO,SAAA;AAAA,MACtB,qBAAqB,MAAA,CAAO;AAAA,KAC7B,CAAA;AAAA,EACH,CAAA;AACF;AAMO,SAAS,WAAW,QAAA,EAAuD;AAChF,EAAA,OAAO,CAAC,MAAA,KAAW;AACjB,IAAA,KAAA,MAAW,KAAK,QAAA,EAAU;AACxB,MAAA,IAAI;AACF,QAAA,CAAA,CAAE,MAAM,CAAA;AAAA,MACV,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,MAER;AAAA,IACF;AAAA,EACF,CAAA;AACF;AAeO,SAAS,sBAAA,CACd,OAAA,GAAyC,EAAC,EACzB;AAxHnB,EAAA,IAAA,EAAA;AAyHE,EAAA,MAAM,MAAA,GAAA,CAAS,EAAA,GAAA,OAAA,CAAQ,MAAA,KAAR,IAAA,GAAA,EAAA,GAAkB,4DAAA;AACjC,EAAA,OAAO,CAAC,MAAA,KAAW;AA1HrB,IAAA,IAAAA,GAAAA;AA2HI,IAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACrB,IAAA,MAAM,WACJA,GAAAA,GAAA,OAAA,CAAQ,OAAA,KAAR,IAAA,GAAAA,MAAoB,UAAA,CAA2D,QAAA;AACjF,IAAA,IAAI,CAAC,OAAA,EAAS;AACd,IAAA,OAAA,CAAQ,0BAAA,EAA4B;AAAA,MAClC,KAAA,EAAO;AAAA,QACL,MAAA;AAAA,QACA,IAAA,EAAM;AAAA,UACJ,cAAc,MAAA,CAAO,YAAA;AAAA,UACrB,YAAY,MAAA,CAAO,UAAA;AAAA,UACnB,WAAW,MAAA,CAAO,SAAA;AAAA,UAClB,iBAAiB,MAAA,CAAO,eAAA;AAAA,UACxB,IAAI,MAAA,CAAO,EAAA;AAAA,UACX,OAAA,EAAS,OAAO,OAAA,CAAQ,OAAA;AAAA,UACxB,KAAA,EAAO,OAAO,OAAA,CAAQ;AAAA;AACxB;AACF,KACD,CAAA;AAAA,EACH,CAAA;AACF;AAGO,SAAS,uBAAA,CAAwB,OAAA,GAAmC,EAAC,EAAoB;AAjJhG,EAAA,IAAA,EAAA;AAkJE,EAAA,MAAM,SAAA,GAAA,CAAY,EAAA,GAAA,OAAA,CAAQ,SAAA,KAAR,IAAA,GAAA,EAAA,GAAqB,mBAAA;AACvC,EAAA,OAAO,CAAC,MAAA,KAAW;AAnJrB,IAAA,IAAAA,GAAAA;AAoJI,IAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACrB,IAAA,MAAM,CAAA,GAAI,UAAA;AACV,IAAA,IAAI,CAAC,CAAA,CAAE,SAAA,EAAW,CAAA,CAAE,YAAY,EAAC;AACjC,IAAA,MAAM,MAAKA,GAAAA,GAAA,OAAA,CAAQ,SAAA,KAAR,IAAA,GAAAA,MAAqB,CAAA,CAAE,SAAA;AAClC,IAAA,EAAA,CAAG,IAAA,CAAK;AAAA,MACN,KAAA,EAAO,SAAA;AAAA,MACP,kBAAkB,MAAA,CAAO,YAAA;AAAA,MACzB,gBAAgB,MAAA,CAAO,UAAA;AAAA,MACvB,eAAe,MAAA,CAAO,SAAA;AAAA,MACtB,qBAAqB,MAAA,CAAO,eAAA;AAAA,MAC5B,kBAAA,EAAoB,OAAO,OAAA,CAAQ;AAAA,KACpC,CAAA;AAAA,EACH,CAAA;AACF","file":"index.cjs","sourcesContent":["import type { ExposureRecord } from '@fabricorg/experiments-web';\n\nexport type ExposureAdapter = (record: ExposureRecord) => void;\n\n/**\n * Snowplow self-describing exposure event.\n *\n * Schema: iglu:io.fabric.experiments/exposure/jsonschema/1-0-0\n * (host the schema in your Iglu repo to validate downstream).\n */\nexport interface SnowplowAdapterOptions {\n /** Tracker function: typically `(window as any).snowplow` or the explicit tracker. */\n tracker?: (...args: unknown[]) => void;\n /** Schema URI. Override if you publish a custom schema. */\n schema?: string;\n}\n\nexport function snowplowAdapter(options: SnowplowAdapterOptions = {}): ExposureAdapter {\n const schema = options.schema ?? 'iglu:io.fabric.experiments/exposure/jsonschema/1-0-0';\n return (record) => {\n const tracker =\n options.tracker ?? (globalThis as { snowplow?: (...args: unknown[]) => void }).snowplow;\n if (!tracker) return;\n tracker('trackSelfDescribingEvent', {\n event: {\n schema,\n data: {\n experimentId: record.experimentId,\n variantKey: record.variantKey,\n subjectId: record.subjectId,\n manifestVersion: record.manifestVersion,\n at: record.at,\n failure: record.failure,\n },\n },\n });\n };\n}\n\n/**\n * Google Analytics 4 (gtag) adapter.\n * Sends an `experiment_exposure` event with custom dimensions.\n */\nexport interface GaAdapterOptions {\n gtag?: (...args: unknown[]) => void;\n /** Override the event name. Default: `experiment_exposure`. */\n eventName?: string;\n}\n\nexport function gaAdapter(options: GaAdapterOptions = {}): ExposureAdapter {\n const eventName = options.eventName ?? 'experiment_exposure';\n return (record) => {\n const gtag = options.gtag ?? (globalThis as { gtag?: (...args: unknown[]) => void }).gtag;\n if (!gtag) return;\n gtag('event', eventName, {\n experiment_id: record.experimentId,\n variant_key: record.variantKey,\n manifest_version: record.manifestVersion,\n });\n };\n}\n\n/**\n * Generic GTM dataLayer adapter — pushes a single event GTM tags can listen for.\n * This is also the default tag-loader behavior.\n */\nexport interface DataLayerAdapterOptions {\n /** Override the dataLayer reference (tests). */\n dataLayer?: Array<Record<string, unknown>>;\n /** Override the event name. Default: `fx_exposure`. */\n eventName?: string;\n}\n\nexport function dataLayerAdapter(options: DataLayerAdapterOptions = {}): ExposureAdapter {\n const eventName = options.eventName ?? 'fx_exposure';\n return (record) => {\n const w = globalThis as { dataLayer?: Array<Record<string, unknown>> };\n if (!w.dataLayer) w.dataLayer = [];\n const dl = options.dataLayer ?? w.dataLayer;\n dl.push({\n event: eventName,\n fx_experiment_id: record.experimentId,\n fx_variant_key: record.variantKey,\n fx_subject_id: record.subjectId,\n fx_manifest_version: record.manifestVersion,\n });\n };\n}\n\n/**\n * Fan out a single exposure to multiple adapters. Each adapter is wrapped in\n * a try/catch so a third-party tracker error never breaks the chain.\n */\nexport function compose(...adapters: readonly ExposureAdapter[]): ExposureAdapter {\n return (record) => {\n for (const a of adapters) {\n try {\n a(record);\n } catch {\n /* swallow */\n }\n }\n };\n}\n\n// ---- Failure adapters (Mojito onRecipeFailure parity) ----------------------\n\n/**\n * Snowplow self-describing event for variant failures.\n *\n * Schema: iglu:io.fabric.experiments/recipe_failure/jsonschema/1-0-0\n * Fires once per (experimentId, variantKey, message) — useful for alarming\n * on variant-code crashes without cluttering the exposure stream.\n */\nexport interface SnowplowFailureAdapterOptions extends SnowplowAdapterOptions {\n schema?: string;\n}\n\nexport function snowplowFailureAdapter(\n options: SnowplowFailureAdapterOptions = {},\n): ExposureAdapter {\n const schema = options.schema ?? 'iglu:io.fabric.experiments/recipe_failure/jsonschema/1-0-0';\n return (record) => {\n if (!record.failure) return;\n const tracker =\n options.tracker ?? (globalThis as { snowplow?: (...args: unknown[]) => void }).snowplow;\n if (!tracker) return;\n tracker('trackSelfDescribingEvent', {\n event: {\n schema,\n data: {\n experimentId: record.experimentId,\n variantKey: record.variantKey,\n subjectId: record.subjectId,\n manifestVersion: record.manifestVersion,\n at: record.at,\n message: record.failure.message,\n stack: record.failure.stack,\n },\n },\n });\n };\n}\n\n/** dataLayer push for variant failures — pairs with the default exposure adapter. */\nexport function dataLayerFailureAdapter(options: DataLayerAdapterOptions = {}): ExposureAdapter {\n const eventName = options.eventName ?? 'fx_recipe_failure';\n return (record) => {\n if (!record.failure) return;\n const w = globalThis as { dataLayer?: Array<Record<string, unknown>> };\n if (!w.dataLayer) w.dataLayer = [];\n const dl = options.dataLayer ?? w.dataLayer;\n dl.push({\n event: eventName,\n fx_experiment_id: record.experimentId,\n fx_variant_key: record.variantKey,\n fx_subject_id: record.subjectId,\n fx_manifest_version: record.manifestVersion,\n fx_failure_message: record.failure.message,\n });\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":["_a"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { ActivationFailureRecord, ExposureRecord } from '@fabricorg/experiments-web';\n\nexport type ExposureAdapter = (record: ExposureRecord) => void;\n\n/**\n * Snowplow self-describing exposure event.\n *\n * Schema: iglu:io.fabric.experiments/exposure/jsonschema/1-0-0\n * (host the schema in your Iglu repo to validate downstream).\n */\nexport interface SnowplowAdapterOptions {\n /** Tracker function: typically `(window as any).snowplow` or the explicit tracker. */\n tracker?: (...args: unknown[]) => void;\n /** Schema URI. Override if you publish a custom schema. */\n schema?: string;\n}\n\nexport function snowplowAdapter(options: SnowplowAdapterOptions = {}): ExposureAdapter {\n const schema = options.schema ?? 'iglu:io.fabric.experiments/exposure/jsonschema/1-0-0';\n return (record) => {\n const tracker =\n options.tracker ?? (globalThis as { snowplow?: (...args: unknown[]) => void }).snowplow;\n if (!tracker) return;\n tracker('trackSelfDescribingEvent', {\n event: {\n schema,\n data: {\n experimentId: record.experimentId,\n variantKey: record.variantKey,\n subjectId: record.subjectId,\n manifestVersion: record.manifestVersion,\n at: record.at,\n failure: record.failure,\n },\n },\n });\n };\n}\n\n/**\n * Google Analytics 4 (gtag) adapter.\n * Sends an `experiment_exposure` event with custom dimensions.\n */\nexport interface GaAdapterOptions {\n gtag?: (...args: unknown[]) => void;\n /** Override the event name. Default: `experiment_exposure`. */\n eventName?: string;\n}\n\nexport function gaAdapter(options: GaAdapterOptions = {}): ExposureAdapter {\n const eventName = options.eventName ?? 'experiment_exposure';\n return (record) => {\n const gtag = options.gtag ?? (globalThis as { gtag?: (...args: unknown[]) => void }).gtag;\n if (!gtag) return;\n gtag('event', eventName, {\n experiment_id: record.experimentId,\n variant_key: record.variantKey,\n manifest_version: record.manifestVersion,\n });\n };\n}\n\n/**\n * Generic GTM dataLayer adapter — pushes a single event GTM tags can listen for.\n * This is also the default tag-loader behavior.\n */\nexport interface DataLayerAdapterOptions {\n /** Override the dataLayer reference (tests). */\n dataLayer?: Array<Record<string, unknown>>;\n /** Override the event name. Default: `fx_exposure`. */\n eventName?: string;\n}\n\nexport function dataLayerAdapter(options: DataLayerAdapterOptions = {}): ExposureAdapter {\n const eventName = options.eventName ?? 'fx_exposure';\n return (record) => {\n const w = globalThis as { dataLayer?: Array<Record<string, unknown>> };\n if (!w.dataLayer) w.dataLayer = [];\n const dl = options.dataLayer ?? w.dataLayer;\n dl.push({\n event: eventName,\n fx_experiment_id: record.experimentId,\n fx_variant_key: record.variantKey,\n fx_subject_id: record.subjectId,\n fx_manifest_version: record.manifestVersion,\n });\n };\n}\n\n/**\n * Fan out a single exposure to multiple adapters. Each adapter is wrapped in\n * a try/catch so a third-party tracker error never breaks the chain.\n */\nexport function compose(...adapters: readonly ExposureAdapter[]): ExposureAdapter {\n return (record) => {\n for (const a of adapters) {\n try {\n a(record);\n } catch {\n /* swallow */\n }\n }\n };\n}\n\n// ---- Failure adapters (Mojito onRecipeFailure parity) ----------------------\n\n/**\n * Snowplow self-describing event for variant failures.\n *\n * Schema: iglu:io.fabric.experiments/recipe_failure/jsonschema/1-0-0\n * Fires once per (experimentId, variantKey, message) — useful for alarming\n * on variant-code crashes without cluttering the exposure stream.\n */\nexport interface SnowplowFailureAdapterOptions extends SnowplowAdapterOptions {\n schema?: string;\n}\n\nexport function snowplowFailureAdapter(\n options: SnowplowFailureAdapterOptions = {},\n): ExposureAdapter {\n const schema = options.schema ?? 'iglu:io.fabric.experiments/recipe_failure/jsonschema/1-0-0';\n return (record) => {\n if (!record.failure) return;\n const tracker =\n options.tracker ?? (globalThis as { snowplow?: (...args: unknown[]) => void }).snowplow;\n if (!tracker) return;\n tracker('trackSelfDescribingEvent', {\n event: {\n schema,\n data: {\n experimentId: record.experimentId,\n variantKey: record.variantKey,\n subjectId: record.subjectId,\n manifestVersion: record.manifestVersion,\n at: record.at,\n message: record.failure.message,\n stack: record.failure.stack,\n },\n },\n });\n };\n}\n\n/** dataLayer push for variant failures — pairs with the default exposure adapter. */\nexport function dataLayerFailureAdapter(options: DataLayerAdapterOptions = {}): ExposureAdapter {\n const eventName = options.eventName ?? 'fx_recipe_failure';\n return (record) => {\n if (!record.failure) return;\n const w = globalThis as { dataLayer?: Array<Record<string, unknown>> };\n if (!w.dataLayer) w.dataLayer = [];\n const dl = options.dataLayer ?? w.dataLayer;\n dl.push({\n event: eventName,\n fx_experiment_id: record.experimentId,\n fx_variant_key: record.variantKey,\n fx_subject_id: record.subjectId,\n fx_manifest_version: record.manifestVersion,\n fx_failure_message: record.failure.message,\n });\n };\n}\n\n// ---- Mojito storage-adapter bridge ----------------------------------------\n\n/** Minimal Mojito-shaped object passed to legacy storage-adapter callbacks. */\nexport interface MojitoCompatibleTestObject {\n options: { id: string; name: string };\n chosenRecipe: { id: string; name: string };\n subjectId: string;\n manifestVersion: number;\n fabric: ExposureRecord | ActivationFailureRecord;\n}\n\nexport interface MojitoStorageAdapter {\n onExposure?: (test: MojitoCompatibleTestObject) => void;\n onRecipeFailure?: (test: MojitoCompatibleTestObject, error?: string) => void;\n onVeilTimeout?: (test: MojitoCompatibleTestObject, ultimateRecipe: string) => void;\n}\n\nexport interface MojitoCompatibilityOptions {\n experimentNames?: Record<string, string>;\n variantNames?: Record<string, Record<string, string>>;\n}\n\nfunction mojitoTestObject(\n record: ExposureRecord | ActivationFailureRecord,\n options: MojitoCompatibilityOptions,\n): MojitoCompatibleTestObject {\n return {\n options: {\n id: record.experimentId,\n name: options.experimentNames?.[record.experimentId] ?? record.experimentId,\n },\n chosenRecipe: {\n id: record.variantKey,\n name: options.variantNames?.[record.experimentId]?.[record.variantKey] ?? record.variantKey,\n },\n subjectId: record.subjectId,\n manifestVersion: record.manifestVersion,\n fabric: record,\n };\n}\n\n/**\n * Reuse an existing Mojito `storageAdapter` while migrating delivery to\n * Fabric. Spread the returned hooks into `init()` or `window.__FX__`.\n */\nexport function mojitoCompatibilityAdapter(\n adapter: MojitoStorageAdapter,\n options: MojitoCompatibilityOptions = {},\n): {\n onExposure: ExposureAdapter;\n onRecipeFailure: ExposureAdapter;\n onActivationFailure: (record: ActivationFailureRecord) => void;\n} {\n return {\n onExposure(record) {\n // Failure records are delivered separately, matching Mojito's event split.\n if (!record.failure) adapter.onExposure?.(mojitoTestObject(record, options));\n },\n onRecipeFailure(record) {\n if (!record.failure) return;\n adapter.onRecipeFailure?.(mojitoTestObject(record, options), record.failure.message);\n },\n onActivationFailure(record) {\n adapter.onVeilTimeout?.(mojitoTestObject(record, options), record.variantKey);\n },\n };\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { ExposureRecord } from '@fabricorg/experiments-web';
1
+ import { ExposureRecord, ActivationFailureRecord } from '@fabricorg/experiments-web';
2
2
 
3
3
  type ExposureAdapter = (record: ExposureRecord) => void;
4
4
  /**
@@ -53,5 +53,37 @@ interface SnowplowFailureAdapterOptions extends SnowplowAdapterOptions {
53
53
  declare function snowplowFailureAdapter(options?: SnowplowFailureAdapterOptions): ExposureAdapter;
54
54
  /** dataLayer push for variant failures — pairs with the default exposure adapter. */
55
55
  declare function dataLayerFailureAdapter(options?: DataLayerAdapterOptions): ExposureAdapter;
56
+ /** Minimal Mojito-shaped object passed to legacy storage-adapter callbacks. */
57
+ interface MojitoCompatibleTestObject {
58
+ options: {
59
+ id: string;
60
+ name: string;
61
+ };
62
+ chosenRecipe: {
63
+ id: string;
64
+ name: string;
65
+ };
66
+ subjectId: string;
67
+ manifestVersion: number;
68
+ fabric: ExposureRecord | ActivationFailureRecord;
69
+ }
70
+ interface MojitoStorageAdapter {
71
+ onExposure?: (test: MojitoCompatibleTestObject) => void;
72
+ onRecipeFailure?: (test: MojitoCompatibleTestObject, error?: string) => void;
73
+ onVeilTimeout?: (test: MojitoCompatibleTestObject, ultimateRecipe: string) => void;
74
+ }
75
+ interface MojitoCompatibilityOptions {
76
+ experimentNames?: Record<string, string>;
77
+ variantNames?: Record<string, Record<string, string>>;
78
+ }
79
+ /**
80
+ * Reuse an existing Mojito `storageAdapter` while migrating delivery to
81
+ * Fabric. Spread the returned hooks into `init()` or `window.__FX__`.
82
+ */
83
+ declare function mojitoCompatibilityAdapter(adapter: MojitoStorageAdapter, options?: MojitoCompatibilityOptions): {
84
+ onExposure: ExposureAdapter;
85
+ onRecipeFailure: ExposureAdapter;
86
+ onActivationFailure: (record: ActivationFailureRecord) => void;
87
+ };
56
88
 
57
- export { type DataLayerAdapterOptions, type ExposureAdapter, type GaAdapterOptions, type SnowplowAdapterOptions, type SnowplowFailureAdapterOptions, compose, dataLayerAdapter, dataLayerFailureAdapter, gaAdapter, snowplowAdapter, snowplowFailureAdapter };
89
+ export { type DataLayerAdapterOptions, type ExposureAdapter, type GaAdapterOptions, type MojitoCompatibilityOptions, type MojitoCompatibleTestObject, type MojitoStorageAdapter, type SnowplowAdapterOptions, type SnowplowFailureAdapterOptions, compose, dataLayerAdapter, dataLayerFailureAdapter, gaAdapter, mojitoCompatibilityAdapter, snowplowAdapter, snowplowFailureAdapter };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ExposureRecord } from '@fabricorg/experiments-web';
1
+ import { ExposureRecord, ActivationFailureRecord } from '@fabricorg/experiments-web';
2
2
 
3
3
  type ExposureAdapter = (record: ExposureRecord) => void;
4
4
  /**
@@ -53,5 +53,37 @@ interface SnowplowFailureAdapterOptions extends SnowplowAdapterOptions {
53
53
  declare function snowplowFailureAdapter(options?: SnowplowFailureAdapterOptions): ExposureAdapter;
54
54
  /** dataLayer push for variant failures — pairs with the default exposure adapter. */
55
55
  declare function dataLayerFailureAdapter(options?: DataLayerAdapterOptions): ExposureAdapter;
56
+ /** Minimal Mojito-shaped object passed to legacy storage-adapter callbacks. */
57
+ interface MojitoCompatibleTestObject {
58
+ options: {
59
+ id: string;
60
+ name: string;
61
+ };
62
+ chosenRecipe: {
63
+ id: string;
64
+ name: string;
65
+ };
66
+ subjectId: string;
67
+ manifestVersion: number;
68
+ fabric: ExposureRecord | ActivationFailureRecord;
69
+ }
70
+ interface MojitoStorageAdapter {
71
+ onExposure?: (test: MojitoCompatibleTestObject) => void;
72
+ onRecipeFailure?: (test: MojitoCompatibleTestObject, error?: string) => void;
73
+ onVeilTimeout?: (test: MojitoCompatibleTestObject, ultimateRecipe: string) => void;
74
+ }
75
+ interface MojitoCompatibilityOptions {
76
+ experimentNames?: Record<string, string>;
77
+ variantNames?: Record<string, Record<string, string>>;
78
+ }
79
+ /**
80
+ * Reuse an existing Mojito `storageAdapter` while migrating delivery to
81
+ * Fabric. Spread the returned hooks into `init()` or `window.__FX__`.
82
+ */
83
+ declare function mojitoCompatibilityAdapter(adapter: MojitoStorageAdapter, options?: MojitoCompatibilityOptions): {
84
+ onExposure: ExposureAdapter;
85
+ onRecipeFailure: ExposureAdapter;
86
+ onActivationFailure: (record: ActivationFailureRecord) => void;
87
+ };
56
88
 
57
- export { type DataLayerAdapterOptions, type ExposureAdapter, type GaAdapterOptions, type SnowplowAdapterOptions, type SnowplowFailureAdapterOptions, compose, dataLayerAdapter, dataLayerFailureAdapter, gaAdapter, snowplowAdapter, snowplowFailureAdapter };
89
+ export { type DataLayerAdapterOptions, type ExposureAdapter, type GaAdapterOptions, type MojitoCompatibilityOptions, type MojitoCompatibleTestObject, type MojitoStorageAdapter, type SnowplowAdapterOptions, type SnowplowFailureAdapterOptions, compose, dataLayerAdapter, dataLayerFailureAdapter, gaAdapter, mojitoCompatibilityAdapter, snowplowAdapter, snowplowFailureAdapter };
package/dist/index.js CHANGED
@@ -105,7 +105,40 @@ function dataLayerFailureAdapter(options = {}) {
105
105
  });
106
106
  };
107
107
  }
108
+ function mojitoTestObject(record, options) {
109
+ var _a, _b, _c, _d, _e;
110
+ return {
111
+ options: {
112
+ id: record.experimentId,
113
+ name: (_b = (_a = options.experimentNames) == null ? void 0 : _a[record.experimentId]) != null ? _b : record.experimentId
114
+ },
115
+ chosenRecipe: {
116
+ id: record.variantKey,
117
+ name: (_e = (_d = (_c = options.variantNames) == null ? void 0 : _c[record.experimentId]) == null ? void 0 : _d[record.variantKey]) != null ? _e : record.variantKey
118
+ },
119
+ subjectId: record.subjectId,
120
+ manifestVersion: record.manifestVersion,
121
+ fabric: record
122
+ };
123
+ }
124
+ function mojitoCompatibilityAdapter(adapter, options = {}) {
125
+ return {
126
+ onExposure(record) {
127
+ var _a;
128
+ if (!record.failure) (_a = adapter.onExposure) == null ? void 0 : _a.call(adapter, mojitoTestObject(record, options));
129
+ },
130
+ onRecipeFailure(record) {
131
+ var _a;
132
+ if (!record.failure) return;
133
+ (_a = adapter.onRecipeFailure) == null ? void 0 : _a.call(adapter, mojitoTestObject(record, options), record.failure.message);
134
+ },
135
+ onActivationFailure(record) {
136
+ var _a;
137
+ (_a = adapter.onVeilTimeout) == null ? void 0 : _a.call(adapter, mojitoTestObject(record, options), record.variantKey);
138
+ }
139
+ };
140
+ }
108
141
 
109
- export { compose, dataLayerAdapter, dataLayerFailureAdapter, gaAdapter, snowplowAdapter, snowplowFailureAdapter };
142
+ export { compose, dataLayerAdapter, dataLayerFailureAdapter, gaAdapter, mojitoCompatibilityAdapter, snowplowAdapter, snowplowFailureAdapter };
110
143
  //# sourceMappingURL=index.js.map
111
144
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":["_a"],"mappings":";AAiBO,SAAS,eAAA,CAAgB,OAAA,GAAkC,EAAC,EAAoB;AAjBvF,EAAA,IAAA,EAAA;AAkBE,EAAA,MAAM,MAAA,GAAA,CAAS,EAAA,GAAA,OAAA,CAAQ,MAAA,KAAR,IAAA,GAAA,EAAA,GAAkB,sDAAA;AACjC,EAAA,OAAO,CAAC,MAAA,KAAW;AAnBrB,IAAA,IAAAA,GAAAA;AAoBI,IAAA,MAAM,WACJA,GAAAA,GAAA,OAAA,CAAQ,OAAA,KAAR,IAAA,GAAAA,MAAoB,UAAA,CAA2D,QAAA;AACjF,IAAA,IAAI,CAAC,OAAA,EAAS;AACd,IAAA,OAAA,CAAQ,0BAAA,EAA4B;AAAA,MAClC,KAAA,EAAO;AAAA,QACL,MAAA;AAAA,QACA,IAAA,EAAM;AAAA,UACJ,cAAc,MAAA,CAAO,YAAA;AAAA,UACrB,YAAY,MAAA,CAAO,UAAA;AAAA,UACnB,WAAW,MAAA,CAAO,SAAA;AAAA,UAClB,iBAAiB,MAAA,CAAO,eAAA;AAAA,UACxB,IAAI,MAAA,CAAO,EAAA;AAAA,UACX,SAAS,MAAA,CAAO;AAAA;AAClB;AACF,KACD,CAAA;AAAA,EACH,CAAA;AACF;AAYO,SAAS,SAAA,CAAU,OAAA,GAA4B,EAAC,EAAoB;AAjD3E,EAAA,IAAA,EAAA;AAkDE,EAAA,MAAM,SAAA,GAAA,CAAY,EAAA,GAAA,OAAA,CAAQ,SAAA,KAAR,IAAA,GAAA,EAAA,GAAqB,qBAAA;AACvC,EAAA,OAAO,CAAC,MAAA,KAAW;AAnDrB,IAAA,IAAAA,GAAAA;AAoDI,IAAA,MAAM,QAAOA,GAAAA,GAAA,OAAA,CAAQ,IAAA,KAAR,IAAA,GAAAA,MAAiB,UAAA,CAAuD,IAAA;AACrF,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,IAAA,CAAK,SAAS,SAAA,EAAW;AAAA,MACvB,eAAe,MAAA,CAAO,YAAA;AAAA,MACtB,aAAa,MAAA,CAAO,UAAA;AAAA,MACpB,kBAAkB,MAAA,CAAO;AAAA,KAC1B,CAAA;AAAA,EACH,CAAA;AACF;AAaO,SAAS,gBAAA,CAAiB,OAAA,GAAmC,EAAC,EAAoB;AAzEzF,EAAA,IAAA,EAAA;AA0EE,EAAA,MAAM,SAAA,GAAA,CAAY,EAAA,GAAA,OAAA,CAAQ,SAAA,KAAR,IAAA,GAAA,EAAA,GAAqB,aAAA;AACvC,EAAA,OAAO,CAAC,MAAA,KAAW;AA3ErB,IAAA,IAAAA,GAAAA;AA4EI,IAAA,MAAM,CAAA,GAAI,UAAA;AACV,IAAA,IAAI,CAAC,CAAA,CAAE,SAAA,EAAW,CAAA,CAAE,YAAY,EAAC;AACjC,IAAA,MAAM,MAAKA,GAAAA,GAAA,OAAA,CAAQ,SAAA,KAAR,IAAA,GAAAA,MAAqB,CAAA,CAAE,SAAA;AAClC,IAAA,EAAA,CAAG,IAAA,CAAK;AAAA,MACN,KAAA,EAAO,SAAA;AAAA,MACP,kBAAkB,MAAA,CAAO,YAAA;AAAA,MACzB,gBAAgB,MAAA,CAAO,UAAA;AAAA,MACvB,eAAe,MAAA,CAAO,SAAA;AAAA,MACtB,qBAAqB,MAAA,CAAO;AAAA,KAC7B,CAAA;AAAA,EACH,CAAA;AACF;AAMO,SAAS,WAAW,QAAA,EAAuD;AAChF,EAAA,OAAO,CAAC,MAAA,KAAW;AACjB,IAAA,KAAA,MAAW,KAAK,QAAA,EAAU;AACxB,MAAA,IAAI;AACF,QAAA,CAAA,CAAE,MAAM,CAAA;AAAA,MACV,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,MAER;AAAA,IACF;AAAA,EACF,CAAA;AACF;AAeO,SAAS,sBAAA,CACd,OAAA,GAAyC,EAAC,EACzB;AAxHnB,EAAA,IAAA,EAAA;AAyHE,EAAA,MAAM,MAAA,GAAA,CAAS,EAAA,GAAA,OAAA,CAAQ,MAAA,KAAR,IAAA,GAAA,EAAA,GAAkB,4DAAA;AACjC,EAAA,OAAO,CAAC,MAAA,KAAW;AA1HrB,IAAA,IAAAA,GAAAA;AA2HI,IAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACrB,IAAA,MAAM,WACJA,GAAAA,GAAA,OAAA,CAAQ,OAAA,KAAR,IAAA,GAAAA,MAAoB,UAAA,CAA2D,QAAA;AACjF,IAAA,IAAI,CAAC,OAAA,EAAS;AACd,IAAA,OAAA,CAAQ,0BAAA,EAA4B;AAAA,MAClC,KAAA,EAAO;AAAA,QACL,MAAA;AAAA,QACA,IAAA,EAAM;AAAA,UACJ,cAAc,MAAA,CAAO,YAAA;AAAA,UACrB,YAAY,MAAA,CAAO,UAAA;AAAA,UACnB,WAAW,MAAA,CAAO,SAAA;AAAA,UAClB,iBAAiB,MAAA,CAAO,eAAA;AAAA,UACxB,IAAI,MAAA,CAAO,EAAA;AAAA,UACX,OAAA,EAAS,OAAO,OAAA,CAAQ,OAAA;AAAA,UACxB,KAAA,EAAO,OAAO,OAAA,CAAQ;AAAA;AACxB;AACF,KACD,CAAA;AAAA,EACH,CAAA;AACF;AAGO,SAAS,uBAAA,CAAwB,OAAA,GAAmC,EAAC,EAAoB;AAjJhG,EAAA,IAAA,EAAA;AAkJE,EAAA,MAAM,SAAA,GAAA,CAAY,EAAA,GAAA,OAAA,CAAQ,SAAA,KAAR,IAAA,GAAA,EAAA,GAAqB,mBAAA;AACvC,EAAA,OAAO,CAAC,MAAA,KAAW;AAnJrB,IAAA,IAAAA,GAAAA;AAoJI,IAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACrB,IAAA,MAAM,CAAA,GAAI,UAAA;AACV,IAAA,IAAI,CAAC,CAAA,CAAE,SAAA,EAAW,CAAA,CAAE,YAAY,EAAC;AACjC,IAAA,MAAM,MAAKA,GAAAA,GAAA,OAAA,CAAQ,SAAA,KAAR,IAAA,GAAAA,MAAqB,CAAA,CAAE,SAAA;AAClC,IAAA,EAAA,CAAG,IAAA,CAAK;AAAA,MACN,KAAA,EAAO,SAAA;AAAA,MACP,kBAAkB,MAAA,CAAO,YAAA;AAAA,MACzB,gBAAgB,MAAA,CAAO,UAAA;AAAA,MACvB,eAAe,MAAA,CAAO,SAAA;AAAA,MACtB,qBAAqB,MAAA,CAAO,eAAA;AAAA,MAC5B,kBAAA,EAAoB,OAAO,OAAA,CAAQ;AAAA,KACpC,CAAA;AAAA,EACH,CAAA;AACF","file":"index.js","sourcesContent":["import type { ExposureRecord } from '@fabricorg/experiments-web';\n\nexport type ExposureAdapter = (record: ExposureRecord) => void;\n\n/**\n * Snowplow self-describing exposure event.\n *\n * Schema: iglu:io.fabric.experiments/exposure/jsonschema/1-0-0\n * (host the schema in your Iglu repo to validate downstream).\n */\nexport interface SnowplowAdapterOptions {\n /** Tracker function: typically `(window as any).snowplow` or the explicit tracker. */\n tracker?: (...args: unknown[]) => void;\n /** Schema URI. Override if you publish a custom schema. */\n schema?: string;\n}\n\nexport function snowplowAdapter(options: SnowplowAdapterOptions = {}): ExposureAdapter {\n const schema = options.schema ?? 'iglu:io.fabric.experiments/exposure/jsonschema/1-0-0';\n return (record) => {\n const tracker =\n options.tracker ?? (globalThis as { snowplow?: (...args: unknown[]) => void }).snowplow;\n if (!tracker) return;\n tracker('trackSelfDescribingEvent', {\n event: {\n schema,\n data: {\n experimentId: record.experimentId,\n variantKey: record.variantKey,\n subjectId: record.subjectId,\n manifestVersion: record.manifestVersion,\n at: record.at,\n failure: record.failure,\n },\n },\n });\n };\n}\n\n/**\n * Google Analytics 4 (gtag) adapter.\n * Sends an `experiment_exposure` event with custom dimensions.\n */\nexport interface GaAdapterOptions {\n gtag?: (...args: unknown[]) => void;\n /** Override the event name. Default: `experiment_exposure`. */\n eventName?: string;\n}\n\nexport function gaAdapter(options: GaAdapterOptions = {}): ExposureAdapter {\n const eventName = options.eventName ?? 'experiment_exposure';\n return (record) => {\n const gtag = options.gtag ?? (globalThis as { gtag?: (...args: unknown[]) => void }).gtag;\n if (!gtag) return;\n gtag('event', eventName, {\n experiment_id: record.experimentId,\n variant_key: record.variantKey,\n manifest_version: record.manifestVersion,\n });\n };\n}\n\n/**\n * Generic GTM dataLayer adapter — pushes a single event GTM tags can listen for.\n * This is also the default tag-loader behavior.\n */\nexport interface DataLayerAdapterOptions {\n /** Override the dataLayer reference (tests). */\n dataLayer?: Array<Record<string, unknown>>;\n /** Override the event name. Default: `fx_exposure`. */\n eventName?: string;\n}\n\nexport function dataLayerAdapter(options: DataLayerAdapterOptions = {}): ExposureAdapter {\n const eventName = options.eventName ?? 'fx_exposure';\n return (record) => {\n const w = globalThis as { dataLayer?: Array<Record<string, unknown>> };\n if (!w.dataLayer) w.dataLayer = [];\n const dl = options.dataLayer ?? w.dataLayer;\n dl.push({\n event: eventName,\n fx_experiment_id: record.experimentId,\n fx_variant_key: record.variantKey,\n fx_subject_id: record.subjectId,\n fx_manifest_version: record.manifestVersion,\n });\n };\n}\n\n/**\n * Fan out a single exposure to multiple adapters. Each adapter is wrapped in\n * a try/catch so a third-party tracker error never breaks the chain.\n */\nexport function compose(...adapters: readonly ExposureAdapter[]): ExposureAdapter {\n return (record) => {\n for (const a of adapters) {\n try {\n a(record);\n } catch {\n /* swallow */\n }\n }\n };\n}\n\n// ---- Failure adapters (Mojito onRecipeFailure parity) ----------------------\n\n/**\n * Snowplow self-describing event for variant failures.\n *\n * Schema: iglu:io.fabric.experiments/recipe_failure/jsonschema/1-0-0\n * Fires once per (experimentId, variantKey, message) — useful for alarming\n * on variant-code crashes without cluttering the exposure stream.\n */\nexport interface SnowplowFailureAdapterOptions extends SnowplowAdapterOptions {\n schema?: string;\n}\n\nexport function snowplowFailureAdapter(\n options: SnowplowFailureAdapterOptions = {},\n): ExposureAdapter {\n const schema = options.schema ?? 'iglu:io.fabric.experiments/recipe_failure/jsonschema/1-0-0';\n return (record) => {\n if (!record.failure) return;\n const tracker =\n options.tracker ?? (globalThis as { snowplow?: (...args: unknown[]) => void }).snowplow;\n if (!tracker) return;\n tracker('trackSelfDescribingEvent', {\n event: {\n schema,\n data: {\n experimentId: record.experimentId,\n variantKey: record.variantKey,\n subjectId: record.subjectId,\n manifestVersion: record.manifestVersion,\n at: record.at,\n message: record.failure.message,\n stack: record.failure.stack,\n },\n },\n });\n };\n}\n\n/** dataLayer push for variant failures — pairs with the default exposure adapter. */\nexport function dataLayerFailureAdapter(options: DataLayerAdapterOptions = {}): ExposureAdapter {\n const eventName = options.eventName ?? 'fx_recipe_failure';\n return (record) => {\n if (!record.failure) return;\n const w = globalThis as { dataLayer?: Array<Record<string, unknown>> };\n if (!w.dataLayer) w.dataLayer = [];\n const dl = options.dataLayer ?? w.dataLayer;\n dl.push({\n event: eventName,\n fx_experiment_id: record.experimentId,\n fx_variant_key: record.variantKey,\n fx_subject_id: record.subjectId,\n fx_manifest_version: record.manifestVersion,\n fx_failure_message: record.failure.message,\n });\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":["_a"],"mappings":"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","file":"index.js","sourcesContent":["import type { ActivationFailureRecord, ExposureRecord } from '@fabricorg/experiments-web';\n\nexport type ExposureAdapter = (record: ExposureRecord) => void;\n\n/**\n * Snowplow self-describing exposure event.\n *\n * Schema: iglu:io.fabric.experiments/exposure/jsonschema/1-0-0\n * (host the schema in your Iglu repo to validate downstream).\n */\nexport interface SnowplowAdapterOptions {\n /** Tracker function: typically `(window as any).snowplow` or the explicit tracker. */\n tracker?: (...args: unknown[]) => void;\n /** Schema URI. Override if you publish a custom schema. */\n schema?: string;\n}\n\nexport function snowplowAdapter(options: SnowplowAdapterOptions = {}): ExposureAdapter {\n const schema = options.schema ?? 'iglu:io.fabric.experiments/exposure/jsonschema/1-0-0';\n return (record) => {\n const tracker =\n options.tracker ?? (globalThis as { snowplow?: (...args: unknown[]) => void }).snowplow;\n if (!tracker) return;\n tracker('trackSelfDescribingEvent', {\n event: {\n schema,\n data: {\n experimentId: record.experimentId,\n variantKey: record.variantKey,\n subjectId: record.subjectId,\n manifestVersion: record.manifestVersion,\n at: record.at,\n failure: record.failure,\n },\n },\n });\n };\n}\n\n/**\n * Google Analytics 4 (gtag) adapter.\n * Sends an `experiment_exposure` event with custom dimensions.\n */\nexport interface GaAdapterOptions {\n gtag?: (...args: unknown[]) => void;\n /** Override the event name. Default: `experiment_exposure`. */\n eventName?: string;\n}\n\nexport function gaAdapter(options: GaAdapterOptions = {}): ExposureAdapter {\n const eventName = options.eventName ?? 'experiment_exposure';\n return (record) => {\n const gtag = options.gtag ?? (globalThis as { gtag?: (...args: unknown[]) => void }).gtag;\n if (!gtag) return;\n gtag('event', eventName, {\n experiment_id: record.experimentId,\n variant_key: record.variantKey,\n manifest_version: record.manifestVersion,\n });\n };\n}\n\n/**\n * Generic GTM dataLayer adapter — pushes a single event GTM tags can listen for.\n * This is also the default tag-loader behavior.\n */\nexport interface DataLayerAdapterOptions {\n /** Override the dataLayer reference (tests). */\n dataLayer?: Array<Record<string, unknown>>;\n /** Override the event name. Default: `fx_exposure`. */\n eventName?: string;\n}\n\nexport function dataLayerAdapter(options: DataLayerAdapterOptions = {}): ExposureAdapter {\n const eventName = options.eventName ?? 'fx_exposure';\n return (record) => {\n const w = globalThis as { dataLayer?: Array<Record<string, unknown>> };\n if (!w.dataLayer) w.dataLayer = [];\n const dl = options.dataLayer ?? w.dataLayer;\n dl.push({\n event: eventName,\n fx_experiment_id: record.experimentId,\n fx_variant_key: record.variantKey,\n fx_subject_id: record.subjectId,\n fx_manifest_version: record.manifestVersion,\n });\n };\n}\n\n/**\n * Fan out a single exposure to multiple adapters. Each adapter is wrapped in\n * a try/catch so a third-party tracker error never breaks the chain.\n */\nexport function compose(...adapters: readonly ExposureAdapter[]): ExposureAdapter {\n return (record) => {\n for (const a of adapters) {\n try {\n a(record);\n } catch {\n /* swallow */\n }\n }\n };\n}\n\n// ---- Failure adapters (Mojito onRecipeFailure parity) ----------------------\n\n/**\n * Snowplow self-describing event for variant failures.\n *\n * Schema: iglu:io.fabric.experiments/recipe_failure/jsonschema/1-0-0\n * Fires once per (experimentId, variantKey, message) — useful for alarming\n * on variant-code crashes without cluttering the exposure stream.\n */\nexport interface SnowplowFailureAdapterOptions extends SnowplowAdapterOptions {\n schema?: string;\n}\n\nexport function snowplowFailureAdapter(\n options: SnowplowFailureAdapterOptions = {},\n): ExposureAdapter {\n const schema = options.schema ?? 'iglu:io.fabric.experiments/recipe_failure/jsonschema/1-0-0';\n return (record) => {\n if (!record.failure) return;\n const tracker =\n options.tracker ?? (globalThis as { snowplow?: (...args: unknown[]) => void }).snowplow;\n if (!tracker) return;\n tracker('trackSelfDescribingEvent', {\n event: {\n schema,\n data: {\n experimentId: record.experimentId,\n variantKey: record.variantKey,\n subjectId: record.subjectId,\n manifestVersion: record.manifestVersion,\n at: record.at,\n message: record.failure.message,\n stack: record.failure.stack,\n },\n },\n });\n };\n}\n\n/** dataLayer push for variant failures — pairs with the default exposure adapter. */\nexport function dataLayerFailureAdapter(options: DataLayerAdapterOptions = {}): ExposureAdapter {\n const eventName = options.eventName ?? 'fx_recipe_failure';\n return (record) => {\n if (!record.failure) return;\n const w = globalThis as { dataLayer?: Array<Record<string, unknown>> };\n if (!w.dataLayer) w.dataLayer = [];\n const dl = options.dataLayer ?? w.dataLayer;\n dl.push({\n event: eventName,\n fx_experiment_id: record.experimentId,\n fx_variant_key: record.variantKey,\n fx_subject_id: record.subjectId,\n fx_manifest_version: record.manifestVersion,\n fx_failure_message: record.failure.message,\n });\n };\n}\n\n// ---- Mojito storage-adapter bridge ----------------------------------------\n\n/** Minimal Mojito-shaped object passed to legacy storage-adapter callbacks. */\nexport interface MojitoCompatibleTestObject {\n options: { id: string; name: string };\n chosenRecipe: { id: string; name: string };\n subjectId: string;\n manifestVersion: number;\n fabric: ExposureRecord | ActivationFailureRecord;\n}\n\nexport interface MojitoStorageAdapter {\n onExposure?: (test: MojitoCompatibleTestObject) => void;\n onRecipeFailure?: (test: MojitoCompatibleTestObject, error?: string) => void;\n onVeilTimeout?: (test: MojitoCompatibleTestObject, ultimateRecipe: string) => void;\n}\n\nexport interface MojitoCompatibilityOptions {\n experimentNames?: Record<string, string>;\n variantNames?: Record<string, Record<string, string>>;\n}\n\nfunction mojitoTestObject(\n record: ExposureRecord | ActivationFailureRecord,\n options: MojitoCompatibilityOptions,\n): MojitoCompatibleTestObject {\n return {\n options: {\n id: record.experimentId,\n name: options.experimentNames?.[record.experimentId] ?? record.experimentId,\n },\n chosenRecipe: {\n id: record.variantKey,\n name: options.variantNames?.[record.experimentId]?.[record.variantKey] ?? record.variantKey,\n },\n subjectId: record.subjectId,\n manifestVersion: record.manifestVersion,\n fabric: record,\n };\n}\n\n/**\n * Reuse an existing Mojito `storageAdapter` while migrating delivery to\n * Fabric. Spread the returned hooks into `init()` or `window.__FX__`.\n */\nexport function mojitoCompatibilityAdapter(\n adapter: MojitoStorageAdapter,\n options: MojitoCompatibilityOptions = {},\n): {\n onExposure: ExposureAdapter;\n onRecipeFailure: ExposureAdapter;\n onActivationFailure: (record: ActivationFailureRecord) => void;\n} {\n return {\n onExposure(record) {\n // Failure records are delivered separately, matching Mojito's event split.\n if (!record.failure) adapter.onExposure?.(mojitoTestObject(record, options));\n },\n onRecipeFailure(record) {\n if (!record.failure) return;\n adapter.onRecipeFailure?.(mojitoTestObject(record, options), record.failure.message);\n },\n onActivationFailure(record) {\n adapter.onVeilTimeout?.(mojitoTestObject(record, options), record.variantKey);\n },\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fabricorg/experiments-web-adapters",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org",
6
6
  "access": "public"
@@ -26,11 +26,11 @@
26
26
  "clean": "rm -rf dist"
27
27
  },
28
28
  "dependencies": {
29
- "@fabricorg/experiments-web": "^0.2.0"
29
+ "@fabricorg/experiments-web": "^0.3.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "tsup": "^8.3.5",
33
33
  "typescript": "^5.8.3",
34
- "vitest": "^2.1.8"
34
+ "vitest": "^3.2.7"
35
35
  }
36
36
  }