@ai-matrx/records 0.96.13 → 0.97.0
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 +21 -0
- package/dist/{client-D7bvxEZW.d.ts → client-MVuEbxKl.d.ts} +6 -0
- package/dist/{client-DKgbZUNt.d.cts → client-pFV_8AhM.d.cts} +6 -0
- package/dist/core/index.cjs +637 -3
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +3 -2
- package/dist/core/index.d.ts +3 -2
- package/dist/core/index.js +637 -3
- package/dist/core/index.js.map +1 -1
- package/dist/data/index.cjs +634 -0
- package/dist/data/index.cjs.map +1 -1
- package/dist/data/index.d.cts +2 -1
- package/dist/data/index.d.ts +2 -1
- package/dist/data/index.js +634 -0
- package/dist/data/index.js.map +1 -1
- package/dist/{declareTable-VoNRi_j_.d.cts → declareTable-Bekj6UwK.d.cts} +1 -1
- package/dist/{declareTable-D_CiMnXM.d.ts → declareTable-C7zVyyLA.d.ts} +1 -1
- package/dist/doors-C43_5HjC.d.ts +487 -0
- package/dist/doors-CJPHsohF.d.cts +487 -0
- package/dist/questions/index.d.cts +2 -1
- package/dist/questions/index.d.ts +2 -1
- package/dist/react/index.cjs +637 -3
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +338 -5
- package/dist/react/index.d.ts +338 -5
- package/dist/react/index.js +637 -3
- package/dist/react/index.js.map +1 -1
- package/dist/scopes/index.cjs +729 -0
- package/dist/scopes/index.cjs.map +1 -0
- package/dist/scopes/index.d.cts +33 -0
- package/dist/scopes/index.d.ts +33 -0
- package/dist/scopes/index.js +706 -0
- package/dist/scopes/index.js.map +1 -0
- package/dist/setup/index.cjs +634 -0
- package/dist/setup/index.cjs.map +1 -1
- package/dist/setup/index.d.cts +2 -1
- package/dist/setup/index.d.ts +2 -1
- package/dist/setup/index.js +634 -0
- package/dist/setup/index.js.map +1 -1
- package/dist/typed-table/index.cjs +634 -0
- package/dist/typed-table/index.cjs.map +1 -1
- package/dist/typed-table/index.d.cts +3 -2
- package/dist/typed-table/index.d.ts +3 -2
- package/dist/typed-table/index.js +634 -0
- package/dist/typed-table/index.js.map +1 -1
- package/dist/views/index.d.cts +2 -1
- package/dist/views/index.d.ts +2 -1
- package/package.json +14 -4
package/dist/data/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { C as Column, Q as Query, A as AliasBinding, H as HostDataPort } from '../types-Dxc8Pt7Y.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-Dxc8Pt7Y.cjs';
|
|
3
|
-
import { R as RecordsClient } from '../client-
|
|
3
|
+
import { R as RecordsClient } from '../client-pFV_8AhM.cjs';
|
|
4
4
|
import { F as Field } from '../field-DjS7iId2.cjs';
|
|
5
5
|
import { U as Uuid, R as RecordsResult, r as RecordPageSort, q as ReadRow } from '../record-zwSBU5PQ.cjs';
|
|
6
6
|
import { R as RuleExpression } from '../rule-CbBXN-FW.cjs';
|
|
@@ -8,6 +8,7 @@ import '../relation-BbPDcXp5.cjs';
|
|
|
8
8
|
import '../ports-DEkN-WfA.cjs';
|
|
9
9
|
import '../table-kind-CMXvN5Kb.cjs';
|
|
10
10
|
import '../subscription-ycCVo9e2.cjs';
|
|
11
|
+
import '../doors-CJPHsohF.cjs';
|
|
11
12
|
import '../portal-CUwIsXsx.cjs';
|
|
12
13
|
|
|
13
14
|
interface TableShape {
|
package/dist/data/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { C as Column, Q as Query, A as AliasBinding, H as HostDataPort } from '../types-Du4Q9Rvi.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-Du4Q9Rvi.js';
|
|
3
|
-
import { R as RecordsClient } from '../client-
|
|
3
|
+
import { R as RecordsClient } from '../client-MVuEbxKl.js';
|
|
4
4
|
import { F as Field } from '../field-D-1OKy5r.js';
|
|
5
5
|
import { U as Uuid, R as RecordsResult, r as RecordPageSort, q as ReadRow } from '../record-zwSBU5PQ.js';
|
|
6
6
|
import { R as RuleExpression } from '../rule-BVX1C83I.js';
|
|
@@ -8,6 +8,7 @@ import '../relation-Dk9-VzY0.js';
|
|
|
8
8
|
import '../ports-YOhD5T7h.js';
|
|
9
9
|
import '../table-kind-CjTL6PyT.js';
|
|
10
10
|
import '../subscription-DucBLG-Y.js';
|
|
11
|
+
import '../doors-C43_5HjC.js';
|
|
11
12
|
import '../portal-DDOmQR1f.js';
|
|
12
13
|
|
|
13
14
|
interface TableShape {
|
package/dist/data/index.js
CHANGED
|
@@ -622,6 +622,639 @@ function ledgerOver(ours) {
|
|
|
622
622
|
}
|
|
623
623
|
var defaultOpLedger = ledgerOver(globalSlot2("ai-matrx.records.op-ledger", () => /* @__PURE__ */ new Map()));
|
|
624
624
|
|
|
625
|
+
// src/scopes/codec.ts
|
|
626
|
+
var str = (v, fallback = "") => typeof v === "string" ? v : fallback;
|
|
627
|
+
var strOrNull = (v) => typeof v === "string" ? v : null;
|
|
628
|
+
var num = (v, fallback = 0) => {
|
|
629
|
+
const n = typeof v === "number" ? v : typeof v === "string" ? Number(v) : NaN;
|
|
630
|
+
return Number.isFinite(n) ? n : fallback;
|
|
631
|
+
};
|
|
632
|
+
function scopeTypeFromStore(row) {
|
|
633
|
+
const singular = row.label_singular ?? row.name ?? "";
|
|
634
|
+
return {
|
|
635
|
+
id: row.id,
|
|
636
|
+
organization_id: row.organization_id,
|
|
637
|
+
label_singular: singular,
|
|
638
|
+
label_plural: row.label_plural ?? singular,
|
|
639
|
+
icon: row.icon ?? "folder",
|
|
640
|
+
color: row.color ?? "",
|
|
641
|
+
slug: row.slug ?? null,
|
|
642
|
+
description: row.description ?? "",
|
|
643
|
+
sort_order: num(row.sort_order),
|
|
644
|
+
max_assignments_per_entity: row.max_assignments_per_entity ?? null,
|
|
645
|
+
default_variable_keys: Array.isArray(row.default_variable_keys) ? row.default_variable_keys : [],
|
|
646
|
+
created_by: row.created_by ?? null,
|
|
647
|
+
created_at: row.created_at ?? "",
|
|
648
|
+
updated_at: row.updated_at ?? ""
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
function scopeTypeLabelFromStore(t) {
|
|
652
|
+
const singular = t.label_singular ?? t.name ?? "";
|
|
653
|
+
return { id: t.id, label_singular: singular, label_plural: t.label_plural ?? singular, icon: t.icon ?? null, color: t.color ?? null };
|
|
654
|
+
}
|
|
655
|
+
function settingFromStore(value) {
|
|
656
|
+
if (!Array.isArray(value)) return value;
|
|
657
|
+
return value.map((el) => {
|
|
658
|
+
if (typeof el !== "string") return el;
|
|
659
|
+
const t = el.trim();
|
|
660
|
+
if (!(t.startsWith("{") && t.endsWith("}")) && !(t.startsWith("[") && t.endsWith("]"))) return el;
|
|
661
|
+
try {
|
|
662
|
+
return JSON.parse(t);
|
|
663
|
+
} catch {
|
|
664
|
+
return el;
|
|
665
|
+
}
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
function scopeFromStore(row) {
|
|
669
|
+
const settings = {};
|
|
670
|
+
for (const [k, v] of Object.entries(row.settings ?? {})) settings[k] = settingFromStore(v);
|
|
671
|
+
return {
|
|
672
|
+
id: row.id,
|
|
673
|
+
scope_type_id: row.scope_type_id,
|
|
674
|
+
organization_id: row.organization_id,
|
|
675
|
+
name: row.name ?? "",
|
|
676
|
+
description: row.description ?? "",
|
|
677
|
+
slug: row.slug ?? null,
|
|
678
|
+
sort_order: num(row.sort_order),
|
|
679
|
+
parent_scope_id: row.parent_scope_id ?? null,
|
|
680
|
+
settings,
|
|
681
|
+
created_by: row.created_by ?? null,
|
|
682
|
+
created_at: row.created_at ?? "",
|
|
683
|
+
updated_at: row.updated_at ?? ""
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
function scopeWithTypeFromStore(row) {
|
|
687
|
+
return { ...scopeFromStore(row), scope_type: row.scope_type ? scopeTypeLabelFromStore(row.scope_type) : null };
|
|
688
|
+
}
|
|
689
|
+
function archivedScopeTypeFromStore(row) {
|
|
690
|
+
const singular = row.label_singular ?? "";
|
|
691
|
+
return {
|
|
692
|
+
id: row.id,
|
|
693
|
+
organization_id: row.organization_id,
|
|
694
|
+
label_singular: singular,
|
|
695
|
+
label_plural: row.label_plural ?? singular,
|
|
696
|
+
icon: row.icon ?? "folder",
|
|
697
|
+
color: row.color ?? "",
|
|
698
|
+
archived_at: row.deleted_at ?? "",
|
|
699
|
+
created_by: row.created_by ?? null,
|
|
700
|
+
archived_scope_count: row.archived_scope_count ?? 0
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
var FILE_KERNEL_ID = "11111111-0000-4000-8000-000000000006";
|
|
704
|
+
var KINDS = /* @__PURE__ */ new Set([
|
|
705
|
+
"string",
|
|
706
|
+
"markdown",
|
|
707
|
+
"email",
|
|
708
|
+
"url",
|
|
709
|
+
"phone",
|
|
710
|
+
"color",
|
|
711
|
+
"number",
|
|
712
|
+
"percent",
|
|
713
|
+
"currency",
|
|
714
|
+
"boolean",
|
|
715
|
+
"date",
|
|
716
|
+
"datetime",
|
|
717
|
+
"time",
|
|
718
|
+
"object",
|
|
719
|
+
"array",
|
|
720
|
+
"reference",
|
|
721
|
+
"document"
|
|
722
|
+
]);
|
|
723
|
+
function contextFieldKind(doc, carried) {
|
|
724
|
+
if (carried?.as_text && carried.value_type && KINDS.has(carried.value_type)) return carried.value_type;
|
|
725
|
+
const behavior = String(doc.type ?? "text");
|
|
726
|
+
const fmt = doc.format ? String(doc.format) : "";
|
|
727
|
+
const shown = doc.display_format && typeof doc.display_format === "object" ? String(doc.display_format.id ?? "") : "";
|
|
728
|
+
const kind = String(doc.config?.kind ?? "");
|
|
729
|
+
const multi = Boolean(doc.multi);
|
|
730
|
+
if (behavior === "boolean") return "boolean";
|
|
731
|
+
if (behavior === "relation") return doc.relation_target === FILE_KERNEL_ID && !multi ? "document" : "reference";
|
|
732
|
+
if (behavior === "range") {
|
|
733
|
+
if (kind === "date") return "date";
|
|
734
|
+
if (kind === "datetime") return "datetime";
|
|
735
|
+
if (fmt === "percent" || fmt === "currency") return fmt;
|
|
736
|
+
return "number";
|
|
737
|
+
}
|
|
738
|
+
if (behavior === "text") {
|
|
739
|
+
if (multi) return "array";
|
|
740
|
+
if (fmt === "json") return "object";
|
|
741
|
+
for (const word of [fmt, shown]) {
|
|
742
|
+
if (word === "time" || word === "email" || word === "url" || word === "phone" || word === "color" || word === "markdown") return word;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
return "string";
|
|
746
|
+
}
|
|
747
|
+
var POLICIES = /* @__PURE__ */ new Set(["include", "on_request", "exclude"]);
|
|
748
|
+
var SENSITIVITIES = /* @__PURE__ */ new Set(["public", "internal", "confidential", "restricted"]);
|
|
749
|
+
function contextFieldFromStore(row) {
|
|
750
|
+
const d = row.data ?? {};
|
|
751
|
+
const key = str(d.key);
|
|
752
|
+
const policy = str(d.context_policy, "include");
|
|
753
|
+
const sensitivity = str(d.sensitivity, "internal");
|
|
754
|
+
return {
|
|
755
|
+
id: row.id,
|
|
756
|
+
scope_type_id: row.scope_type_id,
|
|
757
|
+
organization_id: row.organization_id,
|
|
758
|
+
key,
|
|
759
|
+
label: str(d.label, key),
|
|
760
|
+
description: str(d.description),
|
|
761
|
+
kind: contextFieldKind(d, row.carried),
|
|
762
|
+
type: str(d.type, "text"),
|
|
763
|
+
multi: Boolean(d.multi),
|
|
764
|
+
format: strOrNull(d.format),
|
|
765
|
+
config: d.config ?? {},
|
|
766
|
+
relation_target: strOrNull(d.relation_target),
|
|
767
|
+
// The store's sort counts the scope's own two columns first (custom._ctx_store_item: + 2).
|
|
768
|
+
sort: Math.max(0, num(d.sort) - 2),
|
|
769
|
+
context_policy: POLICIES.has(policy) ? policy : "include",
|
|
770
|
+
sensitivity: SENSITIVITIES.has(sensitivity) ? sensitivity : "internal",
|
|
771
|
+
source: str(d.source, "manual"),
|
|
772
|
+
status: str(d.status, "active"),
|
|
773
|
+
status_note: strOrNull(d.status_note),
|
|
774
|
+
category: strOrNull(d.category),
|
|
775
|
+
tags: Array.isArray(d.tags) ? d.tags : [],
|
|
776
|
+
max_items: typeof d.max_items === "number" ? d.max_items : 1,
|
|
777
|
+
custom_component: d.custom_component ?? null,
|
|
778
|
+
reference_source: d.reference_source ?? null,
|
|
779
|
+
allowed_scope_type_ids: Array.isArray(d.allowed_scope_type_ids) ? d.allowed_scope_type_ids : null,
|
|
780
|
+
allowed_reference_types: Array.isArray(d.allowed_reference_types) ? d.allowed_reference_types : null,
|
|
781
|
+
review_interval_days: typeof d.review_interval_days === "number" ? d.review_interval_days : null,
|
|
782
|
+
depends_on: Array.isArray(d.depends_on) ? d.depends_on : [],
|
|
783
|
+
version: num(row.version, 1),
|
|
784
|
+
created_by: row.created_by ?? null,
|
|
785
|
+
created_at: row.created_at ?? "",
|
|
786
|
+
updated_at: row.updated_at ?? ""
|
|
787
|
+
};
|
|
788
|
+
}
|
|
789
|
+
var POLICY_TO_DOOR = { include: "always", on_request: "on_demand", exclude: "never" };
|
|
790
|
+
var SENSITIVITY_TO_DOOR = {
|
|
791
|
+
public: "public",
|
|
792
|
+
internal: "internal",
|
|
793
|
+
confidential: "restricted",
|
|
794
|
+
restricted: "privileged"
|
|
795
|
+
};
|
|
796
|
+
var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
797
|
+
function referencesOf(row) {
|
|
798
|
+
const v = row.value;
|
|
799
|
+
const list = Array.isArray(v) ? v : v == null ? [] : [v];
|
|
800
|
+
const labels = row.labels ?? {};
|
|
801
|
+
const files = row.files ?? {};
|
|
802
|
+
const toFile = row.field?.relation_target === FILE_KERNEL_ID;
|
|
803
|
+
const out = [];
|
|
804
|
+
for (const el of list) {
|
|
805
|
+
let ref = null;
|
|
806
|
+
if (typeof el === "string" && UUID.test(el)) ref = { id: el, type: toFile ? "file" : "scope" };
|
|
807
|
+
else if (el && typeof el === "object" && typeof el.id === "string") {
|
|
808
|
+
const token = String(el.token ?? "");
|
|
809
|
+
const own = el.label;
|
|
810
|
+
ref = { id: el.id, type: token === "dataset" ? "table" : token || (toFile ? "file" : "scope") };
|
|
811
|
+
if (typeof own === "string" && own) ref.label = own;
|
|
812
|
+
}
|
|
813
|
+
if (!ref) continue;
|
|
814
|
+
const label = labels[ref.id];
|
|
815
|
+
if (label) ref.label = label;
|
|
816
|
+
const fileId = files[ref.id];
|
|
817
|
+
if (fileId) ref.file_id = fileId;
|
|
818
|
+
out.push(ref);
|
|
819
|
+
}
|
|
820
|
+
return out;
|
|
821
|
+
}
|
|
822
|
+
function contextValueFromStore(row) {
|
|
823
|
+
const kind = contextFieldKind(row.field ?? {}, row.field?.carried);
|
|
824
|
+
const carriedText = Boolean(row.field?.carried?.as_text);
|
|
825
|
+
const isRef = !carriedText && (kind === "reference" || kind === "document");
|
|
826
|
+
return {
|
|
827
|
+
scope_id: row.scope_id,
|
|
828
|
+
field_id: row.context_item_id,
|
|
829
|
+
key: row.key,
|
|
830
|
+
kind,
|
|
831
|
+
value: row.value ?? null,
|
|
832
|
+
references: isRef ? referencesOf(row) : [],
|
|
833
|
+
version: num(row.version, 1),
|
|
834
|
+
set_at: row.set_at ?? null,
|
|
835
|
+
source_type: row.source_type ?? null,
|
|
836
|
+
authored_by: row.authored_by ?? null,
|
|
837
|
+
whole_value: row.whole_value ?? null,
|
|
838
|
+
incomplete: null
|
|
839
|
+
};
|
|
840
|
+
}
|
|
841
|
+
async function sha256Hex(text) {
|
|
842
|
+
const subtle = globalThis.crypto?.subtle;
|
|
843
|
+
if (!subtle) return null;
|
|
844
|
+
const digest = await subtle.digest("SHA-256", new TextEncoder().encode(text));
|
|
845
|
+
return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, "0")).join("");
|
|
846
|
+
}
|
|
847
|
+
async function completeWholeValues(values, read) {
|
|
848
|
+
const texts = /* @__PURE__ */ new Map();
|
|
849
|
+
await Promise.all(
|
|
850
|
+
values.map(async (cell) => {
|
|
851
|
+
const w = cell.whole_value;
|
|
852
|
+
if (!w || w.in_value || typeof cell.value !== "string") return;
|
|
853
|
+
const head = cell.value;
|
|
854
|
+
const chars = typeof w.chars === "number" ? w.chars : null;
|
|
855
|
+
const incomplete = (fileId, why) => {
|
|
856
|
+
cell.incomplete = { head, chars, file_id: fileId, why };
|
|
857
|
+
};
|
|
858
|
+
if (!w.file_id) return incomplete(null, "The rest of this text is still being saved.");
|
|
859
|
+
if (!read) return incomplete(w.file_id, "This place cannot open the file that holds the whole text.");
|
|
860
|
+
if (!texts.has(w.file_id)) texts.set(w.file_id, read(w.file_id));
|
|
861
|
+
try {
|
|
862
|
+
const text = await texts.get(w.file_id);
|
|
863
|
+
if (chars !== null && [...text].length !== chars) {
|
|
864
|
+
return incomplete(w.file_id, `The file holds ${[...text].length} characters, not ${chars}.`);
|
|
865
|
+
}
|
|
866
|
+
if (w.sha256) {
|
|
867
|
+
const sha = await sha256Hex(text);
|
|
868
|
+
if (sha === null) return incomplete(w.file_id, "This browser cannot check the file.");
|
|
869
|
+
if (sha !== w.sha256) return incomplete(w.file_id, "The file's content is not the text the cell points at.");
|
|
870
|
+
}
|
|
871
|
+
cell.value = text;
|
|
872
|
+
} catch (thrown) {
|
|
873
|
+
incomplete(w.file_id, thrown instanceof Error ? thrown.message : String(thrown));
|
|
874
|
+
}
|
|
875
|
+
})
|
|
876
|
+
);
|
|
877
|
+
}
|
|
878
|
+
function definedOnly(fields) {
|
|
879
|
+
const out = {};
|
|
880
|
+
for (const [k, v] of Object.entries(fields)) if (v !== void 0) out[k] = v;
|
|
881
|
+
return out;
|
|
882
|
+
}
|
|
883
|
+
function fieldSpecForDoor(spec) {
|
|
884
|
+
return definedOnly({
|
|
885
|
+
key: spec.key,
|
|
886
|
+
display_name: spec.label,
|
|
887
|
+
value_type: spec.kind,
|
|
888
|
+
description: spec.description,
|
|
889
|
+
category: spec.category,
|
|
890
|
+
fetch_hint: spec.context_policy ? POLICY_TO_DOOR[spec.context_policy] : void 0,
|
|
891
|
+
sensitivity: spec.sensitivity ? SENSITIVITY_TO_DOOR[spec.sensitivity] : void 0,
|
|
892
|
+
tags: spec.tags,
|
|
893
|
+
sort_order: spec.sort,
|
|
894
|
+
status: spec.status,
|
|
895
|
+
status_note: spec.status_note,
|
|
896
|
+
custom_component: spec.custom_component,
|
|
897
|
+
review_interval_days: spec.review_interval_days,
|
|
898
|
+
allowed_reference_types: spec.allowed_reference_types,
|
|
899
|
+
max_items: spec.max_items,
|
|
900
|
+
allowed_scope_type_ids: spec.allowed_scope_type_ids,
|
|
901
|
+
reference_source: spec.reference_source
|
|
902
|
+
});
|
|
903
|
+
}
|
|
904
|
+
function referenceFence(references) {
|
|
905
|
+
const kinds = [...new Set(references.map((r) => r.type))];
|
|
906
|
+
const type = kinds.length === 1 ? kinds[0] : "mixed";
|
|
907
|
+
const items = references.map((r) => {
|
|
908
|
+
if (r.type === "file" && r.file_id) return r.label ? { file_id: r.file_id, label: r.label } : { file_id: r.file_id };
|
|
909
|
+
const item = { id: r.id };
|
|
910
|
+
if (r.label) item.label = r.label;
|
|
911
|
+
if (kinds.length > 1) item.type = r.type;
|
|
912
|
+
return item;
|
|
913
|
+
});
|
|
914
|
+
return "```matrx\n" + JSON.stringify({ matrx_version: 1, kind: "reference", type, items }, null, 2) + "\n```";
|
|
915
|
+
}
|
|
916
|
+
function valuePayloadForDoor(write) {
|
|
917
|
+
const base = definedOnly({
|
|
918
|
+
scope_id: write.scope_id,
|
|
919
|
+
context_item_id: write.field_id,
|
|
920
|
+
source_type: write.source_type,
|
|
921
|
+
change_summary: write.change_summary
|
|
922
|
+
});
|
|
923
|
+
const v = write.value;
|
|
924
|
+
if (write.kind === "reference" || write.kind === "document") {
|
|
925
|
+
if (write.references) return { ...base, value_text: write.references.length ? referenceFence(write.references) : null };
|
|
926
|
+
if (write.kind === "document" && typeof v === "string") return { ...base, value_document_url: v || null };
|
|
927
|
+
return { ...base, value_text: typeof v === "string" ? v || null : null };
|
|
928
|
+
}
|
|
929
|
+
if (v === null || v === void 0 || v === "") {
|
|
930
|
+
return { ...base, value_text: null };
|
|
931
|
+
}
|
|
932
|
+
switch (write.kind) {
|
|
933
|
+
case "number":
|
|
934
|
+
case "percent":
|
|
935
|
+
return typeof v === "number" ? { ...base, value_number: v } : { ...base, value_text: String(v) };
|
|
936
|
+
case "currency":
|
|
937
|
+
return typeof v === "object" ? { ...base, value_json: v } : typeof v === "number" ? { ...base, value_number: v } : { ...base, value_text: String(v) };
|
|
938
|
+
case "boolean":
|
|
939
|
+
return typeof v === "boolean" ? { ...base, value_boolean: v } : { ...base, value_text: String(v) };
|
|
940
|
+
case "date":
|
|
941
|
+
return { ...base, value_date: String(v) };
|
|
942
|
+
case "datetime":
|
|
943
|
+
return { ...base, value_timestamp: String(v) };
|
|
944
|
+
case "time":
|
|
945
|
+
return { ...base, value_time: String(v) };
|
|
946
|
+
case "object":
|
|
947
|
+
case "array":
|
|
948
|
+
return typeof v === "object" ? { ...base, value_json: v } : { ...base, value_text: String(v) };
|
|
949
|
+
default:
|
|
950
|
+
return typeof v === "object" ? { ...base, value_json: v } : { ...base, value_text: String(v) };
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
// src/scopes/rules.ts
|
|
955
|
+
function toSlug(name) {
|
|
956
|
+
return name.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
957
|
+
}
|
|
958
|
+
function isValidSlug(s) {
|
|
959
|
+
return /^[a-z0-9]+(?:[-_][a-z0-9]+)*$/.test(s);
|
|
960
|
+
}
|
|
961
|
+
var RESERVED_SCOPE_SLUGS = /* @__PURE__ */ new Set(["context-items", "scopes", "edit", "manage", "new", "settings"]);
|
|
962
|
+
function isReservedSlug(s) {
|
|
963
|
+
return RESERVED_SCOPE_SLUGS.has(s.toLowerCase().replace(/_/g, "-"));
|
|
964
|
+
}
|
|
965
|
+
function resolveSlug(supplied, fallbackName) {
|
|
966
|
+
const slug = supplied?.trim() || toSlug(fallbackName);
|
|
967
|
+
if (!slug || !isValidSlug(slug)) {
|
|
968
|
+
return {
|
|
969
|
+
ok: false,
|
|
970
|
+
error: { code: "invalid_argument", message: "Use letters, numbers and single hyphens for the short name." }
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
if (isReservedSlug(slug)) {
|
|
974
|
+
return { ok: false, error: { code: "invalid_argument", message: `"${slug}" is a page name here. Pick another short name.` } };
|
|
975
|
+
}
|
|
976
|
+
return { ok: true, data: slug };
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
// src/scopes/doors.ts
|
|
980
|
+
var SCOPES_PER_CALL = 500;
|
|
981
|
+
var SCOPE_TYPES_PER_FIELDS_CALL = 100;
|
|
982
|
+
var SCOPES_PER_VALUES_CALL = 200;
|
|
983
|
+
var TYPE_SCOPES_PAGE = 200;
|
|
984
|
+
var ARCHIVED_SCOPES_PAGE = 200;
|
|
985
|
+
var uniq = (ids) => [...new Set(ids.filter(Boolean))];
|
|
986
|
+
async function inBatches(ids, size, call) {
|
|
987
|
+
const unique = uniq(ids);
|
|
988
|
+
const batches = [];
|
|
989
|
+
for (let i = 0; i < unique.length; i += size) batches.push(unique.slice(i, i + size));
|
|
990
|
+
const answers = await Promise.all(batches.map(call));
|
|
991
|
+
const out = [];
|
|
992
|
+
for (const a of answers) {
|
|
993
|
+
if (!a.ok) return a;
|
|
994
|
+
out.push(...a.data ?? []);
|
|
995
|
+
}
|
|
996
|
+
return { ok: true, data: out };
|
|
997
|
+
}
|
|
998
|
+
function noRow(door) {
|
|
999
|
+
return { ok: false, error: { code: "internal", message: `${door} answered without the row it wrote.`, diagnostic: `@ai-matrx/records/scopes: ${door}` } };
|
|
1000
|
+
}
|
|
1001
|
+
var VALUE_DOOR_CODES = {
|
|
1002
|
+
unauthorized: "door",
|
|
1003
|
+
forbidden: "door",
|
|
1004
|
+
forbidden_org: "door",
|
|
1005
|
+
not_found: "not_found",
|
|
1006
|
+
invalid_argument: "invalid_argument",
|
|
1007
|
+
conflict: "stale_write",
|
|
1008
|
+
unavailable: "not_supported"
|
|
1009
|
+
};
|
|
1010
|
+
function createScopeDoors(call) {
|
|
1011
|
+
async function write(door, args) {
|
|
1012
|
+
const res = await call(door, args, `scopes.${door}`);
|
|
1013
|
+
if (!res.ok) return res;
|
|
1014
|
+
const row = res.data?.row;
|
|
1015
|
+
if (!row || typeof row !== "object") return noRow(door);
|
|
1016
|
+
return { ok: true, data: row };
|
|
1017
|
+
}
|
|
1018
|
+
async function archiveOrRestore(door, args, id) {
|
|
1019
|
+
const res = await call(door, args, `scopes.${door}`);
|
|
1020
|
+
return res.ok ? { ok: true, data: { id } } : res;
|
|
1021
|
+
}
|
|
1022
|
+
async function fieldById(scopeTypeId, fieldId, door) {
|
|
1023
|
+
const fields = await doors.fields([scopeTypeId]);
|
|
1024
|
+
if (!fields.ok) return fields;
|
|
1025
|
+
const field = fields.data.find((f) => f.id === fieldId);
|
|
1026
|
+
return field ? { ok: true, data: field } : noRow(door);
|
|
1027
|
+
}
|
|
1028
|
+
const doors = {
|
|
1029
|
+
async tree(organizationIds) {
|
|
1030
|
+
const ids = uniq(organizationIds);
|
|
1031
|
+
if (ids.length === 0) return { ok: true, data: [] };
|
|
1032
|
+
const res = await call("context_tree", { p_organization_ids: ids }, "scopes.tree");
|
|
1033
|
+
if (!res.ok) return res;
|
|
1034
|
+
const byType = /* @__PURE__ */ new Map();
|
|
1035
|
+
for (const s of res.data?.scopes ?? []) {
|
|
1036
|
+
const scope = scopeFromStore(s);
|
|
1037
|
+
const list = byType.get(scope.scope_type_id) ?? [];
|
|
1038
|
+
list.push(scope);
|
|
1039
|
+
byType.set(scope.scope_type_id, list);
|
|
1040
|
+
}
|
|
1041
|
+
return { ok: true, data: (res.data?.types ?? []).map((t) => ({ ...scopeTypeFromStore(t), scopes: byType.get(t.id) ?? [] })) };
|
|
1042
|
+
},
|
|
1043
|
+
async types(organizationIds, options) {
|
|
1044
|
+
const withCounts = options?.withCounts ?? true;
|
|
1045
|
+
const ids = uniq(organizationIds);
|
|
1046
|
+
if (ids.length === 0) return { ok: true, data: { types: [], counts: withCounts ? {} : null } };
|
|
1047
|
+
const res = await call("context_tree_types", { p_organization_ids: ids, p_with_counts: withCounts }, "scopes.types");
|
|
1048
|
+
if (!res.ok) return res;
|
|
1049
|
+
const rows = res.data?.types ?? [];
|
|
1050
|
+
const counts = withCounts ? {} : null;
|
|
1051
|
+
if (counts) for (const r of rows) counts[r.id] = Number(r.scope_count ?? 0);
|
|
1052
|
+
return { ok: true, data: { types: rows.map(scopeTypeFromStore), counts } };
|
|
1053
|
+
},
|
|
1054
|
+
async typeScopesPage(scopeTypeId, offset = 0, limit = TYPE_SCOPES_PAGE) {
|
|
1055
|
+
const res = await call(
|
|
1056
|
+
"context_tree_type_scopes",
|
|
1057
|
+
{ p_scope_type_id: scopeTypeId, p_offset: offset, p_limit: limit },
|
|
1058
|
+
"scopes.typeScopesPage"
|
|
1059
|
+
);
|
|
1060
|
+
if (!res.ok) return res;
|
|
1061
|
+
return {
|
|
1062
|
+
ok: true,
|
|
1063
|
+
data: { scopes: (res.data?.scopes ?? []).map(scopeFromStore), total: Number(res.data?.total ?? 0), next_offset: res.data?.next_offset ?? null }
|
|
1064
|
+
};
|
|
1065
|
+
},
|
|
1066
|
+
async search(organizationIds, query, limit = 100) {
|
|
1067
|
+
const ids = uniq(organizationIds);
|
|
1068
|
+
const q = query.trim();
|
|
1069
|
+
if (ids.length === 0 || q === "") return { ok: true, data: { scopes: [], total: 0 } };
|
|
1070
|
+
const res = await call(
|
|
1071
|
+
"context_tree_search",
|
|
1072
|
+
{ p_organization_ids: ids, p_query: q, p_limit: limit },
|
|
1073
|
+
"scopes.search"
|
|
1074
|
+
);
|
|
1075
|
+
if (!res.ok) return res;
|
|
1076
|
+
return { ok: true, data: { scopes: (res.data?.scopes ?? []).map(scopeFromStore), total: Number(res.data?.total ?? 0) } };
|
|
1077
|
+
},
|
|
1078
|
+
async scopes(ids) {
|
|
1079
|
+
const res = await inBatches(ids, SCOPES_PER_CALL, (batch) => call("context_scopes", { p_scope_ids: batch }, "scopes.scopes"));
|
|
1080
|
+
return res.ok ? { ok: true, data: res.data.map(scopeWithTypeFromStore) } : res;
|
|
1081
|
+
},
|
|
1082
|
+
async fields(scopeTypeIds) {
|
|
1083
|
+
const res = await inBatches(
|
|
1084
|
+
scopeTypeIds,
|
|
1085
|
+
SCOPE_TYPES_PER_FIELDS_CALL,
|
|
1086
|
+
(batch) => call("context_items", { p_scope_type_ids: batch }, "scopes.fields")
|
|
1087
|
+
);
|
|
1088
|
+
return res.ok ? { ok: true, data: res.data.map(contextFieldFromStore) } : res;
|
|
1089
|
+
},
|
|
1090
|
+
async values(scopeIds, options) {
|
|
1091
|
+
const res = await inBatches(
|
|
1092
|
+
scopeIds,
|
|
1093
|
+
SCOPES_PER_VALUES_CALL,
|
|
1094
|
+
(batch) => call("context_values", { p_scope_ids: batch }, "scopes.values")
|
|
1095
|
+
);
|
|
1096
|
+
if (!res.ok) return res;
|
|
1097
|
+
const cells = res.data.map(contextValueFromStore);
|
|
1098
|
+
await completeWholeValues(cells, options?.readFileText ?? null);
|
|
1099
|
+
return { ok: true, data: cells };
|
|
1100
|
+
},
|
|
1101
|
+
async archivedTypes(organizationId) {
|
|
1102
|
+
const res = await call("context_archived_types", { p_organization_id: organizationId }, "scopes.archivedTypes");
|
|
1103
|
+
return res.ok ? { ok: true, data: (res.data ?? []).map(archivedScopeTypeFromStore) } : res;
|
|
1104
|
+
},
|
|
1105
|
+
async archivedScopesOfType(organizationId, scopeTypeId, wanted) {
|
|
1106
|
+
const out = [];
|
|
1107
|
+
for (let offset = 0; out.length < wanted.size; offset += ARCHIVED_SCOPES_PAGE) {
|
|
1108
|
+
const res = await call(
|
|
1109
|
+
"read_records_archived",
|
|
1110
|
+
{ p_organization_id: organizationId, p_table_id: scopeTypeId, p_lane: "org", p_by_id: false, p_limit: ARCHIVED_SCOPES_PAGE, p_offset: offset },
|
|
1111
|
+
"scopes.archivedScopesOfType"
|
|
1112
|
+
);
|
|
1113
|
+
if (!res.ok) return res;
|
|
1114
|
+
const rows = res.data ?? [];
|
|
1115
|
+
for (const r of rows) {
|
|
1116
|
+
if (!wanted.has(r.id)) continue;
|
|
1117
|
+
out.push({
|
|
1118
|
+
id: r.id,
|
|
1119
|
+
name: typeof r.document?.name === "string" ? r.document.name : null,
|
|
1120
|
+
slug: typeof r.document?.slug === "string" ? r.document.slug : null,
|
|
1121
|
+
archived_at: r.archived_at ?? null
|
|
1122
|
+
});
|
|
1123
|
+
}
|
|
1124
|
+
if (rows.length < ARCHIVED_SCOPES_PAGE) break;
|
|
1125
|
+
}
|
|
1126
|
+
return { ok: true, data: out };
|
|
1127
|
+
},
|
|
1128
|
+
async systemItems() {
|
|
1129
|
+
const res = await call("context_system_items", {}, "scopes.systemItems");
|
|
1130
|
+
return res.ok ? { ok: true, data: res.data ?? [] } : res;
|
|
1131
|
+
},
|
|
1132
|
+
async templates() {
|
|
1133
|
+
const res = await call("context_templates", {}, "scopes.templates");
|
|
1134
|
+
return res.ok ? { ok: true, data: res.data ?? [] } : res;
|
|
1135
|
+
},
|
|
1136
|
+
async createType(organizationId, spec) {
|
|
1137
|
+
const slug = resolveSlug(spec.slug, spec.label_plural || spec.label_singular || "");
|
|
1138
|
+
if (!slug.ok) return slug;
|
|
1139
|
+
const res = await write("context_type_write", {
|
|
1140
|
+
p_organization_id: organizationId,
|
|
1141
|
+
p_type_id: null,
|
|
1142
|
+
p_spec: definedOnly({
|
|
1143
|
+
label_singular: spec.label_singular,
|
|
1144
|
+
label_plural: spec.label_plural,
|
|
1145
|
+
icon: spec.icon ?? "folder",
|
|
1146
|
+
description: spec.description ?? "",
|
|
1147
|
+
sort_order: spec.sort_order ?? 0,
|
|
1148
|
+
max_assignments: spec.max_assignments_per_entity ?? void 0,
|
|
1149
|
+
default_variable_keys: spec.default_variable_keys ?? [],
|
|
1150
|
+
color: spec.color,
|
|
1151
|
+
slug: slug.data
|
|
1152
|
+
})
|
|
1153
|
+
});
|
|
1154
|
+
return res.ok ? { ok: true, data: scopeTypeFromStore(res.data) } : res;
|
|
1155
|
+
},
|
|
1156
|
+
async updateType(typeId, spec) {
|
|
1157
|
+
let slug;
|
|
1158
|
+
if (spec.slug !== void 0) {
|
|
1159
|
+
const resolved = resolveSlug(spec.slug, spec.label_plural ?? spec.label_singular ?? "");
|
|
1160
|
+
if (!resolved.ok) return resolved;
|
|
1161
|
+
slug = resolved.data;
|
|
1162
|
+
}
|
|
1163
|
+
const res = await write("context_type_write", {
|
|
1164
|
+
p_organization_id: null,
|
|
1165
|
+
p_type_id: typeId,
|
|
1166
|
+
p_spec: definedOnly({
|
|
1167
|
+
label_singular: spec.label_singular,
|
|
1168
|
+
label_plural: spec.label_plural,
|
|
1169
|
+
icon: spec.icon,
|
|
1170
|
+
description: spec.description,
|
|
1171
|
+
sort_order: spec.sort_order,
|
|
1172
|
+
max_assignments: spec.max_assignments_per_entity,
|
|
1173
|
+
color: spec.color,
|
|
1174
|
+
slug
|
|
1175
|
+
})
|
|
1176
|
+
});
|
|
1177
|
+
return res.ok ? { ok: true, data: scopeTypeFromStore(res.data) } : res;
|
|
1178
|
+
},
|
|
1179
|
+
archiveType: (typeId) => archiveOrRestore("context_type_archive", { p_type_id: typeId }, typeId),
|
|
1180
|
+
restoreType: (typeId) => archiveOrRestore("context_type_restore", { p_type_id: typeId }, typeId),
|
|
1181
|
+
async createScope(organizationId, typeId, spec) {
|
|
1182
|
+
const slug = resolveSlug(spec.slug, spec.name ?? "");
|
|
1183
|
+
if (!slug.ok) return slug;
|
|
1184
|
+
const res = await write("context_scope_write", {
|
|
1185
|
+
p_organization_id: organizationId,
|
|
1186
|
+
p_scope_id: null,
|
|
1187
|
+
p_type_id: typeId,
|
|
1188
|
+
p_spec: definedOnly({
|
|
1189
|
+
name: spec.name,
|
|
1190
|
+
parent_scope_id: spec.parent_scope_id,
|
|
1191
|
+
description: spec.description ?? "",
|
|
1192
|
+
settings: spec.settings ?? {},
|
|
1193
|
+
slug: slug.data,
|
|
1194
|
+
sort_order: spec.sort_order
|
|
1195
|
+
})
|
|
1196
|
+
});
|
|
1197
|
+
return res.ok ? { ok: true, data: scopeFromStore(res.data) } : res;
|
|
1198
|
+
},
|
|
1199
|
+
async updateScope(scopeId, spec) {
|
|
1200
|
+
let slug;
|
|
1201
|
+
if (spec.slug !== void 0) {
|
|
1202
|
+
const resolved = resolveSlug(spec.slug, spec.name ?? "");
|
|
1203
|
+
if (!resolved.ok) return resolved;
|
|
1204
|
+
slug = resolved.data;
|
|
1205
|
+
}
|
|
1206
|
+
const res = await write("context_scope_write", {
|
|
1207
|
+
p_organization_id: null,
|
|
1208
|
+
p_scope_id: scopeId,
|
|
1209
|
+
p_type_id: null,
|
|
1210
|
+
p_spec: definedOnly({ name: spec.name, description: spec.description, settings: spec.settings, slug, sort_order: spec.sort_order })
|
|
1211
|
+
});
|
|
1212
|
+
return res.ok ? { ok: true, data: scopeFromStore(res.data) } : res;
|
|
1213
|
+
},
|
|
1214
|
+
archiveScope: (scopeId) => archiveOrRestore("context_scope_archive", { p_scope_id: scopeId }, scopeId),
|
|
1215
|
+
restoreScope: (scopeId) => archiveOrRestore("context_scope_restore", { p_scope_id: scopeId }, scopeId),
|
|
1216
|
+
async createField(scopeTypeId, spec) {
|
|
1217
|
+
const res = await write("context_item_write", {
|
|
1218
|
+
p_item_id: null,
|
|
1219
|
+
p_scope_type_id: scopeTypeId,
|
|
1220
|
+
p_spec: fieldSpecForDoor({ kind: "string", description: "", context_policy: "on_request", sensitivity: "internal", tags: [], ...spec })
|
|
1221
|
+
});
|
|
1222
|
+
if (!res.ok) return res;
|
|
1223
|
+
return fieldById(scopeTypeId, String(res.data.id), "context_item_write");
|
|
1224
|
+
},
|
|
1225
|
+
async updateField(fieldId, scopeTypeId, spec) {
|
|
1226
|
+
const res = await write("context_item_write", { p_item_id: fieldId, p_scope_type_id: null, p_spec: fieldSpecForDoor(spec) });
|
|
1227
|
+
if (!res.ok) return res;
|
|
1228
|
+
return fieldById(scopeTypeId, fieldId, "context_item_write");
|
|
1229
|
+
},
|
|
1230
|
+
archiveField: (fieldId) => archiveOrRestore("context_item_archive", { p_item_id: fieldId }, fieldId),
|
|
1231
|
+
restoreField: (fieldId) => archiveOrRestore("context_item_restore", { p_item_id: fieldId }, fieldId),
|
|
1232
|
+
async writeValue(cell) {
|
|
1233
|
+
const res = await call(
|
|
1234
|
+
"context_value_write",
|
|
1235
|
+
{ p_payload: { source_type: "ai_enriched", ...valuePayloadForDoor(cell) } },
|
|
1236
|
+
"scopes.writeValue"
|
|
1237
|
+
);
|
|
1238
|
+
if (!res.ok) return res;
|
|
1239
|
+
const envelope = res.data ?? {};
|
|
1240
|
+
if (!envelope.ok) {
|
|
1241
|
+
const code = VALUE_DOOR_CODES[envelope.error?.code ?? ""] ?? "internal";
|
|
1242
|
+
return { ok: false, error: { code, message: envelope.error?.message ?? "The value was not saved." } };
|
|
1243
|
+
}
|
|
1244
|
+
return {
|
|
1245
|
+
ok: true,
|
|
1246
|
+
data: {
|
|
1247
|
+
scope_id: cell.scope_id,
|
|
1248
|
+
field_id: cell.field_id,
|
|
1249
|
+
version: Number(envelope.data?.version ?? 1),
|
|
1250
|
+
source_type: String(envelope.data?.source_type ?? cell.source_type ?? "ai_enriched")
|
|
1251
|
+
}
|
|
1252
|
+
};
|
|
1253
|
+
}
|
|
1254
|
+
};
|
|
1255
|
+
return doors;
|
|
1256
|
+
}
|
|
1257
|
+
|
|
625
1258
|
// src/placement.ts
|
|
626
1259
|
function countOf(value) {
|
|
627
1260
|
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
@@ -3061,6 +3694,7 @@ function createRecordsClient(given) {
|
|
|
3061
3694
|
const unavailableReason = (error) => `${error.message}${error.hint ? ` ${error.hint}` : ""}`;
|
|
3062
3695
|
const client = {
|
|
3063
3696
|
config,
|
|
3697
|
+
scopes: createScopeDoors(callDoor),
|
|
3064
3698
|
async recordWrite({ table_id, data }) {
|
|
3065
3699
|
const result = await callDoor(
|
|
3066
3700
|
DOORS.recordWrite,
|