@logto/react-router 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +144 -0
  3. package/lib/framework/get-cookie-header-from-request.d.ts +1 -0
  4. package/lib/framework/get-cookie-header-from-request.js +3 -0
  5. package/lib/framework/mocks.d.ts +25 -0
  6. package/lib/framework/mocks.js +50 -0
  7. package/lib/index.d.ts +30 -0
  8. package/lib/index.js +23 -0
  9. package/lib/infrastructure/logto/create-client.d.ts +6 -0
  10. package/lib/infrastructure/logto/create-client.js +11 -0
  11. package/lib/infrastructure/logto/create-client.spec.d.ts +1 -0
  12. package/lib/infrastructure/logto/create-client.spec.js +16 -0
  13. package/lib/infrastructure/logto/create-storage.d.ts +14 -0
  14. package/lib/infrastructure/logto/create-storage.js +28 -0
  15. package/lib/infrastructure/logto/create-storage.spec.d.ts +1 -0
  16. package/lib/infrastructure/logto/create-storage.spec.js +39 -0
  17. package/lib/infrastructure/logto/get-context.d.ts +11 -0
  18. package/lib/infrastructure/logto/get-context.js +10 -0
  19. package/lib/infrastructure/logto/handle-sign-in-callback.d.ts +14 -0
  20. package/lib/infrastructure/logto/handle-sign-in-callback.js +10 -0
  21. package/lib/infrastructure/logto/handle-sign-in.d.ts +15 -0
  22. package/lib/infrastructure/logto/handle-sign-in.js +28 -0
  23. package/lib/infrastructure/logto/handle-sign-out.d.ts +11 -0
  24. package/lib/infrastructure/logto/handle-sign-out.js +24 -0
  25. package/lib/infrastructure/logto/handle-sign-up.d.ts +15 -0
  26. package/lib/infrastructure/logto/handle-sign-up.js +28 -0
  27. package/lib/infrastructure/logto/index.d.ts +32 -0
  28. package/lib/infrastructure/logto/index.js +21 -0
  29. package/lib/useCases/getContext/GetContextController.d.ts +13 -0
  30. package/lib/useCases/getContext/GetContextController.js +19 -0
  31. package/lib/useCases/getContext/GetContextController.spec.d.ts +1 -0
  32. package/lib/useCases/getContext/GetContextController.spec.js +15 -0
  33. package/lib/useCases/getContext/GetContextUseCase.d.ts +15 -0
  34. package/lib/useCases/getContext/GetContextUseCase.js +11 -0
  35. package/lib/useCases/getContext/GetContextUseCase.spec.d.ts +1 -0
  36. package/lib/useCases/getContext/GetContextUseCase.spec.js +20 -0
  37. package/lib/useCases/getContext/index.d.ts +9 -0
  38. package/lib/useCases/getContext/index.js +17 -0
  39. package/lib/useCases/handleAuthRoutes/HandleAuthRoutesError.d.ts +9 -0
  40. package/lib/useCases/handleAuthRoutes/HandleAuthRoutesError.js +19 -0
  41. package/lib/useCases/handleAuthRoutes/index.d.ts +15 -0
  42. package/lib/useCases/handleAuthRoutes/index.js +46 -0
  43. package/lib/useCases/handleSignIn/HandleSignInController.d.ts +14 -0
  44. package/lib/useCases/handleSignIn/HandleSignInController.js +29 -0
  45. package/lib/useCases/handleSignIn/HandleSignInController.spec.d.ts +1 -0
  46. package/lib/useCases/handleSignIn/HandleSignInController.spec.js +16 -0
  47. package/lib/useCases/handleSignIn/HandleSignInUseCase.d.ts +16 -0
  48. package/lib/useCases/handleSignIn/HandleSignInUseCase.js +15 -0
  49. package/lib/useCases/handleSignIn/HandleSignInUseCase.spec.d.ts +1 -0
  50. package/lib/useCases/handleSignIn/HandleSignInUseCase.spec.js +18 -0
  51. package/lib/useCases/handleSignIn/index.d.ts +11 -0
  52. package/lib/useCases/handleSignIn/index.js +17 -0
  53. package/lib/useCases/handleSignInCallback/HandleSignInCallbackController.d.ts +14 -0
  54. package/lib/useCases/handleSignInCallback/HandleSignInCallbackController.js +40 -0
  55. package/lib/useCases/handleSignInCallback/HandleSignInCallbackController.spec.d.ts +1 -0
  56. package/lib/useCases/handleSignInCallback/HandleSignInCallbackController.spec.js +16 -0
  57. package/lib/useCases/handleSignInCallback/HandleSignInCallbackError.d.ts +8 -0
  58. package/lib/useCases/handleSignInCallback/HandleSignInCallbackError.js +15 -0
  59. package/lib/useCases/handleSignInCallback/HandleSignInCallbackUseCase.d.ts +15 -0
  60. package/lib/useCases/handleSignInCallback/HandleSignInCallbackUseCase.js +14 -0
  61. package/lib/useCases/handleSignInCallback/HandleSignInCallbackUseCase.spec.d.ts +1 -0
  62. package/lib/useCases/handleSignInCallback/HandleSignInCallbackUseCase.spec.js +18 -0
  63. package/lib/useCases/handleSignInCallback/index.d.ts +11 -0
  64. package/lib/useCases/handleSignInCallback/index.js +17 -0
  65. package/lib/useCases/handleSignOut/HandleSignOutController.d.ts +14 -0
  66. package/lib/useCases/handleSignOut/HandleSignOutController.js +32 -0
  67. package/lib/useCases/handleSignOut/HandleSignOutController.spec.d.ts +1 -0
  68. package/lib/useCases/handleSignOut/HandleSignOutController.spec.js +16 -0
  69. package/lib/useCases/handleSignOut/HandleSignOutError.d.ts +8 -0
  70. package/lib/useCases/handleSignOut/HandleSignOutError.js +15 -0
  71. package/lib/useCases/handleSignOut/HandleSignOutUseCase.d.ts +16 -0
  72. package/lib/useCases/handleSignOut/HandleSignOutUseCase.js +15 -0
  73. package/lib/useCases/handleSignOut/HandleSignOutUseCase.spec.d.ts +1 -0
  74. package/lib/useCases/handleSignOut/HandleSignOutUseCase.spec.js +18 -0
  75. package/lib/useCases/handleSignOut/index.d.ts +11 -0
  76. package/lib/useCases/handleSignOut/index.js +17 -0
  77. package/lib/useCases/handleSignUp/HandleSignUpController.d.ts +14 -0
  78. package/lib/useCases/handleSignUp/HandleSignUpController.js +29 -0
  79. package/lib/useCases/handleSignUp/HandleSignUpController.spec.d.ts +1 -0
  80. package/lib/useCases/handleSignUp/HandleSignUpController.spec.js +16 -0
  81. package/lib/useCases/handleSignUp/HandleSignUpUseCase.d.ts +16 -0
  82. package/lib/useCases/handleSignUp/HandleSignUpUseCase.js +15 -0
  83. package/lib/useCases/handleSignUp/HandleSignUpUseCase.spec.d.ts +1 -0
  84. package/lib/useCases/handleSignUp/HandleSignUpUseCase.spec.js +18 -0
  85. package/lib/useCases/handleSignUp/index.d.ts +11 -0
  86. package/lib/useCases/handleSignUp/index.js +17 -0
  87. package/package.json +63 -0
@@ -0,0 +1,16 @@
1
+ import { createLogtoAdapter, sessionStorage } from '../../framework/mocks.js';
2
+ import { HandleSignOutController } from './HandleSignOutController.js';
3
+ import { makeHandleSignOutUseCase } from './HandleSignOutUseCase.js';
4
+ describe('useCases:handleSignOut:HandleSignOutController', () => {
5
+ it('can be created', () => {
6
+ const useCase = makeHandleSignOutUseCase({
7
+ createLogtoAdapter,
8
+ sessionStorage,
9
+ });
10
+ const controller = HandleSignOutController.fromDto({
11
+ useCase,
12
+ redirectUri: '/',
13
+ });
14
+ expect(controller.constructor.name).toBe('HandleSignOutController');
15
+ });
16
+ });
@@ -0,0 +1,8 @@
1
+ export declare class HandleSignOutError extends Error {
2
+ private readonly properties;
3
+ static readonly becauseNoCookieHeaderPresent: () => HandleSignOutError;
4
+ readonly code: number;
5
+ readonly cause: Error | undefined;
6
+ readonly plainMessage: string;
7
+ private constructor();
8
+ }
@@ -0,0 +1,15 @@
1
+ class HandleSignOutError extends Error {
2
+ static { this.becauseNoCookieHeaderPresent = () => new HandleSignOutError({
3
+ code: 1_665_388_713,
4
+ message: `The authentication sign-out route can't be accessed without a valid cookie.`,
5
+ }); }
6
+ constructor(properties) {
7
+ super(`#[${properties.code}] ${properties.message}`);
8
+ this.properties = properties;
9
+ this.code = this.properties.code;
10
+ this.cause = this.properties.cause;
11
+ this.plainMessage = this.properties.message;
12
+ }
13
+ }
14
+
15
+ export { HandleSignOutError };
@@ -0,0 +1,16 @@
1
+ import type { SessionStorage } from 'react-router';
2
+ import type { CreateLogtoAdapter } from '../../infrastructure/logto/index.js';
3
+ type SignOutRequest = {
4
+ readonly cookieHeader: string | undefined;
5
+ redirectUri: string;
6
+ };
7
+ type SignOutResponse = {
8
+ cookieHeader: string;
9
+ readonly navigateToUrl: string;
10
+ };
11
+ export declare const makeHandleSignOutUseCase: (deps: {
12
+ createLogtoAdapter: CreateLogtoAdapter;
13
+ sessionStorage: SessionStorage;
14
+ }) => (request: SignOutRequest) => Promise<SignOutResponse>;
15
+ export type HandleSignOutUseCase = ReturnType<typeof makeHandleSignOutUseCase>;
16
+ export {};
@@ -0,0 +1,15 @@
1
+ const makeHandleSignOutUseCase = (deps) => async (request) => {
2
+ const { sessionStorage, createLogtoAdapter } = deps;
3
+ const session = await sessionStorage.getSession(request.cookieHeader);
4
+ const logto = createLogtoAdapter(session);
5
+ const response = await logto.handleSignOut({
6
+ redirectUri: request.redirectUri,
7
+ });
8
+ const cookieHeader = await sessionStorage.destroySession(session);
9
+ return {
10
+ cookieHeader,
11
+ navigateToUrl: response.navigateToUrl,
12
+ };
13
+ };
14
+
15
+ export { makeHandleSignOutUseCase };
@@ -0,0 +1,18 @@
1
+ import { createLogtoAdapter, sessionStorage, handleSignOut } from '../../framework/mocks.js';
2
+ import { makeHandleSignOutUseCase } from './HandleSignOutUseCase.js';
3
+ describe('useCases:handleSignOut:makeHandleSignOutUseCase', () => {
4
+ afterEach(() => {
5
+ vi.resetAllMocks();
6
+ });
7
+ it('can make a use case executer', async () => {
8
+ const execute = makeHandleSignOutUseCase({
9
+ createLogtoAdapter,
10
+ sessionStorage,
11
+ });
12
+ await execute({
13
+ cookieHeader: 'abcd',
14
+ redirectUri: '/',
15
+ });
16
+ expect(handleSignOut).toBeCalledTimes(1);
17
+ });
18
+ });
@@ -0,0 +1,11 @@
1
+ import type { SessionStorage } from 'react-router';
2
+ import type { CreateLogtoAdapter } from '../../infrastructure/logto/index.js';
3
+ type HandleSignOutDto = {
4
+ readonly redirectBackTo: string;
5
+ };
6
+ type HandleSignOutDeps = {
7
+ readonly createLogtoAdapter: CreateLogtoAdapter;
8
+ readonly sessionStorage: SessionStorage;
9
+ };
10
+ export declare const makeHandleSignOut: (dto: HandleSignOutDto, deps: HandleSignOutDeps) => (request: Request) => Promise<Response>;
11
+ export {};
@@ -0,0 +1,17 @@
1
+ import { HandleSignOutController } from './HandleSignOutController.js';
2
+ import { makeHandleSignOutUseCase } from './HandleSignOutUseCase.js';
3
+
4
+ const makeHandleSignOut = (dto, deps) => async (request) => {
5
+ const { createLogtoAdapter, sessionStorage } = deps;
6
+ const useCase = makeHandleSignOutUseCase({
7
+ createLogtoAdapter,
8
+ sessionStorage,
9
+ });
10
+ const controller = HandleSignOutController.fromDto({
11
+ useCase,
12
+ redirectUri: dto.redirectBackTo,
13
+ });
14
+ return controller.execute(request);
15
+ };
16
+
17
+ export { makeHandleSignOut };
@@ -0,0 +1,14 @@
1
+ import type { HandleSignUpUseCase } from './HandleSignUpUseCase.js';
2
+ type HandleSignUpControllerDto = {
3
+ readonly redirectUri: string;
4
+ readonly useCase: HandleSignUpUseCase;
5
+ };
6
+ export declare class HandleSignUpController {
7
+ private readonly properties;
8
+ static readonly fromDto: (dto: HandleSignUpControllerDto) => HandleSignUpController;
9
+ private readonly useCase;
10
+ private readonly redirectUri;
11
+ private constructor();
12
+ readonly execute: (request: Request) => Promise<Response>;
13
+ }
14
+ export {};
@@ -0,0 +1,29 @@
1
+ import { redirect } from 'react-router';
2
+ import { getCookieHeaderFromRequest } from '../../framework/get-cookie-header-from-request.js';
3
+
4
+ class HandleSignUpController {
5
+ static { this.fromDto = (dto) => new HandleSignUpController({
6
+ useCase: dto.useCase,
7
+ redirectUri: dto.redirectUri,
8
+ }); }
9
+ constructor(properties) {
10
+ this.properties = properties;
11
+ this.useCase = this.properties.useCase;
12
+ this.redirectUri = this.properties.redirectUri;
13
+ this.execute = async (request) => {
14
+ const cookieHeader = getCookieHeaderFromRequest(request);
15
+ const { redirectUri } = this;
16
+ const result = await this.useCase({
17
+ cookieHeader: cookieHeader ?? undefined,
18
+ redirectUri,
19
+ });
20
+ return redirect(result.navigateToUrl, {
21
+ headers: {
22
+ 'Set-Cookie': result.cookieHeader,
23
+ },
24
+ });
25
+ };
26
+ }
27
+ }
28
+
29
+ export { HandleSignUpController };
@@ -0,0 +1,16 @@
1
+ import { createLogtoAdapter, sessionStorage } from '../../framework/mocks.js';
2
+ import { HandleSignUpController } from './HandleSignUpController.js';
3
+ import { makeHandleSignUpUseCase } from './HandleSignUpUseCase.js';
4
+ describe('useCases:handleSignUp:HandleSignUpController', () => {
5
+ it('can be created', () => {
6
+ const useCase = makeHandleSignUpUseCase({
7
+ createLogtoAdapter,
8
+ sessionStorage,
9
+ });
10
+ const controller = HandleSignUpController.fromDto({
11
+ useCase,
12
+ redirectUri: '/',
13
+ });
14
+ expect(controller.constructor.name).toBe('HandleSignUpController');
15
+ });
16
+ });
@@ -0,0 +1,16 @@
1
+ import type { SessionStorage } from 'react-router';
2
+ import type { CreateLogtoAdapter } from '../../infrastructure/logto/index.js';
3
+ type SignUpRequest = {
4
+ readonly cookieHeader: string | undefined;
5
+ readonly redirectUri: string;
6
+ };
7
+ type SignUpResponse = {
8
+ readonly cookieHeader: string;
9
+ readonly navigateToUrl: string;
10
+ };
11
+ export declare const makeHandleSignUpUseCase: (deps: {
12
+ createLogtoAdapter: CreateLogtoAdapter;
13
+ sessionStorage: SessionStorage;
14
+ }) => (request: SignUpRequest) => Promise<SignUpResponse>;
15
+ export type HandleSignUpUseCase = ReturnType<typeof makeHandleSignUpUseCase>;
16
+ export {};
@@ -0,0 +1,15 @@
1
+ const makeHandleSignUpUseCase = (deps) => async (request) => {
2
+ const { sessionStorage, createLogtoAdapter } = deps;
3
+ const session = await sessionStorage.getSession(request.cookieHeader);
4
+ const logto = createLogtoAdapter(session);
5
+ const response = await logto.handleSignUp({
6
+ redirectUri: request.redirectUri,
7
+ });
8
+ const cookieHeader = await sessionStorage.commitSession(response.session);
9
+ return {
10
+ cookieHeader,
11
+ navigateToUrl: response.navigateToUrl,
12
+ };
13
+ };
14
+
15
+ export { makeHandleSignUpUseCase };
@@ -0,0 +1,18 @@
1
+ import { createLogtoAdapter, sessionStorage, handleSignUp } from '../../framework/mocks.js';
2
+ import { makeHandleSignUpUseCase } from './HandleSignUpUseCase.js';
3
+ describe('useCases:handleSignUp:HandleSignUpUseCase', () => {
4
+ afterEach(() => {
5
+ vi.resetAllMocks();
6
+ });
7
+ it('can make a use case executer', async () => {
8
+ const execute = makeHandleSignUpUseCase({
9
+ createLogtoAdapter,
10
+ sessionStorage,
11
+ });
12
+ await execute({
13
+ cookieHeader: 'abcd',
14
+ redirectUri: '/',
15
+ });
16
+ expect(handleSignUp).toBeCalledTimes(1);
17
+ });
18
+ });
@@ -0,0 +1,11 @@
1
+ import type { SessionStorage } from 'react-router';
2
+ import type { CreateLogtoAdapter } from '../../infrastructure/logto/index.js';
3
+ type HandleSignUpDto = {
4
+ readonly redirectBackTo: string;
5
+ };
6
+ type HandleSignUpDeps = {
7
+ readonly createLogtoAdapter: CreateLogtoAdapter;
8
+ readonly sessionStorage: SessionStorage;
9
+ };
10
+ export declare const makeHandleSignUp: (dto: HandleSignUpDto, deps: HandleSignUpDeps) => (request: Request) => Promise<Response>;
11
+ export {};
@@ -0,0 +1,17 @@
1
+ import { HandleSignUpController } from './HandleSignUpController.js';
2
+ import { makeHandleSignUpUseCase } from './HandleSignUpUseCase.js';
3
+
4
+ const makeHandleSignUp = (dto, deps) => async (request) => {
5
+ const { createLogtoAdapter, sessionStorage } = deps;
6
+ const useCase = makeHandleSignUpUseCase({
7
+ createLogtoAdapter,
8
+ sessionStorage,
9
+ });
10
+ const controller = HandleSignUpController.fromDto({
11
+ useCase,
12
+ redirectUri: dto.redirectBackTo,
13
+ });
14
+ return controller.execute(request);
15
+ };
16
+
17
+ export { makeHandleSignUp };
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@logto/react-router",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "module": "./lib/index.js",
6
+ "types": "./lib/index.d.ts",
7
+ "exports": {
8
+ "types": "./lib/index.d.ts",
9
+ "import": "./lib/index.js",
10
+ "default": "./lib/index.js"
11
+ },
12
+ "files": [
13
+ "lib"
14
+ ],
15
+ "license": "MIT",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/logto-io/js.git",
19
+ "directory": "packages/react-router"
20
+ },
21
+ "dependencies": {
22
+ "@logto/node": "^3.1.6"
23
+ },
24
+ "devDependencies": {
25
+ "react-router": "^7.5.3",
26
+ "@silverhand/eslint-config": "^6.0.1",
27
+ "@silverhand/ts-config": "^6.0.0",
28
+ "@types/node": "^22.0.0",
29
+ "@vitest/coverage-v8": "^2.1.9",
30
+ "eslint": "^8.57.0",
31
+ "lint-staged": "^15.0.0",
32
+ "prettier": "^3.0.0",
33
+ "typescript": "^5.3.3",
34
+ "vitest": "^2.1.9"
35
+ },
36
+ "peerDependencies": {
37
+ "react-router": ">=7"
38
+ },
39
+ "eslintConfig": {
40
+ "extends": "@silverhand"
41
+ },
42
+ "prettier": "@silverhand/eslint-config/.prettierrc",
43
+ "publishConfig": {
44
+ "access": "public"
45
+ },
46
+ "targets": {
47
+ "main": {
48
+ "context": "node",
49
+ "engines": {
50
+ "node": ">=18.12.0"
51
+ }
52
+ }
53
+ },
54
+ "scripts": {
55
+ "dev:tsc": "tsc -p tsconfig.build.json -w --preserveWatchOutput",
56
+ "precommit": "lint-staged",
57
+ "check": "tsc --noEmit",
58
+ "build": "rm -rf lib/ && tsc -p tsconfig.build.json --declaration && rollup -c",
59
+ "lint": "eslint --ext .ts src",
60
+ "test": "vitest",
61
+ "test:coverage": "vitest --silent --coverage"
62
+ }
63
+ }