@studio-vaai/js-tracking 0.1.3 → 0.2.1

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
@@ -1,7 +1,7 @@
1
1
  # @studio-vaai/js-tracking
2
2
 
3
- Typed analytics events for studio vaai, plus a beacon-based [Umami](https://umami.is)
4
- transport.
3
+ Typed analytics events for studio vaai, plus a [Umami](https://umami.is) transport
4
+ that posts to `/api/send` via keepalive `fetch`.
5
5
 
6
6
  ## Public surface
7
7
 
@@ -12,9 +12,11 @@ interface TrackingClient {
12
12
  ```
13
13
 
14
14
  Synchronous and fire-and-forget — the default transport dispatches via
15
- `navigator.sendBeacon` so events survive page unload and navigation. The
16
- returned `TrackResult` reflects whether the browser accepted the beacon (or
17
- the event was queued for later flush), not whether the server acknowledged it.
15
+ `fetch` with `keepalive: true` and `credentials: "omit"` so events survive
16
+ page unload and work against cross-origin Umami hosts that return
17
+ `Access-Control-Allow-Origin: *`. The returned `TrackResult` reflects whether
18
+ the request was queued (or the event was buffered for later flush), not
19
+ whether the server acknowledged it.
18
20
 
19
21
  Event-specific by design: every event must appear in `TrackingEvent` (see
20
22
  [`src/events.ts`](src/events.ts)). Until the first variant lands, `trackEvent`
@@ -33,7 +35,7 @@ import { createFetchUmamiTrackingClient } from "@studio-vaai/js-tracking";
33
35
 
34
36
  // Static config: websiteId known at construction.
35
37
  const tracking = createFetchUmamiTrackingClient({
36
- sdkVersion: "@studio-vaai/react-components@0.1.3",
38
+ sdkVersion: "@studio-vaai/react-components@0.2.1",
37
39
  websiteId: "00000000-0000-0000-0000-000000000000",
38
40
  // baseUrl defaults to https://a.studio-vaai.com
39
41
  });
@@ -51,7 +53,7 @@ in order on success.
51
53
 
52
54
  ```ts
53
55
  const tracking = createFetchUmamiTrackingClient({
54
- sdkVersion: "@studio-vaai/react-components@0.1.3",
56
+ sdkVersion: "@studio-vaai/react-components@0.2.1",
55
57
  resolveConfig: async () => {
56
58
  const r = await client.tracking.getTracking({});
57
59
  if (!r.ok) throw new ApiFailureError(r.error);
package/dist/base.d.ts CHANGED
@@ -16,7 +16,7 @@ export interface TrackFailure {
16
16
  * branch product behaviour on `ok`, but may surface a warning in dev.
17
17
  *
18
18
  * Returned synchronously from {@link TrackingClient.trackEvent} — reflects
19
- * whether the event was queued for delivery (via the Beacon API or a buffer
19
+ * whether the event was queued for delivery (via keepalive fetch or a buffer
20
20
  * waiting on a lazy resolver), not whether the server received it.
21
21
  */
22
22
  export type TrackResult = TrackSuccess | TrackFailure;
package/dist/client.d.ts CHANGED
@@ -12,8 +12,9 @@ export type TrackingClientConfig = Record<never, never>;
12
12
  export interface TrackingClient {
13
13
  /**
14
14
  * Send a single typed event. Synchronous and fire-and-forget — implementations
15
- * dispatch via the page-unload-safe Beacon API. Returns a {@link TrackResult}
16
- * reflecting whether the event was successfully queued for delivery, NOT
15
+ * dispatch via fire-and-forget `fetch` with `keepalive: true`. Returns a
16
+ * {@link TrackResult} reflecting whether the event was successfully queued
17
+ * for delivery, NOT
17
18
  * whether the server acknowledged it. Never throws — analytics must not
18
19
  * break the host app.
19
20
  *
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD,sBAAsB;AACtB,eAAO,MAAM,cAAc,EAAG,0BAAmC,CAAC;AAElE,6CAA6C;AAC7C,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAExD;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;;;;;;OAUG;IACH,UAAU,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,WAAW,CAAC;CACvE;AAED,uFAAuF;AACvF,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,oBAAoB,GAAG,cAAc,CAElF"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD,sBAAsB;AACtB,eAAO,MAAM,cAAc,EAAG,0BAAmC,CAAC;AAElE,6CAA6C;AAC7C,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAExD;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,WAAW,CAAC;CACvE;AAED,uFAAuF;AACvF,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,oBAAoB,GAAG,cAAc,CAElF"}
package/dist/events.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { ImageFlowSource } from "./image-flow-source.js";
1
2
  import type { Step } from "./steps.js";
2
3
  /**
3
4
  * Shape every tracked event must satisfy. The `name` field is the
@@ -45,7 +46,7 @@ interface EntrypointClickedEvent extends TrackingEventBase {
45
46
  interface IntroOpenedEvent extends TrackingEventBase {
46
47
  readonly name: "intro-opened";
47
48
  readonly data: CommonData & {
48
- /** Typically `entry` | `image-rejection` | `image-record`. */
49
+ /** `entry` when opened via entrypoint on the user's first sheet open; machine re-entries use the prior step. */
49
50
  readonly source: Step;
50
51
  };
51
52
  }
@@ -56,20 +57,26 @@ interface ConsentGrantedEvent extends TrackingEventBase {
56
57
  interface ImageRecordInitiatedEvent extends TrackingEventBase {
57
58
  readonly name: "image-record-initiated";
58
59
  readonly data: CommonData & {
59
- /** Typically `intro` | `height`. */
60
- readonly source: Step;
60
+ readonly source: ImageFlowSource;
61
+ };
62
+ }
63
+ interface ImageRecordAbortedEvent extends TrackingEventBase {
64
+ readonly name: "image-record-aborted";
65
+ readonly data: CommonData & {
66
+ readonly source: ImageFlowSource;
61
67
  };
62
68
  }
63
69
  interface ImageUploadInitiatedEvent extends TrackingEventBase {
64
70
  readonly name: "image-upload-initiated";
65
71
  readonly data: CommonData & {
66
- /** Typically `intro` | `height`. */
67
- readonly source: Step;
72
+ readonly source: ImageFlowSource;
68
73
  };
69
74
  }
70
75
  interface ImageUploadAbortedEvent extends TrackingEventBase {
71
76
  readonly name: "image-upload-aborted";
72
- readonly data: CommonData;
77
+ readonly data: CommonData & {
78
+ readonly source: ImageFlowSource;
79
+ };
73
80
  }
74
81
  interface ImageUploadedEvent extends TrackingEventBase {
75
82
  readonly name: "image-uploaded";
@@ -84,11 +91,19 @@ interface HeightEnteredEvent extends TrackingEventBase {
84
91
  readonly source: Step;
85
92
  };
86
93
  }
94
+ /** How the user returned to variant selection from the try-on result screen. */
95
+ export type VariantSelectionVia = "back" | "go-to-product-overview";
87
96
  interface VariantSelectionInitiatedEvent extends TrackingEventBase {
88
97
  readonly name: "variant-selection-initiated";
89
98
  readonly data: CommonData & {
90
99
  /** Typically `height` | `try-on`. */
91
100
  readonly source: Step;
101
+ /**
102
+ * Present when re-entering variant selection from the try-on result screen.
103
+ * `back` = header back; `go-to-product-overview` = secondary CTA
104
+ * (`tryOnView.goToProductOverview`).
105
+ */
106
+ readonly via?: VariantSelectionVia;
92
107
  };
93
108
  }
94
109
  /**
@@ -122,6 +137,6 @@ interface ViewClosedEvent extends TrackingEventBase {
122
137
  * declaring a variant interface above and appending it to the union — call
123
138
  * sites get full autocomplete + type-checking on `name` and `data`.
124
139
  */
125
- export type TrackingEvent = EntrypointImpressionEvent | EntrypointClickedEvent | IntroOpenedEvent | ConsentGrantedEvent | ImageRecordInitiatedEvent | ImageUploadInitiatedEvent | ImageUploadAbortedEvent | ImageUploadedEvent | HeightEnteredEvent | VariantSelectionInitiatedEvent | TryOnInitiatedEvent | CartItemAddedEvent | OrderPlacedEvent | ViewClosedEvent;
140
+ export type TrackingEvent = EntrypointImpressionEvent | EntrypointClickedEvent | IntroOpenedEvent | ConsentGrantedEvent | ImageRecordInitiatedEvent | ImageRecordAbortedEvent | ImageUploadInitiatedEvent | ImageUploadAbortedEvent | ImageUploadedEvent | HeightEnteredEvent | VariantSelectionInitiatedEvent | TryOnInitiatedEvent | CartItemAddedEvent | OrderPlacedEvent | ViewClosedEvent;
126
141
  export {};
127
142
  //# sourceMappingURL=events.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Where the user started a gallery upload or in-browser camera capture.
3
+ * Distinct from {@link Step} — these are intentional entry points, not
4
+ * derived machine-state snapshots.
5
+ */
6
+ export type ImageFlowSource = "intro" | "variant-selection" | "image-rejection" | "height";
7
+ //# sourceMappingURL=image-flow-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-flow-source.d.ts","sourceRoot":"","sources":["../src/image-flow-source.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,mBAAmB,GAAG,iBAAiB,GAAG,QAAQ,CAAC"}
@@ -9,12 +9,6 @@ export interface ResolvedUmamiConfig {
9
9
  /** Optional override; defaults to {@link DEFAULT_UMAMI_BASE_URL} when omitted. */
10
10
  baseUrl?: string;
11
11
  }
12
- /**
13
- * Sync sender used by the transport. The default delegates to
14
- * `navigator.sendBeacon` — the page-unload-safe analytics primitive. Tests
15
- * inject their own recorder.
16
- */
17
- export type SendBeaconFn = (url: string, data: BodyInit) => boolean;
18
12
  export interface FetchUmamiTrackingClientConfig extends TrackingClientConfig {
19
13
  /**
20
14
  * Stamped on every event as the `sdk-version` field. Higher SDK layers
@@ -36,15 +30,14 @@ export interface FetchUmamiTrackingClientConfig extends TrackingClientConfig {
36
30
  * the promise settles are buffered internally and flushed (in order) the
37
31
  * moment the resolver returns. Buffered events have already returned
38
32
  * `{ ok: true }` to the caller — if the eventual flush fails (resolver
39
- * rejected or sendBeacon refused) the caller is not notified.
33
+ * rejected or the request could not be queued) the caller is not notified.
40
34
  */
41
35
  resolveConfig?: () => Promise<ResolvedUmamiConfig>;
42
36
  /**
43
- * Override the beacon sender. Defaults to `navigator.sendBeacon` bound to
44
- * `navigator` when available; falls back to a no-op that reports `false`
45
- * (so the call site can surface `{ ok: false }` in SSR / older browsers).
37
+ * Override `fetch`. Defaults to `globalThis.fetch` bound to `globalThis` so
38
+ * the native browser implementation doesn't trip on `this`-binding rules.
46
39
  */
47
- sendBeacon?: SendBeaconFn;
40
+ fetch?: typeof fetch;
48
41
  /**
49
42
  * Ambient context applied to every payload, before per-call overrides. Useful
50
43
  * for SSR-known fields or to pin a hostname different from `window.location`.
@@ -52,10 +45,12 @@ export interface FetchUmamiTrackingClientConfig extends TrackingClientConfig {
52
45
  defaultContext?: EventContext;
53
46
  }
54
47
  /**
55
- * Umami `/api/send` transport for {@link TrackingClient}. Dispatches via the
56
- * Beacon API so events survive page unload and navigation; the return value
57
- * reports whether the browser accepted the beacon, not whether the server
58
- * acknowledged it. Errors are never thrown — analytics cannot break the host app.
48
+ * Umami `/api/send` transport for {@link TrackingClient}. Dispatches via
49
+ * fire-and-forget `fetch` with `keepalive: true` so events survive page unload,
50
+ * and `credentials: "omit"` so cross-origin Umami hosts may use
51
+ * `Access-Control-Allow-Origin: *`. The return value reports whether the
52
+ * request was queued, not whether the server acknowledged it. Errors are never
53
+ * thrown — analytics cannot break the host app.
59
54
  *
60
55
  * Supports two configuration modes:
61
56
  * - **Static**: pass `websiteId` (and optionally `baseUrl`) at construction.
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-umami-tracking-client.d.ts","sourceRoot":"","sources":["../../src/impl/fetch-umami-tracking-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAyC,MAAM,YAAY,CAAC;AACtF,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAGzE,+CAA+C;AAC/C,eAAO,MAAM,sBAAsB,EAAG,2BAAoC,CAAC;AAE3E,uGAAuG;AACvG,MAAM,WAAW,mBAAmB;IAClC,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,kFAAkF;IAClF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,KAAK,OAAO,CAAC;AAEpE,MAAM,WAAW,8BAA+B,SAAQ,oBAAoB;IAC1E;;;;;OAKG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+GAA+G;IAC/G,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACnD;;;;OAIG;IACH,UAAU,CAAC,EAAE,YAAY,CAAC;IAC1B;;;OAGG;IACH,cAAc,CAAC,EAAE,YAAY,CAAC;CAC/B;AAkHD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,8BAA8B,GACrC,cAAc,CAgJhB"}
1
+ {"version":3,"file":"fetch-umami-tracking-client.d.ts","sourceRoot":"","sources":["../../src/impl/fetch-umami-tracking-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAyC,MAAM,YAAY,CAAC;AACtF,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAGzE,+CAA+C;AAC/C,eAAO,MAAM,sBAAsB,EAAG,2BAAoC,CAAC;AAE3E,uGAAuG;AACvG,MAAM,WAAW,mBAAmB;IAClC,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,kFAAkF;IAClF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,8BAA+B,SAAQ,oBAAoB;IAC1E;;;;;OAKG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+GAA+G;IAC/G,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACnD;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB;;;OAGG;IACH,cAAc,CAAC,EAAE,YAAY,CAAC;CAC/B;AAyHD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,8BAA8B,GACrC,cAAc,CAwJhB"}
@@ -1,6 +1,13 @@
1
1
  //#region src/impl/fetch-umami-tracking-client.ts
2
2
  /** Default Umami base URL (int/prod Umami). */
3
3
  var DEFAULT_UMAMI_BASE_URL = "https://a.studio-vaai.com";
4
+ var UMAMI_FETCH_INIT = {
5
+ method: "POST",
6
+ headers: { "Content-Type": "application/json" },
7
+ credentials: "omit",
8
+ keepalive: true,
9
+ mode: "cors"
10
+ };
4
11
  function deriveBrowserContext() {
5
12
  const ctx = {};
6
13
  if (typeof globalThis === "undefined") return ctx;
@@ -53,17 +60,17 @@ function bakeState(websiteId, baseUrl) {
53
60
  websiteId
54
61
  };
55
62
  }
56
- function defaultSendBeacon() {
57
- return (url, data) => {
58
- if (typeof navigator === "undefined" || typeof navigator.sendBeacon !== "function") return false;
59
- return navigator.sendBeacon.bind(navigator)(url, data);
60
- };
63
+ function defaultFetchImpl() {
64
+ if (typeof globalThis.fetch !== "function") return null;
65
+ return globalThis.fetch.bind(globalThis);
61
66
  }
62
67
  /**
63
- * Umami `/api/send` transport for {@link TrackingClient}. Dispatches via the
64
- * Beacon API so events survive page unload and navigation; the return value
65
- * reports whether the browser accepted the beacon, not whether the server
66
- * acknowledged it. Errors are never thrown — analytics cannot break the host app.
68
+ * Umami `/api/send` transport for {@link TrackingClient}. Dispatches via
69
+ * fire-and-forget `fetch` with `keepalive: true` so events survive page unload,
70
+ * and `credentials: "omit"` so cross-origin Umami hosts may use
71
+ * `Access-Control-Allow-Origin: *`. The return value reports whether the
72
+ * request was queued, not whether the server acknowledged it. Errors are never
73
+ * thrown — analytics cannot break the host app.
67
74
  *
68
75
  * Supports two configuration modes:
69
76
  * - **Static**: pass `websiteId` (and optionally `baseUrl`) at construction.
@@ -74,7 +81,7 @@ function defaultSendBeacon() {
74
81
  * the config is available.
75
82
  */
76
83
  function createFetchUmamiTrackingClient(config) {
77
- const sendBeacon = config.sendBeacon ?? defaultSendBeacon();
84
+ const fetchImpl = config.fetch ?? defaultFetchImpl();
78
85
  let resolved = null;
79
86
  let resolverError = null;
80
87
  const pending = [];
@@ -104,20 +111,35 @@ function createFetchUmamiTrackingClient(config) {
104
111
  }
105
112
  })();
106
113
  }
107
- function dispatchBeacon(state, body) {
108
- let blob;
114
+ function dispatchEvent(state, body) {
115
+ let json;
109
116
  try {
110
- blob = new Blob([JSON.stringify(body)], { type: "application/json" });
117
+ json = JSON.stringify(body);
111
118
  } catch (error) {
112
119
  return {
113
120
  ok: false,
114
121
  error: networkError("Failed to serialise event", error)
115
122
  };
116
123
  }
117
- if (!sendBeacon(state.endpoint, blob)) return {
124
+ if (fetchImpl === null) return {
118
125
  ok: false,
119
- error: networkError("navigator.sendBeacon refused the event (quota exceeded, payload too large, or unavailable)")
126
+ error: networkError("fetch is not available in this environment")
120
127
  };
128
+ try {
129
+ (async () => {
130
+ try {
131
+ await fetchImpl(state.endpoint, {
132
+ ...UMAMI_FETCH_INIT,
133
+ body: json
134
+ });
135
+ } catch {}
136
+ })();
137
+ } catch (error) {
138
+ return {
139
+ ok: false,
140
+ error: networkError("Failed to queue Umami request", error)
141
+ };
142
+ }
121
143
  return { ok: true };
122
144
  }
123
145
  function track(state, name, data, contextOverrides) {
@@ -125,7 +147,7 @@ function createFetchUmamiTrackingClient(config) {
125
147
  applyContext(payload, mergeContext(deriveBrowserContext(), config.defaultContext, contextOverrides));
126
148
  if (typeof name !== "undefined") payload.name = name;
127
149
  if (typeof data !== "undefined") payload.data = { ...data };
128
- return dispatchBeacon(state, {
150
+ return dispatchEvent(state, {
129
151
  type: "event",
130
152
  payload
131
153
  });
package/dist/index.d.ts CHANGED
@@ -2,7 +2,8 @@ export type { EventContext, TrackError, TrackErrorKind, TrackFailure, TrackOptio
2
2
  export type { TrackingClient, TrackingClientConfig } from "./client.js";
3
3
  export { createTrackingClient, SDK_PACKAGE_ID } from "./client.js";
4
4
  export { TrackingClientNotImplementedError } from "./errors.js";
5
- export type { TrackingEvent, TrackingEventBase } from "./events.js";
5
+ export type { TrackingEvent, TrackingEventBase, VariantSelectionVia } from "./events.js";
6
+ export type { ImageFlowSource } from "./image-flow-source.js";
6
7
  export type { Step } from "./steps.js";
7
8
  export type { FetchUmamiTrackingClientConfig, ResolvedUmamiConfig, } from "./impl/fetch-umami-tracking-client.js";
8
9
  export { createFetchUmamiTrackingClient, DEFAULT_UMAMI_BASE_URL, } from "./impl/fetch-umami-tracking-client.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,YAAY,EACZ,UAAU,EACV,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,YAAY,GACb,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,iCAAiC,EAAE,MAAM,aAAa,CAAC;AAChE,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACpE,YAAY,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,YAAY,EACV,8BAA8B,EAC9B,mBAAmB,GACpB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACL,8BAA8B,EAC9B,sBAAsB,GACvB,MAAM,uCAAuC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,YAAY,EACZ,UAAU,EACV,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,YAAY,GACb,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,iCAAiC,EAAE,MAAM,aAAa,CAAC;AAChE,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACzF,YAAY,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,YAAY,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,YAAY,EACV,8BAA8B,EAC9B,mBAAmB,GACpB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACL,8BAA8B,EAC9B,sBAAsB,GACvB,MAAM,uCAAuC,CAAC"}
package/dist/steps.d.ts CHANGED
@@ -7,5 +7,5 @@
7
7
  * from machine state to {@link Step} at the event-emit site. Extend the union
8
8
  * here when a new flow step needs to appear in analytics.
9
9
  */
10
- export type Step = "entry" | "intro" | "consent" | "image-record" | "image-upload" | "image-rejection" | "height" | "variant-selection" | "try-on" | "cart" | "order";
10
+ export type Step = "entry" | "intro" | "image-record" | "image-upload" | "image-rejection" | "height" | "variant-selection" | "try-on";
11
11
  //# sourceMappingURL=steps.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"steps.d.ts","sourceRoot":"","sources":["../src/steps.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,MAAM,IAAI,GACZ,OAAO,GACP,OAAO,GACP,SAAS,GACT,cAAc,GACd,cAAc,GACd,iBAAiB,GACjB,QAAQ,GACR,mBAAmB,GACnB,QAAQ,GACR,MAAM,GACN,OAAO,CAAC"}
1
+ {"version":3,"file":"steps.d.ts","sourceRoot":"","sources":["../src/steps.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,MAAM,IAAI,GACZ,OAAO,GACP,OAAO,GACP,cAAc,GACd,cAAc,GACd,iBAAiB,GACjB,QAAQ,GACR,mBAAmB,GACnB,QAAQ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@studio-vaai/js-tracking",
3
- "version": "0.1.3",
3
+ "version": "0.2.1",
4
4
  "description": "Typed analytics events for studio vaai, plus a fetch-based Umami transport.",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -16,13 +16,13 @@
16
16
  "publishConfig": {
17
17
  "access": "public"
18
18
  },
19
+ "devDependencies": {
20
+ "vite": "8.0.5"
21
+ },
19
22
  "scripts": {
20
23
  "build": "vite build --config vite.lib.config.ts && rm -f tsconfig.tsbuildinfo && tsgo --emitDeclarationOnly",
21
24
  "clean": "rm -rf dist tsconfig.tsbuildinfo",
22
25
  "test": "vitest run --config ../../vitest.config.ts",
23
26
  "test:watch": "vitest --config ../../vitest.config.ts"
24
- },
25
- "devDependencies": {
26
- "vite": "8.0.5"
27
27
  }
28
- }
28
+ }