@softr/sdk 0.0.45-alpha.1 → 0.0.45-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.
@@ -69,16 +69,21 @@ function errorPage(error) {
69
69
  setOpen(toggle.getAttribute('aria-expanded') === 'false')
70
70
  })
71
71
 
72
- document.getElementById('copy').addEventListener('click', async (event) => {
73
- const button = event.currentTarget
72
+ const copyStack = async () => {
74
73
  try {
75
74
  await navigator.clipboard.writeText(stack.textContent)
76
- button.dataset.copied = ''
77
- setTimeout(() => delete button.dataset.copied, 1500)
75
+ return true
78
76
  } catch {
79
- // Denied clipboard permission. Select it so Ctrl/Cmd+C works.
80
77
  getSelection().selectAllChildren(stack)
78
+ return document.execCommand('copy')
81
79
  }
80
+ }
81
+
82
+ document.getElementById('copy').addEventListener('click', async (event) => {
83
+ const button = event.currentTarget
84
+ if (!(await copyStack())) return
85
+ button.dataset.copied = ''
86
+ setTimeout(() => delete button.dataset.copied, 1500)
82
87
  })
83
88
  <\/script>` : ""
84
89
  });
@@ -4,7 +4,7 @@ import { readUserTimezone } from "../cookies.js";
4
4
  import { readSessionToken } from "../auth/session.js";
5
5
  import { INTERNAL_KIND, buildFilterCriteria, buildOrderBy, dealiasFilterCriteria } from "./filter.js";
6
6
  import { andAll, makeFieldSet, makeSortSet } from "./fields.js";
7
- import { dsUrl, resolveTarget } from "./record.js";
7
+ import { describeFailure, dsUrl, resolveTarget } from "./record.js";
8
8
 
9
9
  //#region src/datasource/chart.ts
10
10
  const COUNT_CNT = "COUNT_CNT";
@@ -202,7 +202,7 @@ async function executeChart(query, state) {
202
202
  },
203
203
  body: JSON.stringify(body)
204
204
  });
205
- if (!res.ok) throw new Error(`Softr datasource chart failed for action "${actionId}": ${res.status}`);
205
+ if (!res.ok) throw new Error(`datasource chart failed for action "${actionId}": ${await describeFailure(res)}`);
206
206
  const payload = await res.json();
207
207
  return {
208
208
  data: mapChartRows(columns, payload.data),
@@ -275,7 +275,7 @@ async function executeMetric(query, handle, filters) {
275
275
  },
276
276
  body: JSON.stringify(body)
277
277
  });
278
- if (!res.ok) throw new Error(`Softr datasource metric failed for action "${actionId}": ${res.status}`);
278
+ if (!res.ok) throw new Error(`datasource metric failed for action "${actionId}": ${await describeFailure(res)}`);
279
279
  const payload = await res.json();
280
280
  return {
281
281
  value: readMetricValue(responseKey, payload.data),
@@ -15,6 +15,11 @@ const dsUrl = (actionId) => {
15
15
  if (!applicationId) panic("SOFTR_APPLICATION_ID is not set.");
16
16
  return `${withoutTrailingSlash(datasourceApiUrl)}/v1/datasource/vibe/applications/${applicationId}/actions/${actionId}`;
17
17
  };
18
+ async function describeFailure(res) {
19
+ const body = await res.json().catch(() => null);
20
+ const message = typeof body === "object" && body !== null && "message" in body ? body.message : null;
21
+ return typeof message === "string" && message.length > 0 ? `${res.status} ${message}` : `${res.status}`;
22
+ }
18
23
  /**
19
24
  * Queries a list of records from the datasource.
20
25
  *
@@ -87,7 +92,7 @@ async function executeList(query, args) {
87
92
  }
88
93
  })
89
94
  });
90
- if (!res.ok) throw new Error(`Softr datasource list failed for "${actionId}": ${res.status}`);
95
+ if (!res.ok) throw new Error(`datasource list failed for "${actionId}": ${await describeFailure(res)}`);
91
96
  const payload = await res.json();
92
97
  const nextOffset = payload.offset < payload.total ? payload.offset : null;
93
98
  return {
@@ -153,7 +158,7 @@ async function executeGet(query, id, filters) {
153
158
  filterCriteria
154
159
  })
155
160
  });
156
- if (!res.ok) throw new Error(`Softr datasource get failed for action "${actionId}": ${res.status}`);
161
+ if (!res.ok) throw new Error(`datasource get failed for action "${actionId}": ${await describeFailure(res)}`);
157
162
  const contentLength = res.headers.get("Content-Length");
158
163
  if (contentLength && parseInt(contentLength, 10) === 0) return null;
159
164
  const record = await res.json();
@@ -182,7 +187,7 @@ async function createRecord(action, options) {
182
187
  },
183
188
  body: JSON.stringify({ fields: rawFields })
184
189
  });
185
- if (!res.ok) throw new Error(`Softr datasource create failed for action "${actionId}": ${res.status}`);
190
+ if (!res.ok) throw new Error(`datasource create failed for action "${actionId}": ${await describeFailure(res)}`);
186
191
  const record = await res.json();
187
192
  return {
188
193
  id: record.id,
@@ -199,7 +204,7 @@ async function createRecord(action, options) {
199
204
  * })
200
205
  */
201
206
  async function updateRecord(action, options) {
202
- if (!options.id) throw new Error(`Softr datasource update: id must not be empty`);
207
+ if (!options.id) throw new Error(`datasource update: id must not be empty`);
203
208
  const { actionId, select } = resolveTarget(action, "update");
204
209
  const data = options.data;
205
210
  const rawFields = dealiasData(data, select);
@@ -211,7 +216,7 @@ async function updateRecord(action, options) {
211
216
  },
212
217
  body: JSON.stringify({ fields: rawFields })
213
218
  });
214
- if (!res.ok) throw new Error(`Softr datasource update failed for action "${actionId}": ${res.status}`);
219
+ if (!res.ok) throw new Error(`datasource update failed for action "${actionId}": ${await describeFailure(res)}`);
215
220
  const record = await res.json();
216
221
  return {
217
222
  id: record.id,
@@ -230,7 +235,7 @@ async function deleteRecord(action, options) {
230
235
  method: "DELETE",
231
236
  headers: { Authorization: `Bearer ${readSessionToken()}` }
232
237
  });
233
- if (!res.ok) throw new Error(`Softr datasource delete failed for action "${actionId}": ${res.status}`);
238
+ if (!res.ok) throw new Error(`datasource delete failed for action "${actionId}": ${await describeFailure(res)}`);
234
239
  }
235
240
  function resolveTarget(subject, operation) {
236
241
  const declaredBy = operation === "read" ? "defineQuery" : "defineMutation";
@@ -244,7 +249,7 @@ function resolveTarget(subject, operation) {
244
249
  }
245
250
  function aliasFields(fields, aliases) {
246
251
  const result = {};
247
- for (const [alias, fieldId] of Object.entries(aliases)) result[alias] = fields[fieldId];
252
+ for (const [alias, fieldId] of Object.entries(aliases)) result[alias] = fields[fieldId] ?? null;
248
253
  return result;
249
254
  }
250
255
  function dealiasData(data, select) {
@@ -257,4 +262,4 @@ function withoutTrailingSlash(url) {
257
262
  }
258
263
 
259
264
  //#endregion
260
- export { createRecord, deleteRecord, dsUrl, getRecord, listRecords, resolveTarget, updateRecord };
265
+ export { createRecord, deleteRecord, describeFailure, dsUrl, getRecord, listRecords, resolveTarget, updateRecord };
@@ -65,15 +65,20 @@ function StackTrace({ stack }) {
65
65
  const [copied, setCopied] = useState(false);
66
66
  const ref = useRef(null);
67
67
  if (!cleaned) return null;
68
- async function copy() {
68
+ async function copyStack() {
69
69
  try {
70
70
  await navigator.clipboard.writeText(cleaned);
71
- setCopied(true);
72
- setTimeout(() => setCopied(false), 1500);
71
+ return true;
73
72
  } catch {
74
73
  if (ref.current) getSelection()?.selectAllChildren(ref.current);
74
+ return document.execCommand("copy");
75
75
  }
76
76
  }
77
+ async function copy() {
78
+ if (!await copyStack()) return;
79
+ setCopied(true);
80
+ setTimeout(() => setCopied(false), 1500);
81
+ }
77
82
  return /* @__PURE__ */ jsxs("div", {
78
83
  style: {
79
84
  display: "flex",
package/dist/package.js CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "0.0.45";
2
+ var version = "0.0.45-alpha.3";
3
3
 
4
4
  //#endregion
5
5
  export { version };
package/package.json CHANGED
@@ -1,37 +1,16 @@
1
1
  {
2
2
  "name": "@softr/sdk",
3
- "version": "0.0.45-alpha.1",
3
+ "version": "0.0.45-alpha.3",
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",
@@ -179,7 +179,7 @@ ds.list(products).where((q) => q.status.is(selectedStatusId))
179
179
 
180
180
  Skip this request when the options are predefined and fixed — hardcode them instead.
181
181
 
182
- A read the datasource turns down throws rather than coming back empty, and it throws a plain `Error` carrying the status. There is no typed predicate to narrow it with. Handle it where you would handle any other failed fetch: an `errorComponent` on the route, or a check in the handler.
182
+ A read the datasource turns down throws rather than coming back empty, and it throws a plain `Error` carrying the status, followed by the reason the datasource gives when it sends one. There is no typed predicate to narrow it with. Handle it where you would handle any other failed fetch: an `errorComponent` on the route, or a check in the handler.
183
183
 
184
184
  ## Typing
185
185