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

fastify-zod

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fastify-zod - npm Package Compare versions

Comparing version 0.0.2 to 0.1.0

60

build/__tests__/buildJsonSchemas.test.js

@@ -85,4 +85,64 @@ "use strict";

});
test(`mergeRefs:`, () => {
let FooFizzEnum;
(function (FooFizzEnum) {
FooFizzEnum["Foo"] = "Bar";
FooFizzEnum["Fizz"] = "Buzz";
})(FooFizzEnum || (FooFizzEnum = {}));
const FooFizz = _zod.z.nativeEnum(FooFizzEnum);
const FooFizzItem = _zod.z.object({
value: FooFizz
});
const unmerged = (0, _.buildJsonSchemas)({
FooFizz,
FooFizzItem
});
expect(unmerged.schemas).toEqual([{
$id: `FooFizzItem`,
$schema: `http://json-schema.org/draft-07/schema#`,
type: `object`,
properties: {
value: {
type: `string`,
enum: [`Bar`, `Buzz`]
}
},
required: [`value`],
additionalProperties: false
}, {
$id: `FooFizz`,
$schema: `http://json-schema.org/draft-07/schema#`,
type: `string`,
enum: [`Bar`, `Buzz`]
}]);
const merged = (0, _.buildJsonSchemas)({
FooFizz,
FooFizzItem
}, {
mergeRefs: true
});
expect(merged.schemas).toEqual([{
$id: `FooFizzItem`,
$schema: `http://json-schema.org/draft-07/schema#`,
type: `object`,
properties: {
value: {
$ref: `FooFizz#`
}
},
required: [`value`],
additionalProperties: false
}, {
$id: `FooFizz`,
$schema: `http://json-schema.org/draft-07/schema#`,
type: `string`,
enum: [`Bar`, `Buzz`]
}]);
});
}
});
//# sourceMappingURL=buildJsonSchemas.test.js.map
import { FastifyInstance } from "fastify";
import { z } from "zod";
export declare const TodoItemId: z.ZodObject<{
id: z.ZodString;
}, "strip", z.ZodTypeAny, {
id: string;
}, {
id: string;
}>;
export declare type TodoItemId = z.infer<typeof TodoItemId>;
export declare const TodoItem: z.ZodObject<z.extendShape<{
id: z.ZodString;
}, {
label: z.ZodString;
dueDate: z.ZodOptional<z.ZodDate>;
state: z.ZodUnion<[z.ZodLiteral<"todo">, z.ZodLiteral<"in progress">, z.ZodLiteral<"done">]>;
}>, "strip", z.ZodTypeAny, {
dueDate?: Date | undefined;
id: string;
label: string;
state: "done" | "todo" | "in progress";
}, {
dueDate?: Date | undefined;
id: string;
label: string;
state: "done" | "todo" | "in progress";
}>;
export declare type TodoItem = z.infer<typeof TodoItem>;
export declare const TodoItems: z.ZodArray<z.ZodObject<z.extendShape<{
id: z.ZodString;
}, {
label: z.ZodString;
dueDate: z.ZodOptional<z.ZodDate>;
state: z.ZodUnion<[z.ZodLiteral<"todo">, z.ZodLiteral<"in progress">, z.ZodLiteral<"done">]>;
}>, "strip", z.ZodTypeAny, {
dueDate?: Date | undefined;
id: string;
label: string;
state: "done" | "todo" | "in progress";
}, {
dueDate?: Date | undefined;
id: string;
label: string;
state: "done" | "todo" | "in progress";
}>, "many">;
export declare type TodoItems = z.infer<typeof TodoItems>;
export declare const createTestServer: () => FastifyInstance;

5

build/__tests__/fixtures.js

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

});
exports.createTestServer = void 0;
exports.createTestServer = exports.TodoItems = exports.TodoItemId = exports.TodoItem = void 0;

@@ -25,2 +25,3 @@ var _fastify = _interopRequireDefault(require("fastify"));

exports.TodoItemId = TodoItemId;
const TodoItem = TodoItemId.extend({

@@ -31,5 +32,7 @@ label: _zod.z.string(),

});
exports.TodoItem = TodoItem;
const TodoItems = _zod.z.array(TodoItem);
exports.TodoItems = TodoItems;
const {

@@ -36,0 +39,0 @@ schemas,

4

build/__tests__/utils.d.ts

@@ -1,2 +0,2 @@

import { Options } from "..";
import { BuildJsonSchemaOptions } from "..";
declare type Helpers = {

@@ -6,5 +6,5 @@ $schema: Record<string, unknown>;

stringEnum: (values: unknown[]) => Record<string, unknown>;
options: Options;
options: BuildJsonSchemaOptions;
};
export declare const helpers: (target: `jsonSchema7` | `openApi3` | undefined) => Helpers;
export {};

@@ -5,7 +5,11 @@ import { z } from "zod";

$id: $id;
$schema?: string;
};
declare type Target = `openApi3` | `jsonSchema7`;
export declare type Options = {
export declare type BuildJsonSchemaOptions = {
readonly target?: Target;
};
export declare type BuildJsonSchemasOptions = BuildJsonSchemaOptions & {
readonly mergeRefs?: boolean;
};
export declare type JsonSchemas<$id extends string> = {

@@ -17,5 +21,5 @@ schemas: JsonSchema<$id>[];

};
export declare const buildJsonSchema: <$id extends string>(ZodSchema: z.ZodType<unknown>, $id: $id, { target }?: Options) => JsonSchema<$id>;
export declare const buildJsonSchemas: <$id extends string>(zodSchemas: Record<$id, z.ZodType<unknown, z.ZodTypeDef, unknown>>, { target }?: Options) => JsonSchemas<$id>;
export declare const buildJsonSchema: <$id extends string>(ZodSchema: z.ZodType<unknown>, $id: $id, { target }?: BuildJsonSchemaOptions) => JsonSchema<$id>;
export declare const buildJsonSchemas: <$id extends string>(zodSchemas: Record<$id, z.ZodType<unknown, z.ZodTypeDef, unknown>>, { target, mergeRefs }?: BuildJsonSchemasOptions) => JsonSchemas<$id>;
export declare const withRefResolver: (options: SwaggerOptions) => SwaggerOptions;
export {};

@@ -23,13 +23,59 @@ "use strict";

const traverse = (value, visit) => {
const next = visit(value);
if (Array.isArray(next)) {
return next.map(item => traverse(item, visit));
}
if (typeof next === `object` && next !== null) {
return Object.entries(next).reduce((next, [key, value]) => ({ ...next,
[key]: traverse(value, visit)
}), Object.create(null));
}
return next;
};
const buildJsonSchemas = (zodSchemas, {
target = `jsonSchema7`
} = {}) => ({
schemas: Object.entries(zodSchemas).reduce((schemas, [$id, ZodSchema]) => [buildJsonSchema(ZodSchema, $id, {
target
}), ...schemas], []),
$ref: $id => ({
$ref: `${$id}#`
})
});
target = `jsonSchema7`,
mergeRefs = false
} = {}) => {
let schemas = {
schemas: Object.entries(zodSchemas).reduce((schemas, [$id, ZodSchema]) => [buildJsonSchema(ZodSchema, $id, {
target
}), ...schemas], []),
$ref: $id => ({
$ref: `${$id}#`
})
};
if (mergeRefs) {
let dirty = true;
while (dirty) {
dirty = false;
schemas = traverse(schemas, value => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (const {
$id,
$schema,
...schema
} of schemas.schemas) {
if (value !== schema && JSON.stringify(value) === JSON.stringify(schema)) {
dirty = true;
return {
$ref: `${$id}#`
};
}
}
return value;
});
}
}
return schemas;
};
exports.buildJsonSchemas = buildJsonSchemas;

@@ -36,0 +82,0 @@

{
"name": "fastify-zod",
"version": "0.0.2",
"version": "0.1.0",
"description": "Zod integration with Fastify",

@@ -32,30 +32,30 @@ "main": "build/index.js",

"devDependencies": {
"@babel/cli": "^7.16.7",
"@babel/core": "^7.16.7",
"@babel/preset-env": "^7.16.7",
"@babel/cli": "^7.17.6",
"@babel/core": "^7.17.5",
"@babel/preset-env": "^7.16.11",
"@babel/preset-typescript": "^7.16.7",
"@types/http-errors": "^1.8.1",
"@types/jest": "^27.4.0",
"@types/node": "^17.0.8",
"@typescript-eslint/eslint-plugin": "^5.9.0",
"@typescript-eslint/parser": "^5.9.0",
"eslint": "^8.6.0",
"eslint-config-prettier": "^8.3.0",
"@types/http-errors": "^1.8.2",
"@types/jest": "^27.4.1",
"@types/node": "^17.0.21",
"@typescript-eslint/eslint-plugin": "^5.12.1",
"@typescript-eslint/parser": "^5.12.1",
"eslint": "^8.9.0",
"eslint-config-prettier": "^8.4.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-prettier": "^4.0.0",
"fastify": "^3.25.3",
"fastify-swagger": "^4.13.0",
"fastify": "^3.27.2",
"fastify-swagger": "^4.15.0",
"http-errors": "^1.8.0",
"jest": "^27.4.7",
"jest": "^27.5.1",
"prettier": "^2.5.1",
"typescript": "^4.5.4",
"zod": "^3.11.6",
"typescript": "^4.5.5",
"zod": "^3.12.0",
"zod-to-json-schema": "^3.11.3"
},
"peerDependencies": {
"fastify": "^3.25.3",
"fastify-swagger": "^4.13.0",
"zod": "^3.11.6",
"fastify": "^3.27.2",
"fastify-swagger": "^4.15.0",
"zod": "^3.12.0",
"zod-to-json-schema": "^3.11.3"
}
}

@@ -69,2 +69,56 @@ import { z } from "zod";

});
test(`mergeRefs:`, () => {
enum FooFizzEnum {
Foo = `Bar`,
Fizz = `Buzz`,
}
const FooFizz = z.nativeEnum(FooFizzEnum);
const FooFizzItem = z.object({
value: FooFizz,
});
const unmerged = buildJsonSchemas({ FooFizz, FooFizzItem });
expect(unmerged.schemas).toEqual([
{
$id: `FooFizzItem`,
$schema: `http://json-schema.org/draft-07/schema#`,
type: `object`,
properties: { value: { type: `string`, enum: [`Bar`, `Buzz`] } },
required: [`value`],
additionalProperties: false,
},
{
$id: `FooFizz`,
$schema: `http://json-schema.org/draft-07/schema#`,
type: `string`,
enum: [`Bar`, `Buzz`],
},
]);
const merged = buildJsonSchemas(
{ FooFizz, FooFizzItem },
{ mergeRefs: true },
);
expect(merged.schemas).toEqual([
{
$id: `FooFizzItem`,
$schema: `http://json-schema.org/draft-07/schema#`,
type: `object`,
properties: { value: { $ref: `FooFizz#` } },
required: [`value`],
additionalProperties: false,
},
{
$id: `FooFizz`,
$schema: `http://json-schema.org/draft-07/schema#`,
type: `string`,
enum: [`Bar`, `Buzz`],
},
]);
});
}

@@ -71,0 +125,0 @@ });

@@ -8,8 +8,8 @@ import fastify, { FastifyInstance } from "fastify";

const TodoItemId = z.object({
export const TodoItemId = z.object({
id: z.string().uuid(),
});
type TodoItemId = z.infer<typeof TodoItemId>;
export type TodoItemId = z.infer<typeof TodoItemId>;
const TodoItem = TodoItemId.extend({
export const TodoItem = TodoItemId.extend({
label: z.string(),

@@ -24,6 +24,6 @@ dueDate: z.date().optional(),

type TodoItem = z.infer<typeof TodoItem>;
export type TodoItem = z.infer<typeof TodoItem>;
const TodoItems = z.array(TodoItem);
type TodoItems = z.infer<typeof TodoItems>;
export const TodoItems = z.array(TodoItem);
export type TodoItems = z.infer<typeof TodoItems>;

@@ -30,0 +30,0 @@ const { schemas, $ref } = buildJsonSchemas({

@@ -1,2 +0,2 @@

import { Options } from "..";
import { BuildJsonSchemaOptions } from "..";

@@ -7,3 +7,3 @@ type Helpers = {

stringEnum: (values: unknown[]) => Record<string, unknown>;
options: Options;
options: BuildJsonSchemaOptions;
};

@@ -10,0 +10,0 @@

@@ -7,2 +7,3 @@ import { z } from "zod";

$id: $id;
$schema?: string;
};

@@ -12,6 +13,10 @@

export type Options = {
export type BuildJsonSchemaOptions = {
readonly target?: Target;
};
export type BuildJsonSchemasOptions = BuildJsonSchemaOptions & {
readonly mergeRefs?: boolean;
};
export type JsonSchemas<$id extends string> = {

@@ -29,3 +34,3 @@ schemas: JsonSchema<$id>[];

$id: $id,
{ target = `jsonSchema7` }: Options = {},
{ target = `jsonSchema7` }: BuildJsonSchemaOptions = {},
): JsonSchema<$id> => ({

@@ -36,18 +41,65 @@ $id,

const traverse = (
value: unknown,
visit: (value: unknown) => unknown,
): unknown => {
const next = visit(value);
if (Array.isArray(next)) {
return next.map((item) => traverse(item, visit));
}
if (typeof next === `object` && next !== null) {
return Object.entries(next).reduce(
(next, [key, value]) => ({
...next,
[key]: traverse(value, visit),
}),
Object.create(null),
);
}
return next;
};
export const buildJsonSchemas = <$id extends string>(
zodSchemas: Record<$id, z.ZodType<unknown>>,
{ target = `jsonSchema7` }: Options = {},
): JsonSchemas<$id> => ({
schemas: Object.entries(zodSchemas).reduce<JsonSchemas<$id>[`schemas`]>(
(schemas, [$id, ZodSchema]) => [
buildJsonSchema(ZodSchema as z.ZodType<unknown>, $id as $id, { target }),
...schemas,
],
[],
),
$ref: ($id) => ({
$ref: `${$id}#`,
}),
});
{ target = `jsonSchema7`, mergeRefs = false }: BuildJsonSchemasOptions = {},
): JsonSchemas<$id> => {
let schemas: JsonSchemas<$id> = {
schemas: Object.entries(zodSchemas).reduce<JsonSchemas<$id>[`schemas`]>(
(schemas, [$id, ZodSchema]) => [
buildJsonSchema(ZodSchema as z.ZodType<unknown>, $id as $id, {
target,
}),
...schemas,
],
[],
),
$ref: ($id) => ({
$ref: `${$id}#`,
}),
};
if (mergeRefs) {
let dirty = true;
while (dirty) {
dirty = false;
schemas = traverse(schemas, (value) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (const { $id, $schema, ...schema } of schemas.schemas) {
if (
value !== schema &&
JSON.stringify(value) === JSON.stringify(schema)
) {
dirty = true;
return {
$ref: `${$id}#`,
};
}
}
return value;
}) as JsonSchemas<$id>;
}
}
return schemas;
};
export const withRefResolver = (options: SwaggerOptions): SwaggerOptions =>

@@ -54,0 +106,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

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