@softr/sdk 0.0.63 → 0.0.64-alpha.1

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 (38) hide show
  1. package/dist/auth/isomorphic.d.ts +63 -4
  2. package/dist/auth/isomorphic.js +63 -5
  3. package/dist/auth/methods/passwordLink.d.ts +47 -0
  4. package/dist/auth/methods/passwordLink.js +86 -0
  5. package/dist/auth/methods/settings.d.ts +11 -0
  6. package/dist/auth/methods/settings.js +17 -0
  7. package/dist/auth/methods/signup.js +1 -0
  8. package/dist/auth/methods/social.js +1 -0
  9. package/dist/auth/methods/utils.d.ts +1 -1
  10. package/dist/auth/platform.d.ts +46 -0
  11. package/dist/auth/platform.js +54 -0
  12. package/dist/auth/server.d.ts +6 -0
  13. package/dist/auth/server.js +7 -1
  14. package/dist/index.d.ts +4 -3
  15. package/dist/index.js +3 -3
  16. package/dist/mcp.d.ts +2 -8
  17. package/dist/mcp.js +8 -8
  18. package/dist/package.js +1 -1
  19. package/dist/softr-config.d.ts +1 -0
  20. package/dist/softr-config.js +26 -5
  21. package/dist/visibility/route.d.ts +34 -6
  22. package/dist/visibility/route.js +55 -13
  23. package/package.json +33 -10
  24. package/schema/softr.schema.json +42 -1
  25. package/skills/softr-sdk/SKILL.md +4 -3
  26. package/skills/softr-sdk/auth/SKILL.md +131 -31
  27. package/skills/softr-sdk/charts-and-metrics/SKILL.md +1 -1
  28. package/skills/softr-sdk/current-user/SKILL.md +1 -1
  29. package/skills/softr-sdk/file-uploads/SKILL.md +1 -1
  30. package/skills/softr-sdk/formatting/SKILL.md +4 -4
  31. package/skills/softr-sdk/integrations/SKILL.md +1 -1
  32. package/skills/softr-sdk/mcp/SKILL.md +7 -14
  33. package/skills/softr-sdk/pwa/SKILL.md +3 -3
  34. package/skills/softr-sdk/record-mutations/SKILL.md +1 -1
  35. package/skills/softr-sdk/record-queries/SKILL.md +1 -1
  36. package/skills/softr-sdk/region-visibility/SKILL.md +1 -1
  37. package/skills/softr-sdk/routes-and-visibility/SKILL.md +24 -12
  38. package/skills/softr-sdk/workflows/SKILL.md +1 -1
@@ -2,7 +2,9 @@ import { User } from "./user.js";
2
2
  import { Formatting } from "../formatting.js";
3
3
  import { Permissions } from "./permissions.js";
4
4
  import { SoftrContext } from "./context.js";
5
- import * as _tanstack_react_start0 from "@tanstack/react-start";
5
+ import * as react6 from "react";
6
+ import { ReactNode } from "react";
7
+ import * as _tanstack_react_start1 from "@tanstack/react-start";
6
8
 
7
9
  //#region src/auth/isomorphic.d.ts
8
10
 
@@ -19,7 +21,7 @@ import * as _tanstack_react_start0 from "@tanstack/react-start";
19
21
  * requestMiddleware: [softrAuthMiddleware()],
20
22
  * }))
21
23
  */
22
- declare function softrAuthMiddleware(): _tanstack_react_start0.RequestMiddlewareAfterServer<{}, readonly [_tanstack_react_start0.RequestMiddlewareAfterServer<{}, undefined, undefined>, _tanstack_react_start0.RequestMiddlewareAfterServer<{}, undefined, undefined>], {
24
+ declare function softrAuthMiddleware(): _tanstack_react_start1.RequestMiddlewareAfterServer<{}, readonly [_tanstack_react_start1.RequestMiddlewareAfterServer<{}, undefined, undefined>, _tanstack_react_start1.RequestMiddlewareAfterServer<{}, undefined, undefined>], {
23
25
  user: User | null;
24
26
  permissions: Permissions;
25
27
  formatting: Formatting;
@@ -33,7 +35,7 @@ declare function softrAuthMiddleware(): _tanstack_react_start0.RequestMiddleware
33
35
  * beforeLoad: async () => await getSoftrContext(),
34
36
  * })
35
37
  */
36
- declare const getSoftrContext: _tanstack_react_start0.OptionalFetcher<undefined, undefined, Promise<SoftrContext>>;
38
+ declare const getSoftrContext: _tanstack_react_start1.OptionalFetcher<undefined, undefined, Promise<SoftrContext>>;
37
39
  /**
38
40
  * The context to hand `createRouter`, before any request has resolved one.
39
41
  *
@@ -54,5 +56,62 @@ declare function initialSoftrContext(): SoftrContext;
54
56
  * }
55
57
  */
56
58
  declare function useCurrentUser(): User | null;
59
+ /** Which ways in this app offers, each named for the `auth` call it unlocks. */
60
+ type AuthOptions = {
61
+ /** `auth.signIn` */
62
+ password: boolean;
63
+ /** `auth.sendSignInCode`, then `auth.signInWithCode` */
64
+ emailCode: boolean;
65
+ /** `auth.signInWithMagicLink` */
66
+ magicLink: boolean;
67
+ /** `auth.signInWithGoogle`, with the client id to start Google sign-in with. */
68
+ google: {
69
+ clientId: string;
70
+ } | null;
71
+ /** `auth.signUp`, then `auth.confirmSignUp` */
72
+ signUp: boolean;
73
+ /** The builder asked for strong passwords whenever a visitor sets one. */
74
+ strongPasswords: boolean;
75
+ };
76
+ /**
77
+ * Loads the app's {@link AuthOptions}. Call it from the auth layout's loader
78
+ * and hand the result to {@link AuthSettingsProvider}.
79
+ *
80
+ * @example
81
+ * export const Route = createFileRoute("/_auth")({
82
+ * loader: () => getAuthSettings(),
83
+ * staleTime: 60_000,
84
+ * })
85
+ */
86
+ declare const getAuthSettings: _tanstack_react_start1.OptionalFetcher<undefined, undefined, Promise<AuthOptions>>;
87
+ /**
88
+ * Makes the auth options readable with {@link useAuthSettings} anywhere below.
89
+ *
90
+ * @example
91
+ * function AuthLayout() {
92
+ * const authSettings = Route.useLoaderData()
93
+ * return (
94
+ * <AuthSettingsProvider value={authSettings}>
95
+ * <Outlet />
96
+ * </AuthSettingsProvider>
97
+ * )
98
+ * }
99
+ */
100
+ declare function AuthSettingsProvider({
101
+ value,
102
+ children
103
+ }: {
104
+ value: AuthOptions;
105
+ children?: ReactNode;
106
+ }): react6.JSX.Element;
107
+ /**
108
+ * Which ways in this app offers. Requires an {@link AuthSettingsProvider}
109
+ * above it.
110
+ *
111
+ * @example
112
+ * const options = useAuthSettings()
113
+ * return options.password && <PasswordForm />
114
+ */
115
+ declare function useAuthSettings(): AuthOptions;
57
116
  //#endregion
58
- export { getSoftrContext, initialSoftrContext, softrAuthMiddleware, useCurrentUser };
117
+ export { AuthOptions, AuthSettingsProvider, getAuthSettings, getSoftrContext, initialSoftrContext, softrAuthMiddleware, useAuthSettings, useCurrentUser };
@@ -1,17 +1,20 @@
1
- import { assert, panic } from "../assertions.js";
1
+ import { assert, panic, requireDefined } from "../assertions.js";
2
2
  import { readUserTimezone, writeCookies } from "../cookies.js";
3
3
  import { sessionConfig } from "./config.js";
4
4
  import { clearSession, makeSessionDataCookie, readSessionData, readSessionToken } from "./session.js";
5
5
  import { makePlatform } from "./platform.js";
6
6
  import { defaultFormatting, resolveFormatting } from "../formatting.js";
7
7
  import { readLocaleSettings } from "../locale-settings.js";
8
+ import { settings } from "./methods/settings.js";
8
9
  import { bootErrorMiddleware } from "../boot-error.js";
9
10
  import { pwaMiddleware } from "../pwa.js";
11
+ import { createContext, useContext } from "react";
10
12
  import { createMiddleware, createServerFn, getGlobalStartContext } from "@tanstack/react-start";
11
13
  import { getRequestHeader } from "@tanstack/react-start/server";
12
14
  import { rootRouteId, useRouteContext } from "@tanstack/react-router";
15
+ import { jsx } from "react/jsx-runtime";
13
16
 
14
- //#region src/auth/isomorphic.ts
17
+ //#region src/auth/isomorphic.tsx
15
18
  /**
16
19
  * Resolves the Softr visitor, their permissions and the app's formatting for
17
20
  * every request, so that `getSoftrContext` and the route guards have something
@@ -41,11 +44,11 @@ function softrAuthMiddleware() {
41
44
  writeCookies([makeSessionDataCookie(session, token)]);
42
45
  return session;
43
46
  }
44
- const [{ user, permissions }, settings] = await Promise.all([getSession(), readLocaleSettings()]);
47
+ const [{ user, permissions }, settings$1] = await Promise.all([getSession(), readLocaleSettings()]);
45
48
  return next({ context: {
46
49
  user,
47
50
  permissions,
48
- formatting: resolveFormatting(settings, getRequestHeader("accept-language") ?? null, readUserTimezone())
51
+ formatting: resolveFormatting(settings$1, getRequestHeader("accept-language") ?? null, readUserTimezone())
49
52
  } });
50
53
  });
51
54
  }
@@ -94,6 +97,61 @@ function useCurrentUser() {
94
97
  select: (context) => context.user
95
98
  });
96
99
  }
100
+ /**
101
+ * Loads the app's {@link AuthOptions}. Call it from the auth layout's loader
102
+ * and hand the result to {@link AuthSettingsProvider}.
103
+ *
104
+ * @example
105
+ * export const Route = createFileRoute("/_auth")({
106
+ * loader: () => getAuthSettings(),
107
+ * staleTime: 60_000,
108
+ * })
109
+ */
110
+ const getAuthSettings = createServerFn({ method: "GET" }).handler(async () => {
111
+ const raw = await settings();
112
+ const on = (method) => raw.loginEnabled && raw.authenticationMethods.includes(method);
113
+ const emailMethods = on("EMAIL") ? raw.emailAuth?.loginMethods ?? [] : [];
114
+ const clientId = raw.googleAuth?.clientId?.trim();
115
+ return {
116
+ password: emailMethods.includes("PASSWORD"),
117
+ emailCode: emailMethods.includes("EMAIL_CODE"),
118
+ magicLink: on("MAGIC_LINK"),
119
+ google: on("GOOGLE") && clientId ? { clientId } : null,
120
+ signUp: raw.loginEnabled && (raw.signUpPolicy === "OPEN_TO_PUBLIC" || raw.signUpPolicy === "DOMAIN_RESTRICTED"),
121
+ strongPasswords: on("EMAIL") && (raw.emailAuth?.strongPasswords ?? false)
122
+ };
123
+ });
124
+ const AuthSettingsContext = createContext(null);
125
+ /**
126
+ * Makes the auth options readable with {@link useAuthSettings} anywhere below.
127
+ *
128
+ * @example
129
+ * function AuthLayout() {
130
+ * const authSettings = Route.useLoaderData()
131
+ * return (
132
+ * <AuthSettingsProvider value={authSettings}>
133
+ * <Outlet />
134
+ * </AuthSettingsProvider>
135
+ * )
136
+ * }
137
+ */
138
+ function AuthSettingsProvider({ value, children }) {
139
+ return /* @__PURE__ */ jsx(AuthSettingsContext.Provider, {
140
+ value,
141
+ children
142
+ });
143
+ }
144
+ /**
145
+ * Which ways in this app offers. Requires an {@link AuthSettingsProvider}
146
+ * above it.
147
+ *
148
+ * @example
149
+ * const options = useAuthSettings()
150
+ * return options.password && <PasswordForm />
151
+ */
152
+ function useAuthSettings() {
153
+ return requireDefined(useContext(AuthSettingsContext), "useAuthSettings needs an AuthSettingsProvider above it.");
154
+ }
97
155
 
98
156
  //#endregion
99
- export { getSoftrContext, initialSoftrContext, softrAuthMiddleware, useCurrentUser };
157
+ export { AuthSettingsProvider, getAuthSettings, getSoftrContext, initialSoftrContext, softrAuthMiddleware, useAuthSettings, useCurrentUser };
@@ -0,0 +1,47 @@
1
+ import { User } from "../user.js";
2
+ import { AuthError, Result } from "./utils.js";
3
+
4
+ //#region src/auth/methods/passwordLink.d.ts
5
+
6
+ /**
7
+ * Emails a link to set a new password.
8
+ *
9
+ * Succeeds whether or not the address has an account, and sends nothing when
10
+ * it has none.
11
+ */
12
+ declare function requestPasswordReset(details: {
13
+ email: string;
14
+ }): Promise<Result<null, AuthError>>;
15
+ /**
16
+ * Checks a password reset or invitation link, and returns the address it was
17
+ * mailed to. The link stays usable.
18
+ */
19
+ declare function checkPasswordLink(details: {
20
+ token: string;
21
+ }): Promise<Result<{
22
+ email: string;
23
+ }, AuthError>>;
24
+ /**
25
+ * Sets a new password with a password reset or invitation link, and signs the
26
+ * visitor in.
27
+ *
28
+ * Any success uses up the link, `authenticatorRequired` included, and ends
29
+ * the visitor's other sessions.
30
+ */
31
+ declare function setPasswordWithLink(details: {
32
+ token: string;
33
+ password: string;
34
+ }): Promise<Result<{
35
+ status: "signedIn";
36
+ user: User;
37
+ } | {
38
+ status: "authenticatorRequired";
39
+ /**
40
+ * `verify`: they have an authenticator app and owe a code.
41
+ * `setup`: the app requires one and they have none yet.
42
+ * `setupOptional`: same, except they may skip it instead.
43
+ */
44
+ step: "verify" | "setup" | "setupOptional";
45
+ }, AuthError>>;
46
+ //#endregion
47
+ export { checkPasswordLink, requestPasswordReset, setPasswordWithLink };
@@ -0,0 +1,86 @@
1
+ import { assert, panic } from "../../assertions.js";
2
+ import { writeCookies } from "../../cookies.js";
3
+ import { sessionConfig } from "../config.js";
4
+ import { clearPendingAuth, makePendingAuthCookie, makeSessionDataCookie, makeSessionTokenCookie } from "../session.js";
5
+ import { makePlatform } from "../platform.js";
6
+ import { authError } from "./utils.js";
7
+
8
+ //#region src/auth/methods/passwordLink.ts
9
+ /**
10
+ * Emails a link to set a new password.
11
+ *
12
+ * Succeeds whether or not the address has an account, and sends nothing when
13
+ * it has none.
14
+ */
15
+ async function requestPasswordReset(details) {
16
+ const result = await makePlatform(sessionConfig().applicationId).forgotPassword(details);
17
+ if (!result.ok) {
18
+ if (result.status === 429) return authError("tooManyAttempts", result.message);
19
+ panic(`Expected the password reset link to be emailed, but got ${result.status}: ${result.message}.`);
20
+ }
21
+ return {
22
+ success: true,
23
+ data: null
24
+ };
25
+ }
26
+ /**
27
+ * Checks a password reset or invitation link, and returns the address it was
28
+ * mailed to. The link stays usable.
29
+ */
30
+ async function checkPasswordLink(details) {
31
+ const result = await makePlatform(sessionConfig().applicationId).checkPasswordToken(details);
32
+ if (!result.ok) {
33
+ if (result.status === 429) return authError("tooManyAttempts", result.message);
34
+ if (result.status === 400 || result.status === 401) return authError("linkExpired", result.message);
35
+ panic(`Expected the link to be checked, but got ${result.status}: ${result.message}.`);
36
+ }
37
+ return {
38
+ success: true,
39
+ data: result.data
40
+ };
41
+ }
42
+ /**
43
+ * Sets a new password with a password reset or invitation link, and signs the
44
+ * visitor in.
45
+ *
46
+ * Any success uses up the link, `authenticatorRequired` included, and ends
47
+ * the visitor's other sessions.
48
+ */
49
+ async function setPasswordWithLink(details) {
50
+ const result = await makePlatform(sessionConfig().applicationId).setPassword(details);
51
+ if (!result.ok) {
52
+ if (result.status === 429) return authError("tooManyAttempts", result.message);
53
+ if (result.status === 400 && result.message === "Password must be at least 8 characters long.") return authError("invalidDetails", result.message);
54
+ if (result.status === 400 || result.status === 401) return authError("linkExpired", result.message);
55
+ panic(`Expected the password to be set, but got ${result.status}: ${result.message}.`);
56
+ }
57
+ if (result.data.status === "MFA_REQUIRED") {
58
+ const { mfa } = result.data;
59
+ assert(mfa, "Expected a challenge from setting a password, but got none");
60
+ writeCookies([makePendingAuthCookie(mfa.challengeToken)]);
61
+ return {
62
+ success: true,
63
+ data: {
64
+ status: "authenticatorRequired",
65
+ step: mfa.action === "VERIFICATION_REQUIRED" ? "verify" : mfa.action === "SETUP_REQUIRED" ? "setup" : "setupOptional"
66
+ }
67
+ };
68
+ }
69
+ const { session } = result.data;
70
+ assert(session, "Expected a session from setting a password, but got none");
71
+ writeCookies([makeSessionTokenCookie(session.jwt), makeSessionDataCookie({
72
+ user: session.user,
73
+ permissions: session.permissions
74
+ }, session.jwt)]);
75
+ clearPendingAuth();
76
+ return {
77
+ success: true,
78
+ data: {
79
+ status: "signedIn",
80
+ user: session.user
81
+ }
82
+ };
83
+ }
84
+
85
+ //#endregion
86
+ export { checkPasswordLink, requestPasswordReset, setPasswordWithLink };
@@ -0,0 +1,11 @@
1
+ import { AuthSettings } from "../platform.js";
2
+
3
+ //#region src/auth/methods/settings.d.ts
4
+
5
+ /**
6
+ * How visitors may sign in and sign up to this app, as configured in Studio.
7
+ * A login or sign-up page renders only the methods it lists.
8
+ */
9
+ declare function settings(): Promise<AuthSettings>;
10
+ //#endregion
11
+ export { settings };
@@ -0,0 +1,17 @@
1
+ import { panic } from "../../assertions.js";
2
+ import { sessionConfig } from "../config.js";
3
+ import { makePlatform } from "../platform.js";
4
+
5
+ //#region src/auth/methods/settings.ts
6
+ /**
7
+ * How visitors may sign in and sign up to this app, as configured in Studio.
8
+ * A login or sign-up page renders only the methods it lists.
9
+ */
10
+ async function settings() {
11
+ const result = await makePlatform(sessionConfig().applicationId).authSettings();
12
+ if (!result.ok) panic(`Expected the auth settings, but got ${result.status}: ${result.message}`);
13
+ return result.data;
14
+ }
15
+
16
+ //#endregion
17
+ export { settings };
@@ -17,6 +17,7 @@ async function signUp(details) {
17
17
  if (result.status === 409) return authError("emailTaken", result.message);
18
18
  if (result.status === 429) return authError("tooManyAttempts", result.message);
19
19
  if (result.status === 400) return authError("invalidDetails", result.message);
20
+ if (result.status === 401 && result.message === "Email domain not allowed") return authError("emailDomainNotAllowed", result.message);
20
21
  if (result.status >= 500) panic(`Expected the sign-up code to be emailed, but got ${result.status}: ` + result.message);
21
22
  throw new Error(`${result.message}. Check SOFTR_APPLICATION_ID and that the app allows sign-up.`);
22
23
  }
@@ -22,6 +22,7 @@ async function signInWithGoogle(credentials) {
22
22
  const result = await makePlatform(sessionConfig().applicationId).signInWithGoogle(credentials);
23
23
  if (!result.ok) {
24
24
  if (result.status === 429) return authError("tooManyAttempts", result.message);
25
+ if (result.status === 400 && result.message.startsWith("Emails with ") && result.message.endsWith(" domain is not allowed to signup.")) return authError("emailDomainNotAllowed", result.message);
25
26
  if (result.status === 400 || result.status === 401) return authError("invalidCredentials", result.message);
26
27
  if (result.status >= 500) panic(`Expected Google sign-in to succeed, but got ${result.status}: ` + result.message);
27
28
  throw new Error(`${result.message}. Check SOFTR_APPLICATION_ID and that the app allows Google sign-in.`);
@@ -10,6 +10,6 @@ type AuthError = {
10
10
  code: AuthErrorCode;
11
11
  message: string;
12
12
  };
13
- type AuthErrorCode = "invalidCredentials" | "tooManyAttempts" | "emailTaken" | "invalidDetails" | "invalidCode" | "notAuthenticated";
13
+ type AuthErrorCode = "invalidCredentials" | "tooManyAttempts" | "emailTaken" | "invalidDetails" | "invalidCode" | "notAuthenticated" | "emailDomainNotAllowed" | "linkExpired";
14
14
  //#endregion
15
15
  export { AuthError, Result };
@@ -0,0 +1,46 @@
1
+ import "./user.js";
2
+ import "./context.js";
3
+ import { z } from "zod";
4
+
5
+ //#region src/auth/platform.d.ts
6
+
7
+ declare const authSettingsSchema: z.ZodObject<{
8
+ loginEnabled: z.ZodBoolean;
9
+ authenticationMethods: z.ZodArray<z.ZodEnum<{
10
+ EMAIL: "EMAIL";
11
+ SSO: "SSO";
12
+ GOOGLE: "GOOGLE";
13
+ MAGIC_LINK: "MAGIC_LINK";
14
+ }>>;
15
+ signUpPolicy: z.ZodNullable<z.ZodEnum<{
16
+ DISABLED: "DISABLED";
17
+ OPEN_TO_PUBLIC: "OPEN_TO_PUBLIC";
18
+ DOMAIN_RESTRICTED: "DOMAIN_RESTRICTED";
19
+ }>>;
20
+ sessionExpirationDays: z.ZodNullable<z.ZodNumber>;
21
+ inactivityTimeoutMinutes: z.ZodNullable<z.ZodNumber>;
22
+ emailAuth: z.ZodNullable<z.ZodObject<{
23
+ loginMethods: z.ZodArray<z.ZodEnum<{
24
+ PASSWORD: "PASSWORD";
25
+ EMAIL_CODE: "EMAIL_CODE";
26
+ }>>;
27
+ strongPasswords: z.ZodBoolean;
28
+ emailCodeExpirationMinutes: z.ZodNullable<z.ZodNumber>;
29
+ }, z.core.$strip>>;
30
+ googleAuth: z.ZodNullable<z.ZodObject<{
31
+ clientId: z.ZodNullable<z.ZodString>;
32
+ userType: z.ZodNullable<z.ZodEnum<{
33
+ INTERNAL: "INTERNAL";
34
+ EXTERNAL: "EXTERNAL";
35
+ }>>;
36
+ }, z.core.$strip>>;
37
+ sso: z.ZodNullable<z.ZodObject<{
38
+ type: z.ZodNullable<z.ZodEnum<{
39
+ SAML: "SAML";
40
+ OPEN_ID: "OPEN_ID";
41
+ }>>;
42
+ }, z.core.$strip>>;
43
+ }, z.core.$strip>;
44
+ type AuthSettings = z.infer<typeof authSettingsSchema>;
45
+ //#endregion
46
+ export { AuthSettings };
@@ -6,8 +6,35 @@ import { userSchema } from "./user.js";
6
6
  import { z } from "zod";
7
7
 
8
8
  //#region src/auth/platform.ts
9
+ const authSettingsSchema = z.object({
10
+ loginEnabled: z.boolean(),
11
+ authenticationMethods: z.array(z.enum([
12
+ "EMAIL",
13
+ "SSO",
14
+ "GOOGLE",
15
+ "MAGIC_LINK"
16
+ ])),
17
+ signUpPolicy: z.enum([
18
+ "DISABLED",
19
+ "OPEN_TO_PUBLIC",
20
+ "DOMAIN_RESTRICTED"
21
+ ]).nullable(),
22
+ sessionExpirationDays: z.number().nullable(),
23
+ inactivityTimeoutMinutes: z.number().nullable(),
24
+ emailAuth: z.object({
25
+ loginMethods: z.array(z.enum(["PASSWORD", "EMAIL_CODE"])),
26
+ strongPasswords: z.boolean(),
27
+ emailCodeExpirationMinutes: z.number().nullable()
28
+ }).nullable(),
29
+ googleAuth: z.object({
30
+ clientId: z.string().nullable(),
31
+ userType: z.enum(["INTERNAL", "EXTERNAL"]).nullable()
32
+ }).nullable(),
33
+ sso: z.object({ type: z.enum(["SAML", "OPEN_ID"]).nullable() }).nullable()
34
+ });
9
35
  function makePlatform(applicationId) {
10
36
  return {
37
+ authSettings: () => request(`/v1/vibe/applications/${applicationId}/users/auth-settings`, { method: "GET" }, authSettingsSchema),
11
38
  session: async (token) => {
12
39
  const result = await request(`/v1/vibe/applications/${applicationId}/users/session`, {
13
40
  method: "GET",
@@ -99,6 +126,33 @@ function makePlatform(applicationId) {
99
126
  challengeToken: z.string()
100
127
  }).nullish()
101
128
  })),
129
+ forgotPassword: (body) => request(`/v1/vibe/applications/${applicationId}/users/forgot-password`, {
130
+ method: "POST",
131
+ json: body
132
+ }, z.null()),
133
+ checkPasswordToken: (body) => request(`/v1/vibe/applications/${applicationId}/users/set-password/check`, {
134
+ method: "POST",
135
+ json: body
136
+ }, z.object({ email: z.string() })),
137
+ setPassword: (body) => request(`/v1/vibe/applications/${applicationId}/users/set-password`, {
138
+ method: "POST",
139
+ json: body
140
+ }, z.object({
141
+ status: z.enum(["AUTHENTICATED", "MFA_REQUIRED"]),
142
+ session: z.object({
143
+ jwt: z.string(),
144
+ user: userSchema,
145
+ permissions: permissionsSchema
146
+ }).nullish(),
147
+ mfa: z.object({
148
+ action: z.enum([
149
+ "VERIFICATION_REQUIRED",
150
+ "SETUP_REQUIRED",
151
+ "SETUP_OPTIONAL"
152
+ ]),
153
+ challengeToken: z.string()
154
+ }).nullish()
155
+ })),
102
156
  sendSignUpCode: (body) => request(`/v1/vibe/applications/${applicationId}/users/sign-up/send-code`, {
103
157
  method: "POST",
104
158
  json: body
@@ -2,6 +2,8 @@ import { confirmAuthenticatorSetup, removeAuthenticator, resetAuthenticator, sen
2
2
  import { sendSignInCode, signInWithCode } from "./methods/code.js";
3
3
  import { signInWithMagicLink } from "./methods/magicLink.js";
4
4
  import { signIn, signOut } from "./methods/password.js";
5
+ import { checkPasswordLink, requestPasswordReset, setPasswordWithLink } from "./methods/passwordLink.js";
6
+ import { settings } from "./methods/settings.js";
5
7
  import { confirmSignUp, signUp } from "./methods/signup.js";
6
8
  import { signInWithGoogle } from "./methods/social.js";
7
9
  import "@tanstack/react-start/server-only";
@@ -20,6 +22,9 @@ declare const auth: {
20
22
  signInWithCode: typeof signInWithCode;
21
23
  signInWithGoogle: typeof signInWithGoogle;
22
24
  signInWithMagicLink: typeof signInWithMagicLink;
25
+ requestPasswordReset: typeof requestPasswordReset;
26
+ checkPasswordLink: typeof checkPasswordLink;
27
+ setPasswordWithLink: typeof setPasswordWithLink;
23
28
  startAuthenticatorSetup: typeof startAuthenticatorSetup;
24
29
  confirmAuthenticatorSetup: typeof confirmAuthenticatorSetup;
25
30
  skipAuthenticatorSetup: typeof skipAuthenticatorSetup;
@@ -27,6 +32,7 @@ declare const auth: {
27
32
  sendAuthenticatorResetCode: typeof sendAuthenticatorResetCode;
28
33
  resetAuthenticator: typeof resetAuthenticator;
29
34
  removeAuthenticator: typeof removeAuthenticator;
35
+ settings: typeof settings;
30
36
  };
31
37
  //#endregion
32
38
  export { auth };
@@ -1,7 +1,9 @@
1
+ import { settings } from "./methods/settings.js";
1
2
  import { confirmAuthenticatorSetup, removeAuthenticator, resetAuthenticator, sendAuthenticatorResetCode, skipAuthenticatorSetup, startAuthenticatorSetup, verifyAuthenticator } from "./methods/authenticator.js";
2
3
  import { sendSignInCode, signInWithCode } from "./methods/code.js";
3
4
  import { signInWithMagicLink } from "./methods/magicLink.js";
4
5
  import { signIn, signOut } from "./methods/password.js";
6
+ import { checkPasswordLink, requestPasswordReset, setPasswordWithLink } from "./methods/passwordLink.js";
5
7
  import { confirmSignUp, signUp } from "./methods/signup.js";
6
8
  import { signInWithGoogle } from "./methods/social.js";
7
9
  import "@tanstack/react-start/server-only";
@@ -19,13 +21,17 @@ const auth = {
19
21
  signInWithCode,
20
22
  signInWithGoogle,
21
23
  signInWithMagicLink,
24
+ requestPasswordReset,
25
+ checkPasswordLink,
26
+ setPasswordWithLink,
22
27
  startAuthenticatorSetup,
23
28
  confirmAuthenticatorSetup,
24
29
  skipAuthenticatorSetup,
25
30
  verifyAuthenticator,
26
31
  sendAuthenticatorResetCode,
27
32
  resetAuthenticator,
28
- removeAuthenticator
33
+ removeAuthenticator,
34
+ settings
29
35
  };
30
36
 
31
37
  //#endregion
package/dist/index.d.ts CHANGED
@@ -4,12 +4,13 @@ import { FileAttachment } from "./core/file-upload.js";
4
4
  import { FileItem, useFileUpload } from "./core/use-file-upload.js";
5
5
  import { DateOptions, DateParts, DateSeparator, DateValue, FixedDateFormat, FormattedDate, Formatting, FormattingScope, WeekDay, formatDate, formatDateTime, formatNumber, useFormatting } from "./formatting.js";
6
6
  import { SoftrContext } from "./auth/context.js";
7
+ import { AuthSettings } from "./auth/platform.js";
7
8
  import { checkAccess, defineVisibility, isAuthorized } from "./visibility/visibility.js";
8
- import { assertRouteAccess, guardRoute, isAccessError, isAlreadyAuthenticatedError, isForbiddenError, isUnauthenticatedError } from "./visibility/route.js";
9
- import { getSoftrContext, initialSoftrContext, softrAuthMiddleware, useCurrentUser } from "./auth/isomorphic.js";
9
+ import { assertRouteAccess, guardRoute, isAccessError, isAlreadyAuthenticatedError, isForbiddenError, isUnauthenticatedError, toReturnPath } from "./visibility/route.js";
10
+ import { AuthOptions, AuthSettingsProvider, getAuthSettings, getSoftrContext, initialSoftrContext, softrAuthMiddleware, useAuthSettings, useCurrentUser } from "./auth/isomorphic.js";
10
11
  import { softrMcpMiddleware } from "./mcp.js";
11
12
  import { useUserTimezone } from "./timezone.js";
12
13
  import { PwaInstall, PwaPlatform, SoftrPwaHead, usePwaInstall } from "./pwa.js";
13
14
  import { DefaultErrorOverlay } from "./default-error-overlay.js";
14
15
  import { Audience } from "./visibility/audience.js";
15
- export { type ActionPermissions, Audience, type DateOptions, type DateParts, type DateSeparator, type DateValue, DefaultErrorOverlay, type FileAttachment, type FileItem, type FixedDateFormat, FormattedDate, type Formatting, FormattingScope, type PwaInstall, type PwaPlatform, type SoftrContext, type SoftrDatasources, SoftrPwaHead, type SoftrUserGroupId, type SoftrUserGroups, type User, type WeekDay, assertRouteAccess, checkAccess, defineIntegration, defineMutation, defineQuery, defineVisibility, defineWorkflow, formatDate, formatDateTime, formatNumber, getSoftrContext, guardRoute, initialSoftrContext, isAccessError, isAlreadyAuthenticatedError, isAuthorized, isForbiddenError, isUnauthenticatedError, softrAuthMiddleware, softrMcpMiddleware, useCurrentUser, useFileUpload, useFormatting, usePwaInstall, useUserTimezone };
16
+ export { type ActionPermissions, Audience, type AuthOptions, type AuthSettings, AuthSettingsProvider, type DateOptions, type DateParts, type DateSeparator, type DateValue, DefaultErrorOverlay, type FileAttachment, type FileItem, type FixedDateFormat, FormattedDate, type Formatting, FormattingScope, type PwaInstall, type PwaPlatform, type SoftrContext, type SoftrDatasources, SoftrPwaHead, type SoftrUserGroupId, type SoftrUserGroups, type User, type WeekDay, assertRouteAccess, checkAccess, defineIntegration, defineMutation, defineQuery, defineVisibility, defineWorkflow, formatDate, formatDateTime, formatNumber, getAuthSettings, getSoftrContext, guardRoute, initialSoftrContext, isAccessError, isAlreadyAuthenticatedError, isAuthorized, isForbiddenError, isUnauthenticatedError, softrAuthMiddleware, softrMcpMiddleware, toReturnPath, useAuthSettings, useCurrentUser, useFileUpload, useFormatting, usePwaInstall, useUserTimezone };
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import { useFileUpload } from "./core/use-file-upload.js";
2
2
  import { defineIntegration, defineMutation, defineQuery, defineWorkflow } from "./action.js";
3
3
  import { checkAccess, defineVisibility, isAuthorized } from "./visibility/visibility.js";
4
- import { assertRouteAccess, guardRoute, isAccessError, isAlreadyAuthenticatedError, isForbiddenError, isUnauthenticatedError } from "./visibility/route.js";
4
+ import { assertRouteAccess, guardRoute, isAccessError, isAlreadyAuthenticatedError, isForbiddenError, isUnauthenticatedError, toReturnPath } from "./visibility/route.js";
5
5
  import { FormattedDate, FormattingScope, formatDate, formatDateTime, formatNumber, useFormatting } from "./formatting.js";
6
6
  import { SoftrPwaHead, usePwaInstall } from "./pwa.js";
7
- import { getSoftrContext, initialSoftrContext, softrAuthMiddleware, useCurrentUser } from "./auth/isomorphic.js";
7
+ import { AuthSettingsProvider, getAuthSettings, getSoftrContext, initialSoftrContext, softrAuthMiddleware, useAuthSettings, useCurrentUser } from "./auth/isomorphic.js";
8
8
  import { softrMcpMiddleware } from "./mcp.js";
9
9
  import { useUserTimezone } from "./timezone.js";
10
10
  import { DefaultErrorOverlay } from "./default-error-overlay.js";
11
11
  import { Audience } from "./visibility/audience.js";
12
12
 
13
- export { Audience, DefaultErrorOverlay, FormattedDate, FormattingScope, SoftrPwaHead, assertRouteAccess, checkAccess, defineIntegration, defineMutation, defineQuery, defineVisibility, defineWorkflow, formatDate, formatDateTime, formatNumber, getSoftrContext, guardRoute, initialSoftrContext, isAccessError, isAlreadyAuthenticatedError, isAuthorized, isForbiddenError, isUnauthenticatedError, softrAuthMiddleware, softrMcpMiddleware, useCurrentUser, useFileUpload, useFormatting, usePwaInstall, useUserTimezone };
13
+ export { Audience, AuthSettingsProvider, DefaultErrorOverlay, FormattedDate, FormattingScope, SoftrPwaHead, assertRouteAccess, checkAccess, defineIntegration, defineMutation, defineQuery, defineVisibility, defineWorkflow, formatDate, formatDateTime, formatNumber, getAuthSettings, getSoftrContext, guardRoute, initialSoftrContext, isAccessError, isAlreadyAuthenticatedError, isAuthorized, isForbiddenError, isUnauthenticatedError, softrAuthMiddleware, softrMcpMiddleware, toReturnPath, useAuthSettings, useCurrentUser, useFileUpload, useFormatting, usePwaInstall, useUserTimezone };
package/dist/mcp.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { DatasourceAction } from "./action.js";
2
- import * as _tanstack_react_start3 from "@tanstack/react-start";
2
+ import * as _tanstack_react_start0 from "@tanstack/react-start";
3
3
 
4
4
  //#region src/mcp.d.ts
5
5
 
@@ -12,12 +12,6 @@ type SoftrMcpOptions = {
12
12
  * decide who may run the ones that are listed.
13
13
  */
14
14
  actions?: Array<DatasourceAction>;
15
- /**
16
- * The app's sign-in page, as a path on this app. A signed-out visitor who
17
- * opens the approval page is sent here with `?redirect=` pointing back at it.
18
- * Defaults to `/login`.
19
- */
20
- loginPath?: string;
21
15
  };
22
16
  /**
23
17
  * Serves the MCP endpoint and its OAuth flow from the app's own origin.
@@ -37,6 +31,6 @@ type SoftrMcpOptions = {
37
31
  * ],
38
32
  * }))
39
33
  */
40
- declare function softrMcpMiddleware(options?: SoftrMcpOptions): _tanstack_react_start3.RequestMiddlewareAfterServer<{}, undefined, undefined>;
34
+ declare function softrMcpMiddleware(options?: SoftrMcpOptions): _tanstack_react_start0.RequestMiddlewareAfterServer<{}, undefined, undefined>;
41
35
  //#endregion
42
36
  export { softrMcpMiddleware };