ata-validator 1.0.2 → 1.2.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/CHANGELOG.md +24 -0
- package/README.md +19 -2
- package/index.js +110 -12
- package/lib/aot.js +1 -1
- package/lib/interpreter.js +617 -0
- package/lib/js-compiler.js +32 -0
- package/lib/native-load.browser.js +1 -1
- package/lib/native-load.js +83 -11
- package/lib/t.js +90 -0
- package/lib/version.js +3 -3
- package/package.json +14 -20
- package/t.d.ts +84 -0
- package/CMakeLists.txt +0 -150
- package/binding/ata_napi.cpp +0 -1574
- package/binding-options.js +0 -4
- package/deps/simdjson/simdjson.cpp +0 -56221
- package/deps/simdjson/simdjson.h +0 -122784
- package/include/ata.h +0 -111
- package/include/ata_c.h +0 -57
- package/prebuilds/ata-darwin-arm64/node-napi-v10.node +0 -0
- package/prebuilds/ata-linux-arm64/node-napi-v10.node +0 -0
- package/prebuilds/ata-linux-arm64-musl/node-napi-v10.node +0 -0
- package/prebuilds/ata-linux-x64/node-napi-v10.node +0 -0
- package/prebuilds/ata-linux-x64-musl/node-napi-v10.node +0 -0
- package/prebuilds/ata-win32-x64/node-napi-v10.node +0 -0
- package/scripts/check-doc-coverage.js +0 -34
- package/scripts/check-prebuilds.js +0 -54
- package/scripts/install.js +0 -23
- package/scripts/regen-error-codes-doc.js +0 -40
- package/scripts/regen-lock.js +0 -19
- package/scripts/regen-safe-regex-source.js +0 -33
- package/src/ata.cpp +0 -3146
- package/src/ata_c.cpp +0 -63
package/lib/native-load.js
CHANGED
|
@@ -1,21 +1,93 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
// Locate
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
3
|
+
// Locate the optional native engine. Resolution order:
|
|
4
|
+
// 1. ATA_NO_NATIVE set -> null (explicit pure-JS mode)
|
|
5
|
+
// 2. @ata-validator/native-* -> the per-platform optional package
|
|
6
|
+
// 3. other libc variant -> linux only, in case detection misfired
|
|
7
|
+
// 4. repo-local dev build -> contributors working from source
|
|
8
|
+
// 5. null -> JS codegen covers all core validation
|
|
8
9
|
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
10
|
+
// Lives in its own module so the default and browser entries stay free of
|
|
11
|
+
// platform probing; browser bundles swap this file for
|
|
12
|
+
// `native-load.browser.js` via the package.json `browser` field.
|
|
13
|
+
|
|
14
|
+
const VERSION = require('./version');
|
|
15
|
+
|
|
16
|
+
function nativePackageName(platform, arch, isMusl) {
|
|
17
|
+
if (platform === 'darwin') return arch === 'arm64' ? '@ata-validator/native-darwin-arm64' : null;
|
|
18
|
+
if (platform === 'win32') return arch === 'x64' ? '@ata-validator/native-win32-x64' : null;
|
|
19
|
+
if (platform === 'linux') {
|
|
20
|
+
if (arch !== 'x64' && arch !== 'arm64') return null;
|
|
21
|
+
return `@ata-validator/native-linux-${arch}-${isMusl ? 'musl' : 'gnu'}`;
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function detectMusl() {
|
|
27
|
+
// glibc exposes its version in the process report header; musl does not.
|
|
28
|
+
try {
|
|
29
|
+
const report = process.report && process.report.getReport && process.report.getReport();
|
|
30
|
+
return !!report && !!report.header && !report.header.glibcVersionRuntime;
|
|
31
|
+
} catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let warned = false;
|
|
37
|
+
function checkVersion(binding, source) {
|
|
38
|
+
if (!binding) return null;
|
|
39
|
+
try {
|
|
40
|
+
const v = typeof binding.version === 'function' ? binding.version() : null;
|
|
41
|
+
if (v && v !== VERSION) {
|
|
42
|
+
if (!warned) {
|
|
43
|
+
warned = true;
|
|
44
|
+
process.emitWarning(
|
|
45
|
+
`ata-validator ${VERSION} found a native engine reporting ${v} (${source}); ` +
|
|
46
|
+
'ignoring it and using the pure-JS engine. Reinstall to realign versions.',
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
} catch {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
return binding;
|
|
55
|
+
}
|
|
12
56
|
|
|
13
57
|
module.exports = function loadNative() {
|
|
58
|
+
if (process.env.ATA_NO_NATIVE) return null;
|
|
59
|
+
|
|
60
|
+
const isMusl = process.platform === 'linux' ? detectMusl() : false;
|
|
61
|
+
const candidates = [];
|
|
62
|
+
const primary = nativePackageName(process.platform, process.arch, isMusl);
|
|
63
|
+
if (primary) candidates.push(primary);
|
|
64
|
+
if (process.platform === 'linux') {
|
|
65
|
+
const alt = nativePackageName(process.platform, process.arch, !isMusl);
|
|
66
|
+
if (alt) candidates.push(alt);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
for (const name of candidates) {
|
|
70
|
+
try {
|
|
71
|
+
const binding = checkVersion(require(name), name);
|
|
72
|
+
if (binding) return binding;
|
|
73
|
+
} catch {
|
|
74
|
+
// not installed on this platform; keep going
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Contributors running from a source checkout.
|
|
14
79
|
try {
|
|
15
80
|
const path = require('path');
|
|
16
|
-
const
|
|
17
|
-
|
|
81
|
+
const binding = checkVersion(
|
|
82
|
+
require(path.join(__dirname, '..', 'build', 'Release', 'ata.node')),
|
|
83
|
+
'local build',
|
|
84
|
+
);
|
|
85
|
+
if (binding) return binding;
|
|
18
86
|
} catch {
|
|
19
|
-
|
|
87
|
+
// no dev build; fall through
|
|
20
88
|
}
|
|
89
|
+
|
|
90
|
+
return null;
|
|
21
91
|
};
|
|
92
|
+
|
|
93
|
+
module.exports.nativePackageName = nativePackageName;
|
package/lib/t.js
CHANGED
|
@@ -124,6 +124,90 @@ function refine(schema, check, opts) {
|
|
|
124
124
|
return attachRefine(schema, check, opts);
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
+
function assertObjectSchema(schema, fn) {
|
|
128
|
+
if (!schema || typeof schema !== 'object' || schema.type !== 'object' ||
|
|
129
|
+
!schema.properties || typeof schema.properties !== 'object') {
|
|
130
|
+
throw new Error(`t.${fn}: expected an object schema with properties`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Copy every top-level keyword except the two the combinator recomputes.
|
|
135
|
+
function cloneMeta(schema) {
|
|
136
|
+
const out = {};
|
|
137
|
+
for (const key of Object.keys(schema)) {
|
|
138
|
+
if (key !== 'properties' && key !== 'required') out[key] = schema[key];
|
|
139
|
+
}
|
|
140
|
+
return out;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function pick(schema, keys) {
|
|
144
|
+
assertObjectSchema(schema, 'pick');
|
|
145
|
+
const keep = new Set(keys);
|
|
146
|
+
const props = {};
|
|
147
|
+
for (const key of Object.keys(schema.properties)) {
|
|
148
|
+
if (keep.has(key)) props[key] = schema.properties[key];
|
|
149
|
+
}
|
|
150
|
+
const required = (schema.required || []).filter((key) => keep.has(key));
|
|
151
|
+
const out = Object.assign(cloneMeta(schema), { properties: props });
|
|
152
|
+
if (required.length) out.required = required;
|
|
153
|
+
return out;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function omit(schema, keys) {
|
|
157
|
+
assertObjectSchema(schema, 'omit');
|
|
158
|
+
const drop = new Set(keys);
|
|
159
|
+
const props = {};
|
|
160
|
+
for (const key of Object.keys(schema.properties)) {
|
|
161
|
+
if (!drop.has(key)) props[key] = schema.properties[key];
|
|
162
|
+
}
|
|
163
|
+
const required = (schema.required || []).filter((key) => !drop.has(key));
|
|
164
|
+
const out = Object.assign(cloneMeta(schema), { properties: props });
|
|
165
|
+
if (required.length) out.required = required;
|
|
166
|
+
return out;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function partial(schema) {
|
|
170
|
+
assertObjectSchema(schema, 'partial');
|
|
171
|
+
return Object.assign(cloneMeta(schema), { properties: schema.properties });
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function requiredOf(schema, keys) {
|
|
175
|
+
assertObjectSchema(schema, 'required');
|
|
176
|
+
const propKeys = Object.keys(schema.properties);
|
|
177
|
+
let required;
|
|
178
|
+
if (keys === undefined) {
|
|
179
|
+
required = propKeys.slice();
|
|
180
|
+
} else {
|
|
181
|
+
const known = new Set(propKeys);
|
|
182
|
+
required = Array.from(new Set([...(schema.required || []), ...keys])).filter((k) => known.has(k));
|
|
183
|
+
}
|
|
184
|
+
const out = Object.assign(cloneMeta(schema), { properties: schema.properties });
|
|
185
|
+
if (required.length) out.required = required;
|
|
186
|
+
return out;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function recursive(build, opts) {
|
|
190
|
+
// Single fixed def name; nesting t.recursive inside itself is unsupported
|
|
191
|
+
// (both layers would claim '#/$defs/self') and documented as such.
|
|
192
|
+
const self = { $ref: '#/$defs/self' };
|
|
193
|
+
const body = build(self);
|
|
194
|
+
return Object.assign({ $ref: '#/$defs/self', $defs: { self: body } }, opts);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function composite(schemas, opts) {
|
|
198
|
+
const props = {};
|
|
199
|
+
const requiredSet = new Set();
|
|
200
|
+
for (const schema of schemas) {
|
|
201
|
+
assertObjectSchema(schema, 'composite');
|
|
202
|
+
for (const key of Object.keys(schema.properties)) props[key] = schema.properties[key];
|
|
203
|
+
for (const key of schema.required || []) requiredSet.add(key);
|
|
204
|
+
}
|
|
205
|
+
const required = Array.from(requiredSet).filter((key) => Object.hasOwn(props, key));
|
|
206
|
+
const out = { type: 'object', properties: props };
|
|
207
|
+
if (required.length) out.required = required;
|
|
208
|
+
return Object.assign(out, opts);
|
|
209
|
+
}
|
|
210
|
+
|
|
127
211
|
module.exports = {
|
|
128
212
|
string,
|
|
129
213
|
number,
|
|
@@ -146,4 +230,10 @@ module.exports = {
|
|
|
146
230
|
never,
|
|
147
231
|
refine,
|
|
148
232
|
OPTIONAL,
|
|
233
|
+
pick,
|
|
234
|
+
omit,
|
|
235
|
+
partial,
|
|
236
|
+
required: requiredOf,
|
|
237
|
+
composite,
|
|
238
|
+
recursive,
|
|
149
239
|
};
|
package/lib/version.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
// The package version, exported as a plain string so neither the default nor
|
|
4
4
|
// the browser entry has to `require('./package.json')`. Bundling package.json
|
|
5
|
-
// would drag dependency strings
|
|
6
|
-
//
|
|
5
|
+
// would drag dependency strings into browser builds even though the runtime
|
|
6
|
+
// never touches them.
|
|
7
7
|
//
|
|
8
8
|
// Kept in lockstep with package.json by `tests/test_version_sync.js`.
|
|
9
9
|
|
|
10
|
-
module.exports = '1.0
|
|
10
|
+
module.exports = '1.2.0';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ata-validator",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "JSON Schema validation with first-class TypeScript and zero runtime cost. AOT compile to per-schema ESM modules with zero validator dependency. Generic Validator<T> for TypeBox/Zod/Valibot composition. Optional runtime API. Standard Schema V1 compatible.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "index.mjs",
|
|
@@ -37,18 +37,14 @@
|
|
|
37
37
|
"ata": "bin/ata.js"
|
|
38
38
|
},
|
|
39
39
|
"browser": {
|
|
40
|
-
"pkg-prebuilds": false,
|
|
41
40
|
"./lib/native-load.js": "./lib/native-load.browser.js"
|
|
42
41
|
},
|
|
43
42
|
"scripts": {
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"release:check": "node scripts/regen-safe-regex-source.js && node scripts/check-prebuilds.js && node scripts/check-doc-coverage.js && node tests/test_error_codes_lock.js && node tests/test_safe_regex_source_sync.js && node tests/test_version_sync.js",
|
|
43
|
+
"prepublishOnly": "node scripts/regen-safe-regex-source.js && node tests/test_pack_purity.js && ATA_ALLOW_DOC_PLACEHOLDERS=1 node scripts/check-doc-coverage.js && node tests/test_error_codes_lock.js && node tests/test_safe_regex_source_sync.js && node tests/test_version_sync.js",
|
|
44
|
+
"release:check": "node scripts/regen-safe-regex-source.js && node tests/test_pack_purity.js && node scripts/check-doc-coverage.js && node tests/test_error_codes_lock.js && node tests/test_safe_regex_source_sync.js && node tests/test_version_sync.js",
|
|
47
45
|
"build": "cmake-js build --target ata",
|
|
48
46
|
"rebuild": "cmake-js rebuild --target ata",
|
|
49
|
-
"
|
|
50
|
-
"prebuild-all": "npm run prebuild -- --arch x64 && npm run prebuild -- --arch arm64",
|
|
51
|
-
"test": "node test.js && node tests/test_removed_aot_methods.js && node tests/test_no_native.js && node tests/test_browser_nofs.js && node tests/test_browser_imports_guard.js && node tests/test_version_sync.js && node tests/test_safe_regex_source_sync.js && node tests/test_t_builder.js && node tests/test_async_refine.js && node tests/test_safe_regex.js && node tests/test_safe_regex_integration.js && node tests/test_aot_build.js && node tests/test_aot_differential.js && node tests/test_aot_cli_build.js && node tests/test_aot_cli_smoke.js && node tests/test_bundle_standalone.js && node tests/test_standalone_anyof.js && node tests/test_standalone_formats.js && node tests/test_aot_additional_props_errors.js && node tests/test_id_anchor_refs.js && node tests/test_defs_pointer_alias.js && node tests/test_no_input_mutation.js && node tests/test_typed_validator_runner.js && node tests/test_define_schema.js && node tests/test_error_codes_lock.js && node tests/test_nullable.js && node tests/test_validate_and_parse.js && node tests/test_validate_data.js && node tests/test_enrich_error.js && node tests/test_rich_errors_optout.js && node tests/test_error_messages.js && node tests/test_source_positions.js && node tests/fuzz_positions.js && node tests/test_data_positions.js && node tests/test_render_shared.js && node tests/test_renderers.js && node tests/test_runtime_error_dx.js && node tests/test_aot_error_dx.js && node tests/test_abort_early.js && node tests/test_branch_collapse.js && node tests/test_suggestions.js && node tests/test_cli_validate.js && node tests/test_cli_version.js && node benchmark/bench_aot_size.mjs",
|
|
47
|
+
"test": "node test.js && node tests/test_removed_aot_methods.js && node tests/test_no_native.js && node tests/test_pure_js_unsupported.js && node tests/test_native_load_order.js && node tests/test_pack_purity.js && node tests/test_make_native_package.js && node tests/test_browser_nofs.js && node tests/test_browser_imports_guard.js && node tests/test_version_sync.js && node tests/test_safe_regex_source_sync.js && node tests/test_t_builder.js && node tests/test_async_refine.js && node tests/test_safe_regex.js && node tests/test_safe_regex_integration.js && node tests/test_aot_build.js && node tests/test_aot_differential.js && node tests/test_aot_cli_build.js && node tests/test_aot_cli_smoke.js && node tests/test_bundle_standalone.js && node tests/test_standalone_anyof.js && node tests/test_standalone_formats.js && node tests/test_aot_additional_props_errors.js && node tests/test_id_anchor_refs.js && node tests/test_defs_pointer_alias.js && node tests/test_no_input_mutation.js && node tests/test_typed_validator_runner.js && node tests/test_define_schema.js && node tests/test_error_codes_lock.js && node tests/test_error_order.js && node tests/test_nullable.js && node tests/test_validate_and_parse.js && node tests/test_validate_data.js && node tests/test_enrich_error.js && node tests/test_rich_errors_optout.js && node tests/test_error_messages.js && node tests/test_source_positions.js && node tests/fuzz_positions.js && node tests/test_data_positions.js && node tests/test_render_shared.js && node tests/test_renderers.js && node tests/test_runtime_error_dx.js && node tests/test_aot_error_dx.js && node tests/test_abort_early.js && node tests/test_branch_collapse.js && node tests/test_suggestions.js && node tests/test_cli_validate.js && node tests/test_cli_version.js && node benchmark/bench_aot_size.mjs",
|
|
52
48
|
"bench:size": "node benchmark/bench_aot_size.mjs",
|
|
53
49
|
"test:suite": "node tests/run_suite.js",
|
|
54
50
|
"test:compat": "node tests/test_compat.js",
|
|
@@ -110,22 +106,18 @@
|
|
|
110
106
|
"t.js",
|
|
111
107
|
"t.mjs",
|
|
112
108
|
"t.d.ts",
|
|
113
|
-
"
|
|
114
|
-
"binding/",
|
|
115
|
-
"include/",
|
|
116
|
-
"src/",
|
|
117
|
-
"deps/",
|
|
118
|
-
"prebuilds/",
|
|
119
|
-
"scripts/",
|
|
120
|
-
"CMakeLists.txt",
|
|
109
|
+
"bin/",
|
|
121
110
|
"README.md",
|
|
122
111
|
"CHANGELOG.md",
|
|
123
112
|
"LICENSE"
|
|
124
113
|
],
|
|
125
|
-
"
|
|
126
|
-
"
|
|
127
|
-
"
|
|
128
|
-
"
|
|
114
|
+
"optionalDependencies": {
|
|
115
|
+
"@ata-validator/native-darwin-arm64": "1.2.0",
|
|
116
|
+
"@ata-validator/native-linux-x64-gnu": "1.2.0",
|
|
117
|
+
"@ata-validator/native-linux-arm64-gnu": "1.2.0",
|
|
118
|
+
"@ata-validator/native-linux-x64-musl": "1.2.0",
|
|
119
|
+
"@ata-validator/native-linux-arm64-musl": "1.2.0",
|
|
120
|
+
"@ata-validator/native-win32-x64": "1.2.0"
|
|
129
121
|
},
|
|
130
122
|
"peerDependencies": {
|
|
131
123
|
"yaml": "^2.0.0"
|
|
@@ -142,6 +134,8 @@
|
|
|
142
134
|
"esbuild": "^0.28.0",
|
|
143
135
|
"jsonc-parser": "^3.3.1",
|
|
144
136
|
"mitata": "^1.0.34",
|
|
137
|
+
"node-addon-api": "^8.7.0",
|
|
138
|
+
"node-api-headers": "^1.8.0",
|
|
145
139
|
"typebox": "^1.1.7",
|
|
146
140
|
"typescript": "^6.0.3",
|
|
147
141
|
"valibot": "^1.3.1",
|
package/t.d.ts
CHANGED
|
@@ -167,6 +167,72 @@ export interface TRef extends JSONSchema { $ref: string }
|
|
|
167
167
|
export interface TAny extends JSONSchema {}
|
|
168
168
|
export interface TNever extends JSONSchema { not: {} }
|
|
169
169
|
|
|
170
|
+
/** Any object schema the modifier combinators accept. */
|
|
171
|
+
export interface TObjectLike extends JSONSchema {
|
|
172
|
+
type: 'object';
|
|
173
|
+
properties: Record<string, JSONSchema>;
|
|
174
|
+
required?: ReadonlyArray<string>;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
type ReqUnion<S> = S extends { required: ReadonlyArray<infer R> } ? R : never;
|
|
178
|
+
|
|
179
|
+
export interface TPick<S extends TObjectLike, K extends ReadonlyArray<string>> extends JSONSchema {
|
|
180
|
+
type: 'object';
|
|
181
|
+
properties: { [P in Extract<keyof S['properties'], K[number]>]: S['properties'][P] };
|
|
182
|
+
required: ReadonlyArray<Extract<ReqUnion<S>, K[number]>>;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export interface TOmit<S extends TObjectLike, K extends ReadonlyArray<string>> extends JSONSchema {
|
|
186
|
+
type: 'object';
|
|
187
|
+
properties: { [P in Exclude<Extract<keyof S['properties'], string>, K[number]>]: S['properties'][P] };
|
|
188
|
+
required: ReadonlyArray<Exclude<Extract<ReqUnion<S>, string>, K[number]>>;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export interface TPartial<S extends TObjectLike> extends JSONSchema {
|
|
192
|
+
type: 'object';
|
|
193
|
+
properties: S['properties'];
|
|
194
|
+
required: ReadonlyArray<never>;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export interface TRequiredAll<S extends TObjectLike> extends JSONSchema {
|
|
198
|
+
type: 'object';
|
|
199
|
+
properties: S['properties'];
|
|
200
|
+
required: ReadonlyArray<Extract<keyof S['properties'], string>>;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export interface TRequiredWith<S extends TObjectLike, K extends ReadonlyArray<string>> extends JSONSchema {
|
|
204
|
+
type: 'object';
|
|
205
|
+
properties: S['properties'];
|
|
206
|
+
required: ReadonlyArray<Extract<ReqUnion<S> | K[number], Extract<keyof S['properties'], string>>>;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
type MergeProps<A, B> = { [K in Extract<keyof A | keyof B, string>]: K extends keyof B ? B[K] : K extends keyof A ? A[K] : never };
|
|
210
|
+
|
|
211
|
+
type CompositeProps<S extends ReadonlyArray<TObjectLike>> =
|
|
212
|
+
S extends readonly [] ? {} :
|
|
213
|
+
S extends readonly [infer H extends TObjectLike, ...infer R extends ReadonlyArray<TObjectLike>]
|
|
214
|
+
? MergeProps<H['properties'], CompositeProps<R>>
|
|
215
|
+
: Record<string, JSONSchema>;
|
|
216
|
+
|
|
217
|
+
type CompositeReq<S extends ReadonlyArray<TObjectLike>> =
|
|
218
|
+
S extends readonly [] ? never :
|
|
219
|
+
S extends readonly [infer H extends TObjectLike, ...infer R extends ReadonlyArray<TObjectLike>]
|
|
220
|
+
? ReqUnion<H> | CompositeReq<R>
|
|
221
|
+
: never;
|
|
222
|
+
|
|
223
|
+
export interface TComposite<S extends ReadonlyArray<TObjectLike>> extends JSONSchema {
|
|
224
|
+
type: 'object';
|
|
225
|
+
properties: CompositeProps<S>;
|
|
226
|
+
required: ReadonlyArray<Extract<CompositeReq<S>, string>>;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export interface TSelf extends JSONSchema { $ref: '#/$defs/self' }
|
|
230
|
+
|
|
231
|
+
export interface TRecursive<S extends JSONSchema> extends JSONSchema {
|
|
232
|
+
$ref: '#/$defs/self';
|
|
233
|
+
$defs: { self: S };
|
|
234
|
+
}
|
|
235
|
+
|
|
170
236
|
export interface TBuilder {
|
|
171
237
|
string(opts?: StringOptions): TString;
|
|
172
238
|
number(opts?: NumericOptions): TNumber;
|
|
@@ -189,6 +255,24 @@ export interface TBuilder {
|
|
|
189
255
|
intersect<const S extends ReadonlyArray<JSONSchema>>(schemas: S): TIntersect<S>;
|
|
190
256
|
ref(pointer: string): TRef;
|
|
191
257
|
|
|
258
|
+
pick<const S extends TObjectLike, const K extends ReadonlyArray<Extract<keyof S['properties'], string>>>(schema: S, keys: K): TPick<S, K>;
|
|
259
|
+
omit<const S extends TObjectLike, const K extends ReadonlyArray<Extract<keyof S['properties'], string>>>(schema: S, keys: K): TOmit<S, K>;
|
|
260
|
+
|
|
261
|
+
partial<const S extends TObjectLike>(schema: S): TPartial<S>;
|
|
262
|
+
required<const S extends TObjectLike>(schema: S): TRequiredAll<S>;
|
|
263
|
+
required<const S extends TObjectLike, const K extends ReadonlyArray<Extract<keyof S['properties'], string>>>(schema: S, keys: K): TRequiredWith<S, K>;
|
|
264
|
+
|
|
265
|
+
composite<const S extends ReadonlyArray<TObjectLike>>(schemas: S, opts?: ObjectOptions): TComposite<S>;
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Build a recursive (self-referential) schema. The `self` argument passed to
|
|
269
|
+
* `build` is a `$ref` pointing to `#/$defs/self`, and the emitted schema
|
|
270
|
+
* routes through the interpreted engine at runtime. Nesting `t.recursive`
|
|
271
|
+
* inside itself is unsupported: both layers would claim `#/$defs/self` and
|
|
272
|
+
* the inner definition would silently overwrite the outer one.
|
|
273
|
+
*/
|
|
274
|
+
recursive<S extends JSONSchema>(build: (self: TSelf) => S, opts?: { title?: string; description?: string }): TRecursive<S>;
|
|
275
|
+
|
|
192
276
|
any(): TAny;
|
|
193
277
|
unknown(): TAny;
|
|
194
278
|
never(): TNever;
|
package/CMakeLists.txt
DELETED
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
cmake_minimum_required(VERSION 3.28)
|
|
2
|
-
cmake_policy(SET CMP0091 NEW)
|
|
3
|
-
cmake_policy(SET CMP0042 NEW)
|
|
4
|
-
|
|
5
|
-
project(ata VERSION 0.1.0 LANGUAGES CXX)
|
|
6
|
-
|
|
7
|
-
set(CMAKE_EXPORT_COMPILE_COMMANDS True)
|
|
8
|
-
|
|
9
|
-
set(CMAKE_CXX_STANDARD 20)
|
|
10
|
-
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
11
|
-
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
12
|
-
|
|
13
|
-
if(MSVC)
|
|
14
|
-
set(ABSL_MSVC_STATIC_RUNTIME ON)
|
|
15
|
-
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>" CACHE STRING "" FORCE)
|
|
16
|
-
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
|
17
|
-
endif()
|
|
18
|
-
|
|
19
|
-
option(ATA_TESTING "Build test suite" ON)
|
|
20
|
-
option(ATA_BENCHMARKS "Build benchmarks" OFF)
|
|
21
|
-
option(ATA_SANITIZE "Enable address sanitizer" OFF)
|
|
22
|
-
option(ATA_NO_RE2 "Build without RE2 regex engine (disables pattern keyword)" OFF)
|
|
23
|
-
|
|
24
|
-
# Fetch simdjson
|
|
25
|
-
include(FetchContent)
|
|
26
|
-
FetchContent_Declare(
|
|
27
|
-
simdjson
|
|
28
|
-
GIT_REPOSITORY https://github.com/simdjson/simdjson.git
|
|
29
|
-
GIT_TAG v4.5.0
|
|
30
|
-
GIT_SHALLOW TRUE
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
if(NOT ATA_NO_RE2)
|
|
34
|
-
# RE2 — fast regex engine (replaces std::regex)
|
|
35
|
-
set(RE2_BUILD_TESTING OFF CACHE BOOL "" FORCE)
|
|
36
|
-
FetchContent_Declare(
|
|
37
|
-
re2
|
|
38
|
-
GIT_REPOSITORY https://github.com/google/re2.git
|
|
39
|
-
GIT_TAG 2024-07-02
|
|
40
|
-
GIT_SHALLOW TRUE
|
|
41
|
-
EXCLUDE_FROM_ALL
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
# Abseil — required by RE2
|
|
45
|
-
set(ABSL_PROPAGATE_CXX_STD ON CACHE BOOL "" FORCE)
|
|
46
|
-
set(ABSL_BUILD_TESTING OFF CACHE BOOL "" FORCE)
|
|
47
|
-
set(ABSL_ENABLE_INSTALL ON CACHE BOOL "" FORCE)
|
|
48
|
-
FetchContent_Declare(
|
|
49
|
-
abseil-cpp
|
|
50
|
-
GIT_REPOSITORY https://github.com/abseil/abseil-cpp.git
|
|
51
|
-
GIT_TAG 20240722.0
|
|
52
|
-
GIT_SHALLOW TRUE
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
FetchContent_MakeAvailable(abseil-cpp simdjson re2)
|
|
56
|
-
else()
|
|
57
|
-
FetchContent_MakeAvailable(simdjson)
|
|
58
|
-
endif()
|
|
59
|
-
|
|
60
|
-
if (CMAKE_JS_VERSION)
|
|
61
|
-
# add_definitions(-DNAPI_VERSION=10)
|
|
62
|
-
include_directories(${CMAKE_JS_INC})
|
|
63
|
-
file(GLOB SOURCE_FILES "binding/*.cpp" "src/*.cpp")
|
|
64
|
-
else()
|
|
65
|
-
file(GLOB SOURCE_FILES "src/*.cpp")
|
|
66
|
-
endif()
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (CMAKE_JS_VERSION)
|
|
70
|
-
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})
|
|
71
|
-
|
|
72
|
-
# Include Node-API wrappers
|
|
73
|
-
execute_process(
|
|
74
|
-
COMMAND node -p "require('node-addon-api').include"
|
|
75
|
-
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
|
76
|
-
OUTPUT_VARIABLE NODE_ADDON_API_DIR
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
string(REGEX REPLACE "[\r\n\"]" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})
|
|
80
|
-
target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_ADDON_API_DIR})
|
|
81
|
-
|
|
82
|
-
# Include Node-API C headers
|
|
83
|
-
execute_process(
|
|
84
|
-
COMMAND node -p "require('node-api-headers').include_dir"
|
|
85
|
-
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
|
86
|
-
OUTPUT_VARIABLE NODE_API_HEADERS_DIR
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
string(REGEX REPLACE "[\r\n\"]" "" NODE_API_HEADERS_DIR ${NODE_API_HEADERS_DIR})
|
|
90
|
-
target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_API_HEADERS_DIR})
|
|
91
|
-
else()
|
|
92
|
-
add_library(${PROJECT_NAME} ${SOURCE_FILES})
|
|
93
|
-
endif()
|
|
94
|
-
|
|
95
|
-
target_include_directories(${PROJECT_NAME} PUBLIC include)
|
|
96
|
-
if(ATA_NO_RE2)
|
|
97
|
-
target_link_libraries(${PROJECT_NAME} PRIVATE simdjson)
|
|
98
|
-
target_compile_definitions(${PROJECT_NAME} PRIVATE ATA_NO_RE2)
|
|
99
|
-
else()
|
|
100
|
-
target_link_libraries(${PROJECT_NAME} PRIVATE simdjson re2)
|
|
101
|
-
endif()
|
|
102
|
-
|
|
103
|
-
if (CMAKE_JS_VERSION)
|
|
104
|
-
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_JS_INC})
|
|
105
|
-
target_link_libraries(${PROJECT_NAME} PRIVATE ${CMAKE_JS_LIB})
|
|
106
|
-
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")
|
|
107
|
-
endif()
|
|
108
|
-
|
|
109
|
-
add_library(ata::ata ALIAS ata)
|
|
110
|
-
|
|
111
|
-
if(CMAKE_JS_VERSION AND UNIX AND NOT APPLE)
|
|
112
|
-
target_compile_options(${PROJECT_NAME} PRIVATE -fvisibility=hidden -fvisibility-inlines-hidden)
|
|
113
|
-
target_link_options(${PROJECT_NAME} PRIVATE -Wl,--exclude-libs,ALL)
|
|
114
|
-
endif()
|
|
115
|
-
|
|
116
|
-
if(MSVC AND CMAKE_JS_NODELIB_DEF AND CMAKE_JS_NODELIB_TARGET)
|
|
117
|
-
# Generate node.lib
|
|
118
|
-
execute_process(COMMAND ${CMAKE_AR} /def:${CMAKE_JS_NODELIB_DEF} /out:${CMAKE_JS_NODELIB_TARGET} ${CMAKE_STATIC_LINKER_FLAGS})
|
|
119
|
-
endif()
|
|
120
|
-
|
|
121
|
-
if(ATA_SANITIZE)
|
|
122
|
-
target_compile_options(ata PRIVATE -fsanitize=address -fno-omit-frame-pointer)
|
|
123
|
-
target_link_options(ata PRIVATE -fsanitize=address)
|
|
124
|
-
endif()
|
|
125
|
-
|
|
126
|
-
# Tests
|
|
127
|
-
if(ATA_TESTING)
|
|
128
|
-
enable_testing()
|
|
129
|
-
add_executable(ata_tests tests/test.cpp)
|
|
130
|
-
target_link_libraries(ata_tests PRIVATE ata simdjson)
|
|
131
|
-
if(ATA_SANITIZE)
|
|
132
|
-
target_compile_options(ata_tests PRIVATE -fsanitize=address -fno-omit-frame-pointer)
|
|
133
|
-
target_link_options(ata_tests PRIVATE -fsanitize=address)
|
|
134
|
-
endif()
|
|
135
|
-
add_test(NAME ata_tests COMMAND ata_tests)
|
|
136
|
-
endif()
|
|
137
|
-
|
|
138
|
-
# Benchmarks
|
|
139
|
-
if(ATA_BENCHMARKS)
|
|
140
|
-
add_executable(ata_bench benchmark/bench.cpp)
|
|
141
|
-
target_link_libraries(ata_bench PRIVATE ata simdjson)
|
|
142
|
-
endif()
|
|
143
|
-
|
|
144
|
-
# Fuzz targets (for OSS-Fuzz / libFuzzer)
|
|
145
|
-
if(ATA_FUZZING)
|
|
146
|
-
foreach(fuzzer compile_fuzzer validate_fuzzer roundtrip_fuzzer)
|
|
147
|
-
add_executable(${fuzzer} fuzz/${fuzzer}.cpp)
|
|
148
|
-
target_link_libraries(${fuzzer} PRIVATE ata simdjson ${LIB_FUZZING_ENGINE})
|
|
149
|
-
endforeach()
|
|
150
|
-
endif()
|