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.
Files changed (187) hide show
  1. package/README.md +257 -15
  2. package/browser/jsonFsQuery.js +3884 -5057
  3. package/browser/jsonFsQuery.min.js +1 -1
  4. package/dist/data/introspect/alter.d.ts +12 -0
  5. package/dist/data/introspect/alter.js +304 -0
  6. package/dist/data/introspect/alter.min.js +1 -0
  7. package/dist/data/introspect/create.d.ts +10 -0
  8. package/dist/data/introspect/create.js +9 -23
  9. package/dist/data/introspect/create.min.js +1 -1
  10. package/dist/data/introspect/drop.js +7 -15
  11. package/dist/data/introspect/drop.min.js +1 -1
  12. package/dist/data/introspect/formatDatabase.d.ts +17 -0
  13. package/dist/data/introspect/formatDatabase.js +56 -0
  14. package/dist/data/introspect/formatDatabase.min.js +1 -0
  15. package/dist/data/introspect/index.d.ts +9 -0
  16. package/dist/data/introspect/index.js +18 -5
  17. package/dist/data/introspect/index.min.js +1 -1
  18. package/dist/data/introspect/packDatabase.d.ts +27 -0
  19. package/dist/data/introspect/packDatabase.js +113 -0
  20. package/dist/data/introspect/packDatabase.min.js +1 -0
  21. package/dist/data/introspect/policies/foreignKeyExists.d.ts +2 -0
  22. package/dist/data/introspect/policies/foreignKeyExists.js +9 -3
  23. package/dist/data/introspect/policies/foreignKeyExists.min.js +1 -1
  24. package/dist/data/introspect/policies/hasDependents.d.ts +3 -3
  25. package/dist/data/introspect/policies/hasDependents.js +11 -3
  26. package/dist/data/introspect/policies/hasDependents.min.js +1 -1
  27. package/dist/data/introspect/policies/keyUnique.d.ts +3 -0
  28. package/dist/data/introspect/policies/keyUnique.js +10 -0
  29. package/dist/data/introspect/policies/keyUnique.min.js +1 -1
  30. package/dist/data/queries/databaseStatements.d.ts +31 -0
  31. package/dist/data/queries/databaseStatements.js +97 -0
  32. package/dist/data/queries/databaseStatements.min.js +1 -0
  33. package/dist/data/queries/deleteEntity.js +35 -19
  34. package/dist/data/queries/deleteEntity.min.js +1 -1
  35. package/dist/data/queries/insertEntity.d.ts +8 -0
  36. package/dist/data/queries/insertEntity.js +340 -43
  37. package/dist/data/queries/insertEntity.min.js +1 -1
  38. package/dist/data/queries/joinEntity.d.ts +15 -0
  39. package/dist/data/queries/joinEntity.js +91 -15
  40. package/dist/data/queries/joinEntity.min.js +1 -1
  41. package/dist/data/queries/query.d.ts +2 -1
  42. package/dist/data/queries/query.js +5 -2
  43. package/dist/data/queries/query.min.js +1 -1
  44. package/dist/data/queries/selectFields.d.ts +5 -4
  45. package/dist/data/queries/selectFields.js +25 -11
  46. package/dist/data/queries/selectFields.min.js +1 -1
  47. package/dist/data/queries/updateEntity.js +54 -15
  48. package/dist/data/queries/updateEntity.min.js +1 -1
  49. package/dist/data/storage/databases.d.ts +32 -0
  50. package/dist/data/storage/databases.js +93 -0
  51. package/dist/data/storage/databases.min.js +1 -0
  52. package/dist/data/storage/fileExists.d.ts +7 -0
  53. package/dist/data/storage/fileExists.js +25 -0
  54. package/dist/data/storage/fileExists.min.js +1 -0
  55. package/dist/data/storage/index.d.ts +19 -0
  56. package/dist/data/storage/index.js +124 -0
  57. package/dist/data/storage/index.min.js +1 -0
  58. package/dist/data/storage/listFiles.d.ts +8 -0
  59. package/dist/data/storage/listFiles.js +52 -0
  60. package/dist/data/storage/listFiles.min.js +1 -0
  61. package/dist/data/storage/makeDirectory.d.ts +7 -0
  62. package/dist/data/storage/makeDirectory.js +24 -0
  63. package/dist/data/storage/makeDirectory.min.js +1 -0
  64. package/dist/data/storage/nodeFiles.d.ts +6 -0
  65. package/dist/data/storage/nodeFiles.js +12 -0
  66. package/dist/data/storage/nodeFiles.min.js +1 -0
  67. package/dist/data/storage/readCache.d.ts +37 -0
  68. package/dist/data/storage/readCache.js +117 -0
  69. package/dist/data/storage/readCache.min.js +1 -0
  70. package/dist/data/storage/readJson.d.ts +16 -0
  71. package/dist/data/storage/readJson.js +38 -0
  72. package/dist/data/storage/readJson.min.js +1 -0
  73. package/dist/data/storage/removeDirectory.d.ts +8 -0
  74. package/dist/data/storage/removeDirectory.js +30 -0
  75. package/dist/data/storage/removeDirectory.min.js +1 -0
  76. package/dist/data/storage/removeFile.d.ts +8 -0
  77. package/dist/data/storage/removeFile.js +31 -0
  78. package/dist/data/storage/removeFile.min.js +1 -0
  79. package/dist/data/storage/storagePath.d.ts +11 -0
  80. package/dist/data/storage/storagePath.js +25 -0
  81. package/dist/data/storage/storagePath.min.js +1 -0
  82. package/dist/data/storage/writeJson.d.ts +17 -0
  83. package/dist/data/storage/writeJson.js +37 -0
  84. package/dist/data/storage/writeJson.min.js +1 -0
  85. package/dist/data/storage/writeSet.d.ts +64 -0
  86. package/dist/data/storage/writeSet.js +306 -0
  87. package/dist/data/storage/writeSet.min.js +1 -0
  88. package/dist/data/utilities/compareAs.d.ts +1 -0
  89. package/dist/data/utilities/compareAs.js +2 -2
  90. package/dist/data/utilities/compareAs.min.js +1 -1
  91. package/dist/data/utilities/config.d.ts +37 -0
  92. package/dist/data/utilities/config.js +77 -5
  93. package/dist/data/utilities/config.min.js +1 -1
  94. package/dist/data/utilities/databaseLock.d.ts +7 -0
  95. package/dist/data/utilities/databaseLock.js +19 -4
  96. package/dist/data/utilities/databaseLock.min.js +1 -1
  97. package/dist/data/utilities/deregisterRecord.js +4 -10
  98. package/dist/data/utilities/deregisterRecord.min.js +1 -1
  99. package/dist/data/utilities/getConditionIndexedList.js +3 -4
  100. package/dist/data/utilities/getConditionIndexedList.min.js +1 -1
  101. package/dist/data/utilities/indexBuffer.d.ts +35 -0
  102. package/dist/data/utilities/indexBuffer.js +139 -0
  103. package/dist/data/utilities/indexBuffer.min.js +1 -0
  104. package/dist/data/utilities/indexHas.d.ts +13 -0
  105. package/dist/data/utilities/indexHas.js +48 -0
  106. package/dist/data/utilities/indexHas.min.js +1 -0
  107. package/dist/data/utilities/joinBases.d.ts +29 -0
  108. package/dist/data/utilities/joinBases.js +128 -0
  109. package/dist/data/utilities/joinBases.min.js +1 -0
  110. package/dist/data/utilities/joinKey.d.ts +17 -0
  111. package/dist/data/utilities/joinKey.js +31 -0
  112. package/dist/data/utilities/joinKey.min.js +1 -0
  113. package/dist/data/utilities/keyIndexFiles.d.ts +16 -0
  114. package/dist/data/utilities/keyIndexFiles.js +60 -0
  115. package/dist/data/utilities/keyIndexFiles.min.js +1 -0
  116. package/dist/data/utilities/knownFields.d.ts +26 -0
  117. package/dist/data/utilities/knownFields.js +128 -0
  118. package/dist/data/utilities/knownFields.min.js +1 -0
  119. package/dist/data/utilities/packedTable.d.ts +34 -0
  120. package/dist/data/utilities/packedTable.js +60 -0
  121. package/dist/data/utilities/packedTable.min.js +1 -0
  122. package/dist/data/utilities/parsers/findInsertValues.d.ts +3 -3
  123. package/dist/data/utilities/parsers/findInsertValues.js +28 -12
  124. package/dist/data/utilities/parsers/findInsertValues.min.js +1 -1
  125. package/dist/data/utilities/parsers/maskStrings.js +11 -2
  126. package/dist/data/utilities/parsers/maskStrings.min.js +1 -1
  127. package/dist/data/utilities/parsers/parseAlter.d.ts +33 -0
  128. package/dist/data/utilities/parsers/parseAlter.js +84 -0
  129. package/dist/data/utilities/parsers/parseAlter.min.js +1 -0
  130. package/dist/data/utilities/parsers/parseCreate.d.ts +14 -0
  131. package/dist/data/utilities/parsers/parseCreate.js +13 -5
  132. package/dist/data/utilities/parsers/parseCreate.min.js +1 -1
  133. package/dist/data/utilities/parsers/parseDatabaseStatement.d.ts +17 -0
  134. package/dist/data/utilities/parsers/parseDatabaseStatement.js +82 -0
  135. package/dist/data/utilities/parsers/parseDatabaseStatement.min.js +1 -0
  136. package/dist/data/utilities/parsers/parseQuery.d.ts +3 -0
  137. package/dist/data/utilities/parsers/parseQuery.js +24 -0
  138. package/dist/data/utilities/parsers/parseQuery.min.js +1 -1
  139. package/dist/data/utilities/parsers/startsQuery.js +1 -1
  140. package/dist/data/utilities/parsers/startsQuery.min.js +1 -1
  141. package/dist/data/utilities/recordExists.js +2 -7
  142. package/dist/data/utilities/recordExists.min.js +1 -1
  143. package/dist/data/utilities/registerRecord.js +4 -10
  144. package/dist/data/utilities/registerRecord.min.js +1 -1
  145. package/dist/data/utilities/removeFromIndex.js +4 -10
  146. package/dist/data/utilities/removeFromIndex.min.js +1 -1
  147. package/dist/data/utilities/retrieveFile.d.ts +5 -0
  148. package/dist/data/utilities/retrieveFile.js +7 -16
  149. package/dist/data/utilities/retrieveFile.min.js +1 -1
  150. package/dist/data/utilities/retrieveFiles.d.ts +15 -0
  151. package/dist/data/utilities/retrieveFiles.js +48 -0
  152. package/dist/data/utilities/retrieveFiles.min.js +1 -0
  153. package/dist/data/utilities/retrieveRecord.d.ts +6 -0
  154. package/dist/data/utilities/retrieveRecord.js +24 -1
  155. package/dist/data/utilities/retrieveRecord.min.js +1 -1
  156. package/dist/data/utilities/retrieveRecords.d.ts +22 -0
  157. package/dist/data/utilities/retrieveRecords.js +60 -10
  158. package/dist/data/utilities/retrieveRecords.min.js +1 -1
  159. package/dist/data/utilities/rowLookup.d.ts +38 -0
  160. package/dist/data/utilities/rowLookup.js +99 -0
  161. package/dist/data/utilities/rowLookup.min.js +1 -0
  162. package/dist/data/utilities/runQuery.js +28 -4
  163. package/dist/data/utilities/runQuery.min.js +1 -1
  164. package/dist/data/utilities/semiJoin.d.ts +27 -0
  165. package/dist/data/utilities/semiJoin.js +97 -0
  166. package/dist/data/utilities/semiJoin.min.js +1 -0
  167. package/dist/data/utilities/updateIndex.js +5 -14
  168. package/dist/data/utilities/updateIndex.min.js +1 -1
  169. package/dist/index.d.ts +1 -1
  170. package/dist/index.js +24 -0
  171. package/dist/index.min.js +1 -1
  172. package/package.json +10 -4
  173. package/dist/data/utilities/getJoinIndexedList.d.ts +0 -3
  174. package/dist/data/utilities/getJoinIndexedList.js +0 -76
  175. package/dist/data/utilities/getJoinIndexedList.min.js +0 -1
  176. package/dist/data/utilities/getMatchingIndexes.d.ts +0 -2
  177. package/dist/data/utilities/getMatchingIndexes.js +0 -28
  178. package/dist/data/utilities/getMatchingIndexes.min.js +0 -1
  179. package/dist/data/utilities/matchIndexedJoins.d.ts +0 -2
  180. package/dist/data/utilities/matchIndexedJoins.js +0 -63
  181. package/dist/data/utilities/matchIndexedJoins.min.js +0 -1
  182. package/dist/data/utilities/restrictIndexedList.d.ts +0 -2
  183. package/dist/data/utilities/restrictIndexedList.js +0 -45
  184. package/dist/data/utilities/restrictIndexedList.min.js +0 -1
  185. package/dist/data/utilities/useJoinClause.d.ts +0 -6
  186. package/dist/data/utilities/useJoinClause.js +0 -57
  187. package/dist/data/utilities/useJoinClause.min.js +0 -1
@@ -0,0 +1,27 @@
1
+ export type packResult = {
2
+ records: number;
3
+ rows: number;
4
+ };
5
+ export type packCheck = {
6
+ stale: string[];
7
+ orphaned: string[];
8
+ };
9
+ /**
10
+ * Write every record of the configured database into one packed file (`__packed/<record>.json`, compact JSON): its
11
+ * rows in the record's order. A browser then reads a record in one request instead of one per row when it needs more
12
+ * rows than one round of requests (see packedReads in configure); a static site runs this as a build step, after its data changes. The entry files
13
+ * stay the copy that's edited and reviewed; any insert, update or delete through json-fs-query removes the record's
14
+ * packed file, and reads only use one that matches its record, so a packed file is never read in place of a change
15
+ * made through json-fs-query. Packed files of records that no longer exist are removed.
16
+ *
17
+ * Runs as one statement (the public version, see withWriteSet): a row that can't be read fails it and nothing is
18
+ * written. Node only.
19
+ */
20
+ export declare const packDatabase: () => Promise<packResult>;
21
+ /**
22
+ * Which records' packed files don't match their entry files (missing, or packed before a change made by
23
+ * hand), and which packed files belong to no record, without changing anything: for a build or test to check that
24
+ * packDatabase has run since the data last changed. Node only.
25
+ */
26
+ export declare const checkPacked: () => Promise<packCheck>;
27
+ //# sourceMappingURL=packDatabase.d.ts.map
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.packDatabase = exports.checkPacked = 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.filter.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 _storage = require("../storage");
28
+ var _retrieveRecord = require("../utilities/retrieveRecord");
29
+ var _retrieveFiles = require("../utilities/retrieveFiles");
30
+ var _retrieveRecords = require("../utilities/retrieveRecords");
31
+ var _packedTable = require("../utilities/packedTable");
32
+ var _showRecords = require("../queries/showRecords");
33
+ var _requireNode = require("../utilities/requireNode");
34
+ /**
35
+ * The packed file a record should have, read from its entry files (never from a packed file), as the compact
36
+ * text packDatabase writes.
37
+ * @param name - The record's name.
38
+ */
39
+ const packedText = async name => {
40
+ const record = await (0, _retrieveRecord.retrieveRecord)(name);
41
+ const entries = record.entries || [];
42
+ const rows = await (0, _retrieveFiles.retrieveFiles)(entries.map(file => `${record.path}/${file}`), _retrieveRecords.retrieveEntry);
43
+ const packed = {
44
+ entries,
45
+ rows
46
+ };
47
+ return {
48
+ path: (0, _packedTable.packedPath)(record.path),
49
+ text: (0, _storage.jsonText)(packed, 'compact'),
50
+ rows: entries.length
51
+ };
52
+ };
53
+ /**
54
+ * The packed files under `__packed/` that belong to no record (left by a record dropped outside json-fs-query, or
55
+ * renamed by hand).
56
+ * @param names - The records' names.
57
+ */
58
+ const orphanedPacks = async names => {
59
+ const expected = new Set(names.map(name => (0, _packedTable.packedPath)(name)));
60
+ return (await (0, _storage.listFiles)('__packed')).filter(path => !expected.has(path));
61
+ };
62
+ /**
63
+ * Write every record of the configured database into one packed file (`__packed/<record>.json`, compact JSON): its
64
+ * rows in the record's order. A browser then reads a record in one request instead of one per row when it needs more
65
+ * rows than one round of requests (see packedReads in configure); a static site runs this as a build step, after its data changes. The entry files
66
+ * stay the copy that's edited and reviewed; any insert, update or delete through json-fs-query removes the record's
67
+ * packed file, and reads only use one that matches its record, so a packed file is never read in place of a change
68
+ * made through json-fs-query. Packed files of records that no longer exist are removed.
69
+ *
70
+ * Runs as one statement (the public version, see withWriteSet): a row that can't be read fails it and nothing is
71
+ * written. Node only.
72
+ */
73
+ const packDatabase = async () => {
74
+ (0, _requireNode.requireNode)('packDatabase');
75
+ const names = await (0, _showRecords.showRecords)();
76
+ let rows = 0;
77
+ for (const name of names) {
78
+ const packed = await packedText(name);
79
+ await (0, _storage.makeDirectory)(packed.path.slice(0, packed.path.lastIndexOf('/')));
80
+ await (0, _storage.writeJson)(packed.path, JSON.parse(packed.text), 'compact');
81
+ rows += packed.rows;
82
+ }
83
+ for (const path of await orphanedPacks(names)) {
84
+ await (0, _storage.removeFile)(path);
85
+ }
86
+ return {
87
+ records: names.length,
88
+ rows
89
+ };
90
+ };
91
+ /**
92
+ * Which records' packed files don't match their entry files (missing, or packed before a change made by
93
+ * hand), and which packed files belong to no record, without changing anything: for a build or test to check that
94
+ * packDatabase has run since the data last changed. Node only.
95
+ */
96
+ exports.packDatabase = packDatabase;
97
+ const checkPacked = async () => {
98
+ (0, _requireNode.requireNode)('checkPacked');
99
+ const names = await (0, _showRecords.showRecords)();
100
+ const stale = [];
101
+ for (const name of names) {
102
+ const packed = await packedText(name);
103
+ const current = (0, _storage.fileExists)(packed.path) ? await (0, _storage.readText)(packed.path).catch(() => undefined) : undefined;
104
+ if (typeof current === 'undefined' || JSON.stringify(JSON.parse(current)) !== packed.text) {
105
+ stale.push(name);
106
+ }
107
+ }
108
+ return {
109
+ stale,
110
+ orphaned: await orphanedPacks(names)
111
+ };
112
+ };
113
+ exports.checkPacked = checkPacked;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.packDatabase=exports.checkPacked=void 0,require("core-js/modules/es.json.stringify.js"),require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.filter.js"),require("core-js/modules/esnext.iterator.map.js"),require("core-js/modules/esnext.set.add-all.js"),require("core-js/modules/esnext.set.delete-all.js"),require("core-js/modules/esnext.set.difference.js"),require("core-js/modules/esnext.set.every.js"),require("core-js/modules/esnext.set.filter.js"),require("core-js/modules/esnext.set.find.js"),require("core-js/modules/esnext.set.intersection.js"),require("core-js/modules/esnext.set.is-disjoint-from.js"),require("core-js/modules/esnext.set.is-subset-of.js"),require("core-js/modules/esnext.set.is-superset-of.js"),require("core-js/modules/esnext.set.join.js"),require("core-js/modules/esnext.set.map.js"),require("core-js/modules/esnext.set.reduce.js"),require("core-js/modules/esnext.set.some.js"),require("core-js/modules/esnext.set.symmetric-difference.js"),require("core-js/modules/esnext.set.union.js");var _storage=require("../storage"),_retrieveRecord=require("../utilities/retrieveRecord"),_retrieveFiles=require("../utilities/retrieveFiles"),_retrieveRecords=require("../utilities/retrieveRecords"),_packedTable=require("../utilities/packedTable"),_showRecords=require("../queries/showRecords"),_requireNode=require("../utilities/requireNode");const packedText=async e=>{const s=await(0,_retrieveRecord.retrieveRecord)(e),r=s.entries||[],t=await(0,_retrieveFiles.retrieveFiles)(r.map((e=>`${s.path}/${e}`)),_retrieveRecords.retrieveEntry),o={entries:r,rows:t};return{path:(0,_packedTable.packedPath)(s.path),text:(0,_storage.jsonText)(o,"compact"),rows:r.length}},orphanedPacks=async e=>{const s=new Set(e.map((e=>(0,_packedTable.packedPath)(e))));return(await(0,_storage.listFiles)("__packed")).filter((e=>!s.has(e)))},packDatabase=async()=>{(0,_requireNode.requireNode)("packDatabase");const e=await(0,_showRecords.showRecords)();let s=0;for(const r of e){const e=await packedText(r);await(0,_storage.makeDirectory)(e.path.slice(0,e.path.lastIndexOf("/"))),await(0,_storage.writeJson)(e.path,JSON.parse(e.text),"compact"),s+=e.rows}for(const s of await orphanedPacks(e))await(0,_storage.removeFile)(s);return{records:e.length,rows:s}};exports.packDatabase=packDatabase;const checkPacked=async()=>{(0,_requireNode.requireNode)("checkPacked");const e=await(0,_showRecords.showRecords)(),s=[];for(const r of e){const e=await packedText(r),t=(0,_storage.fileExists)(e.path)?await(0,_storage.readText)(e.path).catch((()=>{})):void 0;void 0!==t&&JSON.stringify(JSON.parse(t))===e.text||s.push(r)}return{stale:s,orphaned:await orphanedPacks(e)}};exports.checkPacked=checkPacked;
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * Check whether any record in the referenced entity has the given property set to the given
3
3
  * value - the mirror image of keyUnique(), which checks that no record already has a value.
4
+ * A referenced field with an index (a foreign key usually references a primary key) is answered from it; otherwise
5
+ * every row is read.
4
6
  * @param entity
5
7
  * @param property
6
8
  * @param value
@@ -8,22 +8,28 @@ var _retrieveRecords = require("../../utilities/retrieveRecords");
8
8
  var _where = require("../../queries/where");
9
9
  var _retrieveRecord = require("../../utilities/retrieveRecord");
10
10
  var _fieldType = require("../../utilities/fieldType");
11
+ var _indexHas = require("../../utilities/indexHas");
11
12
  /**
12
13
  * Check whether any record in the referenced entity has the given property set to the given
13
14
  * value - the mirror image of keyUnique(), which checks that no record already has a value.
15
+ * A referenced field with an index (a foreign key usually references a primary key) is answered from it; otherwise
16
+ * every row is read.
14
17
  * @param entity
15
18
  * @param property
16
19
  * @param value
17
20
  */
18
21
  const foreignKeyExists = async (entity, property, value) => {
22
+ const found = await (0, _indexHas.indexHas)(entity, property, value);
23
+ if (typeof found !== 'undefined') {
24
+ return found;
25
+ }
19
26
  const records = await (0, _retrieveRecords.retrieveRecords)(entity);
20
27
  const type = (0, _fieldType.fieldType)(await (0, _retrieveRecord.retrieveRecord)(entity), property);
21
- const found = (0, _where.where)(records, {
28
+ return (0, _where.where)(records, {
22
29
  property,
23
30
  comparator: '=',
24
31
  value,
25
32
  type
26
- });
27
- return found.length > 0;
33
+ }).length > 0;
28
34
  };
29
35
  exports.foreignKeyExists = foreignKeyExists;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.foreignKeyExists=void 0;var _retrieveRecords=require("../../utilities/retrieveRecords"),_where=require("../../queries/where"),_retrieveRecord=require("../../utilities/retrieveRecord"),_fieldType=require("../../utilities/fieldType");const foreignKeyExists=async(e,r,i)=>{const t=await(0,_retrieveRecords.retrieveRecords)(e),s=(0,_fieldType.fieldType)(await(0,_retrieveRecord.retrieveRecord)(e),r);return(0,_where.where)(t,{property:r,comparator:"=",value:i,type:s}).length>0};exports.foreignKeyExists=foreignKeyExists;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.foreignKeyExists=void 0;var _retrieveRecords=require("../../utilities/retrieveRecords"),_where=require("../../queries/where"),_retrieveRecord=require("../../utilities/retrieveRecord"),_fieldType=require("../../utilities/fieldType"),_indexHas=require("../../utilities/indexHas");const foreignKeyExists=async(e,r,i)=>{const t=await(0,_indexHas.indexHas)(e,r,i);if(void 0!==t)return t;const s=await(0,_retrieveRecords.retrieveRecords)(e),o=(0,_fieldType.fieldType)(await(0,_retrieveRecord.retrieveRecord)(e),r);return(0,_where.where)(s,{property:r,comparator:"=",value:i,type:o}).length>0};exports.foreignKeyExists=foreignKeyExists;
@@ -2,9 +2,9 @@
2
2
  * Check whether any other record, in any entity, still has a single-field foreign key pointing
3
3
  * at entity.property = value - the mirror image of foreignKeyExists(), which checks the opposite
4
4
  * direction (that a new/updated foreign key value points at something real). Used to RESTRICT a
5
- * delete or update that would otherwise leave a dangling reference behind. Scans every record in
6
- * the database via the __RECORDS registry, the same "no index needed, just look" approach as
7
- * keyUnique()/foreignKeyExists() - correctness over speed, matching this project's overall scale.
5
+ * delete or update that would otherwise leave a dangling reference behind. Looks at every record in
6
+ * the database (via the __RECORDS registry) for a foreign key to entity.property. A foreign key field with an index
7
+ * (each one gets one) is answered from it; otherwise that record's rows are read.
8
8
  * @param entity
9
9
  * @param property
10
10
  * @param value
@@ -10,13 +10,14 @@ var _retrieveRecords = require("../../utilities/retrieveRecords");
10
10
  var _where = require("../../queries/where");
11
11
  var _fieldType = require("../../utilities/fieldType");
12
12
  var _splitEntityProperty = require("../../utilities/parsers/splitEntityProperty");
13
+ var _indexHas = require("../../utilities/indexHas");
13
14
  /**
14
15
  * Check whether any other record, in any entity, still has a single-field foreign key pointing
15
16
  * at entity.property = value - the mirror image of foreignKeyExists(), which checks the opposite
16
17
  * direction (that a new/updated foreign key value points at something real). Used to RESTRICT a
17
- * delete or update that would otherwise leave a dangling reference behind. Scans every record in
18
- * the database via the __RECORDS registry, the same "no index needed, just look" approach as
19
- * keyUnique()/foreignKeyExists() - correctness over speed, matching this project's overall scale.
18
+ * delete or update that would otherwise leave a dangling reference behind. Looks at every record in
19
+ * the database (via the __RECORDS registry) for a foreign key to entity.property. A foreign key field with an index
20
+ * (each one gets one) is answered from it; otherwise that record's rows are read.
20
21
  * @param entity
21
22
  * @param property
22
23
  * @param value
@@ -37,6 +38,13 @@ const hasDependents = async (entity, property, value) => {
37
38
  if (refEntity !== entity || refProperty !== property) {
38
39
  continue;
39
40
  }
41
+ const indexed = await (0, _indexHas.indexHas)(otherEntity, key.fields[0], value);
42
+ if (typeof indexed !== 'undefined') {
43
+ if (indexed) {
44
+ return true;
45
+ }
46
+ continue;
47
+ }
40
48
  const records = await (0, _retrieveRecords.retrieveRecords)(otherEntity);
41
49
  const found = (0, _where.where)(records, {
42
50
  property: key.fields[0],
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.hasDependents=void 0;var _describe=require("../describe"),_retrieveRecord=require("../../utilities/retrieveRecord"),_retrieveRecords=require("../../utilities/retrieveRecords"),_where=require("../../queries/where"),_fieldType=require("../../utilities/fieldType"),_splitEntityProperty=require("../../utilities/parsers/splitEntityProperty");const hasDependents=async(e,r,t)=>{const i=await(0,_describe.describe)();for(const s of i){const i=s.replace(/\.json$/,""),o=await(0,_retrieveRecord.retrieveRecord)(i);for(const s of o.keys){if("foreign"!==s.type||1!==s.fields.length||!s.references||1!==s.references.length)continue;const{entity:n,property:c}=(0,_splitEntityProperty.splitEntityProperty)(s.references[0].fields[0]);if(n!==e||c!==r)continue;const p=await(0,_retrieveRecords.retrieveRecords)(i);if((0,_where.where)(p,{property:s.fields[0],comparator:"=",value:t,type:(0,_fieldType.fieldType)(o,s.fields[0])}).length)return!0}}return!1};exports.hasDependents=hasDependents;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.hasDependents=void 0;var _describe=require("../describe"),_retrieveRecord=require("../../utilities/retrieveRecord"),_retrieveRecords=require("../../utilities/retrieveRecords"),_where=require("../../queries/where"),_fieldType=require("../../utilities/fieldType"),_splitEntityProperty=require("../../utilities/parsers/splitEntityProperty"),_indexHas=require("../../utilities/indexHas");const hasDependents=async(e,r,i)=>{const t=await(0,_describe.describe)();for(const s of t){const t=s.replace(/\.json$/,""),n=await(0,_retrieveRecord.retrieveRecord)(t);for(const s of n.keys){if("foreign"!==s.type||1!==s.fields.length||!s.references||1!==s.references.length)continue;const{entity:o,property:d}=(0,_splitEntityProperty.splitEntityProperty)(s.references[0].fields[0]);if(o!==e||d!==r)continue;const c=await(0,_indexHas.indexHas)(t,s.fields[0],i);if(void 0!==c){if(c)return!0;continue}const p=await(0,_retrieveRecords.retrieveRecords)(t);if((0,_where.where)(p,{property:s.fields[0],comparator:"=",value:i,type:(0,_fieldType.fieldType)(n,s.fields[0])}).length)return!0}}return!1};exports.hasDependents=hasDependents;
@@ -2,6 +2,9 @@
2
2
  * Check that no existing record already has this combination of values across all of the given
3
3
  * fields - a single field for a normal unique/primary key, or several for a composite one.
4
4
  * references and checkKeys are parallel arrays: references[i]'s value must equal checkKeys[i].
5
+ *
6
+ * One field with an index (every primary and unique key has one) is answered from the index; a composite key, or a
7
+ * field without one, reads every row.
5
8
  * @param entity
6
9
  * @param references
7
10
  * @param checkKeys
@@ -8,10 +8,14 @@ var _retrieveRecords = require("../../utilities/retrieveRecords");
8
8
  var _where = require("../../queries/where");
9
9
  var _retrieveRecord = require("../../utilities/retrieveRecord");
10
10
  var _fieldType = require("../../utilities/fieldType");
11
+ var _indexHas = require("../../utilities/indexHas");
11
12
  /**
12
13
  * Check that no existing record already has this combination of values across all of the given
13
14
  * fields - a single field for a normal unique/primary key, or several for a composite one.
14
15
  * references and checkKeys are parallel arrays: references[i]'s value must equal checkKeys[i].
16
+ *
17
+ * One field with an index (every primary and unique key has one) is answered from the index; a composite key, or a
18
+ * field without one, reads every row.
15
19
  * @param entity
16
20
  * @param references
17
21
  * @param checkKeys
@@ -20,6 +24,12 @@ const keyUnique = async (entity, references = [], checkKeys = []) => {
20
24
  if (!references.length || references.length !== checkKeys.length) {
21
25
  return false;
22
26
  }
27
+ if (references.length === 1) {
28
+ const found = await (0, _indexHas.indexHas)(entity, references[0], checkKeys[0]);
29
+ if (typeof found !== 'undefined') {
30
+ return !found;
31
+ }
32
+ }
23
33
  let records = await (0, _retrieveRecords.retrieveRecords)(entity);
24
34
  const record = await (0, _retrieveRecord.retrieveRecord)(entity);
25
35
  for (let i = 0; i < references.length; i++) {
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.keyUnique=void 0;var _retrieveRecords=require("../../utilities/retrieveRecords"),_where=require("../../queries/where"),_retrieveRecord=require("../../utilities/retrieveRecord"),_fieldType=require("../../utilities/fieldType");const keyUnique=async(e,r=[],t=[])=>{if(!r.length||r.length!==t.length)return!1;let i=await(0,_retrieveRecords.retrieveRecords)(e);const o=await(0,_retrieveRecord.retrieveRecord)(e);for(let e=0;e<r.length;e++)i=(0,_where.where)(i,{property:r[e],comparator:"=",value:t[e],type:(0,_fieldType.fieldType)(o,r[e])});return!i.length};exports.keyUnique=keyUnique;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.keyUnique=void 0;var _retrieveRecords=require("../../utilities/retrieveRecords"),_where=require("../../queries/where"),_retrieveRecord=require("../../utilities/retrieveRecord"),_fieldType=require("../../utilities/fieldType"),_indexHas=require("../../utilities/indexHas");const keyUnique=async(e,r=[],i=[])=>{if(!r.length||r.length!==i.length)return!1;if(1===r.length){const t=await(0,_indexHas.indexHas)(e,r[0],i[0]);if(void 0!==t)return!t}let t=await(0,_retrieveRecords.retrieveRecords)(e);const s=await(0,_retrieveRecord.retrieveRecord)(e);for(let e=0;e<r.length;e++)t=(0,_where.where)(t,{property:r[e],comparator:"=",value:i[e],type:(0,_fieldType.fieldType)(s,r[e])});return!t.length};exports.keyUnique=keyUnique;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * `create database [if not exists] <name>`: a new, empty database in the folder holding them (databasesPath). It
3
+ * doesn't switch to it (see use). The name is listed before the folder is made, so a stop part way leaves a listed
4
+ * database whose folder appears with its first record, never a folder no list names. A folder that's there but not
5
+ * listed (copied in by hand, or left by an older version) is listed by `if not exists`. Node only.
6
+ * @param name
7
+ * @param ifNotExists
8
+ * @returns The name, or null when it existed and `if not exists` was given.
9
+ */
10
+ export declare const createDatabase: (name: string, ifNotExists?: boolean) => Promise<string | null>;
11
+ /**
12
+ * `drop database [if exists] <name>`: delete a database, its records and every row in them. The database in use can't
13
+ * be dropped (use another one first). Node only.
14
+ * @param name
15
+ * @param ifExists
16
+ * @returns The name, or null when it didn't exist and `if exists` was given.
17
+ */
18
+ export declare const dropDatabase: (name: string, ifExists?: boolean) => Promise<string | null>;
19
+ /**
20
+ * `use <name>`: switch to another database in the folder holding them, for the rest of the call and the calls after it
21
+ * (as configure({ database }) does). Works in a browser too (reading only), for a database listed in
22
+ * `__DATABASES.json`, while no other call is running in the page.
23
+ * @param name
24
+ * @returns The name.
25
+ */
26
+ export declare const useDatabase: (name: string) => Promise<string>;
27
+ /**
28
+ * `show databases`: the databases' names, in the order they were created.
29
+ */
30
+ export declare const showDatabases: () => Promise<string[]>;
31
+ //# sourceMappingURL=databaseStatements.d.ts.map
@@ -0,0 +1,97 @@
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.useDatabase = exports.showDatabases = exports.dropDatabase = exports.createDatabase = void 0;
8
+ require("core-js/modules/es.array.includes.js");
9
+ require("core-js/modules/esnext.iterator.constructor.js");
10
+ require("core-js/modules/esnext.iterator.filter.js");
11
+ var jsEnv = _interopRequireWildcard(require("browser-or-node"));
12
+ var _config = require("../utilities/config");
13
+ var _requireNode = require("../utilities/requireNode");
14
+ var _databaseLock = require("../utilities/databaseLock");
15
+ var _storage = require("../storage");
16
+ var e;
17
+ 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; }
18
+ /**
19
+ * Whether a database exists: listed in `__DATABASES.json`, or (in Node) a folder of that name is there.
20
+ * @param name
21
+ */
22
+ const databaseExists = async name => (await (0, _storage.readDatabaseList)()).includes(name) || jsEnv.isNode && (0, _storage.databaseFolderExists)(name);
23
+ /**
24
+ * `create database [if not exists] <name>`: a new, empty database in the folder holding them (databasesPath). It
25
+ * doesn't switch to it (see use). The name is listed before the folder is made, so a stop part way leaves a listed
26
+ * database whose folder appears with its first record, never a folder no list names. A folder that's there but not
27
+ * listed (copied in by hand, or left by an older version) is listed by `if not exists`. Node only.
28
+ * @param name
29
+ * @param ifNotExists
30
+ * @returns The name, or null when it existed and `if not exists` was given.
31
+ */
32
+ const createDatabase = async (name, ifNotExists = false) => {
33
+ (0, _requireNode.requireNode)('"create database"');
34
+ const listed = await (0, _storage.readDatabaseList)();
35
+ if (listed.includes(name) || (0, _storage.databaseFolderExists)(name)) {
36
+ if (!ifNotExists) {
37
+ throw new Error(listed.includes(name) ? `Database "${name}" already exists` : `Database "${name}" already exists as a folder that isn't listed: create database if not exists ${name} lists it`);
38
+ }
39
+ if (!listed.includes(name)) {
40
+ await (0, _storage.writeDatabaseList)([...listed, name]);
41
+ }
42
+ return null;
43
+ }
44
+ await (0, _storage.writeDatabaseList)([...listed, name]);
45
+ await (0, _storage.makeDatabaseFolder)(name);
46
+ return name;
47
+ };
48
+ /**
49
+ * `drop database [if exists] <name>`: delete a database, its records and every row in them. The database in use can't
50
+ * be dropped (use another one first). Node only.
51
+ * @param name
52
+ * @param ifExists
53
+ * @returns The name, or null when it didn't exist and `if exists` was given.
54
+ */
55
+ exports.createDatabase = createDatabase;
56
+ const dropDatabase = async (name, ifExists = false) => {
57
+ (0, _requireNode.requireNode)('"drop database"');
58
+ if (!(await databaseExists(name))) {
59
+ if (ifExists) {
60
+ return null;
61
+ }
62
+ throw new Error(`Database "${name}" doesn't exist`);
63
+ }
64
+ if ((0, _config.getSetting)('database', undefined) === name) {
65
+ throw new Error(`Can't drop the database in use ("${name}"): use another one first`);
66
+ }
67
+ // Unlisted first: a stop part way leaves a folder no list names, never a listed database with no folder
68
+ await (0, _storage.writeDatabaseList)((await (0, _storage.readDatabaseList)()).filter(listed => listed !== name));
69
+ await (0, _storage.removeDatabaseFolder)(name);
70
+ return name;
71
+ };
72
+ /**
73
+ * `use <name>`: switch to another database in the folder holding them, for the rest of the call and the calls after it
74
+ * (as configure({ database }) does). Works in a browser too (reading only), for a database listed in
75
+ * `__DATABASES.json`, while no other call is running in the page.
76
+ * @param name
77
+ * @returns The name.
78
+ */
79
+ exports.dropDatabase = dropDatabase;
80
+ const useDatabase = async name => {
81
+ // A browser runs calls side by side (see withDatabaseLock), and there's one database in use for the page: switching
82
+ // now would move the other calls to it part way
83
+ if (!jsEnv.isNode && (0, _databaseLock.browserCallsRunning)() > 1) {
84
+ throw new Error(`Can't use "${name}" while other calls are running in this page: await them first, or pick the database with configure({ database }) between calls`);
85
+ }
86
+ if (!(await databaseExists(name))) {
87
+ throw new Error(`Database "${name}" doesn't exist${jsEnv.isNode ? '' : ' (or isn\'t listed in __DATABASES.json)'}`);
88
+ }
89
+ (0, _config.switchDatabase)(name);
90
+ return name;
91
+ };
92
+ /**
93
+ * `show databases`: the databases' names, in the order they were created.
94
+ */
95
+ exports.useDatabase = useDatabase;
96
+ const showDatabases = async () => (0, _storage.readDatabaseList)();
97
+ exports.showDatabases = showDatabases;
@@ -0,0 +1 @@
1
+ "use strict";require("core-js/modules/esnext.weak-map.delete-all.js"),Object.defineProperty(exports,"__esModule",{value:!0}),exports.useDatabase=exports.showDatabases=exports.dropDatabase=exports.createDatabase=void 0,require("core-js/modules/es.array.includes.js"),require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.filter.js");var e,jsEnv=_interopRequireWildcard(require("browser-or-node")),_config=require("../utilities/config"),_requireNode=require("../utilities/requireNode"),_databaseLock=require("../utilities/databaseLock"),_storage=require("../storage");function _interopRequireWildcard(a,t){if(!t&&a&&a.__esModule)return a;var s,r,i=Object.defineProperty,o={__proto__:null,default:a};if(Object(a)!==a)return o;if(e||"function"!=typeof WeakMap||(e=new WeakMap),e){if(e.has(a))return e.get(a);e.set(a,o)}for(r in a)"default"!==r&&{}.hasOwnProperty.call(a,r)&&((s=i&&Object.getOwnPropertyDescriptor(a,r))&&(s.get||s.set)?i(o,r,s):o[r]=a[r]);return o}const databaseExists=async e=>(await(0,_storage.readDatabaseList)()).includes(e)||jsEnv.isNode&&(0,_storage.databaseFolderExists)(e),createDatabase=async(e,a=!1)=>{(0,_requireNode.requireNode)('"create database"');const t=await(0,_storage.readDatabaseList)();if(t.includes(e)||(0,_storage.databaseFolderExists)(e)){if(!a)throw new Error(t.includes(e)?`Database "${e}" already exists`:`Database "${e}" already exists as a folder that isn't listed: create database if not exists ${e} lists it`);return t.includes(e)||await(0,_storage.writeDatabaseList)([...t,e]),null}return await(0,_storage.writeDatabaseList)([...t,e]),await(0,_storage.makeDatabaseFolder)(e),e};exports.createDatabase=createDatabase;const dropDatabase=async(e,a=!1)=>{if((0,_requireNode.requireNode)('"drop database"'),!await databaseExists(e)){if(a)return null;throw new Error(`Database "${e}" doesn't exist`)}if((0,_config.getSetting)("database",void 0)===e)throw new Error(`Can't drop the database in use ("${e}"): use another one first`);return await(0,_storage.writeDatabaseList)((await(0,_storage.readDatabaseList)()).filter((a=>a!==e))),await(0,_storage.removeDatabaseFolder)(e),e};exports.dropDatabase=dropDatabase;const useDatabase=async e=>{if(!jsEnv.isNode&&(0,_databaseLock.browserCallsRunning)()>1)throw new Error(`Can't use "${e}" while other calls are running in this page: await them first, or pick the database with configure({ database }) between calls`);if(!await databaseExists(e))throw new Error(`Database "${e}" doesn't exist${jsEnv.isNode?"":" (or isn't listed in __DATABASES.json)"}`);return(0,_config.switchDatabase)(e),e};exports.useDatabase=useDatabase;const showDatabases=async()=>(0,_storage.readDatabaseList)();exports.showDatabases=showDatabases;
@@ -4,8 +4,8 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.deleteEntity = void 0;
7
- require("core-js/modules/es.json.stringify.js");
8
7
  require("core-js/modules/esnext.iterator.constructor.js");
8
+ require("core-js/modules/esnext.iterator.filter.js");
9
9
  require("core-js/modules/esnext.iterator.find.js");
10
10
  require("core-js/modules/esnext.iterator.map.js");
11
11
  require("core-js/modules/esnext.set.add-all.js");
@@ -31,10 +31,9 @@ var _computeKeyValue = require("../utilities/computeKeyValue");
31
31
  var _fieldType = require("../utilities/fieldType");
32
32
  var _hasDependents = require("../introspect/policies/hasDependents");
33
33
  var _config = require("../utilities/config");
34
- const {
35
- rm,
36
- writeFile
37
- } = require('fs/promises');
34
+ var _keyIndexFiles = require("../utilities/keyIndexFiles");
35
+ var _storage = require("../storage");
36
+ var _packedTable = require("../utilities/packedTable");
38
37
  /**
39
38
  * RESTRICT: reject the whole delete (before removing anything) if any row being deleted is still
40
39
  * referenced by a single-field foreign key elsewhere. Only meaningful for a single-field primary
@@ -57,32 +56,45 @@ const assertNoDependents = async (entity, primaryKey, toDelete) => {
57
56
  };
58
57
  /**
59
58
  * A record object carries no memory of which entry file it was read from, and files are not
60
- * guaranteed to be named after any field's value, so the only reliable way to find a record's
61
- * file is to re-scan every entry and match it by its primary key value(s) - a single field, or a
62
- * composite of several for a multi-field primary key.
59
+ * guaranteed to be named after any field's value, so a deleted row's file is found by its primary
60
+ * key value(s) - a single field, or a composite of several for a multi-field primary key. The
61
+ * primary key's index says which files those are (each is read to confirm it); any deleted value
62
+ * the index didn't lead to, or a record without one, is found by looking at every entry, as before.
63
+ * Inserts and updates keep primary key values unique, so each value is one row: only a database
64
+ * edited by hand into two rows of one value, with an index listing just one, would keep the other
65
+ * (looking at every entry used to delete both).
63
66
  * @param entity
64
67
  * @param record
65
68
  * @param primaryKey
66
69
  * @param deletedValues
67
70
  */
68
71
  const removeMatchingEntries = async (entity, record, primaryKey, deletedValues) => {
69
- const databasePath = (0, _config.getSetting)('databasePath', 'database/');
70
- const remainingEntries = [];
71
- for (const fileName of record.entries) {
72
+ const removed = new Set();
73
+ const found = new Set();
74
+ const removeIfDeleted = async fileName => {
72
75
  const data = await (0, _retrieveFile.retrieveFile)(`${record.path}/${fileName}`);
73
- if (!deletedValues.has((0, _computeKeyValue.computeKeyValue)(primaryKey.fields, data))) {
74
- remainingEntries.push(fileName);
75
- continue;
76
+ const value = (0, _computeKeyValue.computeKeyValue)(primaryKey.fields, data);
77
+ if (!deletedValues.has(value)) {
78
+ return;
76
79
  }
77
- await rm(`${databasePath}${record.path}/${fileName}`);
80
+ await (0, _storage.removeFile)(`${record.path}/${fileName}`);
78
81
  for (const key of record.keys) {
79
82
  await (0, _removeFromIndex.removeFromIndex)(record.path, key, (0, _computeKeyValue.computeKeyValue)(key.fields, data), fileName, (0, _fieldType.keyValueType)(record, key));
80
83
  }
84
+ removed.add(fileName);
85
+ found.add(value);
86
+ };
87
+ for (const fileName of (await (0, _keyIndexFiles.keyIndexFiles)(record, primaryKey, value => deletedValues.has(value))) ?? []) {
88
+ await removeIfDeleted(fileName);
81
89
  }
82
- return remainingEntries;
90
+ if (found.size < deletedValues.size) {
91
+ for (const fileName of record.entries.filter(entry => !removed.has(entry))) {
92
+ await removeIfDeleted(fileName);
93
+ }
94
+ }
95
+ return record.entries.filter(fileName => !removed.has(fileName));
83
96
  };
84
97
  const deleteEntity = async (entity = '', dataSet = {}) => {
85
- const databasePath = (0, _config.getSetting)('databasePath', 'database/');
86
98
  const record = await (0, _retrieveRecord.retrieveRecord)(entity);
87
99
  const primaryKey = record.keys.find(key => key.type === 'primary');
88
100
  if (!primaryKey) {
@@ -94,8 +106,12 @@ const deleteEntity = async (entity = '', dataSet = {}) => {
94
106
  }
95
107
  await assertNoDependents(entity, primaryKey, toDelete);
96
108
  const deletedValues = new Set(toDelete.map(row => (0, _computeKeyValue.computeKeyValue)(primaryKey.fields, row)));
97
- record.entries = await removeMatchingEntries(entity, record, primaryKey, deletedValues);
98
- await writeFile(`${databasePath}${record.path}.json`, JSON.stringify(record, null, 2));
109
+ const remaining = await removeMatchingEntries(entity, record, primaryKey, deletedValues);
110
+ if (remaining.length !== record.entries.length) {
111
+ await (0, _packedTable.discardPacked)(record.path);
112
+ }
113
+ record.entries = remaining;
114
+ await (0, _storage.writeJson)(`${record.path}.json`, record);
99
115
  return dataSet;
100
116
  };
101
117
  exports.deleteEntity = deleteEntity;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.deleteEntity=void 0,require("core-js/modules/es.json.stringify.js"),require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.find.js"),require("core-js/modules/esnext.iterator.map.js"),require("core-js/modules/esnext.set.add-all.js"),require("core-js/modules/esnext.set.delete-all.js"),require("core-js/modules/esnext.set.difference.js"),require("core-js/modules/esnext.set.every.js"),require("core-js/modules/esnext.set.filter.js"),require("core-js/modules/esnext.set.find.js"),require("core-js/modules/esnext.set.intersection.js"),require("core-js/modules/esnext.set.is-disjoint-from.js"),require("core-js/modules/esnext.set.is-subset-of.js"),require("core-js/modules/esnext.set.is-superset-of.js"),require("core-js/modules/esnext.set.join.js"),require("core-js/modules/esnext.set.map.js"),require("core-js/modules/esnext.set.reduce.js"),require("core-js/modules/esnext.set.some.js"),require("core-js/modules/esnext.set.symmetric-difference.js"),require("core-js/modules/esnext.set.union.js");var _retrieveRecord=require("../utilities/retrieveRecord"),_retrieveFile=require("../utilities/retrieveFile"),_removeFromIndex=require("../utilities/removeFromIndex"),_computeKeyValue=require("../utilities/computeKeyValue"),_fieldType=require("../utilities/fieldType"),_hasDependents=require("../introspect/policies/hasDependents"),_config=require("../utilities/config");const{rm:rm,writeFile:writeFile}=require("fs/promises"),assertNoDependents=async(e,r,s)=>{if(!(0,_config.getSetting)("enforceForeignKeys",!0)||1!==r.fields.length)return;const t=r.fields[0];for(const r of s)if(await(0,_hasDependents.hasDependents)(e,t,r[t]))throw new Error(`Cannot delete from "${e}" where "${t}" = ${r[t]} - other records still reference it`)},removeMatchingEntries=async(e,r,s,t)=>{const i=(0,_config.getSetting)("databasePath","database/"),o=[];for(const e of r.entries){const n=await(0,_retrieveFile.retrieveFile)(`${r.path}/${e}`);if(t.has((0,_computeKeyValue.computeKeyValue)(s.fields,n))){await rm(`${i}${r.path}/${e}`);for(const s of r.keys)await(0,_removeFromIndex.removeFromIndex)(r.path,s,(0,_computeKeyValue.computeKeyValue)(s.fields,n),e,(0,_fieldType.keyValueType)(r,s))}else o.push(e)}return o},deleteEntity=async(e="",r={})=>{const s=(0,_config.getSetting)("databasePath","database/"),t=await(0,_retrieveRecord.retrieveRecord)(e),i=t.keys.find((e=>"primary"===e.type));if(!i)throw new Error(`Cannot delete from "${e}" without a primary key`);const o=r[e]||[];if(!o.length)return r;await assertNoDependents(e,i,o);const n=new Set(o.map((e=>(0,_computeKeyValue.computeKeyValue)(i.fields,e))));return t.entries=await removeMatchingEntries(0,t,i,n),await writeFile(`${s}${t.path}.json`,JSON.stringify(t,null,2)),r};exports.deleteEntity=deleteEntity;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.deleteEntity=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.filter.js"),require("core-js/modules/esnext.iterator.find.js"),require("core-js/modules/esnext.iterator.map.js"),require("core-js/modules/esnext.set.add-all.js"),require("core-js/modules/esnext.set.delete-all.js"),require("core-js/modules/esnext.set.difference.js"),require("core-js/modules/esnext.set.every.js"),require("core-js/modules/esnext.set.filter.js"),require("core-js/modules/esnext.set.find.js"),require("core-js/modules/esnext.set.intersection.js"),require("core-js/modules/esnext.set.is-disjoint-from.js"),require("core-js/modules/esnext.set.is-subset-of.js"),require("core-js/modules/esnext.set.is-superset-of.js"),require("core-js/modules/esnext.set.join.js"),require("core-js/modules/esnext.set.map.js"),require("core-js/modules/esnext.set.reduce.js"),require("core-js/modules/esnext.set.some.js"),require("core-js/modules/esnext.set.symmetric-difference.js"),require("core-js/modules/esnext.set.union.js");var _retrieveRecord=require("../utilities/retrieveRecord"),_retrieveFile=require("../utilities/retrieveFile"),_removeFromIndex=require("../utilities/removeFromIndex"),_computeKeyValue=require("../utilities/computeKeyValue"),_fieldType=require("../utilities/fieldType"),_hasDependents=require("../introspect/policies/hasDependents"),_config=require("../utilities/config"),_keyIndexFiles=require("../utilities/keyIndexFiles"),_storage=require("../storage"),_packedTable=require("../utilities/packedTable");const assertNoDependents=async(e,r,s)=>{if(!(0,_config.getSetting)("enforceForeignKeys",!0)||1!==r.fields.length)return;const t=r.fields[0];for(const r of s)if(await(0,_hasDependents.hasDependents)(e,t,r[t]))throw new Error(`Cannot delete from "${e}" where "${t}" = ${r[t]} - other records still reference it`)},removeMatchingEntries=async(e,r,s,t)=>{const i=new Set,o=new Set,n=async e=>{const n=await(0,_retrieveFile.retrieveFile)(`${r.path}/${e}`),u=(0,_computeKeyValue.computeKeyValue)(s.fields,n);if(t.has(u)){await(0,_storage.removeFile)(`${r.path}/${e}`);for(const s of r.keys)await(0,_removeFromIndex.removeFromIndex)(r.path,s,(0,_computeKeyValue.computeKeyValue)(s.fields,n),e,(0,_fieldType.keyValueType)(r,s));i.add(e),o.add(u)}};for(const e of await(0,_keyIndexFiles.keyIndexFiles)(r,s,(e=>t.has(e)))??[])await n(e);if(o.size<t.size)for(const e of r.entries.filter((e=>!i.has(e))))await n(e);return r.entries.filter((e=>!i.has(e)))},deleteEntity=async(e="",r={})=>{const s=await(0,_retrieveRecord.retrieveRecord)(e),t=s.keys.find((e=>"primary"===e.type));if(!t)throw new Error(`Cannot delete from "${e}" without a primary key`);const i=r[e]||[];if(!i.length)return r;await assertNoDependents(e,t,i);const o=new Set(i.map((e=>(0,_computeKeyValue.computeKeyValue)(t.fields,e)))),n=await removeMatchingEntries(0,s,t,o);return n.length!==s.entries.length&&await(0,_packedTable.discardPacked)(s.path),s.entries=n,await(0,_storage.writeJson)(`${s.path}.json`,s),r};exports.deleteEntity=deleteEntity;
@@ -1,2 +1,10 @@
1
+ /**
2
+ * Insert rows into a record, all in one statement: every row is checked (against the rows in storage and the rows
3
+ * before it in the statement) and its entry file written, then the record file and each index are written once.
4
+ * Inside a write set (as every query runs, see withWriteSet) a row that fails leaves none of them written.
5
+ * @param entity
6
+ * @param values - The rows, as field -> value.
7
+ * @param dataSet
8
+ */
1
9
  export declare const insertEntity: (entity?: string, values?: Object[], dataSet?: Object) => Promise<Object>;
2
10
  //# sourceMappingURL=insertEntity.d.ts.map