@amplifyup/sdk 0.1.50 → 0.1.51

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.
@@ -4,6 +4,13 @@ export { A as AMPLIFYUP_EDITOR_ROUTE } from './reservedRoutes-aGgViBDM.mjs';
4
4
  /**
5
5
  * Next.js middleware: Composer preview rewrite + variant ISR rewrite.
6
6
  * Edge-runtime safe (no Node APIs).
7
+ *
8
+ * Soft-nav safety (Next.js <Link>):
9
+ * - Prefetch and real navigations must take the **same rewrite path**. Skipping
10
+ * variants on prefetch while rewriting on click aborts client navigation
11
+ * (preventDefault runs, pathname never changes; Ctrl+click still works).
12
+ * - Do **not** Set-Cookie on RSC / prefetch requests. Middleware Set-Cookie
13
+ * during App Router soft navigation commonly cancels the transition.
7
14
  */
8
15
 
9
16
  declare const AMPLIFY_VARIANT_PREFIX = "/__p";
@@ -4,6 +4,13 @@ export { A as AMPLIFYUP_EDITOR_ROUTE } from './reservedRoutes-aGgViBDM.js';
4
4
  /**
5
5
  * Next.js middleware: Composer preview rewrite + variant ISR rewrite.
6
6
  * Edge-runtime safe (no Node APIs).
7
+ *
8
+ * Soft-nav safety (Next.js <Link>):
9
+ * - Prefetch and real navigations must take the **same rewrite path**. Skipping
10
+ * variants on prefetch while rewriting on click aborts client navigation
11
+ * (preventDefault runs, pathname never changes; Ctrl+click still works).
12
+ * - Do **not** Set-Cookie on RSC / prefetch requests. Middleware Set-Cookie
13
+ * during App Router soft navigation commonly cancels the transition.
7
14
  */
8
15
 
9
16
  declare const AMPLIFY_VARIANT_PREFIX = "/__p";
@@ -144,6 +144,14 @@ var amplifyMiddlewareConfig = {
144
144
  function isPrefetch(request) {
145
145
  return request.headers.get("x-middleware-prefetch") === "1" || request.headers.get("Next-Router-Prefetch") === "1" || request.headers.get("purpose") === "prefetch" || request.headers.get("Purpose") === "prefetch";
146
146
  }
147
+ function isNextClientNavigation(request) {
148
+ if (isPrefetch(request)) return true;
149
+ const rsc = request.headers.get("rsc") || request.headers.get("RSC");
150
+ if (rsc === "1") return true;
151
+ if (request.headers.get("next-router-state-tree")) return true;
152
+ if (request.headers.get("Next-Router-State-Tree")) return true;
153
+ return false;
154
+ }
147
155
  function generateAnonId() {
148
156
  const uuid = typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `${Date.now()}-${Math.random().toString(16).slice(2)}`;
149
157
  return `browser_${uuid}`;
@@ -151,7 +159,8 @@ function generateAnonId() {
151
159
  function generateSessionId() {
152
160
  return typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `${Date.now()}-${Math.random().toString(16).slice(2)}`;
153
161
  }
154
- function withSessionCookie(res, existing) {
162
+ function withSessionCookie(res, existing, setCookies) {
163
+ if (!setCookies) return res;
155
164
  res.cookies.set(AMPLIFY_SESSION_COOKIE, existing || generateSessionId(), {
156
165
  path: "/",
157
166
  maxAge: SESSION_MAX_AGE_SECONDS,
@@ -173,23 +182,24 @@ async function amplifyMiddleware(request, options) {
173
182
  url.pathname = pathname === "/" ? "/__preview" : `/__preview${pathname}`;
174
183
  return server.NextResponse.rewrite(url);
175
184
  }
176
- if (isPrefetch(request)) {
177
- return server.NextResponse.next();
178
- }
179
185
  const trackingId = options?.trackingId || (typeof searchParams.get("trackingId") === "string" ? searchParams.get("trackingId") : null) || process.env.NEXT_PUBLIC_AMPLIFYUP_TRACKING_ID || "";
180
186
  if (!trackingId) {
181
187
  return server.NextResponse.next();
182
188
  }
189
+ const setCookies = !isNextClientNavigation(request);
183
190
  const existingAnon = request.cookies.get(AMPLIFY_ANON_COOKIE)?.value || "";
184
191
  const existingSession = request.cookies.get(AMPLIFY_SESSION_COOKIE)?.value || "";
185
192
  if (!existingAnon) {
193
+ if (!setCookies) {
194
+ return server.NextResponse.next();
195
+ }
186
196
  const res = server.NextResponse.next();
187
197
  res.cookies.set(AMPLIFY_ANON_COOKIE, generateAnonId(), {
188
198
  path: "/",
189
199
  maxAge: 60 * 60 * 24 * 365,
190
200
  sameSite: "lax"
191
201
  });
192
- return withSessionCookie(res, existingSession);
202
+ return withSessionCookie(res, existingSession, true);
193
203
  }
194
204
  const target = resolveAmplifyUpTarget();
195
205
  const { edgeUrl } = resolveAmplifyUpUrls(target);
@@ -202,14 +212,14 @@ async function amplifyMiddleware(request, options) {
202
212
  anonId: existingAnon
203
213
  });
204
214
  if (isDefaultVariantKeys(variantKeys)) {
205
- return withSessionCookie(server.NextResponse.next(), existingSession);
215
+ return withSessionCookie(server.NextResponse.next(), existingSession, setCookies);
206
216
  }
207
217
  const sig = encodeURIComponent(serializeVariantKeys(variantKeys));
208
218
  const url = request.nextUrl.clone();
209
219
  url.pathname = pathname === "/" ? `${AMPLIFY_VARIANT_PREFIX}/${sig}` : `${AMPLIFY_VARIANT_PREFIX}/${sig}${pathname}`;
210
- return withSessionCookie(server.NextResponse.rewrite(url), existingSession);
220
+ return withSessionCookie(server.NextResponse.rewrite(url), existingSession, setCookies);
211
221
  } catch {
212
- return withSessionCookie(server.NextResponse.next(), existingSession);
222
+ return withSessionCookie(server.NextResponse.next(), existingSession, setCookies);
213
223
  }
214
224
  }
215
225
 
@@ -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\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\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 withSessionCookie(res: NextResponse, existing?: string): NextResponse {\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 if (isPrefetch(request)) {\n return NextResponse.next();\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 const existingAnon = request.cookies.get(AMPLIFY_ANON_COOKIE)?.value || '';\n const existingSession = request.cookies.get(AMPLIFY_SESSION_COOKIE)?.value || '';\n if (!existingAnon) {\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);\n }\n\n const target = resolveAmplifyUpTarget();\n const { edgeUrl } = resolveAmplifyUpUrls(target);\n const route = normalizeRoute(pathname);\n\n try {\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);\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);\n } catch {\n return withSessionCookie(NextResponse.next(), existingSession);\n }\n}\n"]}
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"]}
@@ -142,6 +142,14 @@ var amplifyMiddlewareConfig = {
142
142
  function isPrefetch(request) {
143
143
  return request.headers.get("x-middleware-prefetch") === "1" || request.headers.get("Next-Router-Prefetch") === "1" || request.headers.get("purpose") === "prefetch" || request.headers.get("Purpose") === "prefetch";
144
144
  }
145
+ function isNextClientNavigation(request) {
146
+ if (isPrefetch(request)) return true;
147
+ const rsc = request.headers.get("rsc") || request.headers.get("RSC");
148
+ if (rsc === "1") return true;
149
+ if (request.headers.get("next-router-state-tree")) return true;
150
+ if (request.headers.get("Next-Router-State-Tree")) return true;
151
+ return false;
152
+ }
145
153
  function generateAnonId() {
146
154
  const uuid = typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `${Date.now()}-${Math.random().toString(16).slice(2)}`;
147
155
  return `browser_${uuid}`;
@@ -149,7 +157,8 @@ function generateAnonId() {
149
157
  function generateSessionId() {
150
158
  return typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `${Date.now()}-${Math.random().toString(16).slice(2)}`;
151
159
  }
152
- function withSessionCookie(res, existing) {
160
+ function withSessionCookie(res, existing, setCookies) {
161
+ if (!setCookies) return res;
153
162
  res.cookies.set(AMPLIFY_SESSION_COOKIE, existing || generateSessionId(), {
154
163
  path: "/",
155
164
  maxAge: SESSION_MAX_AGE_SECONDS,
@@ -171,23 +180,24 @@ async function amplifyMiddleware(request, options) {
171
180
  url.pathname = pathname === "/" ? "/__preview" : `/__preview${pathname}`;
172
181
  return NextResponse.rewrite(url);
173
182
  }
174
- if (isPrefetch(request)) {
175
- return NextResponse.next();
176
- }
177
183
  const trackingId = options?.trackingId || (typeof searchParams.get("trackingId") === "string" ? searchParams.get("trackingId") : null) || process.env.NEXT_PUBLIC_AMPLIFYUP_TRACKING_ID || "";
178
184
  if (!trackingId) {
179
185
  return NextResponse.next();
180
186
  }
187
+ const setCookies = !isNextClientNavigation(request);
181
188
  const existingAnon = request.cookies.get(AMPLIFY_ANON_COOKIE)?.value || "";
182
189
  const existingSession = request.cookies.get(AMPLIFY_SESSION_COOKIE)?.value || "";
183
190
  if (!existingAnon) {
191
+ if (!setCookies) {
192
+ return NextResponse.next();
193
+ }
184
194
  const res = NextResponse.next();
185
195
  res.cookies.set(AMPLIFY_ANON_COOKIE, generateAnonId(), {
186
196
  path: "/",
187
197
  maxAge: 60 * 60 * 24 * 365,
188
198
  sameSite: "lax"
189
199
  });
190
- return withSessionCookie(res, existingSession);
200
+ return withSessionCookie(res, existingSession, true);
191
201
  }
192
202
  const target = resolveAmplifyUpTarget();
193
203
  const { edgeUrl } = resolveAmplifyUpUrls(target);
@@ -200,14 +210,14 @@ async function amplifyMiddleware(request, options) {
200
210
  anonId: existingAnon
201
211
  });
202
212
  if (isDefaultVariantKeys(variantKeys)) {
203
- return withSessionCookie(NextResponse.next(), existingSession);
213
+ return withSessionCookie(NextResponse.next(), existingSession, setCookies);
204
214
  }
205
215
  const sig = encodeURIComponent(serializeVariantKeys(variantKeys));
206
216
  const url = request.nextUrl.clone();
207
217
  url.pathname = pathname === "/" ? `${AMPLIFY_VARIANT_PREFIX}/${sig}` : `${AMPLIFY_VARIANT_PREFIX}/${sig}${pathname}`;
208
- return withSessionCookie(NextResponse.rewrite(url), existingSession);
218
+ return withSessionCookie(NextResponse.rewrite(url), existingSession, setCookies);
209
219
  } catch {
210
- return withSessionCookie(NextResponse.next(), existingSession);
220
+ return withSessionCookie(NextResponse.next(), existingSession, setCookies);
211
221
  }
212
222
  }
213
223
 
@@ -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"],"mappings":"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","file":"middleware.mjs","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\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\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 withSessionCookie(res: NextResponse, existing?: string): NextResponse {\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 if (isPrefetch(request)) {\n return NextResponse.next();\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 const existingAnon = request.cookies.get(AMPLIFY_ANON_COOKIE)?.value || '';\n const existingSession = request.cookies.get(AMPLIFY_SESSION_COOKIE)?.value || '';\n if (!existingAnon) {\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);\n }\n\n const target = resolveAmplifyUpTarget();\n const { edgeUrl } = resolveAmplifyUpUrls(target);\n const route = normalizeRoute(pathname);\n\n try {\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);\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);\n } catch {\n return withSessionCookie(NextResponse.next(), existingSession);\n }\n}\n"]}
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"],"mappings":"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","file":"middleware.mjs","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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amplifyup/sdk",
3
- "version": "0.1.50",
3
+ "version": "0.1.51",
4
4
  "description": "AmplifyUp Tracking SDK - CDP-agnostic event tracking library",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",