@softr/sdk 0.0.68-props.0 → 0.0.68-props.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.
@@ -59,4 +59,4 @@ function throwAtCaller(f, ex) {
59
59
  }
60
60
 
61
61
  //#endregion
62
- export { assert, panic, requireDefined, softAssert };
62
+ export { assert, panic, requireDefined, softAssert, throwAtCaller };
@@ -2,9 +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 react0 from "react";
5
+ import * as react6 from "react";
6
6
  import { ReactNode } from "react";
7
- import * as _tanstack_react_start0 from "@tanstack/react-start";
7
+ import * as _tanstack_react_start1 from "@tanstack/react-start";
8
8
 
9
9
  //#region src/auth/isomorphic.d.ts
10
10
 
@@ -21,7 +21,7 @@ import * as _tanstack_react_start0 from "@tanstack/react-start";
21
21
  * requestMiddleware: [softrAuthMiddleware()],
22
22
  * }))
23
23
  */
24
- 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>], {
25
25
  user: User | null;
26
26
  permissions: Permissions;
27
27
  formatting: Formatting;
@@ -35,7 +35,7 @@ declare function softrAuthMiddleware(): _tanstack_react_start0.RequestMiddleware
35
35
  * beforeLoad: async () => await getSoftrContext(),
36
36
  * })
37
37
  */
38
- declare const getSoftrContext: _tanstack_react_start0.OptionalFetcher<undefined, undefined, Promise<SoftrContext>>;
38
+ declare const getSoftrContext: _tanstack_react_start1.OptionalFetcher<undefined, undefined, Promise<SoftrContext>>;
39
39
  /**
40
40
  * The context to hand `createRouter`, before any request has resolved one.
41
41
  *
@@ -83,7 +83,7 @@ type AuthOptions = {
83
83
  * staleTime: 60_000,
84
84
  * })
85
85
  */
86
- declare const getAuthSettings: _tanstack_react_start0.OptionalFetcher<undefined, undefined, Promise<AuthOptions>>;
86
+ declare const getAuthSettings: _tanstack_react_start1.OptionalFetcher<undefined, undefined, Promise<AuthOptions>>;
87
87
  /**
88
88
  * Makes the auth options readable with {@link useAuthSettings} anywhere below.
89
89
  *
@@ -103,7 +103,7 @@ declare function AuthSettingsProvider({
103
103
  }: {
104
104
  value: AuthOptions;
105
105
  children?: ReactNode;
106
- }): react0.JSX.Element;
106
+ }): react6.JSX.Element;
107
107
  /**
108
108
  * Which ways in this app offers. Requires an {@link AuthSettingsProvider}
109
109
  * above it.
package/dist/cli.js CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import { version } from "./package.js";
3
3
  import { requireDefined } from "./assertions.js";
4
+ import { SoftrConfigError, loadSoftrConfig } from "./softr-config.schema.js";
4
5
  import { fetchSoftrEnvInput, metadataSourceFromEnv } from "./codegen/fetch-metadata.js";
5
6
  import { renderUserPropertiesDoc } from "./codegen/datasource-docs.js";
6
7
  import { renderUserGroupsDoc } from "./codegen/user-groups.js";
7
8
  import { renderSoftrEnv } from "./codegen/softr-env.js";
8
9
  import { writeIfChanged } from "./codegen/write-if-changed.js";
9
10
  import { writeDatasourceDocs } from "./codegen/write-datasource-docs.js";
10
- import { loadSoftrConfig } from "./softr-config.schema.js";
11
11
  import { rmSync, writeFileSync } from "node:fs";
12
12
  import path from "node:path";
13
13
  import { parseArgs } from "node:util";
@@ -76,7 +76,18 @@ const { positionals, values } = parseArgs({
76
76
  } }
77
77
  });
78
78
  const [command] = positionals;
79
- if (command === "generate") await generate({ json: values.json });
79
+ if (command === "generate") try {
80
+ await generate({ json: values.json });
81
+ } catch (error) {
82
+ if (!values.json) throw error;
83
+ const kind = error instanceof SoftrConfigError ? "softr-config" : "other";
84
+ const message = error instanceof Error ? error.message : String(error);
85
+ process.stdout.write(`${JSON.stringify({ error: {
86
+ kind,
87
+ message
88
+ } })}\n`);
89
+ process.exit(1);
90
+ }
80
91
  else {
81
92
  console.error(command ? `softr-sdk: unknown command '${command}'` : "softr-sdk: no command given");
82
93
  console.error("usage: softr-sdk generate [--json]");
@@ -33,8 +33,7 @@ function renderUserPropertiesDoc(users, context) {
33
33
  return [
34
34
  "# User properties",
35
35
  "",
36
- `Users datasource: ${displayName(users.name) || users.tableId} `,
37
- `Datasource ID: ${users.datasourceId}` + (registered === void 0 ? "" : ` \nRegistered as: [${datasourceLabel(registered)}](./datasources/${requireDefined(context.fileNames.get(registered.id))}) (${registered.id})`),
36
+ `Users datasource: ${displayName(users.name) || users.tableId}` + (registered === void 0 ? "" : ` \nRegistered as: [${datasourceLabel(registered)}](./datasources/${requireDefined(context.fileNames.get(registered.id))}) (${registered.id})`),
38
37
  "",
39
38
  "> This document is generated automatically when softr.json's `user.properties` or the users table changes.",
40
39
  "",
@@ -1,5 +1,6 @@
1
- import { assert, panic } from "../assertions.js";
1
+ import { panic } from "../assertions.js";
2
2
  import { fetch } from "../fetch.js";
3
+ import { panicConfig } from "../softr-config.schema.js";
3
4
 
4
5
  //#region src/codegen/fetch-metadata.ts
5
6
  function metadataSourceFromEnv(env = process.env) {
@@ -31,21 +32,15 @@ async function fetchSoftrEnvInput(source, aliases) {
31
32
  }));
32
33
  let users = null;
33
34
  if (Object.keys(aliases).length > 0) {
34
- const { payload } = await apiFetch(`${studioApiUrl}/v1/applications/${applicationId}`, token);
35
- const connection = payload.user_connection?.datasource ?? panic("softr.json declares user.properties, but this app has no users table.");
36
- const metadata = await apiFetch(`${datasourceApiUrl}/v1/datasource/${applicationId}/${connection.integration_id}/metadata`, token, {
37
- datasourceType: connection.datasource_integration_type,
38
- resourceIdentifier: { keys: connection.resource_identifier.keys }
39
- });
35
+ const metadata = await apiFetch(`${datasourceApiUrl}/v1/datasource/vibe/studio/applications/${applicationId}/datasources/user-connection/metadata`, token, () => panic("softr.json declares user.properties, but this app has no users table."));
40
36
  users = {
41
- datasourceId: connection.id,
42
37
  tableId: metadata.id,
43
38
  name: metadata.name,
44
39
  properties: {}
45
40
  };
46
41
  for (const [alias, fieldId] of Object.entries(aliases)) {
47
- const field = metadata.fields.find(({ id }) => id === fieldId) ?? panic(`softr.json user.properties.${alias} names "${fieldId}", which is not a field of the users table.`);
48
- assert(field.type !== "ATTACHMENT" && field.type !== "LONG_TEXT" && !(field.allowMultipleEntries && (field.type === "LINKED_RECORD" || field.type === "LOOKUP")), `softr.json user.properties.${alias} names "${field.name}", a ${field.allowMultipleEntries ? "multiple " : ""}${field.type} field, which can be too big to read with the signed-in user. Remove it, and read it with defineQuery on the users table instead.`);
42
+ const field = metadata.fields.find(({ id }) => id === fieldId) ?? panicConfig(`softr.json user.properties.${alias} names "${fieldId}", which is not a field of the users table.`);
43
+ if (field.type === "ATTACHMENT" || field.type === "LONG_TEXT" || field.allowMultipleEntries && (field.type === "LINKED_RECORD" || field.type === "LOOKUP")) panicConfig(`softr.json user.properties.${alias} names "${field.name}", a ${field.allowMultipleEntries ? "multiple " : ""}${field.type} field, which can be too big to read with the signed-in user. Remove it, and read it with defineQuery on the users table instead.`);
49
44
  users.properties[alias] = field;
50
45
  }
51
46
  }
@@ -55,16 +50,12 @@ async function fetchSoftrEnvInput(source, aliases) {
55
50
  users
56
51
  };
57
52
  }
58
- async function apiFetch(url, token, body) {
59
- const response = await fetch(url, {
60
- method: body === void 0 ? "GET" : "POST",
61
- headers: {
62
- accept: "application/json",
63
- ...body === void 0 ? {} : { "content-type": "application/json" },
64
- Authorization: `Bearer ${token}`
65
- },
66
- body: body === void 0 ? void 0 : JSON.stringify(body)
67
- }).catch(() => panic(`Could not reach ${url}`));
53
+ async function apiFetch(url, token, notFound = () => panic(`${url} answered 404`)) {
54
+ const response = await fetch(url, { headers: {
55
+ accept: "application/json",
56
+ Authorization: `Bearer ${token}`
57
+ } }).catch(() => panic(`Could not reach ${url}`));
58
+ if (response.status === 404) return notFound();
68
59
  if (!response.ok) panic(`${url} answered ${response.status}`);
69
60
  return await response.json();
70
61
  }
@@ -1,4 +1,4 @@
1
- import * as react6 from "react";
1
+ import * as react5 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): react6.JSX.Element;
11
+ }: Props): react5.JSX.Element;
12
12
  //#endregion
13
13
  export { DefaultErrorOverlay };
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import * as react2 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
- }): react2.FunctionComponentElement<react2.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
- }): react2.FunctionComponentElement<react2.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_start4 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
 
@@ -31,6 +31,6 @@ type SoftrMcpOptions = {
31
31
  * ],
32
32
  * }))
33
33
  */
34
- declare function softrMcpMiddleware(options?: SoftrMcpOptions): _tanstack_react_start4.RequestMiddlewareAfterServer<{}, undefined, undefined>;
34
+ declare function softrMcpMiddleware(options?: SoftrMcpOptions): _tanstack_react_start0.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.68-props.0";
2
+ var version = "0.0.68-props.1";
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 react3 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(): react3.FunctionComponentElement<react3.FragmentProps>;
27
27
  type PwaPlatform = "ios" | "android" | "desktop";
28
28
  type PwaInstall = {
29
29
  available: false;
@@ -1,10 +1,17 @@
1
- import { assert, panic } from "./assertions.js";
1
+ import { throwAtCaller } from "./assertions.js";
2
2
  import { existsSync, readFileSync } from "node:fs";
3
3
  import path from "node:path";
4
4
  import { z } from "zod";
5
5
 
6
6
  //#region src/softr-config.schema.ts
7
7
  const SOFTR_CONFIG_FILE = "softr.json";
8
+ /** The cause is in softr.json, so the app's author can fix it. */
9
+ var SoftrConfigError = class extends Error {
10
+ name = "SoftrConfigError";
11
+ };
12
+ function panicConfig(message) {
13
+ throwAtCaller(panicConfig, new SoftrConfigError(message));
14
+ }
8
15
  const AccessBehaviour = z.union([
9
16
  z.string(),
10
17
  z.object({
@@ -44,18 +51,18 @@ const SoftrConfigSchema = z.object({
44
51
  });
45
52
  function loadSoftrConfig(root) {
46
53
  const file = path.join(root, SOFTR_CONFIG_FILE);
47
- assert(existsSync(file), `${SOFTR_CONFIG_FILE} is missing from ${root}`);
54
+ if (!existsSync(file)) panicConfig(`${SOFTR_CONFIG_FILE} is missing from ${root}`);
48
55
  const source = readFileSync(file, "utf8");
49
56
  let parsed;
50
57
  try {
51
58
  parsed = JSON.parse(source);
52
59
  } catch (error) {
53
- panic(`${SOFTR_CONFIG_FILE} is not valid JSON: ${error instanceof Error ? error.message : error}`);
60
+ panicConfig(`${SOFTR_CONFIG_FILE} is not valid JSON: ${error instanceof Error ? error.message : error}`);
54
61
  }
55
62
  const result = SoftrConfigSchema.safeParse(parsed);
56
- if (!result.success) panic(`${SOFTR_CONFIG_FILE} does not match the schema:\n\n${z.prettifyError(result.error)}`);
63
+ if (!result.success) panicConfig(`${SOFTR_CONFIG_FILE} does not match the schema:\n\n${z.prettifyError(result.error)}`);
57
64
  return result.data;
58
65
  }
59
66
 
60
67
  //#endregion
61
- export { SOFTR_CONFIG_FILE, loadSoftrConfig };
68
+ export { SOFTR_CONFIG_FILE, SoftrConfigError, loadSoftrConfig, panicConfig };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softr/sdk",
3
- "version": "0.0.68-props.0",
3
+ "version": "0.0.68-props.1",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -12,7 +12,7 @@ description: >-
12
12
  metadata:
13
13
  type: core
14
14
  library: softr-sdk
15
- library_version: 0.0.68-props.0
15
+ library_version: 0.0.68-props.1
16
16
  ---
17
17
 
18
18
  # Softr SDK core
@@ -19,7 +19,7 @@ description: >-
19
19
  metadata:
20
20
  type: sub-skill
21
21
  library: softr-sdk
22
- library_version: 0.0.68-props.0
22
+ library_version: 0.0.68-props.1
23
23
  ---
24
24
 
25
25
  **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.68-props.0
15
+ library_version: 0.0.68-props.1
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.
@@ -10,7 +10,7 @@ description: >-
10
10
  metadata:
11
11
  type: sub-skill
12
12
  library: softr-sdk
13
- library_version: 0.0.68-props.0
13
+ library_version: 0.0.68-props.1
14
14
  ---
15
15
 
16
16
  # 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.68-props.0
13
+ library_version: 0.0.68-props.1
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.
@@ -10,7 +10,7 @@ description: >-
10
10
  metadata:
11
11
  type: sub-skill
12
12
  library: softr-sdk
13
- library_version: 0.0.68-props.0
13
+ library_version: 0.0.68-props.1
14
14
  ---
15
15
 
16
16
  # Dates, times and numbers
@@ -10,7 +10,7 @@ description: >-
10
10
  metadata:
11
11
  type: sub-skill
12
12
  library: softr-sdk
13
- library_version: 0.0.68-props.0
13
+ library_version: 0.0.68-props.1
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.68-props.0
12
+ library_version: 0.0.68-props.1
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.68-props.0
12
+ library_version: 0.0.68-props.1
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.68-props.0
14
+ library_version: 0.0.68-props.1
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,7 +13,7 @@ description: >-
13
13
  metadata:
14
14
  type: sub-skill
15
15
  library: softr-sdk
16
- library_version: 0.0.68-props.0
16
+ library_version: 0.0.68-props.1
17
17
  ---
18
18
 
19
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.
@@ -9,7 +9,7 @@ description: >-
9
9
  metadata:
10
10
  type: sub-skill
11
11
  library: softr-sdk
12
- library_version: 0.0.68-props.0
12
+ library_version: 0.0.68-props.1
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.68-props.0
16
+ library_version: 0.0.68-props.1
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.68-props.0
12
+ library_version: 0.0.68-props.1
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.