@mazyos/lp-tracker 0.1.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.
Files changed (153) hide show
  1. package/AGENTS.md +71 -0
  2. package/LICENSE +16 -0
  3. package/README.md +208 -0
  4. package/SKILL.md +71 -0
  5. package/dist/attribution.d.ts +16 -0
  6. package/dist/attribution.d.ts.map +1 -0
  7. package/dist/attribution.js +77 -0
  8. package/dist/attribution.js.map +1 -0
  9. package/dist/checkout/profiles.d.ts +18 -0
  10. package/dist/checkout/profiles.d.ts.map +1 -0
  11. package/dist/checkout/profiles.js +89 -0
  12. package/dist/checkout/profiles.js.map +1 -0
  13. package/dist/checkout/resolve.d.ts +16 -0
  14. package/dist/checkout/resolve.d.ts.map +1 -0
  15. package/dist/checkout/resolve.js +95 -0
  16. package/dist/checkout/resolve.js.map +1 -0
  17. package/dist/checkout.d.ts +3 -0
  18. package/dist/checkout.d.ts.map +1 -0
  19. package/dist/checkout.js +3 -0
  20. package/dist/checkout.js.map +1 -0
  21. package/dist/cli.d.ts +3 -0
  22. package/dist/cli.d.ts.map +1 -0
  23. package/dist/cli.js +78 -0
  24. package/dist/cli.js.map +1 -0
  25. package/dist/client/browser-attribution.d.ts +9 -0
  26. package/dist/client/browser-attribution.d.ts.map +1 -0
  27. package/dist/client/browser-attribution.js +116 -0
  28. package/dist/client/browser-attribution.js.map +1 -0
  29. package/dist/client/delegated.d.ts +6 -0
  30. package/dist/client/delegated.d.ts.map +1 -0
  31. package/dist/client/delegated.js +139 -0
  32. package/dist/client/delegated.js.map +1 -0
  33. package/dist/client/engagement-tracking.d.ts +11 -0
  34. package/dist/client/engagement-tracking.d.ts.map +1 -0
  35. package/dist/client/engagement-tracking.js +138 -0
  36. package/dist/client/engagement-tracking.js.map +1 -0
  37. package/dist/client/events.d.ts +43 -0
  38. package/dist/client/events.d.ts.map +1 -0
  39. package/dist/client/events.js +223 -0
  40. package/dist/client/events.js.map +1 -0
  41. package/dist/client/meta-pixel.d.ts +33 -0
  42. package/dist/client/meta-pixel.d.ts.map +1 -0
  43. package/dist/client/meta-pixel.js +143 -0
  44. package/dist/client/meta-pixel.js.map +1 -0
  45. package/dist/client/provider.d.ts +4 -0
  46. package/dist/client/provider.d.ts.map +1 -0
  47. package/dist/client/provider.js +113 -0
  48. package/dist/client/provider.js.map +1 -0
  49. package/dist/client/public-api.d.ts +7 -0
  50. package/dist/client/public-api.d.ts.map +1 -0
  51. package/dist/client/public-api.js +74 -0
  52. package/dist/client/public-api.js.map +1 -0
  53. package/dist/client/retry-queue.d.ts +20 -0
  54. package/dist/client/retry-queue.d.ts.map +1 -0
  55. package/dist/client/retry-queue.js +165 -0
  56. package/dist/client/retry-queue.js.map +1 -0
  57. package/dist/client/runtime.d.ts +81 -0
  58. package/dist/client/runtime.d.ts.map +1 -0
  59. package/dist/client/runtime.js +301 -0
  60. package/dist/client/runtime.js.map +1 -0
  61. package/dist/client/spa-tracking.d.ts +3 -0
  62. package/dist/client/spa-tracking.d.ts.map +1 -0
  63. package/dist/client/spa-tracking.js +54 -0
  64. package/dist/client/spa-tracking.js.map +1 -0
  65. package/dist/client/transport.d.ts +14 -0
  66. package/dist/client/transport.d.ts.map +1 -0
  67. package/dist/client/transport.js +54 -0
  68. package/dist/client/transport.js.map +1 -0
  69. package/dist/client/view-tracking.d.ts +3 -0
  70. package/dist/client/view-tracking.d.ts.map +1 -0
  71. package/dist/client/view-tracking.js +71 -0
  72. package/dist/client/view-tracking.js.map +1 -0
  73. package/dist/doctor/format.d.ts +3 -0
  74. package/dist/doctor/format.d.ts.map +1 -0
  75. package/dist/doctor/format.js +18 -0
  76. package/dist/doctor/format.js.map +1 -0
  77. package/dist/doctor/remote-checks.d.ts +3 -0
  78. package/dist/doctor/remote-checks.d.ts.map +1 -0
  79. package/dist/doctor/remote-checks.js +132 -0
  80. package/dist/doctor/remote-checks.js.map +1 -0
  81. package/dist/doctor/run.d.ts +3 -0
  82. package/dist/doctor/run.d.ts.map +1 -0
  83. package/dist/doctor/run.js +18 -0
  84. package/dist/doctor/run.js.map +1 -0
  85. package/dist/doctor/scan.d.ts +2 -0
  86. package/dist/doctor/scan.d.ts.map +1 -0
  87. package/dist/doctor/scan.js +70 -0
  88. package/dist/doctor/scan.js.map +1 -0
  89. package/dist/doctor/static-checks.d.ts +5 -0
  90. package/dist/doctor/static-checks.d.ts.map +1 -0
  91. package/dist/doctor/static-checks.js +130 -0
  92. package/dist/doctor/static-checks.js.map +1 -0
  93. package/dist/doctor/types.d.ts +20 -0
  94. package/dist/doctor/types.d.ts.map +1 -0
  95. package/dist/doctor/types.js +2 -0
  96. package/dist/doctor/types.js.map +1 -0
  97. package/dist/handler/body.d.ts +7 -0
  98. package/dist/handler/body.d.ts.map +1 -0
  99. package/dist/handler/body.js +67 -0
  100. package/dist/handler/body.js.map +1 -0
  101. package/dist/handler/create.d.ts +16 -0
  102. package/dist/handler/create.d.ts.map +1 -0
  103. package/dist/handler/create.js +69 -0
  104. package/dist/handler/create.js.map +1 -0
  105. package/dist/handler/forward.d.ts +13 -0
  106. package/dist/handler/forward.d.ts.map +1 -0
  107. package/dist/handler/forward.js +65 -0
  108. package/dist/handler/forward.js.map +1 -0
  109. package/dist/handler/health.d.ts +7 -0
  110. package/dist/handler/health.d.ts.map +1 -0
  111. package/dist/handler/health.js +85 -0
  112. package/dist/handler/health.js.map +1 -0
  113. package/dist/handler/sanitize.d.ts +12 -0
  114. package/dist/handler/sanitize.d.ts.map +1 -0
  115. package/dist/handler/sanitize.js +87 -0
  116. package/dist/handler/sanitize.js.map +1 -0
  117. package/dist/ids.d.ts +4 -0
  118. package/dist/ids.d.ts.map +1 -0
  119. package/dist/ids.js +37 -0
  120. package/dist/ids.js.map +1 -0
  121. package/dist/index.d.ts +5 -0
  122. package/dist/index.d.ts.map +1 -0
  123. package/dist/index.js +5 -0
  124. package/dist/index.js.map +1 -0
  125. package/dist/middleware/capture.d.ts +11 -0
  126. package/dist/middleware/capture.d.ts.map +1 -0
  127. package/dist/middleware/capture.js +78 -0
  128. package/dist/middleware/capture.js.map +1 -0
  129. package/dist/middleware.d.ts +8 -0
  130. package/dist/middleware.d.ts.map +1 -0
  131. package/dist/middleware.js +9 -0
  132. package/dist/middleware.js.map +1 -0
  133. package/dist/next.d.ts +8 -0
  134. package/dist/next.d.ts.map +1 -0
  135. package/dist/next.js +10 -0
  136. package/dist/next.js.map +1 -0
  137. package/dist/server/site.d.ts +23 -0
  138. package/dist/server/site.d.ts.map +1 -0
  139. package/dist/server/site.js +147 -0
  140. package/dist/server/site.js.map +1 -0
  141. package/dist/server.d.ts +2 -0
  142. package/dist/server.d.ts.map +1 -0
  143. package/dist/server.js +2 -0
  144. package/dist/server.js.map +1 -0
  145. package/dist/types.d.ts +170 -0
  146. package/dist/types.d.ts.map +1 -0
  147. package/dist/types.js +10 -0
  148. package/dist/types.js.map +1 -0
  149. package/dist/version.d.ts +2 -0
  150. package/dist/version.d.ts.map +1 -0
  151. package/dist/version.js +2 -0
  152. package/dist/version.js.map +1 -0
  153. package/package.json +99 -0
@@ -0,0 +1,13 @@
1
+ export interface ForwardOptions {
2
+ coreUrl: string | undefined;
3
+ endpointPath?: "/conversions/forward" | "/conversions/pulse/forward";
4
+ fetch?: typeof globalThis.fetch | undefined;
5
+ random?: (() => number) | undefined;
6
+ retryJitterMs?: readonly [number, number] | undefined;
7
+ secret: string | undefined;
8
+ sleep?: ((milliseconds: number) => Promise<void>) | undefined;
9
+ timeoutMs?: number | undefined;
10
+ }
11
+ export declare function forwardToCore(payload: Record<string, unknown>, options: ForwardOptions): Promise<boolean>;
12
+ export declare function forwardingEndpoint(coreUrl: string | undefined, endpointPath?: ForwardOptions["endpointPath"]): string | undefined;
13
+ //# sourceMappingURL=forward.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forward.d.ts","sourceRoot":"","sources":["../../src/handler/forward.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,YAAY,CAAC,EAAE,sBAAsB,GAAG,4BAA4B,CAAC;IACrE,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,GAAG,SAAS,CAAC;IAC5C,MAAM,CAAC,EAAE,CAAC,MAAM,MAAM,CAAC,GAAG,SAAS,CAAC;IACpC,aAAa,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IACtD,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,KAAK,CAAC,EAAE,CAAC,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;IAC9D,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,OAAO,CAAC,CAuClB;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,YAAY,GAAE,cAAc,CAAC,cAAc,CAA0B,GAEnE,MAAM,GACN,SAAS,CAiBZ"}
@@ -0,0 +1,65 @@
1
+ export async function forwardToCore(payload, options) {
2
+ const endpoint = forwardingEndpoint(options.coreUrl, options.endpointPath);
3
+ const secret = options.secret?.trim();
4
+ if (!endpoint || !secret) {
5
+ return false;
6
+ }
7
+ const fetcher = options.fetch ?? globalThis.fetch;
8
+ const sleep = options.sleep ?? defaultSleep;
9
+ const random = options.random ?? Math.random;
10
+ const [minimum, maximum] = options.retryJitterMs ?? [40, 120];
11
+ const body = JSON.stringify(payload);
12
+ for (let attempt = 0; attempt < 2; attempt += 1) {
13
+ try {
14
+ const response = await fetcher(endpoint, {
15
+ body,
16
+ headers: {
17
+ authorization: `Bearer ${secret}`,
18
+ "content-type": "application/json",
19
+ },
20
+ method: "POST",
21
+ signal: AbortSignal.timeout(options.timeoutMs ?? 2_500),
22
+ });
23
+ if (response.ok) {
24
+ return true;
25
+ }
26
+ await response.body?.cancel().catch(() => undefined);
27
+ if (response.status < 500 || attempt === 1) {
28
+ return false;
29
+ }
30
+ }
31
+ catch {
32
+ if (attempt === 1) {
33
+ return false;
34
+ }
35
+ }
36
+ const jitter = Math.round(minimum + (maximum - minimum) * random());
37
+ await sleep(Math.max(0, jitter));
38
+ }
39
+ return false;
40
+ }
41
+ export function forwardingEndpoint(coreUrl, endpointPath = "/conversions/forward") {
42
+ const normalized = coreUrl?.trim();
43
+ if (!normalized) {
44
+ return undefined;
45
+ }
46
+ try {
47
+ const url = new URL(normalized);
48
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
49
+ return undefined;
50
+ }
51
+ url.pathname = `${url.pathname.replace(/\/+$/, "")}${endpointPath}`;
52
+ url.search = "";
53
+ url.hash = "";
54
+ return url.href;
55
+ }
56
+ catch {
57
+ return undefined;
58
+ }
59
+ }
60
+ function defaultSleep(milliseconds) {
61
+ return new Promise((resolve) => {
62
+ setTimeout(resolve, milliseconds);
63
+ });
64
+ }
65
+ //# sourceMappingURL=forward.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forward.js","sourceRoot":"","sources":["../../src/handler/forward.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface HealthOptions {
2
+ env?: NodeJS.ProcessEnv | undefined;
3
+ fetch?: typeof globalThis.fetch | undefined;
4
+ timeoutMs?: number | undefined;
5
+ }
6
+ export declare function healthResponse(request: Request, options?: HealthOptions): Promise<Response>;
7
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/handler/health.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC;IACpC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,GAAG,SAAS,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAOD,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,QAAQ,CAAC,CAsCnB"}
@@ -0,0 +1,85 @@
1
+ import { timingSafeEqual } from "node:crypto";
2
+ import { TRACKER_VERSION } from "../version.js";
3
+ export async function healthResponse(request, options = {}) {
4
+ const env = options.env ?? process.env;
5
+ const production = env.NODE_ENV === "production";
6
+ const expectedToken = clean(env.MAZYOS_DIAGNOSTICS_TOKEN);
7
+ const suppliedToken = new URL(request.url).searchParams.get("token");
8
+ const detailed = !production ||
9
+ Boolean(expectedToken &&
10
+ suppliedToken &&
11
+ safeTokenEquals(suppliedToken, expectedToken));
12
+ if (!detailed) {
13
+ return json({ ok: true, version: TRACKER_VERSION });
14
+ }
15
+ const coreUrl = clean(env.MAZYOS_CORE_URL);
16
+ const secret = clean(env.MAZYOS_SITE_SECRET);
17
+ const core = coreUrl && secret
18
+ ? await checkCore(coreUrl, secret, options)
19
+ : { reachable: false };
20
+ return json({
21
+ configured: {
22
+ coreUrl: Boolean(coreUrl),
23
+ pixel: Boolean(env.NEXT_PUBLIC_MAZYOS_PIXEL_ID),
24
+ secret: Boolean(secret),
25
+ },
26
+ core: {
27
+ reachable: core.reachable,
28
+ ...(core.tracker_min_version
29
+ ? { trackerMinVersion: core.tracker_min_version }
30
+ : {}),
31
+ },
32
+ ok: true,
33
+ version: TRACKER_VERSION,
34
+ });
35
+ }
36
+ async function checkCore(coreUrl, secret, options) {
37
+ let endpoint;
38
+ try {
39
+ endpoint = new URL(coreUrl);
40
+ endpoint.pathname = `${endpoint.pathname.replace(/\/+$/, "")}/conversions/site`;
41
+ endpoint.search = "";
42
+ endpoint.hash = "";
43
+ }
44
+ catch {
45
+ return { reachable: false };
46
+ }
47
+ try {
48
+ const response = await (options.fetch ?? globalThis.fetch)(endpoint, {
49
+ headers: { authorization: `Bearer ${secret}` },
50
+ signal: AbortSignal.timeout(options.timeoutMs ?? 1_500),
51
+ });
52
+ if (!response.ok) {
53
+ await response.body?.cancel().catch(() => undefined);
54
+ return { reachable: false };
55
+ }
56
+ const body = (await response.json());
57
+ if (!body || typeof body !== "object") {
58
+ return { reachable: true };
59
+ }
60
+ const version = body
61
+ .tracker_min_version;
62
+ return typeof version === "string"
63
+ ? { reachable: true, tracker_min_version: version }
64
+ : { reachable: true };
65
+ }
66
+ catch {
67
+ return { reachable: false };
68
+ }
69
+ }
70
+ function safeTokenEquals(value, expected) {
71
+ const left = Buffer.from(value);
72
+ const right = Buffer.from(expected);
73
+ return left.length === right.length && timingSafeEqual(left, right);
74
+ }
75
+ function clean(value) {
76
+ return value?.trim() || undefined;
77
+ }
78
+ function json(body) {
79
+ return Response.json(body, {
80
+ headers: {
81
+ "cache-control": "no-store",
82
+ },
83
+ });
84
+ }
85
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/handler/health.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export declare const DEFAULT_BOT_REGEX: RegExp;
2
+ export declare class EventValidationError extends Error {
3
+ readonly status = 422;
4
+ constructor(message: string);
5
+ }
6
+ export declare function validateBrowserEvent(payload: Record<string, unknown>): void;
7
+ export declare function isTrackingPulsePayload(payload: Record<string, unknown>): boolean;
8
+ export declare function validateBrowserPayload(payload: Record<string, unknown>): void;
9
+ export declare function sanitizeBrowserPayload(payload: Record<string, unknown>, headers: Headers): Record<string, unknown>;
10
+ export declare function resolveClientIp(headers: Headers): string | undefined;
11
+ export declare function isBotUserAgent(userAgent: string | null, pattern?: RegExp): boolean;
12
+ //# sourceMappingURL=sanitize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/handler/sanitize.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,iBAAiB,QAC+G,CAAC;AAE9I,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,MAAM,OAAO;IAEtB,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,IAAI,CAUN;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAET;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,IAAI,CAiBN;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,EAAE,OAAO,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAoBzB;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAIpE;AAED,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,OAAO,GAAE,MAA0B,GAClC,OAAO,CAMT"}
@@ -0,0 +1,87 @@
1
+ import { BROWSER_EVENT_NAMES } from "../types.js";
2
+ const BROWSER_EVENTS = new Set(BROWSER_EVENT_NAMES);
3
+ const PULSE_TYPES = new Set([
4
+ "page_start",
5
+ "heartbeat",
6
+ "visibility",
7
+ "page_exit",
8
+ "route_change",
9
+ ]);
10
+ export const DEFAULT_BOT_REGEX = /bot|crawl|spider|headless|preview|lighthouse|pagespeed|facebookexternalhit|whatsapp|slackbot|vercel-screenshot|slurp|uptimerobot|pingdom/i;
11
+ export class EventValidationError extends Error {
12
+ status = 422;
13
+ constructor(message) {
14
+ super(message);
15
+ this.name = "EventValidationError";
16
+ }
17
+ }
18
+ export function validateBrowserEvent(payload) {
19
+ const eventName = payload.event_name;
20
+ if (typeof eventName !== "string" || !eventName.trim()) {
21
+ throw new EventValidationError("event_name is required");
22
+ }
23
+ if (!BROWSER_EVENTS.has(eventName)) {
24
+ throw new EventValidationError("This event must be sent by the checkout or provider");
25
+ }
26
+ }
27
+ export function isTrackingPulsePayload(payload) {
28
+ return payload.payload_type === "pulse";
29
+ }
30
+ export function validateBrowserPayload(payload) {
31
+ if (!isTrackingPulsePayload(payload)) {
32
+ validateBrowserEvent(payload);
33
+ return;
34
+ }
35
+ if (typeof payload.event_id !== "string" || payload.event_id.length < 8) {
36
+ throw new EventValidationError("event_id is required for tracking pulses");
37
+ }
38
+ if (typeof payload.session_id !== "string" ||
39
+ payload.session_id.length < 16) {
40
+ throw new EventValidationError("session_id is required for tracking pulses");
41
+ }
42
+ if (typeof payload.pulse_type !== "string" || !PULSE_TYPES.has(payload.pulse_type)) {
43
+ throw new EventValidationError("pulse_type is invalid");
44
+ }
45
+ }
46
+ export function sanitizeBrowserPayload(payload, headers) {
47
+ const suppliedUserData = payload.user_data &&
48
+ typeof payload.user_data === "object" &&
49
+ !Array.isArray(payload.user_data)
50
+ ? payload.user_data
51
+ : {};
52
+ const userData = { ...suppliedUserData };
53
+ delete userData.client_ip_address;
54
+ delete userData.client_user_agent;
55
+ const clientIp = resolveClientIp(headers);
56
+ const userAgent = cleanHeader(headers.get("user-agent"), 512);
57
+ if (clientIp) {
58
+ userData.client_ip_address = clientIp;
59
+ }
60
+ if (userAgent) {
61
+ userData.client_user_agent = userAgent;
62
+ }
63
+ return { ...payload, user_data: userData };
64
+ }
65
+ export function resolveClientIp(headers) {
66
+ return firstForwarded(headers.get("x-vercel-forwarded-for")) ??
67
+ cleanHeader(headers.get("x-real-ip"), 64) ??
68
+ firstForwarded(headers.get("x-forwarded-for"));
69
+ }
70
+ export function isBotUserAgent(userAgent, pattern = DEFAULT_BOT_REGEX) {
71
+ if (!userAgent) {
72
+ return false;
73
+ }
74
+ pattern.lastIndex = 0;
75
+ return pattern.test(userAgent);
76
+ }
77
+ function firstForwarded(value) {
78
+ return cleanHeader(value?.split(",", 1)[0] ?? null, 64);
79
+ }
80
+ function cleanHeader(value, maximum) {
81
+ const normalized = value?.trim();
82
+ if (!normalized || /[\r\n]/.test(normalized)) {
83
+ return undefined;
84
+ }
85
+ return normalized.slice(0, maximum);
86
+ }
87
+ //# sourceMappingURL=sanitize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../src/handler/sanitize.ts"],"names":[],"mappings":"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"}
package/dist/ids.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export declare function generateBase62(length: number): string;
2
+ export declare function generateMzc(): string;
3
+ export declare function generateEventId(): string;
4
+ //# sourceMappingURL=ids.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ids.d.ts","sourceRoot":"","sources":["../src/ids.ts"],"names":[],"mappings":"AAaA,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAmBrD;AAED,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,wBAAgB,eAAe,IAAI,MAAM,CAKxC"}
package/dist/ids.js ADDED
@@ -0,0 +1,37 @@
1
+ const BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
2
+ const UNBIASED_BYTE_LIMIT = 248;
3
+ function webCrypto() {
4
+ const cryptoApi = globalThis.crypto;
5
+ if (!cryptoApi?.getRandomValues) {
6
+ throw new Error("@mazyos/lp-tracker requires Web Crypto to generate secure identifiers");
7
+ }
8
+ return cryptoApi;
9
+ }
10
+ export function generateBase62(length) {
11
+ const cryptoApi = webCrypto();
12
+ let output = "";
13
+ while (output.length < length) {
14
+ const bytes = new Uint8Array(Math.max(16, length - output.length));
15
+ cryptoApi.getRandomValues(bytes);
16
+ for (const byte of bytes) {
17
+ if (byte >= UNBIASED_BYTE_LIMIT) {
18
+ continue;
19
+ }
20
+ output += BASE62[byte % BASE62.length];
21
+ if (output.length === length) {
22
+ break;
23
+ }
24
+ }
25
+ }
26
+ return output;
27
+ }
28
+ export function generateMzc() {
29
+ return generateBase62(22);
30
+ }
31
+ export function generateEventId() {
32
+ const cryptoApi = webCrypto();
33
+ return typeof cryptoApi.randomUUID === "function"
34
+ ? cryptoApi.randomUUID()
35
+ : `mzy_${generateBase62(24)}`;
36
+ }
37
+ //# sourceMappingURL=ids.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ids.js","sourceRoot":"","sources":["../src/ids.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,GAAG,gEAAgE,CAAC;AAChF,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEhC,SAAS,SAAS;IAChB,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC;IACpC,IAAI,CAAC,SAAS,EAAE,eAAe,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CACb,uEAAuE,CACxE,CAAC;IACJ,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,SAAS,GAAG,SAAS,EAAE,CAAC;IAC9B,IAAI,MAAM,GAAG,EAAE,CAAC;IAEhB,OAAO,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QACnE,SAAS,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QACjC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,IAAI,mBAAmB,EAAE,CAAC;gBAChC,SAAS;YACX,CAAC;YACD,MAAM,IAAI,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YACvC,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC7B,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,cAAc,CAAC,EAAE,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,SAAS,GAAG,SAAS,EAAE,CAAC;IAC9B,OAAO,OAAO,SAAS,CAAC,UAAU,KAAK,UAAU;QAC/C,CAAC,CAAC,SAAS,CAAC,UAAU,EAAE;QACxB,CAAC,CAAC,OAAO,cAAc,CAAC,EAAE,CAAC,EAAE,CAAC;AAClC,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { MazyosProvider, useMazyos } from "./client/provider.js";
2
+ export { consent, identify, track } from "./client/public-api.js";
3
+ export { BROWSER_EVENT_NAMES } from "./types.js";
4
+ export type { AttributionData, BrowserEventName, CollectEvent, ConsentDecision, ConsentMode, ConsentState, DataProcessingOptions, MazyosActions, MazyosContextValue, MazyosIdentity, MazyosMeta, MazyosProviderProps, MazyosState, PageViewPolicy, StorageMode, TrackProperties, TrackingPayload, TrackingPulse, TrackingPulseType, } from "./types.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,WAAW,EACX,YAAY,EACZ,qBAAqB,EACrB,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,UAAU,EACV,mBAAmB,EACnB,WAAW,EACX,cAAc,EACd,WAAW,EACX,eAAe,EACf,eAAe,EACf,aAAa,EACb,iBAAiB,GAClB,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ "use client";
2
+ export { MazyosProvider, useMazyos } from "./client/provider.js";
3
+ export { consent, identify, track } from "./client/public-api.js";
4
+ export { BROWSER_EVENT_NAMES } from "./types.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { NextResponse } from "next/server.js";
2
+ import type { NextRequest } from "next/server.js";
3
+ export interface MazyosMiddlewareOptions {
4
+ cookieDomain?: string;
5
+ cookieMaxAge?: number;
6
+ now?: () => number;
7
+ secure?: boolean;
8
+ }
9
+ export type MazyosMiddleware = (request: NextRequest) => NextResponse;
10
+ export declare function createMazyosMiddleware(options?: MazyosMiddlewareOptions): MazyosMiddleware;
11
+ //# sourceMappingURL=capture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/middleware/capture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAYlD,MAAM,WAAW,uBAAuB;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,MAAM,gBAAgB,GAAG,CAC7B,OAAO,EAAE,WAAW,KACjB,YAAY,CAAC;AAElB,wBAAgB,sBAAsB,CACpC,OAAO,GAAE,uBAA4B,GACpC,gBAAgB,CA+BlB"}
@@ -0,0 +1,78 @@
1
+ import { NextResponse } from "next/server.js";
2
+ import { ATTRIBUTION_COOKIE_MAX_AGE, ATTRIBUTION_FIELDS, createFbc, isUtmField, isMzc, mazyosCookieName, normalizeAttributionValue, } from "../attribution.js";
3
+ import { generateMzc } from "../ids.js";
4
+ export function createMazyosMiddleware(options = {}) {
5
+ const now = options.now ?? Date.now;
6
+ return function mazyosMiddleware(request) {
7
+ const updates = captureUpdates(request, now());
8
+ const requestHeaders = new Headers(request.headers);
9
+ requestHeaders.set("cookie", mergeCookieHeader(request.headers.get("cookie"), updates));
10
+ const response = NextResponse.next({
11
+ request: { headers: requestHeaders },
12
+ });
13
+ const domain = (options.cookieDomain ??
14
+ process.env.MAZYOS_COOKIE_DOMAIN ??
15
+ process.env.NEXT_PUBLIC_MAZYOS_COOKIE_DOMAIN)?.trim() || undefined;
16
+ const cookieOptions = {
17
+ ...(domain ? { domain } : {}),
18
+ httpOnly: false,
19
+ maxAge: options.cookieMaxAge ?? ATTRIBUTION_COOKIE_MAX_AGE,
20
+ path: "/",
21
+ sameSite: "lax",
22
+ secure: options.secure ?? process.env.NODE_ENV === "production",
23
+ };
24
+ for (const [name, value] of updates) {
25
+ response.cookies.set(name, value, cookieOptions);
26
+ }
27
+ return response;
28
+ };
29
+ }
30
+ function captureUpdates(request, arrivalMs) {
31
+ const updates = new Map();
32
+ const query = request.nextUrl.searchParams;
33
+ for (const field of ATTRIBUTION_FIELDS) {
34
+ const value = normalizeAttributionValue(query.get(field));
35
+ if (value) {
36
+ updates.set(mazyosCookieName(field), value);
37
+ }
38
+ }
39
+ let dynamicUtmCount = 0;
40
+ for (const [rawKey, rawValue] of query) {
41
+ const key = rawKey.trim().toLowerCase();
42
+ const value = normalizeAttributionValue(rawValue);
43
+ if (isUtmField(key) && value && dynamicUtmCount < 64) {
44
+ updates.set(mazyosCookieName(key), value);
45
+ dynamicUtmCount += 1;
46
+ }
47
+ }
48
+ const fbclid = normalizeAttributionValue(query.get("fbclid"));
49
+ if (fbclid) {
50
+ updates.set("_mzy_fbc", createFbc(fbclid, arrivalMs));
51
+ }
52
+ const queryMzc = query.get("mzc");
53
+ const cookieMzc = request.cookies.get("_mzc")?.value;
54
+ if (isMzc(queryMzc)) {
55
+ if (queryMzc !== cookieMzc) {
56
+ updates.set("_mzc", queryMzc);
57
+ }
58
+ }
59
+ else if (!isMzc(cookieMzc)) {
60
+ updates.set("_mzc", generateMzc());
61
+ }
62
+ return updates;
63
+ }
64
+ function mergeCookieHeader(current, updates) {
65
+ const cookies = new Map();
66
+ for (const segment of current?.split(";") ?? []) {
67
+ const separator = segment.indexOf("=");
68
+ if (separator < 1) {
69
+ continue;
70
+ }
71
+ cookies.set(segment.slice(0, separator).trim(), segment.slice(separator + 1).trim());
72
+ }
73
+ for (const [name, value] of updates) {
74
+ cookies.set(name, encodeURIComponent(value));
75
+ }
76
+ return [...cookies].map(([name, value]) => `${name}=${value}`).join("; ");
77
+ }
78
+ //# sourceMappingURL=capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/middleware/capture.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { createMazyosMiddleware } from "./middleware/capture.js";
2
+ export { createMazyosMiddleware };
3
+ export type { MazyosMiddleware, MazyosMiddlewareOptions } from "./middleware/capture.js";
4
+ export declare const middleware: import("./middleware.js").MazyosMiddleware;
5
+ export declare const config: {
6
+ readonly matcher: readonly ["/((?!api(?:/|$)|_next(?:/|$)|static(?:/|$)|\\.well-known(?:/|$)|.*\\.[^/]+$).*)"];
7
+ };
8
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,OAAO,EAAE,sBAAsB,EAAE,CAAC;AAClC,YAAY,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAEzF,eAAO,MAAM,UAAU,4CAA2B,CAAC;AAEnD,eAAO,MAAM,MAAM;aACjB,OAAO,YACL,iFAAiF;CAE3E,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { createMazyosMiddleware } from "./middleware/capture.js";
2
+ export { createMazyosMiddleware };
3
+ export const middleware = createMazyosMiddleware();
4
+ export const config = {
5
+ matcher: [
6
+ "/((?!api(?:/|$)|_next(?:/|$)|static(?:/|$)|\\.well-known(?:/|$)|.*\\.[^/]+$).*)",
7
+ ],
8
+ };
9
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,OAAO,EAAE,sBAAsB,EAAE,CAAC;AAGlC,MAAM,CAAC,MAAM,UAAU,GAAG,sBAAsB,EAAE,CAAC;AAEnD,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,OAAO,EAAE;QACP,iFAAiF;KAClF;CACO,CAAC"}
package/dist/next.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ export { createMazyosCollectHandler, type MazyosCollectHandlerOptions, type MazyosCollectHandlers, } from "./handler/create.js";
2
+ export { DEFAULT_MAX_BODY_BYTES } from "./handler/body.js";
3
+ export { DEFAULT_BOT_REGEX, resolveClientIp } from "./handler/sanitize.js";
4
+ export declare const POST: (request: Request) => Promise<Response>;
5
+ export declare const GET: (request: Request) => Promise<Response>;
6
+ export declare const runtime = "nodejs";
7
+ export declare const dynamic = "force-dynamic";
8
+ //# sourceMappingURL=next.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next.d.ts","sourceRoot":"","sources":["../src/next.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,0BAA0B,EAC1B,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAI3E,eAAO,MAAM,IAAI,yCAAgB,CAAC;AAClC,eAAO,MAAM,GAAG,yCAAe,CAAC;AAChC,eAAO,MAAM,OAAO,WAAW,CAAC;AAChC,eAAO,MAAM,OAAO,kBAAkB,CAAC"}
package/dist/next.js ADDED
@@ -0,0 +1,10 @@
1
+ import { createMazyosCollectHandler } from "./handler/create.js";
2
+ export { createMazyosCollectHandler, } from "./handler/create.js";
3
+ export { DEFAULT_MAX_BODY_BYTES } from "./handler/body.js";
4
+ export { DEFAULT_BOT_REGEX, resolveClientIp } from "./handler/sanitize.js";
5
+ const handlers = createMazyosCollectHandler();
6
+ export const POST = handlers.POST;
7
+ export const GET = handlers.GET;
8
+ export const runtime = "nodejs";
9
+ export const dynamic = "force-dynamic";
10
+ //# sourceMappingURL=next.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next.js","sourceRoot":"","sources":["../src/next.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAEjE,OAAO,EACL,0BAA0B,GAG3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE3E,MAAM,QAAQ,GAAG,0BAA0B,EAAE,CAAC;AAE9C,MAAM,CAAC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;AAClC,MAAM,CAAC,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC;AAChC,MAAM,CAAC,MAAM,OAAO,GAAG,QAAQ,CAAC;AAChC,MAAM,CAAC,MAAM,OAAO,GAAG,eAAe,CAAC"}
@@ -0,0 +1,23 @@
1
+ export interface MazyosSite {
2
+ allowed_origins: readonly string[];
3
+ checkout_url?: string;
4
+ consent_mode: "implied" | "required";
5
+ default_content_ids: readonly string[];
6
+ default_content_name?: string;
7
+ gateway?: string;
8
+ name: string;
9
+ pageview_policy: "ledger" | "pixel_only";
10
+ pixel_id?: string;
11
+ tracker_min_version: string;
12
+ }
13
+ export interface GetMazyosSiteOptions {
14
+ cacheTtlMs?: number;
15
+ coreUrl?: string;
16
+ fetch?: typeof globalThis.fetch;
17
+ now?: () => number;
18
+ secret?: string;
19
+ timeoutMs?: number;
20
+ }
21
+ export declare function getMazyosSite(options?: GetMazyosSiteOptions): Promise<MazyosSite>;
22
+ export declare function clearMazyosSiteCache(): void;
23
+ //# sourceMappingURL=site.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"site.d.ts","sourceRoot":"","sources":["../../src/server/site.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,UAAU;IACzB,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,SAAS,GAAG,UAAU,CAAC;IACrC,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,QAAQ,GAAG,YAAY,CAAC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AASD,wBAAsB,aAAa,CACjC,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,UAAU,CAAC,CAuDrB;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}