@fireproof/core 0.18.0 → 0.19.0-dev-use-fix
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +29 -15
- package/chunk-AZVWSRER.js +208 -0
- package/chunk-AZVWSRER.js.map +1 -0
- package/chunk-H3A2HMMM.js +164 -0
- package/chunk-H3A2HMMM.js.map +1 -0
- package/chunk-NZNG6TQT.js +370 -0
- package/chunk-NZNG6TQT.js.map +1 -0
- package/chunk-VZGT7ZYP.js +22 -0
- package/chunk-VZGT7ZYP.js.map +1 -0
- package/chunk-ZHO4NMWL.js +39 -0
- package/chunk-ZHO4NMWL.js.map +1 -0
- package/index.cjs +4706 -0
- package/index.cjs.map +1 -0
- package/index.d.cts +1012 -0
- package/index.d.ts +1012 -0
- package/index.js +2856 -0
- package/index.js.map +1 -0
- package/metafile-cjs.json +1 -0
- package/metafile-esm.json +1 -0
- package/node-sys-container-E7LADX2Z.js +29 -0
- package/node-sys-container-E7LADX2Z.js.map +1 -0
- package/package.json +23 -109
- package/sqlite-data-store-3ST7XOLX.js +120 -0
- package/sqlite-data-store-3ST7XOLX.js.map +1 -0
- package/sqlite-meta-store-QOIMCSJ7.js +137 -0
- package/sqlite-meta-store-QOIMCSJ7.js.map +1 -0
- package/sqlite-wal-store-JFBQPOYT.js +123 -0
- package/sqlite-wal-store-JFBQPOYT.js.map +1 -0
- package/store-file-CSS5THFH.js +193 -0
- package/store-file-CSS5THFH.js.map +1 -0
- package/store-indexdb-DR4HELVP.js +20 -0
- package/store-indexdb-DR4HELVP.js.map +1 -0
- package/store-sql-BG6SMGQJ.js +344 -0
- package/store-sql-BG6SMGQJ.js.map +1 -0
- package/tests/blockstore/loader.test.ts +265 -0
- package/tests/blockstore/store.test.ts +164 -0
- package/tests/blockstore/transaction.test.ts +121 -0
- package/tests/fireproof/config.test.ts +212 -0
- package/tests/fireproof/crdt.test.ts +434 -0
- package/tests/fireproof/database.test.ts +466 -0
- package/tests/fireproof/fireproof.test.ts +602 -0
- package/tests/fireproof/hello.test.ts +54 -0
- package/tests/fireproof/indexer.test.ts +389 -0
- package/tests/helpers.ts +81 -0
- package/tests/react/useFireproof.test.tsx +19 -0
- package/tests/www/gallery.html +132 -0
- package/tests/www/iife.html +42 -0
- package/tests/www/todo-aws.html +232 -0
- package/tests/www/todo-ipfs.html +213 -0
- package/tests/www/todo-local.html +214 -0
- package/tests/www/todo-netlify.html +227 -0
- package/tests/www/todo.html +236 -0
- package/dist/browser/fireproof.cjs +0 -1172
- package/dist/browser/fireproof.cjs.map +0 -1
- package/dist/browser/fireproof.d.cts +0 -268
- package/dist/browser/fireproof.d.ts +0 -268
- package/dist/browser/fireproof.global.js +0 -24178
- package/dist/browser/fireproof.global.js.map +0 -1
- package/dist/browser/fireproof.js +0 -1147
- package/dist/browser/fireproof.js.map +0 -1
- package/dist/browser/metafile-cjs.json +0 -1
- package/dist/browser/metafile-esm.json +0 -1
- package/dist/browser/metafile-iife.json +0 -1
- package/dist/memory/fireproof.cjs +0 -1172
- package/dist/memory/fireproof.cjs.map +0 -1
- package/dist/memory/fireproof.d.cts +0 -268
- package/dist/memory/fireproof.d.ts +0 -268
- package/dist/memory/fireproof.global.js +0 -24178
- package/dist/memory/fireproof.global.js.map +0 -1
- package/dist/memory/fireproof.js +0 -1147
- package/dist/memory/fireproof.js.map +0 -1
- package/dist/memory/metafile-cjs.json +0 -1
- package/dist/memory/metafile-esm.json +0 -1
- package/dist/memory/metafile-iife.json +0 -1
- package/dist/node/fireproof.cjs +0 -1172
- package/dist/node/fireproof.cjs.map +0 -1
- package/dist/node/fireproof.d.cts +0 -268
- package/dist/node/fireproof.d.ts +0 -268
- package/dist/node/fireproof.global.js +0 -38540
- package/dist/node/fireproof.global.js.map +0 -1
- package/dist/node/fireproof.js +0 -1138
- package/dist/node/fireproof.js.map +0 -1
- package/dist/node/metafile-cjs.json +0 -1
- package/dist/node/metafile-esm.json +0 -1
- package/dist/node/metafile-iife.json +0 -1
@@ -0,0 +1,344 @@
|
|
1
|
+
import {
|
2
|
+
NotFoundError
|
3
|
+
} from "./chunk-VZGT7ZYP.js";
|
4
|
+
import {
|
5
|
+
ensureLogger,
|
6
|
+
ensureSQLOpts,
|
7
|
+
exception2Result,
|
8
|
+
exceptionWrapper,
|
9
|
+
getKey,
|
10
|
+
getName
|
11
|
+
} from "./chunk-NZNG6TQT.js";
|
12
|
+
import {
|
13
|
+
SysContainer
|
14
|
+
} from "./chunk-H3A2HMMM.js";
|
15
|
+
|
16
|
+
// src/runtime/store-sql/store-sql.ts
|
17
|
+
import { Result } from "@adviser/cement";
|
18
|
+
|
19
|
+
// src/runtime/store-sql/sqlite-adapter-better-sqlite3.ts
|
20
|
+
import { KeyedResolvOnce } from "@adviser/cement";
|
21
|
+
var onceSQLiteConnections = new KeyedResolvOnce();
|
22
|
+
var SQLiteConnection = class _SQLiteConnection {
|
23
|
+
static fromURL(url, opts = {}) {
|
24
|
+
return new _SQLiteConnection(url, opts);
|
25
|
+
}
|
26
|
+
get client() {
|
27
|
+
if (!this._client) {
|
28
|
+
throw this.logger.Error().Msg("client not connected").AsError();
|
29
|
+
}
|
30
|
+
return this._client;
|
31
|
+
}
|
32
|
+
constructor(url, opts) {
|
33
|
+
this.opts = ensureSQLOpts(url, opts, "SQLiteConnection", { url });
|
34
|
+
this.logger = this.opts.logger;
|
35
|
+
this.url = url;
|
36
|
+
this.logger.Debug().Msg("constructor");
|
37
|
+
}
|
38
|
+
async connect() {
|
39
|
+
let fName = this.url.toString().replace("sqlite://", "").replace(/\?.*$/, "");
|
40
|
+
if (!fName) {
|
41
|
+
throw this.logger.Error().Str("url", this.url.toString()).Msg("filename is empty").AsError();
|
42
|
+
}
|
43
|
+
const hasName = this.url.searchParams.get("name");
|
44
|
+
if (hasName) {
|
45
|
+
fName = SysContainer.join(fName, hasName);
|
46
|
+
if (!fName.endsWith(".sqlite")) {
|
47
|
+
fName += ".sqlite";
|
48
|
+
}
|
49
|
+
}
|
50
|
+
this._client = await onceSQLiteConnections.get(fName).once(async () => {
|
51
|
+
this.logger.Debug().Str("filename", fName).Msg("connect");
|
52
|
+
const Sqlite3Database = (await import("better-sqlite3")).default;
|
53
|
+
if (hasName) {
|
54
|
+
await SysContainer.mkdir(SysContainer.dirname(fName), { recursive: true });
|
55
|
+
}
|
56
|
+
const db = new Sqlite3Database(fName, {
|
57
|
+
// verbose: console.log,
|
58
|
+
nativeBinding: "./node_modules/better-sqlite3/build/Release/better_sqlite3.node"
|
59
|
+
});
|
60
|
+
if (!db) {
|
61
|
+
throw this.logger.Error().Msg("connect failed").AsError();
|
62
|
+
}
|
63
|
+
return db;
|
64
|
+
});
|
65
|
+
}
|
66
|
+
async close() {
|
67
|
+
this.logger.Debug().Msg("close");
|
68
|
+
await this.client.close();
|
69
|
+
}
|
70
|
+
};
|
71
|
+
|
72
|
+
// src/runtime/store-sql/sql-connection-factory.ts
|
73
|
+
function SQLConnectionFactory(databaseURL, opts = {}) {
|
74
|
+
const logger = ensureLogger(opts, "SQLFactory");
|
75
|
+
switch (databaseURL.protocol) {
|
76
|
+
case "sqlite:":
|
77
|
+
logger.Debug().Str("databaseURL", databaseURL.toString()).Msg("connecting to sqlite");
|
78
|
+
return SQLiteConnection.fromURL(databaseURL, {
|
79
|
+
...opts,
|
80
|
+
logger
|
81
|
+
});
|
82
|
+
default:
|
83
|
+
throw logger.Error().Msg("unsupported protocol " + databaseURL.protocol).AsError();
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
// src/runtime/store-sql/store-version-factory.ts
|
88
|
+
async function WalStoreFactory(db) {
|
89
|
+
switch (db.opts.sqlFlavor) {
|
90
|
+
case "sqlite": {
|
91
|
+
const { V0_18_0SQLiteWalStore } = await import("./sqlite-wal-store-JFBQPOYT.js");
|
92
|
+
const store = new V0_18_0SQLiteWalStore(db);
|
93
|
+
return store;
|
94
|
+
}
|
95
|
+
default:
|
96
|
+
throw ensureLogger(db.opts, "WalStoreFactory").Error().Msg("unsupported db connection").AsError();
|
97
|
+
}
|
98
|
+
}
|
99
|
+
async function DataStoreFactory(db) {
|
100
|
+
switch (db.opts.sqlFlavor) {
|
101
|
+
case "sqlite": {
|
102
|
+
const { V0_18_0SQLiteDataStore } = await import("./sqlite-data-store-3ST7XOLX.js");
|
103
|
+
const store = new V0_18_0SQLiteDataStore(db);
|
104
|
+
return store;
|
105
|
+
}
|
106
|
+
default:
|
107
|
+
throw ensureLogger(db.opts, "DataStoreFactory").Error().Msg("unsupported db connection").AsError();
|
108
|
+
}
|
109
|
+
}
|
110
|
+
async function MetaStoreFactory(db) {
|
111
|
+
switch (db.opts.sqlFlavor) {
|
112
|
+
case "sqlite": {
|
113
|
+
const { V0_18_0SQLiteMetaStore } = await import("./sqlite-meta-store-QOIMCSJ7.js");
|
114
|
+
const store = new V0_18_0SQLiteMetaStore(db);
|
115
|
+
return store;
|
116
|
+
}
|
117
|
+
default:
|
118
|
+
throw ensureLogger(db.opts, "MetaStoreFactory").Error().Msg("unsupported db connection").AsError();
|
119
|
+
}
|
120
|
+
}
|
121
|
+
|
122
|
+
// src/runtime/store-sql/store-sql.ts
|
123
|
+
var SQLWalGateway = class {
|
124
|
+
constructor(logger) {
|
125
|
+
this.walSQLStore = {};
|
126
|
+
this.logger = ensureLogger(logger, "SQLWalGateway");
|
127
|
+
}
|
128
|
+
buildUrl(baseUrl, key) {
|
129
|
+
const url = new URL(baseUrl.toString());
|
130
|
+
url.searchParams.set("key", key);
|
131
|
+
return Promise.resolve(Result.Ok(url));
|
132
|
+
}
|
133
|
+
async start(baseUrl) {
|
134
|
+
return exception2Result(async () => {
|
135
|
+
this.logger.Debug().Url(baseUrl).Msg("start");
|
136
|
+
const conn = SQLConnectionFactory(baseUrl);
|
137
|
+
const ws = await WalStoreFactory(conn);
|
138
|
+
await ws.start(baseUrl);
|
139
|
+
this.walSQLStore = ws;
|
140
|
+
});
|
141
|
+
}
|
142
|
+
close(baseUrl) {
|
143
|
+
return this.walSQLStore.close(baseUrl);
|
144
|
+
}
|
145
|
+
destroy(baseUrl) {
|
146
|
+
return this.walSQLStore.destroy(baseUrl);
|
147
|
+
}
|
148
|
+
async put(url, body) {
|
149
|
+
return exception2Result(async () => {
|
150
|
+
const branch = getKey(url, this.logger);
|
151
|
+
const name = getName(url, this.logger);
|
152
|
+
await this.walSQLStore.insert(url, {
|
153
|
+
state: body,
|
154
|
+
updated_at: /* @__PURE__ */ new Date(),
|
155
|
+
name,
|
156
|
+
branch
|
157
|
+
});
|
158
|
+
});
|
159
|
+
}
|
160
|
+
async get(url) {
|
161
|
+
return exceptionWrapper(async () => {
|
162
|
+
const branch = getKey(url, this.logger);
|
163
|
+
const name = getName(url, this.logger);
|
164
|
+
const record = await this.walSQLStore.select(url, { name, branch });
|
165
|
+
if (record.length === 0) {
|
166
|
+
return Result.Err(new NotFoundError(`not found ${name} ${branch}`));
|
167
|
+
}
|
168
|
+
return Result.Ok(record[0].state);
|
169
|
+
});
|
170
|
+
}
|
171
|
+
async delete(url) {
|
172
|
+
return exception2Result(async () => {
|
173
|
+
const branch = getKey(url, this.logger);
|
174
|
+
const name = getName(url, this.logger);
|
175
|
+
await this.walSQLStore.delete(url, { name, branch });
|
176
|
+
});
|
177
|
+
}
|
178
|
+
};
|
179
|
+
var SQLMetaGateway = class {
|
180
|
+
constructor(logger) {
|
181
|
+
this.metaSQLStore = {};
|
182
|
+
this.logger = ensureLogger(logger, "SQLMetaGateway");
|
183
|
+
}
|
184
|
+
buildUrl(baseUrl, key) {
|
185
|
+
const url = new URL(baseUrl.toString());
|
186
|
+
url.searchParams.set("key", key);
|
187
|
+
return Promise.resolve(Result.Ok(url));
|
188
|
+
}
|
189
|
+
async start(baseUrl) {
|
190
|
+
return exception2Result(async () => {
|
191
|
+
this.logger.Debug().Url(baseUrl).Msg("start");
|
192
|
+
const conn = SQLConnectionFactory(baseUrl);
|
193
|
+
const ws = await MetaStoreFactory(conn);
|
194
|
+
await ws.start(baseUrl);
|
195
|
+
this.metaSQLStore = ws;
|
196
|
+
this.logger.Debug().Url(baseUrl).Msg("started");
|
197
|
+
});
|
198
|
+
}
|
199
|
+
close(baseUrl) {
|
200
|
+
return this.metaSQLStore.close(baseUrl);
|
201
|
+
}
|
202
|
+
destroy(baseUrl) {
|
203
|
+
return this.metaSQLStore.destroy(baseUrl);
|
204
|
+
}
|
205
|
+
async put(url, body) {
|
206
|
+
return exception2Result(async () => {
|
207
|
+
const branch = getKey(url, this.logger);
|
208
|
+
const name = getName(url, this.logger);
|
209
|
+
await this.metaSQLStore.insert(url, {
|
210
|
+
meta: body,
|
211
|
+
updated_at: /* @__PURE__ */ new Date(),
|
212
|
+
name,
|
213
|
+
branch
|
214
|
+
});
|
215
|
+
});
|
216
|
+
}
|
217
|
+
async get(url) {
|
218
|
+
return exceptionWrapper(async () => {
|
219
|
+
const branch = getKey(url, this.logger);
|
220
|
+
const name = getName(url, this.logger);
|
221
|
+
const record = await this.metaSQLStore.select(url, {
|
222
|
+
name,
|
223
|
+
branch
|
224
|
+
});
|
225
|
+
if (record.length === 0) {
|
226
|
+
return Result.Err(new NotFoundError(`not found ${name} ${branch}`));
|
227
|
+
}
|
228
|
+
return Result.Ok(record[0].meta);
|
229
|
+
});
|
230
|
+
}
|
231
|
+
async delete(url) {
|
232
|
+
return exception2Result(async () => {
|
233
|
+
const branch = getKey(url, this.logger);
|
234
|
+
const name = getName(url, this.logger);
|
235
|
+
await this.metaSQLStore.delete(url, {
|
236
|
+
name,
|
237
|
+
branch
|
238
|
+
});
|
239
|
+
});
|
240
|
+
}
|
241
|
+
};
|
242
|
+
var SQLDataGateway = class {
|
243
|
+
constructor(logger) {
|
244
|
+
this.dataSQLStore = {};
|
245
|
+
this.logger = ensureLogger(logger, "SQLDataGateway");
|
246
|
+
}
|
247
|
+
buildUrl(baseUrl, key) {
|
248
|
+
const url = new URL(baseUrl.toString());
|
249
|
+
url.searchParams.set("key", key);
|
250
|
+
return Promise.resolve(Result.Ok(url));
|
251
|
+
}
|
252
|
+
async start(baseUrl) {
|
253
|
+
return exception2Result(async () => {
|
254
|
+
this.logger.Debug().Url(baseUrl).Msg("pre-sql-connection");
|
255
|
+
const conn = SQLConnectionFactory(baseUrl);
|
256
|
+
this.logger.Debug().Url(baseUrl).Msg("post-sql-connection");
|
257
|
+
const ws = await DataStoreFactory(conn);
|
258
|
+
this.logger.Debug().Url(baseUrl).Msg("post-data-store-factory");
|
259
|
+
await ws.start(baseUrl);
|
260
|
+
this.dataSQLStore = ws;
|
261
|
+
this.logger.Debug().Url(baseUrl).Msg("started");
|
262
|
+
});
|
263
|
+
}
|
264
|
+
close(baseUrl) {
|
265
|
+
return this.dataSQLStore.close(baseUrl);
|
266
|
+
}
|
267
|
+
destroy(baseUrl) {
|
268
|
+
return this.dataSQLStore.destroy(baseUrl);
|
269
|
+
}
|
270
|
+
async put(url, body) {
|
271
|
+
return exception2Result(async () => {
|
272
|
+
const cid = getKey(url, this.logger);
|
273
|
+
const name = getName(url, this.logger);
|
274
|
+
await this.dataSQLStore.insert(url, {
|
275
|
+
data: body,
|
276
|
+
updated_at: /* @__PURE__ */ new Date(),
|
277
|
+
name,
|
278
|
+
car: cid
|
279
|
+
});
|
280
|
+
});
|
281
|
+
}
|
282
|
+
async get(url) {
|
283
|
+
return exceptionWrapper(async () => {
|
284
|
+
const branch = getKey(url, this.logger);
|
285
|
+
const record = await this.dataSQLStore.select(url, branch);
|
286
|
+
if (record.length === 0) {
|
287
|
+
return Result.Err(new NotFoundError(`not found ${branch}`));
|
288
|
+
}
|
289
|
+
return Result.Ok(record[0].data);
|
290
|
+
});
|
291
|
+
}
|
292
|
+
async delete(url) {
|
293
|
+
return exception2Result(async () => {
|
294
|
+
const branch = getKey(url, this.logger);
|
295
|
+
await this.dataSQLStore.delete(url, branch);
|
296
|
+
return Result.Ok(void 0);
|
297
|
+
});
|
298
|
+
}
|
299
|
+
};
|
300
|
+
var SQLTestStore = class {
|
301
|
+
constructor(ilogger) {
|
302
|
+
const logger = ensureLogger(ilogger, "SQLTestStore");
|
303
|
+
this.logger = logger;
|
304
|
+
}
|
305
|
+
async get(url, key) {
|
306
|
+
const conn = SQLConnectionFactory(url);
|
307
|
+
const name = getName(url, this.logger);
|
308
|
+
switch (url.searchParams.get("store")) {
|
309
|
+
case "wal": {
|
310
|
+
const sqlStore = await WalStoreFactory(conn);
|
311
|
+
await sqlStore.start(url);
|
312
|
+
const records = await sqlStore.select(url, {
|
313
|
+
name,
|
314
|
+
branch: key
|
315
|
+
});
|
316
|
+
return records[0].state;
|
317
|
+
}
|
318
|
+
case "meta": {
|
319
|
+
const sqlStore = await MetaStoreFactory(conn);
|
320
|
+
await sqlStore.start(url);
|
321
|
+
const records = await sqlStore.select(url, {
|
322
|
+
name,
|
323
|
+
branch: key
|
324
|
+
});
|
325
|
+
return records[0].meta;
|
326
|
+
}
|
327
|
+
case "data": {
|
328
|
+
const sqlStore = await DataStoreFactory(conn);
|
329
|
+
await sqlStore.start(url);
|
330
|
+
const records = await sqlStore.select(url, key);
|
331
|
+
return records[0].data;
|
332
|
+
}
|
333
|
+
default:
|
334
|
+
throw this.logger.Error().Str("key", key).Msg(`Method not implemented`);
|
335
|
+
}
|
336
|
+
}
|
337
|
+
};
|
338
|
+
export {
|
339
|
+
SQLDataGateway,
|
340
|
+
SQLMetaGateway,
|
341
|
+
SQLTestStore,
|
342
|
+
SQLWalGateway
|
343
|
+
};
|
344
|
+
//# sourceMappingURL=store-sql-BG6SMGQJ.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["../../src/runtime/store-sql/store-sql.ts","../../src/runtime/store-sql/sqlite-adapter-better-sqlite3.ts","../../src/runtime/store-sql/sql-connection-factory.ts","../../src/runtime/store-sql/store-version-factory.ts"],"sourcesContent":["import { Logger, Result } from \"@adviser/cement\";\n\nimport { TestStore } from \"../../blockstore/types.js\";\nimport { SQLConnectionFactory } from \"./sql-connection-factory.js\";\nimport { DataSQLStore, MetaSQLStore, WalSQLStore } from \"./types.js\";\nimport { DataStoreFactory, MetaStoreFactory, WalStoreFactory } from \"./store-version-factory.js\";\nimport { ensureLogger, exception2Result, exceptionWrapper, getKey, getName } from \"../../utils.js\";\nimport { Gateway, GetResult, NotFoundError } from \"../../blockstore/gateway.js\";\n\nexport class SQLWalGateway implements Gateway {\n readonly logger: Logger;\n walSQLStore: WalSQLStore = {} as WalSQLStore;\n constructor(logger: Logger) {\n this.logger = ensureLogger(logger, \"SQLWalGateway\");\n }\n\n buildUrl(baseUrl: URL, key: string): Promise<Result<URL>> {\n const url = new URL(baseUrl.toString());\n url.searchParams.set(\"key\", key);\n return Promise.resolve(Result.Ok(url));\n }\n\n async start(baseUrl: URL): Promise<Result<void>> {\n return exception2Result(async () => {\n this.logger.Debug().Url(baseUrl).Msg(\"start\");\n const conn = SQLConnectionFactory(baseUrl);\n const ws = await WalStoreFactory(conn);\n await ws.start(baseUrl);\n this.walSQLStore = ws;\n });\n }\n close(baseUrl: URL) {\n return this.walSQLStore.close(baseUrl);\n }\n destroy(baseUrl: URL) {\n return this.walSQLStore.destroy(baseUrl);\n }\n\n async put(url: URL, body: Uint8Array): Promise<Result<void>> {\n return exception2Result(async () => {\n const branch = getKey(url, this.logger);\n const name = getName(url, this.logger);\n await this.walSQLStore.insert(url, {\n state: body,\n updated_at: new Date(),\n name,\n branch,\n });\n });\n }\n async get(url: URL): Promise<GetResult> {\n return exceptionWrapper(async () => {\n const branch = getKey(url, this.logger);\n const name = getName(url, this.logger);\n const record = await this.walSQLStore.select(url, { name, branch });\n if (record.length === 0) {\n return Result.Err(new NotFoundError(`not found ${name} ${branch}`));\n }\n return Result.Ok(record[0].state);\n });\n }\n async delete(url: URL): Promise<Result<void>> {\n return exception2Result(async () => {\n const branch = getKey(url, this.logger);\n const name = getName(url, this.logger);\n await this.walSQLStore.delete(url, { name, branch });\n });\n }\n}\n\nexport class SQLMetaGateway implements Gateway {\n readonly logger: Logger;\n metaSQLStore: MetaSQLStore = {} as MetaSQLStore;\n constructor(logger: Logger) {\n this.logger = ensureLogger(logger, \"SQLMetaGateway\");\n }\n\n buildUrl(baseUrl: URL, key: string): Promise<Result<URL>> {\n const url = new URL(baseUrl.toString());\n url.searchParams.set(\"key\", key);\n return Promise.resolve(Result.Ok(url));\n }\n\n async start(baseUrl: URL): Promise<Result<void>> {\n return exception2Result(async () => {\n this.logger.Debug().Url(baseUrl).Msg(\"start\");\n const conn = SQLConnectionFactory(baseUrl);\n const ws = await MetaStoreFactory(conn);\n await ws.start(baseUrl);\n this.metaSQLStore = ws;\n this.logger.Debug().Url(baseUrl).Msg(\"started\");\n });\n }\n close(baseUrl: URL): Promise<Result<void>> {\n return this.metaSQLStore.close(baseUrl);\n }\n destroy(baseUrl: URL): Promise<Result<void>> {\n return this.metaSQLStore.destroy(baseUrl);\n }\n\n async put(url: URL, body: Uint8Array): Promise<Result<void>> {\n return exception2Result(async () => {\n const branch = getKey(url, this.logger);\n const name = getName(url, this.logger);\n await this.metaSQLStore.insert(url, {\n meta: body,\n updated_at: new Date(),\n name,\n branch,\n });\n });\n }\n async get(url: URL): Promise<GetResult> {\n return exceptionWrapper(async () => {\n const branch = getKey(url, this.logger);\n const name = getName(url, this.logger);\n const record = await this.metaSQLStore.select(url, {\n name,\n branch,\n });\n if (record.length === 0) {\n return Result.Err(new NotFoundError(`not found ${name} ${branch}`));\n }\n return Result.Ok(record[0].meta);\n });\n }\n async delete(url: URL): Promise<Result<void>> {\n return exception2Result(async () => {\n const branch = getKey(url, this.logger);\n const name = getName(url, this.logger);\n await this.metaSQLStore.delete(url, {\n name,\n branch,\n });\n });\n }\n}\n\nexport class SQLDataGateway implements Gateway {\n readonly logger: Logger;\n dataSQLStore: DataSQLStore = {} as DataSQLStore;\n constructor(logger: Logger) {\n this.logger = ensureLogger(logger, \"SQLDataGateway\");\n }\n\n buildUrl(baseUrl: URL, key: string): Promise<Result<URL>> {\n const url = new URL(baseUrl.toString());\n url.searchParams.set(\"key\", key);\n return Promise.resolve(Result.Ok(url));\n }\n\n async start(baseUrl: URL): Promise<Result<void>> {\n return exception2Result(async () => {\n this.logger.Debug().Url(baseUrl).Msg(\"pre-sql-connection\");\n const conn = SQLConnectionFactory(baseUrl);\n this.logger.Debug().Url(baseUrl).Msg(\"post-sql-connection\");\n const ws = await DataStoreFactory(conn);\n this.logger.Debug().Url(baseUrl).Msg(\"post-data-store-factory\");\n await ws.start(baseUrl);\n this.dataSQLStore = ws;\n this.logger.Debug().Url(baseUrl).Msg(\"started\");\n });\n }\n close(baseUrl: URL): Promise<Result<void>> {\n return this.dataSQLStore.close(baseUrl);\n }\n destroy(baseUrl: URL): Promise<Result<void>> {\n return this.dataSQLStore.destroy(baseUrl);\n }\n\n async put(url: URL, body: Uint8Array): Promise<Result<void>> {\n return exception2Result(async () => {\n const cid = getKey(url, this.logger);\n const name = getName(url, this.logger);\n await this.dataSQLStore.insert(url, {\n data: body,\n updated_at: new Date(),\n name: name,\n car: cid,\n });\n });\n }\n async get(url: URL): Promise<GetResult> {\n return exceptionWrapper(async () => {\n const branch = getKey(url, this.logger);\n const record = await this.dataSQLStore.select(url, branch);\n if (record.length === 0) {\n return Result.Err(new NotFoundError(`not found ${branch}`));\n }\n return Result.Ok(record[0].data);\n });\n }\n async delete(url: URL): Promise<Result<void>> {\n return exception2Result(async () => {\n const branch = getKey(url, this.logger);\n await this.dataSQLStore.delete(url, branch);\n return Result.Ok(undefined);\n });\n }\n}\n\nexport class SQLTestStore implements TestStore {\n readonly logger: Logger;\n constructor(ilogger: Logger) {\n const logger = ensureLogger(ilogger, \"SQLTestStore\");\n this.logger = logger;\n }\n async get(url: URL, key: string): Promise<Uint8Array> {\n const conn = SQLConnectionFactory(url);\n const name = getName(url, this.logger);\n switch (url.searchParams.get(\"store\")) {\n case \"wal\": {\n const sqlStore = await WalStoreFactory(conn);\n await sqlStore.start(url);\n const records = await sqlStore.select(url, {\n name,\n branch: key,\n });\n return records[0].state;\n }\n case \"meta\": {\n const sqlStore = await MetaStoreFactory(conn);\n await sqlStore.start(url);\n const records = await sqlStore.select(url, {\n name,\n branch: key,\n });\n return records[0].meta;\n }\n case \"data\": {\n const sqlStore = await DataStoreFactory(conn);\n await sqlStore.start(url);\n const records = await sqlStore.select(url, key);\n return records[0].data;\n }\n default:\n throw this.logger.Error().Str(\"key\", key).Msg(`Method not implemented`);\n }\n }\n}\n","import type { Database } from \"better-sqlite3\";\nimport { KeyedResolvOnce, Logger } from \"@adviser/cement\";\n\nimport { DBConnection, SQLOpts } from \"./types.js\";\nimport { SysContainer } from \"../sys-container.js\";\nimport { ensureSQLOpts } from \"./ensurer.js\";\n\n// export function SimpleSQLite(filename: string, opts?: Partial<SQLOpts>): StoreOpts {\n// ensureLogger(opts, \"SimpleSQLite\").Debug().Str(\"filename\", filename).Msg(\"SimpleSQLite\")\n// const db = SQLiteConnection.fromFilename(filename, opts)\n// return SQLiteStoreOptions({\n// data: DataStoreFactory(db, opts),\n// meta: MetaStoreFactory(db, opts),\n// wal: WalStoreFactory(db, opts)\n// }, opts)\n// }\n\nconst onceSQLiteConnections = new KeyedResolvOnce<Database>();\nexport class SQLiteConnection implements DBConnection {\n static fromURL(url: URL, opts: Partial<SQLOpts> = {}): DBConnection {\n return new SQLiteConnection(url, opts);\n }\n readonly url: URL;\n readonly logger: Logger;\n _client?: Database;\n\n readonly opts: SQLOpts;\n\n get client(): Database {\n if (!this._client) {\n throw this.logger.Error().Msg(\"client not connected\").AsError();\n }\n return this._client;\n }\n\n private constructor(url: URL, opts: Partial<SQLOpts>) {\n // console.log(\"better-sqlite3->url->\", url);\n this.opts = ensureSQLOpts(url, opts, \"SQLiteConnection\", { url });\n this.logger = this.opts.logger;\n this.url = url;\n this.logger.Debug().Msg(\"constructor\");\n }\n async connect(): Promise<void> {\n let fName = this.url.toString().replace(\"sqlite://\", \"\").replace(/\\?.*$/, \"\");\n if (!fName) {\n throw this.logger.Error().Str(\"url\", this.url.toString()).Msg(\"filename is empty\").AsError();\n }\n // const version = this.url.searchParams.get(\"version\");\n // if (!version) {\n // throw this.logger.Error().Str(\"url\", this.url.toString()).Msg(\"version not found\").AsError();\n // }\n const hasName = this.url.searchParams.get(\"name\");\n if (hasName) {\n fName = SysContainer.join(fName, hasName);\n if (!fName.endsWith(\".sqlite\")) {\n fName += \".sqlite\";\n }\n }\n this._client = await onceSQLiteConnections.get(fName).once(async () => {\n this.logger.Debug().Str(\"filename\", fName).Msg(\"connect\");\n const Sqlite3Database = (await import(\"better-sqlite3\")).default;\n if (hasName) {\n await SysContainer.mkdir(SysContainer.dirname(fName), { recursive: true });\n }\n const db = new Sqlite3Database(fName, {\n // verbose: console.log,\n nativeBinding: \"./node_modules/better-sqlite3/build/Release/better_sqlite3.node\",\n });\n // this.logger.Debug().Any(\"client\", this.client).Msg(\"connected\")\n if (!db) {\n throw this.logger.Error().Msg(\"connect failed\").AsError();\n }\n return db;\n });\n }\n async close(): Promise<void> {\n this.logger.Debug().Msg(\"close\");\n await this.client.close();\n }\n}\n","import { ensureLogger } from \"../../utils.js\";\nimport { SQLiteConnection } from \"./sqlite-adapter-better-sqlite3.js\";\nimport { DBConnection, SQLOpts } from \"./types.js\";\n\nexport function SQLConnectionFactory(databaseURL: URL, opts: Partial<SQLOpts> = {}): DBConnection {\n const logger = ensureLogger(opts, \"SQLFactory\");\n switch (databaseURL.protocol) {\n case \"sqlite:\":\n logger.Debug().Str(\"databaseURL\", databaseURL.toString()).Msg(\"connecting to sqlite\");\n return SQLiteConnection.fromURL(databaseURL, {\n ...opts,\n logger,\n });\n default:\n throw logger\n .Error()\n .Msg(\"unsupported protocol \" + databaseURL.protocol)\n .AsError();\n }\n}\n","import { Logger } from \"@adviser/cement\";\nimport { ensureLogger, LoggerOpts } from \"../../utils\";\nimport { DBConnection, DataSQLStore, MetaSQLStore, WalSQLStore } from \"./types\";\nimport { SQLITE_VERSION } from \"./v0.19-sqlite/version\";\n\nexport function prepareSQLVersion(iurl: URL, opts: LoggerOpts | Logger): URL {\n if (iurl.searchParams.get(\"version\")) return iurl;\n const url = new URL(iurl.toString());\n switch (url.protocol) {\n case \"sqlite:\":\n {\n url.searchParams.set(\"version\", SQLITE_VERSION);\n }\n break;\n default:\n throw ensureLogger(opts, \"ensureSQLVersion\").Error().Str(\"url\", url.toString()).Msg(\"unsupported protocol\").AsError();\n }\n return url;\n}\n\nexport async function WalStoreFactory(db: DBConnection): Promise<WalSQLStore> {\n switch (db.opts.sqlFlavor) {\n case \"sqlite\": {\n const { V0_18_0SQLiteWalStore } = await import(\"./v0.19-sqlite/sqlite-wal-store.js\");\n const store = new V0_18_0SQLiteWalStore(db);\n return store;\n }\n default:\n throw ensureLogger(db.opts, \"WalStoreFactory\").Error().Msg(\"unsupported db connection\").AsError();\n }\n}\n\nexport async function DataStoreFactory(db: DBConnection): Promise<DataSQLStore> {\n switch (db.opts.sqlFlavor) {\n case \"sqlite\": {\n const { V0_18_0SQLiteDataStore } = await import(\"./v0.19-sqlite/sqlite-data-store.js\");\n const store = new V0_18_0SQLiteDataStore(db);\n return store;\n }\n default:\n throw ensureLogger(db.opts, \"DataStoreFactory\").Error().Msg(\"unsupported db connection\").AsError();\n }\n}\n\nexport async function MetaStoreFactory(db: DBConnection): Promise<MetaSQLStore> {\n switch (db.opts.sqlFlavor) {\n case \"sqlite\": {\n const { V0_18_0SQLiteMetaStore } = await import(\"./v0.19-sqlite/sqlite-meta-store.js\");\n const store = new V0_18_0SQLiteMetaStore(db);\n return store;\n }\n default:\n throw ensureLogger(db.opts, \"MetaStoreFactory\").Error().Msg(\"unsupported db connection\").AsError();\n }\n}\n"],"mappings":"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","names":[]}
|
@@ -0,0 +1,265 @@
|
|
1
|
+
import * as codec from "@ipld/dag-cbor";
|
2
|
+
import { sha256 as hasher } from "multiformats/hashes/sha2";
|
3
|
+
import { BlockView } from "multiformats";
|
4
|
+
import { encode } from "multiformats/block";
|
5
|
+
import { CID } from "multiformats/cid";
|
6
|
+
import { MemoryBlockstore } from "@web3-storage/pail/block";
|
7
|
+
import { CRDTMeta, IndexTransactionMeta, bs, rt } from "@fireproof/core";
|
8
|
+
|
9
|
+
class MyMemoryBlockStore extends bs.EncryptedBlockstore {
|
10
|
+
readonly memblock = new MemoryBlockstore();
|
11
|
+
constructor() {
|
12
|
+
const ebOpts = {
|
13
|
+
name: "MyMemoryBlockStore",
|
14
|
+
};
|
15
|
+
super(ebOpts);
|
16
|
+
}
|
17
|
+
ready(): Promise<void> {
|
18
|
+
return Promise.resolve();
|
19
|
+
}
|
20
|
+
close(): Promise<void> {
|
21
|
+
return this.loader.close();
|
22
|
+
}
|
23
|
+
loader = new bs.Loader("MyMemoryBlockStore", {});
|
24
|
+
readonly transactions = new Set<bs.CarTransaction>();
|
25
|
+
// readonly lastTxMeta?: TransactionMeta;
|
26
|
+
readonly compacting: boolean = false;
|
27
|
+
|
28
|
+
override async put(cid: bs.AnyAnyLink, block: Uint8Array): Promise<void> {
|
29
|
+
return this.memblock.put(cid, block);
|
30
|
+
}
|
31
|
+
|
32
|
+
// transaction<M ext(fn: (t: CarTransaction) => Promise<MetaType>, opts?: { noLoader: boolean }): Promise<MetaType> {
|
33
|
+
// throw new Error("Method not implemented.");
|
34
|
+
// }
|
35
|
+
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
37
|
+
getFile(car: bs.AnyLink, cid: bs.AnyLink, isPublic?: boolean): Promise<Uint8Array> {
|
38
|
+
throw new Error("Method not implemented.");
|
39
|
+
}
|
40
|
+
compact(): Promise<void> {
|
41
|
+
throw new Error("Method not implemented.");
|
42
|
+
}
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
44
|
+
defaultCompact(blocks: bs.CompactionFetcher): Promise<bs.TransactionMeta> {
|
45
|
+
throw new Error("Method not implemented.");
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
describe("basic Loader simple", function () {
|
50
|
+
let loader: bs.Loader;
|
51
|
+
let block: BlockView;
|
52
|
+
let t: bs.CarTransaction;
|
53
|
+
|
54
|
+
afterEach(async function () {
|
55
|
+
await loader.close();
|
56
|
+
await loader.destroy();
|
57
|
+
});
|
58
|
+
|
59
|
+
beforeEach(async function () {
|
60
|
+
const testDbName = "test-loader-commit";
|
61
|
+
await rt.SysContainer.start();
|
62
|
+
const mockM = new MyMemoryBlockStore();
|
63
|
+
t = new bs.CarTransaction(mockM as bs.EncryptedBlockstore);
|
64
|
+
loader = new bs.Loader(testDbName, { public: true });
|
65
|
+
await loader.ready();
|
66
|
+
block = await encode({
|
67
|
+
value: { hello: "world" },
|
68
|
+
hasher,
|
69
|
+
codec,
|
70
|
+
});
|
71
|
+
await t.put(block.cid, block.bytes);
|
72
|
+
await mockM.put(block.cid, block.bytes);
|
73
|
+
});
|
74
|
+
it("should have an empty car log", function () {
|
75
|
+
expect(loader.carLog.length).toBe(0);
|
76
|
+
});
|
77
|
+
it("should commit", async function () {
|
78
|
+
const carGroup = await loader.commit(t, { head: [block.cid] });
|
79
|
+
expect(loader.carLog.length).toBe(1);
|
80
|
+
const reader = await loader.loadCar(carGroup[0]);
|
81
|
+
expect(reader).toBeTruthy();
|
82
|
+
const parsed = await bs.parseCarFile<CRDTMeta>(reader, loader.logger);
|
83
|
+
expect(parsed.cars).toBeTruthy();
|
84
|
+
expect(parsed.cars.length).toBe(0);
|
85
|
+
expect(parsed.meta).toBeTruthy();
|
86
|
+
expect(parsed.meta.head).toBeTruthy();
|
87
|
+
});
|
88
|
+
});
|
89
|
+
|
90
|
+
describe("basic Loader with two commits", function () {
|
91
|
+
let loader: bs.Loader;
|
92
|
+
let block: BlockView;
|
93
|
+
let block2: BlockView;
|
94
|
+
let block3: BlockView;
|
95
|
+
let block4: BlockView;
|
96
|
+
let t: bs.CarTransaction;
|
97
|
+
let carCid: bs.CarGroup;
|
98
|
+
let carCid0: bs.CarGroup;
|
99
|
+
|
100
|
+
afterEach(async function () {
|
101
|
+
await loader.close();
|
102
|
+
await loader.destroy();
|
103
|
+
});
|
104
|
+
|
105
|
+
beforeEach(async function () {
|
106
|
+
await rt.SysContainer.start();
|
107
|
+
const mockM = new MyMemoryBlockStore();
|
108
|
+
t = new bs.CarTransaction(mockM);
|
109
|
+
loader = new bs.Loader("test-loader-two-commit", { public: true });
|
110
|
+
block = await encode({
|
111
|
+
value: { hello: "world" },
|
112
|
+
hasher,
|
113
|
+
codec,
|
114
|
+
});
|
115
|
+
await t.put(block.cid, block.bytes);
|
116
|
+
carCid0 = await loader.commit(t, { head: [block.cid] });
|
117
|
+
|
118
|
+
block2 = await encode({
|
119
|
+
value: { hello: "universe" },
|
120
|
+
hasher,
|
121
|
+
codec,
|
122
|
+
});
|
123
|
+
await t.put(block2.cid, block2.bytes);
|
124
|
+
carCid = await loader.commit(t, { head: [block2.cid] });
|
125
|
+
|
126
|
+
block3 = await encode({
|
127
|
+
value: { hello: "multiverse" },
|
128
|
+
hasher,
|
129
|
+
codec,
|
130
|
+
});
|
131
|
+
await t.put(block3.cid, block3.bytes);
|
132
|
+
|
133
|
+
block4 = await encode({
|
134
|
+
value: { hello: "megaverse" },
|
135
|
+
hasher,
|
136
|
+
codec,
|
137
|
+
});
|
138
|
+
|
139
|
+
await t.put(block4.cid, block4.bytes);
|
140
|
+
});
|
141
|
+
|
142
|
+
it("should have a car log", function () {
|
143
|
+
expect(loader.carLog.length).toBe(2);
|
144
|
+
expect(loader.carLog[0].toString()).toBe(carCid.toString());
|
145
|
+
expect(loader.carLog[1].toString()).toBe(carCid0.toString());
|
146
|
+
});
|
147
|
+
|
148
|
+
it("should commit", async function () {
|
149
|
+
const reader = await loader.loadCar(carCid[0]);
|
150
|
+
expect(reader).toBeTruthy();
|
151
|
+
const parsed = await bs.parseCarFile<CRDTMeta>(reader, loader.logger);
|
152
|
+
expect(parsed.cars).toBeTruthy();
|
153
|
+
expect(parsed.compact.length).toBe(0);
|
154
|
+
expect(parsed.cars.length).toBe(1);
|
155
|
+
expect(parsed.meta).toBeTruthy();
|
156
|
+
expect(parsed.meta.head).toBeTruthy();
|
157
|
+
});
|
158
|
+
|
159
|
+
it("should compact", async function () {
|
160
|
+
const compactCid = await loader.commit(t, { head: [block2.cid] }, { compact: true });
|
161
|
+
expect(loader.carLog.length).toBe(1);
|
162
|
+
|
163
|
+
const reader = await loader.loadCar(compactCid[0]);
|
164
|
+
expect(reader).toBeTruthy();
|
165
|
+
const parsed = await bs.parseCarFile<CRDTMeta>(reader, loader.logger);
|
166
|
+
expect(parsed.cars).toBeTruthy();
|
167
|
+
expect(parsed.compact.length).toBe(2);
|
168
|
+
expect(parsed.cars.length).toBe(0);
|
169
|
+
expect(parsed.meta).toBeTruthy();
|
170
|
+
expect(parsed.meta.head).toBeTruthy();
|
171
|
+
});
|
172
|
+
|
173
|
+
it("compact should erase old files", async function () {
|
174
|
+
const cs = await loader.carStore();
|
175
|
+
await loader.commit(t, { head: [block2.cid] }, { compact: true });
|
176
|
+
expect(loader.carLog.length).toBe(1);
|
177
|
+
await loader.commit(t, { head: [block3.cid] }, { compact: false });
|
178
|
+
expect(loader.carLog.length).toBe(2);
|
179
|
+
expect(await cs.load(carCid[0])).toBeTruthy();
|
180
|
+
await loader.commit(t, { head: [block3.cid] }, { compact: true });
|
181
|
+
expect(loader.carLog.length).toBe(1);
|
182
|
+
const e0 = await cs.load(carCid[0]).catch((e) => e);
|
183
|
+
expect(e0 instanceof Error).toBeTruthy();
|
184
|
+
await loader.commit(t, { head: [block4.cid] }, { compact: false });
|
185
|
+
expect(loader.carLog.length).toBe(2);
|
186
|
+
|
187
|
+
const e = await loader.loadCar(carCid[0]).catch((e) => e);
|
188
|
+
expect(e).toBeTruthy();
|
189
|
+
expect(e instanceof Error).toBeTruthy();
|
190
|
+
expect(e.message).toMatch("missing car file");
|
191
|
+
}, 10000);
|
192
|
+
});
|
193
|
+
|
194
|
+
describe("basic Loader with index commits", function () {
|
195
|
+
let block: BlockView;
|
196
|
+
let ib: bs.EncryptedBlockstore;
|
197
|
+
let indexerResult: IndexTransactionMeta;
|
198
|
+
let cid: CID;
|
199
|
+
// let indexMap: Map<string, CID>;
|
200
|
+
|
201
|
+
afterEach(async function () {
|
202
|
+
await ib.close();
|
203
|
+
await ib.destroy();
|
204
|
+
});
|
205
|
+
|
206
|
+
beforeEach(async function () {
|
207
|
+
const name = "test-loader-index" + Math.random();
|
208
|
+
await rt.SysContainer.start();
|
209
|
+
// t = new CarTransaction()
|
210
|
+
ib = new bs.EncryptedBlockstore({ name });
|
211
|
+
block = await encode({
|
212
|
+
value: { hello: "world" },
|
213
|
+
hasher,
|
214
|
+
codec,
|
215
|
+
});
|
216
|
+
// console.log('block', block.cid)
|
217
|
+
|
218
|
+
cid = CID.parse("bafybeia4luuns6dgymy5kau5rm7r4qzrrzg6cglpzpogussprpy42cmcn4");
|
219
|
+
indexerResult = {
|
220
|
+
indexes: {
|
221
|
+
hello: {
|
222
|
+
byId: cid,
|
223
|
+
byKey: cid,
|
224
|
+
head: [cid as CID<unknown, number, number, 1>],
|
225
|
+
name: "hello",
|
226
|
+
map: "(doc) => doc.hello",
|
227
|
+
},
|
228
|
+
},
|
229
|
+
};
|
230
|
+
// indexMap = new Map();
|
231
|
+
});
|
232
|
+
|
233
|
+
it("should start with an empty car log", function () {
|
234
|
+
expect(ib.loader).toBeTruthy();
|
235
|
+
expect(ib.loader.carLog.length).toBe(0);
|
236
|
+
});
|
237
|
+
|
238
|
+
it("should commit the index metadata", async function () {
|
239
|
+
const { cars: carCid } = await ib.transaction<IndexTransactionMeta>(
|
240
|
+
async (t) => {
|
241
|
+
await t.put(block.cid, block.bytes);
|
242
|
+
return indexerResult;
|
243
|
+
} /* , indexMap */,
|
244
|
+
);
|
245
|
+
|
246
|
+
expect(carCid).toBeTruthy();
|
247
|
+
expect(ib.loader).toBeTruthy();
|
248
|
+
const carLog = ib.loader.carLog;
|
249
|
+
|
250
|
+
expect(carLog.length).toBe(1);
|
251
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
252
|
+
const reader = await ib.loader.loadCar(carCid![0]);
|
253
|
+
expect(reader).toBeTruthy();
|
254
|
+
const parsed = await bs.parseCarFile<IndexTransactionMeta>(reader, ib.loader.logger);
|
255
|
+
expect(parsed.cars).toBeTruthy();
|
256
|
+
expect(parsed.cars.length).toBe(0);
|
257
|
+
expect(parsed.meta).toBeTruthy();
|
258
|
+
expect(parsed.meta.indexes).toBeTruthy();
|
259
|
+
const indexes = parsed.meta.indexes;
|
260
|
+
expect(indexes).toBeTruthy();
|
261
|
+
expect(indexes.hello).toBeTruthy();
|
262
|
+
expect(indexes.hello.map).toBe("(doc) => doc.hello");
|
263
|
+
expect(indexes.hello.name).toBe("hello");
|
264
|
+
});
|
265
|
+
});
|