@nextlytics/core 0.1.0-canary-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.
Files changed (93) hide show
  1. package/dist/anonymous-user.cjs +118 -0
  2. package/dist/anonymous-user.d.mts +22 -0
  3. package/dist/anonymous-user.d.ts +22 -0
  4. package/dist/anonymous-user.js +94 -0
  5. package/dist/backends/clickhouse.cjs +110 -0
  6. package/dist/backends/clickhouse.d.mts +58 -0
  7. package/dist/backends/clickhouse.d.ts +58 -0
  8. package/dist/backends/clickhouse.js +92 -0
  9. package/dist/backends/ga.cjs +207 -0
  10. package/dist/backends/ga.d.mts +21 -0
  11. package/dist/backends/ga.d.ts +21 -0
  12. package/dist/backends/ga.js +183 -0
  13. package/dist/backends/gtm.cjs +155 -0
  14. package/dist/backends/gtm.d.mts +11 -0
  15. package/dist/backends/gtm.d.ts +11 -0
  16. package/dist/backends/gtm.js +131 -0
  17. package/dist/backends/lib/db.cjs +150 -0
  18. package/dist/backends/lib/db.d.mts +121 -0
  19. package/dist/backends/lib/db.d.ts +121 -0
  20. package/dist/backends/lib/db.js +119 -0
  21. package/dist/backends/logging.cjs +45 -0
  22. package/dist/backends/logging.d.mts +7 -0
  23. package/dist/backends/logging.d.ts +7 -0
  24. package/dist/backends/logging.js +21 -0
  25. package/dist/backends/neon.cjs +84 -0
  26. package/dist/backends/neon.d.mts +11 -0
  27. package/dist/backends/neon.d.ts +11 -0
  28. package/dist/backends/neon.js +66 -0
  29. package/dist/backends/postgrest.cjs +98 -0
  30. package/dist/backends/postgrest.d.mts +46 -0
  31. package/dist/backends/postgrest.d.ts +46 -0
  32. package/dist/backends/postgrest.js +73 -0
  33. package/dist/backends/posthog.cjs +120 -0
  34. package/dist/backends/posthog.d.mts +13 -0
  35. package/dist/backends/posthog.d.ts +13 -0
  36. package/dist/backends/posthog.js +96 -0
  37. package/dist/backends/segment.cjs +112 -0
  38. package/dist/backends/segment.d.mts +43 -0
  39. package/dist/backends/segment.d.ts +43 -0
  40. package/dist/backends/segment.js +88 -0
  41. package/dist/client.cjs +171 -0
  42. package/dist/client.d.mts +29 -0
  43. package/dist/client.d.ts +29 -0
  44. package/dist/client.js +146 -0
  45. package/dist/config-helpers.cjs +71 -0
  46. package/dist/config-helpers.d.mts +16 -0
  47. package/dist/config-helpers.d.ts +16 -0
  48. package/dist/config-helpers.js +45 -0
  49. package/dist/handlers.cjs +123 -0
  50. package/dist/handlers.d.mts +9 -0
  51. package/dist/handlers.d.ts +9 -0
  52. package/dist/handlers.js +99 -0
  53. package/dist/headers.cjs +41 -0
  54. package/dist/headers.d.mts +3 -0
  55. package/dist/headers.d.ts +3 -0
  56. package/dist/headers.js +17 -0
  57. package/dist/index.cjs +41 -0
  58. package/dist/index.d.mts +9 -0
  59. package/dist/index.d.ts +9 -0
  60. package/dist/index.js +12 -0
  61. package/dist/middleware.cjs +204 -0
  62. package/dist/middleware.d.mts +10 -0
  63. package/dist/middleware.d.ts +10 -0
  64. package/dist/middleware.js +183 -0
  65. package/dist/pages-router.cjs +45 -0
  66. package/dist/pages-router.d.mts +45 -0
  67. package/dist/pages-router.d.ts +45 -0
  68. package/dist/pages-router.js +21 -0
  69. package/dist/plugins/vercel-geo.cjs +60 -0
  70. package/dist/plugins/vercel-geo.d.mts +25 -0
  71. package/dist/plugins/vercel-geo.d.ts +25 -0
  72. package/dist/plugins/vercel-geo.js +36 -0
  73. package/dist/server-component-context.cjs +95 -0
  74. package/dist/server-component-context.d.mts +30 -0
  75. package/dist/server-component-context.d.ts +30 -0
  76. package/dist/server-component-context.js +69 -0
  77. package/dist/server.cjs +236 -0
  78. package/dist/server.d.mts +13 -0
  79. package/dist/server.d.ts +13 -0
  80. package/dist/server.js +213 -0
  81. package/dist/template.cjs +108 -0
  82. package/dist/template.d.mts +27 -0
  83. package/dist/template.d.ts +27 -0
  84. package/dist/template.js +83 -0
  85. package/dist/types.cjs +16 -0
  86. package/dist/types.d.mts +216 -0
  87. package/dist/types.d.ts +216 -0
  88. package/dist/types.js +0 -0
  89. package/dist/uitils.cjs +94 -0
  90. package/dist/uitils.d.mts +22 -0
  91. package/dist/uitils.d.ts +22 -0
  92. package/dist/uitils.js +68 -0
  93. package/package.json +162 -0
@@ -0,0 +1,96 @@
1
+ function posthogBackend(opts) {
2
+ const host = (opts.host ?? "https://app.posthog.com").replace(/\/$/, "");
3
+ const apiKey = opts.apiKey;
4
+ return {
5
+ name: "posthog",
6
+ supportsUpdates: false,
7
+ async onEvent(event) {
8
+ const {
9
+ type,
10
+ eventId,
11
+ parentEventId,
12
+ collectedAt,
13
+ userContext,
14
+ clientContext,
15
+ serverContext,
16
+ properties,
17
+ anonymousUserId
18
+ } = event;
19
+ const posthogProps = {
20
+ ...properties,
21
+ nextlytics_event_id: eventId
22
+ };
23
+ if (parentEventId) {
24
+ posthogProps.nextlytics_parent_event_id = parentEventId;
25
+ }
26
+ posthogProps.nextlytics_collected_at = collectedAt;
27
+ posthogProps.$current_url = `${serverContext.host}${serverContext.path}`;
28
+ posthogProps.$pathname = serverContext.path;
29
+ posthogProps.$host = serverContext.host;
30
+ posthogProps.$ip = serverContext.ip;
31
+ posthogProps.http_method = serverContext.method;
32
+ posthogProps.server_collected_at = serverContext.collectedAt;
33
+ if (serverContext.search && Object.keys(serverContext.search).length > 0) {
34
+ posthogProps.query_params = serverContext.search;
35
+ }
36
+ if (serverContext.requestHeaders && Object.keys(serverContext.requestHeaders).length > 0) {
37
+ posthogProps.request_headers = serverContext.requestHeaders;
38
+ }
39
+ if (serverContext.responseHeaders && Object.keys(serverContext.responseHeaders).length > 0) {
40
+ posthogProps.response_headers = serverContext.responseHeaders;
41
+ }
42
+ const referer = clientContext?.referer ?? serverContext.requestHeaders?.["referer"];
43
+ if (referer) {
44
+ posthogProps.$referrer = referer;
45
+ }
46
+ const userAgent = clientContext?.userAgent ?? serverContext.requestHeaders?.["user-agent"];
47
+ if (userAgent) {
48
+ posthogProps.$user_agent = userAgent;
49
+ }
50
+ if (clientContext) {
51
+ posthogProps.client_collected_at = clientContext.collectedAt;
52
+ if (clientContext.path) {
53
+ posthogProps.client_path = clientContext.path;
54
+ }
55
+ if (clientContext.locale) {
56
+ posthogProps.$locale = clientContext.locale;
57
+ }
58
+ if (clientContext.screen) {
59
+ const { screen } = clientContext;
60
+ if (screen.width) posthogProps.$screen_width = screen.width;
61
+ if (screen.height) posthogProps.$screen_height = screen.height;
62
+ if (screen.innerWidth) posthogProps.$viewport_width = screen.innerWidth;
63
+ if (screen.innerHeight) posthogProps.$viewport_height = screen.innerHeight;
64
+ if (screen.density) posthogProps.$device_pixel_ratio = screen.density;
65
+ }
66
+ }
67
+ const distinctId = userContext?.userId ?? anonymousUserId ?? "anonymous";
68
+ const payload = {
69
+ api_key: apiKey,
70
+ event: type,
71
+ distinct_id: distinctId,
72
+ properties: posthogProps,
73
+ timestamp: collectedAt
74
+ };
75
+ if (userContext?.userId && userContext.traits) {
76
+ payload.$set = userContext.traits;
77
+ }
78
+ const res = await fetch(`${host}/capture/`, {
79
+ method: "POST",
80
+ headers: {
81
+ "Content-Type": "application/json"
82
+ },
83
+ body: JSON.stringify(payload)
84
+ });
85
+ if (!res.ok) {
86
+ const text = await res.text();
87
+ throw new Error(`PostHog error ${res.status}: ${text}`);
88
+ }
89
+ },
90
+ updateEvent() {
91
+ }
92
+ };
93
+ }
94
+ export {
95
+ posthogBackend
96
+ };
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var segment_exports = {};
20
+ __export(segment_exports, {
21
+ segmentBackend: () => segmentBackend
22
+ });
23
+ module.exports = __toCommonJS(segment_exports);
24
+ function segmentBackend(config) {
25
+ const host = (config.host ?? "https://api.segment.io").replace(/\/$/, "");
26
+ const authHeader = "Basic " + btoa(config.writeKey + ":");
27
+ async function send(endpoint, payload) {
28
+ const res = await fetch(`${host}${endpoint}`, {
29
+ method: "POST",
30
+ headers: {
31
+ "Content-Type": "application/json",
32
+ Authorization: authHeader
33
+ },
34
+ body: JSON.stringify(payload)
35
+ });
36
+ if (!res.ok) {
37
+ const text = await res.text();
38
+ throw new Error(`Segment error ${res.status}: ${text}`);
39
+ }
40
+ }
41
+ function buildContext(event) {
42
+ const ctx = {
43
+ ip: event.serverContext.ip
44
+ };
45
+ if (event.userContext?.traits) {
46
+ ctx.traits = event.userContext.traits;
47
+ }
48
+ if (event.clientContext) {
49
+ ctx.userAgent = event.clientContext.userAgent;
50
+ ctx.locale = event.clientContext.locale;
51
+ ctx.page = {
52
+ path: event.clientContext.path,
53
+ referrer: event.clientContext.referer
54
+ };
55
+ if (event.clientContext.screen) {
56
+ ctx.screen = {
57
+ width: event.clientContext.screen.width,
58
+ height: event.clientContext.screen.height,
59
+ innerWidth: event.clientContext.screen.innerWidth,
60
+ innerHeight: event.clientContext.screen.innerHeight,
61
+ density: event.clientContext.screen.density
62
+ };
63
+ }
64
+ }
65
+ return ctx;
66
+ }
67
+ function buildProperties(event) {
68
+ return {
69
+ parentEventId: event.parentEventId,
70
+ path: event.serverContext.path,
71
+ host: event.serverContext.host,
72
+ method: event.serverContext.method,
73
+ search: event.serverContext.search,
74
+ ...event.properties
75
+ };
76
+ }
77
+ return {
78
+ name: "segment",
79
+ supportsUpdates: false,
80
+ async onEvent(event) {
81
+ const context = buildContext(event);
82
+ const properties = buildProperties(event);
83
+ if (event.type === "pageView") {
84
+ await send("/v1/page", {
85
+ messageId: event.eventId,
86
+ anonymousId: event.anonymousUserId,
87
+ userId: event.userContext?.userId,
88
+ name: event.serverContext.path,
89
+ timestamp: event.collectedAt,
90
+ context,
91
+ properties
92
+ });
93
+ } else {
94
+ await send("/v1/track", {
95
+ messageId: event.eventId,
96
+ anonymousId: event.anonymousUserId,
97
+ userId: event.userContext?.userId,
98
+ event: event.type,
99
+ timestamp: event.collectedAt,
100
+ context,
101
+ properties
102
+ });
103
+ }
104
+ },
105
+ updateEvent() {
106
+ }
107
+ };
108
+ }
109
+ // Annotate the CommonJS export names for ESM import in node:
110
+ 0 && (module.exports = {
111
+ segmentBackend
112
+ });
@@ -0,0 +1,43 @@
1
+ import { NextlyticsBackend } from '../types.mjs';
2
+ import 'next/dist/server/web/spec-extension/cookies';
3
+ import 'next/server';
4
+
5
+ /**
6
+ * Segment backend for Nextlytics
7
+ *
8
+ * Sends events to Segment's HTTP Tracking API. Also works with Segment-compatible
9
+ * destinations like Jitsu.
10
+ *
11
+ * ## Segment Usage
12
+ *
13
+ * ```typescript
14
+ * import { segmentBackend } from "@nextlytics/core/backends/segment"
15
+ *
16
+ * const analytics = Nextlytics({
17
+ * backends: [
18
+ * segmentBackend({
19
+ * writeKey: process.env.SEGMENT_WRITE_KEY!,
20
+ * })
21
+ * ]
22
+ * })
23
+ * ```
24
+ *
25
+ * ## Jitsu Usage
26
+ *
27
+ * ```typescript
28
+ * segmentBackend({
29
+ * writeKey: process.env.JITSU_WRITE_KEY!,
30
+ * host: "https://ingest.g.jitsu.com",
31
+ * })
32
+ * ```
33
+ */
34
+
35
+ type SegmentBackendConfig = {
36
+ /** Segment write key */
37
+ writeKey: string;
38
+ /** API host (default: "https://api.segment.io") */
39
+ host?: string;
40
+ };
41
+ declare function segmentBackend(config: SegmentBackendConfig): NextlyticsBackend;
42
+
43
+ export { type SegmentBackendConfig, segmentBackend };
@@ -0,0 +1,43 @@
1
+ import { NextlyticsBackend } from '../types.js';
2
+ import 'next/dist/server/web/spec-extension/cookies';
3
+ import 'next/server';
4
+
5
+ /**
6
+ * Segment backend for Nextlytics
7
+ *
8
+ * Sends events to Segment's HTTP Tracking API. Also works with Segment-compatible
9
+ * destinations like Jitsu.
10
+ *
11
+ * ## Segment Usage
12
+ *
13
+ * ```typescript
14
+ * import { segmentBackend } from "@nextlytics/core/backends/segment"
15
+ *
16
+ * const analytics = Nextlytics({
17
+ * backends: [
18
+ * segmentBackend({
19
+ * writeKey: process.env.SEGMENT_WRITE_KEY!,
20
+ * })
21
+ * ]
22
+ * })
23
+ * ```
24
+ *
25
+ * ## Jitsu Usage
26
+ *
27
+ * ```typescript
28
+ * segmentBackend({
29
+ * writeKey: process.env.JITSU_WRITE_KEY!,
30
+ * host: "https://ingest.g.jitsu.com",
31
+ * })
32
+ * ```
33
+ */
34
+
35
+ type SegmentBackendConfig = {
36
+ /** Segment write key */
37
+ writeKey: string;
38
+ /** API host (default: "https://api.segment.io") */
39
+ host?: string;
40
+ };
41
+ declare function segmentBackend(config: SegmentBackendConfig): NextlyticsBackend;
42
+
43
+ export { type SegmentBackendConfig, segmentBackend };
@@ -0,0 +1,88 @@
1
+ function segmentBackend(config) {
2
+ const host = (config.host ?? "https://api.segment.io").replace(/\/$/, "");
3
+ const authHeader = "Basic " + btoa(config.writeKey + ":");
4
+ async function send(endpoint, payload) {
5
+ const res = await fetch(`${host}${endpoint}`, {
6
+ method: "POST",
7
+ headers: {
8
+ "Content-Type": "application/json",
9
+ Authorization: authHeader
10
+ },
11
+ body: JSON.stringify(payload)
12
+ });
13
+ if (!res.ok) {
14
+ const text = await res.text();
15
+ throw new Error(`Segment error ${res.status}: ${text}`);
16
+ }
17
+ }
18
+ function buildContext(event) {
19
+ const ctx = {
20
+ ip: event.serverContext.ip
21
+ };
22
+ if (event.userContext?.traits) {
23
+ ctx.traits = event.userContext.traits;
24
+ }
25
+ if (event.clientContext) {
26
+ ctx.userAgent = event.clientContext.userAgent;
27
+ ctx.locale = event.clientContext.locale;
28
+ ctx.page = {
29
+ path: event.clientContext.path,
30
+ referrer: event.clientContext.referer
31
+ };
32
+ if (event.clientContext.screen) {
33
+ ctx.screen = {
34
+ width: event.clientContext.screen.width,
35
+ height: event.clientContext.screen.height,
36
+ innerWidth: event.clientContext.screen.innerWidth,
37
+ innerHeight: event.clientContext.screen.innerHeight,
38
+ density: event.clientContext.screen.density
39
+ };
40
+ }
41
+ }
42
+ return ctx;
43
+ }
44
+ function buildProperties(event) {
45
+ return {
46
+ parentEventId: event.parentEventId,
47
+ path: event.serverContext.path,
48
+ host: event.serverContext.host,
49
+ method: event.serverContext.method,
50
+ search: event.serverContext.search,
51
+ ...event.properties
52
+ };
53
+ }
54
+ return {
55
+ name: "segment",
56
+ supportsUpdates: false,
57
+ async onEvent(event) {
58
+ const context = buildContext(event);
59
+ const properties = buildProperties(event);
60
+ if (event.type === "pageView") {
61
+ await send("/v1/page", {
62
+ messageId: event.eventId,
63
+ anonymousId: event.anonymousUserId,
64
+ userId: event.userContext?.userId,
65
+ name: event.serverContext.path,
66
+ timestamp: event.collectedAt,
67
+ context,
68
+ properties
69
+ });
70
+ } else {
71
+ await send("/v1/track", {
72
+ messageId: event.eventId,
73
+ anonymousId: event.anonymousUserId,
74
+ userId: event.userContext?.userId,
75
+ event: event.type,
76
+ timestamp: event.collectedAt,
77
+ context,
78
+ properties
79
+ });
80
+ }
81
+ },
82
+ updateEvent() {
83
+ }
84
+ };
85
+ }
86
+ export {
87
+ segmentBackend
88
+ };
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ "use client";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+ var client_exports = {};
21
+ __export(client_exports, {
22
+ NextlyticsClient: () => NextlyticsClient,
23
+ useNextlytics: () => useNextlytics
24
+ });
25
+ module.exports = __toCommonJS(client_exports);
26
+ var import_jsx_runtime = require("react/jsx-runtime");
27
+ var import_react = require("react");
28
+ var import_server_component_context = require("./server-component-context");
29
+ var import_template = require("./template");
30
+ const templateFunctions = {
31
+ q: (v) => JSON.stringify(v ?? null),
32
+ json: (v) => JSON.stringify(v ?? null)
33
+ };
34
+ const compiledCache = {};
35
+ const NextlyticsContext = (0, import_react.createContext)(null);
36
+ function createClientContext() {
37
+ const isBrowser = typeof window !== "undefined";
38
+ return {
39
+ collectedAt: /* @__PURE__ */ new Date(),
40
+ referer: isBrowser ? document.referrer || void 0 : void 0,
41
+ path: isBrowser ? window.location.pathname : void 0,
42
+ screen: {
43
+ width: isBrowser ? window.screen.width : void 0,
44
+ height: isBrowser ? window.screen.height : void 0,
45
+ innerWidth: isBrowser ? window.innerWidth : void 0,
46
+ innerHeight: isBrowser ? window.innerHeight : void 0,
47
+ density: isBrowser ? window.devicePixelRatio : void 0
48
+ },
49
+ userAgent: isBrowser ? navigator.userAgent : void 0,
50
+ locale: isBrowser ? navigator.language : void 0
51
+ };
52
+ }
53
+ function getCompiledTemplate(templateId, itemIndex, item) {
54
+ const cacheKey = `${templateId}:${itemIndex}`;
55
+ if (!compiledCache[cacheKey]) {
56
+ compiledCache[cacheKey] = {
57
+ src: item.src ? (0, import_template.compile)(item.src) : void 0,
58
+ body: item.body ? (0, import_template.compile)(item.body) : void 0
59
+ };
60
+ }
61
+ return compiledCache[cacheKey];
62
+ }
63
+ function executeTemplatedScripts(scripts, templates) {
64
+ if (!scripts || typeof window === "undefined") return;
65
+ for (const script of scripts) {
66
+ if (script.type !== "script-template") {
67
+ console.warn(`[Nextlytics] unsupported script type ${script.type} `);
68
+ continue;
69
+ }
70
+ const template = templates[script.templateId];
71
+ if (!template) {
72
+ console.warn(`[Nextlytics] Missing template: ${script.templateId}`);
73
+ continue;
74
+ }
75
+ const params = script.params;
76
+ for (let i = 0; i < template.items.length; i++) {
77
+ const item = template.items[i];
78
+ const compiled = getCompiledTemplate(script.templateId, i, item);
79
+ const src = compiled.src ? (0, import_template.apply)(compiled.src, params, templateFunctions) : void 0;
80
+ if (item.singleton && src && document.querySelector(`script[src="${src}"]`)) {
81
+ continue;
82
+ }
83
+ const el = document.createElement("script");
84
+ if (src) {
85
+ el.src = src;
86
+ }
87
+ if (compiled.body) {
88
+ el.textContent = (0, import_template.apply)(compiled.body, params, templateFunctions);
89
+ }
90
+ if (item.async) {
91
+ el.async = true;
92
+ }
93
+ document.head.appendChild(el);
94
+ }
95
+ }
96
+ }
97
+ async function sendEvent(requestId, type, payload) {
98
+ try {
99
+ const response = await fetch("/api/event", {
100
+ method: "POST",
101
+ headers: {
102
+ "Content-Type": "application/json",
103
+ [import_server_component_context.headers.pageRenderId]: requestId
104
+ },
105
+ body: JSON.stringify({ type, payload })
106
+ });
107
+ if (response.status === 404) {
108
+ console.error(
109
+ "[Nextlytics] In order for NextlyticsClient to work, you must mount nextlyticsRouteHandler to /api/event"
110
+ );
111
+ return { ok: false };
112
+ }
113
+ const data = await response.json().catch(() => ({ ok: response.ok }));
114
+ return { ok: data.ok ?? response.ok, scripts: data.scripts };
115
+ } catch (error) {
116
+ console.error("[Nextlytics] Failed to send event:", error);
117
+ return { ok: false };
118
+ }
119
+ }
120
+ const initializedRequestIds = /* @__PURE__ */ new Set();
121
+ function NextlyticsClient(props) {
122
+ const requestId = props.ctx?.requestId ?? props.requestId ?? "";
123
+ const scripts = props.ctx?.scripts ?? props.scripts;
124
+ const templates = props.ctx?.templates ?? props.templates ?? {};
125
+ (0, import_react.useEffect)(() => {
126
+ if (initializedRequestIds.has(requestId)) return;
127
+ initializedRequestIds.add(requestId);
128
+ if (scripts && Object.keys(templates).length > 0) {
129
+ executeTemplatedScripts(scripts, templates);
130
+ }
131
+ const clientContext = createClientContext();
132
+ sendEvent(requestId, "client-init", clientContext).then(
133
+ ({ scripts: responseScripts }) => {
134
+ if (responseScripts) {
135
+ executeTemplatedScripts(responseScripts, templates);
136
+ }
137
+ }
138
+ );
139
+ }, [requestId, scripts, templates]);
140
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(NextlyticsContext.Provider, { value: { requestId, templates }, children: props.children });
141
+ }
142
+ function useNextlytics() {
143
+ const context = (0, import_react.useContext)(NextlyticsContext);
144
+ if (!context) {
145
+ throw new Error(
146
+ "[Nextlytics] useNextlytics() must be used within a component wrapped by <NextlyticsServer>. Add <NextlyticsServer> at the top of your layout.tsx file."
147
+ );
148
+ }
149
+ const { requestId, templates } = context;
150
+ const send = (0, import_react.useCallback)(
151
+ async (eventName, opts) => {
152
+ const result = await sendEvent(requestId, "client-event", {
153
+ name: eventName,
154
+ props: opts?.props,
155
+ collectedAt: (/* @__PURE__ */ new Date()).toISOString(),
156
+ clientContext: createClientContext()
157
+ });
158
+ if (result.scripts) {
159
+ executeTemplatedScripts(result.scripts, templates);
160
+ }
161
+ return { ok: result.ok };
162
+ },
163
+ [requestId, templates]
164
+ );
165
+ return { sendEvent: send };
166
+ }
167
+ // Annotate the CommonJS export names for ESM import in node:
168
+ 0 && (module.exports = {
169
+ NextlyticsClient,
170
+ useNextlytics
171
+ });
@@ -0,0 +1,29 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+ import { TemplatizedScriptInsertion, JavascriptTemplate } from './types.mjs';
4
+ import 'next/dist/server/web/spec-extension/cookies';
5
+ import 'next/server';
6
+
7
+ /** Context object for Pages Router integration */
8
+ type NextlyticsContext = {
9
+ requestId: string;
10
+ scripts?: TemplatizedScriptInsertion<unknown>[];
11
+ templates?: Record<string, JavascriptTemplate>;
12
+ };
13
+ declare function NextlyticsClient(props: {
14
+ ctx?: NextlyticsContext;
15
+ requestId?: string;
16
+ scripts?: TemplatizedScriptInsertion<unknown>[];
17
+ templates?: Record<string, JavascriptTemplate>;
18
+ children?: ReactNode;
19
+ }): react_jsx_runtime.JSX.Element;
20
+ type NextlyticsClientApi = {
21
+ sendEvent: (eventName: string, opts?: {
22
+ props?: Record<string, unknown>;
23
+ }) => Promise<{
24
+ ok: boolean;
25
+ }>;
26
+ };
27
+ declare function useNextlytics(): NextlyticsClientApi;
28
+
29
+ export { NextlyticsClient, type NextlyticsClientApi, type NextlyticsContext, useNextlytics };
@@ -0,0 +1,29 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+ import { TemplatizedScriptInsertion, JavascriptTemplate } from './types.js';
4
+ import 'next/dist/server/web/spec-extension/cookies';
5
+ import 'next/server';
6
+
7
+ /** Context object for Pages Router integration */
8
+ type NextlyticsContext = {
9
+ requestId: string;
10
+ scripts?: TemplatizedScriptInsertion<unknown>[];
11
+ templates?: Record<string, JavascriptTemplate>;
12
+ };
13
+ declare function NextlyticsClient(props: {
14
+ ctx?: NextlyticsContext;
15
+ requestId?: string;
16
+ scripts?: TemplatizedScriptInsertion<unknown>[];
17
+ templates?: Record<string, JavascriptTemplate>;
18
+ children?: ReactNode;
19
+ }): react_jsx_runtime.JSX.Element;
20
+ type NextlyticsClientApi = {
21
+ sendEvent: (eventName: string, opts?: {
22
+ props?: Record<string, unknown>;
23
+ }) => Promise<{
24
+ ok: boolean;
25
+ }>;
26
+ };
27
+ declare function useNextlytics(): NextlyticsClientApi;
28
+
29
+ export { NextlyticsClient, type NextlyticsClientApi, type NextlyticsContext, useNextlytics };