Comparing version 0.1.2 to 0.1.3
@@ -6,3 +6,3 @@ import { Type } from './type'; | ||
private ElementType; | ||
[__type_kind]: 'array'; | ||
readonly [__type_kind] = "array"; | ||
constructor(ElementType: TElementType); | ||
@@ -9,0 +9,0 @@ } |
@@ -22,3 +22,3 @@ "use strict"; | ||
writable: true, | ||
value: void 0 | ||
value: 'array' | ||
}); | ||
@@ -119,2 +119,13 @@ } | ||
} | ||
/** @internal */ | ||
_toJSONSchema(context, exact) { | ||
var _b; | ||
exact = (_b = this._exact) !== null && _b !== void 0 ? _b : exact; | ||
return { | ||
schema: context.define(this, exact, { | ||
type: 'array', | ||
items: this.ElementType._toJSONSchema(context, exact).schema, | ||
}), | ||
}; | ||
} | ||
} | ||
@@ -121,0 +132,0 @@ exports.ArrayType = ArrayType; |
@@ -0,1 +1,2 @@ | ||
import type { JSONSchema } from './json-schema'; | ||
import { Type } from './type'; | ||
@@ -6,6 +7,7 @@ import { __type_kind } from './type-partials'; | ||
private constraints; | ||
[__type_kind]: 'atomic'; | ||
constructor(symbol: TSymbol, constraints: AtomicTypeConstraint[]); | ||
private jsonSchema; | ||
readonly [__type_kind] = "atomic"; | ||
constructor(symbol: TSymbol, constraints: AtomicTypeConstraint[], jsonSchema?: JSONSchema); | ||
} | ||
export declare function atomic<TSymbol extends symbol>(symbol: TSymbol, constraints: AtomicTypeConstraint | AtomicTypeConstraint[]): AtomicType<TSymbol>; | ||
export declare function atomic<TSymbol extends symbol>(symbol: TSymbol, constraints: AtomicTypeConstraint | AtomicTypeConstraint[], jsonSchema?: JSONSchema): AtomicType<TSymbol>; | ||
export type AtomicTypeConstraint = (value: unknown) => void; | ||
@@ -12,0 +14,0 @@ type AtomicInMediums<TSymbol extends symbol> = { |
@@ -9,3 +9,3 @@ "use strict"; | ||
class AtomicType extends type_1.Type { | ||
constructor(symbol, constraints) { | ||
constructor(symbol, constraints, jsonSchema) { | ||
super(); | ||
@@ -24,2 +24,8 @@ Object.defineProperty(this, "symbol", { | ||
}); | ||
Object.defineProperty(this, "jsonSchema", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: jsonSchema | ||
}); | ||
Object.defineProperty(this, _a, { | ||
@@ -29,3 +35,3 @@ enumerable: true, | ||
writable: true, | ||
value: void 0 | ||
value: 'atomic' | ||
}); | ||
@@ -100,9 +106,19 @@ } | ||
} | ||
/** @internal */ | ||
_toJSONSchema() { | ||
const schema = this.jsonSchema; | ||
if (!schema) { | ||
throw new TypeError('JSON schema is not defined for this atomic type'); | ||
} | ||
return { | ||
schema, | ||
}; | ||
} | ||
} | ||
exports.AtomicType = AtomicType; | ||
_a = type_partials_1.__type_kind; | ||
function atomic(symbol, constraints) { | ||
return new AtomicType(symbol, Array.isArray(constraints) ? constraints : [constraints]); | ||
function atomic(symbol, constraints, jsonSchema) { | ||
return new AtomicType(symbol, Array.isArray(constraints) ? constraints : [constraints], jsonSchema); | ||
} | ||
exports.atomic = atomic; | ||
//# sourceMappingURL=atomic-type.js.map |
@@ -8,3 +8,3 @@ import type { Medium, MediumName } from './medium'; | ||
private ReturnType; | ||
[__type_kind]: 'function'; | ||
readonly [__type_kind] = "function"; | ||
constructor(ArgumentTypeTuple: TArgumentTypeTuple, ReturnType: TReturnType); | ||
@@ -11,0 +11,0 @@ guard<TFunction extends this[__type_in_mediums]['value']>(fn: TFunction): this[__type_in_mediums]['value']; |
@@ -27,3 +27,3 @@ "use strict"; | ||
writable: true, | ||
value: void 0 | ||
value: 'function' | ||
}); | ||
@@ -146,2 +146,6 @@ } | ||
} | ||
/** @internal */ | ||
_toJSONSchema() { | ||
throw new TypeError('Cannot convert Function type to JSON Schema'); | ||
} | ||
} | ||
@@ -148,0 +152,0 @@ exports.FunctionType = FunctionType; |
@@ -16,1 +16,2 @@ export * from './medium'; | ||
export * from './function-type'; | ||
export * from './json-schema'; |
@@ -19,2 +19,3 @@ "use strict"; | ||
tslib_1.__exportStar(require("./function-type"), exports); | ||
tslib_1.__exportStar(require("./json-schema"), exports); | ||
//# sourceMappingURL=index.js.map |
@@ -11,3 +11,3 @@ import type { TupleInMedium } from './@utils'; | ||
private TypeTuple; | ||
[__type_kind]: 'intersection'; | ||
readonly [__type_kind] = "intersection"; | ||
constructor(TypeTuple: TTypeTuple); | ||
@@ -27,3 +27,3 @@ } | ||
] ? T & __Intersection<TRestTuple> : unknown; | ||
export declare function _mergeIntersectionPartials(partials: unknown[]): unknown; | ||
export declare function internal_mergeIntersectionPartials(partials: unknown[]): unknown; | ||
export {}; |
"use strict"; | ||
var _a; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports._mergeIntersectionPartials = exports.intersection = exports.IntersectionType = void 0; | ||
exports.internal_mergeIntersectionPartials = exports.intersection = exports.IntersectionType = void 0; | ||
const _type_issue_1 = require("./@type-issue"); | ||
@@ -25,3 +25,3 @@ const type_1 = require("./type"); | ||
writable: true, | ||
value: void 0 | ||
value: 'intersection' | ||
}); | ||
@@ -45,3 +45,3 @@ } | ||
? undefined | ||
: _mergeIntersectionPartials(partials), | ||
: internal_mergeIntersectionPartials(partials), | ||
issues, | ||
@@ -68,3 +68,3 @@ ]; | ||
? undefined | ||
: _mergeIntersectionPartials(partials), | ||
: internal_mergeIntersectionPartials(partials), | ||
issues, | ||
@@ -89,3 +89,3 @@ ]; | ||
? undefined | ||
: _mergeIntersectionPartials(partials), | ||
: internal_mergeIntersectionPartials(partials), | ||
issues, | ||
@@ -103,2 +103,18 @@ ]; | ||
} | ||
/** @internal */ | ||
_toJSONSchema(context, exact) { | ||
var _b; | ||
exact = (_b = this._exact) !== null && _b !== void 0 ? _b : exact; | ||
const schemas = this.TypeTuple.map(Type => Type._toJSONSchema(context, exact).schema); | ||
let mergedSchema = mergeIntersectionJSONSchemas(context, schemas); | ||
if (exact && mergedSchema.additionalProperties === undefined) { | ||
mergedSchema = { | ||
...mergedSchema, | ||
additionalProperties: false, | ||
}; | ||
} | ||
return { | ||
schema: context.define(this, exact, mergedSchema), | ||
}; | ||
} | ||
} | ||
@@ -111,3 +127,3 @@ exports.IntersectionType = IntersectionType; | ||
exports.intersection = intersection; | ||
function _mergeIntersectionPartials(partials) { | ||
function internal_mergeIntersectionPartials(partials) { | ||
let pendingMergeKeyToValues; | ||
@@ -146,3 +162,3 @@ const merged = partials.reduce((merged, partial) => { | ||
for (const [key, values] of pendingMergeKeyToValues) { | ||
merged[key] = _mergeIntersectionPartials(values); | ||
merged[key] = internal_mergeIntersectionPartials(values); | ||
} | ||
@@ -152,3 +168,45 @@ } | ||
} | ||
exports._mergeIntersectionPartials = _mergeIntersectionPartials; | ||
exports.internal_mergeIntersectionPartials = internal_mergeIntersectionPartials; | ||
function mergeIntersectionJSONSchemas(context, schemas) { | ||
const requiredSet = new Set(); | ||
const properties = {}; | ||
let additionalProperties; | ||
for (let schema of schemas) { | ||
if (schema.$ref) { | ||
schema = context.requireDefinitionByRef(schema.$ref); | ||
} | ||
if (schema.type !== 'object') { | ||
throw new TypeError('Cannot merge non-object JSON schemas'); | ||
} | ||
if (schema.required) { | ||
for (const key of schema.required) { | ||
requiredSet.add(key); | ||
} | ||
} | ||
if (schema.properties) { | ||
for (const [key, propertySchema] of Object.entries(schema.properties)) { | ||
if (hasOwnProperty.call(properties, key)) { | ||
properties[key] = mergeIntersectionJSONSchemas(context, [ | ||
properties[key], | ||
propertySchema, | ||
]); | ||
} | ||
else { | ||
properties[key] = propertySchema; | ||
} | ||
} | ||
} | ||
if (schema.additionalProperties !== undefined) { | ||
additionalProperties = schema.additionalProperties; | ||
} | ||
} | ||
return { | ||
type: 'object', | ||
required: Array.from(requiredSet), | ||
properties, | ||
...(additionalProperties !== undefined | ||
? { additionalProperties } | ||
: undefined), | ||
}; | ||
} | ||
//# sourceMappingURL=intersection-type.js.map |
@@ -7,3 +7,3 @@ import { OptionalType } from './optional-type'; | ||
private definition; | ||
[__type_kind]: 'object'; | ||
readonly [__type_kind] = "object"; | ||
constructor(definition: TDefinition); | ||
@@ -10,0 +10,0 @@ extend<TDefinitionExtension extends Record<string, TypeInMediumsPartial>>(extension: ObjectType<TDefinitionExtension> | TDefinitionExtension): ObjectType<Omit<TDefinition, keyof TDefinitionExtension> & TDefinitionExtension>; |
@@ -23,3 +23,3 @@ "use strict"; | ||
writable: true, | ||
value: void 0 | ||
value: 'object' | ||
}); | ||
@@ -188,2 +188,24 @@ } | ||
} | ||
/** @internal */ | ||
_toJSONSchema(context, exact) { | ||
var _b; | ||
exact = (_b = this._exact) !== null && _b !== void 0 ? _b : exact; | ||
const required = []; | ||
const properties = {}; | ||
for (const [key, Type] of Object.entries(this.definition)) { | ||
const { schema, optional = false } = Type._toJSONSchema(context, exact); | ||
if (!optional) { | ||
required.push(key); | ||
} | ||
properties[key] = schema; | ||
} | ||
return { | ||
schema: context.define(this, exact, { | ||
type: 'object', | ||
required, | ||
properties, | ||
...(exact ? { additionalProperties: false } : undefined), | ||
}), | ||
}; | ||
} | ||
} | ||
@@ -190,0 +212,0 @@ exports.ObjectType = ObjectType; |
@@ -6,3 +6,3 @@ import { TypeLike } from './type-like'; | ||
private Type; | ||
[__type_kind]: 'optional'; | ||
readonly [__type_kind] = "optional"; | ||
constructor(Type: TType); | ||
@@ -9,0 +9,0 @@ } |
@@ -21,3 +21,3 @@ "use strict"; | ||
writable: true, | ||
value: void 0 | ||
value: 'optional' | ||
}); | ||
@@ -47,2 +47,10 @@ } | ||
} | ||
/** @internal */ | ||
_toJSONSchema(context, exact) { | ||
const { schema } = this.Type._toJSONSchema(context, exact); | ||
return { | ||
schema, | ||
optional: true, | ||
}; | ||
} | ||
} | ||
@@ -49,0 +57,0 @@ exports.OptionalType = OptionalType; |
@@ -7,3 +7,3 @@ import { Type } from './type'; | ||
private Value; | ||
[__type_kind]: 'record'; | ||
readonly [__type_kind] = "record"; | ||
constructor(Key: TKeyType, Value: TValueType); | ||
@@ -10,0 +10,0 @@ } |
@@ -28,3 +28,3 @@ "use strict"; | ||
writable: true, | ||
value: void 0 | ||
value: 'record' | ||
}); | ||
@@ -146,2 +146,14 @@ } | ||
} | ||
/** @internal */ | ||
_toJSONSchema(context, exact) { | ||
var _b; | ||
exact = (_b = this._exact) !== null && _b !== void 0 ? _b : exact; | ||
return { | ||
schema: context.define(this, exact, { | ||
type: 'object', | ||
propertyNames: this.Key._toJSONSchema(context, exact).schema, | ||
additionalProperties: this.Value._toJSONSchema(context, exact).schema, | ||
}), | ||
}; | ||
} | ||
} | ||
@@ -148,0 +160,0 @@ exports.RecordType = RecordType; |
@@ -5,5 +5,6 @@ import { Type } from './type'; | ||
export declare class RecursiveType<TRecursive> extends Type<RecursiveInMediums<TRecursive>> { | ||
[__type_kind]: 'recursive'; | ||
readonly [__type_kind] = "recursive"; | ||
private Type; | ||
constructor(recursion: (Type: RecursiveType<TRecursive>) => TypeInMediumsPartial); | ||
private static jsonSchemaContext; | ||
} | ||
@@ -10,0 +11,0 @@ export declare function recursive<T>(recursion: (Type: RecursiveType<T>) => TypeInMediumsPartial): RecursiveType<T>; |
@@ -14,3 +14,3 @@ "use strict"; | ||
writable: true, | ||
value: void 0 | ||
value: 'recursive' | ||
}); | ||
@@ -41,2 +41,20 @@ Object.defineProperty(this, "Type", { | ||
} | ||
/** @internal */ | ||
_toJSONSchema(context, exact) { | ||
var _b; | ||
exact = (_b = this._exact) !== null && _b !== void 0 ? _b : exact; | ||
const schema = context.getDefinition(this, exact); | ||
if (schema) { | ||
return { | ||
schema, | ||
}; | ||
} | ||
else { | ||
context.define(this, exact); | ||
const { schema } = this.Type._toJSONSchema(context, exact); | ||
return { | ||
schema: context.define(this, exact, schema), | ||
}; | ||
} | ||
} | ||
} | ||
@@ -43,0 +61,0 @@ exports.RecursiveType = RecursiveType; |
@@ -7,3 +7,3 @@ import { Type } from './type'; | ||
private refinements; | ||
[__type_kind]: 'refined'; | ||
readonly [__type_kind] = "refined"; | ||
constructor(Type: TType, refinements: Refinement[]); | ||
@@ -10,0 +10,0 @@ private processRefinements; |
@@ -27,3 +27,3 @@ "use strict"; | ||
writable: true, | ||
value: void 0 | ||
value: 'refined' | ||
}); | ||
@@ -85,2 +85,7 @@ } | ||
} | ||
/** @internal */ | ||
_toJSONSchema(context, exact) { | ||
var _b; | ||
return this.Type._toJSONSchema(context, (_b = this._exact) !== null && _b !== void 0 ? _b : exact); | ||
} | ||
processRefinements(value, path) { | ||
@@ -87,0 +92,0 @@ const issues = []; |
@@ -7,3 +7,3 @@ import type { TupleInMedium } from './@utils'; | ||
private ElementTypeTuple; | ||
[__type_kind]: 'tuple'; | ||
readonly [__type_kind] = "tuple"; | ||
constructor(ElementTypeTuple: TElementTypeTuple); | ||
@@ -10,0 +10,0 @@ } |
@@ -22,3 +22,3 @@ "use strict"; | ||
writable: true, | ||
value: void 0 | ||
value: 'tuple' | ||
}); | ||
@@ -160,2 +160,13 @@ } | ||
} | ||
/** @internal */ | ||
_toJSONSchema(context, exact) { | ||
var _b; | ||
exact = (_b = this._exact) !== null && _b !== void 0 ? _b : exact; | ||
return { | ||
schema: context.define(this, exact, { | ||
type: 'array', | ||
prefixItems: this.ElementTypeTuple.map(Element => Element._toJSONSchema(context, exact).schema), | ||
}), | ||
}; | ||
} | ||
} | ||
@@ -162,0 +173,0 @@ exports.TupleType = TupleType; |
@@ -0,6 +1,22 @@ | ||
import type { JSONSchema } from './json-schema'; | ||
import { __type_in_mediums, __type_kind } from './type-partials'; | ||
import type { TypesInMediums } from './type-partials'; | ||
export declare abstract class TypeLike<TInMediums extends TypesInMediums = TypesInMediums> { | ||
[__type_kind]: string; | ||
abstract [__type_kind]: string; | ||
[__type_in_mediums]: TInMediums; | ||
} | ||
export declare class JSONSchemaContext { | ||
private lastId; | ||
private typeIdMap; | ||
private exactTypeIdMap; | ||
private refToDefinitionMap; | ||
readonly definitions: Record<string, JSONSchema>; | ||
define(Type: TypeLike, exact: boolean): void; | ||
define(Type: TypeLike, exact: boolean, definition: JSONSchema): JSONSchema; | ||
getDefinition(Type: TypeLike, exact: boolean): JSONSchema | undefined; | ||
requireDefinitionByRef(ref: string): JSONSchema; | ||
} | ||
export interface JSONSchemaData { | ||
schema: JSONSchema; | ||
optional?: boolean; | ||
} |
"use strict"; | ||
var _a, _b; | ||
var _a; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.TypeLike = void 0; | ||
exports.JSONSchemaContext = exports.TypeLike = void 0; | ||
const type_partials_1 = require("./type-partials"); | ||
@@ -14,12 +14,76 @@ class TypeLike { | ||
}); | ||
Object.defineProperty(this, _b, { | ||
} | ||
} | ||
exports.TypeLike = TypeLike; | ||
_a = type_partials_1.__type_in_mediums; | ||
function JSON_SCHEMA_TYPE_KEY(id) { | ||
return `type-${id}`; | ||
} | ||
function JSON_SCHEMA_TYPE_REF(id) { | ||
return `#/$defs/${JSON_SCHEMA_TYPE_KEY(id)}`; | ||
} | ||
class JSONSchemaContext { | ||
constructor() { | ||
Object.defineProperty(this, "lastId", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
value: 0 | ||
}); | ||
Object.defineProperty(this, "typeIdMap", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: new Map() | ||
}); | ||
Object.defineProperty(this, "exactTypeIdMap", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: new Map() | ||
}); | ||
Object.defineProperty(this, "refToDefinitionMap", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: new Map() | ||
}); | ||
Object.defineProperty(this, "definitions", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: {} | ||
}); | ||
} | ||
define(Type, exact, definition) { | ||
const typeIdMap = exact ? this.exactTypeIdMap : this.typeIdMap; | ||
let id = typeIdMap.get(Type); | ||
if (id === undefined) { | ||
id = ++this.lastId; | ||
typeIdMap.set(Type, id); | ||
} | ||
if (definition) { | ||
this.definitions[JSON_SCHEMA_TYPE_KEY(id)] = definition; | ||
const ref = JSON_SCHEMA_TYPE_REF(id); | ||
this.refToDefinitionMap.set(ref, definition); | ||
return { $ref: ref }; | ||
} | ||
} | ||
getDefinition(Type, exact) { | ||
const typeIdMap = exact ? this.exactTypeIdMap : this.typeIdMap; | ||
const id = typeIdMap.get(Type); | ||
return typeof id === 'number' | ||
? { $ref: JSON_SCHEMA_TYPE_REF(id) } | ||
: undefined; | ||
} | ||
requireDefinitionByRef(ref) { | ||
const schema = this.refToDefinitionMap.get(ref); | ||
/* istanbul ignore if */ | ||
if (!schema) { | ||
throw new Error('Invalid JSON Schema reference'); | ||
} | ||
return schema; | ||
} | ||
} | ||
exports.TypeLike = TypeLike; | ||
_a = type_partials_1.__type_kind, _b = type_partials_1.__type_in_mediums; | ||
exports.JSONSchemaContext = JSONSchemaContext; | ||
//# sourceMappingURL=type-like.js.map |
import type { Exact } from './@exact-context'; | ||
import { ExactContext } from './@exact-context'; | ||
import type { TypeIssue } from './@type-issue'; | ||
import type { JSONSchema } from './json-schema'; | ||
import type { Medium, MediumTypesPackedType } from './medium'; | ||
@@ -23,2 +24,3 @@ import { TypeLike } from './type-like'; | ||
diagnose(value: unknown): TypeIssue[]; | ||
toJSONSchema(): JSONSchema; | ||
protected getExactContext(exact: Exact, wrapper: 'managed'): { | ||
@@ -25,0 +27,0 @@ context: ExactContext | undefined; |
@@ -67,2 +67,10 @@ "use strict"; | ||
} | ||
toJSONSchema() { | ||
var _a; | ||
const context = new type_like_1.JSONSchemaContext(); | ||
return { | ||
...this._toJSONSchema(context, (_a = this._exact) !== null && _a !== void 0 ? _a : false).schema, | ||
$defs: context.definitions, | ||
}; | ||
} | ||
getExactContext(exact, wrapper) { | ||
@@ -69,0 +77,0 @@ const context = typeof exact === 'boolean' ? undefined : exact; |
@@ -11,3 +11,3 @@ import type { TupleInMedium } from './@utils'; | ||
private TypeTuple; | ||
[__type_kind]: 'union'; | ||
readonly [__type_kind] = "union"; | ||
constructor(TypeTuple: TTypeTuple); | ||
@@ -14,0 +14,0 @@ } |
@@ -25,3 +25,3 @@ "use strict"; | ||
writable: true, | ||
value: void 0 | ||
value: 'union' | ||
}); | ||
@@ -149,2 +149,13 @@ } | ||
} | ||
/** @internal */ | ||
_toJSONSchema(context, exact) { | ||
var _b; | ||
exact = (_b = this._exact) !== null && _b !== void 0 ? _b : exact; | ||
const schemas = this.TypeTuple.map(Type => Type._toJSONSchema(context, exact).schema); | ||
return { | ||
schema: context.define(this, exact, { | ||
anyOf: schemas, | ||
}), | ||
}; | ||
} | ||
} | ||
@@ -151,0 +162,0 @@ exports.UnionType = UnionType; |
@@ -12,3 +12,3 @@ "use strict"; | ||
exports.unknownTypeSymbol = Symbol(); | ||
exports.unknown = (0, core_1.atomic)(exports.unknownTypeSymbol, []); | ||
exports.unknown = (0, core_1.atomic)(exports.unknownTypeSymbol, [], {}); | ||
exports.undefinedTypeSymbol = Symbol(); | ||
@@ -20,11 +20,11 @@ exports.undefined = (0, core_1.atomic)(exports.undefinedTypeSymbol, value => (0, utils_1.constraint)(value === void 0, () => `Expected undefined, getting ${toString.call(value)}.`)); | ||
exports.nullTypeSymbol = Symbol(); | ||
exports.nullType = (0, core_1.atomic)(exports.nullTypeSymbol, value => (0, utils_1.constraint)(value === null, () => `Expected null, getting ${toString.call(value)}.`)); | ||
exports.nullType = (0, core_1.atomic)(exports.nullTypeSymbol, value => (0, utils_1.constraint)(value === null, () => `Expected null, getting ${toString.call(value)}.`), { type: 'null' }); | ||
exports.stringTypeSymbol = Symbol(); | ||
exports.string = (0, core_1.atomic)(exports.stringTypeSymbol, value => (0, utils_1.constraint)(typeof value === 'string', () => `Expected string, getting ${toString.call(value)}.`)); | ||
exports.string = (0, core_1.atomic)(exports.stringTypeSymbol, value => (0, utils_1.constraint)(typeof value === 'string', () => `Expected string, getting ${toString.call(value)}.`), { type: 'string' }); | ||
exports.numberTypeSymbol = Symbol(); | ||
exports.number = (0, core_1.atomic)(exports.numberTypeSymbol, value => (0, utils_1.constraint)(typeof value === 'number', () => `Expected number, getting ${toString.call(value)}.`)); | ||
exports.number = (0, core_1.atomic)(exports.numberTypeSymbol, value => (0, utils_1.constraint)(typeof value === 'number', () => `Expected number, getting ${toString.call(value)}.`), { type: 'number' }); | ||
exports.bigintTypeSymbol = Symbol(); | ||
exports.bigint = (0, core_1.atomic)(exports.bigintTypeSymbol, value => (0, utils_1.constraint)(typeof value === 'bigint', () => `Expected bigint, getting ${toString.call(value)}.`)); | ||
exports.bigint = (0, core_1.atomic)(exports.bigintTypeSymbol, value => (0, utils_1.constraint)(typeof value === 'bigint', () => `Expected bigint, getting ${toString.call(value)}.`), { type: 'integer' }); | ||
exports.booleanTypeSymbol = Symbol(); | ||
exports.boolean = (0, core_1.atomic)(exports.booleanTypeSymbol, value => (0, utils_1.constraint)(typeof value === 'boolean', () => `Expected boolean, getting ${toString.call(value)}.`)); | ||
exports.boolean = (0, core_1.atomic)(exports.booleanTypeSymbol, value => (0, utils_1.constraint)(typeof value === 'boolean', () => `Expected boolean, getting ${toString.call(value)}.`), { type: 'boolean' }); | ||
exports.functionTypeSymbol = Symbol(); | ||
@@ -31,0 +31,0 @@ exports.Function = (0, core_1.atomic)(exports.functionTypeSymbol, value => (0, utils_1.constraint)(typeof value === 'function', () => `Expected function, getting ${toString.call(value)}.`)); |
{ | ||
"name": "x-value", | ||
"version": "0.1.2", | ||
"version": "0.1.3", | ||
"repository": "https://github.com/vilic/x-value.git", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
@@ -6,2 +6,3 @@ import type {Exact} from './@exact-context'; | ||
import {DISABLED_EXACT_CONTEXT_RESULT, Type} from './type'; | ||
import type {JSONSchemaContext, JSONSchemaData} from './type-like'; | ||
import type {TypeInMediumsPartial, __type_in_mediums} from './type-partials'; | ||
@@ -15,3 +16,3 @@ import {__type_kind} from './type-partials'; | ||
> { | ||
[__type_kind]!: 'array'; | ||
readonly [__type_kind] = 'array'; | ||
@@ -189,2 +190,14 @@ constructor(ElementType: TElementType); | ||
} | ||
/** @internal */ | ||
_toJSONSchema(context: JSONSchemaContext, exact: boolean): JSONSchemaData { | ||
exact = this._exact ?? exact; | ||
return { | ||
schema: context.define(this, exact, { | ||
type: 'array', | ||
items: this.ElementType._toJSONSchema(context, exact).schema, | ||
}), | ||
}; | ||
} | ||
} | ||
@@ -191,0 +204,0 @@ |
import type {Exact} from './@exact-context'; | ||
import type {TypeIssue, TypePath} from './@type-issue'; | ||
import {buildIssueByError, hasNonDeferrableTypeIssue} from './@type-issue'; | ||
import type {JSONSchema} from './json-schema'; | ||
import type {Medium} from './medium'; | ||
import {Type} from './type'; | ||
import type {JSONSchemaData} from './type-like'; | ||
import {__type_kind} from './type-partials'; | ||
@@ -11,8 +13,13 @@ | ||
> { | ||
[__type_kind]!: 'atomic'; | ||
readonly [__type_kind] = 'atomic'; | ||
constructor(symbol: TSymbol, constraints: AtomicTypeConstraint[]); | ||
constructor( | ||
symbol: TSymbol, | ||
constraints: AtomicTypeConstraint[], | ||
jsonSchema?: JSONSchema, | ||
); | ||
constructor( | ||
private symbol: symbol, | ||
private constraints: AtomicTypeConstraint[], | ||
private jsonSchema: JSONSchema | undefined, | ||
) { | ||
@@ -118,2 +125,15 @@ super(); | ||
} | ||
/** @internal */ | ||
_toJSONSchema(): JSONSchemaData { | ||
const schema = this.jsonSchema; | ||
if (!schema) { | ||
throw new TypeError('JSON schema is not defined for this atomic type'); | ||
} | ||
return { | ||
schema, | ||
}; | ||
} | ||
} | ||
@@ -124,2 +144,3 @@ | ||
constraints: AtomicTypeConstraint | AtomicTypeConstraint[], | ||
jsonSchema?: JSONSchema, | ||
): AtomicType<TSymbol> { | ||
@@ -129,2 +150,3 @@ return new AtomicType( | ||
Array.isArray(constraints) ? constraints : [constraints], | ||
jsonSchema, | ||
); | ||
@@ -131,0 +153,0 @@ } |
@@ -14,3 +14,3 @@ import type {Exact} from './@exact-context'; | ||
> extends Type<FunctionInMediums<TArgumentTypeTuple, TReturnType>> { | ||
[__type_kind]!: 'function'; | ||
readonly [__type_kind] = 'function'; | ||
@@ -223,2 +223,7 @@ constructor(ArgumentTypeTuple: TArgumentTypeTuple, ReturnType: TReturnType); | ||
} | ||
/** @internal */ | ||
_toJSONSchema(): never { | ||
throw new TypeError('Cannot convert Function type to JSON Schema'); | ||
} | ||
} | ||
@@ -225,0 +230,0 @@ |
@@ -16,1 +16,2 @@ export * from './medium'; | ||
export * from './function-type'; | ||
export * from './json-schema'; |
@@ -5,4 +5,6 @@ import type {Exact} from './@exact-context'; | ||
import type {TupleInMedium} from './@utils'; | ||
import type {JSONSchema} from './json-schema'; | ||
import type {Medium} from './medium'; | ||
import {DISABLED_EXACT_CONTEXT_RESULT, Type} from './type'; | ||
import type {JSONSchemaContext, JSONSchemaData} from './type-like'; | ||
import {__type_kind} from './type-partials'; | ||
@@ -20,3 +22,3 @@ import type {TypeInMediumsPartial} from './type-partials'; | ||
> extends Type<IntersectionInMediums<TTypeTuple>> { | ||
[__type_kind]!: 'intersection'; | ||
readonly [__type_kind] = 'intersection'; | ||
@@ -66,3 +68,3 @@ constructor(TypeTuple: TTypeTuple); | ||
? undefined | ||
: _mergeIntersectionPartials(partials), | ||
: internal_mergeIntersectionPartials(partials), | ||
issues, | ||
@@ -107,3 +109,3 @@ ]; | ||
? undefined | ||
: _mergeIntersectionPartials(partials), | ||
: internal_mergeIntersectionPartials(partials), | ||
issues, | ||
@@ -149,3 +151,3 @@ ]; | ||
? undefined | ||
: _mergeIntersectionPartials(partials), | ||
: internal_mergeIntersectionPartials(partials), | ||
issues, | ||
@@ -172,2 +174,24 @@ ]; | ||
} | ||
/** @internal */ | ||
_toJSONSchema(context: JSONSchemaContext, exact: boolean): JSONSchemaData { | ||
exact = this._exact ?? exact; | ||
const schemas = this.TypeTuple.map( | ||
Type => Type._toJSONSchema(context, exact).schema, | ||
); | ||
let mergedSchema = mergeIntersectionJSONSchemas(context, schemas); | ||
if (exact && mergedSchema.additionalProperties === undefined) { | ||
mergedSchema = { | ||
...mergedSchema, | ||
additionalProperties: false, | ||
}; | ||
} | ||
return { | ||
schema: context.define(this, exact, mergedSchema), | ||
}; | ||
} | ||
} | ||
@@ -198,3 +222,5 @@ | ||
export function _mergeIntersectionPartials(partials: unknown[]): unknown { | ||
export function internal_mergeIntersectionPartials( | ||
partials: unknown[], | ||
): unknown { | ||
let pendingMergeKeyToValues: Map<string | number, unknown[]> | undefined; | ||
@@ -240,3 +266,3 @@ | ||
for (const [key, values] of pendingMergeKeyToValues) { | ||
(merged as any)[key] = _mergeIntersectionPartials(values); | ||
(merged as any)[key] = internal_mergeIntersectionPartials(values); | ||
} | ||
@@ -247,1 +273,54 @@ } | ||
} | ||
function mergeIntersectionJSONSchemas( | ||
context: JSONSchemaContext, | ||
schemas: JSONSchema[], | ||
): JSONSchema { | ||
const requiredSet = new Set<string>(); | ||
const properties: Record<string, JSONSchema> = {}; | ||
let additionalProperties: JSONSchema | boolean | undefined; | ||
for (let schema of schemas) { | ||
if (schema.$ref) { | ||
schema = context.requireDefinitionByRef(schema.$ref); | ||
} | ||
if (schema.type !== 'object') { | ||
throw new TypeError('Cannot merge non-object JSON schemas'); | ||
} | ||
if (schema.required) { | ||
for (const key of schema.required) { | ||
requiredSet.add(key); | ||
} | ||
} | ||
if (schema.properties) { | ||
for (const [key, propertySchema] of Object.entries(schema.properties)) { | ||
if (hasOwnProperty.call(properties, key)) { | ||
properties[key] = mergeIntersectionJSONSchemas(context, [ | ||
properties[key], | ||
propertySchema, | ||
]); | ||
} else { | ||
properties[key] = propertySchema; | ||
} | ||
} | ||
} | ||
if (schema.additionalProperties !== undefined) { | ||
additionalProperties = schema.additionalProperties; | ||
} | ||
} | ||
return { | ||
type: 'object', | ||
required: Array.from(requiredSet), | ||
properties, | ||
...(additionalProperties !== undefined | ||
? {additionalProperties} | ||
: undefined), | ||
}; | ||
} |
import type {Exact} from './@exact-context'; | ||
import type {TypeIssue, TypePath} from './@type-issue'; | ||
import {hasNonDeferrableTypeIssue} from './@type-issue'; | ||
import type {JSONSchema} from './json-schema'; | ||
import type {Medium} from './medium'; | ||
import {OptionalType} from './optional-type'; | ||
import {Type} from './type'; | ||
import type {TypeLike} from './type-like'; | ||
import type {JSONSchemaContext, JSONSchemaData, TypeLike} from './type-like'; | ||
import type { | ||
@@ -20,3 +21,3 @@ TypeInMediumsPartial, | ||
> extends Type<ObjectInMediums<TDefinition>> { | ||
[__type_kind]!: 'object'; | ||
readonly [__type_kind] = 'object'; | ||
@@ -295,2 +296,30 @@ constructor(definition: TDefinition); | ||
} | ||
/** @internal */ | ||
_toJSONSchema(context: JSONSchemaContext, exact: boolean): JSONSchemaData { | ||
exact = this._exact ?? exact; | ||
const required: string[] = []; | ||
const properties: Record<string, JSONSchema> = {}; | ||
for (const [key, Type] of Object.entries(this.definition)) { | ||
const {schema, optional = false} = Type._toJSONSchema(context, exact); | ||
if (!optional) { | ||
required.push(key); | ||
} | ||
properties[key] = schema; | ||
} | ||
return { | ||
schema: context.define(this, exact, { | ||
type: 'object', | ||
required, | ||
properties, | ||
...(exact ? {additionalProperties: false} : undefined), | ||
}), | ||
}; | ||
} | ||
} | ||
@@ -297,0 +326,0 @@ |
@@ -5,2 +5,3 @@ import type {Exact} from './@exact-context'; | ||
import {Type} from './type'; | ||
import type {JSONSchemaContext, JSONSchemaData} from './type-like'; | ||
import {TypeLike} from './type-like'; | ||
@@ -13,3 +14,3 @@ import type {TypeInMediumsPartial, __type_in_mediums} from './type-partials'; | ||
> { | ||
[__type_kind]!: 'optional'; | ||
readonly [__type_kind] = 'optional'; | ||
@@ -63,2 +64,12 @@ constructor(Type: TType); | ||
} | ||
/** @internal */ | ||
_toJSONSchema(context: JSONSchemaContext, exact: boolean): JSONSchemaData { | ||
const {schema} = this.Type._toJSONSchema(context, exact); | ||
return { | ||
schema, | ||
optional: true, | ||
}; | ||
} | ||
} | ||
@@ -65,0 +76,0 @@ |
@@ -6,2 +6,3 @@ import type {Exact} from './@exact-context'; | ||
import {DISABLED_EXACT_CONTEXT_RESULT, Type} from './type'; | ||
import type {JSONSchemaContext, JSONSchemaData} from './type-like'; | ||
import type {TypeInMediumsPartial, __type_in_mediums} from './type-partials'; | ||
@@ -16,3 +17,3 @@ import {__type_kind} from './type-partials'; | ||
> extends Type<RecordInMediums<TKeyType, TValueType>> { | ||
[__type_kind]!: 'record'; | ||
readonly [__type_kind] = 'record'; | ||
@@ -217,2 +218,15 @@ constructor(Key: TKeyType, Value: TValueType); | ||
} | ||
/** @internal */ | ||
_toJSONSchema(context: JSONSchemaContext, exact: boolean): JSONSchemaData { | ||
exact = this._exact ?? exact; | ||
return { | ||
schema: context.define(this, exact, { | ||
type: 'object', | ||
propertyNames: this.Key._toJSONSchema(context, exact).schema, | ||
additionalProperties: this.Value._toJSONSchema(context, exact).schema, | ||
}), | ||
}; | ||
} | ||
} | ||
@@ -219,0 +233,0 @@ |
@@ -5,2 +5,3 @@ import type {Exact} from './@exact-context'; | ||
import {Type} from './type'; | ||
import type {JSONSchemaContext, JSONSchemaData} from './type-like'; | ||
import {__type_kind} from './type-partials'; | ||
@@ -12,3 +13,3 @@ import type {TypeInMediumsPartial} from './type-partials'; | ||
> { | ||
[__type_kind]!: 'recursive'; | ||
readonly [__type_kind] = 'recursive'; | ||
@@ -62,2 +63,27 @@ private Type: Type; | ||
} | ||
/** @internal */ | ||
_toJSONSchema(context: JSONSchemaContext, exact: boolean): JSONSchemaData { | ||
exact = this._exact ?? exact; | ||
const schema = context.getDefinition(this, exact); | ||
if (schema) { | ||
return { | ||
schema, | ||
}; | ||
} else { | ||
context.define(this, exact); | ||
const {schema} = this.Type._toJSONSchema(context, exact); | ||
return { | ||
schema: context.define(this, exact, schema), | ||
}; | ||
} | ||
} | ||
private static jsonSchemaContext: | ||
| Map<RecursiveType<unknown>, string> | ||
| undefined; | ||
} | ||
@@ -64,0 +90,0 @@ |
@@ -6,2 +6,3 @@ import type {Exact} from './@exact-context'; | ||
import {Type} from './type'; | ||
import type {JSONSchemaContext, JSONSchemaData} from './type-like'; | ||
import type { | ||
@@ -19,3 +20,3 @@ TypeInMediumsPartial, | ||
> extends Type<RefinedInMediums<TType, TNominalKey, TRefinement>> { | ||
[__type_kind]!: 'refined'; | ||
readonly [__type_kind] = 'refined'; | ||
@@ -129,2 +130,7 @@ constructor(Type: TType, refinements: Refinement[]); | ||
/** @internal */ | ||
_toJSONSchema(context: JSONSchemaContext, exact: boolean): JSONSchemaData { | ||
return this.Type._toJSONSchema(context, this._exact ?? exact); | ||
} | ||
private processRefinements( | ||
@@ -131,0 +137,0 @@ value: unknown, |
@@ -7,2 +7,3 @@ import type {Exact} from './@exact-context'; | ||
import {DISABLED_EXACT_CONTEXT_RESULT, Type} from './type'; | ||
import type {JSONSchemaContext, JSONSchemaData} from './type-like'; | ||
import {__type_kind} from './type-partials'; | ||
@@ -16,3 +17,3 @@ import type {TypeInMediumsPartial} from './type-partials'; | ||
> extends Type<TupleInMediums<TElementTypeTuple>> { | ||
[__type_kind]!: 'tuple'; | ||
readonly [__type_kind] = 'tuple'; | ||
@@ -243,2 +244,16 @@ constructor(ElementTypeTuple: TElementTypeTuple); | ||
} | ||
/** @internal */ | ||
_toJSONSchema(context: JSONSchemaContext, exact: boolean): JSONSchemaData { | ||
exact = this._exact ?? exact; | ||
return { | ||
schema: context.define(this, exact, { | ||
type: 'array', | ||
prefixItems: this.ElementTypeTuple.map( | ||
Element => Element._toJSONSchema(context, exact).schema, | ||
), | ||
}), | ||
}; | ||
} | ||
} | ||
@@ -245,0 +260,0 @@ |
import type {Exact} from './@exact-context'; | ||
import type {TypeIssue, TypePath} from './@type-issue'; | ||
import type {JSONSchema} from './json-schema'; | ||
import type {Medium} from './medium'; | ||
@@ -10,3 +11,3 @@ import {__type_in_mediums, __type_kind} from './type-partials'; | ||
> { | ||
[__type_kind]!: string; | ||
abstract [__type_kind]: string; | ||
@@ -43,2 +44,80 @@ [__type_in_mediums]!: TInMediums; | ||
abstract _diagnose(value: unknown, path: TypePath, exact: Exact): TypeIssue[]; | ||
/** @internal */ | ||
abstract _toJSONSchema( | ||
context: JSONSchemaContext, | ||
exact: boolean, | ||
): JSONSchemaData; | ||
} | ||
function JSON_SCHEMA_TYPE_KEY(id: number): string { | ||
return `type-${id}`; | ||
} | ||
function JSON_SCHEMA_TYPE_REF(id: number): string { | ||
return `#/$defs/${JSON_SCHEMA_TYPE_KEY(id)}`; | ||
} | ||
export class JSONSchemaContext { | ||
private lastId = 0; | ||
private typeIdMap = new Map<TypeLike, number>(); | ||
private exactTypeIdMap = new Map<TypeLike, number>(); | ||
private refToDefinitionMap = new Map<string, JSONSchema>(); | ||
readonly definitions: Record<string, JSONSchema> = {}; | ||
define(Type: TypeLike, exact: boolean): void; | ||
define(Type: TypeLike, exact: boolean, definition: JSONSchema): JSONSchema; | ||
define( | ||
Type: TypeLike, | ||
exact: boolean, | ||
definition?: JSONSchema, | ||
): JSONSchema | void { | ||
const typeIdMap = exact ? this.exactTypeIdMap : this.typeIdMap; | ||
let id = typeIdMap.get(Type); | ||
if (id === undefined) { | ||
id = ++this.lastId; | ||
typeIdMap.set(Type, id); | ||
} | ||
if (definition) { | ||
this.definitions[JSON_SCHEMA_TYPE_KEY(id)] = definition; | ||
const ref = JSON_SCHEMA_TYPE_REF(id); | ||
this.refToDefinitionMap.set(ref, definition); | ||
return {$ref: ref}; | ||
} | ||
} | ||
getDefinition(Type: TypeLike, exact: boolean): JSONSchema | undefined { | ||
const typeIdMap = exact ? this.exactTypeIdMap : this.typeIdMap; | ||
const id = typeIdMap.get(Type); | ||
return typeof id === 'number' | ||
? {$ref: JSON_SCHEMA_TYPE_REF(id)} | ||
: undefined; | ||
} | ||
requireDefinitionByRef(ref: string): JSONSchema { | ||
const schema = this.refToDefinitionMap.get(ref); | ||
/* istanbul ignore if */ | ||
if (!schema) { | ||
throw new Error('Invalid JSON Schema reference'); | ||
} | ||
return schema; | ||
} | ||
} | ||
export interface JSONSchemaData { | ||
schema: JSONSchema; | ||
optional?: boolean; | ||
} |
import type {Exact} from './@exact-context'; | ||
import {ExactContext} from './@exact-context'; | ||
import type {TypeIssue} from './@type-issue'; | ||
import type {JSONSchema} from './json-schema'; | ||
import type {Medium, MediumTypesPackedType} from './medium'; | ||
import {TypeLike} from './type-like'; | ||
import {JSONSchemaContext, TypeLike} from './type-like'; | ||
import type { | ||
@@ -119,2 +120,11 @@ TypeInMediumsPartial, | ||
toJSONSchema(): JSONSchema { | ||
const context = new JSONSchemaContext(); | ||
return { | ||
...this._toJSONSchema(context, this._exact ?? false).schema, | ||
$defs: context.definitions, | ||
}; | ||
} | ||
protected getExactContext( | ||
@@ -121,0 +131,0 @@ exact: Exact, |
@@ -8,2 +8,3 @@ import type {Exact} from './@exact-context'; | ||
import {DISABLED_EXACT_CONTEXT_RESULT, Type} from './type'; | ||
import type {JSONSchemaContext, JSONSchemaData} from './type-like'; | ||
import {__type_kind} from './type-partials'; | ||
@@ -19,3 +20,3 @@ import type {TypeInMediumsPartial} from './type-partials'; | ||
> extends Type<UnionInMediums<TTypeTuple>> { | ||
[__type_kind]!: 'union'; | ||
readonly [__type_kind] = 'union'; | ||
@@ -231,2 +232,17 @@ constructor(TypeTuple: TTypeTuple); | ||
} | ||
/** @internal */ | ||
_toJSONSchema(context: JSONSchemaContext, exact: boolean): JSONSchemaData { | ||
exact = this._exact ?? exact; | ||
const schemas = this.TypeTuple.map( | ||
Type => Type._toJSONSchema(context, exact).schema, | ||
); | ||
return { | ||
schema: context.define(this, exact, { | ||
anyOf: schemas, | ||
}), | ||
}; | ||
} | ||
} | ||
@@ -233,0 +249,0 @@ |
@@ -37,3 +37,3 @@ import {atomic} from './core'; | ||
export const unknownTypeSymbol = Symbol(); | ||
export const unknown = atomic(unknownTypeSymbol, []); | ||
export const unknown = atomic(unknownTypeSymbol, [], {}); | ||
@@ -59,39 +59,54 @@ export const undefinedTypeSymbol = Symbol(); | ||
export const nullTypeSymbol = Symbol(); | ||
export const nullType = atomic(nullTypeSymbol, value => | ||
constraint( | ||
value === null, | ||
() => `Expected null, getting ${toString.call(value)}.`, | ||
), | ||
export const nullType = atomic( | ||
nullTypeSymbol, | ||
value => | ||
constraint( | ||
value === null, | ||
() => `Expected null, getting ${toString.call(value)}.`, | ||
), | ||
{type: 'null'}, | ||
); | ||
export const stringTypeSymbol = Symbol(); | ||
export const string = atomic(stringTypeSymbol, value => | ||
constraint( | ||
typeof value === 'string', | ||
() => `Expected string, getting ${toString.call(value)}.`, | ||
), | ||
export const string = atomic( | ||
stringTypeSymbol, | ||
value => | ||
constraint( | ||
typeof value === 'string', | ||
() => `Expected string, getting ${toString.call(value)}.`, | ||
), | ||
{type: 'string'}, | ||
); | ||
export const numberTypeSymbol = Symbol(); | ||
export const number = atomic(numberTypeSymbol, value => | ||
constraint( | ||
typeof value === 'number', | ||
() => `Expected number, getting ${toString.call(value)}.`, | ||
), | ||
export const number = atomic( | ||
numberTypeSymbol, | ||
value => | ||
constraint( | ||
typeof value === 'number', | ||
() => `Expected number, getting ${toString.call(value)}.`, | ||
), | ||
{type: 'number'}, | ||
); | ||
export const bigintTypeSymbol = Symbol(); | ||
export const bigint = atomic(bigintTypeSymbol, value => | ||
constraint( | ||
typeof value === 'bigint', | ||
() => `Expected bigint, getting ${toString.call(value)}.`, | ||
), | ||
export const bigint = atomic( | ||
bigintTypeSymbol, | ||
value => | ||
constraint( | ||
typeof value === 'bigint', | ||
() => `Expected bigint, getting ${toString.call(value)}.`, | ||
), | ||
{type: 'integer'}, | ||
); | ||
export const booleanTypeSymbol = Symbol(); | ||
export const boolean = atomic(booleanTypeSymbol, value => | ||
constraint( | ||
typeof value === 'boolean', | ||
() => `Expected boolean, getting ${toString.call(value)}.`, | ||
), | ||
export const boolean = atomic( | ||
booleanTypeSymbol, | ||
value => | ||
constraint( | ||
typeof value === 'boolean', | ||
() => `Expected boolean, getting ${toString.call(value)}.`, | ||
), | ||
{type: 'boolean'}, | ||
); | ||
@@ -98,0 +113,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
300079
139
6488