@amplifyup/sdk 0.1.51 → 0.1.53
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/AmplifyRenderer.js +16 -2
- package/dist/AmplifyRenderer.js.map +1 -1
- package/dist/AmplifyRenderer.mjs +16 -2
- package/dist/AmplifyRenderer.mjs.map +1 -1
- package/dist/index.d.mts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +16 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +16 -2
- package/dist/index.mjs.map +1 -1
- package/dist/middleware.d.mts +14 -12
- package/dist/middleware.d.ts +14 -12
- package/dist/middleware.js +17 -160
- package/dist/middleware.js.map +1 -1
- package/dist/middleware.mjs +17 -161
- package/dist/middleware.mjs.map +1 -1
- package/dist/react.d.mts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +16 -2
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +16 -2
- package/dist/react.mjs.map +1 -1
- package/package.json +1 -1
package/dist/middleware.d.mts
CHANGED
|
@@ -2,15 +2,16 @@ import { NextRequest, NextResponse } from 'next/server';
|
|
|
2
2
|
export { A as AMPLIFYUP_EDITOR_ROUTE } from './reservedRoutes-aGgViBDM.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Next.js middleware: Composer preview rewrite +
|
|
5
|
+
* Next.js middleware: Composer preview rewrite + first-party visitor cookies.
|
|
6
6
|
* Edge-runtime safe (no Node APIs).
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
8
|
+
* Do **not** rewrite live routes to `/__p/{keys}/…`. That changes the App
|
|
9
|
+
* Router tree while the browser URL stays the same. Next.js `<Link>` then
|
|
10
|
+
* calls preventDefault, issues no RSC fetch, and `location.pathname` never
|
|
11
|
+
* changes (Ctrl/Cmd-click still works as a full load). Personalized HTML
|
|
12
|
+
* comes from the SDK client overlay (`/v1/select` + `/v1/resolve`).
|
|
13
|
+
*
|
|
14
|
+
* Cookies are only set on full document loads — never on RSC / prefetch.
|
|
14
15
|
*/
|
|
15
16
|
|
|
16
17
|
declare const AMPLIFY_VARIANT_PREFIX = "/__p";
|
|
@@ -19,13 +20,14 @@ declare const AMPLIFY_SESSION_COOKIE = "amplifyup_session_id";
|
|
|
19
20
|
declare const amplifyMiddlewareConfig: {
|
|
20
21
|
matcher: string[];
|
|
21
22
|
};
|
|
23
|
+
/** App Router flight / soft navigation (including Link prefetch). */
|
|
24
|
+
declare function isNextClientNavigation(request: NextRequest): boolean;
|
|
22
25
|
/**
|
|
23
|
-
* Preview stays dynamic.
|
|
24
|
-
* so Next
|
|
25
|
-
* unchanged SSG. Fail open to the default page on Edge errors/timeouts.
|
|
26
|
+
* Preview stays dynamic. Live traffic is never rewritten off its public path
|
|
27
|
+
* so Next.js `<Link>` soft navigation can complete.
|
|
26
28
|
*/
|
|
27
|
-
declare function amplifyMiddleware(request: NextRequest,
|
|
29
|
+
declare function amplifyMiddleware(request: NextRequest, _options?: {
|
|
28
30
|
trackingId?: string;
|
|
29
31
|
}): Promise<NextResponse>;
|
|
30
32
|
|
|
31
|
-
export { AMPLIFY_ANON_COOKIE, AMPLIFY_SESSION_COOKIE, AMPLIFY_VARIANT_PREFIX, amplifyMiddleware, amplifyMiddlewareConfig };
|
|
33
|
+
export { AMPLIFY_ANON_COOKIE, AMPLIFY_SESSION_COOKIE, AMPLIFY_VARIANT_PREFIX, amplifyMiddleware, amplifyMiddlewareConfig, isNextClientNavigation };
|
package/dist/middleware.d.ts
CHANGED
|
@@ -2,15 +2,16 @@ import { NextRequest, NextResponse } from 'next/server';
|
|
|
2
2
|
export { A as AMPLIFYUP_EDITOR_ROUTE } from './reservedRoutes-aGgViBDM.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Next.js middleware: Composer preview rewrite +
|
|
5
|
+
* Next.js middleware: Composer preview rewrite + first-party visitor cookies.
|
|
6
6
|
* Edge-runtime safe (no Node APIs).
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
8
|
+
* Do **not** rewrite live routes to `/__p/{keys}/…`. That changes the App
|
|
9
|
+
* Router tree while the browser URL stays the same. Next.js `<Link>` then
|
|
10
|
+
* calls preventDefault, issues no RSC fetch, and `location.pathname` never
|
|
11
|
+
* changes (Ctrl/Cmd-click still works as a full load). Personalized HTML
|
|
12
|
+
* comes from the SDK client overlay (`/v1/select` + `/v1/resolve`).
|
|
13
|
+
*
|
|
14
|
+
* Cookies are only set on full document loads — never on RSC / prefetch.
|
|
14
15
|
*/
|
|
15
16
|
|
|
16
17
|
declare const AMPLIFY_VARIANT_PREFIX = "/__p";
|
|
@@ -19,13 +20,14 @@ declare const AMPLIFY_SESSION_COOKIE = "amplifyup_session_id";
|
|
|
19
20
|
declare const amplifyMiddlewareConfig: {
|
|
20
21
|
matcher: string[];
|
|
21
22
|
};
|
|
23
|
+
/** App Router flight / soft navigation (including Link prefetch). */
|
|
24
|
+
declare function isNextClientNavigation(request: NextRequest): boolean;
|
|
22
25
|
/**
|
|
23
|
-
* Preview stays dynamic.
|
|
24
|
-
* so Next
|
|
25
|
-
* unchanged SSG. Fail open to the default page on Edge errors/timeouts.
|
|
26
|
+
* Preview stays dynamic. Live traffic is never rewritten off its public path
|
|
27
|
+
* so Next.js `<Link>` soft navigation can complete.
|
|
26
28
|
*/
|
|
27
|
-
declare function amplifyMiddleware(request: NextRequest,
|
|
29
|
+
declare function amplifyMiddleware(request: NextRequest, _options?: {
|
|
28
30
|
trackingId?: string;
|
|
29
31
|
}): Promise<NextResponse>;
|
|
30
32
|
|
|
31
|
-
export { AMPLIFY_ANON_COOKIE, AMPLIFY_SESSION_COOKIE, AMPLIFY_VARIANT_PREFIX, amplifyMiddleware, amplifyMiddlewareConfig };
|
|
33
|
+
export { AMPLIFY_ANON_COOKIE, AMPLIFY_SESSION_COOKIE, AMPLIFY_VARIANT_PREFIX, amplifyMiddleware, amplifyMiddlewareConfig, isNextClientNavigation };
|
package/dist/middleware.js
CHANGED
|
@@ -5,128 +5,6 @@ var server = require('next/server');
|
|
|
5
5
|
/* @amplifyup/sdk - https://amplifyup.ai */
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
// src/edge/fetchVariants.ts
|
|
9
|
-
async function fetchEdgeVariants(options) {
|
|
10
|
-
const base = options.edgeUrl.replace(/\/+$/, "");
|
|
11
|
-
const params = new URLSearchParams({
|
|
12
|
-
route: options.route,
|
|
13
|
-
trackingId: options.trackingId,
|
|
14
|
-
anonId: options.anonId
|
|
15
|
-
});
|
|
16
|
-
const fetchFn = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
17
|
-
const controller = new AbortController();
|
|
18
|
-
const timer = setTimeout(() => controller.abort(), options.timeoutMs ?? 800);
|
|
19
|
-
try {
|
|
20
|
-
const res = await fetchFn(`${base}/v1/variants?${params.toString()}`, {
|
|
21
|
-
method: "GET",
|
|
22
|
-
headers: { Accept: "application/json" },
|
|
23
|
-
cache: "no-store",
|
|
24
|
-
signal: controller.signal
|
|
25
|
-
});
|
|
26
|
-
if (!res.ok) return {};
|
|
27
|
-
const body = await res.json().catch(() => ({}));
|
|
28
|
-
return body.variantKeys && typeof body.variantKeys === "object" ? body.variantKeys : {};
|
|
29
|
-
} finally {
|
|
30
|
-
clearTimeout(timer);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// src/edge/variantKeys.ts
|
|
35
|
-
function serializeVariantKeys(keys) {
|
|
36
|
-
if (!keys) return "";
|
|
37
|
-
const parts = [];
|
|
38
|
-
const zoneIds = Object.keys(keys).sort();
|
|
39
|
-
for (const zoneId of zoneIds) {
|
|
40
|
-
const variant = keys[zoneId];
|
|
41
|
-
if (!variant || variant === "default") continue;
|
|
42
|
-
parts.push(`${zoneId}:${variant}`);
|
|
43
|
-
}
|
|
44
|
-
return parts.join(",");
|
|
45
|
-
}
|
|
46
|
-
function isDefaultVariantKeys(keys) {
|
|
47
|
-
return serializeVariantKeys(keys) === "";
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// src/edge/normalizeRoute.ts
|
|
51
|
-
function normalizeRoute(route) {
|
|
52
|
-
let path = String(route || "").trim();
|
|
53
|
-
if (!path) return "/";
|
|
54
|
-
try {
|
|
55
|
-
if (/^https?:\/\//i.test(path)) {
|
|
56
|
-
path = new URL(path).pathname;
|
|
57
|
-
}
|
|
58
|
-
} catch {
|
|
59
|
-
}
|
|
60
|
-
const q = path.indexOf("?");
|
|
61
|
-
if (q >= 0) path = path.slice(0, q);
|
|
62
|
-
const h = path.indexOf("#");
|
|
63
|
-
if (h >= 0) path = path.slice(0, h);
|
|
64
|
-
if (!path.startsWith("/")) path = `/${path}`;
|
|
65
|
-
if (path.length > 1 && path.endsWith("/")) {
|
|
66
|
-
path = path.replace(/\/+$/, "");
|
|
67
|
-
}
|
|
68
|
-
return path || "/";
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// src/targets.ts
|
|
72
|
-
var AWS_DEV_API = "https://api-dev.amplifyup.ai";
|
|
73
|
-
var AWS_PROD_API = "https://api.amplifyup.ai";
|
|
74
|
-
var PROD_ORCHESTRATOR = "https://amplifyup.ai";
|
|
75
|
-
var PROD_EDGE = "https://edge.amplifyup.ai";
|
|
76
|
-
function isAmplifyUpTarget(value) {
|
|
77
|
-
return value === "local" || value === "dev" || value === "production";
|
|
78
|
-
}
|
|
79
|
-
function normalizeAmplifyUpTarget(value) {
|
|
80
|
-
return value === "dev" ? "local" : value;
|
|
81
|
-
}
|
|
82
|
-
function resolveAmplifyUpTarget(options) {
|
|
83
|
-
const envTarget = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_AMPLIFYUP_TARGET : void 0;
|
|
84
|
-
if (isAmplifyUpTarget(envTarget)) {
|
|
85
|
-
return normalizeAmplifyUpTarget(envTarget);
|
|
86
|
-
}
|
|
87
|
-
return "production";
|
|
88
|
-
}
|
|
89
|
-
function localOrchestratorUrl() {
|
|
90
|
-
const fromEnv = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_ORCHESTRATOR_URL : void 0;
|
|
91
|
-
return (fromEnv || "http://localhost:5001").replace(/\/$/, "");
|
|
92
|
-
}
|
|
93
|
-
function localAwsApiUrl() {
|
|
94
|
-
const fromEnv = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_AMPLIFYUP_API_URL : void 0;
|
|
95
|
-
return (fromEnv || AWS_DEV_API).replace(/\/$/, "");
|
|
96
|
-
}
|
|
97
|
-
function localEdgeUrl() {
|
|
98
|
-
const fromEnv = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_EDGE_URL : void 0;
|
|
99
|
-
return (fromEnv || "http://localhost:8787").replace(/\/$/, "");
|
|
100
|
-
}
|
|
101
|
-
function resolveAmplifyUpUrls(target) {
|
|
102
|
-
if (target === "local") {
|
|
103
|
-
const orchestratorUrl2 = localOrchestratorUrl();
|
|
104
|
-
const apiGatewayUrl = localAwsApiUrl();
|
|
105
|
-
return {
|
|
106
|
-
target: "local",
|
|
107
|
-
// Layouts / site config / composer APIs → local orchestrator + Neon
|
|
108
|
-
orchestratorUrl: orchestratorUrl2,
|
|
109
|
-
// Events + personalize → AWS development stack
|
|
110
|
-
apiGatewayUrl,
|
|
111
|
-
decisionApiUrl: `${apiGatewayUrl}/v1/personalize`,
|
|
112
|
-
edgeUrl: localEdgeUrl()
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
const resolvedApi = typeof process !== "undefined" && process.env.NEXT_PUBLIC_AMPLIFYUP_API_URL?.replace(/\/$/, "") || AWS_PROD_API;
|
|
116
|
-
const orchestratorFromEnv = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_ORCHESTRATOR_URL : void 0;
|
|
117
|
-
const isLocalOrchestrator = !!orchestratorFromEnv && (orchestratorFromEnv.includes("localhost") || orchestratorFromEnv.includes("127.0.0.1"));
|
|
118
|
-
const orchestratorUrl = isLocalOrchestrator || !orchestratorFromEnv ? PROD_ORCHESTRATOR : orchestratorFromEnv.replace(/\/$/, "");
|
|
119
|
-
const edgeFromEnv = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_EDGE_URL?.replace(/\/$/, "") : void 0;
|
|
120
|
-
const edgeUrl = edgeFromEnv && !edgeFromEnv.includes("localhost") && !edgeFromEnv.includes("127.0.0.1") ? edgeFromEnv : PROD_EDGE;
|
|
121
|
-
return {
|
|
122
|
-
target: "production",
|
|
123
|
-
apiGatewayUrl: resolvedApi,
|
|
124
|
-
orchestratorUrl,
|
|
125
|
-
decisionApiUrl: `${resolvedApi}/v1/personalize`,
|
|
126
|
-
edgeUrl
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
|
|
130
8
|
// src/reservedRoutes.ts
|
|
131
9
|
var AMPLIFYUP_EDITOR_ROUTE = "/__amplifyup/editor";
|
|
132
10
|
function isAmplifyUpEditorRoute(pathname) {
|
|
@@ -159,16 +37,20 @@ function generateAnonId() {
|
|
|
159
37
|
function generateSessionId() {
|
|
160
38
|
return typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
161
39
|
}
|
|
162
|
-
function
|
|
163
|
-
|
|
164
|
-
|
|
40
|
+
function withIdentityCookies(res, anonId, sessionId) {
|
|
41
|
+
res.cookies.set(AMPLIFY_ANON_COOKIE, anonId, {
|
|
42
|
+
path: "/",
|
|
43
|
+
maxAge: 60 * 60 * 24 * 365,
|
|
44
|
+
sameSite: "lax"
|
|
45
|
+
});
|
|
46
|
+
res.cookies.set(AMPLIFY_SESSION_COOKIE, sessionId, {
|
|
165
47
|
path: "/",
|
|
166
48
|
maxAge: SESSION_MAX_AGE_SECONDS,
|
|
167
49
|
sameSite: "lax"
|
|
168
50
|
});
|
|
169
51
|
return res;
|
|
170
52
|
}
|
|
171
|
-
async function amplifyMiddleware(request,
|
|
53
|
+
async function amplifyMiddleware(request, _options) {
|
|
172
54
|
const { pathname, searchParams } = request.nextUrl;
|
|
173
55
|
if (pathname.startsWith("/__preview") || pathname.startsWith(AMPLIFY_VARIANT_PREFIX)) {
|
|
174
56
|
return server.NextResponse.next();
|
|
@@ -182,45 +64,19 @@ async function amplifyMiddleware(request, options) {
|
|
|
182
64
|
url.pathname = pathname === "/" ? "/__preview" : `/__preview${pathname}`;
|
|
183
65
|
return server.NextResponse.rewrite(url);
|
|
184
66
|
}
|
|
185
|
-
|
|
186
|
-
if (!trackingId) {
|
|
67
|
+
if (isNextClientNavigation(request)) {
|
|
187
68
|
return server.NextResponse.next();
|
|
188
69
|
}
|
|
189
|
-
const setCookies = !isNextClientNavigation(request);
|
|
190
70
|
const existingAnon = request.cookies.get(AMPLIFY_ANON_COOKIE)?.value || "";
|
|
191
71
|
const existingSession = request.cookies.get(AMPLIFY_SESSION_COOKIE)?.value || "";
|
|
192
|
-
if (
|
|
193
|
-
|
|
194
|
-
return server.NextResponse.next();
|
|
195
|
-
}
|
|
196
|
-
const res = server.NextResponse.next();
|
|
197
|
-
res.cookies.set(AMPLIFY_ANON_COOKIE, generateAnonId(), {
|
|
198
|
-
path: "/",
|
|
199
|
-
maxAge: 60 * 60 * 24 * 365,
|
|
200
|
-
sameSite: "lax"
|
|
201
|
-
});
|
|
202
|
-
return withSessionCookie(res, existingSession, true);
|
|
203
|
-
}
|
|
204
|
-
const target = resolveAmplifyUpTarget();
|
|
205
|
-
const { edgeUrl } = resolveAmplifyUpUrls(target);
|
|
206
|
-
const route = normalizeRoute(pathname);
|
|
207
|
-
try {
|
|
208
|
-
const variantKeys = await fetchEdgeVariants({
|
|
209
|
-
edgeUrl,
|
|
210
|
-
trackingId,
|
|
211
|
-
route,
|
|
212
|
-
anonId: existingAnon
|
|
213
|
-
});
|
|
214
|
-
if (isDefaultVariantKeys(variantKeys)) {
|
|
215
|
-
return withSessionCookie(server.NextResponse.next(), existingSession, setCookies);
|
|
216
|
-
}
|
|
217
|
-
const sig = encodeURIComponent(serializeVariantKeys(variantKeys));
|
|
218
|
-
const url = request.nextUrl.clone();
|
|
219
|
-
url.pathname = pathname === "/" ? `${AMPLIFY_VARIANT_PREFIX}/${sig}` : `${AMPLIFY_VARIANT_PREFIX}/${sig}${pathname}`;
|
|
220
|
-
return withSessionCookie(server.NextResponse.rewrite(url), existingSession, setCookies);
|
|
221
|
-
} catch {
|
|
222
|
-
return withSessionCookie(server.NextResponse.next(), existingSession, setCookies);
|
|
72
|
+
if (existingAnon && existingSession) {
|
|
73
|
+
return server.NextResponse.next();
|
|
223
74
|
}
|
|
75
|
+
return withIdentityCookies(
|
|
76
|
+
server.NextResponse.next(),
|
|
77
|
+
existingAnon || generateAnonId(),
|
|
78
|
+
existingSession || generateSessionId()
|
|
79
|
+
);
|
|
224
80
|
}
|
|
225
81
|
|
|
226
82
|
exports.AMPLIFYUP_EDITOR_ROUTE = AMPLIFYUP_EDITOR_ROUTE;
|
|
@@ -229,5 +85,6 @@ exports.AMPLIFY_SESSION_COOKIE = AMPLIFY_SESSION_COOKIE;
|
|
|
229
85
|
exports.AMPLIFY_VARIANT_PREFIX = AMPLIFY_VARIANT_PREFIX;
|
|
230
86
|
exports.amplifyMiddleware = amplifyMiddleware;
|
|
231
87
|
exports.amplifyMiddlewareConfig = amplifyMiddlewareConfig;
|
|
88
|
+
exports.isNextClientNavigation = isNextClientNavigation;
|
|
232
89
|
//# sourceMappingURL=middleware.js.map
|
|
233
90
|
//# sourceMappingURL=middleware.js.map
|
package/dist/middleware.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/edge/fetchVariants.ts","../src/edge/variantKeys.ts","../src/edge/normalizeRoute.ts","../src/targets.ts","../src/reservedRoutes.ts","../src/middleware.ts"],"names":["orchestratorUrl","NextResponse"],"mappings":"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","file":"middleware.js","sourcesContent":["/**\n * Lightweight Edge call for Next middleware: variant keys only.\n */\n\nexport async function fetchEdgeVariants(options: {\n edgeUrl: string;\n trackingId: string;\n route: string;\n anonId: string;\n fetch?: typeof fetch;\n timeoutMs?: number;\n}): Promise<Record<string, string>> {\n const base = options.edgeUrl.replace(/\\/+$/, '');\n const params = new URLSearchParams({\n route: options.route,\n trackingId: options.trackingId,\n anonId: options.anonId,\n });\n const fetchFn = options.fetch ?? globalThis.fetch.bind(globalThis);\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), options.timeoutMs ?? 800);\n try {\n const res = await fetchFn(`${base}/v1/variants?${params.toString()}`, {\n method: 'GET',\n headers: { Accept: 'application/json' },\n cache: 'no-store',\n signal: controller.signal,\n });\n if (!res.ok) return {};\n const body = (await res.json().catch(() => ({}))) as {\n variantKeys?: Record<string, string>;\n };\n return body.variantKeys && typeof body.variantKeys === 'object'\n ? body.variantKeys\n : {};\n } finally {\n clearTimeout(timer);\n }\n}\n","/**\n * Compact variant-key codec for URLs and Edge `variants` query params.\n * Default variants are omitted so equivalent assignments share one cache entry.\n */\n\nexport function serializeVariantKeys(\n keys: Record<string, string> | null | undefined\n): string {\n if (!keys) return '';\n const parts: string[] = [];\n const zoneIds = Object.keys(keys).sort();\n for (const zoneId of zoneIds) {\n const variant = keys[zoneId];\n if (!variant || variant === 'default') continue;\n parts.push(`${zoneId}:${variant}`);\n }\n return parts.join(',');\n}\n\nexport function parseVariantKeys(\n raw: string | null | undefined\n): Record<string, string> {\n const out: Record<string, string> = {};\n const text = (raw || '').trim();\n if (!text) return out;\n const decoded = safeDecode(text);\n for (const part of decoded.split(',')) {\n const i = part.indexOf(':');\n if (i <= 0) continue;\n const zoneId = part.slice(0, i).trim();\n const variant = part.slice(i + 1).trim();\n if (zoneId && variant) out[zoneId] = variant;\n }\n return out;\n}\n\nexport function isDefaultVariantKeys(\n keys: Record<string, string> | null | undefined\n): boolean {\n return serializeVariantKeys(keys) === '';\n}\n\nfunction safeDecode(value: string): string {\n try {\n return decodeURIComponent(value);\n } catch {\n return value;\n }\n}\n","/**\n * Normalize a route path for Edge resolve requests.\n * Leading slash, no trailing slash (except root), query/hash stripped.\n */\nexport function normalizeRoute(route: string): string {\n let path = String(route || '').trim();\n if (!path) return '/';\n\n try {\n if (/^https?:\\/\\//i.test(path)) {\n path = new URL(path).pathname;\n }\n } catch {\n /* keep path */\n }\n\n const q = path.indexOf('?');\n if (q >= 0) path = path.slice(0, q);\n const h = path.indexOf('#');\n if (h >= 0) path = path.slice(0, h);\n\n if (!path.startsWith('/')) path = `/${path}`;\n if (path.length > 1 && path.endsWith('/')) {\n path = path.replace(/\\/+$/, '');\n }\n return path || '/';\n}\n","/**\n * AmplifyUp environment targets\n *\n * Two environments only:\n * - local: apps/config from localhost + Neon; events & personalize from AWS development\n * - production: all production AmplifyUp / AWS endpoints\n *\n * Controlled via `config.target` or `NEXT_PUBLIC_AMPLIFYUP_TARGET`.\n * Legacy value `dev` is treated as `local`.\n */\n\nexport type AmplifyUpTarget = 'local' | 'production';\n\n/** Accepted env/config strings (includes legacy `dev` → local). */\nexport type AmplifyUpTargetInput = AmplifyUpTarget | 'dev';\n\nexport interface AmplifyUpUrls {\n target: AmplifyUpTarget;\n apiGatewayUrl: string;\n orchestratorUrl: string;\n decisionApiUrl: string;\n edgeUrl: string;\n}\n\nconst AWS_DEV_API = 'https://api-dev.amplifyup.ai';\nconst AWS_PROD_API = 'https://api.amplifyup.ai';\nconst PROD_ORCHESTRATOR = 'https://amplifyup.ai';\nconst PROD_EDGE = 'https://edge.amplifyup.ai';\n\nexport function isAmplifyUpTarget(value: unknown): value is AmplifyUpTargetInput {\n return value === 'local' || value === 'dev' || value === 'production';\n}\n\nexport function normalizeAmplifyUpTarget(value: AmplifyUpTargetInput): AmplifyUpTarget {\n return value === 'dev' ? 'local' : value;\n}\n\n/**\n * Resolve which target to use.\n *\n * Priority:\n * 1. explicit config.target\n * 2. config.dev === true → 'local' (local apps + AWS-dev pipeline)\n * 3. NEXT_PUBLIC_AMPLIFYUP_TARGET\n * 4. unset → 'production' (live endpoints — hosting on localhost does NOT imply local)\n *\n * Use `local` only when developing against the AmplifyUp monorepo\n * (set NEXT_PUBLIC_AMPLIFYUP_TARGET=local in .env.local).\n */\nexport function resolveAmplifyUpTarget(options?: {\n configTarget?: AmplifyUpTargetInput;\n /** @deprecated Prefer NEXT_PUBLIC_AMPLIFYUP_TARGET=local. When true, resolves to local. */\n configDev?: boolean;\n}): AmplifyUpTarget {\n if (options?.configTarget && isAmplifyUpTarget(options.configTarget)) {\n return normalizeAmplifyUpTarget(options.configTarget);\n }\n\n if (options?.configDev === true) {\n return 'local';\n }\n\n const envTarget =\n typeof process !== 'undefined'\n ? process.env.NEXT_PUBLIC_AMPLIFYUP_TARGET\n : undefined;\n if (isAmplifyUpTarget(envTarget)) {\n return normalizeAmplifyUpTarget(envTarget);\n }\n\n return 'production';\n}\n\n/** True when the orchestrator origin is a remote AmplifyUp deployment (not localhost). */\nexport function isRemoteOrchestratorUrl(orchestratorUrl: string): boolean {\n try {\n const host = new URL(orchestratorUrl).hostname.toLowerCase();\n return host !== 'localhost' && host !== '127.0.0.1' && host !== '::1';\n } catch {\n return false;\n }\n}\n\nfunction localOrchestratorUrl(): string {\n const fromEnv =\n typeof process !== 'undefined'\n ? process.env.NEXT_PUBLIC_ORCHESTRATOR_URL\n : undefined;\n return (fromEnv || 'http://localhost:5001').replace(/\\/$/, '');\n}\n\n/**\n * Optional override for the local→AWS-dev API base (events + personalize).\n * Defaults to https://api-dev.amplifyup.ai\n */\nfunction localAwsApiUrl(): string {\n const fromEnv =\n typeof process !== 'undefined'\n ? process.env.NEXT_PUBLIC_AMPLIFYUP_API_URL\n : undefined;\n return (fromEnv || AWS_DEV_API).replace(/\\/$/, '');\n}\n\n/**\n * Optional override for the local Edge Worker URL.\n * Defaults to http://localhost:8787\n */\nfunction localEdgeUrl(): string {\n const fromEnv =\n typeof process !== 'undefined'\n ? process.env.NEXT_PUBLIC_EDGE_URL\n : undefined;\n return (fromEnv || 'http://localhost:8787').replace(/\\/$/, '');\n}\n\nexport function resolveAmplifyUpUrls(target: AmplifyUpTarget): AmplifyUpUrls {\n if (target === 'local') {\n const orchestratorUrl = localOrchestratorUrl();\n const apiGatewayUrl = localAwsApiUrl();\n return {\n target: 'local',\n // Layouts / site config / composer APIs → local orchestrator + Neon\n orchestratorUrl,\n // Events + personalize → AWS development stack\n apiGatewayUrl,\n decisionApiUrl: `${apiGatewayUrl}/v1/personalize`,\n edgeUrl: localEdgeUrl(),\n };\n }\n\n const resolvedApi =\n (typeof process !== 'undefined' &&\n process.env.NEXT_PUBLIC_AMPLIFYUP_API_URL?.replace(/\\/$/, '')) ||\n AWS_PROD_API;\n\n const orchestratorFromEnv =\n typeof process !== 'undefined'\n ? process.env.NEXT_PUBLIC_ORCHESTRATOR_URL\n : undefined;\n\n // Production: don't accidentally use a localhost orchestrator URL from a local env file\n const isLocalOrchestrator =\n !!orchestratorFromEnv &&\n (orchestratorFromEnv.includes('localhost') ||\n orchestratorFromEnv.includes('127.0.0.1'));\n\n const orchestratorUrl = isLocalOrchestrator || !orchestratorFromEnv\n ? PROD_ORCHESTRATOR\n : orchestratorFromEnv.replace(/\\/$/, '');\n\n const edgeFromEnv =\n typeof process !== 'undefined'\n ? process.env.NEXT_PUBLIC_EDGE_URL?.replace(/\\/$/, '')\n : undefined;\n const edgeUrl =\n edgeFromEnv &&\n !edgeFromEnv.includes('localhost') &&\n !edgeFromEnv.includes('127.0.0.1')\n ? edgeFromEnv\n : PROD_EDGE;\n\n return {\n target: 'production',\n apiGatewayUrl: resolvedApi,\n orchestratorUrl,\n decisionApiUrl: `${resolvedApi}/v1/personalize`,\n edgeUrl,\n };\n}\n","/**\n * Reserved customer-site pathnames owned by AmplifyUp (not marketing URLs).\n */\n\n/** Composer composition / layout editing. Live visitors must not see this page. */\nexport const AMPLIFYUP_EDITOR_ROUTE = '/__amplifyup/editor';\n\nexport function isAmplifyUpEditorRoute(pathname: string): boolean {\n return (\n pathname === AMPLIFYUP_EDITOR_ROUTE ||\n pathname.startsWith(`${AMPLIFYUP_EDITOR_ROUTE}/`)\n );\n}\n","/**\n * Next.js middleware: Composer preview rewrite + variant ISR rewrite.\n * Edge-runtime safe (no Node APIs).\n *\n * Soft-nav safety (Next.js <Link>):\n * - Prefetch and real navigations must take the **same rewrite path**. Skipping\n * variants on prefetch while rewriting on click aborts client navigation\n * (preventDefault runs, pathname never changes; Ctrl+click still works).\n * - Do **not** Set-Cookie on RSC / prefetch requests. Middleware Set-Cookie\n * during App Router soft navigation commonly cancels the transition.\n */\n\nimport { NextResponse } from 'next/server';\nimport type { NextRequest } from 'next/server';\nimport { fetchEdgeVariants } from './edge/fetchVariants';\nimport {\n isDefaultVariantKeys,\n serializeVariantKeys,\n} from './edge/variantKeys';\nimport { normalizeRoute } from './edge/normalizeRoute';\nimport { resolveAmplifyUpTarget, resolveAmplifyUpUrls } from './targets';\nimport {\n isAmplifyUpEditorRoute,\n} from './reservedRoutes';\n\nexport { AMPLIFYUP_EDITOR_ROUTE } from './reservedRoutes';\nexport const AMPLIFY_VARIANT_PREFIX = '/__p';\nexport const AMPLIFY_ANON_COOKIE = 'amplifyup_anon_id';\nexport const AMPLIFY_SESSION_COOKIE = 'amplifyup_session_id';\nconst SESSION_MAX_AGE_SECONDS = 30 * 60;\n\nexport const amplifyMiddlewareConfig = {\n matcher: ['/((?!api|_next/static|_next/image|favicon.ico|.*\\\\..*).*)'],\n};\n\nfunction isPrefetch(request: NextRequest): boolean {\n return (\n request.headers.get('x-middleware-prefetch') === '1' ||\n request.headers.get('Next-Router-Prefetch') === '1' ||\n request.headers.get('purpose') === 'prefetch' ||\n request.headers.get('Purpose') === 'prefetch'\n );\n}\n\n/** App Router flight / soft navigation (including Link prefetch). */\nfunction isNextClientNavigation(request: NextRequest): boolean {\n if (isPrefetch(request)) return true;\n const rsc = request.headers.get('rsc') || request.headers.get('RSC');\n if (rsc === '1') return true;\n if (request.headers.get('next-router-state-tree')) return true;\n if (request.headers.get('Next-Router-State-Tree')) return true;\n return false;\n}\n\nfunction generateAnonId(): string {\n const uuid =\n typeof crypto !== 'undefined' && 'randomUUID' in crypto\n ? crypto.randomUUID()\n : `${Date.now()}-${Math.random().toString(16).slice(2)}`;\n return `browser_${uuid}`;\n}\n\nfunction generateSessionId(): string {\n return typeof crypto !== 'undefined' && 'randomUUID' in crypto\n ? crypto.randomUUID()\n : `${Date.now()}-${Math.random().toString(16).slice(2)}`;\n}\n\n/**\n * Touch session cookie only when allowed (full document requests).\n * Re-setting cookies on every RSC response breaks Next.js soft navigation.\n */\nfunction withSessionCookie(\n res: NextResponse,\n existing: string | undefined,\n setCookies: boolean\n): NextResponse {\n if (!setCookies) return res;\n res.cookies.set(AMPLIFY_SESSION_COOKIE, existing || generateSessionId(), {\n path: '/',\n maxAge: SESSION_MAX_AGE_SECONDS,\n sameSite: 'lax',\n });\n return res;\n}\n\n/**\n * Preview stays dynamic. Personalized variants rewrite to `/__p/{keys}/…`\n * so Next can SSR the combo once and cache it (ISR). Default traffic is\n * unchanged SSG. Fail open to the default page on Edge errors/timeouts.\n */\nexport async function amplifyMiddleware(\n request: NextRequest,\n options?: { trackingId?: string }\n): Promise<NextResponse> {\n const { pathname, searchParams } = request.nextUrl;\n\n if (\n pathname.startsWith('/__preview') ||\n pathname.startsWith(AMPLIFY_VARIANT_PREFIX)\n ) {\n return NextResponse.next();\n }\n\n const isPreview =\n searchParams.get('preview') === 'true' ||\n searchParams.get('visualEditor') === 'true';\n\n // Composer-only editor route: live visitors get 404; preview rewrites like any page.\n if (isAmplifyUpEditorRoute(pathname) && !isPreview) {\n return new NextResponse(null, { status: 404 });\n }\n\n if (isPreview) {\n const url = request.nextUrl.clone();\n url.pathname = pathname === '/' ? '/__preview' : `/__preview${pathname}`;\n return NextResponse.rewrite(url);\n }\n\n const trackingId =\n options?.trackingId ||\n (typeof searchParams.get('trackingId') === 'string'\n ? searchParams.get('trackingId')\n : null) ||\n process.env.NEXT_PUBLIC_AMPLIFYUP_TRACKING_ID ||\n '';\n if (!trackingId) {\n return NextResponse.next();\n }\n\n // Full document loads may Set-Cookie; RSC / Link prefetch must not.\n const setCookies = !isNextClientNavigation(request);\n\n const existingAnon = request.cookies.get(AMPLIFY_ANON_COOKIE)?.value || '';\n const existingSession =\n request.cookies.get(AMPLIFY_SESSION_COOKIE)?.value || '';\n\n if (!existingAnon) {\n // First paint without identity: fail open. Mint cookies only on full loads\n // so soft nav is not aborted by Set-Cookie.\n if (!setCookies) {\n return NextResponse.next();\n }\n const res = NextResponse.next();\n res.cookies.set(AMPLIFY_ANON_COOKIE, generateAnonId(), {\n path: '/',\n maxAge: 60 * 60 * 24 * 365,\n sameSite: 'lax',\n });\n return withSessionCookie(res, existingSession, true);\n }\n\n const target = resolveAmplifyUpTarget();\n const { edgeUrl } = resolveAmplifyUpUrls(target);\n const route = normalizeRoute(pathname);\n\n try {\n // Same variant rewrite for prefetch and click — asymmetry breaks <Link>.\n const variantKeys = await fetchEdgeVariants({\n edgeUrl,\n trackingId,\n route,\n anonId: existingAnon,\n });\n if (isDefaultVariantKeys(variantKeys)) {\n return withSessionCookie(NextResponse.next(), existingSession, setCookies);\n }\n const sig = encodeURIComponent(serializeVariantKeys(variantKeys));\n const url = request.nextUrl.clone();\n url.pathname =\n pathname === '/'\n ? `${AMPLIFY_VARIANT_PREFIX}/${sig}`\n : `${AMPLIFY_VARIANT_PREFIX}/${sig}${pathname}`;\n return withSessionCookie(NextResponse.rewrite(url), existingSession, setCookies);\n } catch {\n return withSessionCookie(NextResponse.next(), existingSession, setCookies);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/reservedRoutes.ts","../src/middleware.ts"],"names":["NextResponse"],"mappings":"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","file":"middleware.js","sourcesContent":["/**\n * Reserved customer-site pathnames owned by AmplifyUp (not marketing URLs).\n */\n\n/** Composer composition / layout editing. Live visitors must not see this page. */\nexport const AMPLIFYUP_EDITOR_ROUTE = '/__amplifyup/editor';\n\nexport function isAmplifyUpEditorRoute(pathname: string): boolean {\n return (\n pathname === AMPLIFYUP_EDITOR_ROUTE ||\n pathname.startsWith(`${AMPLIFYUP_EDITOR_ROUTE}/`)\n );\n}\n","/**\n * Next.js middleware: Composer preview rewrite + first-party visitor cookies.\n * Edge-runtime safe (no Node APIs).\n *\n * Do **not** rewrite live routes to `/__p/{keys}/…`. That changes the App\n * Router tree while the browser URL stays the same. Next.js `<Link>` then\n * calls preventDefault, issues no RSC fetch, and `location.pathname` never\n * changes (Ctrl/Cmd-click still works as a full load). Personalized HTML\n * comes from the SDK client overlay (`/v1/select` + `/v1/resolve`).\n *\n * Cookies are only set on full document loads — never on RSC / prefetch.\n */\n\nimport { NextResponse } from 'next/server';\nimport type { NextRequest } from 'next/server';\nimport { isAmplifyUpEditorRoute } from './reservedRoutes';\n\nexport { AMPLIFYUP_EDITOR_ROUTE } from './reservedRoutes';\nexport const AMPLIFY_VARIANT_PREFIX = '/__p';\nexport const AMPLIFY_ANON_COOKIE = 'amplifyup_anon_id';\nexport const AMPLIFY_SESSION_COOKIE = 'amplifyup_session_id';\nconst SESSION_MAX_AGE_SECONDS = 30 * 60;\n\nexport const amplifyMiddlewareConfig = {\n matcher: ['/((?!api|_next/static|_next/image|favicon.ico|.*\\\\..*).*)'],\n};\n\nfunction isPrefetch(request: NextRequest): boolean {\n return (\n request.headers.get('x-middleware-prefetch') === '1' ||\n request.headers.get('Next-Router-Prefetch') === '1' ||\n request.headers.get('purpose') === 'prefetch' ||\n request.headers.get('Purpose') === 'prefetch'\n );\n}\n\n/** App Router flight / soft navigation (including Link prefetch). */\nexport function isNextClientNavigation(request: NextRequest): boolean {\n if (isPrefetch(request)) return true;\n const rsc = request.headers.get('rsc') || request.headers.get('RSC');\n if (rsc === '1') return true;\n if (request.headers.get('next-router-state-tree')) return true;\n if (request.headers.get('Next-Router-State-Tree')) return true;\n return false;\n}\n\nfunction generateAnonId(): string {\n const uuid =\n typeof crypto !== 'undefined' && 'randomUUID' in crypto\n ? crypto.randomUUID()\n : `${Date.now()}-${Math.random().toString(16).slice(2)}`;\n return `browser_${uuid}`;\n}\n\nfunction generateSessionId(): string {\n return typeof crypto !== 'undefined' && 'randomUUID' in crypto\n ? crypto.randomUUID()\n : `${Date.now()}-${Math.random().toString(16).slice(2)}`;\n}\n\nfunction withIdentityCookies(\n res: NextResponse,\n anonId: string,\n sessionId: string\n): NextResponse {\n res.cookies.set(AMPLIFY_ANON_COOKIE, anonId, {\n path: '/',\n maxAge: 60 * 60 * 24 * 365,\n sameSite: 'lax',\n });\n res.cookies.set(AMPLIFY_SESSION_COOKIE, sessionId, {\n path: '/',\n maxAge: SESSION_MAX_AGE_SECONDS,\n sameSite: 'lax',\n });\n return res;\n}\n\n/**\n * Preview stays dynamic. Live traffic is never rewritten off its public path\n * so Next.js `<Link>` soft navigation can complete.\n */\nexport async function amplifyMiddleware(\n request: NextRequest,\n _options?: { trackingId?: string }\n): Promise<NextResponse> {\n const { pathname, searchParams } = request.nextUrl;\n\n if (\n pathname.startsWith('/__preview') ||\n pathname.startsWith(AMPLIFY_VARIANT_PREFIX)\n ) {\n return NextResponse.next();\n }\n\n const isPreview =\n searchParams.get('preview') === 'true' ||\n searchParams.get('visualEditor') === 'true';\n\n // Composer-only editor route: live visitors get 404; preview rewrites like any page.\n if (isAmplifyUpEditorRoute(pathname) && !isPreview) {\n return new NextResponse(null, { status: 404 });\n }\n\n if (isPreview) {\n const url = request.nextUrl.clone();\n url.pathname = pathname === '/' ? '/__preview' : `/__preview${pathname}`;\n return NextResponse.rewrite(url);\n }\n\n // Soft nav / prefetch: do not rewrite and do not Set-Cookie.\n if (isNextClientNavigation(request)) {\n return NextResponse.next();\n }\n\n const existingAnon = request.cookies.get(AMPLIFY_ANON_COOKIE)?.value || '';\n const existingSession =\n request.cookies.get(AMPLIFY_SESSION_COOKIE)?.value || '';\n\n // Only mint missing cookies on a full document load. Refreshing the session\n // cookie on every navigation races Next's client router.\n if (existingAnon && existingSession) {\n return NextResponse.next();\n }\n\n return withIdentityCookies(\n NextResponse.next(),\n existingAnon || generateAnonId(),\n existingSession || generateSessionId()\n );\n}\n"]}
|
package/dist/middleware.mjs
CHANGED
|
@@ -3,128 +3,6 @@ import { NextResponse } from 'next/server';
|
|
|
3
3
|
/* @amplifyup/sdk - https://amplifyup.ai */
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
// src/edge/fetchVariants.ts
|
|
7
|
-
async function fetchEdgeVariants(options) {
|
|
8
|
-
const base = options.edgeUrl.replace(/\/+$/, "");
|
|
9
|
-
const params = new URLSearchParams({
|
|
10
|
-
route: options.route,
|
|
11
|
-
trackingId: options.trackingId,
|
|
12
|
-
anonId: options.anonId
|
|
13
|
-
});
|
|
14
|
-
const fetchFn = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
15
|
-
const controller = new AbortController();
|
|
16
|
-
const timer = setTimeout(() => controller.abort(), options.timeoutMs ?? 800);
|
|
17
|
-
try {
|
|
18
|
-
const res = await fetchFn(`${base}/v1/variants?${params.toString()}`, {
|
|
19
|
-
method: "GET",
|
|
20
|
-
headers: { Accept: "application/json" },
|
|
21
|
-
cache: "no-store",
|
|
22
|
-
signal: controller.signal
|
|
23
|
-
});
|
|
24
|
-
if (!res.ok) return {};
|
|
25
|
-
const body = await res.json().catch(() => ({}));
|
|
26
|
-
return body.variantKeys && typeof body.variantKeys === "object" ? body.variantKeys : {};
|
|
27
|
-
} finally {
|
|
28
|
-
clearTimeout(timer);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// src/edge/variantKeys.ts
|
|
33
|
-
function serializeVariantKeys(keys) {
|
|
34
|
-
if (!keys) return "";
|
|
35
|
-
const parts = [];
|
|
36
|
-
const zoneIds = Object.keys(keys).sort();
|
|
37
|
-
for (const zoneId of zoneIds) {
|
|
38
|
-
const variant = keys[zoneId];
|
|
39
|
-
if (!variant || variant === "default") continue;
|
|
40
|
-
parts.push(`${zoneId}:${variant}`);
|
|
41
|
-
}
|
|
42
|
-
return parts.join(",");
|
|
43
|
-
}
|
|
44
|
-
function isDefaultVariantKeys(keys) {
|
|
45
|
-
return serializeVariantKeys(keys) === "";
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// src/edge/normalizeRoute.ts
|
|
49
|
-
function normalizeRoute(route) {
|
|
50
|
-
let path = String(route || "").trim();
|
|
51
|
-
if (!path) return "/";
|
|
52
|
-
try {
|
|
53
|
-
if (/^https?:\/\//i.test(path)) {
|
|
54
|
-
path = new URL(path).pathname;
|
|
55
|
-
}
|
|
56
|
-
} catch {
|
|
57
|
-
}
|
|
58
|
-
const q = path.indexOf("?");
|
|
59
|
-
if (q >= 0) path = path.slice(0, q);
|
|
60
|
-
const h = path.indexOf("#");
|
|
61
|
-
if (h >= 0) path = path.slice(0, h);
|
|
62
|
-
if (!path.startsWith("/")) path = `/${path}`;
|
|
63
|
-
if (path.length > 1 && path.endsWith("/")) {
|
|
64
|
-
path = path.replace(/\/+$/, "");
|
|
65
|
-
}
|
|
66
|
-
return path || "/";
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// src/targets.ts
|
|
70
|
-
var AWS_DEV_API = "https://api-dev.amplifyup.ai";
|
|
71
|
-
var AWS_PROD_API = "https://api.amplifyup.ai";
|
|
72
|
-
var PROD_ORCHESTRATOR = "https://amplifyup.ai";
|
|
73
|
-
var PROD_EDGE = "https://edge.amplifyup.ai";
|
|
74
|
-
function isAmplifyUpTarget(value) {
|
|
75
|
-
return value === "local" || value === "dev" || value === "production";
|
|
76
|
-
}
|
|
77
|
-
function normalizeAmplifyUpTarget(value) {
|
|
78
|
-
return value === "dev" ? "local" : value;
|
|
79
|
-
}
|
|
80
|
-
function resolveAmplifyUpTarget(options) {
|
|
81
|
-
const envTarget = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_AMPLIFYUP_TARGET : void 0;
|
|
82
|
-
if (isAmplifyUpTarget(envTarget)) {
|
|
83
|
-
return normalizeAmplifyUpTarget(envTarget);
|
|
84
|
-
}
|
|
85
|
-
return "production";
|
|
86
|
-
}
|
|
87
|
-
function localOrchestratorUrl() {
|
|
88
|
-
const fromEnv = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_ORCHESTRATOR_URL : void 0;
|
|
89
|
-
return (fromEnv || "http://localhost:5001").replace(/\/$/, "");
|
|
90
|
-
}
|
|
91
|
-
function localAwsApiUrl() {
|
|
92
|
-
const fromEnv = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_AMPLIFYUP_API_URL : void 0;
|
|
93
|
-
return (fromEnv || AWS_DEV_API).replace(/\/$/, "");
|
|
94
|
-
}
|
|
95
|
-
function localEdgeUrl() {
|
|
96
|
-
const fromEnv = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_EDGE_URL : void 0;
|
|
97
|
-
return (fromEnv || "http://localhost:8787").replace(/\/$/, "");
|
|
98
|
-
}
|
|
99
|
-
function resolveAmplifyUpUrls(target) {
|
|
100
|
-
if (target === "local") {
|
|
101
|
-
const orchestratorUrl2 = localOrchestratorUrl();
|
|
102
|
-
const apiGatewayUrl = localAwsApiUrl();
|
|
103
|
-
return {
|
|
104
|
-
target: "local",
|
|
105
|
-
// Layouts / site config / composer APIs → local orchestrator + Neon
|
|
106
|
-
orchestratorUrl: orchestratorUrl2,
|
|
107
|
-
// Events + personalize → AWS development stack
|
|
108
|
-
apiGatewayUrl,
|
|
109
|
-
decisionApiUrl: `${apiGatewayUrl}/v1/personalize`,
|
|
110
|
-
edgeUrl: localEdgeUrl()
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
const resolvedApi = typeof process !== "undefined" && process.env.NEXT_PUBLIC_AMPLIFYUP_API_URL?.replace(/\/$/, "") || AWS_PROD_API;
|
|
114
|
-
const orchestratorFromEnv = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_ORCHESTRATOR_URL : void 0;
|
|
115
|
-
const isLocalOrchestrator = !!orchestratorFromEnv && (orchestratorFromEnv.includes("localhost") || orchestratorFromEnv.includes("127.0.0.1"));
|
|
116
|
-
const orchestratorUrl = isLocalOrchestrator || !orchestratorFromEnv ? PROD_ORCHESTRATOR : orchestratorFromEnv.replace(/\/$/, "");
|
|
117
|
-
const edgeFromEnv = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_EDGE_URL?.replace(/\/$/, "") : void 0;
|
|
118
|
-
const edgeUrl = edgeFromEnv && !edgeFromEnv.includes("localhost") && !edgeFromEnv.includes("127.0.0.1") ? edgeFromEnv : PROD_EDGE;
|
|
119
|
-
return {
|
|
120
|
-
target: "production",
|
|
121
|
-
apiGatewayUrl: resolvedApi,
|
|
122
|
-
orchestratorUrl,
|
|
123
|
-
decisionApiUrl: `${resolvedApi}/v1/personalize`,
|
|
124
|
-
edgeUrl
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
|
|
128
6
|
// src/reservedRoutes.ts
|
|
129
7
|
var AMPLIFYUP_EDITOR_ROUTE = "/__amplifyup/editor";
|
|
130
8
|
function isAmplifyUpEditorRoute(pathname) {
|
|
@@ -157,16 +35,20 @@ function generateAnonId() {
|
|
|
157
35
|
function generateSessionId() {
|
|
158
36
|
return typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
159
37
|
}
|
|
160
|
-
function
|
|
161
|
-
|
|
162
|
-
|
|
38
|
+
function withIdentityCookies(res, anonId, sessionId) {
|
|
39
|
+
res.cookies.set(AMPLIFY_ANON_COOKIE, anonId, {
|
|
40
|
+
path: "/",
|
|
41
|
+
maxAge: 60 * 60 * 24 * 365,
|
|
42
|
+
sameSite: "lax"
|
|
43
|
+
});
|
|
44
|
+
res.cookies.set(AMPLIFY_SESSION_COOKIE, sessionId, {
|
|
163
45
|
path: "/",
|
|
164
46
|
maxAge: SESSION_MAX_AGE_SECONDS,
|
|
165
47
|
sameSite: "lax"
|
|
166
48
|
});
|
|
167
49
|
return res;
|
|
168
50
|
}
|
|
169
|
-
async function amplifyMiddleware(request,
|
|
51
|
+
async function amplifyMiddleware(request, _options) {
|
|
170
52
|
const { pathname, searchParams } = request.nextUrl;
|
|
171
53
|
if (pathname.startsWith("/__preview") || pathname.startsWith(AMPLIFY_VARIANT_PREFIX)) {
|
|
172
54
|
return NextResponse.next();
|
|
@@ -180,47 +62,21 @@ async function amplifyMiddleware(request, options) {
|
|
|
180
62
|
url.pathname = pathname === "/" ? "/__preview" : `/__preview${pathname}`;
|
|
181
63
|
return NextResponse.rewrite(url);
|
|
182
64
|
}
|
|
183
|
-
|
|
184
|
-
if (!trackingId) {
|
|
65
|
+
if (isNextClientNavigation(request)) {
|
|
185
66
|
return NextResponse.next();
|
|
186
67
|
}
|
|
187
|
-
const setCookies = !isNextClientNavigation(request);
|
|
188
68
|
const existingAnon = request.cookies.get(AMPLIFY_ANON_COOKIE)?.value || "";
|
|
189
69
|
const existingSession = request.cookies.get(AMPLIFY_SESSION_COOKIE)?.value || "";
|
|
190
|
-
if (
|
|
191
|
-
|
|
192
|
-
return NextResponse.next();
|
|
193
|
-
}
|
|
194
|
-
const res = NextResponse.next();
|
|
195
|
-
res.cookies.set(AMPLIFY_ANON_COOKIE, generateAnonId(), {
|
|
196
|
-
path: "/",
|
|
197
|
-
maxAge: 60 * 60 * 24 * 365,
|
|
198
|
-
sameSite: "lax"
|
|
199
|
-
});
|
|
200
|
-
return withSessionCookie(res, existingSession, true);
|
|
201
|
-
}
|
|
202
|
-
const target = resolveAmplifyUpTarget();
|
|
203
|
-
const { edgeUrl } = resolveAmplifyUpUrls(target);
|
|
204
|
-
const route = normalizeRoute(pathname);
|
|
205
|
-
try {
|
|
206
|
-
const variantKeys = await fetchEdgeVariants({
|
|
207
|
-
edgeUrl,
|
|
208
|
-
trackingId,
|
|
209
|
-
route,
|
|
210
|
-
anonId: existingAnon
|
|
211
|
-
});
|
|
212
|
-
if (isDefaultVariantKeys(variantKeys)) {
|
|
213
|
-
return withSessionCookie(NextResponse.next(), existingSession, setCookies);
|
|
214
|
-
}
|
|
215
|
-
const sig = encodeURIComponent(serializeVariantKeys(variantKeys));
|
|
216
|
-
const url = request.nextUrl.clone();
|
|
217
|
-
url.pathname = pathname === "/" ? `${AMPLIFY_VARIANT_PREFIX}/${sig}` : `${AMPLIFY_VARIANT_PREFIX}/${sig}${pathname}`;
|
|
218
|
-
return withSessionCookie(NextResponse.rewrite(url), existingSession, setCookies);
|
|
219
|
-
} catch {
|
|
220
|
-
return withSessionCookie(NextResponse.next(), existingSession, setCookies);
|
|
70
|
+
if (existingAnon && existingSession) {
|
|
71
|
+
return NextResponse.next();
|
|
221
72
|
}
|
|
73
|
+
return withIdentityCookies(
|
|
74
|
+
NextResponse.next(),
|
|
75
|
+
existingAnon || generateAnonId(),
|
|
76
|
+
existingSession || generateSessionId()
|
|
77
|
+
);
|
|
222
78
|
}
|
|
223
79
|
|
|
224
|
-
export { AMPLIFYUP_EDITOR_ROUTE, AMPLIFY_ANON_COOKIE, AMPLIFY_SESSION_COOKIE, AMPLIFY_VARIANT_PREFIX, amplifyMiddleware, amplifyMiddlewareConfig };
|
|
80
|
+
export { AMPLIFYUP_EDITOR_ROUTE, AMPLIFY_ANON_COOKIE, AMPLIFY_SESSION_COOKIE, AMPLIFY_VARIANT_PREFIX, amplifyMiddleware, amplifyMiddlewareConfig, isNextClientNavigation };
|
|
225
81
|
//# sourceMappingURL=middleware.mjs.map
|
|
226
82
|
//# sourceMappingURL=middleware.mjs.map
|