@ai-matrx/records 0.57.3 → 0.58.1

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/dist/index.js CHANGED
@@ -176,6 +176,7 @@ var FIELD_KINDS = [
176
176
  "currency",
177
177
  "datetime",
178
178
  "email",
179
+ "entity_reference",
179
180
  "formula",
180
181
  "json",
181
182
  "long_text",
@@ -214,6 +215,7 @@ function fieldKindFor(field, kernel) {
214
215
  case "list":
215
216
  return field.multi ? "multi_select" : "select";
216
217
  case "relation": {
218
+ if (isEntityReferenceConfig(config)) return "entity_reference";
217
219
  const parity = String(config["parity"] ?? "");
218
220
  if (parity === "attachment" || parity === "member") return parity;
219
221
  if (kernel?.file && field.relation_target === kernel.file) return "attachment";
@@ -231,6 +233,14 @@ function fieldKindFor(field, kernel) {
231
233
  }
232
234
  }
233
235
  var UUID_TEXT = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
236
+ function isEntityReferenceConfig(config) {
237
+ const allowed = config?.["allowed_types"];
238
+ return Array.isArray(allowed) && allowed.length > 0;
239
+ }
240
+ function entityReferenceKindsOf(field) {
241
+ const allowed = field.config?.["allowed_types"];
242
+ return Array.isArray(allowed) ? allowed.map((k) => String(k).trim().toLowerCase()).filter(Boolean) : [];
243
+ }
234
244
  var TRUE_WORDS = /* @__PURE__ */ new Set(["true", "yes", "y", "1", "\u2713", "x", "checked", "on"]);
235
245
  var FALSE_WORDS = /* @__PURE__ */ new Set(["false", "no", "n", "0", "", "unchecked", "off"]);
236
246
  function coercionLabel(field) {
@@ -346,6 +356,23 @@ function coerceTypedAnswer(field, raw, opts = {}) {
346
356
  return {
347
357
  refusal: `${label} points at another record, so it is chosen rather than typed. Open it and pick the record.`
348
358
  };
359
+ // SC-R / P12. An entity reference names a platform thing by kind and id.
360
+ // An import or an agent may hand over `note:<id>` — or a bare id when the
361
+ // column allows exactly one kind; the store then decides whether the thing
362
+ // is there and whether the writer may open it. Words are chosen, not typed.
363
+ case "entity_reference": {
364
+ const allowed = entityReferenceKindsOf(field);
365
+ const [maybeToken, maybeId] = text.includes(":") ? text.split(/:(.*)/s, 2) : ["", text];
366
+ const token = (maybeToken ?? "").trim().toLowerCase() || (allowed.length === 1 ? allowed[0] : "");
367
+ const id = (maybeId ?? "").trim();
368
+ if (token && UUID_TEXT.test(id)) {
369
+ const ref = { token, id: id.toLowerCase() };
370
+ return { value: field.multi ? [ref] : ref };
371
+ }
372
+ return {
373
+ refusal: `${label} points at something on the platform, so it is chosen rather than typed. Open it and pick it.`
374
+ };
375
+ }
349
376
  case "formula":
350
377
  case "lookup":
351
378
  case "rollup":
@@ -402,6 +429,10 @@ function publicFormPath(formId) {
402
429
  }
403
430
 
404
431
  // src/portal.ts
432
+ var PORTAL_ACCENTS = ["slate", "green", "amber", "red", "blue", "violet", "teal"];
433
+ function isPortalAccent(word) {
434
+ return typeof word === "string" && PORTAL_ACCENTS.includes(word);
435
+ }
405
436
  function portalPath(slug) {
406
437
  return `/portal/c/${slug}`;
407
438
  }
@@ -425,11 +456,17 @@ function emptyPortalArchiveLine() {
425
456
  }
426
457
 
427
458
  // src/aggregate.ts
459
+ function isRuleFilter(filter) {
460
+ if (!filter || typeof filter !== "object" || Array.isArray(filter)) return false;
461
+ const node = filter;
462
+ return typeof node.op === "string" && Array.isArray(node.args);
463
+ }
428
464
  function measureKey(measure) {
429
465
  return measure.op === "count" ? "count" : `${measure.op}_${measure.key ?? ""}`;
430
466
  }
431
467
  function stableFilterKey(filter) {
432
468
  if (!filter) return "{}";
469
+ if (isRuleFilter(filter)) return JSON.stringify(filter);
433
470
  const keys = Object.keys(filter).sort();
434
471
  if (keys.length === 0) return "{}";
435
472
  const parts = keys.map((key) => {
@@ -525,6 +562,161 @@ function recordChangeTrigger(tableId, options = {}) {
525
562
  ...options.changedFields && options.changedFields.length > 0 ? { changed_fields: options.changedFields } : {}
526
563
  };
527
564
  }
565
+ function sheetSyncSpec(args) {
566
+ const [header = [], ...body] = args.cells;
567
+ const columns = header.map((c, i) => {
568
+ const name = c == null ? "" : String(c).trim();
569
+ return name === "" ? `Column ${i + 1}` : name;
570
+ });
571
+ if (columns.length === 0) {
572
+ throw new Error("The sheet has no header row, so there are no columns to sync. Nothing was sent.");
573
+ }
574
+ const seenCol = /* @__PURE__ */ new Set();
575
+ for (const c of columns) {
576
+ if (seenCol.has(c)) throw new Error(`The sheet has two columns named "${c}". Rename one and sync again.`);
577
+ seenCol.add(c);
578
+ }
579
+ const refIdx = args.refColumn == null ? -1 : columns.indexOf(args.refColumn);
580
+ if (args.refColumn != null && refIdx < 0) {
581
+ throw new Error(`The id column "${args.refColumn}" is not in the sheet's header. Nothing was sent.`);
582
+ }
583
+ const seen = /* @__PURE__ */ new Set();
584
+ const rows = [];
585
+ body.forEach((cells, i) => {
586
+ if (cells.every((v) => v == null || String(v).trim() === "")) return;
587
+ const ref = refIdx >= 0 ? String(cells[refIdx] ?? "").trim() : `row-${i + 2}`;
588
+ if (ref === "") throw new Error(`Sheet row ${i + 2} has no value in the id column "${args.refColumn}".`);
589
+ if (seen.has(ref)) throw new Error(`Two sheet rows share the id "${ref}"; each row needs its own.`);
590
+ seen.add(ref);
591
+ const values = {};
592
+ columns.forEach((c, j) => {
593
+ const v = cells[j];
594
+ values[c] = v === void 0 || v === "" ? null : v;
595
+ });
596
+ rows.push({ ref, values });
597
+ });
598
+ return { source: args.source, table_name: args.tableName, columns, rows };
599
+ }
600
+ function withRowCounts(tables, counts) {
601
+ if (!counts) return [...tables];
602
+ const byId = new Map(counts.map((c) => [c.table_id, Number(c.visible_rows)]));
603
+ return tables.map((t) => byId.has(t.id) ? { ...t, row_count: byId.get(t.id) } : t);
604
+ }
605
+ function moveInOrder(order, moved, toIndex) {
606
+ const rest = order.filter((id) => id !== moved);
607
+ const at = Math.max(0, Math.min(Math.trunc(toIndex), rest.length));
608
+ return [...rest.slice(0, at), moved, ...rest.slice(at)];
609
+ }
610
+
611
+ // src/placement.ts
612
+ function keptOutOfSight(placement) {
613
+ return placement?.kept_by_the_app === true;
614
+ }
615
+ function offeredAsContext(placement) {
616
+ return placement?.offered_as_context === true;
617
+ }
618
+ function withTablePlacement(tables, facts) {
619
+ if (!facts) return [...tables];
620
+ const byId = new Map(facts.map((f) => [f.table_id, f]));
621
+ return tables.map((table) => {
622
+ const fact = byId.get(table.id);
623
+ if (!fact || fact.kept_by_the_app === void 0) return table;
624
+ return {
625
+ ...table,
626
+ kept_by_the_app: fact.kept_by_the_app,
627
+ kept_for: fact.kept_for ?? null,
628
+ offered_as_context: fact.offered_as_context ?? false,
629
+ keeper_group: fact.keeper_group ?? null,
630
+ keeper_says: fact.keeper_says ?? null,
631
+ used_in_kind: fact.used_in_kind ?? null,
632
+ used_in_id: fact.used_in_id ?? null,
633
+ used_in_table_id: fact.used_in_table_id ?? null
634
+ };
635
+ });
636
+ }
637
+ function keptGroups(tables) {
638
+ const out = [];
639
+ const at = /* @__PURE__ */ new Map();
640
+ for (const table of tables) {
641
+ if (!keptOutOfSight(table)) continue;
642
+ const group = table.keeper_group?.trim() || "Kept by the app";
643
+ let i = at.get(group);
644
+ if (i === void 0) {
645
+ i = out.length;
646
+ at.set(group, i);
647
+ out.push({ group, tables: [] });
648
+ }
649
+ out[i].tables.push(table);
650
+ }
651
+ return out;
652
+ }
653
+ function keptTableHref(fact, hrefs) {
654
+ if (fact.used_in_kind === "scope" && fact.used_in_id) return hrefs.scope(fact.used_in_id);
655
+ if (fact.used_in_kind === "table" && (fact.used_in_table_id || fact.used_in_id)) {
656
+ return hrefs.table(fact.used_in_table_id || fact.used_in_id);
657
+ }
658
+ return hrefs.table(fact.table_id);
659
+ }
660
+ function countOf(value) {
661
+ return typeof value === "number" && Number.isFinite(value) ? value : 0;
662
+ }
663
+ function wordsOf(value) {
664
+ return typeof value === "string" && value.length > 0 ? value : null;
665
+ }
666
+ function parseTableHome(raw) {
667
+ if (!raw || typeof raw !== "object") return null;
668
+ const row = raw;
669
+ const table = row.table;
670
+ const org = row.organization;
671
+ if (!table || !org || !wordsOf(table.id) || !wordsOf(org.id) || !wordsOf(org.name)) return null;
672
+ const carries = row.carries ?? {};
673
+ const destinations = Array.isArray(row.destinations) ? row.destinations : [];
674
+ return {
675
+ table: { id: String(table.id), name: wordsOf(table.name) ?? "This table", version: countOf(table.version) },
676
+ organization: { id: String(org.id), name: String(org.name) },
677
+ mayMove: row.may_move === true,
678
+ whyNot: wordsOf(row.why_not),
679
+ heldBy: Array.isArray(row.held_by) ? row.held_by.filter((s) => typeof s === "string") : [],
680
+ destinations: destinations.filter((d) => !!d && typeof d === "object" && !!wordsOf(d.id)).map((d) => ({
681
+ id: String(d.id),
682
+ name: wordsOf(d.name) ?? "An organization",
683
+ role: wordsOf(d.role) ?? "member",
684
+ ok: d.ok === true,
685
+ why: wordsOf(d.why)
686
+ })),
687
+ carries: {
688
+ fields: countOf(carries.fields),
689
+ records: countOf(carries.records),
690
+ inTrash: countOf(carries.in_trash),
691
+ choiceLists: countOf(carries.choice_lists),
692
+ withIt: countOf(carries.with_it),
693
+ tablesInside: countOf(carries.tables_inside),
694
+ linksAcross: countOf(carries.links_across)
695
+ }
696
+ };
697
+ }
698
+ function parseTableMoved(raw) {
699
+ const row = raw ?? {};
700
+ const to = row.to ?? {};
701
+ const from = row.from ?? {};
702
+ const table = row.table ?? {};
703
+ if (row.moved !== true || !wordsOf(to.id)) return null;
704
+ return {
705
+ to: { id: String(to.id), name: wordsOf(to.name) ?? "the new organization" },
706
+ from: { id: wordsOf(from.id) ?? "", name: wordsOf(from.name) ?? "its old organization" },
707
+ tableName: wordsOf(table.name) ?? "The table"
708
+ };
709
+ }
710
+ function plural(n, one, many) {
711
+ return `${n} ${n === 1 ? one : many}`;
712
+ }
713
+ function moveConsequence(home, to) {
714
+ const c = home.carries;
715
+ const parts = [plural(c.fields, "column", "columns"), plural(c.records, "row", "rows")];
716
+ if (c.inTrash > 0) parts.push(`${c.inTrash} in the trash`);
717
+ const extra = c.choiceLists + c.withIt;
718
+ return `${home.table.name} moves to ${to.name} with its ${parts.join(", ")}` + (c.tablesInside > 0 ? `, the ${plural(c.tablesInside, "table", "tables")} that live${c.tablesInside === 1 ? "s" : ""} inside it or its rows (with their own rows)` : "") + (extra > 0 ? `, and ${plural(extra, "thing", "things")} built only on it (choice lists, rules, dashboards, templates)` : "") + `, its comments, forms, saved views and history. ` + (c.linksAcross > 0 ? `${plural(c.linksAcross, "link", "links")} to rows that stay in ${home.organization.name} keep${c.linksAcross === 1 ? "s" : ""} pointing there, across the two organizations. ` : "") + `People who see it only because they are in ${home.organization.name} stop seeing it; people it was shared with by name keep it. You can move it back from the same place.`;
719
+ }
528
720
 
529
721
  // src/capture-queue.ts
530
722
  var DB_NAME = "matrx-capture";
@@ -594,7 +786,7 @@ function memoryStore() {
594
786
  setMeta: async (key, value) => void meta.set(key, value)
595
787
  };
596
788
  }
597
- function countOf(items) {
789
+ function countOf2(items) {
598
790
  const c = { waiting: 0, sending: 0, refused: 0, landed: 0 };
599
791
  for (const i of items) c[i.state] += 1;
600
792
  return c;
@@ -611,7 +803,7 @@ function openCaptureQueue(opts) {
611
803
  const announce = async () => {
612
804
  if (!opts.onChange) return;
613
805
  const items = await store.all();
614
- opts.onChange(countOf(items), items);
806
+ opts.onChange(countOf2(items), items);
615
807
  };
616
808
  const oldestFirst = (items) => items.slice().sort((a, b) => a.captured_at.localeCompare(b.captured_at));
617
809
  const queue = {
@@ -640,7 +832,7 @@ function openCaptureQueue(opts) {
640
832
  return key;
641
833
  },
642
834
  list: () => store.all().then(oldestFirst),
643
- counts: () => store.all().then(countOf),
835
+ counts: () => store.all().then(countOf2),
644
836
  async sync() {
645
837
  if (syncing) return syncing;
646
838
  syncing = (async () => {
@@ -812,6 +1004,182 @@ function isRecordsErr(result) {
812
1004
  var ok = (data) => ({ ok: true, data });
813
1005
  var err = (error) => ({ ok: false, error });
814
1006
 
1007
+ // src/core/pgError.ts
1008
+ var BY_SQLSTATE = {
1009
+ PT409: "stale_write",
1010
+ "42501": "door",
1011
+ "23514": "refused_by_rule",
1012
+ "22004": "invalid_argument",
1013
+ "22023": "invalid_argument",
1014
+ // 22P02 — a value does not fit the type the store holds for it. The class is
1015
+ // real and was hit live: an organization whose copy of a package table grew
1016
+ // `status` as a uuid-valued Field was sent the text "open", and the store
1017
+ // answered `invalid input syntax for type uuid: "open"`. It is the CALL that
1018
+ // is wrong for the shape the store holds, which is what `invalid_argument`
1019
+ // already means — the store's own sentence names the value and the type.
1020
+ "22P02": "invalid_argument",
1021
+ // 42703 — a column that is not there. The store raises it from
1022
+ // `custom.entity_table`, which is asked for a column by NAME, so the class is
1023
+ // exactly "the call named something the shape does not have": the same thing
1024
+ // `invalid_argument` already means, and the store's own sentence names the
1025
+ // column. Added 2026-09-20 (lane FORMS) because the package's live-door suite
1026
+ // caught it raised by a door this package did not know about — which is the
1027
+ // suite working, and is why the map is a census rather than a guess.
1028
+ "42703": "invalid_argument",
1029
+ // 22007 — a date or a time the store could not read as one. It is raised by
1030
+ // `custom.dashboard_window_sql`, which is handed a window a caller wrote
1031
+ // ("last 30 days", a literal date), so the class is again "the call named
1032
+ // something the shape does not accept" and the store's own sentence names the
1033
+ // text it could not read. Added 2026-09-20 (lane SCREEN-BREAK) after the
1034
+ // live-door census caught it — the same way 42703 arrived, which is the
1035
+ // census working rather than a guess.
1036
+ "22007": "invalid_argument",
1037
+ // 22003 — a number the store could not hold at the size it was handed. It is
1038
+ // raised by `custom.context_resolve`, which is given a window or a depth a
1039
+ // caller wrote, so the class is the same one 22P02, 42703 and 22007 already
1040
+ // are: the CALL named a value the shape does not accept, and the store's own
1041
+ // sentence names the number and the range. Added 2026-09-20 (lane GRID-TWO)
1042
+ // when the live-door census caught the release gate red on it — which is the
1043
+ // census working, and the fourth time it has been the thing that found a new
1044
+ // refusal class rather than a person guessing one.
1045
+ "22003": "invalid_argument",
1046
+ "02000": "not_found",
1047
+ "23503": "missing_reference",
1048
+ "23505": "already_exists",
1049
+ "0A000": "not_supported",
1050
+ "53400": "store_limit",
1051
+ "22012": "store_limit",
1052
+ // 54001 — `custom.record_delete` stops a cascade that nests past sixty-four
1053
+ // levels of containment, because that is a loop somebody built rather than a
1054
+ // hierarchy, and saying so beats recursing until the server runs out of
1055
+ // stack. It is a LIMIT of the store, and the store's own sentence names what
1056
+ // to do about it, so it reads as one.
1057
+ "54001": "store_limit",
1058
+ // 54000 — the grid primitives' organization ceilings (GRID-PRIMITIVES, 2026-09-23):
1059
+ // `custom.action_run` on a selection past its knob, `custom.table_decorate` past the
1060
+ // rule count, `custom.table_from_example` past `custom/example_rows_max`,
1061
+ // `custom.table_webhook_declare` past `custom/table_webhooks_max`, and
1062
+ // `custom.hub_changed_by`. Each names its knob in the hint and writes nothing, so it
1063
+ // reads exactly like 54001: a limit of the store, in the store's own sentence.
1064
+ "54000": "store_limit",
1065
+ // VIS: `custom.has_visibility_at` refuses to answer from a snapshot older
1066
+ // than a write this reader has already seen, rather than returning something
1067
+ // they just lost access to. It is retryable on a fresher connection, which is
1068
+ // a different instruction from every other refusal here.
1069
+ "40001": "stale_read",
1070
+ // 57014 — the store cancelled the statement at its own timeout. Like
1071
+ // `stale_read` and unlike every other refusal here, the call was never
1072
+ // refused on its merits: the same call on a smaller page, or once the
1073
+ // organization's kernel is not being rewritten, can succeed. It gets its own
1074
+ // code so a screen can offer "try again" honestly instead of showing a
1075
+ // failure sentence the caller cannot act on.
1076
+ "57014": "timed_out",
1077
+ // PostgREST's own two: the store is not being SERVED, which is a different
1078
+ // thing from the store refusing. `custom` absent from `pgrst.db_schemas`, or
1079
+ // the grants not copied, land here.
1080
+ PGRST202: "store_not_served",
1081
+ PGRST205: "store_not_served",
1082
+ PGRST301: "door",
1083
+ // PT428 — NOT A FAILURE, and the release gate's live census is what found it
1084
+ // missing: the store raises it and this package answered `internal`, which is
1085
+ // the one classification that tells a screen nothing. A stage gate whose
1086
+ // `on_fail` is `require_approval` files the request and leaves the record
1087
+ // where it was; the transaction is rolled back to the pipeline's own block, so
1088
+ // "nothing was written" is a fact rather than a promise. Landed by lane
1089
+ // STAGE-RULES; mapped here by STAGE-RULES-2 the day after, when the census
1090
+ // caught it — the sixth time that census has been the thing that found a
1091
+ // refusal class rather than a person guessing one.
1092
+ PT428: "needs_approval"
1093
+ };
1094
+ var MAPPED_SQLSTATES = Object.keys(BY_SQLSTATE);
1095
+ function parseDetail(details) {
1096
+ if (!details) return void 0;
1097
+ const trimmed = details.trim();
1098
+ if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) return details;
1099
+ try {
1100
+ return JSON.parse(trimmed);
1101
+ } catch {
1102
+ return details;
1103
+ }
1104
+ }
1105
+ function isNotASqlstate(code) {
1106
+ if (!code) return true;
1107
+ return /^[0-9]{3}$/.test(code);
1108
+ }
1109
+ function mapPgError(error, where) {
1110
+ const raw = error.code ?? void 0;
1111
+ const sqlstate = raw && raw !== "" ? raw : void 0;
1112
+ const mapped = {
1113
+ code: "internal",
1114
+ message: error.message,
1115
+ ...error.hint ? { hint: error.hint } : {},
1116
+ ...sqlstate ? { sqlstate } : {}
1117
+ };
1118
+ if (isNotASqlstate(sqlstate)) {
1119
+ mapped.code = "unreachable";
1120
+ } else {
1121
+ mapped.code = BY_SQLSTATE[sqlstate] ?? "internal";
1122
+ }
1123
+ const detail = parseDetail(error.details);
1124
+ if (detail !== void 0) mapped.detail = detail;
1125
+ if (mapped.code === "internal") {
1126
+ mapped.unmapped = true;
1127
+ mapped.diagnostic = `@ai-matrx/records did not recognise SQLSTATE ${sqlstate ?? "(none)"} from ${where}; the store's own message is the thing to act on.`;
1128
+ } else if (mapped.code === "unreachable") {
1129
+ mapped.unmapped = true;
1130
+ mapped.diagnostic = `@ai-matrx/records never reached the store from ${where}: ${raw ? `the transport answered ${raw}` : "no response"} \u2014 ${error.message}`;
1131
+ mapped.message = "We could not reach your data.";
1132
+ delete mapped.hint;
1133
+ }
1134
+ return mapped;
1135
+ }
1136
+
1137
+ // src/relation.ts
1138
+ var ENTITY_REF_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
1139
+ function isRefLike(value) {
1140
+ return typeof value === "object" && value !== null && "token" in value && "id" in value;
1141
+ }
1142
+ function entityRefsOf(value) {
1143
+ const items = Array.isArray(value) ? value : value == null ? [] : [value];
1144
+ const out = [];
1145
+ for (const item of items) {
1146
+ if (!isRefLike(item)) continue;
1147
+ const token = String(item.token ?? "").trim().toLowerCase();
1148
+ const id = String(item.id ?? "").trim();
1149
+ if (!token || !ENTITY_REF_ID.test(id)) continue;
1150
+ const label = item.label;
1151
+ out.push({ token, id: id.toLowerCase(), label: typeof label === "string" ? label : null });
1152
+ }
1153
+ return out;
1154
+ }
1155
+ function entityRefsToWrite(value, multi) {
1156
+ const seen = /* @__PURE__ */ new Set();
1157
+ const refs = [];
1158
+ for (const ref of entityRefsOf(value)) {
1159
+ const k = `${ref.token}:${ref.id}`;
1160
+ if (seen.has(k)) continue;
1161
+ seen.add(k);
1162
+ refs.push({ token: ref.token, id: ref.id });
1163
+ }
1164
+ if (multi) return refs;
1165
+ return refs[0] ?? null;
1166
+ }
1167
+ async function entityReferenceKinds(source) {
1168
+ const { data, error } = await source.rpc("entity_reference_kinds", {}, { schema: "custom" });
1169
+ if (error) return err(mapPgError(error, "entityReferenceKinds"));
1170
+ return ok(Array.isArray(data) ? data : []);
1171
+ }
1172
+ async function entityReferenceWords(source, organizationId, refs) {
1173
+ if (refs.length === 0) return ok([]);
1174
+ const { data, error } = await source.rpc(
1175
+ "entity_reference_words",
1176
+ { p_organization_id: organizationId, p_refs: refs.map((r) => ({ token: r.token, id: r.id })) },
1177
+ { schema: "custom" }
1178
+ );
1179
+ if (error) return err(mapPgError(error, "entityReferenceWords"));
1180
+ return ok(entityRefsOf(data));
1181
+ }
1182
+
815
1183
  // src/ops.ts
816
1184
  var REMEMBER_MS = 3e4;
817
1185
  var REMEMBER_MAX = 500;
@@ -1525,6 +1893,7 @@ var STORE_DOORS = [
1525
1893
  { name: "table_work_kind", args: "p_organization_id uuid, p_table_id uuid", returns: "text", security: "invoker" },
1526
1894
  { name: "tables_at_home", args: "p_organization_id uuid, p_home_ids uuid[]", returns: "TABLE(table_id uuid, home_record_id uuid, kind text)", security: "definer" },
1527
1895
  { name: "tables_described_without_asking", args: "", returns: "TABLE(function_name text, identity_args text, why text)", security: "invoker" },
1896
+ { name: "tables_i_can_open", args: "", returns: "TABLE(table_id uuid, table_name text, organization_id uuid, organization_name text, member boolean, visibility text, updated_at timestamp with time zone)", security: "definer" },
1528
1897
  { name: "tables_shared_with_me", args: "", returns: "TABLE(table_id uuid, organization_id uuid, organization text, table_name text, level text, level_label text, shared_at timestamp with time zone, opens boolean, say text)", security: "definer" },
1529
1898
  { name: "trg_associations_bump_visibility", args: "", returns: "trigger", security: "definer" },
1530
1899
  { name: "undeclared_keys", args: "p_organization_id uuid, p_table_id uuid, p_data jsonb", returns: "text[]", security: "invoker" },
@@ -1549,6 +1918,7 @@ var STORE_DOORS = [
1549
1918
  { name: "visible_predicate_sql", args: "p_user uuid, p_organization_id uuid, p_table_id uuid, p_required permission_level DEFAULT 'viewer'::permission_level, p_alias text DEFAULT 'r'::text", returns: "text", security: "definer" },
1550
1919
  { name: "visible_record_ids", args: "p_user_id uuid, p_required permission_level DEFAULT 'viewer'::permission_level", returns: "TABLE(id uuid)", security: "definer" },
1551
1920
  { name: "visible_set", args: "p_user uuid, p_organization_id uuid, p_table_id uuid, p_required permission_level DEFAULT 'viewer'::permission_level, OUT o_all_visible boolean, OUT o_true_visibility platform.visibility[], OUT o_granted_all uuid[], OUT o_granted_visible uuid[], OUT o_carried_visible uuid[], OUT o_ladder_calls integer, OUT o_fallback boolean, OUT o_note text", returns: "record", security: "definer" },
1921
+ { name: "where_id_opens", args: "p_id uuid", returns: "jsonb", security: "definer" },
1552
1922
  { name: "widget_kernel_id", args: "", returns: "uuid", security: "invoker" },
1553
1923
  { name: "withheld_marker", args: "p_mask jsonb, p_key text", returns: "jsonb", security: "invoker" },
1554
1924
  { name: "withheld_sentence", args: "p_mask jsonb, p_key text", returns: "text", security: "invoker" },
@@ -1655,7 +2025,7 @@ var STORE_REFUSAL_CODES = [
1655
2025
  { code: "23505", raised_by: "_share_write_person,_unique_rule_holds,doc_sign,doc_signature_write,entity_field_declare,field_declare,home_add,inbound_declare,io_proposal_accept,relation_carry,relation_own,sign_request_cancel,sign_request_create,table_share_outside_resend,work_approval_decide,work_slot_hold" },
1656
2026
  { code: "23514", raised_by: "_checklist_instantiate,_checklist_step_guard,_containment_guard,_dated_values_guard,_derived_fields,_display_format_check,_display_spec_for,_entity_custom_fields_guard,_field_class_guard,_field_document_for,_field_shape_guard,_field_type_parity_guard,_merge_field_shape_guard,_merge_field_temporal_guard,_promoted_field_cap_guard,_record_rule_uses,_relation_halves_agree,_relation_kernel_targets,_resolve_choice_words,_rule_shape_guard,_rule_topology_guard,_store_relation_edge_names_its_field,_table_columns_word_guard,_table_shape_guard,_undeclared_key_guard,_value_envelope,_with_display,_work_shape_guard,_workdoors_approval_guard,action_run,assert_columns_are_defined,assert_entity_is_organization_scoped,booking_declare,capture_publish,capture_sheet_declare,checklist_declare,checklist_step_complete,doc_sign,doc_signature_write,doc_template_save,entity_field_declare,entity_field_retire,entity_field_update,entity_records_find,entity_table,field_declare,field_retire,field_update,home_add,io_comment_write,io_import_rows,migrate_merge,migrate_purge_hard,portal_archive,portal_restore,record_write_graph,relation_carry,relation_halves_repair,relation_own,sign_request_create,sign_request_sign,table_declare,table_from_example,validate_value_envelope,validate_values,work_set_state,work_slots_declare,work_take_assignment,work_template_instantiate" },
1657
2027
  { code: "40001", raised_by: "has_visibility_at" },
1658
- { code: "42501", raised_by: "_doc_render_immutable,_doc_signature_immutable,_field_definition_write,_field_write_door,_rule_definition_write,_store_door,agent_table_claim,anon_capture,anon_inbound_land,anon_publish,anon_token_issue,anon_token_verify,anon_write,assert_client_may_change,assert_client_may_open,assert_client_may_reach,assert_may_know_table,assert_organization_admin,assert_store_door,booking_confirm,booking_declare,booking_hold,capture_submit,checklist_run,comment_write,conversation_scope_bind,conversation_scope_unbind,doc_sign,enrich_declare,enrich_due,enrich_land,enrich_normalize,entity_field_declare,entity_field_retire,entity_field_update,entity_value_write,external_write_through,form_declare,form_submit,inbound_mail_land,io_comment_resolve,io_comment_write,io_import_begin,io_import_finish,io_restore,migrate_purge,migrate_purge_hard,migrate_purge_hard_request,migrate_reclass,my_levels,organization_clear,portal_declare,portal_invitation,portal_invite,portal_invite_accept,portal_principal_bind,promote_table,query_visibility_parity,read_record,read_records,read_records_archived,read_records_by_ids,read_records_matching,record_table,record_write_graph,relation_halves_disagreements,relation_halves_repair,share_grant,subscription_mute,subscription_preview,table_share_outside_accept,table_share_outside_invite,table_share_outside_resend,table_webhook_declare,visibility_as_of,work_approval_decide,work_approval_read,work_approval_request,work_person" },
2028
+ { code: "42501", raised_by: "_doc_render_immutable,_doc_signature_immutable,_field_definition_write,_field_write_door,_rule_definition_write,_store_door,agent_table_claim,anon_capture,anon_inbound_land,anon_publish,anon_token_issue,anon_token_verify,anon_write,assert_client_may_change,assert_client_may_open,assert_client_may_reach,assert_may_know_table,assert_organization_admin,assert_store_door,booking_confirm,booking_declare,booking_hold,capture_submit,checklist_run,comment_write,conversation_scope_bind,conversation_scope_unbind,doc_sign,enrich_declare,enrich_due,enrich_land,enrich_normalize,entity_field_declare,entity_field_retire,entity_field_update,entity_value_write,external_write_through,form_declare,form_submit,inbound_mail_land,io_comment_resolve,io_comment_write,io_import_begin,io_import_finish,io_restore,migrate_purge,migrate_purge_hard,migrate_purge_hard_request,migrate_reclass,my_levels,organization_clear,organization_contents,portal_declare,portal_invitation,portal_invite,portal_invite_accept,portal_principal_bind,promote_table,query_visibility_parity,read_record,read_records,read_records_archived,read_records_by_ids,read_records_matching,record_table,record_write_graph,relation_halves_disagreements,relation_halves_repair,share_grant,subscription_mute,subscription_preview,table_share_outside_accept,table_share_outside_invite,table_share_outside_resend,table_webhook_declare,visibility_as_of,work_approval_decide,work_approval_read,work_approval_request,work_person" },
1659
2029
  { code: "42703", raised_by: "entity_table,portal_declare" },
1660
2030
  { code: "53400", raised_by: "anon_rate_take,delete_cascade_closure,enrich_due,enrich_land,promote_field" },
1661
2031
  { code: "54000", raised_by: "action_run,hub_changed_by,table_decorate,table_from_example,table_webhook_declare" },
@@ -2724,6 +3094,7 @@ export {
2724
3094
  PERMISSION_LEVELS,
2725
3095
  PER_VALUE_ACCESS_WORDS,
2726
3096
  PIPELINE_RULE_KINDS,
3097
+ PORTAL_ACCENTS,
2727
3098
  PORTAL_ARCHIVE_FILTERS,
2728
3099
  REFUSALS_WORTH_REPEATING,
2729
3100
  RELATION_BINDINGS,
@@ -2758,6 +3129,11 @@ export {
2758
3129
  coercionLabel,
2759
3130
  emptyArchiveLine,
2760
3131
  emptyPortalArchiveLine,
3132
+ entityReferenceKinds,
3133
+ entityReferenceKindsOf,
3134
+ entityReferenceWords,
3135
+ entityRefsOf,
3136
+ entityRefsToWrite,
2761
3137
  err,
2762
3138
  exampleSpec,
2763
3139
  exportPageXlsx,
@@ -2768,20 +3144,31 @@ export {
2768
3144
  indexedDbStore,
2769
3145
  isArchiveLane,
2770
3146
  isDecided,
3147
+ isEntityReferenceConfig,
2771
3148
  isOwnOp,
3149
+ isPortalAccent,
2772
3150
  isPortalArchiveFilter,
2773
3151
  isRecordsErr,
3152
+ isRuleFilter,
2774
3153
  isTheChosen,
3154
+ keptGroups,
3155
+ keptOutOfSight,
3156
+ keptTableHref,
2775
3157
  looksLikeAnId,
2776
3158
  mayDrag,
2777
3159
  measureKey,
2778
3160
  memoryStore,
2779
3161
  mintClientKey,
2780
3162
  mintOpId,
3163
+ moveConsequence,
3164
+ moveInOrder,
3165
+ offeredAsContext,
2781
3166
  ok,
2782
3167
  openCaptureQueue,
2783
3168
  optionKey,
2784
3169
  optionLabel,
3170
+ parseTableHome,
3171
+ parseTableMoved,
2785
3172
  portalArchiveConsequence,
2786
3173
  portalConfirmLine,
2787
3174
  portalPath,
@@ -2791,6 +3178,9 @@ export {
2791
3178
  rememberedOpCount,
2792
3179
  sameDocument,
2793
3180
  scopeChip,
2794
- stableFilterKey
3181
+ sheetSyncSpec,
3182
+ stableFilterKey,
3183
+ withRowCounts,
3184
+ withTablePlacement
2795
3185
  };
2796
3186
  //# sourceMappingURL=index.js.map