@fireproof/core 0.19.9-dev-frag → 0.19.11-dev-dryrun2

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.
Files changed (48) hide show
  1. package/README.md +27 -0
  2. package/{chunk-YS4GL6OK.js → chunk-OFGPKRCM.js} +30 -6
  3. package/chunk-OFGPKRCM.js.map +1 -0
  4. package/{chunk-JO5AVWG7.js → chunk-WS3YRPIA.js} +14 -6
  5. package/chunk-WS3YRPIA.js.map +1 -0
  6. package/deno.json +20 -0
  7. package/{gateway-YSNUK2L3.js → gateway-5FCWPX5W.js} +4 -5
  8. package/{gateway-YSNUK2L3.js.map → gateway-5FCWPX5W.js.map} +1 -1
  9. package/{gateway-IZRHJWPE.js → gateway-H7UD6TNB.js} +3 -4
  10. package/gateway-H7UD6TNB.js.map +1 -0
  11. package/index.cjs +468 -338
  12. package/index.cjs.map +1 -1
  13. package/index.d.cts +80 -52
  14. package/index.d.ts +80 -52
  15. package/index.global.js +21378 -15079
  16. package/index.global.js.map +1 -1
  17. package/index.js +389 -293
  18. package/index.js.map +1 -1
  19. package/{key-bag-file-NMEBFSPM.js → key-bag-file-WADZBHYG.js} +3 -3
  20. package/{key-bag-indexdb-X5V6GNBZ.js → key-bag-indexdb-PGVAI3FJ.js} +3 -3
  21. package/key-bag-indexdb-PGVAI3FJ.js.map +1 -0
  22. package/{mem-filesystem-B6C6QOIP.js → mem-filesystem-YPPJV7Q2.js} +3 -3
  23. package/metafile-cjs.json +1 -1
  24. package/metafile-esm.json +1 -1
  25. package/metafile-iife.json +1 -1
  26. package/{node-filesystem-5JLBSHKQ.js → node-filesystem-INX4ZTHE.js} +8 -4
  27. package/node-filesystem-INX4ZTHE.js.map +1 -0
  28. package/package.json +8 -5
  29. package/tests/blockstore/keyed-crypto.test.ts +34 -4
  30. package/tests/blockstore/store.test.ts +18 -13
  31. package/tests/fireproof/all-gateway.test.ts +394 -0
  32. package/tests/fireproof/cars/bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i.car +0 -0
  33. package/tests/fireproof/cars/bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i.ts +316 -0
  34. package/tests/fireproof/fireproof.test.ts +18 -18
  35. package/tests/fireproof/hello.test.ts +33 -19
  36. package/tests/fireproof/utils.test.ts +19 -0
  37. package/tests/helpers.ts +7 -4
  38. package/tests/www/todo-local.html +1 -1
  39. package/tests/www/todo.html +12 -15
  40. package/{utils-IZPK4QS7.js → utils-QO2HIWGI.js} +3 -3
  41. package/chunk-JO5AVWG7.js.map +0 -1
  42. package/chunk-YS4GL6OK.js.map +0 -1
  43. package/gateway-IZRHJWPE.js.map +0 -1
  44. package/key-bag-indexdb-X5V6GNBZ.js.map +0 -1
  45. package/node-filesystem-5JLBSHKQ.js.map +0 -1
  46. /package/{key-bag-file-NMEBFSPM.js.map → key-bag-file-WADZBHYG.js.map} +0 -0
  47. /package/{mem-filesystem-B6C6QOIP.js.map → mem-filesystem-YPPJV7Q2.js.map} +0 -0
  48. /package/{utils-IZPK4QS7.js.map → utils-QO2HIWGI.js.map} +0 -0
@@ -1,12 +1,13 @@
1
1
  import {
2
2
  toArrayBuffer
3
- } from "./chunk-JO5AVWG7.js";
4
- import "./chunk-YS4GL6OK.js";
3
+ } from "./chunk-WS3YRPIA.js";
4
+ import "./chunk-OFGPKRCM.js";
5
5
 
6
6
  // src/runtime/gateways/file/node-filesystem.ts
7
+ import { runtimeFn } from "@adviser/cement";
7
8
  var NodeFileSystem = class {
8
9
  async start() {
9
- this.fs = await import("fs/promises");
10
+ this.fs = await import("node:fs/promises");
10
11
  return this;
11
12
  }
12
13
  async mkdir(path, options) {
@@ -32,10 +33,13 @@ var NodeFileSystem = class {
32
33
  return this.fs?.unlink(path);
33
34
  }
34
35
  async writefile(path, data) {
36
+ if (runtimeFn().isDeno) {
37
+ return this.fs?.writeFile(path, data);
38
+ }
35
39
  return this.fs?.writeFile(path, Buffer.from(data));
36
40
  }
37
41
  };
38
42
  export {
39
43
  NodeFileSystem
40
44
  };
41
- //# sourceMappingURL=node-filesystem-5JLBSHKQ.js.map
45
+ //# sourceMappingURL=node-filesystem-INX4ZTHE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/runtime/gateways/file/node-filesystem.ts"],"sourcesContent":["import type { PathLike, MakeDirectoryOptions, Stats, ObjectEncodingOptions } from \"node:fs\";\nimport type { mkdir, readdir, rm, copyFile, readFile, stat, unlink, writeFile } from \"node:fs/promises\";\nimport { toArrayBuffer } from \"./utils.js\";\nimport { SysFileSystem } from \"../../../types.js\";\nimport { runtimeFn } from \"@adviser/cement\";\n\nexport class NodeFileSystem implements SysFileSystem {\n fs?: {\n mkdir: typeof mkdir;\n readdir: typeof readdir;\n rm: typeof rm;\n copyFile: typeof copyFile;\n readFile: typeof readFile;\n stat: typeof stat;\n unlink: typeof unlink;\n writeFile: typeof writeFile;\n };\n\n async start(): Promise<SysFileSystem> {\n this.fs = await import(\"node:fs/promises\");\n return this;\n }\n async mkdir(path: PathLike, options?: { recursive: boolean }): Promise<string | undefined> {\n return this.fs?.mkdir(path, options);\n }\n async readdir(path: PathLike, options?: ObjectEncodingOptions): Promise<string[]> {\n return this.fs?.readdir(path, options) as Promise<string[]>;\n }\n async rm(path: PathLike, options?: MakeDirectoryOptions & { recursive: boolean }): Promise<void> {\n return this.fs?.rm(path, options);\n }\n async copyFile(source: PathLike, destination: PathLike): Promise<void> {\n return this.fs?.copyFile(source, destination);\n }\n async readfile(path: PathLike, options?: { encoding: BufferEncoding; flag?: string }): Promise<Uint8Array> {\n const ret = (await this.fs?.readFile(path, options)) as Buffer;\n return toArrayBuffer(ret);\n }\n stat(path: PathLike): Promise<Stats> {\n return this.fs?.stat(path) as Promise<Stats>;\n }\n async unlink(path: PathLike): Promise<void> {\n return this.fs?.unlink(path);\n }\n async writefile(path: PathLike, data: Uint8Array | string): Promise<void> {\n if (runtimeFn().isDeno) {\n return this.fs?.writeFile(path, data);\n }\n return this.fs?.writeFile(path, Buffer.from(data));\n }\n}\n\n// import { type NodeMap, join } from \"../../sys-container.js\";\n// import type { ObjectEncodingOptions, PathLike } from \"fs\";\n// import * as fs from \"fs/promises\";\n// import * as path from \"path\";\n// import * as os from \"os\";\n// import * as url from \"url\";\n// import { toArrayBuffer } from \"./utils.js\";\n\n// export async function createNodeSysContainer(): Promise<NodeMap> {\n// // const nodePath = \"node:path\";\n// // const nodeOS = \"node:os\";\n// // const nodeURL = \"node:url\";\n// // const nodeFS = \"node:fs\";\n// // const fs = (await import(\"node:fs\")).promises;\n// // const assert = \"assert\";\n// // const path = await import(\"node:path\");\n// return {\n// state: \"node\",\n// ...path,\n// // ...(await import(\"node:os\")),\n// // ...(await import(\"node:url\")),\n// ...os,\n// ...url,\n// ...fs,\n// join,\n// stat: fs.stat as NodeMap[\"stat\"],\n// readdir: fs.readdir as NodeMap[\"readdir\"],\n// readfile: async (path: PathLike, options?: ObjectEncodingOptions): Promise<Uint8Array> => {\n// const rs = await fs.readFile(path, options);\n// return toArrayBuffer(rs);\n// },\n// writefile: fs.writeFile as NodeMap[\"writefile\"],\n// };\n// }\n"],"mappings":";;;;;;AAIA,SAAS,iBAAiB;AAEnB,IAAM,iBAAN,MAA8C;AAAA,EAYnD,MAAM,QAAgC;AACpC,SAAK,KAAK,MAAM,OAAO,kBAAkB;AACzC,WAAO;AAAA,EACT;AAAA,EACA,MAAM,MAAM,MAAgB,SAA+D;AACzF,WAAO,KAAK,IAAI,MAAM,MAAM,OAAO;AAAA,EACrC;AAAA,EACA,MAAM,QAAQ,MAAgB,SAAoD;AAChF,WAAO,KAAK,IAAI,QAAQ,MAAM,OAAO;AAAA,EACvC;AAAA,EACA,MAAM,GAAG,MAAgB,SAAwE;AAC/F,WAAO,KAAK,IAAI,GAAG,MAAM,OAAO;AAAA,EAClC;AAAA,EACA,MAAM,SAAS,QAAkB,aAAsC;AACrE,WAAO,KAAK,IAAI,SAAS,QAAQ,WAAW;AAAA,EAC9C;AAAA,EACA,MAAM,SAAS,MAAgB,SAA4E;AACzG,UAAM,MAAO,MAAM,KAAK,IAAI,SAAS,MAAM,OAAO;AAClD,WAAO,cAAc,GAAG;AAAA,EAC1B;AAAA,EACA,KAAK,MAAgC;AACnC,WAAO,KAAK,IAAI,KAAK,IAAI;AAAA,EAC3B;AAAA,EACA,MAAM,OAAO,MAA+B;AAC1C,WAAO,KAAK,IAAI,OAAO,IAAI;AAAA,EAC7B;AAAA,EACA,MAAM,UAAU,MAAgB,MAA0C;AACxE,QAAI,UAAU,EAAE,QAAQ;AACtB,aAAO,KAAK,IAAI,UAAU,MAAM,IAAI;AAAA,IACtC;AACA,WAAO,KAAK,IAAI,UAAU,MAAM,OAAO,KAAK,IAAI,CAAC;AAAA,EACnD;AACF;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fireproof/core",
3
- "version": "0.19.9-dev-frag",
3
+ "version": "0.19.11-dev-dryrun2",
4
4
  "description": "Live database for the web.",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -46,16 +46,19 @@
46
46
  "react": ">=18.0.0"
47
47
  },
48
48
  "dependencies": {
49
- "@adviser/cement": "^0.2.22",
49
+ "@adviser/cement": "^0.2.31",
50
+ "multiformats": "^13.3.0",
50
51
  "@ipld/unixfs": "^3.0.0",
51
52
  "@ipld/car": "^5.3.2",
53
+ "@ipld/dag-json": "^10.2.2",
54
+ "@ipld/dag-cbor": "^9.2.1",
52
55
  "@web3-storage/pail": "^0.6.0",
53
- "cborg": "^4.2.3",
56
+ "cborg": "^4.2.4",
54
57
  "charwise": "^3.0.1",
55
58
  "prolly-trees": "^1.0.4",
56
59
  "idb": "^8.0.0",
57
- "ipfs-unixfs-exporter": "^13.5.0",
58
- "memfs": "^4.11.0",
60
+ "ipfs-unixfs-exporter": "^13.6.1",
61
+ "memfs": "^4.12.0",
59
62
  "p-limit": "^6.1.0",
60
63
  "react": "^18.3.1"
61
64
  },
@@ -3,12 +3,14 @@ import { BuildURI, Logger, MockLogger, runtimeFn, toCryptoRuntime, URI } from "@
3
3
  import { base58btc } from "multiformats/bases/base58";
4
4
  import { sha256 as hasher } from "multiformats/hashes/sha2";
5
5
  import * as dagCodec from "@ipld/dag-cbor";
6
- import { mockSuperThis } from "../helpers";
6
+ import { MockSuperThis, mockSuperThis } from "../helpers";
7
7
 
8
8
  describe("KeyBag", () => {
9
9
  let url: URI;
10
- const sthis = mockSuperThis();
11
- beforeAll(async () => {
10
+ let sthis: MockSuperThis;
11
+
12
+ beforeEach(async () => {
13
+ sthis = mockSuperThis();
12
14
  await sthis.start();
13
15
  if (runtimeFn().isBrowser) {
14
16
  url = URI.from("indexdb://fp-keybag");
@@ -34,6 +36,33 @@ describe("KeyBag", () => {
34
36
  expect(kb.rt.url.toString()).toBe(url.toString());
35
37
  sthis.env.set("FP_KEYBAG_URL", old);
36
38
  });
39
+
40
+ it("extract keyMaterial", async () => {
41
+ const dkb = await rt.kb.getKeyBag(sthis);
42
+ const old = sthis.env.get("FP_KEYBAG_URL");
43
+ sthis.env.set("FP_KEYBAG_URL", BuildURI.from(dkb.rt.url).setParam("extractKey", "_deprecated_internal_api").toString());
44
+ const kb = await rt.kb.getKeyBag(sthis);
45
+ const key = kb.rt.crypto.randomBytes(kb.rt.keyLength);
46
+ const keyStr = base58btc.encode(key);
47
+ const res = await kb.setNamedKey("extract.test", keyStr);
48
+ expect(res.isOk()).toBeTruthy();
49
+ const gkb = await kb.getNamedExtractableKey("extract.test", true);
50
+ expect(gkb.isOk()).toBeTruthy();
51
+ expect(await gkb.Ok().extract()).toEqual({
52
+ key,
53
+ keyStr,
54
+ });
55
+ sthis.env.set("FP_KEYBAG_URL", old);
56
+ await sthis.logger.Flush();
57
+ expect(sthis.logCollector.Logs()).toEqual([
58
+ {
59
+ level: "warn",
60
+ module: "KeyBag",
61
+ msg: "extractKey is enabled via _deprecated_internal_api --- handle keys safely!!!",
62
+ },
63
+ ]);
64
+ });
65
+
37
66
  it("simple add", async () => {
38
67
  const kb = await rt.kb.getKeyBag(sthis, {
39
68
  url: url.toString(),
@@ -105,7 +134,8 @@ describe("KeyedCryptoStore", () => {
105
134
  baseUrl = URI.from("indexdb://fp-keyed-crypto-store");
106
135
  } else {
107
136
  kbUrl = URI.merge(`file://./dist/tests/key.bag`, sthis.env.get("FP_KEYBAG_URL"));
108
- baseUrl = URI.merge("file://./dist/tests/keyed-crypto-store", sthis.env.get("FP_STORAGE_URL"));
137
+ // baseUrl = URI.merge("file://./dist/tests/keyed-crypto-store", sthis.env.get("FP_STORAGE_URL"));
138
+ baseUrl = URI.from(sthis.env.get("FP_STORAGE_URL"));
109
139
  }
110
140
  kb = await rt.kb.getKeyBag(sthis, {
111
141
  url: kbUrl,
@@ -88,9 +88,8 @@ describe("DataStore with a saved car", function () {
88
88
 
89
89
  it("should remove a car", async function () {
90
90
  await store.remove(car.cid);
91
- const error = (await store.load(car.cid).catch((e: Error) => e)) as NotFoundError;
92
- expect(error.code).toMatch("ENOENT");
93
- // matches(error.message, "ENOENT");
91
+ const { e: error } = (await store.load(car.cid).catch((e: Error) => ({ e }))) as { e: NotFoundError };
92
+ expect(error).toBeTruthy();
94
93
  });
95
94
  });
96
95
 
@@ -124,10 +123,11 @@ describe("MetaStore", function () {
124
123
  };
125
124
  await store.save(h);
126
125
  const file = await raw.get(store.url(), "main");
127
- const header = JSON.parse(decoder.decode(file));
128
- expect(header).toBeTruthy();
129
- expect(header.cars).toBeTruthy();
130
- expect(header.cars[0]["/"]).toEqual(cid.toString());
126
+ const [blockMeta] = await store.handleByteHeads(file);
127
+ const decodedHeader = blockMeta.dbMeta;
128
+ expect(decodedHeader).toBeTruthy();
129
+ expect(decodedHeader.cars).toBeTruthy();
130
+ expect(decodedHeader.cars[0].toString()).toEqual(cid.toString());
131
131
  });
132
132
  });
133
133
 
@@ -152,12 +152,17 @@ describe("MetaStore with a saved header", function () {
152
152
  });
153
153
 
154
154
  it("should have a header", async function () {
155
- const data = decoder.decode(await raw.get(store.url(), "main"));
156
- expect(data).toMatch(/car/);
157
- const header = JSON.parse(data);
158
- expect(header).toBeTruthy();
159
- expect(header.cars).toBeTruthy();
160
- expect(header.cars[0]["/"]).toEqual(cid.toString());
155
+ const bytes = await raw.get(store.url(), "main");
156
+ const data = decoder.decode(bytes);
157
+ expect(data).toMatch(/parents/);
158
+ const header = JSON.parse(data)[0];
159
+ expect(header).toBeDefined();
160
+ expect(header.parents).toBeDefined();
161
+ const [blockMeta] = await store.handleByteHeads(bytes);
162
+ const decodedHeader = blockMeta.dbMeta;
163
+ expect(decodedHeader).toBeDefined();
164
+ expect(decodedHeader.cars).toBeDefined();
165
+ expect(decodedHeader.cars[0].toString()).toEqual(cid.toString());
161
166
  });
162
167
 
163
168
  it("should load a header", async function () {
@@ -0,0 +1,394 @@
1
+ import { Database, bs } from "@fireproof/core";
2
+ import { URI } from "@adviser/cement";
3
+
4
+ import { fileContent } from "./cars/bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i.js";
5
+
6
+ function customExpect(value: unknown, matcher: (val: unknown) => void, message: string): void {
7
+ try {
8
+ matcher(value);
9
+ } catch (error) {
10
+ void error;
11
+ // console.error(error);
12
+ throw new Error(message);
13
+ }
14
+ }
15
+
16
+ interface ExtendedGateway extends bs.Gateway {
17
+ logger: { _attributes: { module: string; url?: string } };
18
+ headerSize: number;
19
+ fidLength: number;
20
+ }
21
+
22
+ interface ExtendedStore {
23
+ gateway: ExtendedGateway;
24
+ _url: URI;
25
+ name: string;
26
+ }
27
+
28
+ describe("noop Gateway", function () {
29
+ let db: Database;
30
+ let carStore: ExtendedStore;
31
+ let metaStore: ExtendedStore;
32
+ let fileStore: ExtendedStore;
33
+ let walStore: ExtendedStore;
34
+ let carGateway: ExtendedGateway;
35
+ let metaGateway: ExtendedGateway;
36
+ let fileGateway: ExtendedGateway;
37
+ let walGateway: ExtendedGateway;
38
+
39
+ afterEach(async function () {
40
+ await db.close();
41
+ await db.destroy();
42
+ });
43
+ beforeEach(async function () {
44
+ db = new Database("test-gateway-" + Math.random().toString(36).substring(7));
45
+
46
+ // Extract stores from the loader
47
+ carStore = (await db.blockstore.loader?.carStore()) as unknown as ExtendedStore;
48
+ metaStore = (await db.blockstore.loader?.metaStore()) as unknown as ExtendedStore;
49
+ fileStore = (await db.blockstore.loader?.fileStore()) as unknown as ExtendedStore;
50
+ walStore = (await db.blockstore.loader?.WALStore()) as unknown as ExtendedStore;
51
+
52
+ // Extract and log gateways
53
+ carGateway = carStore?.gateway;
54
+ metaGateway = metaStore?.gateway;
55
+ fileGateway = fileStore?.gateway;
56
+ walGateway = walStore?.gateway;
57
+ });
58
+
59
+ it("should have valid stores and gateways", async function () {
60
+ // Add assertions
61
+ expect(carStore).toBeTruthy();
62
+ expect(metaStore).toBeTruthy();
63
+ expect(fileStore).toBeTruthy();
64
+ expect(walStore).toBeTruthy();
65
+
66
+ expect(carGateway).toBeTruthy();
67
+ expect(metaGateway).toBeTruthy();
68
+ expect(fileGateway).toBeTruthy();
69
+ expect(walGateway).toBeTruthy();
70
+ });
71
+
72
+ it("should have correct store names", async function () {
73
+ // Check that all stores have the correct name
74
+ expect(carStore?.name).toContain("test-gateway");
75
+ expect(metaStore?.name).toContain("test-gateway");
76
+ expect(fileStore?.name).toContain("test-gateway");
77
+ expect(walStore?.name).toContain("test-gateway");
78
+ });
79
+
80
+ it("should have correct store types in URLs", async function () {
81
+ // Check that all stores have the correct store type in their URL
82
+ expect(carStore?._url.toString()).toContain("store=data");
83
+ expect(metaStore?._url.toString()).toContain("store=meta");
84
+ expect(fileStore?._url.toString()).toContain("store=data");
85
+ expect(walStore?._url.toString()).toContain("store=wal");
86
+ });
87
+
88
+ it("should have version specified in URLs", async function () {
89
+ // Verify that all stores have a version specified
90
+ expect(carStore?._url.toString()).toContain("version=");
91
+ expect(metaStore?._url.toString()).toContain("version=");
92
+ expect(fileStore?._url.toString()).toContain("version=");
93
+ expect(walStore?._url.toString()).toContain("version=");
94
+ });
95
+
96
+ it("should have correct gateway types", async function () {
97
+ // Check that all gateways are instances of the expected gateway class
98
+ expect(typeof carGateway).toBe("object");
99
+ expect(typeof metaGateway).toBe("object");
100
+ expect(typeof fileGateway).toBe("object");
101
+ expect(typeof walGateway).toBe("object");
102
+ });
103
+
104
+ it("should build CAR Gateway URL", async function () {
105
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
106
+ const carUrl = await carGateway?.buildUrl(carStore?._url, testKey);
107
+ expect(carUrl?.Ok()).toBeTruthy();
108
+ });
109
+
110
+ it("should start CAR Gateway", async function () {
111
+ await carGateway?.start(carStore?._url);
112
+ });
113
+
114
+ it("should put data in CAR Gateway", async function () {
115
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
116
+ const testData = fileContent;
117
+ const carUrl = await carGateway?.buildUrl(carStore?._url, testKey);
118
+ await carGateway?.start(carStore?._url);
119
+ const carPutResult = await carGateway?.put(carUrl?.Ok(), testData);
120
+ expect(carPutResult?.Ok()).toBeFalsy();
121
+ });
122
+
123
+ it("should get data from CAR Gateway", async function () {
124
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
125
+ const testData = fileContent;
126
+ const carUrl = await carGateway?.buildUrl(carStore?._url, testKey);
127
+ await carGateway?.start(carStore?._url);
128
+ await carGateway?.put(carUrl?.Ok(), testData);
129
+ const carGetResult = await carGateway?.get(carUrl?.Ok());
130
+ customExpect(carGetResult?.Ok(), (v) => expect(v).toEqual(testData), "carGetResult should match testData");
131
+ });
132
+
133
+ it("should delete data from CAR Gateway", async function () {
134
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
135
+ const testData = fileContent;
136
+ const carUrl = await carGateway?.buildUrl(carStore?._url, testKey);
137
+ await carGateway?.start(carStore?._url);
138
+ await carGateway?.put(carUrl?.Ok(), testData);
139
+ const carDeleteResult = await carGateway?.delete(carUrl?.Ok());
140
+ expect(carDeleteResult?.Ok()).toBeFalsy();
141
+ });
142
+
143
+ it("should close CAR Gateway", async function () {
144
+ await carGateway?.close(carStore?._url);
145
+ });
146
+ it("should build Meta Gateway URL", async function () {
147
+ const metaUrl = await metaGateway?.buildUrl(metaStore?._url, "main");
148
+ expect(metaUrl?.Ok()).toBeTruthy();
149
+ });
150
+
151
+ it("should start Meta Gateway", async function () {
152
+ await metaGateway?.start(metaStore?._url);
153
+ });
154
+
155
+ it("should close Meta Gateway", async function () {
156
+ await metaGateway?.start(metaStore?._url);
157
+ await metaGateway?.close(metaStore?._url);
158
+ });
159
+
160
+ it("should build File Gateway URL", async function () {
161
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
162
+ const fileUrl = await fileGateway?.buildUrl(fileStore?._url, testKey);
163
+ expect(fileUrl?.Ok()).toBeTruthy();
164
+ });
165
+
166
+ it("should start File Gateway", async function () {
167
+ await fileGateway?.start(fileStore?._url);
168
+ });
169
+
170
+ it("should put data to File Gateway", async function () {
171
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
172
+ const testData = fileContent;
173
+ const fileUrl = await fileGateway?.buildUrl(fileStore?._url, testKey);
174
+ await fileGateway?.start(fileStore?._url);
175
+ const filePutResult = await fileGateway?.put(fileUrl?.Ok(), testData);
176
+ expect(filePutResult?.Ok()).toBeFalsy();
177
+ });
178
+
179
+ it("should get data from File Gateway", async function () {
180
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
181
+ const testData = fileContent;
182
+ const fileUrl = await fileGateway?.buildUrl(fileStore?._url, testKey);
183
+ await fileGateway?.start(fileStore?._url);
184
+ await fileGateway?.put(fileUrl?.Ok(), testData);
185
+ const fileGetResult = await fileGateway?.get(fileUrl?.Ok());
186
+ customExpect(fileGetResult?.Ok(), (v) => expect(v).toEqual(testData), "fileGetResult should match testData");
187
+ });
188
+
189
+ it("should delete data from File Gateway", async function () {
190
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
191
+ const testData = fileContent;
192
+ const fileUrl = await fileGateway?.buildUrl(fileStore?._url, testKey);
193
+ await fileGateway?.start(fileStore?._url);
194
+ await fileGateway?.put(fileUrl?.Ok(), testData);
195
+ const fileDeleteResult = await fileGateway?.delete(fileUrl?.Ok());
196
+ expect(fileDeleteResult?.Ok()).toBeFalsy();
197
+ });
198
+
199
+ it("should close File Gateway", async function () {
200
+ await fileGateway?.close(fileStore?._url);
201
+ });
202
+ it("should build WAL Gateway URL", async function () {
203
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
204
+ const walUrl = await walGateway?.buildUrl(walStore?._url, testKey);
205
+ expect(walUrl?.Ok()).toBeTruthy();
206
+ });
207
+
208
+ it("should start WAL Gateway", async function () {
209
+ await walGateway?.start(walStore?._url);
210
+ });
211
+
212
+ it("should put data to WAL Gateway", async function () {
213
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
214
+ const walUrl = await walGateway?.buildUrl(walStore?._url, testKey);
215
+ await walGateway?.start(walStore?._url);
216
+ const walTestDataString = JSON.stringify({
217
+ operations: [],
218
+ noLoaderOps: [],
219
+ fileOperations: [],
220
+ });
221
+ const walEncoder = new TextEncoder();
222
+ const walTestData = walEncoder.encode(walTestDataString);
223
+ const walPutResult = await walGateway?.put(walUrl?.Ok(), walTestData);
224
+ expect(walPutResult?.Ok()).toBeFalsy();
225
+ });
226
+
227
+ it("should get data from WAL Gateway", async function () {
228
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
229
+ const walUrl = await walGateway?.buildUrl(walStore?._url, testKey);
230
+ await walGateway?.start(walStore?._url);
231
+ const walTestDataString = JSON.stringify({
232
+ operations: [],
233
+ noLoaderOps: [],
234
+ fileOperations: [],
235
+ });
236
+ const walEncoder = new TextEncoder();
237
+ const walTestData = walEncoder.encode(walTestDataString);
238
+ await walGateway?.put(walUrl?.Ok(), walTestData);
239
+ const walGetResult = await walGateway?.get(walUrl?.Ok());
240
+ const okResult = walGetResult?.Ok();
241
+ const decodedResult = new TextDecoder().decode(okResult);
242
+ expect(decodedResult).toEqual(walTestDataString);
243
+ });
244
+
245
+ it("should delete data from WAL Gateway", async function () {
246
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
247
+ const walUrl = await walGateway?.buildUrl(walStore?._url, testKey);
248
+ await walGateway?.start(walStore?._url);
249
+ const walTestDataString = JSON.stringify({
250
+ operations: [],
251
+ noLoaderOps: [],
252
+ fileOperations: [],
253
+ });
254
+ const walEncoder = new TextEncoder();
255
+ const walTestData = walEncoder.encode(walTestDataString);
256
+ await walGateway?.put(walUrl?.Ok(), walTestData);
257
+ const walDeleteResult = await walGateway?.delete(walUrl?.Ok());
258
+ expect(walDeleteResult?.Ok()).toBeFalsy();
259
+ });
260
+
261
+ it("should close WAL Gateway", async function () {
262
+ await walGateway?.start(walStore?._url);
263
+ await walGateway?.close(walStore?._url);
264
+ });
265
+
266
+ it("should have correct CAR Gateway properties", async function () {
267
+ // CAR Gateway assertions
268
+ expect(carGateway?.fidLength).toBe(4);
269
+ expect(carGateway?.headerSize).toBe(36);
270
+ expect(carGateway?.logger._attributes).toHaveProperty("module");
271
+ expect(carGateway?.logger._attributes).toHaveProperty("url");
272
+ });
273
+
274
+ it("should have correct Meta Gateway properties", async function () {
275
+ // Meta Gateway assertions
276
+ expect(metaGateway?.fidLength).toBe(4);
277
+ expect(metaGateway?.headerSize).toBe(36);
278
+ expect(metaGateway?.logger._attributes).toHaveProperty("module");
279
+ expect(metaGateway?.logger._attributes).not.toHaveProperty("url");
280
+ });
281
+
282
+ it("should have correct File Gateway properties", async function () {
283
+ // File Gateway assertions
284
+ expect(fileGateway?.fidLength).toBe(4);
285
+ expect(fileGateway?.headerSize).toBe(36);
286
+ expect(fileGateway?.logger._attributes).toHaveProperty("module");
287
+ expect(fileGateway?.logger._attributes).toHaveProperty("url");
288
+ });
289
+
290
+ it("should have correct WAL Gateway properties", async function () {
291
+ // WAL Gateway assertions
292
+ expect(walGateway?.fidLength).toBe(4);
293
+ expect(walGateway?.headerSize).toBe(36);
294
+ expect(walGateway?.logger._attributes).toHaveProperty("module");
295
+ expect(walGateway?.logger._attributes).not.toHaveProperty("url");
296
+ });
297
+ });
298
+
299
+ describe("noop Gateway subscribe", function () {
300
+ let db: Database;
301
+
302
+ let metaStore: ExtendedStore;
303
+
304
+ let metaGateway: ExtendedGateway;
305
+
306
+ afterEach(async function () {
307
+ await db.close();
308
+ await db.destroy();
309
+ });
310
+ beforeEach(async function () {
311
+ db = new Database("test-gateway-" + Math.random().toString(36).substring(7));
312
+
313
+ // Extract stores from the loader
314
+ metaStore = (await db.blockstore.loader?.metaStore()) as unknown as ExtendedStore;
315
+
316
+ metaGateway = metaStore?.gateway;
317
+ });
318
+ it("should subscribe to meta Gateway", async function () {
319
+ const metaUrl = await metaGateway?.buildUrl(metaStore?._url, "main");
320
+ await metaGateway?.start(metaStore?._url);
321
+
322
+ let resolve: () => void;
323
+ let didCall = false;
324
+ const p = new Promise<void>((r) => {
325
+ resolve = r;
326
+ });
327
+ const metaSubscribeResult = await metaGateway?.subscribe?.(metaUrl?.Ok(), async (data: Uint8Array) => {
328
+ const decodedData = new TextDecoder().decode(data);
329
+ expect(decodedData).toContain("[]");
330
+ didCall = true;
331
+ resolve();
332
+ });
333
+ if (!metaSubscribeResult?.isErr()) {
334
+ expect(metaSubscribeResult?.Ok()).toBeTruthy();
335
+ const ok = await db.put({ _id: "key1", hello: "world1" });
336
+ expect(ok).toBeTruthy();
337
+ expect(ok.id).toBe("key1");
338
+ await p;
339
+ expect(didCall).toBeTruthy();
340
+ }
341
+ });
342
+ });
343
+
344
+ describe("Gateway", function () {
345
+ let db: Database;
346
+ // let carStore: ExtendedStore;
347
+ let metaStore: ExtendedStore;
348
+ // let fileStore: ExtendedStore;
349
+ // let walStore: ExtendedStore;
350
+ // let carGateway: ExtendedGateway;
351
+ let metaGateway: ExtendedGateway;
352
+ // let fileGateway: ExtendedGateway;
353
+ // let walGateway: ExtendedGateway;
354
+
355
+ afterEach(async function () {
356
+ await db.close();
357
+ await db.destroy();
358
+ });
359
+ beforeEach(async function () {
360
+ db = new Database("test-gateway-" + Math.random().toString(36).substring(7));
361
+ const ok = await db.put({ _id: "test", foo: "bar" });
362
+ expect(ok).toBeTruthy();
363
+ expect(ok.id).toBe("test");
364
+
365
+ // Extract stores from the loader
366
+ // carStore = (await db.blockstore.loader?.carStore()) as unknown as ExtendedStore;
367
+ metaStore = (await db.blockstore.loader?.metaStore()) as unknown as ExtendedStore;
368
+ // fileStore = (await db.blockstore.loader?.fileStore()) as unknown as ExtendedStore;
369
+ // walStore = (await db.blockstore.loader?.WALStore()) as unknown as ExtendedStore;
370
+
371
+ // Extract and log gateways
372
+ // carGateway = carStore?.gateway;
373
+ metaGateway = metaStore?.gateway;
374
+ // fileGateway = fileStore?.gateway;
375
+ // walGateway = walStore?.gateway;
376
+ });
377
+
378
+ it("should get data from Meta Gateway", async function () {
379
+ const metaUrl = await metaGateway?.buildUrl(metaStore?._url, "main");
380
+ await metaGateway?.start(metaStore?._url);
381
+ const metaGetResult = await metaGateway?.get(metaUrl?.Ok());
382
+ const metaGetResultOk = metaGetResult?.Ok();
383
+ const decodedMetaGetResultOk = new TextDecoder().decode(metaGetResultOk);
384
+ expect(decodedMetaGetResultOk).toContain("parents");
385
+ });
386
+
387
+ it("should delete data from Meta Gateway", async function () {
388
+ const metaUrl = await metaGateway?.buildUrl(metaStore?._url, "main");
389
+ await metaGateway?.start(metaStore?._url);
390
+ // should we be testing .destroy() instead?
391
+ const metaDeleteResult = await metaGateway?.delete(metaUrl?.Ok());
392
+ expect(metaDeleteResult?.Ok()).toBeFalsy();
393
+ });
394
+ });