@softr/sdk 0.0.92-emailotc.0 → 0.0.92

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.
@@ -0,0 +1,25 @@
1
+ import { createMiddleware } from "@tanstack/react-start";
2
+
3
+ //#region src/app-identity.ts
4
+ /**
5
+ * Tells support which Softr app answered, in an `x-softr-app-id` response
6
+ * header.
7
+ */
8
+ function appIdentityMiddleware() {
9
+ return createMiddleware({ type: "request" }).server(async ({ next }) => {
10
+ const result = await next();
11
+ const applicationId = process.env.SOFTR_APPLICATION_ID;
12
+ if (!applicationId) return result;
13
+ try {
14
+ result.response.headers.set("x-softr-app-id", applicationId);
15
+ return result;
16
+ } catch {
17
+ const response = new Response(result.response.body, result.response);
18
+ response.headers.set("x-softr-app-id", applicationId);
19
+ return response;
20
+ }
21
+ });
22
+ }
23
+
24
+ //#endregion
25
+ export { appIdentityMiddleware };
@@ -22,7 +22,7 @@ import * as _tanstack_react_start0 from "@tanstack/react-start";
22
22
  * requestMiddleware: [softrAuthMiddleware()],
23
23
  * }))
24
24
  */
25
- declare function softrAuthMiddleware(): _tanstack_react_start0.RequestMiddlewareAfterServer<{}, readonly [_tanstack_react_start0.RequestMiddlewareAfterServer<{}, undefined, undefined>, _tanstack_react_start0.RequestMiddlewareAfterServer<{}, undefined, undefined>, _tanstack_react_start0.RequestMiddlewareAfterServer<{}, undefined, undefined>, _tanstack_react_start0.RequestMiddlewareAfterServer<{}, undefined, undefined>], {
25
+ declare function softrAuthMiddleware(): _tanstack_react_start0.RequestMiddlewareAfterServer<{}, readonly [_tanstack_react_start0.RequestMiddlewareAfterServer<{}, undefined, undefined>, _tanstack_react_start0.RequestMiddlewareAfterServer<{}, undefined, undefined>, _tanstack_react_start0.RequestMiddlewareAfterServer<{}, undefined, undefined>, _tanstack_react_start0.RequestMiddlewareAfterServer<{}, undefined, undefined>, _tanstack_react_start0.RequestMiddlewareAfterServer<{}, undefined, undefined>], {
26
26
  user: User | null;
27
27
  permissions: Permissions;
28
28
  formatting: Formatting;
@@ -10,6 +10,7 @@ import { bootErrorMiddleware } from "../boot-error.js";
10
10
  import { pwaMiddleware } from "../pwa.js";
11
11
  import { faviconMiddleware } from "../favicon.js";
12
12
  import { embeddingMiddleware } from "../embedding.js";
13
+ import { appIdentityMiddleware } from "../app-identity.js";
13
14
  import { createContext, useContext } from "react";
14
15
  import { createMiddleware, createServerFn, getGlobalStartContext } from "@tanstack/react-start";
15
16
  import { getRequestHeader } from "@tanstack/react-start/server";
@@ -34,6 +35,7 @@ import { jsx } from "react/jsx-runtime";
34
35
  function softrAuthMiddleware() {
35
36
  return createMiddleware({ type: "request" }).middleware([
36
37
  embeddingMiddleware(),
38
+ appIdentityMiddleware(),
37
39
  bootErrorMiddleware(),
38
40
  pwaMiddleware(),
39
41
  faviconMiddleware()
@@ -8,8 +8,7 @@ import { AuthError, Result } from "./utils.js";
8
8
  *
9
9
  * A `signedIn` result means the visitor is signed in. An app that also asks for
10
10
  * an authenticator app answers `authenticatorRequired` instead, naming the step
11
- * to send them to next. An app that also asks for an emailed code answers
12
- * `emailCodeRequired`; `verifyEmailCode` finishes it.
11
+ * to send them to next.
13
12
  */
14
13
  declare function signIn(credentials: {
15
14
  email: string;
@@ -25,8 +24,6 @@ declare function signIn(credentials: {
25
24
  * `setupOptional`: same, except they may skip it instead.
26
25
  */
27
26
  step: "verify" | "setup" | "setupOptional";
28
- } | {
29
- status: "emailCodeRequired";
30
27
  }, AuthError>>;
31
28
  /**
32
29
  * Signs the visitor out.
@@ -11,8 +11,7 @@ import { authError } from "./utils.js";
11
11
  *
12
12
  * A `signedIn` result means the visitor is signed in. An app that also asks for
13
13
  * an authenticator app answers `authenticatorRequired` instead, naming the step
14
- * to send them to next. An app that also asks for an emailed code answers
15
- * `emailCodeRequired`; `verifyEmailCode` finishes it.
14
+ * to send them to next.
16
15
  */
17
16
  async function signIn(credentials) {
18
17
  const result = await makePlatform(sessionConfig().applicationId).tokens(credentials);
@@ -26,10 +25,6 @@ async function signIn(credentials) {
26
25
  const { mfa } = result.data;
27
26
  assert(mfa, "Expected a challenge from sign-in, but got none");
28
27
  writeCookies([makePendingAuthCookie(mfa.challengeToken)]);
29
- if (mfa.action === "EMAIL_CODE_REQUIRED") return {
30
- success: true,
31
- data: { status: "emailCodeRequired" }
32
- };
33
28
  return {
34
29
  success: true,
35
30
  data: {
@@ -71,27 +71,6 @@ function makePlatform(applicationId) {
71
71
  tokens: (credentials) => request(`/v1/vibe/applications/${applicationId}/users/tokens${withAttributes}`, {
72
72
  method: "POST",
73
73
  json: credentials
74
- }, z.object({
75
- status: z.enum(["AUTHENTICATED", "MFA_REQUIRED"]),
76
- session: z.object({
77
- jwt: z.string(),
78
- user: userSchema,
79
- permissions: permissionsSchema
80
- }).nullish(),
81
- mfa: z.object({
82
- action: z.enum([
83
- "VERIFICATION_REQUIRED",
84
- "SETUP_REQUIRED",
85
- "SETUP_OPTIONAL",
86
- "EMAIL_CODE_REQUIRED"
87
- ]),
88
- challengeToken: z.string()
89
- }).nullish()
90
- })),
91
- emailCodeVerify: (token, code) => request(`/v1/vibe/applications/${applicationId}/users/tokens/email-code/verify${withAttributes}`, {
92
- method: "POST",
93
- token,
94
- json: { code }
95
74
  }, z.object({
96
75
  status: z.enum(["AUTHENTICATED", "MFA_REQUIRED"]),
97
76
  session: z.object({
@@ -108,10 +87,6 @@ function makePlatform(applicationId) {
108
87
  challengeToken: z.string()
109
88
  }).nullish()
110
89
  })),
111
- emailCodeResend: (token) => request(`/v1/vibe/applications/${applicationId}/users/tokens/email-code/resend`, {
112
- method: "POST",
113
- token
114
- }, z.null()),
115
90
  sendSignInCode: (email) => request(`/v1/vibe/applications/${applicationId}/users/tokens/send-code`, {
116
91
  method: "POST",
117
92
  json: { email }
@@ -1,6 +1,5 @@
1
1
  import { confirmAuthenticatorSetup, removeAuthenticator, resetAuthenticator, sendAuthenticatorResetCode, skipAuthenticatorSetup, startAuthenticatorSetup, verifyAuthenticator } from "./methods/authenticator.js";
2
2
  import { sendSignInCode, signInWithCode } from "./methods/code.js";
3
- import { resendEmailCode, verifyEmailCode } from "./methods/emailCode2fa.js";
4
3
  import { signInWithMagicLink } from "./methods/magicLink.js";
5
4
  import { signIn, signOut } from "./methods/password.js";
6
5
  import { checkPasswordLink, requestPasswordReset, setPasswordWithLink } from "./methods/passwordLink.js";
@@ -35,8 +34,6 @@ declare const auth: {
35
34
  sendAuthenticatorResetCode: typeof sendAuthenticatorResetCode;
36
35
  resetAuthenticator: typeof resetAuthenticator;
37
36
  removeAuthenticator: typeof removeAuthenticator;
38
- verifyEmailCode: typeof verifyEmailCode;
39
- resendEmailCode: typeof resendEmailCode;
40
37
  settings: typeof settings;
41
38
  updateProfile: typeof updateProfile;
42
39
  removeAvatar: typeof removeAvatar;
@@ -1,7 +1,6 @@
1
1
  import { settings } from "./methods/settings.js";
2
2
  import { confirmAuthenticatorSetup, removeAuthenticator, resetAuthenticator, sendAuthenticatorResetCode, skipAuthenticatorSetup, startAuthenticatorSetup, verifyAuthenticator } from "./methods/authenticator.js";
3
3
  import { sendSignInCode, signInWithCode } from "./methods/code.js";
4
- import { resendEmailCode, verifyEmailCode } from "./methods/emailCode2fa.js";
5
4
  import { signInWithMagicLink } from "./methods/magicLink.js";
6
5
  import { signIn, signOut } from "./methods/password.js";
7
6
  import { checkPasswordLink, requestPasswordReset, setPasswordWithLink } from "./methods/passwordLink.js";
@@ -34,8 +33,6 @@ const auth = {
34
33
  sendAuthenticatorResetCode,
35
34
  resetAuthenticator,
36
35
  removeAuthenticator,
37
- verifyEmailCode,
38
- resendEmailCode,
39
36
  settings,
40
37
  updateProfile,
41
38
  removeAvatar,
@@ -1,4 +1,4 @@
1
- import * as react2 from "react";
1
+ import * as react6 from "react";
2
2
 
3
3
  //#region src/default-error-overlay.d.ts
4
4
  type Props = {
@@ -8,6 +8,6 @@ type Props = {
8
8
  declare function DefaultErrorOverlay({
9
9
  error,
10
10
  reset
11
- }: Props): react2.JSX.Element;
11
+ }: Props): react6.JSX.Element;
12
12
  //#endregion
13
13
  export { DefaultErrorOverlay };
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import * as react3 from "react";
2
+ import * as react0 from "react";
3
3
  import { ReactNode } from "react";
4
4
 
5
5
  //#region src/formatting.d.ts
@@ -94,7 +94,7 @@ declare function FormattingScope({
94
94
  /** A BCP 47 locale, such as `de-DE`. It drops the app's fixed date format inside the scope. */
95
95
  locale?: string;
96
96
  children?: ReactNode;
97
- }): react3.FunctionComponentElement<react3.ProviderProps<Scope>>;
97
+ }): react0.FunctionComponentElement<react0.ProviderProps<Scope>>;
98
98
  /**
99
99
  * A date in the app's format, safe to render on the server. A timestamp whose
100
100
  * zone is not known yet renders `fallback` until the browser supplies it, so
@@ -115,6 +115,6 @@ declare function FormattedDate({
115
115
  time?: boolean;
116
116
  /** What renders while the visitor's zone is unknown. */
117
117
  fallback?: ReactNode;
118
- }): react3.FunctionComponentElement<react3.FragmentProps>;
118
+ }): react0.FunctionComponentElement<react0.FragmentProps>;
119
119
  //#endregion
120
120
  export { DateOptions, DateParts, DateSeparator, DateValue, FixedDateFormat, FormattedDate, Formatting, FormattingScope, WeekDay, formatDate, formatDateTime, formatNumber, useFormatting };
package/dist/mcp.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { DatasourceAction } from "./action.js";
2
- import * as _tanstack_react_start6 from "@tanstack/react-start";
2
+ import * as _tanstack_react_start7 from "@tanstack/react-start";
3
3
 
4
4
  //#region src/mcp.d.ts
5
5
 
@@ -31,6 +31,6 @@ type SoftrMcpOptions = {
31
31
  * ],
32
32
  * }))
33
33
  */
34
- declare function softrMcpMiddleware(options?: SoftrMcpOptions): _tanstack_react_start6.RequestMiddlewareAfterServer<{}, undefined, undefined>;
34
+ declare function softrMcpMiddleware(options?: SoftrMcpOptions): _tanstack_react_start7.RequestMiddlewareAfterServer<{}, undefined, undefined>;
35
35
  //#endregion
36
36
  export { softrMcpMiddleware };
package/dist/package.js CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "0.0.92-emailotc.0";
2
+ var version = "0.0.92";
3
3
 
4
4
  //#endregion
5
5
  export { version };
package/dist/pwa.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import * as react0 from "react";
1
+ import * as react4 from "react";
2
2
  import "@tanstack/react-start";
3
3
 
4
4
  //#region src/pwa.d.ts
@@ -23,7 +23,7 @@ import "@tanstack/react-start";
23
23
  * )
24
24
  * }
25
25
  */
26
- declare function SoftrPwaHead(): react0.FunctionComponentElement<react0.FragmentProps>;
26
+ declare function SoftrPwaHead(): react4.FunctionComponentElement<react4.FragmentProps>;
27
27
  type PwaPlatform = "ios" | "android" | "desktop";
28
28
  type PwaInstall = {
29
29
  available: false;
package/package.json CHANGED
@@ -1,37 +1,16 @@
1
1
  {
2
2
  "name": "@softr/sdk",
3
- "version": "0.0.92-emailotc.0",
3
+ "version": "0.0.92",
4
4
  "type": "module",
5
5
  "exports": {
6
- ".": {
7
- "types": "./dist/index.d.ts",
8
- "import": "./dist/index.js"
9
- },
10
- "./client": {
11
- "types": "./dist/client.d.ts",
12
- "import": "./dist/client.js"
13
- },
14
- "./server": {
15
- "types": "./dist/server.d.ts",
16
- "import": "./dist/server.js"
17
- },
18
- "./vite": {
19
- "types": "./dist/vite.d.ts",
20
- "import": "./dist/vite.js"
21
- }
22
- },
23
- "bin": {
24
- "softr-sdk": "./dist/cli.js"
25
- },
26
- "files": [
27
- "dist",
28
- "schema",
29
- "skills",
30
- "!skills/_artifacts"
31
- ],
32
- "publishConfig": {
33
- "access": "public"
34
- },
6
+ ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" },
7
+ "./client": { "types": "./dist/client.d.ts", "import": "./dist/client.js" },
8
+ "./server": { "types": "./dist/server.d.ts", "import": "./dist/server.js" },
9
+ "./vite": { "types": "./dist/vite.d.ts", "import": "./dist/vite.js" }
10
+ },
11
+ "bin": { "softr-sdk": "./dist/cli.js" },
12
+ "files": ["dist", "schema", "skills", "!skills/_artifacts"],
13
+ "publishConfig": { "access": "public" },
35
14
  "scripts": {
36
15
  "build": "tsdown",
37
16
  "test": "node --import ./src/test-utils/setup.ts --test",
@@ -63,9 +42,7 @@
63
42
  "optional": true
64
43
  }
65
44
  },
66
- "keywords": [
67
- "tanstack-intent"
68
- ],
45
+ "keywords": ["tanstack-intent"],
69
46
  "intent": {
70
47
  "version": 1,
71
48
  "repo": "@softr/sdk",
@@ -9,7 +9,7 @@ description: >-
9
9
  metadata:
10
10
  type: core
11
11
  library: softr-sdk
12
- library_version: 0.0.91
12
+ library_version: 0.0.92
13
13
  ---
14
14
 
15
15
  # Softr SDK core
@@ -13,7 +13,7 @@ description: >-
13
13
  metadata:
14
14
  type: sub-skill
15
15
  library: softr-sdk
16
- library_version: 0.0.91
16
+ library_version: 0.0.92
17
17
  ---
18
18
 
19
19
  **Boundary.** `ai` lives on `@softr/sdk/server` and runs only inside a `createServerFn` handler — importing it into a component fails the build. `defineAiAction` and every type come from `@softr/sdk` and can be imported anywhere.
@@ -3,13 +3,13 @@ name: auth
3
3
  description: >-
4
4
  Sign a visitor in, out or up from a server function with auth from
5
5
  @softr/sdk/server: password, code, Google and magic link, sign-up and its
6
- confirmation, the emailed-code and authenticator-app steps, password reset links,
6
+ confirmation, the authenticator-app steps, password reset links,
7
7
  updateProfile, and getAuthSettings and useAuthSettings for the methods the app
8
8
  enables. Covers the Result shape, its error codes, and toReturnPath.
9
9
  metadata:
10
10
  type: sub-skill
11
11
  library: softr-sdk
12
- library_version: 0.0.91
12
+ library_version: 0.0.92
13
13
  ---
14
14
 
15
15
  **Boundary.** `auth` lives on `@softr/sdk/server` and runs only inside a `createServerFn` handler — importing it into a component fails the build.
@@ -55,13 +55,6 @@ Signing out:
55
55
  | --- | --- |
56
56
  | `auth.signOut()` | Ends every session that visitor has in this app, on every device |
57
57
 
58
- Finishing a sign-in that wants a code from the visitor's inbox:
59
-
60
- | Call | Does |
61
- | --- | --- |
62
- | `auth.verifyEmailCode({ code })` | Answers it with the code that was emailed |
63
- | `auth.resendEmailCode()` | Emails that code again |
64
-
65
58
  Finishing a sign-in that wants an authenticator app:
66
59
 
67
60
  | Call | Does |
@@ -204,8 +197,6 @@ Those calls take only what the visitor typed. The sign-in they finish is the one
204
197
 
205
198
  An app with no authenticator app configured never answers `authenticatorRequired`. The type still has both arms either way, so `result.data.user` does not exist until you have narrowed on `status`.
206
199
 
207
- `signIn` has a third answer, `{ status: 'emailCodeRequired' }`, for an app that asks a password sign-in for a code from the visitor's inbox as well. The code is already on its way. Show a code field as the next step and finish with `auth.verifyEmailCode({ code })`, see [Finishing a sign-in that needs an emailed code](#finishing-a-sign-in-that-needs-an-emailed-code). That call answers like `signIn` does, so an app that also wants an authenticator app goes on to that step after it.
208
-
209
200
  ## Landing after sign-in
210
201
 
211
202
  A guard that turns a signed-out visitor away sends them to the page `softr.json` names for that, usually the login page. The page they wanted rides along in the search param named for the login page. `toReturnPath` from `@softr/sdk` reads it back:
@@ -264,13 +255,10 @@ if (answer.message !== null) return setMessage(answer.message)
264
255
  if (answer.outcome.status === 'authenticatorRequired') {
265
256
  return setStep({ name: 'secondFactor', opensOn: answer.outcome.step })
266
257
  }
267
- if (answer.outcome.status === 'emailCodeRequired') {
268
- return setStep({ name: 'emailCode' })
269
- }
270
258
  await navigate({ href: target })
271
259
  ```
272
260
 
273
- Four exits: a message for the form to render, the emailed-code step, the authenticator step, the return target.
261
+ Three exits: a message for the form to render, the second-factor step, the return target.
274
262
 
275
263
  A server function that throws `redirect` needs the hook. Call the imported function directly and the throw never reaches the router, so a successful sign-in leaves the visitor on the form.
276
264
 
@@ -397,22 +385,6 @@ The UI has to carry email into step two, plus the name if step one collected one
397
385
 
398
386
  `password` is what the account is created with. Leave it out only for an app that signs people in with an emailed code. An app that expects a password rejects a sign-up without one, and an app that does not expect one rejects a sign-up that sends it.
399
387
 
400
- ### Finishing a sign-in that needs an emailed code
401
-
402
- After `signIn` answers `emailCodeRequired`, the visitor owes the code that was just emailed to them:
403
-
404
- ```ts
405
- // invalidCode for a wrong or expired code, otherwise the same two-armed result as signIn.
406
- const result = await auth.verifyEmailCode({ code })
407
-
408
- // For a "Resend code" link.
409
- const sent = await auth.resendEmailCode()
410
- ```
411
-
412
- Send `authenticatorRequired` on to the authenticator step, never into the app.
413
-
414
- Asking for a resend too soon sends nothing and still succeeds. It answers `notAuthenticated` once the sign-in has run out of time, and the visitor then signs in again from the start.
415
-
416
388
  ### Finishing a sign-in that needs an authenticator app
417
389
 
418
390
  On `step: 'verify'` the visitor already has an app, and owes a code from it:
@@ -9,7 +9,7 @@ description: >-
9
9
  metadata:
10
10
  type: sub-skill
11
11
  library: softr-sdk
12
- library_version: 0.0.91
12
+ library_version: 0.0.92
13
13
  ---
14
14
 
15
15
  **Boundary.** `ds` lives on `@softr/sdk/server` and runs only inside a `createServerFn` handler or a server-side route hook — importing it into a component fails the build. `defineQuery` and every type come from `@softr/sdk` and can be imported anywhere.
@@ -9,7 +9,7 @@ description: >-
9
9
  metadata:
10
10
  type: sub-skill
11
11
  library: softr-sdk
12
- library_version: 0.0.91
12
+ library_version: 0.0.92
13
13
  ---
14
14
 
15
15
  # The current user
@@ -7,7 +7,7 @@ description: >-
7
7
  metadata:
8
8
  type: sub-skill
9
9
  library: softr-sdk
10
- library_version: 0.0.91
10
+ library_version: 0.0.92
11
11
  ---
12
12
 
13
13
  **Boundary.** `upload` lives on `@softr/sdk/server` and runs inside server functions. `useFileUpload` and `FileItem` live on `@softr/sdk` and run in components. `FileAttachment` comes from `@softr/sdk` and can be imported anywhere.
@@ -8,7 +8,7 @@ description: >-
8
8
  metadata:
9
9
  type: sub-skill
10
10
  library: softr-sdk
11
- library_version: 0.0.91
11
+ library_version: 0.0.92
12
12
  ---
13
13
 
14
14
  # Dates, times and numbers
@@ -7,7 +7,7 @@ description: >-
7
7
  metadata:
8
8
  type: sub-skill
9
9
  library: softr-sdk
10
- library_version: 0.0.91
10
+ library_version: 0.0.92
11
11
  ---
12
12
 
13
13
  **Boundary.** `integration` lives on `@softr/sdk/server` and runs only inside a `createServerFn` handler — importing it into a component fails the build. `defineIntegration` and every type come from `@softr/sdk` and can be imported anywhere.
@@ -9,7 +9,7 @@ description: >-
9
9
  metadata:
10
10
  type: sub-skill
11
11
  library: softr-sdk
12
- library_version: 0.0.91
12
+ library_version: 0.0.92
13
13
  ---
14
14
 
15
15
  **Boundary.** `softrMcpMiddleware` lives on `@softr/sdk` and is registered once, in `src/start.ts`. The actions you hand it are the same `defineQuery` / `defineMutation` values the app's own pages use — declared wherever they already live, not duplicated for MCP.
@@ -9,7 +9,7 @@ description: >-
9
9
  metadata:
10
10
  type: sub-skill
11
11
  library: softr-sdk
12
- library_version: 0.0.91
12
+ library_version: 0.0.92
13
13
  ---
14
14
 
15
15
  # Installing the app
@@ -8,7 +8,7 @@ description: >-
8
8
  metadata:
9
9
  type: sub-skill
10
10
  library: softr-sdk
11
- library_version: 0.0.91
11
+ library_version: 0.0.92
12
12
  ---
13
13
 
14
14
  **Boundary.** `ds` lives on `@softr/sdk/server` and runs only inside a `createServerFn` handler — importing it into a component fails the build. `defineMutation` and every type come from `@softr/sdk` and can be imported anywhere.
@@ -9,7 +9,7 @@ description: >-
9
9
  metadata:
10
10
  type: sub-skill
11
11
  library: softr-sdk
12
- library_version: 0.0.91
12
+ library_version: 0.0.92
13
13
  ---
14
14
 
15
15
  **Boundary.** `ds` lives on `@softr/sdk/server` and runs only inside a `createServerFn` handler or a server-side route hook — importing it into a component fails the build. The same holds for any helper that calls `ds`: declare it inside the handler. A function at module level that calls `ds` keeps the server-only import in the browser bundle, and every page stops loading until it moves. `defineQuery` and every type come from `@softr/sdk` and can be imported anywhere.
@@ -9,7 +9,7 @@ description: >-
9
9
  metadata:
10
10
  type: sub-skill
11
11
  library: softr-sdk
12
- library_version: 0.0.91
12
+ library_version: 0.0.92
13
13
  ---
14
14
 
15
15
  **Boundary.** `Audience` and `defineVisibility` come from `@softr/sdk` and work anywhere.
@@ -9,7 +9,7 @@ description: >-
9
9
  metadata:
10
10
  type: sub-skill
11
11
  library: softr-sdk
12
- library_version: 0.0.91
12
+ library_version: 0.0.92
13
13
  ---
14
14
 
15
15
  **Boundary.** `definePage`, `pageHead`, the access functions and the error predicates come from `@softr/sdk` and work anywhere.
@@ -9,7 +9,7 @@ description: >-
9
9
  metadata:
10
10
  type: sub-skill
11
11
  library: softr-sdk
12
- library_version: 0.0.91
12
+ library_version: 0.0.92
13
13
  ---
14
14
 
15
15
  **Boundary.** `workflow` lives on `@softr/sdk/server` and runs only inside a `createServerFn` handler — importing it into a component fails the build. `defineWorkflow` and every type come from `@softr/sdk` and can be imported anywhere.
@@ -1,34 +0,0 @@
1
- import { User } from "../user.js";
2
- import { AuthError, Result } from "./utils.js";
3
-
4
- //#region src/auth/methods/emailCode2fa.d.ts
5
-
6
- /**
7
- * Finishes a sign-in that answered `emailCodeRequired`, with the code emailed
8
- * to the visitor.
9
- *
10
- * A `signedIn` result means the visitor is signed in. An app that also asks for
11
- * an authenticator app answers `authenticatorRequired` instead, naming the step
12
- * to send them to next.
13
- */
14
- declare function verifyEmailCode(details: {
15
- code: string;
16
- }): Promise<Result<{
17
- status: "signedIn";
18
- user: User;
19
- } | {
20
- status: "authenticatorRequired";
21
- /**
22
- * `verify`: they have an authenticator app and owe a code.
23
- * `setup`: the app requires one and they have none yet.
24
- * `setupOptional`: same, except they may skip it instead.
25
- */
26
- step: "verify" | "setup" | "setupOptional";
27
- }, AuthError>>;
28
- /**
29
- * Emails the code for {@link verifyEmailCode} again. Asking again within a
30
- * short wait sends nothing and still succeeds.
31
- */
32
- declare function resendEmailCode(): Promise<Result<null, AuthError>>;
33
- //#endregion
34
- export { resendEmailCode, verifyEmailCode };
@@ -1,71 +0,0 @@
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, readPendingAuthToken } from "../session.js";
5
- import { makePlatform } from "../platform.js";
6
- import { authError } from "./utils.js";
7
-
8
- //#region src/auth/methods/emailCode2fa.ts
9
- /**
10
- * Finishes a sign-in that answered `emailCodeRequired`, with the code emailed
11
- * to the visitor.
12
- *
13
- * A `signedIn` result means the visitor is signed in. An app that also asks for
14
- * an authenticator app answers `authenticatorRequired` instead, naming the step
15
- * to send them to next.
16
- */
17
- async function verifyEmailCode(details) {
18
- const result = await makePlatform(sessionConfig().applicationId).emailCodeVerify(readPendingAuthToken(), details.code);
19
- if (!result.ok) {
20
- if (result.status === 400 || result.status === 401) return authError("invalidCode", result.message);
21
- if (result.status === 429) return authError("tooManyAttempts", result.message);
22
- if (result.status >= 500) panic(`Expected to verify the emailed code, but got ${result.status}: ` + result.message);
23
- throw new Error(`${result.message}. Check SOFTR_APPLICATION_ID and that the app asks for an emailed code at sign-in.`);
24
- }
25
- if (result.data.status === "MFA_REQUIRED") {
26
- const { mfa } = result.data;
27
- assert(mfa, "Expected a challenge from verification, but got none");
28
- writeCookies([makePendingAuthCookie(mfa.challengeToken)]);
29
- return {
30
- success: true,
31
- data: {
32
- status: "authenticatorRequired",
33
- step: mfa.action === "VERIFICATION_REQUIRED" ? "verify" : mfa.action === "SETUP_REQUIRED" ? "setup" : "setupOptional"
34
- }
35
- };
36
- }
37
- const { session } = result.data;
38
- assert(session, "Expected a session from verification, but got none");
39
- writeCookies([...makeSessionTokenCookie(session.jwt), makeSessionDataCookie({
40
- user: session.user,
41
- permissions: session.permissions
42
- }, session.jwt)]);
43
- clearPendingAuth();
44
- return {
45
- success: true,
46
- data: {
47
- status: "signedIn",
48
- user: session.user
49
- }
50
- };
51
- }
52
- /**
53
- * Emails the code for {@link verifyEmailCode} again. Asking again within a
54
- * short wait sends nothing and still succeeds.
55
- */
56
- async function resendEmailCode() {
57
- const result = await makePlatform(sessionConfig().applicationId).emailCodeResend(readPendingAuthToken());
58
- if (!result.ok) {
59
- if (result.status === 401) return authError("notAuthenticated", result.message);
60
- if (result.status === 429) return authError("tooManyAttempts", result.message);
61
- if (result.status >= 500) panic(`Expected the code to be emailed again, but got ${result.status}: ` + result.message);
62
- throw new Error(`${result.message}. Check SOFTR_APPLICATION_ID and that the app asks for an emailed code at sign-in.`);
63
- }
64
- return {
65
- success: true,
66
- data: null
67
- };
68
- }
69
-
70
- //#endregion
71
- export { resendEmailCode, verifyEmailCode };