@asteasolutions/zod-to-openapi
Advanced tools
Comparing version 1.3.0 to 1.4.0
@@ -11,1 +11,2 @@ export declare function isUndefined<T>(value: any): value is undefined; | ||
export declare function compact<T extends any>(arr: (T | null | undefined)[]): T[]; | ||
export declare function objectEquals(x: any, y: any): boolean; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.compact = exports.omitBy = exports.omit = exports.mapValues = exports.isNil = exports.isUndefined = void 0; | ||
exports.objectEquals = exports.compact = exports.omitBy = exports.omit = exports.mapValues = exports.isNil = exports.isUndefined = void 0; | ||
function isUndefined(value) { | ||
@@ -44,1 +44,26 @@ return value === undefined; | ||
exports.compact = compact; | ||
function objectEquals(x, y) { | ||
if (x === null || x === undefined || y === null || y === undefined) { | ||
return x === y; | ||
} | ||
if (x === y || x.valueOf() === y.valueOf()) { | ||
return true; | ||
} | ||
if (Array.isArray(x)) { | ||
if (!Array.isArray(y)) { | ||
return false; | ||
} | ||
if (x.length !== y.length) { | ||
return false; | ||
} | ||
} | ||
// if they are strictly equal, they both need to be object at least | ||
if (!(x instanceof Object) || !(y instanceof Object)) { | ||
return false; | ||
} | ||
// recursive object equality check | ||
const keysX = Object.keys(x); | ||
return (Object.keys(y).every(keyY => keysX.indexOf(keyY) !== -1) && | ||
keysX.every(key => objectEquals(x[key], y[key]))); | ||
} | ||
exports.objectEquals = objectEquals; |
@@ -194,5 +194,13 @@ "use strict"; | ||
if (refId && this.schemaRefs[refId]) { | ||
return { | ||
const referenceObject = { | ||
$ref: `#/components/schemas/${refId}`, | ||
}; | ||
const nullableMetadata = zodSchema.isNullable() ? { nullable: true } : {}; | ||
const appliedMetadata = this.applySchemaMetadata(nullableMetadata, metadata); | ||
if (Object.keys(appliedMetadata).length > 0) { | ||
return { | ||
allOf: [referenceObject, appliedMetadata], | ||
}; | ||
} | ||
return referenceObject; | ||
} | ||
@@ -422,2 +430,4 @@ const result = (metadata === null || metadata === void 0 ? void 0 : metadata.type) | ||
toOpenAPIObjectSchema(zodSchema, isNullable) { | ||
var _a, _b, _c; | ||
const extendedFrom = (_a = zodSchema._def.openapi) === null || _a === void 0 ? void 0 : _a.extendedFrom; | ||
const propTypes = zodSchema._def.shape(); | ||
@@ -428,9 +438,29 @@ const unknownKeysOption = zodSchema._unknownKeys; | ||
.map(([key, _type]) => key); | ||
return { | ||
type: 'object', | ||
properties: (0, lodash_1.mapValues)(propTypes, propSchema => this.generateInnerSchema(propSchema)), | ||
required: requiredProperties.length > 0 ? requiredProperties : undefined, | ||
additionalProperties: unknownKeysOption === 'passthrough' || undefined, | ||
nullable: isNullable ? true : undefined, | ||
}; | ||
const schemaProperties = (0, lodash_1.mapValues)(propTypes, propSchema => this.generateInnerSchema(propSchema)); | ||
let alreadyRegistered = []; | ||
let alreadyRequired = []; | ||
if (extendedFrom) { | ||
const registeredSchema = this.schemaRefs[extendedFrom]; | ||
if (!registeredSchema) { | ||
throw new Error(`Attempt to extend an unregistered schema with id ${extendedFrom}.`); | ||
} | ||
const registeredProperties = (_b = registeredSchema.properties) !== null && _b !== void 0 ? _b : {}; | ||
alreadyRegistered = Object.keys(registeredProperties).filter(propKey => { | ||
return (0, lodash_1.objectEquals)(schemaProperties[propKey], registeredProperties[propKey]); | ||
}); | ||
alreadyRequired = (_c = registeredSchema.required) !== null && _c !== void 0 ? _c : []; | ||
} | ||
const properties = (0, lodash_1.omit)(schemaProperties, alreadyRegistered); | ||
const additionallyRequired = requiredProperties.filter(prop => !alreadyRequired.includes(prop)); | ||
const objectData = Object.assign(Object.assign(Object.assign({ type: 'object', properties }, (isNullable ? { nullable: true } : {})), (additionallyRequired.length > 0 | ||
? { required: additionallyRequired } | ||
: {})), (unknownKeysOption === 'passthrough' | ||
? { additionalProperties: true } | ||
: {})); | ||
if (extendedFrom) { | ||
return { | ||
allOf: [{ $ref: `#/components/schemas/${extendedFrom}` }, objectData], | ||
}; | ||
} | ||
return objectData; | ||
} | ||
@@ -467,3 +497,3 @@ flattenUnionTypes(schema) { | ||
// A place to omit all custom keys added to the openapi | ||
return (0, lodash_1.omitBy)((0, lodash_1.omit)(metadata, ['param', 'refId']), lodash_1.isNil); | ||
return (0, lodash_1.omitBy)((0, lodash_1.omit)(metadata, ['param', 'refId', 'extendedFrom']), lodash_1.isNil); | ||
} | ||
@@ -470,0 +500,0 @@ buildParameterMetadata(metadata) { |
@@ -5,2 +5,3 @@ import { ParameterObject, SchemaObject } from 'openapi3-ts'; | ||
refId?: string; | ||
extendedFrom?: string; | ||
param?: Partial<ParameterObject> & { | ||
@@ -7,0 +8,0 @@ example?: T; |
@@ -15,2 +15,3 @@ "use strict"; | ||
exports.extendZodWithOpenApi = void 0; | ||
const zod_is_type_1 = require("./lib/zod-is-type"); | ||
function extendZodWithOpenApi(zod) { | ||
@@ -26,3 +27,16 @@ if (typeof zod.ZodSchema.prototype.openapi !== 'undefined') { | ||
const _b = openapi !== null && openapi !== void 0 ? openapi : {}, { param } = _b, restOfOpenApi = __rest(_b, ["param"]); | ||
return new this.constructor(Object.assign(Object.assign({}, this._def), { openapi: Object.assign(Object.assign(Object.assign({}, this._def.openapi), restOfOpenApi), { param: Object.assign(Object.assign({}, (_a = this._def.openapi) === null || _a === void 0 ? void 0 : _a.param), param) }) })); | ||
const result = new this.constructor(Object.assign(Object.assign({}, this._def), { openapi: Object.assign(Object.assign(Object.assign({}, this._def.openapi), restOfOpenApi), { param: Object.assign(Object.assign({}, (_a = this._def.openapi) === null || _a === void 0 ? void 0 : _a.param), param) }) })); | ||
if ((0, zod_is_type_1.isZodType)(this, 'ZodObject')) { | ||
const initialExtend = this.extend; | ||
// TODO: This does an overload everytime. So .extend().openapi() makes this change twice | ||
result.extend = function (...args) { | ||
var _a; | ||
const extendedResult = initialExtend.apply(result, args); | ||
extendedResult._def.openapi = { | ||
extendedFrom: (_a = result._def.openapi) === null || _a === void 0 ? void 0 : _a.refId, | ||
}; | ||
return extendedResult; | ||
}; | ||
} | ||
return result; | ||
}; | ||
@@ -29,0 +43,0 @@ const zodOptional = zod.ZodSchema.prototype.optional; |
{ | ||
"name": "@asteasolutions/zod-to-openapi", | ||
"version": "1.3.0", | ||
"version": "1.4.0", | ||
"description": "Builds OpenAPI schemas from Zod schemas", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -368,2 +368,4 @@ # Zod to OpenAPI | ||
Extending an instance of `ZodObject` is also supported and results in an OpenApi definition with `allOf` | ||
### Unsupported types | ||
@@ -370,0 +372,0 @@ |
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
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
54936
981
383
0