@lotics/app-sdk 0.122.2 → 0.122.4

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.
@@ -173,6 +173,13 @@ function transportErrorMessage(status, parsed) {
173
173
  const authored = typeof parsed.code === "string" && parsed.code.length > 0;
174
174
  return status < 500 || authored ? jsonMessage : gatewayErrorMessage(status);
175
175
  }
176
+ function telemetryErrorMessage(status, parsed) {
177
+ if (parsed === null || typeof parsed !== "object") return gatewayErrorMessage(status);
178
+ const code = "code" in parsed && typeof parsed.code === "string" && parsed.code.length > 0 ? parsed.code : null;
179
+ const system = "message_source" in parsed && parsed.message_source === "system";
180
+ if (system && "message" in parsed && typeof parsed.message === "string") return parsed.message;
181
+ return code ?? gatewayErrorMessage(status);
182
+ }
176
183
 
177
184
  // ../shared/src/schemas/app_spec_rules.ts
178
185
  function tiersAscend(tiers) {
@@ -1521,11 +1528,13 @@ async function boot() {
1521
1528
  return attempt;
1522
1529
  }
1523
1530
  var ApiRefusal = class extends Error {
1524
- constructor(message, field_errors) {
1525
- super(message);
1531
+ constructor(status, parsed, field_errors) {
1532
+ super(transportErrorMessage(status, parsed));
1526
1533
  this.field_errors = field_errors;
1534
+ this.telemetryMessage = telemetryErrorMessage(status, parsed);
1527
1535
  }
1528
1536
  field_errors;
1537
+ telemetryMessage;
1529
1538
  };
1530
1539
  function readFieldErrors(parsed) {
1531
1540
  if (parsed === null || typeof parsed !== "object" || !("field_errors" in parsed)) {
@@ -1547,7 +1556,7 @@ async function streamStartError(res) {
1547
1556
  } catch {
1548
1557
  }
1549
1558
  }
1550
- return new Error(transportErrorMessage(res.status, parsed));
1559
+ return new ApiRefusal(res.status, parsed);
1551
1560
  }
1552
1561
  var API_TIMEOUT_MS = 3e4;
1553
1562
  async function apiCall(method, path, body, opts) {
@@ -1597,7 +1606,7 @@ async function apiCall(method, path, body, opts) {
1597
1606
  return new Promise(() => {
1598
1607
  });
1599
1608
  }
1600
- throw new ApiRefusal(transportErrorMessage(res.status, parsed), readFieldErrors(parsed));
1609
+ throw new ApiRefusal(res.status, parsed, readFieldErrors(parsed));
1601
1610
  }
1602
1611
  return parsed ?? (text ? text : {});
1603
1612
  }
@@ -1766,7 +1775,7 @@ async function sendAskedReads() {
1766
1775
  const answer = results[k];
1767
1776
  if (answer === void 0) read.reject(new Error(`The server answered ${results.length} of ${chunk.length} reads.`));
1768
1777
  else if ("result" in answer) read.resolve(answer.result);
1769
- else read.reject(new ApiRefusal(transportErrorMessage(answer.error.status, answer.error)));
1778
+ else read.reject(new ApiRefusal(answer.error.status, answer.error));
1770
1779
  });
1771
1780
  }).catch((error) => chunk.forEach((read) => read.reject(error)));
1772
1781
  }
@@ -1779,7 +1788,14 @@ function batchResults(answered) {
1779
1788
  if (answer !== null && typeof answer === "object" && "result" in answer) return { result: answer.result };
1780
1789
  const error = answer !== null && typeof answer === "object" && "error" in answer ? answer.error : void 0;
1781
1790
  if (error !== null && typeof error === "object" && "status" in error && typeof error.status === "number" && "message" in error && typeof error.message === "string") {
1782
- return { error: { status: error.status, message: error.message, code: "code" in error ? error.code : void 0 } };
1791
+ return {
1792
+ error: {
1793
+ status: error.status,
1794
+ message: error.message,
1795
+ code: "code" in error ? error.code : void 0,
1796
+ message_source: "message_source" in error ? error.message_source : void 0
1797
+ }
1798
+ };
1783
1799
  }
1784
1800
  throw new Error(`The server's batch answer ${at} is neither a result nor a refusal.`);
1785
1801
  });
package/dist/index.js CHANGED
@@ -40,7 +40,7 @@ import {
40
40
  sumDecimal,
41
41
  tiersAscend,
42
42
  urlParam
43
- } from "./chunk-I2BOTPL6.js";
43
+ } from "./chunk-GXEBJ3RC.js";
44
44
 
45
45
  // src/mount.tsx
46
46
  import { createRoot } from "react-dom/client";
@@ -94,6 +94,14 @@ function getMockRecordings() {
94
94
  // ../shared/src/app_host/app_spec_inline.ts
95
95
  var APP_SPEC_ELEMENT_ID = "lotics-app-spec";
96
96
 
97
+ // ../shared/src/customer_worded.ts
98
+ function isCustomerWorded(error51) {
99
+ return "telemetryMessage" in error51 && typeof error51.telemetryMessage === "string";
100
+ }
101
+ function telemetryMessage(error51) {
102
+ return isCustomerWorded(error51) ? error51.telemetryMessage : error51.message;
103
+ }
104
+
97
105
  // src/error_report.ts
98
106
  var REPORTS_PER_PAGE = 5;
99
107
  var MESSAGE_LIMIT = 300;
@@ -107,7 +115,8 @@ function reportAppError(kind, error51) {
107
115
  kind,
108
116
  served: document.getElementById(APP_SPEC_ELEMENT_ID) === null ? "bundle" : "spec",
109
117
  name: known ? error51.name : typeof error51,
110
- message: withoutOrigins(known ? error51.message : String(error51)).slice(0, MESSAGE_LIMIT),
118
+ // A refusal's own sentence can be a customer's (a table check's); the report says it in ours.
119
+ message: withoutOrigins(known ? telemetryMessage(error51) : String(error51)).slice(0, MESSAGE_LIMIT),
111
120
  stack_top: known && error51.stack !== void 0 ? firstFrame(error51, error51.stack) : null
112
121
  });
113
122
  }
package/dist/router.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  isEmbedded,
3
3
  postHostNotification,
4
4
  setUrlParams
5
- } from "./chunk-I2BOTPL6.js";
5
+ } from "./chunk-GXEBJ3RC.js";
6
6
 
7
7
  // src/router.tsx
8
8
  import { useEffect } from "react";
package/docs/ai.md CHANGED
@@ -358,7 +358,7 @@ workflows (run_app_workflow):
358
358
  `?` marks an input the caller may omit, `[]` one that takes a list, a
359
359
  `select` spells out every legal value as `label=value` — **the agent sends the
360
360
  value** — and a `record_link` names the table an id must come from. Both tools
361
- take an opaque inputs object, so this listing is the only place any of it is
361
+ take an opaque object (a query's `params`, a workflow's `inputs`), so this listing is the only place any of it is
362
362
  legible.
363
363
 
364
364
  The app's own `description` heads that listing as `about:`, on both surfaces. It
@@ -369,7 +369,7 @@ Wire shapes per output column type:
369
369
  | Column type | Cell value on the wire |
370
370
  |---|---|
371
371
  | `text` | `string` |
372
- | `number` | `number` (numeric database strings are normalized server-side; a rare decimal too precise for float64 stays a string — `row.num` parses both) |
372
+ | `number` | `number` (numeric database strings are normalized server-side; a decimal with more digits than a double holds rounds to the double) |
373
373
  | `boolean` | `boolean` |
374
374
  | `date` | `"YYYY-MM-DD"` — a calendar day, no time component (a reduced-precision date field may also carry `"YYYY-MM"` or `"YYYY"`; see below) |
375
375
  | `datetime` | `"YYYY-MM-DDTHH:mm"` — workspace wall-clock, minute precision |
@@ -424,7 +424,7 @@ const { reverted, kept } = await undoRecordChange("job", recordId, entry.id);
424
424
  the call arrives, on a row their own row rule covers, and the record's lock, the table's checks
425
425
  and its write rules answer as for any save of theirs. `undoable` is `false`, and the call
426
426
  refused, for the entry that made the record, an entry that is an undo, one already put back, and
427
- a viewer who may not write the record.
427
+ a viewer who may not write the record; a record in the trash is refused until it is restored.
428
428
  The undo is an entry of its own; the answer arrives once the record's reads are read anew.
429
429
  - **Pages**: newest first, about thirty entries each; `next` is where the trail goes on —
430
430
  `undefined` at its end. A page may hold fewer entries and still say `next` where the trail it read
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lotics/app-sdk",
3
- "version": "0.122.2",
3
+ "version": "0.122.4",
4
4
  "description": "The SDK a Lotics custom-code app reads and writes through — typed hooks over the host bridge, cell readers, mount() and AppRouter",
5
5
  "type": "module",
6
6
  "exports": {