jsonbadger 0.5.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 (65) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +114 -0
  3. package/docs/api.md +152 -0
  4. package/docs/examples.md +612 -0
  5. package/docs/local-integration-testing.md +17 -0
  6. package/docs/query-translation.md +98 -0
  7. package/index.js +2 -0
  8. package/package.json +58 -0
  9. package/src/connection/connect.js +56 -0
  10. package/src/connection/disconnect.js +16 -0
  11. package/src/connection/pool-store.js +46 -0
  12. package/src/connection/server-capabilities.js +59 -0
  13. package/src/constants/defaults.js +20 -0
  14. package/src/constants/id-strategies.js +29 -0
  15. package/src/debug/debug-logger.js +15 -0
  16. package/src/errors/query-error.js +23 -0
  17. package/src/errors/validation-error.js +23 -0
  18. package/src/field-types/base-field-type.js +140 -0
  19. package/src/field-types/builtins/advanced.js +365 -0
  20. package/src/field-types/builtins/index.js +585 -0
  21. package/src/field-types/registry.js +122 -0
  22. package/src/index.js +36 -0
  23. package/src/migration/ensure-index.js +155 -0
  24. package/src/migration/ensure-schema.js +16 -0
  25. package/src/migration/ensure-table.js +31 -0
  26. package/src/migration/schema-indexes-resolver.js +6 -0
  27. package/src/model/document-instance.js +540 -0
  28. package/src/model/model-factory.js +555 -0
  29. package/src/query/limit-skip-compiler.js +31 -0
  30. package/src/query/operators/all.js +10 -0
  31. package/src/query/operators/contains.js +7 -0
  32. package/src/query/operators/elem-match.js +3 -0
  33. package/src/query/operators/eq.js +6 -0
  34. package/src/query/operators/gt.js +16 -0
  35. package/src/query/operators/gte.js +16 -0
  36. package/src/query/operators/has-all-keys.js +11 -0
  37. package/src/query/operators/has-any-keys.js +11 -0
  38. package/src/query/operators/has-key.js +6 -0
  39. package/src/query/operators/in.js +12 -0
  40. package/src/query/operators/index.js +60 -0
  41. package/src/query/operators/jsonpath-exists.js +15 -0
  42. package/src/query/operators/jsonpath-match.js +15 -0
  43. package/src/query/operators/lt.js +16 -0
  44. package/src/query/operators/lte.js +16 -0
  45. package/src/query/operators/ne.js +6 -0
  46. package/src/query/operators/nin.js +12 -0
  47. package/src/query/operators/regex.js +8 -0
  48. package/src/query/operators/size.js +16 -0
  49. package/src/query/path-parser.js +43 -0
  50. package/src/query/query-builder.js +93 -0
  51. package/src/query/sort-compiler.js +30 -0
  52. package/src/query/where-compiler.js +477 -0
  53. package/src/schema/field-definition-parser.js +218 -0
  54. package/src/schema/path-introspection.js +82 -0
  55. package/src/schema/schema-compiler.js +212 -0
  56. package/src/schema/schema.js +234 -0
  57. package/src/sql/parameter-binder.js +13 -0
  58. package/src/sql/sql-runner.js +31 -0
  59. package/src/utils/array.js +31 -0
  60. package/src/utils/assert.js +27 -0
  61. package/src/utils/json-safe.js +9 -0
  62. package/src/utils/json.js +21 -0
  63. package/src/utils/object-path.js +33 -0
  64. package/src/utils/object.js +168 -0
  65. package/src/utils/value.js +30 -0
@@ -0,0 +1,168 @@
1
+ import {is_object} from '#src/utils/value.js';
2
+
3
+ function has_own(target, key) {
4
+ return Object.prototype.hasOwnProperty.call(target, key);
5
+ }
6
+
7
+ // Optimized deep clone with fallback and circular reference handling
8
+ function deep_clone(value, cache = new WeakMap()) {
9
+ // Use native high-performance clone if available
10
+ if(typeof globalThis.structuredClone === 'function') {
11
+ return globalThis.structuredClone(value);
12
+ }
13
+
14
+ if(value === null || typeof value !== 'object') {
15
+ return value;
16
+ }
17
+
18
+ if(cache.has(value)) {
19
+ return cache.get(value);
20
+ }
21
+
22
+ if(Array.isArray(value)) {
23
+ const result = [];
24
+ cache.set(value, result);
25
+
26
+ for(let i = 0; i < value.length; i++) {
27
+ result[i] = deep_clone(value[i], cache);
28
+ }
29
+
30
+ return result;
31
+ }
32
+
33
+ const result = {};
34
+ const keys = Object.keys(value);
35
+ cache.set(value, result);
36
+
37
+ for(let i = 0; i < keys.length; i++) {
38
+ const key = keys[i];
39
+ result[key] = deep_clone(value[key], cache);
40
+ }
41
+
42
+ return result;
43
+ }
44
+
45
+ // TODO: rename this? maybe?
46
+ function normalize(schema, value, cache = new WeakMap()) {
47
+ // 1. Array Handling
48
+ if(Array.isArray(schema)) {
49
+ const item_schema = schema.length ? schema[0] : undefined;
50
+ if(item_schema === undefined) return []; // Empty schema enforces empty array
51
+
52
+ const source_list = Array.isArray(value) ? value : [];
53
+
54
+ if(cache.has(source_list)) return cache.get(source_list);
55
+
56
+ const result_list = [];
57
+ cache.set(source_list, result_list);
58
+
59
+ for(let i = 0; i < source_list.length; i++) {
60
+ const item = source_list[i];
61
+ // If strict object matching is needed, skip invalid items
62
+ if(is_object(item_schema) && !is_object(item)) continue;
63
+
64
+ result_list.push(normalize(item_schema, item, cache));
65
+ }
66
+
67
+ return result_list;
68
+ }
69
+
70
+ // 2. Object Handling
71
+ if(is_object(schema)) {
72
+ const source_obj = is_object(value) ? value : null;
73
+
74
+ if(source_obj && cache.has(source_obj)) return cache.get(source_obj);
75
+
76
+ const result_obj = {};
77
+ if(source_obj) cache.set(source_obj, result_obj);
78
+
79
+ // Iterate schema keys (sanitization: ignores extra keys in value)
80
+ const keys = Object.keys(schema);
81
+ for(let i = 0; i < keys.length; i++) {
82
+ const key = keys[i];
83
+ const sub_value = source_obj ? source_obj[key] : undefined;
84
+ result_obj[key] = normalize(schema[key], sub_value, cache);
85
+ }
86
+
87
+ return result_obj;
88
+ }
89
+
90
+ // 3. Primitives & Defaults
91
+ if(value === undefined || value === null) {
92
+ // Return cloned default to prevent shared reference issues
93
+ return typeof schema === 'object' ? deep_clone(schema) : schema;
94
+ }
95
+
96
+ const type = typeof schema;
97
+
98
+ if(type === 'string') {
99
+ return String(value).trim();
100
+ }
101
+
102
+ if(type === 'number') {
103
+ const num = Number(value);
104
+ if(!Number.isFinite(num)) return schema; // Invalid number returns default
105
+
106
+ // Apply specific integer/positive logic based on schema default
107
+ const normalized = Number.isInteger(schema) ? Math.floor(num) : num;
108
+ return normalized >= 0 ? normalized : schema;
109
+ }
110
+
111
+ if(type === 'boolean') {
112
+ return Boolean(value);
113
+ }
114
+
115
+ return deep_clone(schema);
116
+ }
117
+
118
+ function merge(schema, base, value, cache = new WeakMap()) {
119
+ if(value === undefined) return base;
120
+
121
+ if(Array.isArray(schema)) {
122
+ if(!Array.isArray(value)) return base;
123
+ // Arrays are replaced by the new list (normalized), not merged element-wise
124
+ return normalize(schema, value, cache);
125
+ }
126
+
127
+ if(is_object(schema)) {
128
+ if(!is_object(value)) return base;
129
+
130
+ if(cache.has(value)) return cache.get(value);
131
+
132
+ const merged = {};
133
+ cache.set(value, merged);
134
+
135
+ const keys = Object.keys(schema);
136
+ for(let i = 0; i < keys.length; i++) {
137
+ const key = keys[i];
138
+ // Use base value if available, else create default
139
+ const base_child = base && has_own(base, key)
140
+ ? base[key]
141
+ : normalize(schema[key], undefined);
142
+
143
+ if(has_own(value, key)) {
144
+ merged[key] = merge(schema[key], base_child, value[key], cache);
145
+ } else {
146
+ merged[key] = base_child;
147
+ }
148
+ }
149
+
150
+ return merged;
151
+ }
152
+
153
+ return normalize(schema, value, cache);
154
+ }
155
+
156
+ export {
157
+ has_own,
158
+ deep_clone,
159
+ normalize,
160
+ merge
161
+ };
162
+
163
+ export default {
164
+ has_own,
165
+ deep_clone,
166
+ normalize,
167
+ merge
168
+ };
@@ -0,0 +1,30 @@
1
+ const is_object = (value) => {
2
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
3
+ };
4
+
5
+ const is_not_object = (value) => {
6
+ return value === null || Array.isArray(value) || typeof value !== 'object';
7
+ };
8
+
9
+ const is_nan = (value) => {
10
+ const numeric_value = Number(value);
11
+ return Number.isNaN(numeric_value);
12
+ };
13
+
14
+ const is_string = (value) => {
15
+ return typeof value === 'string';
16
+ };
17
+
18
+ export {
19
+ is_object,
20
+ is_not_object,
21
+ is_nan,
22
+ is_string
23
+ };
24
+
25
+ export default {
26
+ is_object,
27
+ is_not_object,
28
+ is_nan,
29
+ is_string
30
+ };