@ai-matrx/records 0.92.2 → 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 +37 -0
- 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 +13 -3
package/dist/memory/index.d.cts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { T as TemplateSpec } from '../types-
|
|
3
|
-
import { P as PgError } from '../record-
|
|
4
|
-
import '../
|
|
5
|
-
import '../
|
|
6
|
-
import '../
|
|
7
|
-
import '../
|
|
1
|
+
import { d as RecordsDataSource, a as RecordsConfig } from '../ports-9BQ3zo2y.cjs';
|
|
2
|
+
import { T as TemplateSpec } from '../types-DsgXrESm.cjs';
|
|
3
|
+
import { P as PgError } from '../record-DmmeuUrC.cjs';
|
|
4
|
+
import '../field-6rwt4ejZ.cjs';
|
|
5
|
+
import '../subscription-Drbxn-9Z.cjs';
|
|
6
|
+
import '../rule-CeHg1sy1.cjs';
|
|
7
|
+
import '../types-CBmUdBT0.cjs';
|
|
8
8
|
|
|
9
9
|
type Json$1 = Record<string, unknown>;
|
|
10
10
|
/** One presented column, exactly as `platform.drill_describe(...).api.columns[]` says it. */
|
package/dist/memory/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { T as TemplateSpec } from '../types-
|
|
3
|
-
import { P as PgError } from '../record-
|
|
4
|
-
import '../
|
|
5
|
-
import '../
|
|
6
|
-
import '../
|
|
7
|
-
import '../
|
|
1
|
+
import { d as RecordsDataSource, a as RecordsConfig } from '../ports-DYWE1ENo.js';
|
|
2
|
+
import { T as TemplateSpec } from '../types-hrw-Eff1.js';
|
|
3
|
+
import { P as PgError } from '../record-DmmeuUrC.js';
|
|
4
|
+
import '../field-B-WaVZnS.js';
|
|
5
|
+
import '../subscription-hdTaRrfK.js';
|
|
6
|
+
import '../rule-tN2lxvJ1.js';
|
|
7
|
+
import '../types-BauAeFW8.js';
|
|
8
8
|
|
|
9
9
|
type Json$1 = Record<string, unknown>;
|
|
10
10
|
/** One presented column, exactly as `platform.drill_describe(...).api.columns[]` says it. */
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { d as RecordsDataSource } from './ports-DYWE1ENo.js';
|
|
2
|
+
|
|
3
|
+
/** What kind of object the id is, as `custom.where_id_opens` names it — carried as the door's own word. */
|
|
4
|
+
type ObjectKind = string;
|
|
5
|
+
type ObjectOrganizationAnswer =
|
|
6
|
+
/** The store named the object's organization, and the person may open the object. */
|
|
7
|
+
{
|
|
8
|
+
state: "found";
|
|
9
|
+
organizationId: string;
|
|
10
|
+
kind: ObjectKind;
|
|
11
|
+
/** The screen the store says opens it (`/data/<table>?record=…`), or null for a part with none. */
|
|
12
|
+
path: string | null;
|
|
13
|
+
/** False when it is in the trash — the person may still open it, to bring it back. */
|
|
14
|
+
live: boolean;
|
|
15
|
+
/** The id it answers as — a merged record's survivor. */
|
|
16
|
+
resolvedId: string;
|
|
17
|
+
}
|
|
18
|
+
/** Not given to this person — or not there at all. The store does not say which, on purpose. */
|
|
19
|
+
| {
|
|
20
|
+
state: "not-given";
|
|
21
|
+
}
|
|
22
|
+
/** We could not ask. NOT an answer about the person's access. */
|
|
23
|
+
| {
|
|
24
|
+
state: "unavailable";
|
|
25
|
+
why: string;
|
|
26
|
+
};
|
|
27
|
+
/** Which organization owns an object — the port `createRecords({ organizationOf })` accepts. */
|
|
28
|
+
interface RecordOrganizationPort {
|
|
29
|
+
organizationOf(id: string): Promise<ObjectOrganizationAnswer>;
|
|
30
|
+
}
|
|
31
|
+
declare const WHERE_ID_OPENS_DOOR = "where_id_opens";
|
|
32
|
+
/** Ask the store which organization `id` lives in — the one call an object page makes before any other door. */
|
|
33
|
+
declare function resolveObjectOrganization(dataSource: Pick<RecordsDataSource, "rpc">, id: string): Promise<ObjectOrganizationAnswer>;
|
|
34
|
+
/** Read one `custom.where_id_opens` answer — asked here, or asked by a server render as the same person. */
|
|
35
|
+
declare function readObjectOrganizationAnswer(answered: {
|
|
36
|
+
data: unknown;
|
|
37
|
+
error: {
|
|
38
|
+
code?: string | null;
|
|
39
|
+
message?: string | null;
|
|
40
|
+
} | null;
|
|
41
|
+
}, id: string): ObjectOrganizationAnswer;
|
|
42
|
+
/** The default port: one `custom.where_id_opens` call per ask, nothing kept. */
|
|
43
|
+
declare function whereIdOpensPort(dataSource: Pick<RecordsDataSource, "rpc">): RecordOrganizationPort;
|
|
44
|
+
|
|
45
|
+
export { type ObjectOrganizationAnswer as O, type RecordOrganizationPort as R, WHERE_ID_OPENS_DOOR as W, type ObjectKind as a, resolveObjectOrganization as b, readObjectOrganizationAnswer as r, whereIdOpensPort as w };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { d as RecordsDataSource } from './ports-9BQ3zo2y.cjs';
|
|
2
|
+
|
|
3
|
+
/** What kind of object the id is, as `custom.where_id_opens` names it — carried as the door's own word. */
|
|
4
|
+
type ObjectKind = string;
|
|
5
|
+
type ObjectOrganizationAnswer =
|
|
6
|
+
/** The store named the object's organization, and the person may open the object. */
|
|
7
|
+
{
|
|
8
|
+
state: "found";
|
|
9
|
+
organizationId: string;
|
|
10
|
+
kind: ObjectKind;
|
|
11
|
+
/** The screen the store says opens it (`/data/<table>?record=…`), or null for a part with none. */
|
|
12
|
+
path: string | null;
|
|
13
|
+
/** False when it is in the trash — the person may still open it, to bring it back. */
|
|
14
|
+
live: boolean;
|
|
15
|
+
/** The id it answers as — a merged record's survivor. */
|
|
16
|
+
resolvedId: string;
|
|
17
|
+
}
|
|
18
|
+
/** Not given to this person — or not there at all. The store does not say which, on purpose. */
|
|
19
|
+
| {
|
|
20
|
+
state: "not-given";
|
|
21
|
+
}
|
|
22
|
+
/** We could not ask. NOT an answer about the person's access. */
|
|
23
|
+
| {
|
|
24
|
+
state: "unavailable";
|
|
25
|
+
why: string;
|
|
26
|
+
};
|
|
27
|
+
/** Which organization owns an object — the port `createRecords({ organizationOf })` accepts. */
|
|
28
|
+
interface RecordOrganizationPort {
|
|
29
|
+
organizationOf(id: string): Promise<ObjectOrganizationAnswer>;
|
|
30
|
+
}
|
|
31
|
+
declare const WHERE_ID_OPENS_DOOR = "where_id_opens";
|
|
32
|
+
/** Ask the store which organization `id` lives in — the one call an object page makes before any other door. */
|
|
33
|
+
declare function resolveObjectOrganization(dataSource: Pick<RecordsDataSource, "rpc">, id: string): Promise<ObjectOrganizationAnswer>;
|
|
34
|
+
/** Read one `custom.where_id_opens` answer — asked here, or asked by a server render as the same person. */
|
|
35
|
+
declare function readObjectOrganizationAnswer(answered: {
|
|
36
|
+
data: unknown;
|
|
37
|
+
error: {
|
|
38
|
+
code?: string | null;
|
|
39
|
+
message?: string | null;
|
|
40
|
+
} | null;
|
|
41
|
+
}, id: string): ObjectOrganizationAnswer;
|
|
42
|
+
/** The default port: one `custom.where_id_opens` call per ask, nothing kept. */
|
|
43
|
+
declare function whereIdOpensPort(dataSource: Pick<RecordsDataSource, "rpc">): RecordOrganizationPort;
|
|
44
|
+
|
|
45
|
+
export { type ObjectOrganizationAnswer as O, type RecordOrganizationPort as R, WHERE_ID_OPENS_DOOR as W, type ObjectKind as a, resolveObjectOrganization as b, readObjectOrganizationAnswer as r, whereIdOpensPort as w };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { L as Lane, H as HostDataPort, V as Values } from './types-
|
|
2
|
-
import { U as Uuid, R as RecordsResult } from './record-
|
|
1
|
+
import { L as Lane, H as HostDataPort, V as Values } from './types-HVgWcZDY.js';
|
|
2
|
+
import { U as Uuid, R as RecordsResult } from './record-DmmeuUrC.js';
|
|
3
|
+
import { O as OpLedger } from './ports-DYWE1ENo.js';
|
|
3
4
|
import * as _ai_matrx_realtime from '@ai-matrx/realtime';
|
|
4
5
|
import { RealtimeManager, ChannelSpec } from '@ai-matrx/realtime';
|
|
5
6
|
|
|
@@ -272,6 +273,8 @@ interface CreateEntityDataPortOptions {
|
|
|
272
273
|
organization?: Uuid | null;
|
|
273
274
|
/** The host's live-notice layer (`createEntityRealtime`). Left out, lists are as fresh as their last read. */
|
|
274
275
|
realtime?: EntityRealtime;
|
|
276
|
+
/** This port's own-write memory (`createOpLedger()`); absent ⇒ the realm's default ledger. */
|
|
277
|
+
opLedger?: OpLedger;
|
|
275
278
|
}
|
|
276
279
|
/** A value as rows carry it → as the write doors take it: a link (`EntityRef[]` or one ref) becomes its id. */
|
|
277
280
|
declare function toWireValue(value: unknown): unknown;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { L as Lane, H as HostDataPort, V as Values } from './types-
|
|
2
|
-
import { U as Uuid, R as RecordsResult } from './record-
|
|
1
|
+
import { L as Lane, H as HostDataPort, V as Values } from './types-Dek9owBe.cjs';
|
|
2
|
+
import { U as Uuid, R as RecordsResult } from './record-DmmeuUrC.cjs';
|
|
3
|
+
import { O as OpLedger } from './ports-9BQ3zo2y.cjs';
|
|
3
4
|
import * as _ai_matrx_realtime from '@ai-matrx/realtime';
|
|
4
5
|
import { RealtimeManager, ChannelSpec } from '@ai-matrx/realtime';
|
|
5
6
|
|
|
@@ -272,6 +273,8 @@ interface CreateEntityDataPortOptions {
|
|
|
272
273
|
organization?: Uuid | null;
|
|
273
274
|
/** The host's live-notice layer (`createEntityRealtime`). Left out, lists are as fresh as their last read. */
|
|
274
275
|
realtime?: EntityRealtime;
|
|
276
|
+
/** This port's own-write memory (`createOpLedger()`); absent ⇒ the realm's default ledger. */
|
|
277
|
+
opLedger?: OpLedger;
|
|
275
278
|
}
|
|
276
279
|
/** A value as rows carry it → as the write doors take it: a link (`EntityRef[]` or one ref) becomes its id. */
|
|
277
280
|
declare function toWireValue(value: unknown): unknown;
|
|
@@ -1,4 +1,80 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { b as Field } from './field-6rwt4ejZ.cjs';
|
|
2
|
+
import { U as Uuid, A as Actor, P as PgError, l as RecordDocument } from './record-DmmeuUrC.cjs';
|
|
3
|
+
|
|
4
|
+
/** `public.permission_level`, in the store's own order. */
|
|
5
|
+
/**
|
|
6
|
+
* `edit_content` (Notion's "Can edit content") sits between `commenter` and `editor`: it may change
|
|
7
|
+
* the rows and page content of a thing, never its structure (columns, views, settings) or its
|
|
8
|
+
* sharing — those stay with `editor` and `admin`.
|
|
9
|
+
*/
|
|
10
|
+
type PermissionLevel = "viewer" | "commenter" | "edit_content" | "editor" | "admin";
|
|
11
|
+
/** The order the store writes them in, lowest first. */
|
|
12
|
+
declare const PERMISSION_LEVELS: readonly PermissionLevel[];
|
|
13
|
+
/** Whether `held` is the same rung as `needed` or a higher one. Nothing held is never enough. */
|
|
14
|
+
declare function atLeast(held: PermissionLevel | null | undefined, needed: PermissionLevel): boolean;
|
|
15
|
+
/** A level word the store sent, or null when it sent something this package does not know. */
|
|
16
|
+
declare function asPermissionLevel(word: unknown): PermissionLevel | null;
|
|
17
|
+
/** The higher of two levels — what a person holds when two ways in both let them through. */
|
|
18
|
+
declare function highestLevel(left: PermissionLevel | null | undefined, right: PermissionLevel | null | undefined): PermissionLevel | null;
|
|
19
|
+
/**
|
|
20
|
+
* What one subject's level is, as `custom.my_levels` answers it. `null` is an
|
|
21
|
+
* ANSWER — "you hold nothing on this" — and never a missing row: a screen that
|
|
22
|
+
* could not tell "no access" from "not asked yet" would draw one of them as the
|
|
23
|
+
* other.
|
|
24
|
+
*/
|
|
25
|
+
interface MyLevel {
|
|
26
|
+
id: string;
|
|
27
|
+
level: PermissionLevel | null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* One client's memory of its own operations. `mint()` names a write and remembers it; `isOwn(opId)`
|
|
32
|
+
* answers whether a notice is that write's echo.
|
|
33
|
+
*
|
|
34
|
+
* OWN-WRITE DETECTION IS PER CLIENT INSTANCE. Two setups in ONE process (a server holding two
|
|
35
|
+
* identities, a worker beside a UI) must hear each other: a realm-wide ledger made A's write "ours" to
|
|
36
|
+
* B as well, and B dropped it as an echo (2026-10-08, the README proof). `createRecords` gives every
|
|
37
|
+
* setup its own ledger and hands it to its client, its entity port and its live-changes port.
|
|
38
|
+
*/
|
|
39
|
+
interface OpLedger {
|
|
40
|
+
mint(): Uuid;
|
|
41
|
+
isOwn(opId: string | null | undefined): boolean;
|
|
42
|
+
/** Test seam: forget everything. */
|
|
43
|
+
clear(): void;
|
|
44
|
+
/** Test seam: how many operations are currently remembered. */
|
|
45
|
+
readonly size: number;
|
|
46
|
+
}
|
|
47
|
+
/** A ledger of one client's own: hand the SAME one to the client that writes and the port that listens. */
|
|
48
|
+
declare function createOpLedger(): OpLedger;
|
|
49
|
+
/**
|
|
50
|
+
* THE REALM'S DEFAULT LEDGER, IN A GLOBAL SLOT — for hosts that mount one client per realm (a browser
|
|
51
|
+
* tab) and never name a ledger. Every section of the built package (root, core, react, realtime, data,
|
|
52
|
+
* typed-table) carries its own copy of this module, and the ESM and CJS builds are two more graphs; a
|
|
53
|
+
* module-level Map split it so `records/core` minted in one and `records/realtime` checked another — own
|
|
54
|
+
* writes came back as strangers' changes (2026-10-08). Guarded on the packed tarball by
|
|
55
|
+
* scripts/check-shared-state.mjs.
|
|
56
|
+
*/
|
|
57
|
+
declare const defaultOpLedger: OpLedger;
|
|
58
|
+
/**
|
|
59
|
+
* Mint the id for one client operation and remember it as ours (the realm's default ledger).
|
|
60
|
+
*
|
|
61
|
+
* ONE CALL IS ONE OPERATION. A fifty-row paste through `recordWriteMany` is ONE op id, because
|
|
62
|
+
* the store announces one statement once — and it REFUSES a batch carrying two different ones
|
|
63
|
+
* by name, for exactly that reason.
|
|
64
|
+
*/
|
|
65
|
+
declare function mintOpId(): Uuid;
|
|
66
|
+
/**
|
|
67
|
+
* Is this notice the echo of a write this realm's default ledger made?
|
|
68
|
+
*
|
|
69
|
+
* `undefined`/`null` is NOT ours and never has been: a notice with no `op_id` came from a
|
|
70
|
+
* server-side write, an agent tool, another client, or a store older than this mechanism —
|
|
71
|
+
* all of which are changes this browser has not seen and must read.
|
|
72
|
+
*/
|
|
73
|
+
declare function isOwnOp(opId: string | null | undefined): boolean;
|
|
74
|
+
/** Test seam: forget everything. Never called by product code. */
|
|
75
|
+
declare function forgetAllOps(): void;
|
|
76
|
+
/** Test seam: how many operations are currently remembered. */
|
|
77
|
+
declare function rememberedOpCount(): number;
|
|
2
78
|
|
|
3
79
|
/**
|
|
4
80
|
* The data seam: a structural subset of `SupabaseClient`. The package never
|
|
@@ -173,6 +249,11 @@ interface RecordsConfig {
|
|
|
173
249
|
*/
|
|
174
250
|
organizationIds?: readonly Uuid[];
|
|
175
251
|
realtime?: RecordsRealtimePort;
|
|
252
|
+
/**
|
|
253
|
+
* This client's own-write memory (`createOpLedger()`). Hand the SAME ledger to the live-changes port
|
|
254
|
+
* that listens for this client. Absent ⇒ the realm's default ledger (one client per browser tab).
|
|
255
|
+
*/
|
|
256
|
+
opLedger?: OpLedger;
|
|
176
257
|
onError?: RecordsErrorSink;
|
|
177
258
|
resolver?: RecordsResolverPort;
|
|
178
259
|
/**
|
|
@@ -189,5 +270,30 @@ interface RecordsConfig {
|
|
|
189
270
|
*/
|
|
190
271
|
knownDoors?: readonly string[];
|
|
191
272
|
}
|
|
273
|
+
/**
|
|
274
|
+
* RUN AN AGENT ON THIS ROW — a PORT (step 10, 2026-10-08). A table's agent button ("Draft follow-up") hands
|
|
275
|
+
* the row to an agent with the action's own prompt. The store ships no agent: the host binds the run (the
|
|
276
|
+
* agent run itself belongs to `@ai-matrx/agents`; the website starts it through the `data.row_action`
|
|
277
|
+
* mandate). Everything the run needs rides the target, read as THIS reader sees it — no second read.
|
|
278
|
+
*/
|
|
279
|
+
interface RowAgentTarget {
|
|
280
|
+
tableId: Uuid;
|
|
281
|
+
recordId: Uuid;
|
|
282
|
+
title: string;
|
|
283
|
+
action: string;
|
|
284
|
+
prompt: string;
|
|
285
|
+
/** The table's name, as the reader sees it. */
|
|
286
|
+
tableName: string;
|
|
287
|
+
/** The table's columns. */
|
|
288
|
+
fields: readonly Field[];
|
|
289
|
+
/** The row, masked for this reader. */
|
|
290
|
+
document: RecordDocument;
|
|
291
|
+
/** This reader's level on the row. */
|
|
292
|
+
level: PermissionLevel | null;
|
|
293
|
+
}
|
|
294
|
+
/** The host's agent runner — `createRecords({ rowAgent })`; records-ui's grid calls it for `kind: "agent"` actions. */
|
|
295
|
+
interface RowAgentPort {
|
|
296
|
+
run(target: RowAgentTarget): void | Promise<void>;
|
|
297
|
+
}
|
|
192
298
|
|
|
193
|
-
export type
|
|
299
|
+
export { type MyLevel as M, type OpLedger as O, PERMISSION_LEVELS as P, type RecordsRealtimePort as R, type RecordsConfig as a, type RowAgentPort as b, type RecordsErrorSink as c, type RecordsDataSource as d, type RecordsChangeSink as e, type RowAgentTarget as f, type PermissionLevel as g, type RecordsActor as h, type RecordsFilter as i, type RecordsResolverPort as j, type RecordsResponse as k, type RecordsTableQuery as l, asPermissionLevel as m, atLeast as n, createOpLedger as o, defaultOpLedger as p, forgetAllOps as q, highestLevel as r, isOwnOp as s, mintOpId as t, rememberedOpCount as u };
|
|
@@ -1,4 +1,80 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { b as Field } from './field-B-WaVZnS.js';
|
|
2
|
+
import { U as Uuid, A as Actor, P as PgError, l as RecordDocument } from './record-DmmeuUrC.js';
|
|
3
|
+
|
|
4
|
+
/** `public.permission_level`, in the store's own order. */
|
|
5
|
+
/**
|
|
6
|
+
* `edit_content` (Notion's "Can edit content") sits between `commenter` and `editor`: it may change
|
|
7
|
+
* the rows and page content of a thing, never its structure (columns, views, settings) or its
|
|
8
|
+
* sharing — those stay with `editor` and `admin`.
|
|
9
|
+
*/
|
|
10
|
+
type PermissionLevel = "viewer" | "commenter" | "edit_content" | "editor" | "admin";
|
|
11
|
+
/** The order the store writes them in, lowest first. */
|
|
12
|
+
declare const PERMISSION_LEVELS: readonly PermissionLevel[];
|
|
13
|
+
/** Whether `held` is the same rung as `needed` or a higher one. Nothing held is never enough. */
|
|
14
|
+
declare function atLeast(held: PermissionLevel | null | undefined, needed: PermissionLevel): boolean;
|
|
15
|
+
/** A level word the store sent, or null when it sent something this package does not know. */
|
|
16
|
+
declare function asPermissionLevel(word: unknown): PermissionLevel | null;
|
|
17
|
+
/** The higher of two levels — what a person holds when two ways in both let them through. */
|
|
18
|
+
declare function highestLevel(left: PermissionLevel | null | undefined, right: PermissionLevel | null | undefined): PermissionLevel | null;
|
|
19
|
+
/**
|
|
20
|
+
* What one subject's level is, as `custom.my_levels` answers it. `null` is an
|
|
21
|
+
* ANSWER — "you hold nothing on this" — and never a missing row: a screen that
|
|
22
|
+
* could not tell "no access" from "not asked yet" would draw one of them as the
|
|
23
|
+
* other.
|
|
24
|
+
*/
|
|
25
|
+
interface MyLevel {
|
|
26
|
+
id: string;
|
|
27
|
+
level: PermissionLevel | null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* One client's memory of its own operations. `mint()` names a write and remembers it; `isOwn(opId)`
|
|
32
|
+
* answers whether a notice is that write's echo.
|
|
33
|
+
*
|
|
34
|
+
* OWN-WRITE DETECTION IS PER CLIENT INSTANCE. Two setups in ONE process (a server holding two
|
|
35
|
+
* identities, a worker beside a UI) must hear each other: a realm-wide ledger made A's write "ours" to
|
|
36
|
+
* B as well, and B dropped it as an echo (2026-10-08, the README proof). `createRecords` gives every
|
|
37
|
+
* setup its own ledger and hands it to its client, its entity port and its live-changes port.
|
|
38
|
+
*/
|
|
39
|
+
interface OpLedger {
|
|
40
|
+
mint(): Uuid;
|
|
41
|
+
isOwn(opId: string | null | undefined): boolean;
|
|
42
|
+
/** Test seam: forget everything. */
|
|
43
|
+
clear(): void;
|
|
44
|
+
/** Test seam: how many operations are currently remembered. */
|
|
45
|
+
readonly size: number;
|
|
46
|
+
}
|
|
47
|
+
/** A ledger of one client's own: hand the SAME one to the client that writes and the port that listens. */
|
|
48
|
+
declare function createOpLedger(): OpLedger;
|
|
49
|
+
/**
|
|
50
|
+
* THE REALM'S DEFAULT LEDGER, IN A GLOBAL SLOT — for hosts that mount one client per realm (a browser
|
|
51
|
+
* tab) and never name a ledger. Every section of the built package (root, core, react, realtime, data,
|
|
52
|
+
* typed-table) carries its own copy of this module, and the ESM and CJS builds are two more graphs; a
|
|
53
|
+
* module-level Map split it so `records/core` minted in one and `records/realtime` checked another — own
|
|
54
|
+
* writes came back as strangers' changes (2026-10-08). Guarded on the packed tarball by
|
|
55
|
+
* scripts/check-shared-state.mjs.
|
|
56
|
+
*/
|
|
57
|
+
declare const defaultOpLedger: OpLedger;
|
|
58
|
+
/**
|
|
59
|
+
* Mint the id for one client operation and remember it as ours (the realm's default ledger).
|
|
60
|
+
*
|
|
61
|
+
* ONE CALL IS ONE OPERATION. A fifty-row paste through `recordWriteMany` is ONE op id, because
|
|
62
|
+
* the store announces one statement once — and it REFUSES a batch carrying two different ones
|
|
63
|
+
* by name, for exactly that reason.
|
|
64
|
+
*/
|
|
65
|
+
declare function mintOpId(): Uuid;
|
|
66
|
+
/**
|
|
67
|
+
* Is this notice the echo of a write this realm's default ledger made?
|
|
68
|
+
*
|
|
69
|
+
* `undefined`/`null` is NOT ours and never has been: a notice with no `op_id` came from a
|
|
70
|
+
* server-side write, an agent tool, another client, or a store older than this mechanism —
|
|
71
|
+
* all of which are changes this browser has not seen and must read.
|
|
72
|
+
*/
|
|
73
|
+
declare function isOwnOp(opId: string | null | undefined): boolean;
|
|
74
|
+
/** Test seam: forget everything. Never called by product code. */
|
|
75
|
+
declare function forgetAllOps(): void;
|
|
76
|
+
/** Test seam: how many operations are currently remembered. */
|
|
77
|
+
declare function rememberedOpCount(): number;
|
|
2
78
|
|
|
3
79
|
/**
|
|
4
80
|
* The data seam: a structural subset of `SupabaseClient`. The package never
|
|
@@ -173,6 +249,11 @@ interface RecordsConfig {
|
|
|
173
249
|
*/
|
|
174
250
|
organizationIds?: readonly Uuid[];
|
|
175
251
|
realtime?: RecordsRealtimePort;
|
|
252
|
+
/**
|
|
253
|
+
* This client's own-write memory (`createOpLedger()`). Hand the SAME ledger to the live-changes port
|
|
254
|
+
* that listens for this client. Absent ⇒ the realm's default ledger (one client per browser tab).
|
|
255
|
+
*/
|
|
256
|
+
opLedger?: OpLedger;
|
|
176
257
|
onError?: RecordsErrorSink;
|
|
177
258
|
resolver?: RecordsResolverPort;
|
|
178
259
|
/**
|
|
@@ -189,5 +270,30 @@ interface RecordsConfig {
|
|
|
189
270
|
*/
|
|
190
271
|
knownDoors?: readonly string[];
|
|
191
272
|
}
|
|
273
|
+
/**
|
|
274
|
+
* RUN AN AGENT ON THIS ROW — a PORT (step 10, 2026-10-08). A table's agent button ("Draft follow-up") hands
|
|
275
|
+
* the row to an agent with the action's own prompt. The store ships no agent: the host binds the run (the
|
|
276
|
+
* agent run itself belongs to `@ai-matrx/agents`; the website starts it through the `data.row_action`
|
|
277
|
+
* mandate). Everything the run needs rides the target, read as THIS reader sees it — no second read.
|
|
278
|
+
*/
|
|
279
|
+
interface RowAgentTarget {
|
|
280
|
+
tableId: Uuid;
|
|
281
|
+
recordId: Uuid;
|
|
282
|
+
title: string;
|
|
283
|
+
action: string;
|
|
284
|
+
prompt: string;
|
|
285
|
+
/** The table's name, as the reader sees it. */
|
|
286
|
+
tableName: string;
|
|
287
|
+
/** The table's columns. */
|
|
288
|
+
fields: readonly Field[];
|
|
289
|
+
/** The row, masked for this reader. */
|
|
290
|
+
document: RecordDocument;
|
|
291
|
+
/** This reader's level on the row. */
|
|
292
|
+
level: PermissionLevel | null;
|
|
293
|
+
}
|
|
294
|
+
/** The host's agent runner — `createRecords({ rowAgent })`; records-ui's grid calls it for `kind: "agent"` actions. */
|
|
295
|
+
interface RowAgentPort {
|
|
296
|
+
run(target: RowAgentTarget): void | Promise<void>;
|
|
297
|
+
}
|
|
192
298
|
|
|
193
|
-
export type
|
|
299
|
+
export { type MyLevel as M, type OpLedger as O, PERMISSION_LEVELS as P, type RecordsRealtimePort as R, type RecordsConfig as a, type RowAgentPort as b, type RecordsErrorSink as c, type RecordsDataSource as d, type RecordsChangeSink as e, type RowAgentTarget as f, type PermissionLevel as g, type RecordsActor as h, type RecordsFilter as i, type RecordsResolverPort as j, type RecordsResponse as k, type RecordsTableQuery as l, asPermissionLevel as m, atLeast as n, createOpLedger as o, defaultOpLedger as p, forgetAllOps as q, highestLevel as r, isOwnOp as s, mintOpId as t, rememberedOpCount as u };
|