@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
@@ -1,13 +1,14 @@
1
1
  import { C as Column, Q as Query, A as AliasBinding, H as HostDataPort } from '../types-B54BeQzf.cjs';
2
2
  export { a as AnyAlias, b as CUSTOM_ROW_TOKEN, D as DataEvents, c as DataPort, d as DataPortEventName, e as DataSource, E as EntityAlias, f as EntityRef, L as Lane, P as Page, R as Row, g as RowsEvent, T as TableAlias, V as Values, W as WhereClause, h as WhereOp } from '../types-B54BeQzf.cjs';
3
- import { R as RecordsClient } from '../client-D1EwyWfh.cjs';
3
+ import { R as RecordsClient } from '../client-jKf1Z-kp.cjs';
4
4
  import { F as Field } from '../field-B8loYt-A.cjs';
5
5
  import { U as Uuid, R as RecordsResult, k as RecordPageSort, l as ReadRow } from '../record-CTgSgWe3.cjs';
6
6
  import { R as RuleExpression } from '../rule-49jO7lN-.cjs';
7
7
  import '../relation-BjjjXyqn.cjs';
8
8
  import '../ports-alv3bgKY.cjs';
9
9
  import '../subscription-CuaGi3lC.cjs';
10
- import '../doors-D1yAs0a0.cjs';
10
+ import '../doors-BgjRUdxw.cjs';
11
+ import '../pickListDoors-C-_eAEGL.cjs';
11
12
  import '../portal-L_mN8l9P.cjs';
12
13
  import '../table-kind/index.cjs';
13
14
 
@@ -1,13 +1,14 @@
1
1
  import { C as Column, Q as Query, A as AliasBinding, H as HostDataPort } from '../types-bN7dG2ji.js';
2
2
  export { a as AnyAlias, b as CUSTOM_ROW_TOKEN, D as DataEvents, c as DataPort, d as DataPortEventName, e as DataSource, E as EntityAlias, f as EntityRef, L as Lane, P as Page, R as Row, g as RowsEvent, T as TableAlias, V as Values, W as WhereClause, h as WhereOp } from '../types-bN7dG2ji.js';
3
- import { R as RecordsClient } from '../client-CrwedBYU.js';
3
+ import { R as RecordsClient } from '../client-CSfkP7Xf.js';
4
4
  import { F as Field } from '../field-DaE90BZ7.js';
5
5
  import { U as Uuid, R as RecordsResult, k as RecordPageSort, l as ReadRow } from '../record-CTgSgWe3.js';
6
6
  import { R as RuleExpression } from '../rule-DzNj0QvN.js';
7
7
  import '../relation-T4biacnz.js';
8
8
  import '../ports-CmmvR8OI.js';
9
9
  import '../subscription-Bp1RSb6p.js';
10
- import '../doors-D2z3kH2i.js';
10
+ import '../doors-D7_jEKtg.js';
11
+ import '../pickListDoors-DgWVnNRI.js';
11
12
  import '../portal-CAssJHRZ.js';
12
13
  import '../table-kind/index.js';
13
14
 
@@ -235,137 +235,6 @@ function isWritingDoor(door) {
235
235
  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);
236
236
  }
237
237
 
238
- // src/core/recordChanges.ts
239
- import { globalSlot } from "@ai-matrx/kit/global-slot";
240
- var listeners = globalSlot("ai-matrx.records.record-change-listeners", () => /* @__PURE__ */ new Set());
241
- function announceRecordChanged(recordId) {
242
- for (const listener of [...listeners]) {
243
- try {
244
- listener(recordId);
245
- } catch (thrown) {
246
- console.error("[@ai-matrx/records] a record-change listener threw", thrown);
247
- }
248
- }
249
- }
250
- var removed = globalSlot("ai-matrx.records.removed-records", () => /* @__PURE__ */ new Set());
251
- function markRecordRemoved(recordId) {
252
- removed.add(recordId);
253
- }
254
- function markRecordRestored(recordId) {
255
- removed.delete(recordId);
256
- }
257
- function onRecordChanged(listener) {
258
- listeners.add(listener);
259
- return () => listeners.delete(listener);
260
- }
261
- var tableListeners = globalSlot("ai-matrx.records.table-structure-listeners", () => /* @__PURE__ */ new Set());
262
- function announceTableStructureChanged(tableId) {
263
- for (const listener of [...tableListeners]) {
264
- try {
265
- listener(tableId);
266
- } catch (thrown) {
267
- console.error("[@ai-matrx/records] a table-structure listener threw", thrown);
268
- }
269
- }
270
- }
271
-
272
- // src/archive.ts
273
- var DEFAULT_ARCHIVE_LANE = "org";
274
-
275
- // src/aggregate.ts
276
- function isRuleFilter(filter) {
277
- if (!filter || typeof filter !== "object" || Array.isArray(filter)) return false;
278
- const node = filter;
279
- return typeof node.op === "string" && Array.isArray(node.args);
280
- }
281
- function stableFilterKey(filter) {
282
- if (!filter) return "{}";
283
- if (isRuleFilter(filter)) return JSON.stringify(filter);
284
- const keys = Object.keys(filter).sort();
285
- if (keys.length === 0) return "{}";
286
- const parts = keys.map((key) => {
287
- const value = filter[key];
288
- if (value !== null && typeof value === "object") {
289
- const window = value;
290
- return `${JSON.stringify(key)}:{"from":${JSON.stringify(window.from ?? null)},"to":${JSON.stringify(window.to ?? null)}}`;
291
- }
292
- return `${JSON.stringify(key)}:${JSON.stringify(value ?? null)}`;
293
- });
294
- return `{${parts.join(",")}}`;
295
- }
296
- function liftWithheld(rows) {
297
- let shared;
298
- for (const row of rows) {
299
- const m = (row.measures ?? {})["_withheld"];
300
- if (m !== void 0 && m !== null && typeof m === "object") {
301
- shared = m;
302
- break;
303
- }
304
- }
305
- return rows.map((row) => {
306
- const measures = row.measures ?? {};
307
- const own = measures["_withheld"];
308
- const marker = own !== void 0 && own !== null && typeof own === "object" ? own : shared;
309
- const rowCount = row.row_count ?? 0;
310
- if (marker === void 0 || marker === null || typeof marker !== "object") {
311
- return rowCount === row.row_count ? row : { ...row, row_count: rowCount };
312
- }
313
- const { _withheld: _drop, ...rest } = measures;
314
- const withheld = {};
315
- for (const [name, raw] of Object.entries(marker)) {
316
- const m = raw ?? {};
317
- withheld[name] = {
318
- reason: m.withheld?.reason ?? null,
319
- needs: m.withheld?.needs ?? null,
320
- or: m.withheld?.or ?? null,
321
- ...m.says ? { says: m.says } : {},
322
- ...m.label ? { label: m.label } : {},
323
- ...m.field_key ? { field_key: m.field_key } : {}
324
- };
325
- }
326
- return { ...row, measures: rest, withheld, row_count: rowCount };
327
- });
328
- }
329
-
330
- // src/record.ts
331
- function isLockedStub(row) {
332
- if (!row) return false;
333
- if (row.level !== null && row.level !== void 0) return false;
334
- const doc = row.document;
335
- if (!doc || typeof doc !== "object") return false;
336
- const keys = Object.keys(doc);
337
- if (keys.length === 0 || keys.length > 3) return false;
338
- const d = doc;
339
- return d["exists"] === true && keys.every((k) => k === "id" || k === "exists" || k === "submitted_at");
340
- }
341
- function splitLockedRows(rows) {
342
- const open = [];
343
- let locked = 0;
344
- for (const row of rows) {
345
- if (isLockedStub(row)) locked += 1;
346
- else open.push(row);
347
- }
348
- return { rows: open, locked };
349
- }
350
-
351
- // src/subscription.ts
352
- function callersTimeZone() {
353
- try {
354
- return Intl.DateTimeFormat().resolvedOptions().timeZone || null;
355
- } catch {
356
- return null;
357
- }
358
- }
359
- function withCallersClock(spec, zone = callersTimeZone()) {
360
- if (!zone || spec.quiet_hours?.tz) return spec;
361
- return { ...spec, quiet_hours: { ...spec.quiet_hours ?? {}, tz: zone } };
362
- }
363
-
364
- // src/rowLabel.ts
365
- function clearsRowLabel(formula) {
366
- return formula == null || formula.trim() === "";
367
- }
368
-
369
238
  // src/results.ts
370
239
  var ok = (data) => ({ ok: true, data });
371
240
  var err = (error) => ({ ok: false, error });
@@ -536,6 +405,230 @@ function mapPgError(error, where) {
536
405
  return mapped;
537
406
  }
538
407
 
408
+ // src/core/doorCall.ts
409
+ var DEFAULT_DOOR_SCHEMA = "custom";
410
+ function canonicalArgs(value) {
411
+ return JSON.stringify(
412
+ value,
413
+ (_key, held) => held && typeof held === "object" && !Array.isArray(held) ? Object.fromEntries(Object.keys(held).sort().map((k) => [k, held[k]])) : held
414
+ );
415
+ }
416
+ var A_PERSONS_REFUSAL = /* @__PURE__ */ new Set([
417
+ "refused_by_rule",
418
+ "stale_write",
419
+ "invalid_argument",
420
+ "already_exists",
421
+ "missing_reference"
422
+ ]);
423
+ function isAPersonsRefusal(code) {
424
+ return A_PERSONS_REFUSAL.has(code);
425
+ }
426
+ function recordsErrorSink(onError) {
427
+ return onError ?? ((e) => {
428
+ const line = `[@ai-matrx/records] ${e.where}: ${e.code} \u2014 ${e.message}${e.hint ? ` (${e.hint})` : ""}`;
429
+ if (isAPersonsRefusal(e.code)) console.info(line);
430
+ else console.error(line);
431
+ });
432
+ }
433
+ function doorAbsentRefusal(name, owedBy) {
434
+ return {
435
+ code: "door_absent",
436
+ message: `The record store has no door \`custom.${name}\` yet, so this call was not made. Nothing was read and nothing was written.`,
437
+ 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\`.`
438
+ };
439
+ }
440
+ function primedDoorAnswer(door, args) {
441
+ const look = LOOK_WRITES[door];
442
+ if (look) {
443
+ dropPrimedDoorAnswers(look);
444
+ return null;
445
+ }
446
+ if (isWritingDoor(door)) {
447
+ dropPrimedDoorAnswers();
448
+ return null;
449
+ }
450
+ return takePrimedDoorAnswer(`${door}|${canonicalArgs(args)}`);
451
+ }
452
+ function createDoorCall(options) {
453
+ const { dataSource, doorReady: doorReady2, held, wrote } = options;
454
+ const schema = options.schema ?? DEFAULT_DOOR_SCHEMA;
455
+ const scream = recordsErrorSink(options.onError);
456
+ const absent = options.absent ?? ((door) => doorAbsentRefusal(door));
457
+ const readsInFlight = /* @__PURE__ */ new Map();
458
+ const say = (refusal2, where) => scream({ code: refusal2.code, message: refusal2.message, ...refusal2.hint ? { hint: refusal2.hint } : {}, where });
459
+ return async function callDoor(door, args, where, opts) {
460
+ const primed = primedDoorAnswer(door, args);
461
+ if (primed) return ok(primed.data);
462
+ if (held) {
463
+ const bundled = await held(door, args);
464
+ if (bundled) return ok(bundled.data);
465
+ }
466
+ if (doorReady2 && !doorReady2(door)) {
467
+ const refusal2 = absent(door);
468
+ say(refusal2, where);
469
+ return err(refusal2);
470
+ }
471
+ const flightKey = isWritingDoor(door) ? null : `${door}|${canonicalArgs(args)}`;
472
+ const flying = flightKey ? readsInFlight.get(flightKey) : void 0;
473
+ const response = await (flying ?? (() => {
474
+ const call = Promise.resolve(dataSource.rpc(`${door}`, args, { schema }));
475
+ if (flightKey) {
476
+ readsInFlight.set(flightKey, call);
477
+ const forget = () => {
478
+ if (readsInFlight.get(flightKey) === call) readsInFlight.delete(flightKey);
479
+ };
480
+ call.then(forget, forget);
481
+ }
482
+ return call;
483
+ })());
484
+ if (response.error) {
485
+ const code = response.error.code;
486
+ const refusal2 = !doorReady2 && (code === "PGRST202" || code === "42883") ? absent(door) : mapPgError(response.error, where);
487
+ if (opts?.quiet) console.info(`[@ai-matrx/records] ${where}: ${refusal2.code} - ${refusal2.message}`);
488
+ else say(refusal2, where);
489
+ return err(refusal2);
490
+ }
491
+ if (isWritingDoor(door) || LOOK_WRITES[door]) {
492
+ const tableId = args["p_table_id"];
493
+ wrote?.(door, args);
494
+ forgetPrimedTablePageBundlesOf(typeof tableId === "string" ? tableId : null);
495
+ dropPrimedDoorAnswers(LOOK_WRITES[door]);
496
+ }
497
+ return ok(response.data);
498
+ };
499
+ }
500
+
501
+ // src/core/recordChanges.ts
502
+ import { globalSlot } from "@ai-matrx/kit/global-slot";
503
+ var listeners = globalSlot("ai-matrx.records.record-change-listeners", () => /* @__PURE__ */ new Set());
504
+ function announceRecordChanged(recordId) {
505
+ for (const listener of [...listeners]) {
506
+ try {
507
+ listener(recordId);
508
+ } catch (thrown) {
509
+ console.error("[@ai-matrx/records] a record-change listener threw", thrown);
510
+ }
511
+ }
512
+ }
513
+ var removed = globalSlot("ai-matrx.records.removed-records", () => /* @__PURE__ */ new Set());
514
+ function markRecordRemoved(recordId) {
515
+ removed.add(recordId);
516
+ }
517
+ function markRecordRestored(recordId) {
518
+ removed.delete(recordId);
519
+ }
520
+ function onRecordChanged(listener) {
521
+ listeners.add(listener);
522
+ return () => listeners.delete(listener);
523
+ }
524
+ var tableListeners = globalSlot("ai-matrx.records.table-structure-listeners", () => /* @__PURE__ */ new Set());
525
+ function announceTableStructureChanged(tableId) {
526
+ for (const listener of [...tableListeners]) {
527
+ try {
528
+ listener(tableId);
529
+ } catch (thrown) {
530
+ console.error("[@ai-matrx/records] a table-structure listener threw", thrown);
531
+ }
532
+ }
533
+ }
534
+
535
+ // src/archive.ts
536
+ var DEFAULT_ARCHIVE_LANE = "org";
537
+
538
+ // src/aggregate.ts
539
+ function isRuleFilter(filter) {
540
+ if (!filter || typeof filter !== "object" || Array.isArray(filter)) return false;
541
+ const node = filter;
542
+ return typeof node.op === "string" && Array.isArray(node.args);
543
+ }
544
+ function stableFilterKey(filter) {
545
+ if (!filter) return "{}";
546
+ if (isRuleFilter(filter)) return JSON.stringify(filter);
547
+ const keys = Object.keys(filter).sort();
548
+ if (keys.length === 0) return "{}";
549
+ const parts = keys.map((key) => {
550
+ const value = filter[key];
551
+ if (value !== null && typeof value === "object") {
552
+ const window = value;
553
+ return `${JSON.stringify(key)}:{"from":${JSON.stringify(window.from ?? null)},"to":${JSON.stringify(window.to ?? null)}}`;
554
+ }
555
+ return `${JSON.stringify(key)}:${JSON.stringify(value ?? null)}`;
556
+ });
557
+ return `{${parts.join(",")}}`;
558
+ }
559
+ function liftWithheld(rows) {
560
+ let shared;
561
+ for (const row of rows) {
562
+ const m = (row.measures ?? {})["_withheld"];
563
+ if (m !== void 0 && m !== null && typeof m === "object") {
564
+ shared = m;
565
+ break;
566
+ }
567
+ }
568
+ return rows.map((row) => {
569
+ const measures = row.measures ?? {};
570
+ const own = measures["_withheld"];
571
+ const marker = own !== void 0 && own !== null && typeof own === "object" ? own : shared;
572
+ const rowCount = row.row_count ?? 0;
573
+ if (marker === void 0 || marker === null || typeof marker !== "object") {
574
+ return rowCount === row.row_count ? row : { ...row, row_count: rowCount };
575
+ }
576
+ const { _withheld: _drop, ...rest } = measures;
577
+ const withheld = {};
578
+ for (const [name, raw] of Object.entries(marker)) {
579
+ const m = raw ?? {};
580
+ withheld[name] = {
581
+ reason: m.withheld?.reason ?? null,
582
+ needs: m.withheld?.needs ?? null,
583
+ or: m.withheld?.or ?? null,
584
+ ...m.says ? { says: m.says } : {},
585
+ ...m.label ? { label: m.label } : {},
586
+ ...m.field_key ? { field_key: m.field_key } : {}
587
+ };
588
+ }
589
+ return { ...row, measures: rest, withheld, row_count: rowCount };
590
+ });
591
+ }
592
+
593
+ // src/record.ts
594
+ function isLockedStub(row) {
595
+ if (!row) return false;
596
+ if (row.level !== null && row.level !== void 0) return false;
597
+ const doc = row.document;
598
+ if (!doc || typeof doc !== "object") return false;
599
+ const keys = Object.keys(doc);
600
+ if (keys.length === 0 || keys.length > 3) return false;
601
+ const d = doc;
602
+ return d["exists"] === true && keys.every((k) => k === "id" || k === "exists" || k === "submitted_at");
603
+ }
604
+ function splitLockedRows(rows) {
605
+ const open = [];
606
+ let locked = 0;
607
+ for (const row of rows) {
608
+ if (isLockedStub(row)) locked += 1;
609
+ else open.push(row);
610
+ }
611
+ return { rows: open, locked };
612
+ }
613
+
614
+ // src/subscription.ts
615
+ function callersTimeZone() {
616
+ try {
617
+ return Intl.DateTimeFormat().resolvedOptions().timeZone || null;
618
+ } catch {
619
+ return null;
620
+ }
621
+ }
622
+ function withCallersClock(spec, zone = callersTimeZone()) {
623
+ if (!zone || spec.quiet_hours?.tz) return spec;
624
+ return { ...spec, quiet_hours: { ...spec.quiet_hours ?? {}, tz: zone } };
625
+ }
626
+
627
+ // src/rowLabel.ts
628
+ function clearsRowLabel(formula) {
629
+ return formula == null || formula.trim() === "";
630
+ }
631
+
539
632
  // src/relation.ts
540
633
  import { isUuidShape as isUuidShape3 } from "@ai-matrx/kit/uuid";
541
634
  function isRefLike(value) {
@@ -1341,11 +1434,51 @@ function createScopeDoors(call) {
1341
1434
  source_type: String(envelope.data?.source_type ?? cell.source_type ?? "ai_enriched")
1342
1435
  }
1343
1436
  };
1437
+ },
1438
+ tableProvision({ organization_id, item_id, scope_id, home_id }) {
1439
+ return call(
1440
+ "scope_table_provision",
1441
+ { p_organization_id: organization_id, p_item_id: item_id, p_scope_id: scope_id, p_home_id: home_id ?? null },
1442
+ "scopeTableProvision"
1443
+ );
1344
1444
  }
1345
1445
  };
1346
1446
  return doors;
1347
1447
  }
1348
1448
 
1449
+ // src/core/pickListDoors.ts
1450
+ var PICK_LIST_DOORS = {
1451
+ pickListGet: "pick_list_get",
1452
+ pickListForSelection: "pick_list_for_selection",
1453
+ pickListUpdate: "pick_list_update"
1454
+ };
1455
+ function createPickListDoors(callDoor) {
1456
+ return {
1457
+ async pickListGet({ list_id }) {
1458
+ return callDoor(PICK_LIST_DOORS.pickListGet, { p_list_id: list_id }, "pickListGet");
1459
+ },
1460
+ async pickListForSelection({ list_id }) {
1461
+ return callDoor(
1462
+ PICK_LIST_DOORS.pickListForSelection,
1463
+ { p_list_id: list_id },
1464
+ "pickListForSelection"
1465
+ );
1466
+ },
1467
+ async pickListUpdate({ list_id, list_name, description, items }) {
1468
+ return callDoor(
1469
+ PICK_LIST_DOORS.pickListUpdate,
1470
+ {
1471
+ p_list_id: list_id,
1472
+ p_list_name: list_name ?? null,
1473
+ p_description: description ?? null,
1474
+ p_items: items ? [...items] : null
1475
+ },
1476
+ "pickListUpdate"
1477
+ );
1478
+ }
1479
+ };
1480
+ }
1481
+
1349
1482
  // src/placement.ts
1350
1483
  function countOf(value) {
1351
1484
  return typeof value === "number" && Number.isFinite(value) ? value : 0;
@@ -2665,12 +2798,7 @@ function doorReady(config, name) {
2665
2798
  return DOOR_NAMES.has(name) || Boolean(config?.knownDoors?.includes(name));
2666
2799
  }
2667
2800
  function doorAbsent(name) {
2668
- const owed = OWED_BY[name];
2669
- return {
2670
- code: "door_absent",
2671
- message: `The record store has no door \`custom.${name}\` yet, so this call was not made. Nothing was read and nothing was written.`,
2672
- 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\`.`
2673
- };
2801
+ return doorAbsentRefusal(name, OWED_BY[name]);
2674
2802
  }
2675
2803
  var DOORS = {
2676
2804
  // THE READ DOOR (DOOR-1). Every read of a record's values goes through these
@@ -3450,29 +3578,6 @@ function intersectIds(sets) {
3450
3578
 
3451
3579
  // src/core/client.ts
3452
3580
  var DEFAULT_SCHEMA = "custom";
3453
- function canonicalArgs(value) {
3454
- return JSON.stringify(
3455
- value,
3456
- (_key, held) => held && typeof held === "object" && !Array.isArray(held) ? Object.fromEntries(Object.keys(held).sort().map((k) => [k, held[k]])) : held
3457
- );
3458
- }
3459
- var A_PERSONS_REFUSAL = /* @__PURE__ */ new Set([
3460
- "refused_by_rule",
3461
- "stale_write",
3462
- "invalid_argument",
3463
- "already_exists",
3464
- "missing_reference"
3465
- ]);
3466
- function isAPersonsRefusal(code) {
3467
- return A_PERSONS_REFUSAL.has(code);
3468
- }
3469
- function sink(config) {
3470
- return config.onError ?? ((e) => {
3471
- const line = `[@ai-matrx/records] ${e.where}: ${e.code} \u2014 ${e.message}${e.hint ? ` (${e.hint})` : ""}`;
3472
- if (isAPersonsRefusal(e.code)) console.info(line);
3473
- else console.error(line);
3474
- });
3475
- }
3476
3581
  var TABLE_LIST_PAGE = 500;
3477
3582
  var TABLE_ARCHIVE_PASS = 20;
3478
3583
  var TABLE_RESTORE_PASS = 20;
@@ -3485,7 +3590,7 @@ function createRecordsClient(given) {
3485
3590
  const org = config.organizationId;
3486
3591
  const ledger = config.opLedger ?? defaultOpLedger;
3487
3592
  const mintOp = () => ledger.mint();
3488
- const scream = sink(config);
3593
+ const scream = recordsErrorSink(config.onError);
3489
3594
  const BUNDLE_TTL_MS = 1e4;
3490
3595
  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"]);
3491
3596
  const bundleParts = /* @__PURE__ */ new Map();
@@ -3627,56 +3732,20 @@ function createRecordsClient(given) {
3627
3732
  bundleAsked.delete(tableId);
3628
3733
  for (const key of [...bundleParts.keys()]) if (key.includes(tableId)) bundleParts.delete(key);
3629
3734
  }
3630
- function primedFor(door, args) {
3631
- const look = LOOK_WRITES[door];
3632
- if (look) {
3633
- dropPrimedDoorAnswers(look);
3634
- return null;
3635
- }
3636
- if (isWritingDoor(door)) {
3637
- dropPrimedDoorAnswers();
3638
- return null;
3639
- }
3640
- return takePrimedDoorAnswer(`${door}|${canonicalArgs(args)}`);
3641
- }
3642
- const readsInFlight = /* @__PURE__ */ new Map();
3643
- async function callDoor(door, args, where, opts) {
3644
- const primed = primedFor(door, args);
3645
- if (primed) return ok(primed.data);
3646
- const bundled = await fromBundle(door, args);
3647
- if (bundled) return ok(bundled.data);
3648
- if (!doorReady(config, door)) {
3649
- const refusal2 = doorAbsent(door);
3650
- scream({ code: refusal2.code, message: refusal2.message, ...refusal2.hint ? { hint: refusal2.hint } : {}, where });
3651
- return err(refusal2);
3652
- }
3653
- const flightKey = isWritingDoor(door) ? null : `${door}|${canonicalArgs(args)}`;
3654
- const flying = flightKey ? readsInFlight.get(flightKey) : void 0;
3655
- const response = await (flying ?? (() => {
3656
- const call = Promise.resolve(config.dataSource.rpc(`${door}`, args, { schema }));
3657
- if (flightKey) {
3658
- readsInFlight.set(flightKey, call);
3659
- const forget = () => {
3660
- if (readsInFlight.get(flightKey) === call) readsInFlight.delete(flightKey);
3661
- };
3662
- call.then(forget, forget);
3663
- }
3664
- return call;
3665
- })());
3666
- if (response.error) {
3667
- const refusal2 = mapPgError(response.error, where);
3668
- if (opts?.quiet) console.info(`[@ai-matrx/records] ${where}: ${refusal2.code} - ${refusal2.message}`);
3669
- else scream({ code: refusal2.code, message: refusal2.message, ...refusal2.hint ? { hint: refusal2.hint } : {}, where });
3670
- return err(refusal2);
3671
- }
3672
- if (isWritingDoor(door) || LOOK_WRITES[door]) {
3735
+ const primedFor = primedDoorAnswer;
3736
+ const callDoor = createDoorCall({
3737
+ dataSource: config.dataSource,
3738
+ schema,
3739
+ onError: scream,
3740
+ doorReady: (door) => doorReady(config, door),
3741
+ absent: doorAbsent,
3742
+ held: fromBundle,
3743
+ wrote: (_door, args) => {
3673
3744
  const tableId = args["p_table_id"];
3674
3745
  bundleDrop(typeof tableId === "string" ? tableId : null);
3675
- forgetPrimedTablePageBundlesOf(typeof tableId === "string" ? tableId : null);
3676
- dropPrimedDoorAnswers(LOOK_WRITES[door]);
3677
3746
  }
3678
- return ok(response.data);
3679
- }
3747
+ });
3748
+ const scopes = createScopeDoors(callDoor);
3680
3749
  function structureMoved(tableId, result) {
3681
3750
  if (result.ok) {
3682
3751
  bundleDrop(tableId);
@@ -3875,7 +3944,7 @@ function createRecordsClient(given) {
3875
3944
  const unavailableReason = (error) => `${error.message}${error.hint ? ` ${error.hint}` : ""}`;
3876
3945
  const client = {
3877
3946
  config,
3878
- scopes: createScopeDoors(callDoor),
3947
+ scopes,
3879
3948
  async recordWrite({ table_id, data }) {
3880
3949
  const result = await callDoor(
3881
3950
  DOORS.recordWrite,
@@ -4574,28 +4643,7 @@ function createRecordsClient(given) {
4574
4643
  "fieldOptions"
4575
4644
  );
4576
4645
  },
4577
- async pickListGet({ list_id }) {
4578
- return callDoor(DOORS.pickListGet, { p_list_id: list_id }, "pickListGet");
4579
- },
4580
- async pickListForSelection({ list_id }) {
4581
- return callDoor(
4582
- DOORS.pickListForSelection,
4583
- { p_list_id: list_id },
4584
- "pickListForSelection"
4585
- );
4586
- },
4587
- async pickListUpdate({ list_id, list_name, description, items }) {
4588
- return callDoor(
4589
- DOORS.pickListUpdate,
4590
- {
4591
- p_list_id: list_id,
4592
- p_list_name: list_name ?? null,
4593
- p_description: description ?? null,
4594
- p_items: items ? [...items] : null
4595
- },
4596
- "pickListUpdate"
4597
- );
4598
- },
4646
+ ...createPickListDoors(callDoor),
4599
4647
  async fieldChoiceUsage({ field_id }) {
4600
4648
  const result = await callDoor(
4601
4649
  DOORS.fieldChoiceUsage,
@@ -7129,11 +7177,7 @@ function createRecordsClient(given) {
7129
7177
  );
7130
7178
  },
7131
7179
  async scopeTableProvision({ home_id, item_id, scope_id }) {
7132
- return callDoor(
7133
- DOORS.scopeTableProvision,
7134
- { p_organization_id: org, p_item_id: item_id, p_scope_id: scope_id, p_home_id: home_id ?? null },
7135
- "scopeTableProvision"
7136
- );
7180
+ return scopes.tableProvision({ organization_id: org, item_id, scope_id, home_id: home_id ?? null });
7137
7181
  },
7138
7182
  async tableRowCounts({ table_ids }) {
7139
7183
  return callDoor(