@softr/sdk 0.0.56-alpha.1 → 0.0.56-alpha.3

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 (37) hide show
  1. package/dist/action.d.ts +1 -31
  2. package/dist/action.js +1 -26
  3. package/dist/client.d.ts +1 -2
  4. package/dist/client.js +1 -2
  5. package/dist/codegen/datasource-types.js +1 -1
  6. package/dist/codegen/softr-env.js +2 -2
  7. package/dist/core/file-upload.d.ts +2 -7
  8. package/dist/core/file-upload.js +1 -6
  9. package/dist/core/use-file-upload.d.ts +2 -2
  10. package/dist/default-error-overlay.d.ts +1 -1
  11. package/dist/default-error-overlay.js +2 -2
  12. package/dist/index.d.ts +2 -3
  13. package/dist/index.js +2 -2
  14. package/dist/mcp.d.ts +2 -2
  15. package/dist/package.js +1 -1
  16. package/dist/server.d.ts +1 -2
  17. package/dist/server.js +1 -2
  18. package/package.json +1 -3
  19. package/skills/softr-sdk/SKILL.md +7 -7
  20. package/skills/softr-sdk/auth/SKILL.md +1 -1
  21. package/skills/softr-sdk/charts-and-metrics/SKILL.md +1 -1
  22. package/skills/softr-sdk/current-user/SKILL.md +1 -1
  23. package/skills/softr-sdk/file-uploads/SKILL.md +4 -5
  24. package/skills/softr-sdk/integrations/SKILL.md +1 -1
  25. package/skills/softr-sdk/mcp/SKILL.md +1 -1
  26. package/skills/softr-sdk/pwa/SKILL.md +1 -1
  27. package/skills/softr-sdk/record-mutations/SKILL.md +1 -1
  28. package/skills/softr-sdk/record-queries/SKILL.md +3 -3
  29. package/skills/softr-sdk/record-queries/references/field-types.md +6 -2
  30. package/skills/softr-sdk/region-visibility/SKILL.md +1 -1
  31. package/skills/softr-sdk/routes-and-visibility/SKILL.md +1 -1
  32. package/skills/softr-sdk/workflows/SKILL.md +1 -1
  33. package/dist/comments/comments.d.ts +0 -168
  34. package/dist/comments/comments.js +0 -413
  35. package/dist/comments/use-comment-composer.d.ts +0 -46
  36. package/dist/comments/use-comment-composer.js +0 -134
  37. package/skills/softr-sdk/comments/SKILL.md +0 -180
package/dist/action.d.ts CHANGED
@@ -234,35 +234,5 @@ type IntegrationDefinition<TId extends string> = {
234
234
  * const res = await listEvents({ query: { timeMin: now, singleEvents: "true" } })
235
235
  */
236
236
  declare function defineIntegration<const TId extends string>(definition: IntegrationDefinition<TId>): IntegrationAction<TId>;
237
- type CommentsResource = {
238
- type: "COMMENTS";
239
- datasourceId: SoftrDatasourceId;
240
- };
241
- /** Comment threads on the records of one datasource. It has no `permissions`. */
242
- type CommentsAction<TId extends string = string> = {
243
- id: TId;
244
- resource: CommentsResource;
245
- };
246
- type CommentsDefinition<TId extends string> = {
247
- id: TId;
248
- datasourceId: SoftrDatasourceId;
249
- };
250
- /**
251
- * Declares comment threads on the records of a datasource. Each record has one thread.
252
- *
253
- * Who may read, post and delete comes from the app's comment settings in Softr, not from code. Two
254
- * declarations on the same datasource share the same threads.
255
- *
256
- * Pass the returned object to `comments.*` from `@softr/sdk/server`.
257
- *
258
- * @example
259
- * const orderComments = defineComments({
260
- * id: "orderComments",
261
- * datasourceId: "8f14e45f-ceea-467a-9d0b-2c1a0e3b5d77",
262
- * })
263
- *
264
- * const thread = await comments.list(orderComments, { recordId })
265
- */
266
- declare function defineComments<const TId extends string>(definition: CommentsDefinition<TId>): CommentsAction<TId>;
267
237
  //#endregion
268
- export { ActionData, ActionPermissions, ActionRecord, ActionShape, CommentsAction, DatasourceAction, FieldTypeOf, IntegrationAction, ReadOf, ReadShape, SoftrDatasources, WorkflowAction, defineComments, defineIntegration, defineMutation, defineQuery, defineWorkflow };
238
+ export { ActionData, ActionPermissions, ActionRecord, ActionShape, DatasourceAction, FieldTypeOf, IntegrationAction, ReadOf, ReadShape, SoftrDatasources, WorkflowAction, defineIntegration, defineMutation, defineQuery, defineWorkflow };
package/dist/action.js CHANGED
@@ -50,31 +50,6 @@ function defineIntegration(definition) {
50
50
  permissions
51
51
  };
52
52
  }
53
- /**
54
- * Declares comment threads on the records of a datasource. Each record has one thread.
55
- *
56
- * Who may read, post and delete comes from the app's comment settings in Softr, not from code. Two
57
- * declarations on the same datasource share the same threads.
58
- *
59
- * Pass the returned object to `comments.*` from `@softr/sdk/server`.
60
- *
61
- * @example
62
- * const orderComments = defineComments({
63
- * id: "orderComments",
64
- * datasourceId: "8f14e45f-ceea-467a-9d0b-2c1a0e3b5d77",
65
- * })
66
- *
67
- * const thread = await comments.list(orderComments, { recordId })
68
- */
69
- function defineComments(definition) {
70
- return {
71
- id: definition.id,
72
- resource: {
73
- type: "COMMENTS",
74
- datasourceId: definition.datasourceId
75
- }
76
- };
77
- }
78
53
  function isDatasourceAction(value) {
79
54
  if (typeof value !== "object" || value === null) return false;
80
55
  const candidate = value;
@@ -83,4 +58,4 @@ function isDatasourceAction(value) {
83
58
  }
84
59
 
85
60
  //#endregion
86
- export { defineComments, defineIntegration, defineMutation, defineQuery, defineWorkflow, isDatasourceAction };
61
+ export { defineIntegration, defineMutation, defineQuery, defineWorkflow, isDatasourceAction };
package/dist/client.d.ts CHANGED
@@ -1,4 +1,3 @@
1
1
  import { FileItem, useFileUpload } from "./core/use-file-upload.js";
2
- import { useCommentComposer } from "./comments/use-comment-composer.js";
3
2
  import "@tanstack/react-start/client-only";
4
- export { type FileItem, useCommentComposer, useFileUpload };
3
+ export { type FileItem, useFileUpload };
package/dist/client.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { useFileUpload } from "./core/use-file-upload.js";
2
- import { useCommentComposer } from "./comments/use-comment-composer.js";
3
2
  import "@tanstack/react-start/client-only";
4
3
 
5
- export { useCommentComposer, useFileUpload };
4
+ export { useFileUpload };
@@ -422,7 +422,7 @@ function scalarExample(shape) {
422
422
  case "PROGRESS":
423
423
  case "COUNT":
424
424
  case "AUTONUMBER": return String(numberExample(shape.options));
425
- case "DURATION": return "3600";
425
+ case "DURATION": return "3600000";
426
426
  case "RATING": {
427
427
  const max = option(shape.options, "max");
428
428
  return String(typeof max === "number" ? max : 5);
@@ -77,8 +77,8 @@ type LinkedRecordInput = { id: string };
77
77
 
78
78
  type WorkspaceUser = {
79
79
  id: string;
80
- name: string;
81
- email: EmailAddress;
80
+ name: string | null;
81
+ email: EmailAddress | null;
82
82
  avatarUrl: string | null;
83
83
  };
84
84
 
@@ -1,4 +1,4 @@
1
- import { CommentsAction, DatasourceAction } from "../action.js";
1
+ import { DatasourceAction } from "../action.js";
2
2
 
3
3
  //#region src/core/file-upload.d.ts
4
4
 
@@ -10,12 +10,7 @@ type FileAttachment = {
10
10
  url: string;
11
11
  filename: string;
12
12
  id: string;
13
- type?: string | null;
14
13
  };
15
- /**
16
- * A COMMENTS action uploads a comment attachment.
17
- * The platform checks the comment settings.
18
- */
19
- declare function upload(action: DatasourceAction | CommentsAction, file: File): Promise<FileAttachment>;
14
+ declare function upload(action: DatasourceAction, file: File): Promise<FileAttachment>;
20
15
  //#endregion
21
16
  export { FileAttachment, upload };
@@ -5,10 +5,6 @@ import { platformApiUrl } from "../auth/platform.js";
5
5
  import { randomUUID } from "node:crypto";
6
6
 
7
7
  //#region src/core/file-upload.ts
8
- /**
9
- * A COMMENTS action uploads a comment attachment.
10
- * The platform checks the comment settings.
11
- */
12
8
  async function upload(action, file) {
13
9
  const { applicationId } = sessionConfig();
14
10
  const baseUrl = await platformApiUrl();
@@ -27,8 +23,7 @@ async function upload(action, file) {
27
23
  return {
28
24
  url: resultJSON.url,
29
25
  filename: resultJSON.filename || "Untitled file",
30
- id: resultJSON.id || randomUUID(),
31
- type: resultJSON.type ?? null
26
+ id: resultJSON.id || randomUUID()
32
27
  };
33
28
  }
34
29
 
@@ -1,4 +1,4 @@
1
- import { CommentsAction, DatasourceAction } from "../action.js";
1
+ import { DatasourceAction } from "../action.js";
2
2
  import { FileAttachment } from "./file-upload.js";
3
3
 
4
4
  //#region src/core/use-file-upload.d.ts
@@ -16,7 +16,7 @@ type FileItem = {
16
16
  filename: string;
17
17
  error: Error;
18
18
  };
19
- declare function useFileUpload(action: DatasourceAction | CommentsAction, options?: {
19
+ declare function useFileUpload(action: DatasourceAction, options?: {
20
20
  initialAttachments?: FileAttachment[];
21
21
  }): {
22
22
  files: FileItem[];
@@ -2,7 +2,7 @@ import * as react1 from "react";
2
2
 
3
3
  //#region src/default-error-overlay.d.ts
4
4
  type Props = {
5
- error: Error;
5
+ error: unknown;
6
6
  reset?: () => void;
7
7
  };
8
8
  declare function DefaultErrorOverlay({
@@ -88,9 +88,9 @@ function DevView({ error, reset }) {
88
88
  ] }),
89
89
  /* @__PURE__ */ jsx("pre", {
90
90
  style: s.message,
91
- children: error.message
91
+ children: error instanceof Error ? error.message : String(error)
92
92
  }),
93
- error.stack && /* @__PURE__ */ jsx(StackTrace, { stack: error.stack }),
93
+ error instanceof Error && error.stack && /* @__PURE__ */ jsx(StackTrace, { stack: error.stack }),
94
94
  /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(RetryButton, { onClick: reset }) })
95
95
  ]
96
96
  })
package/dist/index.d.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  import { SoftrUserGroupId, SoftrUserGroups, User } from "./auth/user.js";
2
- import { ActionPermissions, SoftrDatasources, defineComments, defineIntegration, defineMutation, defineQuery, defineWorkflow } from "./action.js";
2
+ import { ActionPermissions, SoftrDatasources, defineIntegration, defineMutation, defineQuery, defineWorkflow } from "./action.js";
3
3
  import { FileAttachment } from "./core/file-upload.js";
4
4
  import { FileItem, useFileUpload } from "./core/use-file-upload.js";
5
- import { CommentAttachmentInput, CommentMention, CommentThread, CommentView } from "./comments/comments.js";
6
5
  import { SoftrContext } from "./auth/context.js";
7
6
  import { checkAccess, defineVisibility, isAuthorized } from "./visibility/visibility.js";
8
7
  import { assertRouteAccess, guardRoute, isAccessError, isAlreadyAuthenticatedError, isForbiddenError, isUnauthenticatedError } from "./visibility/route.js";
@@ -12,4 +11,4 @@ import { useUserTimezone } from "./timezone.js";
12
11
  import { PwaInstall, PwaPlatform, SoftrPwaHead, usePwaInstall } from "./pwa.js";
13
12
  import { DefaultErrorOverlay } from "./default-error-overlay.js";
14
13
  import { Audience } from "./visibility/audience.js";
15
- export { type ActionPermissions, Audience, type CommentAttachmentInput, type CommentMention, type CommentThread, type CommentView, DefaultErrorOverlay, type FileAttachment, type FileItem, type PwaInstall, type PwaPlatform, type SoftrContext, type SoftrDatasources, SoftrPwaHead, type SoftrUserGroupId, type SoftrUserGroups, type User, assertRouteAccess, checkAccess, defineComments, defineIntegration, defineMutation, defineQuery, defineVisibility, defineWorkflow, getSoftrContext, guardRoute, initialSoftrContext, isAccessError, isAlreadyAuthenticatedError, isAuthorized, isForbiddenError, isUnauthenticatedError, softrAuthMiddleware, softrMcpMiddleware, useCurrentUser, useFileUpload, usePwaInstall, useUserTimezone };
14
+ export { type ActionPermissions, Audience, DefaultErrorOverlay, type FileAttachment, type FileItem, type PwaInstall, type PwaPlatform, type SoftrContext, type SoftrDatasources, SoftrPwaHead, type SoftrUserGroupId, type SoftrUserGroups, type User, assertRouteAccess, checkAccess, defineIntegration, defineMutation, defineQuery, defineVisibility, defineWorkflow, getSoftrContext, guardRoute, initialSoftrContext, isAccessError, isAlreadyAuthenticatedError, isAuthorized, isForbiddenError, isUnauthenticatedError, softrAuthMiddleware, softrMcpMiddleware, useCurrentUser, useFileUpload, usePwaInstall, useUserTimezone };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { useFileUpload } from "./core/use-file-upload.js";
2
- import { defineComments, defineIntegration, defineMutation, defineQuery, defineWorkflow } from "./action.js";
2
+ import { defineIntegration, defineMutation, defineQuery, defineWorkflow } from "./action.js";
3
3
  import { checkAccess, defineVisibility, isAuthorized } from "./visibility/visibility.js";
4
4
  import { assertRouteAccess, guardRoute, isAccessError, isAlreadyAuthenticatedError, isForbiddenError, isUnauthenticatedError } from "./visibility/route.js";
5
5
  import { SoftrPwaHead, usePwaInstall } from "./pwa.js";
@@ -9,4 +9,4 @@ import { useUserTimezone } from "./timezone.js";
9
9
  import { DefaultErrorOverlay } from "./default-error-overlay.js";
10
10
  import { Audience } from "./visibility/audience.js";
11
11
 
12
- export { Audience, DefaultErrorOverlay, SoftrPwaHead, assertRouteAccess, checkAccess, defineComments, defineIntegration, defineMutation, defineQuery, defineVisibility, defineWorkflow, getSoftrContext, guardRoute, initialSoftrContext, isAccessError, isAlreadyAuthenticatedError, isAuthorized, isForbiddenError, isUnauthenticatedError, softrAuthMiddleware, softrMcpMiddleware, useCurrentUser, useFileUpload, usePwaInstall, useUserTimezone };
12
+ export { Audience, DefaultErrorOverlay, SoftrPwaHead, assertRouteAccess, checkAccess, defineIntegration, defineMutation, defineQuery, defineVisibility, defineWorkflow, getSoftrContext, guardRoute, initialSoftrContext, isAccessError, isAlreadyAuthenticatedError, isAuthorized, isForbiddenError, isUnauthenticatedError, softrAuthMiddleware, softrMcpMiddleware, useCurrentUser, useFileUpload, usePwaInstall, useUserTimezone };
package/dist/mcp.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { DatasourceAction } from "./action.js";
2
- import * as _tanstack_react_start4 from "@tanstack/react-start";
2
+ import * as _tanstack_react_start3 from "@tanstack/react-start";
3
3
 
4
4
  //#region src/mcp.d.ts
5
5
 
@@ -37,6 +37,6 @@ type SoftrMcpOptions = {
37
37
  * ],
38
38
  * }))
39
39
  */
40
- declare function softrMcpMiddleware(options?: SoftrMcpOptions): _tanstack_react_start4.RequestMiddlewareAfterServer<{}, undefined, undefined>;
40
+ declare function softrMcpMiddleware(options?: SoftrMcpOptions): _tanstack_react_start3.RequestMiddlewareAfterServer<{}, undefined, undefined>;
41
41
  //#endregion
42
42
  export { softrMcpMiddleware };
package/dist/package.js CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "0.0.56-alpha.1";
2
+ var version = "0.0.56-alpha.3";
3
3
 
4
4
  //#endregion
5
5
  export { version };
package/dist/server.d.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  import { upload } from "./core/file-upload.js";
2
- import { comments } from "./comments/comments.js";
3
2
  import { auth } from "./auth/server.js";
4
3
  import { ds } from "./datasource/datasource.js";
5
4
  import { workflow } from "./core/workflow.js";
6
5
  import { integration } from "./core/integration.js";
7
6
  import "@tanstack/react-start/server-only";
8
- export { auth, comments, ds, integration, upload, workflow };
7
+ export { auth, ds, integration, upload, workflow };
package/dist/server.js CHANGED
@@ -3,7 +3,6 @@ import { ds } from "./datasource/datasource.js";
3
3
  import { auth } from "./auth/server.js";
4
4
  import { workflow } from "./core/workflow.js";
5
5
  import { integration } from "./core/integration.js";
6
- import { comments } from "./comments/comments.js";
7
6
  import "@tanstack/react-start/server-only";
8
7
 
9
- export { auth, comments, ds, integration, upload, workflow };
8
+ export { auth, ds, integration, upload, workflow };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softr/sdk",
3
- "version": "0.0.56-alpha.1",
3
+ "version": "0.0.56-alpha.3",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" },
@@ -17,8 +17,6 @@
17
17
  "typecheck": "tsc --noEmit"
18
18
  },
19
19
  "dependencies": {
20
- "marked": "^18.0.14",
21
- "xss": "^1.0.15",
22
20
  "zod": "^4.4.3"
23
21
  },
24
22
  "devDependencies": {
@@ -11,7 +11,7 @@ description: >-
11
11
  metadata:
12
12
  type: core
13
13
  library: softr-sdk
14
- library_version: 0.0.56-alpha.1
14
+ library_version: 0.0.55
15
15
  ---
16
16
 
17
17
  # Softr SDK core
@@ -29,9 +29,9 @@ Each sub-skill stands alone for its task and repeats the boundary above, so most
29
29
 
30
30
  | Import | Runs | Holds |
31
31
  | --- | --- | --- |
32
- | `@softr/sdk` | Both | `defineQuery`, `defineMutation`, `defineComments`, `defineVisibility`, `guardRoute`, `assertRouteAccess`, `isAuthorized`, `checkAccess`, `Audience`, `useCurrentUser`, `useUserTimezone`, `getSoftrContext`, `initialSoftrContext`, `softrAuthMiddleware`, the error predicates, and every type |
33
- | `@softr/sdk/server` | Server only | `ds`, `auth`, `workflow`, `integration`, `comments` |
34
- | `@softr/sdk/client` | Browser only | `useCommentComposer` |
32
+ | `@softr/sdk` | Both | `defineQuery`, `defineMutation`, `defineVisibility`, `guardRoute`, `assertRouteAccess`, `isAuthorized`, `checkAccess`, `Audience`, `useCurrentUser`, `useUserTimezone`, `SoftrPwaHead`, `usePwaInstall`, `getSoftrContext`, `initialSoftrContext`, `softrAuthMiddleware`, the error predicates, and every type |
33
+ | `@softr/sdk/server` | Server only | `ds`, `auth`, `workflow`, `integration` |
34
+ | `@softr/sdk/client` | Browser only | Nothing yet, reserved for browser-only utilities |
35
35
  | `@softr/sdk/vite` | Build | `softr()`, already in `vite.config.ts` |
36
36
 
37
37
  ## Sub-Skills
@@ -48,7 +48,7 @@ Each sub-skill stands alone for its task and repeats the boundary above, so most
48
48
  | Sign a visitor in, out, or up | [auth/SKILL.md](./auth/SKILL.md) |
49
49
  | Call a connected third-party API (Slack, Stripe, Gmail, …) | [integrations/SKILL.md](./integrations/SKILL.md) |
50
50
  | Open the app to AI assistants over MCP | [mcp/SKILL.md](./mcp/SKILL.md) |
51
- | Add comments to a record | [comments/SKILL.md](./comments/SKILL.md) |
51
+ | Let visitors install the app on their home screen | [pwa/SKILL.md](./pwa/SKILL.md) |
52
52
 
53
53
  ## Quick Decision Tree
54
54
 
@@ -83,8 +83,8 @@ Calling a connected third-party API (Slack, Stripe, Gmail, Google Calendar, …)
83
83
  Opening the app to an AI assistant over MCP?
84
84
  load softr-sdk/mcp
85
85
 
86
- Letting visitors comment on a record?
87
- load softr-sdk/comments
86
+ Adding an install button, or making the app installable?
87
+ load softr-sdk/pwa
88
88
 
89
89
  Writing a server function, loader, or middleware in general?
90
90
  not a Softr concern. Use the TanStack Start skills.
@@ -16,7 +16,7 @@ description: >-
16
16
  metadata:
17
17
  type: sub-skill
18
18
  library: softr-sdk
19
- library_version: 0.0.56-alpha.1
19
+ library_version: 0.0.55
20
20
  ---
21
21
 
22
22
  **Boundary.** `auth` lives on `@softr/sdk/server` and runs only inside a `createServerFn` handler — importing it into a component fails the build.
@@ -12,7 +12,7 @@ description: >-
12
12
  metadata:
13
13
  type: sub-skill
14
14
  library: softr-sdk
15
- library_version: 0.0.56-alpha.1
15
+ library_version: 0.0.55
16
16
  ---
17
17
 
18
18
  **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.56-alpha.1
12
+ library_version: 0.0.55
13
13
  ---
14
14
 
15
15
  # The current user
@@ -10,7 +10,7 @@ description: >-
10
10
  metadata:
11
11
  type: sub-skill
12
12
  library: softr-sdk
13
- library_version: 0.0.56-alpha.1
13
+ library_version: 0.0.55
14
14
  ---
15
15
 
16
16
  **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.
@@ -75,10 +75,9 @@ function ApplicationForm() {
75
75
 
76
76
  ```ts
77
77
  type FileAttachment = {
78
- url: string // clean URL, no internal query params
79
- filename: string // original filename
80
- id: string // file id extracted from the upload response
81
- type?: string | null // content type from the upload response, or null when the platform doesn't know it
78
+ url: string // clean URL, no internal query params
79
+ filename: string // original filename
80
+ id: string // file id extracted from the upload response
82
81
  }
83
82
  ```
84
83
 
@@ -10,7 +10,7 @@ description: >-
10
10
  metadata:
11
11
  type: sub-skill
12
12
  library: softr-sdk
13
- library_version: 0.0.56-alpha.1
13
+ library_version: 0.0.55
14
14
  ---
15
15
 
16
16
  **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.56-alpha.1
12
+ library_version: 0.0.55
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.56-alpha.1
12
+ library_version: 0.0.55
13
13
  ---
14
14
 
15
15
  # Installing the app
@@ -11,7 +11,7 @@ description: >-
11
11
  metadata:
12
12
  type: sub-skill
13
13
  library: softr-sdk
14
- library_version: 0.0.56-alpha.1
14
+ library_version: 0.0.55
15
15
  ---
16
16
 
17
17
  **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.
@@ -13,10 +13,10 @@ description: >-
13
13
  metadata:
14
14
  type: sub-skill
15
15
  library: softr-sdk
16
- library_version: 0.0.56-alpha.1
16
+ library_version: 0.0.55
17
17
  ---
18
18
 
19
- **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.
19
+ **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.
20
20
 
21
21
  # Reading records
22
22
 
@@ -183,7 +183,7 @@ A read the datasource turns down throws rather than coming back empty, and it th
183
183
 
184
184
  ## Typing
185
185
 
186
- Queries you write are type safe and a type error is shown when there's a mistake. For an in depth reference on what fields every datasource has, read `docs/datasources/README.md` first — it lists every registered datasource with a link to its file. Follow those links to get field ids, types, and constraints. Do not guess filenames from table names.
186
+ Queries you write are type safe and a type error is shown when there's a mistake. The records a read returns are typed the same way, so never validate them again with a zod schema of your own. A schema guesses each field's shape, and one value it misses, such as a person with no email, throws for the whole read and the page stops loading. Show each field with a fallback instead: `record.fields.owner?.name ?? '—'`. For an in depth reference on what fields every datasource has, read `docs/datasources/README.md` first — it lists every registered datasource with a link to its file. Follow those links to get field ids, types, and constraints. Do not guess filenames from table names.
187
187
 
188
188
  ## References
189
189
 
@@ -27,7 +27,7 @@ CHECKBOX: boolean
27
27
  SELECT: { id: string; label: string | null } // generated with literal id and label unions
28
28
  LINKED_RECORD: { id: string; label: string | null } // label is the linked record's primary field
29
29
  DATE_RANGE: { from: string; to: string }
30
- USER: { id: string; name: string; email: string; avatarUrl: string | null }
30
+ USER: { id: string; name: string | null; email: string | null; avatarUrl: string | null }
31
31
  ATTACHMENT: {
32
32
  id: string | null
33
33
  filename: string | null
@@ -56,7 +56,11 @@ Every scalar above is `| null` on the record unless the field allows multiple en
56
56
  <td>{record.fields.status}</td>
57
57
  ```
58
58
 
59
- **DURATION** is seconds, whatever format the field displays in.
59
+ **CREATED_BY and UPDATED_BY** are the person's name as a plain string, not a `USER` object.
60
+
61
+ **USER** can lack a name or an email: show `owner?.name ?? owner?.email ?? '—'`, never assume either is there.
62
+
63
+ **DURATION** is milliseconds, whatever format the field displays in: `3600000` is one hour.
60
64
 
61
65
  **DATETIME at date precision** is generated as a `DATE` field and holds `'2026-03-14'`, not a timestamp.
62
66
 
@@ -9,7 +9,7 @@ description: >-
9
9
  metadata:
10
10
  type: sub-skill
11
11
  library: softr-sdk
12
- library_version: 0.0.56-alpha.1
12
+ library_version: 0.0.55
13
13
  ---
14
14
 
15
15
  **Boundary.** `Audience` and `defineVisibility` come from `@softr/sdk` and work anywhere.
@@ -13,7 +13,7 @@ description: >-
13
13
  metadata:
14
14
  type: sub-skill
15
15
  library: softr-sdk
16
- library_version: 0.0.56-alpha.1
16
+ library_version: 0.0.55
17
17
  ---
18
18
 
19
19
  **Boundary.** `defineVisibility`, 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.56-alpha.1
12
+ library_version: 0.0.55
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.