@01.software/sdk 0.13.0 → 0.14.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/dist/index.cjs CHANGED
@@ -60,6 +60,7 @@ __export(src_exports, {
60
60
  buildProductListingProjection: () => buildProductListingProjection,
61
61
  buildProductOptionMatrix: () => buildProductOptionMatrix,
62
62
  collectionKeys: () => collectionKeys,
63
+ createAnalytics: () => createAnalytics,
63
64
  createAuthError: () => createAuthError,
64
65
  createClient: () => createClient,
65
66
  createConflictError: () => createConflictError,
@@ -3126,4 +3127,174 @@ function getVideoStreamUrl(playbackId) {
3126
3127
  function getVideoMp4Url(playbackId, resolution = "high") {
3127
3128
  return `${MUX_STREAM_BASE}/${playbackId}/${resolution}.mp4`;
3128
3129
  }
3130
+
3131
+ // src/analytics.ts
3132
+ function createAnalytics(config) {
3133
+ if (typeof window === "undefined") {
3134
+ return { pageview() {
3135
+ }, track() {
3136
+ }, destroy() {
3137
+ } };
3138
+ }
3139
+ const endpoint = config.endpoint ?? `${resolveApiUrl()}/api/analytics/collect`;
3140
+ const respectDnt = config.respectDnt !== false;
3141
+ function isDntActive() {
3142
+ if (!respectDnt) return false;
3143
+ const nav = navigator;
3144
+ return nav.doNotTrack === "1" || nav.globalPrivacyControl === true;
3145
+ }
3146
+ let lastPath = null;
3147
+ let lastAt = 0;
3148
+ const autoTrack = config.autoTrack !== false;
3149
+ const originalPushState = history.pushState;
3150
+ const originalReplaceState = history.replaceState;
3151
+ let destroyed = false;
3152
+ function newEventId() {
3153
+ return typeof crypto !== "undefined" && typeof crypto.randomUUID === "function" ? crypto.randomUUID() : String(Date.now()) + String(Math.random());
3154
+ }
3155
+ function sendBeaconOrFetch(body) {
3156
+ try {
3157
+ if (typeof navigator.sendBeacon === "function") {
3158
+ const blob = new Blob([body], { type: "text/plain" });
3159
+ const sent = navigator.sendBeacon(endpoint, blob);
3160
+ if (sent) return;
3161
+ }
3162
+ fetch(endpoint, {
3163
+ method: "POST",
3164
+ keepalive: true,
3165
+ headers: { "Content-Type": "application/json" },
3166
+ body
3167
+ }).catch(() => {
3168
+ });
3169
+ } catch {
3170
+ }
3171
+ }
3172
+ function sendPageview(pathname) {
3173
+ if (isDntActive()) return;
3174
+ const doc = document;
3175
+ if (doc.prerendering === true || document.visibilityState === "prerender") return;
3176
+ const now = Date.now();
3177
+ if (pathname === lastPath && now - lastAt < 500) return;
3178
+ lastPath = pathname;
3179
+ lastAt = now;
3180
+ const body = JSON.stringify({
3181
+ publishableKey: config.publishableKey,
3182
+ pathname,
3183
+ referrer: document.referrer || "",
3184
+ eventId: newEventId()
3185
+ });
3186
+ sendBeaconOrFetch(body);
3187
+ }
3188
+ function trackCurrentPath() {
3189
+ if (destroyed) return;
3190
+ sendPageview(location.pathname);
3191
+ }
3192
+ function patchedPushState(data, unused, url) {
3193
+ originalPushState.apply(this, [data, unused, url]);
3194
+ if (!destroyed) setTimeout(trackCurrentPath, 0);
3195
+ }
3196
+ function patchedReplaceState(data, unused, url) {
3197
+ originalReplaceState.apply(this, [data, unused, url]);
3198
+ if (!destroyed) setTimeout(trackCurrentPath, 0);
3199
+ }
3200
+ if (autoTrack) {
3201
+ history.pushState = patchedPushState;
3202
+ history.replaceState = patchedReplaceState;
3203
+ window.addEventListener("popstate", trackCurrentPath);
3204
+ if (document.readyState === "complete") {
3205
+ trackCurrentPath();
3206
+ } else {
3207
+ window.addEventListener("load", trackCurrentPath, { once: true });
3208
+ }
3209
+ }
3210
+ const isProduction = (() => {
3211
+ try {
3212
+ const hostname = location.hostname;
3213
+ return hostname !== "localhost" && hostname !== "127.0.0.1" && !hostname.endsWith(".local");
3214
+ } catch {
3215
+ return true;
3216
+ }
3217
+ })();
3218
+ const warnedReasons = /* @__PURE__ */ new Set();
3219
+ function devWarn(name, reason) {
3220
+ if (isProduction) return;
3221
+ if (warnedReasons.has(reason)) return;
3222
+ warnedReasons.add(reason);
3223
+ console.warn(`[01 analytics] dropped event ${name}: ${reason}`);
3224
+ }
3225
+ const EVENT_NAME_RE = /^[a-zA-Z][a-zA-Z0-9_:-]{0,49}$/;
3226
+ const RESERVED_PREFIXES = ["__", "_pv_"];
3227
+ function validateEventName(name) {
3228
+ if (!name || typeof name !== "string") return "name-empty";
3229
+ for (const prefix of RESERVED_PREFIXES) {
3230
+ if (name.startsWith(prefix)) return "name-reserved";
3231
+ }
3232
+ if (!EVENT_NAME_RE.test(name)) return "name-regex";
3233
+ return null;
3234
+ }
3235
+ const PROP_KEY_RE = /^[a-zA-Z_][a-zA-Z0-9_]{0,31}$/;
3236
+ function validateEventProps(props) {
3237
+ if (props === void 0 || props === null) return null;
3238
+ if (typeof props !== "object" || Array.isArray(props)) return "props-value-type";
3239
+ const keys = Object.keys(props);
3240
+ if (keys.length > 10) return "props-too-many-keys";
3241
+ for (const k of keys) {
3242
+ const v = props[k];
3243
+ if (!PROP_KEY_RE.test(k)) return "props-key-regex";
3244
+ if (typeof v === "string") {
3245
+ if (v.length > 80) return "props-value-too-long";
3246
+ } else if (typeof v === "number") {
3247
+ if (!isFinite(v)) return "props-value-not-finite";
3248
+ } else if (typeof v === "boolean") {
3249
+ } else {
3250
+ return "props-value-type";
3251
+ }
3252
+ }
3253
+ return null;
3254
+ }
3255
+ return {
3256
+ pageview(path) {
3257
+ if (destroyed) return;
3258
+ sendPageview(path ?? location.pathname);
3259
+ },
3260
+ track(name, props) {
3261
+ if (destroyed) return;
3262
+ if (isDntActive()) return;
3263
+ const doc = document;
3264
+ if (doc.prerendering === true || document.visibilityState === "prerender") return;
3265
+ const nameErr = validateEventName(name);
3266
+ if (nameErr) {
3267
+ devWarn(name, nameErr);
3268
+ return;
3269
+ }
3270
+ if (props !== void 0) {
3271
+ const propsErr = validateEventProps(props);
3272
+ if (propsErr) {
3273
+ devWarn(name, propsErr);
3274
+ return;
3275
+ }
3276
+ }
3277
+ const body = JSON.stringify({
3278
+ publishableKey: config.publishableKey,
3279
+ pathname: location.pathname,
3280
+ referrer: document.referrer || "",
3281
+ eventId: newEventId(),
3282
+ eventName: name,
3283
+ eventProps: props
3284
+ });
3285
+ sendBeaconOrFetch(body);
3286
+ },
3287
+ destroy() {
3288
+ if (destroyed) return;
3289
+ destroyed = true;
3290
+ if (autoTrack) {
3291
+ history.pushState = originalPushState;
3292
+ history.replaceState = originalReplaceState;
3293
+ window.removeEventListener("popstate", trackCurrentPath);
3294
+ }
3295
+ lastPath = null;
3296
+ lastAt = 0;
3297
+ }
3298
+ };
3299
+ }
3129
3300
  //# sourceMappingURL=index.cjs.map