@bandeira-tech/b3nd-save 0.8.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/LICENSE +21 -0
- package/esm/_dnt.shims.d.ts +2 -0
- package/esm/_dnt.shims.d.ts.map +1 -0
- package/esm/_dnt.shims.js +57 -0
- package/esm/byte-entity-shim.d.ts +47 -0
- package/esm/byte-entity-shim.d.ts.map +1 -0
- package/esm/byte-entity-shim.js +138 -0
- package/esm/clients/mod.d.ts +15 -0
- package/esm/clients/mod.d.ts.map +1 -0
- package/esm/clients/mod.js +14 -0
- package/esm/clients/save-client.d.ts +87 -0
- package/esm/clients/save-client.d.ts.map +1 -0
- package/esm/clients/save-client.js +174 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/mod.d.ts +40 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/mod.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/mod.js +31 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/client-console/client.d.ts +30 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/client-console/client.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/client-console/client.js +70 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/encoding/encoding.d.ts +16 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/encoding/encoding.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/encoding/encoding.js +50 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/encrypt/mod.d.ts +235 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/encrypt/mod.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/encrypt/mod.js +619 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/functional-client/functional-client.d.ts +43 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/functional-client/functional-client.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/functional-client/functional-client.js +54 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/match-pattern/match-pattern.d.ts +47 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/match-pattern/match-pattern.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/match-pattern/match-pattern.js +134 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/network/decorators.d.ts +20 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/network/decorators.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/network/decorators.js +34 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/network/network.d.ts +46 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/network/network.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/network/network.js +131 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/network/peer.d.ts +27 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/network/peer.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/network/peer.js +25 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/network/policies/flood.d.ts +59 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/network/policies/flood.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/network/policies/flood.js +188 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/network/policies/path-vector.d.ts +35 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/network/policies/path-vector.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/network/policies/path-vector.js +57 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/network/policies/tell-and-read.d.ts +117 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/network/policies/tell-and-read.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/network/policies/tell-and-read.js +125 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/network/types.d.ts +112 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/network/types.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/network/types.js +21 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/observe-emitter/observe-emitter.d.ts +35 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/observe-emitter/observe-emitter.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/observe-emitter/observe-emitter.js +106 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/connection.d.ts +88 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/connection.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/connection.js +86 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/events.d.ts +83 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/events.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/events.js +115 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/hooks.d.ts +164 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/hooks.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/hooks.js +67 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/identity.d.ts +99 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/identity.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/identity.js +190 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/operation-handle.d.ts +185 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/operation-handle.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/operation-handle.js +103 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/reactions.d.ts +58 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/reactions.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/reactions.js +64 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/rig.d.ts +295 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/rig.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/rig.js +898 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/types.d.ts +167 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/types.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/rig/types.js +5 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/types/types.d.ts +278 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/types/types.d.ts.map +1 -0
- package/esm/deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/types/types.js +89 -0
- package/esm/dispatch.d.ts +35 -0
- package/esm/dispatch.d.ts.map +1 -0
- package/esm/dispatch.js +40 -0
- package/esm/elasticsearch/mod.d.ts +31 -0
- package/esm/elasticsearch/mod.d.ts.map +1 -0
- package/esm/elasticsearch/mod.js +8 -0
- package/esm/elasticsearch/store.d.ts +44 -0
- package/esm/elasticsearch/store.d.ts.map +1 -0
- package/esm/elasticsearch/store.js +213 -0
- package/esm/entity-store.d.ts +106 -0
- package/esm/entity-store.d.ts.map +1 -0
- package/esm/entity-store.js +46 -0
- package/esm/entity.d.ts +125 -0
- package/esm/entity.d.ts.map +1 -0
- package/esm/entity.js +66 -0
- package/esm/errors.d.ts +23 -0
- package/esm/errors.d.ts.map +1 -0
- package/esm/errors.js +25 -0
- package/esm/fs/mod.d.ts +28 -0
- package/esm/fs/mod.d.ts.map +1 -0
- package/esm/fs/mod.js +13 -0
- package/esm/fs/store.d.ts +45 -0
- package/esm/fs/store.d.ts.map +1 -0
- package/esm/fs/store.js +194 -0
- package/esm/indexeddb/mod.d.ts +9 -0
- package/esm/indexeddb/mod.d.ts.map +1 -0
- package/esm/indexeddb/mod.js +8 -0
- package/esm/indexeddb/store.d.ts +47 -0
- package/esm/indexeddb/store.d.ts.map +1 -0
- package/esm/indexeddb/store.js +299 -0
- package/esm/ipfs/mod.d.ts +24 -0
- package/esm/ipfs/mod.d.ts.map +1 -0
- package/esm/ipfs/mod.js +13 -0
- package/esm/ipfs/store.d.ts +42 -0
- package/esm/ipfs/store.d.ts.map +1 -0
- package/esm/ipfs/store.js +197 -0
- package/esm/localstorage/mod.d.ts +9 -0
- package/esm/localstorage/mod.d.ts.map +1 -0
- package/esm/localstorage/mod.js +8 -0
- package/esm/localstorage/store.d.ts +45 -0
- package/esm/localstorage/store.d.ts.map +1 -0
- package/esm/localstorage/store.js +147 -0
- package/esm/memory/mod.d.ts +12 -0
- package/esm/memory/mod.d.ts.map +1 -0
- package/esm/memory/mod.js +11 -0
- package/esm/memory/store.d.ts +73 -0
- package/esm/memory/store.d.ts.map +1 -0
- package/esm/memory/store.js +300 -0
- package/esm/mod.d.ts +36 -0
- package/esm/mod.d.ts.map +1 -0
- package/esm/mod.js +31 -0
- package/esm/mongo/mod.d.ts +35 -0
- package/esm/mongo/mod.d.ts.map +1 -0
- package/esm/mongo/mod.js +8 -0
- package/esm/mongo/store.d.ts +42 -0
- package/esm/mongo/store.d.ts.map +1 -0
- package/esm/mongo/store.js +185 -0
- package/esm/package.json +3 -0
- package/esm/payload.d.ts +24 -0
- package/esm/payload.d.ts.map +1 -0
- package/esm/payload.js +30 -0
- package/esm/postgres/columns.d.ts +33 -0
- package/esm/postgres/columns.d.ts.map +1 -0
- package/esm/postgres/columns.js +51 -0
- package/esm/postgres/mod.d.ts +19 -0
- package/esm/postgres/mod.d.ts.map +1 -0
- package/esm/postgres/mod.js +9 -0
- package/esm/postgres/store.d.ts +75 -0
- package/esm/postgres/store.d.ts.map +1 -0
- package/esm/postgres/store.js +364 -0
- package/esm/read.d.ts +40 -0
- package/esm/read.d.ts.map +1 -0
- package/esm/read.js +67 -0
- package/esm/s3/mod.d.ts +23 -0
- package/esm/s3/mod.d.ts.map +1 -0
- package/esm/s3/mod.js +13 -0
- package/esm/s3/store.d.ts +46 -0
- package/esm/s3/store.d.ts.map +1 -0
- package/esm/s3/store.js +183 -0
- package/esm/sqlite/mod.d.ts +18 -0
- package/esm/sqlite/mod.d.ts.map +1 -0
- package/esm/sqlite/mod.js +8 -0
- package/esm/sqlite/schema.d.ts +10 -0
- package/esm/sqlite/schema.d.ts.map +1 -0
- package/esm/sqlite/schema.js +26 -0
- package/esm/sqlite/store.d.ts +42 -0
- package/esm/sqlite/store.d.ts.map +1 -0
- package/esm/sqlite/store.js +184 -0
- package/esm/types.d.ts +101 -0
- package/esm/types.d.ts.map +1 -0
- package/esm/types.js +21 -0
- package/esm/url.d.ts +108 -0
- package/esm/url.d.ts.map +1 -0
- package/esm/url.js +151 -0
- package/package.json +93 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IPFS backend for b3nd.
|
|
3
|
+
*
|
|
4
|
+
* Store implementation backed by IPFS. Requires an injected
|
|
5
|
+
* IpfsExecutor so the package does not depend on a specific IPFS
|
|
6
|
+
* library. Blocks hold raw payload bytes — the store is opaque.
|
|
7
|
+
*
|
|
8
|
+
* `add` accepts the `StorePayload` union to support both buffered
|
|
9
|
+
* and streaming callers; `cat` returns a `ReadableStream<Uint8Array>`
|
|
10
|
+
* to avoid materializing the block in memory unless the caller wants
|
|
11
|
+
* it.
|
|
12
|
+
*/
|
|
13
|
+
import type { StorePayload } from "../types.js";
|
|
14
|
+
export interface IpfsExecutor {
|
|
15
|
+
add: (content: StorePayload) => Promise<string>;
|
|
16
|
+
cat: (cid: string) => Promise<ReadableStream<Uint8Array>>;
|
|
17
|
+
pin: (cid: string) => Promise<void>;
|
|
18
|
+
unpin: (cid: string) => Promise<void>;
|
|
19
|
+
listPins: () => Promise<string[]>;
|
|
20
|
+
isOnline: () => Promise<boolean>;
|
|
21
|
+
cleanup?: () => Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
export { IpfsStore } from "./store.js";
|
|
24
|
+
//# sourceMappingURL=mod.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/ipfs/mod.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAChD,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;IAC1D,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,QAAQ,EAAE,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAClC,QAAQ,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AAED,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC"}
|
package/esm/ipfs/mod.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IPFS backend for b3nd.
|
|
3
|
+
*
|
|
4
|
+
* Store implementation backed by IPFS. Requires an injected
|
|
5
|
+
* IpfsExecutor so the package does not depend on a specific IPFS
|
|
6
|
+
* library. Blocks hold raw payload bytes — the store is opaque.
|
|
7
|
+
*
|
|
8
|
+
* `add` accepts the `StorePayload` union to support both buffered
|
|
9
|
+
* and streaming callers; `cat` returns a `ReadableStream<Uint8Array>`
|
|
10
|
+
* to avoid materializing the block in memory unless the caller wants
|
|
11
|
+
* it.
|
|
12
|
+
*/
|
|
13
|
+
export { IpfsStore } from "./store.js";
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IpfsStore — IPFS implementation of Store.
|
|
3
|
+
*
|
|
4
|
+
* Pure mechanical byte storage with no protocol awareness. Writes
|
|
5
|
+
* pinned IPFS objects and maintains an in-memory `uri → CID` index
|
|
6
|
+
* for lookups. The block body is the payload bytes verbatim.
|
|
7
|
+
*
|
|
8
|
+
* `fn=ls` / `fn=count` are shallow direct-leaves only: scan the
|
|
9
|
+
* in-memory index, keep URIs whose remainder under the prefix has no
|
|
10
|
+
* further `/`.
|
|
11
|
+
*/
|
|
12
|
+
import type { DeleteResult, Output, StatusResult } from "../deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/types/types.js";
|
|
13
|
+
import { type BytesOnlyEntityMeta } from "../byte-entity-shim.js";
|
|
14
|
+
import type { EntityStore } from "../entity-store.js";
|
|
15
|
+
import type { EntityRecord, EntitySchema } from "../entity.js";
|
|
16
|
+
import type { StoreCapabilities, StoreWriteResult } from "../types.js";
|
|
17
|
+
import type { IpfsExecutor } from "./mod.js";
|
|
18
|
+
export declare class IpfsStore implements EntityStore<BytesOnlyEntityMeta> {
|
|
19
|
+
private readonly executor;
|
|
20
|
+
private readonly index;
|
|
21
|
+
constructor(executor: IpfsExecutor);
|
|
22
|
+
entitySupport(schema: EntitySchema): BytesOnlyEntityMeta;
|
|
23
|
+
entityStatus(meta: BytesOnlyEntityMeta): Promise<"live" | "unprovisioned">;
|
|
24
|
+
provisionEntity(_meta: BytesOnlyEntityMeta): Promise<void>;
|
|
25
|
+
write(meta: BytesOnlyEntityMeta, entries: {
|
|
26
|
+
uri: string;
|
|
27
|
+
record: EntityRecord;
|
|
28
|
+
}[]): Promise<StoreWriteResult[]>;
|
|
29
|
+
read<T = EntityRecord | undefined>(meta: BytesOnlyEntityMeta, urls: string[]): Promise<Output<T>[]>;
|
|
30
|
+
delete(meta: BytesOnlyEntityMeta, uris: string[]): Promise<DeleteResult[]>;
|
|
31
|
+
private _writeBytes;
|
|
32
|
+
private _readBytes;
|
|
33
|
+
private _readOne;
|
|
34
|
+
/** Shallow direct-leaves from the in-memory URI index. */
|
|
35
|
+
private _directLeafUris;
|
|
36
|
+
private _ls;
|
|
37
|
+
private _count;
|
|
38
|
+
private _deleteBytes;
|
|
39
|
+
status(): Promise<StatusResult>;
|
|
40
|
+
capabilities(): StoreCapabilities;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/ipfs/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,MAAM,EACN,YAAY,EACb,MAAM,mEAAmE,CAAC;AAC3E,OAAO,EAEL,KAAK,mBAAmB,EAIzB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAM/D,OAAO,KAAK,EACV,iBAAiB,EAEjB,gBAAgB,EACjB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAQ7C,qBAAa,SAAU,YAAW,WAAW,CAAC,mBAAmB,CAAC;IAChE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;gBAE3C,QAAQ,EAAE,YAAY;IAOlC,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,mBAAmB;IAIxD,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,GAAG,eAAe,CAAC;IAI1E,eAAe,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1D,KAAK,CACH,IAAI,EAAE,mBAAmB,EACzB,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,YAAY,CAAA;KAAE,EAAE,GAC/C,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAS9B,IAAI,CAAC,CAAC,GAAG,YAAY,GAAG,SAAS,EAC/B,IAAI,EAAE,mBAAmB,EACzB,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IASvB,MAAM,CAAC,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;YAW5D,WAAW;IAiCzB,OAAO,CAAC,UAAU;YAQJ,QAAQ;IAYtB,0DAA0D;IAC1D,OAAO,CAAC,eAAe;YAWT,GAAG;IA0BjB,OAAO,CAAC,MAAM;YAOA,YAAY;IA4BpB,MAAM,IAAI,OAAO,CAAC,YAAY,CAAC;IAqCrC,YAAY,IAAI,iBAAiB;CAGlC"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IpfsStore — IPFS implementation of Store.
|
|
3
|
+
*
|
|
4
|
+
* Pure mechanical byte storage with no protocol awareness. Writes
|
|
5
|
+
* pinned IPFS objects and maintains an in-memory `uri → CID` index
|
|
6
|
+
* for lookups. The block body is the payload bytes verbatim.
|
|
7
|
+
*
|
|
8
|
+
* `fn=ls` / `fn=count` are shallow direct-leaves only: scan the
|
|
9
|
+
* in-memory index, keep URIs whose remainder under the prefix has no
|
|
10
|
+
* further `/`.
|
|
11
|
+
*/
|
|
12
|
+
import { bytesOnlyDelete, bytesOnlyEntitySupport, bytesOnlyRead, bytesOnlyWrite, } from "../byte-entity-shim.js";
|
|
13
|
+
import { dispatchRead } from "../dispatch.js";
|
|
14
|
+
import { storageFailure } from "../errors.js";
|
|
15
|
+
import { validateReadParams } from "../read.js";
|
|
16
|
+
const STORE_NAME = "IpfsStore";
|
|
17
|
+
export class IpfsStore {
|
|
18
|
+
executor;
|
|
19
|
+
index = new Map();
|
|
20
|
+
constructor(executor) {
|
|
21
|
+
if (!executor)
|
|
22
|
+
throw new Error("executor is required");
|
|
23
|
+
this.executor = executor;
|
|
24
|
+
}
|
|
25
|
+
// ── EntityStore surface ──────────────────────────────────────────
|
|
26
|
+
entitySupport(schema) {
|
|
27
|
+
return bytesOnlyEntitySupport(schema);
|
|
28
|
+
}
|
|
29
|
+
entityStatus(meta) {
|
|
30
|
+
return Promise.resolve(meta.isBytes ? "live" : "unprovisioned");
|
|
31
|
+
}
|
|
32
|
+
provisionEntity(_meta) {
|
|
33
|
+
return Promise.resolve();
|
|
34
|
+
}
|
|
35
|
+
write(meta, entries) {
|
|
36
|
+
return bytesOnlyWrite(meta, STORE_NAME, entries, (e) => this._writeBytes(e));
|
|
37
|
+
}
|
|
38
|
+
read(meta, urls) {
|
|
39
|
+
return bytesOnlyRead(meta, STORE_NAME, urls, (u) => this._readBytes(u));
|
|
40
|
+
}
|
|
41
|
+
delete(meta, uris) {
|
|
42
|
+
return bytesOnlyDelete(meta, STORE_NAME, uris, (u) => this._deleteBytes(u));
|
|
43
|
+
}
|
|
44
|
+
// ── Byte ops (BYTES_ENTITY routing) ──────────────────────────────
|
|
45
|
+
async _writeBytes(entries) {
|
|
46
|
+
const results = [];
|
|
47
|
+
for (const entry of entries) {
|
|
48
|
+
try {
|
|
49
|
+
const cid = await this.executor.add(entry.payload);
|
|
50
|
+
await this.executor.pin(cid);
|
|
51
|
+
// Unpin the old CID if this URI was already indexed
|
|
52
|
+
const existing = this.index.get(entry.uri);
|
|
53
|
+
if (existing) {
|
|
54
|
+
try {
|
|
55
|
+
await this.executor.unpin(existing.cid);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// Old CID may already be unpinned — ignore
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
this.index.set(entry.uri, { cid });
|
|
62
|
+
results.push({ success: true });
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
results.push({
|
|
66
|
+
success: false,
|
|
67
|
+
...storageFailure(err, "Write failed", entry.uri),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return results;
|
|
72
|
+
}
|
|
73
|
+
_readBytes(urls) {
|
|
74
|
+
return dispatchRead(urls, STORE_NAME, {
|
|
75
|
+
read: (p) => this._readOne(p.uri),
|
|
76
|
+
ls: (p) => this._ls(p),
|
|
77
|
+
count: (p) => this._count(p),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
async _readOne(uri) {
|
|
81
|
+
const entry = this.index.get(uri);
|
|
82
|
+
if (!entry)
|
|
83
|
+
return undefined;
|
|
84
|
+
try {
|
|
85
|
+
return await this.executor.cat(entry.cid);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/** Shallow direct-leaves from the in-memory URI index. */
|
|
92
|
+
_directLeafUris(prefixUri) {
|
|
93
|
+
const out = [];
|
|
94
|
+
for (const uri of this.index.keys()) {
|
|
95
|
+
if (!uri.startsWith(prefixUri))
|
|
96
|
+
continue;
|
|
97
|
+
const tail = uri.slice(prefixUri.length);
|
|
98
|
+
if (tail === "" || tail.includes("/"))
|
|
99
|
+
continue;
|
|
100
|
+
out.push(uri);
|
|
101
|
+
}
|
|
102
|
+
return out;
|
|
103
|
+
}
|
|
104
|
+
async _ls(parsed) {
|
|
105
|
+
validateReadParams(parsed.params, STORE_NAME);
|
|
106
|
+
const { params } = parsed;
|
|
107
|
+
const format = params.format ?? "full";
|
|
108
|
+
let uris = this._directLeafUris(parsed.uri);
|
|
109
|
+
if (params.sortBy === "uri") {
|
|
110
|
+
const dir = params.sortOrder === "desc" ? -1 : 1;
|
|
111
|
+
uris = [...uris].sort((a, b) => a.localeCompare(b) * dir);
|
|
112
|
+
}
|
|
113
|
+
if (params.limit !== undefined) {
|
|
114
|
+
const page = params.page ?? 1;
|
|
115
|
+
const start = (page - 1) * params.limit;
|
|
116
|
+
uris = uris.slice(start, start + params.limit);
|
|
117
|
+
}
|
|
118
|
+
if (format === "uris")
|
|
119
|
+
return uris;
|
|
120
|
+
const out = [];
|
|
121
|
+
for (const uri of uris) {
|
|
122
|
+
out.push([uri, await this._readOne(uri)]);
|
|
123
|
+
}
|
|
124
|
+
return out;
|
|
125
|
+
}
|
|
126
|
+
_count(parsed) {
|
|
127
|
+
if (parsed.params.pattern !== undefined) {
|
|
128
|
+
throw new Error(`${STORE_NAME}: pattern filter not supported`);
|
|
129
|
+
}
|
|
130
|
+
return this._directLeafUris(parsed.uri).length;
|
|
131
|
+
}
|
|
132
|
+
async _deleteBytes(uris) {
|
|
133
|
+
const results = [];
|
|
134
|
+
for (const uri of uris) {
|
|
135
|
+
try {
|
|
136
|
+
const entry = this.index.get(uri);
|
|
137
|
+
if (entry) {
|
|
138
|
+
try {
|
|
139
|
+
await this.executor.unpin(entry.cid);
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
// CID may already be unpinned — ignore
|
|
143
|
+
}
|
|
144
|
+
this.index.delete(uri);
|
|
145
|
+
}
|
|
146
|
+
results.push({ success: true });
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
results.push({
|
|
150
|
+
success: false,
|
|
151
|
+
...storageFailure(err, "Delete failed", uri),
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return results;
|
|
156
|
+
}
|
|
157
|
+
// ── Status ───────────────────────────────────────────────────────
|
|
158
|
+
async status() {
|
|
159
|
+
try {
|
|
160
|
+
const online = await this.executor.isOnline();
|
|
161
|
+
if (!online) {
|
|
162
|
+
return {
|
|
163
|
+
status: "unhealthy",
|
|
164
|
+
message: "IPFS node is not reachable",
|
|
165
|
+
fns: ["read", "ls", "count"],
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
// Derive schema from indexed URIs
|
|
169
|
+
const programs = new Set();
|
|
170
|
+
for (const uri of this.index.keys()) {
|
|
171
|
+
try {
|
|
172
|
+
const url = new URL(uri);
|
|
173
|
+
programs.add(`${url.protocol}//${url.hostname}`);
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
// skip malformed URIs
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
status: "healthy",
|
|
181
|
+
schema: [...programs],
|
|
182
|
+
fns: ["read", "ls", "count"],
|
|
183
|
+
details: { indexedUris: this.index.size },
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
return {
|
|
188
|
+
status: "unhealthy",
|
|
189
|
+
message: error instanceof Error ? error.message : String(error),
|
|
190
|
+
fns: ["read", "ls", "count"],
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
capabilities() {
|
|
195
|
+
return { atomicBatch: false };
|
|
196
|
+
}
|
|
197
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LocalStorage backend for b3nd.
|
|
3
|
+
*
|
|
4
|
+
* Browser localStorage Store implementation. Pure mechanical storage
|
|
5
|
+
* with no protocol awareness — wrap with SaveClient
|
|
6
|
+
* for NodeProtocolInterface.
|
|
7
|
+
*/
|
|
8
|
+
export { LocalStorageStore } from "./store.js";
|
|
9
|
+
//# sourceMappingURL=mod.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/localstorage/mod.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LocalStorageStore — browser localStorage implementation of Store.
|
|
3
|
+
*
|
|
4
|
+
* Pure mechanical byte storage with no protocol awareness. Uses
|
|
5
|
+
* `localStorage` as a flat key→string KV. Payload bytes are
|
|
6
|
+
* base64-encoded since `localStorage` values are strings.
|
|
7
|
+
*/
|
|
8
|
+
import type { DeleteResult, Output, StatusResult } from "../deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/types/types.js";
|
|
9
|
+
import { type BytesOnlyEntityMeta } from "../byte-entity-shim.js";
|
|
10
|
+
import type { EntityStore } from "../entity-store.js";
|
|
11
|
+
import type { EntityRecord, EntitySchema } from "../entity.js";
|
|
12
|
+
import type { StoreCapabilities, StoreWriteResult } from "../types.js";
|
|
13
|
+
export declare class LocalStorageStore implements EntityStore<BytesOnlyEntityMeta> {
|
|
14
|
+
private readonly keyPrefix;
|
|
15
|
+
private readonly storage;
|
|
16
|
+
constructor(config?: {
|
|
17
|
+
keyPrefix?: string;
|
|
18
|
+
storage?: Storage;
|
|
19
|
+
});
|
|
20
|
+
private getKey;
|
|
21
|
+
entitySupport(schema: EntitySchema): BytesOnlyEntityMeta;
|
|
22
|
+
entityStatus(meta: BytesOnlyEntityMeta): Promise<"live" | "unprovisioned">;
|
|
23
|
+
provisionEntity(_meta: BytesOnlyEntityMeta): Promise<void>;
|
|
24
|
+
write(meta: BytesOnlyEntityMeta, entries: {
|
|
25
|
+
uri: string;
|
|
26
|
+
record: EntityRecord;
|
|
27
|
+
}[]): Promise<StoreWriteResult[]>;
|
|
28
|
+
read<T = EntityRecord | undefined>(meta: BytesOnlyEntityMeta, urls: string[]): Promise<Output<T>[]>;
|
|
29
|
+
delete(meta: BytesOnlyEntityMeta, uris: string[]): Promise<DeleteResult[]>;
|
|
30
|
+
private _writeBytes;
|
|
31
|
+
private _readBytes;
|
|
32
|
+
private _readOne;
|
|
33
|
+
/**
|
|
34
|
+
* Walk localStorage once, returning `[uri, bytes]` for every entry
|
|
35
|
+
* whose URI is `prefix + <segment>` with no further `/`. Subtree-only
|
|
36
|
+
* paths are excluded by the slash check.
|
|
37
|
+
*/
|
|
38
|
+
private _directLeaves;
|
|
39
|
+
private _ls;
|
|
40
|
+
private _count;
|
|
41
|
+
private _deleteBytes;
|
|
42
|
+
status(): Promise<StatusResult>;
|
|
43
|
+
capabilities(): StoreCapabilities;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/localstorage/store.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,MAAM,EACN,YAAY,EACb,MAAM,mEAAmE,CAAC;AAC3E,OAAO,EAEL,KAAK,mBAAmB,EAIzB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAQ/D,OAAO,KAAK,EACV,iBAAiB,EAEjB,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAIrB,qBAAa,iBAAkB,YAAW,WAAW,CAAC,mBAAmB,CAAC;IACxE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;gBAEtB,MAAM,GAAE;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,OAAO,CAAC;KACd;IAUN,OAAO,CAAC,MAAM;IAMd,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,mBAAmB;IAIxD,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,GAAG,eAAe,CAAC;IAI1E,eAAe,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1D,KAAK,CACH,IAAI,EAAE,mBAAmB,EACzB,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,YAAY,CAAA;KAAE,EAAE,GAC/C,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAS9B,IAAI,CAAC,CAAC,GAAG,YAAY,GAAG,SAAS,EAC/B,IAAI,EAAE,mBAAmB,EACzB,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IASvB,MAAM,CAAC,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;YAW5D,WAAW;IAqBzB,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,QAAQ;IAMhB;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,GAAG;IAQX,OAAO,CAAC,MAAM;IAOd,OAAO,CAAC,YAAY;IAoBpB,MAAM,IAAI,OAAO,CAAC,YAAY,CAAC;IAmB/B,YAAY,IAAI,iBAAiB;CAGlC"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LocalStorageStore — browser localStorage implementation of Store.
|
|
3
|
+
*
|
|
4
|
+
* Pure mechanical byte storage with no protocol awareness. Uses
|
|
5
|
+
* `localStorage` as a flat key→string KV. Payload bytes are
|
|
6
|
+
* base64-encoded since `localStorage` values are strings.
|
|
7
|
+
*/
|
|
8
|
+
import { bytesOnlyDelete, bytesOnlyEntitySupport, bytesOnlyRead, bytesOnlyWrite, } from "../byte-entity-shim.js";
|
|
9
|
+
import { decodeBase64, encodeBase64 } from "../deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/mod.js";
|
|
10
|
+
import { dispatchRead } from "../dispatch.js";
|
|
11
|
+
import { storageFailure } from "../errors.js";
|
|
12
|
+
import { toBytes } from "../payload.js";
|
|
13
|
+
import { applyReadParams } from "../read.js";
|
|
14
|
+
const STORE_NAME = "LocalStorageStore";
|
|
15
|
+
export class LocalStorageStore {
|
|
16
|
+
keyPrefix;
|
|
17
|
+
storage;
|
|
18
|
+
constructor(config = {}) {
|
|
19
|
+
this.keyPrefix = config.keyPrefix || "b3nd:";
|
|
20
|
+
this.storage = config.storage ||
|
|
21
|
+
(typeof localStorage !== "undefined" ? localStorage : null);
|
|
22
|
+
if (!this.storage) {
|
|
23
|
+
throw new Error("localStorage is not available in this environment");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
getKey(uri) {
|
|
27
|
+
return `${this.keyPrefix}${uri}`;
|
|
28
|
+
}
|
|
29
|
+
// ── EntityStore surface ──────────────────────────────────────────
|
|
30
|
+
entitySupport(schema) {
|
|
31
|
+
return bytesOnlyEntitySupport(schema);
|
|
32
|
+
}
|
|
33
|
+
entityStatus(meta) {
|
|
34
|
+
return Promise.resolve(meta.isBytes ? "live" : "unprovisioned");
|
|
35
|
+
}
|
|
36
|
+
provisionEntity(_meta) {
|
|
37
|
+
return Promise.resolve();
|
|
38
|
+
}
|
|
39
|
+
write(meta, entries) {
|
|
40
|
+
return bytesOnlyWrite(meta, STORE_NAME, entries, (e) => this._writeBytes(e));
|
|
41
|
+
}
|
|
42
|
+
read(meta, urls) {
|
|
43
|
+
return bytesOnlyRead(meta, STORE_NAME, urls, (u) => this._readBytes(u));
|
|
44
|
+
}
|
|
45
|
+
delete(meta, uris) {
|
|
46
|
+
return bytesOnlyDelete(meta, STORE_NAME, uris, (u) => this._deleteBytes(u));
|
|
47
|
+
}
|
|
48
|
+
// ── Byte ops (BYTES_ENTITY routing) ──────────────────────────────
|
|
49
|
+
async _writeBytes(entries) {
|
|
50
|
+
const results = [];
|
|
51
|
+
for (const entry of entries) {
|
|
52
|
+
try {
|
|
53
|
+
const bytes = await toBytes(entry.payload);
|
|
54
|
+
this.storage.setItem(this.getKey(entry.uri), encodeBase64(bytes));
|
|
55
|
+
results.push({ success: true });
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
results.push({
|
|
59
|
+
success: false,
|
|
60
|
+
...storageFailure(err, "Write failed", entry.uri),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return results;
|
|
65
|
+
}
|
|
66
|
+
_readBytes(urls) {
|
|
67
|
+
return dispatchRead(urls, STORE_NAME, {
|
|
68
|
+
read: (p) => this._readOne(p.uri),
|
|
69
|
+
ls: (p) => this._ls(p),
|
|
70
|
+
count: (p) => this._count(p),
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
_readOne(uri) {
|
|
74
|
+
const serialized = this.storage.getItem(this.getKey(uri));
|
|
75
|
+
if (serialized === null)
|
|
76
|
+
return undefined;
|
|
77
|
+
return decodeBase64(serialized);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Walk localStorage once, returning `[uri, bytes]` for every entry
|
|
81
|
+
* whose URI is `prefix + <segment>` with no further `/`. Subtree-only
|
|
82
|
+
* paths are excluded by the slash check.
|
|
83
|
+
*/
|
|
84
|
+
_directLeaves(prefixUri) {
|
|
85
|
+
const prefixKey = this.getKey(prefixUri);
|
|
86
|
+
const out = [];
|
|
87
|
+
for (let i = 0; i < this.storage.length; i++) {
|
|
88
|
+
const key = this.storage.key(i);
|
|
89
|
+
if (!key || !key.startsWith(prefixKey))
|
|
90
|
+
continue;
|
|
91
|
+
const rest = key.substring(prefixKey.length);
|
|
92
|
+
if (rest === "" || rest.includes("/"))
|
|
93
|
+
continue;
|
|
94
|
+
const childUri = `${prefixUri}${rest}`;
|
|
95
|
+
out.push([childUri, this._readOne(childUri)]);
|
|
96
|
+
}
|
|
97
|
+
return out;
|
|
98
|
+
}
|
|
99
|
+
_ls(parsed) {
|
|
100
|
+
return applyReadParams(this._directLeaves(parsed.uri), parsed.params, STORE_NAME);
|
|
101
|
+
}
|
|
102
|
+
_count(parsed) {
|
|
103
|
+
if (parsed.params.pattern !== undefined) {
|
|
104
|
+
throw new Error(`${STORE_NAME}: pattern filter not supported`);
|
|
105
|
+
}
|
|
106
|
+
return this._directLeaves(parsed.uri).length;
|
|
107
|
+
}
|
|
108
|
+
_deleteBytes(uris) {
|
|
109
|
+
const results = [];
|
|
110
|
+
for (const uri of uris) {
|
|
111
|
+
try {
|
|
112
|
+
this.storage.removeItem(this.getKey(uri));
|
|
113
|
+
results.push({ success: true });
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
results.push({
|
|
117
|
+
success: false,
|
|
118
|
+
...storageFailure(err, "Delete failed", uri),
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return Promise.resolve(results);
|
|
123
|
+
}
|
|
124
|
+
// ── Status ───────────────────────────────────────────────────────
|
|
125
|
+
status() {
|
|
126
|
+
try {
|
|
127
|
+
const testKey = `${this.keyPrefix}__health_check__`;
|
|
128
|
+
this.storage.setItem(testKey, "ok");
|
|
129
|
+
this.storage.removeItem(testKey);
|
|
130
|
+
return Promise.resolve({
|
|
131
|
+
status: "healthy",
|
|
132
|
+
schema: [],
|
|
133
|
+
fns: ["read", "ls", "count"],
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return Promise.resolve({
|
|
138
|
+
status: "unhealthy",
|
|
139
|
+
schema: [],
|
|
140
|
+
fns: ["read", "ls", "count"],
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
capabilities() {
|
|
145
|
+
return { atomicBatch: false };
|
|
146
|
+
}
|
|
147
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory `EntityStore` backend.
|
|
3
|
+
*
|
|
4
|
+
* `MemoryStore` is the reference implementation — one flat
|
|
5
|
+
* `Map<uri, EntityRecord>` per ensured entity. Useful as a
|
|
6
|
+
* deterministic stand-in for tests and prototypes.
|
|
7
|
+
*
|
|
8
|
+
* Follows the shallow direct-leaves `fn=ls` / `fn=count` contract
|
|
9
|
+
* enforced across every backend in this package.
|
|
10
|
+
*/
|
|
11
|
+
export { MemoryStore } from "./store.js";
|
|
12
|
+
//# sourceMappingURL=mod.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/memory/mod.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory `EntityStore` backend.
|
|
3
|
+
*
|
|
4
|
+
* `MemoryStore` is the reference implementation — one flat
|
|
5
|
+
* `Map<uri, EntityRecord>` per ensured entity. Useful as a
|
|
6
|
+
* deterministic stand-in for tests and prototypes.
|
|
7
|
+
*
|
|
8
|
+
* Follows the shallow direct-leaves `fn=ls` / `fn=count` contract
|
|
9
|
+
* enforced across every backend in this package.
|
|
10
|
+
*/
|
|
11
|
+
export { MemoryStore } from "./store.js";
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MemoryStore — in-memory reference implementation of `EntityStore`.
|
|
3
|
+
*
|
|
4
|
+
* One flat `Map<uri, EntityRecord>` per provisioned entity, keyed by
|
|
5
|
+
* the entity's name. `BYTES_ENTITY` is just another entity here — its
|
|
6
|
+
* records sit in the same map as any custom entity.
|
|
7
|
+
*
|
|
8
|
+
* ## Lifecycle
|
|
9
|
+
*
|
|
10
|
+
* `entitySupport(schema)` is pure: it walks the schema's fields,
|
|
11
|
+
* picks the first recognised `TYPE_TAGS` entry per field as the
|
|
12
|
+
* canonical tag, and returns the operational handle (declared field
|
|
13
|
+
* set, bytes-field set, signature for collision detection, support
|
|
14
|
+
* report). `provisionEntity(meta)` allocates the bucket and stores
|
|
15
|
+
* the meta's signature so future collisions can be detected.
|
|
16
|
+
* `entityStatus(meta)` returns `"live"` only when the cached
|
|
17
|
+
* signature matches `meta` exactly — a same-name-different-shape
|
|
18
|
+
* schema reports `"unprovisioned"`, where "shape" includes the
|
|
19
|
+
* canonical type tag of each field (so changing `["string"]` to
|
|
20
|
+
* `["bigint"]` on an existing field name is a collision, mirroring
|
|
21
|
+
* what SQL backends catch via column-type introspection).
|
|
22
|
+
*
|
|
23
|
+
* Writes/reads/deletes consume the meta directly: there is no
|
|
24
|
+
* per-call cache lookup gate. If `meta`'s bucket does not exist on
|
|
25
|
+
* this store, `write` and `delete` surface the medium's natural
|
|
26
|
+
* "not provisioned" storage failure per entry; `read` returns misses.
|
|
27
|
+
*
|
|
28
|
+
* ## Validation
|
|
29
|
+
*
|
|
30
|
+
* A record under `meta` may only contain keys declared in
|
|
31
|
+
* `meta.declared`. Extra keys produce a per-entry
|
|
32
|
+
* `StoreWriteResult` failure. The store does not coerce.
|
|
33
|
+
*
|
|
34
|
+
* `payload: ReadableStream` (and any other field whose type tag is
|
|
35
|
+
* `"bytes"`) is collected to `Uint8Array` via `toBytes` before the
|
|
36
|
+
* record lands in the bucket. That coercion runs for every entity
|
|
37
|
+
* that declares a bytes field; nothing about it is bytes-entity-
|
|
38
|
+
* specific.
|
|
39
|
+
*/
|
|
40
|
+
import type { DeleteResult, Output, StatusResult } from "../deps/jsr.io/@bandeira-tech/b3nd-core/0.22.0/src/types/types.js";
|
|
41
|
+
import type { StoreCapabilities, StoreWriteResult } from "../types.js";
|
|
42
|
+
import type { EntityStore } from "../entity-store.js";
|
|
43
|
+
import { type EntityMeta, type EntityRecord, type EntitySchema } from "../entity.js";
|
|
44
|
+
/**
|
|
45
|
+
* MemoryStore-specific entity handle.
|
|
46
|
+
*
|
|
47
|
+
* `declared` and `bytesFields` drive the per-write extras check and
|
|
48
|
+
* bytes-field normalisation. `signature` is the canonical string for
|
|
49
|
+
* collision detection in `entityStatus` / `provisionEntity`.
|
|
50
|
+
*/
|
|
51
|
+
export interface MemoryEntityMeta extends EntityMeta {
|
|
52
|
+
readonly declared: ReadonlySet<string>;
|
|
53
|
+
readonly bytesFields: ReadonlySet<string>;
|
|
54
|
+
readonly signature: string;
|
|
55
|
+
}
|
|
56
|
+
export declare class MemoryStore implements EntityStore<MemoryEntityMeta> {
|
|
57
|
+
private readonly buckets;
|
|
58
|
+
entitySupport(schema: EntitySchema): MemoryEntityMeta;
|
|
59
|
+
entityStatus(meta: MemoryEntityMeta): Promise<"live" | "unprovisioned">;
|
|
60
|
+
provisionEntity(meta: MemoryEntityMeta): Promise<void>;
|
|
61
|
+
write(meta: MemoryEntityMeta, entries: {
|
|
62
|
+
uri: string;
|
|
63
|
+
record: EntityRecord;
|
|
64
|
+
}[]): Promise<StoreWriteResult[]>;
|
|
65
|
+
read<T = EntityRecord | undefined>(meta: MemoryEntityMeta, urls: string[]): Promise<Output<T>[]>;
|
|
66
|
+
private _walk;
|
|
67
|
+
private _list;
|
|
68
|
+
private _count;
|
|
69
|
+
delete(meta: MemoryEntityMeta, uris: string[]): Promise<DeleteResult[]>;
|
|
70
|
+
status(): Promise<StatusResult>;
|
|
71
|
+
capabilities(): StoreCapabilities;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/memory/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,MAAM,EACN,YAAY,EACb,MAAM,mEAAmE,CAAC;AAK3E,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EACL,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,YAAY,EAGlB,MAAM,cAAc,CAAC;AAKtB;;;;;;GAMG;AACH,MAAM,WAAW,gBAAiB,SAAQ,UAAU;IAClD,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;AAOD,qBAAa,WAAY,YAAW,WAAW,CAAC,gBAAgB,CAAC;IAC/D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IAIrD,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,gBAAgB;IAwC/C,YAAY,CAChB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,MAAM,GAAG,eAAe,CAAC;IAO9B,eAAe,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBtD,KAAK,CACT,IAAI,EAAE,gBAAgB,EACtB,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,YAAY,CAAA;KAAE,EAAE,GAC/C,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAsDxB,IAAI,CAAC,CAAC,GAAG,YAAY,GAAG,SAAS,EACrC,IAAI,EAAE,gBAAgB,EACtB,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IAiBvB,OAAO,CAAC,KAAK;IAgBb,OAAO,CAAC,KAAK;IA8Bb,OAAO,CAAC,MAAM;IAYd,MAAM,CACJ,IAAI,EAAE,gBAAgB,EACtB,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,YAAY,EAAE,CAAC;IAgC1B,MAAM,IAAI,OAAO,CAAC,YAAY,CAAC;IAQ/B,YAAY,IAAI,iBAAiB;CAGlC"}
|