@nextlytics/core 0.5.1 → 0.6.0-canary.114

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.
@@ -59,6 +59,8 @@ function createNextlyticsMiddleware(config, dispatchEvent, updateEvent, collectT
59
59
  integrity: request.integrity,
60
60
  isPrefetch: reqInfo.isPrefetch,
61
61
  isRsc: reqInfo.isRsc,
62
+ isDocumentRequest: reqInfo.isDocumentRequest,
63
+ isBrowserSubrequest: reqInfo.isBrowserSubrequest,
62
64
  isPageNavigation: reqInfo.isPageNavigation,
63
65
  isStaticFile: reqInfo.isStaticFile,
64
66
  isNextjsInternal: reqInfo.isNextjsInternal,
@@ -76,7 +78,13 @@ function createNextlyticsMiddleware(config, dispatchEvent, updateEvent, collectT
76
78
  response2.headers.set(import_server_component_context.headerNames.active, "1");
77
79
  return response2;
78
80
  }
79
- if (!reqInfo.isPageNavigation && !config.isApiPath(pathname)) {
81
+ if (reqInfo.isBrowserSubrequest && !config.isApiPath(pathname)) {
82
+ const response2 = import_server.NextResponse.next();
83
+ response2.headers.set(import_server_component_context.headerNames.active, "1");
84
+ return response2;
85
+ }
86
+ const isReadMethod = request.method === "GET" || request.method === "HEAD";
87
+ if (!isReadMethod && !reqInfo.isDocumentRequest && !config.isApiPath(pathname)) {
80
88
  const response2 = import_server.NextResponse.next();
81
89
  response2.headers.set(import_server_component_context.headerNames.active, "1");
82
90
  return response2;
package/dist/server.js CHANGED
@@ -227,7 +227,9 @@ function Nextlytics(userConfig) {
227
227
  collectedAt: (/* @__PURE__ */ new Date()).toISOString(),
228
228
  anonymousUserId,
229
229
  serverContext,
230
- userContext,
230
+ // An explicit per-event user (e.g. an email recipient resolved from a
231
+ // link) overrides the request-derived one from callbacks.getUser.
232
+ userContext: opts?.user ?? userContext,
231
233
  properties: { ...propsFromCallback, ...opts?.props }
232
234
  };
233
235
  const { completion } = dispatchEventInternal(event, ctx);
package/dist/types.d.ts CHANGED
@@ -231,6 +231,10 @@ type NextlyticsServerSide = {
231
231
  /** Send custom event from a server component, server action, or API route */
232
232
  sendEvent: (eventName: string, opts?: {
233
233
  props?: Record<string, unknown>;
234
+ /** Identify the event's user explicitly. Overrides callbacks.getUser for
235
+ * this event — e.g. an email recipient resolved from a link, where the
236
+ * request has no session to derive identity from. */
237
+ user?: UserContext;
234
238
  }) => Promise<{
235
239
  ok: boolean;
236
240
  }>;
package/dist/uitils.d.ts CHANGED
@@ -16,6 +16,17 @@ type RequestInfo = {
16
16
  isPrefetch: boolean;
17
17
  /** True if this is an RSC (React Server Components) navigation */
18
18
  isRsc: boolean;
19
+ /** True if this is a hard document navigation (sec-fetch-dest=document or
20
+ * sec-fetch-mode=navigate) — the strong signal, distinct from the weaker
21
+ * accepts-HTML heuristic folded into isPageNavigation. */
22
+ isDocumentRequest: boolean;
23
+ /** True if this is a browser-initiated sub-request (RSC soft-navigation, XHR,
24
+ * fetch(), or a subresource) — Sec-Fetch-Dest is present and is not
25
+ * "document". Modern browsers always send Sec-Fetch-Dest (it's a forbidden
26
+ * header, so it can't be spoofed); non-browser clients (curl, agents, bots,
27
+ * server-to-server) omit it. Used to skip soft-navigation RSC fetches, which
28
+ * carry no reliable RSC header in Next 15.5+ yet must not be double-counted. */
29
+ isBrowserSubrequest: boolean;
19
30
  /** True if this is a standard document or RSC navigation */
20
31
  isPageNavigation: boolean;
21
32
  /** True if this is a static file (ico, png, css, js, etc.) */
package/dist/uitils.js CHANGED
@@ -81,6 +81,7 @@ function getRequestInfo(request) {
81
81
  const secFetchMode = headers.get("sec-fetch-mode");
82
82
  const accept = headers.get("accept") || "";
83
83
  const isDocumentRequest = secFetchDest === "document" || secFetchMode === "navigate";
84
+ const isBrowserSubrequest = secFetchDest !== null && !isDocumentRequest;
84
85
  const acceptsHtml = accept.includes("text/html");
85
86
  const isPageNavigation = isDocumentRequest || acceptsHtml;
86
87
  const isRscPrefetch = nextUrl !== null && nextUrl !== pathname;
@@ -88,6 +89,8 @@ function getRequestInfo(request) {
88
89
  return {
89
90
  isPrefetch,
90
91
  isRsc,
92
+ isDocumentRequest,
93
+ isBrowserSubrequest,
91
94
  isPageNavigation,
92
95
  isStaticFile,
93
96
  isNextjsInternal
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextlytics/core",
3
- "version": "0.5.1",
3
+ "version": "0.6.0-canary.114",
4
4
  "description": "Analytics library for Next.js",
5
5
  "license": "MIT",
6
6
  "repository": {