🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@amritk/generate-validators

Package Overview
Dependencies
Maintainers
1
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@amritk/generate-validators - npm Package Compare versions

Comparing version
0.11.5
to
0.11.6
+29
-0
dist/generators/build-schema.js

@@ -48,2 +48,31 @@ import { generateIndexBarrel } from '@amritk/helpers/generate-index-barrel';

}
/**
* True when every element of \`arr\` is distinct under structural equality
* ({@link valuesEqual}). Backs generated \`uniqueItems\` checks whose items may be
* objects or arrays, where a \`JSON.stringify\` dedupe key would be key-order
* sensitive and let a reordered-but-equal duplicate (\`{ a: 1, b: 2 }\` vs
* \`{ b: 2, a: 1 }\`) slip through. A native \`Set\` dedupes the all-primitive case
* in one linear pass; object/array elements fall back to an exact pairwise
* structural comparison.
*/
export const allUnique = (arr: readonly unknown[]): boolean => {
const len = arr.length
if (len < 2) return true
let allPrimitive = true
for (let i = 0; i < len; i++) {
const v = arr[i]
if (v !== null && typeof v === 'object') {
allPrimitive = false
break
}
}
if (allPrimitive) return new Set(arr).size === len
for (let i = 0; i < len; i++) {
for (let j = i + 1; j < len; j++) {
if (valuesEqual(arr[i], arr[j])) return false
}
}
return true
}
`;

@@ -50,0 +79,0 @@ /**

+1
-1

@@ -57,3 +57,3 @@ import { refToFilename } from '@amritk/helpers/ref-to-filename';

// harmless no-op.
const subSchemaMaps = ['properties', 'patternProperties'];
const subSchemaMaps = ['properties', 'patternProperties', 'dependentSchemas'];
for (const mapKey of subSchemaMaps) {

@@ -60,0 +60,0 @@ const map = schema[mapKey];

@@ -40,7 +40,10 @@ import { generateTypeDefinition } from '@amritk/helpers/generate-type-definition';

let result = `import type { ValidationResult, ValidationError } from './validation-result.js'\n`;
// `const` checks on object/array values call the runtime `valuesEqual` helper.
// Only import it when the generated body actually uses it, so files without a
// structural `const` do not carry an unused import.
if (validatorFunction.includes('valuesEqual(')) {
result += `import { valuesEqual } from './validation-result.js'\n`;
// Structural `const` checks call the runtime `valuesEqual` helper; structural
// `uniqueItems` checks call `allUnique`. Both live in `validation-result.js`;
// import each only when the generated body (validator or boolean guard) uses
// it, so files that need neither carry no unused import.
const body = validatorFunction + booleanGuard;
const runtimeHelpers = ['valuesEqual', 'allUnique'].filter((name) => body.includes(`${name}(`));
if (runtimeHelpers.length > 0) {
result += `import { ${runtimeHelpers.join(', ')} } from './validation-result.js'\n`;
}

@@ -47,0 +50,0 @@ for (const imp of refImports) {

{
"name": "@amritk/generate-validators",
"version": "0.11.5",
"version": "0.11.6",
"description": "Generate TypeScript validation functions from JSON Schemas.",

@@ -49,5 +49,6 @@ "module": "./dist/index.js",

"json-schema-typed": "^8.0.1",
"@amritk/helpers": "0.12.0"
"@amritk/helpers": "0.13.0"
},
"devDependencies": {
"@amritk/runtime-validators": "0.7.0",
"@ryoppippi/unplugin-typia": "^2.6.5",

@@ -54,0 +55,0 @@ "@scalar/openapi-parser": "^0.26.1",

@@ -95,2 +95,23 @@ <div align="center">

## Semantics
Generated validators track the `@amritk/runtime-validators` interpreter. Array
items are validated in full — an item's type, `$ref`, nested `properties` /
`required`, and scalar constraints (`minLength`, `minimum`, …) are all enforced,
recursing to any depth — and the boolean guard (`isX`) reaches the identical
verdict. Validating array item *contents* costs throughput proportional to the
per-item work (a bare `string[]` is free; a closed object with several fields is
meaningfully slower), which is why array-heavy schemas validate more slowly than
scalar/object ones.
One divergence is worth calling out: **`NaN` satisfies a constrained number.**
Because the numeric bound checks are the exact negation of the error condition
(e.g. `!(x < minimum)`), and every comparison against `NaN` is `false`, a `NaN`
passes `minimum`/`maximum`/`exclusive*`/`multipleOf`. This matches the interpreter
but differs from validators (e.g. Ajv) that reject `NaN` for `type: "number"`.
`NaN` never appears in parsed JSON; guard against it upstream if your values can
be non-JSON.
---
## Benchmarks

@@ -97,0 +118,0 @@

Sorry, the diff of this file is too big to display