json-fs-query 0.1.0 → 1.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.
- package/README.md +41 -6
- package/browser/jsonFsQuery.js +28271 -0
- package/browser/jsonFsQuery.min.js +1 -0
- package/dist/data/introspect/create.js +6 -4
- package/dist/data/introspect/create.min.js +1 -1
- package/dist/data/introspect/drop.js +2 -2
- package/dist/data/introspect/drop.min.js +1 -1
- package/dist/data/introspect/policies/hasDependents.d.ts +13 -0
- package/dist/data/introspect/policies/hasDependents.js +52 -0
- package/dist/data/introspect/policies/hasDependents.min.js +1 -0
- package/dist/data/introspect/policies/keyGenerate.js +1 -1
- package/dist/data/introspect/policies/keyGenerate.min.js +1 -1
- package/dist/data/introspect/policies/keyUnique.d.ts +9 -1
- package/dist/data/introspect/policies/keyUnique.js +19 -9
- package/dist/data/introspect/policies/keyUnique.min.js +1 -1
- package/dist/data/queries/deleteEntity.js +36 -15
- package/dist/data/queries/deleteEntity.min.js +1 -1
- package/dist/data/queries/groupBy.js +22 -22
- package/dist/data/queries/groupBy.min.js +1 -1
- package/dist/data/queries/insertEntity.js +14 -12
- package/dist/data/queries/insertEntity.min.js +1 -1
- package/dist/data/queries/readEntity.js +1 -1
- package/dist/data/queries/readEntity.min.js +1 -1
- package/dist/data/queries/updateEntity.js +68 -42
- package/dist/data/queries/updateEntity.min.js +1 -1
- package/dist/data/queries/where.js +1 -1
- package/dist/data/queries/where.min.js +1 -1
- package/dist/data/utilities/computeKeyValue.d.ts +13 -0
- package/dist/data/utilities/computeKeyValue.js +26 -0
- package/dist/data/utilities/computeKeyValue.min.js +1 -0
- package/dist/data/utilities/config.d.ts +28 -0
- package/dist/data/utilities/config.js +45 -0
- package/dist/data/utilities/config.min.js +1 -0
- package/dist/data/utilities/deregisterRecord.js +2 -2
- package/dist/data/utilities/deregisterRecord.min.js +1 -1
- package/dist/data/utilities/getConditionIndexedList.js +1 -1
- package/dist/data/utilities/getConditionIndexedList.min.js +1 -1
- package/dist/data/utilities/getJoinIndexedList.js +2 -2
- package/dist/data/utilities/getJoinIndexedList.min.js +1 -1
- package/dist/data/utilities/getMatchingIndexes.js +2 -2
- package/dist/data/utilities/getMatchingIndexes.min.js +1 -1
- package/dist/data/utilities/matchIndexedJoins.js +2 -2
- package/dist/data/utilities/matchIndexedJoins.min.js +1 -1
- package/dist/data/utilities/reconcileJoin.js +26 -26
- package/dist/data/utilities/reconcileJoin.min.js +1 -1
- package/dist/data/utilities/reconcileJoins.js +26 -27
- package/dist/data/utilities/reconcileJoins.min.js +1 -1
- package/dist/data/utilities/registerRecord.js +2 -2
- package/dist/data/utilities/registerRecord.min.js +1 -1
- package/dist/data/utilities/removeFromIndex.js +2 -2
- package/dist/data/utilities/removeFromIndex.min.js +1 -1
- package/dist/data/utilities/restrictIndexedList.js +45 -45
- package/dist/data/utilities/restrictIndexedList.min.js +1 -1
- package/dist/data/utilities/retrieveFile.js +3 -3
- package/dist/data/utilities/retrieveFile.min.js +1 -1
- package/dist/data/utilities/retrieveIndexes.js +1 -1
- package/dist/data/utilities/retrieveIndexes.min.js +1 -1
- package/dist/data/utilities/updateIndex.js +2 -2
- package/dist/data/utilities/updateIndex.min.js +1 -1
- package/dist/data/utilities/useJoinClause.js +4 -4
- package/dist/data/utilities/useJoinClause.min.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +7 -0
- package/dist/index.min.js +1 -1
- package/package.json +11 -4
- package/.browserslistrc +0 -1
- package/.nvmrc +0 -1
- package/MAIN.md +0 -15
- package/babel.config.js +0 -3
- package/build-tools.config.json +0 -30
- package/gulpfile.mjs +0 -15
- package/src/data/introspect/create.test.js +0 -67
- package/src/data/introspect/create.ts +0 -29
- package/src/data/introspect/definitions/field.test.js +0 -23
- package/src/data/introspect/definitions/field.ts +0 -48
- package/src/data/introspect/definitions/key.test.js +0 -100
- package/src/data/introspect/definitions/key.ts +0 -64
- package/src/data/introspect/definitions/keyReference.test.js +0 -8
- package/src/data/introspect/definitions/keyReference.ts +0 -23
- package/src/data/introspect/definitions/record.ts +0 -42
- package/src/data/introspect/describe.test.js +0 -36
- package/src/data/introspect/describe.ts +0 -9
- package/src/data/introspect/drop.test.js +0 -77
- package/src/data/introspect/drop.ts +0 -20
- package/src/data/introspect/index.ts +0 -8
- package/src/data/introspect/policies/foreignKeyExists.test.js +0 -44
- package/src/data/introspect/policies/foreignKeyExists.ts +0 -15
- package/src/data/introspect/policies/keyGenerate.ts +0 -11
- package/src/data/introspect/policies/keyUnique.ts +0 -11
- package/src/data/introspect/policies/typeCheck.test.js +0 -84
- package/src/data/introspect/policies/typeCheck.ts +0 -49
- package/src/data/introspect/policies/typeEnum.ts +0 -6
- package/src/data/introspect/policies/useDefault.ts +0 -6
- package/src/data/queries/deleteEntity.test.js +0 -86
- package/src/data/queries/deleteEntity.ts +0 -56
- package/src/data/queries/groupBy.test.js +0 -135
- package/src/data/queries/groupBy.ts +0 -16
- package/src/data/queries/insertEntity.test.js +0 -156
- package/src/data/queries/insertEntity.ts +0 -113
- package/src/data/queries/joinEntity.test.js +0 -109
- package/src/data/queries/joinEntity.ts +0 -20
- package/src/data/queries/mergeJoins.test.js +0 -174
- package/src/data/queries/mergeJoins.ts +0 -13
- package/src/data/queries/parser.test.js +0 -343
- package/src/data/queries/parser.ts +0 -24
- package/src/data/queries/query.test.js +0 -233
- package/src/data/queries/query.ts +0 -12
- package/src/data/queries/readEntity.test.js +0 -85
- package/src/data/queries/readEntity.ts +0 -8
- package/src/data/queries/sortBy.test.js +0 -131
- package/src/data/queries/sortBy.ts +0 -18
- package/src/data/queries/updateEntity.test.js +0 -228
- package/src/data/queries/updateEntity.ts +0 -162
- package/src/data/queries/where.test.js +0 -129
- package/src/data/queries/where.ts +0 -54
- package/src/data/utilities/deregisterRecord.test.js +0 -26
- package/src/data/utilities/deregisterRecord.ts +0 -24
- package/src/data/utilities/getConditionIndexedList.ts +0 -43
- package/src/data/utilities/getJoinIndexedList.ts +0 -53
- package/src/data/utilities/getMatchingIndexes.ts +0 -21
- package/src/data/utilities/matchIndexedJoins.ts +0 -45
- package/src/data/utilities/mergeJoin.test.js +0 -102
- package/src/data/utilities/mergeJoin.ts +0 -28
- package/src/data/utilities/parsers/findCommand.ts +0 -25
- package/src/data/utilities/parsers/findConditions.test.js +0 -38
- package/src/data/utilities/parsers/findConditions.ts +0 -32
- package/src/data/utilities/parsers/findGroupBy.ts +0 -20
- package/src/data/utilities/parsers/findInsertValues.test.js +0 -26
- package/src/data/utilities/parsers/findInsertValues.ts +0 -32
- package/src/data/utilities/parsers/findJoinClauses.ts +0 -29
- package/src/data/utilities/parsers/findJoinEntity.ts +0 -20
- package/src/data/utilities/parsers/findLimit.ts +0 -20
- package/src/data/utilities/parsers/findMergeJoins.ts +0 -27
- package/src/data/utilities/parsers/findOffset.ts +0 -20
- package/src/data/utilities/parsers/findSelects.ts +0 -31
- package/src/data/utilities/parsers/findSortClauses.ts +0 -31
- package/src/data/utilities/parsers/findUpdateValues.test.js +0 -37
- package/src/data/utilities/parsers/findUpdateValues.ts +0 -32
- package/src/data/utilities/parsers/isEntityProperty.ts +0 -1
- package/src/data/utilities/parsers/parseLiteralValue.test.js +0 -41
- package/src/data/utilities/parsers/parseLiteralValue.ts +0 -29
- package/src/data/utilities/parsers/parseQuery.ts +0 -73
- package/src/data/utilities/parsers/removeFromQuery.ts +0 -1
- package/src/data/utilities/parsers/splitEntityProperty.test.js +0 -8
- package/src/data/utilities/parsers/splitEntityProperty.ts +0 -17
- package/src/data/utilities/parsers/splitQueries.test.js +0 -33
- package/src/data/utilities/parsers/splitQueries.ts +0 -4
- package/src/data/utilities/reconcileJoin.test.js +0 -38
- package/src/data/utilities/reconcileJoin.ts +0 -23
- package/src/data/utilities/reconcileJoins.test.js +0 -160
- package/src/data/utilities/reconcileJoins.ts +0 -15
- package/src/data/utilities/registerRecord.test.js +0 -44
- package/src/data/utilities/registerRecord.ts +0 -44
- package/src/data/utilities/removeFromIndex.test.js +0 -44
- package/src/data/utilities/removeFromIndex.ts +0 -34
- package/src/data/utilities/restrictIndexedList.ts +0 -38
- package/src/data/utilities/retrieveFile.test.js +0 -49
- package/src/data/utilities/retrieveFile.ts +0 -19
- package/src/data/utilities/retrieveIndexes.ts +0 -17
- package/src/data/utilities/retrieveRecord.ts +0 -3
- package/src/data/utilities/retrieveRecords.test.js +0 -223
- package/src/data/utilities/retrieveRecords.ts +0 -16
- package/src/data/utilities/runQuery.test.js +0 -88
- package/src/data/utilities/runQuery.ts +0 -75
- package/src/data/utilities/updateIndex.test.js +0 -44
- package/src/data/utilities/updateIndex.ts +0 -45
- package/src/data/utilities/useJoinClause.test.js +0 -94
- package/src/data/utilities/useJoinClause.ts +0 -44
- package/src/global.d.ts +0 -1
- package/src/index.test.js +0 -52
- package/src/index.ts +0 -17
- package/test-data/__RECORDS.json +0 -32
- package/test-data/__indexes/exercise_muscle/fk_exercise_id.json +0 -14
- package/test-data/__indexes/exercise_muscle/fk_muscle_id.json +0 -14
- package/test-data/__indexes/exercise_muscle/pk__id.json +0 -14
- package/test-data/__indexes/exercises/pk__id.json +0 -14
- package/test-data/__indexes/muscles/pk__id.json +0 -58
- package/test-data/__indexes/workouts/fk_exercise_id.json +0 -23
- package/test-data/__indexes/workouts/index_date.json +0 -18
- package/test-data/__indexes/workouts/pk__id.json +0 -26
- package/test-data/copyDatabase.ts +0 -64
- package/test-data/exercise_muscle/bench_press_pectorals.json +0 -6
- package/test-data/exercise_muscle/deadlift_hamstrings.json +0 -6
- package/test-data/exercise_muscle/squat_quadriceps.json +0 -6
- package/test-data/exercise_muscle.json +0 -69
- package/test-data/exercises/bench_press.json +0 -5
- package/test-data/exercises/deadlift.json +0 -5
- package/test-data/exercises/squat.json +0 -5
- package/test-data/exercises.json +0 -34
- package/test-data/muscles/abdominal.json +0 -6
- package/test-data/muscles/biceps.json +0 -6
- package/test-data/muscles/calves.json +0 -6
- package/test-data/muscles/deltoids.json +0 -6
- package/test-data/muscles/erector_spinae.json +0 -6
- package/test-data/muscles/forearms.json +0 -6
- package/test-data/muscles/gluteus_maximus.json +0 -6
- package/test-data/muscles/hamstrings.json +0 -6
- package/test-data/muscles/latissimus_dorsi.json +0 -6
- package/test-data/muscles/obliques.json +0 -6
- package/test-data/muscles/pectorals.json +0 -6
- package/test-data/muscles/quadriceps.json +0 -6
- package/test-data/muscles/trapezius.json +0 -6
- package/test-data/muscles/triceps.json +0 -6
- package/test-data/muscles.json +0 -50
- package/test-data/workouts/2024-06-02-001.json +0 -10
- package/test-data/workouts/2024-06-02-002.json +0 -10
- package/test-data/workouts/2024-06-02-003.json +0 -10
- package/test-data/workouts/2024-06-05-001.json +0 -10
- package/test-data/workouts/2024-06-05-002.json +0 -10
- package/test-data/workouts/2024-06-05-003.json +0 -10
- package/test-data/workouts.json +0 -84
- package/tsconfig.json +0 -15
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { splitEntityProperty } from './parsers/splitEntityProperty'
|
|
2
|
-
|
|
3
|
-
export const restrictIndexedList = (joinClause, filterJoins, indexedClone) => {
|
|
4
|
-
const { entity: entityA, property: propertyA } = splitEntityProperty(joinClause.propertyA)
|
|
5
|
-
const { entity: entityB, property: propertyB } = splitEntityProperty(joinClause.propertyB)
|
|
6
|
-
if (filterJoins.hasOwnProperty(entityA)) {
|
|
7
|
-
const existingEntities = filterJoins[entityA]
|
|
8
|
-
if (!indexedClone.hasOwnProperty(entityA)) {
|
|
9
|
-
indexedClone[entityA] = {}
|
|
10
|
-
}
|
|
11
|
-
if (!indexedClone[entityA].hasOwnProperty(propertyA)) {
|
|
12
|
-
indexedClone[entityA][propertyA] = {}
|
|
13
|
-
}
|
|
14
|
-
indexedClone[entityA][propertyA] = [
|
|
15
|
-
{
|
|
16
|
-
value: existingEntities[0][propertyA],
|
|
17
|
-
record: existingEntities
|
|
18
|
-
}
|
|
19
|
-
]
|
|
20
|
-
}
|
|
21
|
-
if (filterJoins.hasOwnProperty(entityB)) {
|
|
22
|
-
const existingEntities = filterJoins[entityB]
|
|
23
|
-
if (!indexedClone.hasOwnProperty(entityB)) {
|
|
24
|
-
indexedClone[entityB] = {}
|
|
25
|
-
}
|
|
26
|
-
if (!indexedClone[entityB].hasOwnProperty(propertyB)) {
|
|
27
|
-
indexedClone[entityB][propertyB] = {}
|
|
28
|
-
}
|
|
29
|
-
indexedClone[entityB][propertyB] = [
|
|
30
|
-
{
|
|
31
|
-
value: existingEntities[0][propertyB],
|
|
32
|
-
record: existingEntities
|
|
33
|
-
}
|
|
34
|
-
]
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return indexedClone
|
|
38
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { retrieveFile } from './retrieveFile'
|
|
2
|
-
import { testHelpers } from 'js-build-tools/testHelpers'
|
|
3
|
-
import fs from 'fs'
|
|
4
|
-
|
|
5
|
-
const databasePath = 'retrieve-file-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
|
-
describe('retrieveFile', () => {
|
|
15
|
-
test('should get the file if found', async () => {
|
|
16
|
-
const recordsContent = {
|
|
17
|
-
path: '',
|
|
18
|
-
definition: [
|
|
19
|
-
{
|
|
20
|
-
name: 'path',
|
|
21
|
-
type: 'string',
|
|
22
|
-
optional: false,
|
|
23
|
-
keys: []
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
name: 'definition',
|
|
27
|
-
type: 'object',
|
|
28
|
-
optional: false,
|
|
29
|
-
keys: []
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
name: 'entries',
|
|
33
|
-
type: 'array',
|
|
34
|
-
optional: false,
|
|
35
|
-
keys: []
|
|
36
|
-
},
|
|
37
|
-
],
|
|
38
|
-
entries: [
|
|
39
|
-
'exercise_muscle.json',
|
|
40
|
-
'exercises.json',
|
|
41
|
-
'muscles.json',
|
|
42
|
-
'workouts.json',
|
|
43
|
-
]
|
|
44
|
-
}
|
|
45
|
-
const fileName = '__RECORDS.json'
|
|
46
|
-
fs.writeFileSync(`${databasePath}${fileName}`, JSON.stringify(recordsContent))
|
|
47
|
-
expect(await retrieveFile(fileName)).toEqual(recordsContent)
|
|
48
|
-
})
|
|
49
|
-
})
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import * as jsEnv from 'browser-or-node'
|
|
2
|
-
import * as gulpConfig from 'js-build-tools/gulp.config'
|
|
3
|
-
|
|
4
|
-
export const retrieveFile = async (path) => {
|
|
5
|
-
let retrieveFn = url => fetch(url).then(res => res.json())
|
|
6
|
-
let relativePath = jsEnv.isBrowser ? gulpConfig.get('relativePath', '') : ''
|
|
7
|
-
if (jsEnv.isNode) {
|
|
8
|
-
const { readFile } = require('fs/promises')
|
|
9
|
-
retrieveFn = url => readFile(url).then(res => JSON.parse(res))
|
|
10
|
-
}
|
|
11
|
-
const databasePath = gulpConfig.get('databasePath', 'database/')
|
|
12
|
-
const fetchUrl = `${relativePath}${databasePath}${path}`
|
|
13
|
-
const recordInfo = await retrieveFn(fetchUrl)
|
|
14
|
-
.catch(err => console.error(err))
|
|
15
|
-
if (!recordInfo) {
|
|
16
|
-
throw new Error(`Could not read ${path}`)
|
|
17
|
-
}
|
|
18
|
-
return recordInfo
|
|
19
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { retrieveFile } from './retrieveFile'
|
|
2
|
-
import { retrieveRecord } from './retrieveRecord'
|
|
3
|
-
|
|
4
|
-
export const retrieveIndexes = async (entity = '', properties = [], recordData = {}) => {
|
|
5
|
-
if (!recordData.hasOwnProperty(entity)) {
|
|
6
|
-
recordData[entity] = await retrieveRecord(entity)
|
|
7
|
-
}
|
|
8
|
-
const indexSet = {}
|
|
9
|
-
for (let property of properties) {
|
|
10
|
-
for (let key of recordData[entity].keys) {
|
|
11
|
-
if (key.fields.includes(property)) {
|
|
12
|
-
indexSet[property] = await retrieveFile(`__indexes/${entity}/${key.lookup}`)
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
return indexSet
|
|
17
|
-
}
|
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
import { retrieveRecords } from './retrieveRecords'
|
|
2
|
-
import { testHelpers } from 'js-build-tools/testHelpers'
|
|
3
|
-
import { copyDatabase } from '../../../test-data/copyDatabase'
|
|
4
|
-
|
|
5
|
-
const databasePath = 'retrieve-records-database/'
|
|
6
|
-
const gulpConfig = testHelpers.gulpConfig
|
|
7
|
-
gulpConfig.set('databasePath', databasePath)
|
|
8
|
-
testHelpers.setDefaults(databasePath)
|
|
9
|
-
|
|
10
|
-
beforeEach(
|
|
11
|
-
() => testHelpers.beforeEach()
|
|
12
|
-
.then(() => copyDatabase(databasePath))
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
afterEach(testHelpers.afterEach)
|
|
16
|
-
|
|
17
|
-
describe('retrieveRecords', () => {
|
|
18
|
-
test('retrieve main RECORDS file', async () => {
|
|
19
|
-
expect(await retrieveRecords('__RECORDS')).toEqual([
|
|
20
|
-
{
|
|
21
|
-
path: 'exercise_muscle',
|
|
22
|
-
definition: [
|
|
23
|
-
{
|
|
24
|
-
name: '_id',
|
|
25
|
-
type: 'string',
|
|
26
|
-
optional: false
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
name: 'exercise_id',
|
|
30
|
-
type: 'string',
|
|
31
|
-
optional: false
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
name: 'muscle_id',
|
|
35
|
-
type: 'string',
|
|
36
|
-
optional: false
|
|
37
|
-
},
|
|
38
|
-
{ name: 'muscle_rank', type: 'int', optional: false }
|
|
39
|
-
],
|
|
40
|
-
keys: [
|
|
41
|
-
{ type: 'primary', fields: ['_id'], lookup: 'pk__id.json' },
|
|
42
|
-
{
|
|
43
|
-
type: 'foreign', fields: ['exercise_id'], lookup: 'fk_exercise_id.json', references: [
|
|
44
|
-
{
|
|
45
|
-
'fields': ['exercises._id'],
|
|
46
|
-
'lookup': 'exercises.json'
|
|
47
|
-
}
|
|
48
|
-
]
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
type: 'foreign', fields: ['muscle_id'], lookup: 'fk_muscle_id.json', references: [
|
|
52
|
-
{
|
|
53
|
-
'fields': ['muscles._id'],
|
|
54
|
-
'lookup': 'muscles.json'
|
|
55
|
-
}
|
|
56
|
-
]
|
|
57
|
-
}
|
|
58
|
-
],
|
|
59
|
-
entries: [
|
|
60
|
-
'bench_press_pectorals.json',
|
|
61
|
-
'deadlift_hamstrings.json',
|
|
62
|
-
'squat_quadriceps.json'
|
|
63
|
-
]
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
path: 'exercises',
|
|
67
|
-
definition: [
|
|
68
|
-
{
|
|
69
|
-
name: '_id',
|
|
70
|
-
type: 'string',
|
|
71
|
-
optional: false
|
|
72
|
-
},
|
|
73
|
-
{ name: 'name', type: 'string', optional: false },
|
|
74
|
-
{ name: 'description', type: 'string', optional: true }
|
|
75
|
-
],
|
|
76
|
-
keys: [
|
|
77
|
-
{ type: 'primary', fields: ['_id'], lookup: 'pk__id.json' },
|
|
78
|
-
],
|
|
79
|
-
entries: ['bench_press.json', 'deadlift.json', 'squat.json']
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
path: 'muscles',
|
|
83
|
-
definition: [
|
|
84
|
-
{
|
|
85
|
-
name: '_id',
|
|
86
|
-
type: 'string',
|
|
87
|
-
optional: false
|
|
88
|
-
},
|
|
89
|
-
{ name: 'name', type: 'string', optional: false },
|
|
90
|
-
{ name: 'alias', type: 'string', optional: true },
|
|
91
|
-
{ name: 'image', type: 'string', optional: true }
|
|
92
|
-
],
|
|
93
|
-
keys: [
|
|
94
|
-
{ type: 'primary', fields: ['_id'], lookup: 'pk__id.json' },
|
|
95
|
-
],
|
|
96
|
-
entries: [
|
|
97
|
-
'abdominal.json',
|
|
98
|
-
'biceps.json',
|
|
99
|
-
'calves.json',
|
|
100
|
-
'deltoids.json',
|
|
101
|
-
'erector_spinae.json',
|
|
102
|
-
'forearms.json',
|
|
103
|
-
'gluteus_maximus.json',
|
|
104
|
-
'hamstrings.json',
|
|
105
|
-
'latissimus_dorsi.json',
|
|
106
|
-
'obliques.json',
|
|
107
|
-
'pectorals.json',
|
|
108
|
-
'quadriceps.json',
|
|
109
|
-
'trapezius.json',
|
|
110
|
-
'triceps.json'
|
|
111
|
-
]
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
path: 'workouts',
|
|
115
|
-
definition: [
|
|
116
|
-
{
|
|
117
|
-
name: '_id',
|
|
118
|
-
type: 'string',
|
|
119
|
-
optional: false
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
name: 'exercise_id',
|
|
123
|
-
type: 'string',
|
|
124
|
-
optional: false
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
name: 'weight_effort',
|
|
128
|
-
type: 'string',
|
|
129
|
-
optional: true
|
|
130
|
-
},
|
|
131
|
-
{ name: 'reps', type: 'int', optional: true },
|
|
132
|
-
{ name: 'sets', type: 'int', optional: true },
|
|
133
|
-
{ name: 'note', type: 'string', optional: true },
|
|
134
|
-
{ name: 'order', type: 'int', optional: false },
|
|
135
|
-
{ name: 'date', type: 'string', optional: false }
|
|
136
|
-
],
|
|
137
|
-
keys: [
|
|
138
|
-
{ type: 'primary', fields: ['_id'], lookup: 'pk__id.json' },
|
|
139
|
-
{ type: 'index', fields: ['date'], lookup: 'index_date.json' },
|
|
140
|
-
{
|
|
141
|
-
type: 'foreign',
|
|
142
|
-
fields: ['exercise_id'],
|
|
143
|
-
lookup: 'fk_exercise_id.json',
|
|
144
|
-
references: [{ fields: ['exercises._id'], lookup: 'exercises.json' }]
|
|
145
|
-
}
|
|
146
|
-
],
|
|
147
|
-
entries: [
|
|
148
|
-
'2024-06-02-001.json',
|
|
149
|
-
'2024-06-02-002.json',
|
|
150
|
-
'2024-06-02-003.json',
|
|
151
|
-
'2024-06-05-001.json',
|
|
152
|
-
'2024-06-05-002.json',
|
|
153
|
-
'2024-06-05-003.json'
|
|
154
|
-
]
|
|
155
|
-
}
|
|
156
|
-
])
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
test('retrieve workouts entries', async () => {
|
|
160
|
-
expect(await retrieveRecords('workouts')).toEqual([
|
|
161
|
-
{
|
|
162
|
-
_id: 1,
|
|
163
|
-
exercise_id: 1,
|
|
164
|
-
weight_effort: '115lbs',
|
|
165
|
-
reps: 10,
|
|
166
|
-
sets: 3,
|
|
167
|
-
note: '',
|
|
168
|
-
order: 0,
|
|
169
|
-
date: '2024-06-02'
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
_id: 2,
|
|
173
|
-
exercise_id: 2,
|
|
174
|
-
weight_effort: '155lbs',
|
|
175
|
-
reps: 10,
|
|
176
|
-
sets: 3,
|
|
177
|
-
note: '',
|
|
178
|
-
order: 1,
|
|
179
|
-
date: '2024-06-02'
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
_id: 3,
|
|
183
|
-
exercise_id: 3,
|
|
184
|
-
weight_effort: '155lbs',
|
|
185
|
-
reps: 10,
|
|
186
|
-
sets: 3,
|
|
187
|
-
note: '',
|
|
188
|
-
order: 2,
|
|
189
|
-
date: '2024-06-02'
|
|
190
|
-
},
|
|
191
|
-
{
|
|
192
|
-
_id: 4,
|
|
193
|
-
exercise_id: 1,
|
|
194
|
-
weight_effort: '120lbs',
|
|
195
|
-
reps: 10,
|
|
196
|
-
sets: 3,
|
|
197
|
-
note: '',
|
|
198
|
-
order: 0,
|
|
199
|
-
date: '2024-06-05'
|
|
200
|
-
},
|
|
201
|
-
{
|
|
202
|
-
_id: 5,
|
|
203
|
-
exercise_id: 2,
|
|
204
|
-
weight_effort: '160lbs',
|
|
205
|
-
reps: 10,
|
|
206
|
-
sets: 3,
|
|
207
|
-
note: '',
|
|
208
|
-
order: 1,
|
|
209
|
-
date: '2024-06-05'
|
|
210
|
-
},
|
|
211
|
-
{
|
|
212
|
-
_id: 6,
|
|
213
|
-
exercise_id: 3,
|
|
214
|
-
weight_effort: '160lbs',
|
|
215
|
-
reps: 10,
|
|
216
|
-
sets: 3,
|
|
217
|
-
note: '',
|
|
218
|
-
order: 2,
|
|
219
|
-
date: '2024-06-05'
|
|
220
|
-
}
|
|
221
|
-
])
|
|
222
|
-
})
|
|
223
|
-
})
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { retrieveFile } from './retrieveFile'
|
|
2
|
-
import { retrieveRecord } from './retrieveRecord'
|
|
3
|
-
|
|
4
|
-
export const retrieveRecords = async (entity = '') => {
|
|
5
|
-
const recordFile = await retrieveRecord(entity)
|
|
6
|
-
const dataSet = []
|
|
7
|
-
for (let file of recordFile.entries) {
|
|
8
|
-
const data = await retrieveFile(`${recordFile.path}/${file}`)
|
|
9
|
-
.catch(err => console.error(err))
|
|
10
|
-
if (!data) {
|
|
11
|
-
throw new Error(`Could not read entity ${file}`)
|
|
12
|
-
}
|
|
13
|
-
dataSet.push(data)
|
|
14
|
-
}
|
|
15
|
-
return dataSet
|
|
16
|
-
}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { create } from '../introspect/create'
|
|
2
|
-
import { insertEntity } from '../queries/insertEntity'
|
|
3
|
-
import { runQuery } from './runQuery'
|
|
4
|
-
import { testHelpers } from 'js-build-tools/testHelpers'
|
|
5
|
-
|
|
6
|
-
const databasePath = 'run-query-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: 'bar', type: 'string', optional: false, autoGenerate: false }
|
|
18
|
-
]
|
|
19
|
-
|
|
20
|
-
const keys = [
|
|
21
|
-
{ type: 'primary', fields: ['_id'], lookup: 'pk__id.json' }
|
|
22
|
-
]
|
|
23
|
-
|
|
24
|
-
const baseParsed = (overrides) => Object.assign({
|
|
25
|
-
entity: 'foo',
|
|
26
|
-
joinEntity: undefined,
|
|
27
|
-
conditions: [],
|
|
28
|
-
joinClauses: [],
|
|
29
|
-
mergeJoins: [],
|
|
30
|
-
sortClauses: [],
|
|
31
|
-
groupBy: undefined
|
|
32
|
-
}, overrides)
|
|
33
|
-
|
|
34
|
-
describe('runQuery', () => {
|
|
35
|
-
describe('delete', () => {
|
|
36
|
-
test('deletes only the rows matching a non-indexed condition', async () => {
|
|
37
|
-
await create('foo', definition, keys)
|
|
38
|
-
await insertEntity('foo', [{ bar: 'keep' }, { bar: 'remove' }, { bar: 'keep' }], {})
|
|
39
|
-
|
|
40
|
-
const result = await runQuery(baseParsed({
|
|
41
|
-
command: 'delete',
|
|
42
|
-
conditions: [{ property: 'bar', comparator: '=', value: 'remove' }]
|
|
43
|
-
}))
|
|
44
|
-
|
|
45
|
-
expect(result.foo.map(row => row.bar)).toEqual(['remove'])
|
|
46
|
-
const remaining = await runQuery(baseParsed({ command: 'read' }))
|
|
47
|
-
expect(remaining.foo.map(row => row.bar).sort()).toEqual(['keep', 'keep'])
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
test('with no conditions, deletes every row', async () => {
|
|
51
|
-
await create('foo', definition, keys)
|
|
52
|
-
await insertEntity('foo', [{ bar: 'one' }, { bar: 'two' }], {})
|
|
53
|
-
|
|
54
|
-
await runQuery(baseParsed({ command: 'delete' }))
|
|
55
|
-
|
|
56
|
-
const remaining = await runQuery(baseParsed({ command: 'read' }))
|
|
57
|
-
expect(remaining.foo).toEqual([])
|
|
58
|
-
})
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
describe('update', () => {
|
|
62
|
-
test('updates only the rows matching a non-indexed condition', async () => {
|
|
63
|
-
await create('foo', definition, keys)
|
|
64
|
-
await insertEntity('foo', [{ bar: 'change-me' }, { bar: 'leave-me' }], {})
|
|
65
|
-
|
|
66
|
-
const result = await runQuery(baseParsed({
|
|
67
|
-
command: 'update',
|
|
68
|
-
conditions: [{ property: 'bar', comparator: '=', value: 'change-me' }],
|
|
69
|
-
updateValues: { bar: 'changed' }
|
|
70
|
-
}))
|
|
71
|
-
|
|
72
|
-
expect(result.foo).toHaveLength(1)
|
|
73
|
-
expect(result.foo[0].bar).toBe('changed')
|
|
74
|
-
const remaining = await runQuery(baseParsed({ command: 'read' }))
|
|
75
|
-
expect(remaining.foo.map(row => row.bar).sort()).toEqual(['changed', 'leave-me'])
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
test('with no conditions, updates every row', async () => {
|
|
79
|
-
await create('foo', definition, keys)
|
|
80
|
-
await insertEntity('foo', [{ bar: 'one' }, { bar: 'two' }], {})
|
|
81
|
-
|
|
82
|
-
await runQuery(baseParsed({ command: 'update', updateValues: { bar: 'all-changed' } }))
|
|
83
|
-
|
|
84
|
-
const remaining = await runQuery(baseParsed({ command: 'read' }))
|
|
85
|
-
expect(remaining.foo.map(row => row.bar)).toEqual(['all-changed', 'all-changed'])
|
|
86
|
-
})
|
|
87
|
-
})
|
|
88
|
-
})
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { deleteEntity } from '../queries/deleteEntity'
|
|
2
|
-
import { insertEntity } from '../queries/insertEntity'
|
|
3
|
-
import { readEntity } from '../queries/readEntity'
|
|
4
|
-
import { updateEntity } from '../queries/updateEntity'
|
|
5
|
-
import { joinEntity } from '../queries/joinEntity'
|
|
6
|
-
import { mergeJoins } from '../queries/mergeJoins'
|
|
7
|
-
import { where } from '../queries/where'
|
|
8
|
-
import { sortBy } from '../queries/sortBy'
|
|
9
|
-
import { groupBy } from '../queries/groupBy'
|
|
10
|
-
import { retrieveRecord } from './retrieveRecord'
|
|
11
|
-
import { getConditionIndexedList } from './getConditionIndexedList'
|
|
12
|
-
import { getJoinIndexedList } from './getJoinIndexedList'
|
|
13
|
-
|
|
14
|
-
export const runQuery = async (parsed) => {
|
|
15
|
-
const recordData = {
|
|
16
|
-
[parsed.entity]: await retrieveRecord(parsed.entity)
|
|
17
|
-
}
|
|
18
|
-
if (typeof parsed.joinEntity !== 'undefined') {
|
|
19
|
-
recordData[parsed.joinEntity] = await retrieveRecord(parsed.joinEntity)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
let dataSet: any = { [parsed.entity]: [] }
|
|
23
|
-
|
|
24
|
-
parsed = await getConditionIndexedList(parsed, recordData, dataSet)
|
|
25
|
-
parsed = await getJoinIndexedList(parsed, recordData, dataSet)
|
|
26
|
-
|
|
27
|
-
// delete/update act on whatever is already in dataSet[entity] - unlike read, which loads
|
|
28
|
-
// everything and lets the where-reduce below narrow it down afterward, they never get a second
|
|
29
|
-
// pass. So the matching rows have to be fully resolved (indexed conditions already are, via
|
|
30
|
-
// getConditionIndexedList above; anything left in parsed.conditions is not) before either runs.
|
|
31
|
-
if (parsed.command === 'delete' || parsed.command === 'update') {
|
|
32
|
-
dataSet = await readEntity(parsed.entity, dataSet)
|
|
33
|
-
dataSet[parsed.entity] = parsed.conditions.reduce(
|
|
34
|
-
(remainingData, condition) => where(remainingData, condition),
|
|
35
|
-
dataSet[parsed.entity]
|
|
36
|
-
)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
switch (parsed.command) {
|
|
40
|
-
case 'delete':
|
|
41
|
-
dataSet = await deleteEntity(parsed.entity, dataSet)
|
|
42
|
-
break
|
|
43
|
-
case 'insert':
|
|
44
|
-
dataSet = await insertEntity(parsed.entity, parsed.insertValues, dataSet)
|
|
45
|
-
break
|
|
46
|
-
case 'read':
|
|
47
|
-
dataSet = await readEntity(parsed.entity, dataSet)
|
|
48
|
-
break
|
|
49
|
-
case 'update':
|
|
50
|
-
dataSet = await updateEntity(parsed.entity, parsed.updateValues, dataSet)
|
|
51
|
-
break
|
|
52
|
-
default:
|
|
53
|
-
throw new Error(`Unknown command: ${parsed.command}`)
|
|
54
|
-
}
|
|
55
|
-
dataSet = await joinEntity(parsed.entity, parsed.joinEntity, dataSet, parsed.joinClauses)
|
|
56
|
-
dataSet = await mergeJoins(dataSet, parsed.mergeJoins)
|
|
57
|
-
|
|
58
|
-
// delete/update already had parsed.conditions applied above, before they ran. Re-applying the
|
|
59
|
-
// same conditions here would be wrong, not just redundant, for update specifically: if the
|
|
60
|
-
// update just changed the very field a condition filters on, re-checking that condition against
|
|
61
|
-
// the now-changed data would filter the just-updated rows back out.
|
|
62
|
-
if (parsed.command !== 'delete' && parsed.command !== 'update') {
|
|
63
|
-
dataSet[parsed.entity] = parsed.conditions.reduce(
|
|
64
|
-
(remainingData, condition) => {
|
|
65
|
-
return where(remainingData, condition)
|
|
66
|
-
},
|
|
67
|
-
dataSet[parsed.entity]
|
|
68
|
-
)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
dataSet[parsed.entity] = sortBy(dataSet[parsed.entity], parsed.sortClauses)
|
|
72
|
-
dataSet[parsed.entity] = groupBy(dataSet[parsed.entity], parsed.groupBy)
|
|
73
|
-
|
|
74
|
-
return dataSet
|
|
75
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { updateIndex } from './updateIndex'
|
|
2
|
-
import { testHelpers } from 'js-build-tools/testHelpers'
|
|
3
|
-
|
|
4
|
-
const databasePath = 'update-index-database/'
|
|
5
|
-
const gulpConfig = testHelpers.gulpConfig
|
|
6
|
-
gulpConfig.set('databasePath', databasePath)
|
|
7
|
-
testHelpers.setDefaults(databasePath)
|
|
8
|
-
|
|
9
|
-
beforeEach(testHelpers.beforeEach)
|
|
10
|
-
|
|
11
|
-
afterEach(testHelpers.afterEach)
|
|
12
|
-
|
|
13
|
-
describe('updateIndex', () => {
|
|
14
|
-
test('does nothing for a key with no lookup', async () => {
|
|
15
|
-
const result = await updateIndex('foo', { type: 'multi', fields: ['a', 'b'], lookup: '' }, 'x', 'x.json')
|
|
16
|
-
expect(result).toBeNull()
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
test('creates a new index file the first time a value is indexed', async () => {
|
|
20
|
-
const key = { type: 'primary', fields: ['_id'], lookup: 'pk__id.json' }
|
|
21
|
-
const result = await updateIndex('foo', key, 1, '1.json')
|
|
22
|
-
expect(result).toEqual([{ value: 1, record: ['1.json'] }])
|
|
23
|
-
expect(testHelpers.fileExists(`${databasePath}__indexes/foo/pk__id.json`)).toBeTruthy()
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
test('appends a new value onto an existing index file', async () => {
|
|
27
|
-
const key = { type: 'index', fields: ['date'], lookup: 'index_date.json' }
|
|
28
|
-
await updateIndex('foo', key, '2024-06-02', '1.json')
|
|
29
|
-
const result = await updateIndex('foo', key, '2024-06-05', '2.json')
|
|
30
|
-
expect(result).toEqual([
|
|
31
|
-
{ value: '2024-06-02', record: ['1.json'] },
|
|
32
|
-
{ value: '2024-06-05', record: ['2.json'] }
|
|
33
|
-
])
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
test('adds a matching file onto an existing value instead of duplicating the value', async () => {
|
|
37
|
-
const key = { type: 'index', fields: ['date'], lookup: 'index_date.json' }
|
|
38
|
-
await updateIndex('foo', key, '2024-06-02', '1.json')
|
|
39
|
-
const result = await updateIndex('foo', key, '2024-06-02', '2.json')
|
|
40
|
-
expect(result).toEqual([
|
|
41
|
-
{ value: '2024-06-02', record: ['1.json', '2.json'] }
|
|
42
|
-
])
|
|
43
|
-
})
|
|
44
|
-
})
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { keyDefinition } from '../introspect/definitions/key'
|
|
2
|
-
import { recordPath } from '../introspect/definitions/record'
|
|
3
|
-
|
|
4
|
-
const gulpConfig = require('js-build-tools/gulp.config')
|
|
5
|
-
const { readFile, writeFile, mkdir } = require('fs/promises')
|
|
6
|
-
|
|
7
|
-
export type indexEntry = {
|
|
8
|
-
value: any
|
|
9
|
-
record: string[]
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Add a single entry file to the index that backs one of a record's keys, creating the index
|
|
14
|
-
* file (and its __indexes/{record} directory) the first time a value is indexed. Keys with no
|
|
15
|
-
* lookup (multi-field keys are not indexed here) are left untouched.
|
|
16
|
-
* @param path
|
|
17
|
-
* @param key
|
|
18
|
-
* @param value
|
|
19
|
-
* @param fileName
|
|
20
|
-
*/
|
|
21
|
-
export const updateIndex = async (path: recordPath = '', key: keyDefinition = null, value: any = undefined, fileName: string = ''): Promise<indexEntry[] | null> => {
|
|
22
|
-
if (!key || !key.lookup) {
|
|
23
|
-
return null
|
|
24
|
-
}
|
|
25
|
-
const databasePath = gulpConfig.get('databasePath', 'database/')
|
|
26
|
-
const indexDir = `${databasePath}__indexes/${path}`
|
|
27
|
-
const indexPath = `${indexDir}/${key.lookup}`
|
|
28
|
-
let index: indexEntry[] = []
|
|
29
|
-
try {
|
|
30
|
-
index = JSON.parse(await readFile(indexPath, 'utf8'))
|
|
31
|
-
} catch (err) {
|
|
32
|
-
index = []
|
|
33
|
-
}
|
|
34
|
-
const existingEntry = index.find(entry => entry.value == value)
|
|
35
|
-
if (existingEntry) {
|
|
36
|
-
if (!existingEntry.record.includes(fileName)) {
|
|
37
|
-
existingEntry.record.push(fileName)
|
|
38
|
-
}
|
|
39
|
-
} else {
|
|
40
|
-
index.push({ value, record: [fileName] })
|
|
41
|
-
}
|
|
42
|
-
await mkdir(indexDir, { recursive: true })
|
|
43
|
-
await writeFile(indexPath, JSON.stringify(index, null, 2))
|
|
44
|
-
return index
|
|
45
|
-
}
|