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

object-shape-tester

Package Overview
Dependencies
Maintainers
0
Versions
48
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

object-shape-tester - npm Package Compare versions

Comparing version 3.0.0 to 3.1.0

3

configs/typedoc.config.ts

@@ -22,6 +22,7 @@ import {baseTypedocConfig} from '@virmator/docs/configs/typedoc.config.base';

'unknownSymbol',
'numericRangeSymbol',
'optionalSymbol',
'BaseParts',
'ExpandParts',
'MaybeRequired',
'OptionallyReadonly',

@@ -28,0 +29,0 @@ 'ShapeSpecifierType',

import { ArrayElement, AtLeastTuple, type AnyFunction } from '@augment-vir/common';
import { LiteralToPrimitive, Primitive, UnionToIntersection, WritableDeep } from 'type-fest';
import { LiteralToPrimitive, Primitive, UnionToIntersection, WritableDeep, type Simplify } from 'type-fest';
/**

@@ -53,2 +53,4 @@ * ========================================

declare const unknownSymbol: unique symbol;
declare const numericRangeSymbol: unique symbol;
declare const optionalSymbol: unique symbol;
/**

@@ -59,3 +61,3 @@ * Symbols used to mark the outputs of each sub-shape function (like {@link or}).

*/
export declare const shapeSpecifiersTypes: readonly [typeof andSymbol, typeof enumSymbol, typeof exactSymbol, typeof indexedKeysSymbol, typeof classSymbol, typeof orSymbol, typeof unknownSymbol];
export declare const shapeSpecifiersTypes: readonly [typeof andSymbol, typeof enumSymbol, typeof exactSymbol, typeof indexedKeysSymbol, typeof classSymbol, typeof orSymbol, typeof unknownSymbol, typeof numericRangeSymbol, typeof optionalSymbol];
type BaseParts = AtLeastTuple<unknown, 0>;

@@ -155,2 +157,17 @@ /**

/**
* {@link ShapeSpecifier} for {@link numericRange}.
*
* @category Internal
*/
export type ShapeNumericRange<T extends number = number> = ShapeSpecifier<[
T,
T
], typeof numericRangeSymbol>;
/**
* {@link ShapeSpecifier} for {@link optional}.
*
* @category Internal
*/
export type ShapeOptional<T = unknown> = ShapeSpecifier<[T], typeof optionalSymbol>;
/**
* ========================================

@@ -288,3 +305,3 @@ *

*
* // `myShape.runtimeType` is `{a: unknown`
* // `myShape.runtimeType` is `{a: unknown}`
* ```

@@ -294,2 +311,42 @@ */

/**
* Define a shape part that requires numbers to be within a specific range, inclusive.
*
* @category Shape Part
* @example
*
* ```ts
* import {numericRange, defineShape} from 'object-shape-tester';
*
* const myShape = defineShape({
* // This will simply produce a type of `number` but will validate runtime values against the range.
* a: numericRange(1, 10),
* });
* // `myShape.runtimeType` is just `{a: number}`
*
* const myShape2 = defineShape({
* // If you want type safety, you must specify the allowed numbers manually
* a: numericRange<1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10>(1, 10),
* });
* // `myShape2.runtimeType` is `{a: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10}`
* ```
*/
export declare function numericRange<T extends number = number>(min: NoInfer<T>, max: NoInfer<T>): ShapeNumericRange<T>;
/**
* Define a shape part that is optional. This only makes sense as a property in an object.
*
* @category Shape Part
* @example
*
* ```ts
* import {optional, defineShape} from 'object-shape-tester';
*
* const myShape = defineShape({
* a: optional(-1),
* });
*
* // `myShape.runtimeType` is `{a?: number}`
* ```
*/
export declare function optional<T>(part: T): ShapeOptional<T>;
/**
* ========================================

@@ -302,3 +359,3 @@ *

/**
* Checks if the input is an `and` shape specifier for internal type guarding purposes.
* Checks if the input is an {@link and} shape specifier for internal type guarding purposes.
*

@@ -309,3 +366,3 @@ * @category Internal

/**
* Checks if the input is a `classShape` shape specifier for internal type guarding purposes.
* Checks if the input is a {@link classShape} shape specifier for internal type guarding purposes.
*

@@ -316,3 +373,3 @@ * @category Internal

/**
* Checks if the input is an `enumShape` shape specifier for internal type guarding purposes.
* Checks if the input is an {@link enumShape} shape specifier for internal type guarding purposes.
*

@@ -323,3 +380,3 @@ * @category Internal

/**
* Checks if the input is an `exact` shape specifier for internal type guarding purposes.
* Checks if the input is an {@link exact} shape specifier for internal type guarding purposes.
*

@@ -330,3 +387,3 @@ * @category Internal

/**
* Checks if the input is an `indexedKeys` shape specifier for internal type guarding purposes.
* Checks if the input is an {@link indexedKeys} shape specifier for internal type guarding purposes.
*

@@ -337,3 +394,3 @@ * @category Internal

/**
* Checks if the input is an `or` shape specifier for internal type guarding purposes.
* Checks if the input is an {@link or} shape specifier for internal type guarding purposes.
*

@@ -344,3 +401,4 @@ * @category Internal

/**
* Checks if the input is an `unknown` shape specifier for internal type guarding purposes.
* Checks if the input is an {@link unknownShape} shape specifier for internal type guarding
* purposes.
*

@@ -351,2 +409,14 @@ * @category Internal

/**
* Checks if the input is a {@link numericRange} shape specifier for internal type guarding purposes.
*
* @category Internal
*/
export declare function isNumericRangeShapeSpecifier(maybeSpecifier: unknown): maybeSpecifier is ShapeNumericRange;
/**
* Checks if the input is a {@link optional} shape specifier for internal type guarding purposes.
*
* @category Internal
*/
export declare function isOptionalShapeSpecifier(maybeSpecifier: unknown): maybeSpecifier is ShapeOptional;
/**
* ========================================

@@ -365,7 +435,9 @@ *

*/
export type SpecifierToRuntimeType<PossiblySpecifier, IsExact extends boolean, IsReadonly extends boolean> = PossiblySpecifier extends ShapeSpecifier<infer Parts, infer Type> ? Type extends typeof andSymbol ? OptionallyReadonly<IsReadonly, UnionToIntersection<ExpandParts<Parts, IsExact, IsReadonly>>> : Type extends typeof classSymbol ? Parts[0] extends AnyConstructor ? OptionallyReadonly<IsReadonly, InstanceType<Parts[0]>> : 'TypeError: classShape input must be a constructor.' : Type extends typeof orSymbol ? OptionallyReadonly<IsReadonly, ExpandParts<Parts, IsExact, IsReadonly>> : Type extends typeof exactSymbol ? OptionallyReadonly<IsReadonly, WritableDeep<ExpandParts<Parts, true, IsReadonly>>> : Type extends typeof enumSymbol ? OptionallyReadonly<IsReadonly, Parts[0][keyof Parts[0]]> : Type extends typeof indexedKeysSymbol ? Parts[0] extends {
export type SpecifierToRuntimeType<PossiblySpecifier, IsExact extends boolean, IsReadonly extends boolean> = PossiblySpecifier extends ShapeSpecifier<infer Parts, infer Type> ? Type extends typeof numericRangeSymbol ? Parts[0] : Type extends typeof andSymbol ? OptionallyReadonly<IsReadonly, UnionToIntersection<ExpandParts<Parts, IsExact, IsReadonly>>> : Type extends typeof classSymbol ? Parts[0] extends AnyConstructor ? OptionallyReadonly<IsReadonly, InstanceType<Parts[0]>> : 'TypeError: classShape input must be a constructor.' : Type extends typeof orSymbol ? OptionallyReadonly<IsReadonly, ExpandParts<Parts, IsExact, IsReadonly>> : Type extends typeof exactSymbol ? OptionallyReadonly<IsReadonly, WritableDeep<ExpandParts<Parts, true, IsReadonly>>> : Type extends typeof enumSymbol ? OptionallyReadonly<IsReadonly, Parts[0][keyof Parts[0]]> : Type extends typeof indexedKeysSymbol ? Parts[0] extends {
keys: unknown;
values: unknown;
required: boolean;
} ? ExpandParts<[Parts[0]['keys']], IsExact, IsReadonly> extends PropertyKey ? OptionallyReadonly<IsReadonly, MaybeRequired<Record<ExpandParts<[Parts[0]['keys']], IsExact, IsReadonly>, ExpandParts<[Parts[0]['values']], IsExact, IsReadonly>>, Parts[0]['required']>> : 'TypeError: indexedKeys keys be a subset of PropertyKey.' : 'TypeError: indexedKeys input is invalid.' : Type extends typeof unknownSymbol ? unknown : 'TypeError: found not match for shape specifier type.' : PossiblySpecifier extends Primitive ? IsExact extends true ? PossiblySpecifier : LiteralToPrimitive<PossiblySpecifier> : PossiblySpecifier extends object ? PossiblySpecifier extends ShapeDefinition<any, any> ? PossiblySpecifier['runtimeType'] : OptionallyReadonly<IsReadonly, {
} ? ExpandParts<[
Parts[0]['keys']
], IsExact, IsReadonly> extends PropertyKey ? OptionallyReadonly<IsReadonly, MaybeRequired<Record<ExpandParts<[Parts[0]['keys']], IsExact, IsReadonly>, ExpandParts<[Parts[0]['values']], IsExact, IsReadonly>>, Parts[0]['required']>> : 'TypeError: indexedKeys keys be a subset of PropertyKey.' : 'TypeError: indexedKeys input is invalid.' : Type extends typeof unknownSymbol ? unknown : Type extends typeof optionalSymbol ? Parts[0] : 'TypeError: found no match for shape specifier type.' : PossiblySpecifier extends Primitive ? IsExact extends true ? PossiblySpecifier : LiteralToPrimitive<PossiblySpecifier> : PossiblySpecifier extends object ? PossiblySpecifier extends ShapeDefinition<any, any> ? PossiblySpecifier['runtimeType'] : OptionallyReadonly<IsReadonly, {
[Prop in keyof PossiblySpecifier]: SpecifierToRuntimeType<PossiblySpecifier[Prop], IsExact, IsReadonly>;

@@ -379,5 +451,9 @@ }> : PossiblySpecifier;

*/
export type ShapeToRuntimeType<Shape, IsExact extends boolean, IsReadonly extends boolean> = Shape extends AnyFunction ? Shape : Shape extends object ? Shape extends ShapeDefinition<infer InnerShape, any> ? ShapeToRuntimeType<InnerShape, IsExact, IsReadonly> : Shape extends ShapeSpecifier<any, any> ? Shape extends ShapeSpecifier<any, typeof exactSymbol> ? SpecifierToRuntimeType<Shape, true, IsReadonly> : SpecifierToRuntimeType<Shape, IsExact, IsReadonly> : OptionallyReadonly<IsReadonly, {
[PropName in keyof Shape]: Shape[PropName] extends ShapeSpecifier<any, typeof exactSymbol> ? ShapeToRuntimeType<Shape[PropName], true, IsReadonly> : ShapeToRuntimeType<Shape[PropName], IsExact, IsReadonly>;
}> : Shape;
export type ShapeToRuntimeType<Shape, IsExact extends boolean, IsReadonly extends boolean> = Shape extends AnyFunction ? Shape : Shape extends object ? Shape extends ShapeDefinition<infer InnerShape, any> ? ShapeToRuntimeType<InnerShape, IsExact, IsReadonly> : Shape extends ShapeSpecifier<any, any> ? Shape extends ShapeSpecifier<any, typeof exactSymbol> ? SpecifierToRuntimeType<Shape, true, IsReadonly> : SpecifierToRuntimeType<Shape, IsExact, IsReadonly> : Shape extends Array<any> ? OptionallyReadonly<IsReadonly, {
[Prop in keyof Shape]: Shape[Prop] extends ShapeSpecifier<any, typeof exactSymbol> ? ShapeToRuntimeType<Shape[Prop], true, IsReadonly> : ShapeToRuntimeType<Shape[Prop], IsExact, IsReadonly>;
}> : OptionallyReadonly<IsReadonly, Simplify<{
[Prop in keyof Shape as Shape[Prop] extends ShapeOptional<any> ? never : Prop]: Shape[Prop] extends ShapeOptional<any> ? never : Shape[Prop] extends ShapeSpecifier<any, typeof exactSymbol> ? ShapeToRuntimeType<Shape[Prop], true, IsReadonly> : ShapeToRuntimeType<Shape[Prop], IsExact, IsReadonly>;
} & {
[Prop in keyof Shape as Shape[Prop] extends ShapeOptional<any> ? Prop : never]?: Shape[Prop] extends ShapeOptional<any> ? Shape[Prop] extends ShapeSpecifier<any, typeof exactSymbol> ? ShapeToRuntimeType<Shape[Prop], true, IsReadonly> : ShapeToRuntimeType<Shape[Prop], IsExact, IsReadonly> : never;
}>> : Shape;
/**

@@ -384,0 +460,0 @@ * Checks if the given `subject` matches the given `shape`.

@@ -43,2 +43,4 @@ import { check } from '@augment-vir/assert';

const unknownSymbol = Symbol('unknown');
const numericRangeSymbol = Symbol('numeric-range');
const optionalSymbol = Symbol('optional');
/**

@@ -57,2 +59,4 @@ * Symbols used to mark the outputs of each sub-shape function (like {@link or}).

unknownSymbol,
numericRangeSymbol,
optionalSymbol,
];

@@ -214,3 +218,3 @@ /**

*
* // `myShape.runtimeType` is `{a: unknown`
* // `myShape.runtimeType` is `{a: unknown}`
* ```

@@ -222,2 +226,49 @@ */

/**
* Define a shape part that requires numbers to be within a specific range, inclusive.
*
* @category Shape Part
* @example
*
* ```ts
* import {numericRange, defineShape} from 'object-shape-tester';
*
* const myShape = defineShape({
* // This will simply produce a type of `number` but will validate runtime values against the range.
* a: numericRange(1, 10),
* });
* // `myShape.runtimeType` is just `{a: number}`
*
* const myShape2 = defineShape({
* // If you want type safety, you must specify the allowed numbers manually
* a: numericRange<1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10>(1, 10),
* });
* // `myShape2.runtimeType` is `{a: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10}`
* ```
*/
export function numericRange(min, max) {
return specifier([
min,
max,
], numericRangeSymbol);
}
/**
* Define a shape part that is optional. This only makes sense as a property in an object.
*
* @category Shape Part
* @example
*
* ```ts
* import {optional, defineShape} from 'object-shape-tester';
*
* const myShape = defineShape({
* a: optional(-1),
* });
*
* // `myShape.runtimeType` is `{a?: number}`
* ```
*/
export function optional(part) {
return specifier([part], optionalSymbol);
}
/**
* ========================================

@@ -230,3 +281,3 @@ *

/**
* Checks if the input is an `and` shape specifier for internal type guarding purposes.
* Checks if the input is an {@link and} shape specifier for internal type guarding purposes.
*

@@ -239,3 +290,3 @@ * @category Internal

/**
* Checks if the input is a `classShape` shape specifier for internal type guarding purposes.
* Checks if the input is a {@link classShape} shape specifier for internal type guarding purposes.
*

@@ -248,3 +299,3 @@ * @category Internal

/**
* Checks if the input is an `enumShape` shape specifier for internal type guarding purposes.
* Checks if the input is an {@link enumShape} shape specifier for internal type guarding purposes.
*

@@ -257,3 +308,3 @@ * @category Internal

/**
* Checks if the input is an `exact` shape specifier for internal type guarding purposes.
* Checks if the input is an {@link exact} shape specifier for internal type guarding purposes.
*

@@ -266,3 +317,3 @@ * @category Internal

/**
* Checks if the input is an `indexedKeys` shape specifier for internal type guarding purposes.
* Checks if the input is an {@link indexedKeys} shape specifier for internal type guarding purposes.
*

@@ -275,3 +326,3 @@ * @category Internal

/**
* Checks if the input is an `or` shape specifier for internal type guarding purposes.
* Checks if the input is an {@link or} shape specifier for internal type guarding purposes.
*

@@ -284,3 +335,4 @@ * @category Internal

/**
* Checks if the input is an `unknown` shape specifier for internal type guarding purposes.
* Checks if the input is an {@link unknownShape} shape specifier for internal type guarding
* purposes.
*

@@ -293,2 +345,18 @@ * @category Internal

/**
* Checks if the input is a {@link numericRange} shape specifier for internal type guarding purposes.
*
* @category Internal
*/
export function isNumericRangeShapeSpecifier(maybeSpecifier) {
return specifierHasSymbol(maybeSpecifier, numericRangeSymbol);
}
/**
* Checks if the input is a {@link optional} shape specifier for internal type guarding purposes.
*
* @category Internal
*/
export function isOptionalShapeSpecifier(maybeSpecifier) {
return specifierHasSymbol(maybeSpecifier, optionalSymbol);
}
/**
* ========================================

@@ -319,3 +387,9 @@ *

if (specifier) {
if (isClassShapeSpecifier(specifier)) {
if (isNumericRangeShapeSpecifier(specifier)) {
if (!check.isNumber(subject)) {
return false;
}
return subject >= specifier.parts[0] && subject <= specifier.parts[1];
}
else if (isClassShapeSpecifier(specifier)) {
return subject instanceof specifier.parts[0];

@@ -322,0 +396,0 @@ }

import { check } from '@augment-vir/assert';
import { extractErrorMessage, mapObjectValues } from '@augment-vir/common';
import { DefaultValueConstructionError } from '../errors/default-value-construction.error.js';
import { expandIndexedKeysKeys, getShapeSpecifier, isAndShapeSpecifier, isClassShapeSpecifier, isEnumShapeSpecifier, isExactShapeSpecifier, isIndexedKeysSpecifier, isOrShapeSpecifier, isShapeDefinition, isUnknownShapeSpecifier, } from './shape-specifiers.js';
import { expandIndexedKeysKeys, getShapeSpecifier, isAndShapeSpecifier, isClassShapeSpecifier, isEnumShapeSpecifier, isExactShapeSpecifier, isIndexedKeysSpecifier, isNumericRangeShapeSpecifier, isOptionalShapeSpecifier, isOrShapeSpecifier, isShapeDefinition, isUnknownShapeSpecifier, } from './shape-specifiers.js';
export function shapeToDefaultValue(shape) {

@@ -11,3 +11,9 @@ return innerShapeToDefaultValue(shape);

if (specifier) {
if (isClassShapeSpecifier(specifier)) {
if (isOptionalShapeSpecifier(specifier)) {
return innerShapeToDefaultValue(specifier.parts[0]);
}
else if (isNumericRangeShapeSpecifier(specifier)) {
return specifier.parts[0];
}
else if (isClassShapeSpecifier(specifier)) {
const classConstructor = specifier.parts[0];

@@ -14,0 +20,0 @@ try {

import { check } from '@augment-vir/assert';
import { combineErrorMessages, ensureErrorAndPrependMessage, getObjectTypedKeys, mapObjectValues, } from '@augment-vir/common';
import { getShapeSpecifier, isAndShapeSpecifier, isClassShapeSpecifier, isEnumShapeSpecifier, isExactShapeSpecifier, isIndexedKeysSpecifier, isOrShapeSpecifier, isShapeDefinition, isUnknownShapeSpecifier, matchesShape, } from '../define-shape/shape-specifiers.js';
import { getShapeSpecifier, isAndShapeSpecifier, isClassShapeSpecifier, isEnumShapeSpecifier, isExactShapeSpecifier, isIndexedKeysSpecifier, isOptionalShapeSpecifier, isOrShapeSpecifier, isShapeDefinition, isUnknownShapeSpecifier, matchesShape, } from '../define-shape/shape-specifiers.js';
import { ShapeMismatchError } from '../errors/shape-mismatch.error.js';

@@ -94,2 +94,14 @@ /**

}
else if (isOptionalShapeSpecifier(shape)) {
/**
* The optional specifier does not add any extra restrictions when the subject actually
* exists. Thus, we'll just compare the subject to the optional shape's input.
*/
return internalAssertValidShape({
keys,
options,
shape: shape.parts[0],
subject,
});
}
else if (!matchesShape(subject, shape, !options.ignoreExtraKeys)) {

@@ -122,5 +134,3 @@ throw new ShapeMismatchError(`Subject does not match shape definition at key ${keysString}`);

keys,
options: {
...options,
},
options,
});

@@ -254,3 +264,3 @@ Object.assign(keysPassed, newKeysPassed);

else {
// if we have no specifier, pass in the whole shape itself
/** If we have no specifier, check the whole object. */
const newKeysPassed = isValidRawObjectShape({

@@ -303,4 +313,7 @@ keys,

shapeKeys.forEach((shapeKey) => {
// try to account for non-enumerable keys
if (shapeKey in subject) {
if (
/** Account for non-enumerable keys. */
shapeKey in subject ||
/** Account for optional keys. */
isOptionalShapeSpecifier(shape[shapeKey])) {
subjectKeys.add(shapeKey);

@@ -327,2 +340,7 @@ }

subjectKeys.forEach((key) => {
/** If the key doesn't exist and it's optional, mark it as passed. */
if (!(key in subject) && isOptionalShapeSpecifier(shape[key])) {
keysPassed[key] = true;
return;
}
const subjectChild = subject[key];

@@ -347,5 +365,5 @@ if (options.ignoreExtraKeys && !shapeKeys.has(key)) {

else {
throw new ShapeMismatchError(`shape definition at ${keysString} was not an object.`);
throw new ShapeMismatchError(`Shape definition at ${keysString} was not an object.`);
}
return keysPassed;
}

@@ -5,1 +5,2 @@ /**

*/
export {};

@@ -1,6 +0,1 @@

"use strict";
/* eslint-disable unicorn/no-empty-file */
/**
* This file is helpful for easy in-browser debugging. Simply run `npm start` to start a web-server
* that hosts it.
*/
export {};
{
"name": "object-shape-tester",
"version": "3.0.0",
"version": "3.1.0",
"description": "Test object properties and value types.",

@@ -5,0 +5,0 @@ "keywords": [

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