jsonbadger 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +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
|
@@ -1,212 +1,126 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
function
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
while(segment_index < path_segments.length) {
|
|
129
|
-
const segment_value = path_segments[segment_index];
|
|
130
|
-
|
|
131
|
-
if(current_value === null || typeof current_value !== 'object' || !has_own(current_value, segment_value)) {
|
|
132
|
-
return {
|
|
133
|
-
exists: false,
|
|
134
|
-
value: undefined
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
current_value = current_value[segment_value];
|
|
139
|
-
segment_index += 1;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
return {
|
|
143
|
-
exists: true,
|
|
144
|
-
value: current_value
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
function write_path(root_object, path_segments, next_value) {
|
|
149
|
-
let current_value = root_object;
|
|
150
|
-
let segment_index = 0;
|
|
151
|
-
|
|
152
|
-
while(segment_index < path_segments.length) {
|
|
153
|
-
const segment_value = path_segments[segment_index];
|
|
154
|
-
const is_leaf = segment_index === path_segments.length - 1;
|
|
155
|
-
|
|
156
|
-
if(is_leaf) {
|
|
157
|
-
current_value[segment_value] = next_value;
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// TODO: implement a code review agent that catches these
|
|
162
|
-
if(
|
|
163
|
-
!has_own(current_value, segment_value) ||
|
|
164
|
-
current_value[segment_value] === null ||
|
|
165
|
-
typeof current_value[segment_value] !== 'object' ||
|
|
166
|
-
Array.isArray(current_value[segment_value])
|
|
167
|
-
) {
|
|
168
|
-
current_value[segment_value] = {};
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
current_value = current_value[segment_value];
|
|
172
|
-
segment_index += 1;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function clone_value(value) {
|
|
177
|
-
if(Array.isArray(value)) {
|
|
178
|
-
const cloned_array = [];
|
|
179
|
-
let value_index = 0;
|
|
180
|
-
|
|
181
|
-
while(value_index < value.length) {
|
|
182
|
-
cloned_array.push(clone_value(value[value_index]));
|
|
183
|
-
value_index += 1;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
return cloned_array;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
if(value instanceof Date) {
|
|
190
|
-
return new Date(value.getTime());
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
if(Buffer.isBuffer(value)) {
|
|
194
|
-
return Buffer.from(value);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
if(value && typeof value === 'object') {
|
|
198
|
-
const cloned_object = {};
|
|
199
|
-
const object_entries = Object.entries(value);
|
|
200
|
-
let entry_index = 0;
|
|
201
|
-
|
|
202
|
-
while(entry_index < object_entries.length) {
|
|
203
|
-
const object_entry = object_entries[entry_index];
|
|
204
|
-
cloned_object[object_entry[0]] = clone_value(object_entry[1]);
|
|
205
|
-
entry_index += 1;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
return cloned_object;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
return value;
|
|
212
|
-
}
|
|
1
|
+
import field_definition_parser from '#src/schema/field-definition-parser.js';
|
|
2
|
+
import {create_path_introspection} from '#src/schema/path-introspection.js';
|
|
3
|
+
|
|
4
|
+
import {is_array} from '#src/utils/array.js';
|
|
5
|
+
import {has_own} from '#src/utils/object.js';
|
|
6
|
+
import {is_function, is_not_object} from '#src/utils/value.js';
|
|
7
|
+
|
|
8
|
+
const schema_validation_error_message = 'Schema validation failed';
|
|
9
|
+
const schema_validation_error_code = 'validation_error';
|
|
10
|
+
|
|
11
|
+
// --- PUBLIC API ---
|
|
12
|
+
|
|
13
|
+
function prepare_schema_state(schema_definition = {}) {
|
|
14
|
+
const parsed_schema = field_definition_parser(schema_definition);
|
|
15
|
+
const path_introspection = create_path_introspection(parsed_schema);
|
|
16
|
+
const field_types = path_introspection.field_types;
|
|
17
|
+
const sorted_paths = Object.keys(field_types).sort(sort_paths_by_depth);
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
path_introspection,
|
|
21
|
+
field_types,
|
|
22
|
+
sorted_paths
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Build one reusable validator from a prepared field-type path map.
|
|
28
|
+
*
|
|
29
|
+
* @param {object} field_types
|
|
30
|
+
* @returns {Function}
|
|
31
|
+
*/
|
|
32
|
+
function create_path_validator(field_types = {}) {
|
|
33
|
+
const sorted_paths = Object.keys(field_types).sort(sort_paths_by_depth);
|
|
34
|
+
|
|
35
|
+
return (payload) => {
|
|
36
|
+
return validate_payload(payload, sorted_paths, field_types);
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function validate_payload(payload, sorted_paths, field_types) {
|
|
41
|
+
if(is_not_object(payload) || is_array(payload)) {
|
|
42
|
+
return {
|
|
43
|
+
valid: false,
|
|
44
|
+
errors: [{
|
|
45
|
+
path: '',
|
|
46
|
+
code: schema_validation_error_code,
|
|
47
|
+
message: schema_validation_error_message,
|
|
48
|
+
type: 'object'
|
|
49
|
+
}]
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const error_list = [];
|
|
54
|
+
|
|
55
|
+
for(const path_name of sorted_paths) {
|
|
56
|
+
const field_type = field_types[path_name];
|
|
57
|
+
const path_segments = path_name.split('.');
|
|
58
|
+
const current_path_state = read_path(payload, path_segments);
|
|
59
|
+
const current_value = current_path_state.exists ? current_path_state.value : undefined;
|
|
60
|
+
|
|
61
|
+
if(is_function(field_type.validate)) {
|
|
62
|
+
try {
|
|
63
|
+
field_type.validate(current_value, {path: path_name, exists: current_path_state.exists});
|
|
64
|
+
} catch(error) {
|
|
65
|
+
error_list.push(format_field_error(path_name, error));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
valid: error_list.length === 0,
|
|
72
|
+
errors: error_list.length > 0 ? error_list : null
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function sort_paths_by_depth(left_path, right_path) {
|
|
77
|
+
const left_depth = left_path.split('.').length;
|
|
78
|
+
const right_depth = right_path.split('.').length;
|
|
79
|
+
|
|
80
|
+
if(left_depth !== right_depth) {
|
|
81
|
+
return left_depth - right_depth;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return left_path.localeCompare(right_path);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// --- LOCAL HELPER FUNCTIONS ---
|
|
88
|
+
|
|
89
|
+
function format_field_error(path_name, error) {
|
|
90
|
+
const error_message = error && error.message ? error.message : schema_validation_error_message;
|
|
91
|
+
const error_code = error && error.code ? error.code : schema_validation_error_code;
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
path: path_name,
|
|
95
|
+
code: error_code,
|
|
96
|
+
message: error_message,
|
|
97
|
+
type: error_code
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function read_path(root_object, path_segments) {
|
|
102
|
+
let current_value = root_object;
|
|
103
|
+
|
|
104
|
+
for(const segment_value of path_segments) {
|
|
105
|
+
if(current_value === null || typeof current_value !== 'object' || !has_own(current_value, segment_value)) {
|
|
106
|
+
return {
|
|
107
|
+
exists: false,
|
|
108
|
+
value: undefined
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
current_value = current_value[segment_value];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
exists: true,
|
|
117
|
+
value: current_value
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export {
|
|
122
|
+
create_path_validator,
|
|
123
|
+
prepare_schema_state,
|
|
124
|
+
validate_payload,
|
|
125
|
+
sort_paths_by_depth
|
|
126
|
+
};
|