json-fs-query 1.0.6 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/LICENSE +674 -674
  2. package/README.md +295 -98
  3. package/browser/jsonFsQuery.js +12733 -10777
  4. package/browser/jsonFsQuery.min.js +1 -1
  5. package/dist/data/introspect/create.d.ts +1 -1
  6. package/dist/data/introspect/create.js +35 -4
  7. package/dist/data/introspect/create.min.js +1 -1
  8. package/dist/data/introspect/definitions/field.d.ts +6 -2
  9. package/dist/data/introspect/definitions/field.js +7 -1
  10. package/dist/data/introspect/definitions/field.min.js +1 -1
  11. package/dist/data/introspect/index.d.ts +6 -3
  12. package/dist/data/introspect/index.js +10 -19
  13. package/dist/data/introspect/index.min.js +1 -1
  14. package/dist/data/introspect/policies/foreignKeyExists.js +5 -1
  15. package/dist/data/introspect/policies/foreignKeyExists.min.js +1 -1
  16. package/dist/data/introspect/policies/hasDependents.js +3 -1
  17. package/dist/data/introspect/policies/hasDependents.min.js +1 -1
  18. package/dist/data/introspect/policies/keyUnique.js +5 -1
  19. package/dist/data/introspect/policies/keyUnique.min.js +1 -1
  20. package/dist/data/introspect/policies/typeCheck.d.ts +9 -1
  21. package/dist/data/introspect/policies/typeCheck.js +16 -2
  22. package/dist/data/introspect/policies/typeCheck.min.js +1 -1
  23. package/dist/data/queries/createRecord.d.ts +11 -0
  24. package/dist/data/queries/createRecord.js +58 -0
  25. package/dist/data/queries/createRecord.min.js +1 -0
  26. package/dist/data/queries/deleteEntity.js +2 -1
  27. package/dist/data/queries/deleteEntity.min.js +1 -1
  28. package/dist/data/queries/describeRecord.d.ts +9 -0
  29. package/dist/data/queries/describeRecord.js +29 -0
  30. package/dist/data/queries/describeRecord.min.js +1 -0
  31. package/dist/data/queries/dropRecord.d.ts +9 -0
  32. package/dist/data/queries/dropRecord.js +61 -0
  33. package/dist/data/queries/dropRecord.min.js +1 -0
  34. package/dist/data/queries/insertEntity.js +11 -5
  35. package/dist/data/queries/insertEntity.min.js +1 -1
  36. package/dist/data/queries/parser.d.ts +1 -1
  37. package/dist/data/queries/parser.js +7 -15
  38. package/dist/data/queries/parser.min.js +1 -1
  39. package/dist/data/queries/query.d.ts +6 -0
  40. package/dist/data/queries/query.js +15 -6
  41. package/dist/data/queries/query.min.js +1 -1
  42. package/dist/data/queries/queryStatus.d.ts +15 -0
  43. package/dist/data/queries/queryStatus.js +52 -0
  44. package/dist/data/queries/queryStatus.min.js +1 -0
  45. package/dist/data/queries/quote.d.ts +11 -0
  46. package/dist/data/queries/quote.js +17 -0
  47. package/dist/data/queries/quote.min.js +1 -0
  48. package/dist/data/queries/showRecords.d.ts +6 -0
  49. package/dist/data/queries/showRecords.js +21 -0
  50. package/dist/data/queries/showRecords.min.js +1 -0
  51. package/dist/data/queries/sortBy.js +3 -0
  52. package/dist/data/queries/updateEntity.js +74 -18
  53. package/dist/data/queries/updateEntity.min.js +1 -1
  54. package/dist/data/queries/where.d.ts +2 -1
  55. package/dist/data/queries/where.js +18 -6
  56. package/dist/data/queries/where.min.js +1 -1
  57. package/dist/data/utilities/compareAs.d.ts +20 -0
  58. package/dist/data/utilities/compareAs.js +58 -0
  59. package/dist/data/utilities/compareAs.min.js +1 -0
  60. package/dist/data/utilities/config.d.ts +15 -0
  61. package/dist/data/utilities/config.js +31 -1
  62. package/dist/data/utilities/config.min.js +1 -1
  63. package/dist/data/utilities/databaseLock.d.ts +16 -0
  64. package/dist/data/utilities/databaseLock.js +63 -0
  65. package/dist/data/utilities/databaseLock.min.js +1 -0
  66. package/dist/data/utilities/fieldType.d.ts +16 -0
  67. package/dist/data/utilities/fieldType.js +23 -0
  68. package/dist/data/utilities/fieldType.min.js +1 -0
  69. package/dist/data/utilities/getConditionIndexedList.js +2 -1
  70. package/dist/data/utilities/getConditionIndexedList.min.js +1 -1
  71. package/dist/data/utilities/matchIndexedJoins.js +3 -1
  72. package/dist/data/utilities/matchIndexedJoins.min.js +1 -1
  73. package/dist/data/utilities/mergeJoin.js +5 -1
  74. package/dist/data/utilities/mergeJoin.min.js +1 -1
  75. package/dist/data/utilities/parsers/findConditions.d.ts +5 -1
  76. package/dist/data/utilities/parsers/findConditions.js +15 -6
  77. package/dist/data/utilities/parsers/findConditions.min.js +1 -1
  78. package/dist/data/utilities/parsers/findInsertValues.js +3 -2
  79. package/dist/data/utilities/parsers/findInsertValues.min.js +1 -1
  80. package/dist/data/utilities/parsers/findSelects.js +6 -3
  81. package/dist/data/utilities/parsers/findSelects.min.js +1 -1
  82. package/dist/data/utilities/parsers/findSortClauses.js +5 -2
  83. package/dist/data/utilities/parsers/findSortClauses.min.js +1 -1
  84. package/dist/data/utilities/parsers/findUpdateValues.js +3 -2
  85. package/dist/data/utilities/parsers/findUpdateValues.min.js +1 -1
  86. package/dist/data/utilities/parsers/maskStrings.d.ts +39 -0
  87. package/dist/data/utilities/parsers/maskStrings.js +123 -0
  88. package/dist/data/utilities/parsers/maskStrings.min.js +1 -0
  89. package/dist/data/utilities/parsers/parseCreate.d.ts +20 -0
  90. package/dist/data/utilities/parsers/parseCreate.js +330 -0
  91. package/dist/data/utilities/parsers/parseCreate.min.js +1 -0
  92. package/dist/data/utilities/parsers/parseLiteralValue.d.ts +2 -1
  93. package/dist/data/utilities/parsers/parseLiteralValue.js +6 -3
  94. package/dist/data/utilities/parsers/parseLiteralValue.min.js +1 -1
  95. package/dist/data/utilities/parsers/parseQuery.d.ts +3 -0
  96. package/dist/data/utilities/parsers/parseQuery.js +28 -2
  97. package/dist/data/utilities/parsers/parseQuery.min.js +1 -1
  98. package/dist/data/utilities/parsers/parseSchemaStatement.d.ts +13 -0
  99. package/dist/data/utilities/parsers/parseSchemaStatement.js +82 -0
  100. package/dist/data/utilities/parsers/parseSchemaStatement.min.js +1 -0
  101. package/dist/data/utilities/parsers/scanQuery.d.ts +52 -0
  102. package/dist/data/utilities/parsers/scanQuery.js +158 -0
  103. package/dist/data/utilities/parsers/scanQuery.min.js +1 -0
  104. package/dist/data/utilities/parsers/splitQueries.d.ts +6 -0
  105. package/dist/data/utilities/parsers/splitQueries.js +20 -2
  106. package/dist/data/utilities/parsers/splitQueries.min.js +1 -1
  107. package/dist/data/utilities/parsers/startsQuery.d.ts +5 -0
  108. package/dist/data/utilities/parsers/startsQuery.js +10 -0
  109. package/dist/data/utilities/parsers/startsQuery.min.js +1 -0
  110. package/dist/data/utilities/recordExists.d.ts +6 -0
  111. package/dist/data/utilities/recordExists.js +18 -0
  112. package/dist/data/utilities/recordExists.min.js +1 -0
  113. package/dist/data/utilities/removeFromIndex.d.ts +2 -1
  114. package/dist/data/utilities/removeFromIndex.js +4 -2
  115. package/dist/data/utilities/removeFromIndex.min.js +1 -1
  116. package/dist/data/utilities/runQuery.js +49 -0
  117. package/dist/data/utilities/runQuery.min.js +1 -1
  118. package/dist/data/utilities/updateIndex.d.ts +2 -1
  119. package/dist/data/utilities/updateIndex.js +4 -2
  120. package/dist/data/utilities/updateIndex.min.js +1 -1
  121. package/dist/data/utilities/useJoinClause.js +8 -2
  122. package/dist/data/utilities/useJoinClause.min.js +1 -1
  123. package/dist/index.d.ts +2 -0
  124. package/dist/index.js +14 -0
  125. package/dist/index.min.js +1 -1
  126. package/package.json +68 -55
@@ -2,7 +2,7 @@ import { recordDefinition } from './definitions/record';
2
2
  import { keyProperties } from './definitions/key';
3
3
  import { fieldProperties } from './definitions/field';
4
4
  /**
5
- * Create a new record.
5
+ * Create a new record. Throws if the definition is invalid (see assertValidDefinition).
6
6
  * @param recordName
7
7
  * @param definition
8
8
  * @param keys
@@ -5,11 +5,41 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.create = void 0;
7
7
  require("core-js/modules/es.json.stringify.js");
8
+ require("core-js/modules/esnext.iterator.constructor.js");
9
+ require("core-js/modules/esnext.iterator.find.js");
10
+ require("core-js/modules/esnext.iterator.some.js");
8
11
  var _record = require("./definitions/record");
9
12
  var _registerRecord = require("../utilities/registerRecord");
10
13
  var _config = require("../utilities/config");
14
+ var _typeCheck = require("./policies/typeCheck");
11
15
  /**
12
- * Create a new record.
16
+ * Reject a definition that could never be written correctly, before anything is created: a
17
+ * default that fails its field's type check (otherwise every insert leaving that field out would
18
+ * fail instead), including a null default on a field that isn't nullable, and a nullable field in
19
+ * the primary key (an entry's file name comes from its primary key value).
20
+ * @param recordName
21
+ * @param recordContent
22
+ */
23
+ const assertValidDefinition = (recordName, recordContent) => {
24
+ for (const field of recordContent.definition) {
25
+ if (!Object.prototype.hasOwnProperty.call(field, 'default')) {
26
+ continue;
27
+ }
28
+ try {
29
+ (0, _typeCheck.typeCheck)(field.type, field['default'], field.nullable);
30
+ } catch (err) {
31
+ throw new Error(`Invalid default for field "${field.name}" of ${recordName}: ${err.message}`);
32
+ }
33
+ }
34
+ const primaryKey = recordContent.keys.find(key => key.type === 'primary');
35
+ for (const fieldName of primaryKey ? primaryKey.fields : []) {
36
+ if (recordContent.definition.some(field => field.name === fieldName && field.nullable)) {
37
+ throw new Error(`Primary key field "${fieldName}" of ${recordName} can't be nullable`);
38
+ }
39
+ }
40
+ };
41
+ /**
42
+ * Create a new record. Throws if the definition is invalid (see assertValidDefinition).
13
43
  * @param recordName
14
44
  * @param definition
15
45
  * @param keys
@@ -29,14 +59,15 @@ const create = async (recordName, definition = [], keys = []) => {
29
59
  if (existsSync(`${databasePath}${recordName}.json`)) {
30
60
  return null;
31
61
  }
32
- await mkdir(databasePath, {
33
- recursive: true
34
- });
35
62
  const recordContent = (0, _record.record)({
36
63
  path: recordName,
37
64
  definition,
38
65
  keys
39
66
  });
67
+ assertValidDefinition(recordName, recordContent);
68
+ await mkdir(databasePath, {
69
+ recursive: true
70
+ });
40
71
  await writeFile(`${databasePath}${recordName}.json`, JSON.stringify(recordContent, null, 2));
41
72
  await mkdir(`${databasePath}${recordName}`, {
42
73
  recursive: true
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.create=void 0,require("core-js/modules/es.json.stringify.js");var _record=require("./definitions/record"),_registerRecord=require("../utilities/registerRecord"),_config=require("../utilities/config");const create=async(e,r=[],i=[])=>{const{writeFile:t,mkdir:s}=require("fs/promises"),{existsSync:o}=require("fs"),c=(0,_config.getSetting)("databasePath","database/");if("__RECORDS"===e)return null;if(o(`${c}${e}.json`))return null;await s(c,{recursive:!0});const n=(0,_record.record)({path:e,definition:r,keys:i});return await t(`${c}${e}.json`,JSON.stringify(n,null,2)),await s(`${c}${e}`,{recursive:!0}),await(0,_registerRecord.registerRecord)(e),n};exports.create=create;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.create=void 0,require("core-js/modules/es.json.stringify.js"),require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.find.js"),require("core-js/modules/esnext.iterator.some.js");var _record=require("./definitions/record"),_registerRecord=require("../utilities/registerRecord"),_config=require("../utilities/config"),_typeCheck=require("./policies/typeCheck");const assertValidDefinition=(e,r)=>{for(const t of r.definition)if(Object.prototype.hasOwnProperty.call(t,"default"))try{(0,_typeCheck.typeCheck)(t.type,t.default,t.nullable)}catch(r){throw new Error(`Invalid default for field "${t.name}" of ${e}: ${r.message}`)}const t=r.keys.find((e=>"primary"===e.type));for(const i of t?t.fields:[])if(r.definition.some((e=>e.name===i&&e.nullable)))throw new Error(`Primary key field "${i}" of ${e} can't be nullable`)},create=async(e,r=[],t=[])=>{const{writeFile:i,mkdir:s}=require("fs/promises"),{existsSync:o}=require("fs"),n=(0,_config.getSetting)("databasePath","database/");if("__RECORDS"===e)return null;if(o(`${n}${e}.json`))return null;const a=(0,_record.record)({path:e,definition:r,keys:t});return assertValidDefinition(e,a),await s(n,{recursive:!0}),await i(`${n}${e}.json`,JSON.stringify(a,null,2)),await s(`${n}${e}`,{recursive:!0}),await(0,_registerRecord.registerRecord)(e),a};exports.create=create;
@@ -3,6 +3,7 @@ export type fieldDefinition = {
3
3
  name: fieldName;
4
4
  type: string;
5
5
  optional: boolean;
6
+ nullable?: boolean;
6
7
  default?: any;
7
8
  autoGenerate: boolean;
8
9
  };
@@ -10,19 +11,22 @@ export type fieldProperties = {
10
11
  name?: string;
11
12
  type?: string;
12
13
  optional?: boolean;
14
+ nullable?: boolean;
13
15
  useDefault?: boolean;
14
16
  defaultValue?: any;
15
17
  autoGenerate?: boolean;
16
18
  };
17
19
  /**
18
- * Generate a field for a record.
20
+ * Generate a field for a record. `nullable` is only stored when true (like `default`), so fields
21
+ * that never mention it, and schemas written before it existed, stay exactly as they were.
19
22
  * @param properties
20
23
  * @param properties.name
21
24
  * @param properties.type
22
25
  * @param properties.optional
26
+ * @param properties.nullable
23
27
  * @param properties.useDefault
24
28
  * @param properties.defaultValue
25
29
  * @param properties.autoGenerate
26
30
  */
27
- export declare const field: ({ name, type, optional, useDefault, defaultValue, autoGenerate }?: fieldProperties) => fieldDefinition;
31
+ export declare const field: ({ name, type, optional, nullable, useDefault, defaultValue, autoGenerate }?: fieldProperties) => fieldDefinition;
28
32
  //# sourceMappingURL=field.d.ts.map
@@ -5,11 +5,13 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.field = void 0;
7
7
  /**
8
- * Generate a field for a record.
8
+ * Generate a field for a record. `nullable` is only stored when true (like `default`), so fields
9
+ * that never mention it, and schemas written before it existed, stay exactly as they were.
9
10
  * @param properties
10
11
  * @param properties.name
11
12
  * @param properties.type
12
13
  * @param properties.optional
14
+ * @param properties.nullable
13
15
  * @param properties.useDefault
14
16
  * @param properties.defaultValue
15
17
  * @param properties.autoGenerate
@@ -18,6 +20,7 @@ const field = ({
18
20
  name = '',
19
21
  type = 'string',
20
22
  optional = false,
23
+ nullable = false,
21
24
  useDefault = false,
22
25
  defaultValue = '',
23
26
  autoGenerate = false
@@ -28,6 +31,9 @@ const field = ({
28
31
  optional,
29
32
  autoGenerate
30
33
  };
34
+ if (nullable) {
35
+ returnField['nullable'] = true;
36
+ }
31
37
  if (useDefault) {
32
38
  returnField['default'] = defaultValue;
33
39
  }
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.field=void 0;const field=({name:e="",type:t="string",optional:o=!1,useDefault:a=!1,defaultValue:l="",autoGenerate:n=!1}={})=>{const r={name:e,type:t,optional:o,autoGenerate:n};return a&&(r.default=l),r};exports.field=field;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.field=void 0;const field=({name:e="",type:t="string",optional:l=!1,nullable:a=!1,useDefault:o=!1,defaultValue:n="",autoGenerate:u=!1}={})=>{const r={name:e,type:t,optional:l,autoGenerate:u};return a&&(r.nullable=!0),o&&(r.default=n),r};exports.field=field;
@@ -1,6 +1,9 @@
1
- export { create } from './create';
2
- export { drop } from './drop';
3
- export { describe } from './describe';
1
+ import { create as createRecord } from './create';
2
+ import { drop as dropRecord } from './drop';
3
+ import { describe as describeRecord } from './describe';
4
+ export declare const create: (...args: Parameters<typeof createRecord>) => ReturnType<typeof createRecord>;
5
+ export declare const drop: (...args: Parameters<typeof dropRecord>) => ReturnType<typeof dropRecord>;
6
+ export declare const describe: (...args: Parameters<typeof describeRecord>) => ReturnType<typeof describeRecord>;
4
7
  export { fieldProperties, fieldDefinition, fieldName } from './definitions/field';
5
8
  export { keyProperties, keyDefinition, indexType, indexLocation } from './definitions/key';
6
9
  export { referenceProperties, reference } from './definitions/keyReference';
@@ -7,24 +7,15 @@ require("core-js/modules/esnext.iterator.drop.js");
7
7
  Object.defineProperty(exports, "__esModule", {
8
8
  value: true
9
9
  });
10
- Object.defineProperty(exports, "create", {
11
- enumerable: true,
12
- get: function () {
13
- return _create.create;
14
- }
15
- });
16
- Object.defineProperty(exports, "describe", {
17
- enumerable: true,
18
- get: function () {
19
- return _describe.describe;
20
- }
21
- });
22
- Object.defineProperty(exports, "drop", {
23
- enumerable: true,
24
- get: function () {
25
- return _drop.drop;
26
- }
27
- });
10
+ exports.drop = exports.describe = exports.create = void 0;
28
11
  var _create = require("./create");
29
12
  var _drop = require("./drop");
30
- var _describe = require("./describe");
13
+ var _describe = require("./describe");
14
+ var _databaseLock = require("../utilities/databaseLock");
15
+ // The public versions take the database lock (see withDatabaseLock); code inside the package imports the files directly
16
+ const create = (...args) => (0, _databaseLock.withDatabaseLock)(() => (0, _create.create)(...args));
17
+ exports.create = create;
18
+ const drop = (...args) => (0, _databaseLock.withDatabaseLock)(() => (0, _drop.drop)(...args));
19
+ exports.drop = drop;
20
+ const describe = (...args) => (0, _databaseLock.withDatabaseLock)(() => (0, _describe.describe)(...args));
21
+ exports.describe = describe;
@@ -1 +1 @@
1
- "use strict";require("core-js/modules/esnext.async-iterator.constructor.js"),require("core-js/modules/esnext.async-iterator.drop.js"),require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.drop.js"),Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"create",{enumerable:!0,get:function(){return _create.create}}),Object.defineProperty(exports,"describe",{enumerable:!0,get:function(){return _describe.describe}}),Object.defineProperty(exports,"drop",{enumerable:!0,get:function(){return _drop.drop}});var _create=require("./create"),_drop=require("./drop"),_describe=require("./describe");
1
+ "use strict";require("core-js/modules/esnext.async-iterator.constructor.js"),require("core-js/modules/esnext.async-iterator.drop.js"),require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.drop.js"),Object.defineProperty(exports,"__esModule",{value:!0}),exports.drop=exports.describe=exports.create=void 0;var _create=require("./create"),_drop=require("./drop"),_describe=require("./describe"),_databaseLock=require("../utilities/databaseLock");const create=(...e)=>(0,_databaseLock.withDatabaseLock)((()=>(0,_create.create)(...e)));exports.create=create;const drop=(...e)=>(0,_databaseLock.withDatabaseLock)((()=>(0,_drop.drop)(...e)));exports.drop=drop;const describe=(...e)=>(0,_databaseLock.withDatabaseLock)((()=>(0,_describe.describe)(...e)));exports.describe=describe;
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.foreignKeyExists = void 0;
7
7
  var _retrieveRecords = require("../../utilities/retrieveRecords");
8
8
  var _where = require("../../queries/where");
9
+ var _retrieveRecord = require("../../utilities/retrieveRecord");
10
+ var _fieldType = require("../../utilities/fieldType");
9
11
  /**
10
12
  * Check whether any record in the referenced entity has the given property set to the given
11
13
  * value - the mirror image of keyUnique(), which checks that no record already has a value.
@@ -15,10 +17,12 @@ var _where = require("../../queries/where");
15
17
  */
16
18
  const foreignKeyExists = async (entity, property, value) => {
17
19
  const records = await (0, _retrieveRecords.retrieveRecords)(entity);
20
+ const type = (0, _fieldType.fieldType)(await (0, _retrieveRecord.retrieveRecord)(entity), property);
18
21
  const found = (0, _where.where)(records, {
19
22
  property,
20
23
  comparator: '=',
21
- value
24
+ value,
25
+ type
22
26
  });
23
27
  return found.length > 0;
24
28
  };
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.foreignKeyExists=void 0;var _retrieveRecords=require("../../utilities/retrieveRecords"),_where=require("../../queries/where");const foreignKeyExists=async(e,r,t)=>{const s=await(0,_retrieveRecords.retrieveRecords)(e);return(0,_where.where)(s,{property:r,comparator:"=",value:t}).length>0};exports.foreignKeyExists=foreignKeyExists;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.foreignKeyExists=void 0;var _retrieveRecords=require("../../utilities/retrieveRecords"),_where=require("../../queries/where"),_retrieveRecord=require("../../utilities/retrieveRecord"),_fieldType=require("../../utilities/fieldType");const foreignKeyExists=async(e,r,i)=>{const t=await(0,_retrieveRecords.retrieveRecords)(e),s=(0,_fieldType.fieldType)(await(0,_retrieveRecord.retrieveRecord)(e),r);return(0,_where.where)(t,{property:r,comparator:"=",value:i,type:s}).length>0};exports.foreignKeyExists=foreignKeyExists;
@@ -8,6 +8,7 @@ var _describe = require("../describe");
8
8
  var _retrieveRecord = require("../../utilities/retrieveRecord");
9
9
  var _retrieveRecords = require("../../utilities/retrieveRecords");
10
10
  var _where = require("../../queries/where");
11
+ var _fieldType = require("../../utilities/fieldType");
11
12
  var _splitEntityProperty = require("../../utilities/parsers/splitEntityProperty");
12
13
  /**
13
14
  * Check whether any other record, in any entity, still has a single-field foreign key pointing
@@ -40,7 +41,8 @@ const hasDependents = async (entity, property, value) => {
40
41
  const found = (0, _where.where)(records, {
41
42
  property: key.fields[0],
42
43
  comparator: '=',
43
- value
44
+ value,
45
+ type: (0, _fieldType.fieldType)(otherRecord, key.fields[0])
44
46
  });
45
47
  if (found.length) {
46
48
  return true;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.hasDependents=void 0;var _describe=require("../describe"),_retrieveRecord=require("../../utilities/retrieveRecord"),_retrieveRecords=require("../../utilities/retrieveRecords"),_where=require("../../queries/where"),_splitEntityProperty=require("../../utilities/parsers/splitEntityProperty");const hasDependents=async(e,r,t)=>{const i=await(0,_describe.describe)();for(const s of i){const i=s.replace(/\.json$/,""),o=await(0,_retrieveRecord.retrieveRecord)(i);for(const s of o.keys){if("foreign"!==s.type||1!==s.fields.length||!s.references||1!==s.references.length)continue;const{entity:o,property:n}=(0,_splitEntityProperty.splitEntityProperty)(s.references[0].fields[0]);if(o!==e||n!==r)continue;const c=await(0,_retrieveRecords.retrieveRecords)(i);if((0,_where.where)(c,{property:s.fields[0],comparator:"=",value:t}).length)return!0}}return!1};exports.hasDependents=hasDependents;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.hasDependents=void 0;var _describe=require("../describe"),_retrieveRecord=require("../../utilities/retrieveRecord"),_retrieveRecords=require("../../utilities/retrieveRecords"),_where=require("../../queries/where"),_fieldType=require("../../utilities/fieldType"),_splitEntityProperty=require("../../utilities/parsers/splitEntityProperty");const hasDependents=async(e,r,t)=>{const i=await(0,_describe.describe)();for(const s of i){const i=s.replace(/\.json$/,""),o=await(0,_retrieveRecord.retrieveRecord)(i);for(const s of o.keys){if("foreign"!==s.type||1!==s.fields.length||!s.references||1!==s.references.length)continue;const{entity:n,property:c}=(0,_splitEntityProperty.splitEntityProperty)(s.references[0].fields[0]);if(n!==e||c!==r)continue;const p=await(0,_retrieveRecords.retrieveRecords)(i);if((0,_where.where)(p,{property:s.fields[0],comparator:"=",value:t,type:(0,_fieldType.fieldType)(o,s.fields[0])}).length)return!0}}return!1};exports.hasDependents=hasDependents;
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.keyUnique = void 0;
7
7
  var _retrieveRecords = require("../../utilities/retrieveRecords");
8
8
  var _where = require("../../queries/where");
9
+ var _retrieveRecord = require("../../utilities/retrieveRecord");
10
+ var _fieldType = require("../../utilities/fieldType");
9
11
  /**
10
12
  * Check that no existing record already has this combination of values across all of the given
11
13
  * fields - a single field for a normal unique/primary key, or several for a composite one.
@@ -19,11 +21,13 @@ const keyUnique = async (entity, references = [], checkKeys = []) => {
19
21
  return false;
20
22
  }
21
23
  let records = await (0, _retrieveRecords.retrieveRecords)(entity);
24
+ const record = await (0, _retrieveRecord.retrieveRecord)(entity);
22
25
  for (let i = 0; i < references.length; i++) {
23
26
  records = (0, _where.where)(records, {
24
27
  property: references[i],
25
28
  comparator: '=',
26
- value: checkKeys[i]
29
+ value: checkKeys[i],
30
+ type: (0, _fieldType.fieldType)(record, references[i])
27
31
  });
28
32
  }
29
33
  return !records.length;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.keyUnique=void 0;var _retrieveRecords=require("../../utilities/retrieveRecords"),_where=require("../../queries/where");const keyUnique=async(e,r=[],t=[])=>{if(!r.length||r.length!==t.length)return!1;let i=await(0,_retrieveRecords.retrieveRecords)(e);for(let e=0;e<r.length;e++)i=(0,_where.where)(i,{property:r[e],comparator:"=",value:t[e]});return!i.length};exports.keyUnique=keyUnique;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.keyUnique=void 0;var _retrieveRecords=require("../../utilities/retrieveRecords"),_where=require("../../queries/where"),_retrieveRecord=require("../../utilities/retrieveRecord"),_fieldType=require("../../utilities/fieldType");const keyUnique=async(e,r=[],t=[])=>{if(!r.length||r.length!==t.length)return!1;let i=await(0,_retrieveRecords.retrieveRecords)(e);const o=await(0,_retrieveRecord.retrieveRecord)(e);for(let e=0;e<r.length;e++)i=(0,_where.where)(i,{property:r[e],comparator:"=",value:t[e],type:(0,_fieldType.fieldType)(o,r[e])});return!i.length};exports.keyUnique=keyUnique;
@@ -1,3 +1,7 @@
1
+ /**
2
+ * The type names typeCheck knows. The create statement accepts only these; create() accepts any name (see below).
3
+ */
4
+ export declare const fieldTypes: string[];
1
5
  /**
2
6
  * Validate (and where sensible, coerce) a value against a field's declared type. Runs only
3
7
  * against values being written by insertEntity/updateEntity - it never re-validates data already
@@ -5,8 +9,12 @@
5
9
  * happen, since nothing enforced this before) is left alone until something actually updates it.
6
10
  * An unrecognized type name is treated as unconstrained rather than rejected, so a typo in a
7
11
  * schema's field type can't silently block every write to that field.
12
+ *
13
+ * A null is a real JSON null, kept as it is for a nullable field and rejected for any other, of
14
+ * any type: it is never coerced, so a string field can't store the text "null" or an int field 0.
8
15
  * @param type
9
16
  * @param value
17
+ * @param nullable - Whether the field may hold null (the field definition's `nullable`).
10
18
  */
11
- export declare const typeCheck: (type?: string, value?: any) => any;
19
+ export declare const typeCheck: (type?: string, value?: any, nullable?: boolean) => any;
12
20
  //# sourceMappingURL=typeCheck.d.ts.map
@@ -3,7 +3,11 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.typeCheck = void 0;
6
+ exports.typeCheck = exports.fieldTypes = void 0;
7
+ /**
8
+ * The type names typeCheck knows. The create statement accepts only these; create() accepts any name (see below).
9
+ */
10
+ const fieldTypes = exports.fieldTypes = ['string', 'int', 'boolean', 'object', 'array'];
7
11
  /**
8
12
  * Validate (and where sensible, coerce) a value against a field's declared type. Runs only
9
13
  * against values being written by insertEntity/updateEntity - it never re-validates data already
@@ -11,13 +15,23 @@ exports.typeCheck = void 0;
11
15
  * happen, since nothing enforced this before) is left alone until something actually updates it.
12
16
  * An unrecognized type name is treated as unconstrained rather than rejected, so a typo in a
13
17
  * schema's field type can't silently block every write to that field.
18
+ *
19
+ * A null is a real JSON null, kept as it is for a nullable field and rejected for any other, of
20
+ * any type: it is never coerced, so a string field can't store the text "null" or an int field 0.
14
21
  * @param type
15
22
  * @param value
23
+ * @param nullable - Whether the field may hold null (the field definition's `nullable`).
16
24
  */
17
- const typeCheck = (type = 'string', value = undefined) => {
25
+ const typeCheck = (type = 'string', value = undefined, nullable = false) => {
18
26
  if (typeof value === 'undefined') {
19
27
  return value;
20
28
  }
29
+ if (value === null) {
30
+ if (nullable) {
31
+ return value;
32
+ }
33
+ throw new Error('Value "null" is not allowed: the field is not nullable');
34
+ }
21
35
  switch (type) {
22
36
  case 'string':
23
37
  return typeof value === 'string' ? value : String(value);
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.typeCheck=void 0;const typeCheck=(r="string",e=void 0)=>{if(void 0===e)return e;switch(r){case"string":return"string"==typeof e?e:String(e);case"int":{const r=Number(e);if(Number.isNaN(r)||!Number.isInteger(r))throw new Error(`Value "${e}" is not a valid int`);return r}case"boolean":if("boolean"==typeof e)return e;if("true"===e)return!0;if("false"===e)return!1;throw new Error(`Value "${e}" is not a valid boolean`);case"object":if("object"!=typeof e||null===e||Array.isArray(e))throw new Error(`Value "${e}" is not a valid object`);return e;case"array":if(!Array.isArray(e))throw new Error(`Value "${e}" is not a valid array`);return e;default:return e}};exports.typeCheck=typeCheck;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.typeCheck=exports.fieldTypes=void 0;const fieldTypes=exports.fieldTypes=["string","int","boolean","object","array"],typeCheck=(e="string",r=void 0,t=!1)=>{if(void 0===r)return r;if(null===r){if(t)return r;throw new Error('Value "null" is not allowed: the field is not nullable')}switch(e){case"string":return"string"==typeof r?r:String(r);case"int":{const e=Number(r);if(Number.isNaN(e)||!Number.isInteger(e))throw new Error(`Value "${r}" is not a valid int`);return e}case"boolean":if("boolean"==typeof r)return r;if("true"===r)return!0;if("false"===r)return!1;throw new Error(`Value "${r}" is not a valid boolean`);case"object":if("object"!=typeof r||null===r||Array.isArray(r))throw new Error(`Value "${r}" is not a valid object`);return r;case"array":if(!Array.isArray(r))throw new Error(`Value "${r}" is not a valid array`);return r;default:return r}};exports.typeCheck=typeCheck;
@@ -0,0 +1,11 @@
1
+ import { recordDefinition } from '../introspect/definitions/record';
2
+ import { ParsedCreate } from '../utilities/parsers/parseCreate';
3
+ /**
4
+ * Run a parsed create statement: an error if the record already exists, unless the statement says
5
+ * `if not exists` (then nothing happens and the result is null). Otherwise create() it and resolve to its
6
+ * definition, as create() does.
7
+ * @param entity
8
+ * @param parsed
9
+ */
10
+ export declare const createRecord: (entity: string, parsed: ParsedCreate) => Promise<recordDefinition | null>;
11
+ //# sourceMappingURL=createRecord.d.ts.map
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createRecord = void 0;
7
+ require("core-js/modules/es.array.includes.js");
8
+ require("core-js/modules/esnext.iterator.constructor.js");
9
+ require("core-js/modules/esnext.iterator.map.js");
10
+ var _create = require("../introspect/create");
11
+ var _retrieveRecord = require("../utilities/retrieveRecord");
12
+ var _splitEntityProperty = require("../utilities/parsers/splitEntityProperty");
13
+ var _recordExists = require("../utilities/recordExists");
14
+ /**
15
+ * Reject a foreign key whose referenced record, or field on it, doesn't exist. A key referencing the record being
16
+ * created is checked against its own fields.
17
+ * @param entity
18
+ * @param parsed
19
+ */
20
+ const assertReferencesExist = async (entity, parsed) => {
21
+ for (const key of parsed.keys) {
22
+ if (key.type !== 'foreign') {
23
+ continue;
24
+ }
25
+ const {
26
+ entity: refEntity,
27
+ property: refProperty
28
+ } = (0, _splitEntityProperty.splitEntityProperty)(key.references[0].fields[0]);
29
+ let fields = parsed.definition.map(field => field.name);
30
+ if (refEntity !== entity) {
31
+ if (!(0, _recordExists.recordExists)(refEntity)) {
32
+ throw new Error(`Foreign key "${key.fields[0]}" references "${refEntity}", which doesn't exist`);
33
+ }
34
+ fields = (await (0, _retrieveRecord.retrieveRecord)(refEntity)).definition.map(field => field.name);
35
+ }
36
+ if (!fields.includes(refProperty)) {
37
+ throw new Error(`Foreign key "${key.fields[0]}" references "${refEntity}.${refProperty}", which is not a field`);
38
+ }
39
+ }
40
+ };
41
+ /**
42
+ * Run a parsed create statement: an error if the record already exists, unless the statement says
43
+ * `if not exists` (then nothing happens and the result is null). Otherwise create() it and resolve to its
44
+ * definition, as create() does.
45
+ * @param entity
46
+ * @param parsed
47
+ */
48
+ const createRecord = async (entity, parsed) => {
49
+ if ((0, _recordExists.recordExists)(entity)) {
50
+ if (parsed.ifNotExists) {
51
+ return null;
52
+ }
53
+ throw new Error(`Record "${entity}" already exists`);
54
+ }
55
+ await assertReferencesExist(entity, parsed);
56
+ return (0, _create.create)(entity, parsed.definition, parsed.keys);
57
+ };
58
+ exports.createRecord = createRecord;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.createRecord=void 0,require("core-js/modules/es.array.includes.js"),require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.map.js");var _create=require("../introspect/create"),_retrieveRecord=require("../utilities/retrieveRecord"),_splitEntityProperty=require("../utilities/parsers/splitEntityProperty"),_recordExists=require("../utilities/recordExists");const assertReferencesExist=async(e,r)=>{for(const t of r.keys){if("foreign"!==t.type)continue;const{entity:i,property:s}=(0,_splitEntityProperty.splitEntityProperty)(t.references[0].fields[0]);let o=r.definition.map((e=>e.name));if(i!==e){if(!(0,_recordExists.recordExists)(i))throw new Error(`Foreign key "${t.fields[0]}" references "${i}", which doesn't exist`);o=(await(0,_retrieveRecord.retrieveRecord)(i)).definition.map((e=>e.name))}if(!o.includes(s))throw new Error(`Foreign key "${t.fields[0]}" references "${i}.${s}", which is not a field`)}},createRecord=async(e,r)=>{if((0,_recordExists.recordExists)(e)){if(r.ifNotExists)return null;throw new Error(`Record "${e}" already exists`)}return await assertReferencesExist(e,r),(0,_create.create)(e,r.definition,r.keys)};exports.createRecord=createRecord;
@@ -28,6 +28,7 @@ var _retrieveRecord = require("../utilities/retrieveRecord");
28
28
  var _retrieveFile = require("../utilities/retrieveFile");
29
29
  var _removeFromIndex = require("../utilities/removeFromIndex");
30
30
  var _computeKeyValue = require("../utilities/computeKeyValue");
31
+ var _fieldType = require("../utilities/fieldType");
31
32
  var _hasDependents = require("../introspect/policies/hasDependents");
32
33
  var _config = require("../utilities/config");
33
34
  const {
@@ -75,7 +76,7 @@ const removeMatchingEntries = async (entity, record, primaryKey, deletedValues)
75
76
  }
76
77
  await rm(`${databasePath}${record.path}/${fileName}`);
77
78
  for (const key of record.keys) {
78
- await (0, _removeFromIndex.removeFromIndex)(record.path, key, (0, _computeKeyValue.computeKeyValue)(key.fields, data), fileName);
79
+ await (0, _removeFromIndex.removeFromIndex)(record.path, key, (0, _computeKeyValue.computeKeyValue)(key.fields, data), fileName, (0, _fieldType.keyValueType)(record, key));
79
80
  }
80
81
  }
81
82
  return remainingEntries;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.deleteEntity=void 0,require("core-js/modules/es.json.stringify.js"),require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.find.js"),require("core-js/modules/esnext.iterator.map.js"),require("core-js/modules/esnext.set.add-all.js"),require("core-js/modules/esnext.set.delete-all.js"),require("core-js/modules/esnext.set.difference.js"),require("core-js/modules/esnext.set.every.js"),require("core-js/modules/esnext.set.filter.js"),require("core-js/modules/esnext.set.find.js"),require("core-js/modules/esnext.set.intersection.js"),require("core-js/modules/esnext.set.is-disjoint-from.js"),require("core-js/modules/esnext.set.is-subset-of.js"),require("core-js/modules/esnext.set.is-superset-of.js"),require("core-js/modules/esnext.set.join.js"),require("core-js/modules/esnext.set.map.js"),require("core-js/modules/esnext.set.reduce.js"),require("core-js/modules/esnext.set.some.js"),require("core-js/modules/esnext.set.symmetric-difference.js"),require("core-js/modules/esnext.set.union.js");var _retrieveRecord=require("../utilities/retrieveRecord"),_retrieveFile=require("../utilities/retrieveFile"),_removeFromIndex=require("../utilities/removeFromIndex"),_computeKeyValue=require("../utilities/computeKeyValue"),_hasDependents=require("../introspect/policies/hasDependents"),_config=require("../utilities/config");const{rm:rm,writeFile:writeFile}=require("fs/promises"),assertNoDependents=async(e,r,s)=>{if(!(0,_config.getSetting)("enforceForeignKeys",!0)||1!==r.fields.length)return;const t=r.fields[0];for(const r of s)if(await(0,_hasDependents.hasDependents)(e,t,r[t]))throw new Error(`Cannot delete from "${e}" where "${t}" = ${r[t]} - other records still reference it`)},removeMatchingEntries=async(e,r,s,t)=>{const i=(0,_config.getSetting)("databasePath","database/"),o=[];for(const e of r.entries){const n=await(0,_retrieveFile.retrieveFile)(`${r.path}/${e}`);if(t.has((0,_computeKeyValue.computeKeyValue)(s.fields,n))){await rm(`${i}${r.path}/${e}`);for(const s of r.keys)await(0,_removeFromIndex.removeFromIndex)(r.path,s,(0,_computeKeyValue.computeKeyValue)(s.fields,n),e)}else o.push(e)}return o},deleteEntity=async(e="",r={})=>{const s=(0,_config.getSetting)("databasePath","database/"),t=await(0,_retrieveRecord.retrieveRecord)(e),i=t.keys.find((e=>"primary"===e.type));if(!i)throw new Error(`Cannot delete from "${e}" without a primary key`);const o=r[e]||[];if(!o.length)return r;await assertNoDependents(e,i,o);const n=new Set(o.map((e=>(0,_computeKeyValue.computeKeyValue)(i.fields,e))));return t.entries=await removeMatchingEntries(0,t,i,n),await writeFile(`${s}${t.path}.json`,JSON.stringify(t,null,2)),r};exports.deleteEntity=deleteEntity;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.deleteEntity=void 0,require("core-js/modules/es.json.stringify.js"),require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.find.js"),require("core-js/modules/esnext.iterator.map.js"),require("core-js/modules/esnext.set.add-all.js"),require("core-js/modules/esnext.set.delete-all.js"),require("core-js/modules/esnext.set.difference.js"),require("core-js/modules/esnext.set.every.js"),require("core-js/modules/esnext.set.filter.js"),require("core-js/modules/esnext.set.find.js"),require("core-js/modules/esnext.set.intersection.js"),require("core-js/modules/esnext.set.is-disjoint-from.js"),require("core-js/modules/esnext.set.is-subset-of.js"),require("core-js/modules/esnext.set.is-superset-of.js"),require("core-js/modules/esnext.set.join.js"),require("core-js/modules/esnext.set.map.js"),require("core-js/modules/esnext.set.reduce.js"),require("core-js/modules/esnext.set.some.js"),require("core-js/modules/esnext.set.symmetric-difference.js"),require("core-js/modules/esnext.set.union.js");var _retrieveRecord=require("../utilities/retrieveRecord"),_retrieveFile=require("../utilities/retrieveFile"),_removeFromIndex=require("../utilities/removeFromIndex"),_computeKeyValue=require("../utilities/computeKeyValue"),_fieldType=require("../utilities/fieldType"),_hasDependents=require("../introspect/policies/hasDependents"),_config=require("../utilities/config");const{rm:rm,writeFile:writeFile}=require("fs/promises"),assertNoDependents=async(e,r,s)=>{if(!(0,_config.getSetting)("enforceForeignKeys",!0)||1!==r.fields.length)return;const t=r.fields[0];for(const r of s)if(await(0,_hasDependents.hasDependents)(e,t,r[t]))throw new Error(`Cannot delete from "${e}" where "${t}" = ${r[t]} - other records still reference it`)},removeMatchingEntries=async(e,r,s,t)=>{const i=(0,_config.getSetting)("databasePath","database/"),o=[];for(const e of r.entries){const n=await(0,_retrieveFile.retrieveFile)(`${r.path}/${e}`);if(t.has((0,_computeKeyValue.computeKeyValue)(s.fields,n))){await rm(`${i}${r.path}/${e}`);for(const s of r.keys)await(0,_removeFromIndex.removeFromIndex)(r.path,s,(0,_computeKeyValue.computeKeyValue)(s.fields,n),e,(0,_fieldType.keyValueType)(r,s))}else o.push(e)}return o},deleteEntity=async(e="",r={})=>{const s=(0,_config.getSetting)("databasePath","database/"),t=await(0,_retrieveRecord.retrieveRecord)(e),i=t.keys.find((e=>"primary"===e.type));if(!i)throw new Error(`Cannot delete from "${e}" without a primary key`);const o=r[e]||[];if(!o.length)return r;await assertNoDependents(e,i,o);const n=new Set(o.map((e=>(0,_computeKeyValue.computeKeyValue)(i.fields,e))));return t.entries=await removeMatchingEntries(0,t,i,n),await writeFile(`${s}${t.path}.json`,JSON.stringify(t,null,2)),r};exports.deleteEntity=deleteEntity;
@@ -0,0 +1,9 @@
1
+ import { recordDefinition } from '../introspect/definitions/record';
2
+ export type recordDescription = Pick<recordDefinition, 'path' | 'definition' | 'keys'>;
3
+ /**
4
+ * Run a parsed describe statement: the record's fields and keys (describe() in JS gives only the fields). An error
5
+ * if the record doesn't exist.
6
+ * @param entity
7
+ */
8
+ export declare const describeRecord: (entity: string) => Promise<recordDescription>;
9
+ //# sourceMappingURL=describeRecord.d.ts.map
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.describeRecord = void 0;
7
+ var _retrieveRecord = require("../utilities/retrieveRecord");
8
+ var _recordExists = require("../utilities/recordExists");
9
+ /**
10
+ * Run a parsed describe statement: the record's fields and keys (describe() in JS gives only the fields). An error
11
+ * if the record doesn't exist.
12
+ * @param entity
13
+ */
14
+ const describeRecord = async entity => {
15
+ if (!(0, _recordExists.recordExists)(entity)) {
16
+ throw new Error(`Record "${entity}" doesn't exist`);
17
+ }
18
+ const {
19
+ path,
20
+ definition,
21
+ keys
22
+ } = await (0, _retrieveRecord.retrieveRecord)(entity);
23
+ return {
24
+ path,
25
+ definition,
26
+ keys
27
+ };
28
+ };
29
+ exports.describeRecord = describeRecord;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.describeRecord=void 0;var _retrieveRecord=require("../utilities/retrieveRecord"),_recordExists=require("../utilities/recordExists");const describeRecord=async e=>{if(!(0,_recordExists.recordExists)(e))throw new Error(`Record "${e}" doesn't exist`);const{path:r,definition:i,keys:t}=await(0,_retrieveRecord.retrieveRecord)(e);return{path:r,definition:i,keys:t}};exports.describeRecord=describeRecord;
@@ -0,0 +1,9 @@
1
+ import { recordDefinition } from '../introspect/definitions/record';
2
+ /**
3
+ * Run a parsed drop statement: an error if the record doesn't exist, unless the statement says `if exists` (then
4
+ * nothing happens and the result is null). Otherwise drop() it and resolve to the definition it had.
5
+ * @param entity
6
+ * @param ifExists
7
+ */
8
+ export declare const dropRecord: (entity: string, ifExists: boolean) => Promise<recordDefinition | null>;
9
+ //# sourceMappingURL=dropRecord.d.ts.map
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+
3
+ require("core-js/modules/esnext.async-iterator.constructor.js");
4
+ require("core-js/modules/esnext.async-iterator.drop.js");
5
+ require("core-js/modules/esnext.iterator.drop.js");
6
+ Object.defineProperty(exports, "__esModule", {
7
+ value: true
8
+ });
9
+ exports.dropRecord = void 0;
10
+ require("core-js/modules/esnext.iterator.constructor.js");
11
+ require("core-js/modules/esnext.iterator.some.js");
12
+ var _drop = require("../introspect/drop");
13
+ var _retrieveRecord = require("../utilities/retrieveRecord");
14
+ var _recordExists = require("../utilities/recordExists");
15
+ var _splitEntityProperty = require("../utilities/parsers/splitEntityProperty");
16
+ var _config = require("../utilities/config");
17
+ /**
18
+ * RESTRICT, as MySQL does for a referenced table: reject dropping a record while another record has a foreign key
19
+ * referencing it, since every write to that record would then fail looking for the dropped one. A record referencing
20
+ * itself doesn't count. Off with enforceForeignKeys, like the row-level checks.
21
+ * @param entity
22
+ */
23
+ const assertNotReferenced = async entity => {
24
+ if (!(0, _config.getSetting)('enforceForeignKeys', true) || !(0, _recordExists.recordExists)('__RECORDS')) {
25
+ return;
26
+ }
27
+ const registry = await (0, _retrieveRecord.retrieveRecord)('__RECORDS');
28
+ for (const fileName of registry.entries) {
29
+ const other = fileName.replace(/\.json$/, '');
30
+ if (other === entity || !(0, _recordExists.recordExists)(other)) {
31
+ continue;
32
+ }
33
+ for (const key of (await (0, _retrieveRecord.retrieveRecord)(other)).keys) {
34
+ if (key.type !== 'foreign' || !key.references) {
35
+ continue;
36
+ }
37
+ if (key.references.some(reference => (0, _splitEntityProperty.splitEntityProperty)(reference.fields[0]).entity === entity)) {
38
+ throw new Error(`Cannot drop "${entity}": ${other}.${key.fields.join(', ')} references it`);
39
+ }
40
+ }
41
+ }
42
+ };
43
+ /**
44
+ * Run a parsed drop statement: an error if the record doesn't exist, unless the statement says `if exists` (then
45
+ * nothing happens and the result is null). Otherwise drop() it and resolve to the definition it had.
46
+ * @param entity
47
+ * @param ifExists
48
+ */
49
+ const dropRecord = async (entity, ifExists) => {
50
+ if (!(0, _recordExists.recordExists)(entity)) {
51
+ if (ifExists) {
52
+ return null;
53
+ }
54
+ throw new Error(`Record "${entity}" doesn't exist`);
55
+ }
56
+ await assertNotReferenced(entity);
57
+ const record = await (0, _retrieveRecord.retrieveRecord)(entity);
58
+ await (0, _drop.drop)(entity);
59
+ return record;
60
+ };
61
+ exports.dropRecord = dropRecord;
@@ -0,0 +1 @@
1
+ "use strict";require("core-js/modules/esnext.async-iterator.constructor.js"),require("core-js/modules/esnext.async-iterator.drop.js"),require("core-js/modules/esnext.iterator.drop.js"),Object.defineProperty(exports,"__esModule",{value:!0}),exports.dropRecord=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.some.js");var _drop=require("../introspect/drop"),_retrieveRecord=require("../utilities/retrieveRecord"),_recordExists=require("../utilities/recordExists"),_splitEntityProperty=require("../utilities/parsers/splitEntityProperty"),_config=require("../utilities/config");const assertNotReferenced=async e=>{if(!(0,_config.getSetting)("enforceForeignKeys",!0)||!(0,_recordExists.recordExists)("__RECORDS"))return;const r=await(0,_retrieveRecord.retrieveRecord)("__RECORDS");for(const t of r.entries){const r=t.replace(/\.json$/,"");if(r!==e&&(0,_recordExists.recordExists)(r))for(const t of(await(0,_retrieveRecord.retrieveRecord)(r)).keys)if("foreign"===t.type&&t.references&&t.references.some((r=>(0,_splitEntityProperty.splitEntityProperty)(r.fields[0]).entity===e)))throw new Error(`Cannot drop "${e}": ${r}.${t.fields.join(", ")} references it`)}},dropRecord=async(e,r)=>{if(!(0,_recordExists.recordExists)(e)){if(r)return null;throw new Error(`Record "${e}" doesn't exist`)}await assertNotReferenced(e);const t=await(0,_retrieveRecord.retrieveRecord)(e);return await(0,_drop.drop)(e),t};exports.dropRecord=dropRecord;