@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/backends/ga.d.ts +0 -5
- package/dist/backends/ga.js +17 -93
- package/dist/backends/gtm.js +8 -25
- package/dist/backends/logging.js +0 -33
- package/dist/backends/segment.js +0 -1
- package/dist/client.d.ts +4 -1
- package/dist/client.js +67 -141
- package/dist/config-helpers.js +1 -1
- package/dist/handlers.d.ts +12 -0
- package/dist/handlers.js +40 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -1
- package/dist/middleware.d.ts +3 -2
- package/dist/middleware.js +127 -39
- package/dist/pages-router.d.ts +31 -6
- package/dist/pages-router.js +2 -1
- package/dist/server-component-context.d.ts +11 -10
- package/dist/server-component-context.js +28 -18
- package/dist/server.d.ts +6 -1
- package/dist/server.js +21 -40
- package/dist/types.d.ts +18 -61
- package/dist/uitils.d.ts +1 -7
- package/dist/uitils.js +5 -39
- package/package.json +1 -1
- package/dist/api-handler.d.ts +0 -11
- package/dist/api-handler.js +0 -182
- package/dist/client-utils.d.ts +0 -35
- package/dist/client-utils.js +0 -121
- package/dist/stable-hash.d.ts +0 -6
- package/dist/stable-hash.js +0 -76
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,
|
|
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
|
package/dist/middleware.d.ts
CHANGED
|
@@ -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 };
|
package/dist/middleware.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
|
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, "
|
|
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
|
package/dist/pages-router.d.ts
CHANGED
|
@@ -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
|
|
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
|
-
*
|
|
16
|
-
*
|
|
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:
|
|
43
|
+
declare function getNextlyticsProps(ctx: ContextWithHeaders): NextlyticsContext;
|
|
19
44
|
|
|
20
|
-
export {
|
|
45
|
+
export { getNextlyticsProps };
|
package/dist/pages-router.js
CHANGED
|
@@ -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
|
|
6
|
-
readonly pathname: "x-
|
|
7
|
-
readonly search: "x-
|
|
8
|
-
readonly pageRenderId: "x-
|
|
9
|
-
readonly
|
|
10
|
-
readonly
|
|
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
|
|
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 {
|
|
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
|
-
|
|
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-
|
|
28
|
-
const
|
|
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
|
-
|
|
33
|
-
|
|
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(
|
|
38
|
-
response.headers.set(
|
|
39
|
-
response.headers.set(
|
|
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(
|
|
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(
|
|
65
|
+
const pageRenderId = headersList.get(headerKeys.pageRenderId);
|
|
65
66
|
if (!pageRenderId) {
|
|
66
67
|
return null;
|
|
67
68
|
}
|
|
68
|
-
const pathname = headersList.get(
|
|
69
|
-
const search = headersList.get(
|
|
70
|
-
const scriptsHeader = headersList.get(
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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
|
|
83
|
-
const
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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, "
|
|
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
|
-
|
|
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.
|
|
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.
|
|
238
|
-
const search = headersList.get(import_server_component_context.
|
|
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
|
});
|