Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,6 @@ yarn-error.log*
dist
.eslintcache
/.idea/

lib/tests/test-generation/*-output.ts
lib/tests/test-generation/*-output
3 changes: 2 additions & 1 deletion lib/src/template-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ export const getZodClientTemplateContext = (
data.schemas[normalizeString(name)] = wrapWithLazyIfNeeded(name);
}

for (const ref in depsGraphs.deepDependencyGraph) {
for (const [name] of Object.entries(docSchemas)) {
const ref = asComponentSchema(name);
const isCircular = ref && depsGraphs.deepDependencyGraph[ref]?.has(ref);
const ctx: TsConversionContext = { nodeByRef: {}, resolver: result.resolver, visitedsRefs: {} };

Expand Down
8 changes: 4 additions & 4 deletions lib/tests/allOf-infer-required-only-item.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,15 @@ test("allOf-infer-required-only-item", async () => {
"import { makeApi, Zodios, type ZodiosOptions } from "@zodios/core";
import { z } from "zod";

type user = Partial<{
name: string;
email: string;
}>;
type userResponse = Partial<{
user: user & {
name: string;
};
}>;
type user = Partial<{
name: string;
email: string;
}>;

const user: z.ZodType<user> = z
.object({ name: z.string(), email: z.string() })
Expand Down
69 changes: 69 additions & 0 deletions lib/tests/api-doc.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import SwaggerParser from "@apidevtools/swagger-parser";
import type { OpenAPIObject } from "openapi3-ts";
import { generateZodClientFromOpenAPI } from "../src";
import { readFileSync, writeFileSync } from "node:fs";
import { resolve } from "path";
import { expect, test } from "vitest";

test("api-doc.yaml generates expected TypeScript client", async () => {
const openApiDoc = (await SwaggerParser.parse(resolve(__dirname, "schemas/api-doc.yaml"))) as OpenAPIObject;

const result = await generateZodClientFromOpenAPI({
openApiDoc,
disableWriteToFile: true,
options: {
apiClientName: "api",
shouldExportAllTypes: true,
},
});

const expectedContent = readFileSync(resolve(__dirname, "test-generation/api-doc-expected.ts"), "utf8");

writeFileSync(resolve(__dirname, "test-generation/api-doc-output.ts"), result, "utf8");

expect(result).toBe(expectedContent);
});

test("api-doc.yaml with groupStrategy tag-file and shouldExportAllTypes", async () => {
const openApiDoc = (await SwaggerParser.parse(resolve(__dirname, "schemas/api-doc.yaml"))) as OpenAPIObject;

const result = await generateZodClientFromOpenAPI({
openApiDoc,
disableWriteToFile: true,
options: {
groupStrategy: "tag-file",
shouldExportAllTypes: true,
},
});

// Write actual output files to folder
const outputDir = resolve(__dirname, "test-generation/api-doc-grouped-output");
const expectedDir = resolve(__dirname, "test-generation/api-doc-grouped-expected");

const fs = await import("@liuli-util/fs-extra");
await fs.ensureDir(outputDir);
await fs.ensureDir(expectedDir);

// Write all generated files to output directory
for (const [fileName, content] of Object.entries(result)) {
const filePath = fileName.startsWith("__") ? `${fileName.slice(2)}.ts` : `${fileName}.ts`;
writeFileSync(resolve(outputDir, filePath), content, "utf8");
}

// Compare each file with expected
for (const [fileName, content] of Object.entries(result)) {
const filePath = fileName.startsWith("__") ? `${fileName.slice(2)}.ts` : `${fileName}.ts`;
const expectedPath = resolve(expectedDir, filePath);

let expectedContent: string;
try {
expectedContent = readFileSync(expectedPath, "utf8");
} catch (error) {
// If expected file doesn't exist, create it from actual output
expectedContent = content;
writeFileSync(expectedPath, expectedContent, "utf8");
}

expect(content).toBe(expectedContent);
}
});
14 changes: 7 additions & 7 deletions lib/tests/enum-null.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,18 +111,18 @@ test("enum-null", async () => {
"import { makeApi, Zodios, type ZodiosOptions } from "@zodios/core";
import { z } from "zod";

type Compound = Partial<{
field: Null1 | Null2 | Null3 | Null4 | string;
}>;
type Null1 = null;
type Null2 = "a" | null;
type Null3 = "a" | null;
type Null4 = null;
type Compound = Partial<{
field: Null1 | Null2 | Null3 | Null4 | string;
}>;

const Null1 = z.literal(null);
const Null2 = z.enum(["a", null]);
const Null3 = z.enum(["a", null]);
const Null4 = z.literal(null);
const Null1: z.ZodType<Null1> = z.literal(null);
const Null2: z.ZodType<Null2> = z.enum(["a", null]);
const Null3: z.ZodType<Null3> = z.enum(["a", null]);
const Null4: z.ZodType<Null4> = z.literal(null);
const Compound: z.ZodType<Compound> = z
.object({ field: z.union([Null1, Null2, Null3, Null4, z.string()]) })
.partial()
Expand Down
6 changes: 3 additions & 3 deletions lib/tests/jsdoc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ test("jsdoc", async () => {
expect(output).toMatchInlineSnapshot(`"import { makeApi, Zodios, type ZodiosOptions } from "@zodios/core";
import { z } from "zod";

type SimpleObject = Partial<{
str: string;
}>;
type ComplexObject = Partial<{
/**
* A string with example tag
Expand Down Expand Up @@ -156,9 +159,6 @@ type ComplexObject = Partial<{
*/
refArray: Array<SimpleObject>;
}>;
type SimpleObject = Partial<{
str: string;
}>;

const SimpleObject: z.ZodType<SimpleObject> = z
.object({ str: z.string() })
Expand Down
Loading