From f34f04d7eb4a282d7fc3ccca4213356dd3edf7ca Mon Sep 17 00:00:00 2001
From: aeneasr <3372410+aeneasr@users.noreply.github.com>
Date: Tue, 15 Oct 2024 19:59:00 +0200
Subject: [PATCH] chore: synchronize workspaces
---
examples/nextjs-app-router/.env | 1 +
examples/nextjs-app-router/.eslintrc.json | 3 +
examples/nextjs-app-router/.gitignore | 36 ++
examples/nextjs-app-router/README.md | 36 ++
.../nextjs-app-router/app/(ory)/config.ts | 19 +
.../nextjs-app-router/app/(ory)/layout.tsx | 3 +
examples/nextjs-app-router/app/(ory)/sdk.ts | 11 +
examples/nextjs-app-router/next.config.mjs | 4 +
examples/nextjs-app-router/package.json | 30 ++
examples/nextjs-app-router/postcss.config.mjs | 8 +
.../app/common/default-forwarded-headers.ts | 13 +
.../routers/app/common/get-base-url.ts | 26 +
.../app/common/get-cookie-domain.test.ts | 71 +++
.../routers/app/common/get-cookie-domain.ts | 27 +
.../app/common/process-location-header.ts | 18 +
.../nextjs-app-router/routers/app/layout.tsx | 12 +
.../nextjs-app-router/routers/app/login.ts | 62 +++
.../nextjs-app-router/routers/app/proxy.ts | 148 ++++++
.../app/type/create-api-handler-options.ts | 48 ++
.../nextjs-app-router/routers/app/utils.ts | 70 +++
examples/nextjs-app-router/tailwind.config.ts | 19 +
examples/nextjs-app-router/tsconfig.json | 26 +
package-lock.json | 482 +++++++++++++++++-
23 files changed, 1172 insertions(+), 1 deletion(-)
create mode 100644 examples/nextjs-app-router/.env
create mode 100644 examples/nextjs-app-router/.eslintrc.json
create mode 100644 examples/nextjs-app-router/.gitignore
create mode 100644 examples/nextjs-app-router/README.md
create mode 100644 examples/nextjs-app-router/app/(ory)/config.ts
create mode 100644 examples/nextjs-app-router/app/(ory)/layout.tsx
create mode 100644 examples/nextjs-app-router/app/(ory)/sdk.ts
create mode 100644 examples/nextjs-app-router/next.config.mjs
create mode 100644 examples/nextjs-app-router/package.json
create mode 100644 examples/nextjs-app-router/postcss.config.mjs
create mode 100644 examples/nextjs-app-router/routers/app/common/default-forwarded-headers.ts
create mode 100644 examples/nextjs-app-router/routers/app/common/get-base-url.ts
create mode 100644 examples/nextjs-app-router/routers/app/common/get-cookie-domain.test.ts
create mode 100644 examples/nextjs-app-router/routers/app/common/get-cookie-domain.ts
create mode 100644 examples/nextjs-app-router/routers/app/common/process-location-header.ts
create mode 100644 examples/nextjs-app-router/routers/app/layout.tsx
create mode 100644 examples/nextjs-app-router/routers/app/login.ts
create mode 100644 examples/nextjs-app-router/routers/app/proxy.ts
create mode 100644 examples/nextjs-app-router/routers/app/type/create-api-handler-options.ts
create mode 100644 examples/nextjs-app-router/routers/app/utils.ts
create mode 100644 examples/nextjs-app-router/tailwind.config.ts
create mode 100644 examples/nextjs-app-router/tsconfig.json
diff --git a/examples/nextjs-app-router/.env b/examples/nextjs-app-router/.env
new file mode 100644
index 000000000..3f25fd45d
--- /dev/null
+++ b/examples/nextjs-app-router/.env
@@ -0,0 +1 @@
+ORY_SDK_URL=https://playground.projects.oryapis.com
diff --git a/examples/nextjs-app-router/.eslintrc.json b/examples/nextjs-app-router/.eslintrc.json
new file mode 100644
index 000000000..372241854
--- /dev/null
+++ b/examples/nextjs-app-router/.eslintrc.json
@@ -0,0 +1,3 @@
+{
+ "extends": ["next/core-web-vitals", "next/typescript"]
+}
diff --git a/examples/nextjs-app-router/.gitignore b/examples/nextjs-app-router/.gitignore
new file mode 100644
index 000000000..fd3dbb571
--- /dev/null
+++ b/examples/nextjs-app-router/.gitignore
@@ -0,0 +1,36 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+.yarn/install-state.gz
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env*.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
diff --git a/examples/nextjs-app-router/README.md b/examples/nextjs-app-router/README.md
new file mode 100644
index 000000000..e215bc4cc
--- /dev/null
+++ b/examples/nextjs-app-router/README.md
@@ -0,0 +1,36 @@
+This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
+
+## Getting Started
+
+First, run the development server:
+
+```bash
+npm run dev
+# or
+yarn dev
+# or
+pnpm dev
+# or
+bun dev
+```
+
+Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
+
+You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
+
+This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
+
+## Learn More
+
+To learn more about Next.js, take a look at the following resources:
+
+- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
+- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
+
+You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
+
+## Deploy on Vercel
+
+The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
+
+Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
diff --git a/examples/nextjs-app-router/app/(ory)/config.ts b/examples/nextjs-app-router/app/(ory)/config.ts
new file mode 100644
index 000000000..818f88205
--- /dev/null
+++ b/examples/nextjs-app-router/app/(ory)/config.ts
@@ -0,0 +1,19 @@
+import { OryClientConfiguration } from "@ory/elements-react"
+
+const config: OryClientConfiguration = {
+ name: "Ory Elements example app",
+ sdk: {
+ url: process.env.ORY_SDK_URL || ''
+ },
+ project:{
+ registration_enabled: true,
+ verification_enabled: true,
+ recovery_enabled: true,
+ recovery_ui_url: '/recovery',
+ registration_ui_url: '/registration',
+ verification_ui_url: '/verification',
+ login_ui_url: '/login',
+ }
+}
+
+export default config
diff --git a/examples/nextjs-app-router/app/(ory)/layout.tsx b/examples/nextjs-app-router/app/(ory)/layout.tsx
new file mode 100644
index 000000000..15b59b749
--- /dev/null
+++ b/examples/nextjs-app-router/app/(ory)/layout.tsx
@@ -0,0 +1,3 @@
+import AuthLayout from "@/routers/app/layout";
+
+export default AuthLayout
diff --git a/examples/nextjs-app-router/app/(ory)/sdk.ts b/examples/nextjs-app-router/app/(ory)/sdk.ts
new file mode 100644
index 000000000..7e8668e95
--- /dev/null
+++ b/examples/nextjs-app-router/app/(ory)/sdk.ts
@@ -0,0 +1,11 @@
+import { Configuration, FrontendApi } from "@ory/client-fetch"
+
+export function newSDK() {
+ const config = new Configuration({
+ headers: {
+ Accept: "application/json",
+ },
+ basePath: process.env.ORY_SDK_URL,
+ })
+ return new FrontendApi(config)
+}
diff --git a/examples/nextjs-app-router/next.config.mjs b/examples/nextjs-app-router/next.config.mjs
new file mode 100644
index 000000000..4678774e6
--- /dev/null
+++ b/examples/nextjs-app-router/next.config.mjs
@@ -0,0 +1,4 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {};
+
+export default nextConfig;
diff --git a/examples/nextjs-app-router/package.json b/examples/nextjs-app-router/package.json
new file mode 100644
index 000000000..4215d23ac
--- /dev/null
+++ b/examples/nextjs-app-router/package.json
@@ -0,0 +1,30 @@
+{
+ "name": "nextjs-app-router",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "next lint"
+ },
+ "dependencies": {
+ "@types/set-cookie-parser": "^2.4.10",
+ "cookie": "^1.0.1",
+ "next": "14.2.15",
+ "react": "^18",
+ "react-dom": "^18",
+ "set-cookie-parser": "^2.7.0"
+ },
+ "devDependencies": {
+ "@ory/client-fetch": "^1.15.6",
+ "@types/node": "^20",
+ "@types/react": "^18",
+ "@types/react-dom": "^18",
+ "eslint": "^8",
+ "eslint-config-next": "14.2.15",
+ "postcss": "^8",
+ "tailwindcss": "^3.4.1",
+ "typescript": "^5"
+ }
+}
diff --git a/examples/nextjs-app-router/postcss.config.mjs b/examples/nextjs-app-router/postcss.config.mjs
new file mode 100644
index 000000000..1a69fd2a4
--- /dev/null
+++ b/examples/nextjs-app-router/postcss.config.mjs
@@ -0,0 +1,8 @@
+/** @type {import('postcss-load-config').Config} */
+const config = {
+ plugins: {
+ tailwindcss: {},
+ },
+};
+
+export default config;
diff --git a/examples/nextjs-app-router/routers/app/common/default-forwarded-headers.ts b/examples/nextjs-app-router/routers/app/common/default-forwarded-headers.ts
new file mode 100644
index 000000000..f8d7ed9c6
--- /dev/null
+++ b/examples/nextjs-app-router/routers/app/common/default-forwarded-headers.ts
@@ -0,0 +1,13 @@
+export const defaultForwardedHeaders = [
+ "accept",
+ "accept-charset",
+ "accept-encoding",
+ "accept-language",
+ "authorization",
+ "cache-control",
+ "content-type",
+ "cookie",
+ "host",
+ "user-agent",
+ "referer",
+]
diff --git a/examples/nextjs-app-router/routers/app/common/get-base-url.ts b/examples/nextjs-app-router/routers/app/common/get-base-url.ts
new file mode 100644
index 000000000..4f4c03d9f
--- /dev/null
+++ b/examples/nextjs-app-router/routers/app/common/get-base-url.ts
@@ -0,0 +1,26 @@
+import { type CreateApiHandlerOptions } from "../type/create-api-handler-options"
+
+export function getBaseUrl(options: CreateApiHandlerOptions) {
+ let baseUrl = options.fallbackToPlayground
+ ? "https://playground.projects.oryapis.com/"
+ : ""
+
+ if (process.env.ORY_SDK_URL) {
+ baseUrl = process.env.ORY_SDK_URL
+ }
+
+ if (process.env.ORY_KRATOS_URL) {
+ baseUrl = process.env.ORY_KRATOS_URL
+ }
+
+ if (process.env.ORY_SDK_URL && process.env.ORY_KRATOS_URL) {
+ throw new Error("Only one of ORY_SDK_URL or ORY_KRATOS_URL can be set.")
+ }
+
+ if (options.apiBaseUrlOverride) {
+ baseUrl = options.apiBaseUrlOverride
+ }
+
+ return baseUrl.replace(/\/$/, "")
+}
+export { CreateApiHandlerOptions }
diff --git a/examples/nextjs-app-router/routers/app/common/get-cookie-domain.test.ts b/examples/nextjs-app-router/routers/app/common/get-cookie-domain.test.ts
new file mode 100644
index 000000000..4e5d378c6
--- /dev/null
+++ b/examples/nextjs-app-router/routers/app/common/get-cookie-domain.test.ts
@@ -0,0 +1,71 @@
+import { guessCookieDomain } from "./get-cookie-domain"
+
+describe("cookie guesser", () => {
+ test("uses force domain", async () => {
+ expect(
+ guessCookieDomain("https://localhost", {
+ forceCookieDomain: "some-domain",
+ }),
+ ).toEqual("some-domain")
+ })
+
+ test("does not use any guessing domain", async () => {
+ expect(
+ guessCookieDomain("https://localhost", {
+ dontUseTldForCookieDomain: true,
+ }),
+ ).toEqual(undefined)
+ })
+
+ test("is not confused by invalid data", async () => {
+ expect(
+ guessCookieDomain("5qw5tare4g", {
+ dontUseTldForCookieDomain: true,
+ }),
+ ).toEqual(undefined)
+ expect(
+ guessCookieDomain("https://123.123.123.123.123", {
+ dontUseTldForCookieDomain: true,
+ }),
+ ).toEqual(undefined)
+ })
+
+ test("is not confused by IP", async () => {
+ expect(
+ guessCookieDomain("https://123.123.123.123", {
+ dontUseTldForCookieDomain: true,
+ }),
+ ).toEqual(undefined)
+ expect(
+ guessCookieDomain("https://2001:0db8:0000:0000:0000:ff00:0042:8329", {
+ dontUseTldForCookieDomain: true,
+ }),
+ ).toEqual(undefined)
+ })
+
+ test("uses TLD", async () => {
+ expect(guessCookieDomain("https://foo.localhost", {})).toEqual(
+ "foo.localhost",
+ )
+
+ expect(guessCookieDomain("https://foo.localhost:1234", {})).toEqual(
+ "foo.localhost",
+ )
+
+ expect(
+ guessCookieDomain(
+ "https://spark-public.s3.amazonaws.com/dataanalysis/loansData.csv",
+ {},
+ ),
+ ).toEqual("spark-public.s3.amazonaws.com")
+
+ expect(guessCookieDomain("spark-public.s3.amazonaws.com", {})).toEqual(
+ "spark-public.s3.amazonaws.com",
+ )
+
+ expect(guessCookieDomain("https://localhost/123", {})).toEqual("localhost")
+ expect(guessCookieDomain("https://localhost:1234/123", {})).toEqual(
+ "localhost",
+ )
+ })
+})
diff --git a/examples/nextjs-app-router/routers/app/common/get-cookie-domain.ts b/examples/nextjs-app-router/routers/app/common/get-cookie-domain.ts
new file mode 100644
index 000000000..d307121d7
--- /dev/null
+++ b/examples/nextjs-app-router/routers/app/common/get-cookie-domain.ts
@@ -0,0 +1,27 @@
+import tldjs from "tldjs"
+import { CreateApiHandlerOptions } from "./get-base-url"
+
+export function guessCookieDomain(
+ url: string | undefined,
+ options: CreateApiHandlerOptions,
+) {
+ if (!url || options.forceCookieDomain) {
+ return options.forceCookieDomain
+ }
+
+ if (options.dontUseTldForCookieDomain) {
+ return undefined
+ }
+
+ const parsed = tldjs.parse(url || "")
+
+ if (!parsed.isValid || parsed.isIp) {
+ return undefined
+ }
+
+ if (!parsed.domain) {
+ return parsed.hostname
+ }
+
+ return parsed.domain
+}
diff --git a/examples/nextjs-app-router/routers/app/common/process-location-header.ts b/examples/nextjs-app-router/routers/app/common/process-location-header.ts
new file mode 100644
index 000000000..f9ddc0cfa
--- /dev/null
+++ b/examples/nextjs-app-router/routers/app/common/process-location-header.ts
@@ -0,0 +1,18 @@
+export function processLocationHeader(
+ locationHeaderValue: string,
+ baseUrl: string,
+) {
+ if (locationHeaderValue.startsWith(baseUrl)) {
+ return locationHeaderValue.replace(baseUrl, "/api/.ory")
+ }
+
+ if (
+ locationHeaderValue.startsWith("/api/kratos/public/") ||
+ locationHeaderValue.startsWith("/self-service/") ||
+ locationHeaderValue.startsWith("/ui/")
+ ) {
+ return "/api/.ory" + locationHeaderValue
+ }
+
+ return locationHeaderValue
+}
diff --git a/examples/nextjs-app-router/routers/app/layout.tsx b/examples/nextjs-app-router/routers/app/layout.tsx
new file mode 100644
index 000000000..e0f2d47b6
--- /dev/null
+++ b/examples/nextjs-app-router/routers/app/layout.tsx
@@ -0,0 +1,12 @@
+import "@ory/elements-react/theme/styles.css"
+import { PropsWithChildren } from "react"
+
+export default async function AuthLayout({ children }: PropsWithChildren) {
+ return (
+ <>
+
+ {children}
+
+ >
+ )
+}
diff --git a/examples/nextjs-app-router/routers/app/login.ts b/examples/nextjs-app-router/routers/app/login.ts
new file mode 100644
index 000000000..8109bf5f1
--- /dev/null
+++ b/examples/nextjs-app-router/routers/app/login.ts
@@ -0,0 +1,62 @@
+import {
+ redirectToBrowserEndpoint,
+ initOverrides,
+ onRedirect,
+ onValidationError,
+ QueryParams,
+ toFlowParams,
+ toValue,
+} from "./utils"
+import {LoginFlow, FlowType, handleFlowError, FrontendApi} from "@ory/client-fetch"
+
+/**
+ * Use this method in an app router page to fetch an existing login flow or to create a new one. This method works with server-side rendering.
+ *
+ * ```
+ * import { getOrCreateLoginFlow } from "$/elements/frameworks/nextjs/routers/app/login"
+ * import { Login } from "$/elements/headless/flows/login"
+ *
+ * export default async function LoginPage({ searchParams }: PageProps) {
+ * const flow = await getOrCreateLoginFlow(searchParams)
+ *
+ * return (
+ * .projects.oryapis.com" },
+ * }}
+ * />
+ * )
+ * }
+ * ```
+ *
+ * @param params The query parameters of the request.
+ * @param client The client to use for the request.
+ */
+export async function getOrCreateLoginFlow(
+ params: QueryParams,
+ client: FrontendApi
+): Promise {
+ const onRestartFlow = () => redirectToBrowserEndpoint(params, FlowType.Login)
+ if (!params.flow) {
+ return onRestartFlow()
+ }
+
+ try {
+ const resp = await client.getLoginFlowRaw(
+ toFlowParams(params),
+ initOverrides,
+ )
+
+ return toValue(resp)
+ } catch (error) {
+ const errorHandler = handleFlowError({
+ onValidationError,
+ onRestartFlow,
+ onRedirect,
+ })
+ await errorHandler(error)
+ return null
+ }
+}
diff --git a/examples/nextjs-app-router/routers/app/proxy.ts b/examples/nextjs-app-router/routers/app/proxy.ts
new file mode 100644
index 000000000..166b35da6
--- /dev/null
+++ b/examples/nextjs-app-router/routers/app/proxy.ts
@@ -0,0 +1,148 @@
+import { SerializeOptions as CookieSerializeOptions, serialize } from "cookie"
+import { headers } from "next/headers"
+import { redirect } from "next/navigation"
+import { NextResponse, type NextRequest } from "next/server"
+import parse, { splitCookiesString } from "set-cookie-parser"
+import { getBaseUrl } from "./common/get-base-url"
+import { CreateApiHandlerOptions } from "./type/create-api-handler-options"
+import { defaultForwardedHeaders } from "./common/default-forwarded-headers"
+import { processLocationHeader } from "./common/process-location-header"
+import { guessCookieDomain } from "./common/get-cookie-domain"
+
+export function filterRequestHeaders(
+ forwardAdditionalHeaders?: string[],
+): Headers {
+ const filteredHeaders = new Headers()
+ headers().forEach((value, key) => {
+ const isValid =
+ defaultForwardedHeaders.includes(key) ||
+ (forwardAdditionalHeaders ?? []).includes(key)
+ if (isValid) filteredHeaders.set(key, value)
+ })
+
+ return filteredHeaders
+}
+
+function processSetCookieHeader(
+ protocol: string,
+ fetchResponse: Response,
+ options: CreateApiHandlerOptions,
+) {
+ const requestHeaders = headers()
+ const isTls =
+ protocol === "https:" || requestHeaders.get("x-forwarded-proto") === "https"
+
+ const secure =
+ options.forceCookieSecure === undefined ? isTls : options.forceCookieSecure
+
+ const forwarded = requestHeaders.get("x-forwarded-host")
+ const host = forwarded ? forwarded : requestHeaders.get("host")
+ const domain = guessCookieDomain(host, options)
+
+ return parse(
+ splitCookiesString(fetchResponse.headers.get("set-cookie") || ""),
+ )
+ .map((cookie) => ({
+ ...cookie,
+ domain,
+ secure,
+ encode: (v: string) => v,
+ }))
+ .map(({ value, name, ...options }) =>
+ serialize(name, value, options as CookieSerializeOptions),
+ )
+}
+
+export function createApiHandler(options: CreateApiHandlerOptions) {
+ const baseUrl = getBaseUrl(options)
+
+ const handler = async (
+ request: NextRequest,
+ { params }: { params: { path: string[] } },
+ ) => {
+
+ const path = request.nextUrl.pathname
+ const url = new URL(path, baseUrl)
+ url.search = request.nextUrl.search
+
+ const requestHeaders = filterRequestHeaders(
+ options.forwardAdditionalHeaders,
+ )
+
+ requestHeaders.set("X-Ory-Base-URL-Rewrite", "false")
+ requestHeaders.set("Ory-Base-URL-Rewrite", "false")
+ requestHeaders.set("Ory-No-Custom-Domain-Redirect", "true")
+
+ try {
+ const response = await fetch(url, {
+ method: request.method,
+ headers: requestHeaders,
+ body:
+ request.method !== "GET" && request.method !== "HEAD"
+ ? await request.arrayBuffer()
+ : null,
+ redirect: "manual",
+ })
+
+ const responseHeaders = new Headers()
+ for (const [key, value] of response.headers) {
+ responseHeaders.append(key, value)
+ }
+
+ responseHeaders.delete("location")
+ responseHeaders.delete("set-cookie")
+ if (response.headers.get("set-cookie")) {
+ const cookies = processSetCookieHeader(
+ request.nextUrl.protocol,
+ response,
+ options,
+ )
+ cookies.forEach((cookie) => {
+ responseHeaders.append("Set-Cookie", cookie)
+ })
+ }
+
+ if (response.headers.get("location")) {
+ const location = processLocationHeader(
+ response.headers.get("location"),
+ baseUrl,
+ )
+ responseHeaders.set("location", location)
+ }
+
+ responseHeaders.delete("transfer-encoding")
+ responseHeaders.delete("content-encoding")
+ responseHeaders.delete("content-length")
+
+ const buf = Buffer.from(await response.arrayBuffer())
+
+ try {
+ return new NextResponse(
+ buf.toString("utf-8").replace(new RegExp(baseUrl, "g"), "/api/.ory"),
+ {
+ status: response.status,
+ headers: responseHeaders,
+ },
+ )
+ } catch (err) {
+ return new NextResponse(response.body, {
+ status: response.status,
+ headers: responseHeaders,
+ })
+ }
+ } catch (error) {
+ console.error(error, {
+ path,
+ url,
+ method: request.method,
+ headers: requestHeaders,
+ })
+ throw error
+ }
+ }
+
+ return {
+ GET: handler,
+ POST: handler,
+ }
+}
diff --git a/examples/nextjs-app-router/routers/app/type/create-api-handler-options.ts b/examples/nextjs-app-router/routers/app/type/create-api-handler-options.ts
new file mode 100644
index 000000000..79637d523
--- /dev/null
+++ b/examples/nextjs-app-router/routers/app/type/create-api-handler-options.ts
@@ -0,0 +1,48 @@
+export interface CreateApiHandlerOptions {
+ /**
+ * If set overrides the API Base URL. Usually, this URL
+ * is taken from the ORY_KRATOS_URL environment variable.
+ *
+ * If you don't have a project you can use the playground project SDK URL:
+ *
+ * https://playground.projects.oryapis.com
+ */
+ apiBaseUrlOverride?: string
+
+ /**
+ * Per default, this handler will strip the cookie domain from
+ * the Set-Cookie instruction which is recommended for most set ups.
+ *
+ * If you are running this app on a subdomain and you want the session and CSRF cookies
+ * to be valid for the whole TLD, you can use this setting to force a cookie domain.
+ *
+ * Please be aware that his method disables the `dontUseTldForCookieDomain` option.
+ */
+ forceCookieDomain?: string
+
+ /**
+ * Per default the cookie will be set on the hosts top-level-domain. If the app
+ * runs on www.example.org, the cookie domain will be set automatically to example.org.
+ *
+ * Set this option to true to disable that behaviour.
+ */
+ dontUseTldForCookieDomain?: boolean
+
+ /**
+ * If set to true will set the "Secure" flag for all cookies. This might come in handy when you deploy
+ * not on Vercel.
+ */
+ forceCookieSecure?: boolean
+
+ /**
+ * If set to true will fallback to the playground if no other value is set for the Ory SDK URL.
+ */
+ fallbackToPlayground?: boolean
+
+ /*
+ * Per default headers are filtered to forward only a fixed list.
+ *
+ * If you need to forward additional headers you can use this setting to define them.
+ */
+ forwardAdditionalHeaders?: string[]
+}
diff --git a/examples/nextjs-app-router/routers/app/utils.ts b/examples/nextjs-app-router/routers/app/utils.ts
new file mode 100644
index 000000000..0007b212f
--- /dev/null
+++ b/examples/nextjs-app-router/routers/app/utils.ts
@@ -0,0 +1,70 @@
+import { headers } from "next/headers"
+import { ApiResponse, FlowType, handleFlowError, OnRedirectHandler } from "@ory/client-fetch"
+import { redirect, RedirectType } from "next/navigation"
+
+export type QueryParams = { [key: string]: any }
+
+/**
+ * Get the cookie header from the HTTP request.
+ *
+ * @returns The cookie header.
+ */
+export function getCookieHeader() {
+ return headers().get("cookie") ?? undefined
+}
+
+export const initOverrides: RequestInit = {
+ cache: "no-cache",
+}
+
+export function toValue(res: ApiResponse) {
+ return res.value()
+}
+
+export const onRedirect: OnRedirectHandler = (url, external) => {
+ redirect(url)
+}
+
+export function onValidationError(value: T): T {
+ return value
+}
+
+export type FlowParams = {
+ id: string
+ cookie: string | undefined
+ return_to: string
+}
+
+export function toFlowParams(params: QueryParams): FlowParams {
+ return {
+ id: params.flow,
+ cookie: getCookieHeader(),
+ return_to: params.return_to,
+ }
+}
+
+export function redirectToBrowserEndpoint(params: QueryParams, flowType: FlowType) {
+ // Take advantage of the fact, that Ory handles the flow creation for us and redirects the user to the default
+ // return to automatically if they're logged in already.
+ return redirect(
+ sdkUrl()+"/self-service/" +
+ flowType.toString() +
+ "/browser?" +
+ new URLSearchParams(params).toString(),
+ RedirectType.replace,
+ )
+}
+
+export const onError = (onRestartFlow: () => void) => (err: any) =>
+ new Promise((resolve) => {
+ handleFlowError({
+ onValidationError: resolve,
+ // RestartFlow and Redirect both use redirects hence we don't need to resolve here.
+ onRestartFlow,
+ onRedirect,
+ })(err)
+ })
+
+export function sdkUrl() {
+ return (process.env.ORY_SDK_URL || '').replace(/\/$/, '')
+}
\ No newline at end of file
diff --git a/examples/nextjs-app-router/tailwind.config.ts b/examples/nextjs-app-router/tailwind.config.ts
new file mode 100644
index 000000000..d43da912d
--- /dev/null
+++ b/examples/nextjs-app-router/tailwind.config.ts
@@ -0,0 +1,19 @@
+import type { Config } from "tailwindcss";
+
+const config: Config = {
+ content: [
+ "./pages/**/*.{js,ts,jsx,tsx,mdx}",
+ "./components/**/*.{js,ts,jsx,tsx,mdx}",
+ "./app/**/*.{js,ts,jsx,tsx,mdx}",
+ ],
+ theme: {
+ extend: {
+ colors: {
+ background: "var(--background)",
+ foreground: "var(--foreground)",
+ },
+ },
+ },
+ plugins: [],
+};
+export default config;
diff --git a/examples/nextjs-app-router/tsconfig.json b/examples/nextjs-app-router/tsconfig.json
new file mode 100644
index 000000000..e7ff90fd2
--- /dev/null
+++ b/examples/nextjs-app-router/tsconfig.json
@@ -0,0 +1,26 @@
+{
+ "compilerOptions": {
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true,
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "paths": {
+ "@/*": ["./*"]
+ }
+ },
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
+ "exclude": ["node_modules"]
+}
diff --git a/package-lock.json b/package-lock.json
index b473555d6..78be7ce55 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -113,6 +113,470 @@
"npm": ">=8.11.0"
}
},
+ "examples/nextjs-app-router": {
+ "version": "0.1.0",
+ "dependencies": {
+ "@types/set-cookie-parser": "^2.4.10",
+ "cookie": "^1.0.1",
+ "next": "14.2.15",
+ "react": "^18",
+ "react-dom": "^18",
+ "set-cookie-parser": "^2.7.0"
+ },
+ "devDependencies": {
+ "@ory/client-fetch": "^1.15.6",
+ "@types/node": "^20",
+ "@types/react": "^18",
+ "@types/react-dom": "^18",
+ "eslint": "^8",
+ "eslint-config-next": "14.2.15",
+ "postcss": "^8",
+ "tailwindcss": "^3.4.1",
+ "typescript": "^5"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/@next/env": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.15.tgz",
+ "integrity": "sha512-S1qaj25Wru2dUpcIZMjxeMVSwkt8BK4dmWHHiBuRstcIyOsMapqT4A4jSB6onvqeygkSSmOkyny9VVx8JIGamQ=="
+ },
+ "examples/nextjs-app-router/node_modules/@next/eslint-plugin-next": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.15.tgz",
+ "integrity": "sha512-pKU0iqKRBlFB/ocOI1Ip2CkKePZpYpnw5bEItEkuZ/Nr9FQP1+p7VDWr4VfOdff4i9bFmrOaeaU1bFEyAcxiMQ==",
+ "dev": true,
+ "dependencies": {
+ "glob": "10.3.10"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/@next/swc-darwin-arm64": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.15.tgz",
+ "integrity": "sha512-Rvh7KU9hOUBnZ9TJ28n2Oa7dD9cvDBKua9IKx7cfQQ0GoYUwg9ig31O2oMwH3wm+pE3IkAQ67ZobPfEgurPZIA==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/@next/swc-darwin-x64": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.15.tgz",
+ "integrity": "sha512-5TGyjFcf8ampZP3e+FyCax5zFVHi+Oe7sZyaKOngsqyaNEpOgkKB3sqmymkZfowy3ufGA/tUgDPPxpQx931lHg==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/@next/swc-linux-arm64-gnu": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.15.tgz",
+ "integrity": "sha512-3Bwv4oc08ONiQ3FiOLKT72Q+ndEMyLNsc/D3qnLMbtUYTQAmkx9E/JRu0DBpHxNddBmNT5hxz1mYBphJ3mfrrw==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/@next/swc-linux-arm64-musl": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.15.tgz",
+ "integrity": "sha512-k5xf/tg1FBv/M4CMd8S+JL3uV9BnnRmoe7F+GWC3DxkTCD9aewFRH1s5rJ1zkzDa+Do4zyN8qD0N8c84Hu96FQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/@next/swc-linux-x64-gnu": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.15.tgz",
+ "integrity": "sha512-kE6q38hbrRbKEkkVn62reLXhThLRh6/TvgSP56GkFNhU22TbIrQDEMrO7j0IcQHcew2wfykq8lZyHFabz0oBrA==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/@next/swc-linux-x64-musl": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.15.tgz",
+ "integrity": "sha512-PZ5YE9ouy/IdO7QVJeIcyLn/Rc4ml9M2G4y3kCM9MNf1YKvFY4heg3pVa/jQbMro+tP6yc4G2o9LjAz1zxD7tQ==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/@next/swc-win32-arm64-msvc": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.15.tgz",
+ "integrity": "sha512-2raR16703kBvYEQD9HNLyb0/394yfqzmIeyp2nDzcPV4yPjqNUG3ohX6jX00WryXz6s1FXpVhsCo3i+g4RUX+g==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/@next/swc-win32-ia32-msvc": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.15.tgz",
+ "integrity": "sha512-fyTE8cklgkyR1p03kJa5zXEaZ9El+kDNM5A+66+8evQS5e/6v0Gk28LqA0Jet8gKSOyP+OTm/tJHzMlGdQerdQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/@next/swc-win32-x64-msvc": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.15.tgz",
+ "integrity": "sha512-SzqGbsLsP9OwKNUG9nekShTwhj6JSB9ZLMWQ8g1gG6hdE5gQLncbnbymrwy2yVmH9nikSLYRYxYMFu78Ggp7/g==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/@ory/client-fetch": {
+ "version": "1.15.6",
+ "resolved": "https://registry.npmjs.org/@ory/client-fetch/-/client-fetch-1.15.6.tgz",
+ "integrity": "sha512-etWhiJC5kF/qbXugAtUHGi+8Z8L/v+dKXzkRA7jy90tlfSTVem+rmwCPtaH3KaLaYWQ4ltAjOh0LEOCetrE2sQ==",
+ "dev": true
+ },
+ "examples/nextjs-app-router/node_modules/@swc/helpers": {
+ "version": "0.5.5",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz",
+ "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==",
+ "dependencies": {
+ "@swc/counter": "^0.1.3",
+ "tslib": "^2.4.0"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/@types/node": {
+ "version": "20.16.11",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.11.tgz",
+ "integrity": "sha512-y+cTCACu92FyA5fgQSAI8A1H429g7aSK2HsO7K4XYUWc4dY5IUz55JSDIYT6/VsOLfGy8vmvQYC2hfb0iF16Uw==",
+ "dev": true,
+ "dependencies": {
+ "undici-types": "~6.19.2"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/cookie": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.1.tgz",
+ "integrity": "sha512-Xd8lFX4LM9QEEwxQpF9J9NTUh8pmdJO0cyRJhFiDoLTk2eH8FXlRv2IFGYVadZpqI3j8fhNrSdKCeYPxiAhLXw==",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/eslint-config-next": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.2.15.tgz",
+ "integrity": "sha512-mKg+NC/8a4JKLZRIOBplxXNdStgxy7lzWuedUaCc8tev+Al9mwDUTujQH6W6qXDH9kycWiVo28tADWGvpBsZcQ==",
+ "dev": true,
+ "dependencies": {
+ "@next/eslint-plugin-next": "14.2.15",
+ "@rushstack/eslint-patch": "^1.3.3",
+ "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0",
+ "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0",
+ "eslint-import-resolver-node": "^0.3.6",
+ "eslint-import-resolver-typescript": "^3.5.2",
+ "eslint-plugin-import": "^2.28.1",
+ "eslint-plugin-jsx-a11y": "^6.7.1",
+ "eslint-plugin-react": "^7.33.2",
+ "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705"
+ },
+ "peerDependencies": {
+ "eslint": "^7.23.0 || ^8.0.0",
+ "typescript": ">=3.3.1"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "examples/nextjs-app-router/node_modules/eslint-plugin-react": {
+ "version": "7.37.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.1.tgz",
+ "integrity": "sha512-xwTnwDqzbDRA8uJ7BMxPs/EXRB3i8ZfnOIp8BsxEQkT0nHPp+WWceqGgo6rKb9ctNi8GJLDT4Go5HAWELa/WMg==",
+ "dev": true,
+ "dependencies": {
+ "array-includes": "^3.1.8",
+ "array.prototype.findlast": "^1.2.5",
+ "array.prototype.flatmap": "^1.3.2",
+ "array.prototype.tosorted": "^1.1.4",
+ "doctrine": "^2.1.0",
+ "es-iterator-helpers": "^1.0.19",
+ "estraverse": "^5.3.0",
+ "hasown": "^2.0.2",
+ "jsx-ast-utils": "^2.4.1 || ^3.0.0",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.8",
+ "object.fromentries": "^2.0.8",
+ "object.values": "^1.2.0",
+ "prop-types": "^15.8.1",
+ "resolve": "^2.0.0-next.5",
+ "semver": "^6.3.1",
+ "string.prototype.matchall": "^4.0.11",
+ "string.prototype.repeat": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/foreground-child": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
+ "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/glob": {
+ "version": "10.3.10",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
+ "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
+ "dev": true,
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^2.3.5",
+ "minimatch": "^9.0.1",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
+ "path-scurry": "^1.10.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/glob/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/jackspeak": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
+ "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
+ "dev": true,
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/next": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/next/-/next-14.2.15.tgz",
+ "integrity": "sha512-h9ctmOokpoDphRvMGnwOJAedT6zKhwqyZML9mDtspgf4Rh3Pn7UTYKqePNoDvhsWBAO5GoPNYshnAUGIazVGmw==",
+ "dependencies": {
+ "@next/env": "14.2.15",
+ "@swc/helpers": "0.5.5",
+ "busboy": "1.6.0",
+ "caniuse-lite": "^1.0.30001579",
+ "graceful-fs": "^4.2.11",
+ "postcss": "8.4.31",
+ "styled-jsx": "5.1.1"
+ },
+ "bin": {
+ "next": "dist/bin/next"
+ },
+ "engines": {
+ "node": ">=18.17.0"
+ },
+ "optionalDependencies": {
+ "@next/swc-darwin-arm64": "14.2.15",
+ "@next/swc-darwin-x64": "14.2.15",
+ "@next/swc-linux-arm64-gnu": "14.2.15",
+ "@next/swc-linux-arm64-musl": "14.2.15",
+ "@next/swc-linux-x64-gnu": "14.2.15",
+ "@next/swc-linux-x64-musl": "14.2.15",
+ "@next/swc-win32-arm64-msvc": "14.2.15",
+ "@next/swc-win32-ia32-msvc": "14.2.15",
+ "@next/swc-win32-x64-msvc": "14.2.15"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.1.0",
+ "@playwright/test": "^1.41.2",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "sass": "^1.3.0"
+ },
+ "peerDependenciesMeta": {
+ "@opentelemetry/api": {
+ "optional": true
+ },
+ "@playwright/test": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ }
+ }
+ },
+ "examples/nextjs-app-router/node_modules/postcss": {
+ "version": "8.4.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
+ "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.6",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/resolve": {
+ "version": "2.0.0-next.5",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
+ "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "examples/nextjs-app-router/node_modules/tslib": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
+ "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA=="
+ },
"examples/nextjs-spa": {
"version": "0.0.0",
"dependencies": {
@@ -13134,7 +13598,6 @@
"version": "18.16.19",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.19.tgz",
"integrity": "sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==",
- "dev": true,
"license": "MIT"
},
"node_modules/@types/node-fetch": {
@@ -13260,6 +13723,14 @@
"@types/send": "*"
}
},
+ "node_modules/@types/set-cookie-parser": {
+ "version": "2.4.10",
+ "resolved": "https://registry.npmjs.org/@types/set-cookie-parser/-/set-cookie-parser-2.4.10.tgz",
+ "integrity": "sha512-GGmQVGpQWUe5qglJozEjZV/5dyxbOOZ0LHe/lqyWssB88Y4svNfst0uqBVscdDeIKl5Jy5+aPSvy7mI9tYRguw==",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/stack-utils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
@@ -26505,6 +26976,10 @@
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
"license": "0BSD"
},
+ "node_modules/nextjs-app-router": {
+ "resolved": "examples/nextjs-app-router",
+ "link": true
+ },
"node_modules/nextjs-spa": {
"resolved": "examples/nextjs-spa",
"link": true
@@ -29635,6 +30110,11 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/set-cookie-parser": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.0.tgz",
+ "integrity": "sha512-lXLOiqpkUumhRdFF3k1osNXCy9akgx/dyPZ5p8qAg9seJzXr5ZrlqZuWIMuY6ejOsVLE6flJ5/h3lsn57fQ/PQ=="
+ },
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",