@fireproof/core 0.6.1 → 0.6.3-dev

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.
@@ -1,5 +1,8 @@
1
1
  'use strict';
2
2
 
3
+ var node_fs = require('node:fs');
4
+ var promises = require('fs/promises');
5
+
3
6
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
4
7
 
5
8
  function getDefaultExportFromCjs (x) {
@@ -8143,267 +8146,6 @@ var raw = /*#__PURE__*/Object.freeze({
8143
8146
  name: name$2
8144
8147
  });
8145
8148
 
8146
- const instanceOfAny = (object, constructors) => constructors.some((c) => object instanceof c);
8147
-
8148
- let idbProxyableTypes;
8149
- let cursorAdvanceMethods;
8150
- // This is a function to prevent it throwing up in node environments.
8151
- function getIdbProxyableTypes() {
8152
- return (idbProxyableTypes ||
8153
- (idbProxyableTypes = [
8154
- IDBDatabase,
8155
- IDBObjectStore,
8156
- IDBIndex,
8157
- IDBCursor,
8158
- IDBTransaction,
8159
- ]));
8160
- }
8161
- // This is a function to prevent it throwing up in node environments.
8162
- function getCursorAdvanceMethods() {
8163
- return (cursorAdvanceMethods ||
8164
- (cursorAdvanceMethods = [
8165
- IDBCursor.prototype.advance,
8166
- IDBCursor.prototype.continue,
8167
- IDBCursor.prototype.continuePrimaryKey,
8168
- ]));
8169
- }
8170
- const cursorRequestMap = new WeakMap();
8171
- const transactionDoneMap = new WeakMap();
8172
- const transactionStoreNamesMap = new WeakMap();
8173
- const transformCache = new WeakMap();
8174
- const reverseTransformCache = new WeakMap();
8175
- function promisifyRequest(request) {
8176
- const promise = new Promise((resolve, reject) => {
8177
- const unlisten = () => {
8178
- request.removeEventListener('success', success);
8179
- request.removeEventListener('error', error);
8180
- };
8181
- const success = () => {
8182
- resolve(wrap$1(request.result));
8183
- unlisten();
8184
- };
8185
- const error = () => {
8186
- reject(request.error);
8187
- unlisten();
8188
- };
8189
- request.addEventListener('success', success);
8190
- request.addEventListener('error', error);
8191
- });
8192
- promise
8193
- .then((value) => {
8194
- // Since cursoring reuses the IDBRequest (*sigh*), we cache it for later retrieval
8195
- // (see wrapFunction).
8196
- if (value instanceof IDBCursor) {
8197
- cursorRequestMap.set(value, request);
8198
- }
8199
- // Catching to avoid "Uncaught Promise exceptions"
8200
- })
8201
- .catch(() => { });
8202
- // This mapping exists in reverseTransformCache but doesn't doesn't exist in transformCache. This
8203
- // is because we create many promises from a single IDBRequest.
8204
- reverseTransformCache.set(promise, request);
8205
- return promise;
8206
- }
8207
- function cacheDonePromiseForTransaction(tx) {
8208
- // Early bail if we've already created a done promise for this transaction.
8209
- if (transactionDoneMap.has(tx))
8210
- return;
8211
- const done = new Promise((resolve, reject) => {
8212
- const unlisten = () => {
8213
- tx.removeEventListener('complete', complete);
8214
- tx.removeEventListener('error', error);
8215
- tx.removeEventListener('abort', error);
8216
- };
8217
- const complete = () => {
8218
- resolve();
8219
- unlisten();
8220
- };
8221
- const error = () => {
8222
- reject(tx.error || new DOMException('AbortError', 'AbortError'));
8223
- unlisten();
8224
- };
8225
- tx.addEventListener('complete', complete);
8226
- tx.addEventListener('error', error);
8227
- tx.addEventListener('abort', error);
8228
- });
8229
- // Cache it for later retrieval.
8230
- transactionDoneMap.set(tx, done);
8231
- }
8232
- let idbProxyTraps = {
8233
- get(target, prop, receiver) {
8234
- if (target instanceof IDBTransaction) {
8235
- // Special handling for transaction.done.
8236
- if (prop === 'done')
8237
- return transactionDoneMap.get(target);
8238
- // Polyfill for objectStoreNames because of Edge.
8239
- if (prop === 'objectStoreNames') {
8240
- return target.objectStoreNames || transactionStoreNamesMap.get(target);
8241
- }
8242
- // Make tx.store return the only store in the transaction, or undefined if there are many.
8243
- if (prop === 'store') {
8244
- return receiver.objectStoreNames[1]
8245
- ? undefined
8246
- : receiver.objectStore(receiver.objectStoreNames[0]);
8247
- }
8248
- }
8249
- // Else transform whatever we get back.
8250
- return wrap$1(target[prop]);
8251
- },
8252
- set(target, prop, value) {
8253
- target[prop] = value;
8254
- return true;
8255
- },
8256
- has(target, prop) {
8257
- if (target instanceof IDBTransaction &&
8258
- (prop === 'done' || prop === 'store')) {
8259
- return true;
8260
- }
8261
- return prop in target;
8262
- },
8263
- };
8264
- function replaceTraps(callback) {
8265
- idbProxyTraps = callback(idbProxyTraps);
8266
- }
8267
- function wrapFunction(func) {
8268
- // Due to expected object equality (which is enforced by the caching in `wrap`), we
8269
- // only create one new func per func.
8270
- // Edge doesn't support objectStoreNames (booo), so we polyfill it here.
8271
- if (func === IDBDatabase.prototype.transaction &&
8272
- !('objectStoreNames' in IDBTransaction.prototype)) {
8273
- return function (storeNames, ...args) {
8274
- const tx = func.call(unwrap(this), storeNames, ...args);
8275
- transactionStoreNamesMap.set(tx, storeNames.sort ? storeNames.sort() : [storeNames]);
8276
- return wrap$1(tx);
8277
- };
8278
- }
8279
- // Cursor methods are special, as the behaviour is a little more different to standard IDB. In
8280
- // IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the
8281
- // cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense
8282
- // with real promises, so each advance methods returns a new promise for the cursor object, or
8283
- // undefined if the end of the cursor has been reached.
8284
- if (getCursorAdvanceMethods().includes(func)) {
8285
- return function (...args) {
8286
- // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
8287
- // the original object.
8288
- func.apply(unwrap(this), args);
8289
- return wrap$1(cursorRequestMap.get(this));
8290
- };
8291
- }
8292
- return function (...args) {
8293
- // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
8294
- // the original object.
8295
- return wrap$1(func.apply(unwrap(this), args));
8296
- };
8297
- }
8298
- function transformCachableValue(value) {
8299
- if (typeof value === 'function')
8300
- return wrapFunction(value);
8301
- // This doesn't return, it just creates a 'done' promise for the transaction,
8302
- // which is later returned for transaction.done (see idbObjectHandler).
8303
- if (value instanceof IDBTransaction)
8304
- cacheDonePromiseForTransaction(value);
8305
- if (instanceOfAny(value, getIdbProxyableTypes()))
8306
- return new Proxy(value, idbProxyTraps);
8307
- // Return the same value back if we're not going to transform it.
8308
- return value;
8309
- }
8310
- function wrap$1(value) {
8311
- // We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because
8312
- // IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.
8313
- if (value instanceof IDBRequest)
8314
- return promisifyRequest(value);
8315
- // If we've already transformed this value before, reuse the transformed value.
8316
- // This is faster, but it also provides object equality.
8317
- if (transformCache.has(value))
8318
- return transformCache.get(value);
8319
- const newValue = transformCachableValue(value);
8320
- // Not all types are transformed.
8321
- // These may be primitive types, so they can't be WeakMap keys.
8322
- if (newValue !== value) {
8323
- transformCache.set(value, newValue);
8324
- reverseTransformCache.set(newValue, value);
8325
- }
8326
- return newValue;
8327
- }
8328
- const unwrap = (value) => reverseTransformCache.get(value);
8329
-
8330
- /**
8331
- * Open a database.
8332
- *
8333
- * @param name Name of the database.
8334
- * @param version Schema version.
8335
- * @param callbacks Additional callbacks.
8336
- */
8337
- function openDB(name, version, { blocked, upgrade, blocking, terminated } = {}) {
8338
- const request = indexedDB.open(name, version);
8339
- const openPromise = wrap$1(request);
8340
- if (upgrade) {
8341
- request.addEventListener('upgradeneeded', (event) => {
8342
- upgrade(wrap$1(request.result), event.oldVersion, event.newVersion, wrap$1(request.transaction), event);
8343
- });
8344
- }
8345
- if (blocked) {
8346
- request.addEventListener('blocked', (event) => blocked(
8347
- // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405
8348
- event.oldVersion, event.newVersion, event));
8349
- }
8350
- openPromise
8351
- .then((db) => {
8352
- if (terminated)
8353
- db.addEventListener('close', () => terminated());
8354
- if (blocking) {
8355
- db.addEventListener('versionchange', (event) => blocking(event.oldVersion, event.newVersion, event));
8356
- }
8357
- })
8358
- .catch(() => { });
8359
- return openPromise;
8360
- }
8361
-
8362
- const readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];
8363
- const writeMethods = ['put', 'add', 'delete', 'clear'];
8364
- const cachedMethods = new Map();
8365
- function getMethod(target, prop) {
8366
- if (!(target instanceof IDBDatabase &&
8367
- !(prop in target) &&
8368
- typeof prop === 'string')) {
8369
- return;
8370
- }
8371
- if (cachedMethods.get(prop))
8372
- return cachedMethods.get(prop);
8373
- const targetFuncName = prop.replace(/FromIndex$/, '');
8374
- const useIndex = prop !== targetFuncName;
8375
- const isWrite = writeMethods.includes(targetFuncName);
8376
- if (
8377
- // Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.
8378
- !(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) ||
8379
- !(isWrite || readMethods.includes(targetFuncName))) {
8380
- return;
8381
- }
8382
- const method = async function (storeName, ...args) {
8383
- // isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(
8384
- const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');
8385
- let target = tx.store;
8386
- if (useIndex)
8387
- target = target.index(args.shift());
8388
- // Must reject if op rejects.
8389
- // If it's a write operation, must reject if tx.done rejects.
8390
- // Must reject with op rejection first.
8391
- // Must resolve with op value.
8392
- // Must handle both promises (no unhandled rejections)
8393
- return (await Promise.all([
8394
- target[targetFuncName](...args),
8395
- isWrite && tx.done,
8396
- ]))[0];
8397
- };
8398
- cachedMethods.set(prop, method);
8399
- return method;
8400
- }
8401
- replaceTraps((oldTraps) => ({
8402
- ...oldTraps,
8403
- get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),
8404
- has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop),
8405
- }));
8406
-
8407
8149
  var cargoQueueExports = {};
8408
8150
  var cargoQueue$1 = {
8409
8151
  get exports(){ return cargoQueueExports; },
@@ -8445,7 +8187,7 @@ Object.defineProperty(setImmediate$1, "__esModule", {
8445
8187
  value: true
8446
8188
  });
8447
8189
  setImmediate$1.fallback = fallback;
8448
- setImmediate$1.wrap = wrap;
8190
+ setImmediate$1.wrap = wrap$1;
8449
8191
  /* istanbul ignore file */
8450
8192
 
8451
8193
  var hasQueueMicrotask = setImmediate$1.hasQueueMicrotask = typeof queueMicrotask === 'function' && queueMicrotask;
@@ -8456,7 +8198,7 @@ function fallback(fn) {
8456
8198
  setTimeout(fn, 0);
8457
8199
  }
8458
8200
 
8459
- function wrap(defer) {
8201
+ function wrap$1(defer) {
8460
8202
  return (fn, ...args) => defer(() => fn(...args));
8461
8203
  }
8462
8204
 
@@ -8472,7 +8214,7 @@ if (hasQueueMicrotask) {
8472
8214
  _defer = fallback;
8473
8215
  }
8474
8216
 
8475
- setImmediate$1.default = wrap(_defer);
8217
+ setImmediate$1.default = wrap$1(_defer);
8476
8218
 
8477
8219
  var DoublyLinkedListExports = {};
8478
8220
  var DoublyLinkedList = {
@@ -9143,6 +8885,559 @@ function requireWrapAsync () {
9143
8885
 
9144
8886
  var cargoQueue = /*@__PURE__*/getDefaultExportFromCjs(cargoQueueExports);
9145
8887
 
8888
+ const instanceOfAny = (object, constructors) => constructors.some((c) => object instanceof c);
8889
+
8890
+ let idbProxyableTypes;
8891
+ let cursorAdvanceMethods;
8892
+ // This is a function to prevent it throwing up in node environments.
8893
+ function getIdbProxyableTypes() {
8894
+ return (idbProxyableTypes ||
8895
+ (idbProxyableTypes = [
8896
+ IDBDatabase,
8897
+ IDBObjectStore,
8898
+ IDBIndex,
8899
+ IDBCursor,
8900
+ IDBTransaction,
8901
+ ]));
8902
+ }
8903
+ // This is a function to prevent it throwing up in node environments.
8904
+ function getCursorAdvanceMethods() {
8905
+ return (cursorAdvanceMethods ||
8906
+ (cursorAdvanceMethods = [
8907
+ IDBCursor.prototype.advance,
8908
+ IDBCursor.prototype.continue,
8909
+ IDBCursor.prototype.continuePrimaryKey,
8910
+ ]));
8911
+ }
8912
+ const cursorRequestMap = new WeakMap();
8913
+ const transactionDoneMap = new WeakMap();
8914
+ const transactionStoreNamesMap = new WeakMap();
8915
+ const transformCache = new WeakMap();
8916
+ const reverseTransformCache = new WeakMap();
8917
+ function promisifyRequest(request) {
8918
+ const promise = new Promise((resolve, reject) => {
8919
+ const unlisten = () => {
8920
+ request.removeEventListener('success', success);
8921
+ request.removeEventListener('error', error);
8922
+ };
8923
+ const success = () => {
8924
+ resolve(wrap(request.result));
8925
+ unlisten();
8926
+ };
8927
+ const error = () => {
8928
+ reject(request.error);
8929
+ unlisten();
8930
+ };
8931
+ request.addEventListener('success', success);
8932
+ request.addEventListener('error', error);
8933
+ });
8934
+ promise
8935
+ .then((value) => {
8936
+ // Since cursoring reuses the IDBRequest (*sigh*), we cache it for later retrieval
8937
+ // (see wrapFunction).
8938
+ if (value instanceof IDBCursor) {
8939
+ cursorRequestMap.set(value, request);
8940
+ }
8941
+ // Catching to avoid "Uncaught Promise exceptions"
8942
+ })
8943
+ .catch(() => { });
8944
+ // This mapping exists in reverseTransformCache but doesn't doesn't exist in transformCache. This
8945
+ // is because we create many promises from a single IDBRequest.
8946
+ reverseTransformCache.set(promise, request);
8947
+ return promise;
8948
+ }
8949
+ function cacheDonePromiseForTransaction(tx) {
8950
+ // Early bail if we've already created a done promise for this transaction.
8951
+ if (transactionDoneMap.has(tx))
8952
+ return;
8953
+ const done = new Promise((resolve, reject) => {
8954
+ const unlisten = () => {
8955
+ tx.removeEventListener('complete', complete);
8956
+ tx.removeEventListener('error', error);
8957
+ tx.removeEventListener('abort', error);
8958
+ };
8959
+ const complete = () => {
8960
+ resolve();
8961
+ unlisten();
8962
+ };
8963
+ const error = () => {
8964
+ reject(tx.error || new DOMException('AbortError', 'AbortError'));
8965
+ unlisten();
8966
+ };
8967
+ tx.addEventListener('complete', complete);
8968
+ tx.addEventListener('error', error);
8969
+ tx.addEventListener('abort', error);
8970
+ });
8971
+ // Cache it for later retrieval.
8972
+ transactionDoneMap.set(tx, done);
8973
+ }
8974
+ let idbProxyTraps = {
8975
+ get(target, prop, receiver) {
8976
+ if (target instanceof IDBTransaction) {
8977
+ // Special handling for transaction.done.
8978
+ if (prop === 'done')
8979
+ return transactionDoneMap.get(target);
8980
+ // Polyfill for objectStoreNames because of Edge.
8981
+ if (prop === 'objectStoreNames') {
8982
+ return target.objectStoreNames || transactionStoreNamesMap.get(target);
8983
+ }
8984
+ // Make tx.store return the only store in the transaction, or undefined if there are many.
8985
+ if (prop === 'store') {
8986
+ return receiver.objectStoreNames[1]
8987
+ ? undefined
8988
+ : receiver.objectStore(receiver.objectStoreNames[0]);
8989
+ }
8990
+ }
8991
+ // Else transform whatever we get back.
8992
+ return wrap(target[prop]);
8993
+ },
8994
+ set(target, prop, value) {
8995
+ target[prop] = value;
8996
+ return true;
8997
+ },
8998
+ has(target, prop) {
8999
+ if (target instanceof IDBTransaction &&
9000
+ (prop === 'done' || prop === 'store')) {
9001
+ return true;
9002
+ }
9003
+ return prop in target;
9004
+ },
9005
+ };
9006
+ function replaceTraps(callback) {
9007
+ idbProxyTraps = callback(idbProxyTraps);
9008
+ }
9009
+ function wrapFunction(func) {
9010
+ // Due to expected object equality (which is enforced by the caching in `wrap`), we
9011
+ // only create one new func per func.
9012
+ // Edge doesn't support objectStoreNames (booo), so we polyfill it here.
9013
+ if (func === IDBDatabase.prototype.transaction &&
9014
+ !('objectStoreNames' in IDBTransaction.prototype)) {
9015
+ return function (storeNames, ...args) {
9016
+ const tx = func.call(unwrap(this), storeNames, ...args);
9017
+ transactionStoreNamesMap.set(tx, storeNames.sort ? storeNames.sort() : [storeNames]);
9018
+ return wrap(tx);
9019
+ };
9020
+ }
9021
+ // Cursor methods are special, as the behaviour is a little more different to standard IDB. In
9022
+ // IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the
9023
+ // cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense
9024
+ // with real promises, so each advance methods returns a new promise for the cursor object, or
9025
+ // undefined if the end of the cursor has been reached.
9026
+ if (getCursorAdvanceMethods().includes(func)) {
9027
+ return function (...args) {
9028
+ // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
9029
+ // the original object.
9030
+ func.apply(unwrap(this), args);
9031
+ return wrap(cursorRequestMap.get(this));
9032
+ };
9033
+ }
9034
+ return function (...args) {
9035
+ // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
9036
+ // the original object.
9037
+ return wrap(func.apply(unwrap(this), args));
9038
+ };
9039
+ }
9040
+ function transformCachableValue(value) {
9041
+ if (typeof value === 'function')
9042
+ return wrapFunction(value);
9043
+ // This doesn't return, it just creates a 'done' promise for the transaction,
9044
+ // which is later returned for transaction.done (see idbObjectHandler).
9045
+ if (value instanceof IDBTransaction)
9046
+ cacheDonePromiseForTransaction(value);
9047
+ if (instanceOfAny(value, getIdbProxyableTypes()))
9048
+ return new Proxy(value, idbProxyTraps);
9049
+ // Return the same value back if we're not going to transform it.
9050
+ return value;
9051
+ }
9052
+ function wrap(value) {
9053
+ // We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because
9054
+ // IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.
9055
+ if (value instanceof IDBRequest)
9056
+ return promisifyRequest(value);
9057
+ // If we've already transformed this value before, reuse the transformed value.
9058
+ // This is faster, but it also provides object equality.
9059
+ if (transformCache.has(value))
9060
+ return transformCache.get(value);
9061
+ const newValue = transformCachableValue(value);
9062
+ // Not all types are transformed.
9063
+ // These may be primitive types, so they can't be WeakMap keys.
9064
+ if (newValue !== value) {
9065
+ transformCache.set(value, newValue);
9066
+ reverseTransformCache.set(newValue, value);
9067
+ }
9068
+ return newValue;
9069
+ }
9070
+ const unwrap = (value) => reverseTransformCache.get(value);
9071
+
9072
+ /**
9073
+ * Open a database.
9074
+ *
9075
+ * @param name Name of the database.
9076
+ * @param version Schema version.
9077
+ * @param callbacks Additional callbacks.
9078
+ */
9079
+ function openDB(name, version, { blocked, upgrade, blocking, terminated } = {}) {
9080
+ const request = indexedDB.open(name, version);
9081
+ const openPromise = wrap(request);
9082
+ if (upgrade) {
9083
+ request.addEventListener('upgradeneeded', (event) => {
9084
+ upgrade(wrap(request.result), event.oldVersion, event.newVersion, wrap(request.transaction), event);
9085
+ });
9086
+ }
9087
+ if (blocked) {
9088
+ request.addEventListener('blocked', (event) => blocked(
9089
+ // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405
9090
+ event.oldVersion, event.newVersion, event));
9091
+ }
9092
+ openPromise
9093
+ .then((db) => {
9094
+ if (terminated)
9095
+ db.addEventListener('close', () => terminated());
9096
+ if (blocking) {
9097
+ db.addEventListener('versionchange', (event) => blocking(event.oldVersion, event.newVersion, event));
9098
+ }
9099
+ })
9100
+ .catch(() => { });
9101
+ return openPromise;
9102
+ }
9103
+
9104
+ const readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];
9105
+ const writeMethods = ['put', 'add', 'delete', 'clear'];
9106
+ const cachedMethods = new Map();
9107
+ function getMethod(target, prop) {
9108
+ if (!(target instanceof IDBDatabase &&
9109
+ !(prop in target) &&
9110
+ typeof prop === 'string')) {
9111
+ return;
9112
+ }
9113
+ if (cachedMethods.get(prop))
9114
+ return cachedMethods.get(prop);
9115
+ const targetFuncName = prop.replace(/FromIndex$/, '');
9116
+ const useIndex = prop !== targetFuncName;
9117
+ const isWrite = writeMethods.includes(targetFuncName);
9118
+ if (
9119
+ // Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.
9120
+ !(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) ||
9121
+ !(isWrite || readMethods.includes(targetFuncName))) {
9122
+ return;
9123
+ }
9124
+ const method = async function (storeName, ...args) {
9125
+ // isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(
9126
+ const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');
9127
+ let target = tx.store;
9128
+ if (useIndex)
9129
+ target = target.index(args.shift());
9130
+ // Must reject if op rejects.
9131
+ // If it's a write operation, must reject if tx.done rejects.
9132
+ // Must reject with op rejection first.
9133
+ // Must resolve with op value.
9134
+ // Must handle both promises (no unhandled rejections)
9135
+ return (await Promise.all([
9136
+ target[targetFuncName](...args),
9137
+ isWrite && tx.done,
9138
+ ]))[0];
9139
+ };
9140
+ cachedMethods.set(prop, method);
9141
+ return method;
9142
+ }
9143
+ replaceTraps((oldTraps) => ({
9144
+ ...oldTraps,
9145
+ get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),
9146
+ has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop),
9147
+ }));
9148
+
9149
+ // Copyright Joyent, Inc. and other Node contributors.
9150
+ //
9151
+ // Permission is hereby granted, free of charge, to any person obtaining a
9152
+ // copy of this software and associated documentation files (the
9153
+ // "Software"), to deal in the Software without restriction, including
9154
+ // without limitation the rights to use, copy, modify, merge, publish,
9155
+ // distribute, sublicense, and/or sell copies of the Software, and to permit
9156
+ // persons to whom the Software is furnished to do so, subject to the
9157
+ // following conditions:
9158
+ //
9159
+ // The above copyright notice and this permission notice shall be included
9160
+ // in all copies or substantial portions of the Software.
9161
+ //
9162
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
9163
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
9164
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
9165
+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
9166
+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
9167
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
9168
+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
9169
+
9170
+ // resolves . and .. elements in a path array with directory names there
9171
+ // must be no slashes, empty elements, or device names (c:\) in the array
9172
+ // (so also no leading and trailing slashes - it does not distinguish
9173
+ // relative and absolute paths)
9174
+ function normalizeArray(parts, allowAboveRoot) {
9175
+ // if the path tries to go above the root, `up` ends up > 0
9176
+ var up = 0;
9177
+ for (var i = parts.length - 1; i >= 0; i--) {
9178
+ var last = parts[i];
9179
+ if (last === '.') {
9180
+ parts.splice(i, 1);
9181
+ } else if (last === '..') {
9182
+ parts.splice(i, 1);
9183
+ up++;
9184
+ } else if (up) {
9185
+ parts.splice(i, 1);
9186
+ up--;
9187
+ }
9188
+ }
9189
+
9190
+ // if the path is allowed to go above the root, restore leading ..s
9191
+ if (allowAboveRoot) {
9192
+ for (; up--; up) {
9193
+ parts.unshift('..');
9194
+ }
9195
+ }
9196
+
9197
+ return parts;
9198
+ }
9199
+
9200
+ // Split a filename into [root, dir, basename, ext], unix version
9201
+ // 'root' is just a slash, or nothing.
9202
+ var splitPathRe =
9203
+ /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
9204
+ var splitPath = function(filename) {
9205
+ return splitPathRe.exec(filename).slice(1);
9206
+ };
9207
+
9208
+ // path.normalize(path)
9209
+ // posix version
9210
+ function normalize(path) {
9211
+ var isPathAbsolute = isAbsolute(path),
9212
+ trailingSlash = substr(path, -1) === '/';
9213
+
9214
+ // Normalize the path
9215
+ path = normalizeArray(filter(path.split('/'), function(p) {
9216
+ return !!p;
9217
+ }), !isPathAbsolute).join('/');
9218
+
9219
+ if (!path && !isPathAbsolute) {
9220
+ path = '.';
9221
+ }
9222
+ if (path && trailingSlash) {
9223
+ path += '/';
9224
+ }
9225
+
9226
+ return (isPathAbsolute ? '/' : '') + path;
9227
+ }
9228
+ // posix version
9229
+ function isAbsolute(path) {
9230
+ return path.charAt(0) === '/';
9231
+ }
9232
+
9233
+ // posix version
9234
+ function join() {
9235
+ var paths = Array.prototype.slice.call(arguments, 0);
9236
+ return normalize(filter(paths, function(p, index) {
9237
+ if (typeof p !== 'string') {
9238
+ throw new TypeError('Arguments to path.join must be strings');
9239
+ }
9240
+ return p;
9241
+ }).join('/'));
9242
+ }
9243
+
9244
+ function dirname(path) {
9245
+ var result = splitPath(path),
9246
+ root = result[0],
9247
+ dir = result[1];
9248
+
9249
+ if (!root && !dir) {
9250
+ // No dirname whatsoever
9251
+ return '.';
9252
+ }
9253
+
9254
+ if (dir) {
9255
+ // It has a dirname, strip trailing slash
9256
+ dir = dir.substr(0, dir.length - 1);
9257
+ }
9258
+
9259
+ return root + dir;
9260
+ }
9261
+ function filter (xs, f) {
9262
+ if (xs.filter) return xs.filter(f);
9263
+ var res = [];
9264
+ for (var i = 0; i < xs.length; i++) {
9265
+ if (f(xs[i], i, xs)) res.push(xs[i]);
9266
+ }
9267
+ return res;
9268
+ }
9269
+
9270
+ // String.prototype.substr - negative index don't work in IE8
9271
+ var substr = 'ab'.substr(-1) === 'b' ?
9272
+ function (str, start, len) { return str.substr(start, len) } :
9273
+ function (str, start, len) {
9274
+ if (start < 0) start = str.length + start;
9275
+ return str.substr(start, len);
9276
+ }
9277
+ ;
9278
+
9279
+ function homedir(){
9280
+ return '$HOME'
9281
+ }
9282
+
9283
+ const defaultConfig = {
9284
+ dataDir: join(homedir(), '.fireproof'),
9285
+ headerKeyPrefix: 'fp.'
9286
+ };
9287
+
9288
+ const FORCE_IDB = typeof process !== 'undefined' && !!process.env?.FORCE_IDB;
9289
+
9290
+ /* global localStorage */
9291
+
9292
+ class Loader {
9293
+ constructor (name, keyId, config = defaultConfig) {
9294
+ this.name = name;
9295
+ this.keyId = keyId;
9296
+ this.config = config;
9297
+ this.isBrowser = false;
9298
+ try {
9299
+ this.isBrowser = window.localStorage && true;
9300
+ } catch (e) {}
9301
+ }
9302
+
9303
+ withDB = async (dbWorkFun) => {
9304
+ if (!this.idb) {
9305
+ this.idb = await openDB(`fp.${this.keyId}.${this.name}.valet`, 3, {
9306
+ upgrade (db, oldVersion, newVersion, transaction) {
9307
+ if (oldVersion < 1) {
9308
+ db.createObjectStore('cars');
9309
+ }
9310
+ }
9311
+ });
9312
+ }
9313
+ return await dbWorkFun(this.idb)
9314
+ }
9315
+
9316
+ async writeCars (cars) {
9317
+ // console.log('writeCars', this.config.dataDir, this.name, cars.map(c => c.cid.toString()))
9318
+ // console.log('writeCars', cars.length)
9319
+
9320
+ if (FORCE_IDB || this.isBrowser) {
9321
+ await this.writeCarsIDB(cars);
9322
+ } else {
9323
+ const writes = [];
9324
+ for (const { cid, bytes } of cars) {
9325
+ const carFilename = join(this.config.dataDir, this.name, `${cid.toString()}.car`);
9326
+ // console.log('writeCars', carFilename)
9327
+ writes.push(writeSync(carFilename, bytes));
9328
+ }
9329
+ await Promise.all(writes);
9330
+ }
9331
+ }
9332
+
9333
+ async writeCarsIDB (cars) {
9334
+ return await this.withDB(async db => {
9335
+ const tx = db.transaction(['cars'], 'readwrite');
9336
+ for (const { cid, bytes, replaces } of cars) {
9337
+ await tx.objectStore('cars').put(bytes, cid.toString());
9338
+ // todo remove old maps
9339
+ if (replaces) {
9340
+ await tx.objectStore('cars').delete(replaces.toString());
9341
+ }
9342
+ }
9343
+ return await tx.done
9344
+ })
9345
+ }
9346
+
9347
+ async readCar (carCid) {
9348
+ if (FORCE_IDB || this.isBrowser) {
9349
+ return await this.readCarIDB(carCid)
9350
+ } else {
9351
+ const carFilename = join(this.config.dataDir, this.name, `${carCid.toString()}.car`);
9352
+ const got = node_fs.readFileSync(carFilename);
9353
+ // console.log('readCar', carFilename, got.constructor.name)
9354
+ return got
9355
+ }
9356
+ }
9357
+
9358
+ async readCarIDB (carCid) {
9359
+ return await this.withDB(async db => {
9360
+ const tx = db.transaction(['cars'], 'readonly');
9361
+ // console.log('getCarReader', carCid)
9362
+ return await tx.objectStore('cars').get(carCid)
9363
+ })
9364
+ }
9365
+
9366
+ getHeader () {
9367
+ if (this.isBrowser) {
9368
+ return localStorage.getItem(this.config.headerKeyPrefix + this.name)
9369
+ } else {
9370
+ return loadSync(this.headerFilename())
9371
+ // return null
9372
+ }
9373
+ }
9374
+
9375
+ async saveHeader (stringValue) {
9376
+ // console.log('saveHeader', this.isBrowser)
9377
+ if (this.isBrowser) {
9378
+ // console.log('localStorage!', this.config.headerKeyPrefix)
9379
+ return localStorage.setItem(this.config.headerKeyPrefix + this.name, stringValue)
9380
+ } else {
9381
+ // console.log('no localStorage', this.config.dataDir, this.name)
9382
+ // console.log('saving clock to', this.headerFilename(), stringValue)
9383
+
9384
+ try {
9385
+ await writeSync(this.headerFilename(), stringValue);
9386
+ } catch (error) {
9387
+ console.log('error', error);
9388
+ }
9389
+
9390
+ // console.log('saved clock to', this.headerFilename())
9391
+ }
9392
+ }
9393
+
9394
+ headerFilename () {
9395
+ // console.log('headerFilename', this.config.dataDir, this.name)
9396
+ return join(this.config.dataDir, this.name, 'header.json')
9397
+ }
9398
+
9399
+ // async loadData (database, filename) {
9400
+ // const fullFilePath = join(process.cwd(), filename)
9401
+ // const readableStream = createReadStream(fullFilePath)
9402
+ // const parseStream = parse()
9403
+ // readableStream.pipe(parseStream)
9404
+
9405
+ // const saveQueue = cargoQueue(async (tasks, callback) => {
9406
+ // for (const t of tasks) {
9407
+ // await database.put(t)
9408
+ // }
9409
+ // callback()
9410
+ // })
9411
+
9412
+ // parseStream.on('data', async (data) => {
9413
+ // saveQueue.push(data)
9414
+ // })
9415
+ // let res
9416
+ // const p = new Promise((resolve, reject) => {
9417
+ // res = resolve
9418
+ // })
9419
+ // saveQueue.drain(async (x) => {
9420
+ // res()
9421
+ // })
9422
+ // return p
9423
+ // }
9424
+ }
9425
+
9426
+ function loadSync (filename) {
9427
+ try {
9428
+ return node_fs.readFileSync(filename, 'utf8').toString()
9429
+ } catch (error) {
9430
+ // console.log('error', error)
9431
+ return null
9432
+ }
9433
+ }
9434
+
9435
+ async function writeSync (fullpath, stringValue) {
9436
+ await promises.mkdir(dirname(fullpath), { recursive: true });
9437
+ // writeFileSync(fullpath, stringValue)
9438
+ await promises.writeFile(fullpath, stringValue);
9439
+ }
9440
+
9146
9441
  var cryptoBrowserify = {};
9147
9442
 
9148
9443
  var inherits$x;
@@ -39546,6 +39841,7 @@ class Valet {
39546
39841
  constructor (name = 'default', keyMaterial) {
39547
39842
  this.name = name;
39548
39843
  this.setKeyMaterial(keyMaterial);
39844
+ this.loader = new Loader(name, this.keyId); // todo send this config.loader, if we ever need it
39549
39845
  this.uploadQueue = cargoQueue(async (tasks, callback) => {
39550
39846
  // console.log(
39551
39847
  // 'queue worker',
@@ -39580,6 +39876,10 @@ class Valet {
39580
39876
  });
39581
39877
  }
39582
39878
 
39879
+ saveHeader (header) {
39880
+ return this.loader.saveHeader(header)
39881
+ }
39882
+
39583
39883
  getKeyMaterial () {
39584
39884
  return this.keyMaterial
39585
39885
  }
@@ -39620,19 +39920,6 @@ class Valet {
39620
39920
  }
39621
39921
  }
39622
39922
 
39623
- withDB = async dbWorkFun => {
39624
- if (!this.idb) {
39625
- this.idb = await openDB(`fp.${this.keyId}.${this.name}.valet`, 3, {
39626
- upgrade (db, oldVersion, newVersion, transaction) {
39627
- if (oldVersion < 1) {
39628
- db.createObjectStore('cars');
39629
- }
39630
- }
39631
- });
39632
- }
39633
- return await dbWorkFun(this.idb)
39634
- }
39635
-
39636
39923
  /**
39637
39924
  * Iterate over all blocks in the store.
39638
39925
  *
@@ -39673,6 +39960,7 @@ class Valet {
39673
39960
  blockHasher: blockOpts$1.hasher,
39674
39961
  blockCodec: blockOpts$1.codec
39675
39962
  });
39963
+ this.valetRoot = indexNode;
39676
39964
  }
39677
39965
 
39678
39966
  const got = await indexNode.get(cid);
@@ -39719,6 +40007,7 @@ class Valet {
39719
40007
  * @param {*} value
39720
40008
  */
39721
40009
  async parkCar (carCid, value, cids) {
40010
+ // const callId = Math.random().toString(36).substring(7)
39722
40011
  // console.log('parkCar', this.instanceId, this.name, carCid, cids)
39723
40012
  const combinedReader = await this.getCombinedReader(carCid);
39724
40013
  const mapNode = await addCidsToCarIndex(
@@ -39731,7 +40020,7 @@ class Valet {
39731
40020
  this.valetRoot = mapNode;
39732
40021
  this.valetRootCid = mapNode.cid;
39733
40022
  // make a block set with all the cids of the map
39734
- const saveValetBlocks = new VMemoryBlockstore(); // todo this blockstore should read from the last valetCid car also
40023
+ const saveValetBlocks = new VMemoryBlockstore();
39735
40024
 
39736
40025
  for await (const cidx of mapNode.cids()) {
39737
40026
  const bytes = await combinedReader.get(cidx);
@@ -39744,7 +40033,8 @@ class Valet {
39744
40033
  newValetCidCar = await blocksToCarBlock(this.valetRootCid, saveValetBlocks);
39745
40034
  }
39746
40035
  // console.log('newValetCidCar', this.name, Math.floor(newValetCidCar.bytes.length / 1024))
39747
- await this.writeCars([
40036
+ // console.log('writeCars', callId, carCid.toString(), newValetCidCar.cid.toString())
40037
+ await this.loader.writeCars([
39748
40038
  {
39749
40039
  cid: carCid,
39750
40040
  bytes: value,
@@ -39760,6 +40050,8 @@ class Valet {
39760
40050
 
39761
40051
  this.valetRootCarCid = newValetCidCar.cid; // goes to clock
39762
40052
 
40053
+ // console.log('wroteCars', callId, carCid.toString(), newValetCidCar.cid.toString())
40054
+
39763
40055
  // console.log('parked car', carCid, value.length, Array.from(cids))
39764
40056
  // upload to web3.storage if we have credentials
39765
40057
  if (this.uploadFunction) {
@@ -39774,29 +40066,13 @@ class Valet {
39774
40066
  }
39775
40067
  }
39776
40068
 
39777
- async writeCars (cars) {
39778
- return await this.withDB(async db => {
39779
- const tx = db.transaction(['cars'], 'readwrite');
39780
- for (const { cid, bytes, replaces } of cars) {
39781
- await tx.objectStore('cars').put(bytes, cid.toString());
39782
- // todo remove old maps
39783
- if (replaces) {
39784
- await tx.objectStore('cars').delete(replaces.toString());
39785
- }
39786
- }
39787
- return await tx.done
39788
- })
39789
- }
39790
-
39791
40069
  remoteBlockFunction = null
39792
40070
 
39793
40071
  async getCarReader (carCid) {
39794
40072
  carCid = carCid.toString();
39795
- const carBytes = await this.withDB(async db => {
39796
- const tx = db.transaction(['cars'], 'readonly');
39797
- // console.log('getCarReader', carCid)
39798
- return await tx.objectStore('cars').get(carCid)
39799
- });
40073
+ const carBytes = await this.loader.readCar(carCid);
40074
+ // const callID = Math.random().toString(36).substring(7)
40075
+ // console.log('getCarReader', callID, carCid)
39800
40076
  const reader = await CarReader.fromBytes(carBytes);
39801
40077
  if (this.keyMaterial) {
39802
40078
  const roots = await reader.getRoots();
@@ -39820,7 +40096,7 @@ class Valet {
39820
40096
 
39821
40097
  // last block is the root ??? todo
39822
40098
  const rootBlock = blocks[blocks.length - 1];
39823
-
40099
+ // console.log('got reader', callID, carCid)
39824
40100
  return {
39825
40101
  root: rootBlock,
39826
40102
  get: async dataCID => {
@@ -39947,6 +40223,8 @@ const blocksFromEncryptedCarBlock = async (cid, get, keyMaterial) => {
39947
40223
 
39948
40224
  const addCidsToCarIndex = async (blockstore, valetRoot, valetRootCid, bulkOperations) => {
39949
40225
  let indexNode;
40226
+ // const callID = Math.random().toString(32).substring(2, 8)
40227
+ // console.log('addCidsToCarIndex', callID, valetRootCid, bulkOperations.length)
39950
40228
  if (valetRootCid) {
39951
40229
  if (valetRoot) {
39952
40230
  indexNode = valetRoot;
@@ -39966,6 +40244,7 @@ const addCidsToCarIndex = async (blockstore, valetRoot, valetRootCid, bulkOperat
39966
40244
  // console.log('adding', key, value)
39967
40245
  await indexNode.set(key, value);
39968
40246
  }
40247
+ // console.log('newCidsToCarIndex', callID, indexNode.cid, bulkOperations.length)
39969
40248
  return indexNode
39970
40249
  };
39971
40250
 
@@ -40918,22 +41197,6 @@ object.factory = function (codec) {
40918
41197
  exports.type = 'charwise';
40919
41198
  } (charwise));
40920
41199
 
40921
- /* global localStorage */
40922
- let storageSupported = false;
40923
- try {
40924
- storageSupported = window.localStorage && true;
40925
- } catch (e) {}
40926
- function localGet (key) {
40927
- if (storageSupported) {
40928
- return localStorage && localStorage.getItem(key)
40929
- }
40930
- }
40931
- function localSet (key, value) {
40932
- if (storageSupported) {
40933
- return localStorage && localStorage.setItem(key, value)
40934
- }
40935
- }
40936
-
40937
41200
  // @ts-nocheck
40938
41201
  const parseCID = cid => (typeof cid === 'string' ? CID$1.parse(cid) : cid);
40939
41202
 
@@ -40958,7 +41221,7 @@ class Database {
40958
41221
  this.name = name;
40959
41222
  this.instanceId = `fp.${this.name}.${Math.random().toString(36).substring(2, 7)}`;
40960
41223
  this.blocks = new TransactionBlockstore(name, config.key);
40961
- this.indexBlocks = new TransactionBlockstore(name + '.indexes', config.key);
41224
+ this.indexBlocks = new TransactionBlockstore(name ? name + '.indexes' : null, config.key);
40962
41225
  this.clock = clock;
40963
41226
  this.config = config;
40964
41227
  }
@@ -41002,7 +41265,7 @@ class Database {
41002
41265
 
41003
41266
  maybeSaveClock () {
41004
41267
  if (this.name && this.blocks.valet) {
41005
- localSet('fp.' + this.name, JSON.stringify(this));
41268
+ this.blocks.valet.saveHeader(JSON.stringify(this));
41006
41269
  }
41007
41270
  }
41008
41271
 
@@ -41238,6 +41501,7 @@ class Database {
41238
41501
  console.error('failed', event);
41239
41502
  throw new Error('failed to put at storage layer')
41240
41503
  }
41504
+ // await new Promise(resolve => setTimeout(resolve, 10)) // makes concurrent tests work
41241
41505
  this.applyClock(prevClock, result.head);
41242
41506
  await this.notifyListeners([decodedEvent]); // this type is odd
41243
41507
  return {
@@ -44099,8 +44363,8 @@ class Fireproof {
44099
44363
  static storage = (name = null, opts = {}) => {
44100
44364
  if (name) {
44101
44365
  opts.name = name;
44102
- // todo this can come from a registry also eg remote database / config, etc
44103
- const existing = localGet('fp.' + name);
44366
+ const loader = new Loader(name, opts.loader);
44367
+ const existing = loader.getHeader();
44104
44368
  if (existing) {
44105
44369
  const existingConfig = JSON.parse(existing);
44106
44370
  return Fireproof.fromConfig(name, existingConfig, opts)