json-fs-query 3.1.4 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +257 -15
- package/browser/jsonFsQuery.js +3884 -5057
- package/browser/jsonFsQuery.min.js +1 -1
- package/dist/data/introspect/alter.d.ts +12 -0
- package/dist/data/introspect/alter.js +304 -0
- package/dist/data/introspect/alter.min.js +1 -0
- package/dist/data/introspect/create.d.ts +10 -0
- package/dist/data/introspect/create.js +9 -23
- package/dist/data/introspect/create.min.js +1 -1
- package/dist/data/introspect/drop.js +7 -15
- package/dist/data/introspect/drop.min.js +1 -1
- package/dist/data/introspect/formatDatabase.d.ts +17 -0
- package/dist/data/introspect/formatDatabase.js +56 -0
- package/dist/data/introspect/formatDatabase.min.js +1 -0
- package/dist/data/introspect/index.d.ts +9 -0
- package/dist/data/introspect/index.js +18 -5
- package/dist/data/introspect/index.min.js +1 -1
- package/dist/data/introspect/packDatabase.d.ts +27 -0
- package/dist/data/introspect/packDatabase.js +113 -0
- package/dist/data/introspect/packDatabase.min.js +1 -0
- package/dist/data/introspect/policies/foreignKeyExists.d.ts +2 -0
- package/dist/data/introspect/policies/foreignKeyExists.js +9 -3
- package/dist/data/introspect/policies/foreignKeyExists.min.js +1 -1
- package/dist/data/introspect/policies/hasDependents.d.ts +3 -3
- package/dist/data/introspect/policies/hasDependents.js +11 -3
- package/dist/data/introspect/policies/hasDependents.min.js +1 -1
- package/dist/data/introspect/policies/keyUnique.d.ts +3 -0
- package/dist/data/introspect/policies/keyUnique.js +10 -0
- package/dist/data/introspect/policies/keyUnique.min.js +1 -1
- package/dist/data/queries/databaseStatements.d.ts +31 -0
- package/dist/data/queries/databaseStatements.js +97 -0
- package/dist/data/queries/databaseStatements.min.js +1 -0
- package/dist/data/queries/deleteEntity.js +35 -19
- package/dist/data/queries/deleteEntity.min.js +1 -1
- package/dist/data/queries/insertEntity.d.ts +8 -0
- package/dist/data/queries/insertEntity.js +340 -43
- package/dist/data/queries/insertEntity.min.js +1 -1
- package/dist/data/queries/joinEntity.d.ts +15 -0
- package/dist/data/queries/joinEntity.js +91 -15
- package/dist/data/queries/joinEntity.min.js +1 -1
- package/dist/data/queries/query.d.ts +2 -1
- package/dist/data/queries/query.js +5 -2
- package/dist/data/queries/query.min.js +1 -1
- package/dist/data/queries/selectFields.d.ts +5 -4
- package/dist/data/queries/selectFields.js +25 -11
- package/dist/data/queries/selectFields.min.js +1 -1
- package/dist/data/queries/updateEntity.js +54 -15
- package/dist/data/queries/updateEntity.min.js +1 -1
- package/dist/data/storage/databases.d.ts +32 -0
- package/dist/data/storage/databases.js +93 -0
- package/dist/data/storage/databases.min.js +1 -0
- package/dist/data/storage/fileExists.d.ts +7 -0
- package/dist/data/storage/fileExists.js +25 -0
- package/dist/data/storage/fileExists.min.js +1 -0
- package/dist/data/storage/index.d.ts +19 -0
- package/dist/data/storage/index.js +124 -0
- package/dist/data/storage/index.min.js +1 -0
- package/dist/data/storage/listFiles.d.ts +8 -0
- package/dist/data/storage/listFiles.js +52 -0
- package/dist/data/storage/listFiles.min.js +1 -0
- package/dist/data/storage/makeDirectory.d.ts +7 -0
- package/dist/data/storage/makeDirectory.js +24 -0
- package/dist/data/storage/makeDirectory.min.js +1 -0
- package/dist/data/storage/nodeFiles.d.ts +6 -0
- package/dist/data/storage/nodeFiles.js +12 -0
- package/dist/data/storage/nodeFiles.min.js +1 -0
- package/dist/data/storage/readCache.d.ts +37 -0
- package/dist/data/storage/readCache.js +117 -0
- package/dist/data/storage/readCache.min.js +1 -0
- package/dist/data/storage/readJson.d.ts +16 -0
- package/dist/data/storage/readJson.js +38 -0
- package/dist/data/storage/readJson.min.js +1 -0
- package/dist/data/storage/removeDirectory.d.ts +8 -0
- package/dist/data/storage/removeDirectory.js +30 -0
- package/dist/data/storage/removeDirectory.min.js +1 -0
- package/dist/data/storage/removeFile.d.ts +8 -0
- package/dist/data/storage/removeFile.js +31 -0
- package/dist/data/storage/removeFile.min.js +1 -0
- package/dist/data/storage/storagePath.d.ts +11 -0
- package/dist/data/storage/storagePath.js +25 -0
- package/dist/data/storage/storagePath.min.js +1 -0
- package/dist/data/storage/writeJson.d.ts +17 -0
- package/dist/data/storage/writeJson.js +37 -0
- package/dist/data/storage/writeJson.min.js +1 -0
- package/dist/data/storage/writeSet.d.ts +64 -0
- package/dist/data/storage/writeSet.js +306 -0
- package/dist/data/storage/writeSet.min.js +1 -0
- package/dist/data/utilities/compareAs.d.ts +1 -0
- package/dist/data/utilities/compareAs.js +2 -2
- package/dist/data/utilities/compareAs.min.js +1 -1
- package/dist/data/utilities/config.d.ts +37 -0
- package/dist/data/utilities/config.js +77 -5
- package/dist/data/utilities/config.min.js +1 -1
- package/dist/data/utilities/databaseLock.d.ts +7 -0
- package/dist/data/utilities/databaseLock.js +19 -4
- package/dist/data/utilities/databaseLock.min.js +1 -1
- package/dist/data/utilities/deregisterRecord.js +4 -10
- package/dist/data/utilities/deregisterRecord.min.js +1 -1
- package/dist/data/utilities/getConditionIndexedList.js +3 -4
- package/dist/data/utilities/getConditionIndexedList.min.js +1 -1
- package/dist/data/utilities/indexBuffer.d.ts +35 -0
- package/dist/data/utilities/indexBuffer.js +139 -0
- package/dist/data/utilities/indexBuffer.min.js +1 -0
- package/dist/data/utilities/indexHas.d.ts +13 -0
- package/dist/data/utilities/indexHas.js +48 -0
- package/dist/data/utilities/indexHas.min.js +1 -0
- package/dist/data/utilities/joinBases.d.ts +29 -0
- package/dist/data/utilities/joinBases.js +128 -0
- package/dist/data/utilities/joinBases.min.js +1 -0
- package/dist/data/utilities/joinKey.d.ts +17 -0
- package/dist/data/utilities/joinKey.js +31 -0
- package/dist/data/utilities/joinKey.min.js +1 -0
- package/dist/data/utilities/keyIndexFiles.d.ts +16 -0
- package/dist/data/utilities/keyIndexFiles.js +60 -0
- package/dist/data/utilities/keyIndexFiles.min.js +1 -0
- package/dist/data/utilities/knownFields.d.ts +26 -0
- package/dist/data/utilities/knownFields.js +128 -0
- package/dist/data/utilities/knownFields.min.js +1 -0
- package/dist/data/utilities/packedTable.d.ts +34 -0
- package/dist/data/utilities/packedTable.js +60 -0
- package/dist/data/utilities/packedTable.min.js +1 -0
- package/dist/data/utilities/parsers/findInsertValues.d.ts +3 -3
- package/dist/data/utilities/parsers/findInsertValues.js +28 -12
- package/dist/data/utilities/parsers/findInsertValues.min.js +1 -1
- package/dist/data/utilities/parsers/maskStrings.js +11 -2
- package/dist/data/utilities/parsers/maskStrings.min.js +1 -1
- package/dist/data/utilities/parsers/parseAlter.d.ts +33 -0
- package/dist/data/utilities/parsers/parseAlter.js +84 -0
- package/dist/data/utilities/parsers/parseAlter.min.js +1 -0
- package/dist/data/utilities/parsers/parseCreate.d.ts +14 -0
- package/dist/data/utilities/parsers/parseCreate.js +13 -5
- package/dist/data/utilities/parsers/parseCreate.min.js +1 -1
- package/dist/data/utilities/parsers/parseDatabaseStatement.d.ts +17 -0
- package/dist/data/utilities/parsers/parseDatabaseStatement.js +82 -0
- package/dist/data/utilities/parsers/parseDatabaseStatement.min.js +1 -0
- package/dist/data/utilities/parsers/parseQuery.d.ts +3 -0
- package/dist/data/utilities/parsers/parseQuery.js +24 -0
- package/dist/data/utilities/parsers/parseQuery.min.js +1 -1
- package/dist/data/utilities/parsers/startsQuery.js +1 -1
- package/dist/data/utilities/parsers/startsQuery.min.js +1 -1
- package/dist/data/utilities/recordExists.js +2 -7
- package/dist/data/utilities/recordExists.min.js +1 -1
- package/dist/data/utilities/registerRecord.js +4 -10
- package/dist/data/utilities/registerRecord.min.js +1 -1
- package/dist/data/utilities/removeFromIndex.js +4 -10
- package/dist/data/utilities/removeFromIndex.min.js +1 -1
- package/dist/data/utilities/retrieveFile.d.ts +5 -0
- package/dist/data/utilities/retrieveFile.js +7 -16
- package/dist/data/utilities/retrieveFile.min.js +1 -1
- package/dist/data/utilities/retrieveFiles.d.ts +15 -0
- package/dist/data/utilities/retrieveFiles.js +48 -0
- package/dist/data/utilities/retrieveFiles.min.js +1 -0
- package/dist/data/utilities/retrieveRecord.d.ts +6 -0
- package/dist/data/utilities/retrieveRecord.js +24 -1
- package/dist/data/utilities/retrieveRecord.min.js +1 -1
- package/dist/data/utilities/retrieveRecords.d.ts +22 -0
- package/dist/data/utilities/retrieveRecords.js +60 -10
- package/dist/data/utilities/retrieveRecords.min.js +1 -1
- package/dist/data/utilities/rowLookup.d.ts +38 -0
- package/dist/data/utilities/rowLookup.js +99 -0
- package/dist/data/utilities/rowLookup.min.js +1 -0
- package/dist/data/utilities/runQuery.js +28 -4
- package/dist/data/utilities/runQuery.min.js +1 -1
- package/dist/data/utilities/semiJoin.d.ts +27 -0
- package/dist/data/utilities/semiJoin.js +97 -0
- package/dist/data/utilities/semiJoin.min.js +1 -0
- package/dist/data/utilities/updateIndex.js +5 -14
- package/dist/data/utilities/updateIndex.min.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +24 -0
- package/dist/index.min.js +1 -1
- package/package.json +10 -4
- package/dist/data/utilities/getJoinIndexedList.d.ts +0 -3
- package/dist/data/utilities/getJoinIndexedList.js +0 -76
- package/dist/data/utilities/getJoinIndexedList.min.js +0 -1
- package/dist/data/utilities/getMatchingIndexes.d.ts +0 -2
- package/dist/data/utilities/getMatchingIndexes.js +0 -28
- package/dist/data/utilities/getMatchingIndexes.min.js +0 -1
- package/dist/data/utilities/matchIndexedJoins.d.ts +0 -2
- package/dist/data/utilities/matchIndexedJoins.js +0 -63
- package/dist/data/utilities/matchIndexedJoins.min.js +0 -1
- package/dist/data/utilities/restrictIndexedList.d.ts +0 -2
- package/dist/data/utilities/restrictIndexedList.js +0 -45
- package/dist/data/utilities/restrictIndexedList.min.js +0 -1
- package/dist/data/utilities/useJoinClause.d.ts +0 -6
- package/dist/data/utilities/useJoinClause.js +0 -57
- package/dist/data/utilities/useJoinClause.min.js +0 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.listFiles = void 0;
|
|
7
|
+
require("core-js/modules/esnext.iterator.constructor.js");
|
|
8
|
+
require("core-js/modules/esnext.iterator.map.js");
|
|
9
|
+
var _storagePath = require("./storagePath");
|
|
10
|
+
var _nodeFiles = require("./nodeFiles");
|
|
11
|
+
var _writeSet = require("./writeSet");
|
|
12
|
+
/**
|
|
13
|
+
* The files in `folder` and the folders inside it, as paths relative to the database (`base` is the folder's own).
|
|
14
|
+
* Walks one folder at a time with a plain readdir, so it needs no `recursive` option (which older Node versions
|
|
15
|
+
* ignore without an error, listing only the top folder) and no `Dirent.parentPath`.
|
|
16
|
+
* @param base - The folder's path inside the database, ending in `/` (empty for the database itself).
|
|
17
|
+
*/
|
|
18
|
+
const walk = async base => {
|
|
19
|
+
let entries;
|
|
20
|
+
try {
|
|
21
|
+
entries = await (0, _nodeFiles.nodeFiles)().readdir((0, _storagePath.storagePath)(base), {
|
|
22
|
+
withFileTypes: true
|
|
23
|
+
});
|
|
24
|
+
} catch (error) {
|
|
25
|
+
if (error?.code === 'ENOENT') {
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
const paths = [];
|
|
31
|
+
for (const entry of entries) {
|
|
32
|
+
if (entry.isDirectory()) {
|
|
33
|
+
paths.push(...(await walk(`${base}${entry.name}/`)));
|
|
34
|
+
} else if (entry.isFile()) {
|
|
35
|
+
paths.push(`${base}${entry.name}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return paths;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Every file in a folder of the database and the folders inside it, as paths inside the database (such as
|
|
42
|
+
* `users/1.json`), sorted. During a statement it counts what the statement has written or deleted (see withWriteSet).
|
|
43
|
+
* A folder that doesn't exist has no files. Node only.
|
|
44
|
+
* @param path - A path inside the database, such as `users`. Empty for the whole database.
|
|
45
|
+
*/
|
|
46
|
+
const listFiles = async (path = '') => {
|
|
47
|
+
const base = path ? `${path.replace(/\/+$/, '')}/` : '';
|
|
48
|
+
const onDisk = (await walk(base)).map(file => (0, _storagePath.storagePath)(file));
|
|
49
|
+
const root = (0, _storagePath.storagePath)();
|
|
50
|
+
return (0, _writeSet.pendingListing)((0, _storagePath.storagePath)(path), onDisk).map(location => location.slice(root.length)).sort();
|
|
51
|
+
};
|
|
52
|
+
exports.listFiles = listFiles;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.listFiles=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.map.js");var _storagePath=require("./storagePath"),_nodeFiles=require("./nodeFiles"),_writeSet=require("./writeSet");const walk=async e=>{let t;try{t=await(0,_nodeFiles.nodeFiles)().readdir((0,_storagePath.storagePath)(e),{withFileTypes:!0})}catch(e){if("ENOENT"===e?.code)return[];throw e}const r=[];for(const s of t)s.isDirectory()?r.push(...await walk(`${e}${s.name}/`)):s.isFile()&&r.push(`${e}${s.name}`);return r},listFiles=async(e="")=>{const t=e?`${e.replace(/\/+$/,"")}/`:"",r=(await walk(t)).map((e=>(0,_storagePath.storagePath)(e))),s=(0,_storagePath.storagePath)();return(0,_writeSet.pendingListing)((0,_storagePath.storagePath)(e),r).map((e=>e.slice(s.length))).sort()};exports.listFiles=listFiles;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create a folder of the database, and any missing folders above it (doing nothing if it already exists). During a
|
|
3
|
+
* statement it's created with the statement's other changes (see withWriteSet). Node only.
|
|
4
|
+
* @param path - A path inside the database, such as `users`. Empty for the database folder itself.
|
|
5
|
+
*/
|
|
6
|
+
export declare const makeDirectory: (path?: string) => Promise<void>;
|
|
7
|
+
//# sourceMappingURL=makeDirectory.d.ts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.makeDirectory = void 0;
|
|
7
|
+
var _storagePath = require("./storagePath");
|
|
8
|
+
var _nodeFiles = require("./nodeFiles");
|
|
9
|
+
var _writeSet = require("./writeSet");
|
|
10
|
+
/**
|
|
11
|
+
* Create a folder of the database, and any missing folders above it (doing nothing if it already exists). During a
|
|
12
|
+
* statement it's created with the statement's other changes (see withWriteSet). Node only.
|
|
13
|
+
* @param path - A path inside the database, such as `users`. Empty for the database folder itself.
|
|
14
|
+
*/
|
|
15
|
+
const makeDirectory = async (path = '') => {
|
|
16
|
+
const location = (0, _storagePath.storagePath)(path);
|
|
17
|
+
if ((0, _writeSet.stageMakeDirectory)(location)) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
await (0, _nodeFiles.nodeFiles)().mkdir(location, {
|
|
21
|
+
recursive: true
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
exports.makeDirectory = makeDirectory;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.makeDirectory=void 0;var _storagePath=require("./storagePath"),_nodeFiles=require("./nodeFiles"),_writeSet=require("./writeSet");const makeDirectory=async(e="")=>{const r=(0,_storagePath.storagePath)(e);(0,_writeSet.stageMakeDirectory)(r)||await(0,_nodeFiles.nodeFiles)().mkdir(r,{recursive:!0})};exports.makeDirectory=makeDirectory;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node's `fs/promises`, loaded when a storage function runs rather than when the module is imported, so the browser
|
|
3
|
+
* bundle (which leaves `fs` out) can still import the storage module.
|
|
4
|
+
*/
|
|
5
|
+
export declare const nodeFiles: () => any;
|
|
6
|
+
//# sourceMappingURL=nodeFiles.d.ts.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.nodeFiles = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Node's `fs/promises`, loaded when a storage function runs rather than when the module is imported, so the browser
|
|
9
|
+
* bundle (which leaves `fs` out) can still import the storage module.
|
|
10
|
+
*/
|
|
11
|
+
const nodeFiles = () => require('fs/promises');
|
|
12
|
+
exports.nodeFiles = nodeFiles;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.nodeFiles=void 0;const nodeFiles=()=>require("fs/promises");exports.nodeFiles=nodeFiles;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run `task` with a read cache for the configured database: while it runs, each file is read from storage once and
|
|
3
|
+
* later reads of it are answered from memory, so a join no longer reads the joined record's files again for every row.
|
|
4
|
+
* Writes and deletes made during the task update the cache (see cacheWrite, cacheRemove), so a query reads its own
|
|
5
|
+
* writes. Outside any task nothing is cached and every read goes to storage, as before.
|
|
6
|
+
*
|
|
7
|
+
* The cache holds text, not parsed objects: every read parses its own copy, so a caller changing what it read (a join
|
|
8
|
+
* attaches rows to the rows it read) never changes what the next reader gets.
|
|
9
|
+
*
|
|
10
|
+
* withDatabaseLock runs every public call (query, create, drop, describe) inside one, so the cache lasts one call. In
|
|
11
|
+
* Node calls on one database never overlap (the lock queues them). In a browser they can, and a read can't tell which
|
|
12
|
+
* call it belongs to, so each call that starts empties the cache: calls still running carry on (only reading their
|
|
13
|
+
* files again), and nothing is older than the newest call, however long calls keep overlapping.
|
|
14
|
+
* @param task
|
|
15
|
+
*/
|
|
16
|
+
export declare const withReadCache: <T>(task: () => Promise<T>) => Promise<T>;
|
|
17
|
+
/**
|
|
18
|
+
* The text of the file at `location`: from the cache when a call is running and the file was read (or written) during
|
|
19
|
+
* it, otherwise from `read`, kept for the rest of the call. A failed read isn't kept, so it fails (or succeeds) afresh
|
|
20
|
+
* the next time.
|
|
21
|
+
* @param location - The file's full location (see storagePath).
|
|
22
|
+
* @param read - Reads the file's text from storage.
|
|
23
|
+
*/
|
|
24
|
+
export declare const cachedRead: (location: string, read: () => Promise<string>) => Promise<string>;
|
|
25
|
+
/**
|
|
26
|
+
* Keep the text just written to `location`, so the rest of the call reads it without going back to storage.
|
|
27
|
+
* @param location - The file's full location (see storagePath).
|
|
28
|
+
* @param text
|
|
29
|
+
*/
|
|
30
|
+
export declare const cacheWrite: (location: string, text: string) => void;
|
|
31
|
+
/**
|
|
32
|
+
* Forget a removed file, or (with `folder`) everything under a removed folder.
|
|
33
|
+
* @param location - The full location (see storagePath) of the file or folder.
|
|
34
|
+
* @param folder - Whether `location` is a folder.
|
|
35
|
+
*/
|
|
36
|
+
export declare const cacheRemove: (location: string, folder?: boolean) => void;
|
|
37
|
+
//# sourceMappingURL=readCache.d.ts.map
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.withReadCache = exports.cachedRead = exports.cacheWrite = exports.cacheRemove = void 0;
|
|
7
|
+
require("core-js/modules/esnext.map.delete-all.js");
|
|
8
|
+
require("core-js/modules/esnext.map.every.js");
|
|
9
|
+
require("core-js/modules/esnext.map.filter.js");
|
|
10
|
+
require("core-js/modules/esnext.map.find.js");
|
|
11
|
+
require("core-js/modules/esnext.map.find-key.js");
|
|
12
|
+
require("core-js/modules/esnext.map.includes.js");
|
|
13
|
+
require("core-js/modules/esnext.map.key-of.js");
|
|
14
|
+
require("core-js/modules/esnext.map.map-keys.js");
|
|
15
|
+
require("core-js/modules/esnext.map.map-values.js");
|
|
16
|
+
require("core-js/modules/esnext.map.merge.js");
|
|
17
|
+
require("core-js/modules/esnext.map.reduce.js");
|
|
18
|
+
require("core-js/modules/esnext.map.some.js");
|
|
19
|
+
require("core-js/modules/esnext.map.update.js");
|
|
20
|
+
var _storagePath = require("./storagePath");
|
|
21
|
+
const scopes = new Map();
|
|
22
|
+
/**
|
|
23
|
+
* The scope of the database configured now (by its location, see storagePath), if a call on it is running.
|
|
24
|
+
*/
|
|
25
|
+
const currentScope = () => scopes.get((0, _storagePath.storagePath)());
|
|
26
|
+
/**
|
|
27
|
+
* Run `task` with a read cache for the configured database: while it runs, each file is read from storage once and
|
|
28
|
+
* later reads of it are answered from memory, so a join no longer reads the joined record's files again for every row.
|
|
29
|
+
* Writes and deletes made during the task update the cache (see cacheWrite, cacheRemove), so a query reads its own
|
|
30
|
+
* writes. Outside any task nothing is cached and every read goes to storage, as before.
|
|
31
|
+
*
|
|
32
|
+
* The cache holds text, not parsed objects: every read parses its own copy, so a caller changing what it read (a join
|
|
33
|
+
* attaches rows to the rows it read) never changes what the next reader gets.
|
|
34
|
+
*
|
|
35
|
+
* withDatabaseLock runs every public call (query, create, drop, describe) inside one, so the cache lasts one call. In
|
|
36
|
+
* Node calls on one database never overlap (the lock queues them). In a browser they can, and a read can't tell which
|
|
37
|
+
* call it belongs to, so each call that starts empties the cache: calls still running carry on (only reading their
|
|
38
|
+
* files again), and nothing is older than the newest call, however long calls keep overlapping.
|
|
39
|
+
* @param task
|
|
40
|
+
*/
|
|
41
|
+
const withReadCache = async task => {
|
|
42
|
+
const database = (0, _storagePath.storagePath)();
|
|
43
|
+
const scope = scopes.get(database) || {
|
|
44
|
+
calls: 0,
|
|
45
|
+
files: new Map()
|
|
46
|
+
};
|
|
47
|
+
scopes.set(database, scope);
|
|
48
|
+
scope.calls++;
|
|
49
|
+
if (scope.calls > 1) {
|
|
50
|
+
scope.files = new Map();
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
return await task();
|
|
54
|
+
} finally {
|
|
55
|
+
scope.calls--;
|
|
56
|
+
if (!scope.calls && scopes.get(database) === scope) {
|
|
57
|
+
scopes.delete(database);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* The text of the file at `location`: from the cache when a call is running and the file was read (or written) during
|
|
63
|
+
* it, otherwise from `read`, kept for the rest of the call. A failed read isn't kept, so it fails (or succeeds) afresh
|
|
64
|
+
* the next time.
|
|
65
|
+
* @param location - The file's full location (see storagePath).
|
|
66
|
+
* @param read - Reads the file's text from storage.
|
|
67
|
+
*/
|
|
68
|
+
exports.withReadCache = withReadCache;
|
|
69
|
+
const cachedRead = (location, read) => {
|
|
70
|
+
const scope = currentScope();
|
|
71
|
+
if (!scope) {
|
|
72
|
+
return read();
|
|
73
|
+
}
|
|
74
|
+
const cached = scope.files.get(location);
|
|
75
|
+
if (cached) {
|
|
76
|
+
return cached;
|
|
77
|
+
}
|
|
78
|
+
const reading = read();
|
|
79
|
+
scope.files.set(location, reading);
|
|
80
|
+
reading.catch(() => {
|
|
81
|
+
if (scope.files.get(location) === reading) {
|
|
82
|
+
scope.files.delete(location);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
return reading;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Keep the text just written to `location`, so the rest of the call reads it without going back to storage.
|
|
89
|
+
* @param location - The file's full location (see storagePath).
|
|
90
|
+
* @param text
|
|
91
|
+
*/
|
|
92
|
+
exports.cachedRead = cachedRead;
|
|
93
|
+
const cacheWrite = (location, text) => {
|
|
94
|
+
currentScope()?.files.set(location, Promise.resolve(text));
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Forget a removed file, or (with `folder`) everything under a removed folder.
|
|
98
|
+
* @param location - The full location (see storagePath) of the file or folder.
|
|
99
|
+
* @param folder - Whether `location` is a folder.
|
|
100
|
+
*/
|
|
101
|
+
exports.cacheWrite = cacheWrite;
|
|
102
|
+
const cacheRemove = (location, folder = false) => {
|
|
103
|
+
const scope = currentScope();
|
|
104
|
+
if (!scope) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
scope.files.delete(location);
|
|
108
|
+
if (folder) {
|
|
109
|
+
const prefix = location.endsWith('/') ? location : `${location}/`;
|
|
110
|
+
for (const cachedLocation of [...scope.files.keys()]) {
|
|
111
|
+
if (cachedLocation.startsWith(prefix)) {
|
|
112
|
+
scope.files.delete(cachedLocation);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
exports.cacheRemove = cacheRemove;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.withReadCache=exports.cachedRead=exports.cacheWrite=exports.cacheRemove=void 0,require("core-js/modules/esnext.map.delete-all.js"),require("core-js/modules/esnext.map.every.js"),require("core-js/modules/esnext.map.filter.js"),require("core-js/modules/esnext.map.find.js"),require("core-js/modules/esnext.map.find-key.js"),require("core-js/modules/esnext.map.includes.js"),require("core-js/modules/esnext.map.key-of.js"),require("core-js/modules/esnext.map.map-keys.js"),require("core-js/modules/esnext.map.map-values.js"),require("core-js/modules/esnext.map.merge.js"),require("core-js/modules/esnext.map.reduce.js"),require("core-js/modules/esnext.map.some.js"),require("core-js/modules/esnext.map.update.js");var _storagePath=require("./storagePath");const scopes=new Map,currentScope=()=>scopes.get((0,_storagePath.storagePath)()),withReadCache=async e=>{const s=(0,_storagePath.storagePath)(),r=scopes.get(s)||{calls:0,files:new Map};scopes.set(s,r),r.calls++,r.calls>1&&(r.files=new Map);try{return await e()}finally{r.calls--,r.calls||scopes.get(s)!==r||scopes.delete(s)}};exports.withReadCache=withReadCache;const cachedRead=(e,s)=>{const r=currentScope();if(!r)return s();const t=r.files.get(e);if(t)return t;const c=s();return r.files.set(e,c),c.catch((()=>{r.files.get(e)===c&&r.files.delete(e)})),c};exports.cachedRead=cachedRead;const cacheWrite=(e,s)=>{currentScope()?.files.set(e,Promise.resolve(s))};exports.cacheWrite=cacheWrite;const cacheRemove=(e,s=!1)=>{const r=currentScope();if(r&&(r.files.delete(e),s)){const s=e.endsWith("/")?e:`${e}/`;for(const e of[...r.files.keys()])e.startsWith(s)&&r.files.delete(e)}};exports.cacheRemove=cacheRemove;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read one file of the database as text, from wherever readJson would read it (the statement's write set, the read
|
|
3
|
+
* cache, then storage).
|
|
4
|
+
* @param path - A path inside the database, such as `users.json`.
|
|
5
|
+
* @throws {Error} When the file can't be read.
|
|
6
|
+
*/
|
|
7
|
+
export declare const readText: (path: string) => Promise<string>;
|
|
8
|
+
/**
|
|
9
|
+
* Read and parse one JSON file of the database: from disk in Node, over `fetch()` in a browser (see storagePath for
|
|
10
|
+
* where it's looked for). During a statement, a file it has written or deleted is answered from its write set (see
|
|
11
|
+
* withWriteSet); otherwise, during a call, a file already read is answered from the read cache (see withReadCache).
|
|
12
|
+
* @param path - A path inside the database, such as `users.json`.
|
|
13
|
+
* @throws {Error} When the file can't be read or isn't valid JSON (the error from the file system, fetch or JSON.parse).
|
|
14
|
+
*/
|
|
15
|
+
export declare const readJson: (path: string) => Promise<any>;
|
|
16
|
+
//# sourceMappingURL=readJson.d.ts.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
require("core-js/modules/esnext.weak-map.delete-all.js");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.readText = exports.readJson = void 0;
|
|
8
|
+
var jsEnv = _interopRequireWildcard(require("browser-or-node"));
|
|
9
|
+
var _storagePath = require("./storagePath");
|
|
10
|
+
var _nodeFiles = require("./nodeFiles");
|
|
11
|
+
var _readCache = require("./readCache");
|
|
12
|
+
var _writeSet = require("./writeSet");
|
|
13
|
+
var e;
|
|
14
|
+
function _interopRequireWildcard(t, r) { if (!r && t && t.__esModule) return t; var n, a, o = Object.defineProperty, f = { __proto__: null, default: t }; if (Object(t) !== t) return f; if (e || "function" != typeof WeakMap || (e = new WeakMap()), e) { if (e.has(t)) return e.get(t); e.set(t, f); } for (a in t) "default" !== a && {}.hasOwnProperty.call(t, a) && ((n = o && Object.getOwnPropertyDescriptor(t, a)) && (n.get || n.set) ? o(f, a, n) : f[a] = t[a]); return f; }
|
|
15
|
+
/**
|
|
16
|
+
* Read one file of the database as text, from wherever readJson would read it (the statement's write set, the read
|
|
17
|
+
* cache, then storage).
|
|
18
|
+
* @param path - A path inside the database, such as `users.json`.
|
|
19
|
+
* @throws {Error} When the file can't be read.
|
|
20
|
+
*/
|
|
21
|
+
const readText = async path => {
|
|
22
|
+
const location = (0, _storagePath.storagePath)(path);
|
|
23
|
+
const pending = (0, _writeSet.pendingFile)(location);
|
|
24
|
+
if (pending === null) {
|
|
25
|
+
throw new Error(`ENOENT: no such file or directory, open '${location}' (deleted by this statement)`);
|
|
26
|
+
}
|
|
27
|
+
return typeof pending === 'string' ? pending : (0, _readCache.cachedRead)(location, () => jsEnv.isNode ? (0, _nodeFiles.nodeFiles)().readFile(location, 'utf8') : fetch(location).then(response => response.text()));
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Read and parse one JSON file of the database: from disk in Node, over `fetch()` in a browser (see storagePath for
|
|
31
|
+
* where it's looked for). During a statement, a file it has written or deleted is answered from its write set (see
|
|
32
|
+
* withWriteSet); otherwise, during a call, a file already read is answered from the read cache (see withReadCache).
|
|
33
|
+
* @param path - A path inside the database, such as `users.json`.
|
|
34
|
+
* @throws {Error} When the file can't be read or isn't valid JSON (the error from the file system, fetch or JSON.parse).
|
|
35
|
+
*/
|
|
36
|
+
exports.readText = readText;
|
|
37
|
+
const readJson = async path => JSON.parse(await readText(path));
|
|
38
|
+
exports.readJson = readJson;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";require("core-js/modules/esnext.weak-map.delete-all.js"),Object.defineProperty(exports,"__esModule",{value:!0}),exports.readText=exports.readJson=void 0;var e,jsEnv=_interopRequireWildcard(require("browser-or-node")),_storagePath=require("./storagePath"),_nodeFiles=require("./nodeFiles"),_readCache=require("./readCache"),_writeSet=require("./writeSet");function _interopRequireWildcard(r,t){if(!t&&r&&r.__esModule)return r;var a,o,n=Object.defineProperty,s={__proto__:null,default:r};if(Object(r)!==r)return s;if(e||"function"!=typeof WeakMap||(e=new WeakMap),e){if(e.has(r))return e.get(r);e.set(r,s)}for(o in r)"default"!==o&&{}.hasOwnProperty.call(r,o)&&((a=n&&Object.getOwnPropertyDescriptor(r,o))&&(a.get||a.set)?n(s,o,a):s[o]=r[o]);return s}const readText=async e=>{const r=(0,_storagePath.storagePath)(e),t=(0,_writeSet.pendingFile)(r);if(null===t)throw new Error(`ENOENT: no such file or directory, open '${r}' (deleted by this statement)`);return"string"==typeof t?t:(0,_readCache.cachedRead)(r,(()=>jsEnv.isNode?(0,_nodeFiles.nodeFiles)().readFile(r,"utf8"):fetch(r).then((e=>e.text()))))};exports.readText=readText;const readJson=async e=>JSON.parse(await readText(e));exports.readJson=readJson;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delete a folder of the database and everything in it; a folder that doesn't exist is left alone. During a statement
|
|
3
|
+
* it's removed with the statement's other changes (see withWriteSet), and reads in the statement already find
|
|
4
|
+
* everything in it gone. Node only.
|
|
5
|
+
* @param path - A path inside the database, such as `__indexes/users`.
|
|
6
|
+
*/
|
|
7
|
+
export declare const removeDirectory: (path: string) => Promise<void>;
|
|
8
|
+
//# sourceMappingURL=removeDirectory.d.ts.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.removeDirectory = void 0;
|
|
7
|
+
var _storagePath = require("./storagePath");
|
|
8
|
+
var _nodeFiles = require("./nodeFiles");
|
|
9
|
+
var _readCache = require("./readCache");
|
|
10
|
+
var _writeSet = require("./writeSet");
|
|
11
|
+
/**
|
|
12
|
+
* Delete a folder of the database and everything in it; a folder that doesn't exist is left alone. During a statement
|
|
13
|
+
* it's removed with the statement's other changes (see withWriteSet), and reads in the statement already find
|
|
14
|
+
* everything in it gone. Node only.
|
|
15
|
+
* @param path - A path inside the database, such as `__indexes/users`.
|
|
16
|
+
*/
|
|
17
|
+
const removeDirectory = async path => {
|
|
18
|
+
const location = (0, _storagePath.storagePath)(path);
|
|
19
|
+
if ((0, _writeSet.stageRemoveDirectory)(location)) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
// Forgotten before and after: a read that starts while rm runs would otherwise keep a removed file's old text
|
|
23
|
+
(0, _readCache.cacheRemove)(location, true);
|
|
24
|
+
await (0, _nodeFiles.nodeFiles)().rm(location, {
|
|
25
|
+
recursive: true,
|
|
26
|
+
force: true
|
|
27
|
+
});
|
|
28
|
+
(0, _readCache.cacheRemove)(location, true);
|
|
29
|
+
};
|
|
30
|
+
exports.removeDirectory = removeDirectory;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.removeDirectory=void 0;var _storagePath=require("./storagePath"),_nodeFiles=require("./nodeFiles"),_readCache=require("./readCache"),_writeSet=require("./writeSet");const removeDirectory=async e=>{const r=(0,_storagePath.storagePath)(e);(0,_writeSet.stageRemoveDirectory)(r)||((0,_readCache.cacheRemove)(r,!0),await(0,_nodeFiles.nodeFiles)().rm(r,{recursive:!0,force:!0}),(0,_readCache.cacheRemove)(r,!0))};exports.removeDirectory=removeDirectory;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delete one file of the database. During a statement the delete waits in its write set until the statement succeeds
|
|
3
|
+
* (see withWriteSet), and reads in the statement already find the file gone. Node only.
|
|
4
|
+
* @param path - A path inside the database, such as `users/1.json`.
|
|
5
|
+
* @throws {Error} When the file doesn't exist.
|
|
6
|
+
*/
|
|
7
|
+
export declare const removeFile: (path: string) => Promise<void>;
|
|
8
|
+
//# sourceMappingURL=removeFile.d.ts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.removeFile = void 0;
|
|
7
|
+
var _storagePath = require("./storagePath");
|
|
8
|
+
var _nodeFiles = require("./nodeFiles");
|
|
9
|
+
var _readCache = require("./readCache");
|
|
10
|
+
var _writeSet = require("./writeSet");
|
|
11
|
+
/**
|
|
12
|
+
* Delete one file of the database. During a statement the delete waits in its write set until the statement succeeds
|
|
13
|
+
* (see withWriteSet), and reads in the statement already find the file gone. Node only.
|
|
14
|
+
* @param path - A path inside the database, such as `users/1.json`.
|
|
15
|
+
* @throws {Error} When the file doesn't exist.
|
|
16
|
+
*/
|
|
17
|
+
const removeFile = async path => {
|
|
18
|
+
const location = (0, _storagePath.storagePath)(path);
|
|
19
|
+
const pending = (0, _writeSet.pendingFile)(location);
|
|
20
|
+
if (pending === null || pending === undefined && !require('fs').existsSync(location)) {
|
|
21
|
+
throw new Error(`ENOENT: no such file or directory, rm '${location}'`);
|
|
22
|
+
}
|
|
23
|
+
if ((0, _writeSet.stageRemove)(location)) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
// Forgotten before and after: a read that starts while rm runs would otherwise keep the file's old text
|
|
27
|
+
(0, _readCache.cacheRemove)(location);
|
|
28
|
+
await (0, _nodeFiles.nodeFiles)().rm(location);
|
|
29
|
+
(0, _readCache.cacheRemove)(location);
|
|
30
|
+
};
|
|
31
|
+
exports.removeFile = removeFile;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.removeFile=void 0;var _storagePath=require("./storagePath"),_nodeFiles=require("./nodeFiles"),_readCache=require("./readCache"),_writeSet=require("./writeSet");const removeFile=async e=>{const r=(0,_storagePath.storagePath)(e),t=(0,_writeSet.pendingFile)(r);if(null===t||void 0===t&&!require("fs").existsSync(r))throw new Error(`ENOENT: no such file or directory, rm '${r}'`);(0,_writeSet.stageRemove)(r)||((0,_readCache.cacheRemove)(r),await(0,_nodeFiles.nodeFiles)().rm(r),(0,_readCache.cacheRemove)(r))};exports.removeFile=removeFile;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turn a path inside the database (such as `users.json` or `__indexes/users/name.json`) into the location the files
|
|
3
|
+
* backend uses: the configured databasePath in front of it, and in a browser also the relativePath (the URL prefix the
|
|
4
|
+
* database is served from).
|
|
5
|
+
*
|
|
6
|
+
* Every other part of json-fs-query names files by their path inside the database only; this is the one place that
|
|
7
|
+
* knows where the database is.
|
|
8
|
+
* @param path - A path inside the database, without a leading slash. Empty for the database folder itself.
|
|
9
|
+
*/
|
|
10
|
+
export declare const storagePath: (path?: string) => string;
|
|
11
|
+
//# sourceMappingURL=storagePath.d.ts.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
require("core-js/modules/esnext.weak-map.delete-all.js");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.storagePath = void 0;
|
|
8
|
+
var jsEnv = _interopRequireWildcard(require("browser-or-node"));
|
|
9
|
+
var _config = require("../utilities/config");
|
|
10
|
+
var e;
|
|
11
|
+
function _interopRequireWildcard(t, r) { if (!r && t && t.__esModule) return t; var n, a, o = Object.defineProperty, f = { __proto__: null, default: t }; if (Object(t) !== t) return f; if (e || "function" != typeof WeakMap || (e = new WeakMap()), e) { if (e.has(t)) return e.get(t); e.set(t, f); } for (a in t) "default" !== a && {}.hasOwnProperty.call(t, a) && ((n = o && Object.getOwnPropertyDescriptor(t, a)) && (n.get || n.set) ? o(f, a, n) : f[a] = t[a]); return f; }
|
|
12
|
+
/**
|
|
13
|
+
* Turn a path inside the database (such as `users.json` or `__indexes/users/name.json`) into the location the files
|
|
14
|
+
* backend uses: the configured databasePath in front of it, and in a browser also the relativePath (the URL prefix the
|
|
15
|
+
* database is served from).
|
|
16
|
+
*
|
|
17
|
+
* Every other part of json-fs-query names files by their path inside the database only; this is the one place that
|
|
18
|
+
* knows where the database is.
|
|
19
|
+
* @param path - A path inside the database, without a leading slash. Empty for the database folder itself.
|
|
20
|
+
*/
|
|
21
|
+
const storagePath = (path = '') => {
|
|
22
|
+
const relativePath = jsEnv.isBrowser ? (0, _config.getSetting)('relativePath', '') : '';
|
|
23
|
+
return `${relativePath}${(0, _config.activeDatabasePath)()}${path}`;
|
|
24
|
+
};
|
|
25
|
+
exports.storagePath = storagePath;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";require("core-js/modules/esnext.weak-map.delete-all.js"),Object.defineProperty(exports,"__esModule",{value:!0}),exports.storagePath=void 0;var e,jsEnv=_interopRequireWildcard(require("browser-or-node")),_config=require("../utilities/config");function _interopRequireWildcard(t,r){if(!r&&t&&t.__esModule)return t;var o,a,i=Object.defineProperty,s={__proto__:null,default:t};if(Object(t)!==t)return s;if(e||"function"!=typeof WeakMap||(e=new WeakMap),e){if(e.has(t))return e.get(t);e.set(t,s)}for(a in t)"default"!==a&&{}.hasOwnProperty.call(t,a)&&((o=i&&Object.getOwnPropertyDescriptor(t,a))&&(o.get||o.set)?i(s,a,o):s[a]=t[a]);return s}const storagePath=(e="")=>`${jsEnv.isBrowser?(0,_config.getSetting)("relativePath",""):""}${(0,_config.activeDatabasePath)()}${e}`;exports.storagePath=storagePath;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The text a file of the database holds for `content`: compact JSON, or indented by 2 spaces for `pretty`.
|
|
3
|
+
* @param content - Anything JSON.stringify accepts.
|
|
4
|
+
* @param format - Defaults to the configured format (see configure).
|
|
5
|
+
*/
|
|
6
|
+
export declare const jsonText: (content: any, format?: "compact" | "pretty") => string;
|
|
7
|
+
/**
|
|
8
|
+
* Write `content` to one file of the database as JSON in the configured format (see jsonText), replacing the file if it
|
|
9
|
+
* exists. Its folder must already exist (see makeDirectory). The file is replaced whole or not at all (see
|
|
10
|
+
* writeAtomically). During a statement the write waits in its write set until the statement succeeds (see
|
|
11
|
+
* withWriteSet). Node only.
|
|
12
|
+
* @param path - A path inside the database, such as `users.json`.
|
|
13
|
+
* @param content - Anything JSON.stringify accepts.
|
|
14
|
+
* @param format - Defaults to the configured format (see configure).
|
|
15
|
+
*/
|
|
16
|
+
export declare const writeJson: (path: string, content: any, format?: "compact" | "pretty") => Promise<void>;
|
|
17
|
+
//# sourceMappingURL=writeJson.d.ts.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.writeJson = exports.jsonText = void 0;
|
|
7
|
+
require("core-js/modules/es.json.stringify.js");
|
|
8
|
+
var _storagePath = require("./storagePath");
|
|
9
|
+
var _readCache = require("./readCache");
|
|
10
|
+
var _writeSet = require("./writeSet");
|
|
11
|
+
var _config = require("../utilities/config");
|
|
12
|
+
/**
|
|
13
|
+
* The text a file of the database holds for `content`: compact JSON, or indented by 2 spaces for `pretty`.
|
|
14
|
+
* @param content - Anything JSON.stringify accepts.
|
|
15
|
+
* @param format - Defaults to the configured format (see configure).
|
|
16
|
+
*/
|
|
17
|
+
const jsonText = (content, format = (0, _config.getSetting)('format', 'compact')) => format === 'pretty' ? JSON.stringify(content, null, 2) : JSON.stringify(content);
|
|
18
|
+
/**
|
|
19
|
+
* Write `content` to one file of the database as JSON in the configured format (see jsonText), replacing the file if it
|
|
20
|
+
* exists. Its folder must already exist (see makeDirectory). The file is replaced whole or not at all (see
|
|
21
|
+
* writeAtomically). During a statement the write waits in its write set until the statement succeeds (see
|
|
22
|
+
* withWriteSet). Node only.
|
|
23
|
+
* @param path - A path inside the database, such as `users.json`.
|
|
24
|
+
* @param content - Anything JSON.stringify accepts.
|
|
25
|
+
* @param format - Defaults to the configured format (see configure).
|
|
26
|
+
*/
|
|
27
|
+
exports.jsonText = jsonText;
|
|
28
|
+
const writeJson = async (path, content, format) => {
|
|
29
|
+
const location = (0, _storagePath.storagePath)(path);
|
|
30
|
+
const text = jsonText(content, format);
|
|
31
|
+
if ((0, _writeSet.stageWrite)(location, text)) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
await (0, _writeSet.writeAtomically)(location, text);
|
|
35
|
+
(0, _readCache.cacheWrite)(location, text);
|
|
36
|
+
};
|
|
37
|
+
exports.writeJson = writeJson;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.writeJson=exports.jsonText=void 0,require("core-js/modules/es.json.stringify.js");var _storagePath=require("./storagePath"),_readCache=require("./readCache"),_writeSet=require("./writeSet"),_config=require("../utilities/config");const jsonText=(e,t=(0,_config.getSetting)("format","compact"))=>"pretty"===t?JSON.stringify(e,null,2):JSON.stringify(e);exports.jsonText=jsonText;const writeJson=async(e,t,r)=>{const s=(0,_storagePath.storagePath)(e),i=jsonText(t,r);(0,_writeSet.stageWrite)(s,i)||(await(0,_writeSet.writeAtomically)(s,i),(0,_readCache.cacheWrite)(s,i))};exports.writeJson=writeJson;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Write `text` to `location` so that the file is always either its old or its new content, never half of one: the
|
|
3
|
+
* text goes to a temporary file next to it, which then replaces it (a rename is atomic within one folder). That holds
|
|
4
|
+
* when the process stops part way (a crash, a kill); there's no fsync, so after a power cut the file system may still
|
|
5
|
+
* lose a recent write. When the write or rename fails, the temporary file is removed and the original error thrown.
|
|
6
|
+
* @param location
|
|
7
|
+
* @param text
|
|
8
|
+
*/
|
|
9
|
+
export declare const writeAtomically: (location: string, text: string) => Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* Run one statement's `task` with a write set for the configured database: its writes and deletes are collected in
|
|
12
|
+
* memory, and reads during the task see them (see pendingFile). When the task finishes, everything it changed is put in
|
|
13
|
+
* storage at once, each file written once however many times the task changed it. When it throws, nothing it changed
|
|
14
|
+
* reaches storage: a multi-row insert or update whose third row fails leaves the first two unwritten too.
|
|
15
|
+
*
|
|
16
|
+
* A task inside another (a public call made from inside a statement) joins the outer write set. Node only: in a
|
|
17
|
+
* browser nothing can be written, so the task just runs.
|
|
18
|
+
* @param task
|
|
19
|
+
*/
|
|
20
|
+
export declare const withWriteSet: <T>(task: () => Promise<T>) => Promise<T>;
|
|
21
|
+
/**
|
|
22
|
+
* What the running statement has done to the file at `location`: its pending text, `null` if the statement deleted it
|
|
23
|
+
* (or a folder it was in), or `undefined` when the statement hasn't touched it (or no statement is running).
|
|
24
|
+
* @param location - The file's full location (see storagePath).
|
|
25
|
+
*/
|
|
26
|
+
export declare const pendingFile: (location: string) => string | null | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Whether the file or folder at `location` exists as far as the running statement knows: true for a file it wrote, a
|
|
29
|
+
* folder it made, or a folder holding something it wrote or made; false for a file it deleted or anything in a folder
|
|
30
|
+
* it removed; `undefined` when the statement hasn't touched it (or no statement is running), so storage decides.
|
|
31
|
+
* @param location - The full location (see storagePath).
|
|
32
|
+
*/
|
|
33
|
+
export declare const pendingExists: (location: string) => boolean | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* The files under `folder` as the running statement sees them: `onDisk` (full locations) without what it deleted or
|
|
36
|
+
* removed, plus what it wrote there. `onDisk` as it is when no statement is running.
|
|
37
|
+
* @param folder - The folder's full location (see storagePath).
|
|
38
|
+
* @param onDisk - The full locations of the files under it in storage.
|
|
39
|
+
*/
|
|
40
|
+
export declare const pendingListing: (folder: string, onDisk: string[]) => string[];
|
|
41
|
+
/**
|
|
42
|
+
* Keep `text` as the new content of `location` in the running statement's write set. False when no statement is
|
|
43
|
+
* running, so the caller writes to storage itself.
|
|
44
|
+
* @param location
|
|
45
|
+
* @param text
|
|
46
|
+
*/
|
|
47
|
+
export declare const stageWrite: (location: string, text: string) => boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Mark `location` deleted in the running statement's write set. False when no statement is running.
|
|
50
|
+
* @param location
|
|
51
|
+
*/
|
|
52
|
+
export declare const stageRemove: (location: string) => boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Note a folder to create in the running statement's write set. False when no statement is running.
|
|
55
|
+
* @param location
|
|
56
|
+
*/
|
|
57
|
+
export declare const stageMakeDirectory: (location: string) => boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Mark a folder and everything in it removed in the running statement's write set: what the statement wrote or
|
|
60
|
+
* created inside it so far is dropped with it. False when no statement is running.
|
|
61
|
+
* @param location
|
|
62
|
+
*/
|
|
63
|
+
export declare const stageRemoveDirectory: (location: string) => boolean;
|
|
64
|
+
//# sourceMappingURL=writeSet.d.ts.map
|