@shipfox/client-auth 1.0.0 → 2.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 (42) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +23 -0
  3. package/dist/feature.d.ts +0 -4
  4. package/dist/feature.d.ts.map +1 -1
  5. package/dist/feature.js +0 -5
  6. package/dist/feature.js.map +1 -1
  7. package/dist/hooks/api/signup-auth.d.ts +4 -0
  8. package/dist/hooks/api/signup-auth.d.ts.map +1 -1
  9. package/dist/hooks/api/verify-email-auth.d.ts +4 -1
  10. package/dist/hooks/api/verify-email-auth.d.ts.map +1 -1
  11. package/dist/index.d.ts +0 -1
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +0 -1
  14. package/dist/index.js.map +1 -1
  15. package/dist/pages/email-verification-resend-model.d.ts +0 -1
  16. package/dist/pages/email-verification-resend-model.d.ts.map +1 -1
  17. package/dist/pages/email-verification-resend-model.js +0 -4
  18. package/dist/pages/email-verification-resend-model.js.map +1 -1
  19. package/dist/pages/signup-page.d.ts.map +1 -1
  20. package/dist/pages/signup-page.js +90 -36
  21. package/dist/pages/signup-page.js.map +1 -1
  22. package/dist/tsconfig.test.tsbuildinfo +1 -1
  23. package/package.json +10 -10
  24. package/src/feature.ts +0 -1
  25. package/src/index.ts +0 -1
  26. package/src/pages/email-verification-resend-model.test.ts +0 -10
  27. package/src/pages/email-verification-resend-model.ts +0 -6
  28. package/src/pages/signup-page.test.tsx +60 -6
  29. package/src/pages/signup-page.tsx +87 -36
  30. package/test/pages.tsx +0 -7
  31. package/tsconfig.build.tsbuildinfo +1 -1
  32. package/dist/pages/verify-email-page.d.ts +0 -2
  33. package/dist/pages/verify-email-page.d.ts.map +0 -1
  34. package/dist/pages/verify-email-page.js +0 -57
  35. package/dist/pages/verify-email-page.js.map +0 -1
  36. package/dist/routes/verify-email.d.ts +0 -5
  37. package/dist/routes/verify-email.d.ts.map +0 -1
  38. package/dist/routes/verify-email.js +0 -11
  39. package/dist/routes/verify-email.js.map +0 -1
  40. package/src/pages/verify-email-page.test.tsx +0 -82
  41. package/src/pages/verify-email-page.tsx +0 -48
  42. package/src/routes/verify-email.tsx +0 -11
@@ -1,2 +0,0 @@
1
- export declare function VerifyEmailPage(): null;
2
- //# sourceMappingURL=verify-email-page.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"verify-email-page.d.ts","sourceRoot":"","sources":["../../src/pages/verify-email-page.tsx"],"names":[],"mappings":"AAUA,wBAAgB,eAAe,SAqC9B"}
@@ -1,57 +0,0 @@
1
- import { toast } from '@shipfox/react-ui/toast';
2
- import { useNavigate, useSearch } from '@tanstack/react-router';
3
- import { useEffect } from 'react';
4
- import { useRefreshAuth } from '#hooks/api/refresh-auth.js';
5
- import { useVerifyEmailAuth } from '#hooks/api/verify-email-auth.js';
6
- import { authErrorMessage } from './form-utils.js';
7
- const verificationRequests = new Map();
8
- const toastedVerificationTokens = new Set();
9
- export function VerifyEmailPage() {
10
- const verifyEmail = useVerifyEmailAuth();
11
- const refreshAuth = useRefreshAuth();
12
- const navigate = useNavigate();
13
- const search = useSearch({
14
- strict: false
15
- });
16
- const token = typeof search.token === 'string' ? search.token : undefined;
17
- useEffect(()=>{
18
- if (!token) {
19
- toast.error('This verification link is missing a token.');
20
- navigate({
21
- to: '/',
22
- replace: true
23
- });
24
- return;
25
- }
26
- let request = verificationRequests.get(token);
27
- if (!request) {
28
- request = verifyEmail.mutateAsync({
29
- token
30
- }).then(async ()=>{
31
- await refreshAuth();
32
- });
33
- verificationRequests.set(token, request);
34
- }
35
- request.then(()=>{
36
- if (toastedVerificationTokens.has(token)) return;
37
- toastedVerificationTokens.add(token);
38
- toast.success('Your email is verified. You are now logged in.');
39
- navigate({
40
- to: '/',
41
- replace: true
42
- });
43
- }).catch((error)=>{
44
- if (toastedVerificationTokens.has(token)) return;
45
- toastedVerificationTokens.add(token);
46
- toast.error(authErrorMessage(error));
47
- });
48
- }, [
49
- navigate,
50
- refreshAuth,
51
- token,
52
- verifyEmail.mutateAsync
53
- ]);
54
- return null;
55
- }
56
-
57
- //# sourceMappingURL=verify-email-page.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/pages/verify-email-page.tsx"],"sourcesContent":["import {toast} from '@shipfox/react-ui/toast';\nimport {useNavigate, useSearch} from '@tanstack/react-router';\nimport {useEffect} from 'react';\nimport {useRefreshAuth} from '#hooks/api/refresh-auth.js';\nimport {useVerifyEmailAuth} from '#hooks/api/verify-email-auth.js';\nimport {authErrorMessage} from './form-utils.js';\n\nconst verificationRequests = new Map<string, Promise<void>>();\nconst toastedVerificationTokens = new Set<string>();\n\nexport function VerifyEmailPage() {\n const verifyEmail = useVerifyEmailAuth();\n const refreshAuth = useRefreshAuth();\n const navigate = useNavigate();\n const search = useSearch({strict: false});\n const token = typeof search.token === 'string' ? search.token : undefined;\n\n useEffect(() => {\n if (!token) {\n toast.error('This verification link is missing a token.');\n navigate({to: '/', replace: true});\n return;\n }\n\n let request = verificationRequests.get(token);\n if (!request) {\n request = verifyEmail.mutateAsync({token}).then(async () => {\n await refreshAuth();\n });\n verificationRequests.set(token, request);\n }\n\n request\n .then(() => {\n if (toastedVerificationTokens.has(token)) return;\n toastedVerificationTokens.add(token);\n toast.success('Your email is verified. You are now logged in.');\n navigate({to: '/', replace: true});\n })\n .catch((error) => {\n if (toastedVerificationTokens.has(token)) return;\n toastedVerificationTokens.add(token);\n toast.error(authErrorMessage(error));\n });\n }, [navigate, refreshAuth, token, verifyEmail.mutateAsync]);\n\n return null;\n}\n"],"names":["toast","useNavigate","useSearch","useEffect","useRefreshAuth","useVerifyEmailAuth","authErrorMessage","verificationRequests","Map","toastedVerificationTokens","Set","VerifyEmailPage","verifyEmail","refreshAuth","navigate","search","strict","token","undefined","error","to","replace","request","get","mutateAsync","then","set","has","add","success","catch"],"mappings":"AAAA,SAAQA,KAAK,QAAO,0BAA0B;AAC9C,SAAQC,WAAW,EAAEC,SAAS,QAAO,yBAAyB;AAC9D,SAAQC,SAAS,QAAO,QAAQ;AAChC,SAAQC,cAAc,QAAO,6BAA6B;AAC1D,SAAQC,kBAAkB,QAAO,kCAAkC;AACnE,SAAQC,gBAAgB,QAAO,kBAAkB;AAEjD,MAAMC,uBAAuB,IAAIC;AACjC,MAAMC,4BAA4B,IAAIC;AAEtC,OAAO,SAASC;IACd,MAAMC,cAAcP;IACpB,MAAMQ,cAAcT;IACpB,MAAMU,WAAWb;IACjB,MAAMc,SAASb,UAAU;QAACc,QAAQ;IAAK;IACvC,MAAMC,QAAQ,OAAOF,OAAOE,KAAK,KAAK,WAAWF,OAAOE,KAAK,GAAGC;IAEhEf,UAAU;QACR,IAAI,CAACc,OAAO;YACVjB,MAAMmB,KAAK,CAAC;YACZL,SAAS;gBAACM,IAAI;gBAAKC,SAAS;YAAI;YAChC;QACF;QAEA,IAAIC,UAAUf,qBAAqBgB,GAAG,CAACN;QACvC,IAAI,CAACK,SAAS;YACZA,UAAUV,YAAYY,WAAW,CAAC;gBAACP;YAAK,GAAGQ,IAAI,CAAC;gBAC9C,MAAMZ;YACR;YACAN,qBAAqBmB,GAAG,CAACT,OAAOK;QAClC;QAEAA,QACGG,IAAI,CAAC;YACJ,IAAIhB,0BAA0BkB,GAAG,CAACV,QAAQ;YAC1CR,0BAA0BmB,GAAG,CAACX;YAC9BjB,MAAM6B,OAAO,CAAC;YACdf,SAAS;gBAACM,IAAI;gBAAKC,SAAS;YAAI;QAClC,GACCS,KAAK,CAAC,CAACX;YACN,IAAIV,0BAA0BkB,GAAG,CAACV,QAAQ;YAC1CR,0BAA0BmB,GAAG,CAACX;YAC9BjB,MAAMmB,KAAK,CAACb,iBAAiBa;QAC/B;IACJ,GAAG;QAACL;QAAUD;QAAaI;QAAOL,YAAYY,WAAW;KAAC;IAE1D,OAAO;AACT"}
@@ -1,5 +0,0 @@
1
- declare const _default: import("@shipfox/client-shell/runtime").RouteImpl<{
2
- readonly component: () => import("react").JSX.Element;
3
- }>;
4
- export default _default;
5
- //# sourceMappingURL=verify-email.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"verify-email.d.ts","sourceRoot":"","sources":["../../src/routes/verify-email.tsx"],"names":[],"mappings":";;;AAIA,wBAMG"}
@@ -1,11 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { defineRoute } from '@shipfox/client-shell/runtime';
3
- import { GuestGuard } from '#components/auth-guard.js';
4
- import { VerifyEmailPage } from '#pages/verify-email-page.js';
5
- export default defineRoute({
6
- component: ()=>/*#__PURE__*/ _jsx(GuestGuard, {
7
- children: /*#__PURE__*/ _jsx(VerifyEmailPage, {})
8
- })
9
- });
10
-
11
- //# sourceMappingURL=verify-email.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/routes/verify-email.tsx"],"sourcesContent":["import {defineRoute} from '@shipfox/client-shell/runtime';\nimport {GuestGuard} from '#components/auth-guard.js';\nimport {VerifyEmailPage} from '#pages/verify-email-page.js';\n\nexport default defineRoute({\n component: () => (\n <GuestGuard>\n <VerifyEmailPage />\n </GuestGuard>\n ),\n});\n"],"names":["defineRoute","GuestGuard","VerifyEmailPage","component"],"mappings":";AAAA,SAAQA,WAAW,QAAO,gCAAgC;AAC1D,SAAQC,UAAU,QAAO,4BAA4B;AACrD,SAAQC,eAAe,QAAO,8BAA8B;AAE5D,eAAeF,YAAY;IACzBG,WAAW,kBACT,KAACF;sBACC,cAAA,KAACC;;AAGP,GAAG"}
@@ -1,82 +0,0 @@
1
- import {configureApiClient} from '@shipfox/client-api';
2
- import {screen, waitFor} from '@testing-library/react';
3
- import {pageUserFactory} from '#test/factories/user.js';
4
- import {renderAuthPage, renderStrictAuthPage} from '#test/pages.js';
5
- import {jsonResponse, requestUrl} from '#test/utils.js';
6
- import {VerifyEmailPage} from './verify-email-page.js';
7
-
8
- describe('VerifyEmailPage', () => {
9
- beforeEach(() => {
10
- configureApiClient({baseUrl: 'https://api.example.test', getAccessToken: undefined});
11
- });
12
-
13
- test('only confirms once under StrictMode', async () => {
14
- const user = pageUserFactory.build();
15
- let didVerify = false;
16
- const fetchImpl = vi.fn((input: RequestInfo | URL) => {
17
- const url = requestUrl(input);
18
- if (url.endsWith('/auth/verify-email/confirm')) {
19
- didVerify = true;
20
- return Promise.resolve(jsonResponse({token: 'verified-access-token', user}));
21
- }
22
- if (url.endsWith('/auth/refresh')) {
23
- return Promise.resolve(
24
- didVerify
25
- ? jsonResponse({token: 'refreshed-access-token', user})
26
- : jsonResponse({code: 'unauthorized', message: 'Unauthorized'}, {status: 401}),
27
- );
28
- }
29
- return Promise.resolve(
30
- jsonResponse({code: 'not-found', message: 'Not found'}, {status: 404}),
31
- );
32
- });
33
- configureApiClient({fetchImpl});
34
-
35
- renderStrictAuthPage('/auth/verify-email?token=strict-token', <VerifyEmailPage />);
36
-
37
- expect(await screen.findByRole('heading', {name: 'Authenticated home'})).toBeInTheDocument();
38
- expect(
39
- await screen.findByText('Your email is verified. You are now logged in.'),
40
- ).toBeInTheDocument();
41
- const verifyCalls = fetchImpl.mock.calls.filter(([input]) =>
42
- requestUrl(input).endsWith('/auth/verify-email/confirm'),
43
- );
44
- expect(verifyCalls).toHaveLength(1);
45
- });
46
-
47
- test('reports an invalid token', async () => {
48
- const fetchImpl = vi.fn((input: RequestInfo | URL) => {
49
- const url = requestUrl(input);
50
- if (url.endsWith('/auth/verify-email/confirm')) {
51
- return Promise.resolve(
52
- jsonResponse({code: 'invalid-token', message: 'Invalid token'}, {status: 400}),
53
- );
54
- }
55
- return Promise.resolve(
56
- jsonResponse({code: 'unauthorized', message: 'Unauthorized'}, {status: 401}),
57
- );
58
- });
59
- configureApiClient({fetchImpl});
60
-
61
- renderAuthPage('/auth/verify-email?token=bad-token', <VerifyEmailPage />);
62
-
63
- expect(await screen.findByText('Invalid token')).toBeInTheDocument();
64
- });
65
-
66
- test('handles missing token locally', async () => {
67
- const fetchImpl = vi
68
- .fn()
69
- .mockResolvedValue(
70
- jsonResponse({code: 'unauthorized', message: 'Unauthorized'}, {status: 401}),
71
- );
72
- configureApiClient({fetchImpl});
73
-
74
- renderAuthPage('/auth/verify-email', <VerifyEmailPage />);
75
-
76
- expect(await screen.findByRole('heading', {name: 'Authenticated home'})).toBeInTheDocument();
77
- expect(
78
- await screen.findByText('This verification link is missing a token.'),
79
- ).toBeInTheDocument();
80
- await waitFor(() => expect(fetchImpl).toHaveBeenCalledTimes(1));
81
- });
82
- });
@@ -1,48 +0,0 @@
1
- import {toast} from '@shipfox/react-ui/toast';
2
- import {useNavigate, useSearch} from '@tanstack/react-router';
3
- import {useEffect} from 'react';
4
- import {useRefreshAuth} from '#hooks/api/refresh-auth.js';
5
- import {useVerifyEmailAuth} from '#hooks/api/verify-email-auth.js';
6
- import {authErrorMessage} from './form-utils.js';
7
-
8
- const verificationRequests = new Map<string, Promise<void>>();
9
- const toastedVerificationTokens = new Set<string>();
10
-
11
- export function VerifyEmailPage() {
12
- const verifyEmail = useVerifyEmailAuth();
13
- const refreshAuth = useRefreshAuth();
14
- const navigate = useNavigate();
15
- const search = useSearch({strict: false});
16
- const token = typeof search.token === 'string' ? search.token : undefined;
17
-
18
- useEffect(() => {
19
- if (!token) {
20
- toast.error('This verification link is missing a token.');
21
- navigate({to: '/', replace: true});
22
- return;
23
- }
24
-
25
- let request = verificationRequests.get(token);
26
- if (!request) {
27
- request = verifyEmail.mutateAsync({token}).then(async () => {
28
- await refreshAuth();
29
- });
30
- verificationRequests.set(token, request);
31
- }
32
-
33
- request
34
- .then(() => {
35
- if (toastedVerificationTokens.has(token)) return;
36
- toastedVerificationTokens.add(token);
37
- toast.success('Your email is verified. You are now logged in.');
38
- navigate({to: '/', replace: true});
39
- })
40
- .catch((error) => {
41
- if (toastedVerificationTokens.has(token)) return;
42
- toastedVerificationTokens.add(token);
43
- toast.error(authErrorMessage(error));
44
- });
45
- }, [navigate, refreshAuth, token, verifyEmail.mutateAsync]);
46
-
47
- return null;
48
- }
@@ -1,11 +0,0 @@
1
- import {defineRoute} from '@shipfox/client-shell/runtime';
2
- import {GuestGuard} from '#components/auth-guard.js';
3
- import {VerifyEmailPage} from '#pages/verify-email-page.js';
4
-
5
- export default defineRoute({
6
- component: () => (
7
- <GuestGuard>
8
- <VerifyEmailPage />
9
- </GuestGuard>
10
- ),
11
- });