json-fs-query 3.2.0 → 3.3.1

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 (124) hide show
  1. package/README.md +265 -17
  2. package/browser/jsonFsQuery.js +2274 -305
  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 +8 -2
  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 +342 -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/reconcileJoin.d.ts +12 -0
  108. package/dist/data/utilities/reconcileJoin.js +30 -10
  109. package/dist/data/utilities/reconcileJoin.min.js +1 -1
  110. package/dist/data/utilities/retrieveFiles.d.ts +15 -0
  111. package/dist/data/utilities/retrieveFiles.js +48 -0
  112. package/dist/data/utilities/retrieveFiles.min.js +1 -0
  113. package/dist/data/utilities/retrieveRecord.d.ts +6 -0
  114. package/dist/data/utilities/retrieveRecord.js +24 -1
  115. package/dist/data/utilities/retrieveRecord.min.js +1 -1
  116. package/dist/data/utilities/retrieveRecords.d.ts +22 -0
  117. package/dist/data/utilities/retrieveRecords.js +60 -10
  118. package/dist/data/utilities/retrieveRecords.min.js +1 -1
  119. package/dist/data/utilities/runQuery.js +27 -2
  120. package/dist/data/utilities/runQuery.min.js +1 -1
  121. package/dist/index.d.ts +1 -1
  122. package/dist/index.js +24 -0
  123. package/dist/index.min.js +1 -1
  124. package/package.json +8 -4
@@ -3375,11 +3375,18 @@ var jsonFsQuery = (() => {
3375
3375
  }
3376
3376
  }
3377
3377
  }
3378
- return strings.reduceRight((masked, {
3378
+ const parts = [];
3379
+ let copied = 0;
3380
+ for (const {
3379
3381
  start,
3380
3382
  end,
3381
3383
  value
3382
- }) => `${masked.slice(0, start)}\0${toHex(value)}\0${masked.slice(end)}`, query);
3384
+ } of strings) {
3385
+ parts.push(query.slice(copied, start), `\0${toHex(value)}\0`);
3386
+ copied = end;
3387
+ }
3388
+ parts.push(query.slice(copied));
3389
+ return parts.join("");
3383
3390
  };
3384
3391
  exports.maskStrings = maskStrings;
3385
3392
  var unmaskStrings = (text, quote = "json") => text.replace(placeholderMatch, (placeholder, hex) => {
@@ -3486,20 +3493,31 @@ var jsonFsQuery = (() => {
3486
3493
  var _parseLiteralValue = require_parseLiteralValue();
3487
3494
  var _maskStrings = require_maskStrings();
3488
3495
  var literal = `(?:${_maskStrings.placeholderSource.replace("(", "(?:")}|${_parseLiteralValue.numberSource}|${_maskStrings.arraySource.replace("(", "(?:")}|null|true|false)`;
3489
- var valuesMatch = new RegExp(`^([a-z0-9_-]+\\s*=\\s*${literal}(?:\\s*,\\s*[a-z0-9_-]+\\s*=\\s*${literal})*)`, "i");
3496
+ var assignments = `[a-z0-9_-]+\\s*=\\s*${literal}(?:\\s*,\\s*[a-z0-9_-]+\\s*=\\s*${literal})*`;
3497
+ var valuesMatch = new RegExp(`^(${assignments})`, "i");
3498
+ var rowSource = `\\(\\s*(${assignments})\\s*\\)`;
3499
+ var rowsMatch = new RegExp(`^${rowSource}(?:\\s*,\\s*${rowSource.replace("(" + assignments, "(?:" + assignments)})*`, "i");
3500
+ var rowMatch = new RegExp(rowSource, "ig");
3490
3501
  var assignmentMatch = new RegExp(`([a-z0-9_-]+)\\s*=\\s*(${_maskStrings.placeholderSource}|(${_parseLiteralValue.numberSource})|${_maskStrings.arraySource}|(null)|(true)|(false))`, "ig");
3502
+ var parseRow = (assignments2) => {
3503
+ const row = {};
3504
+ for (const assignment of assignments2.matchAll(assignmentMatch)) {
3505
+ row[assignment[1]] = (0, _parseLiteralValue.parseLiteralValue)(assignment, 3);
3506
+ }
3507
+ return row;
3508
+ };
3491
3509
  var findInsertValues = (parsed, body) => {
3492
- const clauseFound = body.match(valuesMatch);
3493
3510
  parsed["insertValues"] = [];
3511
+ const rowsFound = body.match(rowsMatch);
3512
+ if (rowsFound) {
3513
+ parsed["insertValues"] = [...rowsFound[0].matchAll(rowMatch)].map((row) => parseRow(row[1]));
3514
+ return body.slice(rowsFound[0].length).trim();
3515
+ }
3516
+ const clauseFound = body.match(valuesMatch);
3494
3517
  if (!clauseFound) {
3495
3518
  return body;
3496
3519
  }
3497
- const row = {};
3498
- const assignmentsFound = clauseFound[1].matchAll(assignmentMatch);
3499
- for (const assignment of assignmentsFound) {
3500
- row[assignment[1]] = (0, _parseLiteralValue.parseLiteralValue)(assignment, 3);
3501
- }
3502
- parsed["insertValues"] = [row];
3520
+ parsed["insertValues"] = [parseRow(clauseFound[1])];
3503
3521
  return body.slice(clauseFound[0].length).trim();
3504
3522
  };
3505
3523
  exports.findInsertValues = findInsertValues;
@@ -5022,7 +5040,7 @@ var jsonFsQuery = (() => {
5022
5040
  value: true
5023
5041
  });
5024
5042
  exports.startsQueryMatch = void 0;
5025
- var startsQueryMatch = exports.startsQueryMatch = /^\s*(create|delete|describe|drop|insert|read|show|update)(?![a-z0-9_-])/i;
5043
+ var startsQueryMatch = exports.startsQueryMatch = /^\s*(alter|create|delete|describe|drop|insert|read|show|update|use)(?![a-z0-9_-])/i;
5026
5044
  }
5027
5045
  });
5028
5046
 
@@ -5034,7 +5052,7 @@ var jsonFsQuery = (() => {
5034
5052
  Object.defineProperty(exports, "__esModule", {
5035
5053
  value: true
5036
5054
  });
5037
- exports.parseCreate = exports.createMatch = void 0;
5055
+ exports.parseField = exports.parseCreate = exports.nameSource = exports.nameMatch = exports.keyLookup = exports.fieldMatch = exports.createMatch = void 0;
5038
5056
  require_es_array_includes();
5039
5057
  require_esnext_iterator_constructor();
5040
5058
  require_esnext_iterator_filter();
@@ -5063,10 +5081,10 @@ var jsonFsQuery = (() => {
5063
5081
  var _startsQuery = require_startsQuery();
5064
5082
  var createMatch = exports.createMatch = /^\s*create(?![a-z0-9_-])/i;
5065
5083
  var headMatch = /^\s*create\s+(if\s+not\s+exists\s+)?([a-z0-9_-]+)\s*\(/i;
5066
- var nameSource = "[a-z0-9_-]+";
5067
- var nameMatch = new RegExp(`^${nameSource}$`, "i");
5084
+ var nameSource = exports.nameSource = "[a-z0-9_-]+";
5085
+ var nameMatch = exports.nameMatch = new RegExp(`^${nameSource}$`, "i");
5068
5086
  var numberMatch = new RegExp(`^${_parseLiteralValue.numberSource}$`, "i");
5069
- var fieldMatch = new RegExp(`^(${nameSource})\\s+(${nameSource})((?:\\s[\\s\\S]*)?)$`, "i");
5087
+ var fieldMatch = exports.fieldMatch = new RegExp(`^(${nameSource})\\s+(${nameSource})((?:\\s[\\s\\S]*)?)$`, "i");
5070
5088
  var primaryMatch = /^primary\s+key\s*\(([^()]*)\)$/i;
5071
5089
  var uniqueMatch = /^unique\s*\(([^()]*)\)$/i;
5072
5090
  var indexMatch = /^index\s*\(([^()]*)\)$/i;
@@ -5079,6 +5097,8 @@ var jsonFsQuery = (() => {
5079
5097
  index: "index",
5080
5098
  foreign: "fk"
5081
5099
  };
5100
+ var keyLookup = (type, fields) => `${lookupPrefix[type]}_${fields.join("_")}.json`;
5101
+ exports.keyLookup = keyLookup;
5082
5102
  var shown = (text) => (0, _maskStrings.unmaskStrings)(text.trim(), "'");
5083
5103
  var findClose = (text, open) => {
5084
5104
  let depth = 0;
@@ -5197,6 +5217,7 @@ var jsonFsQuery = (() => {
5197
5217
  }
5198
5218
  return field;
5199
5219
  };
5220
+ exports.parseField = parseField;
5200
5221
  var parseKey = (item) => {
5201
5222
  let found = item.match(primaryMatch);
5202
5223
  if (found) {
@@ -5248,7 +5269,7 @@ var jsonFsQuery = (() => {
5248
5269
  if (missing) {
5249
5270
  throw new Error(`The ${key.type} key (${key.fields.join(", ")}) names "${missing}", which is not a field`);
5250
5271
  }
5251
- const lookup = `${lookupPrefix[key.type]}_${key.fields.join("_")}.json`;
5272
+ const lookup = keyLookup(key.type, key.fields);
5252
5273
  if (lookups.has(lookup)) {
5253
5274
  throw new Error(`The same ${key.type} key on "${key.fields.join(", ")}" is given twice`);
5254
5275
  }
@@ -5394,6 +5415,162 @@ var jsonFsQuery = (() => {
5394
5415
  }
5395
5416
  });
5396
5417
 
5418
+ // dist/data/utilities/parsers/parseAlter.js
5419
+ var require_parseAlter = __commonJS({
5420
+ "dist/data/utilities/parsers/parseAlter.js"(exports) {
5421
+ "use strict";
5422
+ init_process();
5423
+ Object.defineProperty(exports, "__esModule", {
5424
+ value: true
5425
+ });
5426
+ exports.parseAlter = exports.alterMatch = void 0;
5427
+ var _parseCreate = require_parseCreate();
5428
+ var _maskStrings = require_maskStrings();
5429
+ var _startsQuery = require_startsQuery();
5430
+ var alterMatch = exports.alterMatch = /^\s*alter(?![a-z0-9_-])/i;
5431
+ var headMatch = new RegExp(`^\\s*alter\\s+(${_parseCreate.nameSource})\\s+(add|drop|rename|modify)(?![a-z0-9_-])([\\s\\S]*)$`, "i");
5432
+ var renameMatch = new RegExp(`^\\s*(${_parseCreate.nameSource})\\s+to\\s+(${_parseCreate.nameSource})\\s*$`, "i");
5433
+ var expected = "Expected: alter <record> add <field> <type> ..., drop <field>, rename <field> to <name>, or modify <field> <type> ...";
5434
+ var shown = (text) => (0, _maskStrings.unmaskStrings)(text.trim(), "'");
5435
+ var fieldSpec = (text) => {
5436
+ const found = text.trim().match(_parseCreate.fieldMatch);
5437
+ if (!found) {
5438
+ throw new Error(`Expected a field (<name> <type> ...) in: ${shown(text)}`);
5439
+ }
5440
+ return (0, _parseCreate.parseField)(found);
5441
+ };
5442
+ var parseAlter = (query) => {
5443
+ const head = query.match(headMatch);
5444
+ if (!head) {
5445
+ throw new Error(expected);
5446
+ }
5447
+ const [, entity, actionWord, rest] = head;
5448
+ if (entity === "__RECORDS") {
5449
+ throw new Error("__RECORDS is reserved for the list of records");
5450
+ }
5451
+ const action = actionWord.toLowerCase();
5452
+ if (_startsQuery.startsQueryMatch.test(rest.trim()) && !/^\s*(add|drop|rename|modify)\b/i.test(rest)) {
5453
+ throw new Error(`Missing ; before: ${shown(rest)}`);
5454
+ }
5455
+ switch (action) {
5456
+ case "add":
5457
+ case "modify":
5458
+ return {
5459
+ entity,
5460
+ alter: {
5461
+ action,
5462
+ field: fieldSpec(rest)
5463
+ }
5464
+ };
5465
+ case "drop": {
5466
+ const name = rest.trim();
5467
+ if (!_parseCreate.nameMatch.test(name)) {
5468
+ throw new Error(`Expected: alter ${entity} drop <field>${name ? ` (got: ${shown(name)})` : ""}`);
5469
+ }
5470
+ return {
5471
+ entity,
5472
+ alter: {
5473
+ action,
5474
+ name
5475
+ }
5476
+ };
5477
+ }
5478
+ default: {
5479
+ const found = rest.match(renameMatch);
5480
+ if (!found) {
5481
+ throw new Error(`Expected: alter ${entity} rename <field> to <name>${rest.trim() ? ` (got: ${shown(rest)})` : ""}`);
5482
+ }
5483
+ return {
5484
+ entity,
5485
+ alter: {
5486
+ action: "rename",
5487
+ name: found[1],
5488
+ to: found[2]
5489
+ }
5490
+ };
5491
+ }
5492
+ }
5493
+ };
5494
+ exports.parseAlter = parseAlter;
5495
+ }
5496
+ });
5497
+
5498
+ // dist/data/utilities/parsers/parseDatabaseStatement.js
5499
+ var require_parseDatabaseStatement = __commonJS({
5500
+ "dist/data/utilities/parsers/parseDatabaseStatement.js"(exports) {
5501
+ "use strict";
5502
+ init_process();
5503
+ Object.defineProperty(exports, "__esModule", {
5504
+ value: true
5505
+ });
5506
+ exports.parseDatabaseStatement = exports.databaseStatementMatch = void 0;
5507
+ var _maskStrings = require_maskStrings();
5508
+ var _startsQuery = require_startsQuery();
5509
+ var databaseStatementMatch = exports.databaseStatementMatch = /^\s*(?:(?:create|drop)\s+database\s+(?!\()[a-z0-9_-]|show\s+databases(?![a-z0-9_-])|use(?![a-z0-9_.-]))/i;
5510
+ var createMatch = /^\s*create\s+database\s+(if\s+not\s+exists\s+)?([a-z0-9_-]+)/i;
5511
+ var dropMatch = /^\s*drop\s+database\s+(if\s+exists\s+)?([a-z0-9_-]+)/i;
5512
+ var useMatch = /^\s*use\s+([a-z0-9_-]+)/i;
5513
+ var showMatch = /^\s*show\s+databases/i;
5514
+ var assertNothingAfter = (rest) => {
5515
+ const after = rest.trim();
5516
+ if (!after) {
5517
+ return;
5518
+ }
5519
+ const shown = (0, _maskStrings.unmaskStrings)(after, "'");
5520
+ if (_startsQuery.startsQueryMatch.test(after)) {
5521
+ throw new Error(`Missing ; before: ${shown}`);
5522
+ }
5523
+ throw new Error(`Unrecognized query value: ${shown}`);
5524
+ };
5525
+ var parseDatabaseStatement = (query) => {
5526
+ const statement = {
5527
+ ifExists: false,
5528
+ ifNotExists: false
5529
+ };
5530
+ let found = query.match(createMatch);
5531
+ if (found) {
5532
+ assertNothingAfter(query.slice(found[0].length));
5533
+ return {
5534
+ ...statement,
5535
+ command: "create database",
5536
+ entity: found[2],
5537
+ ifNotExists: Boolean(found[1])
5538
+ };
5539
+ }
5540
+ found = query.match(dropMatch);
5541
+ if (found) {
5542
+ assertNothingAfter(query.slice(found[0].length));
5543
+ return {
5544
+ ...statement,
5545
+ command: "drop database",
5546
+ entity: found[2],
5547
+ ifExists: Boolean(found[1])
5548
+ };
5549
+ }
5550
+ found = query.match(showMatch);
5551
+ if (found) {
5552
+ assertNothingAfter(query.slice(found[0].length));
5553
+ return {
5554
+ ...statement,
5555
+ command: "show databases",
5556
+ entity: "__DATABASES"
5557
+ };
5558
+ }
5559
+ found = query.match(useMatch);
5560
+ if (!found) {
5561
+ throw new Error("Expected: use <database>");
5562
+ }
5563
+ assertNothingAfter(query.slice(found[0].length));
5564
+ return {
5565
+ ...statement,
5566
+ command: "use",
5567
+ entity: found[1]
5568
+ };
5569
+ };
5570
+ exports.parseDatabaseStatement = parseDatabaseStatement;
5571
+ }
5572
+ });
5573
+
5397
5574
  // dist/data/utilities/parsers/parseQuery.js
5398
5575
  var require_parseQuery = __commonJS({
5399
5576
  "dist/data/utilities/parsers/parseQuery.js"(exports) {
@@ -5419,6 +5596,8 @@ var jsonFsQuery = (() => {
5419
5596
  var _maskStrings = require_maskStrings();
5420
5597
  var _parseCreate = require_parseCreate();
5421
5598
  var _parseSchemaStatement = require_parseSchemaStatement();
5599
+ var _parseAlter = require_parseAlter();
5600
+ var _parseDatabaseStatement = require_parseDatabaseStatement();
5422
5601
  var _splitClauses = require_splitClauses();
5423
5602
  var _startsQuery = require_startsQuery();
5424
5603
  var clauseSteps = {
@@ -5489,6 +5668,9 @@ var jsonFsQuery = (() => {
5489
5668
  ifExists: void 0
5490
5669
  };
5491
5670
  query = (0, _maskStrings.maskArrays)((0, _maskStrings.maskStrings)(query));
5671
+ if (_parseDatabaseStatement.databaseStatementMatch.test(query)) {
5672
+ return Object.assign(parsedQuery, (0, _parseDatabaseStatement.parseDatabaseStatement)(query));
5673
+ }
5492
5674
  if (_parseCreate.createMatch.test(query)) {
5493
5675
  const {
5494
5676
  entity,
@@ -5503,6 +5685,17 @@ var jsonFsQuery = (() => {
5503
5685
  if (_parseSchemaStatement.schemaStatementMatch.test(query)) {
5504
5686
  return Object.assign(parsedQuery, (0, _parseSchemaStatement.parseSchemaStatement)(query));
5505
5687
  }
5688
+ if (_parseAlter.alterMatch.test(query)) {
5689
+ const {
5690
+ entity,
5691
+ alter
5692
+ } = (0, _parseAlter.parseAlter)(query);
5693
+ return Object.assign(parsedQuery, {
5694
+ command: "alter",
5695
+ entity,
5696
+ alter
5697
+ });
5698
+ }
5506
5699
  const split = (0, _splitClauses.splitClauses)(query);
5507
5700
  if (!split) {
5508
5701
  query = query.trim();
@@ -5532,6 +5725,9 @@ var jsonFsQuery = (() => {
5532
5725
  throw leftoverError(rest, `${keyword} ${body.slice(0, body.length - rest.length).trim()}`);
5533
5726
  }
5534
5727
  }
5728
+ if ((parsedQuery.joinClauses || []).length && !parsedQuery.joinEntity) {
5729
+ throw new Error(`"on" needs the record to join, after the one read: ${parsedQuery.command} ${parsedQuery.entity}.<record> on ...`);
5730
+ }
5535
5731
  return parsedQuery;
5536
5732
  };
5537
5733
  exports.parseQuery = parseQuery;
@@ -6086,16 +6282,39 @@ var jsonFsQuery = (() => {
6086
6282
  Object.defineProperty(exports, "__esModule", {
6087
6283
  value: true
6088
6284
  });
6089
- exports.trackDatabaseCall = exports.resolveDatabasePath = exports.getSetting = exports.configure = void 0;
6285
+ exports.trackDatabaseCall = exports.switchDatabase = exports.resolveDatabasePath = exports.lockPath = exports.getSetting = exports.databasesFolder = exports.configure = exports.activeDatabasePath = void 0;
6286
+ require_es_json_stringify();
6090
6287
  var defaults = {
6091
6288
  databasePath: "database/",
6092
6289
  relativePath: "",
6093
- enforceForeignKeys: true
6290
+ enforceForeignKeys: true,
6291
+ readConcurrency: 16,
6292
+ format: "compact"
6094
6293
  };
6095
6294
  var settings = {
6096
6295
  ...defaults
6097
6296
  };
6098
6297
  var activeCalls = 0;
6298
+ var databaseNameMatch = /^[a-z0-9_-]+$/i;
6299
+ var withSlash = (path) => path.endsWith("/") ? path : `${path}/`;
6300
+ var activeDatabasePath = () => settings.databasesPath && settings.database ? `${withSlash(settings.databasesPath)}${settings.database}/` : getSetting("databasePath", "database/");
6301
+ exports.activeDatabasePath = activeDatabasePath;
6302
+ var lockPath = () => settings.databasesPath ? withSlash(settings.databasesPath) : activeDatabasePath();
6303
+ exports.lockPath = lockPath;
6304
+ var databasesFolder = () => {
6305
+ if (!settings.databasesPath) {
6306
+ throw new Error("Several databases need a folder to hold them: configure({ databasesPath: 'databases/' }) first");
6307
+ }
6308
+ return withSlash(settings.databasesPath);
6309
+ };
6310
+ exports.databasesFolder = databasesFolder;
6311
+ var switchDatabase = (name) => {
6312
+ settings = {
6313
+ ...settings,
6314
+ database: name
6315
+ };
6316
+ };
6317
+ exports.switchDatabase = switchDatabase;
6099
6318
  var resolveDatabasePath = (databasePath) => require_path_browserify().resolve(databasePath);
6100
6319
  exports.resolveDatabasePath = resolveDatabasePath;
6101
6320
  var trackDatabaseCall = () => {
@@ -6110,13 +6329,34 @@ var jsonFsQuery = (() => {
6110
6329
  };
6111
6330
  exports.trackDatabaseCall = trackDatabaseCall;
6112
6331
  var configure = (newSettings) => {
6113
- if (activeCalls > 0 && typeof newSettings.databasePath !== "undefined" && resolveDatabasePath(newSettings.databasePath) !== resolveDatabasePath(settings.databasePath)) {
6114
- throw new Error(`Can't change databasePath while ${activeCalls} database call(s) are still running or queued: await them first`);
6332
+ if (typeof newSettings.format !== "undefined" && newSettings.format !== "compact" && newSettings.format !== "pretty") {
6333
+ throw new Error(`Unknown format "${newSettings.format}": use 'compact' or 'pretty'`);
6115
6334
  }
6116
- settings = {
6335
+ if (typeof newSettings.database !== "undefined" && newSettings.database !== null && !databaseNameMatch.test(newSettings.database)) {
6336
+ throw new Error(`Invalid database name ${JSON.stringify(newSettings.database)}: names use letters, digits, _ and - only`);
6337
+ }
6338
+ const next = {
6117
6339
  ...settings,
6118
6340
  ...newSettings
6119
6341
  };
6342
+ if (next.database && !next.databasesPath) {
6343
+ throw new Error("A database name needs the folder that holds the databases: configure({ databasesPath: 'databases/', database: '...' })");
6344
+ }
6345
+ if (activeCalls > 0) {
6346
+ const before = {
6347
+ active: resolveDatabasePath(activeDatabasePath()),
6348
+ lock: resolveDatabasePath(lockPath())
6349
+ };
6350
+ const previous = settings;
6351
+ settings = next;
6352
+ const changed = resolveDatabasePath(activeDatabasePath()) !== before.active || resolveDatabasePath(lockPath()) !== before.lock;
6353
+ settings = previous;
6354
+ if (changed) {
6355
+ const named = ["databasePath", "databasesPath", "database"].filter((key) => typeof newSettings[key] !== "undefined").join(" / ");
6356
+ throw new Error(`Can't change ${named} while ${activeCalls} database call(s) are still running or queued: await them first`);
6357
+ }
6358
+ }
6359
+ settings = next;
6120
6360
  };
6121
6361
  exports.configure = configure;
6122
6362
  var getSetting = (key, defaultValue) => {
@@ -6152,7 +6392,7 @@ var jsonFsQuery = (() => {
6152
6392
  }
6153
6393
  var storagePath = (path = "") => {
6154
6394
  const relativePath = jsEnv.isBrowser ? (0, _config.getSetting)("relativePath", "") : "";
6155
- return `${relativePath}${(0, _config.getSetting)("databasePath", "database/")}${path}`;
6395
+ return `${relativePath}${(0, _config.activeDatabasePath)()}${path}`;
6156
6396
  };
6157
6397
  exports.storagePath = storagePath;
6158
6398
  }
@@ -6644,6 +6884,248 @@ var jsonFsQuery = (() => {
6644
6884
  }
6645
6885
  });
6646
6886
 
6887
+ // dist/data/storage/writeSet.js
6888
+ var require_writeSet = __commonJS({
6889
+ "dist/data/storage/writeSet.js"(exports) {
6890
+ "use strict";
6891
+ init_process();
6892
+ require_esnext_weak_map_delete_all();
6893
+ Object.defineProperty(exports, "__esModule", {
6894
+ value: true
6895
+ });
6896
+ exports.writeAtomically = exports.withWriteSet = exports.stageWrite = exports.stageRemoveDirectory = exports.stageRemove = exports.stageMakeDirectory = exports.pendingListing = exports.pendingFile = exports.pendingExists = void 0;
6897
+ require_esnext_iterator_constructor();
6898
+ require_esnext_iterator_filter();
6899
+ require_esnext_map_delete_all();
6900
+ require_esnext_map_every();
6901
+ require_esnext_map_filter();
6902
+ require_esnext_map_find();
6903
+ require_esnext_map_find_key();
6904
+ require_esnext_map_includes();
6905
+ require_esnext_map_key_of();
6906
+ require_esnext_map_map_keys();
6907
+ require_esnext_map_map_values();
6908
+ require_esnext_map_merge();
6909
+ require_esnext_map_reduce();
6910
+ require_esnext_map_some();
6911
+ require_esnext_map_update();
6912
+ require_esnext_set_add_all();
6913
+ require_esnext_set_delete_all();
6914
+ require_esnext_set_difference();
6915
+ require_esnext_set_every();
6916
+ require_esnext_set_filter();
6917
+ require_esnext_set_find();
6918
+ require_esnext_set_intersection();
6919
+ require_esnext_set_is_disjoint_from();
6920
+ require_esnext_set_is_subset_of();
6921
+ require_esnext_set_is_superset_of();
6922
+ require_esnext_set_join();
6923
+ require_esnext_set_map();
6924
+ require_esnext_set_reduce();
6925
+ require_esnext_set_some();
6926
+ require_esnext_set_symmetric_difference();
6927
+ require_esnext_set_union();
6928
+ var jsEnv = _interopRequireWildcard(require_dist());
6929
+ var _storagePath = require_storagePath();
6930
+ var _nodeFiles = require_nodeFiles();
6931
+ var _readCache = require_readCache();
6932
+ var e;
6933
+ function _interopRequireWildcard(t, r) {
6934
+ if (!r && t && t.__esModule) return t;
6935
+ var n, a, o = Object.defineProperty, f = { __proto__: null, default: t };
6936
+ if (Object(t) !== t) return f;
6937
+ if (e || "function" != typeof WeakMap || (e = /* @__PURE__ */ new WeakMap()), e) {
6938
+ if (e.has(t)) return e.get(t);
6939
+ e.set(t, f);
6940
+ }
6941
+ 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]);
6942
+ return f;
6943
+ }
6944
+ var writeSets = /* @__PURE__ */ new Map();
6945
+ var currentWriteSet = () => writeSets.get((0, _storagePath.storagePath)());
6946
+ var folderPrefix = (location) => location.endsWith("/") ? location : `${location}/`;
6947
+ var insideAny = (location, folders) => {
6948
+ for (const folder of folders) {
6949
+ if (location === folder || location.startsWith(folderPrefix(folder))) {
6950
+ return true;
6951
+ }
6952
+ }
6953
+ return false;
6954
+ };
6955
+ var writeAtomically = async (location, text) => {
6956
+ const temporary = `${location}.${crypto.randomUUID()}.tmp`;
6957
+ const files = (0, _nodeFiles.nodeFiles)();
6958
+ try {
6959
+ await files.writeFile(temporary, text);
6960
+ await files.rename(temporary, location);
6961
+ } catch (error) {
6962
+ await files.rm(temporary, {
6963
+ force: true
6964
+ }).catch(() => void 0);
6965
+ throw error;
6966
+ }
6967
+ };
6968
+ exports.writeAtomically = writeAtomically;
6969
+ var removeFolder = async (location) => {
6970
+ (0, _readCache.cacheRemove)(location, true);
6971
+ await (0, _nodeFiles.nodeFiles)().rm(location, {
6972
+ recursive: true,
6973
+ force: true
6974
+ });
6975
+ (0, _readCache.cacheRemove)(location, true);
6976
+ };
6977
+ var commit = async (writeSet) => {
6978
+ const files = (0, _nodeFiles.nodeFiles)();
6979
+ const writtenInto = (folder) => {
6980
+ const prefix = folderPrefix(folder);
6981
+ return [...writeSet.madeFolders].some((made) => made === folder || made.startsWith(prefix)) || [...writeSet.files].some(([location, text]) => text !== null && location.startsWith(prefix));
6982
+ };
6983
+ const removedFolders = [...writeSet.removedFolders];
6984
+ for (const folder of removedFolders.filter(writtenInto)) {
6985
+ await removeFolder(folder);
6986
+ }
6987
+ for (const folder of writeSet.madeFolders) {
6988
+ await files.mkdir(folder, {
6989
+ recursive: true
6990
+ });
6991
+ }
6992
+ for (const [location, text] of writeSet.files) {
6993
+ if (text !== null) {
6994
+ await writeAtomically(location, text);
6995
+ (0, _readCache.cacheWrite)(location, text);
6996
+ }
6997
+ }
6998
+ for (const [location, text] of writeSet.files) {
6999
+ if (text === null) {
7000
+ (0, _readCache.cacheRemove)(location);
7001
+ await files.rm(location, {
7002
+ force: true
7003
+ });
7004
+ (0, _readCache.cacheRemove)(location);
7005
+ }
7006
+ }
7007
+ for (const folder of removedFolders.filter((folder2) => !writtenInto(folder2))) {
7008
+ await removeFolder(folder);
7009
+ }
7010
+ };
7011
+ var withWriteSet = async (task) => {
7012
+ const database = (0, _storagePath.storagePath)();
7013
+ if (!jsEnv.isNode || writeSets.has(database)) {
7014
+ return task();
7015
+ }
7016
+ const writeSet = {
7017
+ files: /* @__PURE__ */ new Map(),
7018
+ madeFolders: /* @__PURE__ */ new Set(),
7019
+ removedFolders: /* @__PURE__ */ new Set()
7020
+ };
7021
+ writeSets.set(database, writeSet);
7022
+ let result;
7023
+ try {
7024
+ result = await task();
7025
+ } finally {
7026
+ writeSets.delete(database);
7027
+ }
7028
+ await commit(writeSet);
7029
+ return result;
7030
+ };
7031
+ exports.withWriteSet = withWriteSet;
7032
+ var pendingFile = (location) => {
7033
+ const writeSet = currentWriteSet();
7034
+ if (!writeSet) {
7035
+ return void 0;
7036
+ }
7037
+ if (writeSet.files.has(location)) {
7038
+ return writeSet.files.get(location);
7039
+ }
7040
+ return insideAny(location, writeSet.removedFolders) ? null : void 0;
7041
+ };
7042
+ exports.pendingFile = pendingFile;
7043
+ var pendingExists = (location) => {
7044
+ const writeSet = currentWriteSet();
7045
+ if (!writeSet) {
7046
+ return void 0;
7047
+ }
7048
+ if (writeSet.files.has(location)) {
7049
+ return writeSet.files.get(location) !== null;
7050
+ }
7051
+ const prefix = folderPrefix(location);
7052
+ const madeInside = (path) => path === location || path.startsWith(prefix);
7053
+ if ([...writeSet.madeFolders].some(madeInside) || [...writeSet.files].some(([path, text]) => text !== null && path.startsWith(prefix))) {
7054
+ return true;
7055
+ }
7056
+ return insideAny(location, writeSet.removedFolders) ? false : void 0;
7057
+ };
7058
+ exports.pendingExists = pendingExists;
7059
+ var pendingListing = (folder, onDisk) => {
7060
+ const writeSet = currentWriteSet();
7061
+ if (!writeSet) {
7062
+ return onDisk;
7063
+ }
7064
+ const prefix = folderPrefix(folder);
7065
+ const listed = new Set(onDisk.filter((location) => !insideAny(location, writeSet.removedFolders)));
7066
+ for (const [location, text] of writeSet.files) {
7067
+ if (location.startsWith(prefix)) {
7068
+ if (text === null) {
7069
+ listed.delete(location);
7070
+ } else {
7071
+ listed.add(location);
7072
+ }
7073
+ }
7074
+ }
7075
+ return [...listed];
7076
+ };
7077
+ exports.pendingListing = pendingListing;
7078
+ var stageWrite = (location, text) => {
7079
+ const writeSet = currentWriteSet();
7080
+ if (!writeSet) {
7081
+ return false;
7082
+ }
7083
+ writeSet.files.delete(location);
7084
+ writeSet.files.set(location, text);
7085
+ return true;
7086
+ };
7087
+ exports.stageWrite = stageWrite;
7088
+ var stageRemove = (location) => {
7089
+ const writeSet = currentWriteSet();
7090
+ if (!writeSet) {
7091
+ return false;
7092
+ }
7093
+ writeSet.files.delete(location);
7094
+ writeSet.files.set(location, null);
7095
+ return true;
7096
+ };
7097
+ exports.stageRemove = stageRemove;
7098
+ var stageMakeDirectory = (location) => {
7099
+ const writeSet = currentWriteSet();
7100
+ if (!writeSet) {
7101
+ return false;
7102
+ }
7103
+ writeSet.madeFolders.add(location);
7104
+ return true;
7105
+ };
7106
+ exports.stageMakeDirectory = stageMakeDirectory;
7107
+ var stageRemoveDirectory = (location) => {
7108
+ const writeSet = currentWriteSet();
7109
+ if (!writeSet) {
7110
+ return false;
7111
+ }
7112
+ for (const file of [...writeSet.files.keys()]) {
7113
+ if (insideAny(file, /* @__PURE__ */ new Set([location]))) {
7114
+ writeSet.files.delete(file);
7115
+ }
7116
+ }
7117
+ for (const folder of [...writeSet.madeFolders]) {
7118
+ if (insideAny(folder, /* @__PURE__ */ new Set([location]))) {
7119
+ writeSet.madeFolders.delete(folder);
7120
+ }
7121
+ }
7122
+ writeSet.removedFolders.add(location);
7123
+ return true;
7124
+ };
7125
+ exports.stageRemoveDirectory = stageRemoveDirectory;
7126
+ }
7127
+ });
7128
+
6647
7129
  // dist/data/storage/readJson.js
6648
7130
  var require_readJson = __commonJS({
6649
7131
  "dist/data/storage/readJson.js"(exports) {
@@ -6653,11 +7135,12 @@ var jsonFsQuery = (() => {
6653
7135
  Object.defineProperty(exports, "__esModule", {
6654
7136
  value: true
6655
7137
  });
6656
- exports.readJson = void 0;
7138
+ exports.readText = exports.readJson = void 0;
6657
7139
  var jsEnv = _interopRequireWildcard(require_dist());
6658
7140
  var _storagePath = require_storagePath();
6659
7141
  var _nodeFiles = require_nodeFiles();
6660
7142
  var _readCache = require_readCache();
7143
+ var _writeSet = require_writeSet();
6661
7144
  var e;
6662
7145
  function _interopRequireWildcard(t, r) {
6663
7146
  if (!r && t && t.__esModule) return t;
@@ -6670,11 +7153,16 @@ var jsonFsQuery = (() => {
6670
7153
  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]);
6671
7154
  return f;
6672
7155
  }
6673
- var readJson = async (path) => {
7156
+ var readText = async (path) => {
6674
7157
  const location = (0, _storagePath.storagePath)(path);
6675
- const text = await (0, _readCache.cachedRead)(location, () => jsEnv.isNode ? (0, _nodeFiles.nodeFiles)().readFile(location, "utf8") : fetch(location).then((response) => response.text()));
6676
- return JSON.parse(text);
7158
+ const pending = (0, _writeSet.pendingFile)(location);
7159
+ if (pending === null) {
7160
+ throw new Error(`ENOENT: no such file or directory, open '${location}' (deleted by this statement)`);
7161
+ }
7162
+ return typeof pending === "string" ? pending : (0, _readCache.cachedRead)(location, () => jsEnv.isNode ? (0, _nodeFiles.nodeFiles)().readFile(location, "utf8") : fetch(location).then((response) => response.text()));
6677
7163
  };
7164
+ exports.readText = readText;
7165
+ var readJson = async (path) => JSON.parse(await readText(path));
6678
7166
  exports.readJson = readJson;
6679
7167
  }
6680
7168
  });
@@ -6687,15 +7175,21 @@ var jsonFsQuery = (() => {
6687
7175
  Object.defineProperty(exports, "__esModule", {
6688
7176
  value: true
6689
7177
  });
6690
- exports.writeJson = void 0;
7178
+ exports.writeJson = exports.jsonText = void 0;
6691
7179
  require_es_json_stringify();
6692
7180
  var _storagePath = require_storagePath();
6693
- var _nodeFiles = require_nodeFiles();
6694
7181
  var _readCache = require_readCache();
6695
- var writeJson = async (path, content) => {
7182
+ var _writeSet = require_writeSet();
7183
+ var _config = require_config();
7184
+ var jsonText = (content, format = (0, _config.getSetting)("format", "compact")) => format === "pretty" ? JSON.stringify(content, null, 2) : JSON.stringify(content);
7185
+ exports.jsonText = jsonText;
7186
+ var writeJson = async (path, content, format) => {
6696
7187
  const location = (0, _storagePath.storagePath)(path);
6697
- const text = JSON.stringify(content, null, 2);
6698
- await (0, _nodeFiles.nodeFiles)().writeFile(location, text);
7188
+ const text = jsonText(content, format);
7189
+ if ((0, _writeSet.stageWrite)(location, text)) {
7190
+ return;
7191
+ }
7192
+ await (0, _writeSet.writeAtomically)(location, text);
6699
7193
  (0, _readCache.cacheWrite)(location, text);
6700
7194
  };
6701
7195
  exports.writeJson = writeJson;
@@ -6713,8 +7207,13 @@ var jsonFsQuery = (() => {
6713
7207
  exports.makeDirectory = void 0;
6714
7208
  var _storagePath = require_storagePath();
6715
7209
  var _nodeFiles = require_nodeFiles();
7210
+ var _writeSet = require_writeSet();
6716
7211
  var makeDirectory = async (path = "") => {
6717
- await (0, _nodeFiles.nodeFiles)().mkdir((0, _storagePath.storagePath)(path), {
7212
+ const location = (0, _storagePath.storagePath)(path);
7213
+ if ((0, _writeSet.stageMakeDirectory)(location)) {
7214
+ return;
7215
+ }
7216
+ await (0, _nodeFiles.nodeFiles)().mkdir(location, {
6718
7217
  recursive: true
6719
7218
  });
6720
7219
  };
@@ -6722,6 +7221,14 @@ var jsonFsQuery = (() => {
6722
7221
  }
6723
7222
  });
6724
7223
 
7224
+ // js-build-tools-empty:fs
7225
+ var require_fs = __commonJS({
7226
+ "js-build-tools-empty:fs"(exports, module) {
7227
+ init_process();
7228
+ module.exports = {};
7229
+ }
7230
+ });
7231
+
6725
7232
  // dist/data/storage/removeFile.js
6726
7233
  var require_removeFile = __commonJS({
6727
7234
  "dist/data/storage/removeFile.js"(exports) {
@@ -6734,8 +7241,16 @@ var jsonFsQuery = (() => {
6734
7241
  var _storagePath = require_storagePath();
6735
7242
  var _nodeFiles = require_nodeFiles();
6736
7243
  var _readCache = require_readCache();
7244
+ var _writeSet = require_writeSet();
6737
7245
  var removeFile = async (path) => {
6738
7246
  const location = (0, _storagePath.storagePath)(path);
7247
+ const pending = (0, _writeSet.pendingFile)(location);
7248
+ if (pending === null || pending === void 0 && !require_fs().existsSync(location)) {
7249
+ throw new Error(`ENOENT: no such file or directory, rm '${location}'`);
7250
+ }
7251
+ if ((0, _writeSet.stageRemove)(location)) {
7252
+ return;
7253
+ }
6739
7254
  (0, _readCache.cacheRemove)(location);
6740
7255
  await (0, _nodeFiles.nodeFiles)().rm(location);
6741
7256
  (0, _readCache.cacheRemove)(location);
@@ -6756,8 +7271,12 @@ var jsonFsQuery = (() => {
6756
7271
  var _storagePath = require_storagePath();
6757
7272
  var _nodeFiles = require_nodeFiles();
6758
7273
  var _readCache = require_readCache();
7274
+ var _writeSet = require_writeSet();
6759
7275
  var removeDirectory = async (path) => {
6760
7276
  const location = (0, _storagePath.storagePath)(path);
7277
+ if ((0, _writeSet.stageRemoveDirectory)(location)) {
7278
+ return;
7279
+ }
6761
7280
  (0, _readCache.cacheRemove)(location, true);
6762
7281
  await (0, _nodeFiles.nodeFiles)().rm(location, {
6763
7282
  recursive: true,
@@ -6769,14 +7288,6 @@ var jsonFsQuery = (() => {
6769
7288
  }
6770
7289
  });
6771
7290
 
6772
- // js-build-tools-empty:fs
6773
- var require_fs = __commonJS({
6774
- "js-build-tools-empty:fs"(exports, module) {
6775
- init_process();
6776
- module.exports = {};
6777
- }
6778
- });
6779
-
6780
7291
  // dist/data/storage/fileExists.js
6781
7292
  var require_fileExists = __commonJS({
6782
7293
  "dist/data/storage/fileExists.js"(exports) {
@@ -6787,16 +7298,151 @@ var jsonFsQuery = (() => {
6787
7298
  });
6788
7299
  exports.fileExists = void 0;
6789
7300
  var _storagePath = require_storagePath();
7301
+ var _writeSet = require_writeSet();
6790
7302
  var fileExists = (path) => {
7303
+ const location = (0, _storagePath.storagePath)(path);
7304
+ const pending = (0, _writeSet.pendingExists)(location);
7305
+ if (pending !== void 0) {
7306
+ return pending;
7307
+ }
6791
7308
  const {
6792
7309
  existsSync
6793
7310
  } = require_fs();
6794
- return existsSync((0, _storagePath.storagePath)(path));
7311
+ return existsSync(location);
6795
7312
  };
6796
7313
  exports.fileExists = fileExists;
6797
7314
  }
6798
7315
  });
6799
7316
 
7317
+ // dist/data/storage/listFiles.js
7318
+ var require_listFiles = __commonJS({
7319
+ "dist/data/storage/listFiles.js"(exports) {
7320
+ "use strict";
7321
+ init_process();
7322
+ Object.defineProperty(exports, "__esModule", {
7323
+ value: true
7324
+ });
7325
+ exports.listFiles = void 0;
7326
+ require_esnext_iterator_constructor();
7327
+ require_esnext_iterator_map();
7328
+ var _storagePath = require_storagePath();
7329
+ var _nodeFiles = require_nodeFiles();
7330
+ var _writeSet = require_writeSet();
7331
+ var walk = async (base) => {
7332
+ let entries;
7333
+ try {
7334
+ entries = await (0, _nodeFiles.nodeFiles)().readdir((0, _storagePath.storagePath)(base), {
7335
+ withFileTypes: true
7336
+ });
7337
+ } catch (error) {
7338
+ if (error?.code === "ENOENT") {
7339
+ return [];
7340
+ }
7341
+ throw error;
7342
+ }
7343
+ const paths = [];
7344
+ for (const entry of entries) {
7345
+ if (entry.isDirectory()) {
7346
+ paths.push(...await walk(`${base}${entry.name}/`));
7347
+ } else if (entry.isFile()) {
7348
+ paths.push(`${base}${entry.name}`);
7349
+ }
7350
+ }
7351
+ return paths;
7352
+ };
7353
+ var listFiles = async (path = "") => {
7354
+ const base = path ? `${path.replace(/\/+$/, "")}/` : "";
7355
+ const onDisk = (await walk(base)).map((file) => (0, _storagePath.storagePath)(file));
7356
+ const root = (0, _storagePath.storagePath)();
7357
+ return (0, _writeSet.pendingListing)((0, _storagePath.storagePath)(path), onDisk).map((location) => location.slice(root.length)).sort();
7358
+ };
7359
+ exports.listFiles = listFiles;
7360
+ }
7361
+ });
7362
+
7363
+ // dist/data/storage/databases.js
7364
+ var require_databases = __commonJS({
7365
+ "dist/data/storage/databases.js"(exports) {
7366
+ "use strict";
7367
+ init_process();
7368
+ require_esnext_weak_map_delete_all();
7369
+ Object.defineProperty(exports, "__esModule", {
7370
+ value: true
7371
+ });
7372
+ exports.writeDatabaseList = exports.removeDatabaseFolder = exports.readDatabaseList = exports.makeDatabaseFolder = exports.databasesLocation = exports.databaseFolderExists = void 0;
7373
+ require_es_json_stringify();
7374
+ var jsEnv = _interopRequireWildcard(require_dist());
7375
+ var _config = require_config();
7376
+ var _nodeFiles = require_nodeFiles();
7377
+ var _readCache = require_readCache();
7378
+ var _writeSet = require_writeSet();
7379
+ var e;
7380
+ function _interopRequireWildcard(t, r) {
7381
+ if (!r && t && t.__esModule) return t;
7382
+ var n, a, o = Object.defineProperty, f = { __proto__: null, default: t };
7383
+ if (Object(t) !== t) return f;
7384
+ if (e || "function" != typeof WeakMap || (e = /* @__PURE__ */ new WeakMap()), e) {
7385
+ if (e.has(t)) return e.get(t);
7386
+ e.set(t, f);
7387
+ }
7388
+ 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]);
7389
+ return f;
7390
+ }
7391
+ var databasesLocation = (path = "") => {
7392
+ const relativePath = jsEnv.isBrowser ? (0, _config.getSetting)("relativePath", "") : "";
7393
+ return `${relativePath}${(0, _config.databasesFolder)()}${path}`;
7394
+ };
7395
+ exports.databasesLocation = databasesLocation;
7396
+ var listLocation = () => databasesLocation("__DATABASES.json");
7397
+ var readDatabaseList = async () => {
7398
+ let text;
7399
+ try {
7400
+ text = jsEnv.isNode ? await (0, _nodeFiles.nodeFiles)().readFile(listLocation(), "utf8") : await fetch(listLocation()).then((response) => response.ok === false ? "[]" : response.text());
7401
+ } catch (error) {
7402
+ if (jsEnv.isNode && error?.code !== "ENOENT") {
7403
+ throw error;
7404
+ }
7405
+ return [];
7406
+ }
7407
+ try {
7408
+ const names = JSON.parse(text);
7409
+ return Array.isArray(names) ? names : [];
7410
+ } catch (error) {
7411
+ if (!jsEnv.isNode) {
7412
+ return [];
7413
+ }
7414
+ throw new Error(`Could not read ${listLocation()}: ${error.message}`);
7415
+ }
7416
+ };
7417
+ exports.readDatabaseList = readDatabaseList;
7418
+ var writeDatabaseList = async (names) => {
7419
+ await (0, _nodeFiles.nodeFiles)().mkdir(databasesLocation(), {
7420
+ recursive: true
7421
+ });
7422
+ await (0, _writeSet.writeAtomically)(listLocation(), JSON.stringify(names));
7423
+ };
7424
+ exports.writeDatabaseList = writeDatabaseList;
7425
+ var databaseFolderExists = (name) => require_fs().existsSync(databasesLocation(name));
7426
+ exports.databaseFolderExists = databaseFolderExists;
7427
+ var makeDatabaseFolder = async (name) => {
7428
+ await (0, _nodeFiles.nodeFiles)().mkdir(databasesLocation(name), {
7429
+ recursive: true
7430
+ });
7431
+ };
7432
+ exports.makeDatabaseFolder = makeDatabaseFolder;
7433
+ var removeDatabaseFolder = async (name) => {
7434
+ const location = databasesLocation(name);
7435
+ (0, _readCache.cacheRemove)(location, true);
7436
+ await (0, _nodeFiles.nodeFiles)().rm(location, {
7437
+ recursive: true,
7438
+ force: true
7439
+ });
7440
+ (0, _readCache.cacheRemove)(location, true);
7441
+ };
7442
+ exports.removeDatabaseFolder = removeDatabaseFolder;
7443
+ }
7444
+ });
7445
+
6800
7446
  // dist/data/storage/index.js
6801
7447
  var require_storage = __commonJS({
6802
7448
  "dist/data/storage/index.js"(exports) {
@@ -6805,24 +7451,72 @@ var jsonFsQuery = (() => {
6805
7451
  Object.defineProperty(exports, "__esModule", {
6806
7452
  value: true
6807
7453
  });
7454
+ Object.defineProperty(exports, "databaseFolderExists", {
7455
+ enumerable: true,
7456
+ get: function() {
7457
+ return _databases.databaseFolderExists;
7458
+ }
7459
+ });
7460
+ Object.defineProperty(exports, "databasesLocation", {
7461
+ enumerable: true,
7462
+ get: function() {
7463
+ return _databases.databasesLocation;
7464
+ }
7465
+ });
6808
7466
  Object.defineProperty(exports, "fileExists", {
6809
7467
  enumerable: true,
6810
7468
  get: function() {
6811
7469
  return _fileExists.fileExists;
6812
7470
  }
6813
7471
  });
7472
+ Object.defineProperty(exports, "jsonText", {
7473
+ enumerable: true,
7474
+ get: function() {
7475
+ return _writeJson.jsonText;
7476
+ }
7477
+ });
7478
+ Object.defineProperty(exports, "listFiles", {
7479
+ enumerable: true,
7480
+ get: function() {
7481
+ return _listFiles.listFiles;
7482
+ }
7483
+ });
7484
+ Object.defineProperty(exports, "makeDatabaseFolder", {
7485
+ enumerable: true,
7486
+ get: function() {
7487
+ return _databases.makeDatabaseFolder;
7488
+ }
7489
+ });
6814
7490
  Object.defineProperty(exports, "makeDirectory", {
6815
7491
  enumerable: true,
6816
7492
  get: function() {
6817
7493
  return _makeDirectory.makeDirectory;
6818
7494
  }
6819
7495
  });
7496
+ Object.defineProperty(exports, "readDatabaseList", {
7497
+ enumerable: true,
7498
+ get: function() {
7499
+ return _databases.readDatabaseList;
7500
+ }
7501
+ });
6820
7502
  Object.defineProperty(exports, "readJson", {
6821
7503
  enumerable: true,
6822
7504
  get: function() {
6823
7505
  return _readJson.readJson;
6824
7506
  }
6825
7507
  });
7508
+ Object.defineProperty(exports, "readText", {
7509
+ enumerable: true,
7510
+ get: function() {
7511
+ return _readJson.readText;
7512
+ }
7513
+ });
7514
+ Object.defineProperty(exports, "removeDatabaseFolder", {
7515
+ enumerable: true,
7516
+ get: function() {
7517
+ return _databases.removeDatabaseFolder;
7518
+ }
7519
+ });
6826
7520
  Object.defineProperty(exports, "removeDirectory", {
6827
7521
  enumerable: true,
6828
7522
  get: function() {
@@ -6847,6 +7541,18 @@ var jsonFsQuery = (() => {
6847
7541
  return _readCache.withReadCache;
6848
7542
  }
6849
7543
  });
7544
+ Object.defineProperty(exports, "withWriteSet", {
7545
+ enumerable: true,
7546
+ get: function() {
7547
+ return _writeSet.withWriteSet;
7548
+ }
7549
+ });
7550
+ Object.defineProperty(exports, "writeDatabaseList", {
7551
+ enumerable: true,
7552
+ get: function() {
7553
+ return _databases.writeDatabaseList;
7554
+ }
7555
+ });
6850
7556
  Object.defineProperty(exports, "writeJson", {
6851
7557
  enumerable: true,
6852
7558
  get: function() {
@@ -6860,7 +7566,10 @@ var jsonFsQuery = (() => {
6860
7566
  var _removeFile = require_removeFile();
6861
7567
  var _removeDirectory = require_removeDirectory();
6862
7568
  var _fileExists = require_fileExists();
7569
+ var _listFiles = require_listFiles();
7570
+ var _databases = require_databases();
6863
7571
  var _readCache = require_readCache();
7572
+ var _writeSet = require_writeSet();
6864
7573
  }
6865
7574
  });
6866
7575
 
@@ -6885,17 +7594,59 @@ var jsonFsQuery = (() => {
6885
7594
  }
6886
7595
  });
6887
7596
 
7597
+ // dist/data/utilities/recordExists.js
7598
+ var require_recordExists = __commonJS({
7599
+ "dist/data/utilities/recordExists.js"(exports) {
7600
+ "use strict";
7601
+ init_process();
7602
+ Object.defineProperty(exports, "__esModule", {
7603
+ value: true
7604
+ });
7605
+ exports.recordExists = void 0;
7606
+ var _storage = require_storage();
7607
+ var recordExists = (entity) => (0, _storage.fileExists)(`${entity}.json`);
7608
+ exports.recordExists = recordExists;
7609
+ }
7610
+ });
7611
+
6888
7612
  // dist/data/utilities/retrieveRecord.js
6889
7613
  var require_retrieveRecord = __commonJS({
6890
7614
  "dist/data/utilities/retrieveRecord.js"(exports) {
6891
7615
  "use strict";
6892
7616
  init_process();
7617
+ require_esnext_weak_map_delete_all();
6893
7618
  Object.defineProperty(exports, "__esModule", {
6894
7619
  value: true
6895
7620
  });
6896
7621
  exports.retrieveRecord = void 0;
7622
+ var jsEnv = _interopRequireWildcard(require_dist());
6897
7623
  var _retrieveFile = require_retrieveFile();
6898
- var retrieveRecord = async (entity = "") => await (0, _retrieveFile.retrieveFile)(`${entity}.json`);
7624
+ var _recordExists = require_recordExists();
7625
+ var e;
7626
+ function _interopRequireWildcard(t, r) {
7627
+ if (!r && t && t.__esModule) return t;
7628
+ var n, a, o = Object.defineProperty, f = { __proto__: null, default: t };
7629
+ if (Object(t) !== t) return f;
7630
+ if (e || "function" != typeof WeakMap || (e = /* @__PURE__ */ new WeakMap()), e) {
7631
+ if (e.has(t)) return e.get(t);
7632
+ e.set(t, f);
7633
+ }
7634
+ 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]);
7635
+ return f;
7636
+ }
7637
+ var retrieveRecord = async (entity = "") => {
7638
+ if (jsEnv.isNode && !(0, _recordExists.recordExists)(entity)) {
7639
+ throw new Error(`Record "${entity}" doesn't exist`);
7640
+ }
7641
+ try {
7642
+ return await (0, _retrieveFile.retrieveFile)(`${entity}.json`);
7643
+ } catch (error) {
7644
+ if (!jsEnv.isNode) {
7645
+ throw new Error(`Record "${entity}" doesn't exist, or ${entity}.json can't be read`);
7646
+ }
7647
+ throw error;
7648
+ }
7649
+ };
6899
7650
  exports.retrieveRecord = retrieveRecord;
6900
7651
  }
6901
7652
  });
@@ -7042,6 +7793,104 @@ var jsonFsQuery = (() => {
7042
7793
  }
7043
7794
  });
7044
7795
 
7796
+ // dist/data/utilities/retrieveFiles.js
7797
+ var require_retrieveFiles = __commonJS({
7798
+ "dist/data/utilities/retrieveFiles.js"(exports) {
7799
+ "use strict";
7800
+ init_process();
7801
+ Object.defineProperty(exports, "__esModule", {
7802
+ value: true
7803
+ });
7804
+ exports.retrieveFiles = void 0;
7805
+ var _retrieveFile = require_retrieveFile();
7806
+ var _config = require_config();
7807
+ var retrieveFiles = async (paths, read = _retrieveFile.retrieveFile) => {
7808
+ const limit = Math.max(1, Math.floor((0, _config.getSetting)("readConcurrency", 16)) || 1);
7809
+ const contents = new Array(paths.length);
7810
+ const failures = [];
7811
+ let next = 0;
7812
+ const worker = async () => {
7813
+ while (next < paths.length && !failures.length) {
7814
+ const position = next++;
7815
+ try {
7816
+ contents[position] = await read(paths[position]);
7817
+ } catch (error) {
7818
+ failures.push({
7819
+ position,
7820
+ error
7821
+ });
7822
+ }
7823
+ }
7824
+ };
7825
+ await Promise.all(Array.from({
7826
+ length: Math.min(limit, paths.length)
7827
+ }, worker));
7828
+ if (failures.length) {
7829
+ throw failures.reduce((first, failure) => failure.position < first.position ? failure : first).error;
7830
+ }
7831
+ return contents;
7832
+ };
7833
+ exports.retrieveFiles = retrieveFiles;
7834
+ }
7835
+ });
7836
+
7837
+ // dist/data/utilities/packedTable.js
7838
+ var require_packedTable = __commonJS({
7839
+ "dist/data/utilities/packedTable.js"(exports) {
7840
+ "use strict";
7841
+ init_process();
7842
+ require_esnext_weak_map_delete_all();
7843
+ Object.defineProperty(exports, "__esModule", {
7844
+ value: true
7845
+ });
7846
+ exports.usesPackedReads = exports.retrievePacked = exports.packedPath = exports.discardPacked = void 0;
7847
+ require_esnext_iterator_constructor();
7848
+ require_esnext_iterator_some();
7849
+ var jsEnv = _interopRequireWildcard(require_dist());
7850
+ var _storage = require_storage();
7851
+ var _config = require_config();
7852
+ var e;
7853
+ function _interopRequireWildcard(t, r) {
7854
+ if (!r && t && t.__esModule) return t;
7855
+ var n, a, o = Object.defineProperty, f = { __proto__: null, default: t };
7856
+ if (Object(t) !== t) return f;
7857
+ if (e || "function" != typeof WeakMap || (e = /* @__PURE__ */ new WeakMap()), e) {
7858
+ if (e.has(t)) return e.get(t);
7859
+ e.set(t, f);
7860
+ }
7861
+ 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]);
7862
+ return f;
7863
+ }
7864
+ var packedPath = (recordPath) => `__packed/${recordPath}.json`;
7865
+ exports.packedPath = packedPath;
7866
+ var usesPackedReads = () => (0, _config.getSetting)("packedReads", !jsEnv.isNode);
7867
+ exports.usesPackedReads = usesPackedReads;
7868
+ var retrievePacked = async (record) => {
7869
+ if (!usesPackedReads()) {
7870
+ return void 0;
7871
+ }
7872
+ let packed;
7873
+ try {
7874
+ packed = await (0, _storage.readJson)(packedPath(record.path));
7875
+ } catch (error) {
7876
+ return void 0;
7877
+ }
7878
+ const entries = record.entries || [];
7879
+ if (!packed || !Array.isArray(packed.entries) || !Array.isArray(packed.rows) || packed.entries.length !== entries.length || packed.rows.length !== entries.length || packed.entries.some((entry, position) => entry !== entries[position])) {
7880
+ return void 0;
7881
+ }
7882
+ return packed;
7883
+ };
7884
+ exports.retrievePacked = retrievePacked;
7885
+ var discardPacked = async (recordPath) => {
7886
+ if ((0, _storage.fileExists)(packedPath(recordPath))) {
7887
+ await (0, _storage.removeFile)(packedPath(recordPath));
7888
+ }
7889
+ };
7890
+ exports.discardPacked = discardPacked;
7891
+ }
7892
+ });
7893
+
7045
7894
  // dist/data/utilities/retrieveRecords.js
7046
7895
  var require_retrieveRecords = __commonJS({
7047
7896
  "dist/data/utilities/retrieveRecords.js"(exports) {
@@ -7050,20 +7899,51 @@ var jsonFsQuery = (() => {
7050
7899
  Object.defineProperty(exports, "__esModule", {
7051
7900
  value: true
7052
7901
  });
7053
- exports.retrieveRecords = void 0;
7902
+ exports.retrieveRecords = exports.retrieveEntryRows = exports.retrieveEntry = void 0;
7903
+ require_esnext_iterator_constructor();
7904
+ require_esnext_iterator_filter();
7905
+ require_esnext_iterator_map();
7906
+ require_esnext_map_delete_all();
7907
+ require_esnext_map_every();
7908
+ require_esnext_map_filter();
7909
+ require_esnext_map_find();
7910
+ require_esnext_map_find_key();
7911
+ require_esnext_map_includes();
7912
+ require_esnext_map_key_of();
7913
+ require_esnext_map_map_keys();
7914
+ require_esnext_map_map_values();
7915
+ require_esnext_map_merge();
7916
+ require_esnext_map_reduce();
7917
+ require_esnext_map_some();
7918
+ require_esnext_map_update();
7054
7919
  var _retrieveFile = require_retrieveFile();
7055
7920
  var _retrieveRecord = require_retrieveRecord();
7921
+ var _retrieveFiles = require_retrieveFiles();
7922
+ var _packedTable = require_packedTable();
7923
+ var _config = require_config();
7924
+ var retrieveEntry = async (path) => {
7925
+ const data = await (0, _retrieveFile.retrieveFile)(path).catch((err) => console.error(err));
7926
+ if (!data) {
7927
+ throw new Error(`Could not read entity ${path.slice(path.lastIndexOf("/") + 1)}`);
7928
+ }
7929
+ return data;
7930
+ };
7931
+ exports.retrieveEntry = retrieveEntry;
7932
+ var retrieveEntryRows = async (record, files, read = retrieveEntry) => {
7933
+ const packed = files.length > (0, _config.getSetting)("readConcurrency", 16) ? await (0, _packedTable.retrievePacked)(record) : void 0;
7934
+ if (!packed) {
7935
+ return (0, _retrieveFiles.retrieveFiles)(files.map((file) => `${record.path}/${file}`), read);
7936
+ }
7937
+ const positions = new Map(packed.entries.map((entry, position) => [entry, position]));
7938
+ const unpacked = files.filter((file) => !positions.has(file));
7939
+ const readRows = unpacked.length ? await (0, _retrieveFiles.retrieveFiles)(unpacked.map((file) => `${record.path}/${file}`), read) : [];
7940
+ const fromFiles = new Map(unpacked.map((file, position) => [file, readRows[position]]));
7941
+ return files.map((file) => positions.has(file) ? packed.rows[positions.get(file)] : fromFiles.get(file));
7942
+ };
7943
+ exports.retrieveEntryRows = retrieveEntryRows;
7056
7944
  var retrieveRecords = async (entity = "") => {
7057
7945
  const recordFile = await (0, _retrieveRecord.retrieveRecord)(entity);
7058
- const dataSet = [];
7059
- for (const file of recordFile.entries) {
7060
- const data = await (0, _retrieveFile.retrieveFile)(`${recordFile.path}/${file}`).catch((err) => console.error(err));
7061
- if (!data) {
7062
- throw new Error(`Could not read entity ${file}`);
7063
- }
7064
- dataSet.push(data);
7065
- }
7066
- return dataSet;
7946
+ return retrieveEntryRows(recordFile, recordFile.entries);
7067
7947
  };
7068
7948
  exports.retrieveRecords = retrieveRecords;
7069
7949
  }
@@ -7482,6 +8362,7 @@ var jsonFsQuery = (() => {
7482
8362
  var _config = require_config();
7483
8363
  var _keyIndexFiles = require_keyIndexFiles();
7484
8364
  var _storage = require_storage();
8365
+ var _packedTable = require_packedTable();
7485
8366
  var assertNoDependents = async (entity, primaryKey, toDelete) => {
7486
8367
  if (!(0, _config.getSetting)("enforceForeignKeys", true) || primaryKey.fields.length !== 1) {
7487
8368
  return;
@@ -7531,7 +8412,11 @@ var jsonFsQuery = (() => {
7531
8412
  }
7532
8413
  await assertNoDependents(entity, primaryKey, toDelete);
7533
8414
  const deletedValues = new Set(toDelete.map((row) => (0, _computeKeyValue.computeKeyValue)(primaryKey.fields, row)));
7534
- record.entries = await removeMatchingEntries(entity, record, primaryKey, deletedValues);
8415
+ const remaining = await removeMatchingEntries(entity, record, primaryKey, deletedValues);
8416
+ if (remaining.length !== record.entries.length) {
8417
+ await (0, _packedTable.discardPacked)(record.path);
8418
+ }
8419
+ record.entries = remaining;
7535
8420
  await (0, _storage.writeJson)(`${record.path}.json`, record);
7536
8421
  return dataSet;
7537
8422
  };
@@ -7539,48 +8424,45 @@ var jsonFsQuery = (() => {
7539
8424
  }
7540
8425
  });
7541
8426
 
7542
- // dist/data/utilities/updateIndex.js
7543
- var require_updateIndex = __commonJS({
7544
- "dist/data/utilities/updateIndex.js"(exports) {
8427
+ // node_modules/core-js/modules/es.iterator.every.js
8428
+ var require_es_iterator_every = __commonJS({
8429
+ "node_modules/core-js/modules/es.iterator.every.js"() {
7545
8430
  "use strict";
7546
8431
  init_process();
7547
- Object.defineProperty(exports, "__esModule", {
7548
- value: true
7549
- });
7550
- exports.updateIndex = void 0;
7551
- require_es_array_includes();
7552
- require_esnext_iterator_constructor();
7553
- require_esnext_iterator_find();
7554
- var _compareAs = require_compareAs();
7555
- var _storage = require_storage();
7556
- var updateIndex = async (path = "", key = null, value = void 0, fileName = "", type = void 0) => {
7557
- if (!key || !key.lookup) {
7558
- return null;
7559
- }
7560
- const indexDir = `__indexes/${path}`;
7561
- const indexPath = `${indexDir}/${key.lookup}`;
7562
- let index = [];
7563
- try {
7564
- index = await (0, _storage.readJson)(indexPath);
7565
- } catch (err) {
7566
- index = [];
7567
- }
7568
- const existingEntry = index.find((entry) => (0, _compareAs.sameValue)(type, entry.value, value));
7569
- if (existingEntry) {
7570
- if (!existingEntry.record.includes(fileName)) {
7571
- existingEntry.record.push(fileName);
8432
+ var $ = require_export();
8433
+ var call = require_function_call();
8434
+ var iterate = require_iterate();
8435
+ var aCallable = require_a_callable();
8436
+ var anObject = require_an_object();
8437
+ var getIteratorDirect = require_get_iterator_direct();
8438
+ var iteratorClose = require_iterator_close();
8439
+ var iteratorHelperWithoutClosingOnEarlyError = require_iterator_helper_without_closing_on_early_error();
8440
+ var everyWithoutClosingOnEarlyError = iteratorHelperWithoutClosingOnEarlyError("every", TypeError);
8441
+ $({ target: "Iterator", proto: true, real: true, forced: everyWithoutClosingOnEarlyError }, {
8442
+ every: function every(predicate) {
8443
+ anObject(this);
8444
+ try {
8445
+ aCallable(predicate);
8446
+ } catch (error) {
8447
+ iteratorClose(this, "throw", error);
7572
8448
  }
7573
- } else {
7574
- index.push({
7575
- value,
7576
- record: [fileName]
7577
- });
8449
+ if (everyWithoutClosingOnEarlyError) return call(everyWithoutClosingOnEarlyError, this, predicate);
8450
+ var record = getIteratorDirect(this);
8451
+ var counter = 0;
8452
+ return !iterate(record, function(value, stop) {
8453
+ if (!predicate(value, counter++)) return stop();
8454
+ }, { IS_RECORD: true, INTERRUPTED: true }).stopped;
7578
8455
  }
7579
- await (0, _storage.makeDirectory)(indexDir);
7580
- await (0, _storage.writeJson)(indexPath, index);
7581
- return index;
7582
- };
7583
- exports.updateIndex = updateIndex;
8456
+ });
8457
+ }
8458
+ });
8459
+
8460
+ // node_modules/core-js/modules/esnext.iterator.every.js
8461
+ var require_esnext_iterator_every = __commonJS({
8462
+ "node_modules/core-js/modules/esnext.iterator.every.js"() {
8463
+ "use strict";
8464
+ init_process();
8465
+ require_es_iterator_every();
7584
8466
  }
7585
8467
  });
7586
8468
 
@@ -7624,29 +8506,6 @@ var jsonFsQuery = (() => {
7624
8506
  }
7625
8507
  });
7626
8508
 
7627
- // dist/data/introspect/policies/keyGenerate.js
7628
- var require_keyGenerate = __commonJS({
7629
- "dist/data/introspect/policies/keyGenerate.js"(exports) {
7630
- "use strict";
7631
- init_process();
7632
- Object.defineProperty(exports, "__esModule", {
7633
- value: true
7634
- });
7635
- exports.keyGenerate = void 0;
7636
- var _keyUnique = require_keyUnique();
7637
- var keyGenerate = async (entity, references = []) => {
7638
- let uuid = null;
7639
- let isUnique = false;
7640
- while (!isUnique) {
7641
- uuid = crypto.randomUUID();
7642
- isUnique = await (0, _keyUnique.keyUnique)(entity, references, [uuid]);
7643
- }
7644
- return uuid;
7645
- };
7646
- exports.keyGenerate = keyGenerate;
7647
- }
7648
- });
7649
-
7650
8509
  // dist/data/introspect/policies/useDefault.js
7651
8510
  var require_useDefault = __commonJS({
7652
8511
  "dist/data/introspect/policies/useDefault.js"(exports) {
@@ -7698,6 +8557,253 @@ var jsonFsQuery = (() => {
7698
8557
  }
7699
8558
  });
7700
8559
 
8560
+ // dist/data/utilities/indexBuffer.js
8561
+ var require_indexBuffer = __commonJS({
8562
+ "dist/data/utilities/indexBuffer.js"(exports) {
8563
+ "use strict";
8564
+ init_process();
8565
+ Object.defineProperty(exports, "__esModule", {
8566
+ value: true
8567
+ });
8568
+ exports.IndexBuffer = void 0;
8569
+ require_es_array_includes();
8570
+ require_esnext_iterator_constructor();
8571
+ require_esnext_iterator_find();
8572
+ require_esnext_iterator_some();
8573
+ require_esnext_map_delete_all();
8574
+ require_esnext_map_every();
8575
+ require_esnext_map_filter();
8576
+ require_esnext_map_find();
8577
+ require_esnext_map_find_key();
8578
+ require_esnext_map_includes();
8579
+ require_esnext_map_key_of();
8580
+ require_esnext_map_map_keys();
8581
+ require_esnext_map_map_values();
8582
+ require_esnext_map_merge();
8583
+ require_esnext_map_reduce();
8584
+ require_esnext_map_some();
8585
+ require_esnext_map_update();
8586
+ require_esnext_set_add_all();
8587
+ require_esnext_set_delete_all();
8588
+ require_esnext_set_difference();
8589
+ require_esnext_set_every();
8590
+ require_esnext_set_filter();
8591
+ require_esnext_set_find();
8592
+ require_esnext_set_intersection();
8593
+ require_esnext_set_is_disjoint_from();
8594
+ require_esnext_set_is_subset_of();
8595
+ require_esnext_set_is_superset_of();
8596
+ require_esnext_set_join();
8597
+ require_esnext_set_map();
8598
+ require_esnext_set_reduce();
8599
+ require_esnext_set_some();
8600
+ require_esnext_set_symmetric_difference();
8601
+ require_esnext_set_union();
8602
+ require_esnext_weak_map_delete_all();
8603
+ var _compareAs = require_compareAs();
8604
+ var unkeyed = /* @__PURE__ */ Symbol("unkeyed");
8605
+ var keyOf = (type, value) => {
8606
+ if (!_compareAs.comparableTypes.includes(type)) {
8607
+ return unkeyed;
8608
+ }
8609
+ const key = (0, _compareAs.compareAs)(type, value);
8610
+ return typeof key === "object" && key !== null ? unkeyed : key;
8611
+ };
8612
+ var IndexBuffer = class {
8613
+ /**
8614
+ * @param entries - The index as read from its file ([] when there's none yet).
8615
+ * @param type - The key's value type (see keyValueType).
8616
+ */
8617
+ constructor(entries, type) {
8618
+ this.byKey = /* @__PURE__ */ new Map();
8619
+ this.listed = /* @__PURE__ */ new WeakMap();
8620
+ this.entries = entries;
8621
+ this.type = type;
8622
+ for (const entry of entries) {
8623
+ const key = keyOf(type, entry.value);
8624
+ if (key !== unkeyed && !this.byKey.has(key)) {
8625
+ this.byKey.set(key, entry);
8626
+ }
8627
+ }
8628
+ }
8629
+ /**
8630
+ * The entry for `value`, as updateIndex finds it.
8631
+ * @param value
8632
+ */
8633
+ find(value) {
8634
+ const key = keyOf(this.type, value);
8635
+ return key === unkeyed ? this.entries.find((entry) => (0, _compareAs.sameValue)(this.type, entry.value, value)) : this.byKey.get(key);
8636
+ }
8637
+ /**
8638
+ * Whether a row holds `value`, as indexHas answers it: an entry for it lists a file (never for null or undefined).
8639
+ * @param value
8640
+ */
8641
+ has(value) {
8642
+ if (value === null || typeof value === "undefined") {
8643
+ return false;
8644
+ }
8645
+ const listsFiles = (entry) => Boolean(entry && Array.isArray(entry.record) && entry.record.length);
8646
+ const first = this.find(value);
8647
+ if (!first || listsFiles(first)) {
8648
+ return listsFiles(first);
8649
+ }
8650
+ return this.entries.some((entry) => (0, _compareAs.sameValue)(this.type, entry.value, value) && listsFiles(entry));
8651
+ }
8652
+ /**
8653
+ * List `fileName` under `value`, as updateIndex does.
8654
+ * @param value
8655
+ * @param fileName
8656
+ */
8657
+ add(value, fileName) {
8658
+ const existing = this.find(value);
8659
+ if (existing) {
8660
+ if (!this.listed.has(existing)) {
8661
+ this.listed.set(existing, new Set(existing.record));
8662
+ }
8663
+ const files = this.listed.get(existing);
8664
+ if (!files.has(fileName)) {
8665
+ files.add(fileName);
8666
+ existing.record.push(fileName);
8667
+ }
8668
+ return;
8669
+ }
8670
+ const entry = {
8671
+ value,
8672
+ record: [fileName]
8673
+ };
8674
+ this.entries.push(entry);
8675
+ this.listed.set(entry, new Set(entry.record));
8676
+ const key = keyOf(this.type, value);
8677
+ if (key !== unkeyed) {
8678
+ this.byKey.set(key, entry);
8679
+ }
8680
+ }
8681
+ };
8682
+ exports.IndexBuffer = IndexBuffer;
8683
+ }
8684
+ });
8685
+
8686
+ // dist/data/utilities/parsers/isEntityProperty.js
8687
+ var require_isEntityProperty = __commonJS({
8688
+ "dist/data/utilities/parsers/isEntityProperty.js"(exports) {
8689
+ "use strict";
8690
+ init_process();
8691
+ Object.defineProperty(exports, "__esModule", {
8692
+ value: true
8693
+ });
8694
+ exports.isEntityProperty = void 0;
8695
+ var isEntityProperty = (property) => /^[a-z0-9_-]+\.([a-z0-9_-]+)$/i.test(property);
8696
+ exports.isEntityProperty = isEntityProperty;
8697
+ }
8698
+ });
8699
+
8700
+ // dist/data/utilities/knownFields.js
8701
+ var require_knownFields = __commonJS({
8702
+ "dist/data/utilities/knownFields.js"(exports) {
8703
+ "use strict";
8704
+ init_process();
8705
+ Object.defineProperty(exports, "__esModule", {
8706
+ value: true
8707
+ });
8708
+ exports.assertKnownFields = exports.assertFieldsDefined = void 0;
8709
+ require_esnext_iterator_constructor();
8710
+ require_esnext_iterator_filter();
8711
+ require_esnext_iterator_find();
8712
+ require_esnext_iterator_flat_map();
8713
+ require_esnext_iterator_map();
8714
+ require_esnext_set_add_all();
8715
+ require_esnext_set_delete_all();
8716
+ require_esnext_set_difference();
8717
+ require_esnext_set_every();
8718
+ require_esnext_set_filter();
8719
+ require_esnext_set_find();
8720
+ require_esnext_set_intersection();
8721
+ require_esnext_set_is_disjoint_from();
8722
+ require_esnext_set_is_subset_of();
8723
+ require_esnext_set_is_superset_of();
8724
+ require_esnext_set_join();
8725
+ require_esnext_set_map();
8726
+ require_esnext_set_reduce();
8727
+ require_esnext_set_some();
8728
+ require_esnext_set_symmetric_difference();
8729
+ require_esnext_set_union();
8730
+ var _retrieveRecord = require_retrieveRecord();
8731
+ var _isEntityProperty = require_isEntityProperty();
8732
+ var _splitEntityProperty = require_splitEntityProperty();
8733
+ var _conditionTree = require_conditionTree();
8734
+ var fieldList = (record) => record.definition.map((field) => field.name).join(", ");
8735
+ var assertFieldsDefined = (entity, record, fields, where) => {
8736
+ const defined = new Set(record.definition.map((field) => field.name));
8737
+ const unknown = fields.find((field) => !defined.has(field));
8738
+ if (typeof unknown !== "undefined") {
8739
+ throw new Error(`Unknown field "${unknown}" in ${where}: ${entity} has ${fieldList(record)}`);
8740
+ }
8741
+ };
8742
+ exports.assertFieldsDefined = assertFieldsDefined;
8743
+ var assertKnownFields = async (parsed, recordData) => {
8744
+ const merged = new Set((parsed.mergeJoins || []).map((merge) => (0, _splitEntityProperty.splitEntityProperty)(merge.propertyB).entity));
8745
+ const named = [...(0, _conditionTree.conditionsOf)(parsed.where).map((condition) => ({
8746
+ property: condition.property,
8747
+ clause: "where"
8748
+ })), ...(parsed.sortClauses || []).map((sort) => ({
8749
+ property: sort.property,
8750
+ clause: "sort"
8751
+ })), ...(parsed.groupBy || []).map((property) => ({
8752
+ property,
8753
+ clause: "group by"
8754
+ })), ...(parsed.selectClauses || []).filter((select) => select.property !== parsed.joinEntity).map((select) => ({
8755
+ property: select.property,
8756
+ clause: "select"
8757
+ })), ...(parsed.insertValues || []).flatMap((row) => Object.keys(row || {}).map((property) => ({
8758
+ property,
8759
+ clause: "insert",
8760
+ own: true
8761
+ }))), ...Object.keys(parsed.updateValues || {}).map((property) => ({
8762
+ property,
8763
+ clause: "set",
8764
+ own: true
8765
+ })), ...(parsed.joinClauses || []).flatMap((join) => [{
8766
+ property: join.propertyA,
8767
+ clause: "on"
8768
+ }, {
8769
+ property: join.propertyB,
8770
+ clause: "on"
8771
+ }]), ...(parsed.mergeJoins || []).flatMap((merge) => [{
8772
+ property: merge.propertyA,
8773
+ clause: "merge"
8774
+ }, {
8775
+ property: merge.propertyB,
8776
+ clause: "merge"
8777
+ }])];
8778
+ for (const {
8779
+ property,
8780
+ clause,
8781
+ own
8782
+ } of named) {
8783
+ if (typeof property !== "string") {
8784
+ continue;
8785
+ }
8786
+ let entity = parsed.entity;
8787
+ let field = property;
8788
+ if (!own && (0, _isEntityProperty.isEntityProperty)(property)) {
8789
+ ({
8790
+ entity,
8791
+ property: field
8792
+ } = (0, _splitEntityProperty.splitEntityProperty)(property));
8793
+ }
8794
+ if (clause === "select" && entity !== parsed.entity && !merged.has(entity)) {
8795
+ 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>)`);
8796
+ }
8797
+ if (!Object.prototype.hasOwnProperty.call(recordData, entity)) {
8798
+ recordData[entity] = await (0, _retrieveRecord.retrieveRecord)(entity);
8799
+ }
8800
+ assertFieldsDefined(entity, recordData[entity], [field], clause);
8801
+ }
8802
+ };
8803
+ exports.assertKnownFields = assertKnownFields;
8804
+ }
8805
+ });
8806
+
7701
8807
  // dist/data/queries/insertEntity.js
7702
8808
  var require_insertEntity = __commonJS({
7703
8809
  "dist/data/queries/insertEntity.js"(exports) {
@@ -7707,13 +8813,44 @@ var jsonFsQuery = (() => {
7707
8813
  value: true
7708
8814
  });
7709
8815
  exports.insertEntity = void 0;
8816
+ require_es_array_includes();
8817
+ require_es_json_stringify();
7710
8818
  require_esnext_iterator_constructor();
8819
+ require_esnext_iterator_every();
7711
8820
  require_esnext_iterator_find();
8821
+ require_esnext_iterator_for_each();
7712
8822
  require_esnext_iterator_map();
7713
8823
  require_esnext_iterator_some();
8824
+ require_esnext_map_delete_all();
8825
+ require_esnext_map_every();
8826
+ require_esnext_map_filter();
8827
+ require_esnext_map_find();
8828
+ require_esnext_map_find_key();
8829
+ require_esnext_map_includes();
8830
+ require_esnext_map_key_of();
8831
+ require_esnext_map_map_keys();
8832
+ require_esnext_map_map_values();
8833
+ require_esnext_map_merge();
8834
+ require_esnext_map_reduce();
8835
+ require_esnext_map_some();
8836
+ require_esnext_map_update();
8837
+ require_esnext_set_add_all();
8838
+ require_esnext_set_delete_all();
8839
+ require_esnext_set_difference();
8840
+ require_esnext_set_every();
8841
+ require_esnext_set_filter();
8842
+ require_esnext_set_find();
8843
+ require_esnext_set_intersection();
8844
+ require_esnext_set_is_disjoint_from();
8845
+ require_esnext_set_is_subset_of();
8846
+ require_esnext_set_is_superset_of();
8847
+ require_esnext_set_join();
8848
+ require_esnext_set_map();
8849
+ require_esnext_set_reduce();
8850
+ require_esnext_set_some();
8851
+ require_esnext_set_symmetric_difference();
8852
+ require_esnext_set_union();
7714
8853
  var _retrieveRecord = require_retrieveRecord();
7715
- var _updateIndex = require_updateIndex();
7716
- var _keyGenerate = require_keyGenerate();
7717
8854
  var _keyUnique = require_keyUnique();
7718
8855
  var _useDefault = require_useDefault();
7719
8856
  var _typeCheck = require_typeCheck();
@@ -7721,19 +8858,262 @@ var jsonFsQuery = (() => {
7721
8858
  var _splitEntityProperty = require_splitEntityProperty();
7722
8859
  var _computeKeyValue = require_computeKeyValue();
7723
8860
  var _fieldType = require_fieldType();
8861
+ var _compareAs = require_compareAs();
8862
+ var _retrieveRecords = require_retrieveRecords();
8863
+ var _isSingleFieldKey = require_isSingleFieldKey();
8864
+ var _indexBuffer = require_indexBuffer();
7724
8865
  var _storage = require_storage();
7725
- var buildEntityValues = async (entity, record, rowValues = {}) => {
8866
+ var _packedTable = require_packedTable();
8867
+ var _knownFields = require_knownFields();
8868
+ var RowValues = class {
8869
+ constructor(record, fields) {
8870
+ this.seen = /* @__PURE__ */ new Set();
8871
+ this.fields = fields;
8872
+ this.types = fields.map((field) => (0, _fieldType.fieldType)(record, field));
8873
+ }
8874
+ /**
8875
+ * Whether these fields' values can be compared this way: every field of a comparable type (see compareAs).
8876
+ * @param record
8877
+ * @param fields
8878
+ */
8879
+ static usable(record, fields) {
8880
+ return fields.every((field) => _compareAs.comparableTypes.includes((0, _fieldType.fieldType)(record, field)));
8881
+ }
8882
+ /**
8883
+ * The values' key, or undefined when one is null or missing (where's = never matches those) or compareAs leaves it an
8884
+ * object (compared by identity, so not by a key).
8885
+ * @param row
8886
+ */
8887
+ keyOf(row) {
8888
+ const typed = [];
8889
+ for (let position = 0; position < this.fields.length; position++) {
8890
+ const value = row[this.fields[position]];
8891
+ if (value === null || typeof value === "undefined") {
8892
+ return void 0;
8893
+ }
8894
+ const key = (0, _compareAs.compareAs)(this.types[position], value);
8895
+ if (typeof key === "object") {
8896
+ return void 0;
8897
+ }
8898
+ typed.push([typeof key, key]);
8899
+ }
8900
+ return JSON.stringify(typed);
8901
+ }
8902
+ add(row) {
8903
+ const key = this.keyOf(row);
8904
+ if (typeof key !== "undefined") {
8905
+ this.seen.add(key);
8906
+ }
8907
+ }
8908
+ has(row) {
8909
+ const key = this.keyOf(row);
8910
+ return typeof key !== "undefined" && this.seen.has(key);
8911
+ }
8912
+ };
8913
+ var InsertStatement = class {
8914
+ constructor(entity, record) {
8915
+ this.rows = [];
8916
+ this.buffers = /* @__PURE__ */ new Map();
8917
+ this.unreadable = /* @__PURE__ */ new Set();
8918
+ this.otherLookups = /* @__PURE__ */ new Map();
8919
+ this.scans = /* @__PURE__ */ new Map();
8920
+ this.entity = entity;
8921
+ this.record = record;
8922
+ this.hadEntries = (record.entries || []).length > 0;
8923
+ }
8924
+ /**
8925
+ * Read the record's index files, once. An index that can't be read starts empty (as updateIndex starts one) and its
8926
+ * key is checked by looking at every row.
8927
+ */
8928
+ async load() {
8929
+ for (const key of this.record.keys) {
8930
+ if (!key.lookup) {
8931
+ continue;
8932
+ }
8933
+ let entries = [];
8934
+ try {
8935
+ entries = await (0, _storage.readJson)(`__indexes/${this.record.path}/${key.lookup}`);
8936
+ } catch (error) {
8937
+ this.unreadable.add(key);
8938
+ }
8939
+ this.buffers.set(key, new _indexBuffer.IndexBuffer(Array.isArray(entries) ? entries : [], (0, _fieldType.keyValueType)(this.record, key)));
8940
+ }
8941
+ }
8942
+ /**
8943
+ * How to look up a non-null value of `property` in the record being inserted into: through its index buffer, which
8944
+ * holds the statement's rows so far. indexHas reads a record with no entries as holding nothing, whatever its index
8945
+ * file says, so until this statement adds a row to a record that had none, nothing is found.
8946
+ * @param property
8947
+ */
8948
+ ownLookup(property) {
8949
+ const key = this.record.keys.find((key2) => (0, _isSingleFieldKey.isSingleFieldKey)(key2, property) && key2.lookup);
8950
+ if (!key || this.unreadable.has(key)) {
8951
+ return () => void 0;
8952
+ }
8953
+ const buffer = this.buffers.get(key);
8954
+ return (value) => (this.hadEntries || this.rows.length > 0) && buffer.has(value);
8955
+ }
8956
+ /**
8957
+ * How to look up a non-null value of `property` in another record, read once (an insert doesn't change it).
8958
+ * @param entity
8959
+ * @param property
8960
+ */
8961
+ otherLookup(entity, property) {
8962
+ const name = `${entity}\0${property}`;
8963
+ if (!this.otherLookups.has(name)) {
8964
+ this.otherLookups.set(name, (async () => {
8965
+ const record = await (0, _retrieveRecord.retrieveRecord)(entity);
8966
+ const key = record.keys.find((key2) => (0, _isSingleFieldKey.isSingleFieldKey)(key2, property) && key2.lookup);
8967
+ if (!key) {
8968
+ return () => void 0;
8969
+ }
8970
+ if (!(record.entries || []).length) {
8971
+ return () => false;
8972
+ }
8973
+ let entries;
8974
+ try {
8975
+ entries = await (0, _storage.readJson)(`__indexes/${record.path}/${key.lookup}`);
8976
+ } catch (error) {
8977
+ return () => void 0;
8978
+ }
8979
+ const buffer = new _indexBuffer.IndexBuffer(Array.isArray(entries) ? entries : [], (0, _fieldType.fieldType)(record, property));
8980
+ return (value) => buffer.has(value);
8981
+ })());
8982
+ }
8983
+ return this.otherLookups.get(name);
8984
+ }
8985
+ /**
8986
+ * The values of these fields in every row of `entity` (read once per statement), plus, for the record being inserted
8987
+ * into, every row this statement adds; undefined when a field's type can't be compared by key.
8988
+ * @param entity
8989
+ * @param fields
8990
+ */
8991
+ scan(entity, fields) {
8992
+ const name = `${entity}\0${fields.join("\0")}`;
8993
+ if (!this.scans.has(name)) {
8994
+ this.scans.set(name, (async () => {
8995
+ const record = entity === this.entity ? this.record : await (0, _retrieveRecord.retrieveRecord)(entity);
8996
+ if (!RowValues.usable(record, fields)) {
8997
+ return void 0;
8998
+ }
8999
+ const values = new RowValues(record, fields);
9000
+ for (const row of await (0, _retrieveRecords.retrieveRecords)(entity)) {
9001
+ values.add(row);
9002
+ }
9003
+ if (entity === this.entity) {
9004
+ this.rows.forEach((row) => values.add(row));
9005
+ }
9006
+ return values;
9007
+ })());
9008
+ }
9009
+ return this.scans.get(name);
9010
+ }
9011
+ /**
9012
+ * Whether one of this statement's rows already holds these values in every one of these fields (none of them null).
9013
+ * @param fields
9014
+ * @param values
9015
+ */
9016
+ claimed(fields, values) {
9017
+ return this.rows.some((row) => fields.every((field) => row[field] !== null && typeof row[field] !== "undefined" && (0, _compareAs.sameValue)((0, _fieldType.fieldType)(this.record, field), row[field], values[field])));
9018
+ }
9019
+ /**
9020
+ * Whether no row (in storage or earlier in this statement) holds these values for these fields, as keyUnique answers
9021
+ * it after each earlier row is written.
9022
+ * @param fields
9023
+ * @param values
9024
+ */
9025
+ async isUnique(fields, values) {
9026
+ if (fields.length === 1) {
9027
+ const found = this.ownLookup(fields[0])(values[fields[0]]);
9028
+ if (typeof found !== "undefined") {
9029
+ return !found;
9030
+ }
9031
+ }
9032
+ const scanned = await this.scan(this.entity, fields);
9033
+ if (scanned) {
9034
+ return !scanned.has(values);
9035
+ }
9036
+ return await (0, _keyUnique.keyUnique)(this.entity, fields, fields.map((field) => values[field])) && !this.claimed(fields, values);
9037
+ }
9038
+ /**
9039
+ * Whether `entity` holds `value` in `property`, as foreignKeyExists answers it after each earlier row is written: a
9040
+ * row may reference one added earlier in the same statement when the key points at its own record.
9041
+ * @param entity
9042
+ * @param property
9043
+ * @param value
9044
+ */
9045
+ async exists(entity, property, value) {
9046
+ const own = entity === this.entity;
9047
+ const found = own ? this.ownLookup(property)(value) : (await this.otherLookup(entity, property))(value);
9048
+ if (typeof found !== "undefined") {
9049
+ return found;
9050
+ }
9051
+ const scanned = await this.scan(entity, [property]);
9052
+ if (scanned) {
9053
+ return scanned.has({
9054
+ [property]: value
9055
+ });
9056
+ }
9057
+ return await (0, _foreignKeyExists.foreignKeyExists)(entity, property, value) || own && this.claimed([property], {
9058
+ [property]: value
9059
+ });
9060
+ }
9061
+ /**
9062
+ * Note a row added to the statement, filed under `fileName`, in the record's entries and every index buffer.
9063
+ * @param entityValues
9064
+ * @param fileName
9065
+ */
9066
+ async add(entityValues, fileName) {
9067
+ this.rows.push(entityValues);
9068
+ for (const [name, scanned] of this.scans) {
9069
+ if (name.startsWith(`${this.entity}\0`)) {
9070
+ (await scanned)?.add(entityValues);
9071
+ }
9072
+ }
9073
+ this.record.entries.push(fileName);
9074
+ for (const [key, buffer] of this.buffers) {
9075
+ buffer.add((0, _computeKeyValue.computeKeyValue)(key.fields, entityValues), fileName);
9076
+ }
9077
+ }
9078
+ /**
9079
+ * Write the record file and each index once, with every row the statement added.
9080
+ */
9081
+ async write() {
9082
+ await (0, _storage.writeJson)(`${this.record.path}.json`, this.record);
9083
+ if (this.buffers.size) {
9084
+ await (0, _storage.makeDirectory)(`__indexes/${this.record.path}`);
9085
+ }
9086
+ for (const [key, buffer] of this.buffers) {
9087
+ await (0, _storage.writeJson)(`__indexes/${this.record.path}/${key.lookup}`, buffer.entries);
9088
+ }
9089
+ }
9090
+ };
9091
+ var generateKey = async (statement, field) => {
9092
+ let uuid;
9093
+ do {
9094
+ uuid = crypto.randomUUID();
9095
+ } while (!await statement.isUnique([field], {
9096
+ [field]: uuid
9097
+ }));
9098
+ return uuid;
9099
+ };
9100
+ var buildEntityValues = async (statement, rowValues = {}) => {
7726
9101
  const entityValues = {};
7727
- for (const field of record.definition) {
9102
+ for (const field of statement.record.definition) {
7728
9103
  let value = rowValues[field.name];
9104
+ if (value === null && field.optional && !field.nullable) {
9105
+ value = void 0;
9106
+ }
7729
9107
  if (field.autoGenerate) {
7730
- value = await (0, _keyGenerate.keyGenerate)(entity, [field.name]);
9108
+ if (value === void 0 || value === null) {
9109
+ value = await generateKey(statement, field.name);
9110
+ }
7731
9111
  } else if (Object.prototype.hasOwnProperty.call(field, "default")) {
7732
9112
  value = (0, _useDefault.useDefault)(field["default"], value);
7733
9113
  }
7734
9114
  if (typeof value === "undefined") {
7735
9115
  if (!field.optional) {
7736
- throw new Error(`Missing required field "${field.name}" for ${entity}`);
9116
+ throw new Error(`Missing required field "${field.name}" for ${statement.entity}`);
7737
9117
  }
7738
9118
  continue;
7739
9119
  }
@@ -7741,23 +9121,21 @@ var jsonFsQuery = (() => {
7741
9121
  }
7742
9122
  return entityValues;
7743
9123
  };
7744
- var assertUnique = async (entity, record, entityValues) => {
7745
- for (const key of record.keys) {
9124
+ var assertUnique = async (statement, entityValues) => {
9125
+ for (const key of statement.record.keys) {
7746
9126
  if (key.type !== "primary" && key.type !== "unique") {
7747
9127
  continue;
7748
9128
  }
7749
- const checkKeys = key.fields.map((field) => entityValues[field]);
7750
- if (checkKeys.some((value) => value === null)) {
9129
+ if (key.fields.some((field) => entityValues[field] === null)) {
7751
9130
  continue;
7752
9131
  }
7753
- const isUnique = await (0, _keyUnique.keyUnique)(entity, key.fields, checkKeys);
7754
- if (!isUnique) {
7755
- throw new Error(`Duplicate value for ${key.type} key "${key.fields.join(", ")}" on ${entity}`);
9132
+ if (!await statement.isUnique(key.fields, entityValues)) {
9133
+ throw new Error(`Duplicate value for ${key.type} key "${key.fields.join(", ")}" on ${statement.entity}`);
7756
9134
  }
7757
9135
  }
7758
9136
  };
7759
- var assertForeignKeys = async (entity, record, entityValues) => {
7760
- for (const key of record.keys) {
9137
+ var assertForeignKeys = async (statement, entityValues) => {
9138
+ for (const key of statement.record.keys) {
7761
9139
  if (key.type !== "foreign" || key.fields.length !== 1 || !key.references || key.references.length !== 1) {
7762
9140
  continue;
7763
9141
  }
@@ -7769,9 +9147,8 @@ var jsonFsQuery = (() => {
7769
9147
  entity: refEntity,
7770
9148
  property: refProperty
7771
9149
  } = (0, _splitEntityProperty.splitEntityProperty)(key.references[0].fields[0]);
7772
- const exists = await (0, _foreignKeyExists.foreignKeyExists)(refEntity, refProperty, entityValues[field]);
7773
- if (!exists) {
7774
- throw new Error(`Foreign key "${field}" on ${entity} references a nonexistent ${refEntity}.${refProperty} = ${entityValues[field]}`);
9150
+ if (!await statement.exists(refEntity, refProperty, entityValues[field])) {
9151
+ throw new Error(`Foreign key "${field}" on ${statement.entity} references a nonexistent ${refEntity}.${refProperty} = ${entityValues[field]}`);
7775
9152
  }
7776
9153
  }
7777
9154
  };
@@ -7781,20 +9158,26 @@ var jsonFsQuery = (() => {
7781
9158
  if (!Object.prototype.hasOwnProperty.call(dataSet, entity)) {
7782
9159
  dataSet[entity] = [];
7783
9160
  }
7784
- await (0, _storage.makeDirectory)(record.path);
9161
+ await (0, _storage.makeDirectory)(record.path);
9162
+ if (!values.length) {
9163
+ return dataSet;
9164
+ }
9165
+ for (const rowValues of values) {
9166
+ (0, _knownFields.assertFieldsDefined)(entity, record, Object.keys(rowValues || {}), "insert");
9167
+ }
9168
+ await (0, _packedTable.discardPacked)(record.path);
9169
+ const statement = new InsertStatement(entity, record);
9170
+ await statement.load();
7785
9171
  for (const rowValues of values) {
7786
- const entityValues = await buildEntityValues(entity, record, rowValues);
7787
- await assertUnique(entity, record, entityValues);
7788
- await assertForeignKeys(entity, record, entityValues);
9172
+ const entityValues = await buildEntityValues(statement, rowValues);
9173
+ await assertUnique(statement, entityValues);
9174
+ await assertForeignKeys(statement, entityValues);
7789
9175
  const fileName = `${primaryKey ? entityValues[primaryKey.fields[0]] : crypto.randomUUID()}.json`;
7790
9176
  await (0, _storage.writeJson)(`${record.path}/${fileName}`, entityValues);
7791
- record.entries.push(fileName);
7792
- await (0, _storage.writeJson)(`${record.path}.json`, record);
7793
- for (const key of record.keys) {
7794
- await (0, _updateIndex.updateIndex)(record.path, key, (0, _computeKeyValue.computeKeyValue)(key.fields, entityValues), fileName, (0, _fieldType.keyValueType)(record, key));
7795
- }
9177
+ await statement.add(entityValues, fileName);
7796
9178
  dataSet[entity].push(entityValues);
7797
9179
  }
9180
+ await statement.write();
7798
9181
  return dataSet;
7799
9182
  };
7800
9183
  exports.insertEntity = insertEntity;
@@ -7821,6 +9204,51 @@ var jsonFsQuery = (() => {
7821
9204
  }
7822
9205
  });
7823
9206
 
9207
+ // dist/data/utilities/updateIndex.js
9208
+ var require_updateIndex = __commonJS({
9209
+ "dist/data/utilities/updateIndex.js"(exports) {
9210
+ "use strict";
9211
+ init_process();
9212
+ Object.defineProperty(exports, "__esModule", {
9213
+ value: true
9214
+ });
9215
+ exports.updateIndex = void 0;
9216
+ require_es_array_includes();
9217
+ require_esnext_iterator_constructor();
9218
+ require_esnext_iterator_find();
9219
+ var _compareAs = require_compareAs();
9220
+ var _storage = require_storage();
9221
+ var updateIndex = async (path = "", key = null, value = void 0, fileName = "", type = void 0) => {
9222
+ if (!key || !key.lookup) {
9223
+ return null;
9224
+ }
9225
+ const indexDir = `__indexes/${path}`;
9226
+ const indexPath = `${indexDir}/${key.lookup}`;
9227
+ let index = [];
9228
+ try {
9229
+ index = await (0, _storage.readJson)(indexPath);
9230
+ } catch (err) {
9231
+ index = [];
9232
+ }
9233
+ const existingEntry = index.find((entry) => (0, _compareAs.sameValue)(type, entry.value, value));
9234
+ if (existingEntry) {
9235
+ if (!existingEntry.record.includes(fileName)) {
9236
+ existingEntry.record.push(fileName);
9237
+ }
9238
+ } else {
9239
+ index.push({
9240
+ value,
9241
+ record: [fileName]
9242
+ });
9243
+ }
9244
+ await (0, _storage.makeDirectory)(indexDir);
9245
+ await (0, _storage.writeJson)(indexPath, index);
9246
+ return index;
9247
+ };
9248
+ exports.updateIndex = updateIndex;
9249
+ }
9250
+ });
9251
+
7824
9252
  // dist/data/queries/updateEntity.js
7825
9253
  var require_updateEntity = __commonJS({
7826
9254
  "dist/data/queries/updateEntity.js"(exports) {
@@ -7849,6 +9277,8 @@ var jsonFsQuery = (() => {
7849
9277
  var _config = require_config();
7850
9278
  var _keyIndexFiles = require_keyIndexFiles();
7851
9279
  var _storage = require_storage();
9280
+ var _packedTable = require_packedTable();
9281
+ var _knownFields = require_knownFields();
7852
9282
  var findEntryFile = async (record, primaryKey, primaryValue) => {
7853
9283
  const type = (0, _fieldType.keyValueType)(record, primaryKey);
7854
9284
  const isMatch = async (fileName) => (0, _compareAs.sameValue)(type, (0, _computeKeyValue.computeKeyValue)(primaryKey.fields, await (0, _retrieveFile.retrieveFile)(`${record.path}/${fileName}`)), primaryValue);
@@ -7871,7 +9301,7 @@ var jsonFsQuery = (() => {
7871
9301
  continue;
7872
9302
  }
7873
9303
  const checkKeys = key.fields.map((field) => newData[field]);
7874
- if (checkKeys.some((value) => value === null)) {
9304
+ if (checkKeys.some((value) => value === null || typeof value === "undefined")) {
7875
9305
  continue;
7876
9306
  }
7877
9307
  const isUnique = await (0, _keyUnique.keyUnique)(entity, key.fields, checkKeys);
@@ -7886,7 +9316,7 @@ var jsonFsQuery = (() => {
7886
9316
  continue;
7887
9317
  }
7888
9318
  const field = key.fields[0];
7889
- if (!Object.prototype.hasOwnProperty.call(newValues, field) || newValues[field] === null || (0, _compareAs.sameValue)((0, _fieldType.fieldType)(record, field), newValues[field], oldData[field])) {
9319
+ if (!Object.prototype.hasOwnProperty.call(newValues, field) || newValues[field] === null || typeof newValues[field] === "undefined" || (0, _compareAs.sameValue)((0, _fieldType.fieldType)(record, field), newValues[field], oldData[field])) {
7890
9320
  continue;
7891
9321
  }
7892
9322
  const {
@@ -7927,7 +9357,7 @@ var jsonFsQuery = (() => {
7927
9357
  oldData,
7928
9358
  newData
7929
9359
  } of planned) {
7930
- if (!keyFieldsChanged(record, key, oldData, newValues) || key.fields.some((field) => newData[field] === null)) {
9360
+ if (!keyFieldsChanged(record, key, oldData, newValues) || key.fields.some((field) => newData[field] === null || typeof newData[field] === "undefined")) {
7931
9361
  continue;
7932
9362
  }
7933
9363
  const value = (0, _computeKeyValue.computeKeyValue)(key.fields, newData);
@@ -7949,18 +9379,33 @@ var jsonFsQuery = (() => {
7949
9379
  const typedValues = Object.assign({}, values);
7950
9380
  for (const field of record.definition) {
7951
9381
  if (Object.prototype.hasOwnProperty.call(typedValues, field.name)) {
7952
- typedValues[field.name] = (0, _typeCheck.typeCheck)(field.type, typedValues[field.name], field.nullable);
9382
+ typedValues[field.name] = typedValues[field.name] === null && field.optional && !field.nullable ? void 0 : (0, _typeCheck.typeCheck)(field.type, typedValues[field.name], field.nullable);
7953
9383
  }
7954
9384
  }
7955
9385
  return typedValues;
7956
9386
  };
9387
+ var withoutRemoved = (row, typedValues) => {
9388
+ const kept = Object.assign({}, row);
9389
+ for (const field of Object.keys(typedValues)) {
9390
+ if (typeof typedValues[field] === "undefined") {
9391
+ delete kept[field];
9392
+ }
9393
+ }
9394
+ return kept;
9395
+ };
7957
9396
  var updateEntity = async (entity = "", values = {}, dataSet = {}) => {
7958
9397
  const record = await (0, _retrieveRecord.retrieveRecord)(entity);
7959
9398
  const primaryKey = record.keys.find((key) => key.type === "primary");
7960
9399
  if (!primaryKey) {
7961
9400
  throw new Error(`Cannot update "${entity}" without a primary key`);
7962
9401
  }
9402
+ (0, _knownFields.assertFieldsDefined)(entity, record, Object.keys(values || {}), "set");
7963
9403
  const typedValues = applyFieldTypes(record, values);
9404
+ for (const field of primaryKey.fields) {
9405
+ if (Object.prototype.hasOwnProperty.call(typedValues, field) && typeof typedValues[field] === "undefined") {
9406
+ throw new Error(`Cannot clear "${field}" on ${entity}: it's part of the primary key`);
9407
+ }
9408
+ }
7964
9409
  const planned = [];
7965
9410
  for (const row of dataSet[entity] || []) {
7966
9411
  const fileName = await findEntryFile(record, primaryKey, (0, _computeKeyValue.computeKeyValue)(primaryKey.fields, row));
@@ -7971,7 +9416,7 @@ var jsonFsQuery = (() => {
7971
9416
  continue;
7972
9417
  }
7973
9418
  const oldData = await (0, _retrieveFile.retrieveFile)(`${record.path}/${fileName}`);
7974
- const newData = Object.assign({}, oldData, typedValues);
9419
+ const newData = withoutRemoved(Object.assign({}, oldData, typedValues), typedValues);
7975
9420
  await assertUniqueForUpdate(entity, record, oldData, newData, typedValues);
7976
9421
  await assertForeignKeysForUpdate(entity, record, oldData, typedValues);
7977
9422
  await assertNoDependentsForUpdate(entity, record, primaryKey, oldData, typedValues);
@@ -7983,6 +9428,9 @@ var jsonFsQuery = (() => {
7983
9428
  });
7984
9429
  }
7985
9430
  assertUniqueWithinUpdate(entity, record, planned, typedValues);
9431
+ if (planned.length) {
9432
+ await (0, _packedTable.discardPacked)(record.path);
9433
+ }
7986
9434
  for (const {
7987
9435
  fileName,
7988
9436
  oldData,
@@ -8233,7 +9681,7 @@ var jsonFsQuery = (() => {
8233
9681
  Object.defineProperty(exports, "__esModule", {
8234
9682
  value: true
8235
9683
  });
8236
- exports.create = void 0;
9684
+ exports.create = exports.assertValidDefinition = void 0;
8237
9685
  require_es_array_includes();
8238
9686
  require_esnext_iterator_constructor();
8239
9687
  require_esnext_iterator_filter();
@@ -8277,11 +9725,16 @@ var jsonFsQuery = (() => {
8277
9725
  }
8278
9726
  const primaryKey = recordContent.keys.find((key) => key.type === "primary");
8279
9727
  for (const fieldName of primaryKey ? primaryKey.fields : []) {
8280
- if (recordContent.definition.some((field) => field.name === fieldName && field.nullable)) {
9728
+ const field = recordContent.definition.find((defined) => defined.name === fieldName);
9729
+ if (field && field.nullable) {
8281
9730
  throw new Error(`Primary key field "${fieldName}" of ${recordName} can't be nullable`);
8282
9731
  }
9732
+ if (field && field.optional && !field.autoGenerate) {
9733
+ throw new Error(`Primary key field "${fieldName}" of ${recordName} can't be optional`);
9734
+ }
8283
9735
  }
8284
9736
  };
9737
+ exports.assertValidDefinition = assertValidDefinition;
8285
9738
  var create = async (recordName, definition = [], keys = []) => {
8286
9739
  (0, _requireNode.requireNode)("create()");
8287
9740
  if (recordName === "__RECORDS") {
@@ -8314,21 +9767,6 @@ var jsonFsQuery = (() => {
8314
9767
  }
8315
9768
  });
8316
9769
 
8317
- // dist/data/utilities/recordExists.js
8318
- var require_recordExists = __commonJS({
8319
- "dist/data/utilities/recordExists.js"(exports) {
8320
- "use strict";
8321
- init_process();
8322
- Object.defineProperty(exports, "__esModule", {
8323
- value: true
8324
- });
8325
- exports.recordExists = void 0;
8326
- var _storage = require_storage();
8327
- var recordExists = (entity) => (0, _storage.fileExists)(`${entity}.json`);
8328
- exports.recordExists = recordExists;
8329
- }
8330
- });
8331
-
8332
9770
  // dist/data/queries/createRecord.js
8333
9771
  var require_createRecord = __commonJS({
8334
9772
  "dist/data/queries/createRecord.js"(exports) {
@@ -8426,6 +9864,7 @@ var jsonFsQuery = (() => {
8426
9864
  var _deregisterRecord = require_deregisterRecord();
8427
9865
  var _requireNode = require_requireNode();
8428
9866
  var _storage = require_storage();
9867
+ var _packedTable = require_packedTable();
8429
9868
  var drop = async (record) => {
8430
9869
  (0, _requireNode.requireNode)("drop()");
8431
9870
  if (record === "__RECORDS") {
@@ -8437,6 +9876,7 @@ var jsonFsQuery = (() => {
8437
9876
  }
8438
9877
  await (0, _storage.removeDirectory)(recordFile.path);
8439
9878
  await (0, _storage.removeDirectory)(`__indexes/${recordFile.path}`);
9879
+ await (0, _packedTable.discardPacked)(recordFile.path);
8440
9880
  await (0, _storage.removeFile)(`${record}.json`);
8441
9881
  await (0, _deregisterRecord.deregisterRecord)(record);
8442
9882
  };
@@ -8514,41 +9954,446 @@ var jsonFsQuery = (() => {
8514
9954
  if (!(0, _recordExists.recordExists)(entity)) {
8515
9955
  throw new Error(`Record "${entity}" doesn't exist`);
8516
9956
  }
8517
- const {
8518
- path,
8519
- definition,
8520
- keys
8521
- } = await (0, _retrieveRecord.retrieveRecord)(entity);
8522
- return {
8523
- path,
8524
- definition,
8525
- keys
8526
- };
9957
+ const {
9958
+ path,
9959
+ definition,
9960
+ keys
9961
+ } = await (0, _retrieveRecord.retrieveRecord)(entity);
9962
+ return {
9963
+ path,
9964
+ definition,
9965
+ keys
9966
+ };
9967
+ };
9968
+ exports.describeRecord = describeRecord;
9969
+ }
9970
+ });
9971
+
9972
+ // dist/data/queries/showRecords.js
9973
+ var require_showRecords = __commonJS({
9974
+ "dist/data/queries/showRecords.js"(exports) {
9975
+ "use strict";
9976
+ init_process();
9977
+ Object.defineProperty(exports, "__esModule", {
9978
+ value: true
9979
+ });
9980
+ exports.showRecords = void 0;
9981
+ require_esnext_iterator_constructor();
9982
+ require_esnext_iterator_map();
9983
+ var _retrieveRecord = require_retrieveRecord();
9984
+ var _recordExists = require_recordExists();
9985
+ var showRecords = async () => {
9986
+ if (!(0, _recordExists.recordExists)("__RECORDS")) {
9987
+ return [];
9988
+ }
9989
+ return (await (0, _retrieveRecord.retrieveRecord)("__RECORDS")).entries.map((fileName) => fileName.replace(/\.json$/, ""));
9990
+ };
9991
+ exports.showRecords = showRecords;
9992
+ }
9993
+ });
9994
+
9995
+ // dist/data/introspect/alter.js
9996
+ var require_alter = __commonJS({
9997
+ "dist/data/introspect/alter.js"(exports) {
9998
+ "use strict";
9999
+ init_process();
10000
+ Object.defineProperty(exports, "__esModule", {
10001
+ value: true
10002
+ });
10003
+ exports.alter = void 0;
10004
+ require_es_array_includes();
10005
+ require_es_json_stringify();
10006
+ require_esnext_iterator_constructor();
10007
+ require_esnext_iterator_filter();
10008
+ require_esnext_iterator_find();
10009
+ require_esnext_iterator_map();
10010
+ require_esnext_iterator_some();
10011
+ var _field = require_field();
10012
+ var _create = require_create();
10013
+ var _parseCreate = require_parseCreate();
10014
+ var _retrieveRecord = require_retrieveRecord();
10015
+ var _retrieveFiles = require_retrieveFiles();
10016
+ var _retrieveRecords = require_retrieveRecords();
10017
+ var _knownFields = require_knownFields();
10018
+ var _packedTable = require_packedTable();
10019
+ var _requireNode = require_requireNode();
10020
+ var _showRecords = require_showRecords();
10021
+ var _updateEntity = require_updateEntity();
10022
+ var _typeCheck = require_typeCheck();
10023
+ var _storage = require_storage();
10024
+ var rowsOf = async (record) => {
10025
+ const rows = await (0, _retrieveFiles.retrieveFiles)(record.entries.map((file) => `${record.path}/${file}`), _retrieveRecords.retrieveEntry);
10026
+ return rows.map((data, position) => ({
10027
+ fileName: record.entries[position],
10028
+ data
10029
+ }));
10030
+ };
10031
+ var has = (row, name) => Object.prototype.hasOwnProperty.call(row, name);
10032
+ var keysUsing = (record, name) => record.keys.filter((key) => key.fields.includes(name));
10033
+ var describeKey = (key) => `${key.type} key (${key.fields.join(", ")})`;
10034
+ var referencesTo = async (entity, name) => {
10035
+ const found = [];
10036
+ for (const other of await (0, _showRecords.showRecords)()) {
10037
+ const record = await (0, _retrieveRecord.retrieveRecord)(other);
10038
+ for (const key of record.keys) {
10039
+ if (key.type === "foreign" && (key.references || []).some((reference) => reference.fields.includes(`${entity}.${name}`))) {
10040
+ found.push({
10041
+ entity: other,
10042
+ record,
10043
+ key
10044
+ });
10045
+ }
10046
+ }
10047
+ }
10048
+ return found;
10049
+ };
10050
+ var writeRecord = async (entity, record) => {
10051
+ (0, _create.assertValidDefinition)(entity, record);
10052
+ await (0, _storage.writeJson)(`${entity}.json`, record);
10053
+ };
10054
+ var setField = async (entity, record, rows, name, value) => {
10055
+ if (!rows.length) {
10056
+ return;
10057
+ }
10058
+ await (0, _packedTable.discardPacked)(record.path);
10059
+ if (keysUsing(record, name).length && typeof value !== "function") {
10060
+ if (!record.keys.some((key) => key.type === "primary")) {
10061
+ throw new Error(`Can't change "${name}" on ${entity}'s rows: a key uses it, and rows are found by the primary key, which ${entity} doesn't have`);
10062
+ }
10063
+ await (0, _updateEntity.updateEntity)(entity, {
10064
+ [name]: typeof value === "undefined" ? null : value
10065
+ }, {
10066
+ [entity]: rows.map((row) => row.data)
10067
+ });
10068
+ return;
10069
+ }
10070
+ for (const row of rows) {
10071
+ const changed = Object.assign({}, row.data);
10072
+ const next = typeof value === "function" ? value(row) : value;
10073
+ if (typeof next === "undefined") {
10074
+ delete changed[name];
10075
+ } else {
10076
+ changed[name] = next;
10077
+ }
10078
+ await (0, _storage.writeJson)(`${record.path}/${row.fileName}`, changed);
10079
+ }
10080
+ };
10081
+ var addField = async (entity, record, added) => {
10082
+ if (record.definition.some((field) => field.name === added.name)) {
10083
+ throw new Error(`Field "${added.name}" already exists on ${entity}`);
10084
+ }
10085
+ const updated = {
10086
+ ...record,
10087
+ definition: [...record.definition, added]
10088
+ };
10089
+ const rows = await rowsOf(record);
10090
+ for (const row of rows.filter((row2) => has(row2.data, added.name))) {
10091
+ try {
10092
+ (0, _typeCheck.typeCheck)(added.type, row.data[added.name], added.nullable);
10093
+ } catch (error) {
10094
+ throw new Error(`Can't add "${added.name}" to ${entity}: row ${row.fileName} already holds a value for it that doesn't fit (${error.message})`);
10095
+ }
10096
+ }
10097
+ const missing = rows.filter((row) => !has(row.data, added.name));
10098
+ const hasDefault = has(added, "default");
10099
+ if (missing.length && !added.optional && !hasDefault && !added.autoGenerate) {
10100
+ throw new Error(`Can't add required field "${added.name}" to ${entity}: its ${missing.length} row(s) have no value for it (give it a default, or make it optional)`);
10101
+ }
10102
+ await writeRecord(entity, updated);
10103
+ if (added.autoGenerate) {
10104
+ await setField(entity, updated, missing, added.name, () => crypto.randomUUID());
10105
+ } else if (hasDefault) {
10106
+ await setField(entity, updated, missing, added.name, added["default"]);
10107
+ }
10108
+ return updated;
10109
+ };
10110
+ var dropField = async (entity, record, name) => {
10111
+ (0, _knownFields.assertFieldsDefined)(entity, record, [name], "alter");
10112
+ const key = keysUsing(record, name)[0];
10113
+ if (key) {
10114
+ throw new Error(`Can't drop "${name}" from ${entity}: its ${describeKey(key)} uses it`);
10115
+ }
10116
+ const reference = (await referencesTo(entity, name))[0];
10117
+ if (reference) {
10118
+ throw new Error(`Can't drop "${name}" from ${entity}: ${reference.entity}'s foreign key "${reference.key.fields[0]}" references it`);
10119
+ }
10120
+ const updated = {
10121
+ ...record,
10122
+ definition: record.definition.filter((field) => field.name !== name)
10123
+ };
10124
+ await writeRecord(entity, updated);
10125
+ await setField(entity, updated, (await rowsOf(record)).filter((row) => has(row.data, name)), name, void 0);
10126
+ return updated;
10127
+ };
10128
+ var renameField = async (entity, record, name, to) => {
10129
+ (0, _knownFields.assertFieldsDefined)(entity, record, [name], "alter");
10130
+ if (record.definition.some((field) => field.name === to)) {
10131
+ throw new Error(`Can't rename "${name}" on ${entity} to "${to}": a field of that name already exists`);
10132
+ }
10133
+ const references = await referencesTo(entity, name);
10134
+ const keys = record.keys.map((key) => {
10135
+ if (!key.fields.includes(name)) {
10136
+ return key;
10137
+ }
10138
+ const fields = key.fields.map((field) => field === name ? to : field);
10139
+ const lookup = key.lookup && key.lookup === (0, _parseCreate.keyLookup)(key.type, key.fields) ? (0, _parseCreate.keyLookup)(key.type, fields) : key.lookup;
10140
+ return {
10141
+ ...key,
10142
+ fields,
10143
+ lookup
10144
+ };
10145
+ });
10146
+ const renameReferences = (key) => key.type !== "foreign" ? key : {
10147
+ ...key,
10148
+ references: (key.references || []).map((reference) => ({
10149
+ ...reference,
10150
+ fields: reference.fields.map((field) => field === `${entity}.${name}` ? `${entity}.${to}` : field)
10151
+ }))
10152
+ };
10153
+ const updated = {
10154
+ ...record,
10155
+ definition: record.definition.map((field) => field.name === name ? {
10156
+ ...field,
10157
+ name: to
10158
+ } : field),
10159
+ keys: keys.map(renameReferences)
10160
+ };
10161
+ for (const [position, key] of record.keys.entries()) {
10162
+ const moved = keys[position].lookup;
10163
+ if (key.lookup && moved !== key.lookup && (0, _storage.fileExists)(`__indexes/${record.path}/${key.lookup}`)) {
10164
+ await (0, _storage.writeJson)(`__indexes/${record.path}/${moved}`, await (0, _storage.readJson)(`__indexes/${record.path}/${key.lookup}`));
10165
+ await (0, _storage.removeFile)(`__indexes/${record.path}/${key.lookup}`);
10166
+ }
10167
+ }
10168
+ await writeRecord(entity, updated);
10169
+ for (const reference of references.filter((reference2) => reference2.entity !== entity)) {
10170
+ await (0, _storage.writeJson)(`${reference.entity}.json`, {
10171
+ ...reference.record,
10172
+ keys: reference.record.keys.map(renameReferences)
10173
+ });
10174
+ }
10175
+ const rows = (await rowsOf(record)).filter((row) => has(row.data, name));
10176
+ if (rows.length) {
10177
+ await (0, _packedTable.discardPacked)(record.path);
10178
+ }
10179
+ for (const row of rows) {
10180
+ const moved = Object.assign({}, row.data);
10181
+ moved[to] = moved[name];
10182
+ delete moved[name];
10183
+ await (0, _storage.writeJson)(`${record.path}/${row.fileName}`, moved);
10184
+ }
10185
+ return updated;
10186
+ };
10187
+ var modifyField = async (entity, record, changed) => {
10188
+ (0, _knownFields.assertFieldsDefined)(entity, record, [changed.name], "alter");
10189
+ const current = record.definition.find((field) => field.name === changed.name);
10190
+ if (current.type !== changed.type) {
10191
+ throw new Error(`Can't change the type of "${changed.name}" on ${entity} (${current.type} to ${changed.type}): only optional, null and default can change`);
10192
+ }
10193
+ if (Boolean(current.autoGenerate) !== Boolean(changed.autoGenerate)) {
10194
+ throw new Error(`Can't change whether "${changed.name}" on ${entity} is auto: only optional, null and default can change`);
10195
+ }
10196
+ const updated = {
10197
+ ...record,
10198
+ definition: record.definition.map((field) => field.name === changed.name ? changed : field)
10199
+ };
10200
+ const rows = await rowsOf(record);
10201
+ const hasDefault = has(changed, "default");
10202
+ const holdsNull = changed.nullable ? [] : rows.filter((row) => row.data[changed.name] === null);
10203
+ const missing = changed.optional ? [] : rows.filter((row) => !has(row.data, changed.name));
10204
+ const unfillable = changed.optional ? [] : holdsNull;
10205
+ if ((missing.length || unfillable.length) && !hasDefault) {
10206
+ throw missing.length ? new Error(`Can't make "${changed.name}" required on ${entity}: ${missing.length} row(s) have no value for it (give it a default to fill them in)`) : new Error(`Can't make "${changed.name}" not null on ${entity}: ${unfillable.length} row(s) hold null (give it a default to fill them in, or make it optional)`);
10207
+ }
10208
+ await writeRecord(entity, updated);
10209
+ if (hasDefault) {
10210
+ await setField(entity, updated, [...missing, ...unfillable], changed.name, changed["default"]);
10211
+ }
10212
+ if (changed.optional && holdsNull.length) {
10213
+ await setField(entity, updated, holdsNull, changed.name, void 0);
10214
+ }
10215
+ return updated;
10216
+ };
10217
+ var alter = async (entity, change) => {
10218
+ (0, _requireNode.requireNode)("alter");
10219
+ if (entity === "__RECORDS") {
10220
+ throw new Error("__RECORDS is reserved for the list of records");
10221
+ }
10222
+ const names = [entity, ..."field" in change ? [change.field?.name] : [], ..."name" in change ? [change.name] : [], ..."to" in change ? [change.to] : []];
10223
+ const invalid = names.findIndex((name) => typeof name !== "string" || !_parseCreate.nameMatch.test(name));
10224
+ if (invalid !== -1) {
10225
+ throw new Error(`Invalid name ${JSON.stringify(names[invalid]) ?? "undefined"} in alter: names use letters, digits, _ and - only`);
10226
+ }
10227
+ const record = await (0, _retrieveRecord.retrieveRecord)(entity);
10228
+ switch (change.action) {
10229
+ case "add":
10230
+ return (await addField(entity, record, (0, _field.field)(change.field))).definition;
10231
+ case "drop":
10232
+ return (await dropField(entity, record, change.name)).definition;
10233
+ case "rename":
10234
+ return (await renameField(entity, record, change.name, change.to)).definition;
10235
+ case "modify":
10236
+ return (await modifyField(entity, record, (0, _field.field)(change.field))).definition;
10237
+ default:
10238
+ throw new Error(`Unknown alter action: ${change.action}`);
10239
+ }
10240
+ };
10241
+ exports.alter = alter;
10242
+ }
10243
+ });
10244
+
10245
+ // dist/data/utilities/databaseLock.js
10246
+ var require_databaseLock = __commonJS({
10247
+ "dist/data/utilities/databaseLock.js"(exports) {
10248
+ "use strict";
10249
+ init_process();
10250
+ require_esnext_weak_map_delete_all();
10251
+ Object.defineProperty(exports, "__esModule", {
10252
+ value: true
10253
+ });
10254
+ exports.withDatabaseLock = exports.browserCallsRunning = void 0;
10255
+ require_esnext_map_delete_all();
10256
+ require_esnext_map_every();
10257
+ require_esnext_map_filter();
10258
+ require_esnext_map_find();
10259
+ require_esnext_map_find_key();
10260
+ require_esnext_map_includes();
10261
+ require_esnext_map_key_of();
10262
+ require_esnext_map_map_keys();
10263
+ require_esnext_map_map_values();
10264
+ require_esnext_map_merge();
10265
+ require_esnext_map_reduce();
10266
+ require_esnext_map_some();
10267
+ require_esnext_map_update();
10268
+ var jsEnv = _interopRequireWildcard(require_dist());
10269
+ var _config = require_config();
10270
+ var _storage = require_storage();
10271
+ var e;
10272
+ function _interopRequireWildcard(t, r) {
10273
+ if (!r && t && t.__esModule) return t;
10274
+ var n, a, o = Object.defineProperty, f = { __proto__: null, default: t };
10275
+ if (Object(t) !== t) return f;
10276
+ if (e || "function" != typeof WeakMap || (e = /* @__PURE__ */ new WeakMap()), e) {
10277
+ if (e.has(t)) return e.get(t);
10278
+ e.set(t, f);
10279
+ }
10280
+ 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]);
10281
+ return f;
10282
+ }
10283
+ var queues = /* @__PURE__ */ new Map();
10284
+ var browserCalls = 0;
10285
+ var browserCallsRunning = () => browserCalls;
10286
+ exports.browserCallsRunning = browserCallsRunning;
10287
+ var withDatabaseLock = async (task) => {
10288
+ if (!jsEnv.isNode) {
10289
+ browserCalls++;
10290
+ try {
10291
+ return await (0, _storage.withReadCache)(task);
10292
+ } finally {
10293
+ browserCalls--;
10294
+ }
10295
+ }
10296
+ const database = (0, _config.resolveDatabasePath)((0, _config.lockPath)());
10297
+ const ended = (0, _config.trackDatabaseCall)();
10298
+ const previous = queues.get(database) || Promise.resolve();
10299
+ let release;
10300
+ const turn = new Promise((resolve) => {
10301
+ release = resolve;
10302
+ });
10303
+ const queued = previous.then(() => turn);
10304
+ queues.set(database, queued);
10305
+ await previous;
10306
+ try {
10307
+ return await (0, _storage.withReadCache)(task);
10308
+ } finally {
10309
+ ended();
10310
+ release();
10311
+ if (queues.get(database) === queued) {
10312
+ queues.delete(database);
10313
+ }
10314
+ }
8527
10315
  };
8528
- exports.describeRecord = describeRecord;
10316
+ exports.withDatabaseLock = withDatabaseLock;
8529
10317
  }
8530
10318
  });
8531
10319
 
8532
- // dist/data/queries/showRecords.js
8533
- var require_showRecords = __commonJS({
8534
- "dist/data/queries/showRecords.js"(exports) {
10320
+ // dist/data/queries/databaseStatements.js
10321
+ var require_databaseStatements = __commonJS({
10322
+ "dist/data/queries/databaseStatements.js"(exports) {
8535
10323
  "use strict";
8536
10324
  init_process();
10325
+ require_esnext_weak_map_delete_all();
8537
10326
  Object.defineProperty(exports, "__esModule", {
8538
10327
  value: true
8539
10328
  });
8540
- exports.showRecords = void 0;
10329
+ exports.useDatabase = exports.showDatabases = exports.dropDatabase = exports.createDatabase = void 0;
10330
+ require_es_array_includes();
8541
10331
  require_esnext_iterator_constructor();
8542
- require_esnext_iterator_map();
8543
- var _retrieveRecord = require_retrieveRecord();
8544
- var _recordExists = require_recordExists();
8545
- var showRecords = async () => {
8546
- if (!(0, _recordExists.recordExists)("__RECORDS")) {
8547
- return [];
10332
+ require_esnext_iterator_filter();
10333
+ var jsEnv = _interopRequireWildcard(require_dist());
10334
+ var _config = require_config();
10335
+ var _requireNode = require_requireNode();
10336
+ var _databaseLock = require_databaseLock();
10337
+ var _storage = require_storage();
10338
+ var e;
10339
+ function _interopRequireWildcard(t, r) {
10340
+ if (!r && t && t.__esModule) return t;
10341
+ var n, a, o = Object.defineProperty, f = { __proto__: null, default: t };
10342
+ if (Object(t) !== t) return f;
10343
+ if (e || "function" != typeof WeakMap || (e = /* @__PURE__ */ new WeakMap()), e) {
10344
+ if (e.has(t)) return e.get(t);
10345
+ e.set(t, f);
8548
10346
  }
8549
- return (await (0, _retrieveRecord.retrieveRecord)("__RECORDS")).entries.map((fileName) => fileName.replace(/\.json$/, ""));
10347
+ 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]);
10348
+ return f;
10349
+ }
10350
+ var databaseExists = async (name) => (await (0, _storage.readDatabaseList)()).includes(name) || jsEnv.isNode && (0, _storage.databaseFolderExists)(name);
10351
+ var createDatabase = async (name, ifNotExists = false) => {
10352
+ (0, _requireNode.requireNode)('"create database"');
10353
+ const listed = await (0, _storage.readDatabaseList)();
10354
+ if (listed.includes(name) || (0, _storage.databaseFolderExists)(name)) {
10355
+ if (!ifNotExists) {
10356
+ throw new Error(listed.includes(name) ? `Database "${name}" already exists` : `Database "${name}" already exists as a folder that isn't listed: create database if not exists ${name} lists it`);
10357
+ }
10358
+ if (!listed.includes(name)) {
10359
+ await (0, _storage.writeDatabaseList)([...listed, name]);
10360
+ }
10361
+ return null;
10362
+ }
10363
+ await (0, _storage.writeDatabaseList)([...listed, name]);
10364
+ await (0, _storage.makeDatabaseFolder)(name);
10365
+ return name;
8550
10366
  };
8551
- exports.showRecords = showRecords;
10367
+ exports.createDatabase = createDatabase;
10368
+ var dropDatabase = async (name, ifExists = false) => {
10369
+ (0, _requireNode.requireNode)('"drop database"');
10370
+ if (!await databaseExists(name)) {
10371
+ if (ifExists) {
10372
+ return null;
10373
+ }
10374
+ throw new Error(`Database "${name}" doesn't exist`);
10375
+ }
10376
+ if ((0, _config.getSetting)("database", void 0) === name) {
10377
+ throw new Error(`Can't drop the database in use ("${name}"): use another one first`);
10378
+ }
10379
+ await (0, _storage.writeDatabaseList)((await (0, _storage.readDatabaseList)()).filter((listed) => listed !== name));
10380
+ await (0, _storage.removeDatabaseFolder)(name);
10381
+ return name;
10382
+ };
10383
+ exports.dropDatabase = dropDatabase;
10384
+ var useDatabase = async (name) => {
10385
+ if (!jsEnv.isNode && (0, _databaseLock.browserCallsRunning)() > 1) {
10386
+ throw new Error(`Can't use "${name}" while other calls are running in this page: await them first, or pick the database with configure({ database }) between calls`);
10387
+ }
10388
+ if (!await databaseExists(name)) {
10389
+ throw new Error(`Database "${name}" doesn't exist${jsEnv.isNode ? "" : " (or isn't listed in __DATABASES.json)"}`);
10390
+ }
10391
+ (0, _config.switchDatabase)(name);
10392
+ return name;
10393
+ };
10394
+ exports.useDatabase = useDatabase;
10395
+ var showDatabases = async () => (0, _storage.readDatabaseList)();
10396
+ exports.showDatabases = showDatabases;
8552
10397
  }
8553
10398
  });
8554
10399
 
@@ -8824,7 +10669,7 @@ var jsonFsQuery = (() => {
8824
10669
  require_esnext_set_union();
8825
10670
  var _readEntity = require_readEntity();
8826
10671
  var _retrieveRecord = require_retrieveRecord();
8827
- var _retrieveFile = require_retrieveFile();
10672
+ var _retrieveRecords = require_retrieveRecords();
8828
10673
  var _retrieveIndexes = require_retrieveIndexes();
8829
10674
  var _joinKey = require_joinKey();
8830
10675
  var _rowLookup = require_rowLookup();
@@ -8841,15 +10686,7 @@ var jsonFsQuery = (() => {
8841
10686
  }
8842
10687
  }
8843
10688
  const record = await (0, _retrieveRecord.retrieveRecord)(entity);
8844
- const rows = [];
8845
- for (const file of record.entries.filter((entry) => files.has(entry))) {
8846
- const data = await (0, _retrieveFile.retrieveFile)(`${record.path}/${file}`).catch((err) => console.error(err));
8847
- if (!data) {
8848
- throw new Error(`Could not read entity ${file}`);
8849
- }
8850
- rows.push(data);
8851
- }
8852
- return rows;
10689
+ return (0, _retrieveRecords.retrieveEntryRows)(record, record.entries.filter((entry) => files.has(entry)));
8853
10690
  };
8854
10691
  var joinBases = async (entity, joinEntity, dataSets, steps, joinAlreadyResolved) => {
8855
10692
  const bases = /* @__PURE__ */ new Map();
@@ -9050,20 +10887,23 @@ var jsonFsQuery = (() => {
9050
10887
  value: true
9051
10888
  });
9052
10889
  exports.reconcileJoin = void 0;
10890
+ require_es_json_stringify();
9053
10891
  require_esnext_iterator_constructor();
10892
+ require_esnext_iterator_every();
10893
+ require_esnext_iterator_find();
9054
10894
  require_esnext_iterator_for_each();
9055
- var _where = require_where();
10895
+ var sameValue = (a, b) => a === b || JSON.stringify(a) === JSON.stringify(b);
9056
10896
  var reconcileJoin = (dataSet, entityName, entityKey, joinEntity, joinProp) => {
9057
10897
  const entity = dataSet[entityName][entityKey];
9058
- if (Object.prototype.hasOwnProperty.call(entity, joinEntity) && Array.isArray(entity[joinEntity])) {
9059
- entity[joinEntity].forEach((mergedEntity, k) => {
9060
- const matchedEntity = (0, _where.where)(dataSet[joinEntity], {
9061
- property: joinProp,
9062
- comparator: "=",
9063
- value: mergedEntity[joinProp]
9064
- });
9065
- if (matchedEntity.length) {
9066
- dataSet[entityName][entityKey][joinEntity][k] = matchedEntity[0];
10898
+ if (Object.prototype.hasOwnProperty.call(entity, joinEntity) && Array.isArray(entity[joinEntity]) && Array.isArray(dataSet[joinEntity])) {
10899
+ entity[joinEntity].forEach((joinedRow, k) => {
10900
+ if (!joinedRow || !Object.prototype.hasOwnProperty.call(joinedRow, joinProp)) {
10901
+ return;
10902
+ }
10903
+ const fields = Object.keys(joinedRow);
10904
+ const mergedRow = dataSet[joinEntity].find((row) => fields.every((field) => sameValue(row[field], joinedRow[field])));
10905
+ if (mergedRow) {
10906
+ dataSet[entityName][entityKey][joinEntity][k] = mergedRow;
9067
10907
  }
9068
10908
  });
9069
10909
  }
@@ -9289,47 +11129,39 @@ var jsonFsQuery = (() => {
9289
11129
  require_esnext_iterator_constructor();
9290
11130
  require_esnext_iterator_map();
9291
11131
  require_esnext_iterator_reduce();
9292
- var shapeRow = (row, selectClauses) => selectClauses.reduce((shaped, {
11132
+ var pick = (row, property, entity) => {
11133
+ if (Object.prototype.hasOwnProperty.call(row, property) || typeof entity === "undefined" || !property.startsWith(`${entity}.`)) {
11134
+ return row[property];
11135
+ }
11136
+ return row[property.slice(entity.length + 1)];
11137
+ };
11138
+ var shapeRow = (row, selectClauses, entity) => selectClauses.reduce((shaped, {
9293
11139
  property,
9294
11140
  alias
9295
11141
  }) => {
9296
- shaped[alias || property] = row[property];
11142
+ shaped[alias || property] = pick(row, property, entity);
9297
11143
  return shaped;
9298
11144
  }, {});
9299
- var shapeGroup = (group, selectClauses) => group.groups ? {
11145
+ var shapeGroup = (group, selectClauses, entity) => group.groups ? {
9300
11146
  ...group,
9301
- groups: group.groups.map((inner) => shapeGroup(inner, selectClauses))
11147
+ groups: group.groups.map((inner) => shapeGroup(inner, selectClauses, entity))
9302
11148
  } : {
9303
11149
  ...group,
9304
- rows: group.rows.map((row) => shapeRow(row, selectClauses))
11150
+ rows: group.rows.map((row) => shapeRow(row, selectClauses, entity))
9305
11151
  };
9306
- var selectFields = (dataSet = [], selectClauses = [], grouped = false) => {
11152
+ var selectFields = (dataSet = [], selectClauses = [], grouped = false, entity) => {
9307
11153
  if (!selectClauses.length) {
9308
11154
  return dataSet;
9309
11155
  }
9310
11156
  if (grouped) {
9311
- return dataSet.map((group) => shapeGroup(group, selectClauses));
11157
+ return dataSet.map((group) => shapeGroup(group, selectClauses, entity));
9312
11158
  }
9313
- return dataSet.map((row) => shapeRow(row, selectClauses));
11159
+ return dataSet.map((row) => shapeRow(row, selectClauses, entity));
9314
11160
  };
9315
11161
  exports.selectFields = selectFields;
9316
11162
  }
9317
11163
  });
9318
11164
 
9319
- // dist/data/utilities/parsers/isEntityProperty.js
9320
- var require_isEntityProperty = __commonJS({
9321
- "dist/data/utilities/parsers/isEntityProperty.js"(exports) {
9322
- "use strict";
9323
- init_process();
9324
- Object.defineProperty(exports, "__esModule", {
9325
- value: true
9326
- });
9327
- exports.isEntityProperty = void 0;
9328
- var isEntityProperty = (property) => /^[a-z0-9_-]+\.([a-z0-9_-]+)$/i.test(property);
9329
- exports.isEntityProperty = isEntityProperty;
9330
- }
9331
- });
9332
-
9333
11165
  // dist/data/utilities/getConditionIndexedList.js
9334
11166
  var require_getConditionIndexedList = __commonJS({
9335
11167
  "dist/data/utilities/getConditionIndexedList.js"(exports) {
@@ -9363,6 +11195,7 @@ var jsonFsQuery = (() => {
9363
11195
  var _splitEntityProperty = require_splitEntityProperty();
9364
11196
  var _retrieveRecord = require_retrieveRecord();
9365
11197
  var _where = require_where();
11198
+ var _retrieveRecords = require_retrieveRecords();
9366
11199
  var _retrieveFile = require_retrieveFile();
9367
11200
  var _retrieveIndexes = require_retrieveIndexes();
9368
11201
  var _isSingleFieldKey = require_isSingleFieldKey();
@@ -9445,10 +11278,8 @@ var jsonFsQuery = (() => {
9445
11278
  }
9446
11279
  for (const entity of Object.keys(matchedFiles)) {
9447
11280
  resolved.add(entity);
9448
- dataSet[entity] = [];
9449
- for (const file of matchedFiles[entity]) {
9450
- dataSet[entity].push(await (0, _retrieveFile.retrieveFile)(`${entity}/${file}`));
9451
- }
11281
+ const record = recordData[entity] || await (0, _retrieveRecord.retrieveRecord)(entity);
11282
+ dataSet[entity] = await (0, _retrieveRecords.retrieveEntryRows)(record, [...matchedFiles[entity]], _retrieveFile.retrieveFile);
9452
11283
  }
9453
11284
  return parsed;
9454
11285
  };
@@ -9563,6 +11394,8 @@ var jsonFsQuery = (() => {
9563
11394
  var _createRecord = require_createRecord();
9564
11395
  var _dropRecord = require_dropRecord();
9565
11396
  var _describeRecord = require_describeRecord();
11397
+ var _alter = require_alter();
11398
+ var _databaseStatements = require_databaseStatements();
9566
11399
  var _showRecords = require_showRecords();
9567
11400
  var _joinEntity = require_joinEntity();
9568
11401
  var _mergeJoins = require_mergeJoins();
@@ -9579,6 +11412,7 @@ var jsonFsQuery = (() => {
9579
11412
  var _conditionTree = require_conditionTree();
9580
11413
  var _conditionEntities = require_conditionEntities();
9581
11414
  var _requireNode = require_requireNode();
11415
+ var _knownFields = require_knownFields();
9582
11416
  var typeClauses = async (parsed, recordData) => {
9583
11417
  for (const clause of [...(0, _conditionTree.conditionsOf)(parsed.where), ...parsed.sortClauses]) {
9584
11418
  let entity = parsed.entity;
@@ -9597,7 +11431,7 @@ var jsonFsQuery = (() => {
9597
11431
  };
9598
11432
  var runQuery = async (parsed) => {
9599
11433
  const perPair = typeof parsed.where !== "undefined" && (0, _conditionEntities.conditionEntities)(parsed);
9600
- if (["insert", "update", "delete", "create", "drop"].includes(parsed.command)) {
11434
+ if (["insert", "update", "delete", "create", "drop", "alter"].includes(parsed.command)) {
9601
11435
  (0, _requireNode.requireNode)(`"${parsed.command}"`);
9602
11436
  }
9603
11437
  switch (parsed.command) {
@@ -9613,6 +11447,26 @@ var jsonFsQuery = (() => {
9613
11447
  return {
9614
11448
  [parsed.entity]: await (0, _describeRecord.describeRecord)(parsed.entity)
9615
11449
  };
11450
+ case "alter":
11451
+ return {
11452
+ [parsed.entity]: await (0, _alter.alter)(parsed.entity, parsed.alter)
11453
+ };
11454
+ case "create database":
11455
+ return {
11456
+ [parsed.entity]: await (0, _databaseStatements.createDatabase)(parsed.entity, parsed.ifNotExists)
11457
+ };
11458
+ case "drop database":
11459
+ return {
11460
+ [parsed.entity]: await (0, _databaseStatements.dropDatabase)(parsed.entity, parsed.ifExists)
11461
+ };
11462
+ case "use":
11463
+ return {
11464
+ [parsed.entity]: await (0, _databaseStatements.useDatabase)(parsed.entity)
11465
+ };
11466
+ case "show databases":
11467
+ return {
11468
+ [parsed.entity]: await (0, _databaseStatements.showDatabases)()
11469
+ };
9616
11470
  case "show":
9617
11471
  return {
9618
11472
  [parsed.entity]: await (0, _showRecords.showRecords)()
@@ -9624,6 +11478,7 @@ var jsonFsQuery = (() => {
9624
11478
  if (typeof parsed.joinEntity !== "undefined") {
9625
11479
  recordData[parsed.joinEntity] = await (0, _retrieveRecord.retrieveRecord)(parsed.joinEntity);
9626
11480
  }
11481
+ await (0, _knownFields.assertKnownFields)(parsed, recordData);
9627
11482
  await typeClauses(parsed, recordData);
9628
11483
  let dataSet = {
9629
11484
  [parsed.entity]: []
@@ -9663,80 +11518,13 @@ var jsonFsQuery = (() => {
9663
11518
  dataSet[parsed.entity] = (0, _sortBy.sortBy)(dataSet[parsed.entity], parsed.sortClauses);
9664
11519
  dataSet[parsed.entity] = (0, _groupBy.groupBy)(dataSet[parsed.entity], parsed.groupBy);
9665
11520
  dataSet[parsed.entity] = (0, _limitOffset.limitOffset)(dataSet[parsed.entity], parsed.offset, parsed.limit);
9666
- dataSet[parsed.entity] = (0, _selectFields.selectFields)(dataSet[parsed.entity], parsed.selectClauses, Boolean(parsed.groupBy?.length));
11521
+ dataSet[parsed.entity] = (0, _selectFields.selectFields)(dataSet[parsed.entity], parsed.selectClauses, Boolean(parsed.groupBy?.length), parsed.entity);
9667
11522
  return dataSet;
9668
11523
  };
9669
11524
  exports.runQuery = runQuery;
9670
11525
  }
9671
11526
  });
9672
11527
 
9673
- // dist/data/utilities/databaseLock.js
9674
- var require_databaseLock = __commonJS({
9675
- "dist/data/utilities/databaseLock.js"(exports) {
9676
- "use strict";
9677
- init_process();
9678
- require_esnext_weak_map_delete_all();
9679
- Object.defineProperty(exports, "__esModule", {
9680
- value: true
9681
- });
9682
- exports.withDatabaseLock = void 0;
9683
- require_esnext_map_delete_all();
9684
- require_esnext_map_every();
9685
- require_esnext_map_filter();
9686
- require_esnext_map_find();
9687
- require_esnext_map_find_key();
9688
- require_esnext_map_includes();
9689
- require_esnext_map_key_of();
9690
- require_esnext_map_map_keys();
9691
- require_esnext_map_map_values();
9692
- require_esnext_map_merge();
9693
- require_esnext_map_reduce();
9694
- require_esnext_map_some();
9695
- require_esnext_map_update();
9696
- var jsEnv = _interopRequireWildcard(require_dist());
9697
- var _config = require_config();
9698
- var _storage = require_storage();
9699
- var e;
9700
- function _interopRequireWildcard(t, r) {
9701
- if (!r && t && t.__esModule) return t;
9702
- var n, a, o = Object.defineProperty, f = { __proto__: null, default: t };
9703
- if (Object(t) !== t) return f;
9704
- if (e || "function" != typeof WeakMap || (e = /* @__PURE__ */ new WeakMap()), e) {
9705
- if (e.has(t)) return e.get(t);
9706
- e.set(t, f);
9707
- }
9708
- 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]);
9709
- return f;
9710
- }
9711
- var queues = /* @__PURE__ */ new Map();
9712
- var withDatabaseLock = async (task) => {
9713
- if (!jsEnv.isNode) {
9714
- return (0, _storage.withReadCache)(task);
9715
- }
9716
- const database = (0, _config.resolveDatabasePath)((0, _config.getSetting)("databasePath", "database/"));
9717
- const ended = (0, _config.trackDatabaseCall)();
9718
- const previous = queues.get(database) || Promise.resolve();
9719
- let release;
9720
- const turn = new Promise((resolve) => {
9721
- release = resolve;
9722
- });
9723
- const queued = previous.then(() => turn);
9724
- queues.set(database, queued);
9725
- await previous;
9726
- try {
9727
- return await (0, _storage.withReadCache)(task);
9728
- } finally {
9729
- ended();
9730
- release();
9731
- if (queues.get(database) === queued) {
9732
- queues.delete(database);
9733
- }
9734
- }
9735
- };
9736
- exports.withDatabaseLock = withDatabaseLock;
9737
- }
9738
- });
9739
-
9740
11528
  // dist/data/queries/query.js
9741
11529
  var require_query = __commonJS({
9742
11530
  "dist/data/queries/query.js"(exports) {
@@ -9749,12 +11537,13 @@ var jsonFsQuery = (() => {
9749
11537
  var _parser = require_parser();
9750
11538
  var _runQuery = require_runQuery();
9751
11539
  var _databaseLock = require_databaseLock();
11540
+ var _storage = require_storage();
9752
11541
  var query = async (queryString = "") => {
9753
11542
  const parsedQueries = (0, _parser.parser)(queryString);
9754
11543
  return (0, _databaseLock.withDatabaseLock)(async () => {
9755
11544
  const queryResults = [];
9756
11545
  for (const parsed of parsedQueries) {
9757
- const dataSet = await (0, _runQuery.runQuery)(parsed);
11546
+ const dataSet = await (0, _storage.withWriteSet)(() => (0, _runQuery.runQuery)(parsed));
9758
11547
  queryResults.push(dataSet[parsed.entity]);
9759
11548
  }
9760
11549
  return queryResults;
@@ -9827,6 +11616,150 @@ var jsonFsQuery = (() => {
9827
11616
  }
9828
11617
  });
9829
11618
 
11619
+ // dist/data/introspect/formatDatabase.js
11620
+ var require_formatDatabase = __commonJS({
11621
+ "dist/data/introspect/formatDatabase.js"(exports) {
11622
+ "use strict";
11623
+ init_process();
11624
+ Object.defineProperty(exports, "__esModule", {
11625
+ value: true
11626
+ });
11627
+ exports.formatDatabase = void 0;
11628
+ require_esnext_iterator_constructor();
11629
+ require_esnext_iterator_filter();
11630
+ var _storage = require_storage();
11631
+ var _config = require_config();
11632
+ var _requireNode = require_requireNode();
11633
+ var formatDatabase = async (format = (0, _config.getSetting)("format", "compact")) => {
11634
+ (0, _requireNode.requireNode)("formatDatabase");
11635
+ if (format !== "compact" && format !== "pretty") {
11636
+ throw new Error(`Unknown format "${format}": use 'compact' or 'pretty'`);
11637
+ }
11638
+ const paths = (await (0, _storage.listFiles)()).filter((path) => path.endsWith(".json"));
11639
+ const changes = [];
11640
+ for (const path of paths) {
11641
+ const text = await (0, _storage.readText)(path);
11642
+ let content;
11643
+ try {
11644
+ content = JSON.parse(text);
11645
+ } catch (error) {
11646
+ throw new Error(`Could not format ${path}: ${error.message}`);
11647
+ }
11648
+ if ((0, _storage.jsonText)(content, format) !== text) {
11649
+ changes.push({
11650
+ path,
11651
+ content
11652
+ });
11653
+ }
11654
+ }
11655
+ for (const {
11656
+ path,
11657
+ content
11658
+ } of changes) {
11659
+ await (0, _storage.writeJson)(path, content, format);
11660
+ }
11661
+ return {
11662
+ files: paths.length,
11663
+ rewritten: changes.length
11664
+ };
11665
+ };
11666
+ exports.formatDatabase = formatDatabase;
11667
+ }
11668
+ });
11669
+
11670
+ // dist/data/introspect/packDatabase.js
11671
+ var require_packDatabase = __commonJS({
11672
+ "dist/data/introspect/packDatabase.js"(exports) {
11673
+ "use strict";
11674
+ init_process();
11675
+ Object.defineProperty(exports, "__esModule", {
11676
+ value: true
11677
+ });
11678
+ exports.packDatabase = exports.checkPacked = void 0;
11679
+ require_es_json_stringify();
11680
+ require_esnext_iterator_constructor();
11681
+ require_esnext_iterator_filter();
11682
+ require_esnext_iterator_map();
11683
+ require_esnext_set_add_all();
11684
+ require_esnext_set_delete_all();
11685
+ require_esnext_set_difference();
11686
+ require_esnext_set_every();
11687
+ require_esnext_set_filter();
11688
+ require_esnext_set_find();
11689
+ require_esnext_set_intersection();
11690
+ require_esnext_set_is_disjoint_from();
11691
+ require_esnext_set_is_subset_of();
11692
+ require_esnext_set_is_superset_of();
11693
+ require_esnext_set_join();
11694
+ require_esnext_set_map();
11695
+ require_esnext_set_reduce();
11696
+ require_esnext_set_some();
11697
+ require_esnext_set_symmetric_difference();
11698
+ require_esnext_set_union();
11699
+ var _storage = require_storage();
11700
+ var _retrieveRecord = require_retrieveRecord();
11701
+ var _retrieveFiles = require_retrieveFiles();
11702
+ var _retrieveRecords = require_retrieveRecords();
11703
+ var _packedTable = require_packedTable();
11704
+ var _showRecords = require_showRecords();
11705
+ var _requireNode = require_requireNode();
11706
+ var packedText = async (name) => {
11707
+ const record = await (0, _retrieveRecord.retrieveRecord)(name);
11708
+ const entries = record.entries || [];
11709
+ const rows = await (0, _retrieveFiles.retrieveFiles)(entries.map((file) => `${record.path}/${file}`), _retrieveRecords.retrieveEntry);
11710
+ const packed = {
11711
+ entries,
11712
+ rows
11713
+ };
11714
+ return {
11715
+ path: (0, _packedTable.packedPath)(record.path),
11716
+ text: (0, _storage.jsonText)(packed, "compact"),
11717
+ rows: entries.length
11718
+ };
11719
+ };
11720
+ var orphanedPacks = async (names) => {
11721
+ const expected = new Set(names.map((name) => (0, _packedTable.packedPath)(name)));
11722
+ return (await (0, _storage.listFiles)("__packed")).filter((path) => !expected.has(path));
11723
+ };
11724
+ var packDatabase = async () => {
11725
+ (0, _requireNode.requireNode)("packDatabase");
11726
+ const names = await (0, _showRecords.showRecords)();
11727
+ let rows = 0;
11728
+ for (const name of names) {
11729
+ const packed = await packedText(name);
11730
+ await (0, _storage.makeDirectory)(packed.path.slice(0, packed.path.lastIndexOf("/")));
11731
+ await (0, _storage.writeJson)(packed.path, JSON.parse(packed.text), "compact");
11732
+ rows += packed.rows;
11733
+ }
11734
+ for (const path of await orphanedPacks(names)) {
11735
+ await (0, _storage.removeFile)(path);
11736
+ }
11737
+ return {
11738
+ records: names.length,
11739
+ rows
11740
+ };
11741
+ };
11742
+ exports.packDatabase = packDatabase;
11743
+ var checkPacked = async () => {
11744
+ (0, _requireNode.requireNode)("checkPacked");
11745
+ const names = await (0, _showRecords.showRecords)();
11746
+ const stale = [];
11747
+ for (const name of names) {
11748
+ const packed = await packedText(name);
11749
+ const current = (0, _storage.fileExists)(packed.path) ? await (0, _storage.readText)(packed.path).catch(() => void 0) : void 0;
11750
+ if (typeof current === "undefined" || JSON.stringify(JSON.parse(current)) !== packed.text) {
11751
+ stale.push(name);
11752
+ }
11753
+ }
11754
+ return {
11755
+ stale,
11756
+ orphaned: await orphanedPacks(names)
11757
+ };
11758
+ };
11759
+ exports.checkPacked = checkPacked;
11760
+ }
11761
+ });
11762
+
9830
11763
  // dist/data/introspect/index.js
9831
11764
  var require_introspect = __commonJS({
9832
11765
  "dist/data/introspect/index.js"(exports) {
@@ -9839,17 +11772,29 @@ var jsonFsQuery = (() => {
9839
11772
  Object.defineProperty(exports, "__esModule", {
9840
11773
  value: true
9841
11774
  });
9842
- exports.drop = exports.describe = exports.create = void 0;
11775
+ exports.packDatabase = exports.formatDatabase = exports.drop = exports.describe = exports.create = exports.checkPacked = exports.alter = void 0;
9843
11776
  var _create = require_create();
9844
11777
  var _drop = require_drop();
9845
11778
  var _describe = require_describe();
11779
+ var _formatDatabase = require_formatDatabase();
11780
+ var _alter = require_alter();
11781
+ var _packDatabase = require_packDatabase();
9846
11782
  var _databaseLock = require_databaseLock();
9847
- var create = (...args) => (0, _databaseLock.withDatabaseLock)(() => (0, _create.create)(...args));
11783
+ var _storage = require_storage();
11784
+ var create = (...args) => (0, _databaseLock.withDatabaseLock)(() => (0, _storage.withWriteSet)(() => (0, _create.create)(...args)));
9848
11785
  exports.create = create;
9849
- var drop = (...args) => (0, _databaseLock.withDatabaseLock)(() => (0, _drop.drop)(...args));
11786
+ var drop = (...args) => (0, _databaseLock.withDatabaseLock)(() => (0, _storage.withWriteSet)(() => (0, _drop.drop)(...args)));
9850
11787
  exports.drop = drop;
11788
+ var alter = (...args) => (0, _databaseLock.withDatabaseLock)(() => (0, _storage.withWriteSet)(() => (0, _alter.alter)(...args)));
11789
+ exports.alter = alter;
9851
11790
  var describe = (...args) => (0, _databaseLock.withDatabaseLock)(() => (0, _describe.describe)(...args));
9852
11791
  exports.describe = describe;
11792
+ var formatDatabase = (...args) => (0, _databaseLock.withDatabaseLock)(() => (0, _storage.withWriteSet)(() => (0, _formatDatabase.formatDatabase)(...args)));
11793
+ exports.formatDatabase = formatDatabase;
11794
+ var packDatabase = () => (0, _databaseLock.withDatabaseLock)(() => (0, _storage.withWriteSet)(() => (0, _packDatabase.packDatabase)()));
11795
+ exports.packDatabase = packDatabase;
11796
+ var checkPacked = () => (0, _databaseLock.withDatabaseLock)(() => (0, _packDatabase.checkPacked)());
11797
+ exports.checkPacked = checkPacked;
9853
11798
  }
9854
11799
  });
9855
11800
 
@@ -9864,6 +11809,18 @@ var jsonFsQuery = (() => {
9864
11809
  Object.defineProperty(exports, "__esModule", {
9865
11810
  value: true
9866
11811
  });
11812
+ Object.defineProperty(exports, "alter", {
11813
+ enumerable: true,
11814
+ get: function() {
11815
+ return _introspect.alter;
11816
+ }
11817
+ });
11818
+ Object.defineProperty(exports, "checkPacked", {
11819
+ enumerable: true,
11820
+ get: function() {
11821
+ return _introspect.checkPacked;
11822
+ }
11823
+ });
9867
11824
  Object.defineProperty(exports, "configure", {
9868
11825
  enumerable: true,
9869
11826
  get: function() {
@@ -9888,6 +11845,18 @@ var jsonFsQuery = (() => {
9888
11845
  return _introspect.drop;
9889
11846
  }
9890
11847
  });
11848
+ Object.defineProperty(exports, "formatDatabase", {
11849
+ enumerable: true,
11850
+ get: function() {
11851
+ return _introspect.formatDatabase;
11852
+ }
11853
+ });
11854
+ Object.defineProperty(exports, "packDatabase", {
11855
+ enumerable: true,
11856
+ get: function() {
11857
+ return _introspect.packDatabase;
11858
+ }
11859
+ });
9891
11860
  Object.defineProperty(exports, "query", {
9892
11861
  enumerable: true,
9893
11862
  get: function() {