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,329 @@
|
|
|
1
|
+
# Field Types API
|
|
2
|
+
|
|
3
|
+
Use field types inside `Schema` definitions to describe how each path is interpreted, cast, and validated.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
import JsonBadger, {Schema} from 'jsonbadger';
|
|
9
|
+
|
|
10
|
+
const user_schema = new Schema({
|
|
11
|
+
name: {type: String, trim: true, minLength: 2},
|
|
12
|
+
age: {type: Number, min: 18},
|
|
13
|
+
active: Boolean,
|
|
14
|
+
tags: [String],
|
|
15
|
+
preferences: {type: Map, of: String},
|
|
16
|
+
payload: {},
|
|
17
|
+
idempotency_key: JsonBadger.field_types.UUIDv7,
|
|
18
|
+
score: {type: 'Double'},
|
|
19
|
+
value: {type: 'Union', of: [String, Number]}
|
|
20
|
+
});
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
> **Note:** A field type is the per-path type definition. `JsonBadger.field_types.UUIDv7` is the type reference; `{type: JsonBadger.field_types.UUIDv7, required: true}` is the field definition.
|
|
24
|
+
|
|
25
|
+
## Declaration Forms
|
|
26
|
+
|
|
27
|
+
### Implicit form
|
|
28
|
+
|
|
29
|
+
```js
|
|
30
|
+
const schema = new Schema({
|
|
31
|
+
name: String,
|
|
32
|
+
age: Number,
|
|
33
|
+
active: Boolean,
|
|
34
|
+
tags: [String]
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Explicit form
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
const schema = new Schema({
|
|
42
|
+
name: {type: String, trim: true},
|
|
43
|
+
age: {type: Number, min: 18},
|
|
44
|
+
preferences: {type: Map, of: String},
|
|
45
|
+
score: {type: 'Double'}
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Nested object form
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
const schema = new Schema({
|
|
53
|
+
profile: {
|
|
54
|
+
name: String,
|
|
55
|
+
city: String
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
> **Note:** The key `type` is reserved inside schema definitions. If a nested object really needs a property named `type`, define that property explicitly:
|
|
61
|
+
>
|
|
62
|
+
> ```js
|
|
63
|
+
> const schema = new Schema({
|
|
64
|
+
> asset: {
|
|
65
|
+
> type: {type: String},
|
|
66
|
+
> ticker: String
|
|
67
|
+
> }
|
|
68
|
+
> });
|
|
69
|
+
> ```
|
|
70
|
+
|
|
71
|
+
## Built-in Field Types
|
|
72
|
+
|
|
73
|
+
The default registry includes these canonical field types:
|
|
74
|
+
|
|
75
|
+
1. `String`
|
|
76
|
+
2. `Number`
|
|
77
|
+
3. `Date`
|
|
78
|
+
4. `Boolean`
|
|
79
|
+
5. `UUIDv7`
|
|
80
|
+
6. `Buffer`
|
|
81
|
+
7. `Mixed`
|
|
82
|
+
8. `Array`
|
|
83
|
+
9. `Map`
|
|
84
|
+
10. `Decimal128`
|
|
85
|
+
11. `BigInt`
|
|
86
|
+
12. `Double`
|
|
87
|
+
13. `Int32`
|
|
88
|
+
14. `Union`
|
|
89
|
+
|
|
90
|
+
Use constructor references where they exist:
|
|
91
|
+
|
|
92
|
+
```js
|
|
93
|
+
const schema = new Schema({
|
|
94
|
+
name: String,
|
|
95
|
+
active: Boolean,
|
|
96
|
+
payload: {},
|
|
97
|
+
tags: [String],
|
|
98
|
+
preferences: {type: Map, of: String}
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Use string aliases for advanced built-ins:
|
|
103
|
+
|
|
104
|
+
```js
|
|
105
|
+
const schema = new Schema({
|
|
106
|
+
score: {type: 'Double'},
|
|
107
|
+
count: {type: 'Int32'},
|
|
108
|
+
value: {type: 'Union', of: [String, Number]}
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Use the public namespace for the built-in UUIDv7 reference and boolean casting sets:
|
|
113
|
+
|
|
114
|
+
```js
|
|
115
|
+
JsonBadger.field_types.UUIDv7;
|
|
116
|
+
JsonBadger.field_types.boolean_convert_to_true;
|
|
117
|
+
JsonBadger.field_types.boolean_convert_to_false;
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Common Options
|
|
121
|
+
|
|
122
|
+
These options are implemented by the base field-type layer and work across field types:
|
|
123
|
+
|
|
124
|
+
1. `required`
|
|
125
|
+
2. `default`
|
|
126
|
+
3. `validate`
|
|
127
|
+
4. `get`
|
|
128
|
+
5. `set`
|
|
129
|
+
6. `alias`
|
|
130
|
+
|
|
131
|
+
```js
|
|
132
|
+
const schema = new Schema({
|
|
133
|
+
name: {
|
|
134
|
+
type: String,
|
|
135
|
+
required: true,
|
|
136
|
+
default: 'Anonymous',
|
|
137
|
+
set(value) {
|
|
138
|
+
return value.trim();
|
|
139
|
+
},
|
|
140
|
+
get(value) {
|
|
141
|
+
return value;
|
|
142
|
+
},
|
|
143
|
+
validate(value) {
|
|
144
|
+
return value.length >= 2;
|
|
145
|
+
},
|
|
146
|
+
alias: 'display_name'
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Type-Specific Options
|
|
152
|
+
|
|
153
|
+
### String
|
|
154
|
+
|
|
155
|
+
```js
|
|
156
|
+
const schema = new Schema({
|
|
157
|
+
name: {
|
|
158
|
+
type: String,
|
|
159
|
+
trim: true,
|
|
160
|
+
lowercase: true,
|
|
161
|
+
match: /^[a-z ]+$/,
|
|
162
|
+
minLength: 2,
|
|
163
|
+
maxLength: 40
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Supported options:
|
|
169
|
+
|
|
170
|
+
1. `trim`
|
|
171
|
+
2. `lowercase`
|
|
172
|
+
3. `uppercase`
|
|
173
|
+
4. `match`
|
|
174
|
+
5. `enum`
|
|
175
|
+
6. `minLength`
|
|
176
|
+
7. `maxLength`
|
|
177
|
+
|
|
178
|
+
### Number
|
|
179
|
+
|
|
180
|
+
```js
|
|
181
|
+
const schema = new Schema({
|
|
182
|
+
age: {
|
|
183
|
+
type: Number,
|
|
184
|
+
min: 18,
|
|
185
|
+
max: 99
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Supported options:
|
|
191
|
+
|
|
192
|
+
1. `min`
|
|
193
|
+
2. `max`
|
|
194
|
+
3. `enum`
|
|
195
|
+
|
|
196
|
+
### Date
|
|
197
|
+
|
|
198
|
+
```js
|
|
199
|
+
const schema = new Schema({
|
|
200
|
+
published_at: {
|
|
201
|
+
type: Date,
|
|
202
|
+
min: new Date('2020-01-01')
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Supported options:
|
|
208
|
+
|
|
209
|
+
1. `min`
|
|
210
|
+
2. `max`
|
|
211
|
+
|
|
212
|
+
### Array
|
|
213
|
+
|
|
214
|
+
```js
|
|
215
|
+
const schema = new Schema({
|
|
216
|
+
tags: [String],
|
|
217
|
+
scores: {type: Array, of: Number}
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
> **Note:** Arrays default to `[]`. Set `default: undefined` when you want to disable the implicit empty-array default.
|
|
222
|
+
|
|
223
|
+
### Map
|
|
224
|
+
|
|
225
|
+
```js
|
|
226
|
+
const schema = new Schema({
|
|
227
|
+
preferences: {type: Map, of: String}
|
|
228
|
+
});
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Union
|
|
232
|
+
|
|
233
|
+
```js
|
|
234
|
+
const schema = new Schema({
|
|
235
|
+
value: {
|
|
236
|
+
type: 'Union',
|
|
237
|
+
of: [String, Number]
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Runtime Notes
|
|
243
|
+
|
|
244
|
+
1. `Mixed` accepts any value and skips type-specific casting.
|
|
245
|
+
2. `Boolean` casting uses the public sets `JsonBadger.field_types.boolean_convert_to_true` and `JsonBadger.field_types.boolean_convert_to_false`.
|
|
246
|
+
3. `UUIDv7` normalizes to lowercase and rejects non-v7 UUID strings.
|
|
247
|
+
4. `Map` casts input into a plain object with string keys.
|
|
248
|
+
5. `Union` keeps exact matches first, then tries casts in declared order.
|
|
249
|
+
|
|
250
|
+
## Introspection
|
|
251
|
+
|
|
252
|
+
Use `schema.get_path(path_name)` to inspect one compiled field type:
|
|
253
|
+
|
|
254
|
+
```js
|
|
255
|
+
const schema = new Schema({
|
|
256
|
+
name: {type: String, minLength: 2}
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
const field_type = schema.get_path('name');
|
|
260
|
+
const type_name = schema.get_path_type('name');
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
The field-type instance exposes these introspection fields:
|
|
264
|
+
|
|
265
|
+
1. `path`
|
|
266
|
+
2. `instance`
|
|
267
|
+
3. `validators`
|
|
268
|
+
4. `regExp`
|
|
269
|
+
5. `enum_values`
|
|
270
|
+
|
|
271
|
+
## Registry Namespace
|
|
272
|
+
|
|
273
|
+
Use the public registry namespace to register or resolve field types.
|
|
274
|
+
|
|
275
|
+
### `JsonBadger.field_type.register(name, type_constructor, aliases?)`
|
|
276
|
+
|
|
277
|
+
```js
|
|
278
|
+
JsonBadger.field_type.register('Money', money_field_type, ['money']);
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Registers a canonical name and optional aliases.
|
|
282
|
+
|
|
283
|
+
### `JsonBadger.field_type.resolve(type)`
|
|
284
|
+
|
|
285
|
+
```js
|
|
286
|
+
const type_name = JsonBadger.field_type.resolve('money');
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Returns the canonical registered name, or `null` when the alias is unknown.
|
|
290
|
+
|
|
291
|
+
## Custom Field Types
|
|
292
|
+
|
|
293
|
+
Custom field types are registry-based.
|
|
294
|
+
|
|
295
|
+
Register the type first, then use the registered name or alias in schema definitions.
|
|
296
|
+
|
|
297
|
+
```js
|
|
298
|
+
class money_field_type {
|
|
299
|
+
constructor(path, options) {
|
|
300
|
+
this.path = path;
|
|
301
|
+
this.options = options || {};
|
|
302
|
+
this.instance = 'Money';
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
validate(value, context) {
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
JsonBadger.field_type.register('Money', money_field_type, ['money']);
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
```js
|
|
314
|
+
const schema = new Schema({
|
|
315
|
+
price: {type: 'Money'},
|
|
316
|
+
discount_price: {type: 'money'}
|
|
317
|
+
});
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Custom field types should follow the same runtime shape as built-in field types. At minimum, the constructed instance should expose:
|
|
321
|
+
|
|
322
|
+
1. `path`
|
|
323
|
+
2. `options`
|
|
324
|
+
3. `instance`
|
|
325
|
+
4. `validate(value, context)` when custom validation is needed
|
|
326
|
+
|
|
327
|
+
Use registration names or aliases in schema definitions. Raw constructor references are not the documented custom-type entry path.
|
|
328
|
+
|
|
329
|
+
> **Note:** There is no separate required base class for custom types. The important part is matching the field-type instance contract the schema/runtime expects.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# API Index
|
|
2
|
+
|
|
3
|
+
Use this directory for module-scoped API reference pages.
|
|
4
|
+
|
|
5
|
+
## TOC
|
|
6
|
+
|
|
7
|
+
- [API Index](#api-index)
|
|
8
|
+
- [Top-level Exports](#top-level-exports)
|
|
9
|
+
- [Module Docs](#module-docs)
|
|
10
|
+
|
|
11
|
+
## Top-level Exports
|
|
12
|
+
|
|
13
|
+
Named exports:
|
|
14
|
+
- `connect(uri, options)`
|
|
15
|
+
- `Schema`
|
|
16
|
+
- `ID_STRATEGY`
|
|
17
|
+
- `field_type`
|
|
18
|
+
|
|
19
|
+
Default export (`JsonBadger`) includes the same plus:
|
|
20
|
+
- `field_type.register(name, type_constructor, aliases?)`
|
|
21
|
+
- `field_type.resolve(type)`
|
|
22
|
+
- `field_types.UUIDv7`
|
|
23
|
+
- `field_types.boolean_convert_to_true`
|
|
24
|
+
- `field_types.boolean_convert_to_false`
|
|
25
|
+
|
|
26
|
+
## Module Docs
|
|
27
|
+
|
|
28
|
+
- [`connection.md`](connection.md)
|
|
29
|
+
- [`delta-tracker.md`](delta-tracker.md)
|
|
30
|
+
- [`document.md`](document.md)
|
|
31
|
+
- [`schema.md`](schema.md)
|
|
32
|
+
- [`model.md`](model.md)
|
|
33
|
+
- [`query-builder.md`](query-builder.md)
|
|
34
|
+
- [`field-types.md`](field-types.md)
|
|
35
|
+
- [`../query-translation.md`](../query-translation.md)
|