json-fs-query 0.1.0 → 0.1.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 (198) hide show
  1. package/dist/data/introspect/create.js +6 -4
  2. package/dist/data/introspect/create.min.js +1 -1
  3. package/dist/data/introspect/drop.js +2 -2
  4. package/dist/data/introspect/drop.min.js +1 -1
  5. package/dist/data/queries/deleteEntity.js +3 -3
  6. package/dist/data/queries/deleteEntity.min.js +1 -1
  7. package/dist/data/queries/groupBy.js +22 -22
  8. package/dist/data/queries/groupBy.min.js +1 -1
  9. package/dist/data/queries/insertEntity.js +5 -5
  10. package/dist/data/queries/insertEntity.min.js +1 -1
  11. package/dist/data/queries/readEntity.js +1 -1
  12. package/dist/data/queries/readEntity.min.js +1 -1
  13. package/dist/data/queries/updateEntity.js +6 -6
  14. package/dist/data/queries/updateEntity.min.js +1 -1
  15. package/dist/data/queries/where.js +1 -1
  16. package/dist/data/queries/where.min.js +1 -1
  17. package/dist/data/utilities/config.d.ts +22 -0
  18. package/dist/data/utilities/config.js +39 -0
  19. package/dist/data/utilities/config.min.js +1 -0
  20. package/dist/data/utilities/deregisterRecord.js +2 -2
  21. package/dist/data/utilities/deregisterRecord.min.js +1 -1
  22. package/dist/data/utilities/getConditionIndexedList.js +1 -1
  23. package/dist/data/utilities/getConditionIndexedList.min.js +1 -1
  24. package/dist/data/utilities/getJoinIndexedList.js +2 -2
  25. package/dist/data/utilities/getJoinIndexedList.min.js +1 -1
  26. package/dist/data/utilities/getMatchingIndexes.js +2 -2
  27. package/dist/data/utilities/getMatchingIndexes.min.js +1 -1
  28. package/dist/data/utilities/matchIndexedJoins.js +2 -2
  29. package/dist/data/utilities/matchIndexedJoins.min.js +1 -1
  30. package/dist/data/utilities/reconcileJoin.js +26 -26
  31. package/dist/data/utilities/reconcileJoin.min.js +1 -1
  32. package/dist/data/utilities/reconcileJoins.js +26 -27
  33. package/dist/data/utilities/reconcileJoins.min.js +1 -1
  34. package/dist/data/utilities/registerRecord.js +2 -2
  35. package/dist/data/utilities/registerRecord.min.js +1 -1
  36. package/dist/data/utilities/removeFromIndex.js +2 -2
  37. package/dist/data/utilities/removeFromIndex.min.js +1 -1
  38. package/dist/data/utilities/restrictIndexedList.js +45 -45
  39. package/dist/data/utilities/restrictIndexedList.min.js +1 -1
  40. package/dist/data/utilities/retrieveFile.js +3 -3
  41. package/dist/data/utilities/retrieveFile.min.js +1 -1
  42. package/dist/data/utilities/retrieveIndexes.js +1 -1
  43. package/dist/data/utilities/retrieveIndexes.min.js +1 -1
  44. package/dist/data/utilities/updateIndex.js +2 -2
  45. package/dist/data/utilities/updateIndex.min.js +1 -1
  46. package/dist/data/utilities/useJoinClause.js +4 -4
  47. package/dist/data/utilities/useJoinClause.min.js +1 -1
  48. package/dist/index.d.ts +1 -0
  49. package/dist/index.js +7 -0
  50. package/dist/index.min.js +1 -1
  51. package/package.json +5 -1
  52. package/.browserslistrc +0 -1
  53. package/.nvmrc +0 -1
  54. package/MAIN.md +0 -15
  55. package/babel.config.js +0 -3
  56. package/build-tools.config.json +0 -30
  57. package/gulpfile.mjs +0 -15
  58. package/src/data/introspect/create.test.js +0 -67
  59. package/src/data/introspect/create.ts +0 -29
  60. package/src/data/introspect/definitions/field.test.js +0 -23
  61. package/src/data/introspect/definitions/field.ts +0 -48
  62. package/src/data/introspect/definitions/key.test.js +0 -100
  63. package/src/data/introspect/definitions/key.ts +0 -64
  64. package/src/data/introspect/definitions/keyReference.test.js +0 -8
  65. package/src/data/introspect/definitions/keyReference.ts +0 -23
  66. package/src/data/introspect/definitions/record.ts +0 -42
  67. package/src/data/introspect/describe.test.js +0 -36
  68. package/src/data/introspect/describe.ts +0 -9
  69. package/src/data/introspect/drop.test.js +0 -77
  70. package/src/data/introspect/drop.ts +0 -20
  71. package/src/data/introspect/index.ts +0 -8
  72. package/src/data/introspect/policies/foreignKeyExists.test.js +0 -44
  73. package/src/data/introspect/policies/foreignKeyExists.ts +0 -15
  74. package/src/data/introspect/policies/keyGenerate.ts +0 -11
  75. package/src/data/introspect/policies/keyUnique.ts +0 -11
  76. package/src/data/introspect/policies/typeCheck.test.js +0 -84
  77. package/src/data/introspect/policies/typeCheck.ts +0 -49
  78. package/src/data/introspect/policies/typeEnum.ts +0 -6
  79. package/src/data/introspect/policies/useDefault.ts +0 -6
  80. package/src/data/queries/deleteEntity.test.js +0 -86
  81. package/src/data/queries/deleteEntity.ts +0 -56
  82. package/src/data/queries/groupBy.test.js +0 -135
  83. package/src/data/queries/groupBy.ts +0 -16
  84. package/src/data/queries/insertEntity.test.js +0 -156
  85. package/src/data/queries/insertEntity.ts +0 -113
  86. package/src/data/queries/joinEntity.test.js +0 -109
  87. package/src/data/queries/joinEntity.ts +0 -20
  88. package/src/data/queries/mergeJoins.test.js +0 -174
  89. package/src/data/queries/mergeJoins.ts +0 -13
  90. package/src/data/queries/parser.test.js +0 -343
  91. package/src/data/queries/parser.ts +0 -24
  92. package/src/data/queries/query.test.js +0 -233
  93. package/src/data/queries/query.ts +0 -12
  94. package/src/data/queries/readEntity.test.js +0 -85
  95. package/src/data/queries/readEntity.ts +0 -8
  96. package/src/data/queries/sortBy.test.js +0 -131
  97. package/src/data/queries/sortBy.ts +0 -18
  98. package/src/data/queries/updateEntity.test.js +0 -228
  99. package/src/data/queries/updateEntity.ts +0 -162
  100. package/src/data/queries/where.test.js +0 -129
  101. package/src/data/queries/where.ts +0 -54
  102. package/src/data/utilities/deregisterRecord.test.js +0 -26
  103. package/src/data/utilities/deregisterRecord.ts +0 -24
  104. package/src/data/utilities/getConditionIndexedList.ts +0 -43
  105. package/src/data/utilities/getJoinIndexedList.ts +0 -53
  106. package/src/data/utilities/getMatchingIndexes.ts +0 -21
  107. package/src/data/utilities/matchIndexedJoins.ts +0 -45
  108. package/src/data/utilities/mergeJoin.test.js +0 -102
  109. package/src/data/utilities/mergeJoin.ts +0 -28
  110. package/src/data/utilities/parsers/findCommand.ts +0 -25
  111. package/src/data/utilities/parsers/findConditions.test.js +0 -38
  112. package/src/data/utilities/parsers/findConditions.ts +0 -32
  113. package/src/data/utilities/parsers/findGroupBy.ts +0 -20
  114. package/src/data/utilities/parsers/findInsertValues.test.js +0 -26
  115. package/src/data/utilities/parsers/findInsertValues.ts +0 -32
  116. package/src/data/utilities/parsers/findJoinClauses.ts +0 -29
  117. package/src/data/utilities/parsers/findJoinEntity.ts +0 -20
  118. package/src/data/utilities/parsers/findLimit.ts +0 -20
  119. package/src/data/utilities/parsers/findMergeJoins.ts +0 -27
  120. package/src/data/utilities/parsers/findOffset.ts +0 -20
  121. package/src/data/utilities/parsers/findSelects.ts +0 -31
  122. package/src/data/utilities/parsers/findSortClauses.ts +0 -31
  123. package/src/data/utilities/parsers/findUpdateValues.test.js +0 -37
  124. package/src/data/utilities/parsers/findUpdateValues.ts +0 -32
  125. package/src/data/utilities/parsers/isEntityProperty.ts +0 -1
  126. package/src/data/utilities/parsers/parseLiteralValue.test.js +0 -41
  127. package/src/data/utilities/parsers/parseLiteralValue.ts +0 -29
  128. package/src/data/utilities/parsers/parseQuery.ts +0 -73
  129. package/src/data/utilities/parsers/removeFromQuery.ts +0 -1
  130. package/src/data/utilities/parsers/splitEntityProperty.test.js +0 -8
  131. package/src/data/utilities/parsers/splitEntityProperty.ts +0 -17
  132. package/src/data/utilities/parsers/splitQueries.test.js +0 -33
  133. package/src/data/utilities/parsers/splitQueries.ts +0 -4
  134. package/src/data/utilities/reconcileJoin.test.js +0 -38
  135. package/src/data/utilities/reconcileJoin.ts +0 -23
  136. package/src/data/utilities/reconcileJoins.test.js +0 -160
  137. package/src/data/utilities/reconcileJoins.ts +0 -15
  138. package/src/data/utilities/registerRecord.test.js +0 -44
  139. package/src/data/utilities/registerRecord.ts +0 -44
  140. package/src/data/utilities/removeFromIndex.test.js +0 -44
  141. package/src/data/utilities/removeFromIndex.ts +0 -34
  142. package/src/data/utilities/restrictIndexedList.ts +0 -38
  143. package/src/data/utilities/retrieveFile.test.js +0 -49
  144. package/src/data/utilities/retrieveFile.ts +0 -19
  145. package/src/data/utilities/retrieveIndexes.ts +0 -17
  146. package/src/data/utilities/retrieveRecord.ts +0 -3
  147. package/src/data/utilities/retrieveRecords.test.js +0 -223
  148. package/src/data/utilities/retrieveRecords.ts +0 -16
  149. package/src/data/utilities/runQuery.test.js +0 -88
  150. package/src/data/utilities/runQuery.ts +0 -75
  151. package/src/data/utilities/updateIndex.test.js +0 -44
  152. package/src/data/utilities/updateIndex.ts +0 -45
  153. package/src/data/utilities/useJoinClause.test.js +0 -94
  154. package/src/data/utilities/useJoinClause.ts +0 -44
  155. package/src/global.d.ts +0 -1
  156. package/src/index.test.js +0 -52
  157. package/src/index.ts +0 -17
  158. package/test-data/__RECORDS.json +0 -32
  159. package/test-data/__indexes/exercise_muscle/fk_exercise_id.json +0 -14
  160. package/test-data/__indexes/exercise_muscle/fk_muscle_id.json +0 -14
  161. package/test-data/__indexes/exercise_muscle/pk__id.json +0 -14
  162. package/test-data/__indexes/exercises/pk__id.json +0 -14
  163. package/test-data/__indexes/muscles/pk__id.json +0 -58
  164. package/test-data/__indexes/workouts/fk_exercise_id.json +0 -23
  165. package/test-data/__indexes/workouts/index_date.json +0 -18
  166. package/test-data/__indexes/workouts/pk__id.json +0 -26
  167. package/test-data/copyDatabase.ts +0 -64
  168. package/test-data/exercise_muscle/bench_press_pectorals.json +0 -6
  169. package/test-data/exercise_muscle/deadlift_hamstrings.json +0 -6
  170. package/test-data/exercise_muscle/squat_quadriceps.json +0 -6
  171. package/test-data/exercise_muscle.json +0 -69
  172. package/test-data/exercises/bench_press.json +0 -5
  173. package/test-data/exercises/deadlift.json +0 -5
  174. package/test-data/exercises/squat.json +0 -5
  175. package/test-data/exercises.json +0 -34
  176. package/test-data/muscles/abdominal.json +0 -6
  177. package/test-data/muscles/biceps.json +0 -6
  178. package/test-data/muscles/calves.json +0 -6
  179. package/test-data/muscles/deltoids.json +0 -6
  180. package/test-data/muscles/erector_spinae.json +0 -6
  181. package/test-data/muscles/forearms.json +0 -6
  182. package/test-data/muscles/gluteus_maximus.json +0 -6
  183. package/test-data/muscles/hamstrings.json +0 -6
  184. package/test-data/muscles/latissimus_dorsi.json +0 -6
  185. package/test-data/muscles/obliques.json +0 -6
  186. package/test-data/muscles/pectorals.json +0 -6
  187. package/test-data/muscles/quadriceps.json +0 -6
  188. package/test-data/muscles/trapezius.json +0 -6
  189. package/test-data/muscles/triceps.json +0 -6
  190. package/test-data/muscles.json +0 -50
  191. package/test-data/workouts/2024-06-02-001.json +0 -10
  192. package/test-data/workouts/2024-06-02-002.json +0 -10
  193. package/test-data/workouts/2024-06-02-003.json +0 -10
  194. package/test-data/workouts/2024-06-05-001.json +0 -10
  195. package/test-data/workouts/2024-06-05-002.json +0 -10
  196. package/test-data/workouts/2024-06-05-003.json +0 -10
  197. package/test-data/workouts.json +0 -84
  198. package/tsconfig.json +0 -15
@@ -1,100 +0,0 @@
1
- import { key } from './key'
2
-
3
- describe('key', () => {
4
- test('can generate a primary key', () => {
5
- const primaryKey = {
6
- type: 'primary',
7
- fields: [
8
- '_id'
9
- ],
10
- lookup: 'pk__id.json'
11
- }
12
- expect(key(primaryKey)).toEqual(primaryKey)
13
- })
14
-
15
- test('can generate an index key', () => {
16
- const indexKey = {
17
- type: 'index',
18
- fields: [
19
- 'date'
20
- ],
21
- lookup: 'index_date.json'
22
- }
23
- expect(key(indexKey)).toEqual(indexKey)
24
- })
25
-
26
- test('can generate an unique key', () => {
27
- const uniqueKey = {
28
- type: 'unique',
29
- fields: [
30
- 'email'
31
- ],
32
- lookup: 'unique_email.json'
33
- }
34
- expect(key(uniqueKey)).toEqual(uniqueKey)
35
- })
36
-
37
- test('can generate a multi key', () => {
38
- const multiKey = {
39
- type: 'multi',
40
- fields: [
41
- 'email',
42
- 'user_id'
43
- ],
44
- lookup: 'multi_email_user_id.json'
45
- }
46
- expect(key(multiKey)).toEqual(multiKey)
47
- })
48
-
49
- test('can generate a foreign key', () => {
50
- const foreignKey = {
51
- type: 'foreign',
52
- fields: [
53
- 'user_id'
54
- ],
55
- lookup: 'fk_user_id.json',
56
- references: [
57
- {
58
- fields: [
59
- 'users._id'
60
- ],
61
- lookup: 'users.json'
62
- }
63
- ]
64
- }
65
- expect(key(foreignKey)).toEqual(foreignKey)
66
- })
67
-
68
- test('will throw Error for invalid multi, insufficient fields', () => {
69
- const multiKey = {
70
- type: 'multi',
71
- fields: [
72
- 'email'
73
- ],
74
- lookup: 'multi_email_user_id.json'
75
- }
76
- expect(() => key(multiKey)).toThrow(Error)
77
- })
78
-
79
- test('will throw Error for invalid foreign, insufficient references', () => {
80
- const foreignKey = {
81
- type: 'foreign',
82
- fields: [
83
- 'user_id'
84
- ],
85
- lookup: 'fk_user_id.json'
86
- }
87
- expect(() => key(foreignKey)).toThrow(Error)
88
- })
89
-
90
- test('will throw Error for unknown key type', () => {
91
- const strangeKey = {
92
- type: 'strange',
93
- fields: [
94
- 'blah'
95
- ],
96
- lookup: 'strange_blah.json'
97
- }
98
- expect(() => key(strangeKey)).toThrow(Error)
99
- })
100
- })
@@ -1,64 +0,0 @@
1
- import { keyReference, reference } from './keyReference'
2
- import { fieldName } from './field'
3
-
4
- export type indexType = string
5
-
6
- export type indexLocation = string
7
-
8
- export type keyDefinition = {
9
- type: indexType
10
- fields: Array<fieldName>
11
- lookup: indexLocation
12
- references?: Array<reference>
13
- }
14
-
15
- export type keyProperties = {
16
- type?: indexType
17
- fields?: Array<fieldName>
18
- lookup?: indexLocation
19
- references?: Array<reference>
20
- }
21
-
22
- /**
23
- * Create a field key.
24
- * @param properties
25
- * @param properties.type
26
- * @param properties.fields
27
- * @param properties.lookup
28
- * @param properties.references
29
- */
30
- export const key = ({
31
- type = 'index',
32
- fields = [],
33
- lookup = '',
34
- references = []
35
- }: keyProperties = {}): keyDefinition => {
36
- switch (type) {
37
- case 'primary':
38
- case 'index':
39
- case 'unique':
40
- references = []
41
- break
42
- case 'multi':
43
- if (fields.length < 2) {
44
- throw new Error('Multi key indicated with less than two fields')
45
- }
46
- break
47
- case 'foreign':
48
- if (references.length < 1) {
49
- throw new Error('Foreign key must have one reference to an external record')
50
- }
51
- break
52
- default:
53
- throw new Error('Unrecognized key type; must be index, primary, unique, multi, or foreign')
54
- }
55
- const keyDefinition = {
56
- type: type,
57
- fields: fields,
58
- lookup: lookup
59
- }
60
- if (typeof references !== 'undefined' && references.length > 0) {
61
- keyDefinition['references'] = references.map(keyReference)
62
- }
63
- return keyDefinition
64
- }
@@ -1,8 +0,0 @@
1
- import { keyReference } from './keyReference'
2
-
3
- describe('keyReference', () => {
4
- test('can generate a reference', () => {
5
- const reference = { fields: ['exercises._id'], lookup: 'exercises.json' }
6
- expect(keyReference(reference)).toEqual(reference)
7
- })
8
- })
@@ -1,23 +0,0 @@
1
- import { fieldName } from './field'
2
- import { recordPath } from './record'
3
-
4
- export type reference = {
5
- fields: fieldName[];
6
- lookup: recordPath;
7
- }
8
-
9
- export type referenceProperties = {
10
- fields?: fieldName[];
11
- lookup?: recordPath;
12
- }
13
-
14
- /**
15
- * Create a reference to a remote (foreign; existing on another record) key.
16
- * @param properties
17
- * @param properties.fields
18
- * @param properties.lookup
19
- */
20
- export const keyReference = ({ fields = [], lookup = '' }: referenceProperties = {}): reference => ({
21
- fields: fields,
22
- lookup: lookup
23
- })
@@ -1,42 +0,0 @@
1
- import { field, fieldDefinition, fieldProperties } from './field'
2
- import { key, keyDefinition, keyProperties } from './key'
3
-
4
- export type recordPath = string
5
-
6
- export type entityPath = string
7
-
8
- export type recordDefinition = {
9
- path: recordPath
10
- definition: fieldDefinition[]
11
- keys: keyDefinition[]
12
- entries: entityPath[]
13
- }
14
-
15
- export type recordProperties = {
16
- path?: recordPath
17
- definition?: fieldProperties[]
18
- keys?: keyProperties[]
19
- entries?: entityPath[]
20
- }
21
-
22
- /**
23
- *
24
- * @param properties
25
- * @param properties.path
26
- * @param properties.definition
27
- * @param properties.keys
28
- * @param properties.entries
29
- */
30
- export const record = ({
31
- path = '',
32
- definition = [],
33
- keys = [],
34
- entries = []
35
- }: recordProperties = {}): recordDefinition => {
36
- return {
37
- path: path,
38
- definition: definition.map(field),
39
- keys: keys.map(key),
40
- entries: entries
41
- }
42
- }
@@ -1,36 +0,0 @@
1
- import { create } from './create'
2
- import { describe as describeRecord } from './describe'
3
- import { testHelpers } from 'js-build-tools/testHelpers'
4
-
5
- const databasePath = 'describe-database/'
6
- const gulpConfig = testHelpers.gulpConfig
7
- gulpConfig.set('databasePath', databasePath)
8
- testHelpers.setDefaults(databasePath)
9
-
10
- beforeEach(testHelpers.beforeEach)
11
-
12
- afterEach(testHelpers.afterEach)
13
-
14
- const definition = [
15
- { name: '_id', type: 'string', optional: false, autoGenerate: true },
16
- { name: 'bar', type: 'string', optional: true, autoGenerate: false }
17
- ]
18
-
19
- const keys = [
20
- { type: 'primary', fields: ['_id'], lookup: 'pk__id.json' }
21
- ]
22
-
23
- describe('describe', () => {
24
- test('describes a record by returning its field definition', async () => {
25
- await create('foo', definition, keys)
26
- const result = await describeRecord('foo')
27
- expect(result).toEqual(definition)
28
- })
29
-
30
- test('describes __RECORDS by returning the list of known records', async () => {
31
- await create('foo', definition, keys)
32
- await create('bar', definition, keys)
33
- const result = await describeRecord()
34
- expect(result).toEqual(['foo.json', 'bar.json'])
35
- })
36
- })
@@ -1,9 +0,0 @@
1
- import { retrieveFile } from '../utilities/retrieveFile'
2
-
3
- export const describe = async (record = '__RECORDS') => {
4
- const recordFile = await retrieveFile(`${record}.json`)
5
- if (record === '__RECORDS') {
6
- return recordFile.entries
7
- }
8
- return recordFile.definition
9
- }
@@ -1,77 +0,0 @@
1
- import { create } from './create'
2
- import { drop } from './drop'
3
- import { insertEntity } from '../queries/insertEntity'
4
- import { testHelpers } from 'js-build-tools/testHelpers'
5
-
6
- const { writeFile, readFile } = require('fs/promises')
7
-
8
- const databasePath = 'drop-database/'
9
- const gulpConfig = testHelpers.gulpConfig
10
- gulpConfig.set('databasePath', databasePath)
11
- testHelpers.setDefaults(databasePath)
12
-
13
- beforeEach(testHelpers.beforeEach)
14
-
15
- afterEach(testHelpers.afterEach)
16
-
17
- describe('drop', () => {
18
- test('returns null for the reserved __RECORDS name, without touching anything', async () => {
19
- expect(await drop('__RECORDS')).toBeNull()
20
- })
21
-
22
- test('removes every entry file listed on the record', async () => {
23
- const recordName = 'foo'
24
- await create(recordName, [], [])
25
- // insertEntity is not implemented yet, so simulate a real entry directly: write the data file, and record it
26
- // on the record's own entries list, exactly as a working insertEntity would.
27
- const entryFile = 'entry1.json'
28
- await writeFile(`${databasePath}${recordName}/${entryFile}`, JSON.stringify({ _id: 1 }))
29
- const recordContent = JSON.parse(await readFile(`${databasePath}${recordName}.json`, 'utf8'))
30
- recordContent.entries = [entryFile]
31
- await writeFile(`${databasePath}${recordName}.json`, JSON.stringify(recordContent))
32
-
33
- expect(testHelpers.fileExists(`${databasePath}${recordName}/${entryFile}`)).toBeTruthy()
34
- await drop(recordName)
35
- expect(testHelpers.fileExists(`${databasePath}${recordName}/${entryFile}`)).toBeFalsy()
36
- })
37
-
38
- test('deregisters the record from __RECORDS', async () => {
39
- await create('foo', [], [])
40
- await create('bar', [], [])
41
- await drop('foo')
42
- const registry = JSON.parse(await readFile(`${databasePath}__RECORDS.json`, 'utf8'))
43
- expect(registry.entries).toEqual(['bar.json'])
44
- })
45
-
46
- test('removes the record\'s own definition file and data directory', async () => {
47
- await create('foo', [], [])
48
- expect(testHelpers.fileExists(`${databasePath}foo.json`)).toBeTruthy()
49
- expect(testHelpers.fileExists(`${databasePath}foo`)).toBeTruthy()
50
-
51
- await drop('foo')
52
-
53
- expect(testHelpers.fileExists(`${databasePath}foo.json`)).toBeFalsy()
54
- expect(testHelpers.fileExists(`${databasePath}foo`)).toBeFalsy()
55
- })
56
-
57
- test('removes the record\'s own index directory', async () => {
58
- const definition = [
59
- { name: '_id', type: 'string', optional: false, autoGenerate: true }
60
- ]
61
- const keys = [
62
- { type: 'primary', fields: ['_id'], lookup: 'pk__id.json' }
63
- ]
64
- await create('foo', definition, keys)
65
- await insertEntity('foo', [{}], {})
66
- expect(testHelpers.fileExists(`${databasePath}__indexes/foo/pk__id.json`)).toBeTruthy()
67
-
68
- await drop('foo')
69
-
70
- expect(testHelpers.fileExists(`${databasePath}__indexes/foo`)).toBeFalsy()
71
- })
72
-
73
- test('does not throw when the record has no index directory to remove', async () => {
74
- await create('foo', [], [])
75
- await expect(drop('foo')).resolves.not.toThrow()
76
- })
77
- })
@@ -1,20 +0,0 @@
1
- import { retrieveFile } from '../utilities/retrieveFile'
2
- import { deregisterRecord } from '../utilities/deregisterRecord'
3
-
4
- const gulpConfig = require('js-build-tools/gulp.config')
5
- const { rm } = require('fs/promises')
6
-
7
- export const drop = async (record) => {
8
- const databasePath = gulpConfig.get('databasePath', 'database/')
9
- if (record === '__RECORDS') {
10
- return null
11
- }
12
- const recordFile = await retrieveFile(`${record}.json`)
13
- for (const file of recordFile.entries) {
14
- await rm(`${databasePath}${recordFile.path}/${file}`)
15
- }
16
- await rm(`${databasePath}${recordFile.path}`, { recursive: true, force: true })
17
- await rm(`${databasePath}__indexes/${recordFile.path}`, { recursive: true, force: true })
18
- await rm(`${databasePath}${record}.json`)
19
- await deregisterRecord(record)
20
- }
@@ -1,8 +0,0 @@
1
- export { create } from './create'
2
- export { drop } from './drop'
3
- export { describe } from './describe'
4
-
5
- export { fieldProperties, fieldDefinition, fieldName } from './definitions/field'
6
- export { keyProperties, keyDefinition, indexType, indexLocation } from './definitions/key'
7
- export { referenceProperties, reference } from './definitions/keyReference'
8
- export { recordProperties, recordDefinition, recordPath, entityPath } from './definitions/record'
@@ -1,44 +0,0 @@
1
- import { create } from '../create'
2
- import { insertEntity } from '../../queries/insertEntity'
3
- import { foreignKeyExists } from './foreignKeyExists'
4
- import { testHelpers } from 'js-build-tools/testHelpers'
5
-
6
- const databasePath = 'foreign-key-exists-database/'
7
- const gulpConfig = testHelpers.gulpConfig
8
- gulpConfig.set('databasePath', databasePath)
9
- testHelpers.setDefaults(databasePath)
10
-
11
- beforeEach(testHelpers.beforeEach)
12
-
13
- afterEach(testHelpers.afterEach)
14
-
15
- const definition = [
16
- { name: '_id', type: 'string', optional: false, autoGenerate: true },
17
- { name: 'name', type: 'string', optional: true, autoGenerate: false }
18
- ]
19
-
20
- const keys = [
21
- { type: 'primary', fields: ['_id'], lookup: 'pk__id.json' }
22
- ]
23
-
24
- describe('foreignKeyExists', () => {
25
- test('returns true when a record has the given property set to the given value', async () => {
26
- await create('exercises', definition, keys)
27
- const inserted = await insertEntity('exercises', [{ name: 'Bench Press' }], {})
28
- const exists = await foreignKeyExists('exercises', '_id', inserted.exercises[0]._id)
29
- expect(exists).toBe(true)
30
- })
31
-
32
- test('returns false when no record matches', async () => {
33
- await create('exercises', definition, keys)
34
- await insertEntity('exercises', [{ name: 'Bench Press' }], {})
35
- const exists = await foreignKeyExists('exercises', '_id', 'does-not-exist')
36
- expect(exists).toBe(false)
37
- })
38
-
39
- test('returns false for an entity with no entries', async () => {
40
- await create('exercises', definition, keys)
41
- const exists = await foreignKeyExists('exercises', '_id', 'anything')
42
- expect(exists).toBe(false)
43
- })
44
- })
@@ -1,15 +0,0 @@
1
- import { retrieveRecords } from '../../utilities/retrieveRecords'
2
- import { where } from '../../queries/where'
3
-
4
- /**
5
- * Check whether any record in the referenced entity has the given property set to the given
6
- * value - the mirror image of keyUnique(), which checks that no record already has a value.
7
- * @param entity
8
- * @param property
9
- * @param value
10
- */
11
- export const foreignKeyExists = async (entity: string, property: string, value: any): Promise<boolean> => {
12
- const records = await retrieveRecords(entity)
13
- const found = where(records, { property, comparator: '=', value })
14
- return found.length > 0
15
- }
@@ -1,11 +0,0 @@
1
- import { keyUnique } from './keyUnique'
2
-
3
- export const keyGenerate = async (entity, references = []) => {
4
- let uuid = null
5
- let isUnique = false
6
- while (!isUnique) {
7
- uuid = crypto.randomUUID()
8
- isUnique = await keyUnique(entity, references, uuid)
9
- }
10
- return uuid
11
- }
@@ -1,11 +0,0 @@
1
- import { retrieveRecords } from '../../utilities/retrieveRecords'
2
- import { where } from '../../queries/where'
3
-
4
- export const keyUnique = async (entity, references = [], checkKey = null) => {
5
- if (references.length !== 1) {
6
- return false
7
- }
8
- const records = await retrieveRecords(entity)
9
- const found = where(records, { property: references[0], comparator: '=', value: checkKey })
10
- return !found.length
11
- }
@@ -1,84 +0,0 @@
1
- import { typeCheck } from './typeCheck'
2
-
3
- describe('typeCheck', () => {
4
- test('passes an undefined value through unchanged, for optional fields', () => {
5
- expect(typeCheck('string', undefined)).toBeUndefined()
6
- })
7
-
8
- test('does not constrain an unrecognized type name', () => {
9
- expect(typeCheck('whatever', 42)).toBe(42)
10
- })
11
-
12
- describe('string', () => {
13
- test('leaves an existing string alone', () => {
14
- expect(typeCheck('string', 'foo')).toBe('foo')
15
- })
16
-
17
- test('coerces a non-string to a string', () => {
18
- expect(typeCheck('string', 42)).toBe('42')
19
- })
20
- })
21
-
22
- describe('int', () => {
23
- test('leaves an existing integer alone', () => {
24
- expect(typeCheck('int', 42)).toBe(42)
25
- })
26
-
27
- test('coerces a numeric string to a number', () => {
28
- expect(typeCheck('int', '42')).toBe(42)
29
- })
30
-
31
- test('rejects a non-integer number', () => {
32
- expect(() => typeCheck('int', 4.2)).toThrow('Value "4.2" is not a valid int')
33
- })
34
-
35
- test('rejects a value that cannot be coerced to a number', () => {
36
- expect(() => typeCheck('int', 'not a number')).toThrow('Value "not a number" is not a valid int')
37
- })
38
- })
39
-
40
- describe('boolean', () => {
41
- test('leaves an existing boolean alone', () => {
42
- expect(typeCheck('boolean', false)).toBe(false)
43
- })
44
-
45
- test('coerces the strings "true"/"false" to real booleans', () => {
46
- expect(typeCheck('boolean', 'true')).toBe(true)
47
- expect(typeCheck('boolean', 'false')).toBe(false)
48
- })
49
-
50
- test('rejects anything else', () => {
51
- expect(() => typeCheck('boolean', 'yes')).toThrow('Value "yes" is not a valid boolean')
52
- })
53
- })
54
-
55
- describe('object', () => {
56
- test('accepts a plain object', () => {
57
- const value = { a: 1 }
58
- expect(typeCheck('object', value)).toBe(value)
59
- })
60
-
61
- test('rejects null', () => {
62
- expect(() => typeCheck('object', null)).toThrow('Value "null" is not a valid object')
63
- })
64
-
65
- test('rejects an array', () => {
66
- expect(() => typeCheck('object', [])).toThrow('is not a valid object')
67
- })
68
-
69
- test('rejects a primitive', () => {
70
- expect(() => typeCheck('object', 'foo')).toThrow('is not a valid object')
71
- })
72
- })
73
-
74
- describe('array', () => {
75
- test('accepts an array', () => {
76
- const value = [1, 2, 3]
77
- expect(typeCheck('array', value)).toBe(value)
78
- })
79
-
80
- test('rejects a non-array', () => {
81
- expect(() => typeCheck('array', { a: 1 })).toThrow('is not a valid array')
82
- })
83
- })
84
- })
@@ -1,49 +0,0 @@
1
- /**
2
- * Validate (and where sensible, coerce) a value against a field's declared type. Runs only
3
- * against values being written by insertEntity/updateEntity - it never re-validates data already
4
- * on disk, so a field whose declared type doesn't match its already-stored values (which can
5
- * happen, since nothing enforced this before) is left alone until something actually updates it.
6
- * An unrecognized type name is treated as unconstrained rather than rejected, so a typo in a
7
- * schema's field type can't silently block every write to that field.
8
- * @param type
9
- * @param value
10
- */
11
- export const typeCheck = (type: string = 'string', value: any = undefined): any => {
12
- if (typeof value === 'undefined') {
13
- return value
14
- }
15
- switch (type) {
16
- case 'string':
17
- return typeof value === 'string' ? value : String(value)
18
- case 'int': {
19
- const coerced = Number(value)
20
- if (Number.isNaN(coerced) || !Number.isInteger(coerced)) {
21
- throw new Error(`Value "${value}" is not a valid int`)
22
- }
23
- return coerced
24
- }
25
- case 'boolean':
26
- if (typeof value === 'boolean') {
27
- return value
28
- }
29
- if (value === 'true') {
30
- return true
31
- }
32
- if (value === 'false') {
33
- return false
34
- }
35
- throw new Error(`Value "${value}" is not a valid boolean`)
36
- case 'object':
37
- if (typeof value !== 'object' || value === null || Array.isArray(value)) {
38
- throw new Error(`Value "${value}" is not a valid object`)
39
- }
40
- return value
41
- case 'array':
42
- if (!Array.isArray(value)) {
43
- throw new Error(`Value "${value}" is not a valid array`)
44
- }
45
- return value
46
- default:
47
- return value
48
- }
49
- }
@@ -1,6 +0,0 @@
1
- export const typeEnum = (values = [], value = '', optional = false) => {
2
- if (values.includes(value)) {
3
- return true
4
- }
5
- return typeof value === 'undefined' && optional
6
- }
@@ -1,6 +0,0 @@
1
- export const useDefault = (defaultValue = '', value = undefined) => {
2
- if (typeof value === 'undefined') {
3
- return defaultValue
4
- }
5
- return value
6
- }