@fuzdev/fuz_app 0.142.0 → 0.144.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/dist/auth/CLAUDE.md +8 -0
- package/dist/auth/cell_action_specs.d.ts +13 -0
- package/dist/auth/cell_action_specs.d.ts.map +1 -1
- package/dist/auth/cell_action_specs.js +13 -0
- package/dist/auth/cell_actions.d.ts +7 -0
- package/dist/auth/cell_actions.d.ts.map +1 -1
- package/dist/auth/cell_actions.js +30 -0
- package/dist/auth/cell_ref_admission.d.ts +51 -0
- package/dist/auth/cell_ref_admission.d.ts.map +1 -0
- package/dist/auth/cell_ref_admission.js +69 -0
- package/dist/auth/deps.d.ts +6 -3
- package/dist/auth/deps.d.ts.map +1 -1
- package/dist/db/CLAUDE.md +34 -21
- package/dist/db/cell_ddl.d.ts +3 -2
- package/dist/db/cell_ddl.d.ts.map +1 -1
- package/dist/db/cell_ddl.js +3 -2
- package/dist/db/cell_queries.d.ts +31 -6
- package/dist/db/cell_queries.d.ts.map +1 -1
- package/dist/db/cell_queries.js +45 -18
- package/dist/db/fact_ddl.d.ts +29 -4
- package/dist/db/fact_ddl.d.ts.map +1 -1
- package/dist/db/fact_ddl.js +43 -4
- package/dist/db/fact_holder_queries.d.ts +66 -0
- package/dist/db/fact_holder_queries.d.ts.map +1 -0
- package/dist/db/fact_holder_queries.js +75 -0
- package/dist/db/fact_queries.d.ts +9 -7
- package/dist/db/fact_queries.d.ts.map +1 -1
- package/dist/db/fact_store.d.ts +65 -9
- package/dist/db/fact_store.d.ts.map +1 -1
- package/dist/db/fact_store.js +49 -20
- package/dist/http/CLAUDE.md +1 -1
- package/dist/http/ip_canonical.d.ts +26 -2
- package/dist/http/ip_canonical.d.ts.map +1 -1
- package/dist/http/ip_canonical.js +107 -42
- package/dist/server/serve_fact_route.d.ts +24 -4
- package/dist/server/serve_fact_route.d.ts.map +1 -1
- package/dist/server/serve_fact_route.js +24 -4
- package/dist/testing/CLAUDE.md +31 -5
- package/dist/testing/cross_backend/cell_crud.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_crud.js +6 -3
- package/dist/testing/cross_backend/cell_gated_create.d.ts.map +1 -1
- package/dist/testing/cross_backend/cell_gated_create.js +25 -16
- package/dist/testing/cross_backend/cell_ref_admission.d.ts +4 -0
- package/dist/testing/cross_backend/cell_ref_admission.d.ts.map +1 -0
- package/dist/testing/cross_backend/cell_ref_admission.js +268 -0
- package/dist/testing/cross_backend/expected_schema.json +66 -10
- package/dist/testing/cross_backend/fact_serving.d.ts +19 -1
- package/dist/testing/cross_backend/fact_serving.d.ts.map +1 -1
- package/dist/testing/cross_backend/fact_serving.js +31 -9
- package/dist/testing/cross_backend/full_spine_mount.js +2 -1
- package/dist/testing/cross_backend/origin_conformance.d.ts +1 -1
- package/dist/testing/cross_backend/origin_conformance.d.ts.map +1 -1
- package/dist/testing/cross_backend/origin_conformance.js +1 -1
- package/dist/testing/cross_backend/spine_surface_constants.d.ts +12 -20
- package/dist/testing/cross_backend/spine_surface_constants.d.ts.map +1 -1
- package/dist/testing/cross_backend/spine_surface_constants.js +12 -20
- package/dist/testing/cross_backend/testing_origin_check.d.ts +128 -0
- package/dist/testing/cross_backend/testing_origin_check.d.ts.map +1 -0
- package/dist/testing/cross_backend/testing_origin_check.js +87 -0
- package/dist/testing/cross_backend/testing_reset_actions.d.ts +13 -121
- package/dist/testing/cross_backend/testing_reset_actions.d.ts.map +1 -1
- package/dist/testing/cross_backend/testing_reset_actions.js +21 -95
- package/package.json +1 -1
package/dist/db/cell_queries.js
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
* Convention: `deps: QueryDeps` first, no audit side effects, mutations
|
|
5
5
|
* return the affected row (or `null` for not-found).
|
|
6
6
|
*
|
|
7
|
-
* `cell.refs` is
|
|
8
|
-
* `
|
|
9
|
-
* never pass `refs` directly — the column is a derived
|
|
10
|
-
* `data
|
|
11
|
-
*
|
|
7
|
+
* `cell.refs` is derived from `data` on every create and update via
|
|
8
|
+
* `derive_cell_refs` (depth-first walk for string values that are exactly a
|
|
9
|
+
* fact hash). Callers never pass `refs` directly — the column is a derived
|
|
10
|
+
* projection of `data`, what fact serving admits a read through and what
|
|
11
|
+
* cell ref admission (`auth/cell_ref_admission.ts`) gates on a write.
|
|
12
12
|
*
|
|
13
13
|
* Soft delete via `deleted_at`. All `get` / `list` queries exclude
|
|
14
14
|
* tombstones by default; `include_deleted: true` opts in for admin /
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
*
|
|
21
21
|
* @module
|
|
22
22
|
*/
|
|
23
|
-
import {
|
|
23
|
+
import { is_fact_hash } from '@fuzdev/fuz_util/hash_schemas.ts';
|
|
24
24
|
import { assert_row } from './assert_row.js';
|
|
25
25
|
import { columns_sql, iso8601_timestamp_expr, qualify_columns } from './sql_columns.js';
|
|
26
26
|
import { cell_moderation_admits_audience_sql, cell_moderation_is_stewardable_sql } from './cell_moderation.js';
|
|
@@ -98,7 +98,7 @@ export const CELL_VIEW_COLUMNS = [
|
|
|
98
98
|
* @mutates `cell` - inserts one row
|
|
99
99
|
*/
|
|
100
100
|
export const query_cell_create = async (deps, input) => {
|
|
101
|
-
const refs =
|
|
101
|
+
const refs = derive_cell_refs(input.data);
|
|
102
102
|
const row = await deps.db.query_one(`INSERT INTO cell
|
|
103
103
|
(data, kind, visibility, path, refs, parent_id, root_id, moderation, created_by)
|
|
104
104
|
VALUES ($1::jsonb, $2, COALESCE($3::cell_visibility, 'private'::cell_visibility), $4, $5::text[], $6, $7, $8, $9)
|
|
@@ -196,7 +196,7 @@ export const query_cell_view_load_many = async (deps, ids) => {
|
|
|
196
196
|
*/
|
|
197
197
|
export const query_cell_update = async (deps, id, patch) => {
|
|
198
198
|
const data_provided = patch.data !== undefined;
|
|
199
|
-
const refs = data_provided ?
|
|
199
|
+
const refs = data_provided ? derive_cell_refs(patch.data) : null;
|
|
200
200
|
const visibility_provided = patch.visibility !== undefined;
|
|
201
201
|
const row = await deps.db.query_one(`UPDATE cell SET
|
|
202
202
|
data = CASE WHEN $2::bool THEN $3::jsonb ELSE data END,
|
|
@@ -485,20 +485,47 @@ const build_shared_with_sql = (order_column, order_direction) => `${CALLER_ROLE_
|
|
|
485
485
|
ORDER BY c.${order_column} ${order_direction} NULLS LAST
|
|
486
486
|
LIMIT $8 OFFSET $9`;
|
|
487
487
|
/**
|
|
488
|
-
* Derive the `refs` array column value from a cell's `data
|
|
488
|
+
* Derive the `refs` array column value from a cell's `data`: the string
|
|
489
|
+
* values that are exactly a fact hash, deduped and sorted.
|
|
490
|
+
*
|
|
491
|
+
* A ref is a **whole** string value matching the wire fact-hash grammar —
|
|
492
|
+
* `blake3:` followed by exactly sixty-four lowercase hex characters
|
|
493
|
+
* (`is_fact_hash`, `FACT_HASH_EXACT`). A hash inside prose or markup, an
|
|
494
|
+
* uppercase-hex digest, or a `blake3:` string of any other length is not a
|
|
495
|
+
* ref. Refs are what fact serving admits a read through and what cell ref
|
|
496
|
+
* admission gates on a write, so the grammar is exact: a string either is an
|
|
497
|
+
* address or isn't one. Object keys are not walked — only values. (JSON facts'
|
|
498
|
+
* `fact_ref` edges keep `fact_hash_extract_refs`, the substring scan.)
|
|
489
499
|
*
|
|
490
500
|
* Returns `null` (rather than `[]`) when no refs are present — the column
|
|
491
501
|
* is nullable and the `idx_cell_refs` partial index is `WHERE refs IS NOT
|
|
492
502
|
* NULL`, so an empty array would force every cell into the index.
|
|
493
503
|
*
|
|
494
|
-
* Sorts the deduped refs
|
|
495
|
-
*
|
|
496
|
-
*
|
|
497
|
-
*
|
|
498
|
-
*
|
|
499
|
-
*
|
|
504
|
+
* Sorts the deduped refs so the stored `text[]` is deterministic and
|
|
505
|
+
* byte-identical to the Rust twin (`fuz_cell`'s `extract_refs`); every ref is
|
|
506
|
+
* ASCII, so the code-unit sort here and the byte sort there agree.
|
|
507
|
+
*
|
|
508
|
+
* @param data - the cell's `data`
|
|
509
|
+
* @returns the sorted refs, or `null` when there are none
|
|
500
510
|
*/
|
|
501
|
-
const
|
|
502
|
-
const
|
|
503
|
-
|
|
511
|
+
export const derive_cell_refs = (data) => {
|
|
512
|
+
const found = new Set();
|
|
513
|
+
collect_cell_refs(data, found);
|
|
514
|
+
return found.size > 0 ? [...found].sort() : null;
|
|
515
|
+
};
|
|
516
|
+
const collect_cell_refs = (value, found) => {
|
|
517
|
+
if (typeof value === 'string') {
|
|
518
|
+
if (is_fact_hash(value))
|
|
519
|
+
found.add(value);
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
if (value === null || typeof value !== 'object')
|
|
523
|
+
return;
|
|
524
|
+
if (Array.isArray(value)) {
|
|
525
|
+
for (const item of value)
|
|
526
|
+
collect_cell_refs(item, found);
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
for (const v of Object.values(value))
|
|
530
|
+
collect_cell_refs(v, found);
|
|
504
531
|
};
|
package/dist/db/fact_ddl.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Fact + memo PG schema.
|
|
2
|
+
* Fact + memo + possession PG schema.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Tables:
|
|
5
5
|
*
|
|
6
6
|
* - `fact` — content-addressed bytes. `hash = 'blake3:<hex64>'`. Either
|
|
7
7
|
* embedded (`bytes`) or referenced (`external_url`); the CHECK constraint
|
|
@@ -11,6 +11,20 @@
|
|
|
11
11
|
* `target_hash` is intentionally **not** a foreign key: in federation a
|
|
12
12
|
* reference may target a fact stored on another instance.
|
|
13
13
|
* - `memo` — `(fn_id, input_hash) → output_hash` for memoized computations.
|
|
14
|
+
* - `fact_holder` — which actors hold which facts: one row per `(actor, fact)`
|
|
15
|
+
* the actor has put, the possession record cell ref admission reads.
|
|
16
|
+
*
|
|
17
|
+
* `fact_holder.actor_id` references the auth schema's `actor` table, so the
|
|
18
|
+
* namespace runs after `fuz_auth`.
|
|
19
|
+
*
|
|
20
|
+
* **The released chain is frozen — every schema change ships as an appended
|
|
21
|
+
* migration.** Migrations are tracked by `(namespace, name)` with no checksum,
|
|
22
|
+
* so editing a released entry in place never reruns on a database that already
|
|
23
|
+
* recorded it. Never edit, rename, reorder, or re-purpose an entry in
|
|
24
|
+
* `FACT_MIGRATIONS`; append a new one with idempotent DDL. Each entry is
|
|
25
|
+
* twinned with the Rust `fuz_fact` migration of the same name and position,
|
|
26
|
+
* statement for statement (the `_testing_migration_tracker` and schema-parity
|
|
27
|
+
* gates compare the two).
|
|
14
28
|
*
|
|
15
29
|
* @module
|
|
16
30
|
*/
|
|
@@ -27,9 +41,20 @@ export declare const FACT_REFS_SCHEMA = "\nCREATE TABLE IF NOT EXISTS fact_ref (
|
|
|
27
41
|
export declare const FACT_REFS_TARGET_INDEX = "\nCREATE INDEX IF NOT EXISTS idx_fact_ref_target ON fact_ref(target_hash)";
|
|
28
42
|
/** `memo` table — `(fn_id, input_hash) → output_hash` for memoized computations. */
|
|
29
43
|
export declare const MEMOS_SCHEMA = "\nCREATE TABLE IF NOT EXISTS memo (\n\tfn_id TEXT NOT NULL,\n\tinput_hash TEXT NOT NULL,\n\toutput_hash TEXT NOT NULL,\n\tcreated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n\tPRIMARY KEY (fn_id, input_hash)\n)";
|
|
44
|
+
/**
|
|
45
|
+
* `fact_holder` table — the possession record: one row per `(actor, fact)` the
|
|
46
|
+
* actor has put, a deduplicated put by a second actor included.
|
|
47
|
+
*
|
|
48
|
+
* Both FKs cascade: deleting an actor erases its possession, and deleting a
|
|
49
|
+
* fact (the orphan sweep) drops its holders. The primary key leads with
|
|
50
|
+
* `actor_id`, serving the admission lookup and the actor-side cascade.
|
|
51
|
+
*/
|
|
52
|
+
export declare const FACT_HOLDER_SCHEMA = "\nCREATE TABLE IF NOT EXISTS fact_holder (\n\tactor_id UUID NOT NULL REFERENCES actor(id) ON DELETE CASCADE,\n\thash TEXT NOT NULL REFERENCES fact(hash) ON DELETE CASCADE,\n\tcreated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n\tPRIMARY KEY (actor_id, hash)\n)";
|
|
53
|
+
/** Serves the fact-side cascade of `fact_holder`. */
|
|
54
|
+
export declare const FACT_HOLDER_HASH_INDEX = "\nCREATE INDEX IF NOT EXISTS idx_fact_holder_hash ON fact_holder(hash)";
|
|
30
55
|
/** Tables created by `FACT_MIGRATION_NS`, in drop order (children first). */
|
|
31
|
-
export declare const FACT_DROP_TABLES: readonly ["memo", "fact_ref", "fact"];
|
|
32
|
-
/** Fact + memo migrations. */
|
|
56
|
+
export declare const FACT_DROP_TABLES: readonly ["fact_holder", "memo", "fact_ref", "fact"];
|
|
57
|
+
/** Fact + memo + possession migrations. Frozen + append-only — see the module doc. */
|
|
33
58
|
export declare const FACT_MIGRATIONS: Array<Migration>;
|
|
34
59
|
/** Namespace identifier for fact + memo migrations. */
|
|
35
60
|
export declare const FACT_MIGRATION_NAMESPACE = "fuz_facts";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fact_ddl.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/fact_ddl.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"fact_ddl.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/fact_ddl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElE,mDAAmD;AACnD,eAAO,MAAM,YAAY,qSASvB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,6LAK3B,CAAC;AAEH,4DAA4D;AAC5D,eAAO,MAAM,sBAAsB,8EACqC,CAAC;AAEzE,oFAAoF;AACpF,eAAO,MAAM,YAAY,mNAOvB,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,qQAM7B,CAAC;AAEH,qDAAqD;AACrD,eAAO,MAAM,sBAAsB,2EACkC,CAAC;AAEtE,6EAA6E;AAC7E,eAAO,MAAM,gBAAgB,sDAAuD,CAAC;AAErF,sFAAsF;AACtF,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,SAAS,CAiB5C,CAAC;AAEF,uDAAuD;AACvD,eAAO,MAAM,wBAAwB,cAAc,CAAC;AAEpD,wDAAwD;AACxD,eAAO,MAAM,iBAAiB,EAAE,kBAG/B,CAAC"}
|
package/dist/db/fact_ddl.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Fact + memo PG schema.
|
|
2
|
+
* Fact + memo + possession PG schema.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Tables:
|
|
5
5
|
*
|
|
6
6
|
* - `fact` — content-addressed bytes. `hash = 'blake3:<hex64>'`. Either
|
|
7
7
|
* embedded (`bytes`) or referenced (`external_url`); the CHECK constraint
|
|
@@ -11,6 +11,20 @@
|
|
|
11
11
|
* `target_hash` is intentionally **not** a foreign key: in federation a
|
|
12
12
|
* reference may target a fact stored on another instance.
|
|
13
13
|
* - `memo` — `(fn_id, input_hash) → output_hash` for memoized computations.
|
|
14
|
+
* - `fact_holder` — which actors hold which facts: one row per `(actor, fact)`
|
|
15
|
+
* the actor has put, the possession record cell ref admission reads.
|
|
16
|
+
*
|
|
17
|
+
* `fact_holder.actor_id` references the auth schema's `actor` table, so the
|
|
18
|
+
* namespace runs after `fuz_auth`.
|
|
19
|
+
*
|
|
20
|
+
* **The released chain is frozen — every schema change ships as an appended
|
|
21
|
+
* migration.** Migrations are tracked by `(namespace, name)` with no checksum,
|
|
22
|
+
* so editing a released entry in place never reruns on a database that already
|
|
23
|
+
* recorded it. Never edit, rename, reorder, or re-purpose an entry in
|
|
24
|
+
* `FACT_MIGRATIONS`; append a new one with idempotent DDL. Each entry is
|
|
25
|
+
* twinned with the Rust `fuz_fact` migration of the same name and position,
|
|
26
|
+
* statement for statement (the `_testing_migration_tracker` and schema-parity
|
|
27
|
+
* gates compare the two).
|
|
14
28
|
*
|
|
15
29
|
* @module
|
|
16
30
|
*/
|
|
@@ -48,9 +62,27 @@ CREATE TABLE IF NOT EXISTS memo (
|
|
|
48
62
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
49
63
|
PRIMARY KEY (fn_id, input_hash)
|
|
50
64
|
)`;
|
|
65
|
+
/**
|
|
66
|
+
* `fact_holder` table — the possession record: one row per `(actor, fact)` the
|
|
67
|
+
* actor has put, a deduplicated put by a second actor included.
|
|
68
|
+
*
|
|
69
|
+
* Both FKs cascade: deleting an actor erases its possession, and deleting a
|
|
70
|
+
* fact (the orphan sweep) drops its holders. The primary key leads with
|
|
71
|
+
* `actor_id`, serving the admission lookup and the actor-side cascade.
|
|
72
|
+
*/
|
|
73
|
+
export const FACT_HOLDER_SCHEMA = `
|
|
74
|
+
CREATE TABLE IF NOT EXISTS fact_holder (
|
|
75
|
+
actor_id UUID NOT NULL REFERENCES actor(id) ON DELETE CASCADE,
|
|
76
|
+
hash TEXT NOT NULL REFERENCES fact(hash) ON DELETE CASCADE,
|
|
77
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
78
|
+
PRIMARY KEY (actor_id, hash)
|
|
79
|
+
)`;
|
|
80
|
+
/** Serves the fact-side cascade of `fact_holder`. */
|
|
81
|
+
export const FACT_HOLDER_HASH_INDEX = `
|
|
82
|
+
CREATE INDEX IF NOT EXISTS idx_fact_holder_hash ON fact_holder(hash)`;
|
|
51
83
|
/** Tables created by `FACT_MIGRATION_NS`, in drop order (children first). */
|
|
52
|
-
export const FACT_DROP_TABLES = ['memo', 'fact_ref', 'fact'];
|
|
53
|
-
/** Fact + memo migrations. */
|
|
84
|
+
export const FACT_DROP_TABLES = ['fact_holder', 'memo', 'fact_ref', 'fact'];
|
|
85
|
+
/** Fact + memo + possession migrations. Frozen + append-only — see the module doc. */
|
|
54
86
|
export const FACT_MIGRATIONS = [
|
|
55
87
|
{
|
|
56
88
|
name: 'full_fact_schema',
|
|
@@ -60,6 +92,13 @@ export const FACT_MIGRATIONS = [
|
|
|
60
92
|
await db.query(FACT_REFS_TARGET_INDEX);
|
|
61
93
|
await db.query(MEMOS_SCHEMA);
|
|
62
94
|
}
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: 'fact_holder',
|
|
98
|
+
up: async (db) => {
|
|
99
|
+
await db.query(FACT_HOLDER_SCHEMA);
|
|
100
|
+
await db.query(FACT_HOLDER_HASH_INDEX);
|
|
101
|
+
}
|
|
63
102
|
}
|
|
64
103
|
];
|
|
65
104
|
/** Namespace identifier for fact + memo migrations. */
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Raw queries against `fact_holder` — the possession record.
|
|
3
|
+
*
|
|
4
|
+
* A `fact_holder` row says an actor has put a fact's bytes. `PgFactStore`
|
|
5
|
+
* writes one on every put that names a holder (`HeldFactPutOptions.holder`),
|
|
6
|
+
* deduplicated puts included: identical bytes put again by a second actor
|
|
7
|
+
* make that actor a holder too. Cell ref admission
|
|
8
|
+
* (`auth/cell_ref_admission.ts`) reads it back — a write may introduce a fact
|
|
9
|
+
* ref only for a fact the acting actor holds.
|
|
10
|
+
*
|
|
11
|
+
* Same discipline as `db/fact_queries.ts`: `deps: QueryDeps` first (the caller
|
|
12
|
+
* owns the transaction), no audit side effects, idempotent inserts.
|
|
13
|
+
*
|
|
14
|
+
* @module
|
|
15
|
+
*/
|
|
16
|
+
import type { FactHash } from '@fuzdev/fuz_util/hash_schemas.ts';
|
|
17
|
+
import type { QueryDeps } from './query_deps.js';
|
|
18
|
+
import type { Uuid } from '../primitive_schemas.js';
|
|
19
|
+
/** Row shape of `fact_holder`. */
|
|
20
|
+
export interface FactHolderRow {
|
|
21
|
+
actor_id: Uuid;
|
|
22
|
+
hash: FactHash;
|
|
23
|
+
created_at: Date;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The `fact_holder` table's columns.
|
|
27
|
+
*
|
|
28
|
+
* Twin of the Rust `fuz_fact::FACT_HOLDER_COLUMNS` (same names, same order).
|
|
29
|
+
* No query reads whole rows — admission reads hashes only — so the const is
|
|
30
|
+
* the drift guard's anchor rather than a projection source.
|
|
31
|
+
*/
|
|
32
|
+
export declare const FACT_HOLDER_COLUMNS: readonly ["actor_id", "hash", "created_at"];
|
|
33
|
+
/**
|
|
34
|
+
* Record `actor_id` as a holder of `hash`. Idempotent (`ON CONFLICT DO
|
|
35
|
+
* NOTHING`); the `fact` row must already exist (FK).
|
|
36
|
+
*
|
|
37
|
+
* @param deps - query deps
|
|
38
|
+
* @param actor_id - the actor that brought the bytes
|
|
39
|
+
* @param hash - the fact's hash
|
|
40
|
+
* @mutates fact_holder - inserts the `(actor_id, hash)` row when absent
|
|
41
|
+
*/
|
|
42
|
+
export declare const query_put_fact_holder: (deps: QueryDeps, actor_id: Uuid, hash: FactHash) => Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Whether the `fact_holder` table exists — `false` on a database that mounts
|
|
45
|
+
* the cell verbs without the fact chain.
|
|
46
|
+
*
|
|
47
|
+
* Probed before `query_fact_holder_unheld`, since naming a missing table
|
|
48
|
+
* would abort the caller's transaction. Twin of the Rust admission's
|
|
49
|
+
* `to_regclass('fact_holder')` probe, read from `information_schema` (which
|
|
50
|
+
* every supported driver answers).
|
|
51
|
+
*/
|
|
52
|
+
export declare const query_fact_holder_table_exists: (deps: QueryDeps) => Promise<boolean>;
|
|
53
|
+
/**
|
|
54
|
+
* The subset of `hashes` that `actor_id` does **not** hold, in input order.
|
|
55
|
+
*
|
|
56
|
+
* Answered from `fact_holder` alone: a hash with no stored fact and a stored
|
|
57
|
+
* fact the actor never put read the same. Hashes are compared as text. The
|
|
58
|
+
* caller has checked the table exists.
|
|
59
|
+
*
|
|
60
|
+
* @param deps - query deps
|
|
61
|
+
* @param actor_id - the acting actor
|
|
62
|
+
* @param hashes - the candidate hashes
|
|
63
|
+
* @returns the hashes with no `(actor_id, hash)` row
|
|
64
|
+
*/
|
|
65
|
+
export declare const query_fact_holder_unheld: (deps: QueryDeps, actor_id: Uuid, hashes: ReadonlyArray<string>) => Promise<Array<string>>;
|
|
66
|
+
//# sourceMappingURL=fact_holder_queries.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fact_holder_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/fact_holder_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAEjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAEpD,kCAAkC;AAClC,MAAM,WAAW,aAAa;IAC7B,QAAQ,EAAE,IAAI,CAAC;IACf,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,EAAE,IAAI,CAAC;CACjB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,6CAIuB,CAAC;AAExD;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,GACjC,MAAM,SAAS,EACf,UAAU,IAAI,EACd,MAAM,QAAQ,KACZ,OAAO,CAAC,IAAI,CAMd,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,8BAA8B,GAAU,MAAM,SAAS,KAAG,OAAO,CAAC,OAAO,CAQrF,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,wBAAwB,GACpC,MAAM,SAAS,EACf,UAAU,IAAI,EACd,QAAQ,aAAa,CAAC,MAAM,CAAC,KAC3B,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAQvB,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Raw queries against `fact_holder` — the possession record.
|
|
3
|
+
*
|
|
4
|
+
* A `fact_holder` row says an actor has put a fact's bytes. `PgFactStore`
|
|
5
|
+
* writes one on every put that names a holder (`HeldFactPutOptions.holder`),
|
|
6
|
+
* deduplicated puts included: identical bytes put again by a second actor
|
|
7
|
+
* make that actor a holder too. Cell ref admission
|
|
8
|
+
* (`auth/cell_ref_admission.ts`) reads it back — a write may introduce a fact
|
|
9
|
+
* ref only for a fact the acting actor holds.
|
|
10
|
+
*
|
|
11
|
+
* Same discipline as `db/fact_queries.ts`: `deps: QueryDeps` first (the caller
|
|
12
|
+
* owns the transaction), no audit side effects, idempotent inserts.
|
|
13
|
+
*
|
|
14
|
+
* @module
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* The `fact_holder` table's columns.
|
|
18
|
+
*
|
|
19
|
+
* Twin of the Rust `fuz_fact::FACT_HOLDER_COLUMNS` (same names, same order).
|
|
20
|
+
* No query reads whole rows — admission reads hashes only — so the const is
|
|
21
|
+
* the drift guard's anchor rather than a projection source.
|
|
22
|
+
*/
|
|
23
|
+
export const FACT_HOLDER_COLUMNS = [
|
|
24
|
+
'actor_id',
|
|
25
|
+
'hash',
|
|
26
|
+
'created_at'
|
|
27
|
+
];
|
|
28
|
+
/**
|
|
29
|
+
* Record `actor_id` as a holder of `hash`. Idempotent (`ON CONFLICT DO
|
|
30
|
+
* NOTHING`); the `fact` row must already exist (FK).
|
|
31
|
+
*
|
|
32
|
+
* @param deps - query deps
|
|
33
|
+
* @param actor_id - the actor that brought the bytes
|
|
34
|
+
* @param hash - the fact's hash
|
|
35
|
+
* @mutates fact_holder - inserts the `(actor_id, hash)` row when absent
|
|
36
|
+
*/
|
|
37
|
+
export const query_put_fact_holder = async (deps, actor_id, hash) => {
|
|
38
|
+
await deps.db.query(`INSERT INTO fact_holder (actor_id, hash) VALUES ($1, $2)
|
|
39
|
+
ON CONFLICT (actor_id, hash) DO NOTHING`, [actor_id, hash]);
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Whether the `fact_holder` table exists — `false` on a database that mounts
|
|
43
|
+
* the cell verbs without the fact chain.
|
|
44
|
+
*
|
|
45
|
+
* Probed before `query_fact_holder_unheld`, since naming a missing table
|
|
46
|
+
* would abort the caller's transaction. Twin of the Rust admission's
|
|
47
|
+
* `to_regclass('fact_holder')` probe, read from `information_schema` (which
|
|
48
|
+
* every supported driver answers).
|
|
49
|
+
*/
|
|
50
|
+
export const query_fact_holder_table_exists = async (deps) => {
|
|
51
|
+
const row = await deps.db.query_one(`SELECT EXISTS (
|
|
52
|
+
SELECT 1 FROM information_schema.tables
|
|
53
|
+
WHERE table_schema = 'public' AND table_name = 'fact_holder'
|
|
54
|
+
) AS exists`);
|
|
55
|
+
return row?.exists === true;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* The subset of `hashes` that `actor_id` does **not** hold, in input order.
|
|
59
|
+
*
|
|
60
|
+
* Answered from `fact_holder` alone: a hash with no stored fact and a stored
|
|
61
|
+
* fact the actor never put read the same. Hashes are compared as text. The
|
|
62
|
+
* caller has checked the table exists.
|
|
63
|
+
*
|
|
64
|
+
* @param deps - query deps
|
|
65
|
+
* @param actor_id - the acting actor
|
|
66
|
+
* @param hashes - the candidate hashes
|
|
67
|
+
* @returns the hashes with no `(actor_id, hash)` row
|
|
68
|
+
*/
|
|
69
|
+
export const query_fact_holder_unheld = async (deps, actor_id, hashes) => {
|
|
70
|
+
if (hashes.length === 0)
|
|
71
|
+
return [];
|
|
72
|
+
const rows = await deps.db.query(`SELECT hash FROM fact_holder WHERE actor_id = $1 AND hash = ANY($2::text[])`, [actor_id, hashes]);
|
|
73
|
+
const held = new Set(rows.map((r) => r.hash));
|
|
74
|
+
return hashes.filter((h) => !held.has(h));
|
|
75
|
+
};
|
|
@@ -37,6 +37,14 @@ export interface FactMetaRow {
|
|
|
37
37
|
size: number | string;
|
|
38
38
|
created_at: Date;
|
|
39
39
|
}
|
|
40
|
+
/** Input for `query_put_fact` — one `fact` row. Twin of the Rust `PutFactInput`. */
|
|
41
|
+
export interface PutFactInput {
|
|
42
|
+
hash: FactHash;
|
|
43
|
+
bytes: Uint8Array | null;
|
|
44
|
+
external_url: string | null;
|
|
45
|
+
content_type: string | null;
|
|
46
|
+
size: number;
|
|
47
|
+
}
|
|
40
48
|
/**
|
|
41
49
|
* Idempotently insert a fact row.
|
|
42
50
|
*
|
|
@@ -46,13 +54,7 @@ export interface FactMetaRow {
|
|
|
46
54
|
* inserted, `false` when a row already existed (caller can use this to
|
|
47
55
|
* decide whether to also write `fact_ref`).
|
|
48
56
|
*/
|
|
49
|
-
export declare const query_put_fact: (deps: QueryDeps, input:
|
|
50
|
-
hash: FactHash;
|
|
51
|
-
bytes: Uint8Array | null;
|
|
52
|
-
external_url: string | null;
|
|
53
|
-
content_type: string | null;
|
|
54
|
-
size: number;
|
|
55
|
-
}) => Promise<boolean>;
|
|
57
|
+
export declare const query_put_fact: (deps: QueryDeps, input: PutFactInput) => Promise<boolean>;
|
|
56
58
|
/**
|
|
57
59
|
* Idempotently insert declared refs for a fact. No-ops on `(source_hash,
|
|
58
60
|
* target_hash)` collisions and skips the round trip entirely when
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fact_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/fact_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAGjE,0CAA0C;AAC1C,MAAM,WAAW,OAAO;IACvB,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAK5B,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,UAAU,EAAE,IAAI,CAAC;CACjB;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY,kFAOwB,CAAC;AAYlD,qEAAqE;AACrE,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,QAAQ,CAAC;IACf,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAE5B,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,UAAU,EAAE,IAAI,CAAC;CACjB;AAED
|
|
1
|
+
{"version":3,"file":"fact_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/fact_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAGjE,0CAA0C;AAC1C,MAAM,WAAW,OAAO;IACvB,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAK5B,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,UAAU,EAAE,IAAI,CAAC;CACjB;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY,kFAOwB,CAAC;AAYlD,qEAAqE;AACrE,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,QAAQ,CAAC;IACf,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAE5B,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,UAAU,EAAE,IAAI,CAAC;CACjB;AAED,oFAAoF;AACpF,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,GAAU,MAAM,SAAS,EAAE,OAAO,YAAY,KAAG,OAAO,CAAC,OAAO,CAS1F,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAC/B,MAAM,SAAS,EACf,aAAa,QAAQ,EACrB,eAAe,KAAK,CAAC,QAAQ,CAAC,KAC5B,OAAO,CAAC,IAAI,CAQd,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAU,MAAM,SAAS,EAAE,MAAM,QAAQ,KAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAO5F,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAC/B,MAAM,SAAS,EACf,MAAM,QAAQ,KACZ,OAAO,CAAC,WAAW,GAAG,IAAI,CAO5B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,GAAU,MAAM,SAAS,EAAE,MAAM,QAAQ,KAAG,OAAO,CAAC,OAAO,CAMrF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAC/B,MAAM,SAAS,EACf,aAAa,QAAQ,KACnB,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAMzB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iBAAiB,GAC7B,MAAM,SAAS,EACf,MAAM,QAAQ,KACZ,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CAQ9D,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,QAAQ,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;KAC5B,CAAC,CAAC;CACH;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,uBAAuB,GACnC,MAAM,SAAS,EACf,YAAY,IAAI,GAAG,IAAI,EACvB,cAAc,MAAM,KAClB,OAAO,CAAC,qBAAqB,CA2C/B,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,oCAAoC,GAChD,MAAM,SAAS,EACf,YAAY,IAAI,KACd,OAAO,CAAC,KAAK,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAiB9E,CAAC"}
|
package/dist/db/fact_store.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* PG-backed `
|
|
2
|
+
* PG-backed `HeldFactStore` implementation.
|
|
3
3
|
*
|
|
4
4
|
* Wraps the raw queries in `db/fact_queries.ts` with the lifecycle the
|
|
5
|
-
* `
|
|
5
|
+
* `HeldFactStore` interface promises:
|
|
6
6
|
*
|
|
7
7
|
* - sync hash on `put`; `put_stream` hashes as it streams
|
|
8
8
|
* - idempotent insert (`ON CONFLICT DO NOTHING` in the queries layer)
|
|
@@ -33,13 +33,63 @@
|
|
|
33
33
|
* `external_url` has any other shape, and any external row on a store with no
|
|
34
34
|
* disk CAS configured, as unavailable: a warning and `null`.
|
|
35
35
|
*
|
|
36
|
+
* ## Holders
|
|
37
|
+
*
|
|
38
|
+
* Every put names its holder (`HeldFactPutOptions.holder`): the actor whose
|
|
39
|
+
* request carried the bytes, or `null` for a system put (seeds, server-side
|
|
40
|
+
* imports). A named holder gets a `fact_holder` row on every put — a
|
|
41
|
+
* deduplicated put included, since bringing identical bytes is possession. The
|
|
42
|
+
* `fact` row, its refs, and the holder row commit in one transaction. Cell ref
|
|
43
|
+
* admission (`auth/cell_ref_admission.ts`) reads the holder rows. The holder is
|
|
44
|
+
* a spine concept, so `PgFactStore` implements `HeldFactStore` — the
|
|
45
|
+
* `@fuzdev/fuz_util` `FactStore` reads plus puts that take `HeldFactPutOptions` —
|
|
46
|
+
* rather than the backend-agnostic `FactStore`, whose puts name no actor.
|
|
47
|
+
*
|
|
36
48
|
* @module
|
|
37
49
|
*/
|
|
38
50
|
import type { QueryDeps } from './query_deps.js';
|
|
51
|
+
import type { Uuid } from '../primitive_schemas.js';
|
|
39
52
|
import type { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
40
53
|
import type { FactHash } from '@fuzdev/fuz_util/hash_schemas.ts';
|
|
41
54
|
import type { FactMeta, FactPutOptions, FactStore, PutStreamOutcome } from '@fuzdev/fuz_util/fact_store.ts';
|
|
42
55
|
import { type FactDiskStorageDeps } from './fact_disk_storage.js';
|
|
56
|
+
/**
|
|
57
|
+
* Options for `HeldFactStore.put` / `put_stream`: the `@fuzdev/fuz_util`
|
|
58
|
+
* `FactPutOptions` plus the required `holder`.
|
|
59
|
+
*
|
|
60
|
+
* `holder` is the actor that brought these bytes, recorded in `fact_holder`
|
|
61
|
+
* whether or not the fact already existed. `null` is a system put (seeds,
|
|
62
|
+
* server-side imports) that records no holder — a cell write can newly
|
|
63
|
+
* reference such a fact only as a global admin or as an actor that puts the
|
|
64
|
+
* same bytes itself (refs a cell already carries stay admitted through update
|
|
65
|
+
* and clone). Required, so a put on behalf of a caller can't silently skip the
|
|
66
|
+
* possession record. Twin of the Rust `PutOptions::holder`.
|
|
67
|
+
*/
|
|
68
|
+
export interface HeldFactPutOptions extends FactPutOptions {
|
|
69
|
+
holder: Uuid | null;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* A fact store whose puts record possession: the `@fuzdev/fuz_util`
|
|
73
|
+
* `FactStore` reads, plus `put` / `put_stream` taking `HeldFactPutOptions` with
|
|
74
|
+
* its required `holder`.
|
|
75
|
+
*
|
|
76
|
+
* The holder is required — a store typed by the generic `FactStore` cannot
|
|
77
|
+
* record possession, so cell ref admission (`auth/cell_ref_admission.ts`)
|
|
78
|
+
* could never admit a ref to a fact put through it. `AppDeps.fact_store` is
|
|
79
|
+
* typed by this interface; `PgFactStore` implements it.
|
|
80
|
+
*/
|
|
81
|
+
export interface HeldFactStore extends Omit<FactStore, 'put' | 'put_stream'> {
|
|
82
|
+
/**
|
|
83
|
+
* Idempotent like `FactStore.put`; records `options.holder` (when non-null)
|
|
84
|
+
* on a fresh insert and a dedup hit alike.
|
|
85
|
+
*/
|
|
86
|
+
put: (bytes: Uint8Array, options: HeldFactPutOptions) => Promise<FactHash>;
|
|
87
|
+
/**
|
|
88
|
+
* Idempotent like `FactStore.put_stream`; records `options.holder` (when
|
|
89
|
+
* non-null) on a fresh insert and a dedup hit alike.
|
|
90
|
+
*/
|
|
91
|
+
put_stream: (stream: ReadableStream<Uint8Array>, max_bytes: number, options: HeldFactPutOptions) => Promise<PutStreamOutcome>;
|
|
92
|
+
}
|
|
43
93
|
/** Default embedded-vs-referenced cutoff (1 MiB). */
|
|
44
94
|
export declare const FACT_EMBEDDED_THRESHOLD_DEFAULT: number;
|
|
45
95
|
/**
|
|
@@ -70,10 +120,11 @@ export interface PgFactStoreDeps {
|
|
|
70
120
|
log?: Logger;
|
|
71
121
|
}
|
|
72
122
|
/**
|
|
73
|
-
* PG-backed
|
|
74
|
-
* the lifecycle layer described in the module doc.
|
|
123
|
+
* PG-backed fact store. Delegates to `db/fact_queries.ts` for I/O and adds
|
|
124
|
+
* the lifecycle layer described in the module doc. Implements `HeldFactStore`:
|
|
125
|
+
* the `@fuzdev/fuz_util` `FactStore` reads, puts taking `HeldFactPutOptions`.
|
|
75
126
|
*/
|
|
76
|
-
export declare class PgFactStore implements
|
|
127
|
+
export declare class PgFactStore implements HeldFactStore {
|
|
77
128
|
#private;
|
|
78
129
|
constructor(options: PgFactStoreDeps);
|
|
79
130
|
/**
|
|
@@ -82,9 +133,12 @@ export declare class PgFactStore implements FactStore {
|
|
|
82
133
|
* are configured) at `<facts_dir>/<shard>/<rest>` with a `file:` URL. Oversize
|
|
83
134
|
* without a disk root throws: the store has nowhere to put bytes it cannot
|
|
84
135
|
* embed. Idempotent — `ON CONFLICT DO NOTHING` + content-addressed disk
|
|
85
|
-
* filenames make a re-write a no-op.
|
|
136
|
+
* filenames make a re-write a no-op. `options.holder`, when set, is recorded
|
|
137
|
+
* as a holder on a fresh insert and a dedup hit alike.
|
|
138
|
+
*
|
|
139
|
+
* @mutates fact_holder - records `options.holder` (when non-null) in the transaction that writes the `fact` row
|
|
86
140
|
*/
|
|
87
|
-
put(bytes: Uint8Array, options
|
|
141
|
+
put(bytes: Uint8Array, options: HeldFactPutOptions): Promise<FactHash>;
|
|
88
142
|
/**
|
|
89
143
|
* Stream bytes into the store with bounded memory, returning the finalized
|
|
90
144
|
* digests + size. Delegates the byte path to `stream_fact_to_disk` (hash
|
|
@@ -100,9 +154,11 @@ export declare class PgFactStore implements FactStore {
|
|
|
100
154
|
*
|
|
101
155
|
* Requires `fs` (and, for the over-threshold spill, `disk_root`) to be
|
|
102
156
|
* configured. The streaming twin of `put`; mirrors the Rust
|
|
103
|
-
* `FactStore::put_stream`.
|
|
157
|
+
* `FactStore::put_stream`. Records `options.holder` the way `put` does.
|
|
158
|
+
*
|
|
159
|
+
* @mutates fact_holder - records `options.holder` (when non-null) in the transaction that writes the `fact` row
|
|
104
160
|
*/
|
|
105
|
-
put_stream(stream: ReadableStream<Uint8Array>, max_bytes: number, options
|
|
161
|
+
put_stream(stream: ReadableStream<Uint8Array>, max_bytes: number, options: HeldFactPutOptions): Promise<PutStreamOutcome>;
|
|
106
162
|
/**
|
|
107
163
|
* Retrieve bytes. Embedded reads return PG bytes directly. An external
|
|
108
164
|
* read comes from the disk CAS and nowhere else: the bytes at the row's
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fact_store.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/fact_store.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"fact_store.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/db/fact_store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAOtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,KAAK,EACX,QAAQ,EACR,cAAc,EACd,SAAS,EACT,gBAAgB,EAChB,MAAM,gCAAgC,CAAC;AAcxC,OAAO,EAIN,KAAK,mBAAmB,EACxB,MAAM,wBAAwB,CAAC;AAEhC;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,kBAAmB,SAAQ,cAAc;IACzD,MAAM,EAAE,IAAI,GAAG,IAAI,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAc,SAAQ,IAAI,CAAC,SAAS,EAAE,KAAK,GAAG,YAAY,CAAC;IAC3E;;;OAGG;IACH,GAAG,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,kBAAkB,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC3E;;;OAGG;IACH,UAAU,EAAE,CACX,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,EAClC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,kBAAkB,KACvB,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAC/B;AAED,qDAAqD;AACrD,eAAO,MAAM,+BAA+B,QAAc,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,SAAS,CAAC;IAChB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,mBAAmB,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;;;GAIG;AACH,qBAAa,WAAY,YAAW,aAAa;;gBAOpC,OAAO,EAAE,eAAe;IAQpC;;;;;;;;;;OAUG;IACG,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAgC5E;;;;;;;;;;;;;;;;;;OAkBG;IACG,UAAU,CACf,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,EAClC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,kBAAkB,GACzB,OAAO,CAAC,gBAAgB,CAAC;IA+C5B;;;;;;;;;OASG;IACG,GAAG,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IA0C/C,GAAG,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAIrC,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAWlD,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAIxD;;;;;;;;;;;;;;;;;;OAkBG;IACG,MAAM,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;CAG3F"}
|