json-fs-query 1.0.6 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/LICENSE +674 -674
  2. package/README.md +295 -98
  3. package/browser/jsonFsQuery.js +12733 -10777
  4. package/browser/jsonFsQuery.min.js +1 -1
  5. package/dist/data/introspect/create.d.ts +1 -1
  6. package/dist/data/introspect/create.js +35 -4
  7. package/dist/data/introspect/create.min.js +1 -1
  8. package/dist/data/introspect/definitions/field.d.ts +6 -2
  9. package/dist/data/introspect/definitions/field.js +7 -1
  10. package/dist/data/introspect/definitions/field.min.js +1 -1
  11. package/dist/data/introspect/index.d.ts +6 -3
  12. package/dist/data/introspect/index.js +10 -19
  13. package/dist/data/introspect/index.min.js +1 -1
  14. package/dist/data/introspect/policies/foreignKeyExists.js +5 -1
  15. package/dist/data/introspect/policies/foreignKeyExists.min.js +1 -1
  16. package/dist/data/introspect/policies/hasDependents.js +3 -1
  17. package/dist/data/introspect/policies/hasDependents.min.js +1 -1
  18. package/dist/data/introspect/policies/keyUnique.js +5 -1
  19. package/dist/data/introspect/policies/keyUnique.min.js +1 -1
  20. package/dist/data/introspect/policies/typeCheck.d.ts +9 -1
  21. package/dist/data/introspect/policies/typeCheck.js +16 -2
  22. package/dist/data/introspect/policies/typeCheck.min.js +1 -1
  23. package/dist/data/queries/createRecord.d.ts +11 -0
  24. package/dist/data/queries/createRecord.js +58 -0
  25. package/dist/data/queries/createRecord.min.js +1 -0
  26. package/dist/data/queries/deleteEntity.js +2 -1
  27. package/dist/data/queries/deleteEntity.min.js +1 -1
  28. package/dist/data/queries/describeRecord.d.ts +9 -0
  29. package/dist/data/queries/describeRecord.js +29 -0
  30. package/dist/data/queries/describeRecord.min.js +1 -0
  31. package/dist/data/queries/dropRecord.d.ts +9 -0
  32. package/dist/data/queries/dropRecord.js +61 -0
  33. package/dist/data/queries/dropRecord.min.js +1 -0
  34. package/dist/data/queries/insertEntity.js +11 -5
  35. package/dist/data/queries/insertEntity.min.js +1 -1
  36. package/dist/data/queries/parser.d.ts +1 -1
  37. package/dist/data/queries/parser.js +7 -15
  38. package/dist/data/queries/parser.min.js +1 -1
  39. package/dist/data/queries/query.d.ts +6 -0
  40. package/dist/data/queries/query.js +15 -6
  41. package/dist/data/queries/query.min.js +1 -1
  42. package/dist/data/queries/queryStatus.d.ts +15 -0
  43. package/dist/data/queries/queryStatus.js +52 -0
  44. package/dist/data/queries/queryStatus.min.js +1 -0
  45. package/dist/data/queries/quote.d.ts +11 -0
  46. package/dist/data/queries/quote.js +17 -0
  47. package/dist/data/queries/quote.min.js +1 -0
  48. package/dist/data/queries/showRecords.d.ts +6 -0
  49. package/dist/data/queries/showRecords.js +21 -0
  50. package/dist/data/queries/showRecords.min.js +1 -0
  51. package/dist/data/queries/sortBy.js +3 -0
  52. package/dist/data/queries/updateEntity.js +74 -18
  53. package/dist/data/queries/updateEntity.min.js +1 -1
  54. package/dist/data/queries/where.d.ts +2 -1
  55. package/dist/data/queries/where.js +18 -6
  56. package/dist/data/queries/where.min.js +1 -1
  57. package/dist/data/utilities/compareAs.d.ts +20 -0
  58. package/dist/data/utilities/compareAs.js +58 -0
  59. package/dist/data/utilities/compareAs.min.js +1 -0
  60. package/dist/data/utilities/config.d.ts +15 -0
  61. package/dist/data/utilities/config.js +31 -1
  62. package/dist/data/utilities/config.min.js +1 -1
  63. package/dist/data/utilities/databaseLock.d.ts +16 -0
  64. package/dist/data/utilities/databaseLock.js +63 -0
  65. package/dist/data/utilities/databaseLock.min.js +1 -0
  66. package/dist/data/utilities/fieldType.d.ts +16 -0
  67. package/dist/data/utilities/fieldType.js +23 -0
  68. package/dist/data/utilities/fieldType.min.js +1 -0
  69. package/dist/data/utilities/getConditionIndexedList.js +2 -1
  70. package/dist/data/utilities/getConditionIndexedList.min.js +1 -1
  71. package/dist/data/utilities/matchIndexedJoins.js +3 -1
  72. package/dist/data/utilities/matchIndexedJoins.min.js +1 -1
  73. package/dist/data/utilities/mergeJoin.js +5 -1
  74. package/dist/data/utilities/mergeJoin.min.js +1 -1
  75. package/dist/data/utilities/parsers/findConditions.d.ts +5 -1
  76. package/dist/data/utilities/parsers/findConditions.js +15 -6
  77. package/dist/data/utilities/parsers/findConditions.min.js +1 -1
  78. package/dist/data/utilities/parsers/findInsertValues.js +3 -2
  79. package/dist/data/utilities/parsers/findInsertValues.min.js +1 -1
  80. package/dist/data/utilities/parsers/findSelects.js +6 -3
  81. package/dist/data/utilities/parsers/findSelects.min.js +1 -1
  82. package/dist/data/utilities/parsers/findSortClauses.js +5 -2
  83. package/dist/data/utilities/parsers/findSortClauses.min.js +1 -1
  84. package/dist/data/utilities/parsers/findUpdateValues.js +3 -2
  85. package/dist/data/utilities/parsers/findUpdateValues.min.js +1 -1
  86. package/dist/data/utilities/parsers/maskStrings.d.ts +39 -0
  87. package/dist/data/utilities/parsers/maskStrings.js +123 -0
  88. package/dist/data/utilities/parsers/maskStrings.min.js +1 -0
  89. package/dist/data/utilities/parsers/parseCreate.d.ts +20 -0
  90. package/dist/data/utilities/parsers/parseCreate.js +330 -0
  91. package/dist/data/utilities/parsers/parseCreate.min.js +1 -0
  92. package/dist/data/utilities/parsers/parseLiteralValue.d.ts +2 -1
  93. package/dist/data/utilities/parsers/parseLiteralValue.js +6 -3
  94. package/dist/data/utilities/parsers/parseLiteralValue.min.js +1 -1
  95. package/dist/data/utilities/parsers/parseQuery.d.ts +3 -0
  96. package/dist/data/utilities/parsers/parseQuery.js +28 -2
  97. package/dist/data/utilities/parsers/parseQuery.min.js +1 -1
  98. package/dist/data/utilities/parsers/parseSchemaStatement.d.ts +13 -0
  99. package/dist/data/utilities/parsers/parseSchemaStatement.js +82 -0
  100. package/dist/data/utilities/parsers/parseSchemaStatement.min.js +1 -0
  101. package/dist/data/utilities/parsers/scanQuery.d.ts +52 -0
  102. package/dist/data/utilities/parsers/scanQuery.js +158 -0
  103. package/dist/data/utilities/parsers/scanQuery.min.js +1 -0
  104. package/dist/data/utilities/parsers/splitQueries.d.ts +6 -0
  105. package/dist/data/utilities/parsers/splitQueries.js +20 -2
  106. package/dist/data/utilities/parsers/splitQueries.min.js +1 -1
  107. package/dist/data/utilities/parsers/startsQuery.d.ts +5 -0
  108. package/dist/data/utilities/parsers/startsQuery.js +10 -0
  109. package/dist/data/utilities/parsers/startsQuery.min.js +1 -0
  110. package/dist/data/utilities/recordExists.d.ts +6 -0
  111. package/dist/data/utilities/recordExists.js +18 -0
  112. package/dist/data/utilities/recordExists.min.js +1 -0
  113. package/dist/data/utilities/removeFromIndex.d.ts +2 -1
  114. package/dist/data/utilities/removeFromIndex.js +4 -2
  115. package/dist/data/utilities/removeFromIndex.min.js +1 -1
  116. package/dist/data/utilities/runQuery.js +49 -0
  117. package/dist/data/utilities/runQuery.min.js +1 -1
  118. package/dist/data/utilities/updateIndex.d.ts +2 -1
  119. package/dist/data/utilities/updateIndex.js +4 -2
  120. package/dist/data/utilities/updateIndex.min.js +1 -1
  121. package/dist/data/utilities/useJoinClause.js +8 -2
  122. package/dist/data/utilities/useJoinClause.min.js +1 -1
  123. package/dist/index.d.ts +2 -0
  124. package/dist/index.js +14 -0
  125. package/dist/index.min.js +1 -1
  126. package/package.json +68 -55
package/README.md CHANGED
@@ -1,98 +1,295 @@
1
- # json-fs-query
2
-
3
- Read and manage data with JSON files - a small query engine that treats a folder of JSON files as a database, with
4
- a SQL-like query string (`read workouts where date = '2024-06-02'`) instead of a query builder API.
5
-
6
- The core engine (schema management, a full read/insert/update/delete query language, single- and multi-field key
7
- support, and referential integrity) is implemented and tested. Still open, tracked for whenever they're actually
8
- needed: multi-field *foreign* keys specifically (single-field ones work; composite primary/unique/index keys work
9
- too), and CASCADE/SET NULL modes for referential integrity (deleting/updating a referenced record is RESTRICTed -
10
- blocked outright - rather than cascading or nulling out the dependents; see `configure()` below to turn that
11
- enforcement off entirely if it doesn't fit your workflow).
12
-
13
- ## Install
14
-
15
- ```shell
16
- npm install json-fs-query
17
- ```
18
-
19
- ## Usage
20
-
21
- ```js
22
- const { create, query, drop } = require('json-fs-query')
23
-
24
- await create('workouts', [
25
- { name: '_id', type: 'string', optional: false, autoGenerate: true },
26
- { name: 'reps', type: 'int', optional: false },
27
- { name: 'date', type: 'string', optional: false }
28
- ], [
29
- { type: 'primary', fields: ['_id'], lookup: 'pk__id.json' }
30
- ])
31
-
32
- await query("insert workouts values reps = 10, date = '2024-06-02'")
33
- const rows = await query("read workouts where date = '2024-06-02'")
34
- await query("update workouts set reps = 12 where date = '2024-06-02'")
35
- await query("delete workouts where date = '2024-06-02'")
36
-
37
- await drop('workouts')
38
- ```
39
-
40
- ## Configuration
41
-
42
- `configure()` sets where this package's data lives and how strictly it enforces foreign keys - call it once,
43
- before anything else:
44
-
45
- ```js
46
- const { configure } = require('json-fs-query')
47
-
48
- configure({
49
- databasePath: 'database/', // where the JSON files live (default 'database/')
50
- relativePath: '', // URL prefix prepended to databasePath when reading via fetch() in a browser
51
- enforceForeignKeys: true // RESTRICT delete/update of a record other entities still reference (default true)
52
- })
53
- ```
54
-
55
- Turning `enforceForeignKeys` off restores the pre-1.0 behavior (no referential integrity checks at all) - useful if
56
- it doesn't fit a particular workflow, mirroring MySQL's own toggleable `foreign_key_checks`.
57
-
58
- ## In the browser
59
-
60
- A pre-built bundle is included (`browser/jsonFsQuery.js`, `.min.js` - also served directly via
61
- [unpkg](https://unpkg.com/json-fs-query) or [jsDelivr](https://cdn.jsdelivr.net/npm/json-fs-query)) and exposes the
62
- same functions as a global:
63
-
64
- ```html
65
- <script src="https://unpkg.com/json-fs-query"></script>
66
- <script>
67
- jsonFsQuery.configure({ databasePath: 'database/', relativePath: 'https://example.com/' })
68
- jsonFsQuery.query("read workouts where date = '2024-06-02'").then(console.log)
69
- </script>
70
- ```
71
-
72
- Reads work in the browser via `fetch()` - `create`/`drop`, and any write through `query()` (`insert`/`update`/
73
- `delete`), need real filesystem access and only work in Node. They're still present in the browser build (same
74
- public API either way), but throw if actually called there, rather than being silently unavailable.
75
-
76
- ## Documentation
77
-
78
- The reference for every function is in [`docs/`](https://joshuaheagle.com/projects/json-file-db/docs/index.html) (or open `docs/index.html` locally). It is generated from the TypeScript source, and each module is a folder of `src/data/`:
79
-
80
- | Module | What it holds |
81
- | --- | --- |
82
- | `introspect` | Create, drop and describe a JSON-file "table" (and the policies that validate one) |
83
- | `queries` | Parse a query string and run it - reads, inserts, updates, deletes, joins, `where`, `sortBy`, `groupBy` |
84
- | `utilities` | Shared helpers the queries use - retrieving records/files/indexes and merging join results |
85
-
86
- `src/index.ts` is the package's public entry point - it re-exports `query`, `create`, `drop`, `describe`, and the
87
- schema-definition types (`fieldProperties`, `keyProperties`, etc.) needed to build a `create()` call. Everything else
88
- under `src/data/` is an internal module, reachable but not part of the supported public API.
89
-
90
- ## Development
91
-
92
- ```shell
93
- npm install
94
- npm test # the tests
95
- npm run typecheck # the types
96
- npm run build # dist/ and docs/
97
- npm run docs # only the documentation
98
- ```
1
+ # json-fs-query
2
+
3
+ Read and manage data with JSON files - a small query engine that treats a folder of JSON files as a database, with
4
+ a SQL-like query string (`read workouts where date = '2024-06-02'`) instead of a query builder API.
5
+
6
+ The core engine (schema management, a full read/insert/update/delete query language, single- and multi-field key
7
+ support, and referential integrity) is implemented and tested. Still open, tracked for whenever they're actually
8
+ needed: multi-field *foreign* keys specifically (single-field ones work; composite primary/unique/index keys work
9
+ too), and CASCADE/SET NULL modes for referential integrity (deleting/updating a referenced record is RESTRICTed -
10
+ blocked outright - rather than cascading or nulling out the dependents; see `configure()` below to turn that
11
+ enforcement off entirely if it doesn't fit your workflow).
12
+
13
+ ## Install
14
+
15
+ ```shell
16
+ npm install json-fs-query
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ```js
22
+ const { create, query, drop } = require('json-fs-query')
23
+
24
+ await create('workouts', [
25
+ { name: '_id', type: 'string', optional: false, autoGenerate: true },
26
+ { name: 'reps', type: 'int', optional: false },
27
+ { name: 'date', type: 'string', optional: false }
28
+ ], [
29
+ { type: 'primary', fields: ['_id'], lookup: 'pk__id.json' }
30
+ ])
31
+
32
+ await query("insert workouts values reps = 10, date = '2024-06-02'")
33
+ const rows = await query("read workouts where date = '2024-06-02'")
34
+ await query("update workouts set reps = 12 where date = '2024-06-02'")
35
+ await query("delete workouts where date = '2024-06-02'")
36
+
37
+ await drop('workouts')
38
+ ```
39
+
40
+ ### Fields: `optional`, `nullable` and defaults
41
+
42
+ A field is required and can't be `null` unless its definition says otherwise. The two flags are separate, because
43
+ JSON can leave a key out or store it as `null`:
44
+
45
+ | Definition | Left out | `null` |
46
+ |---|---|---|
47
+ | `{ name: 'note', type: 'string' }` | error | error |
48
+ | `{ name: 'note', type: 'string', optional: true }` | allowed | error |
49
+ | `{ name: 'note', type: 'string', nullable: true }` | error | stored as `null` |
50
+ | `{ name: 'note', type: 'string', optional: true, nullable: true }` | allowed | stored as `null` |
51
+
52
+ `useDefault: true, defaultValue: …` fills in a field that is left out. `create()` checks the default against the
53
+ field's type (a `null` default needs `nullable: true`) and throws if it doesn't fit. Primary key fields can't be
54
+ nullable. As in SQL, a `null` is never a duplicate in a unique key (any number of rows can hold it), and
55
+ a `null` foreign key isn't checked against the record it references.
56
+
57
+ ## Writing queries
58
+
59
+ `query()` takes one query, or several separated by `;`, and resolves to one result per query:
60
+
61
+ ```js
62
+ const [workouts, exercises] = await query("read workouts where date = '2024-06-02'; read exercises;")
63
+ ```
64
+
65
+ The `;` after the last (or only) query is optional. A `;` inside a string, a comment or brackets doesn't end a query.
66
+
67
+ ### Strings
68
+
69
+ Strings use single or double quotes. A string closes only with the quote it opened with, so the other quote is just
70
+ a character inside it:
71
+
72
+ ```sql
73
+ insert notes values text = "it's done"
74
+ insert notes values text = 'say "hi"'
75
+ ```
76
+
77
+ Inside a string, a backslash escapes the next character: `\'`, `\"` and `\\` are a quote and a backslash, `\n` and
78
+ `\t` are a newline and a tab, and any other `\x` is just `x`. Escapes are read left to right, so `'\\\''` is a
79
+ backslash followed by a quote:
80
+
81
+ ```sql
82
+ insert notes values text = 'it\'s done'
83
+ insert files values path = 'C:\\temp'
84
+ ```
85
+
86
+ An unclosed string, or mismatched quotes (`'abc"`), is an error rather than a guess. Keywords, commas and `;` inside a
87
+ string are only text: `where note = 'x sort b limit 1'` compares against that whole text.
88
+
89
+ ### Building a query from values: `quote()`
90
+
91
+ To put any text into a query (such as user input), wrap it with `quote()`. It escapes the backslash and the quote, so
92
+ the query reads back exactly the text given:
93
+
94
+ ```js
95
+ const { query, quote } = require('json-fs-query')
96
+
97
+ const name = "Farmer's walk"
98
+ await query(`insert exercises values name = ${quote(name)}`)
99
+ await query(`read exercises where name = ${quote(name)}`)
100
+ ```
101
+
102
+ `quote(value, '"')` wraps in double quotes instead.
103
+
104
+ ### Arrays
105
+
106
+ Arrays are JSON-style, and their strings can use either quote. They can be nested, and are used by `in` and
107
+ `between`, or stored as a value:
108
+
109
+ ```sql
110
+ read workouts where exercise_id in [3, 5, 8]
111
+ read workouts where reps between [8, 12]
112
+ read exercises where name in ['bench press', "farmer's walk"]
113
+ insert routines values days = ['mon', 'thu'], sets = [[3, 10], [3, 8]]
114
+ ```
115
+
116
+ ### Comments
117
+
118
+ `-- to the end of the line` and `/* anything, over several lines */`. A `--` starts a comment only at the start of a
119
+ line or after whitespace or a `;`, since names can contain `-` (`my--table` is a name). Comment markers inside a
120
+ string are just text.
121
+
122
+ ```sql
123
+ -- this week's sessions
124
+ read workouts where date = '2024-06-02' /* the Sunday */;
125
+ ```
126
+
127
+ ### Several conditions
128
+
129
+ Each condition starts with `where`; join them with `and where`:
130
+
131
+ ```sql
132
+ read workouts where reps > 8 and where date = '2024-06-02'
133
+ ```
134
+
135
+ `or where` is not supported yet, and is an error (in 1.x it was silently read as `and where`). And/or with grouping
136
+ and precedence is planned.
137
+
138
+ ### Creating a record: `create`
139
+
140
+ The query form of `create()`. Inside the brackets: the fields, then the keys, separated by commas. Everything is
141
+ case-insensitive except names.
142
+
143
+ ```sql
144
+ create if not exists exercise_muscle (
145
+ _id string auto,
146
+ exercise_id string,
147
+ muscle_id string,
148
+ muscle_rank int,
149
+ note string optional default '',
150
+ replaced_by string null default null,
151
+ primary key (_id),
152
+ index (muscle_id, muscle_rank),
153
+ foreign key (exercise_id) references exercises (_id),
154
+ foreign key (muscle_id) references muscles (_id)
155
+ );
156
+ ```
157
+
158
+ A field is `<name> <type>`, then any of these, in any order:
159
+
160
+ | Modifier | Means |
161
+ |---|---|
162
+ | `optional` | may be left out (see "Fields" above) |
163
+ | `null` / `not null` | may hold `null` / may not (the default) |
164
+ | `auto` | a UUID is generated on insert; the type must be `string` |
165
+ | `default <value>` | used when the field is left out: a string, a whole number, an array, `null`, `true` or `false` (so an `object` field can only default to `null` here; `create()` takes any default) |
166
+
167
+ The types are `string`, `int`, `boolean`, `object` and `array`; any other is an error.
168
+
169
+ | Key | Index file |
170
+ |---|---|
171
+ | `primary key (a)` | `pk_a.json` |
172
+ | `unique (a)` | `unique_a.json` |
173
+ | `index (a)` | `index_a.json` |
174
+ | `foreign key (a) references other (b)` | `fk_a.json` (other's record file: `other.json`) |
175
+
176
+ Several fields join with `_`: `index (a, b)` is `index_a_b.json`. Foreign keys are single-field for now.
177
+
178
+ The result is the new record's definition, as from `create()`. Creating a record that already exists is an error;
179
+ with `if not exists` it is left as it is and the result is `null`. A foreign key's record and field must exist
180
+ already (or be the record being created).
181
+
182
+ ### Dropping, describing and listing records: `drop`, `describe`, `show records`
183
+
184
+ ```sql
185
+ drop exercise_muscle; -- removes the record, its entries and its indexes
186
+ drop if exists exercise_muscle; -- the same, or nothing if there is no such record
187
+ describe exercises; -- the record's fields and keys
188
+ show records; -- the name of every record, in the order they were created
189
+ ```
190
+
191
+ `drop` resolves to the definition the record had, or `null` with `if exists` for a record that doesn't exist; without
192
+ it, that is an error. A record that another record's foreign key references can't be dropped until that one is
193
+ (unless `enforceForeignKeys` is turned off, see Configuration). `describe` resolves to `{ path, definition, keys }`
194
+ (the `describe()` function gives only the fields), and `show records` to an array of names.
195
+
196
+ ### Reading a query over several lines: `queryStatus()`
197
+
198
+ For a prompt which reads a query line by line (like the CLI), `queryStatus()` says whether the text so far is ready to
199
+ run, and if not, what it is waiting for: `'` or `"` (a string), `/*` (a comment), `[` or `(` (a bracket), or `;`.
200
+ Join the lines with `'\n'`, since a `--` comment ends at the end of its line.
201
+
202
+ ```js
203
+ const { queryStatus } = require('json-fs-query')
204
+
205
+ queryStatus("read notes where text = 'it") // { complete: false, waitingFor: "'" }
206
+ queryStatus('read notes') // { complete: false, waitingFor: ';' }
207
+ queryStatus('read notes;') // { complete: true, waitingFor: '' }
208
+ ```
209
+
210
+ ### Upgrading from 1.x
211
+
212
+ - Several queries in one string need a `;` between them: `read a; read b`. Before, they were split on command words,
213
+ which also split a value such as `'please read this'` and stored it as `pleaseread this`.
214
+ - Unclosed strings and mismatched quotes are errors.
215
+ - A backslash inside a string is an escape: write `\\` for a backslash (or use `quote()`).
216
+ - `--` and `/* */` start comments outside strings.
217
+ - `null` is only accepted by fields with `nullable: true`, and is stored as a real `null`. Before, a `string` field
218
+ stored the text `"null"` and an `int` field stored `0`.
219
+ - `create()` throws for a default that doesn't fit its field's type, and for a nullable primary key field.
220
+ - `or where` is an error until or is supported. Before, it was read as `and where`, returning the wrong rows.
221
+ - A select alias needs `as`: `select name as n`. Before, the first field took the next word as its alias, so
222
+ `select name where a = 1` failed and `select name limit 1` lost its limit; `select name n` is now an error.
223
+ - Sort fields need a comma between them: `sort a, b desc`. Before, the list ran on into the next clause, so
224
+ `sort a limit 1` sorted by `a`, `limit` and `1` and lost the limit; `sort a b` is now an error.
225
+
226
+ ## Configuration
227
+
228
+ `configure()` sets where this package's data lives and how strictly it enforces foreign keys - call it once,
229
+ before anything else:
230
+
231
+ ```js
232
+ const { configure } = require('json-fs-query')
233
+
234
+ configure({
235
+ databasePath: 'database/', // where the JSON files live (default 'database/')
236
+ relativePath: '', // URL prefix prepended to databasePath when reading via fetch() in a browser
237
+ enforceForeignKeys: true // RESTRICT delete/update of a record other entities still reference (default true)
238
+ })
239
+ ```
240
+
241
+ Turning `enforceForeignKeys` off restores the pre-1.0 behavior (no referential integrity checks at all) - useful if
242
+ it doesn't fit a particular workflow, mirroring MySQL's own toggleable `foreign_key_checks`.
243
+
244
+ ## Several calls at once
245
+
246
+ Calls to `query()`, `create()`, `drop()` and `describe()` on one database (one `databasePath`) run one at a time, in
247
+ the order they were made, so concurrent requests (for example in a web server) can't overwrite each other's
248
+ changes. All the queries in one `query()` string run together, with no other call in between. This covers one Node
249
+ process: two processes writing to the same folder (say a server and a CLI) are not protected from each other.
250
+
251
+ `configure()` can't point `databasePath` at another folder while calls are still running or queued (it throws:
252
+ await them first), since each call reads the setting again at every step. The same folder written another way
253
+ (`database/`, `./database`, its absolute path) counts as one database.
254
+
255
+ ## In the browser
256
+
257
+ A pre-built bundle is included (`browser/jsonFsQuery.js`, `.min.js` - also served directly via
258
+ [unpkg](https://unpkg.com/json-fs-query) or [jsDelivr](https://cdn.jsdelivr.net/npm/json-fs-query)) and exposes the
259
+ same functions as a global:
260
+
261
+ ```html
262
+ <script src="https://unpkg.com/json-fs-query"></script>
263
+ <script>
264
+ jsonFsQuery.configure({ databasePath: 'database/', relativePath: 'https://example.com/' })
265
+ jsonFsQuery.query("read workouts where date = '2024-06-02'").then(console.log)
266
+ </script>
267
+ ```
268
+
269
+ Reads work in the browser via `fetch()` - `create`/`drop`, and any write through `query()` (`insert`/`update`/
270
+ `delete`), need real filesystem access and only work in Node. They're still present in the browser build (same
271
+ public API either way), but throw if actually called there, rather than being silently unavailable.
272
+
273
+ ## Documentation
274
+
275
+ The reference for every function is in [`docs/`](https://joshuaheagle.com/projects/json-file-db/docs/index.html) (or open `docs/index.html` locally). It is generated from the TypeScript source, and each module is a folder of `src/data/`:
276
+
277
+ | Module | What it holds |
278
+ | --- | --- |
279
+ | `introspect` | Create, drop and describe a JSON-file "table" (and the policies that validate one) |
280
+ | `queries` | Parse a query string and run it - reads, inserts, updates, deletes, joins, `where`, `sortBy`, `groupBy` |
281
+ | `utilities` | Shared helpers the queries use - retrieving records/files/indexes and merging join results |
282
+
283
+ `src/index.ts` is the package's public entry point - it re-exports `query`, `quote`, `queryStatus`, `create`, `drop`,
284
+ `describe`, `configure`, and the schema-definition types (`fieldProperties`, `keyProperties`, etc.) needed to build a `create()` call. Everything else
285
+ under `src/data/` is an internal module, reachable but not part of the supported public API.
286
+
287
+ ## Development
288
+
289
+ ```shell
290
+ npm install
291
+ npm test # the tests
292
+ npm run typecheck # the types
293
+ npm run build # dist/ and browser/ (not committed; npm publish builds them)
294
+ npm run docs # the documentation (docs.to)
295
+ ```