@shipfox/client-auth 0.2.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/.storybook/main.ts +1 -0
- package/.storybook/preview.css +7 -0
- package/.storybook/preview.tsx +56 -0
- package/.turbo/turbo-build.log +2 -0
- package/.turbo/turbo-type$colon$emit.log +1 -0
- package/.turbo/turbo-type.log +1 -0
- package/CHANGELOG.md +111 -0
- package/LICENSE +21 -0
- package/dist/components/auth-guard.d.ts +5 -0
- package/dist/components/auth-guard.d.ts.map +1 -0
- package/dist/components/auth-guard.js +61 -0
- package/dist/components/auth-guard.js.map +1 -0
- package/dist/components/auth-provider.d.ts +11 -0
- package/dist/components/auth-provider.d.ts.map +1 -0
- package/dist/components/auth-provider.js +21 -0
- package/dist/components/auth-provider.js.map +1 -0
- package/dist/components/auth-shell.d.ts +11 -0
- package/dist/components/auth-shell.d.ts.map +1 -0
- package/dist/components/auth-shell.js +63 -0
- package/dist/components/auth-shell.js.map +1 -0
- package/dist/components/redirect-target.d.ts +2 -0
- package/dist/components/redirect-target.d.ts.map +1 -0
- package/dist/components/redirect-target.js +22 -0
- package/dist/components/redirect-target.js.map +1 -0
- package/dist/components/workspace-crumb.d.ts +3 -0
- package/dist/components/workspace-crumb.d.ts.map +1 -0
- package/dist/components/workspace-crumb.js +3 -0
- package/dist/components/workspace-crumb.js.map +1 -0
- package/dist/components/workspace-switcher.d.ts +6 -0
- package/dist/components/workspace-switcher.d.ts.map +1 -0
- package/dist/components/workspace-switcher.js +91 -0
- package/dist/components/workspace-switcher.js.map +1 -0
- package/dist/components/workspace-switcher.stories.d.ts +26 -0
- package/dist/components/workspace-switcher.stories.d.ts.map +1 -0
- package/dist/components/workspace-switcher.stories.js +168 -0
- package/dist/components/workspace-switcher.stories.js.map +1 -0
- package/dist/feature.d.ts +33 -0
- package/dist/feature.d.ts.map +1 -0
- package/dist/feature.js +43 -0
- package/dist/feature.js.map +1 -0
- package/dist/hooks/api/login-auth.d.ts +29 -0
- package/dist/hooks/api/login-auth.d.ts.map +1 -0
- package/dist/hooks/api/login-auth.js +42 -0
- package/dist/hooks/api/login-auth.js.map +1 -0
- package/dist/hooks/api/logout-auth.d.ts +2 -0
- package/dist/hooks/api/logout-auth.d.ts.map +1 -0
- package/dist/hooks/api/logout-auth.js +32 -0
- package/dist/hooks/api/logout-auth.js.map +1 -0
- package/dist/hooks/api/password-reset-auth.d.ts +33 -0
- package/dist/hooks/api/password-reset-auth.d.ts.map +1 -0
- package/dist/hooks/api/password-reset-auth.js +48 -0
- package/dist/hooks/api/password-reset-auth.js.map +1 -0
- package/dist/hooks/api/refresh-auth.d.ts +2 -0
- package/dist/hooks/api/refresh-auth.d.ts.map +1 -0
- package/dist/hooks/api/refresh-auth.js +3 -0
- package/dist/hooks/api/refresh-auth.js.map +1 -0
- package/dist/hooks/api/signup-auth.d.ts +27 -0
- package/dist/hooks/api/signup-auth.d.ts.map +1 -0
- package/dist/hooks/api/signup-auth.js +15 -0
- package/dist/hooks/api/signup-auth.js.map +1 -0
- package/dist/hooks/api/verify-email-auth.d.ts +20 -0
- package/dist/hooks/api/verify-email-auth.d.ts.map +1 -0
- package/dist/hooks/api/verify-email-auth.js +48 -0
- package/dist/hooks/api/verify-email-auth.js.map +1 -0
- package/dist/hooks/api/workspace-auth.d.ts +22 -0
- package/dist/hooks/api/workspace-auth.d.ts.map +1 -0
- package/dist/hooks/api/workspace-auth.js +25 -0
- package/dist/hooks/api/workspace-auth.js.map +1 -0
- package/dist/hooks/index.d.ts +11 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +11 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/use-active-workspace.d.ts +2 -0
- package/dist/hooks/use-active-workspace.d.ts.map +1 -0
- package/dist/hooks/use-active-workspace.js +3 -0
- package/dist/hooks/use-active-workspace.js.map +1 -0
- package/dist/hooks/use-auth-state.d.ts +2 -0
- package/dist/hooks/use-auth-state.d.ts.map +1 -0
- package/dist/hooks/use-auth-state.js +3 -0
- package/dist/hooks/use-auth-state.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/pages/email-verification-resend-model.d.ts +7 -0
- package/dist/pages/email-verification-resend-model.d.ts.map +1 -0
- package/dist/pages/email-verification-resend-model.js +15 -0
- package/dist/pages/email-verification-resend-model.js.map +1 -0
- package/dist/pages/form-errors.d.ts +19 -0
- package/dist/pages/form-errors.d.ts.map +1 -0
- package/dist/pages/form-errors.js +51 -0
- package/dist/pages/form-errors.js.map +1 -0
- package/dist/pages/form-utils.d.ts +2 -0
- package/dist/pages/form-utils.d.ts.map +1 -0
- package/dist/pages/form-utils.js +28 -0
- package/dist/pages/form-utils.js.map +1 -0
- package/dist/pages/invitation-context.d.ts +31 -0
- package/dist/pages/invitation-context.d.ts.map +1 -0
- package/dist/pages/invitation-context.js +50 -0
- package/dist/pages/invitation-context.js.map +1 -0
- package/dist/pages/login-page.d.ts +2 -0
- package/dist/pages/login-page.d.ts.map +1 -0
- package/dist/pages/login-page.js +214 -0
- package/dist/pages/login-page.js.map +1 -0
- package/dist/pages/logout-page.d.ts +2 -0
- package/dist/pages/logout-page.d.ts.map +1 -0
- package/dist/pages/logout-page.js +45 -0
- package/dist/pages/logout-page.js.map +1 -0
- package/dist/pages/password-reset-page.d.ts +2 -0
- package/dist/pages/password-reset-page.d.ts.map +1 -0
- package/dist/pages/password-reset-page.js +265 -0
- package/dist/pages/password-reset-page.js.map +1 -0
- package/dist/pages/signup-page.d.ts +2 -0
- package/dist/pages/signup-page.d.ts.map +1 -0
- package/dist/pages/signup-page.js +384 -0
- package/dist/pages/signup-page.js.map +1 -0
- package/dist/pages/verify-email-page.d.ts +2 -0
- package/dist/pages/verify-email-page.d.ts.map +1 -0
- package/dist/pages/verify-email-page.js +57 -0
- package/dist/pages/verify-email-page.js.map +1 -0
- package/dist/pages/workspace-onboarding-page.d.ts +2 -0
- package/dist/pages/workspace-onboarding-page.d.ts.map +1 -0
- package/dist/pages/workspace-onboarding-page.js +294 -0
- package/dist/pages/workspace-onboarding-page.js.map +1 -0
- package/dist/routes/index.d.ts +10 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +29 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/login.d.ts +5 -0
- package/dist/routes/login.d.ts.map +1 -0
- package/dist/routes/login.js +11 -0
- package/dist/routes/login.js.map +1 -0
- package/dist/routes/logout.d.ts +6 -0
- package/dist/routes/logout.d.ts.map +1 -0
- package/dist/routes/logout.js +7 -0
- package/dist/routes/logout.js.map +1 -0
- package/dist/routes/reset.d.ts +5 -0
- package/dist/routes/reset.d.ts.map +1 -0
- package/dist/routes/reset.js +11 -0
- package/dist/routes/reset.js.map +1 -0
- package/dist/routes/signup.d.ts +5 -0
- package/dist/routes/signup.d.ts.map +1 -0
- package/dist/routes/signup.js +11 -0
- package/dist/routes/signup.js.map +1 -0
- package/dist/routes/verify-email.d.ts +5 -0
- package/dist/routes/verify-email.d.ts.map +1 -0
- package/dist/routes/verify-email.js +11 -0
- package/dist/routes/verify-email.js.map +1 -0
- package/dist/routes/workspace-onboarding.d.ts +13 -0
- package/dist/routes/workspace-onboarding.d.ts.map +1 -0
- package/dist/routes/workspace-onboarding.js +18 -0
- package/dist/routes/workspace-onboarding.js.map +1 -0
- package/dist/state/auth.d.ts +10 -0
- package/dist/state/auth.d.ts.map +1 -0
- package/dist/state/auth.js +9 -0
- package/dist/state/auth.js.map +1 -0
- package/dist/state/last-workspace.d.ts +2 -0
- package/dist/state/last-workspace.d.ts.map +1 -0
- package/dist/state/last-workspace.js +3 -0
- package/dist/state/last-workspace.js.map +1 -0
- package/dist/tsconfig.test.tsbuildinfo +1 -0
- package/package.json +116 -0
- package/src/components/auth-guard.tsx +58 -0
- package/src/components/auth-provider.test.tsx +164 -0
- package/src/components/auth-provider.tsx +24 -0
- package/src/components/auth-shell.tsx +53 -0
- package/src/components/redirect-target.test.ts +60 -0
- package/src/components/redirect-target.ts +21 -0
- package/src/components/workspace-crumb.tsx +2 -0
- package/src/components/workspace-switcher.stories.tsx +169 -0
- package/src/components/workspace-switcher.tsx +76 -0
- package/src/feature.ts +18 -0
- package/src/hooks/api/login-auth.test.ts +45 -0
- package/src/hooks/api/login-auth.ts +41 -0
- package/src/hooks/api/logout-auth.ts +26 -0
- package/src/hooks/api/password-reset-auth.test.ts +68 -0
- package/src/hooks/api/password-reset-auth.ts +51 -0
- package/src/hooks/api/refresh-auth.test.ts +37 -0
- package/src/hooks/api/refresh-auth.ts +5 -0
- package/src/hooks/api/signup-auth.ts +11 -0
- package/src/hooks/api/verify-email-auth.ts +55 -0
- package/src/hooks/api/workspace-auth.test.ts +40 -0
- package/src/hooks/api/workspace-auth.ts +25 -0
- package/src/hooks/index.ts +13 -0
- package/src/hooks/use-active-workspace.ts +1 -0
- package/src/hooks/use-auth-state.ts +1 -0
- package/src/index.ts +18 -0
- package/src/pages/email-verification-resend-model.test.ts +52 -0
- package/src/pages/email-verification-resend-model.ts +21 -0
- package/src/pages/form-errors.test.ts +114 -0
- package/src/pages/form-errors.ts +45 -0
- package/src/pages/form-utils.test.ts +37 -0
- package/src/pages/form-utils.ts +29 -0
- package/src/pages/invitation-context.ts +57 -0
- package/src/pages/login-page.test.tsx +128 -0
- package/src/pages/login-page.tsx +184 -0
- package/src/pages/logout-page.tsx +33 -0
- package/src/pages/password-reset-page.test.tsx +109 -0
- package/src/pages/password-reset-page.tsx +222 -0
- package/src/pages/signup-page.test.tsx +289 -0
- package/src/pages/signup-page.tsx +354 -0
- package/src/pages/verify-email-page.test.tsx +82 -0
- package/src/pages/verify-email-page.tsx +48 -0
- package/src/pages/workspace-onboarding-page.test.tsx +161 -0
- package/src/pages/workspace-onboarding-page.tsx +213 -0
- package/src/routes/index.tsx +18 -0
- package/src/routes/login.tsx +11 -0
- package/src/routes/logout.tsx +4 -0
- package/src/routes/reset.tsx +11 -0
- package/src/routes/signup.tsx +11 -0
- package/src/routes/verify-email.tsx +11 -0
- package/src/routes/workspace-onboarding.tsx +14 -0
- package/src/state/auth.ts +18 -0
- package/src/state/last-workspace.test.ts +63 -0
- package/src/state/last-workspace.ts +5 -0
- package/test/factories/user.ts +17 -0
- package/test/pages.tsx +83 -0
- package/test/setup.ts +3 -0
- package/test/utils.ts +11 -0
- package/tsconfig.build.json +10 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.json +3 -0
- package/tsconfig.test.json +8 -0
- package/vercel.json +8 -0
- package/vitest.config.ts +71 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { apiRequest } from '@shipfox/client-api';
|
|
2
|
+
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
3
|
+
import { useSetAtom } from 'jotai';
|
|
4
|
+
import { authStateAtom, toAuthenticatedState } from '#state/auth.js';
|
|
5
|
+
import { authRefreshQueryKey } from './refresh-auth.js';
|
|
6
|
+
import { listUserWorkspaces, userWorkspacesQueryKey } from './workspace-auth.js';
|
|
7
|
+
async function verifyEmailAuth(body) {
|
|
8
|
+
return await apiRequest('/auth/verify-email/confirm', {
|
|
9
|
+
method: 'POST',
|
|
10
|
+
body
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
async function resendEmailVerificationAuth(body) {
|
|
14
|
+
return await apiRequest('/auth/verify-email/resend', {
|
|
15
|
+
method: 'POST',
|
|
16
|
+
body
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
export function useResendEmailVerificationAuth() {
|
|
20
|
+
return useMutation({
|
|
21
|
+
mutationFn: resendEmailVerificationAuth
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
export function useVerifyEmailAuth() {
|
|
25
|
+
const queryClient = useQueryClient();
|
|
26
|
+
const setState = useSetAtom(authStateAtom);
|
|
27
|
+
return useMutation({
|
|
28
|
+
mutationFn: verifyEmailAuth,
|
|
29
|
+
onSuccess: async (result)=>{
|
|
30
|
+
setState(toAuthenticatedState(result));
|
|
31
|
+
queryClient.setQueryData(authRefreshQueryKey, result);
|
|
32
|
+
try {
|
|
33
|
+
const workspaces = await queryClient.fetchQuery({
|
|
34
|
+
queryKey: userWorkspacesQueryKey,
|
|
35
|
+
queryFn: ()=>listUserWorkspaces(result.token),
|
|
36
|
+
retry: false,
|
|
37
|
+
staleTime: 0
|
|
38
|
+
});
|
|
39
|
+
setState(toAuthenticatedState(result, workspaces.memberships));
|
|
40
|
+
queryClient.setQueryData(userWorkspacesQueryKey, workspaces);
|
|
41
|
+
} catch {
|
|
42
|
+
// The user is authenticated even if workspace hydration fails.
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
//# sourceMappingURL=verify-email-auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/hooks/api/verify-email-auth.ts"],"sourcesContent":["import type {\n VerifyEmailConfirmBodyDto,\n VerifyEmailConfirmResponseDto,\n VerifyEmailResendBodyDto,\n VerifyEmailResendResponseDto,\n} from '@shipfox/api-auth-dto';\nimport {apiRequest} from '@shipfox/client-api';\nimport {useMutation, useQueryClient} from '@tanstack/react-query';\nimport {useSetAtom} from 'jotai';\nimport {authStateAtom, toAuthenticatedState} from '#state/auth.js';\nimport {authRefreshQueryKey} from './refresh-auth.js';\nimport {listUserWorkspaces, userWorkspacesQueryKey} from './workspace-auth.js';\n\nasync function verifyEmailAuth(body: VerifyEmailConfirmBodyDto) {\n return await apiRequest<VerifyEmailConfirmResponseDto>('/auth/verify-email/confirm', {\n method: 'POST',\n body,\n });\n}\n\nasync function resendEmailVerificationAuth(body: VerifyEmailResendBodyDto) {\n return await apiRequest<VerifyEmailResendResponseDto>('/auth/verify-email/resend', {\n method: 'POST',\n body,\n });\n}\n\nexport function useResendEmailVerificationAuth() {\n return useMutation({mutationFn: resendEmailVerificationAuth});\n}\n\nexport function useVerifyEmailAuth() {\n const queryClient = useQueryClient();\n const setState = useSetAtom(authStateAtom);\n\n return useMutation({\n mutationFn: verifyEmailAuth,\n onSuccess: async (result) => {\n setState(toAuthenticatedState(result));\n queryClient.setQueryData(authRefreshQueryKey, result);\n try {\n const workspaces = await queryClient.fetchQuery({\n queryKey: userWorkspacesQueryKey,\n queryFn: () => listUserWorkspaces(result.token),\n retry: false,\n staleTime: 0,\n });\n setState(toAuthenticatedState(result, workspaces.memberships));\n queryClient.setQueryData(userWorkspacesQueryKey, workspaces);\n } catch {\n // The user is authenticated even if workspace hydration fails.\n }\n },\n });\n}\n"],"names":["apiRequest","useMutation","useQueryClient","useSetAtom","authStateAtom","toAuthenticatedState","authRefreshQueryKey","listUserWorkspaces","userWorkspacesQueryKey","verifyEmailAuth","body","method","resendEmailVerificationAuth","useResendEmailVerificationAuth","mutationFn","useVerifyEmailAuth","queryClient","setState","onSuccess","result","setQueryData","workspaces","fetchQuery","queryKey","queryFn","token","retry","staleTime","memberships"],"mappings":"AAMA,SAAQA,UAAU,QAAO,sBAAsB;AAC/C,SAAQC,WAAW,EAAEC,cAAc,QAAO,wBAAwB;AAClE,SAAQC,UAAU,QAAO,QAAQ;AACjC,SAAQC,aAAa,EAAEC,oBAAoB,QAAO,iBAAiB;AACnE,SAAQC,mBAAmB,QAAO,oBAAoB;AACtD,SAAQC,kBAAkB,EAAEC,sBAAsB,QAAO,sBAAsB;AAE/E,eAAeC,gBAAgBC,IAA+B;IAC5D,OAAO,MAAMV,WAA0C,8BAA8B;QACnFW,QAAQ;QACRD;IACF;AACF;AAEA,eAAeE,4BAA4BF,IAA8B;IACvE,OAAO,MAAMV,WAAyC,6BAA6B;QACjFW,QAAQ;QACRD;IACF;AACF;AAEA,OAAO,SAASG;IACd,OAAOZ,YAAY;QAACa,YAAYF;IAA2B;AAC7D;AAEA,OAAO,SAASG;IACd,MAAMC,cAAcd;IACpB,MAAMe,WAAWd,WAAWC;IAE5B,OAAOH,YAAY;QACjBa,YAAYL;QACZS,WAAW,OAAOC;YAChBF,SAASZ,qBAAqBc;YAC9BH,YAAYI,YAAY,CAACd,qBAAqBa;YAC9C,IAAI;gBACF,MAAME,aAAa,MAAML,YAAYM,UAAU,CAAC;oBAC9CC,UAAUf;oBACVgB,SAAS,IAAMjB,mBAAmBY,OAAOM,KAAK;oBAC9CC,OAAO;oBACPC,WAAW;gBACb;gBACAV,SAASZ,qBAAqBc,QAAQE,WAAWO,WAAW;gBAC5DZ,YAAYI,YAAY,CAACZ,wBAAwBa;YACnD,EAAE,OAAM;YACN,+DAA+D;YACjE;QACF;IACF;AACF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { CreateWorkspaceBodyDto } from '@shipfox/api-workspaces-dto';
|
|
2
|
+
import { listUserWorkspaces, userWorkspacesQueryKey } from '@shipfox/client-shell/runtime';
|
|
3
|
+
export declare function createWorkspace(body: CreateWorkspaceBodyDto): Promise<{
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
status: "active" | "suspended" | "deleted";
|
|
7
|
+
settings: Record<string, unknown>;
|
|
8
|
+
created_at: string;
|
|
9
|
+
updated_at: string;
|
|
10
|
+
}>;
|
|
11
|
+
export { listUserWorkspaces, userWorkspacesQueryKey };
|
|
12
|
+
export declare function useCreateWorkspaceAuth(): import("@tanstack/react-query").UseMutationResult<{
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
status: "active" | "suspended" | "deleted";
|
|
16
|
+
settings: Record<string, unknown>;
|
|
17
|
+
created_at: string;
|
|
18
|
+
updated_at: string;
|
|
19
|
+
}, Error, {
|
|
20
|
+
name: string;
|
|
21
|
+
}, unknown>;
|
|
22
|
+
//# sourceMappingURL=workspace-auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-auth.d.ts","sourceRoot":"","sources":["../../../src/hooks/api/workspace-auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,sBAAsB,EAAuB,MAAM,6BAA6B,CAAC;AAE9F,OAAO,EAAC,kBAAkB,EAAE,sBAAsB,EAAC,MAAM,+BAA+B,CAAC;AAIzF,wBAAsB,eAAe,CAAC,IAAI,EAAE,sBAAsB;;;;;;;GAEjE;AAED,OAAO,EAAC,kBAAkB,EAAE,sBAAsB,EAAC,CAAC;AAEpD,wBAAgB,sBAAsB;;;;;;;;;YAYrC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { apiRequest } from '@shipfox/client-api';
|
|
2
|
+
import { listUserWorkspaces, userWorkspacesQueryKey } from '@shipfox/client-shell/runtime';
|
|
3
|
+
import { useMutation } from '@tanstack/react-query';
|
|
4
|
+
import { useRefreshAuth } from './refresh-auth.js';
|
|
5
|
+
export async function createWorkspace(body) {
|
|
6
|
+
return await apiRequest('/workspaces', {
|
|
7
|
+
method: 'POST',
|
|
8
|
+
body
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
export { listUserWorkspaces, userWorkspacesQueryKey };
|
|
12
|
+
export function useCreateWorkspaceAuth() {
|
|
13
|
+
const refreshAuth = useRefreshAuth();
|
|
14
|
+
return useMutation({
|
|
15
|
+
mutationFn: createWorkspace,
|
|
16
|
+
onSuccess: async ()=>{
|
|
17
|
+
// The new workspace introduces a membership the existing access token
|
|
18
|
+
// doesn't carry. Refresh so the next request includes it in the JWT
|
|
19
|
+
// claim and passes the in-memory canAccess() check on the server.
|
|
20
|
+
await refreshAuth();
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=workspace-auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/hooks/api/workspace-auth.ts"],"sourcesContent":["import type {CreateWorkspaceBodyDto, WorkspaceResponseDto} from '@shipfox/api-workspaces-dto';\nimport {apiRequest} from '@shipfox/client-api';\nimport {listUserWorkspaces, userWorkspacesQueryKey} from '@shipfox/client-shell/runtime';\nimport {useMutation} from '@tanstack/react-query';\nimport {useRefreshAuth} from './refresh-auth.js';\n\nexport async function createWorkspace(body: CreateWorkspaceBodyDto) {\n return await apiRequest<WorkspaceResponseDto>('/workspaces', {method: 'POST', body});\n}\n\nexport {listUserWorkspaces, userWorkspacesQueryKey};\n\nexport function useCreateWorkspaceAuth() {\n const refreshAuth = useRefreshAuth();\n\n return useMutation({\n mutationFn: createWorkspace,\n onSuccess: async () => {\n // The new workspace introduces a membership the existing access token\n // doesn't carry. Refresh so the next request includes it in the JWT\n // claim and passes the in-memory canAccess() check on the server.\n await refreshAuth();\n },\n });\n}\n"],"names":["apiRequest","listUserWorkspaces","userWorkspacesQueryKey","useMutation","useRefreshAuth","createWorkspace","body","method","useCreateWorkspaceAuth","refreshAuth","mutationFn","onSuccess"],"mappings":"AACA,SAAQA,UAAU,QAAO,sBAAsB;AAC/C,SAAQC,kBAAkB,EAAEC,sBAAsB,QAAO,gCAAgC;AACzF,SAAQC,WAAW,QAAO,wBAAwB;AAClD,SAAQC,cAAc,QAAO,oBAAoB;AAEjD,OAAO,eAAeC,gBAAgBC,IAA4B;IAChE,OAAO,MAAMN,WAAiC,eAAe;QAACO,QAAQ;QAAQD;IAAI;AACpF;AAEA,SAAQL,kBAAkB,EAAEC,sBAAsB,GAAE;AAEpD,OAAO,SAASM;IACd,MAAMC,cAAcL;IAEpB,OAAOD,YAAY;QACjBO,YAAYL;QACZM,WAAW;YACT,sEAAsE;YACtE,oEAAoE;YACpE,kEAAkE;YAClE,MAAMF;QACR;IACF;AACF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { useLoginAuth } from './api/login-auth.js';
|
|
2
|
+
export { useLogoutAuth } from './api/logout-auth.js';
|
|
3
|
+
export { useConfirmPasswordResetAuth, useRequestPasswordResetAuth, } from './api/password-reset-auth.js';
|
|
4
|
+
export { useRefreshAuth } from './api/refresh-auth.js';
|
|
5
|
+
export { useSignupAuth } from './api/signup-auth.js';
|
|
6
|
+
export { useResendEmailVerificationAuth, useVerifyEmailAuth } from './api/verify-email-auth.js';
|
|
7
|
+
export { useCreateWorkspaceAuth } from './api/workspace-auth.js';
|
|
8
|
+
export { useActiveWorkspace, useMaybeActiveWorkspace } from './use-active-workspace.js';
|
|
9
|
+
export type { AuthStateValue } from './use-auth-state.js';
|
|
10
|
+
export { useAuthState } from './use-auth-state.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAC,aAAa,EAAC,MAAM,sBAAsB,CAAC;AACnD,OAAO,EACL,2BAA2B,EAC3B,2BAA2B,GAC5B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAC,cAAc,EAAC,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAC,aAAa,EAAC,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAC,8BAA8B,EAAE,kBAAkB,EAAC,MAAM,4BAA4B,CAAC;AAC9F,OAAO,EAAC,sBAAsB,EAAC,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAC,kBAAkB,EAAE,uBAAuB,EAAC,MAAM,2BAA2B,CAAC;AACtF,YAAY,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAC,YAAY,EAAC,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { useLoginAuth } from './api/login-auth.js';
|
|
2
|
+
export { useLogoutAuth } from './api/logout-auth.js';
|
|
3
|
+
export { useConfirmPasswordResetAuth, useRequestPasswordResetAuth } from './api/password-reset-auth.js';
|
|
4
|
+
export { useRefreshAuth } from './api/refresh-auth.js';
|
|
5
|
+
export { useSignupAuth } from './api/signup-auth.js';
|
|
6
|
+
export { useResendEmailVerificationAuth, useVerifyEmailAuth } from './api/verify-email-auth.js';
|
|
7
|
+
export { useCreateWorkspaceAuth } from './api/workspace-auth.js';
|
|
8
|
+
export { useActiveWorkspace, useMaybeActiveWorkspace } from './use-active-workspace.js';
|
|
9
|
+
export { useAuthState } from './use-auth-state.js';
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/index.ts"],"sourcesContent":["export {useLoginAuth} from './api/login-auth.js';\nexport {useLogoutAuth} from './api/logout-auth.js';\nexport {\n useConfirmPasswordResetAuth,\n useRequestPasswordResetAuth,\n} from './api/password-reset-auth.js';\nexport {useRefreshAuth} from './api/refresh-auth.js';\nexport {useSignupAuth} from './api/signup-auth.js';\nexport {useResendEmailVerificationAuth, useVerifyEmailAuth} from './api/verify-email-auth.js';\nexport {useCreateWorkspaceAuth} from './api/workspace-auth.js';\nexport {useActiveWorkspace, useMaybeActiveWorkspace} from './use-active-workspace.js';\nexport type {AuthStateValue} from './use-auth-state.js';\nexport {useAuthState} from './use-auth-state.js';\n"],"names":["useLoginAuth","useLogoutAuth","useConfirmPasswordResetAuth","useRequestPasswordResetAuth","useRefreshAuth","useSignupAuth","useResendEmailVerificationAuth","useVerifyEmailAuth","useCreateWorkspaceAuth","useActiveWorkspace","useMaybeActiveWorkspace","useAuthState"],"mappings":"AAAA,SAAQA,YAAY,QAAO,sBAAsB;AACjD,SAAQC,aAAa,QAAO,uBAAuB;AACnD,SACEC,2BAA2B,EAC3BC,2BAA2B,QACtB,+BAA+B;AACtC,SAAQC,cAAc,QAAO,wBAAwB;AACrD,SAAQC,aAAa,QAAO,uBAAuB;AACnD,SAAQC,8BAA8B,EAAEC,kBAAkB,QAAO,6BAA6B;AAC9F,SAAQC,sBAAsB,QAAO,0BAA0B;AAC/D,SAAQC,kBAAkB,EAAEC,uBAAuB,QAAO,4BAA4B;AAEtF,SAAQC,YAAY,QAAO,sBAAsB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-active-workspace.d.ts","sourceRoot":"","sources":["../../src/hooks/use-active-workspace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,kBAAkB,EAAE,uBAAuB,EAAC,MAAM,+BAA+B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/use-active-workspace.ts"],"sourcesContent":["export {useActiveWorkspace, useMaybeActiveWorkspace} from '@shipfox/client-shell/runtime';\n"],"names":["useActiveWorkspace","useMaybeActiveWorkspace"],"mappings":"AAAA,SAAQA,kBAAkB,EAAEC,uBAAuB,QAAO,gCAAgC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-auth-state.d.ts","sourceRoot":"","sources":["../../src/hooks/use-auth-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,cAAc,EAAE,YAAY,EAAC,MAAM,+BAA+B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/use-auth-state.ts"],"sourcesContent":["export {type AuthStateValue, useAuthState} from '@shipfox/client-shell/runtime';\n"],"names":["useAuthState"],"mappings":"AAAA,SAA6BA,YAAY,QAAO,gCAAgC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from './components/auth-guard.js';
|
|
2
|
+
export * from './components/auth-provider.js';
|
|
3
|
+
export * from './components/auth-shell.js';
|
|
4
|
+
export { WorkspaceCrumb, type WorkspaceCrumbProps } from './components/workspace-crumb.js';
|
|
5
|
+
export { WorkspaceSwitcher, type WorkspaceSwitcherProps } from './components/workspace-switcher.js';
|
|
6
|
+
export * from './hooks/index.js';
|
|
7
|
+
export * from './pages/login-page.js';
|
|
8
|
+
export * from './pages/logout-page.js';
|
|
9
|
+
export * from './pages/password-reset-page.js';
|
|
10
|
+
export * from './pages/signup-page.js';
|
|
11
|
+
export * from './pages/verify-email-page.js';
|
|
12
|
+
export * from './pages/workspace-onboarding-page.js';
|
|
13
|
+
export * from './state/auth.js';
|
|
14
|
+
export { getLastWorkspaceId, lastWorkspaceIdAtom, rememberLastWorkspaceId, } from './state/last-workspace.js';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAAC,cAAc,EAAE,KAAK,mBAAmB,EAAC,MAAM,iCAAiC,CAAC;AACzF,OAAO,EAAC,iBAAiB,EAAE,KAAK,sBAAsB,EAAC,MAAM,oCAAoC,CAAC;AAClG,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sCAAsC,CAAC;AACrD,cAAc,iBAAiB,CAAC;AAChC,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,2BAA2B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export * from './components/auth-guard.js';
|
|
2
|
+
export * from './components/auth-provider.js';
|
|
3
|
+
export * from './components/auth-shell.js';
|
|
4
|
+
export { WorkspaceCrumb } from './components/workspace-crumb.js';
|
|
5
|
+
export { WorkspaceSwitcher } from './components/workspace-switcher.js';
|
|
6
|
+
export * from './hooks/index.js';
|
|
7
|
+
export * from './pages/login-page.js';
|
|
8
|
+
export * from './pages/logout-page.js';
|
|
9
|
+
export * from './pages/password-reset-page.js';
|
|
10
|
+
export * from './pages/signup-page.js';
|
|
11
|
+
export * from './pages/verify-email-page.js';
|
|
12
|
+
export * from './pages/workspace-onboarding-page.js';
|
|
13
|
+
export * from './state/auth.js';
|
|
14
|
+
export { getLastWorkspaceId, lastWorkspaceIdAtom, rememberLastWorkspaceId } from './state/last-workspace.js';
|
|
15
|
+
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from './components/auth-guard.js';\nexport * from './components/auth-provider.js';\nexport * from './components/auth-shell.js';\nexport {WorkspaceCrumb, type WorkspaceCrumbProps} from './components/workspace-crumb.js';\nexport {WorkspaceSwitcher, type WorkspaceSwitcherProps} from './components/workspace-switcher.js';\nexport * from './hooks/index.js';\nexport * from './pages/login-page.js';\nexport * from './pages/logout-page.js';\nexport * from './pages/password-reset-page.js';\nexport * from './pages/signup-page.js';\nexport * from './pages/verify-email-page.js';\nexport * from './pages/workspace-onboarding-page.js';\nexport * from './state/auth.js';\nexport {\n getLastWorkspaceId,\n lastWorkspaceIdAtom,\n rememberLastWorkspaceId,\n} from './state/last-workspace.js';\n"],"names":["WorkspaceCrumb","WorkspaceSwitcher","getLastWorkspaceId","lastWorkspaceIdAtom","rememberLastWorkspaceId"],"mappings":"AAAA,cAAc,6BAA6B;AAC3C,cAAc,gCAAgC;AAC9C,cAAc,6BAA6B;AAC3C,SAAQA,cAAc,QAAiC,kCAAkC;AACzF,SAAQC,iBAAiB,QAAoC,qCAAqC;AAClG,cAAc,mBAAmB;AACjC,cAAc,wBAAwB;AACtC,cAAc,yBAAyB;AACvC,cAAc,iCAAiC;AAC/C,cAAc,yBAAyB;AACvC,cAAc,+BAA+B;AAC7C,cAAc,uCAAuC;AACrD,cAAc,kBAAkB;AAChC,SACEC,kBAAkB,EAClBC,mBAAmB,EACnBC,uBAAuB,QAClB,4BAA4B"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function getLocalResendAvailableAt(now: number): number;
|
|
2
|
+
export declare function getResendRemainingSeconds(params: {
|
|
3
|
+
nextResendAvailableAt: number | undefined;
|
|
4
|
+
now: number;
|
|
5
|
+
}): number;
|
|
6
|
+
export declare function parseNextResendAvailableAt(value: string): number | undefined;
|
|
7
|
+
//# sourceMappingURL=email-verification-resend-model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-verification-resend-model.d.ts","sourceRoot":"","sources":["../../src/pages/email-verification-resend-model.ts"],"names":[],"mappings":"AAEA,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE;IAChD,qBAAqB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,GAAG,EAAE,MAAM,CAAC;CACb,GAAG,MAAM,CAIT;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAK5E"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { EMAIL_VERIFICATION_RESEND_COOLDOWN_SECONDS } from '@shipfox/api-auth-dto';
|
|
2
|
+
export function getLocalResendAvailableAt(now) {
|
|
3
|
+
return now + EMAIL_VERIFICATION_RESEND_COOLDOWN_SECONDS * 1000;
|
|
4
|
+
}
|
|
5
|
+
export function getResendRemainingSeconds(params) {
|
|
6
|
+
if (!params.nextResendAvailableAt) return 0;
|
|
7
|
+
return Math.max(0, Math.ceil((params.nextResendAvailableAt - params.now) / 1000));
|
|
8
|
+
}
|
|
9
|
+
export function parseNextResendAvailableAt(value) {
|
|
10
|
+
const nextAvailableAt = Date.parse(value);
|
|
11
|
+
if (!Number.isFinite(nextAvailableAt)) return undefined;
|
|
12
|
+
return nextAvailableAt;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=email-verification-resend-model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/pages/email-verification-resend-model.ts"],"sourcesContent":["import {EMAIL_VERIFICATION_RESEND_COOLDOWN_SECONDS} from '@shipfox/api-auth-dto';\n\nexport function getLocalResendAvailableAt(now: number): number {\n return now + EMAIL_VERIFICATION_RESEND_COOLDOWN_SECONDS * 1000;\n}\n\nexport function getResendRemainingSeconds(params: {\n nextResendAvailableAt: number | undefined;\n now: number;\n}): number {\n if (!params.nextResendAvailableAt) return 0;\n\n return Math.max(0, Math.ceil((params.nextResendAvailableAt - params.now) / 1000));\n}\n\nexport function parseNextResendAvailableAt(value: string): number | undefined {\n const nextAvailableAt = Date.parse(value);\n if (!Number.isFinite(nextAvailableAt)) return undefined;\n\n return nextAvailableAt;\n}\n"],"names":["EMAIL_VERIFICATION_RESEND_COOLDOWN_SECONDS","getLocalResendAvailableAt","now","getResendRemainingSeconds","params","nextResendAvailableAt","Math","max","ceil","parseNextResendAvailableAt","value","nextAvailableAt","Date","parse","Number","isFinite","undefined"],"mappings":"AAAA,SAAQA,0CAA0C,QAAO,wBAAwB;AAEjF,OAAO,SAASC,0BAA0BC,GAAW;IACnD,OAAOA,MAAMF,6CAA6C;AAC5D;AAEA,OAAO,SAASG,0BAA0BC,MAGzC;IACC,IAAI,CAACA,OAAOC,qBAAqB,EAAE,OAAO;IAE1C,OAAOC,KAAKC,GAAG,CAAC,GAAGD,KAAKE,IAAI,CAAC,AAACJ,CAAAA,OAAOC,qBAAqB,GAAGD,OAAOF,GAAG,AAAD,IAAK;AAC7E;AAEA,OAAO,SAASO,2BAA2BC,KAAa;IACtD,MAAMC,kBAAkBC,KAAKC,KAAK,CAACH;IACnC,IAAI,CAACI,OAAOC,QAAQ,CAACJ,kBAAkB,OAAOK;IAE9C,OAAOL;AACT"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type FormErrorMapping<TField extends string> = {
|
|
2
|
+
kind: 'field';
|
|
3
|
+
field: TField;
|
|
4
|
+
message: string;
|
|
5
|
+
} | {
|
|
6
|
+
kind: 'form';
|
|
7
|
+
message: string;
|
|
8
|
+
};
|
|
9
|
+
type LoginField = 'email' | 'password';
|
|
10
|
+
type SignupField = 'email' | 'password' | 'name';
|
|
11
|
+
type PasswordResetRequestField = 'email';
|
|
12
|
+
type PasswordResetConfirmField = 'new_password';
|
|
13
|
+
export declare function loginErrorToFormError(error: unknown): FormErrorMapping<LoginField>;
|
|
14
|
+
export declare function signupErrorToFormError(error: unknown): FormErrorMapping<SignupField>;
|
|
15
|
+
export declare function passwordResetRequestErrorToFormError(error: unknown): FormErrorMapping<PasswordResetRequestField>;
|
|
16
|
+
export declare function passwordResetConfirmErrorToFormError(error: unknown): FormErrorMapping<PasswordResetConfirmField>;
|
|
17
|
+
export declare function workspaceOnboardingErrorToFormError(error: unknown): FormErrorMapping<'name'>;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=form-errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form-errors.d.ts","sourceRoot":"","sources":["../../src/pages/form-errors.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,gBAAgB,CAAC,MAAM,SAAS,MAAM,IAC9C;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,GAC/C;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAAC;AAEpC,KAAK,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;AACvC,KAAK,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,CAAC;AACjD,KAAK,yBAAyB,GAAG,OAAO,CAAC;AACzC,KAAK,yBAAyB,GAAG,cAAc,CAAC;AAMhD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAKlF;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAKpF;AAED,wBAAgB,oCAAoC,CAClD,KAAK,EAAE,OAAO,GACb,gBAAgB,CAAC,yBAAyB,CAAC,CAE7C;AAED,wBAAgB,oCAAoC,CAClD,KAAK,EAAE,OAAO,GACb,gBAAgB,CAAC,yBAAyB,CAAC,CAE7C;AAED,wBAAgB,mCAAmC,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAE5F"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { ApiError } from '@shipfox/client-api';
|
|
2
|
+
import { authErrorMessage } from './form-utils.js';
|
|
3
|
+
function apiCode(error) {
|
|
4
|
+
return error instanceof ApiError ? error.code : undefined;
|
|
5
|
+
}
|
|
6
|
+
export function loginErrorToFormError(error) {
|
|
7
|
+
if (apiCode(error) === 'email-not-verified') {
|
|
8
|
+
return {
|
|
9
|
+
kind: 'field',
|
|
10
|
+
field: 'email',
|
|
11
|
+
message: authErrorMessage(error)
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
kind: 'form',
|
|
16
|
+
message: authErrorMessage(error)
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export function signupErrorToFormError(error) {
|
|
20
|
+
if (apiCode(error) === 'email-taken') {
|
|
21
|
+
return {
|
|
22
|
+
kind: 'field',
|
|
23
|
+
field: 'email',
|
|
24
|
+
message: authErrorMessage(error)
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
kind: 'form',
|
|
29
|
+
message: authErrorMessage(error)
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export function passwordResetRequestErrorToFormError(error) {
|
|
33
|
+
return {
|
|
34
|
+
kind: 'form',
|
|
35
|
+
message: authErrorMessage(error)
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export function passwordResetConfirmErrorToFormError(error) {
|
|
39
|
+
return {
|
|
40
|
+
kind: 'form',
|
|
41
|
+
message: authErrorMessage(error)
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export function workspaceOnboardingErrorToFormError(error) {
|
|
45
|
+
return {
|
|
46
|
+
kind: 'form',
|
|
47
|
+
message: authErrorMessage(error)
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
//# sourceMappingURL=form-errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/pages/form-errors.ts"],"sourcesContent":["import {ApiError} from '@shipfox/client-api';\nimport {authErrorMessage} from './form-utils.js';\n\nexport type FormErrorMapping<TField extends string> =\n | {kind: 'field'; field: TField; message: string}\n | {kind: 'form'; message: string};\n\ntype LoginField = 'email' | 'password';\ntype SignupField = 'email' | 'password' | 'name';\ntype PasswordResetRequestField = 'email';\ntype PasswordResetConfirmField = 'new_password';\n\nfunction apiCode(error: unknown): string | undefined {\n return error instanceof ApiError ? error.code : undefined;\n}\n\nexport function loginErrorToFormError(error: unknown): FormErrorMapping<LoginField> {\n if (apiCode(error) === 'email-not-verified') {\n return {kind: 'field', field: 'email', message: authErrorMessage(error)};\n }\n return {kind: 'form', message: authErrorMessage(error)};\n}\n\nexport function signupErrorToFormError(error: unknown): FormErrorMapping<SignupField> {\n if (apiCode(error) === 'email-taken') {\n return {kind: 'field', field: 'email', message: authErrorMessage(error)};\n }\n return {kind: 'form', message: authErrorMessage(error)};\n}\n\nexport function passwordResetRequestErrorToFormError(\n error: unknown,\n): FormErrorMapping<PasswordResetRequestField> {\n return {kind: 'form', message: authErrorMessage(error)};\n}\n\nexport function passwordResetConfirmErrorToFormError(\n error: unknown,\n): FormErrorMapping<PasswordResetConfirmField> {\n return {kind: 'form', message: authErrorMessage(error)};\n}\n\nexport function workspaceOnboardingErrorToFormError(error: unknown): FormErrorMapping<'name'> {\n return {kind: 'form', message: authErrorMessage(error)};\n}\n"],"names":["ApiError","authErrorMessage","apiCode","error","code","undefined","loginErrorToFormError","kind","field","message","signupErrorToFormError","passwordResetRequestErrorToFormError","passwordResetConfirmErrorToFormError","workspaceOnboardingErrorToFormError"],"mappings":"AAAA,SAAQA,QAAQ,QAAO,sBAAsB;AAC7C,SAAQC,gBAAgB,QAAO,kBAAkB;AAWjD,SAASC,QAAQC,KAAc;IAC7B,OAAOA,iBAAiBH,WAAWG,MAAMC,IAAI,GAAGC;AAClD;AAEA,OAAO,SAASC,sBAAsBH,KAAc;IAClD,IAAID,QAAQC,WAAW,sBAAsB;QAC3C,OAAO;YAACI,MAAM;YAASC,OAAO;YAASC,SAASR,iBAAiBE;QAAM;IACzE;IACA,OAAO;QAACI,MAAM;QAAQE,SAASR,iBAAiBE;IAAM;AACxD;AAEA,OAAO,SAASO,uBAAuBP,KAAc;IACnD,IAAID,QAAQC,WAAW,eAAe;QACpC,OAAO;YAACI,MAAM;YAASC,OAAO;YAASC,SAASR,iBAAiBE;QAAM;IACzE;IACA,OAAO;QAACI,MAAM;QAAQE,SAASR,iBAAiBE;IAAM;AACxD;AAEA,OAAO,SAASQ,qCACdR,KAAc;IAEd,OAAO;QAACI,MAAM;QAAQE,SAASR,iBAAiBE;IAAM;AACxD;AAEA,OAAO,SAASS,qCACdT,KAAc;IAEd,OAAO;QAACI,MAAM;QAAQE,SAASR,iBAAiBE;IAAM;AACxD;AAEA,OAAO,SAASU,oCAAoCV,KAAc;IAChE,OAAO;QAACI,MAAM;QAAQE,SAASR,iBAAiBE;IAAM;AACxD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form-utils.d.ts","sourceRoot":"","sources":["../../src/pages/form-utils.ts"],"names":[],"mappings":"AAEA,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CA0BvD"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ApiError } from '@shipfox/client-api';
|
|
2
|
+
export function authErrorMessage(error) {
|
|
3
|
+
if (!(error instanceof ApiError)) return 'Something went wrong. Try again.';
|
|
4
|
+
if (error.code === 'invalid-credentials') {
|
|
5
|
+
return 'Email or password is incorrect.';
|
|
6
|
+
}
|
|
7
|
+
if (error.code === 'email-not-verified') {
|
|
8
|
+
return 'Verify your email before signing in.';
|
|
9
|
+
}
|
|
10
|
+
if (error.code === 'email-taken') {
|
|
11
|
+
return 'An account already exists for this email.';
|
|
12
|
+
}
|
|
13
|
+
if (error.code === 'token-invalid') {
|
|
14
|
+
return 'This link is invalid or expired.';
|
|
15
|
+
}
|
|
16
|
+
if (error.code === 'rate-limited') {
|
|
17
|
+
return 'Too many attempts. Wait a bit and try again.';
|
|
18
|
+
}
|
|
19
|
+
if (error.code === 'auth-rate-limit-unavailable') {
|
|
20
|
+
return 'Sign-in protection is temporarily unavailable. Try again soon.';
|
|
21
|
+
}
|
|
22
|
+
if (error.code === 'network-error') {
|
|
23
|
+
return 'We could not reach the API. Check your connection and try again.';
|
|
24
|
+
}
|
|
25
|
+
return error.message || 'Something went wrong. Try again.';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
//# sourceMappingURL=form-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/pages/form-utils.ts"],"sourcesContent":["import {ApiError} from '@shipfox/client-api';\n\nexport function authErrorMessage(error: unknown): string {\n if (!(error instanceof ApiError)) return 'Something went wrong. Try again.';\n\n if (error.code === 'invalid-credentials') {\n return 'Email or password is incorrect.';\n }\n if (error.code === 'email-not-verified') {\n return 'Verify your email before signing in.';\n }\n if (error.code === 'email-taken') {\n return 'An account already exists for this email.';\n }\n if (error.code === 'token-invalid') {\n return 'This link is invalid or expired.';\n }\n if (error.code === 'rate-limited') {\n return 'Too many attempts. Wait a bit and try again.';\n }\n if (error.code === 'auth-rate-limit-unavailable') {\n return 'Sign-in protection is temporarily unavailable. Try again soon.';\n }\n if (error.code === 'network-error') {\n return 'We could not reach the API. Check your connection and try again.';\n }\n\n return error.message || 'Something went wrong. Try again.';\n}\n"],"names":["ApiError","authErrorMessage","error","code","message"],"mappings":"AAAA,SAAQA,QAAQ,QAAO,sBAAsB;AAE7C,OAAO,SAASC,iBAAiBC,KAAc;IAC7C,IAAI,CAAEA,CAAAA,iBAAiBF,QAAO,GAAI,OAAO;IAEzC,IAAIE,MAAMC,IAAI,KAAK,uBAAuB;QACxC,OAAO;IACT;IACA,IAAID,MAAMC,IAAI,KAAK,sBAAsB;QACvC,OAAO;IACT;IACA,IAAID,MAAMC,IAAI,KAAK,eAAe;QAChC,OAAO;IACT;IACA,IAAID,MAAMC,IAAI,KAAK,iBAAiB;QAClC,OAAO;IACT;IACA,IAAID,MAAMC,IAAI,KAAK,gBAAgB;QACjC,OAAO;IACT;IACA,IAAID,MAAMC,IAAI,KAAK,+BAA+B;QAChD,OAAO;IACT;IACA,IAAID,MAAMC,IAAI,KAAK,iBAAiB;QAClC,OAAO;IACT;IAEA,OAAOD,MAAME,OAAO,IAAI;AAC1B"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { PreviewInvitationPendingDto, PreviewInvitationResponseDto } from '@shipfox/api-workspaces-dto';
|
|
2
|
+
/**
|
|
3
|
+
* Extract an invitation token from a `redirect=` URL if it points at the
|
|
4
|
+
* canonical pre-auth invitation page. Returns undefined when the redirect is
|
|
5
|
+
* absent, malformed, or unrelated to invitations.
|
|
6
|
+
*/
|
|
7
|
+
export declare function extractInvitationToken(redirect: unknown): string | undefined;
|
|
8
|
+
export declare function pendingInvitation(data: PreviewInvitationResponseDto | undefined): PreviewInvitationPendingDto | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Mirrors the hook in `@shipfox/client-invitations` but lives in `client-auth`
|
|
11
|
+
* to avoid a circular dependency. Signup/login pages call this to lock the
|
|
12
|
+
* email field when arriving from an invitation link.
|
|
13
|
+
*/
|
|
14
|
+
export declare function useInvitationContext(token: string | undefined): import("@tanstack/react-query").UseQueryResult<NoInfer<{
|
|
15
|
+
status: "pending";
|
|
16
|
+
workspace_id: string;
|
|
17
|
+
workspace_name: string;
|
|
18
|
+
email: string;
|
|
19
|
+
invited_by_display: string | null;
|
|
20
|
+
expires_at: string;
|
|
21
|
+
} | {
|
|
22
|
+
status: "expired";
|
|
23
|
+
workspace_name: string;
|
|
24
|
+
expires_at: string;
|
|
25
|
+
} | {
|
|
26
|
+
status: "already_used";
|
|
27
|
+
workspace_name: string;
|
|
28
|
+
} | {
|
|
29
|
+
status: "invalid";
|
|
30
|
+
}>, Error>;
|
|
31
|
+
//# sourceMappingURL=invitation-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invitation-context.d.ts","sourceRoot":"","sources":["../../src/pages/invitation-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,2BAA2B,EAC3B,4BAA4B,EAC7B,MAAM,6BAA6B,CAAC;AAMrC;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAc5E;AASD,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,4BAA4B,GAAG,SAAS,GAC7C,2BAA2B,GAAG,SAAS,CAEzC;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS;;;;;;;;;;;;;;;;WAQ7D"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { apiRequest } from '@shipfox/client-api';
|
|
2
|
+
import { useQuery } from '@tanstack/react-query';
|
|
3
|
+
const INVITATION_ACCEPT_PATH = '/invitations/accept';
|
|
4
|
+
/**
|
|
5
|
+
* Extract an invitation token from a `redirect=` URL if it points at the
|
|
6
|
+
* canonical pre-auth invitation page. Returns undefined when the redirect is
|
|
7
|
+
* absent, malformed, or unrelated to invitations.
|
|
8
|
+
*/ export function extractInvitationToken(redirect) {
|
|
9
|
+
if (typeof redirect !== 'string') return undefined;
|
|
10
|
+
let decoded;
|
|
11
|
+
try {
|
|
12
|
+
decoded = decodeURIComponent(redirect);
|
|
13
|
+
} catch {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
if (!decoded.startsWith('/')) return undefined;
|
|
17
|
+
const [path, queryString = ''] = decoded.split('?', 2);
|
|
18
|
+
if (path !== INVITATION_ACCEPT_PATH) return undefined;
|
|
19
|
+
const params = new URLSearchParams(queryString);
|
|
20
|
+
const token = params.get('token');
|
|
21
|
+
return token && token.length > 0 ? token : undefined;
|
|
22
|
+
}
|
|
23
|
+
async function fetchPreview(token) {
|
|
24
|
+
const params = new URLSearchParams({
|
|
25
|
+
token
|
|
26
|
+
});
|
|
27
|
+
return await apiRequest(`/invitations/preview?${params.toString()}`);
|
|
28
|
+
}
|
|
29
|
+
export function pendingInvitation(data) {
|
|
30
|
+
return data?.status === 'pending' ? data : undefined;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Mirrors the hook in `@shipfox/client-invitations` but lives in `client-auth`
|
|
34
|
+
* to avoid a circular dependency. Signup/login pages call this to lock the
|
|
35
|
+
* email field when arriving from an invitation link.
|
|
36
|
+
*/ export function useInvitationContext(token) {
|
|
37
|
+
return useQuery({
|
|
38
|
+
queryKey: [
|
|
39
|
+
'invitations',
|
|
40
|
+
'preview',
|
|
41
|
+
token ?? ''
|
|
42
|
+
],
|
|
43
|
+
queryFn: ()=>fetchPreview(token),
|
|
44
|
+
enabled: Boolean(token),
|
|
45
|
+
retry: false,
|
|
46
|
+
staleTime: 30_000
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
//# sourceMappingURL=invitation-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/pages/invitation-context.ts"],"sourcesContent":["import type {\n PreviewInvitationPendingDto,\n PreviewInvitationResponseDto,\n} from '@shipfox/api-workspaces-dto';\nimport {apiRequest} from '@shipfox/client-api';\nimport {useQuery} from '@tanstack/react-query';\n\nconst INVITATION_ACCEPT_PATH = '/invitations/accept';\n\n/**\n * Extract an invitation token from a `redirect=` URL if it points at the\n * canonical pre-auth invitation page. Returns undefined when the redirect is\n * absent, malformed, or unrelated to invitations.\n */\nexport function extractInvitationToken(redirect: unknown): string | undefined {\n if (typeof redirect !== 'string') return undefined;\n let decoded: string;\n try {\n decoded = decodeURIComponent(redirect);\n } catch {\n return undefined;\n }\n if (!decoded.startsWith('/')) return undefined;\n const [path, queryString = ''] = decoded.split('?', 2);\n if (path !== INVITATION_ACCEPT_PATH) return undefined;\n const params = new URLSearchParams(queryString);\n const token = params.get('token');\n return token && token.length > 0 ? token : undefined;\n}\n\nasync function fetchPreview(token: string): Promise<PreviewInvitationResponseDto> {\n const params = new URLSearchParams({token});\n return await apiRequest<PreviewInvitationResponseDto>(\n `/invitations/preview?${params.toString()}`,\n );\n}\n\nexport function pendingInvitation(\n data: PreviewInvitationResponseDto | undefined,\n): PreviewInvitationPendingDto | undefined {\n return data?.status === 'pending' ? data : undefined;\n}\n\n/**\n * Mirrors the hook in `@shipfox/client-invitations` but lives in `client-auth`\n * to avoid a circular dependency. Signup/login pages call this to lock the\n * email field when arriving from an invitation link.\n */\nexport function useInvitationContext(token: string | undefined) {\n return useQuery({\n queryKey: ['invitations', 'preview', token ?? ''] as const,\n queryFn: () => fetchPreview(token as string),\n enabled: Boolean(token),\n retry: false,\n staleTime: 30_000,\n });\n}\n"],"names":["apiRequest","useQuery","INVITATION_ACCEPT_PATH","extractInvitationToken","redirect","undefined","decoded","decodeURIComponent","startsWith","path","queryString","split","params","URLSearchParams","token","get","length","fetchPreview","toString","pendingInvitation","data","status","useInvitationContext","queryKey","queryFn","enabled","Boolean","retry","staleTime"],"mappings":"AAIA,SAAQA,UAAU,QAAO,sBAAsB;AAC/C,SAAQC,QAAQ,QAAO,wBAAwB;AAE/C,MAAMC,yBAAyB;AAE/B;;;;CAIC,GACD,OAAO,SAASC,uBAAuBC,QAAiB;IACtD,IAAI,OAAOA,aAAa,UAAU,OAAOC;IACzC,IAAIC;IACJ,IAAI;QACFA,UAAUC,mBAAmBH;IAC/B,EAAE,OAAM;QACN,OAAOC;IACT;IACA,IAAI,CAACC,QAAQE,UAAU,CAAC,MAAM,OAAOH;IACrC,MAAM,CAACI,MAAMC,cAAc,EAAE,CAAC,GAAGJ,QAAQK,KAAK,CAAC,KAAK;IACpD,IAAIF,SAASP,wBAAwB,OAAOG;IAC5C,MAAMO,SAAS,IAAIC,gBAAgBH;IACnC,MAAMI,QAAQF,OAAOG,GAAG,CAAC;IACzB,OAAOD,SAASA,MAAME,MAAM,GAAG,IAAIF,QAAQT;AAC7C;AAEA,eAAeY,aAAaH,KAAa;IACvC,MAAMF,SAAS,IAAIC,gBAAgB;QAACC;IAAK;IACzC,OAAO,MAAMd,WACX,CAAC,qBAAqB,EAAEY,OAAOM,QAAQ,IAAI;AAE/C;AAEA,OAAO,SAASC,kBACdC,IAA8C;IAE9C,OAAOA,MAAMC,WAAW,YAAYD,OAAOf;AAC7C;AAEA;;;;CAIC,GACD,OAAO,SAASiB,qBAAqBR,KAAyB;IAC5D,OAAOb,SAAS;QACdsB,UAAU;YAAC;YAAe;YAAWT,SAAS;SAAG;QACjDU,SAAS,IAAMP,aAAaH;QAC5BW,SAASC,QAAQZ;QACjBa,OAAO;QACPC,WAAW;IACb;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login-page.d.ts","sourceRoot":"","sources":["../../src/pages/login-page.tsx"],"names":[],"mappings":"AAoBA,wBAAgB,SAAS,gCAmKxB"}
|