@ai-matrx/records 0.99.32 → 0.99.34

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 (62) hide show
  1. package/CHANGELOG.md +16 -1
  2. package/dist/{client-CrwedBYU.d.ts → client-CSfkP7Xf.d.ts} +5 -74
  3. package/dist/{client-D1EwyWfh.d.cts → client-jKf1Z-kp.d.cts} +5 -74
  4. package/dist/core/index.cjs +149 -105
  5. package/dist/core/index.cjs.map +1 -1
  6. package/dist/core/index.d.cts +9 -331
  7. package/dist/core/index.d.ts +9 -331
  8. package/dist/core/index.js +149 -105
  9. package/dist/core/index.js.map +1 -1
  10. package/dist/data/index.cjs +280 -236
  11. package/dist/data/index.cjs.map +1 -1
  12. package/dist/data/index.d.cts +3 -2
  13. package/dist/data/index.d.ts +3 -2
  14. package/dist/data/index.js +280 -236
  15. package/dist/data/index.js.map +1 -1
  16. package/dist/{declareTable-CC5rTTIA.d.ts → declareTable-0emxEewn.d.ts} +1 -1
  17. package/dist/{declareTable-BIIt0Wqt.d.cts → declareTable-800bwUn3.d.cts} +1 -1
  18. package/dist/door-call/index.cjs +1287 -0
  19. package/dist/door-call/index.cjs.map +1 -0
  20. package/dist/door-call/index.d.cts +20 -0
  21. package/dist/door-call/index.d.ts +20 -0
  22. package/dist/door-call/index.js +1264 -0
  23. package/dist/door-call/index.js.map +1 -0
  24. package/dist/{doors-D1yAs0a0.d.cts → doors-BgjRUdxw.d.cts} +13 -1
  25. package/dist/{doors-D2z3kH2i.d.ts → doors-D7_jEKtg.d.ts} +13 -1
  26. package/dist/index.d.cts +5 -4
  27. package/dist/index.d.ts +5 -4
  28. package/dist/{objectOrganization-DazBoDAq.d.cts → objectOrganization-B5YFGVUB.d.cts} +1 -1
  29. package/dist/{objectOrganization-D1ox3gUx.d.ts → objectOrganization-DozoVIxS.d.ts} +1 -1
  30. package/dist/pickListDoors-C-_eAEGL.d.cts +135 -0
  31. package/dist/pickListDoors-DgWVnNRI.d.ts +135 -0
  32. package/dist/questions/index.d.cts +3 -2
  33. package/dist/questions/index.d.ts +3 -2
  34. package/dist/react/index.cjs +363 -319
  35. package/dist/react/index.cjs.map +1 -1
  36. package/dist/react/index.d.cts +37 -22
  37. package/dist/react/index.d.ts +37 -22
  38. package/dist/react/index.js +363 -319
  39. package/dist/react/index.js.map +1 -1
  40. package/dist/scopes/index.cjs +7 -0
  41. package/dist/scopes/index.cjs.map +1 -1
  42. package/dist/scopes/index.d.cts +2 -2
  43. package/dist/scopes/index.d.ts +2 -2
  44. package/dist/scopes/index.js +7 -0
  45. package/dist/scopes/index.js.map +1 -1
  46. package/dist/setup/index.cjs +289 -245
  47. package/dist/setup/index.cjs.map +1 -1
  48. package/dist/setup/index.d.cts +4 -3
  49. package/dist/setup/index.d.ts +4 -3
  50. package/dist/setup/index.js +289 -245
  51. package/dist/setup/index.js.map +1 -1
  52. package/dist/table-logic-BPquabNN.d.ts +328 -0
  53. package/dist/table-logic-CTh6lwaq.d.cts +328 -0
  54. package/dist/typed-table/index.cjs +280 -236
  55. package/dist/typed-table/index.cjs.map +1 -1
  56. package/dist/typed-table/index.d.cts +4 -3
  57. package/dist/typed-table/index.d.ts +4 -3
  58. package/dist/typed-table/index.js +280 -236
  59. package/dist/typed-table/index.js.map +1 -1
  60. package/dist/views/index.d.cts +3 -2
  61. package/dist/views/index.d.ts +3 -2
  62. package/package.json +13 -3
@@ -89,137 +89,6 @@ function isWritingDoor(door) {
89
89
  return /(_declare|_set(_|$)|_update|_write|_delete|_restore|_archive|_upsert|_reparent|_change|_duplicate|_move|_decide|_run$|_submit|_publish|_import_|_start$|_complete|_sign$|_add$|_retire|_propose|_promote|_land$|_pin$|_mute|_snooze|_unsnooze|_clear|_unclear|_revoke|_issue|_bind|_unbind|_apply|_backfill|_sync$|_decorate|_designate|_ensure|^migrate_|^set_table_|^home_add|^capture_|^claim_|^record_stage|^anon_|^io_import_|^io_comment_resolve|^enrich_(declare|land|pin)|^field_(declare|duplicate|propose|restore|retire|update)|^table_(declare|ensure|from_example|move|sync)|^value_restore|^relation_own)/.test(door);
90
90
  }
91
91
 
92
- // src/core/recordChanges.ts
93
- var import_global_slot = require("@ai-matrx/kit/global-slot");
94
- var listeners = (0, import_global_slot.globalSlot)("ai-matrx.records.record-change-listeners", () => /* @__PURE__ */ new Set());
95
- function announceRecordChanged(recordId) {
96
- for (const listener of [...listeners]) {
97
- try {
98
- listener(recordId);
99
- } catch (thrown) {
100
- console.error("[@ai-matrx/records] a record-change listener threw", thrown);
101
- }
102
- }
103
- }
104
- var removed = (0, import_global_slot.globalSlot)("ai-matrx.records.removed-records", () => /* @__PURE__ */ new Set());
105
- function markRecordRemoved(recordId) {
106
- removed.add(recordId);
107
- }
108
- function markRecordRestored(recordId) {
109
- removed.delete(recordId);
110
- }
111
- function onRecordChanged(listener) {
112
- listeners.add(listener);
113
- return () => listeners.delete(listener);
114
- }
115
- var tableListeners = (0, import_global_slot.globalSlot)("ai-matrx.records.table-structure-listeners", () => /* @__PURE__ */ new Set());
116
- function announceTableStructureChanged(tableId) {
117
- for (const listener of [...tableListeners]) {
118
- try {
119
- listener(tableId);
120
- } catch (thrown) {
121
- console.error("[@ai-matrx/records] a table-structure listener threw", thrown);
122
- }
123
- }
124
- }
125
-
126
- // src/archive.ts
127
- var DEFAULT_ARCHIVE_LANE = "org";
128
-
129
- // src/aggregate.ts
130
- function isRuleFilter(filter) {
131
- if (!filter || typeof filter !== "object" || Array.isArray(filter)) return false;
132
- const node = filter;
133
- return typeof node.op === "string" && Array.isArray(node.args);
134
- }
135
- function stableFilterKey(filter) {
136
- if (!filter) return "{}";
137
- if (isRuleFilter(filter)) return JSON.stringify(filter);
138
- const keys = Object.keys(filter).sort();
139
- if (keys.length === 0) return "{}";
140
- const parts = keys.map((key) => {
141
- const value = filter[key];
142
- if (value !== null && typeof value === "object") {
143
- const window = value;
144
- return `${JSON.stringify(key)}:{"from":${JSON.stringify(window.from ?? null)},"to":${JSON.stringify(window.to ?? null)}}`;
145
- }
146
- return `${JSON.stringify(key)}:${JSON.stringify(value ?? null)}`;
147
- });
148
- return `{${parts.join(",")}}`;
149
- }
150
- function liftWithheld(rows) {
151
- let shared;
152
- for (const row of rows) {
153
- const m = (row.measures ?? {})["_withheld"];
154
- if (m !== void 0 && m !== null && typeof m === "object") {
155
- shared = m;
156
- break;
157
- }
158
- }
159
- return rows.map((row) => {
160
- const measures = row.measures ?? {};
161
- const own = measures["_withheld"];
162
- const marker = own !== void 0 && own !== null && typeof own === "object" ? own : shared;
163
- const rowCount = row.row_count ?? 0;
164
- if (marker === void 0 || marker === null || typeof marker !== "object") {
165
- return rowCount === row.row_count ? row : { ...row, row_count: rowCount };
166
- }
167
- const { _withheld: _drop, ...rest } = measures;
168
- const withheld = {};
169
- for (const [name, raw] of Object.entries(marker)) {
170
- const m = raw ?? {};
171
- withheld[name] = {
172
- reason: m.withheld?.reason ?? null,
173
- needs: m.withheld?.needs ?? null,
174
- or: m.withheld?.or ?? null,
175
- ...m.says ? { says: m.says } : {},
176
- ...m.label ? { label: m.label } : {},
177
- ...m.field_key ? { field_key: m.field_key } : {}
178
- };
179
- }
180
- return { ...row, measures: rest, withheld, row_count: rowCount };
181
- });
182
- }
183
-
184
- // src/record.ts
185
- function isLockedStub(row) {
186
- if (!row) return false;
187
- if (row.level !== null && row.level !== void 0) return false;
188
- const doc = row.document;
189
- if (!doc || typeof doc !== "object") return false;
190
- const keys = Object.keys(doc);
191
- if (keys.length === 0 || keys.length > 3) return false;
192
- const d = doc;
193
- return d["exists"] === true && keys.every((k) => k === "id" || k === "exists" || k === "submitted_at");
194
- }
195
- function splitLockedRows(rows) {
196
- const open = [];
197
- let locked = 0;
198
- for (const row of rows) {
199
- if (isLockedStub(row)) locked += 1;
200
- else open.push(row);
201
- }
202
- return { rows: open, locked };
203
- }
204
-
205
- // src/subscription.ts
206
- function callersTimeZone() {
207
- try {
208
- return Intl.DateTimeFormat().resolvedOptions().timeZone || null;
209
- } catch {
210
- return null;
211
- }
212
- }
213
- function withCallersClock(spec, zone = callersTimeZone()) {
214
- if (!zone || spec.quiet_hours?.tz) return spec;
215
- return { ...spec, quiet_hours: { ...spec.quiet_hours ?? {}, tz: zone } };
216
- }
217
-
218
- // src/rowLabel.ts
219
- function clearsRowLabel(formula) {
220
- return formula == null || formula.trim() === "";
221
- }
222
-
223
92
  // src/results.ts
224
93
  var ok = (data) => ({ ok: true, data });
225
94
  var err = (error) => ({ ok: false, error });
@@ -390,6 +259,230 @@ function mapPgError(error, where) {
390
259
  return mapped;
391
260
  }
392
261
 
262
+ // src/core/doorCall.ts
263
+ var DEFAULT_DOOR_SCHEMA = "custom";
264
+ function canonicalArgs(value) {
265
+ return JSON.stringify(
266
+ value,
267
+ (_key, held) => held && typeof held === "object" && !Array.isArray(held) ? Object.fromEntries(Object.keys(held).sort().map((k) => [k, held[k]])) : held
268
+ );
269
+ }
270
+ var A_PERSONS_REFUSAL = /* @__PURE__ */ new Set([
271
+ "refused_by_rule",
272
+ "stale_write",
273
+ "invalid_argument",
274
+ "already_exists",
275
+ "missing_reference"
276
+ ]);
277
+ function isAPersonsRefusal(code) {
278
+ return A_PERSONS_REFUSAL.has(code);
279
+ }
280
+ function recordsErrorSink(onError) {
281
+ return onError ?? ((e) => {
282
+ const line = `[@ai-matrx/records] ${e.where}: ${e.code} \u2014 ${e.message}${e.hint ? ` (${e.hint})` : ""}`;
283
+ if (isAPersonsRefusal(e.code)) console.info(line);
284
+ else console.error(line);
285
+ });
286
+ }
287
+ function doorAbsentRefusal(name, owedBy) {
288
+ return {
289
+ code: "door_absent",
290
+ message: `The record store has no door \`custom.${name}\` yet, so this call was not made. Nothing was read and nothing was written.`,
291
+ hint: owedBy ? `That door is ${owedBy}. Until it lands, this call refuses rather than guessing: an empty answer here would read like "there is nothing", which is a different sentence.` : `No lane in the build book claims this door. Either the name is wrong, or the door was removed from the store and this package has not been regenerated \u2014 run \`pnpm records:generate\`.`
292
+ };
293
+ }
294
+ function primedDoorAnswer(door, args) {
295
+ const look = LOOK_WRITES[door];
296
+ if (look) {
297
+ dropPrimedDoorAnswers(look);
298
+ return null;
299
+ }
300
+ if (isWritingDoor(door)) {
301
+ dropPrimedDoorAnswers();
302
+ return null;
303
+ }
304
+ return takePrimedDoorAnswer(`${door}|${canonicalArgs(args)}`);
305
+ }
306
+ function createDoorCall(options) {
307
+ const { dataSource, doorReady: doorReady2, held, wrote } = options;
308
+ const schema = options.schema ?? DEFAULT_DOOR_SCHEMA;
309
+ const scream = recordsErrorSink(options.onError);
310
+ const absent = options.absent ?? ((door) => doorAbsentRefusal(door));
311
+ const readsInFlight = /* @__PURE__ */ new Map();
312
+ const say = (refusal2, where) => scream({ code: refusal2.code, message: refusal2.message, ...refusal2.hint ? { hint: refusal2.hint } : {}, where });
313
+ return async function callDoor(door, args, where, opts) {
314
+ const primed = primedDoorAnswer(door, args);
315
+ if (primed) return ok(primed.data);
316
+ if (held) {
317
+ const bundled = await held(door, args);
318
+ if (bundled) return ok(bundled.data);
319
+ }
320
+ if (doorReady2 && !doorReady2(door)) {
321
+ const refusal2 = absent(door);
322
+ say(refusal2, where);
323
+ return err(refusal2);
324
+ }
325
+ const flightKey = isWritingDoor(door) ? null : `${door}|${canonicalArgs(args)}`;
326
+ const flying = flightKey ? readsInFlight.get(flightKey) : void 0;
327
+ const response = await (flying ?? (() => {
328
+ const call = Promise.resolve(dataSource.rpc(`${door}`, args, { schema }));
329
+ if (flightKey) {
330
+ readsInFlight.set(flightKey, call);
331
+ const forget = () => {
332
+ if (readsInFlight.get(flightKey) === call) readsInFlight.delete(flightKey);
333
+ };
334
+ call.then(forget, forget);
335
+ }
336
+ return call;
337
+ })());
338
+ if (response.error) {
339
+ const code = response.error.code;
340
+ const refusal2 = !doorReady2 && (code === "PGRST202" || code === "42883") ? absent(door) : mapPgError(response.error, where);
341
+ if (opts?.quiet) console.info(`[@ai-matrx/records] ${where}: ${refusal2.code} - ${refusal2.message}`);
342
+ else say(refusal2, where);
343
+ return err(refusal2);
344
+ }
345
+ if (isWritingDoor(door) || LOOK_WRITES[door]) {
346
+ const tableId = args["p_table_id"];
347
+ wrote?.(door, args);
348
+ forgetPrimedTablePageBundlesOf(typeof tableId === "string" ? tableId : null);
349
+ dropPrimedDoorAnswers(LOOK_WRITES[door]);
350
+ }
351
+ return ok(response.data);
352
+ };
353
+ }
354
+
355
+ // src/core/recordChanges.ts
356
+ var import_global_slot = require("@ai-matrx/kit/global-slot");
357
+ var listeners = (0, import_global_slot.globalSlot)("ai-matrx.records.record-change-listeners", () => /* @__PURE__ */ new Set());
358
+ function announceRecordChanged(recordId) {
359
+ for (const listener of [...listeners]) {
360
+ try {
361
+ listener(recordId);
362
+ } catch (thrown) {
363
+ console.error("[@ai-matrx/records] a record-change listener threw", thrown);
364
+ }
365
+ }
366
+ }
367
+ var removed = (0, import_global_slot.globalSlot)("ai-matrx.records.removed-records", () => /* @__PURE__ */ new Set());
368
+ function markRecordRemoved(recordId) {
369
+ removed.add(recordId);
370
+ }
371
+ function markRecordRestored(recordId) {
372
+ removed.delete(recordId);
373
+ }
374
+ function onRecordChanged(listener) {
375
+ listeners.add(listener);
376
+ return () => listeners.delete(listener);
377
+ }
378
+ var tableListeners = (0, import_global_slot.globalSlot)("ai-matrx.records.table-structure-listeners", () => /* @__PURE__ */ new Set());
379
+ function announceTableStructureChanged(tableId) {
380
+ for (const listener of [...tableListeners]) {
381
+ try {
382
+ listener(tableId);
383
+ } catch (thrown) {
384
+ console.error("[@ai-matrx/records] a table-structure listener threw", thrown);
385
+ }
386
+ }
387
+ }
388
+
389
+ // src/archive.ts
390
+ var DEFAULT_ARCHIVE_LANE = "org";
391
+
392
+ // src/aggregate.ts
393
+ function isRuleFilter(filter) {
394
+ if (!filter || typeof filter !== "object" || Array.isArray(filter)) return false;
395
+ const node = filter;
396
+ return typeof node.op === "string" && Array.isArray(node.args);
397
+ }
398
+ function stableFilterKey(filter) {
399
+ if (!filter) return "{}";
400
+ if (isRuleFilter(filter)) return JSON.stringify(filter);
401
+ const keys = Object.keys(filter).sort();
402
+ if (keys.length === 0) return "{}";
403
+ const parts = keys.map((key) => {
404
+ const value = filter[key];
405
+ if (value !== null && typeof value === "object") {
406
+ const window = value;
407
+ return `${JSON.stringify(key)}:{"from":${JSON.stringify(window.from ?? null)},"to":${JSON.stringify(window.to ?? null)}}`;
408
+ }
409
+ return `${JSON.stringify(key)}:${JSON.stringify(value ?? null)}`;
410
+ });
411
+ return `{${parts.join(",")}}`;
412
+ }
413
+ function liftWithheld(rows) {
414
+ let shared;
415
+ for (const row of rows) {
416
+ const m = (row.measures ?? {})["_withheld"];
417
+ if (m !== void 0 && m !== null && typeof m === "object") {
418
+ shared = m;
419
+ break;
420
+ }
421
+ }
422
+ return rows.map((row) => {
423
+ const measures = row.measures ?? {};
424
+ const own = measures["_withheld"];
425
+ const marker = own !== void 0 && own !== null && typeof own === "object" ? own : shared;
426
+ const rowCount = row.row_count ?? 0;
427
+ if (marker === void 0 || marker === null || typeof marker !== "object") {
428
+ return rowCount === row.row_count ? row : { ...row, row_count: rowCount };
429
+ }
430
+ const { _withheld: _drop, ...rest } = measures;
431
+ const withheld = {};
432
+ for (const [name, raw] of Object.entries(marker)) {
433
+ const m = raw ?? {};
434
+ withheld[name] = {
435
+ reason: m.withheld?.reason ?? null,
436
+ needs: m.withheld?.needs ?? null,
437
+ or: m.withheld?.or ?? null,
438
+ ...m.says ? { says: m.says } : {},
439
+ ...m.label ? { label: m.label } : {},
440
+ ...m.field_key ? { field_key: m.field_key } : {}
441
+ };
442
+ }
443
+ return { ...row, measures: rest, withheld, row_count: rowCount };
444
+ });
445
+ }
446
+
447
+ // src/record.ts
448
+ function isLockedStub(row) {
449
+ if (!row) return false;
450
+ if (row.level !== null && row.level !== void 0) return false;
451
+ const doc = row.document;
452
+ if (!doc || typeof doc !== "object") return false;
453
+ const keys = Object.keys(doc);
454
+ if (keys.length === 0 || keys.length > 3) return false;
455
+ const d = doc;
456
+ return d["exists"] === true && keys.every((k) => k === "id" || k === "exists" || k === "submitted_at");
457
+ }
458
+ function splitLockedRows(rows) {
459
+ const open = [];
460
+ let locked = 0;
461
+ for (const row of rows) {
462
+ if (isLockedStub(row)) locked += 1;
463
+ else open.push(row);
464
+ }
465
+ return { rows: open, locked };
466
+ }
467
+
468
+ // src/subscription.ts
469
+ function callersTimeZone() {
470
+ try {
471
+ return Intl.DateTimeFormat().resolvedOptions().timeZone || null;
472
+ } catch {
473
+ return null;
474
+ }
475
+ }
476
+ function withCallersClock(spec, zone = callersTimeZone()) {
477
+ if (!zone || spec.quiet_hours?.tz) return spec;
478
+ return { ...spec, quiet_hours: { ...spec.quiet_hours ?? {}, tz: zone } };
479
+ }
480
+
481
+ // src/rowLabel.ts
482
+ function clearsRowLabel(formula) {
483
+ return formula == null || formula.trim() === "";
484
+ }
485
+
393
486
  // src/relation.ts
394
487
  var import_uuid = require("@ai-matrx/kit/uuid");
395
488
  function isReverseField(field) {
@@ -1172,11 +1265,51 @@ function createScopeDoors(call) {
1172
1265
  source_type: String(envelope.data?.source_type ?? cell.source_type ?? "ai_enriched")
1173
1266
  }
1174
1267
  };
1268
+ },
1269
+ tableProvision({ organization_id, item_id, scope_id, home_id }) {
1270
+ return call(
1271
+ "scope_table_provision",
1272
+ { p_organization_id: organization_id, p_item_id: item_id, p_scope_id: scope_id, p_home_id: home_id ?? null },
1273
+ "scopeTableProvision"
1274
+ );
1175
1275
  }
1176
1276
  };
1177
1277
  return doors;
1178
1278
  }
1179
1279
 
1280
+ // src/core/pickListDoors.ts
1281
+ var PICK_LIST_DOORS = {
1282
+ pickListGet: "pick_list_get",
1283
+ pickListForSelection: "pick_list_for_selection",
1284
+ pickListUpdate: "pick_list_update"
1285
+ };
1286
+ function createPickListDoors(callDoor) {
1287
+ return {
1288
+ async pickListGet({ list_id }) {
1289
+ return callDoor(PICK_LIST_DOORS.pickListGet, { p_list_id: list_id }, "pickListGet");
1290
+ },
1291
+ async pickListForSelection({ list_id }) {
1292
+ return callDoor(
1293
+ PICK_LIST_DOORS.pickListForSelection,
1294
+ { p_list_id: list_id },
1295
+ "pickListForSelection"
1296
+ );
1297
+ },
1298
+ async pickListUpdate({ list_id, list_name, description, items }) {
1299
+ return callDoor(
1300
+ PICK_LIST_DOORS.pickListUpdate,
1301
+ {
1302
+ p_list_id: list_id,
1303
+ p_list_name: list_name ?? null,
1304
+ p_description: description ?? null,
1305
+ p_items: items ? [...items] : null
1306
+ },
1307
+ "pickListUpdate"
1308
+ );
1309
+ }
1310
+ };
1311
+ }
1312
+
1180
1313
  // src/choice.ts
1181
1314
  var import_uuid3 = require("@ai-matrx/kit/uuid");
1182
1315
  var CHOICE_NUDGES = ["ask", "always_add", "never_add"];
@@ -2498,12 +2631,7 @@ function doorReady(config, name) {
2498
2631
  return DOOR_NAMES.has(name) || Boolean(config?.knownDoors?.includes(name));
2499
2632
  }
2500
2633
  function doorAbsent(name) {
2501
- const owed = OWED_BY[name];
2502
- return {
2503
- code: "door_absent",
2504
- message: `The record store has no door \`custom.${name}\` yet, so this call was not made. Nothing was read and nothing was written.`,
2505
- hint: owed ? `That door is ${owed}. Until it lands, this call refuses rather than guessing: an empty answer here would read like "there is nothing", which is a different sentence.` : `No lane in the build book claims this door. Either the name is wrong, or the door was removed from the store and this package has not been regenerated \u2014 run \`pnpm records:generate\`.`
2506
- };
2634
+ return doorAbsentRefusal(name, OWED_BY[name]);
2507
2635
  }
2508
2636
  var DOORS = {
2509
2637
  // THE READ DOOR (DOOR-1). Every read of a record's values goes through these
@@ -3283,29 +3411,6 @@ function intersectIds(sets) {
3283
3411
 
3284
3412
  // src/core/client.ts
3285
3413
  var DEFAULT_SCHEMA = "custom";
3286
- function canonicalArgs(value) {
3287
- return JSON.stringify(
3288
- value,
3289
- (_key, held) => held && typeof held === "object" && !Array.isArray(held) ? Object.fromEntries(Object.keys(held).sort().map((k) => [k, held[k]])) : held
3290
- );
3291
- }
3292
- var A_PERSONS_REFUSAL = /* @__PURE__ */ new Set([
3293
- "refused_by_rule",
3294
- "stale_write",
3295
- "invalid_argument",
3296
- "already_exists",
3297
- "missing_reference"
3298
- ]);
3299
- function isAPersonsRefusal(code) {
3300
- return A_PERSONS_REFUSAL.has(code);
3301
- }
3302
- function sink(config) {
3303
- return config.onError ?? ((e) => {
3304
- const line = `[@ai-matrx/records] ${e.where}: ${e.code} \u2014 ${e.message}${e.hint ? ` (${e.hint})` : ""}`;
3305
- if (isAPersonsRefusal(e.code)) console.info(line);
3306
- else console.error(line);
3307
- });
3308
- }
3309
3414
  var TABLE_LIST_PAGE = 500;
3310
3415
  var TABLE_ARCHIVE_PASS = 20;
3311
3416
  var TABLE_RESTORE_PASS = 20;
@@ -3318,7 +3423,7 @@ function createRecordsClient(given) {
3318
3423
  const org = config.organizationId;
3319
3424
  const ledger = config.opLedger ?? defaultOpLedger;
3320
3425
  const mintOp = () => ledger.mint();
3321
- const scream = sink(config);
3426
+ const scream = recordsErrorSink(config.onError);
3322
3427
  const BUNDLE_TTL_MS = 1e4;
3323
3428
  const BUNDLE_OPENERS = /* @__PURE__ */ new Set(["applicable_fields", "views", "view_look_read", "table_decorations", "row_actions", "reverse_columns", "record_change_actions", "grid_layout", "io_imports"]);
3324
3429
  const bundleParts = /* @__PURE__ */ new Map();
@@ -3460,56 +3565,20 @@ function createRecordsClient(given) {
3460
3565
  bundleAsked.delete(tableId);
3461
3566
  for (const key of [...bundleParts.keys()]) if (key.includes(tableId)) bundleParts.delete(key);
3462
3567
  }
3463
- function primedFor(door, args) {
3464
- const look = LOOK_WRITES[door];
3465
- if (look) {
3466
- dropPrimedDoorAnswers(look);
3467
- return null;
3468
- }
3469
- if (isWritingDoor(door)) {
3470
- dropPrimedDoorAnswers();
3471
- return null;
3472
- }
3473
- return takePrimedDoorAnswer(`${door}|${canonicalArgs(args)}`);
3474
- }
3475
- const readsInFlight = /* @__PURE__ */ new Map();
3476
- async function callDoor(door, args, where, opts) {
3477
- const primed = primedFor(door, args);
3478
- if (primed) return ok(primed.data);
3479
- const bundled = await fromBundle(door, args);
3480
- if (bundled) return ok(bundled.data);
3481
- if (!doorReady(config, door)) {
3482
- const refusal2 = doorAbsent(door);
3483
- scream({ code: refusal2.code, message: refusal2.message, ...refusal2.hint ? { hint: refusal2.hint } : {}, where });
3484
- return err(refusal2);
3485
- }
3486
- const flightKey = isWritingDoor(door) ? null : `${door}|${canonicalArgs(args)}`;
3487
- const flying = flightKey ? readsInFlight.get(flightKey) : void 0;
3488
- const response = await (flying ?? (() => {
3489
- const call = Promise.resolve(config.dataSource.rpc(`${door}`, args, { schema }));
3490
- if (flightKey) {
3491
- readsInFlight.set(flightKey, call);
3492
- const forget = () => {
3493
- if (readsInFlight.get(flightKey) === call) readsInFlight.delete(flightKey);
3494
- };
3495
- call.then(forget, forget);
3496
- }
3497
- return call;
3498
- })());
3499
- if (response.error) {
3500
- const refusal2 = mapPgError(response.error, where);
3501
- if (opts?.quiet) console.info(`[@ai-matrx/records] ${where}: ${refusal2.code} - ${refusal2.message}`);
3502
- else scream({ code: refusal2.code, message: refusal2.message, ...refusal2.hint ? { hint: refusal2.hint } : {}, where });
3503
- return err(refusal2);
3504
- }
3505
- if (isWritingDoor(door) || LOOK_WRITES[door]) {
3568
+ const primedFor = primedDoorAnswer;
3569
+ const callDoor = createDoorCall({
3570
+ dataSource: config.dataSource,
3571
+ schema,
3572
+ onError: scream,
3573
+ doorReady: (door) => doorReady(config, door),
3574
+ absent: doorAbsent,
3575
+ held: fromBundle,
3576
+ wrote: (_door, args) => {
3506
3577
  const tableId = args["p_table_id"];
3507
3578
  bundleDrop(typeof tableId === "string" ? tableId : null);
3508
- forgetPrimedTablePageBundlesOf(typeof tableId === "string" ? tableId : null);
3509
- dropPrimedDoorAnswers(LOOK_WRITES[door]);
3510
3579
  }
3511
- return ok(response.data);
3512
- }
3580
+ });
3581
+ const scopes = createScopeDoors(callDoor);
3513
3582
  function structureMoved(tableId, result) {
3514
3583
  if (result.ok) {
3515
3584
  bundleDrop(tableId);
@@ -3708,7 +3777,7 @@ function createRecordsClient(given) {
3708
3777
  const unavailableReason = (error) => `${error.message}${error.hint ? ` ${error.hint}` : ""}`;
3709
3778
  const client = {
3710
3779
  config,
3711
- scopes: createScopeDoors(callDoor),
3780
+ scopes,
3712
3781
  async recordWrite({ table_id, data }) {
3713
3782
  const result = await callDoor(
3714
3783
  DOORS.recordWrite,
@@ -4407,28 +4476,7 @@ function createRecordsClient(given) {
4407
4476
  "fieldOptions"
4408
4477
  );
4409
4478
  },
4410
- async pickListGet({ list_id }) {
4411
- return callDoor(DOORS.pickListGet, { p_list_id: list_id }, "pickListGet");
4412
- },
4413
- async pickListForSelection({ list_id }) {
4414
- return callDoor(
4415
- DOORS.pickListForSelection,
4416
- { p_list_id: list_id },
4417
- "pickListForSelection"
4418
- );
4419
- },
4420
- async pickListUpdate({ list_id, list_name, description, items }) {
4421
- return callDoor(
4422
- DOORS.pickListUpdate,
4423
- {
4424
- p_list_id: list_id,
4425
- p_list_name: list_name ?? null,
4426
- p_description: description ?? null,
4427
- p_items: items ? [...items] : null
4428
- },
4429
- "pickListUpdate"
4430
- );
4431
- },
4479
+ ...createPickListDoors(callDoor),
4432
4480
  async fieldChoiceUsage({ field_id }) {
4433
4481
  const result = await callDoor(
4434
4482
  DOORS.fieldChoiceUsage,
@@ -6962,11 +7010,7 @@ function createRecordsClient(given) {
6962
7010
  );
6963
7011
  },
6964
7012
  async scopeTableProvision({ home_id, item_id, scope_id }) {
6965
- return callDoor(
6966
- DOORS.scopeTableProvision,
6967
- { p_organization_id: org, p_item_id: item_id, p_scope_id: scope_id, p_home_id: home_id ?? null },
6968
- "scopeTableProvision"
6969
- );
7013
+ return scopes.tableProvision({ organization_id: org, item_id, scope_id, home_id: home_id ?? null });
6970
7014
  },
6971
7015
  async tableRowCounts({ table_ids }) {
6972
7016
  return callDoor(
@@ -7596,7 +7640,7 @@ function createEntityDataPort(options) {
7596
7640
  let stopped = false;
7597
7641
  let joined = [];
7598
7642
  let stopLive = null;
7599
- const sink2 = { rows: (ids) => listener({ ids: ids === null ? null : [...ids] }) };
7643
+ const sink = { rows: (ids) => listener({ ids: ids === null ? null : [...ids] }) };
7600
7644
  const plan = async () => {
7601
7645
  const organizationIds = binding.organizationId ? [binding.organizationId] : orderOrganizationTopics({
7602
7646
  active: activeOrganization(),
@@ -7608,7 +7652,7 @@ function createEntityDataPort(options) {
7608
7652
  if (organizationIds.length === joined.length && organizationIds.every((org, i) => org === joined[i])) return;
7609
7653
  const previous = stopLive;
7610
7654
  joined = organizationIds;
7611
- stopLive = realtime.subscribe({ token: binding.token, organizationIds }, sink2);
7655
+ stopLive = realtime.subscribe({ token: binding.token, organizationIds }, sink);
7612
7656
  previous?.();
7613
7657
  };
7614
7658
  const replan = () => void plan();
@@ -7730,7 +7774,7 @@ function createRecordsRealtimePort(options = {}) {
7730
7774
  return channel;
7731
7775
  };
7732
7776
  return {
7733
- subscribeRecords({ table_id }, sink2) {
7777
+ subscribeRecords({ table_id }, sink) {
7734
7778
  let timer = null;
7735
7779
  let pending = /* @__PURE__ */ new Set();
7736
7780
  let wholePage = false;
@@ -7740,15 +7784,15 @@ function createRecordsRealtimePort(options = {}) {
7740
7784
  const all = wholePage;
7741
7785
  pending = /* @__PURE__ */ new Set();
7742
7786
  wholePage = false;
7743
- if (all) sink2.records(null);
7744
- else if (ids.length > 0) sink2.records(ids);
7787
+ if (all) sink.records(null);
7788
+ else if (ids.length > 0) sink.records(ids);
7745
7789
  };
7746
7790
  const nudge = () => {
7747
7791
  if (timer === null) timer = setTimeout(flush, NUDGE_DEBOUNCE_MS);
7748
7792
  };
7749
7793
  const listener = {
7750
7794
  notice(notice) {
7751
- if (notice.kind === "field" || notice.kind === "table") sink2.shape();
7795
+ if (notice.kind === "field" || notice.kind === "table") sink.shape();
7752
7796
  if (notice.kind === "field") return;
7753
7797
  if (notice.record_ids == null) wholePage = true;
7754
7798
  else for (const id of notice.record_ids) pending.add(id);
@@ -7869,7 +7913,7 @@ async function createRecords(options) {
7869
7913
  realtime,
7870
7914
  search: (request) => searchRecords(dataSource, request),
7871
7915
  recordCandidates: (args) => listStoreRecordCandidates(dataSource, args),
7872
- watch(tableId, sink2, organizationId2) {
7916
+ watch(tableId, sink, organizationId2) {
7873
7917
  const activeOrganizationId = organizationIdChosen;
7874
7918
  const org = organizationId2 ?? activeOrganizationId;
7875
7919
  if (!realtimePort || !org) {
@@ -7880,8 +7924,8 @@ async function createRecords(options) {
7880
7924
  return () => {
7881
7925
  };
7882
7926
  }
7883
- return realtimePort.subscribeRecords({ organization_id: org, table_id: tableId }, { records: sink2.records ?? (() => {
7884
- }), shape: sink2.shape ?? (() => {
7927
+ return realtimePort.subscribeRecords({ organization_id: org, table_id: tableId }, { records: sink.records ?? (() => {
7928
+ }), shape: sink.shape ?? (() => {
7885
7929
  }) });
7886
7930
  },
7887
7931
  associations: options.associations,