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

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. package/README.md +27 -0
  2. package/{chunk-YS4GL6OK.js → chunk-MAK4D54P.js} +20 -6
  3. package/chunk-MAK4D54P.js.map +1 -0
  4. package/{chunk-JO5AVWG7.js → chunk-XINRLWR3.js} +14 -6
  5. package/chunk-XINRLWR3.js.map +1 -0
  6. package/deno.json +20 -0
  7. package/{gateway-IZRHJWPE.js → gateway-7OM6OSYK.js} +3 -4
  8. package/gateway-7OM6OSYK.js.map +1 -0
  9. package/{gateway-YSNUK2L3.js → gateway-VWWKLHUI.js} +4 -5
  10. package/{gateway-YSNUK2L3.js.map → gateway-VWWKLHUI.js.map} +1 -1
  11. package/index.cjs +549 -372
  12. package/index.cjs.map +1 -1
  13. package/index.d.cts +75 -51
  14. package/index.d.ts +75 -51
  15. package/index.global.js +21461 -15114
  16. package/index.global.js.map +1 -1
  17. package/index.js +465 -313
  18. package/index.js.map +1 -1
  19. package/{key-bag-file-NMEBFSPM.js → key-bag-file-DFMW6ZM6.js} +3 -3
  20. package/{key-bag-indexdb-X5V6GNBZ.js → key-bag-indexdb-R2RWGSQ4.js} +3 -3
  21. package/key-bag-indexdb-R2RWGSQ4.js.map +1 -0
  22. package/{mem-filesystem-B6C6QOIP.js → mem-filesystem-BZQZLUR6.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-7YZR3POJ.js} +8 -4
  27. package/node-filesystem-7YZR3POJ.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 +395 -0
  32. package/tests/fireproof/cars/bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i.car +0 -0
  33. package/tests/fireproof/cars/bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i.js +316 -0
  34. package/tests/fireproof/convert_uint8.py +27 -0
  35. package/tests/fireproof/fireproof.test.ts +18 -18
  36. package/tests/fireproof/hello.test.ts +33 -19
  37. package/tests/helpers.ts +7 -4
  38. package/{utils-IZPK4QS7.js → utils-AISQB3PB.js} +3 -3
  39. package/chunk-JO5AVWG7.js.map +0 -1
  40. package/chunk-YS4GL6OK.js.map +0 -1
  41. package/gateway-IZRHJWPE.js.map +0 -1
  42. package/key-bag-indexdb-X5V6GNBZ.js.map +0 -1
  43. package/node-filesystem-5JLBSHKQ.js.map +0 -1
  44. /package/{key-bag-file-NMEBFSPM.js.map → key-bag-file-DFMW6ZM6.js.map} +0 -0
  45. /package/{mem-filesystem-B6C6QOIP.js.map → mem-filesystem-BZQZLUR6.js.map} +0 -0
  46. /package/{utils-IZPK4QS7.js.map → utils-AISQB3PB.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-XINRLWR3.js";
4
+ import "./chunk-MAK4D54P.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-7YZR3POJ.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-dryrun",
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,395 @@
1
+ import { Database, bs } from "@fireproof/core";
2
+ import { URI } from "@adviser/cement";
3
+
4
+ // @ts-expect-error - This import has no type definitions
5
+ import { fileContent } from "./cars/bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i.js";
6
+
7
+ function customExpect(value: unknown, matcher: (val: unknown) => void, message: string): void {
8
+ try {
9
+ matcher(value);
10
+ } catch (error) {
11
+ void error;
12
+ // console.error(error);
13
+ throw new Error(message);
14
+ }
15
+ }
16
+
17
+ interface ExtendedGateway extends bs.Gateway {
18
+ logger: { _attributes: { module: string; url?: string } };
19
+ headerSize: number;
20
+ fidLength: number;
21
+ }
22
+
23
+ interface ExtendedStore {
24
+ gateway: ExtendedGateway;
25
+ _url: URI;
26
+ name: string;
27
+ }
28
+
29
+ describe("noop Gateway", function () {
30
+ let db: Database;
31
+ let carStore: ExtendedStore;
32
+ let metaStore: ExtendedStore;
33
+ let fileStore: ExtendedStore;
34
+ let walStore: ExtendedStore;
35
+ let carGateway: ExtendedGateway;
36
+ let metaGateway: ExtendedGateway;
37
+ let fileGateway: ExtendedGateway;
38
+ let walGateway: ExtendedGateway;
39
+
40
+ afterEach(async function () {
41
+ await db.close();
42
+ await db.destroy();
43
+ });
44
+ beforeEach(async function () {
45
+ db = new Database("test-gateway-" + Math.random().toString(36).substring(7));
46
+
47
+ // Extract stores from the loader
48
+ carStore = (await db.blockstore.loader?.carStore()) as unknown as ExtendedStore;
49
+ metaStore = (await db.blockstore.loader?.metaStore()) as unknown as ExtendedStore;
50
+ fileStore = (await db.blockstore.loader?.fileStore()) as unknown as ExtendedStore;
51
+ walStore = (await db.blockstore.loader?.WALStore()) as unknown as ExtendedStore;
52
+
53
+ // Extract and log gateways
54
+ carGateway = carStore?.gateway;
55
+ metaGateway = metaStore?.gateway;
56
+ fileGateway = fileStore?.gateway;
57
+ walGateway = walStore?.gateway;
58
+ });
59
+
60
+ it("should have valid stores and gateways", async function () {
61
+ // Add assertions
62
+ expect(carStore).toBeTruthy();
63
+ expect(metaStore).toBeTruthy();
64
+ expect(fileStore).toBeTruthy();
65
+ expect(walStore).toBeTruthy();
66
+
67
+ expect(carGateway).toBeTruthy();
68
+ expect(metaGateway).toBeTruthy();
69
+ expect(fileGateway).toBeTruthy();
70
+ expect(walGateway).toBeTruthy();
71
+ });
72
+
73
+ it("should have correct store names", async function () {
74
+ // Check that all stores have the correct name
75
+ expect(carStore?.name).toContain("test-gateway");
76
+ expect(metaStore?.name).toContain("test-gateway");
77
+ expect(fileStore?.name).toContain("test-gateway");
78
+ expect(walStore?.name).toContain("test-gateway");
79
+ });
80
+
81
+ it("should have correct store types in URLs", async function () {
82
+ // Check that all stores have the correct store type in their URL
83
+ expect(carStore?._url.toString()).toContain("store=data");
84
+ expect(metaStore?._url.toString()).toContain("store=meta");
85
+ expect(fileStore?._url.toString()).toContain("store=data");
86
+ expect(walStore?._url.toString()).toContain("store=wal");
87
+ });
88
+
89
+ it("should have version specified in URLs", async function () {
90
+ // Verify that all stores have a version specified
91
+ expect(carStore?._url.toString()).toContain("version=");
92
+ expect(metaStore?._url.toString()).toContain("version=");
93
+ expect(fileStore?._url.toString()).toContain("version=");
94
+ expect(walStore?._url.toString()).toContain("version=");
95
+ });
96
+
97
+ it("should have correct gateway types", async function () {
98
+ // Check that all gateways are instances of the expected gateway class
99
+ expect(typeof carGateway).toBe("object");
100
+ expect(typeof metaGateway).toBe("object");
101
+ expect(typeof fileGateway).toBe("object");
102
+ expect(typeof walGateway).toBe("object");
103
+ });
104
+
105
+ it("should build CAR Gateway URL", async function () {
106
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
107
+ const carUrl = await carGateway?.buildUrl(carStore?._url, testKey);
108
+ expect(carUrl?.Ok()).toBeTruthy();
109
+ });
110
+
111
+ it("should start CAR Gateway", async function () {
112
+ await carGateway?.start(carStore?._url);
113
+ });
114
+
115
+ it("should put data in CAR Gateway", async function () {
116
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
117
+ const testData = fileContent;
118
+ const carUrl = await carGateway?.buildUrl(carStore?._url, testKey);
119
+ await carGateway?.start(carStore?._url);
120
+ const carPutResult = await carGateway?.put(carUrl?.Ok(), testData);
121
+ expect(carPutResult?.Ok()).toBeFalsy();
122
+ });
123
+
124
+ it("should get data from CAR Gateway", async function () {
125
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
126
+ const testData = fileContent;
127
+ const carUrl = await carGateway?.buildUrl(carStore?._url, testKey);
128
+ await carGateway?.start(carStore?._url);
129
+ await carGateway?.put(carUrl?.Ok(), testData);
130
+ const carGetResult = await carGateway?.get(carUrl?.Ok());
131
+ customExpect(carGetResult?.Ok(), (v) => expect(v).toEqual(testData), "carGetResult should match testData");
132
+ });
133
+
134
+ it("should delete data from CAR Gateway", async function () {
135
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
136
+ const testData = fileContent;
137
+ const carUrl = await carGateway?.buildUrl(carStore?._url, testKey);
138
+ await carGateway?.start(carStore?._url);
139
+ await carGateway?.put(carUrl?.Ok(), testData);
140
+ const carDeleteResult = await carGateway?.delete(carUrl?.Ok());
141
+ expect(carDeleteResult?.Ok()).toBeFalsy();
142
+ });
143
+
144
+ it("should close CAR Gateway", async function () {
145
+ await carGateway?.close(carStore?._url);
146
+ });
147
+ it("should build Meta Gateway URL", async function () {
148
+ const metaUrl = await metaGateway?.buildUrl(metaStore?._url, "main");
149
+ expect(metaUrl?.Ok()).toBeTruthy();
150
+ });
151
+
152
+ it("should start Meta Gateway", async function () {
153
+ await metaGateway?.start(metaStore?._url);
154
+ });
155
+
156
+ it("should close Meta Gateway", async function () {
157
+ await metaGateway?.start(metaStore?._url);
158
+ await metaGateway?.close(metaStore?._url);
159
+ });
160
+
161
+ it("should build File Gateway URL", async function () {
162
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
163
+ const fileUrl = await fileGateway?.buildUrl(fileStore?._url, testKey);
164
+ expect(fileUrl?.Ok()).toBeTruthy();
165
+ });
166
+
167
+ it("should start File Gateway", async function () {
168
+ await fileGateway?.start(fileStore?._url);
169
+ });
170
+
171
+ it("should put data to File Gateway", async function () {
172
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
173
+ const testData = fileContent;
174
+ const fileUrl = await fileGateway?.buildUrl(fileStore?._url, testKey);
175
+ await fileGateway?.start(fileStore?._url);
176
+ const filePutResult = await fileGateway?.put(fileUrl?.Ok(), testData);
177
+ expect(filePutResult?.Ok()).toBeFalsy();
178
+ });
179
+
180
+ it("should get data from File Gateway", async function () {
181
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
182
+ const testData = fileContent;
183
+ const fileUrl = await fileGateway?.buildUrl(fileStore?._url, testKey);
184
+ await fileGateway?.start(fileStore?._url);
185
+ await fileGateway?.put(fileUrl?.Ok(), testData);
186
+ const fileGetResult = await fileGateway?.get(fileUrl?.Ok());
187
+ customExpect(fileGetResult?.Ok(), (v) => expect(v).toEqual(testData), "fileGetResult should match testData");
188
+ });
189
+
190
+ it("should delete data from File Gateway", async function () {
191
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
192
+ const testData = fileContent;
193
+ const fileUrl = await fileGateway?.buildUrl(fileStore?._url, testKey);
194
+ await fileGateway?.start(fileStore?._url);
195
+ await fileGateway?.put(fileUrl?.Ok(), testData);
196
+ const fileDeleteResult = await fileGateway?.delete(fileUrl?.Ok());
197
+ expect(fileDeleteResult?.Ok()).toBeFalsy();
198
+ });
199
+
200
+ it("should close File Gateway", async function () {
201
+ await fileGateway?.close(fileStore?._url);
202
+ });
203
+ it("should build WAL Gateway URL", async function () {
204
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
205
+ const walUrl = await walGateway?.buildUrl(walStore?._url, testKey);
206
+ expect(walUrl?.Ok()).toBeTruthy();
207
+ });
208
+
209
+ it("should start WAL Gateway", async function () {
210
+ await walGateway?.start(walStore?._url);
211
+ });
212
+
213
+ it("should put data to WAL Gateway", async function () {
214
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
215
+ const walUrl = await walGateway?.buildUrl(walStore?._url, testKey);
216
+ await walGateway?.start(walStore?._url);
217
+ const walTestDataString = JSON.stringify({
218
+ operations: [],
219
+ noLoaderOps: [],
220
+ fileOperations: [],
221
+ });
222
+ const walEncoder = new TextEncoder();
223
+ const walTestData = walEncoder.encode(walTestDataString);
224
+ const walPutResult = await walGateway?.put(walUrl?.Ok(), walTestData);
225
+ expect(walPutResult?.Ok()).toBeFalsy();
226
+ });
227
+
228
+ it("should get data from WAL Gateway", async function () {
229
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
230
+ const walUrl = await walGateway?.buildUrl(walStore?._url, testKey);
231
+ await walGateway?.start(walStore?._url);
232
+ const walTestDataString = JSON.stringify({
233
+ operations: [],
234
+ noLoaderOps: [],
235
+ fileOperations: [],
236
+ });
237
+ const walEncoder = new TextEncoder();
238
+ const walTestData = walEncoder.encode(walTestDataString);
239
+ await walGateway?.put(walUrl?.Ok(), walTestData);
240
+ const walGetResult = await walGateway?.get(walUrl?.Ok());
241
+ const okResult = walGetResult?.Ok();
242
+ const decodedResult = new TextDecoder().decode(okResult);
243
+ expect(decodedResult).toEqual(walTestDataString);
244
+ });
245
+
246
+ it("should delete data from WAL Gateway", async function () {
247
+ const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
248
+ const walUrl = await walGateway?.buildUrl(walStore?._url, testKey);
249
+ await walGateway?.start(walStore?._url);
250
+ const walTestDataString = JSON.stringify({
251
+ operations: [],
252
+ noLoaderOps: [],
253
+ fileOperations: [],
254
+ });
255
+ const walEncoder = new TextEncoder();
256
+ const walTestData = walEncoder.encode(walTestDataString);
257
+ await walGateway?.put(walUrl?.Ok(), walTestData);
258
+ const walDeleteResult = await walGateway?.delete(walUrl?.Ok());
259
+ expect(walDeleteResult?.Ok()).toBeFalsy();
260
+ });
261
+
262
+ it("should close WAL Gateway", async function () {
263
+ await walGateway?.start(walStore?._url);
264
+ await walGateway?.close(walStore?._url);
265
+ });
266
+
267
+ it("should have correct CAR Gateway properties", async function () {
268
+ // CAR Gateway assertions
269
+ expect(carGateway?.fidLength).toBe(4);
270
+ expect(carGateway?.headerSize).toBe(36);
271
+ expect(carGateway?.logger._attributes).toHaveProperty("module");
272
+ expect(carGateway?.logger._attributes).toHaveProperty("url");
273
+ });
274
+
275
+ it("should have correct Meta Gateway properties", async function () {
276
+ // Meta Gateway assertions
277
+ expect(metaGateway?.fidLength).toBe(4);
278
+ expect(metaGateway?.headerSize).toBe(36);
279
+ expect(metaGateway?.logger._attributes).toHaveProperty("module");
280
+ expect(metaGateway?.logger._attributes).not.toHaveProperty("url");
281
+ });
282
+
283
+ it("should have correct File Gateway properties", async function () {
284
+ // File Gateway assertions
285
+ expect(fileGateway?.fidLength).toBe(4);
286
+ expect(fileGateway?.headerSize).toBe(36);
287
+ expect(fileGateway?.logger._attributes).toHaveProperty("module");
288
+ expect(fileGateway?.logger._attributes).toHaveProperty("url");
289
+ });
290
+
291
+ it("should have correct WAL Gateway properties", async function () {
292
+ // WAL Gateway assertions
293
+ expect(walGateway?.fidLength).toBe(4);
294
+ expect(walGateway?.headerSize).toBe(36);
295
+ expect(walGateway?.logger._attributes).toHaveProperty("module");
296
+ expect(walGateway?.logger._attributes).not.toHaveProperty("url");
297
+ });
298
+ });
299
+
300
+ describe("noop Gateway subscribe", function () {
301
+ let db: Database;
302
+
303
+ let metaStore: ExtendedStore;
304
+
305
+ let metaGateway: ExtendedGateway;
306
+
307
+ afterEach(async function () {
308
+ await db.close();
309
+ await db.destroy();
310
+ });
311
+ beforeEach(async function () {
312
+ db = new Database("test-gateway-" + Math.random().toString(36).substring(7));
313
+
314
+ // Extract stores from the loader
315
+ metaStore = (await db.blockstore.loader?.metaStore()) as unknown as ExtendedStore;
316
+
317
+ metaGateway = metaStore?.gateway;
318
+ });
319
+ it("should subscribe to meta Gateway", async function () {
320
+ const metaUrl = await metaGateway?.buildUrl(metaStore?._url, "main");
321
+ await metaGateway?.start(metaStore?._url);
322
+
323
+ if (metaGateway.subscribe) {
324
+ let resolve: () => void;
325
+ let didCall = false;
326
+ const p = new Promise<void>((r) => {
327
+ resolve = r;
328
+ });
329
+ const metaSubscribeResult = await metaGateway?.subscribe?.(metaUrl?.Ok(), async (data: Uint8Array) => {
330
+ const decodedData = new TextDecoder().decode(data);
331
+ expect(decodedData).toContain("[]");
332
+ didCall = true;
333
+ resolve();
334
+ });
335
+ expect(metaSubscribeResult?.Ok()).toBeTruthy();
336
+ const ok = await db.put({ _id: "key1", hello: "world1" });
337
+ expect(ok).toBeTruthy();
338
+ expect(ok.id).toBe("key1");
339
+ await p;
340
+ expect(didCall).toBeTruthy();
341
+ }
342
+ });
343
+ });
344
+
345
+ describe("Gateway", function () {
346
+ let db: Database;
347
+ // let carStore: ExtendedStore;
348
+ let metaStore: ExtendedStore;
349
+ // let fileStore: ExtendedStore;
350
+ // let walStore: ExtendedStore;
351
+ // let carGateway: ExtendedGateway;
352
+ let metaGateway: ExtendedGateway;
353
+ // let fileGateway: ExtendedGateway;
354
+ // let walGateway: ExtendedGateway;
355
+
356
+ afterEach(async function () {
357
+ await db.close();
358
+ await db.destroy();
359
+ });
360
+ beforeEach(async function () {
361
+ db = new Database("test-gateway-" + Math.random().toString(36).substring(7));
362
+ const ok = await db.put({ _id: "test", foo: "bar" });
363
+ expect(ok).toBeTruthy();
364
+ expect(ok.id).toBe("test");
365
+
366
+ // Extract stores from the loader
367
+ // carStore = (await db.blockstore.loader?.carStore()) as unknown as ExtendedStore;
368
+ metaStore = (await db.blockstore.loader?.metaStore()) as unknown as ExtendedStore;
369
+ // fileStore = (await db.blockstore.loader?.fileStore()) as unknown as ExtendedStore;
370
+ // walStore = (await db.blockstore.loader?.WALStore()) as unknown as ExtendedStore;
371
+
372
+ // Extract and log gateways
373
+ // carGateway = carStore?.gateway;
374
+ metaGateway = metaStore?.gateway;
375
+ // fileGateway = fileStore?.gateway;
376
+ // walGateway = walStore?.gateway;
377
+ });
378
+
379
+ it("should get data from Meta Gateway", async function () {
380
+ const metaUrl = await metaGateway?.buildUrl(metaStore?._url, "main");
381
+ await metaGateway?.start(metaStore?._url);
382
+ const metaGetResult = await metaGateway?.get(metaUrl?.Ok());
383
+ const metaGetResultOk = metaGetResult?.Ok();
384
+ const decodedMetaGetResultOk = new TextDecoder().decode(metaGetResultOk);
385
+ expect(decodedMetaGetResultOk).toContain("parents");
386
+ });
387
+
388
+ it("should delete data from Meta Gateway", async function () {
389
+ const metaUrl = await metaGateway?.buildUrl(metaStore?._url, "main");
390
+ await metaGateway?.start(metaStore?._url);
391
+ // should we be testing .destroy() instead?
392
+ const metaDeleteResult = await metaGateway?.delete(metaUrl?.Ok());
393
+ expect(metaDeleteResult?.Ok()).toBeFalsy();
394
+ });
395
+ });