@strivacity/sdk-next 3.0.3 → 4.0.0-beta.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 (90) hide show
  1. package/README.md +1983 -428
  2. package/dist/client/components.cjs +1 -0
  3. package/dist/client/components.d.ts +1 -0
  4. package/dist/client/components.mjs +1 -0
  5. package/dist/client/hooks.cjs +1 -0
  6. package/dist/client/hooks.d.ts +1 -0
  7. package/dist/client/hooks.mjs +1 -0
  8. package/dist/client/index.cjs +1 -0
  9. package/dist/client/index.d.ts +9 -0
  10. package/dist/client/index.mjs +1 -0
  11. package/dist/client/storages.cjs +1 -0
  12. package/dist/client/storages.d.ts +1 -0
  13. package/dist/client/storages.mjs +1 -0
  14. package/dist/client/types.cjs +1 -0
  15. package/dist/client/types.d.ts +1 -0
  16. package/dist/client/types.mjs +1 -0
  17. package/dist/client/utils.cjs +1 -0
  18. package/dist/client/utils.d.ts +1 -0
  19. package/dist/client/utils.mjs +1 -0
  20. package/dist/errors.cjs +1 -0
  21. package/dist/errors.d.ts +1 -0
  22. package/dist/errors.mjs +1 -0
  23. package/dist/server/handlers/api.cjs +2 -0
  24. package/dist/server/handlers/api.cjs.map +1 -0
  25. package/dist/server/handlers/api.d.ts +4 -0
  26. package/dist/server/handlers/api.mjs +2 -0
  27. package/dist/server/handlers/api.mjs.map +1 -0
  28. package/dist/server/handlers/route.cjs +2 -0
  29. package/dist/server/handlers/route.cjs.map +1 -0
  30. package/dist/server/handlers/route.d.ts +4 -0
  31. package/dist/server/handlers/route.mjs +2 -0
  32. package/dist/server/handlers/route.mjs.map +1 -0
  33. package/dist/server/index.cjs +1 -0
  34. package/dist/server/index.d.ts +8 -0
  35. package/dist/server/index.mjs +1 -0
  36. package/dist/server/sdk.cjs +2 -0
  37. package/dist/server/sdk.cjs.map +1 -0
  38. package/dist/server/sdk.d.ts +8 -0
  39. package/dist/server/sdk.mjs +2 -0
  40. package/dist/server/sdk.mjs.map +1 -0
  41. package/dist/server/storages.cjs +2 -0
  42. package/dist/server/storages.cjs.map +1 -0
  43. package/dist/server/storages.d.ts +20 -0
  44. package/dist/server/storages.mjs +2 -0
  45. package/dist/server/storages.mjs.map +1 -0
  46. package/dist/server/types.cjs +1 -0
  47. package/dist/server/types.d.ts +101 -0
  48. package/dist/server/types.mjs +1 -0
  49. package/dist/server/utils.cjs +2 -0
  50. package/dist/server/utils.cjs.map +1 -0
  51. package/dist/server/utils.d.ts +28 -0
  52. package/dist/server/utils.mjs +2 -0
  53. package/dist/server/utils.mjs.map +1 -0
  54. package/dist/types.cjs +1 -2
  55. package/dist/types.d.ts +2 -176
  56. package/dist/types.mjs +1 -2
  57. package/package.json +48 -10
  58. package/testing/tests/client/components.spec.ts +10 -0
  59. package/testing/tests/client/hooks.spec.ts +10 -0
  60. package/testing/tests/client/index.spec.ts +106 -0
  61. package/testing/tests/client/storages.spec.ts +10 -0
  62. package/testing/tests/client/utils.spec.ts +10 -0
  63. package/testing/tests/server/handlers/api.spec.ts +110 -0
  64. package/testing/tests/server/handlers/route.spec.ts +173 -0
  65. package/testing/tests/server/index.spec.ts +103 -0
  66. package/testing/tests/server/sdk.spec.ts +250 -0
  67. package/testing/tests/server/storages.spec.ts +353 -0
  68. package/testing/tests/server/utils.spec.ts +110 -0
  69. package/dist/AuthProvider.cjs +0 -2
  70. package/dist/AuthProvider.cjs.map +0 -1
  71. package/dist/AuthProvider.d.ts +0 -7
  72. package/dist/AuthProvider.mjs +0 -2
  73. package/dist/AuthProvider.mjs.map +0 -1
  74. package/dist/LoginRenderer.cjs +0 -2
  75. package/dist/LoginRenderer.cjs.map +0 -1
  76. package/dist/LoginRenderer.d.ts +0 -20
  77. package/dist/LoginRenderer.mjs +0 -2
  78. package/dist/LoginRenderer.mjs.map +0 -1
  79. package/dist/composables.cjs +0 -2
  80. package/dist/composables.cjs.map +0 -1
  81. package/dist/composables.d.ts +0 -12
  82. package/dist/composables.mjs +0 -2
  83. package/dist/composables.mjs.map +0 -1
  84. package/dist/index.cjs +0 -2
  85. package/dist/index.cjs.map +0 -1
  86. package/dist/index.d.ts +0 -13
  87. package/dist/index.mjs +0 -2
  88. package/dist/index.mjs.map +0 -1
  89. package/dist/types.cjs.map +0 -1
  90. package/dist/types.mjs.map +0 -1
package/dist/types.d.ts CHANGED
@@ -1,176 +1,2 @@
1
- import { IdTokenClaims, LoginFlowMessage, LoginFlowState, SDKOptions } from '@strivacity/sdk-core';
2
- import { PopupFlow } from '@strivacity/sdk-core/flows/PopupFlow';
3
- import { RedirectFlow } from '@strivacity/sdk-core/flows/RedirectFlow';
4
- import { NativeFlow } from '@strivacity/sdk-core/flows/NativeFlow';
5
- export type Children = React.ReactElement | React.ReactNode | Array<React.ReactElement | React.ReactNode>;
6
- /**
7
- * Represents the session state, including authentication details and token information.
8
- */
9
- export type Session = {
10
- /**
11
- * Indicates if the session is being loaded.
12
- */
13
- loading: boolean;
14
- /**
15
- * The SDK options used to configure the session.
16
- */
17
- options: SDKOptions;
18
- /**
19
- * Indicates whether the user is authenticated.
20
- */
21
- isAuthenticated: boolean;
22
- /**
23
- * Claims from the ID token or `null` if not available.
24
- */
25
- idTokenClaims: IdTokenClaims | null;
26
- /**
27
- * The access token or `null` if not available.
28
- */
29
- accessToken: string | null;
30
- /**
31
- * The refresh token or `null` if not available.
32
- */
33
- refreshToken: string | null;
34
- /**
35
- * Indicates if the access token has expired.
36
- */
37
- accessTokenExpired: boolean;
38
- /**
39
- * Expiration date of the access token or `null` if not set.
40
- */
41
- accessTokenExpirationDate: number | null;
42
- };
43
- /**
44
- * Represents the available authentication flows and operations for Popup-based interactions.
45
- */
46
- export type PopupSDK = {
47
- /**
48
- * Represents the SDK instance.
49
- */
50
- sdk: InstanceType<typeof PopupFlow>;
51
- /**
52
- * Initiates the login process.
53
- */
54
- login: InstanceType<typeof PopupFlow>['login'];
55
- /**
56
- * Registers a new user.
57
- */
58
- register: InstanceType<typeof PopupFlow>['register'];
59
- /**
60
- * Initiates the entry process.
61
- */
62
- entry: InstanceType<typeof PopupFlow>['entry'];
63
- /**
64
- * Refreshes the user's session.
65
- */
66
- refresh: InstanceType<typeof PopupFlow>['refresh'];
67
- /**
68
- * Revokes the current session tokens.
69
- */
70
- revoke: InstanceType<typeof PopupFlow>['revoke'];
71
- /**
72
- * Logs out the user.
73
- */
74
- logout: InstanceType<typeof PopupFlow>['logout'];
75
- /**
76
- * Handles the callback after authentication or token exchange.
77
- */
78
- handleCallback: InstanceType<typeof PopupFlow>['handleCallback'];
79
- };
80
- /**
81
- * Represents the available authentication flows and operations for Redirect-based interactions.
82
- */
83
- export type RedirectSDK = {
84
- /**
85
- * Represents the SDK instance.
86
- */
87
- sdk: InstanceType<typeof RedirectFlow>;
88
- /**
89
- * Initiates the login process.
90
- */
91
- login: InstanceType<typeof RedirectFlow>['login'];
92
- /**
93
- * Registers a new user.
94
- */
95
- register: InstanceType<typeof RedirectFlow>['register'];
96
- /**
97
- * Initiates the entry process.
98
- */
99
- entry: InstanceType<typeof RedirectFlow>['entry'];
100
- /**
101
- * Refreshes the user's session.
102
- */
103
- refresh: InstanceType<typeof RedirectFlow>['refresh'];
104
- /**
105
- * Revokes the current session tokens.
106
- */
107
- revoke: InstanceType<typeof RedirectFlow>['revoke'];
108
- /**
109
- * Logs out the user.
110
- */
111
- logout: InstanceType<typeof RedirectFlow>['logout'];
112
- /**
113
- * Handles the callback after authentication or token exchange.
114
- */
115
- handleCallback: InstanceType<typeof RedirectFlow>['handleCallback'];
116
- };
117
- /**
118
- * Represents the available authentication flows and operations for Native-based interactions.
119
- */
120
- export type NativeSDK = {
121
- /**
122
- * Represents the SDK instance.
123
- */
124
- sdk: InstanceType<typeof NativeFlow>;
125
- /**
126
- * Initiates the login process.
127
- */
128
- login: InstanceType<typeof NativeFlow>['login'];
129
- /**
130
- * Registers a new user.
131
- */
132
- register: InstanceType<typeof NativeFlow>['register'];
133
- /**
134
- * Initiates the entry process.
135
- */
136
- entry: InstanceType<typeof NativeFlow>['entry'];
137
- /**
138
- * Refreshes the user's session.
139
- */
140
- refresh: InstanceType<typeof NativeFlow>['refresh'];
141
- /**
142
- * Revokes the current session tokens.
143
- */
144
- revoke: InstanceType<typeof NativeFlow>['revoke'];
145
- /**
146
- * Logs out the user.
147
- */
148
- logout: InstanceType<typeof NativeFlow>['logout'];
149
- /**
150
- * Handles the callback after authentication or token exchange.
151
- */
152
- handleCallback: InstanceType<typeof NativeFlow>['handleCallback'];
153
- };
154
- /**
155
- * Represents a combined context for Popup-based flows, containing both the Popup SDK and the session state.
156
- */
157
- export type PopupContext = PopupSDK & Session;
158
- /**
159
- * Represents a combined context for Redirect-based flows, containing both the Redirect SDK and the session state.
160
- */
161
- export type RedirectContext = RedirectSDK & Session;
162
- /**
163
- * Represents a combined context for Native-based flows, containing both the Native SDK and the session state.
164
- */
165
- export type NativeContext = NativeSDK & Session;
166
- export type NativeFlowContextValue = {
167
- loading: boolean;
168
- forms: Record<string, Record<string, unknown>>;
169
- messages: Record<string, Record<string, LoginFlowMessage>>;
170
- state: Partial<LoginFlowState>;
171
- submitForm: (formId: string) => Promise<void>;
172
- triggerFallback: (hostedUrl?: string) => void;
173
- triggerClose: () => void;
174
- setFormValue: (formId: string, widgetId: string, value: unknown) => void;
175
- setMessage: (formId: string, widgetId: string, value: LoginFlowMessage) => void;
176
- };
1
+ export * from './client/types';
2
+ export * from './server/types';
package/dist/types.mjs CHANGED
@@ -1,2 +1 @@
1
-
2
- //# sourceMappingURL=types.mjs.map
1
+ import"./client/types.mjs";import"./server/types.mjs";export*from"@strivacity/sdk-react/types";export*from"@strivacity/sdk-core/types";
package/package.json CHANGED
@@ -1,27 +1,65 @@
1
1
  {
2
2
  "name": "@strivacity/sdk-next",
3
- "version": "3.0.3",
4
- "license": "MIT",
3
+ "version": "4.0.0-beta.0",
5
4
  "description": "Strivacity Next.js SDK client",
5
+ "license": "MIT",
6
6
  "author": "strivacity <opensource@strivacity.com>",
7
7
  "repository": {
8
8
  "type": "git",
9
9
  "url": "https://github.com/Strivacity/sdk-js"
10
10
  },
11
- "dependencies": {
12
- "@strivacity/sdk-core": "3.0.3"
13
- },
14
- "peerDependencies": {
15
- "next": ">=13"
16
- },
17
- "main": "./dist/index.cjs",
18
- "types": "./dist/index.d.ts",
11
+ "sideEffects": false,
12
+ "main": "./dist/client.cjs",
13
+ "types": "./dist/types.d.ts",
19
14
  "exports": {
20
15
  ".": {
21
16
  "types": "./dist/index.d.ts",
22
17
  "import": "./dist/index.mjs",
23
18
  "require": "./dist/index.cjs",
24
19
  "default": "./dist/index.mjs"
20
+ },
21
+ "./client": {
22
+ "types": "./dist/client/index.d.ts",
23
+ "import": "./dist/client/index.mjs",
24
+ "require": "./dist/client/index.cjs",
25
+ "default": "./dist/client/index.mjs"
26
+ },
27
+ "./client/*": {
28
+ "types": "./dist/client/*.d.ts",
29
+ "import": "./dist/client/*.mjs",
30
+ "require": "./dist/client/*.cjs",
31
+ "default": "./dist/client/*.mjs"
32
+ },
33
+ "./server": {
34
+ "types": "./dist/server/index.d.ts",
35
+ "import": "./dist/server/index.mjs",
36
+ "require": "./dist/server/index.cjs",
37
+ "default": "./dist/server/index.mjs"
38
+ },
39
+ "./server/*": {
40
+ "types": "./dist/server/*.d.ts",
41
+ "import": "./dist/server/*.mjs",
42
+ "require": "./dist/server/*.cjs",
43
+ "default": "./dist/server/*.mjs"
44
+ },
45
+ "./errors": {
46
+ "types": "./dist/errors.d.ts",
47
+ "import": "./dist/errors.mjs",
48
+ "require": "./dist/errors.cjs",
49
+ "default": "./dist/errors.mjs"
50
+ },
51
+ "./types": {
52
+ "types": "./dist/types.d.ts",
53
+ "import": "./dist/types.mjs",
54
+ "require": "./dist/types.cjs",
55
+ "default": "./dist/types.mjs"
25
56
  }
57
+ },
58
+ "dependencies": {
59
+ "@strivacity/sdk-core": "4.0.0-beta.0",
60
+ "@strivacity/sdk-react": "4.0.0-beta.0"
61
+ },
62
+ "peerDependencies": {
63
+ "next": ">=15"
26
64
  }
27
65
  }
@@ -0,0 +1,10 @@
1
+ import { test, expect } from 'vitest';
2
+ import * as nextComponents from '../../../src/client/components';
3
+ import * as reactComponents from '@strivacity/sdk-react/components';
4
+
5
+ test('re-exports components from the react sdk', () => {
6
+ const reactKeys = Object.keys(reactComponents);
7
+
8
+ expect(reactKeys.length).toBeGreaterThan(0);
9
+ expect(Object.keys(nextComponents).sort()).toEqual(reactKeys.sort());
10
+ });
@@ -0,0 +1,10 @@
1
+ import { test, expect } from 'vitest';
2
+ import * as nextHooks from '../../../src/client/hooks';
3
+ import * as reactHooks from '@strivacity/sdk-react/hooks';
4
+
5
+ test('re-exports hooks from the react sdk', () => {
6
+ const reactKeys = Object.keys(reactHooks);
7
+
8
+ expect(reactKeys.length).toBeGreaterThan(0);
9
+ expect(Object.keys(nextHooks).sort()).toEqual(reactKeys.sort());
10
+ });
@@ -0,0 +1,106 @@
1
+ import { test, expect } from 'vitest';
2
+ import * as clientIndex from '../../../src/client/index';
3
+
4
+ test('should export the correct things', () => {
5
+ const expectedExports = [
6
+ 'AlgorithmTypeList',
7
+ 'BACKCHANNEL_LOGOUT_EVENT',
8
+ 'COOKIE_CHUNK_SIZE',
9
+ 'COOKIE_CONTEXT',
10
+ 'ConfigurationError',
11
+ 'DEFAULT_COOKIE_MAX_AGE',
12
+ 'DISALLOWED_PROXY_HEADERS',
13
+ 'FallbackError',
14
+ 'GrantTypeList',
15
+ 'InternalError',
16
+ 'NetworkError',
17
+ 'OidcError',
18
+ 'PopupBlockedError',
19
+ 'PopupClosedError',
20
+ 'ProtocolError',
21
+ 'RETURN_TO_COOKIE',
22
+ 'ResponseModeList',
23
+ 'ResponseTypeList',
24
+ 'STRIVACITY_SDK',
25
+ 'ServerError',
26
+ 'SessionExpiredError',
27
+ 'StyAuthProvider',
28
+ 'SubjectTypeList',
29
+ 'TokenEndpointAuthMethodList',
30
+ 'UnsupportedFlowError',
31
+ 'assertWebAuthnCredential',
32
+ 'buildAuthorizationUrl',
33
+ 'buildCookieString',
34
+ 'buildEndSessionUrl',
35
+ 'createBaseFlow',
36
+ 'createCacheAPIStorage',
37
+ 'createDefaultLogging',
38
+ 'createEmbeddedFlow',
39
+ 'createEncryptedCookieStorage',
40
+ 'createHttpClient',
41
+ 'createIndexedDBStorage',
42
+ 'createLocalStorage',
43
+ 'createMemoryStorage',
44
+ 'createNativeFlow',
45
+ 'createPopupFlow',
46
+ 'createRedirectFlow',
47
+ 'createServerMemoryStorage',
48
+ 'createServerStateStorage',
49
+ 'createSession',
50
+ 'createSessionIdCookieStorage',
51
+ 'createSessionStorage',
52
+ 'createState',
53
+ 'createWebAuthnCredential',
54
+ 'createWorkerStorage',
55
+ 'decodeBase64URL',
56
+ 'decodeJwt',
57
+ 'decryptString',
58
+ 'defaultOptions',
59
+ 'encodeBase64URL',
60
+ 'encryptString',
61
+ 'exchangeCode',
62
+ 'fetchFlowEntry',
63
+ 'finalizeLoginSession',
64
+ 'flushSetCookies',
65
+ 'generateCodeChallenge',
66
+ 'generateCodeVerifier',
67
+ 'generateJwt',
68
+ 'generateRandomHex',
69
+ 'getDefaultFlowState',
70
+ 'getDiscoveryDocument',
71
+ 'getSDKOptions',
72
+ 'getServerSDKOptions',
73
+ 'handleWorkerStorageRequests',
74
+ 'injectScript',
75
+ 'isSessionExpired',
76
+ 'loadSession',
77
+ 'parseCookieHeader',
78
+ 'parseState',
79
+ 'popupCallbackHandler',
80
+ 'popupUrlHandler',
81
+ 'proxyResponse',
82
+ 'pushSetCookie',
83
+ 'redirectCallbackHandler',
84
+ 'redirectUrlHandler',
85
+ 'refreshToken',
86
+ 'revokeToken',
87
+ 'serializeCookie',
88
+ 'serializeSession',
89
+ 'serializeState',
90
+ 'submitLoginForm',
91
+ 'throwHttpError',
92
+ 'throwTokenEndpointError',
93
+ 'timestamp',
94
+ 'toSafeRedirect',
95
+ 'unflattenObject',
96
+ 'useNativeLogin',
97
+ 'useNativeLoginContext',
98
+ 'useStrivacity',
99
+ 'verifyIdToken',
100
+ 'verifyJwt',
101
+ 'withAuthGuard',
102
+ ];
103
+
104
+ expect(Object.keys(clientIndex)).toHaveLength(expectedExports.length);
105
+ expect(Object.keys(clientIndex).sort()).toEqual(expectedExports.sort());
106
+ });
@@ -0,0 +1,10 @@
1
+ import { test, expect } from 'vitest';
2
+ import * as nextStorages from '../../../src/client/storages';
3
+ import * as reactStorages from '@strivacity/sdk-react/storages';
4
+
5
+ test('re-exports storages from the react sdk', () => {
6
+ const reactKeys = Object.keys(reactStorages);
7
+
8
+ expect(reactKeys.length).toBeGreaterThan(0);
9
+ expect(Object.keys(nextStorages).sort()).toEqual(reactKeys.sort());
10
+ });
@@ -0,0 +1,10 @@
1
+ import { test, expect } from 'vitest';
2
+ import * as nextUtils from '../../../src/client/utils';
3
+ import * as reactUtils from '@strivacity/sdk-react/utils';
4
+
5
+ test('re-exports utilities from the react sdk', () => {
6
+ const reactKeys = Object.keys(reactUtils);
7
+
8
+ expect(reactKeys.length).toBeGreaterThan(0);
9
+ expect(Object.keys(nextUtils).sort()).toEqual(reactKeys.sort());
10
+ });
@@ -0,0 +1,110 @@
1
+ import type { Mock } from 'vitest';
2
+ import { describe, test, expect, vi } from 'vitest';
3
+ import { NextRequest, NextResponse } from 'next/server';
4
+ import { createMockBaseServerSDK } from '@strivacity/testing/mocks/sdk';
5
+ import { apiAppRouteHandlerFactory, apiPageRouteHandlerFactory } from '../../../../src/server/handlers/api';
6
+ import type { BaseServerSDK, PagesRouterRequest } from '../../../../src/server/types';
7
+
8
+ describe('apiAppRouteHandlerFactory', () => {
9
+ test('returns a 401 response and does not call the route when there is no session', async () => {
10
+ const sdk = createMockBaseServerSDK<BaseServerSDK<NextRequest | Request | PagesRouterRequest | undefined>>();
11
+ const apiRoute = vi.fn();
12
+ const handler = apiAppRouteHandlerFactory(sdk)(apiRoute);
13
+
14
+ const response = await handler(new NextRequest('https://brandtegrity.io/api/secret'), {});
15
+
16
+ expect(response.status).toBe(401);
17
+ await expect(response.json()).resolves.toEqual({
18
+ error: 'not_authenticated',
19
+ description: 'The user does not have an active session or is not authenticated',
20
+ });
21
+ expect(apiRoute).not.toHaveBeenCalled();
22
+ });
23
+
24
+ test('calls the route with the request and params when there is a session', async () => {
25
+ const sdk = createMockBaseServerSDK<BaseServerSDK<NextRequest | Request | PagesRouterRequest | undefined>>({ getSession: vi.fn().mockResolvedValue({}) });
26
+ const apiRoute = vi.fn().mockResolvedValue(NextResponse.json({ ok: true }));
27
+ const handler = apiAppRouteHandlerFactory(sdk)(apiRoute);
28
+ const req = new NextRequest('https://brandtegrity.io/api/secret');
29
+ const params = { params: Promise.resolve({ id: '1' }) };
30
+
31
+ await handler(req, params);
32
+
33
+ expect(apiRoute).toHaveBeenCalledWith(req, params);
34
+ expect(sdk.getSession).toHaveBeenCalledWith(req);
35
+ });
36
+
37
+ test('returns the route NextResponse unchanged', async () => {
38
+ const sdk = createMockBaseServerSDK<BaseServerSDK<NextRequest | Request | PagesRouterRequest | undefined>>({ getSession: vi.fn().mockResolvedValue({}) });
39
+ const routeResponse = NextResponse.json({ ok: true });
40
+ const apiRoute = vi.fn().mockResolvedValue(routeResponse);
41
+ const handler = apiAppRouteHandlerFactory(sdk)(apiRoute);
42
+
43
+ const response = await handler(new NextRequest('https://brandtegrity.io/api/secret'), {});
44
+
45
+ expect(response).toBe(routeResponse);
46
+ });
47
+
48
+ test('wraps a plain Response returned by the route into a NextResponse', async () => {
49
+ const sdk = createMockBaseServerSDK<BaseServerSDK<NextRequest | Request | PagesRouterRequest | undefined>>({ getSession: vi.fn().mockResolvedValue({}) });
50
+ const apiRoute = vi.fn().mockResolvedValue(new Response('plain body', { status: 201, headers: { 'x-custom': 'yes' } }));
51
+ const handler = apiAppRouteHandlerFactory(sdk)(apiRoute);
52
+
53
+ const response = await handler(new NextRequest('https://brandtegrity.io/api/secret'), {});
54
+
55
+ expect(response).toBeInstanceOf(NextResponse);
56
+ expect(response.status).toBe(201);
57
+ expect(response.headers.get('x-custom')).toBe('yes');
58
+ await expect(response.text()).resolves.toBe('plain body');
59
+ });
60
+
61
+ test('converts a plain Request to a NextRequest before checking the session and calling the route', async () => {
62
+ const sdk = createMockBaseServerSDK<BaseServerSDK<NextRequest | Request | PagesRouterRequest | undefined>>({ getSession: vi.fn().mockResolvedValue({}) });
63
+ const apiRoute = vi.fn().mockResolvedValue(NextResponse.json({ ok: true }));
64
+ const handler = apiAppRouteHandlerFactory(sdk)(apiRoute);
65
+ const req = new Request('https://brandtegrity.io/api/secret');
66
+
67
+ await handler(req, {});
68
+
69
+ const usedRequest = (sdk.getSession as Mock).mock.calls[0][0] as NextRequest;
70
+ expect(usedRequest).toBeInstanceOf(NextRequest);
71
+ expect(usedRequest.url).toBe(req.url);
72
+ expect(apiRoute).toHaveBeenCalledWith(usedRequest, {});
73
+ });
74
+ });
75
+
76
+ describe('apiPageRouteHandlerFactory', () => {
77
+ function createFakeRes() {
78
+ const json = vi.fn();
79
+ const status = vi.fn().mockReturnValue({ json });
80
+
81
+ return { status, json };
82
+ }
83
+
84
+ test('responds with 401 and does not call the route when there is no session', async () => {
85
+ const sdk = createMockBaseServerSDK<BaseServerSDK<NextRequest | Request | PagesRouterRequest | undefined>>();
86
+ const apiRoute = vi.fn();
87
+ const handler = apiPageRouteHandlerFactory(sdk)(apiRoute);
88
+ const req = {} as PagesRouterRequest;
89
+ const res = createFakeRes();
90
+
91
+ await handler(req, res as never);
92
+
93
+ expect(res.status).toHaveBeenCalledWith(401);
94
+ expect(res.json).toHaveBeenCalledWith({ error: 'not_authenticated', description: 'The user does not have an active session or is not authenticated' });
95
+ expect(apiRoute).not.toHaveBeenCalled();
96
+ });
97
+
98
+ test('calls the route with the request and response when there is a session', async () => {
99
+ const sdk = createMockBaseServerSDK<BaseServerSDK<NextRequest | Request | PagesRouterRequest | undefined>>({ getSession: vi.fn().mockResolvedValue({}) });
100
+ const apiRoute = vi.fn();
101
+ const handler = apiPageRouteHandlerFactory(sdk)(apiRoute);
102
+ const req = {} as PagesRouterRequest;
103
+ const res = createFakeRes();
104
+
105
+ await handler(req, res as never);
106
+
107
+ expect(apiRoute).toHaveBeenCalledWith(req, res);
108
+ expect(res.status).not.toHaveBeenCalled();
109
+ });
110
+ });