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,17 @@
1
+ export type ParsedDatabaseStatement = {
2
+ command: 'create database' | 'drop database' | 'use' | 'show databases';
3
+ entity: string;
4
+ ifExists: boolean;
5
+ ifNotExists: boolean;
6
+ };
7
+ /**
8
+ * The statements about databases rather than records. `create database (...)` and a bare `drop database` stay a record
9
+ * named "database": these need a database name after the keyword.
10
+ */
11
+ export declare const databaseStatementMatch: RegExp;
12
+ /**
13
+ * Read `create database [if not exists] <name>`, `drop database [if exists] <name>`, `use <name>` or `show databases`.
14
+ * @param query - The statement, with its strings and arrays masked (see maskStrings).
15
+ */
16
+ export declare const parseDatabaseStatement: (query: string) => ParsedDatabaseStatement;
17
+ //# sourceMappingURL=parseDatabaseStatement.d.ts.map
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.parseDatabaseStatement = exports.databaseStatementMatch = void 0;
7
+ var _maskStrings = require("./maskStrings");
8
+ var _startsQuery = require("./startsQuery");
9
+ /**
10
+ * The statements about databases rather than records. `create database (...)` and a bare `drop database` stay a record
11
+ * named "database": these need a database name after the keyword.
12
+ */
13
+ const databaseStatementMatch = exports.databaseStatementMatch = /^\s*(?:(?:create|drop)\s+database\s+(?!\()[a-z0-9_-]|show\s+databases(?![a-z0-9_-])|use(?![a-z0-9_.-]))/i;
14
+ const createMatch = /^\s*create\s+database\s+(if\s+not\s+exists\s+)?([a-z0-9_-]+)/i;
15
+ const dropMatch = /^\s*drop\s+database\s+(if\s+exists\s+)?([a-z0-9_-]+)/i;
16
+ const useMatch = /^\s*use\s+([a-z0-9_-]+)/i;
17
+ const showMatch = /^\s*show\s+databases/i;
18
+ /**
19
+ * Nothing may follow a database statement but the end of the query.
20
+ * @param rest
21
+ */
22
+ const assertNothingAfter = rest => {
23
+ const after = rest.trim();
24
+ if (!after) {
25
+ return;
26
+ }
27
+ const shown = (0, _maskStrings.unmaskStrings)(after, '\'');
28
+ if (_startsQuery.startsQueryMatch.test(after)) {
29
+ throw new Error(`Missing ; before: ${shown}`);
30
+ }
31
+ throw new Error(`Unrecognized query value: ${shown}`);
32
+ };
33
+ /**
34
+ * Read `create database [if not exists] <name>`, `drop database [if exists] <name>`, `use <name>` or `show databases`.
35
+ * @param query - The statement, with its strings and arrays masked (see maskStrings).
36
+ */
37
+ const parseDatabaseStatement = query => {
38
+ const statement = {
39
+ ifExists: false,
40
+ ifNotExists: false
41
+ };
42
+ let found = query.match(createMatch);
43
+ if (found) {
44
+ assertNothingAfter(query.slice(found[0].length));
45
+ return {
46
+ ...statement,
47
+ command: 'create database',
48
+ entity: found[2],
49
+ ifNotExists: Boolean(found[1])
50
+ };
51
+ }
52
+ found = query.match(dropMatch);
53
+ if (found) {
54
+ assertNothingAfter(query.slice(found[0].length));
55
+ return {
56
+ ...statement,
57
+ command: 'drop database',
58
+ entity: found[2],
59
+ ifExists: Boolean(found[1])
60
+ };
61
+ }
62
+ found = query.match(showMatch);
63
+ if (found) {
64
+ assertNothingAfter(query.slice(found[0].length));
65
+ return {
66
+ ...statement,
67
+ command: 'show databases',
68
+ entity: '__DATABASES'
69
+ };
70
+ }
71
+ found = query.match(useMatch);
72
+ if (!found) {
73
+ throw new Error('Expected: use <database>');
74
+ }
75
+ assertNothingAfter(query.slice(found[0].length));
76
+ return {
77
+ ...statement,
78
+ command: 'use',
79
+ entity: found[1]
80
+ };
81
+ };
82
+ exports.parseDatabaseStatement = parseDatabaseStatement;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.parseDatabaseStatement=exports.databaseStatementMatch=void 0;var _maskStrings=require("./maskStrings"),_startsQuery=require("./startsQuery");const databaseStatementMatch=exports.databaseStatementMatch=/^\s*(?:(?:create|drop)\s+database\s+(?!\()[a-z0-9_-]|show\s+databases(?![a-z0-9_-])|use(?![a-z0-9_.-]))/i,createMatch=/^\s*create\s+database\s+(if\s+not\s+exists\s+)?([a-z0-9_-]+)/i,dropMatch=/^\s*drop\s+database\s+(if\s+exists\s+)?([a-z0-9_-]+)/i,useMatch=/^\s*use\s+([a-z0-9_-]+)/i,showMatch=/^\s*show\s+databases/i,assertNothingAfter=t=>{const e=t.trim();if(!e)return;const s=(0,_maskStrings.unmaskStrings)(e,"'");if(_startsQuery.startsQueryMatch.test(e))throw new Error(`Missing ; before: ${s}`);throw new Error(`Unrecognized query value: ${s}`)},parseDatabaseStatement=t=>{const e={ifExists:!1,ifNotExists:!1};let s=t.match(createMatch);if(s)return assertNothingAfter(t.slice(s[0].length)),{...e,command:"create database",entity:s[2],ifNotExists:Boolean(s[1])};if(s=t.match(dropMatch),s)return assertNothingAfter(t.slice(s[0].length)),{...e,command:"drop database",entity:s[2],ifExists:Boolean(s[1])};if(s=t.match(showMatch),s)return assertNothingAfter(t.slice(s[0].length)),{...e,command:"show databases",entity:"__DATABASES"};if(s=t.match(useMatch),!s)throw new Error("Expected: use <database>");return assertNothingAfter(t.slice(s[0].length)),{...e,command:"use",entity:s[1]}};exports.parseDatabaseStatement=parseDatabaseStatement;
@@ -11,6 +11,7 @@ import { ParsedGroupBy } from './findGroupBy';
11
11
  import { ParsedLimit } from './findLimit';
12
12
  import { ParsedOffset } from './findOffset';
13
13
  import { ParsedCreate } from './parseCreate';
14
+ import { ParsedAlter } from './parseAlter';
14
15
  export type ParsedQuery = {
15
16
  command: ParsedCommand | undefined;
16
17
  entity: ParsedEntity | undefined;
@@ -26,6 +27,8 @@ export type ParsedQuery = {
26
27
  limit: ParsedLimit | undefined;
27
28
  offset: ParsedOffset | undefined;
28
29
  create: ParsedCreate | undefined;
30
+ alter?: ParsedAlter;
31
+ ifNotExists?: boolean;
29
32
  ifExists: boolean | undefined;
30
33
  };
31
34
  /**
@@ -20,6 +20,8 @@ var _findOffset = require("./findOffset");
20
20
  var _maskStrings = require("./maskStrings");
21
21
  var _parseCreate = require("./parseCreate");
22
22
  var _parseSchemaStatement = require("./parseSchemaStatement");
23
+ var _parseAlter = require("./parseAlter");
24
+ var _parseDatabaseStatement = require("./parseDatabaseStatement");
23
25
  var _splitClauses = require("./splitClauses");
24
26
  var _startsQuery = require("./startsQuery");
25
27
  // Each clause's own step, and what its body must start with (for the error when it doesn't)
@@ -101,6 +103,11 @@ const parseQuery = query => {
101
103
  };
102
104
  // No find* step may see inside a string or an array: each one becomes a placeholder holding its value
103
105
  query = (0, _maskStrings.maskArrays)((0, _maskStrings.maskStrings)(query));
106
+ // Statements about databases (create / drop database, use, show databases) come first: they share their first words
107
+ // with the record statements
108
+ if (_parseDatabaseStatement.databaseStatementMatch.test(query)) {
109
+ return Object.assign(parsedQuery, (0, _parseDatabaseStatement.parseDatabaseStatement)(query));
110
+ }
104
111
  // A create statement has its own shape (a bracketed list of fields and keys), so it gets its own parser
105
112
  if (_parseCreate.createMatch.test(query)) {
106
113
  const {
@@ -116,6 +123,18 @@ const parseQuery = query => {
116
123
  if (_parseSchemaStatement.schemaStatementMatch.test(query)) {
117
124
  return Object.assign(parsedQuery, (0, _parseSchemaStatement.parseSchemaStatement)(query));
118
125
  }
126
+ // So does alter: one change to a record's fields
127
+ if (_parseAlter.alterMatch.test(query)) {
128
+ const {
129
+ entity,
130
+ alter
131
+ } = (0, _parseAlter.parseAlter)(query);
132
+ return Object.assign(parsedQuery, {
133
+ command: 'alter',
134
+ entity,
135
+ alter
136
+ });
137
+ }
119
138
  // Clauses come at most once each, in a fixed order (see clauseOrder); each step reads only its own clause's body
120
139
  const split = (0, _splitClauses.splitClauses)(query);
121
140
  if (!split) {
@@ -146,6 +165,11 @@ const parseQuery = query => {
146
165
  throw leftoverError(rest, `${keyword} ${body.slice(0, body.length - rest.length).trim()}`);
147
166
  }
148
167
  }
168
+ // `on` joins the record named after the queried one: without it there's nothing to join (this used to fail later,
169
+ // reading a record with no name, as "Could not read .json")
170
+ if ((parsedQuery.joinClauses || []).length && !parsedQuery.joinEntity) {
171
+ throw new Error(`"on" needs the record to join, after the one read: ${parsedQuery.command} ${parsedQuery.entity}.<record> on ...`);
172
+ }
149
173
  return parsedQuery;
150
174
  };
151
175
  exports.parseQuery = parseQuery;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.parseQuery=void 0;var _findCommand=require("./findCommand"),_findInsertValues=require("./findInsertValues"),_findUpdateValues=require("./findUpdateValues"),_findJoinEntity=require("./findJoinEntity"),_findSelects=require("./findSelects"),_findConditions=require("./findConditions"),_conditionTree=require("../conditionTree"),_findJoinClauses=require("./findJoinClauses"),_findMergeJoins=require("./findMergeJoins"),_findSortClauses=require("./findSortClauses"),_findGroupBy=require("./findGroupBy"),_findLimit=require("./findLimit"),_findOffset=require("./findOffset"),_maskStrings=require("./maskStrings"),_parseCreate=require("./parseCreate"),_parseSchemaStatement=require("./parseSchemaStatement"),_splitClauses=require("./splitClauses"),_startsQuery=require("./startsQuery");const clauseSteps={values:{step:_findInsertValues.findInsertValues,expected:"an assignment (field = value)"},set:{step:_findUpdateValues.findUpdateValues,expected:"an assignment (field = value)"},select:{step:_findSelects.findSelects,expected:"a field"},on:{step:_findJoinClauses.findJoinClauses,expected:"a join condition (a.x = b.y)"},merge:{step:_findMergeJoins.findMergeJoins,expected:"a merge (a.x with b.y)"},where:{step:_findConditions.findConditions,expected:"a condition"},"group by":{step:_findGroupBy.findGroupBy,expected:"a field"},sort:{step:_findSortClauses.findSortClauses,expected:"a field"},limit:{step:_findLimit.findLimit,expected:"a whole number"},offset:{step:_findOffset.findOffset,expected:"a whole number"}},leftoverError=(e,t)=>{const i=e=>(0,_maskStrings.unmaskStrings)(e,"'");return _startsQuery.startsQueryMatch.test(e)?new Error(`Missing ; before: ${i(e)}`):new Error(`Unexpected "${i(e)}" after "${i(t)}"`)},parseQuery=e=>{const t={command:void 0,entity:void 0,joinEntity:void 0,selectClauses:[],insertValues:[],updateValues:{},where:void 0,joinClauses:[],mergeJoins:[],sortClauses:[],groupBy:void 0,limit:void 0,offset:void 0,create:void 0,ifExists:void 0};if(e=(0,_maskStrings.maskArrays)((0,_maskStrings.maskStrings)(e)),_parseCreate.createMatch.test(e)){const{entity:i,create:r}=(0,_parseCreate.parseCreate)(e);return Object.assign(t,{command:"create",entity:i,create:r})}if(_parseSchemaStatement.schemaStatementMatch.test(e))return Object.assign(t,(0,_parseSchemaStatement.parseSchemaStatement)(e));const i=(0,_splitClauses.splitClauses)(e);if(!i){if(e=e.trim(),_startsQuery.startsQueryMatch.test(e))throw new Error(`Missing ; before: ${(0,_maskStrings.unmaskStrings)(e,"'")}`);throw new Error(`Unrecognized query value: ${(0,_maskStrings.unmaskStrings)(e,"'")}`)}if((0,_findJoinEntity.findJoinEntity)(t,(0,_findCommand.findCommand)(t,i.head)),t.where=(0,_conditionTree.allOf)([]),i.leading)throw leftoverError(i.leading,i.head);for(const{keyword:e,body:r}of i.clauses){const{step:i,expected:s}=clauseSteps[e],n=i(t,r);if(n===r)throw new Error(`Missing ${s} after ${e}${r?`: ${(0,_maskStrings.unmaskStrings)(r,"'")}`:""}`);if(n)throw leftoverError(n,`${e} ${r.slice(0,r.length-n.length).trim()}`)}return t};exports.parseQuery=parseQuery;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.parseQuery=void 0;var _findCommand=require("./findCommand"),_findInsertValues=require("./findInsertValues"),_findUpdateValues=require("./findUpdateValues"),_findJoinEntity=require("./findJoinEntity"),_findSelects=require("./findSelects"),_findConditions=require("./findConditions"),_conditionTree=require("../conditionTree"),_findJoinClauses=require("./findJoinClauses"),_findMergeJoins=require("./findMergeJoins"),_findSortClauses=require("./findSortClauses"),_findGroupBy=require("./findGroupBy"),_findLimit=require("./findLimit"),_findOffset=require("./findOffset"),_maskStrings=require("./maskStrings"),_parseCreate=require("./parseCreate"),_parseSchemaStatement=require("./parseSchemaStatement"),_parseAlter=require("./parseAlter"),_parseDatabaseStatement=require("./parseDatabaseStatement"),_splitClauses=require("./splitClauses"),_startsQuery=require("./startsQuery");const clauseSteps={values:{step:_findInsertValues.findInsertValues,expected:"an assignment (field = value)"},set:{step:_findUpdateValues.findUpdateValues,expected:"an assignment (field = value)"},select:{step:_findSelects.findSelects,expected:"a field"},on:{step:_findJoinClauses.findJoinClauses,expected:"a join condition (a.x = b.y)"},merge:{step:_findMergeJoins.findMergeJoins,expected:"a merge (a.x with b.y)"},where:{step:_findConditions.findConditions,expected:"a condition"},"group by":{step:_findGroupBy.findGroupBy,expected:"a field"},sort:{step:_findSortClauses.findSortClauses,expected:"a field"},limit:{step:_findLimit.findLimit,expected:"a whole number"},offset:{step:_findOffset.findOffset,expected:"a whole number"}},leftoverError=(e,t)=>{const r=e=>(0,_maskStrings.unmaskStrings)(e,"'");return _startsQuery.startsQueryMatch.test(e)?new Error(`Missing ; before: ${r(e)}`):new Error(`Unexpected "${r(e)}" after "${r(t)}"`)},parseQuery=e=>{const t={command:void 0,entity:void 0,joinEntity:void 0,selectClauses:[],insertValues:[],updateValues:{},where:void 0,joinClauses:[],mergeJoins:[],sortClauses:[],groupBy:void 0,limit:void 0,offset:void 0,create:void 0,ifExists:void 0};if(e=(0,_maskStrings.maskArrays)((0,_maskStrings.maskStrings)(e)),_parseDatabaseStatement.databaseStatementMatch.test(e))return Object.assign(t,(0,_parseDatabaseStatement.parseDatabaseStatement)(e));if(_parseCreate.createMatch.test(e)){const{entity:r,create:s}=(0,_parseCreate.parseCreate)(e);return Object.assign(t,{command:"create",entity:r,create:s})}if(_parseSchemaStatement.schemaStatementMatch.test(e))return Object.assign(t,(0,_parseSchemaStatement.parseSchemaStatement)(e));if(_parseAlter.alterMatch.test(e)){const{entity:r,alter:s}=(0,_parseAlter.parseAlter)(e);return Object.assign(t,{command:"alter",entity:r,alter:s})}const r=(0,_splitClauses.splitClauses)(e);if(!r){if(e=e.trim(),_startsQuery.startsQueryMatch.test(e))throw new Error(`Missing ; before: ${(0,_maskStrings.unmaskStrings)(e,"'")}`);throw new Error(`Unrecognized query value: ${(0,_maskStrings.unmaskStrings)(e,"'")}`)}if((0,_findJoinEntity.findJoinEntity)(t,(0,_findCommand.findCommand)(t,r.head)),t.where=(0,_conditionTree.allOf)([]),r.leading)throw leftoverError(r.leading,r.head);for(const{keyword:e,body:s}of r.clauses){const{step:r,expected:i}=clauseSteps[e],n=r(t,s);if(n===s)throw new Error(`Missing ${i} after ${e}${s?`: ${(0,_maskStrings.unmaskStrings)(s,"'")}`:""}`);if(n)throw leftoverError(n,`${e} ${s.slice(0,s.length-n.length).trim()}`)}if((t.joinClauses||[]).length&&!t.joinEntity)throw new Error(`"on" needs the record to join, after the one read: ${t.command} ${t.entity}.<record> on ...`);return t};exports.parseQuery=parseQuery;
@@ -7,4 +7,4 @@ exports.startsQueryMatch = void 0;
7
7
  /**
8
8
  * Matches text that starts with a command word, for the "Missing ; before" error when a query runs on into the next.
9
9
  */
10
- const startsQueryMatch = exports.startsQueryMatch = /^\s*(create|delete|describe|drop|insert|read|show|update)(?![a-z0-9_-])/i;
10
+ const startsQueryMatch = exports.startsQueryMatch = /^\s*(alter|create|delete|describe|drop|insert|read|show|update|use)(?![a-z0-9_-])/i;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.startsQueryMatch=void 0;const startsQueryMatch=exports.startsQueryMatch=/^\s*(create|delete|describe|drop|insert|read|show|update)(?![a-z0-9_-])/i;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.startsQueryMatch=void 0;const startsQueryMatch=exports.startsQueryMatch=/^\s*(alter|create|delete|describe|drop|insert|read|show|update|use)(?![a-z0-9_-])/i;
@@ -4,15 +4,10 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.recordExists = void 0;
7
- var _config = require("./config");
7
+ var _storage = require("../storage");
8
8
  /**
9
9
  * Whether a record (its `<name>.json` file) exists in the database. Node only, like the schema statements that use it.
10
10
  * @param entity
11
11
  */
12
- const recordExists = entity => {
13
- const {
14
- existsSync
15
- } = require('fs');
16
- return existsSync(`${(0, _config.getSetting)('databasePath', 'database/')}${entity}.json`);
17
- };
12
+ const recordExists = entity => (0, _storage.fileExists)(`${entity}.json`);
18
13
  exports.recordExists = recordExists;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.recordExists=void 0;var _config=require("./config");const recordExists=e=>{const{existsSync:s}=require("fs");return s(`${(0,_config.getSetting)("databasePath","database/")}${e}.json`)};exports.recordExists=recordExists;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.recordExists=void 0;var _storage=require("../storage");const recordExists=e=>(0,_storage.fileExists)(`${e}.json`);exports.recordExists=recordExists;
@@ -5,12 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.registerRecord = void 0;
7
7
  require("core-js/modules/es.array.includes.js");
8
- require("core-js/modules/es.json.stringify.js");
9
- var _config = require("./config");
10
- const {
11
- readFile,
12
- writeFile
13
- } = require('fs/promises');
8
+ var _storage = require("../storage");
14
9
  /**
15
10
  * __RECORDS is itself an ordinary record - path/definition/keys/entries - whose entries are the
16
11
  * filenames of every other record that has been created. This is the schema it's given the first
@@ -49,11 +44,10 @@ const defaultRegistry = () => ({
49
44
  * @param recordName
50
45
  */
51
46
  const registerRecord = async recordName => {
52
- const databasePath = (0, _config.getSetting)('databasePath', 'database/');
53
- const registryPath = `${databasePath}__RECORDS.json`;
47
+ const registryPath = '__RECORDS.json';
54
48
  let registry;
55
49
  try {
56
- registry = JSON.parse(await readFile(registryPath, 'utf8'));
50
+ registry = await (0, _storage.readJson)(registryPath);
57
51
  } catch (err) {
58
52
  registry = defaultRegistry();
59
53
  }
@@ -61,7 +55,7 @@ const registerRecord = async recordName => {
61
55
  if (!registry.entries.includes(fileName)) {
62
56
  registry.entries.push(fileName);
63
57
  }
64
- await writeFile(registryPath, JSON.stringify(registry, null, 2));
58
+ await (0, _storage.writeJson)(registryPath, registry);
65
59
  return registry;
66
60
  };
67
61
  exports.registerRecord = registerRecord;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.registerRecord=void 0,require("core-js/modules/es.array.includes.js"),require("core-js/modules/es.json.stringify.js");var _config=require("./config");const{readFile:readFile,writeFile:writeFile}=require("fs/promises"),defaultRegistry=()=>({path:"",definition:[{name:"path",type:"string",optional:!1,autoGenerate:!1},{name:"definition",type:"object",optional:!1,autoGenerate:!1},{name:"keys",type:"array",optional:!1,autoGenerate:!1},{name:"entries",type:"array",optional:!1,autoGenerate:!1}],keys:[],entries:[]}),registerRecord=async e=>{const t=`${(0,_config.getSetting)("databasePath","database/")}__RECORDS.json`;let r;try{r=JSON.parse(await readFile(t,"utf8"))}catch(e){r=defaultRegistry()}const i=`${e}.json`;return r.entries.includes(i)||r.entries.push(i),await writeFile(t,JSON.stringify(r,null,2)),r};exports.registerRecord=registerRecord;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.registerRecord=void 0,require("core-js/modules/es.array.includes.js");var _storage=require("../storage");const defaultRegistry=()=>({path:"",definition:[{name:"path",type:"string",optional:!1,autoGenerate:!1},{name:"definition",type:"object",optional:!1,autoGenerate:!1},{name:"keys",type:"array",optional:!1,autoGenerate:!1},{name:"entries",type:"array",optional:!1,autoGenerate:!1}],keys:[],entries:[]}),registerRecord=async e=>{const t="__RECORDS.json";let r;try{r=await(0,_storage.readJson)(t)}catch(e){r=defaultRegistry()}const a=`${e}.json`;return r.entries.includes(a)||r.entries.push(a),await(0,_storage.writeJson)(t,r),r};exports.registerRecord=registerRecord;
@@ -4,16 +4,11 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.removeFromIndex = void 0;
7
- require("core-js/modules/es.json.stringify.js");
8
7
  require("core-js/modules/esnext.iterator.constructor.js");
9
8
  require("core-js/modules/esnext.iterator.filter.js");
10
9
  require("core-js/modules/esnext.iterator.map.js");
11
- var _config = require("./config");
12
10
  var _compareAs = require("./compareAs");
13
- const {
14
- readFile,
15
- writeFile
16
- } = require('fs/promises');
11
+ var _storage = require("../storage");
17
12
  /**
18
13
  * Remove a single entry file from the index that backs one of a record's keys, dropping a value
19
14
  * entirely once its last file is removed. A key with no lookup, or an index file that doesn't
@@ -28,11 +23,10 @@ const removeFromIndex = async (path = '', key = null, value = undefined, fileNam
28
23
  if (!key || !key.lookup) {
29
24
  return null;
30
25
  }
31
- const databasePath = (0, _config.getSetting)('databasePath', 'database/');
32
- const indexPath = `${databasePath}__indexes/${path}/${key.lookup}`;
26
+ const indexPath = `__indexes/${path}/${key.lookup}`;
33
27
  let index = [];
34
28
  try {
35
- index = JSON.parse(await readFile(indexPath, 'utf8'));
29
+ index = await (0, _storage.readJson)(indexPath);
36
30
  } catch (err) {
37
31
  return null;
38
32
  }
@@ -40,7 +34,7 @@ const removeFromIndex = async (path = '', key = null, value = undefined, fileNam
40
34
  value: entry.value,
41
35
  record: entry.record.filter(record => record !== fileName)
42
36
  } : entry).filter(entry => entry.record.length);
43
- await writeFile(indexPath, JSON.stringify(index, null, 2));
37
+ await (0, _storage.writeJson)(indexPath, index);
44
38
  return index;
45
39
  };
46
40
  exports.removeFromIndex = removeFromIndex;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.removeFromIndex=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");var _config=require("./config"),_compareAs=require("./compareAs");const{readFile:readFile,writeFile:writeFile}=require("fs/promises"),removeFromIndex=async(e="",r=null,o=void 0,t="",i=void 0)=>{if(!r||!r.lookup)return null;const s=`${(0,_config.getSetting)("databasePath","database/")}__indexes/${e}/${r.lookup}`;let a=[];try{a=JSON.parse(await readFile(s,"utf8"))}catch(e){return null}return a=a.map((e=>(0,_compareAs.sameValue)(i,e.value,o)?{value:e.value,record:e.record.filter((e=>e!==t))}:e)).filter((e=>e.record.length)),await writeFile(s,JSON.stringify(a,null,2)),a};exports.removeFromIndex=removeFromIndex;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.removeFromIndex=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.filter.js"),require("core-js/modules/esnext.iterator.map.js");var _compareAs=require("./compareAs"),_storage=require("../storage");const removeFromIndex=async(e="",r=null,o=void 0,t="",s=void 0)=>{if(!r||!r.lookup)return null;const a=`__indexes/${e}/${r.lookup}`;let u=[];try{u=await(0,_storage.readJson)(a)}catch(e){return null}return u=u.map((e=>(0,_compareAs.sameValue)(s,e.value,o)?{value:e.value,record:e.record.filter((e=>e!==t))}:e)).filter((e=>e.record.length)),await(0,_storage.writeJson)(a,u),u};exports.removeFromIndex=removeFromIndex;
@@ -1,2 +1,7 @@
1
+ /**
2
+ * Read one JSON file of the database (see readJson), logging the underlying error and throwing one that names the file.
3
+ * @param path - A path inside the database, such as `users.json`.
4
+ * @throws {Error} `Could not read <path>` when the file can't be read.
5
+ */
1
6
  export declare const retrieveFile: (path: any) => Promise<any>;
2
7
  //# sourceMappingURL=retrieveFile.d.ts.map
@@ -1,26 +1,17 @@
1
1
  "use strict";
2
2
 
3
- require("core-js/modules/esnext.weak-map.delete-all.js");
4
3
  Object.defineProperty(exports, "__esModule", {
5
4
  value: true
6
5
  });
7
6
  exports.retrieveFile = void 0;
8
- var jsEnv = _interopRequireWildcard(require("browser-or-node"));
9
- var _config = require("./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; }
7
+ var _storage = require("../storage");
8
+ /**
9
+ * Read one JSON file of the database (see readJson), logging the underlying error and throwing one that names the file.
10
+ * @param path - A path inside the database, such as `users.json`.
11
+ * @throws {Error} `Could not read <path>` when the file can't be read.
12
+ */
12
13
  const retrieveFile = async path => {
13
- let retrieveFn = url => fetch(url).then(res => res.json());
14
- const relativePath = jsEnv.isBrowser ? (0, _config.getSetting)('relativePath', '') : '';
15
- if (jsEnv.isNode) {
16
- const {
17
- readFile
18
- } = require('fs/promises');
19
- retrieveFn = url => readFile(url).then(res => JSON.parse(res));
20
- }
21
- const databasePath = (0, _config.getSetting)('databasePath', 'database/');
22
- const fetchUrl = `${relativePath}${databasePath}${path}`;
23
- const recordInfo = await retrieveFn(fetchUrl).catch(err => console.error(err));
14
+ const recordInfo = await (0, _storage.readJson)(path).catch(err => console.error(err));
24
15
  if (!recordInfo) {
25
16
  throw new Error(`Could not read ${path}`);
26
17
  }
@@ -1 +1 @@
1
- "use strict";require("core-js/modules/esnext.weak-map.delete-all.js"),Object.defineProperty(exports,"__esModule",{value:!0}),exports.retrieveFile=void 0;var e,jsEnv=_interopRequireWildcard(require("browser-or-node")),_config=require("./config");function _interopRequireWildcard(r,t){if(!t&&r&&r.__esModule)return r;var i,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)&&((i=n&&Object.getOwnPropertyDescriptor(r,o))&&(i.get||i.set)?n(s,o,i):s[o]=r[o]);return s}const retrieveFile=async e=>{let r=e=>fetch(e).then((e=>e.json()));const t=jsEnv.isBrowser?(0,_config.getSetting)("relativePath",""):"";if(jsEnv.isNode){const{readFile:e}=require("fs/promises");r=r=>e(r).then((e=>JSON.parse(e)))}const i=`${t}${(0,_config.getSetting)("databasePath","database/")}${e}`,o=await r(i).catch((e=>console.error(e)));if(!o)throw new Error(`Could not read ${e}`);return o};exports.retrieveFile=retrieveFile;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.retrieveFile=void 0;var _storage=require("../storage");const retrieveFile=async e=>{const r=await(0,_storage.readJson)(e).catch((e=>console.error(e)));if(!r)throw new Error(`Could not read ${e}`);return r};exports.retrieveFile=retrieveFile;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Read several files of the database at once and resolve to their contents in the order of `paths`. Up to
3
+ * `readConcurrency` reads (see configure) are in flight together: in a browser each file is an HTTP request, so a full
4
+ * read of 1,000 rows no longer waits for 1,000 requests one after another.
5
+ *
6
+ * Fails as reading them one at a time would: with the error of the first file (in `paths` order) that can't be read.
7
+ * Once a read fails no new ones start; the ones already started are awaited, so none is left running after this
8
+ * returns, and since reads start in order, every file before the first failure was read.
9
+ * @param paths - Paths inside the database, such as `users/1.json`.
10
+ * @param read - Reads one path (default retrieveFile); callers with their own error message for a missing file pass it
11
+ * here.
12
+ * @throws {Error} The error of the first file that couldn't be read.
13
+ */
14
+ export declare const retrieveFiles: (paths: string[], read?: (path: string) => Promise<any>) => Promise<any[]>;
15
+ //# sourceMappingURL=retrieveFiles.d.ts.map
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.retrieveFiles = void 0;
7
+ var _retrieveFile = require("./retrieveFile");
8
+ var _config = require("./config");
9
+ /**
10
+ * Read several files of the database at once and resolve to their contents in the order of `paths`. Up to
11
+ * `readConcurrency` reads (see configure) are in flight together: in a browser each file is an HTTP request, so a full
12
+ * read of 1,000 rows no longer waits for 1,000 requests one after another.
13
+ *
14
+ * Fails as reading them one at a time would: with the error of the first file (in `paths` order) that can't be read.
15
+ * Once a read fails no new ones start; the ones already started are awaited, so none is left running after this
16
+ * returns, and since reads start in order, every file before the first failure was read.
17
+ * @param paths - Paths inside the database, such as `users/1.json`.
18
+ * @param read - Reads one path (default retrieveFile); callers with their own error message for a missing file pass it
19
+ * here.
20
+ * @throws {Error} The error of the first file that couldn't be read.
21
+ */
22
+ const retrieveFiles = async (paths, read = _retrieveFile.retrieveFile) => {
23
+ const limit = Math.max(1, Math.floor((0, _config.getSetting)('readConcurrency', 16)) || 1);
24
+ const contents = new Array(paths.length);
25
+ const failures = [];
26
+ let next = 0;
27
+ const worker = async () => {
28
+ while (next < paths.length && !failures.length) {
29
+ const position = next++;
30
+ try {
31
+ contents[position] = await read(paths[position]);
32
+ } catch (error) {
33
+ failures.push({
34
+ position,
35
+ error
36
+ });
37
+ }
38
+ }
39
+ };
40
+ await Promise.all(Array.from({
41
+ length: Math.min(limit, paths.length)
42
+ }, worker));
43
+ if (failures.length) {
44
+ throw failures.reduce((first, failure) => failure.position < first.position ? failure : first).error;
45
+ }
46
+ return contents;
47
+ };
48
+ exports.retrieveFiles = retrieveFiles;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.retrieveFiles=void 0;var _retrieveFile=require("./retrieveFile"),_config=require("./config");const retrieveFiles=async(e,r=_retrieveFile.retrieveFile)=>{const t=Math.max(1,Math.floor((0,_config.getSetting)("readConcurrency",16))||1),i=new Array(e.length),o=[];let n=0;if(await Promise.all(Array.from({length:Math.min(t,e.length)},(async()=>{for(;n<e.length&&!o.length;){const t=n++;try{i[t]=await r(e[t])}catch(e){o.push({position:t,error:e})}}}))),o.length)throw o.reduce(((e,r)=>r.position<e.position?r:e)).error;return i};exports.retrieveFiles=retrieveFiles;
@@ -1,2 +1,8 @@
1
+ /**
2
+ * A record's definition (its fields, keys and entries), from `<entity>.json`.
3
+ * @param entity
4
+ * @throws {Error} `Record "<entity>" doesn't exist` when it doesn't (in Node, checked before reading; in a browser,
5
+ * where that can't be checked without reading, when the file can't be read).
6
+ */
1
7
  export declare const retrieveRecord: (entity?: string) => Promise<any>;
2
8
  //# sourceMappingURL=retrieveRecord.d.ts.map
@@ -1,9 +1,32 @@
1
1
  "use strict";
2
2
 
3
+ require("core-js/modules/esnext.weak-map.delete-all.js");
3
4
  Object.defineProperty(exports, "__esModule", {
4
5
  value: true
5
6
  });
6
7
  exports.retrieveRecord = void 0;
8
+ var jsEnv = _interopRequireWildcard(require("browser-or-node"));
7
9
  var _retrieveFile = require("./retrieveFile");
8
- const retrieveRecord = async (entity = '') => await (0, _retrieveFile.retrieveFile)(`${entity}.json`);
10
+ var _recordExists = require("./recordExists");
11
+ var e;
12
+ 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; }
13
+ /**
14
+ * A record's definition (its fields, keys and entries), from `<entity>.json`.
15
+ * @param entity
16
+ * @throws {Error} `Record "<entity>" doesn't exist` when it doesn't (in Node, checked before reading; in a browser,
17
+ * where that can't be checked without reading, when the file can't be read).
18
+ */
19
+ const retrieveRecord = async (entity = '') => {
20
+ if (jsEnv.isNode && !(0, _recordExists.recordExists)(entity)) {
21
+ throw new Error(`Record "${entity}" doesn't exist`);
22
+ }
23
+ try {
24
+ return await (0, _retrieveFile.retrieveFile)(`${entity}.json`);
25
+ } catch (error) {
26
+ if (!jsEnv.isNode) {
27
+ throw new Error(`Record "${entity}" doesn't exist, or ${entity}.json can't be read`);
28
+ }
29
+ throw error;
30
+ }
31
+ };
9
32
  exports.retrieveRecord = retrieveRecord;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.retrieveRecord=void 0;var _retrieveFile=require("./retrieveFile");const retrieveRecord=async(e="")=>await(0,_retrieveFile.retrieveFile)(`${e}.json`);exports.retrieveRecord=retrieveRecord;
1
+ "use strict";require("core-js/modules/esnext.weak-map.delete-all.js"),Object.defineProperty(exports,"__esModule",{value:!0}),exports.retrieveRecord=void 0;var e,jsEnv=_interopRequireWildcard(require("browser-or-node")),_retrieveFile=require("./retrieveFile"),_recordExists=require("./recordExists");function _interopRequireWildcard(r,t){if(!t&&r&&r.__esModule)return r;var o,i,s=Object.defineProperty,n={__proto__:null,default:r};if(Object(r)!==r)return n;if(e||"function"!=typeof WeakMap||(e=new WeakMap),e){if(e.has(r))return e.get(r);e.set(r,n)}for(i in r)"default"!==i&&{}.hasOwnProperty.call(r,i)&&((o=s&&Object.getOwnPropertyDescriptor(r,i))&&(o.get||o.set)?s(n,i,o):n[i]=r[i]);return n}const retrieveRecord=async(e="")=>{if(jsEnv.isNode&&!(0,_recordExists.recordExists)(e))throw new Error(`Record "${e}" doesn't exist`);try{return await(0,_retrieveFile.retrieveFile)(`${e}.json`)}catch(r){if(!jsEnv.isNode)throw new Error(`Record "${e}" doesn't exist, or ${e}.json can't be read`);throw r}};exports.retrieveRecord=retrieveRecord;
@@ -1,2 +1,24 @@
1
+ import { recordDefinition } from '../introspect/definitions/record';
2
+ /**
3
+ * Read one entry file, failing with the message a missing entry has always had.
4
+ * @param path - The entry's path inside the database, such as `users/1.json`.
5
+ */
6
+ export declare const retrieveEntry: (path: string) => Promise<any>;
7
+ /**
8
+ * The rows of some of a record's entry files, in the order of `files`. When they're more than one round of reads
9
+ * (`readConcurrency`, see retrieveFiles) and the record has a packed file that matches it (see retrievePacked), they
10
+ * come from the packed file in one read; otherwise, and for any file the packed file doesn't hold (an index can list a
11
+ * file the record doesn't), from the entry files, several at a time. So a lookup of a few rows never downloads a whole
12
+ * record, and a record of a few rows is never asked for a packed file.
13
+ * @param record
14
+ * @param files - Entry file names, such as `1.json`.
15
+ * @param read - Reads one entry file (default retrieveEntry).
16
+ */
17
+ export declare const retrieveEntryRows: (record: recordDefinition, files: string[], read?: (path: string) => Promise<any>) => Promise<any[]>;
18
+ /**
19
+ * Every row of a record, in the record's order: from its packed file when there's one that matches (see
20
+ * retrievePacked), otherwise from its entry files, several at a time (see retrieveFiles).
21
+ * @param entity
22
+ */
1
23
  export declare const retrieveRecords: (entity?: string) => Promise<any[]>;
2
24
  //# sourceMappingURL=retrieveRecords.d.ts.map
@@ -3,19 +3,69 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.retrieveRecords = void 0;
6
+ exports.retrieveRecords = exports.retrieveEntryRows = exports.retrieveEntry = void 0;
7
+ require("core-js/modules/esnext.iterator.constructor.js");
8
+ require("core-js/modules/esnext.iterator.filter.js");
9
+ require("core-js/modules/esnext.iterator.map.js");
10
+ require("core-js/modules/esnext.map.delete-all.js");
11
+ require("core-js/modules/esnext.map.every.js");
12
+ require("core-js/modules/esnext.map.filter.js");
13
+ require("core-js/modules/esnext.map.find.js");
14
+ require("core-js/modules/esnext.map.find-key.js");
15
+ require("core-js/modules/esnext.map.includes.js");
16
+ require("core-js/modules/esnext.map.key-of.js");
17
+ require("core-js/modules/esnext.map.map-keys.js");
18
+ require("core-js/modules/esnext.map.map-values.js");
19
+ require("core-js/modules/esnext.map.merge.js");
20
+ require("core-js/modules/esnext.map.reduce.js");
21
+ require("core-js/modules/esnext.map.some.js");
22
+ require("core-js/modules/esnext.map.update.js");
7
23
  var _retrieveFile = require("./retrieveFile");
8
24
  var _retrieveRecord = require("./retrieveRecord");
25
+ var _retrieveFiles = require("./retrieveFiles");
26
+ var _packedTable = require("./packedTable");
27
+ var _config = require("./config");
28
+ /**
29
+ * Read one entry file, failing with the message a missing entry has always had.
30
+ * @param path - The entry's path inside the database, such as `users/1.json`.
31
+ */
32
+ const retrieveEntry = async path => {
33
+ const data = await (0, _retrieveFile.retrieveFile)(path).catch(err => console.error(err));
34
+ if (!data) {
35
+ throw new Error(`Could not read entity ${path.slice(path.lastIndexOf('/') + 1)}`);
36
+ }
37
+ return data;
38
+ };
39
+ /**
40
+ * The rows of some of a record's entry files, in the order of `files`. When they're more than one round of reads
41
+ * (`readConcurrency`, see retrieveFiles) and the record has a packed file that matches it (see retrievePacked), they
42
+ * come from the packed file in one read; otherwise, and for any file the packed file doesn't hold (an index can list a
43
+ * file the record doesn't), from the entry files, several at a time. So a lookup of a few rows never downloads a whole
44
+ * record, and a record of a few rows is never asked for a packed file.
45
+ * @param record
46
+ * @param files - Entry file names, such as `1.json`.
47
+ * @param read - Reads one entry file (default retrieveEntry).
48
+ */
49
+ exports.retrieveEntry = retrieveEntry;
50
+ const retrieveEntryRows = async (record, files, read = retrieveEntry) => {
51
+ const packed = files.length > (0, _config.getSetting)('readConcurrency', 16) ? await (0, _packedTable.retrievePacked)(record) : undefined;
52
+ if (!packed) {
53
+ return (0, _retrieveFiles.retrieveFiles)(files.map(file => `${record.path}/${file}`), read);
54
+ }
55
+ const positions = new Map(packed.entries.map((entry, position) => [entry, position]));
56
+ const unpacked = files.filter(file => !positions.has(file));
57
+ const readRows = unpacked.length ? await (0, _retrieveFiles.retrieveFiles)(unpacked.map(file => `${record.path}/${file}`), read) : [];
58
+ const fromFiles = new Map(unpacked.map((file, position) => [file, readRows[position]]));
59
+ return files.map(file => positions.has(file) ? packed.rows[positions.get(file)] : fromFiles.get(file));
60
+ };
61
+ /**
62
+ * Every row of a record, in the record's order: from its packed file when there's one that matches (see
63
+ * retrievePacked), otherwise from its entry files, several at a time (see retrieveFiles).
64
+ * @param entity
65
+ */
66
+ exports.retrieveEntryRows = retrieveEntryRows;
9
67
  const retrieveRecords = async (entity = '') => {
10
68
  const recordFile = await (0, _retrieveRecord.retrieveRecord)(entity);
11
- const dataSet = [];
12
- for (const file of recordFile.entries) {
13
- const data = await (0, _retrieveFile.retrieveFile)(`${recordFile.path}/${file}`).catch(err => console.error(err));
14
- if (!data) {
15
- throw new Error(`Could not read entity ${file}`);
16
- }
17
- dataSet.push(data);
18
- }
19
- return dataSet;
69
+ return retrieveEntryRows(recordFile, recordFile.entries);
20
70
  };
21
71
  exports.retrieveRecords = retrieveRecords;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.retrieveRecords=void 0;var _retrieveFile=require("./retrieveFile"),_retrieveRecord=require("./retrieveRecord");const retrieveRecords=async(e="")=>{const r=await(0,_retrieveRecord.retrieveRecord)(e),t=[];for(const e of r.entries){const o=await(0,_retrieveFile.retrieveFile)(`${r.path}/${e}`).catch((e=>console.error(e)));if(!o)throw new Error(`Could not read entity ${e}`);t.push(o)}return t};exports.retrieveRecords=retrieveRecords;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.retrieveRecords=exports.retrieveEntryRows=exports.retrieveEntry=void 0,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.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 _retrieveFile=require("./retrieveFile"),_retrieveRecord=require("./retrieveRecord"),_retrieveFiles=require("./retrieveFiles"),_packedTable=require("./packedTable"),_config=require("./config");const retrieveEntry=async e=>{const r=await(0,_retrieveFile.retrieveFile)(e).catch((e=>console.error(e)));if(!r)throw new Error(`Could not read entity ${e.slice(e.lastIndexOf("/")+1)}`);return r};exports.retrieveEntry=retrieveEntry;const retrieveEntryRows=async(e,r,s=retrieveEntry)=>{const t=r.length>(0,_config.getSetting)("readConcurrency",16)?await(0,_packedTable.retrievePacked)(e):void 0;if(!t)return(0,_retrieveFiles.retrieveFiles)(r.map((r=>`${e.path}/${r}`)),s);const i=new Map(t.entries.map(((e,r)=>[e,r]))),o=r.filter((e=>!i.has(e))),n=o.length?await(0,_retrieveFiles.retrieveFiles)(o.map((r=>`${e.path}/${r}`)),s):[],a=new Map(o.map(((e,r)=>[e,n[r]])));return r.map((e=>i.has(e)?t.rows[i.get(e)]:a.get(e)))};exports.retrieveEntryRows=retrieveEntryRows;const retrieveRecords=async(e="")=>{const r=await(0,_retrieveRecord.retrieveRecord)(e);return retrieveEntryRows(r,r.entries)};exports.retrieveRecords=retrieveRecords;