json-fs-query 1.0.5 → 1.0.6
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/browser/jsonFsQuery.js +2 -2
- package/browser/jsonFsQuery.min.js +1 -1
- package/dist/data/introspect/create.js +46 -46
- package/dist/data/introspect/definitions/field.js +35 -35
- package/dist/data/introspect/definitions/key.js +52 -52
- package/dist/data/introspect/definitions/keyReference.js +19 -19
- package/dist/data/introspect/definitions/record.js +31 -31
- package/dist/data/introspect/describe.js +14 -14
- package/dist/data/introspect/drop.js +36 -36
- package/dist/data/introspect/index.js +29 -29
- package/dist/data/introspect/policies/foreignKeyExists.js +24 -24
- package/dist/data/introspect/policies/hasDependents.js +51 -51
- package/dist/data/introspect/policies/keyGenerate.js +16 -16
- package/dist/data/introspect/policies/keyUnique.js +30 -30
- package/dist/data/introspect/policies/typeCheck.js +56 -56
- package/dist/data/introspect/policies/typeEnum.js +13 -13
- package/dist/data/introspect/policies/useDefault.js +12 -12
- package/dist/data/queries/deleteEntity.js +99 -99
- package/dist/data/queries/groupBy.js +21 -21
- package/dist/data/queries/insertEntity.js +116 -116
- package/dist/data/queries/joinEntity.js +31 -31
- package/dist/data/queries/limitOffset.js +20 -20
- package/dist/data/queries/mergeJoins.js +18 -18
- package/dist/data/queries/parser.js +29 -29
- package/dist/data/queries/query.js +17 -17
- package/dist/data/queries/readEntity.js +13 -13
- package/dist/data/queries/selectFields.js +35 -35
- package/dist/data/queries/sortBy.js +24 -24
- package/dist/data/queries/updateEntity.js +189 -189
- package/dist/data/queries/where.js +55 -55
- package/dist/data/utilities/computeKeyValue.js +25 -25
- package/dist/data/utilities/config.js +44 -44
- package/dist/data/utilities/deregisterRecord.js +33 -33
- package/dist/data/utilities/getConditionIndexedList.js +46 -46
- package/dist/data/utilities/getJoinIndexedList.js +75 -75
- package/dist/data/utilities/getMatchingIndexes.js +27 -27
- package/dist/data/utilities/matchIndexedJoins.js +60 -60
- package/dist/data/utilities/mergeJoin.js +43 -43
- package/dist/data/utilities/parsers/findCommand.js +24 -24
- package/dist/data/utilities/parsers/findConditions.js +27 -27
- package/dist/data/utilities/parsers/findGroupBy.js +21 -21
- package/dist/data/utilities/parsers/findInsertValues.js +33 -33
- package/dist/data/utilities/parsers/findJoinClauses.js +26 -26
- package/dist/data/utilities/parsers/findJoinEntity.js +21 -21
- package/dist/data/utilities/parsers/findLimit.js +21 -21
- package/dist/data/utilities/parsers/findMergeJoins.js +25 -25
- package/dist/data/utilities/parsers/findOffset.js +21 -21
- package/dist/data/utilities/parsers/findSelects.js +29 -29
- package/dist/data/utilities/parsers/findSortClauses.js +29 -29
- package/dist/data/utilities/parsers/findUpdateValues.js +33 -33
- package/dist/data/utilities/parsers/isEntityProperty.js +7 -7
- package/dist/data/utilities/parsers/parseLiteralValue.js +33 -33
- package/dist/data/utilities/parsers/parseQuery.js +50 -50
- package/dist/data/utilities/parsers/removeFromQuery.js +7 -7
- package/dist/data/utilities/parsers/splitEntityProperty.js +22 -22
- package/dist/data/utilities/parsers/splitQueries.js +10 -10
- package/dist/data/utilities/reconcileJoin.js +25 -25
- package/dist/data/utilities/reconcileJoins.js +25 -25
- package/dist/data/utilities/registerRecord.js +66 -66
- package/dist/data/utilities/removeFromIndex.js +43 -43
- package/dist/data/utilities/restrictIndexedList.js +44 -44
- package/dist/data/utilities/retrieveFile.js +27 -27
- package/dist/data/utilities/retrieveIndexes.js +23 -23
- package/dist/data/utilities/retrieveRecord.js +8 -8
- package/dist/data/utilities/retrieveRecords.js +20 -20
- package/dist/data/utilities/runQuery.js +86 -86
- package/dist/data/utilities/updateIndex.js +55 -55
- package/dist/data/utilities/useJoinClause.js +50 -50
- package/dist/index.js +41 -41
- package/package.json +9 -5
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.hasDependents = void 0;
|
|
7
|
-
var _describe = require("../describe");
|
|
8
|
-
var _retrieveRecord = require("../../utilities/retrieveRecord");
|
|
9
|
-
var _retrieveRecords = require("../../utilities/retrieveRecords");
|
|
10
|
-
var _where = require("../../queries/where");
|
|
11
|
-
var _splitEntityProperty = require("../../utilities/parsers/splitEntityProperty");
|
|
12
|
-
/**
|
|
13
|
-
* Check whether any other record, in any entity, still has a single-field foreign key pointing
|
|
14
|
-
* at entity.property = value - the mirror image of foreignKeyExists(), which checks the opposite
|
|
15
|
-
* direction (that a new/updated foreign key value points at something real). Used to RESTRICT a
|
|
16
|
-
* delete or update that would otherwise leave a dangling reference behind. Scans every record in
|
|
17
|
-
* the database via the __RECORDS registry, the same "no index needed, just look" approach as
|
|
18
|
-
* keyUnique()/foreignKeyExists() - correctness over speed, matching this project's overall scale.
|
|
19
|
-
* @param entity
|
|
20
|
-
* @param property
|
|
21
|
-
* @param value
|
|
22
|
-
*/
|
|
23
|
-
const hasDependents = async (entity, property, value) => {
|
|
24
|
-
const entityFiles = await (0, _describe.describe)();
|
|
25
|
-
for (const entityFile of entityFiles) {
|
|
26
|
-
const otherEntity = entityFile.replace(/\.json$/, '');
|
|
27
|
-
const otherRecord = await (0, _retrieveRecord.retrieveRecord)(otherEntity);
|
|
28
|
-
for (const key of otherRecord.keys) {
|
|
29
|
-
if (key.type !== 'foreign' || key.fields.length !== 1 || !key.references || key.references.length !== 1) {
|
|
30
|
-
continue;
|
|
31
|
-
}
|
|
32
|
-
const {
|
|
33
|
-
entity: refEntity,
|
|
34
|
-
property: refProperty
|
|
35
|
-
} = (0, _splitEntityProperty.splitEntityProperty)(key.references[0].fields[0]);
|
|
36
|
-
if (refEntity !== entity || refProperty !== property) {
|
|
37
|
-
continue;
|
|
38
|
-
}
|
|
39
|
-
const records = await (0, _retrieveRecords.retrieveRecords)(otherEntity);
|
|
40
|
-
const found = (0, _where.where)(records, {
|
|
41
|
-
property: key.fields[0],
|
|
42
|
-
comparator: '=',
|
|
43
|
-
value
|
|
44
|
-
});
|
|
45
|
-
if (found.length) {
|
|
46
|
-
return true;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
return false;
|
|
51
|
-
};
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.hasDependents = void 0;
|
|
7
|
+
var _describe = require("../describe");
|
|
8
|
+
var _retrieveRecord = require("../../utilities/retrieveRecord");
|
|
9
|
+
var _retrieveRecords = require("../../utilities/retrieveRecords");
|
|
10
|
+
var _where = require("../../queries/where");
|
|
11
|
+
var _splitEntityProperty = require("../../utilities/parsers/splitEntityProperty");
|
|
12
|
+
/**
|
|
13
|
+
* Check whether any other record, in any entity, still has a single-field foreign key pointing
|
|
14
|
+
* at entity.property = value - the mirror image of foreignKeyExists(), which checks the opposite
|
|
15
|
+
* direction (that a new/updated foreign key value points at something real). Used to RESTRICT a
|
|
16
|
+
* delete or update that would otherwise leave a dangling reference behind. Scans every record in
|
|
17
|
+
* the database via the __RECORDS registry, the same "no index needed, just look" approach as
|
|
18
|
+
* keyUnique()/foreignKeyExists() - correctness over speed, matching this project's overall scale.
|
|
19
|
+
* @param entity
|
|
20
|
+
* @param property
|
|
21
|
+
* @param value
|
|
22
|
+
*/
|
|
23
|
+
const hasDependents = async (entity, property, value) => {
|
|
24
|
+
const entityFiles = await (0, _describe.describe)();
|
|
25
|
+
for (const entityFile of entityFiles) {
|
|
26
|
+
const otherEntity = entityFile.replace(/\.json$/, '');
|
|
27
|
+
const otherRecord = await (0, _retrieveRecord.retrieveRecord)(otherEntity);
|
|
28
|
+
for (const key of otherRecord.keys) {
|
|
29
|
+
if (key.type !== 'foreign' || key.fields.length !== 1 || !key.references || key.references.length !== 1) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
const {
|
|
33
|
+
entity: refEntity,
|
|
34
|
+
property: refProperty
|
|
35
|
+
} = (0, _splitEntityProperty.splitEntityProperty)(key.references[0].fields[0]);
|
|
36
|
+
if (refEntity !== entity || refProperty !== property) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const records = await (0, _retrieveRecords.retrieveRecords)(otherEntity);
|
|
40
|
+
const found = (0, _where.where)(records, {
|
|
41
|
+
property: key.fields[0],
|
|
42
|
+
comparator: '=',
|
|
43
|
+
value
|
|
44
|
+
});
|
|
45
|
+
if (found.length) {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
};
|
|
52
52
|
exports.hasDependents = hasDependents;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.keyGenerate = void 0;
|
|
7
|
-
var _keyUnique = require("./keyUnique");
|
|
8
|
-
const keyGenerate = async (entity, references = []) => {
|
|
9
|
-
let uuid = null;
|
|
10
|
-
let isUnique = false;
|
|
11
|
-
while (!isUnique) {
|
|
12
|
-
uuid = crypto.randomUUID();
|
|
13
|
-
isUnique = await (0, _keyUnique.keyUnique)(entity, references, [uuid]);
|
|
14
|
-
}
|
|
15
|
-
return uuid;
|
|
16
|
-
};
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.keyGenerate = void 0;
|
|
7
|
+
var _keyUnique = require("./keyUnique");
|
|
8
|
+
const keyGenerate = async (entity, references = []) => {
|
|
9
|
+
let uuid = null;
|
|
10
|
+
let isUnique = false;
|
|
11
|
+
while (!isUnique) {
|
|
12
|
+
uuid = crypto.randomUUID();
|
|
13
|
+
isUnique = await (0, _keyUnique.keyUnique)(entity, references, [uuid]);
|
|
14
|
+
}
|
|
15
|
+
return uuid;
|
|
16
|
+
};
|
|
17
17
|
exports.keyGenerate = keyGenerate;
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.keyUnique = void 0;
|
|
7
|
-
var _retrieveRecords = require("../../utilities/retrieveRecords");
|
|
8
|
-
var _where = require("../../queries/where");
|
|
9
|
-
/**
|
|
10
|
-
* Check that no existing record already has this combination of values across all of the given
|
|
11
|
-
* fields - a single field for a normal unique/primary key, or several for a composite one.
|
|
12
|
-
* references and checkKeys are parallel arrays: references[i]'s value must equal checkKeys[i].
|
|
13
|
-
* @param entity
|
|
14
|
-
* @param references
|
|
15
|
-
* @param checkKeys
|
|
16
|
-
*/
|
|
17
|
-
const keyUnique = async (entity, references = [], checkKeys = []) => {
|
|
18
|
-
if (!references.length || references.length !== checkKeys.length) {
|
|
19
|
-
return false;
|
|
20
|
-
}
|
|
21
|
-
let records = await (0, _retrieveRecords.retrieveRecords)(entity);
|
|
22
|
-
for (let i = 0; i < references.length; i++) {
|
|
23
|
-
records = (0, _where.where)(records, {
|
|
24
|
-
property: references[i],
|
|
25
|
-
comparator: '=',
|
|
26
|
-
value: checkKeys[i]
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
return !records.length;
|
|
30
|
-
};
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.keyUnique = void 0;
|
|
7
|
+
var _retrieveRecords = require("../../utilities/retrieveRecords");
|
|
8
|
+
var _where = require("../../queries/where");
|
|
9
|
+
/**
|
|
10
|
+
* Check that no existing record already has this combination of values across all of the given
|
|
11
|
+
* fields - a single field for a normal unique/primary key, or several for a composite one.
|
|
12
|
+
* references and checkKeys are parallel arrays: references[i]'s value must equal checkKeys[i].
|
|
13
|
+
* @param entity
|
|
14
|
+
* @param references
|
|
15
|
+
* @param checkKeys
|
|
16
|
+
*/
|
|
17
|
+
const keyUnique = async (entity, references = [], checkKeys = []) => {
|
|
18
|
+
if (!references.length || references.length !== checkKeys.length) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
let records = await (0, _retrieveRecords.retrieveRecords)(entity);
|
|
22
|
+
for (let i = 0; i < references.length; i++) {
|
|
23
|
+
records = (0, _where.where)(records, {
|
|
24
|
+
property: references[i],
|
|
25
|
+
comparator: '=',
|
|
26
|
+
value: checkKeys[i]
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return !records.length;
|
|
30
|
+
};
|
|
31
31
|
exports.keyUnique = keyUnique;
|
|
@@ -1,57 +1,57 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.typeCheck = void 0;
|
|
7
|
-
/**
|
|
8
|
-
* Validate (and where sensible, coerce) a value against a field's declared type. Runs only
|
|
9
|
-
* against values being written by insertEntity/updateEntity - it never re-validates data already
|
|
10
|
-
* on disk, so a field whose declared type doesn't match its already-stored values (which can
|
|
11
|
-
* happen, since nothing enforced this before) is left alone until something actually updates it.
|
|
12
|
-
* An unrecognized type name is treated as unconstrained rather than rejected, so a typo in a
|
|
13
|
-
* schema's field type can't silently block every write to that field.
|
|
14
|
-
* @param type
|
|
15
|
-
* @param value
|
|
16
|
-
*/
|
|
17
|
-
const typeCheck = (type = 'string', value = undefined) => {
|
|
18
|
-
if (typeof value === 'undefined') {
|
|
19
|
-
return value;
|
|
20
|
-
}
|
|
21
|
-
switch (type) {
|
|
22
|
-
case 'string':
|
|
23
|
-
return typeof value === 'string' ? value : String(value);
|
|
24
|
-
case 'int':
|
|
25
|
-
{
|
|
26
|
-
const coerced = Number(value);
|
|
27
|
-
if (Number.isNaN(coerced) || !Number.isInteger(coerced)) {
|
|
28
|
-
throw new Error(`Value "${value}" is not a valid int`);
|
|
29
|
-
}
|
|
30
|
-
return coerced;
|
|
31
|
-
}
|
|
32
|
-
case 'boolean':
|
|
33
|
-
if (typeof value === 'boolean') {
|
|
34
|
-
return value;
|
|
35
|
-
}
|
|
36
|
-
if (value === 'true') {
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
|
-
if (value === 'false') {
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
throw new Error(`Value "${value}" is not a valid boolean`);
|
|
43
|
-
case 'object':
|
|
44
|
-
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
45
|
-
throw new Error(`Value "${value}" is not a valid object`);
|
|
46
|
-
}
|
|
47
|
-
return value;
|
|
48
|
-
case 'array':
|
|
49
|
-
if (!Array.isArray(value)) {
|
|
50
|
-
throw new Error(`Value "${value}" is not a valid array`);
|
|
51
|
-
}
|
|
52
|
-
return value;
|
|
53
|
-
default:
|
|
54
|
-
return value;
|
|
55
|
-
}
|
|
56
|
-
};
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.typeCheck = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Validate (and where sensible, coerce) a value against a field's declared type. Runs only
|
|
9
|
+
* against values being written by insertEntity/updateEntity - it never re-validates data already
|
|
10
|
+
* on disk, so a field whose declared type doesn't match its already-stored values (which can
|
|
11
|
+
* happen, since nothing enforced this before) is left alone until something actually updates it.
|
|
12
|
+
* An unrecognized type name is treated as unconstrained rather than rejected, so a typo in a
|
|
13
|
+
* schema's field type can't silently block every write to that field.
|
|
14
|
+
* @param type
|
|
15
|
+
* @param value
|
|
16
|
+
*/
|
|
17
|
+
const typeCheck = (type = 'string', value = undefined) => {
|
|
18
|
+
if (typeof value === 'undefined') {
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
switch (type) {
|
|
22
|
+
case 'string':
|
|
23
|
+
return typeof value === 'string' ? value : String(value);
|
|
24
|
+
case 'int':
|
|
25
|
+
{
|
|
26
|
+
const coerced = Number(value);
|
|
27
|
+
if (Number.isNaN(coerced) || !Number.isInteger(coerced)) {
|
|
28
|
+
throw new Error(`Value "${value}" is not a valid int`);
|
|
29
|
+
}
|
|
30
|
+
return coerced;
|
|
31
|
+
}
|
|
32
|
+
case 'boolean':
|
|
33
|
+
if (typeof value === 'boolean') {
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
if (value === 'true') {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
if (value === 'false') {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
throw new Error(`Value "${value}" is not a valid boolean`);
|
|
43
|
+
case 'object':
|
|
44
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
45
|
+
throw new Error(`Value "${value}" is not a valid object`);
|
|
46
|
+
}
|
|
47
|
+
return value;
|
|
48
|
+
case 'array':
|
|
49
|
+
if (!Array.isArray(value)) {
|
|
50
|
+
throw new Error(`Value "${value}" is not a valid array`);
|
|
51
|
+
}
|
|
52
|
+
return value;
|
|
53
|
+
default:
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
57
|
exports.typeCheck = typeCheck;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.typeEnum = void 0;
|
|
7
|
-
require("core-js/modules/es.array.includes.js");
|
|
8
|
-
const typeEnum = (values = [], value = '', optional = false) => {
|
|
9
|
-
if (values.includes(value)) {
|
|
10
|
-
return true;
|
|
11
|
-
}
|
|
12
|
-
return typeof value === 'undefined' && optional;
|
|
13
|
-
};
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.typeEnum = void 0;
|
|
7
|
+
require("core-js/modules/es.array.includes.js");
|
|
8
|
+
const typeEnum = (values = [], value = '', optional = false) => {
|
|
9
|
+
if (values.includes(value)) {
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
return typeof value === 'undefined' && optional;
|
|
13
|
+
};
|
|
14
14
|
exports.typeEnum = typeEnum;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.useDefault = void 0;
|
|
7
|
-
const useDefault = (defaultValue = '', value = undefined) => {
|
|
8
|
-
if (typeof value === 'undefined') {
|
|
9
|
-
return defaultValue;
|
|
10
|
-
}
|
|
11
|
-
return value;
|
|
12
|
-
};
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useDefault = void 0;
|
|
7
|
+
const useDefault = (defaultValue = '', value = undefined) => {
|
|
8
|
+
if (typeof value === 'undefined') {
|
|
9
|
+
return defaultValue;
|
|
10
|
+
}
|
|
11
|
+
return value;
|
|
12
|
+
};
|
|
13
13
|
exports.useDefault = useDefault;
|
|
@@ -1,100 +1,100 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.deleteEntity = void 0;
|
|
7
|
-
require("core-js/modules/es.json.stringify.js");
|
|
8
|
-
require("core-js/modules/esnext.iterator.constructor.js");
|
|
9
|
-
require("core-js/modules/esnext.iterator.find.js");
|
|
10
|
-
require("core-js/modules/esnext.iterator.map.js");
|
|
11
|
-
require("core-js/modules/esnext.set.add-all.js");
|
|
12
|
-
require("core-js/modules/esnext.set.delete-all.js");
|
|
13
|
-
require("core-js/modules/esnext.set.difference.js");
|
|
14
|
-
require("core-js/modules/esnext.set.every.js");
|
|
15
|
-
require("core-js/modules/esnext.set.filter.js");
|
|
16
|
-
require("core-js/modules/esnext.set.find.js");
|
|
17
|
-
require("core-js/modules/esnext.set.intersection.js");
|
|
18
|
-
require("core-js/modules/esnext.set.is-disjoint-from.js");
|
|
19
|
-
require("core-js/modules/esnext.set.is-subset-of.js");
|
|
20
|
-
require("core-js/modules/esnext.set.is-superset-of.js");
|
|
21
|
-
require("core-js/modules/esnext.set.join.js");
|
|
22
|
-
require("core-js/modules/esnext.set.map.js");
|
|
23
|
-
require("core-js/modules/esnext.set.reduce.js");
|
|
24
|
-
require("core-js/modules/esnext.set.some.js");
|
|
25
|
-
require("core-js/modules/esnext.set.symmetric-difference.js");
|
|
26
|
-
require("core-js/modules/esnext.set.union.js");
|
|
27
|
-
var _retrieveRecord = require("../utilities/retrieveRecord");
|
|
28
|
-
var _retrieveFile = require("../utilities/retrieveFile");
|
|
29
|
-
var _removeFromIndex = require("../utilities/removeFromIndex");
|
|
30
|
-
var _computeKeyValue = require("../utilities/computeKeyValue");
|
|
31
|
-
var _hasDependents = require("../introspect/policies/hasDependents");
|
|
32
|
-
var _config = require("../utilities/config");
|
|
33
|
-
const {
|
|
34
|
-
rm,
|
|
35
|
-
writeFile
|
|
36
|
-
} = require('fs/promises');
|
|
37
|
-
/**
|
|
38
|
-
* RESTRICT: reject the whole delete (before removing anything) if any row being deleted is still
|
|
39
|
-
* referenced by a single-field foreign key elsewhere. Only meaningful for a single-field primary
|
|
40
|
-
* key, since foreign key support itself is single-field only - a composite primary key can't be
|
|
41
|
-
* the target of one yet, so there's nothing to check.
|
|
42
|
-
* @param entity
|
|
43
|
-
* @param primaryKey
|
|
44
|
-
* @param toDelete
|
|
45
|
-
*/
|
|
46
|
-
const assertNoDependents = async (entity, primaryKey, toDelete) => {
|
|
47
|
-
if (!(0, _config.getSetting)('enforceForeignKeys', true) || primaryKey.fields.length !== 1) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
const property = primaryKey.fields[0];
|
|
51
|
-
for (const row of toDelete) {
|
|
52
|
-
if (await (0, _hasDependents.hasDependents)(entity, property, row[property])) {
|
|
53
|
-
throw new Error(`Cannot delete from "${entity}" where "${property}" = ${row[property]} - other records still reference it`);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
/**
|
|
58
|
-
* A record object carries no memory of which entry file it was read from, and files are not
|
|
59
|
-
* guaranteed to be named after any field's value, so the only reliable way to find a record's
|
|
60
|
-
* file is to re-scan every entry and match it by its primary key value(s) - a single field, or a
|
|
61
|
-
* composite of several for a multi-field primary key.
|
|
62
|
-
* @param entity
|
|
63
|
-
* @param record
|
|
64
|
-
* @param primaryKey
|
|
65
|
-
* @param deletedValues
|
|
66
|
-
*/
|
|
67
|
-
const removeMatchingEntries = async (entity, record, primaryKey, deletedValues) => {
|
|
68
|
-
const databasePath = (0, _config.getSetting)('databasePath', 'database/');
|
|
69
|
-
const remainingEntries = [];
|
|
70
|
-
for (const fileName of record.entries) {
|
|
71
|
-
const data = await (0, _retrieveFile.retrieveFile)(`${record.path}/${fileName}`);
|
|
72
|
-
if (!deletedValues.has((0, _computeKeyValue.computeKeyValue)(primaryKey.fields, data))) {
|
|
73
|
-
remainingEntries.push(fileName);
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
await rm(`${databasePath}${record.path}/${fileName}`);
|
|
77
|
-
for (const key of record.keys) {
|
|
78
|
-
await (0, _removeFromIndex.removeFromIndex)(record.path, key, (0, _computeKeyValue.computeKeyValue)(key.fields, data), fileName);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
return remainingEntries;
|
|
82
|
-
};
|
|
83
|
-
const deleteEntity = async (entity = '', dataSet = {}) => {
|
|
84
|
-
const databasePath = (0, _config.getSetting)('databasePath', 'database/');
|
|
85
|
-
const record = await (0, _retrieveRecord.retrieveRecord)(entity);
|
|
86
|
-
const primaryKey = record.keys.find(key => key.type === 'primary');
|
|
87
|
-
if (!primaryKey) {
|
|
88
|
-
throw new Error(`Cannot delete from "${entity}" without a primary key`);
|
|
89
|
-
}
|
|
90
|
-
const toDelete = dataSet[entity] || [];
|
|
91
|
-
if (!toDelete.length) {
|
|
92
|
-
return dataSet;
|
|
93
|
-
}
|
|
94
|
-
await assertNoDependents(entity, primaryKey, toDelete);
|
|
95
|
-
const deletedValues = new Set(toDelete.map(row => (0, _computeKeyValue.computeKeyValue)(primaryKey.fields, row)));
|
|
96
|
-
record.entries = await removeMatchingEntries(entity, record, primaryKey, deletedValues);
|
|
97
|
-
await writeFile(`${databasePath}${record.path}.json`, JSON.stringify(record, null, 2));
|
|
98
|
-
return dataSet;
|
|
99
|
-
};
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.deleteEntity = void 0;
|
|
7
|
+
require("core-js/modules/es.json.stringify.js");
|
|
8
|
+
require("core-js/modules/esnext.iterator.constructor.js");
|
|
9
|
+
require("core-js/modules/esnext.iterator.find.js");
|
|
10
|
+
require("core-js/modules/esnext.iterator.map.js");
|
|
11
|
+
require("core-js/modules/esnext.set.add-all.js");
|
|
12
|
+
require("core-js/modules/esnext.set.delete-all.js");
|
|
13
|
+
require("core-js/modules/esnext.set.difference.js");
|
|
14
|
+
require("core-js/modules/esnext.set.every.js");
|
|
15
|
+
require("core-js/modules/esnext.set.filter.js");
|
|
16
|
+
require("core-js/modules/esnext.set.find.js");
|
|
17
|
+
require("core-js/modules/esnext.set.intersection.js");
|
|
18
|
+
require("core-js/modules/esnext.set.is-disjoint-from.js");
|
|
19
|
+
require("core-js/modules/esnext.set.is-subset-of.js");
|
|
20
|
+
require("core-js/modules/esnext.set.is-superset-of.js");
|
|
21
|
+
require("core-js/modules/esnext.set.join.js");
|
|
22
|
+
require("core-js/modules/esnext.set.map.js");
|
|
23
|
+
require("core-js/modules/esnext.set.reduce.js");
|
|
24
|
+
require("core-js/modules/esnext.set.some.js");
|
|
25
|
+
require("core-js/modules/esnext.set.symmetric-difference.js");
|
|
26
|
+
require("core-js/modules/esnext.set.union.js");
|
|
27
|
+
var _retrieveRecord = require("../utilities/retrieveRecord");
|
|
28
|
+
var _retrieveFile = require("../utilities/retrieveFile");
|
|
29
|
+
var _removeFromIndex = require("../utilities/removeFromIndex");
|
|
30
|
+
var _computeKeyValue = require("../utilities/computeKeyValue");
|
|
31
|
+
var _hasDependents = require("../introspect/policies/hasDependents");
|
|
32
|
+
var _config = require("../utilities/config");
|
|
33
|
+
const {
|
|
34
|
+
rm,
|
|
35
|
+
writeFile
|
|
36
|
+
} = require('fs/promises');
|
|
37
|
+
/**
|
|
38
|
+
* RESTRICT: reject the whole delete (before removing anything) if any row being deleted is still
|
|
39
|
+
* referenced by a single-field foreign key elsewhere. Only meaningful for a single-field primary
|
|
40
|
+
* key, since foreign key support itself is single-field only - a composite primary key can't be
|
|
41
|
+
* the target of one yet, so there's nothing to check.
|
|
42
|
+
* @param entity
|
|
43
|
+
* @param primaryKey
|
|
44
|
+
* @param toDelete
|
|
45
|
+
*/
|
|
46
|
+
const assertNoDependents = async (entity, primaryKey, toDelete) => {
|
|
47
|
+
if (!(0, _config.getSetting)('enforceForeignKeys', true) || primaryKey.fields.length !== 1) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const property = primaryKey.fields[0];
|
|
51
|
+
for (const row of toDelete) {
|
|
52
|
+
if (await (0, _hasDependents.hasDependents)(entity, property, row[property])) {
|
|
53
|
+
throw new Error(`Cannot delete from "${entity}" where "${property}" = ${row[property]} - other records still reference it`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* A record object carries no memory of which entry file it was read from, and files are not
|
|
59
|
+
* guaranteed to be named after any field's value, so the only reliable way to find a record's
|
|
60
|
+
* file is to re-scan every entry and match it by its primary key value(s) - a single field, or a
|
|
61
|
+
* composite of several for a multi-field primary key.
|
|
62
|
+
* @param entity
|
|
63
|
+
* @param record
|
|
64
|
+
* @param primaryKey
|
|
65
|
+
* @param deletedValues
|
|
66
|
+
*/
|
|
67
|
+
const removeMatchingEntries = async (entity, record, primaryKey, deletedValues) => {
|
|
68
|
+
const databasePath = (0, _config.getSetting)('databasePath', 'database/');
|
|
69
|
+
const remainingEntries = [];
|
|
70
|
+
for (const fileName of record.entries) {
|
|
71
|
+
const data = await (0, _retrieveFile.retrieveFile)(`${record.path}/${fileName}`);
|
|
72
|
+
if (!deletedValues.has((0, _computeKeyValue.computeKeyValue)(primaryKey.fields, data))) {
|
|
73
|
+
remainingEntries.push(fileName);
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
await rm(`${databasePath}${record.path}/${fileName}`);
|
|
77
|
+
for (const key of record.keys) {
|
|
78
|
+
await (0, _removeFromIndex.removeFromIndex)(record.path, key, (0, _computeKeyValue.computeKeyValue)(key.fields, data), fileName);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return remainingEntries;
|
|
82
|
+
};
|
|
83
|
+
const deleteEntity = async (entity = '', dataSet = {}) => {
|
|
84
|
+
const databasePath = (0, _config.getSetting)('databasePath', 'database/');
|
|
85
|
+
const record = await (0, _retrieveRecord.retrieveRecord)(entity);
|
|
86
|
+
const primaryKey = record.keys.find(key => key.type === 'primary');
|
|
87
|
+
if (!primaryKey) {
|
|
88
|
+
throw new Error(`Cannot delete from "${entity}" without a primary key`);
|
|
89
|
+
}
|
|
90
|
+
const toDelete = dataSet[entity] || [];
|
|
91
|
+
if (!toDelete.length) {
|
|
92
|
+
return dataSet;
|
|
93
|
+
}
|
|
94
|
+
await assertNoDependents(entity, primaryKey, toDelete);
|
|
95
|
+
const deletedValues = new Set(toDelete.map(row => (0, _computeKeyValue.computeKeyValue)(primaryKey.fields, row)));
|
|
96
|
+
record.entries = await removeMatchingEntries(entity, record, primaryKey, deletedValues);
|
|
97
|
+
await writeFile(`${databasePath}${record.path}.json`, JSON.stringify(record, null, 2));
|
|
98
|
+
return dataSet;
|
|
99
|
+
};
|
|
100
100
|
exports.deleteEntity = deleteEntity;
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.groupBy = void 0;
|
|
7
|
-
require("core-js/modules/esnext.iterator.constructor.js");
|
|
8
|
-
require("core-js/modules/esnext.iterator.reduce.js");
|
|
9
|
-
const groupBy = (dataSet = [], groupProperty = '') => {
|
|
10
|
-
if (!groupProperty) {
|
|
11
|
-
return dataSet;
|
|
12
|
-
}
|
|
13
|
-
return dataSet.reduce((groupedData, data) => {
|
|
14
|
-
const property = data[groupProperty];
|
|
15
|
-
if (!Object.prototype.hasOwnProperty.call(groupedData, property)) {
|
|
16
|
-
groupedData[property] = [];
|
|
17
|
-
}
|
|
18
|
-
groupedData[property].push(data);
|
|
19
|
-
return groupedData;
|
|
20
|
-
}, {});
|
|
21
|
-
};
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.groupBy = void 0;
|
|
7
|
+
require("core-js/modules/esnext.iterator.constructor.js");
|
|
8
|
+
require("core-js/modules/esnext.iterator.reduce.js");
|
|
9
|
+
const groupBy = (dataSet = [], groupProperty = '') => {
|
|
10
|
+
if (!groupProperty) {
|
|
11
|
+
return dataSet;
|
|
12
|
+
}
|
|
13
|
+
return dataSet.reduce((groupedData, data) => {
|
|
14
|
+
const property = data[groupProperty];
|
|
15
|
+
if (!Object.prototype.hasOwnProperty.call(groupedData, property)) {
|
|
16
|
+
groupedData[property] = [];
|
|
17
|
+
}
|
|
18
|
+
groupedData[property].push(data);
|
|
19
|
+
return groupedData;
|
|
20
|
+
}, {});
|
|
21
|
+
};
|
|
22
22
|
exports.groupBy = groupBy;
|