jsonbadger 0.5.0 → 0.6.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/README.md +36 -18
- package/docs/api/connection.md +144 -0
- package/docs/api/delta-tracker.md +106 -0
- package/docs/api/document.md +77 -0
- package/docs/api/field-types.md +329 -0
- package/docs/api/index.md +35 -0
- package/docs/api/model.md +392 -0
- package/docs/api/query-builder.md +81 -0
- package/docs/api/schema.md +204 -0
- package/docs/architecture-flow.md +397 -0
- package/docs/examples.md +495 -218
- package/docs/jsonb-ops.md +171 -0
- package/docs/lifecycle/model-compilation.md +111 -0
- package/docs/lifecycle.md +146 -0
- package/docs/query-translation.md +11 -10
- package/package.json +10 -3
- package/src/connection/connect.js +12 -17
- package/src/connection/connection.js +128 -0
- package/src/connection/server-capabilities.js +60 -59
- package/src/constants/defaults.js +32 -19
- package/src/constants/{id-strategies.js → id-strategy.js} +28 -29
- package/src/constants/intake-mode.js +8 -0
- package/src/debug/debug-logger.js +17 -15
- package/src/errors/model-overwrite-error.js +25 -0
- package/src/errors/query-error.js +25 -23
- package/src/errors/validation-error.js +25 -23
- package/src/field-types/base-field-type.js +137 -140
- package/src/field-types/builtins/advanced.js +365 -365
- package/src/field-types/builtins/index.js +579 -585
- package/src/field-types/field-type-namespace.js +9 -0
- package/src/field-types/registry.js +149 -122
- package/src/index.js +26 -36
- package/src/migration/ensure-index.js +157 -154
- package/src/migration/ensure-schema.js +27 -15
- package/src/migration/ensure-table.js +44 -31
- package/src/migration/schema-indexes-resolver.js +8 -6
- package/src/model/document-instance.js +29 -540
- package/src/model/document.js +60 -0
- package/src/model/factory/constants.js +36 -0
- package/src/model/factory/index.js +58 -0
- package/src/model/model.js +875 -0
- package/src/model/operations/delete-one.js +39 -0
- package/src/model/operations/insert-one.js +35 -0
- package/src/model/operations/query-builder.js +132 -0
- package/src/model/operations/update-one.js +333 -0
- package/src/model/state.js +34 -0
- package/src/schema/field-definition-parser.js +213 -218
- package/src/schema/path-introspection.js +87 -82
- package/src/schema/schema-compiler.js +126 -212
- package/src/schema/schema.js +621 -138
- package/src/sql/index.js +17 -0
- package/src/sql/jsonb/ops.js +153 -0
- package/src/{query → sql/jsonb}/path-parser.js +54 -43
- package/src/sql/jsonb/read/elem-match.js +133 -0
- package/src/{query → sql/jsonb/read}/operators/contains.js +13 -7
- package/src/sql/jsonb/read/operators/elem-match.js +9 -0
- package/src/{query → sql/jsonb/read}/operators/has-all-keys.js +17 -11
- package/src/{query → sql/jsonb/read}/operators/has-any-keys.js +18 -11
- package/src/sql/jsonb/read/operators/has-key.js +12 -0
- package/src/{query → sql/jsonb/read}/operators/jsonpath-exists.js +22 -15
- package/src/{query → sql/jsonb/read}/operators/jsonpath-match.js +22 -15
- package/src/{query → sql/jsonb/read}/operators/size.js +23 -16
- package/src/sql/parameter-binder.js +18 -13
- package/src/sql/read/build-count-query.js +12 -0
- package/src/sql/read/build-find-query.js +25 -0
- package/src/sql/read/limit-skip.js +21 -0
- package/src/sql/read/sort.js +85 -0
- package/src/sql/read/where/base-fields.js +310 -0
- package/src/sql/read/where/casting.js +90 -0
- package/src/sql/read/where/context.js +79 -0
- package/src/sql/read/where/field-clause.js +58 -0
- package/src/sql/read/where/index.js +38 -0
- package/src/sql/read/where/operator-entries.js +29 -0
- package/src/{query → sql/read/where}/operators/all.js +16 -10
- package/src/sql/read/where/operators/eq.js +12 -0
- package/src/{query → sql/read/where}/operators/gt.js +23 -16
- package/src/{query → sql/read/where}/operators/gte.js +23 -16
- package/src/{query → sql/read/where}/operators/in.js +18 -12
- package/src/sql/read/where/operators/index.js +40 -0
- package/src/{query → sql/read/where}/operators/lt.js +23 -16
- package/src/{query → sql/read/where}/operators/lte.js +23 -16
- package/src/sql/read/where/operators/ne.js +12 -0
- package/src/{query → sql/read/where}/operators/nin.js +18 -12
- package/src/{query → sql/read/where}/operators/regex.js +14 -8
- package/src/sql/read/where/operators.js +126 -0
- package/src/sql/read/where/text-operators.js +83 -0
- package/src/sql/run.js +46 -0
- package/src/sql/write/build-delete-query.js +33 -0
- package/src/sql/write/build-insert-query.js +42 -0
- package/src/sql/write/build-update-query.js +65 -0
- package/src/utils/assert.js +34 -27
- package/src/utils/delta-tracker/.archive/1 tracker-redesign-codex-v2.md +250 -0
- package/src/utils/delta-tracker/.archive/1 tracker-redesign-gemini.md +101 -0
- package/src/utils/delta-tracker/.archive/2 evaluation by gemini.txt +65 -0
- package/src/utils/delta-tracker/.archive/2 evaluation by grok.txt +39 -0
- package/src/utils/delta-tracker/.archive/3 gemini evaluate grok.txt +37 -0
- package/src/utils/delta-tracker/.archive/3 grok evaluate gemini.txt +63 -0
- package/src/utils/delta-tracker/.archive/4 gemini veredict.txt +16 -0
- package/src/utils/delta-tracker/.archive/index.1.js +587 -0
- package/src/utils/delta-tracker/.archive/index.2.js +612 -0
- package/src/utils/delta-tracker/index.js +592 -0
- package/src/utils/dirty-tracker/inline.js +335 -0
- package/src/utils/dirty-tracker/instance.js +414 -0
- package/src/utils/dirty-tracker/static.js +343 -0
- package/src/utils/json-safe.js +13 -9
- package/src/utils/object-path.js +227 -33
- package/src/utils/object.js +408 -168
- package/src/utils/string.js +55 -0
- package/src/utils/value.js +169 -30
- package/docs/api.md +0 -152
- package/src/connection/disconnect.js +0 -16
- package/src/connection/pool-store.js +0 -46
- package/src/model/model-factory.js +0 -555
- package/src/query/limit-skip-compiler.js +0 -31
- package/src/query/operators/elem-match.js +0 -3
- package/src/query/operators/eq.js +0 -6
- package/src/query/operators/has-key.js +0 -6
- package/src/query/operators/index.js +0 -60
- package/src/query/operators/ne.js +0 -6
- package/src/query/query-builder.js +0 -93
- package/src/query/sort-compiler.js +0 -30
- package/src/query/where-compiler.js +0 -477
- package/src/sql/sql-runner.js +0 -31
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
# Architecture Flow
|
|
2
|
+
|
|
3
|
+
This page shows the current JsonBadger runtime flow as ASCII diagrams.
|
|
4
|
+
|
|
5
|
+
## 1. Bootstrap
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
User code
|
|
9
|
+
|
|
|
10
|
+
v
|
|
11
|
+
public API entry
|
|
12
|
+
|
|
|
13
|
+
+--> connect()
|
|
14
|
+
+--> Schema
|
|
15
|
+
+--> field_type
|
|
16
|
+
+--> field_types
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Important:
|
|
20
|
+
|
|
21
|
+
- there is no root `disconnect()`
|
|
22
|
+
- there is no root `model()`
|
|
23
|
+
- the public API is Connection-first
|
|
24
|
+
|
|
25
|
+
## 2. Connection Flow
|
|
26
|
+
|
|
27
|
+
```text
|
|
28
|
+
User
|
|
29
|
+
|
|
|
30
|
+
v
|
|
31
|
+
JsonBadger.connect(uri, options)
|
|
32
|
+
|
|
|
33
|
+
v
|
|
34
|
+
connection bootstrap
|
|
35
|
+
|
|
|
36
|
+
+--> validate options
|
|
37
|
+
+--> create pg.Pool
|
|
38
|
+
+--> SELECT 1
|
|
39
|
+
+--> scan server capabilities
|
|
40
|
+
+--> create Connection(pool_instance, options, server_capabilities)
|
|
41
|
+
+--> on bootstrap failure:
|
|
42
|
+
- close_pool_quietly(pool_instance)
|
|
43
|
+
- rethrow original error
|
|
44
|
+
|
|
|
45
|
+
v
|
|
46
|
+
returns Connection
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Important:
|
|
50
|
+
|
|
51
|
+
- each `connect(...)` call creates a new `Connection`
|
|
52
|
+
- there is no process-global current connection
|
|
53
|
+
- if you want reuse, cache the returned `Connection` explicitly
|
|
54
|
+
|
|
55
|
+
## 3. Connection Ownership
|
|
56
|
+
|
|
57
|
+
```text
|
|
58
|
+
Connection
|
|
59
|
+
|
|
|
60
|
+
+--> owns pool_instance
|
|
61
|
+
+--> owns normalized options
|
|
62
|
+
+--> owns server_capabilities
|
|
63
|
+
+--> owns model registry
|
|
64
|
+
+--> exposes:
|
|
65
|
+
- model(model_definition)
|
|
66
|
+
- disconnect()
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## 4. Schema Flow
|
|
70
|
+
|
|
71
|
+
```text
|
|
72
|
+
User
|
|
73
|
+
|
|
|
74
|
+
v
|
|
75
|
+
new Schema(schema_definition, options)
|
|
76
|
+
|
|
|
77
|
+
v
|
|
78
|
+
Schema
|
|
79
|
+
|
|
|
80
|
+
+--> inject base fields: id / created_at / updated_at
|
|
81
|
+
+--> compile schema definition
|
|
82
|
+
+--> build introspection paths
|
|
83
|
+
+--> normalize inline index declarations
|
|
84
|
+
+--> normalize slug options
|
|
85
|
+
+--> build aliases
|
|
86
|
+
+--> build conform tree
|
|
87
|
+
+--> configure validators:
|
|
88
|
+
- base field validator
|
|
89
|
+
- slug-slice validators
|
|
90
|
+
+--> register field-defined indexes
|
|
91
|
+
+--> register schema instance methods via Schema.add_method(...)
|
|
92
|
+
+--> store:
|
|
93
|
+
- paths
|
|
94
|
+
- indexes
|
|
95
|
+
- options
|
|
96
|
+
- id_strategy
|
|
97
|
+
- auto_index
|
|
98
|
+
- methods
|
|
99
|
+
- aliases
|
|
100
|
+
- validators
|
|
101
|
+
- $conform_tree
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Important:
|
|
105
|
+
|
|
106
|
+
- slug ownership belongs to `Schema`
|
|
107
|
+
- `Schema` owns the final runtime `id_strategy`
|
|
108
|
+
- schema methods are later installed on compiled model constructors
|
|
109
|
+
|
|
110
|
+
## 5. Model Registration Flow
|
|
111
|
+
|
|
112
|
+
```text
|
|
113
|
+
User
|
|
114
|
+
|
|
|
115
|
+
v
|
|
116
|
+
connection.model({name, schema, table_name, ...})
|
|
117
|
+
|
|
|
118
|
+
v
|
|
119
|
+
Connection.model(...)
|
|
120
|
+
|
|
|
121
|
+
+--> validate model_definition.name
|
|
122
|
+
+--> build model options from model_definition
|
|
123
|
+
+--> derive table_name from name when omitted
|
|
124
|
+
+--> return existing model when schema/options match
|
|
125
|
+
+--> throw ModelOverwriteError on conflicting redefinition
|
|
126
|
+
+--> require schema instanceof Schema
|
|
127
|
+
+--> build compiled model constructor/runtime
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Compiled model owns:
|
|
131
|
+
|
|
132
|
+
- `$name`
|
|
133
|
+
- `schema`
|
|
134
|
+
- `options`
|
|
135
|
+
- `connection`
|
|
136
|
+
- `state`
|
|
137
|
+
|
|
138
|
+
Document runtime exposes:
|
|
139
|
+
|
|
140
|
+
- built-in instance methods like `get`, `set`, `save`, `insert`, and `update`
|
|
141
|
+
- schema-defined instance methods copied from `schema.methods`
|
|
142
|
+
|
|
143
|
+
## 6. Construction Flow
|
|
144
|
+
|
|
145
|
+
New payload intake:
|
|
146
|
+
|
|
147
|
+
```text
|
|
148
|
+
External payload
|
|
149
|
+
|
|
|
150
|
+
v
|
|
151
|
+
Model.from(...)
|
|
152
|
+
|
|
|
153
|
+
v
|
|
154
|
+
extract_from_document_fields(...)
|
|
155
|
+
|
|
|
156
|
+
+--> serialize non-plain input
|
|
157
|
+
+--> expand dotted payload keys
|
|
158
|
+
+--> route base fields / default slug / extra slugs
|
|
159
|
+
|
|
|
160
|
+
v
|
|
161
|
+
new Model(document)
|
|
162
|
+
|
|
|
163
|
+
v
|
|
164
|
+
instance.$normalize({mode: 'from'})
|
|
165
|
+
|
|
|
166
|
+
+--> instance.$conform_document(...)
|
|
167
|
+
+--> instance.$apply_defaults(...)
|
|
168
|
+
+--> instance.$cast(...)
|
|
169
|
+
+--> instance.$validate(...)
|
|
170
|
+
|
|
|
171
|
+
v
|
|
172
|
+
instance.document.$rebase_changes()
|
|
173
|
+
|
|
|
174
|
+
v
|
|
175
|
+
new document instance
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Persisted row intake:
|
|
179
|
+
|
|
180
|
+
```text
|
|
181
|
+
Raw row from SQL
|
|
182
|
+
|
|
|
183
|
+
v
|
|
184
|
+
Model.hydrate(...)
|
|
185
|
+
|
|
|
186
|
+
v
|
|
187
|
+
extract_hydrated_document_fields(...)
|
|
188
|
+
|
|
|
189
|
+
+--> serialize non-plain row input
|
|
190
|
+
+--> copy base fields from row root
|
|
191
|
+
+--> read schema.get_slugs() from row roots
|
|
192
|
+
|
|
|
193
|
+
v
|
|
194
|
+
new Model(document)
|
|
195
|
+
|
|
|
196
|
+
v
|
|
197
|
+
instance.$normalize({mode: 'hydrate'})
|
|
198
|
+
|
|
|
199
|
+
+--> instance.$conform_document(...)
|
|
200
|
+
+--> instance.$apply_defaults(...)
|
|
201
|
+
+--> instance.$cast(...)
|
|
202
|
+
+--> instance.$validate(...)
|
|
203
|
+
|
|
|
204
|
+
v
|
|
205
|
+
instance.document.$rebase_changes()
|
|
206
|
+
|
|
|
207
|
+
v
|
|
208
|
+
instance.is_new = false
|
|
209
|
+
|
|
|
210
|
+
v
|
|
211
|
+
rebased persisted model instance
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Manual low-level path:
|
|
215
|
+
|
|
216
|
+
```text
|
|
217
|
+
const instance = new UserModel(document)
|
|
218
|
+
|
|
|
219
|
+
+--> raw tracked document state only
|
|
220
|
+
+--> no conform / defaults / cast / validate yet
|
|
221
|
+
|
|
|
222
|
+
+--> instance.$conform_document(...)
|
|
223
|
+
+--> instance.$apply_defaults(...)
|
|
224
|
+
+--> instance.$cast(...)
|
|
225
|
+
+--> instance.$validate(...)
|
|
226
|
+
+--> or instance.$normalize(...)
|
|
227
|
+
+--> optionally instance.document.$rebase_changes()
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## 7. Read Query Flow
|
|
231
|
+
|
|
232
|
+
```text
|
|
233
|
+
User
|
|
234
|
+
|
|
|
235
|
+
v
|
|
236
|
+
model constructor read methods
|
|
237
|
+
|
|
|
238
|
+
+--> Model.find(...)
|
|
239
|
+
+--> Model.find_one(...)
|
|
240
|
+
+--> Model.count_documents(...)
|
|
241
|
+
|
|
|
242
|
+
v
|
|
243
|
+
query builder
|
|
244
|
+
|
|
|
245
|
+
+--> where_compiler(..., {schema, data_column, id_strategy})
|
|
246
|
+
+--> sort_compiler(...)
|
|
247
|
+
+--> limit_skip_compiler(...)
|
|
248
|
+
+--> sql_runner(sql_text, params, Model.connection)
|
|
249
|
+
|
|
|
250
|
+
v
|
|
251
|
+
Connection.pool_instance.query(...)
|
|
252
|
+
|
|
|
253
|
+
v
|
|
254
|
+
PostgreSQL
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Hydration path for document-returning reads:
|
|
258
|
+
|
|
259
|
+
```text
|
|
260
|
+
query row
|
|
261
|
+
|
|
|
262
|
+
+--> row_to_document(...)
|
|
263
|
+
| - id -> string|null
|
|
264
|
+
| - data -> object fallback
|
|
265
|
+
| - created_at / updated_at -> ISO timestamp
|
|
266
|
+
|
|
|
267
|
+
v
|
|
268
|
+
Model.hydrate(...)
|
|
269
|
+
|
|
|
270
|
+
v
|
|
271
|
+
document instance
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## 8. Write Flow
|
|
275
|
+
|
|
276
|
+
```text
|
|
277
|
+
User
|
|
278
|
+
|
|
|
279
|
+
+--> Model.insert_one(plain_input)
|
|
280
|
+
| |
|
|
281
|
+
| +--> Model.from(...)
|
|
282
|
+
| +--> doc.insert()
|
|
283
|
+
| +--> schema.validate(document)
|
|
284
|
+
| +--> apply_timestamps(document)
|
|
285
|
+
| +--> exec_insert_one(...)
|
|
286
|
+
| +--> sql_runner(..., Model.connection)
|
|
287
|
+
| +--> raw inserted row
|
|
288
|
+
| +--> rebase same instance
|
|
289
|
+
|
|
|
290
|
+
+--> Model.from(...).save()
|
|
291
|
+
| |
|
|
292
|
+
| +--> doc.insert()
|
|
293
|
+
| +--> schema.validate(document)
|
|
294
|
+
| +--> apply_timestamps(document)
|
|
295
|
+
| +--> exec_insert_one(...)
|
|
296
|
+
| +--> sql_runner(..., Model.connection)
|
|
297
|
+
| +--> raw inserted row
|
|
298
|
+
| +--> rebase same instance
|
|
299
|
+
|
|
|
300
|
+
+--> hydrated_doc.save()
|
|
301
|
+
| |
|
|
302
|
+
| +--> schema.validate(document)
|
|
303
|
+
| +--> set updated_at
|
|
304
|
+
| +--> require id for persisted update
|
|
305
|
+
| +--> build tracker delta
|
|
306
|
+
| +--> exec_update_one(...)
|
|
307
|
+
| +--> sql_runner(..., Model.connection)
|
|
308
|
+
| +--> raw updated row
|
|
309
|
+
| +--> rebase current document
|
|
310
|
+
|
|
|
311
|
+
+--> Model.update_one(filter, update_definition)
|
|
312
|
+
| |
|
|
313
|
+
| +--> normalize update gateway
|
|
314
|
+
| +--> normalize update definition
|
|
315
|
+
| +--> JsonbOps.from(...)
|
|
316
|
+
| +--> where_compiler(..., {schema, data_column, id_strategy})
|
|
317
|
+
| +--> exec_update_one(...)
|
|
318
|
+
| +--> sql_runner(..., Model.connection)
|
|
319
|
+
| +--> raw updated row
|
|
320
|
+
| +--> Model.hydrate(row)
|
|
321
|
+
|
|
|
322
|
+
+--> Model.delete_one(...)
|
|
323
|
+
|
|
|
324
|
+
+--> where_compiler(..., {schema, data_column, id_strategy})
|
|
325
|
+
+--> sql_runner(..., Model.connection)
|
|
326
|
+
+--> raw deleted row
|
|
327
|
+
+--> Model.hydrate(row)
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## 9. Migration And Index Flow
|
|
331
|
+
|
|
332
|
+
```text
|
|
333
|
+
App startup / bootstrap
|
|
334
|
+
|
|
|
335
|
+
v
|
|
336
|
+
Model.ensure_table()
|
|
337
|
+
|
|
|
338
|
+
+--> read model.schema.id_strategy
|
|
339
|
+
+--> if uuidv7: assert server capability snapshot
|
|
340
|
+
+--> table migration helper
|
|
341
|
+
+--> execute through explicit Connection
|
|
342
|
+
|
|
343
|
+
Model.ensure_indexes()
|
|
344
|
+
|
|
|
345
|
+
+--> resolve schema indexes
|
|
346
|
+
+--> index migration helper
|
|
347
|
+
+--> execute through explicit Connection
|
|
348
|
+
|
|
349
|
+
Model.ensure_model()
|
|
350
|
+
|
|
|
351
|
+
+--> ensure table
|
|
352
|
+
+--> ensure schema indexes when schema.auto_index is enabled
|
|
353
|
+
+--> execute through explicit Connection
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
Important:
|
|
357
|
+
|
|
358
|
+
- run `ensure_*` helpers during startup/bootstrap
|
|
359
|
+
- `uuidv7` capability is enforced at `Model.ensure_table()`, not at `connect(...)`
|
|
360
|
+
- normal runtime read/write operations do not provision tables or indexes implicitly
|
|
361
|
+
|
|
362
|
+
## Ownership Summary
|
|
363
|
+
|
|
364
|
+
```text
|
|
365
|
+
Connection
|
|
366
|
+
|
|
|
367
|
+
+--> owns one pool
|
|
368
|
+
+--> owns normalized connection options
|
|
369
|
+
+--> owns one capability snapshot
|
|
370
|
+
+--> owns one model registry
|
|
371
|
+
|
|
|
372
|
+
Schema
|
|
373
|
+
|
|
|
374
|
+
+--> owns paths, indexes, slug ownership, aliases, and validators
|
|
375
|
+
+--> owns id_strategy and auto_index
|
|
376
|
+
+--> owns the document conform tree
|
|
377
|
+
|
|
|
378
|
+
Model
|
|
379
|
+
|
|
|
380
|
+
+--> is compiled through Connection.model(...)
|
|
381
|
+
+--> owns schema/options/connection bindings
|
|
382
|
+
+--> reads model.schema.id_strategy as final runtime truth
|
|
383
|
+
+--> executes through its owning Connection
|
|
384
|
+
|
|
|
385
|
+
Document instances
|
|
386
|
+
|
|
|
387
|
+
+--> receive built-in runtime methods plus schema-defined methods
|
|
388
|
+
|
|
|
389
|
+
SQL execution
|
|
390
|
+
|
|
|
391
|
+
+--> stays bound to explicit Connection context
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
Important:
|
|
395
|
+
|
|
396
|
+
- there is no architectural singleton underneath the public API
|
|
397
|
+
- any future root-level convenience must be layered on top, not treated as core runtime state
|