@bandeira-tech/b3nd-save 0.8.1 → 0.13.1
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/esm/clients/save-client.d.ts +63 -29
- package/esm/clients/save-client.d.ts.map +1 -1
- package/esm/clients/save-client.js +148 -68
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/mod.d.ts +1 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.25.0/mod.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/client-console/client.d.ts.map +1 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/encoding/encoding.d.ts.map +1 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/encrypt/mod.d.ts +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.25.0/src/encrypt/mod.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/encrypt/mod.js +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.25.0/src/encrypt/utils.d.ts +6 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.25.0/src/encrypt/utils.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.25.0/src/encrypt/utils.js +12 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/functional-client/functional-client.d.ts.map +1 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/match-pattern/match-pattern.d.ts.map +1 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/network/decorators.d.ts.map +1 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/network/network.d.ts.map +1 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/network/peer.d.ts.map +1 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/network/policies/flood.d.ts.map +1 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/network/policies/path-vector.d.ts +3 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.25.0/src/network/policies/path-vector.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/network/policies/path-vector.js +3 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/network/policies/tell-and-read.d.ts.map +1 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/network/types.d.ts.map +1 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/observe-emitter/observe-emitter.d.ts.map +1 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/rig/connection.d.ts +13 -5
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.25.0/src/rig/connection.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/rig/connection.js +1 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/rig/events.d.ts.map +1 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/rig/hooks.d.ts.map +1 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/rig/identity.d.ts.map +1 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/rig/operation-handle.d.ts.map +1 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/rig/reactions.d.ts.map +1 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/rig/rig.d.ts +3 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.25.0/src/rig/rig.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/rig/rig.js +46 -4
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/rig/types.d.ts +4 -4
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.25.0/src/rig/types.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/types/types.d.ts +119 -80
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.25.0/src/types/types.d.ts.map +1 -0
- package/esm/dispatch.d.ts +116 -3
- package/esm/dispatch.d.ts.map +1 -1
- package/esm/dispatch.js +381 -5
- package/esm/elasticsearch/store.d.ts +124 -25
- package/esm/elasticsearch/store.d.ts.map +1 -1
- package/esm/elasticsearch/store.js +451 -92
- package/esm/entity-store.d.ts +1 -1
- package/esm/errors.d.ts +1 -1
- package/esm/errors.js +1 -1
- package/esm/fs/mod.d.ts +26 -0
- package/esm/fs/mod.d.ts.map +1 -1
- package/esm/fs/store.d.ts +100 -23
- package/esm/fs/store.d.ts.map +1 -1
- package/esm/fs/store.js +250 -66
- package/esm/glob.d.ts +114 -0
- package/esm/glob.d.ts.map +1 -0
- package/esm/glob.js +352 -0
- package/esm/identifiers.d.ts +18 -0
- package/esm/identifiers.d.ts.map +1 -0
- package/esm/identifiers.js +19 -0
- package/esm/indexeddb/fields.d.ts +32 -0
- package/esm/indexeddb/fields.d.ts.map +1 -0
- package/esm/indexeddb/fields.js +51 -0
- package/esm/indexeddb/store.d.ts +72 -17
- package/esm/indexeddb/store.d.ts.map +1 -1
- package/esm/indexeddb/store.js +362 -106
- package/esm/ipfs/mod.d.ts +19 -0
- package/esm/ipfs/mod.d.ts.map +1 -1
- package/esm/ipfs/mod.js +19 -0
- package/esm/ipfs/store.d.ts +82 -21
- package/esm/ipfs/store.d.ts.map +1 -1
- package/esm/ipfs/store.js +269 -68
- package/esm/json-fields.d.ts +61 -0
- package/esm/json-fields.d.ts.map +1 -0
- package/esm/json-fields.js +121 -0
- package/esm/localstorage/store.d.ts +89 -21
- package/esm/localstorage/store.d.ts.map +1 -1
- package/esm/localstorage/store.js +247 -54
- package/esm/memory/store.d.ts +35 -4
- package/esm/memory/store.d.ts.map +1 -1
- package/esm/memory/store.js +69 -47
- package/esm/mod.d.ts +2 -0
- package/esm/mod.d.ts.map +1 -1
- package/esm/mod.js +1 -0
- package/esm/mongo/fields.d.ts +53 -0
- package/esm/mongo/fields.d.ts.map +1 -0
- package/esm/mongo/fields.js +71 -0
- package/esm/mongo/mod.d.ts +19 -4
- package/esm/mongo/mod.d.ts.map +1 -1
- package/esm/mongo/mod.js +4 -2
- package/esm/mongo/store.d.ts +114 -25
- package/esm/mongo/store.d.ts.map +1 -1
- package/esm/mongo/store.js +355 -102
- package/esm/postgres/store.d.ts +50 -1
- package/esm/postgres/store.d.ts.map +1 -1
- package/esm/postgres/store.js +133 -13
- package/esm/read.d.ts +54 -7
- package/esm/read.d.ts.map +1 -1
- package/esm/read.js +141 -16
- package/esm/s3/store.d.ts +125 -23
- package/esm/s3/store.d.ts.map +1 -1
- package/esm/s3/store.js +313 -57
- package/esm/sqlite/columns.d.ts +33 -0
- package/esm/sqlite/columns.d.ts.map +1 -0
- package/esm/sqlite/columns.js +51 -0
- package/esm/sqlite/store.d.ts +73 -25
- package/esm/sqlite/store.d.ts.map +1 -1
- package/esm/sqlite/store.js +411 -107
- package/esm/types.d.ts +1 -1
- package/esm/url.d.ts +122 -19
- package/esm/url.d.ts.map +1 -1
- package/esm/url.js +218 -24
- package/esm/walk-via-ls.d.ts +122 -0
- package/esm/walk-via-ls.d.ts.map +1 -0
- package/esm/walk-via-ls.js +178 -0
- package/package.json +1 -1
- package/esm/byte-entity-shim.d.ts +0 -47
- package/esm/byte-entity-shim.d.ts.map +0 -1
- package/esm/byte-entity-shim.js +0 -138
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/mod.d.ts.map +0 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/encrypt/mod.d.ts.map +0 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/network/policies/path-vector.d.ts.map +0 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/connection.d.ts.map +0 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/rig.d.ts.map +0 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/types.d.ts.map +0 -1
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/types/types.d.ts.map +0 -1
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/mod.js +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/client-console/client.d.ts +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/client-console/client.js +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/encoding/encoding.d.ts +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/encoding/encoding.js +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/functional-client/functional-client.d.ts +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/functional-client/functional-client.js +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/match-pattern/match-pattern.d.ts +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/match-pattern/match-pattern.js +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/network/decorators.d.ts +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/network/decorators.js +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/network/network.d.ts +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/network/network.js +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/network/peer.d.ts +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/network/peer.js +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/network/policies/flood.d.ts +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/network/policies/flood.js +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/network/policies/tell-and-read.d.ts +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/network/policies/tell-and-read.js +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/network/types.d.ts +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/network/types.js +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/observe-emitter/observe-emitter.d.ts +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/observe-emitter/observe-emitter.js +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/rig/events.d.ts +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/rig/events.js +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/rig/hooks.d.ts +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/rig/hooks.js +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/rig/identity.d.ts +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/rig/identity.js +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/rig/operation-handle.d.ts +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/rig/operation-handle.js +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/rig/reactions.d.ts +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/rig/reactions.js +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/rig/types.js +0 -0
- /package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/{0.22.0 → 0.25.0}/src/types/types.js +0 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema field planning for MongoStore native entities.
|
|
3
|
+
*
|
|
4
|
+
* MongoDB collections are schemaless on the wire — Mongo will happily
|
|
5
|
+
* store a document with any keys and any value types. So unlike
|
|
6
|
+
* postgres/sqlite (which lean on column types for both shape pinning
|
|
7
|
+
* and write-time validation), Mongo native entities lean on:
|
|
8
|
+
*
|
|
9
|
+
* 1. A per-field **canonical type tag** (first recognised `TYPE_TAGS`
|
|
10
|
+
* entry, declaration-order), folded into a deterministic signature
|
|
11
|
+
* so collision detection survives the schemaless medium.
|
|
12
|
+
* 2. A per-entity **collection** with a stable name (`{prefix}_{entity}_data`).
|
|
13
|
+
* 3. A separate **meta collection** (`{prefix}_meta`) where each
|
|
14
|
+
* provisioned entity gets one document `{ _id, signature }` — the
|
|
15
|
+
* store reads this on `entityStatus` and writes it on `provisionEntity`.
|
|
16
|
+
*
|
|
17
|
+
* Adapter notes (declared tag → BSON-ish behaviour):
|
|
18
|
+
*
|
|
19
|
+
* - `string` / `timestamp` (stored as ISO-8601 TEXT) / `json` (stored
|
|
20
|
+
* inline as a sub-document or array) / `bigint` (stored as BSON
|
|
21
|
+
* Long if outside double precision; otherwise number) / `number` /
|
|
22
|
+
* `boolean` / `bytes` (stored as `Uint8Array` → BSON Binary).
|
|
23
|
+
*/
|
|
24
|
+
import { type EntityField } from "../entity.js";
|
|
25
|
+
export interface FieldPlan {
|
|
26
|
+
/** Field name (also the document key). */
|
|
27
|
+
name: string;
|
|
28
|
+
/** Canonical tag (one of `TYPE_TAGS`). */
|
|
29
|
+
tag: string;
|
|
30
|
+
}
|
|
31
|
+
export interface FieldPlanResult {
|
|
32
|
+
fields: FieldPlan[];
|
|
33
|
+
unsupported: {
|
|
34
|
+
name: string;
|
|
35
|
+
reason: string;
|
|
36
|
+
}[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Resolve a schema's fields into MongoStore field plans.
|
|
40
|
+
*
|
|
41
|
+
* Skips fields whose tags are all outside `TYPE_TAGS`; reports them
|
|
42
|
+
* via `unsupported`. Rejects invalid field names up front so the
|
|
43
|
+
* downstream signature is deterministic and the keys are safe.
|
|
44
|
+
*/
|
|
45
|
+
export declare function planFields(fields: EntityField[]): FieldPlanResult;
|
|
46
|
+
/**
|
|
47
|
+
* Deterministic signature for collision detection. Same name + same
|
|
48
|
+
* set of supported fields + same canonical tag per field → same string.
|
|
49
|
+
* Mirrors the strictness MemoryStore committed to and SQL backends get
|
|
50
|
+
* for free from column-type introspection.
|
|
51
|
+
*/
|
|
52
|
+
export declare function computeSignature(entityName: string, fields: readonly FieldPlan[]): string;
|
|
53
|
+
//# sourceMappingURL=fields.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../../src/mongo/fields.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,KAAK,WAAW,EAAa,MAAM,cAAc,CAAC;AAK3D,MAAM,WAAW,SAAS;IACxB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACjD;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,eAAe,CA0BjE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,SAAS,SAAS,EAAE,GAC3B,MAAM,CAMR"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema field planning for MongoStore native entities.
|
|
3
|
+
*
|
|
4
|
+
* MongoDB collections are schemaless on the wire — Mongo will happily
|
|
5
|
+
* store a document with any keys and any value types. So unlike
|
|
6
|
+
* postgres/sqlite (which lean on column types for both shape pinning
|
|
7
|
+
* and write-time validation), Mongo native entities lean on:
|
|
8
|
+
*
|
|
9
|
+
* 1. A per-field **canonical type tag** (first recognised `TYPE_TAGS`
|
|
10
|
+
* entry, declaration-order), folded into a deterministic signature
|
|
11
|
+
* so collision detection survives the schemaless medium.
|
|
12
|
+
* 2. A per-entity **collection** with a stable name (`{prefix}_{entity}_data`).
|
|
13
|
+
* 3. A separate **meta collection** (`{prefix}_meta`) where each
|
|
14
|
+
* provisioned entity gets one document `{ _id, signature }` — the
|
|
15
|
+
* store reads this on `entityStatus` and writes it on `provisionEntity`.
|
|
16
|
+
*
|
|
17
|
+
* Adapter notes (declared tag → BSON-ish behaviour):
|
|
18
|
+
*
|
|
19
|
+
* - `string` / `timestamp` (stored as ISO-8601 TEXT) / `json` (stored
|
|
20
|
+
* inline as a sub-document or array) / `bigint` (stored as BSON
|
|
21
|
+
* Long if outside double precision; otherwise number) / `number` /
|
|
22
|
+
* `boolean` / `bytes` (stored as `Uint8Array` → BSON Binary).
|
|
23
|
+
*/
|
|
24
|
+
import { TYPE_TAGS } from "../entity.js";
|
|
25
|
+
import { IDENTIFIER_PATTERN, isValidIdentifier } from "../identifiers.js";
|
|
26
|
+
const KNOWN_TAGS = new Set(Object.values(TYPE_TAGS));
|
|
27
|
+
/**
|
|
28
|
+
* Resolve a schema's fields into MongoStore field plans.
|
|
29
|
+
*
|
|
30
|
+
* Skips fields whose tags are all outside `TYPE_TAGS`; reports them
|
|
31
|
+
* via `unsupported`. Rejects invalid field names up front so the
|
|
32
|
+
* downstream signature is deterministic and the keys are safe.
|
|
33
|
+
*/
|
|
34
|
+
export function planFields(fields) {
|
|
35
|
+
const out = [];
|
|
36
|
+
const unsupported = [];
|
|
37
|
+
for (const field of fields) {
|
|
38
|
+
if (!isValidIdentifier(field.name)) {
|
|
39
|
+
unsupported.push({
|
|
40
|
+
name: field.name,
|
|
41
|
+
reason: `field name must match ${IDENTIFIER_PATTERN.source}; got '${field.name}'`,
|
|
42
|
+
});
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const tag = field.type.find((t) => KNOWN_TAGS.has(t));
|
|
46
|
+
if (tag === undefined) {
|
|
47
|
+
unsupported.push({
|
|
48
|
+
name: field.name,
|
|
49
|
+
reason: field.type.length === 0
|
|
50
|
+
? "field declares no type tags"
|
|
51
|
+
: `no recognised tag in [${field.type.join(", ")}]`,
|
|
52
|
+
});
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
out.push({ name: field.name, tag });
|
|
56
|
+
}
|
|
57
|
+
return { fields: out, unsupported };
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Deterministic signature for collision detection. Same name + same
|
|
61
|
+
* set of supported fields + same canonical tag per field → same string.
|
|
62
|
+
* Mirrors the strictness MemoryStore committed to and SQL backends get
|
|
63
|
+
* for free from column-type introspection.
|
|
64
|
+
*/
|
|
65
|
+
export function computeSignature(entityName, fields) {
|
|
66
|
+
const sorted = [...fields].sort((a, b) => a.name.localeCompare(b.name));
|
|
67
|
+
return JSON.stringify({
|
|
68
|
+
name: entityName,
|
|
69
|
+
fields: sorted.map((f) => [f.name, f.tag]),
|
|
70
|
+
});
|
|
71
|
+
}
|
package/esm/mongo/mod.d.ts
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
* MongoDB backend for b3nd.
|
|
3
3
|
*
|
|
4
4
|
* Store implementation backed by MongoDB. Requires an injected
|
|
5
|
-
* MongoExecutor so the package does not depend on a specific MongoDB
|
|
6
|
-
* driver.
|
|
5
|
+
* `MongoExecutor` so the package does not depend on a specific MongoDB
|
|
6
|
+
* driver. The executor is collection-agnostic: callers reach into a
|
|
7
|
+
* specific collection via `executor.collection(name)`, so a single
|
|
8
|
+
* MongoStore instance can host many entities side-by-side.
|
|
7
9
|
*/
|
|
8
10
|
export interface MongoFindManyOptions {
|
|
9
11
|
sort?: Record<string, 1 | -1>;
|
|
@@ -12,7 +14,7 @@ export interface MongoFindManyOptions {
|
|
|
12
14
|
/** Mongo projection map (1 = include, 0 = exclude). */
|
|
13
15
|
projection?: Record<string, 0 | 1>;
|
|
14
16
|
}
|
|
15
|
-
export interface
|
|
17
|
+
export interface MongoCollection {
|
|
16
18
|
insertOne(doc: Record<string, unknown>): Promise<{
|
|
17
19
|
acknowledged?: boolean;
|
|
18
20
|
}>;
|
|
@@ -27,8 +29,21 @@ export interface MongoExecutor {
|
|
|
27
29
|
deleteOne(filter: Record<string, unknown>): Promise<{
|
|
28
30
|
deletedCount?: number;
|
|
29
31
|
}>;
|
|
32
|
+
/** Idempotent: re-running with the same spec is a no-op. */
|
|
33
|
+
createIndex(spec: Record<string, 1 | -1>): Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
export interface MongoExecutor {
|
|
36
|
+
/** Hand out an ops handle for a specific collection. */
|
|
37
|
+
collection(name: string): MongoCollection;
|
|
38
|
+
/**
|
|
39
|
+
* Materialise a collection on the server. Idempotent — re-running
|
|
40
|
+
* for an existing collection is a no-op. Implementations should
|
|
41
|
+
* swallow the driver's "namespace exists" error.
|
|
42
|
+
*/
|
|
43
|
+
createCollection(name: string): Promise<void>;
|
|
44
|
+
/** List collection names on the active database. */
|
|
45
|
+
listCollectionNames(): Promise<string[]>;
|
|
30
46
|
ping(): Promise<boolean>;
|
|
31
|
-
transaction?: <T>(fn: (executor: MongoExecutor) => Promise<T>) => Promise<T>;
|
|
32
47
|
cleanup?: () => Promise<void>;
|
|
33
48
|
}
|
|
34
49
|
export { MongoStore } from "./store.js";
|
package/esm/mongo/mod.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/mongo/mod.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/mongo/mod.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC7E,SAAS,CACP,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,OAAO,CACR;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,OAAO,CAAA;KAAE,CACxE,CAAC;IACF,OAAO,CACL,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;IAC3C,QAAQ,CACN,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IACtC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACjE,SAAS,CACP,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtC,4DAA4D;IAC5D,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1D;AAED,MAAM,WAAW,aAAa;IAC5B,wDAAwD;IACxD,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAAC;IAC1C;;;;OAIG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,oDAAoD;IACpD,mBAAmB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACzC,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AAED,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
package/esm/mongo/mod.js
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
* MongoDB backend for b3nd.
|
|
3
3
|
*
|
|
4
4
|
* Store implementation backed by MongoDB. Requires an injected
|
|
5
|
-
* MongoExecutor so the package does not depend on a specific MongoDB
|
|
6
|
-
* driver.
|
|
5
|
+
* `MongoExecutor` so the package does not depend on a specific MongoDB
|
|
6
|
+
* driver. The executor is collection-agnostic: callers reach into a
|
|
7
|
+
* specific collection via `executor.collection(name)`, so a single
|
|
8
|
+
* MongoStore instance can host many entities side-by-side.
|
|
7
9
|
*/
|
|
8
10
|
export { MongoStore } from "./store.js";
|
package/esm/mongo/store.d.ts
CHANGED
|
@@ -1,42 +1,131 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* MongoStore — MongoDB implementation of
|
|
2
|
+
* MongoStore — MongoDB implementation of `EntityStore`.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* `
|
|
4
|
+
* One layout for every schema: a per-entity collection named
|
|
5
|
+
* `{prefix}_{entity}_data` with a `uri` primary key and one document
|
|
6
|
+
* key per supported field, plus `createdAt` / `updatedAt`.
|
|
7
|
+
* `BYTES_ENTITY` is just an entity with one `payload` field of BSON
|
|
8
|
+
* binary — no legacy special case.
|
|
8
9
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
10
|
+
* ## Lifecycle
|
|
11
|
+
*
|
|
12
|
+
* `entitySupport(schema)` is pure — it runs `planFields` and returns
|
|
13
|
+
* a `MongoEntityMeta` with the target collection name, declared field
|
|
14
|
+
* set, bytes-field set, canonical-tag-per-field signature, and the
|
|
15
|
+
* support report. No IO.
|
|
16
|
+
*
|
|
17
|
+
* `provisionEntity(meta)` materialises the entity:
|
|
18
|
+
*
|
|
19
|
+
* 1. Reads the meta collection `{prefix}_meta` for a prior entry
|
|
20
|
+
* under `meta.support.entity`.
|
|
21
|
+
* 2. If found with a matching signature → no-op (idempotent).
|
|
22
|
+
* 3. If found with a different signature → throws (collision: a
|
|
23
|
+
* same-name entity is already live in a different shape).
|
|
24
|
+
* 4. Otherwise: creates the entity collection, creates the `uri`
|
|
25
|
+
* index, and upserts the meta entry.
|
|
26
|
+
*
|
|
27
|
+
* `entityStatus(meta)` reads the meta collection and reports `"live"`
|
|
28
|
+
* only when the stored signature matches. Mongo is schemaless on the
|
|
29
|
+
* wire — without an explicit meta record there is nothing to
|
|
30
|
+
* introspect, so the meta collection is how shape collisions get
|
|
31
|
+
* detected (the same approach MemoryStore uses; the SQL backends get
|
|
32
|
+
* the same guarantee for free via column-type introspection).
|
|
33
|
+
*
|
|
34
|
+
* Writes/reads/deletes consume the meta directly: no per-call cache
|
|
35
|
+
* gate. The store enforces the extras check (a record with keys not
|
|
36
|
+
* declared in `meta` produces a per-entry write failure); value-type
|
|
37
|
+
* enforcement is left to higher layers because Mongo will accept any
|
|
38
|
+
* value at the BSON level.
|
|
39
|
+
*
|
|
40
|
+
* `fn=ls` / `fn=count` push down to MongoDB via a regex prefix filter
|
|
41
|
+
* on `uri` that enforces the shallow-direct-leaves contract
|
|
42
|
+
* (`^<prefix>[^/]+$`).
|
|
43
|
+
*
|
|
44
|
+
* `fn=find` (v2 §3.3) reuses the same regex query shape but composes
|
|
45
|
+
* the body for the broader grammar (`**` → `.*`, crosses `/`). The
|
|
46
|
+
* literal prefix stays escaped; the glob tail is compiled via
|
|
47
|
+
* `saveGlobToRegexBody` — the same helper `_ls` uses, which already
|
|
48
|
+
* emits `.*` for `**` regardless of fn (the wildcard semantics are a
|
|
49
|
+
* property of the glob token, not the verb). The `[^/]+` shallow
|
|
50
|
+
* fallback that `_ls` uses for "no pattern" is NOT used here: `find`
|
|
51
|
+
* always arrives with a pattern (parseUrl mirrors the URI-embedded
|
|
52
|
+
* glob into `params.pattern`; dispatch pushes it through under
|
|
53
|
+
* `pushDownFind: true`).
|
|
54
|
+
*
|
|
55
|
+
* Perf note: an anchored `^<literal-prefix><body>$` regex with a long
|
|
56
|
+
* literal prefix can use the per-collection `uri` index for prefix
|
|
57
|
+
* scans; broader patterns (`**` at the start) degrade to a collection
|
|
58
|
+
* scan. The contract advertises `find` with that caveat — callers that
|
|
59
|
+
* need fast deep walks under shallow prefixes should keep their root
|
|
60
|
+
* literal (`<root><room>/alice/**` scans only `alice/`).
|
|
61
|
+
*
|
|
62
|
+
* Mongo does not provide a portable single-collection batch
|
|
63
|
+
* write/delete primitive that fits the package's per-entry result
|
|
64
|
+
* contract, so writes happen one document at a time and
|
|
65
|
+
* `capabilities.atomicBatch` is `false`. Stream-shaped values on
|
|
66
|
+
* bytes fields are collected to `Uint8Array` up front per entry.
|
|
11
67
|
*/
|
|
12
|
-
import type { DeleteResult, Output, StatusResult } from "../deps/jsr.io/@bandeira-tech/b3nd-core/0.
|
|
13
|
-
import { type BytesOnlyEntityMeta } from "../byte-entity-shim.js";
|
|
68
|
+
import type { DeleteResult, Output, StatusResult } from "../deps/jsr.io/@bandeira-tech/b3nd-core/0.25.0/src/types/types.js";
|
|
14
69
|
import type { EntityStore } from "../entity-store.js";
|
|
15
|
-
import type
|
|
70
|
+
import { type EntityMeta, type EntityRecord, type EntitySchema } from "../entity.js";
|
|
16
71
|
import type { StoreCapabilities, StoreWriteResult } from "../types.js";
|
|
72
|
+
import { type FieldPlan } from "./fields.js";
|
|
17
73
|
import type { MongoExecutor } from "./mod.js";
|
|
18
|
-
|
|
19
|
-
|
|
74
|
+
/**
|
|
75
|
+
* MongoStore-specific entity handle.
|
|
76
|
+
*
|
|
77
|
+
* `collectionName` is the prefixed-and-suffixed target collection
|
|
78
|
+
* (`{prefix}_{entity}_data`); `fields` are the planned user fields
|
|
79
|
+
* (without the always-present `uri`, `createdAt`, `updatedAt`);
|
|
80
|
+
* `declared` is the set of user field names for the per-write extras
|
|
81
|
+
* check; `bytesFields` drives stream normalisation. `signature` is
|
|
82
|
+
* the canonical string used by the meta collection for collision
|
|
83
|
+
* detection.
|
|
84
|
+
*/
|
|
85
|
+
export interface MongoEntityMeta extends EntityMeta {
|
|
86
|
+
readonly collectionName: string;
|
|
87
|
+
readonly fields: readonly FieldPlan[];
|
|
88
|
+
readonly declared: ReadonlySet<string>;
|
|
89
|
+
readonly bytesFields: ReadonlySet<string>;
|
|
90
|
+
readonly signature: string;
|
|
91
|
+
}
|
|
92
|
+
export declare class MongoStore implements EntityStore<MongoEntityMeta> {
|
|
93
|
+
private readonly collectionPrefix;
|
|
20
94
|
private readonly executor;
|
|
21
|
-
constructor(
|
|
22
|
-
entitySupport(schema: EntitySchema):
|
|
23
|
-
entityStatus(meta:
|
|
24
|
-
provisionEntity(
|
|
25
|
-
write(meta:
|
|
95
|
+
constructor(collectionPrefix: string, executor: MongoExecutor);
|
|
96
|
+
entitySupport(schema: EntitySchema): MongoEntityMeta;
|
|
97
|
+
entityStatus(meta: MongoEntityMeta): Promise<"live" | "unprovisioned">;
|
|
98
|
+
provisionEntity(meta: MongoEntityMeta): Promise<void>;
|
|
99
|
+
write(meta: MongoEntityMeta, entries: {
|
|
26
100
|
uri: string;
|
|
27
101
|
record: EntityRecord;
|
|
28
102
|
}[]): Promise<StoreWriteResult[]>;
|
|
29
|
-
read<T = EntityRecord | undefined>(meta:
|
|
30
|
-
delete(meta:
|
|
31
|
-
|
|
32
|
-
|
|
103
|
+
read<T = EntityRecord | undefined>(meta: MongoEntityMeta, urls: string[]): Promise<Output<T>[]>;
|
|
104
|
+
delete(meta: MongoEntityMeta, uris: string[]): Promise<DeleteResult[]>;
|
|
105
|
+
status(): Promise<StatusResult>;
|
|
106
|
+
capabilities(): StoreCapabilities;
|
|
33
107
|
private _readOne;
|
|
34
|
-
/**
|
|
108
|
+
/**
|
|
109
|
+
* Compose the Mongo filter for shallow-direct-leaves under
|
|
110
|
+
* `prefixUri`, optionally tightened by a glob `pattern` (regex body
|
|
111
|
+
* spliced in place of `[^/]+`) and a `cursor` (`$gt` or `$lt` on
|
|
112
|
+
* `uri` matching the active sort order).
|
|
113
|
+
*/
|
|
35
114
|
private _leafFilter;
|
|
36
115
|
private _ls;
|
|
116
|
+
/**
|
|
117
|
+
* Compose the Mongo filter for a `find` (deep walk) under
|
|
118
|
+
* `prefixUri`. Same shape as `_leafFilter` — `$regex` anchored on
|
|
119
|
+
* both ends, optional cursor `$gt`/`$lt` — but the body is the glob
|
|
120
|
+
* compiled with `**` → `.*` semantics (crosses `/`). For find we
|
|
121
|
+
* REQUIRE a pattern: parseUrl guarantees `params.pattern` is set
|
|
122
|
+
* whenever fn=find dispatches to this handler (URI-embedded glob or
|
|
123
|
+
* the dual-accept `?pattern=` form). If pattern is absent we throw
|
|
124
|
+
* loudly rather than silently widening to `.*` — that would conflate
|
|
125
|
+
* "find everything" with a parser bug.
|
|
126
|
+
*/
|
|
127
|
+
private _subtreeFilter;
|
|
128
|
+
private _find;
|
|
37
129
|
private _count;
|
|
38
|
-
private _deleteBytes;
|
|
39
|
-
status(): Promise<StatusResult>;
|
|
40
|
-
capabilities(): StoreCapabilities;
|
|
41
130
|
}
|
|
42
131
|
//# sourceMappingURL=store.d.ts.map
|
package/esm/mongo/store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/mongo/store.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/mongo/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,MAAM,EACN,YAAY,EACb,MAAM,mEAAmE,CAAC;AAO3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EACL,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,YAAY,EAGlB,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAoB,KAAK,SAAS,EAAc,MAAM,aAAa,CAAC;AAC3E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAI9C;;;;;;;;;;GAUG;AACH,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACvC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AA4CD,qBAAa,UAAW,YAAW,WAAW,CAAC,eAAe,CAAC;IAC7D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;gBAE7B,gBAAgB,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa;IAe7D,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,eAAe;IAmB9C,YAAY,CAChB,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,MAAM,GAAG,eAAe,CAAC;IAQ9B,eAAe,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAyBrD,KAAK,CACT,IAAI,EAAE,eAAe,EACrB,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,YAAY,CAAA;KAAE,EAAE,GAC/C,OAAO,CAAC,gBAAgB,EAAE,CAAC;IA8C9B,IAAI,CAAC,CAAC,GAAG,YAAY,GAAG,SAAS,EAC/B,IAAI,EAAE,eAAe,EACrB,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IAajB,MAAM,CACV,IAAI,EAAE,eAAe,EACrB,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,YAAY,EAAE,CAAC;IAoBpB,MAAM,IAAI,OAAO,CAAC,YAAY,CAAC;IAyBrC,YAAY,IAAI,iBAAiB;YAMnB,QAAQ;IAYtB;;;;;OAKG;IACH,OAAO,CAAC,WAAW;YAgBL,GAAG;IAmDjB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,cAAc;YAsBR,KAAK;YA8CL,MAAM;CAarB"}
|