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.
- 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/queries/deleteEntity.js +3 -3
- 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 +5 -5
- 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 +6 -6
- 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/config.d.ts +22 -0
- package/dist/data/utilities/config.js +39 -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 +5 -1
- 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,32 +0,0 @@
|
|
|
1
|
-
import { removeFromQuery } from './removeFromQuery'
|
|
2
|
-
import { parseLiteralValue } from './parseLiteralValue'
|
|
3
|
-
import { ParsedQuery } from './parseQuery'
|
|
4
|
-
|
|
5
|
-
const literal = '(?:["\'][^"\']*[\'"]|[0-9]+|\\[.*?]|null|true|false)'
|
|
6
|
-
const setClauseMatch: RegExp = new RegExp(`(set)\\s+([a-z0-9_-]+\\s*=\\s*${literal}(?:\\s*,\\s*[a-z0-9_-]+\\s*=\\s*${literal})*)`, 'i')
|
|
7
|
-
const assignmentMatch: RegExp = /([a-z0-9_-]+)\s*=\s*(["'](.*?)['"]|([0-9]+)|(\[.*?])|(null)|(true)|(false))/ig
|
|
8
|
-
|
|
9
|
-
export type ParsedUpdateValues = { [field: string]: any }
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Extract an update's "set field = value, field2 = value2" clause from the query. Uses a two-pass
|
|
13
|
-
* match, unlike the other parsers here: the set clause's own boundary is found first (so it can
|
|
14
|
-
* be removed from the query as a whole, and so the comma-separated list doesn't get confused with
|
|
15
|
-
* anything that follows, like a where clause), then each individual assignment is parsed out of
|
|
16
|
-
* that captured substring.
|
|
17
|
-
* @param parsed
|
|
18
|
-
* @param query
|
|
19
|
-
*/
|
|
20
|
-
export const findUpdateValues = (parsed: ParsedQuery, query: string): string => {
|
|
21
|
-
const clauseFound: RegExpMatchArray = query.match(setClauseMatch)
|
|
22
|
-
parsed['updateValues'] = {}
|
|
23
|
-
if (!clauseFound) {
|
|
24
|
-
return query
|
|
25
|
-
}
|
|
26
|
-
const assignmentsFound: IterableIterator<RegExpMatchArray> = clauseFound[2].matchAll(assignmentMatch)
|
|
27
|
-
// @ts-ignore
|
|
28
|
-
for (const assignment of assignmentsFound) {
|
|
29
|
-
parsed['updateValues'][assignment[1]] = parseLiteralValue(assignment, 3)
|
|
30
|
-
}
|
|
31
|
-
return removeFromQuery(clauseFound[0], query)
|
|
32
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const isEntityProperty = (property: string): boolean => /^[a-z0-9_-]+\.([a-z0-9_-]+)$/i.test(property)
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { parseLiteralValue } from './parseLiteralValue'
|
|
2
|
-
|
|
3
|
-
describe('parseLiteralValue', () => {
|
|
4
|
-
const groupMatch = (regex, str) => str.match(regex)
|
|
5
|
-
|
|
6
|
-
test('extracts a quoted string', () => {
|
|
7
|
-
const regex = /(["'](.*)['"]|([0-9]+)|(\[.*])|(null)|(true)|(false))/
|
|
8
|
-
const match = groupMatch(regex, "'foo'")
|
|
9
|
-
expect(parseLiteralValue(match, 2)).toBe('foo')
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
test('extracts a number', () => {
|
|
13
|
-
const regex = /(["'](.*)['"]|([0-9]+)|(\[.*])|(null)|(true)|(false))/
|
|
14
|
-
const match = groupMatch(regex, '42')
|
|
15
|
-
expect(parseLiteralValue(match, 2)).toBe(42)
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
test('extracts an array', () => {
|
|
19
|
-
const regex = /(["'](.*)['"]|([0-9]+)|(\[.*])|(null)|(true)|(false))/
|
|
20
|
-
const match = groupMatch(regex, '[1,2,3]')
|
|
21
|
-
expect(parseLiteralValue(match, 2)).toEqual([1, 2, 3])
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
test('extracts null', () => {
|
|
25
|
-
const regex = /(["'](.*)['"]|([0-9]+)|(\[.*])|(null)|(true)|(false))/
|
|
26
|
-
const match = groupMatch(regex, 'null')
|
|
27
|
-
expect(parseLiteralValue(match, 2)).toBeNull()
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
test('extracts true/false', () => {
|
|
31
|
-
const regex = /(["'](.*)['"]|([0-9]+)|(\[.*])|(null)|(true)|(false))/
|
|
32
|
-
expect(parseLiteralValue(groupMatch(regex, 'true'), 2)).toBe(true)
|
|
33
|
-
expect(parseLiteralValue(groupMatch(regex, 'false'), 2)).toBe(false)
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
test('honors a different baseIndex for a differently-shaped parent regex', () => {
|
|
37
|
-
const regex = /([a-z]+)\s*=\s*(["'](.*)['"]|([0-9]+)|(\[.*])|(null)|(true)|(false))/
|
|
38
|
-
const match = groupMatch(regex, 'reps=10')
|
|
39
|
-
expect(parseLiteralValue(match, 3)).toBe(10)
|
|
40
|
-
})
|
|
41
|
-
})
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
export type LiteralValue = string | number | boolean | null | any[]
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Several parsers (findConditions, findInsertValues, findUpdateValues) capture a query-string
|
|
5
|
-
* literal into one of six consecutive alternation groups depending on its shape - quoted string,
|
|
6
|
-
* number, array, null, true, false - since a single regex can't otherwise tell them apart. Given
|
|
7
|
-
* the match and the index of the first of those six groups (which shifts depending on how many
|
|
8
|
-
* groups come before it in the parent regex), return the literal with its real JS type.
|
|
9
|
-
* @param match
|
|
10
|
-
* @param baseIndex
|
|
11
|
-
*/
|
|
12
|
-
export const parseLiteralValue = (match: RegExpMatchArray, baseIndex: number): LiteralValue => {
|
|
13
|
-
if (typeof match[baseIndex] !== 'undefined') {
|
|
14
|
-
return match[baseIndex]
|
|
15
|
-
}
|
|
16
|
-
if (typeof match[baseIndex + 1] !== 'undefined') {
|
|
17
|
-
return Number(match[baseIndex + 1])
|
|
18
|
-
}
|
|
19
|
-
if (typeof match[baseIndex + 2] !== 'undefined') {
|
|
20
|
-
return JSON.parse(match[baseIndex + 2])
|
|
21
|
-
}
|
|
22
|
-
if (typeof match[baseIndex + 3] !== 'undefined') {
|
|
23
|
-
return null
|
|
24
|
-
}
|
|
25
|
-
if (typeof match[baseIndex + 4] !== 'undefined') {
|
|
26
|
-
return true
|
|
27
|
-
}
|
|
28
|
-
return false
|
|
29
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import siFunciona from 'si-funciona'
|
|
2
|
-
import { findCommand, ParsedCommand, ParsedEntity } from './findCommand'
|
|
3
|
-
import { findInsertValues, ParsedInsertRow } from './findInsertValues'
|
|
4
|
-
import { findUpdateValues, ParsedUpdateValues } from './findUpdateValues'
|
|
5
|
-
import { findJoinEntity, ParsedJoinEntity } from './findJoinEntity'
|
|
6
|
-
import { findSelects, ParsedSelect } from './findSelects'
|
|
7
|
-
import { findConditions, ParsedCondition } from './findConditions'
|
|
8
|
-
import { findJoinClauses, ParsedJoinClause } from './findJoinClauses'
|
|
9
|
-
import { findMergeJoins, ParsedMergeJoin } from './findMergeJoins'
|
|
10
|
-
import { findSortClauses, ParsedSortClause } from './findSortClauses'
|
|
11
|
-
import { findGroupBy, ParsedGroupBy } from './findGroupBy'
|
|
12
|
-
import { findLimit, ParsedLimit } from './findLimit'
|
|
13
|
-
import { findOffset, ParsedOffset } from './findOffset'
|
|
14
|
-
|
|
15
|
-
export type ParsedQuery = {
|
|
16
|
-
command: ParsedCommand | undefined
|
|
17
|
-
entity: ParsedEntity | undefined
|
|
18
|
-
joinEntity: ParsedJoinEntity | undefined
|
|
19
|
-
selectClauses: ParsedSelect[]
|
|
20
|
-
insertValues: ParsedInsertRow[]
|
|
21
|
-
updateValues: ParsedUpdateValues
|
|
22
|
-
conditions: ParsedCondition[]
|
|
23
|
-
joinClauses: ParsedJoinClause[]
|
|
24
|
-
mergeJoins: ParsedMergeJoin[]
|
|
25
|
-
sortClauses: ParsedSortClause[]
|
|
26
|
-
groupBy: ParsedGroupBy | undefined
|
|
27
|
-
limit: ParsedLimit | undefined
|
|
28
|
-
offset: ParsedOffset | undefined
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Break a query down into its components.
|
|
33
|
-
* @param query
|
|
34
|
-
*/
|
|
35
|
-
export const parseQuery = (query: string): ParsedQuery => {
|
|
36
|
-
let parsedQuery: ParsedQuery = {
|
|
37
|
-
command: undefined,
|
|
38
|
-
entity: undefined,
|
|
39
|
-
joinEntity: undefined,
|
|
40
|
-
selectClauses: [],
|
|
41
|
-
insertValues: [],
|
|
42
|
-
updateValues: {},
|
|
43
|
-
conditions: [],
|
|
44
|
-
joinClauses: [],
|
|
45
|
-
mergeJoins: [],
|
|
46
|
-
sortClauses: [],
|
|
47
|
-
groupBy: undefined,
|
|
48
|
-
limit: undefined,
|
|
49
|
-
offset: undefined,
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const { curry, pipe } = siFunciona
|
|
53
|
-
|
|
54
|
-
query = pipe(
|
|
55
|
-
curry(findCommand)(parsedQuery),
|
|
56
|
-
curry(findInsertValues)(parsedQuery),
|
|
57
|
-
curry(findUpdateValues)(parsedQuery),
|
|
58
|
-
curry(findJoinEntity)(parsedQuery),
|
|
59
|
-
curry(findSelects)(parsedQuery),
|
|
60
|
-
curry(findConditions)(parsedQuery),
|
|
61
|
-
curry(findJoinClauses)(parsedQuery),
|
|
62
|
-
curry(findMergeJoins)(parsedQuery),
|
|
63
|
-
curry(findSortClauses)(parsedQuery),
|
|
64
|
-
curry(findGroupBy)(parsedQuery),
|
|
65
|
-
curry(findLimit)(parsedQuery),
|
|
66
|
-
curry(findOffset)(parsedQuery)
|
|
67
|
-
)(query)
|
|
68
|
-
|
|
69
|
-
if (query) {
|
|
70
|
-
throw new Error(`Unrecognized query value: ${query}`)
|
|
71
|
-
}
|
|
72
|
-
return parsedQuery
|
|
73
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const removeFromQuery = (substring: string, query: string): string => query.replace(substring, '').trim()
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { splitEntityProperty } from './splitEntityProperty'
|
|
2
|
-
|
|
3
|
-
describe('splitEntityProperty', () => {
|
|
4
|
-
test('can parse entity property', () => {
|
|
5
|
-
const result = splitEntityProperty('workouts.exercise_id')
|
|
6
|
-
expect(result).toEqual({ entity: 'workouts', property: 'exercise_id' })
|
|
7
|
-
})
|
|
8
|
-
})
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
const entityMatch = /^[a-z0-9_-]+/i
|
|
2
|
-
const propertyMatch = /\.([a-z0-9_-]+)$/i
|
|
3
|
-
|
|
4
|
-
export const splitEntityProperty = entityProp => {
|
|
5
|
-
const entityFound = entityProp.match(entityMatch)
|
|
6
|
-
if (!entityFound) {
|
|
7
|
-
throw new Error(`Unable to use property: ${entityProp}`)
|
|
8
|
-
}
|
|
9
|
-
const propFound = entityProp.match(propertyMatch)
|
|
10
|
-
if (!propFound) {
|
|
11
|
-
throw new Error(`Unable to use property: ${entityProp}`)
|
|
12
|
-
}
|
|
13
|
-
return {
|
|
14
|
-
entity: entityFound[0],
|
|
15
|
-
property: propFound[1]
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { splitQueries } from './splitQueries'
|
|
2
|
-
|
|
3
|
-
const sampleQueries = [
|
|
4
|
-
'read workouts where date = \'2024-06-02\'',
|
|
5
|
-
'read workouts.muscles'
|
|
6
|
-
+ ' on workouts.exercise_id = exercises._id'
|
|
7
|
-
+ ' and on exercises._id = exercise_muscle.exercise_id'
|
|
8
|
-
+ ' and on exercise_muscle.muscle_id = muscles._id'
|
|
9
|
-
+ ' where muscles.alias = \'chest\'',
|
|
10
|
-
'read workouts.muscles'
|
|
11
|
-
+ ' on workouts.exercise_id = exercises._id'
|
|
12
|
-
+ ' and on exercises._id = exercise_muscle.exercise_id'
|
|
13
|
-
+ ' and on exercise_muscle.muscle_id = muscles._id'
|
|
14
|
-
+ ' merge workouts.exercise_id with exercises._id'
|
|
15
|
-
+ ' merge exercise_muscle.muscle_id with muscles._id'
|
|
16
|
-
+ ' where muscles.alias = \'chest\'',
|
|
17
|
-
'read workouts sort date desc, order',
|
|
18
|
-
'read workouts group by date',
|
|
19
|
-
'read workouts.exercises'
|
|
20
|
-
+ ' select exercises.name as exercise, workouts.sets as sets, reps'
|
|
21
|
-
+ ' on workouts.exercise_id = exercises._id'
|
|
22
|
-
+ ' merge workouts.exercise_id with exercises._id'
|
|
23
|
-
+ ' limit 2'
|
|
24
|
-
+ ' offset 1'
|
|
25
|
-
]
|
|
26
|
-
|
|
27
|
-
describe('splitQueries', () => {
|
|
28
|
-
test('can identify all queries', () => {
|
|
29
|
-
const queries = sampleQueries.reduce((concatQueries, query) => concatQueries = `${concatQueries} ${query}`, '')
|
|
30
|
-
const result = splitQueries(queries)
|
|
31
|
-
expect(result).toEqual(sampleQueries)
|
|
32
|
-
})
|
|
33
|
-
})
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { reconcileJoin } from './reconcileJoin'
|
|
2
|
-
|
|
3
|
-
describe('reconcileJoin', () => {
|
|
4
|
-
test('will apply found join with changes', () => {
|
|
5
|
-
const dataSet = {
|
|
6
|
-
workouts: [
|
|
7
|
-
{
|
|
8
|
-
_id: 1,
|
|
9
|
-
exercise_id: 1,
|
|
10
|
-
weight_effort: '115lbs',
|
|
11
|
-
reps: 10,
|
|
12
|
-
sets: 3,
|
|
13
|
-
note: '',
|
|
14
|
-
date: '2024-06-02',
|
|
15
|
-
muscles: [{ _id: 11, name: 'Pectorals', alias: 'chest', image: '' }]
|
|
16
|
-
}
|
|
17
|
-
],
|
|
18
|
-
muscles: [
|
|
19
|
-
{
|
|
20
|
-
_id: 11,
|
|
21
|
-
name: 'Pectorals',
|
|
22
|
-
alias: 'chest',
|
|
23
|
-
image: '',
|
|
24
|
-
'exercise_muscle._id': 1,
|
|
25
|
-
'exercise_muscle.exercise_id': 1,
|
|
26
|
-
'exercise_muscle.muscle_rank': 100
|
|
27
|
-
},
|
|
28
|
-
{ _id: 14, name: 'Triceps', alias: '', image: '' }
|
|
29
|
-
]
|
|
30
|
-
}
|
|
31
|
-
const entity = 'workouts'
|
|
32
|
-
const index = 0
|
|
33
|
-
const joinEntity = 'muscles'
|
|
34
|
-
const joinProperty = '_id'
|
|
35
|
-
const result = reconcileJoin(dataSet, entity, index, joinEntity, joinProperty)
|
|
36
|
-
expect(result[entity][index][joinEntity][0]).toEqual(dataSet[joinEntity][0])
|
|
37
|
-
})
|
|
38
|
-
})
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { where } from '../queries/where'
|
|
2
|
-
|
|
3
|
-
export const reconcileJoin = (dataSet, entityName, entityKey, joinEntity, joinProp) => {
|
|
4
|
-
const entity = dataSet[entityName][entityKey]
|
|
5
|
-
if (entity.hasOwnProperty(joinEntity) && Array.isArray(entity[joinEntity])) {
|
|
6
|
-
entity[joinEntity].forEach(
|
|
7
|
-
(mergedEntity, k) => {
|
|
8
|
-
const matchedEntity = where(
|
|
9
|
-
dataSet[joinEntity],
|
|
10
|
-
{
|
|
11
|
-
property: joinProp,
|
|
12
|
-
comparator: '=',
|
|
13
|
-
value: mergedEntity[joinProp]
|
|
14
|
-
}
|
|
15
|
-
)
|
|
16
|
-
if (matchedEntity.length) {
|
|
17
|
-
dataSet[entityName][entityKey][joinEntity][k] = matchedEntity[0]
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
)
|
|
21
|
-
}
|
|
22
|
-
return dataSet
|
|
23
|
-
}
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
import { reconcileJoins } from './reconcileJoins'
|
|
2
|
-
|
|
3
|
-
describe('reconcileJoins', () => {
|
|
4
|
-
test('reconciles several joins', () => {
|
|
5
|
-
const propertyA = 'muscles._id'
|
|
6
|
-
const propertyB = 'exercise_muscle.muscle_id'
|
|
7
|
-
const dataSet = {
|
|
8
|
-
workouts: [
|
|
9
|
-
{
|
|
10
|
-
_id: 1,
|
|
11
|
-
exercise_id: 1,
|
|
12
|
-
weight_effort: '115lbs',
|
|
13
|
-
reps: 10,
|
|
14
|
-
sets: 3,
|
|
15
|
-
note: '',
|
|
16
|
-
date: '2024-06-02',
|
|
17
|
-
muscles: [{ _id: 11, name: 'Pectorals', alias: 'chest', image: '' }]
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
_id: 2,
|
|
21
|
-
exercise_id: 2,
|
|
22
|
-
weight_effort: '155lbs',
|
|
23
|
-
reps: 10,
|
|
24
|
-
sets: 3,
|
|
25
|
-
note: '',
|
|
26
|
-
date: '2024-06-02',
|
|
27
|
-
muscles: [{ _id: 8, name: 'Hamstrings', alias: 'abs', image: '' }]
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
_id: 3,
|
|
31
|
-
exercise_id: 3,
|
|
32
|
-
weight_effort: '155lbs',
|
|
33
|
-
reps: 10,
|
|
34
|
-
sets: 3,
|
|
35
|
-
note: '',
|
|
36
|
-
date: '2024-06-02',
|
|
37
|
-
muscles: [{ _id: 12, name: 'Quadriceps', alias: 'quads', image: '' }]
|
|
38
|
-
}
|
|
39
|
-
],
|
|
40
|
-
muscles: [
|
|
41
|
-
{
|
|
42
|
-
_id: 1,
|
|
43
|
-
name: 'Abdominal',
|
|
44
|
-
alias: 'abs',
|
|
45
|
-
image: '../img/abdominals.jpg'
|
|
46
|
-
},
|
|
47
|
-
{ _id: 2, name: 'Biceps', alias: '', image: '' },
|
|
48
|
-
{ _id: 3, name: 'Calves', alias: '', image: '' },
|
|
49
|
-
{ _id: 4, name: 'Deltoids', alias: 'shoulders', image: '' },
|
|
50
|
-
{
|
|
51
|
-
_id: 5,
|
|
52
|
-
name: 'Erector Spinae',
|
|
53
|
-
alias: 'mid back, along spine',
|
|
54
|
-
image: ''
|
|
55
|
-
},
|
|
56
|
-
{ _id: 6, name: 'Forearms', alias: 'abs', image: '' },
|
|
57
|
-
{ _id: 7, name: 'Gluteus Maximus', alias: 'abs', image: '' },
|
|
58
|
-
{
|
|
59
|
-
_id: 8,
|
|
60
|
-
name: 'Hamstrings',
|
|
61
|
-
alias: 'abs',
|
|
62
|
-
image: '',
|
|
63
|
-
'exercise_muscle._id': 2,
|
|
64
|
-
'exercise_muscle.exercise_id': 2,
|
|
65
|
-
'exercise_muscle.muscle_rank': 100
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
_id: 9,
|
|
69
|
-
name: 'Latissimus Dorsi',
|
|
70
|
-
alias: 'outer lower back',
|
|
71
|
-
image: ''
|
|
72
|
-
},
|
|
73
|
-
{ _id: 10, name: 'Obliques', alias: 'outer abs', image: '' },
|
|
74
|
-
{
|
|
75
|
-
_id: 11,
|
|
76
|
-
name: 'Pectorals',
|
|
77
|
-
alias: 'chest',
|
|
78
|
-
image: '',
|
|
79
|
-
'exercise_muscle._id': 1,
|
|
80
|
-
'exercise_muscle.exercise_id': 1,
|
|
81
|
-
'exercise_muscle.muscle_rank': 100
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
_id: 12,
|
|
85
|
-
name: 'Quadriceps',
|
|
86
|
-
alias: 'quads',
|
|
87
|
-
image: '',
|
|
88
|
-
'exercise_muscle._id': 3,
|
|
89
|
-
'exercise_muscle.exercise_id': 3,
|
|
90
|
-
'exercise_muscle.muscle_rank': 100
|
|
91
|
-
},
|
|
92
|
-
{ _id: 13, name: 'Trapezius', alias: 'upper back', image: '' },
|
|
93
|
-
{ _id: 14, name: 'Triceps', alias: '', image: '' }
|
|
94
|
-
]
|
|
95
|
-
}
|
|
96
|
-
const result = reconcileJoins(propertyA, propertyB, dataSet)
|
|
97
|
-
expect(result['workouts']).toEqual([
|
|
98
|
-
{
|
|
99
|
-
_id: 1,
|
|
100
|
-
exercise_id: 1,
|
|
101
|
-
weight_effort: '115lbs',
|
|
102
|
-
reps: 10,
|
|
103
|
-
sets: 3,
|
|
104
|
-
note: '',
|
|
105
|
-
date: '2024-06-02',
|
|
106
|
-
muscles: [
|
|
107
|
-
{
|
|
108
|
-
_id: 11,
|
|
109
|
-
name: 'Pectorals',
|
|
110
|
-
alias: 'chest',
|
|
111
|
-
image: '',
|
|
112
|
-
'exercise_muscle._id': 1,
|
|
113
|
-
'exercise_muscle.exercise_id': 1,
|
|
114
|
-
'exercise_muscle.muscle_rank': 100
|
|
115
|
-
}
|
|
116
|
-
]
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
_id: 2,
|
|
120
|
-
exercise_id: 2,
|
|
121
|
-
weight_effort: '155lbs',
|
|
122
|
-
reps: 10,
|
|
123
|
-
sets: 3,
|
|
124
|
-
note: '',
|
|
125
|
-
date: '2024-06-02',
|
|
126
|
-
muscles: [
|
|
127
|
-
{
|
|
128
|
-
_id: 8,
|
|
129
|
-
name: 'Hamstrings',
|
|
130
|
-
alias: 'abs',
|
|
131
|
-
image: '',
|
|
132
|
-
'exercise_muscle._id': 2,
|
|
133
|
-
'exercise_muscle.exercise_id': 2,
|
|
134
|
-
'exercise_muscle.muscle_rank': 100
|
|
135
|
-
}
|
|
136
|
-
]
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
_id: 3,
|
|
140
|
-
exercise_id: 3,
|
|
141
|
-
weight_effort: '155lbs',
|
|
142
|
-
reps: 10,
|
|
143
|
-
sets: 3,
|
|
144
|
-
note: '',
|
|
145
|
-
date: '2024-06-02',
|
|
146
|
-
muscles: [
|
|
147
|
-
{
|
|
148
|
-
_id: 12,
|
|
149
|
-
name: 'Quadriceps',
|
|
150
|
-
alias: 'quads',
|
|
151
|
-
image: '',
|
|
152
|
-
'exercise_muscle._id': 3,
|
|
153
|
-
'exercise_muscle.exercise_id': 3,
|
|
154
|
-
'exercise_muscle.muscle_rank': 100
|
|
155
|
-
}
|
|
156
|
-
]
|
|
157
|
-
}
|
|
158
|
-
])
|
|
159
|
-
})
|
|
160
|
-
})
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { splitEntityProperty } from './parsers/splitEntityProperty'
|
|
2
|
-
import { reconcileJoin } from './reconcileJoin'
|
|
3
|
-
|
|
4
|
-
export const reconcileJoins = (propertyA, propertyB, dataSet) => {
|
|
5
|
-
const { entity: entityA, property: propA } = splitEntityProperty(propertyA)
|
|
6
|
-
const { entity: entityB, property: propB } = splitEntityProperty(propertyB)
|
|
7
|
-
for (let entityName in dataSet) {
|
|
8
|
-
for (let entityKey in dataSet[entityName]) {
|
|
9
|
-
const entity = dataSet[entityName][entityKey]
|
|
10
|
-
dataSet = reconcileJoin(dataSet, entityName, entityKey, entityA, propA)
|
|
11
|
-
dataSet = reconcileJoin(dataSet, entityName, entityKey, entityB, propB)
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
return dataSet
|
|
15
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { registerRecord } from './registerRecord'
|
|
2
|
-
import { testHelpers } from 'js-build-tools/testHelpers'
|
|
3
|
-
|
|
4
|
-
const { readFile } = require('fs/promises')
|
|
5
|
-
|
|
6
|
-
const databasePath = 'register-record-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
|
-
describe('registerRecord', () => {
|
|
16
|
-
test('creates a fresh registry the first time a record is registered', async () => {
|
|
17
|
-
const result = await registerRecord('foo')
|
|
18
|
-
expect(result).toEqual({
|
|
19
|
-
path: '',
|
|
20
|
-
definition: [
|
|
21
|
-
{ name: 'path', type: 'string', optional: false, autoGenerate: false },
|
|
22
|
-
{ name: 'definition', type: 'object', optional: false, autoGenerate: false },
|
|
23
|
-
{ name: 'keys', type: 'array', optional: false, autoGenerate: false },
|
|
24
|
-
{ name: 'entries', type: 'array', optional: false, autoGenerate: false }
|
|
25
|
-
],
|
|
26
|
-
keys: [],
|
|
27
|
-
entries: ['foo.json']
|
|
28
|
-
})
|
|
29
|
-
const onDisk = JSON.parse(await readFile(`${databasePath}__RECORDS.json`, 'utf8'))
|
|
30
|
-
expect(onDisk).toEqual(result)
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
test('appends onto an existing registry without disturbing other entries', async () => {
|
|
34
|
-
await registerRecord('foo')
|
|
35
|
-
const result = await registerRecord('bar')
|
|
36
|
-
expect(result.entries).toEqual(['foo.json', 'bar.json'])
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
test('registering the same record twice does not duplicate its entry', async () => {
|
|
40
|
-
await registerRecord('foo')
|
|
41
|
-
const result = await registerRecord('foo')
|
|
42
|
-
expect(result.entries).toEqual(['foo.json'])
|
|
43
|
-
})
|
|
44
|
-
})
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { recordDefinition } from '../introspect/definitions/record'
|
|
2
|
-
|
|
3
|
-
const gulpConfig = require('js-build-tools/gulp.config')
|
|
4
|
-
const { readFile, writeFile } = require('fs/promises')
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* __RECORDS is itself an ordinary record - path/definition/keys/entries - whose entries are the
|
|
8
|
-
* filenames of every other record that has been created. This is the schema it's given the first
|
|
9
|
-
* time a record is registered and no __RECORDS.json exists yet, matching what a hand-authored
|
|
10
|
-
* database (see test-data/__RECORDS.json) already expects to find.
|
|
11
|
-
*/
|
|
12
|
-
const defaultRegistry = (): recordDefinition => ({
|
|
13
|
-
path: '',
|
|
14
|
-
definition: [
|
|
15
|
-
{ name: 'path', type: 'string', optional: false, autoGenerate: false },
|
|
16
|
-
{ name: 'definition', type: 'object', optional: false, autoGenerate: false },
|
|
17
|
-
{ name: 'keys', type: 'array', optional: false, autoGenerate: false },
|
|
18
|
-
{ name: 'entries', type: 'array', optional: false, autoGenerate: false }
|
|
19
|
-
],
|
|
20
|
-
keys: [],
|
|
21
|
-
entries: []
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Add a record's filename to the __RECORDS registry, creating the registry file the first time
|
|
26
|
-
* a record is created if it doesn't already exist.
|
|
27
|
-
* @param recordName
|
|
28
|
-
*/
|
|
29
|
-
export const registerRecord = async (recordName: string): Promise<recordDefinition> => {
|
|
30
|
-
const databasePath = gulpConfig.get('databasePath', 'database/')
|
|
31
|
-
const registryPath = `${databasePath}__RECORDS.json`
|
|
32
|
-
let registry: recordDefinition
|
|
33
|
-
try {
|
|
34
|
-
registry = JSON.parse(await readFile(registryPath, 'utf8'))
|
|
35
|
-
} catch (err) {
|
|
36
|
-
registry = defaultRegistry()
|
|
37
|
-
}
|
|
38
|
-
const fileName = `${recordName}.json`
|
|
39
|
-
if (!registry.entries.includes(fileName)) {
|
|
40
|
-
registry.entries.push(fileName)
|
|
41
|
-
}
|
|
42
|
-
await writeFile(registryPath, JSON.stringify(registry, null, 2))
|
|
43
|
-
return registry
|
|
44
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { updateIndex } from './updateIndex'
|
|
2
|
-
import { removeFromIndex } from './removeFromIndex'
|
|
3
|
-
import { testHelpers } from 'js-build-tools/testHelpers'
|
|
4
|
-
|
|
5
|
-
const { readFile } = require('fs/promises')
|
|
6
|
-
|
|
7
|
-
const databasePath = 'remove-from-index-database/'
|
|
8
|
-
const gulpConfig = testHelpers.gulpConfig
|
|
9
|
-
gulpConfig.set('databasePath', databasePath)
|
|
10
|
-
testHelpers.setDefaults(databasePath)
|
|
11
|
-
|
|
12
|
-
beforeEach(testHelpers.beforeEach)
|
|
13
|
-
|
|
14
|
-
afterEach(testHelpers.afterEach)
|
|
15
|
-
|
|
16
|
-
describe('removeFromIndex', () => {
|
|
17
|
-
test('does nothing for a key with no lookup', async () => {
|
|
18
|
-
const result = await removeFromIndex('foo', { type: 'multi', fields: ['a', 'b'], lookup: '' }, 'x', 'x.json')
|
|
19
|
-
expect(result).toBeNull()
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
test('does nothing when the index file does not exist yet', async () => {
|
|
23
|
-
const key = { type: 'primary', fields: ['_id'], lookup: 'pk__id.json' }
|
|
24
|
-
const result = await removeFromIndex('foo', key, 1, '1.json')
|
|
25
|
-
expect(result).toBeNull()
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
test('removes a file from its value, keeping other files on that value', async () => {
|
|
29
|
-
const key = { type: 'index', fields: ['date'], lookup: 'index_date.json' }
|
|
30
|
-
await updateIndex('foo', key, '2024-06-02', '1.json')
|
|
31
|
-
await updateIndex('foo', key, '2024-06-02', '2.json')
|
|
32
|
-
const result = await removeFromIndex('foo', key, '2024-06-02', '1.json')
|
|
33
|
-
expect(result).toEqual([{ value: '2024-06-02', record: ['2.json'] }])
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
test('drops the whole value once its last file is removed', async () => {
|
|
37
|
-
const key = { type: 'primary', fields: ['_id'], lookup: 'pk__id.json' }
|
|
38
|
-
await updateIndex('foo', key, 1, '1.json')
|
|
39
|
-
const result = await removeFromIndex('foo', key, 1, '1.json')
|
|
40
|
-
expect(result).toEqual([])
|
|
41
|
-
const onDisk = JSON.parse(await readFile(`${databasePath}__indexes/foo/pk__id.json`, 'utf8'))
|
|
42
|
-
expect(onDisk).toEqual([])
|
|
43
|
-
})
|
|
44
|
-
})
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { keyDefinition } from '../introspect/definitions/key'
|
|
2
|
-
import { recordPath } from '../introspect/definitions/record'
|
|
3
|
-
import { indexEntry } from './updateIndex'
|
|
4
|
-
|
|
5
|
-
const gulpConfig = require('js-build-tools/gulp.config')
|
|
6
|
-
const { readFile, writeFile } = require('fs/promises')
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Remove a single entry file from the index that backs one of a record's keys, dropping a value
|
|
10
|
-
* entirely once its last file is removed. A key with no lookup, or an index file that doesn't
|
|
11
|
-
* exist yet, is left untouched.
|
|
12
|
-
* @param path
|
|
13
|
-
* @param key
|
|
14
|
-
* @param value
|
|
15
|
-
* @param fileName
|
|
16
|
-
*/
|
|
17
|
-
export const removeFromIndex = async (path: recordPath = '', key: keyDefinition = null, value: any = undefined, fileName: string = ''): Promise<indexEntry[] | null> => {
|
|
18
|
-
if (!key || !key.lookup) {
|
|
19
|
-
return null
|
|
20
|
-
}
|
|
21
|
-
const databasePath = gulpConfig.get('databasePath', 'database/')
|
|
22
|
-
const indexPath = `${databasePath}__indexes/${path}/${key.lookup}`
|
|
23
|
-
let index: indexEntry[] = []
|
|
24
|
-
try {
|
|
25
|
-
index = JSON.parse(await readFile(indexPath, 'utf8'))
|
|
26
|
-
} catch (err) {
|
|
27
|
-
return null
|
|
28
|
-
}
|
|
29
|
-
index = index
|
|
30
|
-
.map(entry => entry.value == value ? { value: entry.value, record: entry.record.filter(record => record !== fileName) } : entry)
|
|
31
|
-
.filter(entry => entry.record.length)
|
|
32
|
-
await writeFile(indexPath, JSON.stringify(index, null, 2))
|
|
33
|
-
return index
|
|
34
|
-
}
|