-
-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add @ory/nextjs package (#303)
- Loading branch information
1 parent
4c0db56
commit 64c9b50
Showing
47 changed files
with
3,239 additions
and
165 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
comment: | ||
layout: "condensed_header, diff, flags, components" | ||
|
||
component_management: | ||
individual_components: | ||
- component_id: elements-react # this is an identifier that should not be changed | ||
name: "@ory/elements-react" # this is a display name, and can be changed freely | ||
paths: | ||
- packages/elements-react | ||
- component_id: nextjs # this is an identifier that should not be changed | ||
name: "@ory/nextjs" # this is a display name, and can be changed freely | ||
paths: | ||
- packages/nextjs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
{ | ||
// "extends": ["../../.eslintrc.base.json"], | ||
"ignorePatterns": ["!**/*"], | ||
"overrides": [ | ||
{ | ||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"], | ||
"rules": {} | ||
}, | ||
{ | ||
"files": ["*.ts", "*.tsx"], | ||
"rules": {} | ||
}, | ||
{ | ||
"files": ["*.js", "*.jsx"], | ||
"rules": {} | ||
}, | ||
{ | ||
"files": ["*.json"], | ||
"parser": "jsonc-eslint-parser", | ||
"rules": { | ||
"@nx/dependency-checks": "error" | ||
} | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# nextjs | ||
|
||
This library was generated with [Nx](https://nx.dev). | ||
|
||
## Building | ||
|
||
Run `nx build @ory/nextjs` to build the library. | ||
|
||
## Developing | ||
|
||
Run `nx dev @ory/nextjs` to watch the source code for changes and continuously | ||
build the library. | ||
|
||
## Running unit tests | ||
|
||
Run `nx test @ory/nextjs` to execute the unit tests via | ||
[Jest](https://jestjs.io). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// Copyright © 2024 Ory Corp | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
/* eslint-disable */ | ||
export default { | ||
displayName: "nextjs", | ||
preset: "../../jest.preset.js", | ||
testEnvironment: "node", | ||
transform: { | ||
"^.+\\.[tj]s$": ["ts-jest", { tsconfig: "<rootDir>/tsconfig.spec.json" }], | ||
}, | ||
collectCoverageFrom: ["src/**/*.ts", "src/**/*.js"], | ||
moduleFileExtensions: ["ts", "js", "html"], | ||
coverageDirectory: "../../coverage/packages/nextjs", | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
{ | ||
"name": "@ory/nextjs", | ||
"version": "0.0.1", | ||
"type": "commonjs", | ||
"main": "./dist/index.js", | ||
"module": "./dist/index.mjs", | ||
"types": "./dist/index.d.ts", | ||
"private": false, | ||
"dependencies": { | ||
"@ory/client-fetch": "^1.15.6", | ||
"cookie": "^1.0.1", | ||
"psl": "^1.10.0", | ||
"set-cookie-parser": "^2.7.1" | ||
}, | ||
"devDependencies": { | ||
"@types/cookie": "^0.6.0", | ||
"@types/psl": "^1.1.3", | ||
"@types/set-cookie-parser": "^2.4.10", | ||
"babel-jest": "^29.7.0", | ||
"jest-esm-transformer": "^1.0.0", | ||
"tsup": "8.3.0" | ||
}, | ||
"keywords": [ | ||
"ory", | ||
"auth", | ||
"react", | ||
"passwordless", | ||
"login", | ||
"user management", | ||
"permissions", | ||
"authentication", | ||
"nextjs", | ||
"vercel", | ||
"app router", | ||
"pages router" | ||
], | ||
"peerDependencies": { | ||
"next": ">=13.1.0", | ||
"react": ">=16.0.0" | ||
}, | ||
"exports": { | ||
".": { | ||
"types": "./dist/index.d.ts", | ||
"import": "./dist/index.mjs", | ||
"require": "./dist/index.js" | ||
}, | ||
"./middleware": { | ||
"types": "./dist/middleware/index.d.ts", | ||
"import": "./dist/middleware/index.mjs", | ||
"require": "./dist/middleware/index.js" | ||
}, | ||
"./app": { | ||
"types": "./dist/app/index.d.ts", | ||
"import": "./dist/app/index.mjs", | ||
"require": "./dist/app/index.js" | ||
}, | ||
"./pages": { | ||
"types": "./dist/pages/index.d.ts", | ||
"import": "./dist/pages/index.mjs", | ||
"require": "./dist/pages/index.js" | ||
} | ||
}, | ||
"typesVersions": { | ||
"*": { | ||
"index": [ | ||
"./dist/index.d.ts" | ||
], | ||
"middleware": [ | ||
"./dist/middleware/index.d.ts" | ||
] | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
{ | ||
"name": "@ory/nextjs", | ||
"$schema": "../../node_modules/nx/schemas/project-schema.json", | ||
"sourceRoot": "packages/nextjs/src", | ||
"projectType": "library", | ||
"tags": [], | ||
"targets": { | ||
"build": { | ||
"command": "tsup --clean --dts", | ||
"options": { | ||
"cwd": "packages/nextjs" | ||
} | ||
}, | ||
"dev": { | ||
"command": "tsup --watch --dts", | ||
"options": { | ||
"cwd": "packages/nextjs" | ||
} | ||
}, | ||
"test": { | ||
"executor": "@nx/jest:jest", | ||
"dependsOn": ["build"], | ||
"options": { | ||
"jestConfig": "packages/nextjs/jest.config.ts", | ||
"coverage": true, | ||
"coverageReporters": ["text", "cobertura"] | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// Copyright © 2024 Ory Corp | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import { Configuration, FrontendApi } from "@ory/client-fetch" | ||
|
||
import { orySdkUrl } from "../utils/sdk" | ||
|
||
export const serverSideFrontendClient = new FrontendApi( | ||
new Configuration({ | ||
headers: { | ||
Accept: "application/json", | ||
}, | ||
basePath: orySdkUrl(), | ||
}), | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
// Copyright © 2024 Ory Corp | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import { FlowType, handleFlowError } from "@ory/client-fetch" | ||
import { | ||
getLoginFlow, | ||
getRecoveryFlow, | ||
getRegistrationFlow, | ||
getVerificationFlow, | ||
} from "." | ||
import { redirect } from "next/navigation" | ||
import { getPublicUrl, toFlowParams } from "./utils" | ||
import { serverSideFrontendClient } from "./client" | ||
|
||
jest.mock("./utils", () => ({ | ||
getPublicUrl: jest.fn(), | ||
toFlowParams: jest.fn().mockImplementation((params) => params), | ||
})) | ||
|
||
jest.mock("./client", () => ({ | ||
serverSideFrontendClient: { | ||
getLoginFlowRaw: jest.fn(), | ||
getRegistrationFlowRaw: jest.fn(), | ||
getRecoveryFlowRaw: jest.fn(), | ||
getVerificationFlowRaw: jest.fn(), | ||
}, | ||
})) | ||
|
||
jest.mock("next/navigation", () => ({ | ||
redirect: jest.fn(), | ||
RedirectType: { | ||
replace: "replace", | ||
}, | ||
})) | ||
|
||
jest.mock("@ory/client-fetch", () => { | ||
const original = jest.requireActual("@ory/client-fetch") | ||
|
||
return { | ||
...original, | ||
handleFlowError: jest.fn(), | ||
} | ||
}) | ||
|
||
beforeEach(() => { | ||
;(getPublicUrl as jest.Mock).mockResolvedValue("https://example.com") | ||
jest.clearAllMocks() | ||
process.env["NEXT_PUBLIC_ORY_SDK_URL"] = "https://ory.sh/" | ||
;(handleFlowError as jest.Mock).mockReturnValue(async () => {}) | ||
}) | ||
|
||
const testCases = [ | ||
{ | ||
fn: getLoginFlow, | ||
flowType: FlowType.Login, | ||
m: serverSideFrontendClient.getLoginFlowRaw, | ||
}, | ||
{ | ||
fn: getRegistrationFlow, | ||
flowType: FlowType.Registration, | ||
m: serverSideFrontendClient.getRegistrationFlowRaw, | ||
}, | ||
{ | ||
fn: getRecoveryFlow, | ||
flowType: FlowType.Recovery, | ||
m: serverSideFrontendClient.getRecoveryFlowRaw, | ||
}, | ||
{ | ||
fn: getVerificationFlow, | ||
flowType: FlowType.Verification, | ||
m: serverSideFrontendClient.getVerificationFlowRaw, | ||
}, | ||
] | ||
|
||
for (const tc of testCases) { | ||
describe(`flowtype=${tc.flowType}`, () => { | ||
test("restarts flow if no id given", async () => { | ||
const queryParams = {} | ||
await tc.fn(queryParams) | ||
expect(redirect).toHaveBeenCalledWith( | ||
`https://example.com/self-service/${tc.flowType}/browser`, | ||
"replace", | ||
) | ||
}) | ||
|
||
test("restarts flow if no id is given with query params", async () => { | ||
const queryParams = { | ||
refresh: "true", | ||
} | ||
await tc.fn(queryParams) | ||
expect(redirect).toHaveBeenCalledWith( | ||
`https://example.com/self-service/${tc.flowType}/browser?refresh=true`, | ||
"replace", | ||
) | ||
}) | ||
|
||
test("fetches flow and rewrite json response", async () => { | ||
const queryParams = { | ||
flow: "1234", | ||
} | ||
;(tc.m as jest.Mock).mockResolvedValue({ | ||
value: jest.fn().mockResolvedValue({ | ||
foo: "https://ory.sh/a", | ||
bar: "https://ory.sh/", | ||
}), | ||
} as any) | ||
const result = await tc.fn(queryParams) | ||
expect(result).toEqual({ | ||
foo: "https://example.com/a", | ||
bar: "https://example.com/", | ||
}) | ||
}) | ||
|
||
test("fetches flow and calls error handler on error", async () => { | ||
const queryParams = { | ||
flow: "1234", | ||
} | ||
;(tc.m as jest.Mock).mockRejectedValue(new Error("error")) | ||
const result = await tc.fn(queryParams) | ||
expect(result).toBeNull() | ||
expect(handleFlowError).toHaveBeenCalled() | ||
}) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// Copyright © 2024 Ory Corp | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import { redirect, RedirectType } from "next/navigation" | ||
import { FlowType, handleFlowError } from "@ory/client-fetch" | ||
|
||
import { getPublicUrl, onRedirect } from "./utils" | ||
import { QueryParams } from "../types" | ||
import { guessPotentiallyProxiedOrySdkUrl } from "../utils/sdk" | ||
import { onValidationError } from "../utils/utils" | ||
import { rewriteJsonResponse } from "../utils/rewrite" | ||
import * as runtime from "@ory/client-fetch/src/runtime" | ||
|
||
export async function getFlow<T extends object>( | ||
params: QueryParams, | ||
fetchFlowRaw: () => Promise<runtime.ApiResponse<T>>, | ||
flowType: FlowType, | ||
): Promise<T | null | void> { | ||
// Guess our own public url using Next.js helpers. We need the hostname, port, and protocol. | ||
const knownProxiedUrl = await getPublicUrl() | ||
const url = guessPotentiallyProxiedOrySdkUrl({ | ||
knownProxiedUrl, | ||
}) | ||
|
||
const onRestartFlow = () => { | ||
const redirectTo = new URL( | ||
"/self-service/" + flowType.toString() + "/browser", | ||
url, | ||
) | ||
redirectTo.search = new URLSearchParams(params).toString() | ||
return redirect(redirectTo.toString(), RedirectType.replace) | ||
} | ||
|
||
if (!params["flow"]) { | ||
onRestartFlow() | ||
return | ||
} | ||
|
||
try { | ||
const rawResponse = await fetchFlowRaw() | ||
return await rawResponse | ||
.value() | ||
.then((v: T): T => rewriteJsonResponse(v, url)) | ||
} catch (error) { | ||
const errorHandler = handleFlowError({ | ||
onValidationError, | ||
onRestartFlow, | ||
onRedirect: onRedirect, | ||
}) | ||
await errorHandler(error) | ||
return null | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// Copyright © 2024 Ory Corp | ||
// SPDX-License-Identifier: Apache-2.0 | ||
"use server" | ||
|
||
export { getLoginFlow } from "./login" | ||
export { getRegistrationFlow } from "./registration" | ||
export { getRecoveryFlow } from "./recovery" | ||
export { getVerificationFlow } from "./verification" | ||
|
||
export type { OryPageParams } from "./utils" |
Oops, something went wrong.