@nextlytics/core 0.3.0-canary.80 → 0.3.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.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- export { Nextlytics } from './server.js';
2
- export { getNextlyticsProps } from './pages-router.js';
1
+ export { Nextlytics, NextlyticsServer } from './server.js';
3
2
  export { NextlyticsClient, NextlyticsContext, useNextlytics } from './client.js';
3
+ export { getNextlyticsProps } from './pages-router.js';
4
4
  export { loggingBackend } from './backends/logging.js';
5
- export { AnonymousUserResult, BackendConfigEntry, BackendWithConfig, ClientAction, ClientContext, ClientRequest, JavascriptTemplate, NextlyticsBackend, NextlyticsBackendFactory, NextlyticsClientContext, NextlyticsConfig, NextlyticsEvent, NextlyticsPlugin, NextlyticsPluginFactory, NextlyticsResult, NextlyticsServerSide, PageViewDelivery, PagesRouterContext, RequestContext, ServerEventContext, UserContext } from './types.js';
5
+ export { AnonymousUserResult, BackendConfigEntry, BackendWithConfig, ClientContext, IngestPolicy, NextlyticsBackend, NextlyticsBackendFactory, NextlyticsConfig, NextlyticsEvent, NextlyticsPlugin, NextlyticsPluginFactory, NextlyticsResult, NextlyticsServerSide, RequestContext, ServerEventContext, UserContext } from './types.js';
6
6
  import 'react/jsx-runtime';
7
7
  import 'react';
8
8
  import 'next/dist/server/web/spec-extension/cookies';
package/dist/index.js CHANGED
@@ -20,19 +20,21 @@ var index_exports = {};
20
20
  __export(index_exports, {
21
21
  Nextlytics: () => import_server.Nextlytics,
22
22
  NextlyticsClient: () => import_client.NextlyticsClient,
23
+ NextlyticsServer: () => import_server.NextlyticsServer,
23
24
  getNextlyticsProps: () => import_pages_router.getNextlyticsProps,
24
25
  loggingBackend: () => import_logging.loggingBackend,
25
26
  useNextlytics: () => import_client.useNextlytics
26
27
  });
27
28
  module.exports = __toCommonJS(index_exports);
28
29
  var import_server = require("./server");
29
- var import_pages_router = require("./pages-router");
30
30
  var import_client = require("./client");
31
+ var import_pages_router = require("./pages-router");
31
32
  var import_logging = require("./backends/logging");
32
33
  // Annotate the CommonJS export names for ESM import in node:
33
34
  0 && (module.exports = {
34
35
  Nextlytics,
35
36
  NextlyticsClient,
37
+ NextlyticsServer,
36
38
  getNextlyticsProps,
37
39
  loggingBackend,
38
40
  useNextlytics
@@ -1,9 +1,10 @@
1
1
  import { NextMiddleware } from 'next/server';
2
+ import { NextlyticsEvent, RequestContext, IngestPolicy, DispatchResult } from './types.js';
2
3
  import { NextlyticsConfigWithDefaults } from './config-helpers.js';
3
- import { DispatchEvent, UpdateEvent } from './api-handler.js';
4
- import './types.js';
5
4
  import 'next/dist/server/web/spec-extension/cookies';
6
5
 
6
+ type DispatchEvent = (event: NextlyticsEvent, ctx: RequestContext, policyFilter?: IngestPolicy) => DispatchResult;
7
+ type UpdateEvent = (eventId: string, patch: Partial<NextlyticsEvent>, ctx: RequestContext) => Promise<void>;
7
8
  declare function createNextlyticsMiddleware(config: NextlyticsConfigWithDefaults, dispatchEvent: DispatchEvent, updateEvent: UpdateEvent): NextMiddleware;
8
9
 
9
10
  export { createNextlyticsMiddleware };
@@ -25,7 +25,29 @@ var import_server = require("next/server");
25
25
  var import_server_component_context = require("./server-component-context");
26
26
  var import_uitils = require("./uitils");
27
27
  var import_anonymous_user = require("./anonymous-user");
28
- var import_api_handler = require("./api-handler");
28
+ function isBackendWithConfig(entry) {
29
+ return typeof entry === "object" && entry !== null && "backend" in entry;
30
+ }
31
+ function resolveBackends(config, ctx) {
32
+ const entries = config.backends || [];
33
+ return entries.map((entry) => {
34
+ if (isBackendWithConfig(entry)) {
35
+ const backend2 = typeof entry.backend === "function" ? entry.backend(ctx) : entry.backend;
36
+ return backend2 ? { backend: backend2, ingestPolicy: entry.ingestPolicy ?? "immediate" } : null;
37
+ }
38
+ const backend = typeof entry === "function" ? entry(ctx) : entry;
39
+ return backend ? { backend, ingestPolicy: "immediate" } : null;
40
+ }).filter((b) => b !== null);
41
+ }
42
+ function collectTemplates(backends) {
43
+ const templates = {};
44
+ for (const { backend } of backends) {
45
+ if (backend.getClientSideTemplates) {
46
+ Object.assign(templates, backend.getClientSideTemplates());
47
+ }
48
+ }
49
+ return templates;
50
+ }
29
51
  function createRequestContext(request) {
30
52
  return {
31
53
  headers: request.headers,
@@ -37,57 +59,29 @@ function createNextlyticsMiddleware(config, dispatchEvent, updateEvent) {
37
59
  return async (request) => {
38
60
  const pathname = request.nextUrl.pathname;
39
61
  const reqInfo = (0, import_uitils.getRequestInfo)(request);
40
- const middlewareDebug = config.debug || process.env.NEXTLYTICS_MIDDLEWARE_DEBUG === "true";
41
- if (middlewareDebug) {
42
- const headers = request.headers;
43
- const debugHeaders = {};
44
- headers.forEach((value, key) => {
45
- debugHeaders[key] = value;
46
- });
47
- console.log("[Nextlytics][middleware]", {
48
- url: request.url,
49
- pathname,
50
- search: request.nextUrl.search,
51
- method: request.method,
52
- nextVersion: (0, import_uitils.getNextVersion)(),
53
- destination: request.destination,
54
- referrer: request.referrer,
55
- mode: request.mode,
56
- cache: request.cache,
57
- redirect: request.redirect,
58
- integrity: request.integrity,
59
- isPrefetch: reqInfo.isPrefetch,
60
- isRsc: reqInfo.isRsc,
61
- isPageNavigation: reqInfo.isPageNavigation,
62
- isStaticFile: reqInfo.isStaticFile,
63
- isNextjsInternal: reqInfo.isNextjsInternal,
64
- headers: debugHeaders
65
- });
66
- }
67
62
  if (pathname === eventEndpoint) {
68
63
  if (request.method === "POST") {
69
- return (0, import_api_handler.handleEventPost)(request, config, dispatchEvent, updateEvent);
64
+ return handleEventPost(request, config, dispatchEvent, updateEvent);
70
65
  }
71
66
  return Response.json({ error: "Method not allowed" }, { status: 405 });
72
67
  }
73
68
  if (reqInfo.isNextjsInternal || reqInfo.isPrefetch || reqInfo.isStaticFile) {
74
69
  return import_server.NextResponse.next();
75
70
  }
76
- if (!reqInfo.isPageNavigation && !config.isApiPath(pathname)) {
77
- return import_server.NextResponse.next();
78
- }
79
71
  const pageRenderId = (0, import_uitils.generateId)();
80
72
  const serverContext = (0, import_uitils.createServerContext)(request);
81
73
  const response = import_server.NextResponse.next();
82
74
  const ctx = createRequestContext(request);
83
- response.cookies.set(import_server_component_context.LAST_PAGE_RENDER_ID_COOKIE, pageRenderId, { path: "/" });
84
75
  const { anonId } = await (0, import_anonymous_user.resolveAnonymousUser)({ ctx, serverContext, config, response });
76
+ const backends = resolveBackends(config, ctx);
77
+ const templates = collectTemplates(backends);
85
78
  if (config.excludePaths?.(pathname)) {
86
79
  (0, import_server_component_context.serializeServerComponentContext)(response, {
87
80
  pageRenderId,
88
81
  pathname: request.nextUrl.pathname,
89
82
  search: request.nextUrl.search,
90
- scripts: []
83
+ scripts: [],
84
+ templates
91
85
  });
92
86
  return response;
93
87
  }
@@ -97,11 +91,12 @@ function createNextlyticsMiddleware(config, dispatchEvent, updateEvent) {
97
91
  pageRenderId,
98
92
  pathname: request.nextUrl.pathname,
99
93
  search: request.nextUrl.search,
100
- scripts: []
94
+ scripts: [],
95
+ templates
101
96
  });
102
97
  return response;
103
98
  }
104
- const userContext = await (0, import_api_handler.getUserContext)(config, ctx);
99
+ const userContext = await getUserContext(config, ctx);
105
100
  const pageViewEvent = createPageViewEvent(
106
101
  pageRenderId,
107
102
  serverContext,
@@ -109,7 +104,7 @@ function createNextlyticsMiddleware(config, dispatchEvent, updateEvent) {
109
104
  userContext,
110
105
  anonId
111
106
  );
112
- const { clientActions, completion } = dispatchEvent(pageViewEvent, ctx, "on-request");
107
+ const { clientActions, completion } = dispatchEvent(pageViewEvent, ctx, "immediate");
113
108
  const actions = await clientActions;
114
109
  const scripts = actions.items.filter(
115
110
  (i) => i.type === "script-template"
@@ -119,7 +114,8 @@ function createNextlyticsMiddleware(config, dispatchEvent, updateEvent) {
119
114
  pageRenderId,
120
115
  pathname: request.nextUrl.pathname,
121
116
  search: request.nextUrl.search,
122
- scripts
117
+ scripts,
118
+ templates
123
119
  });
124
120
  return response;
125
121
  };
@@ -127,7 +123,6 @@ function createNextlyticsMiddleware(config, dispatchEvent, updateEvent) {
127
123
  function createPageViewEvent(pageRenderId, serverContext, isApiPath, userContext, anonymousUserId) {
128
124
  const eventType = isApiPath ? "apiCall" : "pageView";
129
125
  return {
130
- origin: "server",
131
126
  collectedAt: serverContext.collectedAt.toISOString(),
132
127
  eventId: pageRenderId,
133
128
  type: eventType,
@@ -137,6 +132,99 @@ function createPageViewEvent(pageRenderId, serverContext, isApiPath, userContext
137
132
  properties: {}
138
133
  };
139
134
  }
135
+ async function getUserContext(config, ctx) {
136
+ if (!config.callbacks.getUser) return void 0;
137
+ try {
138
+ return await config.callbacks.getUser(ctx) || void 0;
139
+ } catch {
140
+ return void 0;
141
+ }
142
+ }
143
+ function reconstructServerContext(apiCallContext, clientInit) {
144
+ const searchParams = {};
145
+ if (clientInit.search) {
146
+ const params = new URLSearchParams(clientInit.search);
147
+ params.forEach((value, key) => {
148
+ if (!searchParams[key]) searchParams[key] = [];
149
+ searchParams[key].push(value);
150
+ });
151
+ }
152
+ return {
153
+ ...apiCallContext,
154
+ // Override with client-provided values
155
+ host: clientInit.host || apiCallContext.host,
156
+ path: clientInit.path || apiCallContext.path,
157
+ search: Object.keys(searchParams).length > 0 ? searchParams : apiCallContext.search,
158
+ method: "GET"
159
+ // Page loads are always GET
160
+ };
161
+ }
162
+ async function handleEventPost(request, config, dispatchEvent, updateEvent) {
163
+ const pageRenderId = request.headers.get(import_server_component_context.headers.pageRenderId);
164
+ if (!pageRenderId) {
165
+ return Response.json({ error: "Missing page render ID" }, { status: 400 });
166
+ }
167
+ let body;
168
+ try {
169
+ body = await request.json();
170
+ } catch {
171
+ return Response.json({ error: "Invalid JSON" }, { status: 400 });
172
+ }
173
+ const { type, payload } = body;
174
+ const ctx = createRequestContext(request);
175
+ const apiCallServerContext = (0, import_uitils.createServerContext)(request);
176
+ const userContext = await getUserContext(config, ctx);
177
+ if (type === "client-init") {
178
+ const clientContext = payload;
179
+ const serverContext = reconstructServerContext(apiCallServerContext, clientContext);
180
+ const { anonId: anonymousUserId } = await (0, import_anonymous_user.resolveAnonymousUser)({
181
+ ctx,
182
+ serverContext,
183
+ config
184
+ });
185
+ const event = {
186
+ eventId: pageRenderId,
187
+ type: "pageView",
188
+ collectedAt: (/* @__PURE__ */ new Date()).toISOString(),
189
+ anonymousUserId,
190
+ serverContext,
191
+ clientContext,
192
+ userContext,
193
+ properties: {}
194
+ };
195
+ const { clientActions, completion } = dispatchEvent(event, ctx, "on-client-event");
196
+ const actions = await clientActions;
197
+ (0, import_server.after)(() => completion);
198
+ (0, import_server.after)(() => updateEvent(pageRenderId, { clientContext, userContext, anonymousUserId }, ctx));
199
+ const scripts = actions.items.filter((i) => i.type === "script-template");
200
+ return Response.json({ ok: true, scripts: scripts.length > 0 ? scripts : void 0 });
201
+ } else if (type === "client-event") {
202
+ const clientContext = payload.clientContext || void 0;
203
+ const serverContext = clientContext ? reconstructServerContext(apiCallServerContext, clientContext) : apiCallServerContext;
204
+ const { anonId: anonymousUserId } = await (0, import_anonymous_user.resolveAnonymousUser)({
205
+ ctx,
206
+ serverContext,
207
+ config
208
+ });
209
+ const event = {
210
+ eventId: (0, import_uitils.generateId)(),
211
+ parentEventId: pageRenderId,
212
+ type: payload.name || type,
213
+ collectedAt: payload.collectedAt || (/* @__PURE__ */ new Date()).toISOString(),
214
+ anonymousUserId,
215
+ serverContext,
216
+ clientContext,
217
+ userContext,
218
+ properties: payload.props || {}
219
+ };
220
+ const { clientActions, completion } = dispatchEvent(event, ctx);
221
+ const actions = await clientActions;
222
+ (0, import_server.after)(() => completion);
223
+ const scripts = actions.items.filter((i) => i.type === "script-template");
224
+ return Response.json({ ok: true, scripts: scripts.length > 0 ? scripts : void 0 });
225
+ }
226
+ return Response.json({ ok: true });
227
+ }
140
228
  // Annotate the CommonJS export names for ESM import in node:
141
229
  0 && (module.exports = {
142
230
  createNextlyticsMiddleware
@@ -5,16 +5,41 @@ import './types.js';
5
5
  import 'next/dist/server/web/spec-extension/cookies';
6
6
  import 'next/server';
7
7
 
8
- type PagesRouterContext = {
8
+ type ContextWithHeaders = {
9
9
  req: {
10
10
  headers: Record<string, string | string[] | undefined>;
11
- cookies?: Record<string, string>;
12
11
  };
13
12
  };
14
13
  /**
15
- * Get Nextlytics props for Pages Router _app.tsx.
16
- * Reads context from headers set by middleware.
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
+ * ```
17
42
  */
18
- declare function getNextlyticsProps(ctx: PagesRouterContext): NextlyticsContext;
43
+ declare function getNextlyticsProps(ctx: ContextWithHeaders): NextlyticsContext;
19
44
 
20
- export { type PagesRouterContext, getNextlyticsProps };
45
+ export { getNextlyticsProps };
@@ -35,7 +35,8 @@ function getNextlyticsProps(ctx) {
35
35
  }
36
36
  return {
37
37
  requestId: context.pageRenderId,
38
- scripts: context.scripts
38
+ scripts: context.scripts,
39
+ templates: context.templates
39
40
  };
40
41
  }
41
42
  // Annotate the CommonJS export names for ESM import in node:
@@ -1,15 +1,14 @@
1
1
  import { NextResponse } from 'next/server';
2
- import { TemplatizedScriptInsertion } from './types.js';
2
+ import { TemplatizedScriptInsertion, JavascriptTemplate } from './types.js';
3
3
  import 'next/dist/server/web/spec-extension/cookies';
4
4
 
5
- declare const headerNames: {
6
- readonly pathname: "x-nl-pathname";
7
- readonly search: "x-nl-search";
8
- readonly pageRenderId: "x-nl-page-render-id";
9
- readonly isSoftNavigation: "x-nl-is-soft-nav";
10
- readonly scripts: "x-nl-scripts";
5
+ declare const headerKeys: {
6
+ readonly pathname: "x-nc-pathname";
7
+ readonly search: "x-nc-search";
8
+ readonly pageRenderId: "x-nc-page-render-id";
9
+ readonly scripts: "x-nc-scripts";
10
+ readonly templates: "x-nc-templates";
11
11
  };
12
- declare const LAST_PAGE_RENDER_ID_COOKIE = "last-page-render-id";
13
12
  /** Context passed from middleware to server components via headers */
14
13
  type ServerComponentContext = {
15
14
  /** Unique page render ID (event ID) */
@@ -18,12 +17,14 @@ type ServerComponentContext = {
18
17
  pathname: string;
19
18
  /** Query string */
20
19
  search: string;
21
- /** Script actions to execute on client (params only, templates come from config) */
20
+ /** Script actions to execute on client */
22
21
  scripts: TemplatizedScriptInsertion<unknown>[];
22
+ /** Template definitions for scripts */
23
+ templates: Record<string, JavascriptTemplate>;
23
24
  };
24
25
  /** Serialize context to response headers (called in middleware) */
25
26
  declare function serializeServerComponentContext(response: NextResponse, ctx: ServerComponentContext): void;
26
27
  /** Restore context from request headers (called in server components) */
27
28
  declare function restoreServerComponentContext(headersList: Headers): ServerComponentContext | null;
28
29
 
29
- export { LAST_PAGE_RENDER_ID_COOKIE, type ServerComponentContext, headerNames, restoreServerComponentContext, serializeServerComponentContext };
30
+ export { type ServerComponentContext, headerKeys as headers, restoreServerComponentContext, serializeServerComponentContext };
@@ -18,31 +18,32 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var server_component_context_exports = {};
20
20
  __export(server_component_context_exports, {
21
- LAST_PAGE_RENDER_ID_COOKIE: () => LAST_PAGE_RENDER_ID_COOKIE,
22
- headerNames: () => headerNames,
21
+ headers: () => headerKeys,
23
22
  restoreServerComponentContext: () => restoreServerComponentContext,
24
23
  serializeServerComponentContext: () => serializeServerComponentContext
25
24
  });
26
25
  module.exports = __toCommonJS(server_component_context_exports);
27
- const HEADER_PREFIX = "x-nl-";
28
- const headerNames = {
26
+ const HEADER_PREFIX = "x-nc-";
27
+ const headerKeys = {
29
28
  pathname: `${HEADER_PREFIX}pathname`,
30
29
  search: `${HEADER_PREFIX}search`,
31
30
  pageRenderId: `${HEADER_PREFIX}page-render-id`,
32
- isSoftNavigation: `${HEADER_PREFIX}is-soft-nav`,
33
- scripts: `${HEADER_PREFIX}scripts`
31
+ scripts: `${HEADER_PREFIX}scripts`,
32
+ templates: `${HEADER_PREFIX}templates`
34
33
  };
35
- const LAST_PAGE_RENDER_ID_COOKIE = "last-page-render-id";
36
34
  function serializeServerComponentContext(response, ctx) {
37
- response.headers.set(headerNames.pageRenderId, ctx.pageRenderId);
38
- response.headers.set(headerNames.pathname, ctx.pathname);
39
- response.headers.set(headerNames.search, ctx.search);
35
+ response.headers.set(headerKeys.pageRenderId, ctx.pageRenderId);
36
+ response.headers.set(headerKeys.pathname, ctx.pathname);
37
+ response.headers.set(headerKeys.search, ctx.search);
40
38
  if (ctx.scripts.length > 0) {
41
39
  const scriptParts = ctx.scripts.filter((item) => item.type === "script-template").map((s) => `${s.templateId}=${JSON.stringify(s.params)}`);
42
40
  if (scriptParts.length > 0) {
43
- response.headers.set(headerNames.scripts, scriptParts.join(";"));
41
+ response.headers.set(headerKeys.scripts, scriptParts.join(";"));
44
42
  }
45
43
  }
44
+ if (Object.keys(ctx.templates).length > 0) {
45
+ response.headers.set(headerKeys.templates, JSON.stringify(ctx.templates));
46
+ }
46
47
  }
47
48
  function parseScriptsHeader(header) {
48
49
  const scripts = [];
@@ -61,25 +62,34 @@ function parseScriptsHeader(header) {
61
62
  return scripts;
62
63
  }
63
64
  function restoreServerComponentContext(headersList) {
64
- const pageRenderId = headersList.get(headerNames.pageRenderId);
65
+ const pageRenderId = headersList.get(headerKeys.pageRenderId);
65
66
  if (!pageRenderId) {
66
67
  return null;
67
68
  }
68
- const pathname = headersList.get(headerNames.pathname) || "";
69
- const search = headersList.get(headerNames.search) || "";
70
- const scriptsHeader = headersList.get(headerNames.scripts);
69
+ const pathname = headersList.get(headerKeys.pathname) || "";
70
+ const search = headersList.get(headerKeys.search) || "";
71
+ const scriptsHeader = headersList.get(headerKeys.scripts);
71
72
  const scripts = scriptsHeader ? parseScriptsHeader(scriptsHeader) : [];
73
+ let templates = {};
74
+ const templatesHeader = headersList.get(headerKeys.templates);
75
+ if (templatesHeader) {
76
+ try {
77
+ templates = JSON.parse(templatesHeader);
78
+ } catch {
79
+ console.warn("[Nextlytics] Failed to parse templates header");
80
+ }
81
+ }
72
82
  return {
73
83
  pageRenderId,
74
84
  pathname,
75
85
  search,
76
- scripts
86
+ scripts,
87
+ templates
77
88
  };
78
89
  }
79
90
  // Annotate the CommonJS export names for ESM import in node:
80
91
  0 && (module.exports = {
81
- LAST_PAGE_RENDER_ID_COOKIE,
82
- headerNames,
92
+ headers,
83
93
  restoreServerComponentContext,
84
94
  serializeServerComponentContext
85
95
  });
package/dist/server.d.ts CHANGED
@@ -1,8 +1,13 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
1
3
  import { NextlyticsConfig, NextlyticsResult, RequestContext } from './types.js';
2
4
  import 'next/dist/server/web/spec-extension/cookies';
3
5
  import 'next/server';
4
6
 
5
7
  declare function createRequestContext(): Promise<RequestContext>;
8
+ declare function NextlyticsServer({ children }: {
9
+ children: ReactNode;
10
+ }): Promise<react_jsx_runtime.JSX.Element>;
6
11
  declare function Nextlytics(userConfig: NextlyticsConfig): NextlyticsResult;
7
12
 
8
- export { Nextlytics, createRequestContext };
13
+ export { Nextlytics, NextlyticsServer, createRequestContext };
package/dist/server.js CHANGED
@@ -19,6 +19,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  var server_exports = {};
20
20
  __export(server_exports, {
21
21
  Nextlytics: () => Nextlytics,
22
+ NextlyticsServer: () => NextlyticsServer,
22
23
  createRequestContext: () => createRequestContext
23
24
  });
24
25
  module.exports = __toCommonJS(server_exports);
@@ -28,6 +29,7 @@ var import_headers2 = require("./headers");
28
29
  var import_server_component_context = require("./server-component-context");
29
30
  var import_anonymous_user = require("./anonymous-user");
30
31
  var import_client = require("./client");
32
+ var import_handlers = require("./handlers");
31
33
  var import_config_helpers = require("./config-helpers");
32
34
  var import_middleware = require("./middleware");
33
35
  var import_uitils = require("./uitils");
@@ -39,17 +41,11 @@ function resolveBackends(config, ctx, policyFilter) {
39
41
  return entries.map((entry) => {
40
42
  if (isBackendWithConfig(entry)) {
41
43
  const backend2 = typeof entry.backend === "function" ? entry.backend(ctx) : entry.backend;
42
- return backend2 ? { backend: backend2, pageViewDelivery: entry.pageViewDelivery ?? "on-request" } : null;
44
+ return backend2 ? { backend: backend2, ingestPolicy: entry.ingestPolicy ?? "immediate" } : null;
43
45
  }
44
46
  const backend = typeof entry === "function" ? entry(ctx) : entry;
45
- return backend ? { backend, pageViewDelivery: "on-request" } : null;
46
- }).filter((b) => b !== null).filter((b) => {
47
- if (!policyFilter) return true;
48
- if (policyFilter === "client-actions") {
49
- return b.pageViewDelivery === "on-page-load" || b.backend.returnsClientActions;
50
- }
51
- return b.pageViewDelivery === policyFilter;
52
- });
47
+ return backend ? { backend, ingestPolicy: "immediate" } : null;
48
+ }).filter((b) => b !== null).filter((b) => !policyFilter || b.ingestPolicy === policyFilter);
53
49
  }
54
50
  function resolvePlugins(config, ctx) {
55
51
  const plugins = config.plugins || [];
@@ -79,15 +75,16 @@ async function createRequestContext() {
79
75
  headers: _headers
80
76
  };
81
77
  }
82
- function collectTemplates(config, ctx) {
83
- const templates = {};
84
- const backends = resolveBackends(config, ctx);
85
- for (const { backend } of backends) {
86
- if (backend.getClientSideTemplates) {
87
- Object.assign(templates, backend.getClientSideTemplates());
88
- }
78
+ async function NextlyticsServer({ children }) {
79
+ const headersList = await (0, import_headers.headers)();
80
+ const ctx = (0, import_server_component_context.restoreServerComponentContext)(headersList);
81
+ if (!ctx) {
82
+ console.warn(
83
+ "[Nextlytics] nextlyticsMiddleware should be added in order for NextlyticsServer to work"
84
+ );
85
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children });
89
86
  }
90
- return templates;
87
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_client.NextlyticsClient, { requestId: ctx.pageRenderId, scripts: ctx.scripts, templates: ctx.templates, children });
91
88
  }
92
89
  function Nextlytics(userConfig) {
93
90
  const config = (0, import_config_helpers.withDefaults)(userConfig);
@@ -139,7 +136,7 @@ function Nextlytics(userConfig) {
139
136
  return { clientActions, completion };
140
137
  };
141
138
  const updateEventInternal = async (eventId, patch, ctx) => {
142
- const resolved = resolveBackends(config, ctx, "on-request").filter(
139
+ const resolved = resolveBackends(config, ctx, "immediate").filter(
143
140
  ({ backend }) => backend.supportsUpdates
144
141
  );
145
142
  const results = await Promise.all(
@@ -173,21 +170,11 @@ function Nextlytics(userConfig) {
173
170
  return updateEventInternal(eventId, patch, ctx);
174
171
  };
175
172
  const middleware = (0, import_middleware.createNextlyticsMiddleware)(config, dispatchEventInternal, updateEventInternal);
176
- async function Server({ children }) {
177
- const headersList = await (0, import_headers.headers)();
178
- const ctx = (0, import_server_component_context.restoreServerComponentContext)(headersList);
179
- if (!ctx) {
180
- console.warn("[Nextlytics] nextlyticsMiddleware should be added in order for Server to work");
181
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children });
182
- }
183
- const requestCtx = await createRequestContext();
184
- const templates = collectTemplates(config, requestCtx);
185
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_client.NextlyticsClient, { ctx: { requestId: ctx.pageRenderId, scripts: ctx.scripts, templates }, children });
186
- }
173
+ const handlers = (0, import_handlers.createHandlers)();
187
174
  const analytics = async () => {
188
175
  const headersList = await (0, import_headers.headers)();
189
176
  const cookieStore = await (0, import_headers.cookies)();
190
- const pageRenderId = headersList.get(import_server_component_context.headerNames.pageRenderId);
177
+ const pageRenderId = headersList.get(import_server_component_context.headers.pageRenderId);
191
178
  const serverContext = createServerContextFromHeaders(headersList);
192
179
  const ctx = { headers: headersList, cookies: cookieStore };
193
180
  const { anonId: anonymousUserId } = await (0, import_anonymous_user.resolveAnonymousUser)({ ctx, serverContext, config });
@@ -205,7 +192,6 @@ function Nextlytics(userConfig) {
205
192
  return { ok: false };
206
193
  }
207
194
  const event = {
208
- origin: "server",
209
195
  eventId: (0, import_uitils.generateId)(),
210
196
  parentEventId: pageRenderId,
211
197
  type: eventName,
@@ -220,13 +206,7 @@ function Nextlytics(userConfig) {
220
206
  }
221
207
  };
222
208
  };
223
- return {
224
- middleware,
225
- analytics,
226
- dispatchEvent,
227
- updateEvent,
228
- NextlyticsServer: Server
229
- };
209
+ return { middleware, handlers, analytics, dispatchEvent, updateEvent };
230
210
  }
231
211
  function createServerContextFromHeaders(headersList) {
232
212
  const rawHeaders = {};
@@ -234,8 +214,8 @@ function createServerContextFromHeaders(headersList) {
234
214
  rawHeaders[key] = value;
235
215
  });
236
216
  const requestHeaders = (0, import_headers2.removeSensitiveHeaders)(rawHeaders);
237
- const pathname = headersList.get(import_server_component_context.headerNames.pathname) || "";
238
- const search = headersList.get(import_server_component_context.headerNames.search) || "";
217
+ const pathname = headersList.get(import_server_component_context.headers.pathname) || "";
218
+ const search = headersList.get(import_server_component_context.headers.search) || "";
239
219
  const searchParams = {};
240
220
  if (search) {
241
221
  const params = new URLSearchParams(search);
@@ -260,5 +240,6 @@ function createServerContextFromHeaders(headersList) {
260
240
  // Annotate the CommonJS export names for ESM import in node:
261
241
  0 && (module.exports = {
262
242
  Nextlytics,
243
+ NextlyticsServer,
263
244
  createRequestContext
264
245
  });