@strivacity/sdk-next 3.0.2 → 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.
- package/CHANGELOG.md +6 -0
- package/README.md +1983 -428
- package/dist/client/components.cjs +1 -0
- package/dist/client/components.d.ts +1 -0
- package/dist/client/components.mjs +1 -0
- package/dist/client/hooks.cjs +1 -0
- package/dist/client/hooks.d.ts +1 -0
- package/dist/client/hooks.mjs +1 -0
- package/dist/client/index.cjs +1 -0
- package/dist/client/index.d.ts +9 -0
- package/dist/client/index.mjs +1 -0
- package/dist/client/storages.cjs +1 -0
- package/dist/client/storages.d.ts +1 -0
- package/dist/client/storages.mjs +1 -0
- package/dist/client/types.cjs +1 -0
- package/dist/client/types.d.ts +1 -0
- package/dist/client/types.mjs +1 -0
- package/dist/client/utils.cjs +1 -0
- package/dist/client/utils.d.ts +1 -0
- package/dist/client/utils.mjs +1 -0
- package/dist/errors.cjs +1 -0
- package/dist/errors.d.ts +1 -0
- package/dist/errors.mjs +1 -0
- package/dist/server/handlers/api.cjs +2 -0
- package/dist/server/handlers/api.cjs.map +1 -0
- package/dist/server/handlers/api.d.ts +4 -0
- package/dist/server/handlers/api.mjs +2 -0
- package/dist/server/handlers/api.mjs.map +1 -0
- package/dist/server/handlers/route.cjs +2 -0
- package/dist/server/handlers/route.cjs.map +1 -0
- package/dist/server/handlers/route.d.ts +4 -0
- package/dist/server/handlers/route.mjs +2 -0
- package/dist/server/handlers/route.mjs.map +1 -0
- package/dist/server/index.cjs +1 -0
- package/dist/server/index.d.ts +8 -0
- package/dist/server/index.mjs +1 -0
- package/dist/server/sdk.cjs +2 -0
- package/dist/server/sdk.cjs.map +1 -0
- package/dist/server/sdk.d.ts +8 -0
- package/dist/server/sdk.mjs +2 -0
- package/dist/server/sdk.mjs.map +1 -0
- package/dist/server/storages.cjs +2 -0
- package/dist/server/storages.cjs.map +1 -0
- package/dist/server/storages.d.ts +20 -0
- package/dist/server/storages.mjs +2 -0
- package/dist/server/storages.mjs.map +1 -0
- package/dist/server/types.cjs +1 -0
- package/dist/server/types.d.ts +101 -0
- package/dist/server/types.mjs +1 -0
- package/dist/server/utils.cjs +2 -0
- package/dist/server/utils.cjs.map +1 -0
- package/dist/server/utils.d.ts +28 -0
- package/dist/server/utils.mjs +2 -0
- package/dist/server/utils.mjs.map +1 -0
- package/dist/types.cjs +1 -2
- package/dist/types.d.ts +2 -176
- package/dist/types.mjs +1 -2
- package/package.json +48 -10
- package/testing/tests/client/components.spec.ts +10 -0
- package/testing/tests/client/hooks.spec.ts +10 -0
- package/testing/tests/client/index.spec.ts +106 -0
- package/testing/tests/client/storages.spec.ts +10 -0
- package/testing/tests/client/utils.spec.ts +10 -0
- package/testing/tests/server/handlers/api.spec.ts +110 -0
- package/testing/tests/server/handlers/route.spec.ts +173 -0
- package/testing/tests/server/index.spec.ts +103 -0
- package/testing/tests/server/sdk.spec.ts +250 -0
- package/testing/tests/server/storages.spec.ts +353 -0
- package/testing/tests/server/utils.spec.ts +110 -0
- package/dist/AuthProvider.cjs +0 -2
- package/dist/AuthProvider.cjs.map +0 -1
- package/dist/AuthProvider.d.ts +0 -7
- package/dist/AuthProvider.mjs +0 -2
- package/dist/AuthProvider.mjs.map +0 -1
- package/dist/LoginRenderer.cjs +0 -2
- package/dist/LoginRenderer.cjs.map +0 -1
- package/dist/LoginRenderer.d.ts +0 -20
- package/dist/LoginRenderer.mjs +0 -2
- package/dist/LoginRenderer.mjs.map +0 -1
- package/dist/composables.cjs +0 -2
- package/dist/composables.cjs.map +0 -1
- package/dist/composables.d.ts +0 -12
- package/dist/composables.mjs +0 -2
- package/dist/composables.mjs.map +0 -1
- package/dist/index.cjs +0 -2
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.ts +0 -13
- package/dist/index.mjs +0 -2
- package/dist/index.mjs.map +0 -1
- package/dist/types.cjs.map +0 -1
- package/dist/types.mjs.map +0 -1
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
import type { Mock } from 'vitest';
|
|
2
|
+
import { describe, test, expect, vi } from 'vitest';
|
|
3
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
4
|
+
import { cookies } from 'next/headers';
|
|
5
|
+
import { flushSetCookies } from '@strivacity/sdk-core/utils/server';
|
|
6
|
+
import { InternalError } from '@strivacity/sdk-core/utils/errors';
|
|
7
|
+
import { decryptString } from '@strivacity/sdk-core/utils/crypto';
|
|
8
|
+
import { createMockStorage } from '@strivacity/testing/mocks/sdk';
|
|
9
|
+
import { createSessionIdCookieStorage, createEncryptedCookieStorage } from '../../../src/server/storages';
|
|
10
|
+
import type { NextServerStorage } from '../../../src/server/types';
|
|
11
|
+
|
|
12
|
+
vi.mock('next/headers', () => ({ cookies: vi.fn() }));
|
|
13
|
+
|
|
14
|
+
type FakeCookieJar = { get: Mock; set: Mock; delete: Mock };
|
|
15
|
+
|
|
16
|
+
function createFakeCookieJar(): FakeCookieJar {
|
|
17
|
+
const store = new Map<string, string>();
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
get: vi.fn((name: string) => (store.has(name) ? { name, value: store.get(name)! } : undefined)),
|
|
21
|
+
set: vi.fn((name: string, value: string) => {
|
|
22
|
+
store.set(name, value);
|
|
23
|
+
}),
|
|
24
|
+
delete: vi.fn((name: string) => {
|
|
25
|
+
store.delete(name);
|
|
26
|
+
}),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function createFakePagesResponse() {
|
|
31
|
+
const headers = new Map<string, string | Array<string>>();
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
getHeader: vi.fn((name: string) => headers.get(name)),
|
|
35
|
+
setHeader: vi.fn((name: string, value: string | Array<string>) => {
|
|
36
|
+
headers.set(name, value);
|
|
37
|
+
}),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
describe('createSessionIdCookieStorage', () => {
|
|
42
|
+
test('get returns null when there is no session-id cookie on a NextRequest', async () => {
|
|
43
|
+
const inner = createMockStorage() as unknown as NextServerStorage;
|
|
44
|
+
const storage = createSessionIdCookieStorage(inner);
|
|
45
|
+
|
|
46
|
+
await expect(storage.get('sty.session', new NextRequest('https://brandtegrity.io'))).resolves.toBeNull();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('get resolves the inner storage entry addressed by the session-id cookie on a NextRequest', async () => {
|
|
50
|
+
const inner = createMockStorage() as unknown as NextServerStorage;
|
|
51
|
+
await inner.set('session-id-1', 'serialized-data');
|
|
52
|
+
const storage = createSessionIdCookieStorage(inner);
|
|
53
|
+
const req = new NextRequest('https://brandtegrity.io');
|
|
54
|
+
req.cookies.set('sty.session', 'session-id-1');
|
|
55
|
+
|
|
56
|
+
await expect(storage.get('sty.session', req)).resolves.toBe('serialized-data');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('get resolves the inner storage entry addressed by the session-id cookie on a plain Request', async () => {
|
|
60
|
+
const inner = createMockStorage() as unknown as NextServerStorage;
|
|
61
|
+
await inner.set('session-id-2', 'serialized-data');
|
|
62
|
+
const storage = createSessionIdCookieStorage(inner);
|
|
63
|
+
const req = new Request('https://brandtegrity.io');
|
|
64
|
+
req.headers.set('cookie', 'sty.session=session-id-2');
|
|
65
|
+
|
|
66
|
+
await expect(storage.get('sty.session', req)).resolves.toBe('serialized-data');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test('get resolves the inner storage entry addressed by the session-id cookie on a Pages Router request', async () => {
|
|
70
|
+
const inner = createMockStorage() as unknown as NextServerStorage;
|
|
71
|
+
await inner.set('session-id-3', 'serialized-data');
|
|
72
|
+
const storage = createSessionIdCookieStorage(inner);
|
|
73
|
+
|
|
74
|
+
await expect(storage.get('sty.session', { headers: { cookie: 'sty.session=session-id-3' } } as never)).resolves.toBe('serialized-data');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test('get falls back to next/headers cookies() when no request is given', async () => {
|
|
78
|
+
const inner = createMockStorage() as unknown as NextServerStorage;
|
|
79
|
+
await inner.set('session-id-4', 'serialized-data');
|
|
80
|
+
const jar = createFakeCookieJar();
|
|
81
|
+
jar.set('sty.session', 'session-id-4');
|
|
82
|
+
vi.mocked(cookies).mockResolvedValue(jar as never);
|
|
83
|
+
const storage = createSessionIdCookieStorage(inner);
|
|
84
|
+
|
|
85
|
+
await expect(storage.get('sty.session')).resolves.toBe('serialized-data');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('get resolves null through the cookies() fallback when there is no session-id cookie', async () => {
|
|
89
|
+
const inner = createMockStorage() as unknown as NextServerStorage;
|
|
90
|
+
vi.mocked(cookies).mockResolvedValue(createFakeCookieJar() as never);
|
|
91
|
+
const storage = createSessionIdCookieStorage(inner);
|
|
92
|
+
|
|
93
|
+
await expect(storage.get('sty.session')).resolves.toBeNull();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test('set generates a new session-id and pushes it as an outgoing cookie when none exists yet', async () => {
|
|
97
|
+
const inner = createMockStorage() as unknown as NextServerStorage;
|
|
98
|
+
const storage = createSessionIdCookieStorage(inner);
|
|
99
|
+
const req = new NextRequest('https://brandtegrity.io');
|
|
100
|
+
|
|
101
|
+
await storage.set('sty.session', 'serialized-data', req);
|
|
102
|
+
|
|
103
|
+
expect(inner.set).toHaveBeenCalledWith(expect.any(String), 'serialized-data');
|
|
104
|
+
|
|
105
|
+
const response = flushSetCookies(req, new Response());
|
|
106
|
+
expect(response.headers.getSetCookie().some((cookie) => cookie.startsWith('sty.session='))).toBe(true);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('set reuses an existing session-id from the request without pushing a new cookie', async () => {
|
|
110
|
+
const inner = createMockStorage() as unknown as NextServerStorage;
|
|
111
|
+
const storage = createSessionIdCookieStorage(inner);
|
|
112
|
+
const req = new NextRequest('https://brandtegrity.io');
|
|
113
|
+
req.cookies.set('sty.session', 'existing-id');
|
|
114
|
+
|
|
115
|
+
await storage.set('sty.session', 'serialized-data', req);
|
|
116
|
+
|
|
117
|
+
expect(inner.set).toHaveBeenCalledWith('existing-id', 'serialized-data');
|
|
118
|
+
expect(flushSetCookies(req, new Response()).headers.getSetCookie()).toHaveLength(0);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test('set reuses an existing session-id found through the cookies() fallback with no request', async () => {
|
|
122
|
+
const inner = createMockStorage() as unknown as NextServerStorage;
|
|
123
|
+
const jar = createFakeCookieJar();
|
|
124
|
+
jar.set('sty.session', 'existing-id');
|
|
125
|
+
vi.mocked(cookies).mockResolvedValue(jar as never);
|
|
126
|
+
const storage = createSessionIdCookieStorage(inner);
|
|
127
|
+
|
|
128
|
+
await storage.set('sty.session', 'serialized-data');
|
|
129
|
+
|
|
130
|
+
expect(inner.set).toHaveBeenCalledWith('existing-id', 'serialized-data');
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
test('set throws when no request is given and no session-id cookie exists yet to attach the new one to', async () => {
|
|
134
|
+
const inner = createMockStorage() as unknown as NextServerStorage;
|
|
135
|
+
vi.mocked(cookies).mockResolvedValue(createFakeCookieJar() as never);
|
|
136
|
+
const storage = createSessionIdCookieStorage(inner);
|
|
137
|
+
|
|
138
|
+
await expect(storage.set('sty.session', 'serialized-data')).rejects.toThrow(InternalError);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
test('delete removes the inner storage entry and expires the session-id cookie', async () => {
|
|
142
|
+
const inner = createMockStorage() as unknown as NextServerStorage;
|
|
143
|
+
await inner.set('session-id-5', 'serialized-data');
|
|
144
|
+
const storage = createSessionIdCookieStorage(inner);
|
|
145
|
+
const req = new NextRequest('https://brandtegrity.io');
|
|
146
|
+
req.cookies.set('sty.session', 'session-id-5');
|
|
147
|
+
|
|
148
|
+
await storage.delete('sty.session', req);
|
|
149
|
+
|
|
150
|
+
expect(inner.delete).toHaveBeenCalledWith('session-id-5');
|
|
151
|
+
const setCookies = flushSetCookies(req, new Response()).headers.getSetCookie();
|
|
152
|
+
expect(setCookies.some((cookie) => cookie.startsWith('sty.session=') && cookie.includes('Expires=Thu, 01 Jan 1970'))).toBe(true);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
test('delete always throws when no request is given, since expiring the cookie requires a request-scoped event', async () => {
|
|
156
|
+
const inner = createMockStorage() as unknown as NextServerStorage;
|
|
157
|
+
vi.mocked(cookies).mockResolvedValue(createFakeCookieJar() as never);
|
|
158
|
+
const storage = createSessionIdCookieStorage(inner);
|
|
159
|
+
|
|
160
|
+
await expect(storage.delete('sty.session')).rejects.toThrow(InternalError);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
describe('createEncryptedCookieStorage', () => {
|
|
165
|
+
test('get resolves null when there is no cookie at all', async () => {
|
|
166
|
+
const storage = createEncryptedCookieStorage('secret');
|
|
167
|
+
|
|
168
|
+
await expect(storage.get('sty.session', new NextRequest('https://brandtegrity.io'))).resolves.toBeNull();
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
test('set/get round-trip a short value through an explicit NextRequest/NextResponse pair', async () => {
|
|
172
|
+
const storage = createEncryptedCookieStorage('secret');
|
|
173
|
+
const res = NextResponse.next();
|
|
174
|
+
|
|
175
|
+
await storage.set('sty.session', 'hello world', undefined, res);
|
|
176
|
+
|
|
177
|
+
const cookie = res.cookies.get('sty.session');
|
|
178
|
+
expect(cookie).toBeDefined();
|
|
179
|
+
|
|
180
|
+
const req = new NextRequest('https://brandtegrity.io');
|
|
181
|
+
req.cookies.set('sty.session', cookie!.value);
|
|
182
|
+
|
|
183
|
+
await expect(storage.get('sty.session', req)).resolves.toBe('hello world');
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
test('set applies the given cookie options on top of the secure defaults', async () => {
|
|
187
|
+
const storage = createEncryptedCookieStorage('secret');
|
|
188
|
+
const res = NextResponse.next();
|
|
189
|
+
|
|
190
|
+
await storage.set('sty.session', 'hello world', undefined, res, { maxAge: 60 });
|
|
191
|
+
|
|
192
|
+
const cookie = res.cookies.get('sty.session');
|
|
193
|
+
expect(cookie).toMatchObject({ httpOnly: true, secure: true, sameSite: 'lax', path: '/', maxAge: 60 });
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
test('delete expires the cookie on an explicit NextResponse', async () => {
|
|
197
|
+
const storage = createEncryptedCookieStorage('secret');
|
|
198
|
+
const res = NextResponse.next();
|
|
199
|
+
await storage.set('sty.session', 'hello world', undefined, res);
|
|
200
|
+
|
|
201
|
+
await storage.delete('sty.session', undefined, res);
|
|
202
|
+
|
|
203
|
+
expect(res.cookies.get('sty.session')?.value).toBe('');
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
test('set/get round-trip a short value through a plain Request and a Pages Router response', async () => {
|
|
207
|
+
const storage = createEncryptedCookieStorage('secret');
|
|
208
|
+
const res = createFakePagesResponse();
|
|
209
|
+
|
|
210
|
+
await storage.set('sty.session', 'hello world', undefined, res as never);
|
|
211
|
+
|
|
212
|
+
// NOTE: set() first deletes any existing cookie(s) as cleanup, leaving an empty-valued placeholder alongside the real, non-empty cookie.
|
|
213
|
+
const lastCall = (res.setHeader as Mock).mock.calls.at(-1) as [string, Array<string>];
|
|
214
|
+
const setCookieHeader = lastCall[1].find(
|
|
215
|
+
(cookie) => cookie.startsWith('sty.session=') && cookie.slice('sty.session='.length, cookie.indexOf(';')).length > 0,
|
|
216
|
+
)!;
|
|
217
|
+
const rawValue = setCookieHeader.slice('sty.session='.length, setCookieHeader.indexOf(';'));
|
|
218
|
+
|
|
219
|
+
const req = new Request('https://brandtegrity.io');
|
|
220
|
+
req.headers.set('cookie', `sty.session=${rawValue}`);
|
|
221
|
+
|
|
222
|
+
await expect(storage.get('sty.session', req)).resolves.toBe('hello world');
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
test('delete appends a cleared set-cookie header to a Pages Router response', async () => {
|
|
226
|
+
const storage = createEncryptedCookieStorage('secret');
|
|
227
|
+
const res = createFakePagesResponse();
|
|
228
|
+
|
|
229
|
+
await storage.delete('sty.session', undefined, res as never);
|
|
230
|
+
|
|
231
|
+
// NOTE: the plain-response branch builds the cookie via `buildCookieString`, whose `Max-Age` is only emitted when truthy - `maxAge: 0` is falsy,
|
|
232
|
+
// so unlike the NextResponse branch (which uses `res.cookies.delete()`), this leaves neither `Max-Age` nor `Expires` on the cleared cookie.
|
|
233
|
+
expect(res.setHeader).toHaveBeenCalledWith('set-cookie', ['sty.session=; HttpOnly; Secure; Path=/; SameSite=lax']);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
test('merges a new cookie alongside a pre-existing single set-cookie header string on a Pages Router response', async () => {
|
|
237
|
+
const storage = createEncryptedCookieStorage('secret');
|
|
238
|
+
const res = createFakePagesResponse();
|
|
239
|
+
res.setHeader('set-cookie', 'other=1; Path=/');
|
|
240
|
+
|
|
241
|
+
await storage.set('sty.session', 'hello world', undefined, res as never);
|
|
242
|
+
|
|
243
|
+
const lastCall = (res.setHeader as Mock).mock.calls.at(-1) as [string, Array<string>];
|
|
244
|
+
expect(lastCall[1]).toContain('other=1; Path=/');
|
|
245
|
+
expect(lastCall[1].some((cookie) => cookie.startsWith('sty.session=') && cookie.slice('sty.session='.length, cookie.indexOf(';')).length > 0)).toBe(true);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
test('merges an expiring cookie alongside a pre-existing single set-cookie header string on delete', async () => {
|
|
249
|
+
const storage = createEncryptedCookieStorage('secret');
|
|
250
|
+
const res = createFakePagesResponse();
|
|
251
|
+
res.setHeader('set-cookie', 'other=1; Path=/');
|
|
252
|
+
|
|
253
|
+
await storage.delete('sty.session', undefined, res as never);
|
|
254
|
+
|
|
255
|
+
expect((res.setHeader as Mock).mock.calls.at(-1)![1]).toEqual(['other=1; Path=/', 'sty.session=; HttpOnly; Secure; Path=/; SameSite=lax']);
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
test('set/delete branch on the response, not the request: given a request but no response, they still use the cookies() fallback', async () => {
|
|
259
|
+
const jar = createFakeCookieJar();
|
|
260
|
+
vi.mocked(cookies).mockResolvedValue(jar as never);
|
|
261
|
+
const storage = createEncryptedCookieStorage('secret');
|
|
262
|
+
|
|
263
|
+
await storage.set('sty.session', 'hello world', new NextRequest('https://brandtegrity.io'));
|
|
264
|
+
|
|
265
|
+
expect(jar.set).toHaveBeenCalled();
|
|
266
|
+
await expect(storage.get('sty.session')).resolves.toBe('hello world');
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
test('set/get/delete round-trip a value through the cookies() fallback when no request/response is given', async () => {
|
|
270
|
+
const jar = createFakeCookieJar();
|
|
271
|
+
vi.mocked(cookies).mockResolvedValue(jar as never);
|
|
272
|
+
const storage = createEncryptedCookieStorage('secret');
|
|
273
|
+
|
|
274
|
+
await storage.set('sty.session', 'hello world');
|
|
275
|
+
|
|
276
|
+
await expect(storage.get('sty.session')).resolves.toBe('hello world');
|
|
277
|
+
|
|
278
|
+
await storage.delete('sty.session');
|
|
279
|
+
|
|
280
|
+
await expect(storage.get('sty.session')).resolves.toBeNull();
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
test('set splits a large value into chunk cookies once it exceeds COOKIE_CHUNK_SIZE, and get reassembles them', async () => {
|
|
284
|
+
const jar = createFakeCookieJar();
|
|
285
|
+
vi.mocked(cookies).mockResolvedValue(jar as never);
|
|
286
|
+
const storage = createEncryptedCookieStorage('secret');
|
|
287
|
+
const largeValue = 'x'.repeat(5000);
|
|
288
|
+
|
|
289
|
+
await storage.set('sty.session', largeValue);
|
|
290
|
+
|
|
291
|
+
expect(jar.get('sty.session')).toBeUndefined();
|
|
292
|
+
expect(jar.get('sty.session.0')).toBeDefined();
|
|
293
|
+
expect(jar.get('sty.session.1')).toBeDefined();
|
|
294
|
+
|
|
295
|
+
await expect(storage.get('sty.session')).resolves.toBe(largeValue);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
test('delete removes every chunk cookie left over from a chunked value', async () => {
|
|
299
|
+
const jar = createFakeCookieJar();
|
|
300
|
+
vi.mocked(cookies).mockResolvedValue(jar as never);
|
|
301
|
+
const storage = createEncryptedCookieStorage('secret');
|
|
302
|
+
|
|
303
|
+
await storage.set('sty.session', 'x'.repeat(5000));
|
|
304
|
+
await storage.delete('sty.session');
|
|
305
|
+
|
|
306
|
+
expect(jar.get('sty.session.0')).toBeUndefined();
|
|
307
|
+
expect(jar.get('sty.session.1')).toBeUndefined();
|
|
308
|
+
await expect(storage.get('sty.session')).resolves.toBeNull();
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
test('set splits a large value into chunk cookies on an explicit NextResponse, and get reassembles them from a NextRequest', async () => {
|
|
312
|
+
const storage = createEncryptedCookieStorage('secret');
|
|
313
|
+
const res = NextResponse.next();
|
|
314
|
+
const largeValue = 'y'.repeat(5000);
|
|
315
|
+
|
|
316
|
+
await storage.set('sty.session', largeValue, undefined, res);
|
|
317
|
+
|
|
318
|
+
// NOTE: set() first deletes the plain (non-chunked) key as cleanup; NextResponse.cookies.delete() leaves an emptied entry rather than removing it.
|
|
319
|
+
expect(res.cookies.get('sty.session')?.value).toBe('');
|
|
320
|
+
const chunk0 = res.cookies.get('sty.session.0');
|
|
321
|
+
const chunk1 = res.cookies.get('sty.session.1');
|
|
322
|
+
expect(chunk0).toBeDefined();
|
|
323
|
+
expect(chunk1).toBeDefined();
|
|
324
|
+
|
|
325
|
+
const req = new NextRequest('https://brandtegrity.io');
|
|
326
|
+
req.cookies.set('sty.session.0', chunk0!.value);
|
|
327
|
+
req.cookies.set('sty.session.1', chunk1!.value);
|
|
328
|
+
|
|
329
|
+
await expect(storage.get('sty.session', req)).resolves.toBe(largeValue);
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
test('delete removes every chunk cookie on an explicit NextResponse', async () => {
|
|
333
|
+
const storage = createEncryptedCookieStorage('secret');
|
|
334
|
+
const res = NextResponse.next();
|
|
335
|
+
await storage.set('sty.session', 'z'.repeat(5000), undefined, res);
|
|
336
|
+
|
|
337
|
+
await storage.delete('sty.session', undefined, res);
|
|
338
|
+
|
|
339
|
+
expect(res.cookies.get('sty.session.0')?.value).toBe('');
|
|
340
|
+
expect(res.cookies.get('sty.session.1')?.value).toBe('');
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
test('decrypted cookie value matches encryptString/decryptString used directly with the same secret', async () => {
|
|
344
|
+
const secret = 'shared-secret';
|
|
345
|
+
const storage = createEncryptedCookieStorage(secret);
|
|
346
|
+
const res = NextResponse.next();
|
|
347
|
+
|
|
348
|
+
await storage.set('sty.session', 'hello world', undefined, res);
|
|
349
|
+
|
|
350
|
+
const cookie = res.cookies.get('sty.session')!;
|
|
351
|
+
await expect(decryptString(cookie.value, secret, 'strivacity-session-v1')).resolves.toBe('hello world');
|
|
352
|
+
});
|
|
353
|
+
});
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { test, describe, expect } from 'vitest';
|
|
2
|
+
import { NextRequest } from 'next/server';
|
|
3
|
+
import { collectFromNextUrl, toNextRequest } from '../../../src/server/utils';
|
|
4
|
+
|
|
5
|
+
describe('collectFromNextUrl', () => {
|
|
6
|
+
test('returns undefined when no input is given', () => {
|
|
7
|
+
expect(collectFromNextUrl()).toBeUndefined();
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test('returns undefined for a Pages Router request with no locale signal', () => {
|
|
11
|
+
expect(collectFromNextUrl({ headers: {}, cookies: {} } as never)).toBeUndefined();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test('collects the basePath from a NextRequest whose URL is inside it', () => {
|
|
15
|
+
const req = new NextRequest('https://brandtegrity.io/app/foo', { nextConfig: { basePath: '/app' } });
|
|
16
|
+
|
|
17
|
+
// NextURL always reports `locale` as an empty string when no i18n config is set, so the (falsy) i18n block is still collected alongside basePath.
|
|
18
|
+
expect(collectFromNextUrl(req)).toEqual({ basePath: '/app', i18n: { locales: [], defaultLocale: '' } });
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('collects the locale as i18n config from a NextRequest', () => {
|
|
22
|
+
const req = new NextRequest('https://brandtegrity.io/foo', { nextConfig: { i18n: { locales: ['en', 'hu'], defaultLocale: 'en' } } });
|
|
23
|
+
|
|
24
|
+
expect(collectFromNextUrl(req)).toEqual({ i18n: { locales: ['en'], defaultLocale: 'en' } });
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test('collects trailingSlash from a nextUrl-shaped input', () => {
|
|
28
|
+
expect(collectFromNextUrl({ nextUrl: { trailingSlash: true } } as never)).toEqual({ trailingSlash: true });
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('merges basePath, i18n and trailingSlash when all are present on the nextUrl', () => {
|
|
32
|
+
const input = { nextUrl: { basePath: '/app', locale: 'hu-HU', defaultLocale: 'en-US', trailingSlash: false } };
|
|
33
|
+
|
|
34
|
+
expect(collectFromNextUrl(input as never)).toEqual({
|
|
35
|
+
basePath: '/app',
|
|
36
|
+
i18n: { locales: ['hu-HU'], defaultLocale: 'en-US' },
|
|
37
|
+
trailingSlash: false,
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('collects the locale from the accept-language header on a Pages Router request', () => {
|
|
42
|
+
const input = { headers: { 'accept-language': 'hu-HU' }, cookies: {} };
|
|
43
|
+
|
|
44
|
+
expect(collectFromNextUrl(input as never)).toEqual({ i18n: { locales: ['hu-HU'], defaultLocale: '' } });
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('prefers the NEXT_LOCALE cookie over the accept-language header on a Pages Router request', () => {
|
|
48
|
+
const input = { headers: { 'accept-language': 'hu-HU' }, cookies: { NEXT_LOCALE: 'de-DE' } };
|
|
49
|
+
|
|
50
|
+
expect(collectFromNextUrl(input as never)).toEqual({ i18n: { locales: ['de-DE'], defaultLocale: '' } });
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('returns undefined when reading the input throws', () => {
|
|
54
|
+
const input = new Proxy(
|
|
55
|
+
{},
|
|
56
|
+
{
|
|
57
|
+
get() {
|
|
58
|
+
throw new Error('boom');
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
expect(collectFromNextUrl(input as never)).toBeUndefined();
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe('toNextRequest', () => {
|
|
68
|
+
test('returns a NextRequest unchanged', () => {
|
|
69
|
+
const req = new NextRequest('https://brandtegrity.io/foo');
|
|
70
|
+
|
|
71
|
+
expect(toNextRequest(req)).toBe(req);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test('builds a NextRequest from a plain Request, preserving method, url and headers', () => {
|
|
75
|
+
const req = new Request('https://brandtegrity.io/foo', { method: 'POST', headers: { 'x-custom': 'value' } });
|
|
76
|
+
|
|
77
|
+
const result = toNextRequest(req);
|
|
78
|
+
|
|
79
|
+
expect(result).toBeInstanceOf(NextRequest);
|
|
80
|
+
expect(result.method).toBe('POST');
|
|
81
|
+
expect(result.url).toBe('https://brandtegrity.io/foo');
|
|
82
|
+
expect(result.headers.get('x-custom')).toBe('value');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('preserves the request body', async () => {
|
|
86
|
+
const req = new Request('https://brandtegrity.io/foo', { method: 'POST', body: 'hello world' });
|
|
87
|
+
|
|
88
|
+
const result = toNextRequest(req);
|
|
89
|
+
|
|
90
|
+
await expect(result.text()).resolves.toBe('hello world');
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test('preserves a given abort signal', () => {
|
|
94
|
+
const controller = new AbortController();
|
|
95
|
+
const req = new Request('https://brandtegrity.io/foo', { signal: controller.signal });
|
|
96
|
+
|
|
97
|
+
const result = toNextRequest(req);
|
|
98
|
+
|
|
99
|
+
expect(result.signal).toBe(controller.signal);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test('collects and applies Next.js config found on the input', () => {
|
|
103
|
+
const req = new Request('https://brandtegrity.io/app/foo') as Request & { nextUrl?: { basePath?: string } };
|
|
104
|
+
req.nextUrl = { basePath: '/app' };
|
|
105
|
+
|
|
106
|
+
const result = toNextRequest(req);
|
|
107
|
+
|
|
108
|
+
expect(result.nextUrl.basePath).toBe('/app');
|
|
109
|
+
});
|
|
110
|
+
});
|
package/dist/AuthProvider.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("react/jsx-runtime"),r=require("react"),S=require("@strivacity/sdk-core"),m=require("./composables.cjs");let e;const A=({options:a,children:T=void 0})=>{const[i,h]=r.useState(!0),[o,b]=r.useState(!1),[c,v]=r.useState(null),[u,f]=r.useState(null),[l,E]=r.useState(null),[d,g]=r.useState(!0),[k,p]=r.useState(null),n=r.useRef([]),t=async()=>{b(await e.isAuthenticated),v(e.idTokenClaims||null),f(e.accessToken||null),E(e.refreshToken||null),g(e.accessTokenExpired),p(e.accessTokenExpirationDate||null),i&&h(!1)};r.useEffect(()=>(e||(e=S.initFlow(a),n.current.push(e.subscribeToEvent("init",t)),n.current.push(e.subscribeToEvent("loggedIn",t)),n.current.push(e.subscribeToEvent("sessionLoaded",t)),n.current.push(e.subscribeToEvent("tokenRefreshed",t)),n.current.push(e.subscribeToEvent("tokenRefreshFailed",t)),n.current.push(e.subscribeToEvent("logoutInitiated",t)),n.current.push(e.subscribeToEvent("tokenRevoked",t)),n.current.push(e.subscribeToEvent("tokenRevokeFailed",t))),()=>{n.current.forEach(s=>s.dispose()),n.current=[]}),[a]);const w=r.useMemo(()=>({sdk:e,loading:i,options:a,isAuthenticated:o,idTokenClaims:c,accessToken:u,refreshToken:l,accessTokenExpired:d,accessTokenExpirationDate:k,login:async s=>{if(e.options.mode==="native")return e.login(s);await e.login(s),await t()},register:async s=>{if(e.options.mode==="native")return e.register(s);await e.register(s),await t()},refresh:async()=>{await e.refresh(),await t()},entry:async s=>await e.entry(s),revoke:async()=>{await e.revoke(),await t()},logout:async s=>{await e.logout(s),await t()},handleCallback:async s=>{await e.handleCallback(s),await t()}}),[e,i,a,c,u,l,d,k,o]);return y.jsx(m.STRIVACITY_SDK.Provider,{value:w,children:T})};exports.StyAuthProvider=A;
|
|
2
|
-
//# sourceMappingURL=AuthProvider.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AuthProvider.cjs","sources":["../src/AuthProvider.tsx"],"sourcesContent":["import { type FC } from 'react';\nimport { useMemo, useState, useRef, useEffect } from 'react';\nimport { initFlow } from '@strivacity/sdk-core';\nimport type { SDKOptions, IdTokenClaims } from '@strivacity/sdk-core';\nimport type { PopupFlow } from '@strivacity/sdk-core/flows/PopupFlow';\nimport type { RedirectFlow } from '@strivacity/sdk-core/flows/RedirectFlow';\nimport type { NativeFlow } from '@strivacity/sdk-core/flows/NativeFlow';\nimport type { PopupContext, RedirectContext, NativeContext, Children } from './types';\nimport { STRIVACITY_SDK } from './composables';\n\nlet sdk: RedirectFlow | PopupFlow | NativeFlow;\n\nexport const StyAuthProvider: FC<{ options: SDKOptions; children?: Children }> = ({\n\toptions,\n\tchildren = undefined,\n}: {\n\toptions: SDKOptions;\n\tchildren?: Children;\n}) => {\n\tconst [loading, setLoading] = useState<boolean>(true);\n\tconst [isAuthenticated, setIsAuthenticated] = useState<boolean>(false);\n\tconst [idTokenClaims, setIdTokenClaims] = useState<IdTokenClaims | null>(null);\n\tconst [accessToken, setAccessToken] = useState<string | null>(null);\n\tconst [refreshToken, setRefreshToken] = useState<string | null>(null);\n\tconst [accessTokenExpired, setAccessTokenExpired] = useState<boolean>(true);\n\tconst [accessTokenExpirationDate, setAccessTokenExpirationDate] = useState<number | null>(null);\n\tconst events = useRef<{ dispose: () => void }[]>([]);\n\n\tconst updateSession = async () => {\n\t\tsetIsAuthenticated(await sdk.isAuthenticated);\n\t\tsetIdTokenClaims(sdk.idTokenClaims || null);\n\t\tsetAccessToken(sdk.accessToken || null);\n\t\tsetRefreshToken(sdk.refreshToken || null);\n\t\tsetAccessTokenExpired(sdk.accessTokenExpired);\n\t\tsetAccessTokenExpirationDate(sdk.accessTokenExpirationDate || null);\n\n\t\tif (loading) {\n\t\t\tsetLoading(false);\n\t\t}\n\t};\n\n\tuseEffect(() => {\n\t\tif (!sdk) {\n\t\t\tsdk = initFlow(options);\n\n\t\t\tevents.current.push(sdk.subscribeToEvent('init', updateSession));\n\t\t\tevents.current.push(sdk.subscribeToEvent('loggedIn', updateSession));\n\t\t\tevents.current.push(sdk.subscribeToEvent('sessionLoaded', updateSession));\n\t\t\tevents.current.push(sdk.subscribeToEvent('tokenRefreshed', updateSession));\n\t\t\tevents.current.push(sdk.subscribeToEvent('tokenRefreshFailed', updateSession));\n\t\t\tevents.current.push(sdk.subscribeToEvent('logoutInitiated', updateSession));\n\t\t\tevents.current.push(sdk.subscribeToEvent('tokenRevoked', updateSession));\n\t\t\tevents.current.push(sdk.subscribeToEvent('tokenRevokeFailed', updateSession));\n\t\t}\n\n\t\treturn () => {\n\t\t\tevents.current.forEach((event) => event.dispose());\n\t\t\tevents.current = [];\n\t\t};\n\t}, [options]);\n\n\t// @ts-expect-error: Ignore SDK type mismatch for initFlow\n\tconst value = useMemo<PopupContext | RedirectContext | NativeContext>(() => {\n\t\treturn {\n\t\t\tsdk,\n\t\t\tloading,\n\t\t\toptions,\n\t\t\tisAuthenticated,\n\t\t\tidTokenClaims,\n\t\t\taccessToken,\n\t\t\trefreshToken,\n\t\t\taccessTokenExpired,\n\t\t\taccessTokenExpirationDate,\n\n\t\t\tlogin: async (options?: Parameters<PopupFlow['login'] | RedirectFlow['login'] | NativeFlow['login']>[0]) => {\n\t\t\t\tif (sdk.options.mode === 'native') {\n\t\t\t\t\treturn sdk.login(options);\n\t\t\t\t}\n\n\t\t\t\tawait sdk.login(options);\n\t\t\t\tawait updateSession();\n\t\t\t},\n\t\t\tregister: async (options?: Parameters<PopupFlow['register'] | RedirectFlow['register'] | NativeFlow['register']>[0]) => {\n\t\t\t\tif (sdk.options.mode === 'native') {\n\t\t\t\t\treturn sdk.register(options);\n\t\t\t\t}\n\n\t\t\t\tawait sdk.register(options);\n\t\t\t\tawait updateSession();\n\t\t\t},\n\t\t\trefresh: async () => {\n\t\t\t\tawait sdk.refresh();\n\t\t\t\tawait updateSession();\n\t\t\t},\n\t\t\tentry: async (url?: string) => {\n\t\t\t\treturn await sdk.entry(url);\n\t\t\t},\n\t\t\trevoke: async () => {\n\t\t\t\tawait sdk.revoke();\n\t\t\t\tawait updateSession();\n\t\t\t},\n\t\t\tlogout: async (options?: Parameters<PopupFlow['logout'] | RedirectFlow['logout']>[0]) => {\n\t\t\t\tawait sdk.logout(options);\n\t\t\t\tawait updateSession();\n\t\t\t},\n\t\t\thandleCallback: async (url?: Parameters<PopupFlow['handleCallback'] | RedirectFlow['handleCallback'] | NativeFlow['handleCallback']>[0]) => {\n\t\t\t\tawait sdk.handleCallback(url);\n\t\t\t\tawait updateSession();\n\t\t\t},\n\t\t};\n\t}, [sdk, loading, options, idTokenClaims, accessToken, refreshToken, accessTokenExpired, accessTokenExpirationDate, isAuthenticated]);\n\n\treturn <STRIVACITY_SDK.Provider value={value}>{children}</STRIVACITY_SDK.Provider>;\n};\n"],"names":["sdk","StyAuthProvider","options","children","loading","setLoading","useState","isAuthenticated","setIsAuthenticated","idTokenClaims","setIdTokenClaims","accessToken","setAccessToken","refreshToken","setRefreshToken","accessTokenExpired","setAccessTokenExpired","accessTokenExpirationDate","setAccessTokenExpirationDate","events","useRef","updateSession","useEffect","initFlow","event","value","useMemo","url","jsx","STRIVACITY_SDK"],"mappings":"yMAUA,IAAIA,EAEG,MAAMC,EAAoE,CAAC,CACjF,QAAAC,EACA,SAAAC,EAAW,MACZ,IAGM,CACL,KAAM,CAACC,EAASC,CAAU,EAAIC,EAAAA,SAAkB,EAAI,EAC9C,CAACC,EAAiBC,CAAkB,EAAIF,EAAAA,SAAkB,EAAK,EAC/D,CAACG,EAAeC,CAAgB,EAAIJ,EAAAA,SAA+B,IAAI,EACvE,CAACK,EAAaC,CAAc,EAAIN,EAAAA,SAAwB,IAAI,EAC5D,CAACO,EAAcC,CAAe,EAAIR,EAAAA,SAAwB,IAAI,EAC9D,CAACS,EAAoBC,CAAqB,EAAIV,EAAAA,SAAkB,EAAI,EACpE,CAACW,EAA2BC,CAA4B,EAAIZ,EAAAA,SAAwB,IAAI,EACxFa,EAASC,EAAAA,OAAkC,EAAE,EAE7CC,EAAgB,SAAY,CACjCb,EAAmB,MAAMR,EAAI,eAAe,EAC5CU,EAAiBV,EAAI,eAAiB,IAAI,EAC1CY,EAAeZ,EAAI,aAAe,IAAI,EACtCc,EAAgBd,EAAI,cAAgB,IAAI,EACxCgB,EAAsBhB,EAAI,kBAAkB,EAC5CkB,EAA6BlB,EAAI,2BAA6B,IAAI,EAE9DI,GACHC,EAAW,EAAK,CAElB,EAEAiB,EAAAA,UAAU,KACJtB,IACJA,EAAMuB,EAAAA,SAASrB,CAAO,EAEtBiB,EAAO,QAAQ,KAAKnB,EAAI,iBAAiB,OAAQqB,CAAa,CAAC,EAC/DF,EAAO,QAAQ,KAAKnB,EAAI,iBAAiB,WAAYqB,CAAa,CAAC,EACnEF,EAAO,QAAQ,KAAKnB,EAAI,iBAAiB,gBAAiBqB,CAAa,CAAC,EACxEF,EAAO,QAAQ,KAAKnB,EAAI,iBAAiB,iBAAkBqB,CAAa,CAAC,EACzEF,EAAO,QAAQ,KAAKnB,EAAI,iBAAiB,qBAAsBqB,CAAa,CAAC,EAC7EF,EAAO,QAAQ,KAAKnB,EAAI,iBAAiB,kBAAmBqB,CAAa,CAAC,EAC1EF,EAAO,QAAQ,KAAKnB,EAAI,iBAAiB,eAAgBqB,CAAa,CAAC,EACvEF,EAAO,QAAQ,KAAKnB,EAAI,iBAAiB,oBAAqBqB,CAAa,CAAC,GAGtE,IAAM,CACZF,EAAO,QAAQ,QAASK,GAAUA,EAAM,SAAS,EACjDL,EAAO,QAAU,CAAA,CAClB,GACE,CAACjB,CAAO,CAAC,EAGZ,MAAMuB,EAAQC,EAAAA,QAAwD,KAC9D,CACN,IAAA1B,EACA,QAAAI,EACA,QAAAF,EACA,gBAAAK,EACA,cAAAE,EACA,YAAAE,EACA,aAAAE,EACA,mBAAAE,EACA,0BAAAE,EAEA,MAAO,MAAOf,GAA8F,CAC3G,GAAIF,EAAI,QAAQ,OAAS,SACxB,OAAOA,EAAI,MAAME,CAAO,EAGzB,MAAMF,EAAI,MAAME,CAAO,EACvB,MAAMmB,EAAA,CACP,EACA,SAAU,MAAOnB,GAAuG,CACvH,GAAIF,EAAI,QAAQ,OAAS,SACxB,OAAOA,EAAI,SAASE,CAAO,EAG5B,MAAMF,EAAI,SAASE,CAAO,EAC1B,MAAMmB,EAAA,CACP,EACA,QAAS,SAAY,CACpB,MAAMrB,EAAI,QAAA,EACV,MAAMqB,EAAA,CACP,EACA,MAAO,MAAOM,GACN,MAAM3B,EAAI,MAAM2B,CAAG,EAE3B,OAAQ,SAAY,CACnB,MAAM3B,EAAI,OAAA,EACV,MAAMqB,EAAA,CACP,EACA,OAAQ,MAAOnB,GAA0E,CACxF,MAAMF,EAAI,OAAOE,CAAO,EACxB,MAAMmB,EAAA,CACP,EACA,eAAgB,MAAOM,GAAqH,CAC3I,MAAM3B,EAAI,eAAe2B,CAAG,EAC5B,MAAMN,EAAA,CACP,CAAA,GAEC,CAACrB,EAAKI,EAASF,EAASO,EAAeE,EAAaE,EAAcE,EAAoBE,EAA2BV,CAAe,CAAC,EAEpI,OAAOqB,EAAAA,IAACC,EAAAA,eAAe,SAAf,CAAwB,MAAAJ,EAAe,SAAAtB,CAAA,CAAS,CACzD"}
|
package/dist/AuthProvider.d.ts
DELETED
package/dist/AuthProvider.mjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{jsx as g}from"react/jsx-runtime";import{useState as r,useRef as y,useEffect as x,useMemo as A}from"react";import{initFlow as R}from"@strivacity/sdk-core";import{STRIVACITY_SDK as C}from"./composables.mjs";let e;const L=({options:a,children:T=void 0})=>{const[o,h]=r(!0),[i,f]=r(!1),[c,v]=r(null),[u,b]=r(null),[l,p]=r(null),[d,E]=r(!0),[k,w]=r(null),n=y([]),t=async()=>{f(await e.isAuthenticated),v(e.idTokenClaims||null),b(e.accessToken||null),p(e.refreshToken||null),E(e.accessTokenExpired),w(e.accessTokenExpirationDate||null),o&&h(!1)};x(()=>(e||(e=R(a),n.current.push(e.subscribeToEvent("init",t)),n.current.push(e.subscribeToEvent("loggedIn",t)),n.current.push(e.subscribeToEvent("sessionLoaded",t)),n.current.push(e.subscribeToEvent("tokenRefreshed",t)),n.current.push(e.subscribeToEvent("tokenRefreshFailed",t)),n.current.push(e.subscribeToEvent("logoutInitiated",t)),n.current.push(e.subscribeToEvent("tokenRevoked",t)),n.current.push(e.subscribeToEvent("tokenRevokeFailed",t))),()=>{n.current.forEach(s=>s.dispose()),n.current=[]}),[a]);const m=A(()=>({sdk:e,loading:o,options:a,isAuthenticated:i,idTokenClaims:c,accessToken:u,refreshToken:l,accessTokenExpired:d,accessTokenExpirationDate:k,login:async s=>{if(e.options.mode==="native")return e.login(s);await e.login(s),await t()},register:async s=>{if(e.options.mode==="native")return e.register(s);await e.register(s),await t()},refresh:async()=>{await e.refresh(),await t()},entry:async s=>await e.entry(s),revoke:async()=>{await e.revoke(),await t()},logout:async s=>{await e.logout(s),await t()},handleCallback:async s=>{await e.handleCallback(s),await t()}}),[e,o,a,c,u,l,d,k,i]);return g(C.Provider,{value:m,children:T})};export{L as StyAuthProvider};
|
|
2
|
-
//# sourceMappingURL=AuthProvider.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AuthProvider.mjs","sources":["../src/AuthProvider.tsx"],"sourcesContent":["import { type FC } from 'react';\nimport { useMemo, useState, useRef, useEffect } from 'react';\nimport { initFlow } from '@strivacity/sdk-core';\nimport type { SDKOptions, IdTokenClaims } from '@strivacity/sdk-core';\nimport type { PopupFlow } from '@strivacity/sdk-core/flows/PopupFlow';\nimport type { RedirectFlow } from '@strivacity/sdk-core/flows/RedirectFlow';\nimport type { NativeFlow } from '@strivacity/sdk-core/flows/NativeFlow';\nimport type { PopupContext, RedirectContext, NativeContext, Children } from './types';\nimport { STRIVACITY_SDK } from './composables';\n\nlet sdk: RedirectFlow | PopupFlow | NativeFlow;\n\nexport const StyAuthProvider: FC<{ options: SDKOptions; children?: Children }> = ({\n\toptions,\n\tchildren = undefined,\n}: {\n\toptions: SDKOptions;\n\tchildren?: Children;\n}) => {\n\tconst [loading, setLoading] = useState<boolean>(true);\n\tconst [isAuthenticated, setIsAuthenticated] = useState<boolean>(false);\n\tconst [idTokenClaims, setIdTokenClaims] = useState<IdTokenClaims | null>(null);\n\tconst [accessToken, setAccessToken] = useState<string | null>(null);\n\tconst [refreshToken, setRefreshToken] = useState<string | null>(null);\n\tconst [accessTokenExpired, setAccessTokenExpired] = useState<boolean>(true);\n\tconst [accessTokenExpirationDate, setAccessTokenExpirationDate] = useState<number | null>(null);\n\tconst events = useRef<{ dispose: () => void }[]>([]);\n\n\tconst updateSession = async () => {\n\t\tsetIsAuthenticated(await sdk.isAuthenticated);\n\t\tsetIdTokenClaims(sdk.idTokenClaims || null);\n\t\tsetAccessToken(sdk.accessToken || null);\n\t\tsetRefreshToken(sdk.refreshToken || null);\n\t\tsetAccessTokenExpired(sdk.accessTokenExpired);\n\t\tsetAccessTokenExpirationDate(sdk.accessTokenExpirationDate || null);\n\n\t\tif (loading) {\n\t\t\tsetLoading(false);\n\t\t}\n\t};\n\n\tuseEffect(() => {\n\t\tif (!sdk) {\n\t\t\tsdk = initFlow(options);\n\n\t\t\tevents.current.push(sdk.subscribeToEvent('init', updateSession));\n\t\t\tevents.current.push(sdk.subscribeToEvent('loggedIn', updateSession));\n\t\t\tevents.current.push(sdk.subscribeToEvent('sessionLoaded', updateSession));\n\t\t\tevents.current.push(sdk.subscribeToEvent('tokenRefreshed', updateSession));\n\t\t\tevents.current.push(sdk.subscribeToEvent('tokenRefreshFailed', updateSession));\n\t\t\tevents.current.push(sdk.subscribeToEvent('logoutInitiated', updateSession));\n\t\t\tevents.current.push(sdk.subscribeToEvent('tokenRevoked', updateSession));\n\t\t\tevents.current.push(sdk.subscribeToEvent('tokenRevokeFailed', updateSession));\n\t\t}\n\n\t\treturn () => {\n\t\t\tevents.current.forEach((event) => event.dispose());\n\t\t\tevents.current = [];\n\t\t};\n\t}, [options]);\n\n\t// @ts-expect-error: Ignore SDK type mismatch for initFlow\n\tconst value = useMemo<PopupContext | RedirectContext | NativeContext>(() => {\n\t\treturn {\n\t\t\tsdk,\n\t\t\tloading,\n\t\t\toptions,\n\t\t\tisAuthenticated,\n\t\t\tidTokenClaims,\n\t\t\taccessToken,\n\t\t\trefreshToken,\n\t\t\taccessTokenExpired,\n\t\t\taccessTokenExpirationDate,\n\n\t\t\tlogin: async (options?: Parameters<PopupFlow['login'] | RedirectFlow['login'] | NativeFlow['login']>[0]) => {\n\t\t\t\tif (sdk.options.mode === 'native') {\n\t\t\t\t\treturn sdk.login(options);\n\t\t\t\t}\n\n\t\t\t\tawait sdk.login(options);\n\t\t\t\tawait updateSession();\n\t\t\t},\n\t\t\tregister: async (options?: Parameters<PopupFlow['register'] | RedirectFlow['register'] | NativeFlow['register']>[0]) => {\n\t\t\t\tif (sdk.options.mode === 'native') {\n\t\t\t\t\treturn sdk.register(options);\n\t\t\t\t}\n\n\t\t\t\tawait sdk.register(options);\n\t\t\t\tawait updateSession();\n\t\t\t},\n\t\t\trefresh: async () => {\n\t\t\t\tawait sdk.refresh();\n\t\t\t\tawait updateSession();\n\t\t\t},\n\t\t\tentry: async (url?: string) => {\n\t\t\t\treturn await sdk.entry(url);\n\t\t\t},\n\t\t\trevoke: async () => {\n\t\t\t\tawait sdk.revoke();\n\t\t\t\tawait updateSession();\n\t\t\t},\n\t\t\tlogout: async (options?: Parameters<PopupFlow['logout'] | RedirectFlow['logout']>[0]) => {\n\t\t\t\tawait sdk.logout(options);\n\t\t\t\tawait updateSession();\n\t\t\t},\n\t\t\thandleCallback: async (url?: Parameters<PopupFlow['handleCallback'] | RedirectFlow['handleCallback'] | NativeFlow['handleCallback']>[0]) => {\n\t\t\t\tawait sdk.handleCallback(url);\n\t\t\t\tawait updateSession();\n\t\t\t},\n\t\t};\n\t}, [sdk, loading, options, idTokenClaims, accessToken, refreshToken, accessTokenExpired, accessTokenExpirationDate, isAuthenticated]);\n\n\treturn <STRIVACITY_SDK.Provider value={value}>{children}</STRIVACITY_SDK.Provider>;\n};\n"],"names":["sdk","StyAuthProvider","options","children","loading","setLoading","useState","isAuthenticated","setIsAuthenticated","idTokenClaims","setIdTokenClaims","accessToken","setAccessToken","refreshToken","setRefreshToken","accessTokenExpired","setAccessTokenExpired","accessTokenExpirationDate","setAccessTokenExpirationDate","events","useRef","updateSession","useEffect","initFlow","event","value","useMemo","url","jsx","STRIVACITY_SDK"],"mappings":"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"}
|
package/dist/LoginRenderer.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const g=require("react/jsx-runtime"),r=require("react"),x=require("@strivacity/sdk-core"),V=require("@strivacity/sdk-core/utils/object"),W=require("./composables.cjs"),z=r.createContext(null),j={},T=({items:U,widgets:b,state:d,triggerFallback:f})=>g.jsx(g.Fragment,{children:U.map((l,p)=>{if(l.type==="widget"){const a=d.forms?.find(m=>m.id===l.formId),c=a?.widgets.find(m=>m.id===l.widgetId);if(!a||!c)return f(void 0,`Unable to find form or widget for item: formId=${l.formId}, widgetId=${l.widgetId}`),null;const w=b[c.type];return w?g.jsx(w,{formId:a.id,config:c},`${a.id}.${c.id}`):(f(void 0,`No component found for widget type ${c.type}`),null)}else if(l.type==="vertical"||l.type==="horizontal"){const a=b.layout;return a?g.jsx(a,{formId:l.items[0].formId,type:l.type,children:g.jsx(T,{items:l.items,widgets:b,state:d,triggerFallback:f})},p):(f(void 0,"No layout component provided"),null)}else return f(void 0,"Unknown item type in layout"),null})}),B=U=>{const{params:b,widgets:d,sessionId:f,language:l,onLogin:p,onFallback:a,onClose:c,onError:w,onGlobalMessage:m,onBlockReady:k,onLanguageChange:$}={params:{},widgets:{},sessionId:null,language:null,...U},{sdk:u}=W.useStrivacity(),C=r.useRef(null),[N,v]=r.useState(!1),[E,S]=r.useState({}),[q,h]=r.useState({}),[e,F]=r.useState({}),R=r.useCallback((t,n)=>{const o=t||e.hostedUrl;if(u.logging?.warn(n?`Triggering fallback due to: ${n}`:"Triggering fallback"),!o){const s=new Error("No hosted URL provided");throw u.logging?.error("Fallback error",s),s}a?.(new x.FallbackError(new URL(o)))},[e,a]),M=r.useCallback(()=>{c?.()},[c]),O=r.useCallback((t,n,o)=>{j[t]={...j[t],[n]:o===""?null:o},S(s=>({...s,[t]:{...s[t]||{},[n]:o===""?null:o}}))},[]),I=r.useCallback((t,n,o)=>{h(s=>({...s,[t]:{...s[t]||{},[n]:o}}))},[]),A=r.useCallback(async t=>{try{v(!0);const n=await C.current?.submitForm(t,V.unflattenObject(j[t]));if(await u.isAuthenticated)p?.(u.idTokenClaims);else{const o=structuredClone(e),s={hostedUrl:n?.hostedUrl??e.hostedUrl,finalizeUrl:n?.finalizeUrl??e.finalizeUrl,screen:n?.screen??e.screen,forms:n?.forms??e.forms,layout:n?.layout??e.layout,messages:n?.messages??{},branding:n?.branding??e.branding};if(s.screen!==e.screen){const i={},y={};for(const L of s.forms??[])i[L.id]={},y[L.id]={};S(i),h(y)}Object.keys(s.messages??{}).forEach(i=>{i==="global"?m?.(s.messages?.global?.text??""):h(y=>({...y,[i]:s.messages[i]}))}),F(s),v(!1),setTimeout(()=>{k?.({previousState:o,state:structuredClone(s)})},1)}}catch(n){n instanceof x.FallbackError?a?.(n):w?.(n)}},[u,b,E,e,p,a,c,w,m,k]),P={loading:N,forms:E,messages:q,state:e,submitForm:A,triggerFallback:R,triggerClose:M,setFormValue:O,setMessage:I};return r.useEffect(()=>{C.current=u.login(b),(async()=>{try{const t=await C.current?.startSession(f,l),n=structuredClone(e),o={hostedUrl:t?.hostedUrl??e.hostedUrl,finalizeUrl:t?.finalizeUrl??e.finalizeUrl,screen:t?.screen??e.screen,forms:t?.forms??e.forms,layout:t?.layout??e.layout,messages:t?.messages??{},branding:t?.branding??e.branding};if($?.(C.current?.language??null),await u.isAuthenticated)p?.(u.idTokenClaims);else{if(o.screen!==e.screen){const s={},i={};for(const y of o.forms??[])s[y.id]={},i[y.id]={};S(s),h(i)}else u.logging?.info(`Updating screen: ${o.screen}`);Object.keys(o.messages??{}).forEach(s=>{s==="global"?m?.(o.messages?.global?.text??""):h(i=>({...i,[s]:o.messages[s]}))}),F(o),setTimeout(()=>{k?.({previousState:n,state:structuredClone(o)})},1)}}catch(t){t instanceof x.FallbackError?a?.(t):w?.(t)}})()},[]),g.jsx(z.Provider,{value:P,children:g.jsx("div",{className:"login-renderer",children:e.screen&&d.layout?r.createElement(d.layout,{formId:e.layout?.items?.[0]?.formId,type:e.layout?.type,tag:"form"},g.jsx(T,{items:e.layout?.items??[],widgets:d,state:e,triggerFallback:R})):d.loading?r.createElement(d.loading):null})})};exports.NativeFlowContext=z;exports.StyLoginRenderer=B;
|
|
2
|
-
//# sourceMappingURL=LoginRenderer.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"LoginRenderer.cjs","sources":["../src/LoginRenderer.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { NativeParams, PartialRecord, WidgetType, LayoutWidget, LoginFlowState, Widget, IdTokenClaims, LoginFlowMessage } from '@strivacity/sdk-core';\nimport type { NativeContext, NativeFlowContextValue } from './types';\nimport React, { useRef, useState, useEffect, createContext, useCallback } from 'react';\nimport { FallbackError } from '@strivacity/sdk-core';\nimport { unflattenObject } from '@strivacity/sdk-core/utils/object';\nimport { useStrivacity } from './composables';\n\nexport const NativeFlowContext = createContext<NativeFlowContextValue | null>(null);\nconst formData: Record<string, Record<string, unknown>> = {};\n\nconst StyWidgetRenderer: React.FC<{\n\titems: LayoutWidget['items'];\n\twidgets: PartialRecord<WidgetType, React.ComponentType<any>>;\n\tstate: LoginFlowState;\n\ttriggerFallback: (hostedUrl?: string, message?: string) => void;\n}> = ({ items, widgets, state, triggerFallback }) => {\n\treturn (\n\t\t<>\n\t\t\t{items.map((item, idx) => {\n\t\t\t\tif (item.type === 'widget') {\n\t\t\t\t\tconst form = state.forms?.find((f) => f.id === item.formId);\n\t\t\t\t\tconst widget = form?.widgets.find((w) => w.id === item.widgetId);\n\n\t\t\t\t\tif (!form || !widget) {\n\t\t\t\t\t\ttriggerFallback(undefined, `Unable to find form or widget for item: formId=${item.formId}, widgetId=${item.widgetId}`);\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst WidgetComponent = widgets[widget.type];\n\n\t\t\t\t\tif (!WidgetComponent) {\n\t\t\t\t\t\ttriggerFallback(undefined, `No component found for widget type ${widget.type}`);\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn <WidgetComponent key={`${form.id}.${widget.id}`} formId={form.id} config={widget} />;\n\t\t\t\t} else if (item.type === 'vertical' || item.type === 'horizontal') {\n\t\t\t\t\tconst LayoutComponent = widgets.layout;\n\n\t\t\t\t\tif (!LayoutComponent) {\n\t\t\t\t\t\ttriggerFallback(undefined, 'No layout component provided');\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<LayoutComponent key={idx} formId={(item.items[0] as Widget).formId} type={item.type}>\n\t\t\t\t\t\t\t<StyWidgetRenderer items={item.items} widgets={widgets} state={state} triggerFallback={triggerFallback} />\n\t\t\t\t\t\t</LayoutComponent>\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\ttriggerFallback(undefined, 'Unknown item type in layout');\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t})}\n\t\t</>\n\t);\n};\n\nexport const StyLoginRenderer: React.FC<{\n\tparams?: NativeParams;\n\twidgets?: PartialRecord<WidgetType, React.ComponentType<any>>;\n\tsessionId?: string | null;\n\tlanguage?: string | null;\n\tonLogin?: (claims?: IdTokenClaims | null) => void;\n\tonFallback?: (error: FallbackError) => void;\n\tonClose?: () => void;\n\tonError?: (error: any) => void;\n\tonGlobalMessage?: (message: string) => void;\n\tonBlockReady?: ({ previousState, state }: { previousState: LoginFlowState; state: LoginFlowState }) => void;\n\tonLanguageChange?: (language: string | null) => void;\n}> = (props) => {\n\tconst { params, widgets, sessionId, language, onLogin, onFallback, onClose, onError, onGlobalMessage, onBlockReady, onLanguageChange } = {\n\t\tparams: {},\n\t\twidgets: {},\n\t\tsessionId: null,\n\t\tlanguage: null,\n\t\t...props,\n\t};\n\tconst { sdk } = useStrivacity<NativeContext>();\n\tconst loginHandlerRef = useRef<ReturnType<(typeof sdk)['login']> | null>(null);\n\n\tconst [loading, setLoading] = useState(false);\n\tconst [forms, setForms] = useState<Record<string, Record<string, unknown>>>({});\n\tconst [messages, setMessages] = useState<Record<string, Record<string, LoginFlowMessage>>>({});\n\tconst [state, setState] = useState<LoginFlowState>({});\n\n\tconst triggerFallback = useCallback(\n\t\t(hostedUrl?: string, message?: string) => {\n\t\t\tconst url = hostedUrl || state.hostedUrl;\n\n\t\t\tsdk.logging?.warn(message ? `Triggering fallback due to: ${message}` : 'Triggering fallback');\n\n\t\t\tif (!url) {\n\t\t\t\tconst error = new Error('No hosted URL provided');\n\t\t\t\tsdk.logging?.error('Fallback error', error);\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tonFallback?.(new FallbackError(new URL(url)));\n\t\t},\n\t\t[state, onFallback],\n\t);\n\n\tconst triggerClose = useCallback(() => {\n\t\tonClose?.();\n\t}, [onClose]);\n\n\tconst setFormValue = useCallback((formId: string, widgetId: string, value: unknown) => {\n\t\tformData[formId] = {\n\t\t\t...formData[formId],\n\t\t\t[widgetId]: value === '' ? null : value,\n\t\t};\n\n\t\tsetForms((prev) => ({\n\t\t\t...prev,\n\t\t\t[formId]: { ...(prev[formId] || {}), [widgetId]: value === '' ? null : value },\n\t\t}));\n\t}, []);\n\n\tconst setMessage = useCallback((formId: string, widgetId: string, value: LoginFlowMessage) => {\n\t\tsetMessages((prev) => ({\n\t\t\t...prev,\n\t\t\t[formId]: { ...(prev[formId] || {}), [widgetId]: value },\n\t\t}));\n\t}, []);\n\n\tconst submitForm = useCallback(\n\t\tasync (formId: string) => {\n\t\t\ttry {\n\t\t\t\tsetLoading(true);\n\n\t\t\t\tconst data = await loginHandlerRef.current?.submitForm(formId, unflattenObject(formData[formId]));\n\n\t\t\t\tif (await sdk.isAuthenticated) {\n\t\t\t\t\tonLogin?.(sdk.idTokenClaims);\n\t\t\t\t} else {\n\t\t\t\t\tconst previousState = structuredClone(state);\n\t\t\t\t\tconst newState: LoginFlowState = {\n\t\t\t\t\t\thostedUrl: data?.hostedUrl ?? state.hostedUrl,\n\t\t\t\t\t\tfinalizeUrl: data?.finalizeUrl ?? state.finalizeUrl,\n\t\t\t\t\t\tscreen: data?.screen ?? state.screen,\n\t\t\t\t\t\tforms: data?.forms ?? state.forms,\n\t\t\t\t\t\tlayout: data?.layout ?? state.layout,\n\t\t\t\t\t\tmessages: data?.messages ?? {},\n\t\t\t\t\t\tbranding: data?.branding ?? state.branding,\n\t\t\t\t\t};\n\n\t\t\t\t\tif (newState.screen !== state.screen) {\n\t\t\t\t\t\tconst newForms: typeof forms = {};\n\t\t\t\t\t\tconst newMessages: typeof messages = {};\n\n\t\t\t\t\t\tfor (const form of newState.forms ?? []) {\n\t\t\t\t\t\t\tnewForms[form.id] = {};\n\t\t\t\t\t\t\tnewMessages[form.id] = {};\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tsetForms(newForms);\n\t\t\t\t\t\tsetMessages(newMessages);\n\t\t\t\t\t}\n\n\t\t\t\t\tObject.keys(newState.messages ?? {}).forEach((formId) => {\n\t\t\t\t\t\tif (formId === 'global') {\n\t\t\t\t\t\t\tonGlobalMessage?.(newState.messages?.global?.text ?? '');\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsetMessages((prev) => ({\n\t\t\t\t\t\t\t\t...prev,\n\t\t\t\t\t\t\t\t[formId]: newState.messages![formId],\n\t\t\t\t\t\t\t}));\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tsetState(newState);\n\t\t\t\t\tsetLoading(false);\n\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tonBlockReady?.({ previousState, state: structuredClone(newState) });\n\t\t\t\t\t}, 1);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof FallbackError) {\n\t\t\t\t\tonFallback?.(error);\n\t\t\t\t} else {\n\t\t\t\t\tonError?.(error);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[sdk, params, forms, state, onLogin, onFallback, onClose, onError, onGlobalMessage, onBlockReady],\n\t);\n\n\tconst contextValue: NativeFlowContextValue = {\n\t\tloading,\n\t\tforms,\n\t\tmessages,\n\t\tstate,\n\t\tsubmitForm,\n\t\ttriggerFallback,\n\t\ttriggerClose,\n\t\tsetFormValue,\n\t\tsetMessage,\n\t};\n\n\tuseEffect(() => {\n\t\tloginHandlerRef.current = sdk.login(params);\n\n\t\tvoid (async () => {\n\t\t\ttry {\n\t\t\t\tconst data = await loginHandlerRef.current?.startSession(sessionId, language);\n\t\t\t\tconst previousState = structuredClone(state);\n\t\t\t\tconst newState: LoginFlowState = {\n\t\t\t\t\thostedUrl: data?.hostedUrl ?? state.hostedUrl,\n\t\t\t\t\tfinalizeUrl: data?.finalizeUrl ?? state.finalizeUrl,\n\t\t\t\t\tscreen: data?.screen ?? state.screen,\n\t\t\t\t\tforms: data?.forms ?? state.forms,\n\t\t\t\t\tlayout: data?.layout ?? state.layout,\n\t\t\t\t\tmessages: data?.messages ?? {},\n\t\t\t\t\tbranding: data?.branding ?? state.branding,\n\t\t\t\t};\n\n\t\t\t\tonLanguageChange?.(loginHandlerRef.current?.language ?? null);\n\n\t\t\t\tif (await sdk.isAuthenticated) {\n\t\t\t\t\tonLogin?.(sdk.idTokenClaims);\n\t\t\t\t} else {\n\t\t\t\t\tif (newState.screen !== state.screen) {\n\t\t\t\t\t\tconst newforms: typeof forms = {};\n\t\t\t\t\t\tconst newmessages: typeof messages = {};\n\n\t\t\t\t\t\tfor (const form of newState.forms ?? []) {\n\t\t\t\t\t\t\tnewforms[form.id] = {};\n\t\t\t\t\t\t\tnewmessages[form.id] = {};\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tsetForms(newforms);\n\t\t\t\t\t\tsetMessages(newmessages);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsdk.logging?.info(`Updating screen: ${newState.screen}`);\n\t\t\t\t\t}\n\n\t\t\t\t\tObject.keys(newState.messages ?? {}).forEach((formId) => {\n\t\t\t\t\t\tif (formId === 'global') {\n\t\t\t\t\t\t\tonGlobalMessage?.(newState.messages?.global?.text ?? '');\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsetMessages((prev) => ({\n\t\t\t\t\t\t\t\t...prev,\n\t\t\t\t\t\t\t\t[formId]: newState.messages![formId],\n\t\t\t\t\t\t\t}));\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tsetState(newState);\n\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tonBlockReady?.({ previousState, state: structuredClone(newState) });\n\t\t\t\t\t}, 1);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof FallbackError) {\n\t\t\t\t\tonFallback?.(error);\n\t\t\t\t} else {\n\t\t\t\t\tonError?.(error);\n\t\t\t\t}\n\t\t\t}\n\t\t})();\n\t}, []);\n\n\treturn (\n\t\t<NativeFlowContext.Provider value={contextValue}>\n\t\t\t<div className=\"login-renderer\">\n\t\t\t\t{state.screen && widgets.layout\n\t\t\t\t\t? React.createElement(\n\t\t\t\t\t\t\twidgets.layout,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tformId: (state.layout?.items?.[0] as Widget)?.formId,\n\t\t\t\t\t\t\t\ttype: state.layout?.type,\n\t\t\t\t\t\t\t\ttag: 'form',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t<StyWidgetRenderer items={state.layout?.items ?? []} widgets={widgets} state={state} triggerFallback={triggerFallback} />,\n\t\t\t\t\t\t)\n\t\t\t\t\t: widgets.loading\n\t\t\t\t\t\t? React.createElement(widgets.loading)\n\t\t\t\t\t\t: null}\n\t\t\t</div>\n\t\t</NativeFlowContext.Provider>\n\t);\n};\n"],"names":["NativeFlowContext","createContext","formData","StyWidgetRenderer","items","widgets","state","triggerFallback","jsx","Fragment","item","idx","form","f","widget","w","WidgetComponent","LayoutComponent","StyLoginRenderer","props","params","sessionId","language","onLogin","onFallback","onClose","onError","onGlobalMessage","onBlockReady","onLanguageChange","sdk","useStrivacity","loginHandlerRef","useRef","loading","setLoading","useState","forms","setForms","messages","setMessages","setState","useCallback","hostedUrl","message","url","error","FallbackError","triggerClose","setFormValue","formId","widgetId","value","prev","setMessage","submitForm","data","unflattenObject","previousState","newState","newForms","newMessages","contextValue","useEffect","newforms","newmessages","React"],"mappings":"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"}
|
package/dist/LoginRenderer.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { NativeParams, PartialRecord, WidgetType, LoginFlowState, IdTokenClaims, FallbackError } from '@strivacity/sdk-core';
|
|
2
|
-
import { NativeFlowContextValue } from './types';
|
|
3
|
-
import { default as React } from 'react';
|
|
4
|
-
export declare const NativeFlowContext: React.Context<NativeFlowContextValue | null>;
|
|
5
|
-
export declare const StyLoginRenderer: React.FC<{
|
|
6
|
-
params?: NativeParams;
|
|
7
|
-
widgets?: PartialRecord<WidgetType, React.ComponentType<any>>;
|
|
8
|
-
sessionId?: string | null;
|
|
9
|
-
language?: string | null;
|
|
10
|
-
onLogin?: (claims?: IdTokenClaims | null) => void;
|
|
11
|
-
onFallback?: (error: FallbackError) => void;
|
|
12
|
-
onClose?: () => void;
|
|
13
|
-
onError?: (error: any) => void;
|
|
14
|
-
onGlobalMessage?: (message: string) => void;
|
|
15
|
-
onBlockReady?: ({ previousState, state }: {
|
|
16
|
-
previousState: LoginFlowState;
|
|
17
|
-
state: LoginFlowState;
|
|
18
|
-
}) => void;
|
|
19
|
-
onLanguageChange?: (language: string | null) => void;
|
|
20
|
-
}>;
|
package/dist/LoginRenderer.mjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{jsx as m,Fragment as D}from"react/jsx-runtime";import T,{createContext as G,useRef as H,useState as C,useCallback as b,useEffect as P}from"react";import{FallbackError as E}from"@strivacity/sdk-core";import{unflattenObject as q}from"@strivacity/sdk-core/utils/object";import{useStrivacity as J}from"./composables.mjs";const K=G(null),R={},N=({items:k,widgets:y,state:d,triggerFallback:u})=>m(D,{children:k.map((a,w)=>{if(a.type==="widget"){const r=d.forms?.find(g=>g.id===a.formId),i=r?.widgets.find(g=>g.id===a.widgetId);if(!r||!i)return u(void 0,`Unable to find form or widget for item: formId=${a.formId}, widgetId=${a.widgetId}`),null;const p=y[i.type];return p?m(p,{formId:r.id,config:i},`${r.id}.${i.id}`):(u(void 0,`No component found for widget type ${i.type}`),null)}else if(a.type==="vertical"||a.type==="horizontal"){const r=y.layout;return r?m(r,{formId:a.items[0].formId,type:a.type,children:m(N,{items:a.items,widgets:y,state:d,triggerFallback:u})},w):(u(void 0,"No layout component provided"),null)}else return u(void 0,"Unknown item type in layout"),null})}),ee=k=>{const{params:y,widgets:d,sessionId:u,language:a,onLogin:w,onFallback:r,onClose:i,onError:p,onGlobalMessage:g,onBlockReady:v,onLanguageChange:j}={params:{},widgets:{},sessionId:null,language:null,...k},{sdk:c}=J(),U=H(null),[M,x]=C(!1),[z,S]=C({}),[I,h]=C({}),[e,F]=C({}),L=b((t,s)=>{const n=t||e.hostedUrl;if(c.logging?.warn(s?`Triggering fallback due to: ${s}`:"Triggering fallback"),!n){const o=new Error("No hosted URL provided");throw c.logging?.error("Fallback error",o),o}r?.(new E(new URL(n)))},[e,r]),O=b(()=>{i?.()},[i]),A=b((t,s,n)=>{R[t]={...R[t],[s]:n===""?null:n},S(o=>({...o,[t]:{...o[t]||{},[s]:n===""?null:n}}))},[]),V=b((t,s,n)=>{h(o=>({...o,[t]:{...o[t]||{},[s]:n}}))},[]),W=b(async t=>{try{x(!0);const s=await U.current?.submitForm(t,q(R[t]));if(await c.isAuthenticated)w?.(c.idTokenClaims);else{const n=structuredClone(e),o={hostedUrl:s?.hostedUrl??e.hostedUrl,finalizeUrl:s?.finalizeUrl??e.finalizeUrl,screen:s?.screen??e.screen,forms:s?.forms??e.forms,layout:s?.layout??e.layout,messages:s?.messages??{},branding:s?.branding??e.branding};if(o.screen!==e.screen){const l={},f={};for(const $ of o.forms??[])l[$.id]={},f[$.id]={};S(l),h(f)}Object.keys(o.messages??{}).forEach(l=>{l==="global"?g?.(o.messages?.global?.text??""):h(f=>({...f,[l]:o.messages[l]}))}),F(o),x(!1),setTimeout(()=>{v?.({previousState:n,state:structuredClone(o)})},1)}}catch(s){s instanceof E?r?.(s):p?.(s)}},[c,y,z,e,w,r,i,p,g,v]),B={loading:M,forms:z,messages:I,state:e,submitForm:W,triggerFallback:L,triggerClose:O,setFormValue:A,setMessage:V};return P(()=>{U.current=c.login(y),(async()=>{try{const t=await U.current?.startSession(u,a),s=structuredClone(e),n={hostedUrl:t?.hostedUrl??e.hostedUrl,finalizeUrl:t?.finalizeUrl??e.finalizeUrl,screen:t?.screen??e.screen,forms:t?.forms??e.forms,layout:t?.layout??e.layout,messages:t?.messages??{},branding:t?.branding??e.branding};if(j?.(U.current?.language??null),await c.isAuthenticated)w?.(c.idTokenClaims);else{if(n.screen!==e.screen){const o={},l={};for(const f of n.forms??[])o[f.id]={},l[f.id]={};S(o),h(l)}else c.logging?.info(`Updating screen: ${n.screen}`);Object.keys(n.messages??{}).forEach(o=>{o==="global"?g?.(n.messages?.global?.text??""):h(l=>({...l,[o]:n.messages[o]}))}),F(n),setTimeout(()=>{v?.({previousState:s,state:structuredClone(n)})},1)}}catch(t){t instanceof E?r?.(t):p?.(t)}})()},[]),m(K.Provider,{value:B,children:m("div",{className:"login-renderer",children:e.screen&&d.layout?T.createElement(d.layout,{formId:e.layout?.items?.[0]?.formId,type:e.layout?.type,tag:"form"},m(N,{items:e.layout?.items??[],widgets:d,state:e,triggerFallback:L})):d.loading?T.createElement(d.loading):null})})};export{K as NativeFlowContext,ee as StyLoginRenderer};
|
|
2
|
-
//# sourceMappingURL=LoginRenderer.mjs.map
|