@ai-matrx/records 0.58.0 → 0.58.2
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 +24 -0
- package/dist/core/index.cjs +108 -3
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +26 -3
- package/dist/core/index.d.ts +26 -3
- package/dist/core/index.js +108 -3
- package/dist/core/index.js.map +1 -1
- package/dist/index.cjs +66 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -1
- package/dist/index.d.ts +61 -1
- package/dist/index.js +66 -3
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +158 -53
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +82 -1
- package/dist/react/index.d.ts +82 -1
- package/dist/react/index.js +158 -53
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# Changelog — @ai-matrx/records
|
|
2
2
|
|
|
3
|
+
## 0.58.2
|
|
4
|
+
|
|
5
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
6
|
+
`git diff npm/records/v0.58.1..npm/records/v0.58.2 -- apps/shared/records`).
|
|
7
|
+
No source changes intended and no consumer action required.
|
|
8
|
+
|
|
9
|
+
## Unreleased — lane SC-1-TAILS (2026-09-24)
|
|
10
|
+
|
|
11
|
+
* **`client.tableHome({ table_id })` and `client.tableMove({ table_id, to_organization_id, expected_version })`** — the
|
|
12
|
+
store utility for "which organization is this table in, and move it" (`custom.table_home` / `custom.table_move`,
|
|
13
|
+
SC-1' + SC-1-TAILS). Asked by the TABLE's id, never the bound organization; `null` = not given to this person;
|
|
14
|
+
`door_absent` (and nothing called) on a store whose catalogue lacks the doors.
|
|
15
|
+
* `placement.ts` gains `TableHome`, `TableHomeDestination`, `TableMoved`, `parseTableHome`, `parseTableMoved` and
|
|
16
|
+
`moveConsequence` (the sentence said before a move: columns, rows, trash, the tables that live inside it, links
|
|
17
|
+
that reach back across the wall).
|
|
18
|
+
* **Consumer action:** matrx-frontend swaps `features/unified-data/where-it-lives/` for `@ai-matrx/records-ui`'s
|
|
19
|
+
`WhereItLives` once both are installed. `pnpm records:generate` after the chair applies the doors.
|
|
20
|
+
|
|
21
|
+
## 0.58.1
|
|
22
|
+
|
|
23
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
24
|
+
`git diff npm/records/v0.58.0..npm/records/v0.58.1 -- apps/shared/records`).
|
|
25
|
+
No source changes intended and no consumer action required.
|
|
26
|
+
|
|
3
27
|
## 0.58.0 (2026-09-24 — published by PUBLISH-SWEEP-5; folds every section below down to 0.57.3)
|
|
4
28
|
|
|
5
29
|
* **`src/store.generated.ts` is regenerated from the LIVE main database at publish time** (608 doors).
|
package/dist/core/index.cjs
CHANGED
|
@@ -2310,6 +2310,7 @@ __export(core_exports, {
|
|
|
2310
2310
|
memoryStore: () => memoryStore,
|
|
2311
2311
|
mintClientKey: () => mintClientKey,
|
|
2312
2312
|
mintOpId: () => mintOpId,
|
|
2313
|
+
moveConsequence: () => moveConsequence,
|
|
2313
2314
|
moveInOrder: () => moveInOrder,
|
|
2314
2315
|
offeredAsContext: () => offeredAsContext,
|
|
2315
2316
|
ok: () => ok,
|
|
@@ -2318,6 +2319,8 @@ __export(core_exports, {
|
|
|
2318
2319
|
optionKey: () => optionKey,
|
|
2319
2320
|
optionLabel: () => optionLabel,
|
|
2320
2321
|
parseCsv: () => parseCsv,
|
|
2322
|
+
parseTableHome: () => parseTableHome,
|
|
2323
|
+
parseTableMoved: () => parseTableMoved,
|
|
2321
2324
|
planQuery: () => planQuery,
|
|
2322
2325
|
portalArchiveConsequence: () => portalArchiveConsequence,
|
|
2323
2326
|
portalConfirmLine: () => portalConfirmLine,
|
|
@@ -3003,6 +3006,66 @@ function keptTableHref(fact, hrefs) {
|
|
|
3003
3006
|
}
|
|
3004
3007
|
return hrefs.table(fact.table_id);
|
|
3005
3008
|
}
|
|
3009
|
+
function countOf(value) {
|
|
3010
|
+
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
3011
|
+
}
|
|
3012
|
+
function wordsOf(value) {
|
|
3013
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
3014
|
+
}
|
|
3015
|
+
function parseTableHome(raw) {
|
|
3016
|
+
if (!raw || typeof raw !== "object") return null;
|
|
3017
|
+
const row = raw;
|
|
3018
|
+
const table = row.table;
|
|
3019
|
+
const org = row.organization;
|
|
3020
|
+
if (!table || !org || !wordsOf(table.id) || !wordsOf(org.id) || !wordsOf(org.name)) return null;
|
|
3021
|
+
const carries = row.carries ?? {};
|
|
3022
|
+
const destinations = Array.isArray(row.destinations) ? row.destinations : [];
|
|
3023
|
+
return {
|
|
3024
|
+
table: { id: String(table.id), name: wordsOf(table.name) ?? "This table", version: countOf(table.version) },
|
|
3025
|
+
organization: { id: String(org.id), name: String(org.name) },
|
|
3026
|
+
mayMove: row.may_move === true,
|
|
3027
|
+
whyNot: wordsOf(row.why_not),
|
|
3028
|
+
heldBy: Array.isArray(row.held_by) ? row.held_by.filter((s) => typeof s === "string") : [],
|
|
3029
|
+
destinations: destinations.filter((d) => !!d && typeof d === "object" && !!wordsOf(d.id)).map((d) => ({
|
|
3030
|
+
id: String(d.id),
|
|
3031
|
+
name: wordsOf(d.name) ?? "An organization",
|
|
3032
|
+
role: wordsOf(d.role) ?? "member",
|
|
3033
|
+
ok: d.ok === true,
|
|
3034
|
+
why: wordsOf(d.why)
|
|
3035
|
+
})),
|
|
3036
|
+
carries: {
|
|
3037
|
+
fields: countOf(carries.fields),
|
|
3038
|
+
records: countOf(carries.records),
|
|
3039
|
+
inTrash: countOf(carries.in_trash),
|
|
3040
|
+
choiceLists: countOf(carries.choice_lists),
|
|
3041
|
+
withIt: countOf(carries.with_it),
|
|
3042
|
+
tablesInside: countOf(carries.tables_inside),
|
|
3043
|
+
linksAcross: countOf(carries.links_across)
|
|
3044
|
+
}
|
|
3045
|
+
};
|
|
3046
|
+
}
|
|
3047
|
+
function parseTableMoved(raw) {
|
|
3048
|
+
const row = raw ?? {};
|
|
3049
|
+
const to = row.to ?? {};
|
|
3050
|
+
const from = row.from ?? {};
|
|
3051
|
+
const table = row.table ?? {};
|
|
3052
|
+
if (row.moved !== true || !wordsOf(to.id)) return null;
|
|
3053
|
+
return {
|
|
3054
|
+
to: { id: String(to.id), name: wordsOf(to.name) ?? "the new organization" },
|
|
3055
|
+
from: { id: wordsOf(from.id) ?? "", name: wordsOf(from.name) ?? "its old organization" },
|
|
3056
|
+
tableName: wordsOf(table.name) ?? "The table"
|
|
3057
|
+
};
|
|
3058
|
+
}
|
|
3059
|
+
function plural(n, one, many) {
|
|
3060
|
+
return `${n} ${n === 1 ? one : many}`;
|
|
3061
|
+
}
|
|
3062
|
+
function moveConsequence(home, to) {
|
|
3063
|
+
const c = home.carries;
|
|
3064
|
+
const parts = [plural(c.fields, "column", "columns"), plural(c.records, "row", "rows")];
|
|
3065
|
+
if (c.inTrash > 0) parts.push(`${c.inTrash} in the trash`);
|
|
3066
|
+
const extra = c.choiceLists + c.withIt;
|
|
3067
|
+
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.`;
|
|
3068
|
+
}
|
|
3006
3069
|
|
|
3007
3070
|
// src/capture-queue.ts
|
|
3008
3071
|
var DB_NAME = "matrx-capture";
|
|
@@ -3072,7 +3135,7 @@ function memoryStore() {
|
|
|
3072
3135
|
setMeta: async (key, value) => void meta.set(key, value)
|
|
3073
3136
|
};
|
|
3074
3137
|
}
|
|
3075
|
-
function
|
|
3138
|
+
function countOf2(items) {
|
|
3076
3139
|
const c = { waiting: 0, sending: 0, refused: 0, landed: 0 };
|
|
3077
3140
|
for (const i of items) c[i.state] += 1;
|
|
3078
3141
|
return c;
|
|
@@ -3089,7 +3152,7 @@ function openCaptureQueue(opts) {
|
|
|
3089
3152
|
const announce = async () => {
|
|
3090
3153
|
if (!opts.onChange) return;
|
|
3091
3154
|
const items = await store.all();
|
|
3092
|
-
opts.onChange(
|
|
3155
|
+
opts.onChange(countOf2(items), items);
|
|
3093
3156
|
};
|
|
3094
3157
|
const oldestFirst = (items) => items.slice().sort((a, b) => a.captured_at.localeCompare(b.captured_at));
|
|
3095
3158
|
const queue = {
|
|
@@ -3118,7 +3181,7 @@ function openCaptureQueue(opts) {
|
|
|
3118
3181
|
return key;
|
|
3119
3182
|
},
|
|
3120
3183
|
list: () => store.all().then(oldestFirst),
|
|
3121
|
-
counts: () => store.all().then(
|
|
3184
|
+
counts: () => store.all().then(countOf2),
|
|
3122
3185
|
async sync() {
|
|
3123
3186
|
if (syncing) return syncing;
|
|
3124
3187
|
syncing = (async () => {
|
|
@@ -5368,6 +5431,8 @@ function scopeChip(scope) {
|
|
|
5368
5431
|
|
|
5369
5432
|
// src/core/doors.ts
|
|
5370
5433
|
var OWED_BY = {
|
|
5434
|
+
table_home: "SC-1' \u2014 matrx-frontend migrations/campaign/sc1p_a_table_says_where_it_lives_and_its_owner_can_move_it.sql (and its grant file), applied by the chair",
|
|
5435
|
+
table_move: "SC-1' / SC-1-TAILS \u2014 sc1p_a_table_says_where_it_lives_and_its_owner_can_move_it.sql, then sc1t_a_table_moves_with_the_tables_inside_it.sql, applied by the chair",
|
|
5371
5436
|
metadata_search: "W5-SRV / W5-AGENT \u2014 the agent surface's eight verbs",
|
|
5372
5437
|
record_aggregate: "W5-SRV / W5-AGENT \u2014 `record_aggregate` is one of the eight verbs",
|
|
5373
5438
|
field_propose: "W5-AGENT \u2014 AGT-4/AGT-8, the proposal and its approvers",
|
|
@@ -5693,6 +5758,12 @@ var DOORS = {
|
|
|
5693
5758
|
// ask, under the same wall and visibility gate as `portals` itself.
|
|
5694
5759
|
portalTables: "portal_tables",
|
|
5695
5760
|
tableFacts: "table_facts",
|
|
5761
|
+
// WHERE A TABLE LIVES, AND MOVING IT (SC-1' / SC-1-TAILS). `table_home` answers only when the
|
|
5762
|
+
// caller may open the Table (custom.where_id_opens) and names its organization FROM THE TABLE;
|
|
5763
|
+
// `table_move` moves it into another organization the caller belongs to, with every Table
|
|
5764
|
+
// inside it, or refuses with one sentence.
|
|
5765
|
+
tableHome: "table_home",
|
|
5766
|
+
tableMove: "table_move",
|
|
5696
5767
|
portalCard: "portal_card",
|
|
5697
5768
|
portalDeclare: "portal_declare",
|
|
5698
5769
|
portalInvite: "portal_invite",
|
|
@@ -6215,6 +6286,40 @@ function createRecordsClient(config) {
|
|
|
6215
6286
|
if (!doorExists(DOORS.tableFacts)) return ok(null);
|
|
6216
6287
|
return callDoor(DOORS.tableFacts, { p_organization_id: org }, "tableFacts");
|
|
6217
6288
|
},
|
|
6289
|
+
async tableHome({ table_id }) {
|
|
6290
|
+
const answered = await callDoor(DOORS.tableHome, { p_table_id: table_id }, "tableHome");
|
|
6291
|
+
if (!answered.ok) return answered;
|
|
6292
|
+
if (answered.data === null || answered.data === void 0) return ok(null);
|
|
6293
|
+
const home = parseTableHome(answered.data);
|
|
6294
|
+
if (!home) {
|
|
6295
|
+
const refusal = {
|
|
6296
|
+
code: "not_supported",
|
|
6297
|
+
message: "The record store answered where this table lives in a shape this client cannot read, so nothing is claimed about it.",
|
|
6298
|
+
hint: "Regenerate @ai-matrx/records against the store (pnpm records:generate) \u2014 the door and this client disagree."
|
|
6299
|
+
};
|
|
6300
|
+
scream({ code: refusal.code, message: refusal.message, ...refusal.hint ? { hint: refusal.hint } : {}, where: "tableHome" });
|
|
6301
|
+
return err(refusal);
|
|
6302
|
+
}
|
|
6303
|
+
return ok(home);
|
|
6304
|
+
},
|
|
6305
|
+
async tableMove({ table_id, to_organization_id, expected_version }) {
|
|
6306
|
+
const answered = await callDoor(
|
|
6307
|
+
DOORS.tableMove,
|
|
6308
|
+
{ p_table_id: table_id, p_to_organization_id: to_organization_id, p_expected_version: expected_version ?? null },
|
|
6309
|
+
"tableMove"
|
|
6310
|
+
);
|
|
6311
|
+
if (!answered.ok) return answered;
|
|
6312
|
+
const moved = parseTableMoved(answered.data);
|
|
6313
|
+
if (!moved) {
|
|
6314
|
+
const refusal = {
|
|
6315
|
+
code: "not_supported",
|
|
6316
|
+
message: "The record store answered the move in a shape this client cannot read. Look where the table lives before trying again."
|
|
6317
|
+
};
|
|
6318
|
+
scream({ code: refusal.code, message: refusal.message, where: "tableMove" });
|
|
6319
|
+
return err(refusal);
|
|
6320
|
+
}
|
|
6321
|
+
return ok(moved);
|
|
6322
|
+
},
|
|
6218
6323
|
async tableArchived({ table_id }) {
|
|
6219
6324
|
const kernel = await callDoor(DOORS.tableKernelId, {}, "tableArchived.kernel");
|
|
6220
6325
|
if (!kernel.ok) return err(kernel.error);
|