@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
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ import { Nextlytics, NextlyticsServer } from "./server";
2
+ import { NextlyticsClient, useNextlytics } from "./client";
3
+ import { getNextlyticsProps } from "./pages-router";
4
+ import { loggingBackend } from "./backends/logging";
5
+ export {
6
+ Nextlytics,
7
+ NextlyticsClient,
8
+ NextlyticsServer,
9
+ getNextlyticsProps,
10
+ loggingBackend,
11
+ useNextlytics
12
+ };
@@ -0,0 +1,204 @@
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 middleware_exports = {};
20
+ __export(middleware_exports, {
21
+ createNextlyticsMiddleware: () => createNextlyticsMiddleware
22
+ });
23
+ module.exports = __toCommonJS(middleware_exports);
24
+ var import_server = require("next/server");
25
+ var import_server_component_context = require("./server-component-context");
26
+ var import_uitils = require("./uitils");
27
+ var import_anonymous_user = require("./anonymous-user");
28
+ function resolveBackends(config, ctx) {
29
+ const backends = config.backends || [];
30
+ return backends.map((backend) => typeof backend === "function" ? backend(ctx) : backend).filter((b) => b !== null);
31
+ }
32
+ function collectTemplates(backends) {
33
+ const templates = {};
34
+ for (const backend of backends) {
35
+ if (backend.getClientSideTemplates) {
36
+ Object.assign(templates, backend.getClientSideTemplates());
37
+ }
38
+ }
39
+ return templates;
40
+ }
41
+ function createRequestContext(request) {
42
+ return {
43
+ headers: request.headers,
44
+ cookies: request.cookies
45
+ };
46
+ }
47
+ function createNextlyticsMiddleware(config, dispatchEvent, updateEvent) {
48
+ const { eventEndpoint } = config;
49
+ return async (request) => {
50
+ const pathname = request.nextUrl.pathname;
51
+ const reqInfo = (0, import_uitils.getRequestInfo)(request);
52
+ if (pathname === eventEndpoint) {
53
+ if (request.method === "POST") {
54
+ return handleEventPost(request, config, dispatchEvent, updateEvent);
55
+ }
56
+ return Response.json({ error: "Method not allowed" }, { status: 405 });
57
+ }
58
+ if (reqInfo.isNextjsInternal || reqInfo.isPrefetch || reqInfo.isStaticFile) {
59
+ return import_server.NextResponse.next();
60
+ }
61
+ const pageRenderId = (0, import_uitils.generateId)();
62
+ const serverContext = (0, import_uitils.createServerContext)(request);
63
+ const response = import_server.NextResponse.next();
64
+ const ctx = createRequestContext(request);
65
+ const { anonId } = await (0, import_anonymous_user.resolveAnonymousUser)({ ctx, serverContext, config, response });
66
+ const backends = resolveBackends(config, ctx);
67
+ const templates = collectTemplates(backends);
68
+ let scripts = [];
69
+ if (config.pageViewMode !== "client-init") {
70
+ if (config.excludePaths?.(pathname)) {
71
+ (0, import_server_component_context.serializeServerComponentContext)(response, {
72
+ pageRenderId,
73
+ pathname: request.nextUrl.pathname,
74
+ search: request.nextUrl.search,
75
+ scripts,
76
+ templates
77
+ });
78
+ return response;
79
+ }
80
+ const isApiPath = config.isApiPath(pathname);
81
+ if (isApiPath && config.excludeApiCalls) {
82
+ (0, import_server_component_context.serializeServerComponentContext)(response, {
83
+ pageRenderId,
84
+ pathname: request.nextUrl.pathname,
85
+ search: request.nextUrl.search,
86
+ scripts,
87
+ templates
88
+ });
89
+ return response;
90
+ }
91
+ const userContext = await getUserContext(config, ctx);
92
+ const pageViewEvent = createPageViewEvent(
93
+ pageRenderId,
94
+ serverContext,
95
+ isApiPath,
96
+ userContext,
97
+ anonId
98
+ );
99
+ const { clientActions, completion } = dispatchEvent(pageViewEvent, ctx);
100
+ const actions = await clientActions;
101
+ scripts = actions.items.filter(
102
+ (i) => i.type === "script-template"
103
+ );
104
+ (0, import_server.after)(() => completion);
105
+ }
106
+ (0, import_server_component_context.serializeServerComponentContext)(response, {
107
+ pageRenderId,
108
+ pathname: request.nextUrl.pathname,
109
+ search: request.nextUrl.search,
110
+ scripts,
111
+ templates
112
+ });
113
+ return response;
114
+ };
115
+ }
116
+ function createPageViewEvent(pageRenderId, serverContext, isApiPath, userContext, anonymousUserId) {
117
+ const eventType = isApiPath ? "apiCall" : "pageView";
118
+ return {
119
+ collectedAt: serverContext.collectedAt.toISOString(),
120
+ eventId: pageRenderId,
121
+ type: eventType,
122
+ anonymousUserId,
123
+ serverContext,
124
+ userContext,
125
+ properties: {}
126
+ };
127
+ }
128
+ async function getUserContext(config, ctx) {
129
+ if (!config.callbacks.getUser) return void 0;
130
+ try {
131
+ return await config.callbacks.getUser(ctx) || void 0;
132
+ } catch {
133
+ return void 0;
134
+ }
135
+ }
136
+ async function handleEventPost(request, config, dispatchEvent, updateEvent) {
137
+ const pageRenderId = request.headers.get(import_server_component_context.headers.pageRenderId);
138
+ if (!pageRenderId) {
139
+ return Response.json({ error: "Missing page render ID" }, { status: 400 });
140
+ }
141
+ let body;
142
+ try {
143
+ body = await request.json();
144
+ } catch {
145
+ return Response.json({ error: "Invalid JSON" }, { status: 400 });
146
+ }
147
+ const { type, payload } = body;
148
+ const ctx = createRequestContext(request);
149
+ const serverContext = (0, import_uitils.createServerContext)(request);
150
+ const userContext = await getUserContext(config, ctx);
151
+ const { anonId: anonymousUserId } = await (0, import_anonymous_user.resolveAnonymousUser)({ ctx, serverContext, config });
152
+ if (type === "client-init") {
153
+ const clientContext = payload;
154
+ if (clientContext?.path) {
155
+ serverContext.path = clientContext.path;
156
+ }
157
+ if (config.pageViewMode === "client-init") {
158
+ const event = {
159
+ eventId: pageRenderId,
160
+ type: "pageView",
161
+ collectedAt: (/* @__PURE__ */ new Date()).toISOString(),
162
+ anonymousUserId,
163
+ serverContext,
164
+ clientContext,
165
+ userContext,
166
+ properties: {}
167
+ };
168
+ const { clientActions, completion } = dispatchEvent(event, ctx);
169
+ const actions = await clientActions;
170
+ (0, import_server.after)(() => completion);
171
+ const scripts = actions.items.filter((i) => i.type === "script-template");
172
+ return Response.json({ ok: true, scripts: scripts.length > 0 ? scripts : void 0 });
173
+ } else {
174
+ (0, import_server.after)(() => updateEvent(pageRenderId, { clientContext, userContext, anonymousUserId }, ctx));
175
+ return Response.json({ ok: true });
176
+ }
177
+ } else if (type === "client-event") {
178
+ const clientContext = payload.clientContext || void 0;
179
+ if (clientContext?.path) {
180
+ serverContext.path = clientContext.path;
181
+ }
182
+ const event = {
183
+ eventId: (0, import_uitils.generateId)(),
184
+ parentEventId: pageRenderId,
185
+ type: payload.name || type,
186
+ collectedAt: payload.collectedAt || (/* @__PURE__ */ new Date()).toISOString(),
187
+ anonymousUserId,
188
+ serverContext,
189
+ clientContext,
190
+ userContext,
191
+ properties: payload.props || {}
192
+ };
193
+ const { clientActions, completion } = dispatchEvent(event, ctx);
194
+ const actions = await clientActions;
195
+ (0, import_server.after)(() => completion);
196
+ const scripts = actions.items.filter((i) => i.type === "script-template");
197
+ return Response.json({ ok: true, scripts: scripts.length > 0 ? scripts : void 0 });
198
+ }
199
+ return Response.json({ ok: true });
200
+ }
201
+ // Annotate the CommonJS export names for ESM import in node:
202
+ 0 && (module.exports = {
203
+ createNextlyticsMiddleware
204
+ });
@@ -0,0 +1,10 @@
1
+ import { NextMiddleware } from 'next/server';
2
+ import { NextlyticsEvent, RequestContext, DispatchResult } from './types.mjs';
3
+ import { NextlyticsConfigWithDefaults } from './config-helpers.mjs';
4
+ import 'next/dist/server/web/spec-extension/cookies';
5
+
6
+ type DispatchEvent = (event: NextlyticsEvent, ctx: RequestContext) => DispatchResult;
7
+ type UpdateEvent = (eventId: string, patch: Partial<NextlyticsEvent>, ctx: RequestContext) => Promise<void>;
8
+ declare function createNextlyticsMiddleware(config: NextlyticsConfigWithDefaults, dispatchEvent: DispatchEvent, updateEvent: UpdateEvent): NextMiddleware;
9
+
10
+ export { createNextlyticsMiddleware };
@@ -0,0 +1,10 @@
1
+ import { NextMiddleware } from 'next/server';
2
+ import { NextlyticsEvent, RequestContext, DispatchResult } from './types.js';
3
+ import { NextlyticsConfigWithDefaults } from './config-helpers.js';
4
+ import 'next/dist/server/web/spec-extension/cookies';
5
+
6
+ type DispatchEvent = (event: NextlyticsEvent, ctx: RequestContext) => DispatchResult;
7
+ type UpdateEvent = (eventId: string, patch: Partial<NextlyticsEvent>, ctx: RequestContext) => Promise<void>;
8
+ declare function createNextlyticsMiddleware(config: NextlyticsConfigWithDefaults, dispatchEvent: DispatchEvent, updateEvent: UpdateEvent): NextMiddleware;
9
+
10
+ export { createNextlyticsMiddleware };
@@ -0,0 +1,183 @@
1
+ import { NextResponse, after } from "next/server";
2
+ import {
3
+ headers as analyticsHeaders,
4
+ serializeServerComponentContext
5
+ } from "./server-component-context";
6
+ import { generateId, getRequestInfo, createServerContext } from "./uitils";
7
+ import { resolveAnonymousUser } from "./anonymous-user";
8
+ function resolveBackends(config, ctx) {
9
+ const backends = config.backends || [];
10
+ return backends.map((backend) => typeof backend === "function" ? backend(ctx) : backend).filter((b) => b !== null);
11
+ }
12
+ function collectTemplates(backends) {
13
+ const templates = {};
14
+ for (const backend of backends) {
15
+ if (backend.getClientSideTemplates) {
16
+ Object.assign(templates, backend.getClientSideTemplates());
17
+ }
18
+ }
19
+ return templates;
20
+ }
21
+ function createRequestContext(request) {
22
+ return {
23
+ headers: request.headers,
24
+ cookies: request.cookies
25
+ };
26
+ }
27
+ function createNextlyticsMiddleware(config, dispatchEvent, updateEvent) {
28
+ const { eventEndpoint } = config;
29
+ return async (request) => {
30
+ const pathname = request.nextUrl.pathname;
31
+ const reqInfo = getRequestInfo(request);
32
+ if (pathname === eventEndpoint) {
33
+ if (request.method === "POST") {
34
+ return handleEventPost(request, config, dispatchEvent, updateEvent);
35
+ }
36
+ return Response.json({ error: "Method not allowed" }, { status: 405 });
37
+ }
38
+ if (reqInfo.isNextjsInternal || reqInfo.isPrefetch || reqInfo.isStaticFile) {
39
+ return NextResponse.next();
40
+ }
41
+ const pageRenderId = generateId();
42
+ const serverContext = createServerContext(request);
43
+ const response = NextResponse.next();
44
+ const ctx = createRequestContext(request);
45
+ const { anonId } = await resolveAnonymousUser({ ctx, serverContext, config, response });
46
+ const backends = resolveBackends(config, ctx);
47
+ const templates = collectTemplates(backends);
48
+ let scripts = [];
49
+ if (config.pageViewMode !== "client-init") {
50
+ if (config.excludePaths?.(pathname)) {
51
+ serializeServerComponentContext(response, {
52
+ pageRenderId,
53
+ pathname: request.nextUrl.pathname,
54
+ search: request.nextUrl.search,
55
+ scripts,
56
+ templates
57
+ });
58
+ return response;
59
+ }
60
+ const isApiPath = config.isApiPath(pathname);
61
+ if (isApiPath && config.excludeApiCalls) {
62
+ serializeServerComponentContext(response, {
63
+ pageRenderId,
64
+ pathname: request.nextUrl.pathname,
65
+ search: request.nextUrl.search,
66
+ scripts,
67
+ templates
68
+ });
69
+ return response;
70
+ }
71
+ const userContext = await getUserContext(config, ctx);
72
+ const pageViewEvent = createPageViewEvent(
73
+ pageRenderId,
74
+ serverContext,
75
+ isApiPath,
76
+ userContext,
77
+ anonId
78
+ );
79
+ const { clientActions, completion } = dispatchEvent(pageViewEvent, ctx);
80
+ const actions = await clientActions;
81
+ scripts = actions.items.filter(
82
+ (i) => i.type === "script-template"
83
+ );
84
+ after(() => completion);
85
+ }
86
+ serializeServerComponentContext(response, {
87
+ pageRenderId,
88
+ pathname: request.nextUrl.pathname,
89
+ search: request.nextUrl.search,
90
+ scripts,
91
+ templates
92
+ });
93
+ return response;
94
+ };
95
+ }
96
+ function createPageViewEvent(pageRenderId, serverContext, isApiPath, userContext, anonymousUserId) {
97
+ const eventType = isApiPath ? "apiCall" : "pageView";
98
+ return {
99
+ collectedAt: serverContext.collectedAt.toISOString(),
100
+ eventId: pageRenderId,
101
+ type: eventType,
102
+ anonymousUserId,
103
+ serverContext,
104
+ userContext,
105
+ properties: {}
106
+ };
107
+ }
108
+ async function getUserContext(config, ctx) {
109
+ if (!config.callbacks.getUser) return void 0;
110
+ try {
111
+ return await config.callbacks.getUser(ctx) || void 0;
112
+ } catch {
113
+ return void 0;
114
+ }
115
+ }
116
+ async function handleEventPost(request, config, dispatchEvent, updateEvent) {
117
+ const pageRenderId = request.headers.get(analyticsHeaders.pageRenderId);
118
+ if (!pageRenderId) {
119
+ return Response.json({ error: "Missing page render ID" }, { status: 400 });
120
+ }
121
+ let body;
122
+ try {
123
+ body = await request.json();
124
+ } catch {
125
+ return Response.json({ error: "Invalid JSON" }, { status: 400 });
126
+ }
127
+ const { type, payload } = body;
128
+ const ctx = createRequestContext(request);
129
+ const serverContext = createServerContext(request);
130
+ const userContext = await getUserContext(config, ctx);
131
+ const { anonId: anonymousUserId } = await resolveAnonymousUser({ ctx, serverContext, config });
132
+ if (type === "client-init") {
133
+ const clientContext = payload;
134
+ if (clientContext?.path) {
135
+ serverContext.path = clientContext.path;
136
+ }
137
+ if (config.pageViewMode === "client-init") {
138
+ const event = {
139
+ eventId: pageRenderId,
140
+ type: "pageView",
141
+ collectedAt: (/* @__PURE__ */ new Date()).toISOString(),
142
+ anonymousUserId,
143
+ serverContext,
144
+ clientContext,
145
+ userContext,
146
+ properties: {}
147
+ };
148
+ const { clientActions, completion } = dispatchEvent(event, ctx);
149
+ const actions = await clientActions;
150
+ after(() => completion);
151
+ const scripts = actions.items.filter((i) => i.type === "script-template");
152
+ return Response.json({ ok: true, scripts: scripts.length > 0 ? scripts : void 0 });
153
+ } else {
154
+ after(() => updateEvent(pageRenderId, { clientContext, userContext, anonymousUserId }, ctx));
155
+ return Response.json({ ok: true });
156
+ }
157
+ } else if (type === "client-event") {
158
+ const clientContext = payload.clientContext || void 0;
159
+ if (clientContext?.path) {
160
+ serverContext.path = clientContext.path;
161
+ }
162
+ const event = {
163
+ eventId: generateId(),
164
+ parentEventId: pageRenderId,
165
+ type: payload.name || type,
166
+ collectedAt: payload.collectedAt || (/* @__PURE__ */ new Date()).toISOString(),
167
+ anonymousUserId,
168
+ serverContext,
169
+ clientContext,
170
+ userContext,
171
+ properties: payload.props || {}
172
+ };
173
+ const { clientActions, completion } = dispatchEvent(event, ctx);
174
+ const actions = await clientActions;
175
+ after(() => completion);
176
+ const scripts = actions.items.filter((i) => i.type === "script-template");
177
+ return Response.json({ ok: true, scripts: scripts.length > 0 ? scripts : void 0 });
178
+ }
179
+ return Response.json({ ok: true });
180
+ }
181
+ export {
182
+ createNextlyticsMiddleware
183
+ };
@@ -0,0 +1,45 @@
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 pages_router_exports = {};
20
+ __export(pages_router_exports, {
21
+ getNextlyticsProps: () => getNextlyticsProps
22
+ });
23
+ module.exports = __toCommonJS(pages_router_exports);
24
+ var import_server_component_context = require("./server-component-context");
25
+ function getNextlyticsProps(ctx) {
26
+ const headersList = new Headers();
27
+ for (const [key, value] of Object.entries(ctx.req.headers)) {
28
+ if (value) {
29
+ headersList.set(key, Array.isArray(value) ? value[0] : value);
30
+ }
31
+ }
32
+ const context = (0, import_server_component_context.restoreServerComponentContext)(headersList);
33
+ if (!context) {
34
+ return { requestId: "" };
35
+ }
36
+ return {
37
+ requestId: context.pageRenderId,
38
+ scripts: context.scripts,
39
+ templates: context.templates
40
+ };
41
+ }
42
+ // Annotate the CommonJS export names for ESM import in node:
43
+ 0 && (module.exports = {
44
+ getNextlyticsProps
45
+ });
@@ -0,0 +1,45 @@
1
+ import { NextlyticsContext } from './client.mjs';
2
+ import 'react/jsx-runtime';
3
+ import 'react';
4
+ import './types.mjs';
5
+ import 'next/dist/server/web/spec-extension/cookies';
6
+ import 'next/server';
7
+
8
+ type ContextWithHeaders = {
9
+ req: {
10
+ headers: Record<string, string | string[] | undefined>;
11
+ };
12
+ };
13
+ /**
14
+ * Extract Nextlytics context from Pages Router context (getServerSideProps or getInitialProps).
15
+ * Use this in _app.tsx with getInitialProps to pass context to NextlyticsClient.
16
+ *
17
+ * @example
18
+ * ```tsx
19
+ * // pages/_app.tsx
20
+ * import type { AppContext, AppProps } from 'next/app'
21
+ * import { NextlyticsClient, getNextlyticsProps, type NextlyticsContext } from '@nextlytics/core'
22
+ *
23
+ * type MyAppProps = AppProps & { nextlyticsCtx: NextlyticsContext }
24
+ *
25
+ * function MyApp({ Component, pageProps, nextlyticsCtx }: MyAppProps) {
26
+ * return (
27
+ * <NextlyticsClient ctx={nextlyticsCtx}>
28
+ * <Component {...pageProps} />
29
+ * </NextlyticsClient>
30
+ * )
31
+ * }
32
+ *
33
+ * MyApp.getInitialProps = async (appContext: AppContext) => {
34
+ * return {
35
+ * pageProps: appContext.Component.getInitialProps
36
+ * ? await appContext.Component.getInitialProps(appContext.ctx)
37
+ * : {},
38
+ * nextlyticsCtx: getNextlyticsProps(appContext.ctx),
39
+ * }
40
+ * }
41
+ * ```
42
+ */
43
+ declare function getNextlyticsProps(ctx: ContextWithHeaders): NextlyticsContext;
44
+
45
+ export { getNextlyticsProps };
@@ -0,0 +1,45 @@
1
+ import { NextlyticsContext } from './client.js';
2
+ import 'react/jsx-runtime';
3
+ import 'react';
4
+ import './types.js';
5
+ import 'next/dist/server/web/spec-extension/cookies';
6
+ import 'next/server';
7
+
8
+ type ContextWithHeaders = {
9
+ req: {
10
+ headers: Record<string, string | string[] | undefined>;
11
+ };
12
+ };
13
+ /**
14
+ * Extract Nextlytics context from Pages Router context (getServerSideProps or getInitialProps).
15
+ * Use this in _app.tsx with getInitialProps to pass context to NextlyticsClient.
16
+ *
17
+ * @example
18
+ * ```tsx
19
+ * // pages/_app.tsx
20
+ * import type { AppContext, AppProps } from 'next/app'
21
+ * import { NextlyticsClient, getNextlyticsProps, type NextlyticsContext } from '@nextlytics/core'
22
+ *
23
+ * type MyAppProps = AppProps & { nextlyticsCtx: NextlyticsContext }
24
+ *
25
+ * function MyApp({ Component, pageProps, nextlyticsCtx }: MyAppProps) {
26
+ * return (
27
+ * <NextlyticsClient ctx={nextlyticsCtx}>
28
+ * <Component {...pageProps} />
29
+ * </NextlyticsClient>
30
+ * )
31
+ * }
32
+ *
33
+ * MyApp.getInitialProps = async (appContext: AppContext) => {
34
+ * return {
35
+ * pageProps: appContext.Component.getInitialProps
36
+ * ? await appContext.Component.getInitialProps(appContext.ctx)
37
+ * : {},
38
+ * nextlyticsCtx: getNextlyticsProps(appContext.ctx),
39
+ * }
40
+ * }
41
+ * ```
42
+ */
43
+ declare function getNextlyticsProps(ctx: ContextWithHeaders): NextlyticsContext;
44
+
45
+ export { getNextlyticsProps };
@@ -0,0 +1,21 @@
1
+ import { restoreServerComponentContext } from "./server-component-context";
2
+ function getNextlyticsProps(ctx) {
3
+ const headersList = new Headers();
4
+ for (const [key, value] of Object.entries(ctx.req.headers)) {
5
+ if (value) {
6
+ headersList.set(key, Array.isArray(value) ? value[0] : value);
7
+ }
8
+ }
9
+ const context = restoreServerComponentContext(headersList);
10
+ if (!context) {
11
+ return { requestId: "" };
12
+ }
13
+ return {
14
+ requestId: context.pageRenderId,
15
+ scripts: context.scripts,
16
+ templates: context.templates
17
+ };
18
+ }
19
+ export {
20
+ getNextlyticsProps
21
+ };
@@ -0,0 +1,60 @@
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 vercel_geo_exports = {};
20
+ __export(vercel_geo_exports, {
21
+ vercelGeoPlugin: () => vercelGeoPlugin
22
+ });
23
+ module.exports = __toCommonJS(vercel_geo_exports);
24
+ const VERCEL_GEO_HEADERS = {
25
+ "x-vercel-ip-country": "country",
26
+ "x-vercel-ip-country-region": "region",
27
+ "x-vercel-ip-city": "city",
28
+ "x-vercel-ip-latitude": "latitude",
29
+ "x-vercel-ip-longitude": "longitude",
30
+ "x-vercel-ip-timezone": "timezone"
31
+ };
32
+ function vercelGeoPlugin(options) {
33
+ const geoPropertyName = options?.geoPropertyName ?? "geo";
34
+ return {
35
+ async onDispatch(event) {
36
+ const headers = event.serverContext.requestHeaders;
37
+ const geo = {};
38
+ for (const [header, prop] of Object.entries(VERCEL_GEO_HEADERS)) {
39
+ const value = headers[header];
40
+ if (value) {
41
+ if (prop === "latitude" || prop === "longitude") {
42
+ const num = parseFloat(value);
43
+ if (!isNaN(num)) {
44
+ geo[prop] = num;
45
+ }
46
+ } else {
47
+ geo[prop] = value;
48
+ }
49
+ }
50
+ }
51
+ if (Object.keys(geo).length > 0) {
52
+ event.properties[geoPropertyName] = geo;
53
+ }
54
+ }
55
+ };
56
+ }
57
+ // Annotate the CommonJS export names for ESM import in node:
58
+ 0 && (module.exports = {
59
+ vercelGeoPlugin
60
+ });
@@ -0,0 +1,25 @@
1
+ import { NextlyticsPlugin } from '../types.mjs';
2
+ import 'next/dist/server/web/spec-extension/cookies';
3
+ import 'next/server';
4
+
5
+ type VercelGeoPluginOptions = {
6
+ /** Property name to store geo data under. Default: "geo" */
7
+ geoPropertyName?: string;
8
+ };
9
+ /**
10
+ * Plugin that extracts Vercel geo headers and adds them to event properties.
11
+ * Only works when deployed to Vercel.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { vercelGeoPlugin } from "@nextlytics/core/plugins/vercel-geo";
16
+ *
17
+ * export const { middleware, handlers } = Nextlytics({
18
+ * plugins: [vercelGeoPlugin()],
19
+ * // ...
20
+ * });
21
+ * ```
22
+ */
23
+ declare function vercelGeoPlugin(options?: VercelGeoPluginOptions): NextlyticsPlugin;
24
+
25
+ export { type VercelGeoPluginOptions, vercelGeoPlugin };