New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

suretype

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

suretype - npm Package Compare versions

Comparing version 1.1.2 to 1.2.0

dist/annotations.d.ts

31

dist/api/index.d.ts

@@ -11,6 +11,8 @@ import { BaseValidator } from "../validators/base/validator";

import { IfValidator } from "../validators/if/validator";
import { RecursiveValidator } from "../validators/recursive/validator";
import { TypeOf } from "../validators/functional";
import { ArrayFunction, TupleFunction } from "../validators/array-types";
import { ExtractObject } from "../validators/object-types";
import { Decorations } from "../validators/decorations";
import { Annotations, TopLevelAnnotations } from "../annotations";
import { RecursiveValue } from "../validators/types";
export declare const v: {

@@ -29,19 +31,30 @@ string: () => StringValidator<string>;

any: () => AnyValidator;
recursive: () => RecursiveValidator;
};
/**
* Decorate a validator with a name and other annotations
* Cast a recursive value (a value in a recursive type)
*/
export declare const recursiveCast: <T>(value: RecursiveValue) => T;
/**
* Cast a value into a recursive value (inversion of recursiveCast)
*/
export declare const recursiveUnCast: <T>(value: T) => RecursiveValue;
export declare const raw: <T = unknown>(jsonSchema: any) => BaseValidator<T, BaseValidator<T, any>>;
/**
* Annotate a validator with a name and other decorations
*
* @param decorations Decorations
* @param validator Target validator to decorate
* @returns Decorated validator
* @param annotations Annotations
* @param validator Target validator to annotate
* @returns Annotated validator
*/
export declare function suretype<T extends BaseValidator<unknown, any>>(decorations: Decorations, validator: T): T;
export declare function suretype<T extends BaseValidator<unknown, any>>(annotations: TopLevelAnnotations, validator: T): T;
export declare function annotate<T extends BaseValidator<unknown, any>>(annotations: Partial<Annotations>, validator: T): T;
/**
* Ensures a validator is decorated with a name. This will not overwrite the
* Ensures a validator is annotated with a name. This will not overwrite the
* name of a validator, only ensure it has one.
*
* @param name The name to decorate with, unless already decorated
* @param name The name to annotate with, unless already annotated
* @param validator The target validator
* @returns Decorated validator
* @returns Annotated validator
*/
export declare function ensureNamed<T extends BaseValidator<unknown, any>>(name: string, validator: T): T;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ensureNamed = exports.suretype = exports.v = void 0;
exports.ensureNamed = exports.annotate = exports.suretype = exports.raw = exports.recursiveUnCast = exports.recursiveCast = exports.v = void 0;
const validator_1 = require("../validators/boolean/validator");

@@ -15,4 +15,6 @@ const validator_2 = require("../validators/number/validator");

const validator_11 = require("../validators/if/validator");
const validator_12 = require("../validators/raw/validator");
const validator_13 = require("../validators/recursive/validator");
const validation_1 = require("../validation");
const decorations_1 = require("../validators/decorations");
const annotations_1 = require("../annotations");
const string = () => new validator_3.StringValidator();

@@ -32,2 +34,3 @@ const number = () => new validator_2.NumberValidator();

const _if = (validator) => new validator_11.IfValidator(validator);
const recursive = () => new validator_13.RecursiveValidator();
exports.v = {

@@ -44,28 +47,45 @@ string,

any,
recursive,
};
/**
* Decorate a validator with a name and other annotations
* Cast a recursive value (a value in a recursive type)
*/
const recursiveCast = (value) => value;
exports.recursiveCast = recursiveCast;
/**
* Cast a value into a recursive value (inversion of recursiveCast)
*/
const recursiveUnCast = (value) => value;
exports.recursiveUnCast = recursiveUnCast;
const raw = (jsonSchema) => new validator_12.RawValidator(jsonSchema);
exports.raw = raw;
/**
* Annotate a validator with a name and other decorations
*
* @param decorations Decorations
* @param validator Target validator to decorate
* @returns Decorated validator
* @param annotations Annotations
* @param validator Target validator to annotate
* @returns Annotated validator
*/
function suretype(decorations, validator) {
return validation_1.decorateValidator(validation_1.cloneValidator(validator, false), new decorations_1.DecorationsHolder(decorations));
function suretype(annotations, validator) {
return annotations_1.annotateValidator(validation_1.cloneValidator(validator, false), new annotations_1.AnnotationsHolder(annotations));
}
exports.suretype = suretype;
function annotate(annotations, validator) {
return annotations_1.annotateValidator(validation_1.cloneValidator(validator, false), new annotations_1.AnnotationsHolder(annotations));
}
exports.annotate = annotate;
/**
* Ensures a validator is decorated with a name. This will not overwrite the
* Ensures a validator is annotated with a name. This will not overwrite the
* name of a validator, only ensure it has one.
*
* @param name The name to decorate with, unless already decorated
* @param name The name to annotate with, unless already annotated
* @param validator The target validator
* @returns Decorated validator
* @returns Annotated validator
*/
function ensureNamed(name, validator) {
var _a;
if ((_a = validation_1.getDecorations(validator)) === null || _a === void 0 ? void 0 : _a.options.name)
const annotations = annotations_1.getAnnotations(validator);
if (annotations === null || annotations === void 0 ? void 0 : annotations.name)
return validator;
return validation_1.decorateValidator(validation_1.cloneValidator(validator, false), new decorations_1.DecorationsHolder({ name }));
return annotations_1.annotateValidator(validation_1.cloneValidator(validator, false), new annotations_1.AnnotationsHolder({ ...annotations, name }));
}
exports.ensureNamed = ensureNamed;

@@ -5,3 +5,3 @@ "use strict";

const errors_1 = require("./errors");
const validation_1 = require("./validation");
const annotations_1 = require("./annotations");
const tree_traverser_1 = require("./tree-traverser");

@@ -17,8 +17,9 @@ /**

validators = validators
.filter(validator => validation_1.getDecorations(validator));
.filter(validator => { var _a; return (_a = annotations_1.getAnnotations(validator)) === null || _a === void 0 ? void 0 : _a.name; });
}
else if (onNonSuretypeValidator === 'error') {
validators.forEach(validator => {
if (!validation_1.getDecorations(validator))
throw new TypeError("Got undecorated validator");
var _a;
if (!((_a = annotations_1.getAnnotations(validator)) === null || _a === void 0 ? void 0 : _a.name))
throw new TypeError("Got unnamed validator");
});

@@ -29,5 +30,5 @@ }

validators
.map(validator => validation_1.getDecorations(validator))
.map(validator => { var _a; return (_a = annotations_1.getAnnotations(validator)) === null || _a === void 0 ? void 0 : _a.name; })
.filter((t) => !!t)
.forEach(({ options: { name } }) => {
.forEach(name => {
if (nameSet.has(name))

@@ -34,0 +35,0 @@ throw new errors_1.DuplicateError(`Duplicate validators found with name "${name}"`);

@@ -8,3 +8,4 @@ export * from "./api";

export { getValidatorSchema } from "./validation";
export { Annotations, TopLevelAnnotations, getAnnotations, } from "./annotations";
import type { TypeOf } from "./validators/functional";
export type { TypeOf };

@@ -13,3 +13,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.getValidatorSchema = exports.extractSingleJsonSchema = exports.extractJsonSchema = exports.validate = exports.compile = void 0;
exports.getAnnotations = exports.getValidatorSchema = exports.extractSingleJsonSchema = exports.extractJsonSchema = exports.validate = exports.compile = void 0;
__exportStar(require("./api"), exports);

@@ -26,1 +26,3 @@ __exportStar(require("./errors"), exports);

Object.defineProperty(exports, "getValidatorSchema", { enumerable: true, get: function () { return validation_1.getValidatorSchema; } });
var annotations_1 = require("./annotations");
Object.defineProperty(exports, "getAnnotations", { enumerable: true, get: function () { return annotations_1.getAnnotations; } });

@@ -10,2 +10,3 @@ import { TreeTraverser, BaseValidator } from "./validators/base/validator";

private duplicates;
currentSchemaName: string | undefined;
constructor(initialValidators: Array<BaseValidator<unknown, any>>, refMethod: ExportRefMethod);

@@ -12,0 +13,0 @@ visit(validator: BaseValidator<unknown, any>): any;

@@ -5,2 +5,3 @@ "use strict";

const validation_1 = require("./validation");
const annotations_1 = require("./annotations");
class TreeTraverserImpl {

@@ -14,2 +15,3 @@ constructor(initialValidators, refMethod) {

this.duplicates = new Map();
this.currentSchemaName = undefined;
initialValidators

@@ -36,4 +38,4 @@ .map(validator => this.makeRef(validator, false))

return undefined;
const decorations = validation_1.getDecorations(validator);
if (!decorations)
const decorations = annotations_1.getAnnotations(validator);
if (!(decorations === null || decorations === void 0 ? void 0 : decorations.name))
return undefined;

@@ -52,8 +54,10 @@ const nameIfInitial = this.initialValidators.get(validator);

insert({ name, validator }) {
this.currentSchemaName = name;
this.definitions[name] = validation_1.validatorToSchema(validator, this);
this.currentSchemaName = undefined;
return name;
}
makeRef(validator, extra) {
const decorations = validation_1.getDecorations(validator);
const name = this.getNextName(decorations === null || decorations === void 0 ? void 0 : decorations.options.name);
const decorations = annotations_1.getAnnotations(validator);
const name = this.getNextName(decorations === null || decorations === void 0 ? void 0 : decorations.name);
if (extra)

@@ -60,0 +64,0 @@ this.extraValidators.set(validator, name);

import type { AnyType } from "./validators/types";
import type { DecorationsHolder } from "./validators/decorations";
import { BaseValidator, TreeTraverser } from "./validators/base/validator";

@@ -8,5 +7,3 @@ export declare function validatorToSchema<T extends BaseValidator<unknown>>(validator: T, traverser: TreeTraverser): any;

export declare function cloneValidator<T extends BaseValidator<unknown>>(validator: T, clean: boolean): T;
export declare function decorateValidator<T extends BaseValidator<unknown>>(validator: T, decorations: DecorationsHolder): T;
export declare function getDecorations<T extends BaseValidator<unknown>>(validator: T): DecorationsHolder | undefined;
export declare function attachSchemaToValidator<Fn extends Function>(validator: Fn, schema: BaseValidator<unknown>): typeof validator;
export declare function getValidatorSchema(val: any): BaseValidator<unknown> | undefined;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getValidatorSchema = exports.attachSchemaToValidator = exports.getDecorations = exports.decorateValidator = exports.cloneValidator = exports.validatorParent = exports.validatorType = exports.validatorToSchema = void 0;
exports.getValidatorSchema = exports.attachSchemaToValidator = exports.cloneValidator = exports.validatorParent = exports.validatorType = exports.validatorToSchema = void 0;
const validator_1 = require("./validators/base/validator");

@@ -21,11 +21,2 @@ function validatorToSchema(validator, traverser) {

exports.cloneValidator = cloneValidator;
function decorateValidator(validator, decorations) {
validator._decorations = decorations;
return validator;
}
exports.decorateValidator = decorateValidator;
function getDecorations(validator) {
return validator._decorations;
}
exports.getDecorations = getDecorations;
const schemaLookup = new WeakMap();

@@ -32,0 +23,0 @@ function attachSchemaToValidator(validator, schema) {

import { AnyType } from "../types";
import { DecorationsHolder } from "../decorations";
import { AnnotationsHolder } from "../../annotations";
export interface TreeTraverser {

@@ -9,6 +9,7 @@ visit(validator: BaseValidator<unknown, any>): any;

};
currentSchemaName: string | undefined;
}
export declare abstract class BaseValidator<T, U extends BaseValidator<T, U> = BaseValidator<T, any>> {
protected _parent: this | undefined;
protected _decorations: DecorationsHolder | undefined;
protected _annotations: AnnotationsHolder | undefined;
protected abstract type: AnyType;

@@ -15,0 +16,0 @@ protected abstract toSchema(traverser: TreeTraverser): any;

@@ -7,3 +7,3 @@ "use strict";

this._parent = undefined;
this._decorations = undefined;
this._annotations = undefined;
}

@@ -17,5 +17,5 @@ setupClone(clean, clone) {

getJsonSchemaObject(traverser) {
if (!this._decorations)
if (!this._annotations)
return {};
const { title, description, examples } = this._decorations.options;
const { title, description, examples } = this._annotations.options;
return {

@@ -22,0 +22,0 @@ ...(title ? { title } : {}),

@@ -15,2 +15,5 @@ import { BaseValidator } from "./base/validator";

import { RequiredValidator } from "./required/validator";
import { RawValidator } from "./raw/validator";
import { RecursiveValidator } from "./recursive/validator";
import { RecursiveValue } from "./types";
export declare type IsRequired<T> = T extends RequiredValidator<infer U, infer _> ? true : false;

@@ -21,5 +24,5 @@ export declare type ExtractRequired<T> = T extends RequiredValidator<infer U, infer _> ? U : never;

};
export declare type TypeOf<T, InclRequired = false> = T extends ObjectValidator<infer U> ? FlattenObject<U> : T extends TupleValidator<infer U, infer V, infer N, infer A> ? U : T extends ArrayValidator<infer U> ? U : T extends StringValidator<infer U> ? U : T extends NumberValidator<infer U> ? U : T extends BooleanValidator<infer U> ? U : T extends NullValidator<infer U> ? U : T extends AnyValidator ? any : T extends AnyOfValidator<infer U> ? U : T extends AllOfValidator<infer U> ? U : T extends ElseValidator<infer U> ? U : T extends ThenValidator<infer U> ? U : T extends IfValidator<infer U> ? U : T extends ValueValidator<infer U, infer V> ? U : T extends RequiredValidator<infer U, infer _> ? InclRequired extends true ? U : never : T extends BaseValidator<infer U> ? U : never;
export declare type TypeOf<T, InclRequired = false> = T extends ObjectValidator<infer U> ? FlattenObject<U> : T extends TupleValidator<infer U, infer V, infer N, infer A> ? U : T extends ArrayValidator<infer U> ? U : T extends StringValidator<infer U> ? U : T extends NumberValidator<infer U> ? U : T extends BooleanValidator<infer U> ? U : T extends NullValidator<infer U> ? U : T extends AnyValidator ? any : T extends RecursiveValidator ? RecursiveValue : T extends RawValidator ? unknown : T extends AnyOfValidator<infer U> ? U : T extends AllOfValidator<infer U> ? U : T extends ElseValidator<infer U> ? U : T extends ThenValidator<infer U> ? U : T extends IfValidator<infer U> ? U : T extends ValueValidator<infer U, infer V> ? U : T extends RequiredValidator<infer U, infer _> ? InclRequired extends true ? U : never : T extends BaseValidator<infer U> ? U : never;
export declare type Writeable<T> = {
-readonly [P in keyof T]: T[P];
};

@@ -6,3 +6,4 @@ "use strict";

const validator_1 = require("../value/validator");
const validator_2 = require("../any/validator");
const validator_2 = require("../required/validator");
const validator_3 = require("../any/validator");
class ObjectValidator extends validator_1.ValueValidator {

@@ -17,3 +18,3 @@ constructor(properties) {

var _a, _b, _c;
return (_c = (_a = this._additional) !== null && _a !== void 0 ? _a : (_b = this._parent) === null || _b === void 0 ? void 0 : _b.chainedAdditional()) !== null && _c !== void 0 ? _c : new validator_2.AnyValidator();
return (_c = (_a = this._additional) !== null && _a !== void 0 ? _a : (_b = this._parent) === null || _b === void 0 ? void 0 : _b.chainedAdditional()) !== null && _c !== void 0 ? _c : new validator_3.AnyValidator();
}

@@ -42,3 +43,3 @@ const(value) {

properties[key] = traverser.visit(this._properties[key]);
if (validator_1.isRequired(this._properties[key]))
if (validator_2.isRequired(this._properties[key]))
required.push(key);

@@ -45,0 +46,0 @@ });

@@ -10,1 +10,2 @@ import { AnyType } from "../types";

}
export declare function isRequired(validator: BaseValidator<unknown>): boolean;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RequiredValidator = void 0;
exports.isRequired = exports.RequiredValidator = void 0;
const validator_1 = require("../base/validator");

@@ -26,1 +26,5 @@ const validation_1 = require("../../validation");

exports.RequiredValidator = RequiredValidator;
function isRequired(validator) {
return validator instanceof RequiredValidator;
}
exports.isRequired = isRequired;

@@ -5,3 +5,4 @@ "use strict";

const validator_1 = require("../value/validator");
const validator_2 = require("../any/validator");
const validator_2 = require("../required/validator");
const validator_3 = require("../any/validator");
const errors_1 = require("../../errors");

@@ -28,3 +29,3 @@ class TupleValidator extends validator_1.ValueValidator {

for (let i = validators.length - 1; i >= 0; --i) {
if (validator_1.isRequired(validators[i]))
if (validator_2.isRequired(validators[i]))
return i + 1;

@@ -68,3 +69,3 @@ }

type === true
? new validator_2.AnyValidator()
? new validator_3.AnyValidator()
: type === false

@@ -99,3 +100,3 @@ ? undefined

? false
: this._additional instanceof validator_2.AnyValidator
: this._additional instanceof validator_3.AnyValidator
? true

@@ -102,0 +103,0 @@ : traverser.visit(this._additional)

export declare type Type = "string" | "number" | "integer" | "object" | "array" | "boolean" | "null";
export declare type AnyType = Type | "any" | "any-of" | "all-of" | "if";
export declare type AnyType = Type | "any" | "any-of" | "all-of" | "if" | "recursive";
export declare type FilterProperties<T, Cond> = {

@@ -8,1 +8,3 @@ [K in keyof T]: T[K] extends Cond ? K : never;

export declare type SubType<T, Cond, Invert = false> = Invert extends true ? Omit<T, FilterNames<T, Cond>> : Pick<T, FilterNames<T, Cond>>;
export declare abstract class RecursiveValue {
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RecursiveValue = void 0;
class RecursiveValue {
}
exports.RecursiveValue = RecursiveValue;

@@ -113,2 +113,1 @@ import { Type } from "../types";

}
export declare function isRequired(validator: BaseValidator<unknown>): boolean;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isRequired = exports.ValueValidator = void 0;
exports.ValueValidator = void 0;
const validator_1 = require("../base/validator");

@@ -160,5 +160,1 @@ const errors_1 = require("../../errors");

}
function isRequired(validator) {
return validator instanceof validator_2.RequiredValidator;
}
exports.isRequired = isRequired;
{
"name": "suretype",
"version": "1.1.2",
"version": "1.2.0",
"description": "Typesafe JSON (Schema) validator with magic powers 🧙‍♂️",

@@ -49,2 +49,3 @@ "author": "Gustaf Räntilä",

"rimraf": "^3.0.1",
"superstruct": "^0.15.0",
"tempy": "^1.0.0",

@@ -51,0 +52,0 @@ "ts-jest": "^26.5.3",

@@ -14,8 +14,10 @@ [![npm version][npm-image]][npm-url]

<details style="padding-left: 32px; border-left: 4px solid gray;">
<summary>It's as easy as Joi, but ~50x faster.</summary>
<summary>It's as easy as Joi, but ~50x faster, (at least) as typesafe as Superstruct, but ~80x faster.</summary>
<p>
```
Joi x 412,045 ops/sec ±0.75% (87 runs sampled)
suretype x 22,161,985 ops/sec ±0.43% (90 runs sampled)
❯ yarn benchmark
Joi x 385,563 ops/sec ±0.39% (95 runs sampled)
Superstruct x 257,141 ops/sec ±0.34% (90 runs sampled)
suretype x 21,499,582 ops/sec ±0.85% (92 runs sampled)
```

@@ -26,3 +28,3 @@

It supports most (if not all) of JSON schema, and *nothing beyond that*, so that the validator schemas written in TypeScript (or JavaScript) can be ensured to be convertible into JSON schema.
It supports most (if not all) of JSON schema, and *nothing beyond that*, so that the validator schemas written in TypeScript (or JavaScript) can be ensured to be convertible into JSON schema. This also prevents suretype from becoming feature bloated - it has a small and extremely simple API.

@@ -91,3 +93,3 @@ Errors are prettified using [awesome-ajv-errors][awesome-ajv-errors-url].

The default behaviour of `compile` is to return a validator function returning decorated Ajv output.
The default behaviour of `compile` is to return a validator function returning extended Ajv output.

@@ -151,15 +153,34 @@ ```ts

# Decorating schemas
## Raw JSON Schema validator
You can decorate a validator schema using `suretype()`. The return value is still a validator schema, but when exporting it, the decorations will be included.
Sometimes it's handy to not describe the validator schema programmatically, but rather use a raw JSON Schema. There will be no type deduction, so the corresponding interface must be provided explicitly. Only use this if you know the JSON Schema maps to the interface! `raw` works just like the `v.*` functions and returns a validator schema. It can also be annotated.
```ts
import { suretype, v } from "suretype"
import { raw, compile } from 'suretype'
type User = ...; // Get this type from somewhere
const userSchema = raw< User >( { type: 'object', properties: { /* ... */ } } );
// Compile as usual
const ensureUser = compile( userSchema, { ensure: true } );
```
# Annotating schemas
You can annotate a validator schema using `suretype()` or `annotate()`. The return value is still a validator schema, but when exporting it, the annotations will be included.
The difference between `suretype()` and `annotate()` is that `suretype()` requires the `name` property, where as it's optional in `annotate()`. Use `suretype()` to annotate top-level schemas so that they have proper names in the corresponding JSON Schema.
Annotations are useful when exporting the schema to other formats (e.g. JSON Schema or pretty TypeScript interfaces).
```ts
import { suretype, annotate, v } from "suretype"
const cartItemSchema = suretype(
// Decorations
// Annotations
{ name: "CartItem" },
// The validator schema
v.object( {
productId: v.string( ),
productId: annotate( { title: "The product id string" }, v.string( ) ),
// ...

@@ -170,6 +191,6 @@ } )

The decorator interface (i.e. the fields you can decorate) is:
The interface (i.e. the fields you can use) is called `Annotations`:
```ts
interface Decorations {
interface Annotations {
name: string;

@@ -189,3 +210,3 @@ title?: string;

The `userSchema` is the same as in the above example, although it's wrapped in `suretype()` which decorates it with a name and other attributes.
The `userSchema` is the same as in the above example, although it's wrapped in `suretype()` which annotates it with a name and other attributes.

@@ -192,0 +213,0 @@ <details style="padding-left: 32px;border-left: 4px solid gray;">

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc