@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.
- package/CHANGELOG.md +16 -1
- package/dist/{client-CrwedBYU.d.ts → client-CSfkP7Xf.d.ts} +5 -74
- package/dist/{client-D1EwyWfh.d.cts → client-jKf1Z-kp.d.cts} +5 -74
- package/dist/core/index.cjs +149 -105
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +9 -331
- package/dist/core/index.d.ts +9 -331
- package/dist/core/index.js +149 -105
- package/dist/core/index.js.map +1 -1
- package/dist/data/index.cjs +280 -236
- package/dist/data/index.cjs.map +1 -1
- package/dist/data/index.d.cts +3 -2
- package/dist/data/index.d.ts +3 -2
- package/dist/data/index.js +280 -236
- package/dist/data/index.js.map +1 -1
- package/dist/{declareTable-CC5rTTIA.d.ts → declareTable-0emxEewn.d.ts} +1 -1
- package/dist/{declareTable-BIIt0Wqt.d.cts → declareTable-800bwUn3.d.cts} +1 -1
- package/dist/door-call/index.cjs +1287 -0
- package/dist/door-call/index.cjs.map +1 -0
- package/dist/door-call/index.d.cts +20 -0
- package/dist/door-call/index.d.ts +20 -0
- package/dist/door-call/index.js +1264 -0
- package/dist/door-call/index.js.map +1 -0
- package/dist/{doors-D1yAs0a0.d.cts → doors-BgjRUdxw.d.cts} +13 -1
- package/dist/{doors-D2z3kH2i.d.ts → doors-D7_jEKtg.d.ts} +13 -1
- package/dist/index.d.cts +5 -4
- package/dist/index.d.ts +5 -4
- package/dist/{objectOrganization-DazBoDAq.d.cts → objectOrganization-B5YFGVUB.d.cts} +1 -1
- package/dist/{objectOrganization-D1ox3gUx.d.ts → objectOrganization-DozoVIxS.d.ts} +1 -1
- package/dist/pickListDoors-C-_eAEGL.d.cts +135 -0
- package/dist/pickListDoors-DgWVnNRI.d.ts +135 -0
- package/dist/questions/index.d.cts +3 -2
- package/dist/questions/index.d.ts +3 -2
- package/dist/react/index.cjs +363 -319
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +37 -22
- package/dist/react/index.d.ts +37 -22
- package/dist/react/index.js +363 -319
- package/dist/react/index.js.map +1 -1
- package/dist/scopes/index.cjs +7 -0
- package/dist/scopes/index.cjs.map +1 -1
- package/dist/scopes/index.d.cts +2 -2
- package/dist/scopes/index.d.ts +2 -2
- package/dist/scopes/index.js +7 -0
- package/dist/scopes/index.js.map +1 -1
- package/dist/setup/index.cjs +289 -245
- package/dist/setup/index.cjs.map +1 -1
- package/dist/setup/index.d.cts +4 -3
- package/dist/setup/index.d.ts +4 -3
- package/dist/setup/index.js +289 -245
- package/dist/setup/index.js.map +1 -1
- package/dist/table-logic-BPquabNN.d.ts +328 -0
- package/dist/table-logic-CTh6lwaq.d.cts +328 -0
- package/dist/typed-table/index.cjs +280 -236
- package/dist/typed-table/index.cjs.map +1 -1
- package/dist/typed-table/index.d.cts +4 -3
- package/dist/typed-table/index.d.ts +4 -3
- package/dist/typed-table/index.js +280 -236
- package/dist/typed-table/index.js.map +1 -1
- package/dist/views/index.d.cts +3 -2
- package/dist/views/index.d.ts +3 -2
- package/package.json +13 -3
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { N as NewFieldSpec } from '../declareTable-
|
|
1
|
+
import { N as NewFieldSpec } from '../declareTable-800bwUn3.cjs';
|
|
2
2
|
import { U as Uuid, R as RecordsResult, k as RecordPageSort } from '../record-CTgSgWe3.cjs';
|
|
3
|
-
import { F as FieldDrift, R as RecordsClient, T as TableArchiveProgress } from '../client-
|
|
3
|
+
import { F as FieldDrift, R as RecordsClient, T as TableArchiveProgress } from '../client-jKf1Z-kp.cjs';
|
|
4
4
|
import '../field-B8loYt-A.cjs';
|
|
5
5
|
import '../subscription-CuaGi3lC.cjs';
|
|
6
6
|
import '../rule-49jO7lN-.cjs';
|
|
7
7
|
import '../relation-BjjjXyqn.cjs';
|
|
8
8
|
import '../ports-alv3bgKY.cjs';
|
|
9
|
-
import '../doors-
|
|
9
|
+
import '../doors-BgjRUdxw.cjs';
|
|
10
|
+
import '../pickListDoors-C-_eAEGL.cjs';
|
|
10
11
|
import '../portal-L_mN8l9P.cjs';
|
|
11
12
|
import '../table-kind/index.cjs';
|
|
12
13
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { N as NewFieldSpec } from '../declareTable-
|
|
1
|
+
import { N as NewFieldSpec } from '../declareTable-0emxEewn.js';
|
|
2
2
|
import { U as Uuid, R as RecordsResult, k as RecordPageSort } from '../record-CTgSgWe3.js';
|
|
3
|
-
import { F as FieldDrift, R as RecordsClient, T as TableArchiveProgress } from '../client-
|
|
3
|
+
import { F as FieldDrift, R as RecordsClient, T as TableArchiveProgress } from '../client-CSfkP7Xf.js';
|
|
4
4
|
import '../field-DaE90BZ7.js';
|
|
5
5
|
import '../subscription-Bp1RSb6p.js';
|
|
6
6
|
import '../rule-DzNj0QvN.js';
|
|
7
7
|
import '../relation-T4biacnz.js';
|
|
8
8
|
import '../ports-CmmvR8OI.js';
|
|
9
|
-
import '../doors-
|
|
9
|
+
import '../doors-D7_jEKtg.js';
|
|
10
|
+
import '../pickListDoors-DgWVnNRI.js';
|
|
10
11
|
import '../portal-CAssJHRZ.js';
|
|
11
12
|
import '../table-kind/index.js';
|
|
12
13
|
|
|
@@ -329,137 +329,6 @@ function isWritingDoor(door) {
|
|
|
329
329
|
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);
|
|
330
330
|
}
|
|
331
331
|
|
|
332
|
-
// src/core/recordChanges.ts
|
|
333
|
-
import { globalSlot } from "@ai-matrx/kit/global-slot";
|
|
334
|
-
var listeners = globalSlot("ai-matrx.records.record-change-listeners", () => /* @__PURE__ */ new Set());
|
|
335
|
-
function announceRecordChanged(recordId) {
|
|
336
|
-
for (const listener of [...listeners]) {
|
|
337
|
-
try {
|
|
338
|
-
listener(recordId);
|
|
339
|
-
} catch (thrown) {
|
|
340
|
-
console.error("[@ai-matrx/records] a record-change listener threw", thrown);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
var removed = globalSlot("ai-matrx.records.removed-records", () => /* @__PURE__ */ new Set());
|
|
345
|
-
function markRecordRemoved(recordId) {
|
|
346
|
-
removed.add(recordId);
|
|
347
|
-
}
|
|
348
|
-
function markRecordRestored(recordId) {
|
|
349
|
-
removed.delete(recordId);
|
|
350
|
-
}
|
|
351
|
-
function onRecordChanged(listener) {
|
|
352
|
-
listeners.add(listener);
|
|
353
|
-
return () => listeners.delete(listener);
|
|
354
|
-
}
|
|
355
|
-
var tableListeners = globalSlot("ai-matrx.records.table-structure-listeners", () => /* @__PURE__ */ new Set());
|
|
356
|
-
function announceTableStructureChanged(tableId) {
|
|
357
|
-
for (const listener of [...tableListeners]) {
|
|
358
|
-
try {
|
|
359
|
-
listener(tableId);
|
|
360
|
-
} catch (thrown) {
|
|
361
|
-
console.error("[@ai-matrx/records] a table-structure listener threw", thrown);
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
// src/archive.ts
|
|
367
|
-
var DEFAULT_ARCHIVE_LANE = "org";
|
|
368
|
-
|
|
369
|
-
// src/aggregate.ts
|
|
370
|
-
function isRuleFilter(filter) {
|
|
371
|
-
if (!filter || typeof filter !== "object" || Array.isArray(filter)) return false;
|
|
372
|
-
const node = filter;
|
|
373
|
-
return typeof node.op === "string" && Array.isArray(node.args);
|
|
374
|
-
}
|
|
375
|
-
function stableFilterKey(filter) {
|
|
376
|
-
if (!filter) return "{}";
|
|
377
|
-
if (isRuleFilter(filter)) return JSON.stringify(filter);
|
|
378
|
-
const keys = Object.keys(filter).sort();
|
|
379
|
-
if (keys.length === 0) return "{}";
|
|
380
|
-
const parts = keys.map((key) => {
|
|
381
|
-
const value = filter[key];
|
|
382
|
-
if (value !== null && typeof value === "object") {
|
|
383
|
-
const window = value;
|
|
384
|
-
return `${JSON.stringify(key)}:{"from":${JSON.stringify(window.from ?? null)},"to":${JSON.stringify(window.to ?? null)}}`;
|
|
385
|
-
}
|
|
386
|
-
return `${JSON.stringify(key)}:${JSON.stringify(value ?? null)}`;
|
|
387
|
-
});
|
|
388
|
-
return `{${parts.join(",")}}`;
|
|
389
|
-
}
|
|
390
|
-
function liftWithheld(rows) {
|
|
391
|
-
let shared;
|
|
392
|
-
for (const row of rows) {
|
|
393
|
-
const m = (row.measures ?? {})["_withheld"];
|
|
394
|
-
if (m !== void 0 && m !== null && typeof m === "object") {
|
|
395
|
-
shared = m;
|
|
396
|
-
break;
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
return rows.map((row) => {
|
|
400
|
-
const measures = row.measures ?? {};
|
|
401
|
-
const own = measures["_withheld"];
|
|
402
|
-
const marker = own !== void 0 && own !== null && typeof own === "object" ? own : shared;
|
|
403
|
-
const rowCount = row.row_count ?? 0;
|
|
404
|
-
if (marker === void 0 || marker === null || typeof marker !== "object") {
|
|
405
|
-
return rowCount === row.row_count ? row : { ...row, row_count: rowCount };
|
|
406
|
-
}
|
|
407
|
-
const { _withheld: _drop, ...rest } = measures;
|
|
408
|
-
const withheld = {};
|
|
409
|
-
for (const [name, raw] of Object.entries(marker)) {
|
|
410
|
-
const m = raw ?? {};
|
|
411
|
-
withheld[name] = {
|
|
412
|
-
reason: m.withheld?.reason ?? null,
|
|
413
|
-
needs: m.withheld?.needs ?? null,
|
|
414
|
-
or: m.withheld?.or ?? null,
|
|
415
|
-
...m.says ? { says: m.says } : {},
|
|
416
|
-
...m.label ? { label: m.label } : {},
|
|
417
|
-
...m.field_key ? { field_key: m.field_key } : {}
|
|
418
|
-
};
|
|
419
|
-
}
|
|
420
|
-
return { ...row, measures: rest, withheld, row_count: rowCount };
|
|
421
|
-
});
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
// src/record.ts
|
|
425
|
-
function isLockedStub(row) {
|
|
426
|
-
if (!row) return false;
|
|
427
|
-
if (row.level !== null && row.level !== void 0) return false;
|
|
428
|
-
const doc = row.document;
|
|
429
|
-
if (!doc || typeof doc !== "object") return false;
|
|
430
|
-
const keys = Object.keys(doc);
|
|
431
|
-
if (keys.length === 0 || keys.length > 3) return false;
|
|
432
|
-
const d = doc;
|
|
433
|
-
return d["exists"] === true && keys.every((k) => k === "id" || k === "exists" || k === "submitted_at");
|
|
434
|
-
}
|
|
435
|
-
function splitLockedRows(rows) {
|
|
436
|
-
const open = [];
|
|
437
|
-
let locked = 0;
|
|
438
|
-
for (const row of rows) {
|
|
439
|
-
if (isLockedStub(row)) locked += 1;
|
|
440
|
-
else open.push(row);
|
|
441
|
-
}
|
|
442
|
-
return { rows: open, locked };
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
// src/subscription.ts
|
|
446
|
-
function callersTimeZone() {
|
|
447
|
-
try {
|
|
448
|
-
return Intl.DateTimeFormat().resolvedOptions().timeZone || null;
|
|
449
|
-
} catch {
|
|
450
|
-
return null;
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
function withCallersClock(spec, zone = callersTimeZone()) {
|
|
454
|
-
if (!zone || spec.quiet_hours?.tz) return spec;
|
|
455
|
-
return { ...spec, quiet_hours: { ...spec.quiet_hours ?? {}, tz: zone } };
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
// src/rowLabel.ts
|
|
459
|
-
function clearsRowLabel(formula) {
|
|
460
|
-
return formula == null || formula.trim() === "";
|
|
461
|
-
}
|
|
462
|
-
|
|
463
332
|
// src/results.ts
|
|
464
333
|
var ok = (data) => ({ ok: true, data });
|
|
465
334
|
var err = (error) => ({ ok: false, error });
|
|
@@ -630,6 +499,230 @@ function mapPgError(error, where) {
|
|
|
630
499
|
return mapped;
|
|
631
500
|
}
|
|
632
501
|
|
|
502
|
+
// src/core/doorCall.ts
|
|
503
|
+
var DEFAULT_DOOR_SCHEMA = "custom";
|
|
504
|
+
function canonicalArgs(value) {
|
|
505
|
+
return JSON.stringify(
|
|
506
|
+
value,
|
|
507
|
+
(_key, held) => held && typeof held === "object" && !Array.isArray(held) ? Object.fromEntries(Object.keys(held).sort().map((k) => [k, held[k]])) : held
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
var A_PERSONS_REFUSAL = /* @__PURE__ */ new Set([
|
|
511
|
+
"refused_by_rule",
|
|
512
|
+
"stale_write",
|
|
513
|
+
"invalid_argument",
|
|
514
|
+
"already_exists",
|
|
515
|
+
"missing_reference"
|
|
516
|
+
]);
|
|
517
|
+
function isAPersonsRefusal(code) {
|
|
518
|
+
return A_PERSONS_REFUSAL.has(code);
|
|
519
|
+
}
|
|
520
|
+
function recordsErrorSink(onError) {
|
|
521
|
+
return onError ?? ((e) => {
|
|
522
|
+
const line = `[@ai-matrx/records] ${e.where}: ${e.code} \u2014 ${e.message}${e.hint ? ` (${e.hint})` : ""}`;
|
|
523
|
+
if (isAPersonsRefusal(e.code)) console.info(line);
|
|
524
|
+
else console.error(line);
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
function doorAbsentRefusal(name, owedBy) {
|
|
528
|
+
return {
|
|
529
|
+
code: "door_absent",
|
|
530
|
+
message: `The record store has no door \`custom.${name}\` yet, so this call was not made. Nothing was read and nothing was written.`,
|
|
531
|
+
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\`.`
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
function primedDoorAnswer(door, args) {
|
|
535
|
+
const look = LOOK_WRITES[door];
|
|
536
|
+
if (look) {
|
|
537
|
+
dropPrimedDoorAnswers(look);
|
|
538
|
+
return null;
|
|
539
|
+
}
|
|
540
|
+
if (isWritingDoor(door)) {
|
|
541
|
+
dropPrimedDoorAnswers();
|
|
542
|
+
return null;
|
|
543
|
+
}
|
|
544
|
+
return takePrimedDoorAnswer(`${door}|${canonicalArgs(args)}`);
|
|
545
|
+
}
|
|
546
|
+
function createDoorCall(options) {
|
|
547
|
+
const { dataSource, doorReady: doorReady2, held, wrote } = options;
|
|
548
|
+
const schema = options.schema ?? DEFAULT_DOOR_SCHEMA;
|
|
549
|
+
const scream = recordsErrorSink(options.onError);
|
|
550
|
+
const absent = options.absent ?? ((door) => doorAbsentRefusal(door));
|
|
551
|
+
const readsInFlight = /* @__PURE__ */ new Map();
|
|
552
|
+
const say = (refusal2, where) => scream({ code: refusal2.code, message: refusal2.message, ...refusal2.hint ? { hint: refusal2.hint } : {}, where });
|
|
553
|
+
return async function callDoor(door, args, where, opts) {
|
|
554
|
+
const primed = primedDoorAnswer(door, args);
|
|
555
|
+
if (primed) return ok(primed.data);
|
|
556
|
+
if (held) {
|
|
557
|
+
const bundled = await held(door, args);
|
|
558
|
+
if (bundled) return ok(bundled.data);
|
|
559
|
+
}
|
|
560
|
+
if (doorReady2 && !doorReady2(door)) {
|
|
561
|
+
const refusal2 = absent(door);
|
|
562
|
+
say(refusal2, where);
|
|
563
|
+
return err(refusal2);
|
|
564
|
+
}
|
|
565
|
+
const flightKey = isWritingDoor(door) ? null : `${door}|${canonicalArgs(args)}`;
|
|
566
|
+
const flying = flightKey ? readsInFlight.get(flightKey) : void 0;
|
|
567
|
+
const response = await (flying ?? (() => {
|
|
568
|
+
const call = Promise.resolve(dataSource.rpc(`${door}`, args, { schema }));
|
|
569
|
+
if (flightKey) {
|
|
570
|
+
readsInFlight.set(flightKey, call);
|
|
571
|
+
const forget = () => {
|
|
572
|
+
if (readsInFlight.get(flightKey) === call) readsInFlight.delete(flightKey);
|
|
573
|
+
};
|
|
574
|
+
call.then(forget, forget);
|
|
575
|
+
}
|
|
576
|
+
return call;
|
|
577
|
+
})());
|
|
578
|
+
if (response.error) {
|
|
579
|
+
const code = response.error.code;
|
|
580
|
+
const refusal2 = !doorReady2 && (code === "PGRST202" || code === "42883") ? absent(door) : mapPgError(response.error, where);
|
|
581
|
+
if (opts?.quiet) console.info(`[@ai-matrx/records] ${where}: ${refusal2.code} - ${refusal2.message}`);
|
|
582
|
+
else say(refusal2, where);
|
|
583
|
+
return err(refusal2);
|
|
584
|
+
}
|
|
585
|
+
if (isWritingDoor(door) || LOOK_WRITES[door]) {
|
|
586
|
+
const tableId = args["p_table_id"];
|
|
587
|
+
wrote?.(door, args);
|
|
588
|
+
forgetPrimedTablePageBundlesOf(typeof tableId === "string" ? tableId : null);
|
|
589
|
+
dropPrimedDoorAnswers(LOOK_WRITES[door]);
|
|
590
|
+
}
|
|
591
|
+
return ok(response.data);
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// src/core/recordChanges.ts
|
|
596
|
+
import { globalSlot } from "@ai-matrx/kit/global-slot";
|
|
597
|
+
var listeners = globalSlot("ai-matrx.records.record-change-listeners", () => /* @__PURE__ */ new Set());
|
|
598
|
+
function announceRecordChanged(recordId) {
|
|
599
|
+
for (const listener of [...listeners]) {
|
|
600
|
+
try {
|
|
601
|
+
listener(recordId);
|
|
602
|
+
} catch (thrown) {
|
|
603
|
+
console.error("[@ai-matrx/records] a record-change listener threw", thrown);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
var removed = globalSlot("ai-matrx.records.removed-records", () => /* @__PURE__ */ new Set());
|
|
608
|
+
function markRecordRemoved(recordId) {
|
|
609
|
+
removed.add(recordId);
|
|
610
|
+
}
|
|
611
|
+
function markRecordRestored(recordId) {
|
|
612
|
+
removed.delete(recordId);
|
|
613
|
+
}
|
|
614
|
+
function onRecordChanged(listener) {
|
|
615
|
+
listeners.add(listener);
|
|
616
|
+
return () => listeners.delete(listener);
|
|
617
|
+
}
|
|
618
|
+
var tableListeners = globalSlot("ai-matrx.records.table-structure-listeners", () => /* @__PURE__ */ new Set());
|
|
619
|
+
function announceTableStructureChanged(tableId) {
|
|
620
|
+
for (const listener of [...tableListeners]) {
|
|
621
|
+
try {
|
|
622
|
+
listener(tableId);
|
|
623
|
+
} catch (thrown) {
|
|
624
|
+
console.error("[@ai-matrx/records] a table-structure listener threw", thrown);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// src/archive.ts
|
|
630
|
+
var DEFAULT_ARCHIVE_LANE = "org";
|
|
631
|
+
|
|
632
|
+
// src/aggregate.ts
|
|
633
|
+
function isRuleFilter(filter) {
|
|
634
|
+
if (!filter || typeof filter !== "object" || Array.isArray(filter)) return false;
|
|
635
|
+
const node = filter;
|
|
636
|
+
return typeof node.op === "string" && Array.isArray(node.args);
|
|
637
|
+
}
|
|
638
|
+
function stableFilterKey(filter) {
|
|
639
|
+
if (!filter) return "{}";
|
|
640
|
+
if (isRuleFilter(filter)) return JSON.stringify(filter);
|
|
641
|
+
const keys = Object.keys(filter).sort();
|
|
642
|
+
if (keys.length === 0) return "{}";
|
|
643
|
+
const parts = keys.map((key) => {
|
|
644
|
+
const value = filter[key];
|
|
645
|
+
if (value !== null && typeof value === "object") {
|
|
646
|
+
const window = value;
|
|
647
|
+
return `${JSON.stringify(key)}:{"from":${JSON.stringify(window.from ?? null)},"to":${JSON.stringify(window.to ?? null)}}`;
|
|
648
|
+
}
|
|
649
|
+
return `${JSON.stringify(key)}:${JSON.stringify(value ?? null)}`;
|
|
650
|
+
});
|
|
651
|
+
return `{${parts.join(",")}}`;
|
|
652
|
+
}
|
|
653
|
+
function liftWithheld(rows) {
|
|
654
|
+
let shared;
|
|
655
|
+
for (const row of rows) {
|
|
656
|
+
const m = (row.measures ?? {})["_withheld"];
|
|
657
|
+
if (m !== void 0 && m !== null && typeof m === "object") {
|
|
658
|
+
shared = m;
|
|
659
|
+
break;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
return rows.map((row) => {
|
|
663
|
+
const measures = row.measures ?? {};
|
|
664
|
+
const own = measures["_withheld"];
|
|
665
|
+
const marker = own !== void 0 && own !== null && typeof own === "object" ? own : shared;
|
|
666
|
+
const rowCount = row.row_count ?? 0;
|
|
667
|
+
if (marker === void 0 || marker === null || typeof marker !== "object") {
|
|
668
|
+
return rowCount === row.row_count ? row : { ...row, row_count: rowCount };
|
|
669
|
+
}
|
|
670
|
+
const { _withheld: _drop, ...rest } = measures;
|
|
671
|
+
const withheld = {};
|
|
672
|
+
for (const [name, raw] of Object.entries(marker)) {
|
|
673
|
+
const m = raw ?? {};
|
|
674
|
+
withheld[name] = {
|
|
675
|
+
reason: m.withheld?.reason ?? null,
|
|
676
|
+
needs: m.withheld?.needs ?? null,
|
|
677
|
+
or: m.withheld?.or ?? null,
|
|
678
|
+
...m.says ? { says: m.says } : {},
|
|
679
|
+
...m.label ? { label: m.label } : {},
|
|
680
|
+
...m.field_key ? { field_key: m.field_key } : {}
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
return { ...row, measures: rest, withheld, row_count: rowCount };
|
|
684
|
+
});
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
// src/record.ts
|
|
688
|
+
function isLockedStub(row) {
|
|
689
|
+
if (!row) return false;
|
|
690
|
+
if (row.level !== null && row.level !== void 0) return false;
|
|
691
|
+
const doc = row.document;
|
|
692
|
+
if (!doc || typeof doc !== "object") return false;
|
|
693
|
+
const keys = Object.keys(doc);
|
|
694
|
+
if (keys.length === 0 || keys.length > 3) return false;
|
|
695
|
+
const d = doc;
|
|
696
|
+
return d["exists"] === true && keys.every((k) => k === "id" || k === "exists" || k === "submitted_at");
|
|
697
|
+
}
|
|
698
|
+
function splitLockedRows(rows) {
|
|
699
|
+
const open = [];
|
|
700
|
+
let locked = 0;
|
|
701
|
+
for (const row of rows) {
|
|
702
|
+
if (isLockedStub(row)) locked += 1;
|
|
703
|
+
else open.push(row);
|
|
704
|
+
}
|
|
705
|
+
return { rows: open, locked };
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// src/subscription.ts
|
|
709
|
+
function callersTimeZone() {
|
|
710
|
+
try {
|
|
711
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone || null;
|
|
712
|
+
} catch {
|
|
713
|
+
return null;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
function withCallersClock(spec, zone = callersTimeZone()) {
|
|
717
|
+
if (!zone || spec.quiet_hours?.tz) return spec;
|
|
718
|
+
return { ...spec, quiet_hours: { ...spec.quiet_hours ?? {}, tz: zone } };
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
// src/rowLabel.ts
|
|
722
|
+
function clearsRowLabel(formula) {
|
|
723
|
+
return formula == null || formula.trim() === "";
|
|
724
|
+
}
|
|
725
|
+
|
|
633
726
|
// src/relation.ts
|
|
634
727
|
import { isUuidShape as isUuidShape2 } from "@ai-matrx/kit/uuid";
|
|
635
728
|
function isReverseField(field2) {
|
|
@@ -1409,11 +1502,51 @@ function createScopeDoors(call) {
|
|
|
1409
1502
|
source_type: String(envelope.data?.source_type ?? cell.source_type ?? "ai_enriched")
|
|
1410
1503
|
}
|
|
1411
1504
|
};
|
|
1505
|
+
},
|
|
1506
|
+
tableProvision({ organization_id, item_id, scope_id, home_id }) {
|
|
1507
|
+
return call(
|
|
1508
|
+
"scope_table_provision",
|
|
1509
|
+
{ p_organization_id: organization_id, p_item_id: item_id, p_scope_id: scope_id, p_home_id: home_id ?? null },
|
|
1510
|
+
"scopeTableProvision"
|
|
1511
|
+
);
|
|
1412
1512
|
}
|
|
1413
1513
|
};
|
|
1414
1514
|
return doors;
|
|
1415
1515
|
}
|
|
1416
1516
|
|
|
1517
|
+
// src/core/pickListDoors.ts
|
|
1518
|
+
var PICK_LIST_DOORS = {
|
|
1519
|
+
pickListGet: "pick_list_get",
|
|
1520
|
+
pickListForSelection: "pick_list_for_selection",
|
|
1521
|
+
pickListUpdate: "pick_list_update"
|
|
1522
|
+
};
|
|
1523
|
+
function createPickListDoors(callDoor) {
|
|
1524
|
+
return {
|
|
1525
|
+
async pickListGet({ list_id }) {
|
|
1526
|
+
return callDoor(PICK_LIST_DOORS.pickListGet, { p_list_id: list_id }, "pickListGet");
|
|
1527
|
+
},
|
|
1528
|
+
async pickListForSelection({ list_id }) {
|
|
1529
|
+
return callDoor(
|
|
1530
|
+
PICK_LIST_DOORS.pickListForSelection,
|
|
1531
|
+
{ p_list_id: list_id },
|
|
1532
|
+
"pickListForSelection"
|
|
1533
|
+
);
|
|
1534
|
+
},
|
|
1535
|
+
async pickListUpdate({ list_id, list_name, description, items }) {
|
|
1536
|
+
return callDoor(
|
|
1537
|
+
PICK_LIST_DOORS.pickListUpdate,
|
|
1538
|
+
{
|
|
1539
|
+
p_list_id: list_id,
|
|
1540
|
+
p_list_name: list_name ?? null,
|
|
1541
|
+
p_description: description ?? null,
|
|
1542
|
+
p_items: items ? [...items] : null
|
|
1543
|
+
},
|
|
1544
|
+
"pickListUpdate"
|
|
1545
|
+
);
|
|
1546
|
+
}
|
|
1547
|
+
};
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1417
1550
|
// src/choice.ts
|
|
1418
1551
|
import { isUuidShape as isUuidShape4 } from "@ai-matrx/kit/uuid";
|
|
1419
1552
|
var CHOICE_NUDGES = ["ask", "always_add", "never_add"];
|
|
@@ -2735,12 +2868,7 @@ function doorReady(config, name) {
|
|
|
2735
2868
|
return DOOR_NAMES.has(name) || Boolean(config?.knownDoors?.includes(name));
|
|
2736
2869
|
}
|
|
2737
2870
|
function doorAbsent(name) {
|
|
2738
|
-
|
|
2739
|
-
return {
|
|
2740
|
-
code: "door_absent",
|
|
2741
|
-
message: `The record store has no door \`custom.${name}\` yet, so this call was not made. Nothing was read and nothing was written.`,
|
|
2742
|
-
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\`.`
|
|
2743
|
-
};
|
|
2871
|
+
return doorAbsentRefusal(name, OWED_BY[name]);
|
|
2744
2872
|
}
|
|
2745
2873
|
var DOORS = {
|
|
2746
2874
|
// THE READ DOOR (DOOR-1). Every read of a record's values goes through these
|
|
@@ -3520,29 +3648,6 @@ function intersectIds(sets) {
|
|
|
3520
3648
|
|
|
3521
3649
|
// src/core/client.ts
|
|
3522
3650
|
var DEFAULT_SCHEMA = "custom";
|
|
3523
|
-
function canonicalArgs(value) {
|
|
3524
|
-
return JSON.stringify(
|
|
3525
|
-
value,
|
|
3526
|
-
(_key, held) => held && typeof held === "object" && !Array.isArray(held) ? Object.fromEntries(Object.keys(held).sort().map((k) => [k, held[k]])) : held
|
|
3527
|
-
);
|
|
3528
|
-
}
|
|
3529
|
-
var A_PERSONS_REFUSAL = /* @__PURE__ */ new Set([
|
|
3530
|
-
"refused_by_rule",
|
|
3531
|
-
"stale_write",
|
|
3532
|
-
"invalid_argument",
|
|
3533
|
-
"already_exists",
|
|
3534
|
-
"missing_reference"
|
|
3535
|
-
]);
|
|
3536
|
-
function isAPersonsRefusal(code) {
|
|
3537
|
-
return A_PERSONS_REFUSAL.has(code);
|
|
3538
|
-
}
|
|
3539
|
-
function sink(config) {
|
|
3540
|
-
return config.onError ?? ((e) => {
|
|
3541
|
-
const line = `[@ai-matrx/records] ${e.where}: ${e.code} \u2014 ${e.message}${e.hint ? ` (${e.hint})` : ""}`;
|
|
3542
|
-
if (isAPersonsRefusal(e.code)) console.info(line);
|
|
3543
|
-
else console.error(line);
|
|
3544
|
-
});
|
|
3545
|
-
}
|
|
3546
3651
|
var TABLE_LIST_PAGE = 500;
|
|
3547
3652
|
var TABLE_ARCHIVE_PASS = 20;
|
|
3548
3653
|
var TABLE_RESTORE_PASS = 20;
|
|
@@ -3555,7 +3660,7 @@ function createRecordsClient(given) {
|
|
|
3555
3660
|
const org = config.organizationId;
|
|
3556
3661
|
const ledger = config.opLedger ?? defaultOpLedger;
|
|
3557
3662
|
const mintOp = () => ledger.mint();
|
|
3558
|
-
const scream =
|
|
3663
|
+
const scream = recordsErrorSink(config.onError);
|
|
3559
3664
|
const BUNDLE_TTL_MS = 1e4;
|
|
3560
3665
|
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"]);
|
|
3561
3666
|
const bundleParts = /* @__PURE__ */ new Map();
|
|
@@ -3697,56 +3802,20 @@ function createRecordsClient(given) {
|
|
|
3697
3802
|
bundleAsked.delete(tableId);
|
|
3698
3803
|
for (const key of [...bundleParts.keys()]) if (key.includes(tableId)) bundleParts.delete(key);
|
|
3699
3804
|
}
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
}
|
|
3710
|
-
return takePrimedDoorAnswer(`${door}|${canonicalArgs(args)}`);
|
|
3711
|
-
}
|
|
3712
|
-
const readsInFlight = /* @__PURE__ */ new Map();
|
|
3713
|
-
async function callDoor(door, args, where, opts) {
|
|
3714
|
-
const primed = primedFor(door, args);
|
|
3715
|
-
if (primed) return ok(primed.data);
|
|
3716
|
-
const bundled = await fromBundle(door, args);
|
|
3717
|
-
if (bundled) return ok(bundled.data);
|
|
3718
|
-
if (!doorReady(config, door)) {
|
|
3719
|
-
const refusal2 = doorAbsent(door);
|
|
3720
|
-
scream({ code: refusal2.code, message: refusal2.message, ...refusal2.hint ? { hint: refusal2.hint } : {}, where });
|
|
3721
|
-
return err(refusal2);
|
|
3722
|
-
}
|
|
3723
|
-
const flightKey = isWritingDoor(door) ? null : `${door}|${canonicalArgs(args)}`;
|
|
3724
|
-
const flying = flightKey ? readsInFlight.get(flightKey) : void 0;
|
|
3725
|
-
const response = await (flying ?? (() => {
|
|
3726
|
-
const call = Promise.resolve(config.dataSource.rpc(`${door}`, args, { schema }));
|
|
3727
|
-
if (flightKey) {
|
|
3728
|
-
readsInFlight.set(flightKey, call);
|
|
3729
|
-
const forget = () => {
|
|
3730
|
-
if (readsInFlight.get(flightKey) === call) readsInFlight.delete(flightKey);
|
|
3731
|
-
};
|
|
3732
|
-
call.then(forget, forget);
|
|
3733
|
-
}
|
|
3734
|
-
return call;
|
|
3735
|
-
})());
|
|
3736
|
-
if (response.error) {
|
|
3737
|
-
const refusal2 = mapPgError(response.error, where);
|
|
3738
|
-
if (opts?.quiet) console.info(`[@ai-matrx/records] ${where}: ${refusal2.code} - ${refusal2.message}`);
|
|
3739
|
-
else scream({ code: refusal2.code, message: refusal2.message, ...refusal2.hint ? { hint: refusal2.hint } : {}, where });
|
|
3740
|
-
return err(refusal2);
|
|
3741
|
-
}
|
|
3742
|
-
if (isWritingDoor(door) || LOOK_WRITES[door]) {
|
|
3805
|
+
const primedFor = primedDoorAnswer;
|
|
3806
|
+
const callDoor = createDoorCall({
|
|
3807
|
+
dataSource: config.dataSource,
|
|
3808
|
+
schema,
|
|
3809
|
+
onError: scream,
|
|
3810
|
+
doorReady: (door) => doorReady(config, door),
|
|
3811
|
+
absent: doorAbsent,
|
|
3812
|
+
held: fromBundle,
|
|
3813
|
+
wrote: (_door, args) => {
|
|
3743
3814
|
const tableId = args["p_table_id"];
|
|
3744
3815
|
bundleDrop(typeof tableId === "string" ? tableId : null);
|
|
3745
|
-
forgetPrimedTablePageBundlesOf(typeof tableId === "string" ? tableId : null);
|
|
3746
|
-
dropPrimedDoorAnswers(LOOK_WRITES[door]);
|
|
3747
3816
|
}
|
|
3748
|
-
|
|
3749
|
-
|
|
3817
|
+
});
|
|
3818
|
+
const scopes = createScopeDoors(callDoor);
|
|
3750
3819
|
function structureMoved(tableId, result) {
|
|
3751
3820
|
if (result.ok) {
|
|
3752
3821
|
bundleDrop(tableId);
|
|
@@ -3945,7 +4014,7 @@ function createRecordsClient(given) {
|
|
|
3945
4014
|
const unavailableReason = (error) => `${error.message}${error.hint ? ` ${error.hint}` : ""}`;
|
|
3946
4015
|
const client = {
|
|
3947
4016
|
config,
|
|
3948
|
-
scopes
|
|
4017
|
+
scopes,
|
|
3949
4018
|
async recordWrite({ table_id, data }) {
|
|
3950
4019
|
const result = await callDoor(
|
|
3951
4020
|
DOORS.recordWrite,
|
|
@@ -4644,28 +4713,7 @@ function createRecordsClient(given) {
|
|
|
4644
4713
|
"fieldOptions"
|
|
4645
4714
|
);
|
|
4646
4715
|
},
|
|
4647
|
-
|
|
4648
|
-
return callDoor(DOORS.pickListGet, { p_list_id: list_id }, "pickListGet");
|
|
4649
|
-
},
|
|
4650
|
-
async pickListForSelection({ list_id }) {
|
|
4651
|
-
return callDoor(
|
|
4652
|
-
DOORS.pickListForSelection,
|
|
4653
|
-
{ p_list_id: list_id },
|
|
4654
|
-
"pickListForSelection"
|
|
4655
|
-
);
|
|
4656
|
-
},
|
|
4657
|
-
async pickListUpdate({ list_id, list_name, description, items }) {
|
|
4658
|
-
return callDoor(
|
|
4659
|
-
DOORS.pickListUpdate,
|
|
4660
|
-
{
|
|
4661
|
-
p_list_id: list_id,
|
|
4662
|
-
p_list_name: list_name ?? null,
|
|
4663
|
-
p_description: description ?? null,
|
|
4664
|
-
p_items: items ? [...items] : null
|
|
4665
|
-
},
|
|
4666
|
-
"pickListUpdate"
|
|
4667
|
-
);
|
|
4668
|
-
},
|
|
4716
|
+
...createPickListDoors(callDoor),
|
|
4669
4717
|
async fieldChoiceUsage({ field_id }) {
|
|
4670
4718
|
const result = await callDoor(
|
|
4671
4719
|
DOORS.fieldChoiceUsage,
|
|
@@ -7199,11 +7247,7 @@ function createRecordsClient(given) {
|
|
|
7199
7247
|
);
|
|
7200
7248
|
},
|
|
7201
7249
|
async scopeTableProvision({ home_id, item_id, scope_id }) {
|
|
7202
|
-
return
|
|
7203
|
-
DOORS.scopeTableProvision,
|
|
7204
|
-
{ p_organization_id: org, p_item_id: item_id, p_scope_id: scope_id, p_home_id: home_id ?? null },
|
|
7205
|
-
"scopeTableProvision"
|
|
7206
|
-
);
|
|
7250
|
+
return scopes.tableProvision({ organization_id: org, item_id, scope_id, home_id: home_id ?? null });
|
|
7207
7251
|
},
|
|
7208
7252
|
async tableRowCounts({ table_ids }) {
|
|
7209
7253
|
return callDoor(
|