@ai-matrx/records 0.92.1 → 0.93.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 +43 -0
- package/README.md +4 -4
- package/dist/{client-Dzd8gtAo.d.ts → client-DsPuWFp0.d.ts} +8 -8
- package/dist/{client-Cn3odIIB.d.cts → client-EyD3rS0T.d.cts} +8 -8
- package/dist/core/index.cjs +101 -32
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +16 -15
- package/dist/core/index.d.ts +16 -15
- package/dist/core/index.js +101 -32
- package/dist/core/index.js.map +1 -1
- package/dist/data/index.cjs +46 -24
- package/dist/data/index.cjs.map +1 -1
- package/dist/data/index.d.cts +11 -11
- package/dist/data/index.d.ts +11 -11
- package/dist/data/index.js +46 -24
- package/dist/data/index.js.map +1 -1
- package/dist/{declareTable-CrL6AZKB.d.cts → declareTable-Bkk_Ewib.d.cts} +4 -4
- package/dist/{declareTable-ZRW5EsTQ.d.ts → declareTable-kL5qZoTe.d.ts} +4 -4
- package/dist/entity/index.cjs +43 -29
- package/dist/entity/index.cjs.map +1 -1
- package/dist/entity/index.d.cts +7 -6
- package/dist/entity/index.d.ts +7 -6
- package/dist/entity/index.js +43 -29
- package/dist/entity/index.js.map +1 -1
- package/dist/entity/react.cjs +43 -29
- package/dist/entity/react.cjs.map +1 -1
- package/dist/entity/react.js +43 -29
- package/dist/entity/react.js.map +1 -1
- package/dist/{field-CCY1rG9l.d.cts → field-6rwt4ejZ.d.cts} +1 -1
- package/dist/{field-enufS5ry.d.ts → field-B-WaVZnS.d.ts} +1 -1
- package/dist/forms/index.d.cts +3 -3
- package/dist/forms/index.d.ts +3 -3
- package/dist/index.cjs +92 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -33
- package/dist/index.d.ts +13 -33
- package/dist/index.js +92 -25
- package/dist/index.js.map +1 -1
- package/dist/memory/index.d.cts +7 -7
- package/dist/memory/index.d.ts +7 -7
- package/dist/objectOrganization-BII_K3Gm.d.ts +45 -0
- package/dist/objectOrganization-DfjDQtDb.d.cts +45 -0
- package/dist/{port-C54ykAOv.d.ts → port--acgmxh5.d.ts} +5 -2
- package/dist/{port-Drioh9al.d.cts → port-Cx76dq-X.d.cts} +5 -2
- package/dist/{portal-DRdmZ-xv.d.cts → portal-9sRr6cpG.d.cts} +1 -1
- package/dist/{portal-or_f7BkT.d.ts → portal-BDAqsGkg.d.ts} +1 -1
- package/dist/{ports-s0D2jvqn.d.cts → ports-9BQ3zo2y.d.cts} +108 -2
- package/dist/{ports-BeOgjwYl.d.ts → ports-DYWE1ENo.d.ts} +108 -2
- package/dist/react/index.cjs +101 -32
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +1463 -1363
- package/dist/react/index.d.ts +1463 -1363
- package/dist/react/index.js +101 -32
- package/dist/react/index.js.map +1 -1
- package/dist/realtime/index.cjs +43 -13
- package/dist/realtime/index.cjs.map +1 -1
- package/dist/realtime/index.d.cts +9 -3
- package/dist/realtime/index.d.ts +9 -3
- package/dist/realtime/index.js +43 -13
- package/dist/realtime/index.js.map +1 -1
- package/dist/{record-BwCf9wKW.d.cts → record-DmmeuUrC.d.cts} +1 -1
- package/dist/{record-BwCf9wKW.d.ts → record-DmmeuUrC.d.ts} +1 -1
- package/dist/{relation-eLMgv_dV.d.ts → relation-Op1M67le.d.ts} +2 -2
- package/dist/{relation-8vAWCa67.d.cts → relation-qrb2NbHf.d.cts} +2 -2
- package/dist/{rule-wHI5B0Ka.d.cts → rule-CeHg1sy1.d.cts} +1 -1
- package/dist/{rule-D9yNiorf.d.ts → rule-tN2lxvJ1.d.ts} +1 -1
- package/dist/search/index.d.cts +1 -1
- package/dist/search/index.d.ts +1 -1
- package/dist/setup/index.cjs +117 -42
- package/dist/setup/index.cjs.map +1 -1
- package/dist/setup/index.d.cts +25 -11
- package/dist/setup/index.d.ts +25 -11
- package/dist/setup/index.js +117 -42
- package/dist/setup/index.js.map +1 -1
- package/dist/{subscription-CdoI-UaB.d.cts → subscription-Drbxn-9Z.d.cts} +3 -3
- package/dist/{subscription-BynsG1K6.d.ts → subscription-hdTaRrfK.d.ts} +3 -3
- package/dist/{table-kind-i3lZJa3f.d.ts → table-kind-BZkvzBgc.d.ts} +4 -29
- package/dist/{table-kind-DzctQ7dO.d.cts → table-kind-C-hZxDN7.d.cts} +4 -29
- package/dist/templates/index.d.cts +10 -10
- package/dist/templates/index.d.ts +10 -10
- package/dist/typed-table/index.cjs +46 -24
- package/dist/typed-table/index.cjs.map +1 -1
- package/dist/typed-table/index.d.cts +10 -10
- package/dist/typed-table/index.d.ts +10 -10
- package/dist/typed-table/index.js +46 -24
- package/dist/typed-table/index.js.map +1 -1
- package/dist/{types-BvL_oKFl.d.ts → types-BauAeFW8.d.ts} +2 -2
- package/dist/{types-DAFP6XFe.d.cts → types-CBmUdBT0.d.cts} +2 -2
- package/dist/{types-BKYEeFt4.d.cts → types-Dek9owBe.d.cts} +2 -2
- package/dist/{types-D8qdG3Lg.d.cts → types-DsgXrESm.d.cts} +2 -2
- package/dist/{types-cpKY7Pjb.d.ts → types-HVgWcZDY.d.ts} +2 -2
- package/dist/{types-DYzXhD7j.d.ts → types-hrw-Eff1.d.ts} +2 -2
- package/dist/use-cases/index.d.cts +5 -5
- package/dist/use-cases/index.d.ts +5 -5
- package/dist/{validate-DfNMxjmU.d.cts → validate-B_iUeyh2.d.cts} +1 -1
- package/dist/{validate-DbvAParj.d.ts → validate-w-HGGTf-.d.ts} +1 -1
- package/dist/views/index.cjs +438 -0
- package/dist/views/index.cjs.map +1 -0
- package/dist/views/index.d.cts +401 -0
- package/dist/views/index.d.ts +401 -0
- package/dist/views/index.js +415 -0
- package/dist/views/index.js.map +1 -0
- package/package.json +12 -2
package/dist/setup/index.d.cts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { RealtimeManager } from '@ai-matrx/realtime';
|
|
2
|
-
import { R as RecordsClient } from '../client-
|
|
3
|
-
import { C as CreateEntityDataPortOptions, E as EntityDataPort } from '../port-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { R as RecordsClient } from '../client-EyD3rS0T.cjs';
|
|
3
|
+
import { C as CreateEntityDataPortOptions, E as EntityDataPort } from '../port-Cx76dq-X.cjs';
|
|
4
|
+
import { R as RecordOrganizationPort, O as ObjectOrganizationAnswer } from '../objectOrganization-DfjDQtDb.cjs';
|
|
5
|
+
import { a as RecordsConfig, b as RowAgentPort, c as RecordsErrorSink, d as RecordsDataSource, e as RecordsChangeSink, f as RowAgentTarget } from '../ports-9BQ3zo2y.cjs';
|
|
6
|
+
import { U as Uuid, R as RecordsResult } from '../record-DmmeuUrC.cjs';
|
|
6
7
|
import { RecordSearchRequest, RecordSearchHit, listStoreRecordCandidates } from '../search/index.cjs';
|
|
7
|
-
import '../table-kind-
|
|
8
|
-
import '../field-
|
|
9
|
-
import '../subscription-
|
|
10
|
-
import '../rule-
|
|
11
|
-
import '../relation-
|
|
12
|
-
import '../portal-
|
|
13
|
-
import '../types-
|
|
8
|
+
import '../table-kind-C-hZxDN7.cjs';
|
|
9
|
+
import '../field-6rwt4ejZ.cjs';
|
|
10
|
+
import '../subscription-Drbxn-9Z.cjs';
|
|
11
|
+
import '../rule-CeHg1sy1.cjs';
|
|
12
|
+
import '../relation-qrb2NbHf.cjs';
|
|
13
|
+
import '../portal-9sRr6cpG.cjs';
|
|
14
|
+
import '../types-Dek9owBe.cjs';
|
|
14
15
|
|
|
15
16
|
/** A signed-in database identity: the client every door and live change rides, and who it is. */
|
|
16
17
|
interface RecordsSession {
|
|
@@ -46,6 +47,13 @@ interface CreateRecordsOptions<TAssociations = never> {
|
|
|
46
47
|
entityAliases?: CreateEntityDataPortOptions["aliases"];
|
|
47
48
|
/** The associations store (`@ai-matrx/associations/core` `createAssociationsStore`) bound by the host; handed back as-is. */
|
|
48
49
|
associations?: TAssociations;
|
|
50
|
+
/**
|
|
51
|
+
* WHICH ORGANIZATION OWNS A RECORD — a port. Default: `custom.where_id_opens`, one call per ask. A host
|
|
52
|
+
* that keeps answers across remounts or seeds them from a server render binds its own.
|
|
53
|
+
*/
|
|
54
|
+
organizationOf?: RecordOrganizationPort;
|
|
55
|
+
/** RUN AN AGENT ON A ROW — a port the host binds (the run belongs to `@ai-matrx/agents`). Unbound, there is none. */
|
|
56
|
+
rowAgent?: RowAgentPort;
|
|
49
57
|
onError?: RecordsErrorSink;
|
|
50
58
|
}
|
|
51
59
|
interface RecordsSetup<TAssociations = never> {
|
|
@@ -79,6 +87,12 @@ interface RecordsSetup<TAssociations = never> {
|
|
|
79
87
|
watch(tableId: Uuid, sink: Partial<RecordsChangeSink>, organizationId?: Uuid): () => void;
|
|
80
88
|
/** The associations store the host bound, if any. */
|
|
81
89
|
readonly associations: TAssociations | undefined;
|
|
90
|
+
/** Which organization owns an object (table, record, form…), read from the object — never the person's pick. */
|
|
91
|
+
organizationOf(id: Uuid): Promise<ObjectOrganizationAnswer>;
|
|
92
|
+
/** The host's agent runner, or null when none is bound (agent buttons are then not drawn). */
|
|
93
|
+
readonly rowAgent: RowAgentPort | null;
|
|
94
|
+
/** Run an agent on a row through the bound runner; refuses by name when none is bound. */
|
|
95
|
+
runAgentOnRow(target: RowAgentTarget): Promise<RecordsResult<void>>;
|
|
82
96
|
/** Close live channels (a Node script calls this before it exits). */
|
|
83
97
|
close(): void;
|
|
84
98
|
}
|
package/dist/setup/index.d.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { RealtimeManager } from '@ai-matrx/realtime';
|
|
2
|
-
import { R as RecordsClient } from '../client-
|
|
3
|
-
import { C as CreateEntityDataPortOptions, E as EntityDataPort } from '../port
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { R as RecordsClient } from '../client-DsPuWFp0.js';
|
|
3
|
+
import { C as CreateEntityDataPortOptions, E as EntityDataPort } from '../port--acgmxh5.js';
|
|
4
|
+
import { R as RecordOrganizationPort, O as ObjectOrganizationAnswer } from '../objectOrganization-BII_K3Gm.js';
|
|
5
|
+
import { a as RecordsConfig, b as RowAgentPort, c as RecordsErrorSink, d as RecordsDataSource, e as RecordsChangeSink, f as RowAgentTarget } from '../ports-DYWE1ENo.js';
|
|
6
|
+
import { U as Uuid, R as RecordsResult } from '../record-DmmeuUrC.js';
|
|
6
7
|
import { RecordSearchRequest, RecordSearchHit, listStoreRecordCandidates } from '../search/index.js';
|
|
7
|
-
import '../table-kind-
|
|
8
|
-
import '../field-
|
|
9
|
-
import '../subscription-
|
|
10
|
-
import '../rule-
|
|
11
|
-
import '../relation-
|
|
12
|
-
import '../portal-
|
|
13
|
-
import '../types-
|
|
8
|
+
import '../table-kind-BZkvzBgc.js';
|
|
9
|
+
import '../field-B-WaVZnS.js';
|
|
10
|
+
import '../subscription-hdTaRrfK.js';
|
|
11
|
+
import '../rule-tN2lxvJ1.js';
|
|
12
|
+
import '../relation-Op1M67le.js';
|
|
13
|
+
import '../portal-BDAqsGkg.js';
|
|
14
|
+
import '../types-HVgWcZDY.js';
|
|
14
15
|
|
|
15
16
|
/** A signed-in database identity: the client every door and live change rides, and who it is. */
|
|
16
17
|
interface RecordsSession {
|
|
@@ -46,6 +47,13 @@ interface CreateRecordsOptions<TAssociations = never> {
|
|
|
46
47
|
entityAliases?: CreateEntityDataPortOptions["aliases"];
|
|
47
48
|
/** The associations store (`@ai-matrx/associations/core` `createAssociationsStore`) bound by the host; handed back as-is. */
|
|
48
49
|
associations?: TAssociations;
|
|
50
|
+
/**
|
|
51
|
+
* WHICH ORGANIZATION OWNS A RECORD — a port. Default: `custom.where_id_opens`, one call per ask. A host
|
|
52
|
+
* that keeps answers across remounts or seeds them from a server render binds its own.
|
|
53
|
+
*/
|
|
54
|
+
organizationOf?: RecordOrganizationPort;
|
|
55
|
+
/** RUN AN AGENT ON A ROW — a port the host binds (the run belongs to `@ai-matrx/agents`). Unbound, there is none. */
|
|
56
|
+
rowAgent?: RowAgentPort;
|
|
49
57
|
onError?: RecordsErrorSink;
|
|
50
58
|
}
|
|
51
59
|
interface RecordsSetup<TAssociations = never> {
|
|
@@ -79,6 +87,12 @@ interface RecordsSetup<TAssociations = never> {
|
|
|
79
87
|
watch(tableId: Uuid, sink: Partial<RecordsChangeSink>, organizationId?: Uuid): () => void;
|
|
80
88
|
/** The associations store the host bound, if any. */
|
|
81
89
|
readonly associations: TAssociations | undefined;
|
|
90
|
+
/** Which organization owns an object (table, record, form…), read from the object — never the person's pick. */
|
|
91
|
+
organizationOf(id: Uuid): Promise<ObjectOrganizationAnswer>;
|
|
92
|
+
/** The host's agent runner, or null when none is bound (agent buttons are then not drawn). */
|
|
93
|
+
readonly rowAgent: RowAgentPort | null;
|
|
94
|
+
/** Run an agent on a row through the bound runner; refuses by name when none is bound. */
|
|
95
|
+
runAgentOnRow(target: RowAgentTarget): Promise<RecordsResult<void>>;
|
|
82
96
|
/** Close live channels (a Node script calls this before it exits). */
|
|
83
97
|
close(): void;
|
|
84
98
|
}
|
package/dist/setup/index.js
CHANGED
|
@@ -375,35 +375,48 @@ function sourceArchivedOf(value) {
|
|
|
375
375
|
import { globalSlot as globalSlot2 } from "@ai-matrx/kit/global-slot";
|
|
376
376
|
var REMEMBER_MS = 3e4;
|
|
377
377
|
var REMEMBER_MAX = 500;
|
|
378
|
-
|
|
379
|
-
function trim(now) {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
378
|
+
function ledgerOver(ours) {
|
|
379
|
+
function trim(now) {
|
|
380
|
+
for (const [id, at] of ours) {
|
|
381
|
+
if (now - at <= REMEMBER_MS) break;
|
|
382
|
+
ours.delete(id);
|
|
383
|
+
}
|
|
384
|
+
while (ours.size > REMEMBER_MAX) {
|
|
385
|
+
const oldest = ours.keys().next();
|
|
386
|
+
if (oldest.done === true) break;
|
|
387
|
+
ours.delete(oldest.value);
|
|
388
|
+
}
|
|
388
389
|
}
|
|
390
|
+
return {
|
|
391
|
+
mint() {
|
|
392
|
+
const id = crypto.randomUUID();
|
|
393
|
+
const now = Date.now();
|
|
394
|
+
ours.set(id, now);
|
|
395
|
+
trim(now);
|
|
396
|
+
return id;
|
|
397
|
+
},
|
|
398
|
+
isOwn(opId) {
|
|
399
|
+
if (!opId) return false;
|
|
400
|
+
const at = ours.get(opId);
|
|
401
|
+
if (at === void 0) return false;
|
|
402
|
+
if (Date.now() - at > REMEMBER_MS) {
|
|
403
|
+
ours.delete(opId);
|
|
404
|
+
return false;
|
|
405
|
+
}
|
|
406
|
+
return true;
|
|
407
|
+
},
|
|
408
|
+
clear() {
|
|
409
|
+
ours.clear();
|
|
410
|
+
},
|
|
411
|
+
get size() {
|
|
412
|
+
return ours.size;
|
|
413
|
+
}
|
|
414
|
+
};
|
|
389
415
|
}
|
|
390
|
-
function
|
|
391
|
-
|
|
392
|
-
const now = Date.now();
|
|
393
|
-
ours.set(id, now);
|
|
394
|
-
trim(now);
|
|
395
|
-
return id;
|
|
396
|
-
}
|
|
397
|
-
function isOwnOp(opId) {
|
|
398
|
-
if (!opId) return false;
|
|
399
|
-
const at = ours.get(opId);
|
|
400
|
-
if (at === void 0) return false;
|
|
401
|
-
if (Date.now() - at > REMEMBER_MS) {
|
|
402
|
-
ours.delete(opId);
|
|
403
|
-
return false;
|
|
404
|
-
}
|
|
405
|
-
return true;
|
|
416
|
+
function createOpLedger() {
|
|
417
|
+
return ledgerOver(/* @__PURE__ */ new Map());
|
|
406
418
|
}
|
|
419
|
+
var defaultOpLedger = ledgerOver(globalSlot2("ai-matrx.records.op-ledger", () => /* @__PURE__ */ new Map()));
|
|
407
420
|
|
|
408
421
|
// src/choice.ts
|
|
409
422
|
import { isUuidShape as isUuidShape2 } from "@ai-matrx/kit/uuid";
|
|
@@ -2462,6 +2475,8 @@ function createRecordsClient(given) {
|
|
|
2462
2475
|
const config = { ...given, dataSource: asRecordsDataSource(given.dataSource) };
|
|
2463
2476
|
const schema = config.schema ?? DEFAULT_SCHEMA;
|
|
2464
2477
|
const org = config.organizationId;
|
|
2478
|
+
const ledger = config.opLedger ?? defaultOpLedger;
|
|
2479
|
+
const mintOp = () => ledger.mint();
|
|
2465
2480
|
const scream = sink(config);
|
|
2466
2481
|
const BUNDLE_TTL_MS = 1e4;
|
|
2467
2482
|
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"]);
|
|
@@ -2848,14 +2863,14 @@ function createRecordsClient(given) {
|
|
|
2848
2863
|
async recordWrite({ table_id, data }) {
|
|
2849
2864
|
const result = await callDoor(
|
|
2850
2865
|
DOORS.recordWrite,
|
|
2851
|
-
{ p_organization_id: org, p_table_id: table_id, p_data: { ...data, _op_id:
|
|
2866
|
+
{ p_organization_id: org, p_table_id: table_id, p_data: { ...data, _op_id: mintOp() } },
|
|
2852
2867
|
"recordWrite"
|
|
2853
2868
|
);
|
|
2854
2869
|
if (result.ok && typeof result.data === "string") announceRecordChanged(result.data);
|
|
2855
2870
|
return result;
|
|
2856
2871
|
},
|
|
2857
2872
|
async recordWriteMany({ table_id, rows, ids }) {
|
|
2858
|
-
const opId =
|
|
2873
|
+
const opId = mintOp();
|
|
2859
2874
|
return callDoor(
|
|
2860
2875
|
DOORS.recordWriteMany,
|
|
2861
2876
|
{
|
|
@@ -2868,7 +2883,7 @@ function createRecordsClient(given) {
|
|
|
2868
2883
|
);
|
|
2869
2884
|
},
|
|
2870
2885
|
async recordChangeMany({ table_id, changes }) {
|
|
2871
|
-
const opId =
|
|
2886
|
+
const opId = mintOp();
|
|
2872
2887
|
const result = await callDoor(
|
|
2873
2888
|
DOORS.recordChangeMany,
|
|
2874
2889
|
{
|
|
@@ -2891,7 +2906,7 @@ function createRecordsClient(given) {
|
|
|
2891
2906
|
return result;
|
|
2892
2907
|
},
|
|
2893
2908
|
async recordWriteGraph({ table_id, parent, children, edges }) {
|
|
2894
|
-
const opId =
|
|
2909
|
+
const opId = mintOp();
|
|
2895
2910
|
return callDoor(
|
|
2896
2911
|
DOORS.recordWriteGraph,
|
|
2897
2912
|
{
|
|
@@ -2915,7 +2930,7 @@ function createRecordsClient(given) {
|
|
|
2915
2930
|
{
|
|
2916
2931
|
p_organization_id: org,
|
|
2917
2932
|
p_record_id: record_id,
|
|
2918
|
-
p_patch: { ...patch, _op_id:
|
|
2933
|
+
p_patch: { ...patch, _op_id: mintOp() },
|
|
2919
2934
|
...expectedVersion === void 0 ? {} : { p_expected_version: expectedVersion }
|
|
2920
2935
|
},
|
|
2921
2936
|
"recordUpdate"
|
|
@@ -2929,7 +2944,7 @@ function createRecordsClient(given) {
|
|
|
2929
2944
|
{
|
|
2930
2945
|
p_organization_id: org,
|
|
2931
2946
|
p_record_id: record_id,
|
|
2932
|
-
p_patch: { ...patch, _op_id:
|
|
2947
|
+
p_patch: { ...patch, _op_id: mintOp() },
|
|
2933
2948
|
p_add: add,
|
|
2934
2949
|
...expectedVersion === void 0 ? {} : { p_expected_version: expectedVersion }
|
|
2935
2950
|
},
|
|
@@ -3954,7 +3969,7 @@ function createRecordsClient(given) {
|
|
|
3954
3969
|
p_table_id: table_id,
|
|
3955
3970
|
p_key: keys,
|
|
3956
3971
|
// The op id rides the envelope, as `recordWrite` / `recordUpdate` send it; each door takes it off.
|
|
3957
|
-
p_data: { ...data, _op_id:
|
|
3972
|
+
p_data: { ...data, _op_id: mintOp() },
|
|
3958
3973
|
...expectedVersion === void 0 ? {} : { p_expected_version: expectedVersion }
|
|
3959
3974
|
},
|
|
3960
3975
|
"recordUpsert"
|
|
@@ -6342,6 +6357,7 @@ function toWireValues(values) {
|
|
|
6342
6357
|
}
|
|
6343
6358
|
function createEntityDataPort(options) {
|
|
6344
6359
|
const client = options.client ?? createEntityClient({ dataSource: options.dataSource });
|
|
6360
|
+
const ledger = options.opLedger ?? defaultOpLedger;
|
|
6345
6361
|
const activeOrganization = () => (options.activeOrganizationId ? options.activeOrganizationId() : options.organization) ?? null;
|
|
6346
6362
|
const gets = /* @__PURE__ */ new Map();
|
|
6347
6363
|
const aliases = options.aliases;
|
|
@@ -6532,27 +6548,27 @@ function createEntityDataPort(options) {
|
|
|
6532
6548
|
"Pick an organization, then add the row again. Nothing was saved."
|
|
6533
6549
|
);
|
|
6534
6550
|
}
|
|
6535
|
-
const answer = await client.insert({ token: binding.token, organizationId, rows: [toWireValues(values)], opId:
|
|
6551
|
+
const answer = await client.insert({ token: binding.token, organizationId, rows: [toWireValues(values)], opId: ledger.mint() });
|
|
6536
6552
|
return readBack(alias, answer, "The new row");
|
|
6537
6553
|
},
|
|
6538
6554
|
async update(alias, id, patch, baseVersion) {
|
|
6539
6555
|
const binding = bindingOf(alias);
|
|
6540
6556
|
if (!binding) return noSuchAlias(alias);
|
|
6541
6557
|
if (!isUuidShape3(id)) return refusal("invalid_argument", `"${String(id)}" is not a row id.`);
|
|
6542
|
-
const answer = await client.update({ token: binding.token, id, baseVersion, patch: toWireValues(patch), opId:
|
|
6558
|
+
const answer = await client.update({ token: binding.token, id, baseVersion, patch: toWireValues(patch), opId: ledger.mint() });
|
|
6543
6559
|
return readBack(alias, answer, "The change");
|
|
6544
6560
|
},
|
|
6545
6561
|
async archive(alias, id) {
|
|
6546
6562
|
const binding = bindingOf(alias);
|
|
6547
6563
|
if (!binding) return noSuchAlias(alias);
|
|
6548
6564
|
if (!isUuidShape3(id)) return refusal("invalid_argument", `"${String(id)}" is not a row id.`);
|
|
6549
|
-
return done(await client.archive({ token: binding.token, ids: [id], opId:
|
|
6565
|
+
return done(await client.archive({ token: binding.token, ids: [id], opId: ledger.mint() }));
|
|
6550
6566
|
},
|
|
6551
6567
|
async restore(alias, id) {
|
|
6552
6568
|
const binding = bindingOf(alias);
|
|
6553
6569
|
if (!binding) return noSuchAlias(alias);
|
|
6554
6570
|
if (!isUuidShape3(id)) return refusal("invalid_argument", `"${String(id)}" is not a row id.`);
|
|
6555
|
-
return done(await client.unarchive({ token: binding.token, ids: [id], opId:
|
|
6571
|
+
return done(await client.unarchive({ token: binding.token, ids: [id], opId: ledger.mint() }));
|
|
6556
6572
|
},
|
|
6557
6573
|
subscribe(event, listener) {
|
|
6558
6574
|
const alias = event.startsWith("rows:") ? event.slice(5) : null;
|
|
@@ -6602,6 +6618,48 @@ function createEntityDataPort(options) {
|
|
|
6602
6618
|
};
|
|
6603
6619
|
}
|
|
6604
6620
|
|
|
6621
|
+
// src/objectOrganization.ts
|
|
6622
|
+
var WHERE_ID_OPENS_DOOR = "where_id_opens";
|
|
6623
|
+
function doorIsAbsent(error) {
|
|
6624
|
+
if (error.code === "PGRST202" || error.code === "42883") return true;
|
|
6625
|
+
return /could not find the function/i.test(error.message ?? "");
|
|
6626
|
+
}
|
|
6627
|
+
var DOOR_ABSENT_WHY = "custom.where_id_opens is missing from this database, so this page cannot tell which organization the record lives in and holds instead of guessing. Remedy: the chair applies migrations/campaign/openbyid_one_address_opens_any_id.sql and openbyid_the_resolver_can_be_reached.sql.";
|
|
6628
|
+
async function resolveObjectOrganization(dataSource, id) {
|
|
6629
|
+
let answered;
|
|
6630
|
+
try {
|
|
6631
|
+
answered = await dataSource.rpc(WHERE_ID_OPENS_DOOR, { p_id: id }, { schema: "custom" });
|
|
6632
|
+
} catch (thrown) {
|
|
6633
|
+
return { state: "unavailable", why: thrown instanceof Error ? thrown.message : "The record store did not answer." };
|
|
6634
|
+
}
|
|
6635
|
+
return readObjectOrganizationAnswer(answered, id);
|
|
6636
|
+
}
|
|
6637
|
+
function readObjectOrganizationAnswer(answered, id) {
|
|
6638
|
+
if (answered.error) {
|
|
6639
|
+
if (doorIsAbsent(answered.error)) {
|
|
6640
|
+
console.warn(`[@ai-matrx/records] ${DOOR_ABSENT_WHY}`);
|
|
6641
|
+
return { state: "unavailable", why: DOOR_ABSENT_WHY };
|
|
6642
|
+
}
|
|
6643
|
+
return { state: "unavailable", why: answered.error.message ?? "The record store refused to say where this is." };
|
|
6644
|
+
}
|
|
6645
|
+
const row = answered.data;
|
|
6646
|
+
if (row === null || row === void 0) return { state: "not-given" };
|
|
6647
|
+
if (typeof row !== "object" || typeof row.organization_id !== "string" || typeof row.kind !== "string") {
|
|
6648
|
+
return { state: "unavailable", why: "The record store answered something this page cannot read." };
|
|
6649
|
+
}
|
|
6650
|
+
return {
|
|
6651
|
+
state: "found",
|
|
6652
|
+
organizationId: row.organization_id,
|
|
6653
|
+
kind: row.kind,
|
|
6654
|
+
path: typeof row.path === "string" ? row.path : null,
|
|
6655
|
+
live: row.live !== false,
|
|
6656
|
+
resolvedId: typeof row.resolved_id === "string" ? row.resolved_id : id
|
|
6657
|
+
};
|
|
6658
|
+
}
|
|
6659
|
+
function whereIdOpensPort(dataSource) {
|
|
6660
|
+
return { organizationOf: (id) => resolveObjectOrganization(dataSource, id) };
|
|
6661
|
+
}
|
|
6662
|
+
|
|
6605
6663
|
// src/realtime/index.ts
|
|
6606
6664
|
import {
|
|
6607
6665
|
defineChannelNamespace as defineChannelNamespace2,
|
|
@@ -6620,7 +6678,7 @@ function noticeKey(notice) {
|
|
|
6620
6678
|
const ids = notice.record_ids == null ? "*" : [...notice.record_ids].sort().join(",");
|
|
6621
6679
|
return `${notice.table_id ?? ""}:${notice.kind ?? ""}:${notice.op ?? ""}:${notice.op_id ?? ""}:${notice.at}:${ids}`;
|
|
6622
6680
|
}
|
|
6623
|
-
function storeTableChannelSpec(tableId, onNotice, onBackfill) {
|
|
6681
|
+
function storeTableChannelSpec(tableId, onNotice, onBackfill, ledger = defaultOpLedger) {
|
|
6624
6682
|
return {
|
|
6625
6683
|
topic: storeTableChannel.topic({ tableId }),
|
|
6626
6684
|
// Database Broadcast is authorized by RLS on realtime.messages — that is what `private` means here;
|
|
@@ -6628,14 +6686,14 @@ function storeTableChannelSpec(tableId, onNotice, onBackfill) {
|
|
|
6628
6686
|
// delivers nothing forever).
|
|
6629
6687
|
private: true,
|
|
6630
6688
|
// The sender is Postgres: no Matrx envelope. OUR OWN WRITE is known by the op id the write door carried.
|
|
6631
|
-
wire: { mode: "raw", isOwnMessage: (payload) =>
|
|
6689
|
+
wire: { mode: "raw", isOwnMessage: (payload) => ledger.isOwn(payload?.op_id) },
|
|
6632
6690
|
eventKey: (_source, payload) => noticeKey(payload ?? {}),
|
|
6633
6691
|
broadcast: [
|
|
6634
6692
|
{
|
|
6635
6693
|
event: STORE_NOTICE_EVENT,
|
|
6636
6694
|
onMessage: (message) => {
|
|
6637
6695
|
const notice = message.data ?? {};
|
|
6638
|
-
if (
|
|
6696
|
+
if (ledger.isOwn(notice.op_id)) return;
|
|
6639
6697
|
onNotice(notice);
|
|
6640
6698
|
}
|
|
6641
6699
|
}
|
|
@@ -6655,7 +6713,8 @@ function createRecordsRealtimePort(options = {}) {
|
|
|
6655
6713
|
},
|
|
6656
6714
|
() => {
|
|
6657
6715
|
for (const listener of channel.listeners) listener.backfill();
|
|
6658
|
-
}
|
|
6716
|
+
},
|
|
6717
|
+
options.ledger
|
|
6659
6718
|
);
|
|
6660
6719
|
if (options.manager) {
|
|
6661
6720
|
const handle = options.manager.open(spec);
|
|
@@ -6773,22 +6832,26 @@ async function createRecords(options) {
|
|
|
6773
6832
|
} else if (options.live) {
|
|
6774
6833
|
realtime = options.live;
|
|
6775
6834
|
}
|
|
6776
|
-
const
|
|
6835
|
+
const opLedger = createOpLedger();
|
|
6836
|
+
const realtimePort = realtime ? createRecordsRealtimePort({ manager: realtime, ledger: opLedger }) : void 0;
|
|
6777
6837
|
const actor = options.actor ?? { actor: "user", ...userId ? { user_id: userId } : {} };
|
|
6778
6838
|
const records = createRecordsClient({
|
|
6779
6839
|
dataSource,
|
|
6780
6840
|
actor,
|
|
6781
6841
|
organizationId,
|
|
6782
6842
|
organizationIds,
|
|
6843
|
+
opLedger,
|
|
6783
6844
|
...realtimePort ? { realtime: realtimePort } : {},
|
|
6784
6845
|
...options.onError ? { onError: options.onError } : {}
|
|
6785
6846
|
});
|
|
6786
6847
|
const entities = createEntityDataPort({
|
|
6787
6848
|
dataSource,
|
|
6788
6849
|
aliases: options.entityAliases ?? {},
|
|
6850
|
+
opLedger,
|
|
6789
6851
|
...organizationId ? { organization: organizationId } : {}
|
|
6790
6852
|
});
|
|
6791
6853
|
const organizationIdChosen = organizationId;
|
|
6854
|
+
const organizationPort = options.organizationOf ?? whereIdOpensPort(dataSource);
|
|
6792
6855
|
let warnedNotLive = false;
|
|
6793
6856
|
return {
|
|
6794
6857
|
authKind: options.auth.kind,
|
|
@@ -6817,6 +6880,18 @@ async function createRecords(options) {
|
|
|
6817
6880
|
}) });
|
|
6818
6881
|
},
|
|
6819
6882
|
associations: options.associations,
|
|
6883
|
+
organizationOf: (id) => organizationPort.organizationOf(id),
|
|
6884
|
+
rowAgent: options.rowAgent ?? null,
|
|
6885
|
+
async runAgentOnRow(target) {
|
|
6886
|
+
if (!options.rowAgent) {
|
|
6887
|
+
return {
|
|
6888
|
+
ok: false,
|
|
6889
|
+
error: { code: "not_supported", message: "No agent runner is bound: pass createRecords({ rowAgent }) to run an agent on a row." }
|
|
6890
|
+
};
|
|
6891
|
+
}
|
|
6892
|
+
await options.rowAgent.run(target);
|
|
6893
|
+
return { ok: true, data: void 0 };
|
|
6894
|
+
},
|
|
6820
6895
|
close() {
|
|
6821
6896
|
if (ownsRealtime) realtime?.dispose();
|
|
6822
6897
|
}
|