@ai-matrx/records 0.48.0 → 0.49.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 +30 -0
- package/dist/core/index.cjs +28 -2
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +20 -8
- package/dist/core/index.d.ts +20 -8
- package/dist/core/index.js +28 -2
- package/dist/core/index.js.map +1 -1
- package/dist/{field-CFK39l0H.d.cts → field-z68hD9VX.d.cts} +5 -0
- package/dist/{field-CFK39l0H.d.ts → field-z68hD9VX.d.ts} +5 -0
- package/dist/index.cjs +17 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +37 -5
- package/dist/index.d.ts +37 -5
- package/dist/index.js +17 -1
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +41 -8
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +64 -6
- package/dist/react/index.d.ts +64 -6
- package/dist/react/index.js +41 -8
- package/dist/react/index.js.map +1 -1
- package/dist/use-cases/index.cjs.map +1 -1
- package/dist/use-cases/index.d.cts +1 -1
- package/dist/use-cases/index.d.ts +1 -1
- package/dist/use-cases/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# Changelog — @ai-matrx/records
|
|
2
2
|
|
|
3
|
+
## 0.49.0
|
|
4
|
+
|
|
5
|
+
**A number on a dashboard can be walked into.** (lane DRILL.)
|
|
6
|
+
|
|
7
|
+
* **`custom.read_records_matching` — the store's filtered read door**, and `client.list` now
|
|
8
|
+
asks it for EVERY page, filtered or not, with `{}` when nobody asked a question. The grid,
|
|
9
|
+
the board, the record list and a dashboard drill-through are therefore one door, decided by
|
|
10
|
+
one ladder: a narrowed screen can never be a differently-judged screen. `list({ filter })`
|
|
11
|
+
and `useRecords(tableId, { filter })` are how a caller asks.
|
|
12
|
+
* **`RecordFilter` — the ONE name for the store's filter shape.** It is not new and never was
|
|
13
|
+
the aggregate's private shape: `platform.saved_view` has carried exactly this object of
|
|
14
|
+
Field key → value as `definition -> 'filters'` since DOOR-18, `custom.view_declare` writes
|
|
15
|
+
it, `custom.agg_view_admits` reads it, and `custom.record_aggregate` takes it as `p_filter`.
|
|
16
|
+
A scalar is an equality, `null` is UNSET (the third state of a tick box), an object is a
|
|
17
|
+
half-open time window. `SavedViewRow.filters` and `SavedViewSpecIn.filters` were
|
|
18
|
+
`Record<string, unknown>` and are this now — an `unknown` there is a digest that quietly
|
|
19
|
+
notifies about the wrong records.
|
|
20
|
+
* **One evaluator in the database, not two.** `custom.agg_sql`'s filter loop moved verbatim
|
|
21
|
+
into `custom.record_filter_sql` and the aggregate CALLS it, so the number a chart draws and
|
|
22
|
+
the rows a drill lands on are produced by the same bytes. Measured on Rincon Plumbing Co's
|
|
23
|
+
41 live jobs: the chart says Cancelled 4, the door hands back RPC-1036…1039 and nothing
|
|
24
|
+
else; the rendered choice label and the stored key both land on the same four; a window on
|
|
25
|
+
`scheduled_date` answers 5 through both doors.
|
|
26
|
+
* **Why it is a new name and not a sixth argument** — the REALTIME-2 ruling, again: a defaulted
|
|
27
|
+
`p_filter` beside the live five-argument `custom.read_records` makes every existing call
|
|
28
|
+
ambiguous, and the only way to add it in place is to drop a live door.
|
|
29
|
+
* **`stableFilterKey`** — key-sorted JSON of a `RecordFilter`, so a React parent that rebuilds
|
|
30
|
+
`{ status: "Cancelled" }` on every render re-reads the page when the QUESTION changes rather
|
|
31
|
+
than on every render forever.
|
|
32
|
+
|
|
3
33
|
## 0.48.0
|
|
4
34
|
|
|
5
35
|
**A portal principal carries the link the office copies for them.** (lane TAILS-5.)
|
package/dist/core/index.cjs
CHANGED
|
@@ -124,6 +124,7 @@ __export(core_exports, {
|
|
|
124
124
|
publicFormPath: () => publicFormPath,
|
|
125
125
|
rememberedOpCount: () => rememberedOpCount,
|
|
126
126
|
scopeChip: () => scopeChip,
|
|
127
|
+
stableFilterKey: () => stableFilterKey,
|
|
127
128
|
staleWriteDetail: () => staleWriteDetail,
|
|
128
129
|
supabaseDataSource: () => supabaseDataSource,
|
|
129
130
|
toAoa: () => toAoa
|
|
@@ -484,6 +485,20 @@ function portalPath(slug) {
|
|
|
484
485
|
function measureKey(measure) {
|
|
485
486
|
return measure.op === "count" ? "count" : `${measure.op}_${measure.key ?? ""}`;
|
|
486
487
|
}
|
|
488
|
+
function stableFilterKey(filter) {
|
|
489
|
+
if (!filter) return "{}";
|
|
490
|
+
const keys = Object.keys(filter).sort();
|
|
491
|
+
if (keys.length === 0) return "{}";
|
|
492
|
+
const parts = keys.map((key) => {
|
|
493
|
+
const value = filter[key];
|
|
494
|
+
if (value !== null && typeof value === "object") {
|
|
495
|
+
const window2 = value;
|
|
496
|
+
return `${JSON.stringify(key)}:{"from":${JSON.stringify(window2.from ?? null)},"to":${JSON.stringify(window2.to ?? null)}}`;
|
|
497
|
+
}
|
|
498
|
+
return `${JSON.stringify(key)}:${JSON.stringify(value ?? null)}`;
|
|
499
|
+
});
|
|
500
|
+
return `{${parts.join(",")}}`;
|
|
501
|
+
}
|
|
487
502
|
|
|
488
503
|
// src/capture-queue.ts
|
|
489
504
|
var DB_NAME = "matrx-capture";
|
|
@@ -1258,6 +1273,7 @@ var STORE_DOORS = [
|
|
|
1258
1273
|
{ name: "read_record", args: "p_organization_id uuid, p_record_id uuid, p_by_id boolean DEFAULT false", returns: "jsonb", security: "definer" },
|
|
1259
1274
|
{ name: "read_records", args: "p_organization_id uuid, p_table_id uuid, p_by_id boolean DEFAULT false, p_limit integer DEFAULT 200, p_offset integer DEFAULT 0", returns: "TABLE(id uuid, document jsonb, level permission_level)", security: "definer" },
|
|
1260
1275
|
{ name: "read_records_by_ids", args: "p_organization_id uuid, p_table_id uuid, p_record_ids uuid[], p_by_id boolean DEFAULT false", returns: "TABLE(id uuid, document jsonb, level permission_level)", security: "definer" },
|
|
1276
|
+
{ name: "read_records_matching", args: "p_organization_id uuid, p_table_id uuid, p_filter jsonb DEFAULT '{}'::jsonb, p_by_id boolean DEFAULT false, p_limit integer DEFAULT 200, p_offset integer DEFAULT 0", returns: "TABLE(id uuid, document jsonb, level permission_level)", security: "definer" },
|
|
1261
1277
|
{ name: "realtime_topic_admits", args: "p_topic text", returns: "boolean", security: "definer" },
|
|
1262
1278
|
{ name: "record_aggregate", args: "p_organization_id uuid, p_table_id uuid, p_group_by jsonb DEFAULT '[]'::jsonb, p_measures jsonb DEFAULT '[]'::jsonb, p_bucket jsonb DEFAULT NULL::jsonb, p_filter jsonb DEFAULT '{}'::jsonb, p_limit integer DEFAULT 200, p_required text DEFAULT 'viewer'::text", returns: "TABLE(groups jsonb, measures jsonb, row_count bigint)", security: "definer" },
|
|
1263
1279
|
{ name: "record_applicability", args: "p_organization_id uuid, p_record_id uuid", returns: "TABLE(rule_id uuid, rule_name text, rule_version integer, applies boolean, answer jsonb)", security: "invoker" },
|
|
@@ -2592,6 +2608,15 @@ var DOORS = {
|
|
|
2592
2608
|
// live Postgres function makes every existing call ambiguous — `is not unique`. Same
|
|
2593
2609
|
// ladder, same level, same masking, same page ceiling.
|
|
2594
2610
|
readRecordsByIds: "read_records_by_ids",
|
|
2611
|
+
// THE SAME READ DOOR, ADDRESSED BY A QUESTION. `custom.read_records_matching`
|
|
2612
|
+
// takes the store's one filter shape (`RecordFilter` — the object
|
|
2613
|
+
// `platform.saved_view` carries as `filters` and `custom.record_aggregate`
|
|
2614
|
+
// takes as `p_filter`) and narrows the page INSIDE its own query, in the same
|
|
2615
|
+
// WHERE as Visibility. A separate NAME for the same reason as above. It is
|
|
2616
|
+
// what makes a number on a dashboard walkable: the filter is evaluated by
|
|
2617
|
+
// `custom.record_filter_sql`, the one body `custom.agg_sql` also calls, so the
|
|
2618
|
+
// rows it opens are the rows the number counted.
|
|
2619
|
+
readRecordsMatching: "read_records_matching",
|
|
2595
2620
|
// DOOR-8, the two clocks. `p_recorded_at` is what the store SAID then;
|
|
2596
2621
|
// `p_world_on` is what was TRUE of the world on that date, read out of dated
|
|
2597
2622
|
// values. A client that answered either one itself would be guessing.
|
|
@@ -3291,12 +3316,13 @@ function createRecordsClient(config) {
|
|
|
3291
3316
|
})
|
|
3292
3317
|
);
|
|
3293
3318
|
},
|
|
3294
|
-
async list({ table_id, limit = 50, offset = 0 }) {
|
|
3319
|
+
async list({ table_id, filter, limit = 50, offset = 0 }) {
|
|
3295
3320
|
const door = await callDoor(
|
|
3296
|
-
DOORS.
|
|
3321
|
+
DOORS.readRecordsMatching,
|
|
3297
3322
|
{
|
|
3298
3323
|
p_organization_id: org,
|
|
3299
3324
|
p_table_id: table_id,
|
|
3325
|
+
p_filter: filter ?? {},
|
|
3300
3326
|
p_limit: limit,
|
|
3301
3327
|
p_offset: offset
|
|
3302
3328
|
},
|