🎩 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
27
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.1
to
0.11.2
+47
-34
dist/generators/collect-validator-imports.js
import { refToFilename } from '@amritk/helpers/ref-to-filename';
import { refToName } from '@amritk/helpers/ref-to-name';
import { resolveRef } from '@amritk/helpers/resolve-ref';
import { hasAdditionalProperties, hasAllOf, hasAnyOf, hasItems, hasOneOf, hasProperties, hasRef, } from '@amritk/helpers/schema-guards';
import { hasRef } from '@amritk/helpers/schema-guards';
/**

@@ -13,3 +13,5 @@ * Generates an import statement for a single $ref, importing both the type

const validatorName = `validate${typeName}`;
return `import { type ${typeName}, ${validatorName} } from './${filename}'`;
// `.js` extension so the emitted import resolves under Node ESM (not just Bun);
// `./x.js` → sibling `x.ts` is the standard NodeNext form.
return `import { type ${typeName}, ${validatorName} } from './${filename}.js'`;
};

@@ -25,9 +27,22 @@ /**

/**
* Walks one level of the schema and yields all direct $ref strings that should
* become imports: properties, additionalProperties, items, and union branches.
* Recursively walks a schema and yields every `$ref` the validator emitter can
* turn into a `validateX(...)` call, in traversal order. The emitter recurses
* into far more than properties/items/additionalProperties/top-level
* combinators: it also delegates for `patternProperties`, `propertyNames`,
* `if`/`then`/`else`, `contains`, `prefixItems`, `dependentSchemas`, `not`, and
* objects nested inside any combinator branch. A `$ref` reached by *any* of those
* paths must become an import, or the generated file references an undefined
* `validateX`. (Mirrors the parsers package's `collect-imports` traversal.)
*/
const collectDirectRefs = (schema) => {
if (typeof schema === 'boolean' || schema === null)
return [];
const refs = [];
const collectDirectRefs = (value, refs = []) => {
if (typeof value !== 'object' || value === null)
return refs;
if (Array.isArray(value)) {
for (const item of value)
collectDirectRefs(item, refs);
return refs;
}
const schema = value;
// A `$ref` is a leaf: the emitter delegates the whole value to the referenced
// validator, so record the ref and do not descend past it.
if (hasRef(schema)) {

@@ -37,32 +52,30 @@ refs.push(schema.$ref);

}
const propSchemas = 'properties' in schema && typeof schema.properties === 'object' && schema.properties !== null
? Object.values(schema.properties)
: [];
for (const prop of propSchemas) {
if (hasRef(prop))
refs.push(prop.$ref);
if (hasItems(prop) && hasRef(prop.items))
refs.push(prop.items.$ref);
if (hasAdditionalProperties(prop) && hasRef(prop.additionalProperties)) {
refs.push(prop.additionalProperties.$ref);
// Every keyword whose subschema(s) the emitter recurses into. `properties` and
// `patternProperties` hold subschemas as object *values*; the combinator/tuple
// keywords hold them in arrays; the rest are single subschemas. We deliberately
// do NOT descend into `$defs`/`definitions` — those are split into their own
// generated files, not inlined by this validator. `collectDirectRefs`
// self-guards on non-objects, so a keyword that is a boolean or missing is a
// harmless no-op.
const subSchemaMaps = ['properties', 'patternProperties'];
for (const mapKey of subSchemaMaps) {
const map = schema[mapKey];
if (typeof map === 'object' && map !== null && !Array.isArray(map)) {
for (const sub of Object.values(map))
collectDirectRefs(sub, refs);
}
// Inline nested objects are validated recursively by the generator, so any
// $refs anywhere inside them must become imports as well.
if (hasProperties(prop))
refs.push(...collectDirectRefs(prop));
}
if (hasItems(schema) && hasRef(schema.items)) {
refs.push(schema.items.$ref);
const singleSubSchemas = ['items', 'additionalProperties', 'propertyNames', 'contains', 'if', 'then', 'else', 'not'];
for (const key of singleSubSchemas) {
if (key in schema)
collectDirectRefs(schema[key], refs);
}
if (hasAdditionalProperties(schema) && hasRef(schema.additionalProperties)) {
refs.push(schema.additionalProperties.$ref);
const arraySubSchemas = ['oneOf', 'anyOf', 'allOf', 'prefixItems'];
for (const key of arraySubSchemas) {
const arr = schema[key];
if (Array.isArray(arr)) {
for (const sub of arr)
collectDirectRefs(sub, refs);
}
}
for (const branch of [
...(hasOneOf(schema) ? schema.oneOf : []),
...(hasAnyOf(schema) ? schema.anyOf : []),
...(hasAllOf(schema) ? schema.allOf : []),
]) {
if (hasRef(branch))
refs.push(branch.$ref);
}
return refs;

@@ -69,0 +82,0 @@ };

@@ -38,3 +38,4 @@ import { generateTypeDefinition } from '@amritk/helpers/generate-type-definition';

const booleanGuard = generateBooleanGuard(schema, typeName, typeSuffix);
let result = `import type { ValidationResult, ValidationError } from './validation-result'\n`;
// `.js` extension so the relative import resolves under Node ESM, not only Bun.
let result = `import type { ValidationResult, ValidationError } from './validation-result.js'\n`;
// `const` checks on object/array values call the runtime `valuesEqual` helper.

@@ -44,3 +45,3 @@ // Only import it when the generated body actually uses it, so files without a

if (validatorFunction.includes('valuesEqual(')) {
result += `import { valuesEqual } from './validation-result'\n`;
result += `import { valuesEqual } from './validation-result.js'\n`;
}

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

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

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

"json-schema-typed": "^8.0.1",
"@amritk/helpers": "0.10.1"
"@amritk/helpers": "0.10.2"
},

@@ -52,0 +52,0 @@ "devDependencies": {

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