json-fs-query 3.2.0 → 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 (121) hide show
  1. package/README.md +257 -15
  2. package/browser/jsonFsQuery.js +2253 -293
  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 +2 -1
  9. package/dist/data/introspect/create.min.js +1 -1
  10. package/dist/data/introspect/drop.js +2 -0
  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/queries/databaseStatements.d.ts +31 -0
  22. package/dist/data/queries/databaseStatements.js +97 -0
  23. package/dist/data/queries/databaseStatements.min.js +1 -0
  24. package/dist/data/queries/deleteEntity.js +6 -1
  25. package/dist/data/queries/deleteEntity.min.js +1 -1
  26. package/dist/data/queries/insertEntity.d.ts +8 -0
  27. package/dist/data/queries/insertEntity.js +338 -33
  28. package/dist/data/queries/insertEntity.min.js +1 -1
  29. package/dist/data/queries/query.d.ts +2 -1
  30. package/dist/data/queries/query.js +5 -2
  31. package/dist/data/queries/query.min.js +1 -1
  32. package/dist/data/queries/selectFields.d.ts +5 -4
  33. package/dist/data/queries/selectFields.js +25 -11
  34. package/dist/data/queries/selectFields.min.js +1 -1
  35. package/dist/data/queries/updateEntity.js +39 -5
  36. package/dist/data/queries/updateEntity.min.js +1 -1
  37. package/dist/data/storage/databases.d.ts +32 -0
  38. package/dist/data/storage/databases.js +93 -0
  39. package/dist/data/storage/databases.min.js +1 -0
  40. package/dist/data/storage/fileExists.d.ts +2 -1
  41. package/dist/data/storage/fileExists.js +9 -2
  42. package/dist/data/storage/fileExists.min.js +1 -1
  43. package/dist/data/storage/index.d.ts +5 -2
  44. package/dist/data/storage/index.js +64 -1
  45. package/dist/data/storage/index.min.js +1 -1
  46. package/dist/data/storage/listFiles.d.ts +8 -0
  47. package/dist/data/storage/listFiles.js +52 -0
  48. package/dist/data/storage/listFiles.min.js +1 -0
  49. package/dist/data/storage/makeDirectory.d.ts +2 -1
  50. package/dist/data/storage/makeDirectory.js +8 -2
  51. package/dist/data/storage/makeDirectory.min.js +1 -1
  52. package/dist/data/storage/readJson.d.ts +9 -1
  53. package/dist/data/storage/readJson.js +20 -7
  54. package/dist/data/storage/readJson.min.js +1 -1
  55. package/dist/data/storage/removeDirectory.d.ts +3 -1
  56. package/dist/data/storage/removeDirectory.js +7 -1
  57. package/dist/data/storage/removeDirectory.min.js +1 -1
  58. package/dist/data/storage/removeFile.d.ts +2 -1
  59. package/dist/data/storage/removeFile.js +10 -1
  60. package/dist/data/storage/removeFile.min.js +1 -1
  61. package/dist/data/storage/storagePath.js +1 -1
  62. package/dist/data/storage/storagePath.min.js +1 -1
  63. package/dist/data/storage/writeJson.d.ts +12 -3
  64. package/dist/data/storage/writeJson.js +21 -7
  65. package/dist/data/storage/writeJson.min.js +1 -1
  66. package/dist/data/storage/writeSet.d.ts +64 -0
  67. package/dist/data/storage/writeSet.js +306 -0
  68. package/dist/data/storage/writeSet.min.js +1 -0
  69. package/dist/data/utilities/config.d.ts +37 -0
  70. package/dist/data/utilities/config.js +77 -5
  71. package/dist/data/utilities/config.min.js +1 -1
  72. package/dist/data/utilities/databaseLock.d.ts +5 -0
  73. package/dist/data/utilities/databaseLock.js +15 -3
  74. package/dist/data/utilities/databaseLock.min.js +1 -1
  75. package/dist/data/utilities/getConditionIndexedList.js +3 -4
  76. package/dist/data/utilities/getConditionIndexedList.min.js +1 -1
  77. package/dist/data/utilities/indexBuffer.d.ts +35 -0
  78. package/dist/data/utilities/indexBuffer.js +139 -0
  79. package/dist/data/utilities/indexBuffer.min.js +1 -0
  80. package/dist/data/utilities/joinBases.js +2 -10
  81. package/dist/data/utilities/joinBases.min.js +1 -1
  82. package/dist/data/utilities/knownFields.d.ts +26 -0
  83. package/dist/data/utilities/knownFields.js +128 -0
  84. package/dist/data/utilities/knownFields.min.js +1 -0
  85. package/dist/data/utilities/packedTable.d.ts +34 -0
  86. package/dist/data/utilities/packedTable.js +60 -0
  87. package/dist/data/utilities/packedTable.min.js +1 -0
  88. package/dist/data/utilities/parsers/findInsertValues.d.ts +3 -3
  89. package/dist/data/utilities/parsers/findInsertValues.js +28 -12
  90. package/dist/data/utilities/parsers/findInsertValues.min.js +1 -1
  91. package/dist/data/utilities/parsers/maskStrings.js +11 -2
  92. package/dist/data/utilities/parsers/maskStrings.min.js +1 -1
  93. package/dist/data/utilities/parsers/parseAlter.d.ts +33 -0
  94. package/dist/data/utilities/parsers/parseAlter.js +84 -0
  95. package/dist/data/utilities/parsers/parseAlter.min.js +1 -0
  96. package/dist/data/utilities/parsers/parseCreate.d.ts +14 -0
  97. package/dist/data/utilities/parsers/parseCreate.js +13 -5
  98. package/dist/data/utilities/parsers/parseCreate.min.js +1 -1
  99. package/dist/data/utilities/parsers/parseDatabaseStatement.d.ts +17 -0
  100. package/dist/data/utilities/parsers/parseDatabaseStatement.js +82 -0
  101. package/dist/data/utilities/parsers/parseDatabaseStatement.min.js +1 -0
  102. package/dist/data/utilities/parsers/parseQuery.d.ts +3 -0
  103. package/dist/data/utilities/parsers/parseQuery.js +24 -0
  104. package/dist/data/utilities/parsers/parseQuery.min.js +1 -1
  105. package/dist/data/utilities/parsers/startsQuery.js +1 -1
  106. package/dist/data/utilities/parsers/startsQuery.min.js +1 -1
  107. package/dist/data/utilities/retrieveFiles.d.ts +15 -0
  108. package/dist/data/utilities/retrieveFiles.js +48 -0
  109. package/dist/data/utilities/retrieveFiles.min.js +1 -0
  110. package/dist/data/utilities/retrieveRecord.d.ts +6 -0
  111. package/dist/data/utilities/retrieveRecord.js +24 -1
  112. package/dist/data/utilities/retrieveRecord.min.js +1 -1
  113. package/dist/data/utilities/retrieveRecords.d.ts +22 -0
  114. package/dist/data/utilities/retrieveRecords.js +60 -10
  115. package/dist/data/utilities/retrieveRecords.min.js +1 -1
  116. package/dist/data/utilities/runQuery.js +27 -2
  117. package/dist/data/utilities/runQuery.min.js +1 -1
  118. package/dist/index.d.ts +1 -1
  119. package/dist/index.js +24 -0
  120. package/dist/index.min.js +1 -1
  121. package/package.json +7 -3
@@ -3,21 +3,61 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.trackDatabaseCall = exports.resolveDatabasePath = exports.getSetting = exports.configure = void 0;
6
+ exports.trackDatabaseCall = exports.switchDatabase = exports.resolveDatabasePath = exports.lockPath = exports.getSetting = exports.databasesFolder = exports.configure = exports.activeDatabasePath = void 0;
7
+ require("core-js/modules/es.json.stringify.js");
7
8
  const defaults = {
8
9
  databasePath: 'database/',
9
10
  relativePath: '',
10
- enforceForeignKeys: true
11
+ enforceForeignKeys: true,
12
+ readConcurrency: 16,
13
+ format: 'compact'
11
14
  };
12
15
  let settings = {
13
16
  ...defaults
14
17
  };
15
18
  let activeCalls = 0;
19
+ const databaseNameMatch = /^[a-z0-9_-]+$/i;
20
+ const withSlash = path => path.endsWith('/') ? path : `${path}/`;
21
+ /**
22
+ * The folder of the database in use: `<databasesPath>/<database>/` once both are configured (see configure and the
23
+ * `use` statement), otherwise databasePath, as before there could be several.
24
+ */
25
+ const activeDatabasePath = () => settings.databasesPath && settings.database ? `${withSlash(settings.databasesPath)}${settings.database}/` : getSetting('databasePath', 'database/');
26
+ /**
27
+ * The folder whose calls are queued together (see withDatabaseLock): with several databases, all of them, since a
28
+ * call can switch between them (`use`) part way; otherwise the one database.
29
+ */
30
+ exports.activeDatabasePath = activeDatabasePath;
31
+ const lockPath = () => settings.databasesPath ? withSlash(settings.databasesPath) : activeDatabasePath();
32
+ /**
33
+ * The folder holding the databases, for create database, drop database, use and show databases.
34
+ * @throws {Error} When databasesPath isn't configured.
35
+ */
36
+ exports.lockPath = lockPath;
37
+ const databasesFolder = () => {
38
+ if (!settings.databasesPath) {
39
+ throw new Error("Several databases need a folder to hold them: configure({ databasesPath: 'databases/' }) first");
40
+ }
41
+ return withSlash(settings.databasesPath);
42
+ };
43
+ /**
44
+ * Switch the database in use, from inside a call (the `use` statement, which holds the lock for every database in
45
+ * databasesPath, so no other call is running): configure() refuses to while calls run.
46
+ * @param name
47
+ */
48
+ exports.databasesFolder = databasesFolder;
49
+ const switchDatabase = name => {
50
+ settings = {
51
+ ...settings,
52
+ database: name
53
+ };
54
+ };
16
55
  /**
17
56
  * The folder a databasePath points to, so that `database/`, `./database` and its absolute path count as one database.
18
57
  * Node only (only Node calls are counted, see trackDatabaseCall).
19
58
  * @param databasePath
20
59
  */
60
+ exports.switchDatabase = switchDatabase;
21
61
  const resolveDatabasePath = databasePath => require('path').resolve(databasePath);
22
62
  /**
23
63
  * Count a database call (taken by withDatabaseLock as soon as a call is queued) until the returned function is called.
@@ -46,19 +86,51 @@ const trackDatabaseCall = () => {
46
86
  * mirroring MySQL's own foreign_key_checks setting, which is also toggleable rather than always
47
87
  * on, since strict enforcement isn't always what every consumer wants.
48
88
  *
89
+ * readConcurrency (default 16) is how many entry files a read has in flight at once (see retrieveFiles): in a browser,
90
+ * how many requests run together.
91
+ *
92
+ * format (default 'compact') is how files are written: 'compact' (no whitespace: smaller files that parse faster) or
93
+ * 'pretty' (indented by 2 spaces, for reading data in diffs). Either is read; formatDatabase rewrites a whole database
94
+ * in one.
95
+ *
96
+ * packedReads (default: true in a browser, false in Node) is whether reads use a record's packed file (see
97
+ * packDatabase) when it has one that matches the record, instead of reading each entry file.
98
+ *
49
99
  * Changing databasePath while calls are still running or queued throws (see trackDatabaseCall): await them first.
50
100
  * @param newSettings
51
101
  * @throws {Error} When databasePath would point to another folder while database calls are in progress.
102
+ * @throws {Error} When format is neither 'compact' nor 'pretty'.
52
103
  */
53
104
  exports.trackDatabaseCall = trackDatabaseCall;
54
105
  const configure = newSettings => {
55
- if (activeCalls > 0 && typeof newSettings.databasePath !== 'undefined' && resolveDatabasePath(newSettings.databasePath) !== resolveDatabasePath(settings.databasePath)) {
56
- throw new Error(`Can't change databasePath while ${activeCalls} database call(s) are still running or queued: await them first`);
106
+ if (typeof newSettings.format !== 'undefined' && newSettings.format !== 'compact' && newSettings.format !== 'pretty') {
107
+ throw new Error(`Unknown format "${newSettings.format}": use 'compact' or 'pretty'`);
57
108
  }
58
- settings = {
109
+ if (typeof newSettings.database !== 'undefined' && newSettings.database !== null && !databaseNameMatch.test(newSettings.database)) {
110
+ throw new Error(`Invalid database name ${JSON.stringify(newSettings.database)}: names use letters, digits, _ and - only`);
111
+ }
112
+ const next = {
59
113
  ...settings,
60
114
  ...newSettings
61
115
  };
116
+ if (next.database && !next.databasesPath) {
117
+ throw new Error("A database name needs the folder that holds the databases: configure({ databasesPath: 'databases/', database: '...' })");
118
+ }
119
+ if (activeCalls > 0) {
120
+ const before = {
121
+ active: resolveDatabasePath(activeDatabasePath()),
122
+ lock: resolveDatabasePath(lockPath())
123
+ };
124
+ const previous = settings;
125
+ settings = next;
126
+ const changed = resolveDatabasePath(activeDatabasePath()) !== before.active || resolveDatabasePath(lockPath()) !== before.lock;
127
+ settings = previous;
128
+ if (changed) {
129
+ const named = ['databasePath', 'databasesPath', 'database'].filter(key => typeof newSettings[key] !== 'undefined').join(' / ');
130
+ throw new Error(`Can't change ${named} while ${activeCalls} database call(s) are still running or queued: await them first`);
131
+ }
132
+ }
133
+ settings = next;
62
134
  };
63
135
  /**
64
136
  * Read one runtime setting, falling back to the given default if it was never configured. This is
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.trackDatabaseCall=exports.resolveDatabasePath=exports.getSetting=exports.configure=void 0;const defaults={databasePath:"database/",relativePath:"",enforceForeignKeys:!0};let settings={...defaults},activeCalls=0;const resolveDatabasePath=t=>require("path").resolve(t);exports.resolveDatabasePath=resolveDatabasePath;const trackDatabaseCall=()=>{activeCalls++;let t=!1;return()=>{t||(t=!0,activeCalls--)}};exports.trackDatabaseCall=trackDatabaseCall;const configure=t=>{if(activeCalls>0&&void 0!==t.databasePath&&resolveDatabasePath(t.databasePath)!==resolveDatabasePath(settings.databasePath))throw new Error(`Can't change databasePath while ${activeCalls} database call(s) are still running or queued: await them first`);settings={...settings,...t}};exports.configure=configure;const getSetting=(t,a)=>void 0!==settings[t]?settings[t]:a;exports.getSetting=getSetting;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.trackDatabaseCall=exports.switchDatabase=exports.resolveDatabasePath=exports.lockPath=exports.getSetting=exports.databasesFolder=exports.configure=exports.activeDatabasePath=void 0,require("core-js/modules/es.json.stringify.js");const defaults={databasePath:"database/",relativePath:"",enforceForeignKeys:!0,readConcurrency:16,format:"compact"};let settings={...defaults},activeCalls=0;const databaseNameMatch=/^[a-z0-9_-]+$/i,withSlash=a=>a.endsWith("/")?a:`${a}/`,activeDatabasePath=()=>settings.databasesPath&&settings.database?`${withSlash(settings.databasesPath)}${settings.database}/`:getSetting("databasePath","database/");exports.activeDatabasePath=activeDatabasePath;const lockPath=()=>settings.databasesPath?withSlash(settings.databasesPath):activeDatabasePath();exports.lockPath=lockPath;const databasesFolder=()=>{if(!settings.databasesPath)throw new Error("Several databases need a folder to hold them: configure({ databasesPath: 'databases/' }) first");return withSlash(settings.databasesPath)};exports.databasesFolder=databasesFolder;const switchDatabase=a=>{settings={...settings,database:a}};exports.switchDatabase=switchDatabase;const resolveDatabasePath=a=>require("path").resolve(a);exports.resolveDatabasePath=resolveDatabasePath;const trackDatabaseCall=()=>{activeCalls++;let a=!1;return()=>{a||(a=!0,activeCalls--)}};exports.trackDatabaseCall=trackDatabaseCall;const configure=a=>{if(void 0!==a.format&&"compact"!==a.format&&"pretty"!==a.format)throw new Error(`Unknown format "${a.format}": use 'compact' or 'pretty'`);if(void 0!==a.database&&null!==a.database&&!databaseNameMatch.test(a.database))throw new Error(`Invalid database name ${JSON.stringify(a.database)}: names use letters, digits, _ and - only`);const t={...settings,...a};if(t.database&&!t.databasesPath)throw new Error("A database name needs the folder that holds the databases: configure({ databasesPath: 'databases/', database: '...' })");if(activeCalls>0){const e={active:resolveDatabasePath(activeDatabasePath()),lock:resolveDatabasePath(lockPath())},s=settings;settings=t;const o=resolveDatabasePath(activeDatabasePath())!==e.active||resolveDatabasePath(lockPath())!==e.lock;if(settings=s,o){const t=["databasePath","databasesPath","database"].filter((t=>void 0!==a[t])).join(" / ");throw new Error(`Can't change ${t} while ${activeCalls} database call(s) are still running or queued: await them first`)}}settings=t};exports.configure=configure;const getSetting=(a,t)=>void 0!==settings[a]?settings[a]:t;exports.getSetting=getSetting;
@@ -1,3 +1,8 @@
1
+ /**
2
+ * How many calls are running in this browser page right now (they aren't queued there, see withDatabaseLock): `use`
3
+ * refuses to switch the database while any other call is, as that call would carry on in the other database.
4
+ */
5
+ export declare const browserCallsRunning: () => number;
1
6
  /**
2
7
  * Run `task` once every earlier task on the same database (the configured databasePath) has finished, so that calls
3
8
  * never interleave. Every write is several files in turn (an entry, the record's entry list, each index), each read and
@@ -4,7 +4,7 @@ require("core-js/modules/esnext.weak-map.delete-all.js");
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.withDatabaseLock = void 0;
7
+ exports.withDatabaseLock = exports.browserCallsRunning = void 0;
8
8
  require("core-js/modules/esnext.map.delete-all.js");
9
9
  require("core-js/modules/esnext.map.every.js");
10
10
  require("core-js/modules/esnext.map.filter.js");
@@ -24,6 +24,12 @@ var _storage = require("../storage");
24
24
  var e;
25
25
  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; }
26
26
  const queues = new Map();
27
+ let browserCalls = 0;
28
+ /**
29
+ * How many calls are running in this browser page right now (they aren't queued there, see withDatabaseLock): `use`
30
+ * refuses to switch the database while any other call is, as that call would carry on in the other database.
31
+ */
32
+ const browserCallsRunning = () => browserCalls;
27
33
  /**
28
34
  * Run `task` once every earlier task on the same database (the configured databasePath) has finished, so that calls
29
35
  * never interleave. Every write is several files in turn (an entry, the record's entry list, each index), each read and
@@ -40,11 +46,17 @@ const queues = new Map();
40
46
  * runs, so configure() refuses to change it while tasks are queued or running (see trackDatabaseCall).
41
47
  * @param task
42
48
  */
49
+ exports.browserCallsRunning = browserCallsRunning;
43
50
  const withDatabaseLock = async task => {
44
51
  if (!jsEnv.isNode) {
45
- return (0, _storage.withReadCache)(task);
52
+ browserCalls++;
53
+ try {
54
+ return await (0, _storage.withReadCache)(task);
55
+ } finally {
56
+ browserCalls--;
57
+ }
46
58
  }
47
- const database = (0, _config.resolveDatabasePath)((0, _config.getSetting)('databasePath', 'database/'));
59
+ const database = (0, _config.resolveDatabasePath)((0, _config.lockPath)());
48
60
  const ended = (0, _config.trackDatabaseCall)();
49
61
  const previous = queues.get(database) || Promise.resolve();
50
62
  let release;
@@ -1 +1 @@
1
- "use strict";require("core-js/modules/esnext.weak-map.delete-all.js"),Object.defineProperty(exports,"__esModule",{value:!0}),exports.withDatabaseLock=void 0,require("core-js/modules/esnext.map.delete-all.js"),require("core-js/modules/esnext.map.every.js"),require("core-js/modules/esnext.map.filter.js"),require("core-js/modules/esnext.map.find.js"),require("core-js/modules/esnext.map.find-key.js"),require("core-js/modules/esnext.map.includes.js"),require("core-js/modules/esnext.map.key-of.js"),require("core-js/modules/esnext.map.map-keys.js"),require("core-js/modules/esnext.map.map-values.js"),require("core-js/modules/esnext.map.merge.js"),require("core-js/modules/esnext.map.reduce.js"),require("core-js/modules/esnext.map.some.js"),require("core-js/modules/esnext.map.update.js");var e,jsEnv=_interopRequireWildcard(require("browser-or-node")),_config=require("./config"),_storage=require("../storage");function _interopRequireWildcard(s,r){if(!r&&s&&s.__esModule)return s;var t,a,o=Object.defineProperty,u={__proto__:null,default:s};if(Object(s)!==s)return u;if(e||"function"!=typeof WeakMap||(e=new WeakMap),e){if(e.has(s))return e.get(s);e.set(s,u)}for(a in s)"default"!==a&&{}.hasOwnProperty.call(s,a)&&((t=o&&Object.getOwnPropertyDescriptor(s,a))&&(t.get||t.set)?o(u,a,t):u[a]=s[a]);return u}const queues=new Map,withDatabaseLock=async e=>{if(!jsEnv.isNode)return(0,_storage.withReadCache)(e);const s=(0,_config.resolveDatabasePath)((0,_config.getSetting)("databasePath","database/")),r=(0,_config.trackDatabaseCall)(),t=queues.get(s)||Promise.resolve();let a;const o=new Promise((e=>{a=e})),u=t.then((()=>o));queues.set(s,u),await t;try{return await(0,_storage.withReadCache)(e)}finally{r(),a(),queues.get(s)===u&&queues.delete(s)}};exports.withDatabaseLock=withDatabaseLock;
1
+ "use strict";require("core-js/modules/esnext.weak-map.delete-all.js"),Object.defineProperty(exports,"__esModule",{value:!0}),exports.withDatabaseLock=exports.browserCallsRunning=void 0,require("core-js/modules/esnext.map.delete-all.js"),require("core-js/modules/esnext.map.every.js"),require("core-js/modules/esnext.map.filter.js"),require("core-js/modules/esnext.map.find.js"),require("core-js/modules/esnext.map.find-key.js"),require("core-js/modules/esnext.map.includes.js"),require("core-js/modules/esnext.map.key-of.js"),require("core-js/modules/esnext.map.map-keys.js"),require("core-js/modules/esnext.map.map-values.js"),require("core-js/modules/esnext.map.merge.js"),require("core-js/modules/esnext.map.reduce.js"),require("core-js/modules/esnext.map.some.js"),require("core-js/modules/esnext.map.update.js");var e,jsEnv=_interopRequireWildcard(require("browser-or-node")),_config=require("./config"),_storage=require("../storage");function _interopRequireWildcard(r,s){if(!s&&r&&r.__esModule)return r;var t,o,a=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(o in r)"default"!==o&&{}.hasOwnProperty.call(r,o)&&((t=a&&Object.getOwnPropertyDescriptor(r,o))&&(t.get||t.set)?a(n,o,t):n[o]=r[o]);return n}const queues=new Map;let browserCalls=0;const browserCallsRunning=()=>browserCalls;exports.browserCallsRunning=browserCallsRunning;const withDatabaseLock=async e=>{if(!jsEnv.isNode){browserCalls++;try{return await(0,_storage.withReadCache)(e)}finally{browserCalls--}}const r=(0,_config.resolveDatabasePath)((0,_config.lockPath)()),s=(0,_config.trackDatabaseCall)(),t=queues.get(r)||Promise.resolve();let o;const a=new Promise((e=>{o=e})),n=t.then((()=>a));queues.set(r,n),await t;try{return await(0,_storage.withReadCache)(e)}finally{s(),o(),queues.get(r)===n&&queues.delete(r)}};exports.withDatabaseLock=withDatabaseLock;
@@ -28,6 +28,7 @@ var _isEntityProperty = require("./parsers/isEntityProperty");
28
28
  var _splitEntityProperty = require("./parsers/splitEntityProperty");
29
29
  var _retrieveRecord = require("./retrieveRecord");
30
30
  var _where = require("../queries/where");
31
+ var _retrieveRecords = require("./retrieveRecords");
31
32
  var _retrieveFile = require("./retrieveFile");
32
33
  var _retrieveIndexes = require("./retrieveIndexes");
33
34
  var _isSingleFieldKey = require("./isSingleFieldKey");
@@ -149,10 +150,8 @@ const getConditionIndexedList = async (parsed, recordData, dataSet, resolved = n
149
150
  }
150
151
  for (const entity of Object.keys(matchedFiles)) {
151
152
  resolved.add(entity);
152
- dataSet[entity] = [];
153
- for (const file of matchedFiles[entity]) {
154
- dataSet[entity].push(await (0, _retrieveFile.retrieveFile)(`${entity}/${file}`));
155
- }
153
+ const record = recordData[entity] || (await (0, _retrieveRecord.retrieveRecord)(entity));
154
+ dataSet[entity] = await (0, _retrieveRecords.retrieveEntryRows)(record, [...matchedFiles[entity]], _retrieveFile.retrieveFile);
156
155
  }
157
156
  return parsed;
158
157
  };
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.getConditionIndexedList=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.flat-map.js"),require("core-js/modules/esnext.iterator.for-each.js"),require("core-js/modules/esnext.iterator.some.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 _isEntityProperty=require("./parsers/isEntityProperty"),_splitEntityProperty=require("./parsers/splitEntityProperty"),_retrieveRecord=require("./retrieveRecord"),_where=require("../queries/where"),_retrieveFile=require("./retrieveFile"),_retrieveIndexes=require("./retrieveIndexes"),_isSingleFieldKey=require("./isSingleFieldKey"),_conditionTree=require("./conditionTree");const conditionField=(e,r)=>(0,_isEntityProperty.isEntityProperty)(e.property)?(0,_splitEntityProperty.splitEntityProperty)(e.property):{entity:r,property:e.property},indexedFiles=async(e,r,t,s,i)=>{if(Object.prototype.hasOwnProperty.call(s,e)||(s[e]=await(0,_retrieveRecord.retrieveRecord)(e)),s[e].keys.some((e=>(0,_isSingleFieldKey.isSingleFieldKey)(e,r))))return i[e]=i[e]||{},Object.prototype.hasOwnProperty.call(i[e],r)||(i[e][r]=(await(0,_retrieveIndexes.retrieveIndexes)(e,[r],s))[r]),new Set((0,_where.where)(i[e][r],{property:"value",comparator:t.comparator,value:t.value,type:t.type}).flatMap((e=>e.record)))},candidatesOf=async(e,r,t,s)=>{if((0,_conditionTree.isCondition)(e)){const{entity:i,property:o}=conditionField(e,r);return i===r?await indexedFiles(i,o,e,t,s):void 0}if("not"in e)return;if("or"in e){const i=new Set;for(const o of e.or){const e=await candidatesOf(o,r,t,s);if(void 0===e)return;e.forEach((e=>i.add(e)))}return i}let i;for(const o of e.and){const e=await candidatesOf(o,r,t,s);void 0!==e&&(i=void 0===i?e:new Set([...i].filter((r=>e.has(r)))))}return i},getConditionIndexedList=async(e,r,t,s=new Set)=>{const i={},o={};if(void 0!==e.where){const t=await candidatesOf(e.where,e.entity,r,o);void 0!==t&&(i[e.entity]=t)}for(const t of(0,_conditionTree.requiredConditions)(e.where)){const{entity:s,property:n}=conditionField(t,e.entity);if(s===e.entity)continue;const d=await indexedFiles(s,n,t,r,o);void 0!==d&&(i[s]=Object.prototype.hasOwnProperty.call(i,s)?new Set([...i[s]].filter((e=>d.has(e)))):d)}for(const e of Object.keys(i)){s.add(e),t[e]=[];for(const r of i[e])t[e].push(await(0,_retrieveFile.retrieveFile)(`${e}/${r}`))}return e};exports.getConditionIndexedList=getConditionIndexedList;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.getConditionIndexedList=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.flat-map.js"),require("core-js/modules/esnext.iterator.for-each.js"),require("core-js/modules/esnext.iterator.some.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 _isEntityProperty=require("./parsers/isEntityProperty"),_splitEntityProperty=require("./parsers/splitEntityProperty"),_retrieveRecord=require("./retrieveRecord"),_where=require("../queries/where"),_retrieveRecords=require("./retrieveRecords"),_retrieveFile=require("./retrieveFile"),_retrieveIndexes=require("./retrieveIndexes"),_isSingleFieldKey=require("./isSingleFieldKey"),_conditionTree=require("./conditionTree");const conditionField=(e,r)=>(0,_isEntityProperty.isEntityProperty)(e.property)?(0,_splitEntityProperty.splitEntityProperty)(e.property):{entity:r,property:e.property},indexedFiles=async(e,r,t,i,s)=>{if(Object.prototype.hasOwnProperty.call(i,e)||(i[e]=await(0,_retrieveRecord.retrieveRecord)(e)),i[e].keys.some((e=>(0,_isSingleFieldKey.isSingleFieldKey)(e,r))))return s[e]=s[e]||{},Object.prototype.hasOwnProperty.call(s[e],r)||(s[e][r]=(await(0,_retrieveIndexes.retrieveIndexes)(e,[r],i))[r]),new Set((0,_where.where)(s[e][r],{property:"value",comparator:t.comparator,value:t.value,type:t.type}).flatMap((e=>e.record)))},candidatesOf=async(e,r,t,i)=>{if((0,_conditionTree.isCondition)(e)){const{entity:s,property:o}=conditionField(e,r);return s===r?await indexedFiles(s,o,e,t,i):void 0}if("not"in e)return;if("or"in e){const s=new Set;for(const o of e.or){const e=await candidatesOf(o,r,t,i);if(void 0===e)return;e.forEach((e=>s.add(e)))}return s}let s;for(const o of e.and){const e=await candidatesOf(o,r,t,i);void 0!==e&&(s=void 0===s?e:new Set([...s].filter((r=>e.has(r)))))}return s},getConditionIndexedList=async(e,r,t,i=new Set)=>{const s={},o={};if(void 0!==e.where){const t=await candidatesOf(e.where,e.entity,r,o);void 0!==t&&(s[e.entity]=t)}for(const t of(0,_conditionTree.requiredConditions)(e.where)){const{entity:i,property:n}=conditionField(t,e.entity);if(i===e.entity)continue;const d=await indexedFiles(i,n,t,r,o);void 0!==d&&(s[i]=Object.prototype.hasOwnProperty.call(s,i)?new Set([...s[i]].filter((e=>d.has(e)))):d)}for(const e of Object.keys(s)){i.add(e);const o=r[e]||await(0,_retrieveRecord.retrieveRecord)(e);t[e]=await(0,_retrieveRecords.retrieveEntryRows)(o,[...s[e]],_retrieveFile.retrieveFile)}return e};exports.getConditionIndexedList=getConditionIndexedList;
@@ -0,0 +1,35 @@
1
+ import { indexEntry } from './updateIndex';
2
+ /**
3
+ * One index file held in memory while a statement changes it many times: values are found through a Map instead of a
4
+ * search of the whole index each time, and the file is written once at the end (see insertEntity). It holds and
5
+ * changes the index exactly as updateIndex would, one row after another: a new value is added at the end, a file
6
+ * already listed for its value isn't listed twice.
7
+ */
8
+ export declare class IndexBuffer {
9
+ readonly entries: indexEntry[];
10
+ private readonly type;
11
+ private readonly byKey;
12
+ private readonly listed;
13
+ /**
14
+ * @param entries - The index as read from its file ([] when there's none yet).
15
+ * @param type - The key's value type (see keyValueType).
16
+ */
17
+ constructor(entries: indexEntry[], type: string | undefined);
18
+ /**
19
+ * The entry for `value`, as updateIndex finds it.
20
+ * @param value
21
+ */
22
+ find(value: any): indexEntry | undefined;
23
+ /**
24
+ * Whether a row holds `value`, as indexHas answers it: an entry for it lists a file (never for null or undefined).
25
+ * @param value
26
+ */
27
+ has(value: any): boolean;
28
+ /**
29
+ * List `fileName` under `value`, as updateIndex does.
30
+ * @param value
31
+ * @param fileName
32
+ */
33
+ add(value: any, fileName: string): void;
34
+ }
35
+ //# sourceMappingURL=indexBuffer.d.ts.map
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.IndexBuffer = void 0;
7
+ require("core-js/modules/es.array.includes.js");
8
+ require("core-js/modules/esnext.iterator.constructor.js");
9
+ require("core-js/modules/esnext.iterator.find.js");
10
+ require("core-js/modules/esnext.iterator.some.js");
11
+ require("core-js/modules/esnext.map.delete-all.js");
12
+ require("core-js/modules/esnext.map.every.js");
13
+ require("core-js/modules/esnext.map.filter.js");
14
+ require("core-js/modules/esnext.map.find.js");
15
+ require("core-js/modules/esnext.map.find-key.js");
16
+ require("core-js/modules/esnext.map.includes.js");
17
+ require("core-js/modules/esnext.map.key-of.js");
18
+ require("core-js/modules/esnext.map.map-keys.js");
19
+ require("core-js/modules/esnext.map.map-values.js");
20
+ require("core-js/modules/esnext.map.merge.js");
21
+ require("core-js/modules/esnext.map.reduce.js");
22
+ require("core-js/modules/esnext.map.some.js");
23
+ require("core-js/modules/esnext.map.update.js");
24
+ require("core-js/modules/esnext.set.add-all.js");
25
+ require("core-js/modules/esnext.set.delete-all.js");
26
+ require("core-js/modules/esnext.set.difference.js");
27
+ require("core-js/modules/esnext.set.every.js");
28
+ require("core-js/modules/esnext.set.filter.js");
29
+ require("core-js/modules/esnext.set.find.js");
30
+ require("core-js/modules/esnext.set.intersection.js");
31
+ require("core-js/modules/esnext.set.is-disjoint-from.js");
32
+ require("core-js/modules/esnext.set.is-subset-of.js");
33
+ require("core-js/modules/esnext.set.is-superset-of.js");
34
+ require("core-js/modules/esnext.set.join.js");
35
+ require("core-js/modules/esnext.set.map.js");
36
+ require("core-js/modules/esnext.set.reduce.js");
37
+ require("core-js/modules/esnext.set.some.js");
38
+ require("core-js/modules/esnext.set.symmetric-difference.js");
39
+ require("core-js/modules/esnext.set.union.js");
40
+ require("core-js/modules/esnext.weak-map.delete-all.js");
41
+ var _compareAs = require("./compareAs");
42
+ const unkeyed = Symbol('unkeyed');
43
+ /**
44
+ * The key a value is found by in a Map, so that two values share a key exactly when sameValue says they're the same:
45
+ * compareAs gives that for the comparable types (a Map compares keys like ===). Other types compare with ==, and a
46
+ * value compareAs leaves as an object compares by identity, so those are searched in turn instead.
47
+ * @param type
48
+ * @param value
49
+ */
50
+ const keyOf = (type, value) => {
51
+ if (!_compareAs.comparableTypes.includes(type)) {
52
+ return unkeyed;
53
+ }
54
+ const key = (0, _compareAs.compareAs)(type, value);
55
+ return typeof key === 'object' && key !== null ? unkeyed : key;
56
+ };
57
+ /**
58
+ * One index file held in memory while a statement changes it many times: values are found through a Map instead of a
59
+ * search of the whole index each time, and the file is written once at the end (see insertEntity). It holds and
60
+ * changes the index exactly as updateIndex would, one row after another: a new value is added at the end, a file
61
+ * already listed for its value isn't listed twice.
62
+ */
63
+ class IndexBuffer {
64
+ /**
65
+ * @param entries - The index as read from its file ([] when there's none yet).
66
+ * @param type - The key's value type (see keyValueType).
67
+ */
68
+ constructor(entries, type) {
69
+ this.byKey = new Map();
70
+ // The files each entry lists, built when a file is first added to it: a value shared by every row (a foreign key to
71
+ // one parent) would otherwise be searched once per row, which grows with the square of the rows
72
+ this.listed = new WeakMap();
73
+ this.entries = entries;
74
+ this.type = type;
75
+ for (const entry of entries) {
76
+ const key = keyOf(type, entry.value);
77
+ // The first entry for a value is the one updateIndex's find() would give
78
+ if (key !== unkeyed && !this.byKey.has(key)) {
79
+ this.byKey.set(key, entry);
80
+ }
81
+ }
82
+ }
83
+ /**
84
+ * The entry for `value`, as updateIndex finds it.
85
+ * @param value
86
+ */
87
+ find(value) {
88
+ const key = keyOf(this.type, value);
89
+ return key === unkeyed ? this.entries.find(entry => (0, _compareAs.sameValue)(this.type, entry.value, value)) : this.byKey.get(key);
90
+ }
91
+ /**
92
+ * Whether a row holds `value`, as indexHas answers it: an entry for it lists a file (never for null or undefined).
93
+ * @param value
94
+ */
95
+ has(value) {
96
+ // where's = never matches null or a missing value (an index entry for a row without the field has no value)
97
+ if (value === null || typeof value === 'undefined') {
98
+ return false;
99
+ }
100
+ const listsFiles = entry => Boolean(entry && Array.isArray(entry.record) && entry.record.length);
101
+ const first = this.find(value);
102
+ if (!first || listsFiles(first)) {
103
+ // No entry at all for the value (the Map holds the first of each), or one that lists a file
104
+ return listsFiles(first);
105
+ }
106
+ // indexHas looks at every entry for the value; an index edited by hand can hold more than one
107
+ return this.entries.some(entry => (0, _compareAs.sameValue)(this.type, entry.value, value) && listsFiles(entry));
108
+ }
109
+ /**
110
+ * List `fileName` under `value`, as updateIndex does.
111
+ * @param value
112
+ * @param fileName
113
+ */
114
+ add(value, fileName) {
115
+ const existing = this.find(value);
116
+ if (existing) {
117
+ if (!this.listed.has(existing)) {
118
+ this.listed.set(existing, new Set(existing.record));
119
+ }
120
+ const files = this.listed.get(existing);
121
+ if (!files.has(fileName)) {
122
+ files.add(fileName);
123
+ existing.record.push(fileName);
124
+ }
125
+ return;
126
+ }
127
+ const entry = {
128
+ value,
129
+ record: [fileName]
130
+ };
131
+ this.entries.push(entry);
132
+ this.listed.set(entry, new Set(entry.record));
133
+ const key = keyOf(this.type, value);
134
+ if (key !== unkeyed) {
135
+ this.byKey.set(key, entry);
136
+ }
137
+ }
138
+ }
139
+ exports.IndexBuffer = IndexBuffer;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.IndexBuffer=void 0,require("core-js/modules/es.array.includes.js"),require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.find.js"),require("core-js/modules/esnext.iterator.some.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"),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"),require("core-js/modules/esnext.weak-map.delete-all.js");var _compareAs=require("./compareAs");const unkeyed=Symbol("unkeyed"),keyOf=(e,s)=>{if(!_compareAs.comparableTypes.includes(e))return unkeyed;const r=(0,_compareAs.compareAs)(e,s);return"object"==typeof r&&null!==r?unkeyed:r};class IndexBuffer{constructor(e,s){this.byKey=new Map,this.listed=new WeakMap,this.entries=e,this.type=s;for(const r of e){const e=keyOf(s,r.value);e===unkeyed||this.byKey.has(e)||this.byKey.set(e,r)}}find(e){const s=keyOf(this.type,e);return s===unkeyed?this.entries.find((s=>(0,_compareAs.sameValue)(this.type,s.value,e))):this.byKey.get(s)}has(e){if(null==e)return!1;const s=e=>Boolean(e&&Array.isArray(e.record)&&e.record.length),r=this.find(e);return!r||s(r)?s(r):this.entries.some((r=>(0,_compareAs.sameValue)(this.type,r.value,e)&&s(r)))}add(e,s){const r=this.find(e);if(r){this.listed.has(r)||this.listed.set(r,new Set(r.record));const e=this.listed.get(r);return void(e.has(s)||(e.add(s),r.record.push(s)))}const t={value:e,record:[s]};this.entries.push(t),this.listed.set(t,new Set(t.record));const o=keyOf(this.type,e);o!==unkeyed&&this.byKey.set(o,t)}}exports.IndexBuffer=IndexBuffer;
@@ -39,7 +39,7 @@ require("core-js/modules/esnext.set.symmetric-difference.js");
39
39
  require("core-js/modules/esnext.set.union.js");
40
40
  var _readEntity = require("../queries/readEntity");
41
41
  var _retrieveRecord = require("./retrieveRecord");
42
- var _retrieveFile = require("./retrieveFile");
42
+ var _retrieveRecords = require("./retrieveRecords");
43
43
  var _retrieveIndexes = require("./retrieveIndexes");
44
44
  var _joinKey = require("./joinKey");
45
45
  var _rowLookup = require("./rowLookup");
@@ -66,15 +66,7 @@ const indexedRows = async (entity, property, type, others, otherProperty) => {
66
66
  }
67
67
  // In the record's own order, as a full read gives them
68
68
  const record = await (0, _retrieveRecord.retrieveRecord)(entity);
69
- const rows = [];
70
- for (const file of record.entries.filter(entry => files.has(entry))) {
71
- const data = await (0, _retrieveFile.retrieveFile)(`${record.path}/${file}`).catch(err => console.error(err));
72
- if (!data) {
73
- throw new Error(`Could not read entity ${file}`);
74
- }
75
- rows.push(data);
76
- }
77
- return rows;
69
+ return (0, _retrieveRecords.retrieveEntryRows)(record, record.entries.filter(entry => files.has(entry)));
78
70
  };
79
71
  /**
80
72
  * The rows a join reads for each record in it, once for the whole join (every row's join then works from them):
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.joinBases=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.filter.js"),require("core-js/modules/esnext.iterator.for-each.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"),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 _readEntity=require("../queries/readEntity"),_retrieveRecord=require("./retrieveRecord"),_retrieveFile=require("./retrieveFile"),_retrieveIndexes=require("./retrieveIndexes"),_joinKey=require("./joinKey"),_rowLookup=require("./rowLookup");const indexedRows=async(e,r,s,o,t)=>{const i=(await(0,_retrieveIndexes.retrieveIndexes)(e,[r],{}))[r];if(!i)return;const n=new Set(o.map((e=>(0,_joinKey.joinKey)(s,e[t]))).filter((e=>void 0!==e))),u=new Set;for(const e of i)n.has((0,_joinKey.joinKey)(s,e.value))&&e.record.forEach((e=>u.add(e)));const j=await(0,_retrieveRecord.retrieveRecord)(e),d=[];for(const e of j.entries.filter((e=>u.has(e)))){const r=await(0,_retrieveFile.retrieveFile)(`${j.path}/${e}`).catch((e=>console.error(e)));if(!r)throw new Error(`Could not read entity ${e}`);d.push(r)}return d},joinBases=async(e,r,s,o,t)=>{const i=new Map,n=(e,r)=>i.set(e,{rows:r,lookups:new _rowLookup.RowLookups(r)});n(e,s[e]),t&&n(r,s[r]);const u=async e=>(await(0,_readEntity.readEntity)(e,s))[e];for(const e of o){const r=[{name:e.entityA,property:e.propertyA,other:e.entityB,otherProperty:e.propertyB},{name:e.entityB,property:e.propertyB,other:e.entityA,otherProperty:e.propertyA}];for(const{name:s,property:o,other:t,otherProperty:j}of r){if(i.has(s))continue;n(s,("="===e.comparator&&e.typeA===e.typeB&&(0,_joinKey.isKeyedType)(e.typeA)&&i.has(t)?await indexedRows(s,o,e.typeA,i.get(t).rows,j):void 0)??await u(s))}}return i.has(r)||n(r,await u(r)),i};exports.joinBases=joinBases;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.joinBases=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.filter.js"),require("core-js/modules/esnext.iterator.for-each.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"),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 _readEntity=require("../queries/readEntity"),_retrieveRecord=require("./retrieveRecord"),_retrieveRecords=require("./retrieveRecords"),_retrieveIndexes=require("./retrieveIndexes"),_joinKey=require("./joinKey"),_rowLookup=require("./rowLookup");const indexedRows=async(e,r,s,o,t)=>{const i=(await(0,_retrieveIndexes.retrieveIndexes)(e,[r],{}))[r];if(!i)return;const n=new Set(o.map((e=>(0,_joinKey.joinKey)(s,e[t]))).filter((e=>void 0!==e))),u=new Set;for(const e of i)n.has((0,_joinKey.joinKey)(s,e.value))&&e.record.forEach((e=>u.add(e)));const j=await(0,_retrieveRecord.retrieveRecord)(e);return(0,_retrieveRecords.retrieveEntryRows)(j,j.entries.filter((e=>u.has(e))))},joinBases=async(e,r,s,o,t)=>{const i=new Map,n=(e,r)=>i.set(e,{rows:r,lookups:new _rowLookup.RowLookups(r)});n(e,s[e]),t&&n(r,s[r]);const u=async e=>(await(0,_readEntity.readEntity)(e,s))[e];for(const e of o){const r=[{name:e.entityA,property:e.propertyA,other:e.entityB,otherProperty:e.propertyB},{name:e.entityB,property:e.propertyB,other:e.entityA,otherProperty:e.propertyA}];for(const{name:s,property:o,other:t,otherProperty:j}of r){if(i.has(s))continue;n(s,("="===e.comparator&&e.typeA===e.typeB&&(0,_joinKey.isKeyedType)(e.typeA)&&i.has(t)?await indexedRows(s,o,e.typeA,i.get(t).rows,j):void 0)??await u(s))}}return i.has(r)||n(r,await u(r)),i};exports.joinBases=joinBases;
@@ -0,0 +1,26 @@
1
+ import { recordDefinition } from '../introspect/definitions/record';
2
+ /**
3
+ * Throw unless `record` defines every one of `fields`, naming the first that it doesn't and the fields it has: a
4
+ * misspelled field would otherwise be dropped from an insert, stored by an update, or match nothing in a read.
5
+ * @param entity - The record's name, for the message.
6
+ * @param record
7
+ * @param fields
8
+ * @param where - Where the fields were given (`insert`, `set`, `where`...), for the message.
9
+ * @throws {Error} `Unknown field "<field>" in <where>: <entity> has <fields>`.
10
+ */
11
+ export declare const assertFieldsDefined: (entity: string, record: recordDefinition, fields: string[], where: string) => void;
12
+ /**
13
+ * Throw unless every field a query names (in `where`, `sort`, `group by`, `select`, `on`, `merge`, and an insert's or
14
+ * update's values) is defined by its record, before anything is read: the queried record for a plain name, the named
15
+ * one for `<record>.<field>` (any record, as a join through another one names it). In `select`, the joined record's
16
+ * name stands for its rows, and `<record>.<field>` names the queried record's own field or a merged record's (a joined
17
+ * record's rows are a list, with no one value to pick).
18
+ * @param parsed - The parsed query.
19
+ * @param recordData - Records already read, by name (more are read as they're named, and kept here).
20
+ * @throws {Error} `Unknown field ...` (see assertFieldsDefined), or `Record "<name>" doesn't exist` for a record that
21
+ * doesn't.
22
+ */
23
+ export declare const assertKnownFields: (parsed: any, recordData: {
24
+ [entity: string]: recordDefinition;
25
+ }) => Promise<void>;
26
+ //# sourceMappingURL=knownFields.d.ts.map
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.assertKnownFields = exports.assertFieldsDefined = 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.find.js");
10
+ require("core-js/modules/esnext.iterator.flat-map.js");
11
+ require("core-js/modules/esnext.iterator.map.js");
12
+ require("core-js/modules/esnext.set.add-all.js");
13
+ require("core-js/modules/esnext.set.delete-all.js");
14
+ require("core-js/modules/esnext.set.difference.js");
15
+ require("core-js/modules/esnext.set.every.js");
16
+ require("core-js/modules/esnext.set.filter.js");
17
+ require("core-js/modules/esnext.set.find.js");
18
+ require("core-js/modules/esnext.set.intersection.js");
19
+ require("core-js/modules/esnext.set.is-disjoint-from.js");
20
+ require("core-js/modules/esnext.set.is-subset-of.js");
21
+ require("core-js/modules/esnext.set.is-superset-of.js");
22
+ require("core-js/modules/esnext.set.join.js");
23
+ require("core-js/modules/esnext.set.map.js");
24
+ require("core-js/modules/esnext.set.reduce.js");
25
+ require("core-js/modules/esnext.set.some.js");
26
+ require("core-js/modules/esnext.set.symmetric-difference.js");
27
+ require("core-js/modules/esnext.set.union.js");
28
+ var _retrieveRecord = require("./retrieveRecord");
29
+ var _isEntityProperty = require("./parsers/isEntityProperty");
30
+ var _splitEntityProperty = require("./parsers/splitEntityProperty");
31
+ var _conditionTree = require("./conditionTree");
32
+ /**
33
+ * The fields a record defines, for an error message.
34
+ * @param record
35
+ */
36
+ const fieldList = record => record.definition.map(field => field.name).join(', ');
37
+ /**
38
+ * Throw unless `record` defines every one of `fields`, naming the first that it doesn't and the fields it has: a
39
+ * misspelled field would otherwise be dropped from an insert, stored by an update, or match nothing in a read.
40
+ * @param entity - The record's name, for the message.
41
+ * @param record
42
+ * @param fields
43
+ * @param where - Where the fields were given (`insert`, `set`, `where`...), for the message.
44
+ * @throws {Error} `Unknown field "<field>" in <where>: <entity> has <fields>`.
45
+ */
46
+ const assertFieldsDefined = (entity, record, fields, where) => {
47
+ const defined = new Set(record.definition.map(field => field.name));
48
+ const unknown = fields.find(field => !defined.has(field));
49
+ if (typeof unknown !== 'undefined') {
50
+ throw new Error(`Unknown field "${unknown}" in ${where}: ${entity} has ${fieldList(record)}`);
51
+ }
52
+ };
53
+ /**
54
+ * Throw unless every field a query names (in `where`, `sort`, `group by`, `select`, `on`, `merge`, and an insert's or
55
+ * update's values) is defined by its record, before anything is read: the queried record for a plain name, the named
56
+ * one for `<record>.<field>` (any record, as a join through another one names it). In `select`, the joined record's
57
+ * name stands for its rows, and `<record>.<field>` names the queried record's own field or a merged record's (a joined
58
+ * record's rows are a list, with no one value to pick).
59
+ * @param parsed - The parsed query.
60
+ * @param recordData - Records already read, by name (more are read as they're named, and kept here).
61
+ * @throws {Error} `Unknown field ...` (see assertFieldsDefined), or `Record "<name>" doesn't exist` for a record that
62
+ * doesn't.
63
+ */
64
+ exports.assertFieldsDefined = assertFieldsDefined;
65
+ const assertKnownFields = async (parsed, recordData) => {
66
+ // A merged record's fields are on each row as `<record>.<field>`, so select can name them; a joined one's rows are a
67
+ // list, with no one value to pick
68
+ const merged = new Set((parsed.mergeJoins || []).map(merge => (0, _splitEntityProperty.splitEntityProperty)(merge.propertyB).entity));
69
+ const named = [...(0, _conditionTree.conditionsOf)(parsed.where).map(condition => ({
70
+ property: condition.property,
71
+ clause: 'where'
72
+ })), ...(parsed.sortClauses || []).map(sort => ({
73
+ property: sort.property,
74
+ clause: 'sort'
75
+ })), ...(parsed.groupBy || []).map(property => ({
76
+ property,
77
+ clause: 'group by'
78
+ })), ...(parsed.selectClauses || []).filter(select => select.property !== parsed.joinEntity).map(select => ({
79
+ property: select.property,
80
+ clause: 'select'
81
+ })), ...(parsed.insertValues || []).flatMap(row => Object.keys(row || {}).map(property => ({
82
+ property,
83
+ clause: 'insert',
84
+ own: true
85
+ }))), ...Object.keys(parsed.updateValues || {}).map(property => ({
86
+ property,
87
+ clause: 'set',
88
+ own: true
89
+ })), ...(parsed.joinClauses || []).flatMap(join => [{
90
+ property: join.propertyA,
91
+ clause: 'on'
92
+ }, {
93
+ property: join.propertyB,
94
+ clause: 'on'
95
+ }]), ...(parsed.mergeJoins || []).flatMap(merge => [{
96
+ property: merge.propertyA,
97
+ clause: 'merge'
98
+ }, {
99
+ property: merge.propertyB,
100
+ clause: 'merge'
101
+ }])];
102
+ for (const {
103
+ property,
104
+ clause,
105
+ own
106
+ } of named) {
107
+ if (typeof property !== 'string') {
108
+ continue;
109
+ }
110
+ let entity = parsed.entity;
111
+ let field = property;
112
+ // Insert and set values are always the queried record's own fields, whatever their name
113
+ if (!own && (0, _isEntityProperty.isEntityProperty)(property)) {
114
+ ({
115
+ entity,
116
+ property: field
117
+ } = (0, _splitEntityProperty.splitEntityProperty)(property));
118
+ }
119
+ if (clause === 'select' && entity !== parsed.entity && !merged.has(entity)) {
120
+ throw new Error(`Can't select "${property}": a joined record's rows are a list under its name (select ${entity}), ` + `and its fields are on each row only when merged (merge ... with ${entity}.<field>)`);
121
+ }
122
+ if (!Object.prototype.hasOwnProperty.call(recordData, entity)) {
123
+ recordData[entity] = await (0, _retrieveRecord.retrieveRecord)(entity);
124
+ }
125
+ assertFieldsDefined(entity, recordData[entity], [field], clause);
126
+ }
127
+ };
128
+ exports.assertKnownFields = assertKnownFields;