zod-codegen 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +43 -0
- package/.github/workflows/ci.yml +4 -4
- package/.github/workflows/release.yml +1 -1
- package/CHANGELOG.md +16 -0
- package/dist/src/services/code-generator.service.js +31 -25
- package/package.json +5 -5
- package/scripts/republish-versions.sh +94 -0
- package/src/services/code-generator.service.ts +65 -34
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(npm install:*)",
|
|
5
|
+
"Bash(npm uninstall:*)",
|
|
6
|
+
"Bash(npm run type-check:*)",
|
|
7
|
+
"Bash(npm run build:*)",
|
|
8
|
+
"Bash(./dist/src/cli.js --help)",
|
|
9
|
+
"Bash(./dist/src/cli.js --version)",
|
|
10
|
+
"Bash(npm run dev:*)",
|
|
11
|
+
"Bash(node:*)",
|
|
12
|
+
"Bash(npm run lint)",
|
|
13
|
+
"Bash(npx husky init:*)",
|
|
14
|
+
"Bash(chmod:*)",
|
|
15
|
+
"Bash(npm run validate:*)",
|
|
16
|
+
"Bash(npm run format:*)",
|
|
17
|
+
"Bash(npm run test:*)",
|
|
18
|
+
"Bash(npm test)",
|
|
19
|
+
"Bash(npm audit:*)",
|
|
20
|
+
"Bash(npx depcheck:*)",
|
|
21
|
+
"Bash(npm outdated)",
|
|
22
|
+
"Bash(npm update:*)",
|
|
23
|
+
"WebSearch",
|
|
24
|
+
"Bash(find:*)",
|
|
25
|
+
"Bash(npx zod-codegen:*)",
|
|
26
|
+
"Bash(DEBUG=1 node ./dist/src/cli.js --input ./samples/openapi.json --output ./test-generated)",
|
|
27
|
+
"Bash(rm:*)",
|
|
28
|
+
"Bash(npm outdated:*)",
|
|
29
|
+
"Bash(npm view:*)",
|
|
30
|
+
"Bash(git tag:*)",
|
|
31
|
+
"Bash(npm run release:*)",
|
|
32
|
+
"Bash(git log:*)",
|
|
33
|
+
"Bash(npx commitlint:*)",
|
|
34
|
+
"Bash(git rev-list:*)",
|
|
35
|
+
"Bash(./fix-commit-messages.sh:*)",
|
|
36
|
+
"Bash(git add:*)",
|
|
37
|
+
"Bash(git commit:*)",
|
|
38
|
+
"Bash(FILTER_BRANCH_SQUELCH_WARNING=1 ./fix-commit-messages.sh)"
|
|
39
|
+
],
|
|
40
|
+
"deny": [],
|
|
41
|
+
"ask": []
|
|
42
|
+
}
|
|
43
|
+
}
|
package/.github/workflows/ci.yml
CHANGED
|
@@ -21,7 +21,7 @@ jobs:
|
|
|
21
21
|
|
|
22
22
|
steps:
|
|
23
23
|
- name: Checkout code
|
|
24
|
-
uses: actions/checkout@
|
|
24
|
+
uses: actions/checkout@v6
|
|
25
25
|
with:
|
|
26
26
|
fetch-depth: 0
|
|
27
27
|
|
|
@@ -64,7 +64,7 @@ jobs:
|
|
|
64
64
|
|
|
65
65
|
steps:
|
|
66
66
|
- name: Checkout code
|
|
67
|
-
uses: actions/checkout@
|
|
67
|
+
uses: actions/checkout@v6
|
|
68
68
|
|
|
69
69
|
- name: Setup Node.js
|
|
70
70
|
uses: actions/setup-node@v5
|
|
@@ -85,7 +85,7 @@ jobs:
|
|
|
85
85
|
|
|
86
86
|
steps:
|
|
87
87
|
- name: Checkout code
|
|
88
|
-
uses: actions/checkout@
|
|
88
|
+
uses: actions/checkout@v6
|
|
89
89
|
|
|
90
90
|
- name: Setup Node.js
|
|
91
91
|
uses: actions/setup-node@v5
|
|
@@ -121,7 +121,7 @@ jobs:
|
|
|
121
121
|
|
|
122
122
|
steps:
|
|
123
123
|
- name: Checkout code
|
|
124
|
-
uses: actions/checkout@
|
|
124
|
+
uses: actions/checkout@v6
|
|
125
125
|
with:
|
|
126
126
|
fetch-depth: 0
|
|
127
127
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
## 1.3.0 (2025-11-24)
|
|
2
|
+
|
|
3
|
+
- Merge pull request #36 from julienandreu/dependabot/npm_and_yarn/dev-dependencies-16beb30ed0 ([3d85de4](https://github.com/julienandreu/zod-codegen/commit/3d85de4)), closes [#36](https://github.com/julienandreu/zod-codegen/issues/36)
|
|
4
|
+
- Merge pull request #37 from julienandreu/dependabot/npm_and_yarn/production-dependencies-e947a059e9 ([25bfc2e](https://github.com/julienandreu/zod-codegen/commit/25bfc2e)), closes [#37](https://github.com/julienandreu/zod-codegen/issues/37)
|
|
5
|
+
- Merge pull request #38 from julienandreu/dependabot/github_actions/actions/checkout-6 ([6377f8b](https://github.com/julienandreu/zod-codegen/commit/6377f8b)), closes [#38](https://github.com/julienandreu/zod-codegen/issues/38)
|
|
6
|
+
- Merge pull request #39 from julienandreu/migrate-zod-string-api-v4 ([472d53f](https://github.com/julienandreu/zod-codegen/commit/472d53f)), closes [#39](https://github.com/julienandreu/zod-codegen/issues/39)
|
|
7
|
+
- feat: migrate deprecated Zod string schema API to v4 ([b4461b4](https://github.com/julienandreu/zod-codegen/commit/b4461b4))
|
|
8
|
+
- ci(deps): bump actions/checkout from 5 to 6 ([45d007c](https://github.com/julienandreu/zod-codegen/commit/45d007c))
|
|
9
|
+
- chore(deps-dev): bump the dev-dependencies group with 3 updates ([644ecdc](https://github.com/julienandreu/zod-codegen/commit/644ecdc))
|
|
10
|
+
- chore(deps): bump zod in the production-dependencies group ([69b5694](https://github.com/julienandreu/zod-codegen/commit/69b5694))
|
|
11
|
+
|
|
12
|
+
## <small>1.2.2 (2025-11-19)</small>
|
|
13
|
+
|
|
14
|
+
- Merge pull request #35 from julienandreu/fix/generate-typescript-type-aliases ([b8d9250](https://github.com/julienandreu/zod-codegen/commit/b8d9250)), closes [#35](https://github.com/julienandreu/zod-codegen/issues/35)
|
|
15
|
+
- fix: generate TypeScript type aliases alongside Zod schemas ([7032a69](https://github.com/julienandreu/zod-codegen/commit/7032a69))
|
|
16
|
+
|
|
1
17
|
## <small>1.2.1 (2025-11-19)</small>
|
|
2
18
|
|
|
3
19
|
- Merge pull request #33 from julienandreu/fix/add-z-infer-to-response-types ([a14d81c](https://github.com/julienandreu/zod-codegen/commit/a14d81c)), closes [#33](https://github.com/julienandreu/zod-codegen/issues/33)
|
|
@@ -40,6 +40,7 @@ export class TypeScriptCodeGeneratorService {
|
|
|
40
40
|
buildAST(openapi) {
|
|
41
41
|
const imports = this.importBuilder.buildImports();
|
|
42
42
|
const schemas = this.buildSchemas(openapi);
|
|
43
|
+
const schemaTypeAliases = this.buildSchemaTypeAliases(schemas);
|
|
43
44
|
const serverConfig = this.buildServerConfiguration(openapi);
|
|
44
45
|
const clientClass = this.buildClientClass(openapi, schemas);
|
|
45
46
|
return [
|
|
@@ -47,6 +48,7 @@ export class TypeScriptCodeGeneratorService {
|
|
|
47
48
|
...imports,
|
|
48
49
|
this.createComment('Components schemas'),
|
|
49
50
|
...Object.values(schemas),
|
|
51
|
+
...schemaTypeAliases,
|
|
50
52
|
...serverConfig,
|
|
51
53
|
this.createComment('Client class'),
|
|
52
54
|
clientClass,
|
|
@@ -68,6 +70,12 @@ export class TypeScriptCodeGeneratorService {
|
|
|
68
70
|
};
|
|
69
71
|
}, {});
|
|
70
72
|
}
|
|
73
|
+
buildSchemaTypeAliases(schemas) {
|
|
74
|
+
return Object.keys(schemas).map((name) => {
|
|
75
|
+
const sanitizedName = this.typeBuilder.sanitizeIdentifier(name);
|
|
76
|
+
return ts.factory.createTypeAliasDeclaration([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createIdentifier(sanitizedName), undefined, ts.factory.createTypeReferenceNode(ts.factory.createQualifiedName(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('infer')), [ts.factory.createTypeQueryNode(ts.factory.createIdentifier(sanitizedName), undefined)]));
|
|
77
|
+
});
|
|
78
|
+
}
|
|
71
79
|
buildClientClass(openapi, schemas) {
|
|
72
80
|
const clientName = this.generateClientName(openapi.info.title);
|
|
73
81
|
const methods = this.buildClientMethods(openapi, schemas);
|
|
@@ -516,36 +524,34 @@ export class TypeScriptCodeGeneratorService {
|
|
|
516
524
|
}
|
|
517
525
|
const responseSchema = response.content['application/json'].schema;
|
|
518
526
|
const typeName = this.getSchemaTypeName(responseSchema, schemas);
|
|
519
|
-
const inferredType = this.wrapTypeWithZInfer(typeName, schemas);
|
|
520
|
-
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [inferredType]);
|
|
521
|
-
}
|
|
522
|
-
wrapTypeWithZInfer(typeName, schemas) {
|
|
523
|
-
// Primitive types and Record types don't need z.infer
|
|
524
|
-
const primitiveTypes = ['string', 'number', 'boolean', 'unknown'];
|
|
525
|
-
if (primitiveTypes.includes(typeName) || typeName.startsWith('Record<')) {
|
|
526
|
-
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined);
|
|
527
|
-
}
|
|
528
527
|
// Handle array types like "Pet[]"
|
|
529
528
|
if (typeName.endsWith('[]')) {
|
|
530
529
|
const itemTypeName = typeName.slice(0, -2);
|
|
531
530
|
const sanitizedItemTypeName = this.typeBuilder.sanitizeIdentifier(itemTypeName);
|
|
532
|
-
// Check if the item type is a custom schema
|
|
531
|
+
// Check if the item type is a custom schema (we have a type alias for it)
|
|
533
532
|
if (schemas[sanitizedItemTypeName]) {
|
|
534
|
-
//
|
|
535
|
-
|
|
536
|
-
|
|
533
|
+
// Use the type alias directly (it already uses z.infer)
|
|
534
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
535
|
+
ts.factory.createArrayTypeNode(ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedItemTypeName), undefined)),
|
|
536
|
+
]);
|
|
537
537
|
}
|
|
538
|
-
// If it's a primitive array,
|
|
539
|
-
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(
|
|
538
|
+
// If it's a primitive array, use the type name as-is
|
|
539
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
540
|
+
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined),
|
|
541
|
+
]);
|
|
540
542
|
}
|
|
541
|
-
// Handle custom schema types
|
|
542
543
|
const sanitizedTypeName = this.typeBuilder.sanitizeIdentifier(typeName);
|
|
544
|
+
// Check if it's a custom schema type (we have a type alias for it)
|
|
543
545
|
if (schemas[sanitizedTypeName]) {
|
|
544
|
-
//
|
|
545
|
-
return ts.factory.createTypeReferenceNode(ts.factory.
|
|
546
|
+
// Use the type name directly (we have a type alias that already uses z.infer)
|
|
547
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
548
|
+
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedTypeName), undefined),
|
|
549
|
+
]);
|
|
546
550
|
}
|
|
547
|
-
//
|
|
548
|
-
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(
|
|
551
|
+
// For primitive types and Record types, use the type name directly
|
|
552
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
553
|
+
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined),
|
|
554
|
+
]);
|
|
549
555
|
}
|
|
550
556
|
buildServerConfiguration(openapi) {
|
|
551
557
|
const servers = openapi.servers;
|
|
@@ -975,20 +981,20 @@ export class TypeScriptCodeGeneratorService {
|
|
|
975
981
|
if (prop['format']) {
|
|
976
982
|
switch (prop['format']) {
|
|
977
983
|
case 'email':
|
|
978
|
-
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(
|
|
984
|
+
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('email')), undefined, []);
|
|
979
985
|
break;
|
|
980
986
|
case 'uri':
|
|
981
987
|
case 'url':
|
|
982
|
-
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(
|
|
988
|
+
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('url')), undefined, []);
|
|
983
989
|
break;
|
|
984
990
|
case 'uuid':
|
|
985
|
-
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(
|
|
991
|
+
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('uuid')), undefined, []);
|
|
986
992
|
break;
|
|
987
993
|
case 'date-time':
|
|
988
|
-
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(
|
|
994
|
+
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('iso')), ts.factory.createIdentifier('datetime')), undefined, [this.buildDefaultValue({ local: true })]);
|
|
989
995
|
break;
|
|
990
996
|
case 'date':
|
|
991
|
-
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(
|
|
997
|
+
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('iso')), ts.factory.createIdentifier('date')), undefined, []);
|
|
992
998
|
break;
|
|
993
999
|
case 'time':
|
|
994
1000
|
stringSchema = ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(stringSchema, ts.factory.createIdentifier('time')), undefined, []);
|
package/package.json
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"typescript": "^5.9.3",
|
|
20
20
|
"url-pattern": "^1.0.3",
|
|
21
21
|
"yargs": "^18.0.0",
|
|
22
|
-
"zod": "^4.1.
|
|
22
|
+
"zod": "^4.1.13"
|
|
23
23
|
},
|
|
24
24
|
"description": "A powerful TypeScript code generator that creates Zod schemas and type-safe clients from OpenAPI specifications",
|
|
25
25
|
"keywords": [
|
|
@@ -45,16 +45,16 @@
|
|
|
45
45
|
"@types/jsonpath": "^0.2.4",
|
|
46
46
|
"@types/node": "^24.10.1",
|
|
47
47
|
"@types/yargs": "^17.0.35",
|
|
48
|
-
"@vitest/coverage-v8": "^4.0.
|
|
48
|
+
"@vitest/coverage-v8": "^4.0.13",
|
|
49
49
|
"eslint": "^9.39.1",
|
|
50
50
|
"eslint-config-prettier": "^10.1.8",
|
|
51
51
|
"husky": "^9.1.7",
|
|
52
|
-
"lint-staged": "^16.2.
|
|
52
|
+
"lint-staged": "^16.2.7",
|
|
53
53
|
"semantic-release": "^25.0.2",
|
|
54
54
|
"ts-node": "^10.9.2",
|
|
55
55
|
"typescript-eslint": "^8.46.4",
|
|
56
56
|
"undici": "^7.16.0",
|
|
57
|
-
"vitest": "^4.0.
|
|
57
|
+
"vitest": "^4.0.13",
|
|
58
58
|
"yarn-audit-fix": "^10.1.1"
|
|
59
59
|
},
|
|
60
60
|
"optionalDependencies": {
|
|
@@ -110,5 +110,5 @@
|
|
|
110
110
|
"release": "semantic-release",
|
|
111
111
|
"release:dry": "semantic-release --dry-run"
|
|
112
112
|
},
|
|
113
|
-
"version": "1.
|
|
113
|
+
"version": "1.3.0"
|
|
114
114
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Script to republish missing versions to npm
|
|
4
|
+
# Usage: ./scripts/republish-versions.sh [version1] [version2]
|
|
5
|
+
# Example: ./scripts/republish-versions.sh 1.3.0 1.4.0
|
|
6
|
+
|
|
7
|
+
set -e
|
|
8
|
+
|
|
9
|
+
# Colors for output
|
|
10
|
+
RED='\033[0;31m'
|
|
11
|
+
GREEN='\033[0;32m'
|
|
12
|
+
YELLOW='\033[1;33m'
|
|
13
|
+
NC='\033[0m' # No Color
|
|
14
|
+
|
|
15
|
+
# Function to publish a version
|
|
16
|
+
publish_version() {
|
|
17
|
+
local version=$1
|
|
18
|
+
local tag="v${version}"
|
|
19
|
+
|
|
20
|
+
echo -e "${YELLOW}📦 Publishing version ${version}...${NC}"
|
|
21
|
+
|
|
22
|
+
# Check if tag exists
|
|
23
|
+
if ! git rev-parse "$tag" >/dev/null 2>&1; then
|
|
24
|
+
echo -e "${RED}❌ Tag ${tag} does not exist${NC}"
|
|
25
|
+
return 1
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
# Check if version is already published
|
|
29
|
+
if npm view "zod-codegen@${version}" version >/dev/null 2>&1; then
|
|
30
|
+
echo -e "${YELLOW}⚠️ Version ${version} already exists on npm. Skipping...${NC}"
|
|
31
|
+
return 0
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
# Save current branch/commit
|
|
35
|
+
local current_branch=$(git rev-parse --abbrev-ref HEAD)
|
|
36
|
+
local current_commit=$(git rev-parse HEAD)
|
|
37
|
+
|
|
38
|
+
echo -e "${GREEN}✓ Checking out tag ${tag}${NC}"
|
|
39
|
+
git checkout "$tag" --quiet
|
|
40
|
+
|
|
41
|
+
# Verify package.json version matches
|
|
42
|
+
local package_version=$(node -p "require('./package.json').version")
|
|
43
|
+
if [ "$package_version" != "$version" ]; then
|
|
44
|
+
echo -e "${RED}❌ Package.json version (${package_version}) doesn't match tag version (${version})${NC}"
|
|
45
|
+
git checkout "$current_branch" --quiet 2>/dev/null || git checkout "$current_commit" --quiet
|
|
46
|
+
return 1
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Install dependencies
|
|
50
|
+
echo -e "${GREEN}✓ Installing dependencies...${NC}"
|
|
51
|
+
yarn install --frozen-lockfile
|
|
52
|
+
|
|
53
|
+
# Build project
|
|
54
|
+
echo -e "${GREEN}✓ Building project...${NC}"
|
|
55
|
+
yarn build
|
|
56
|
+
|
|
57
|
+
# Run prepublishOnly checks (build, test, lint, type-check)
|
|
58
|
+
echo -e "${GREEN}✓ Running prepublish checks...${NC}"
|
|
59
|
+
yarn test
|
|
60
|
+
yarn lint:check
|
|
61
|
+
yarn type-check
|
|
62
|
+
|
|
63
|
+
# Publish to npm
|
|
64
|
+
echo -e "${GREEN}✓ Publishing to npm...${NC}"
|
|
65
|
+
npm publish --access public
|
|
66
|
+
|
|
67
|
+
echo -e "${GREEN}✅ Successfully published version ${version}${NC}"
|
|
68
|
+
|
|
69
|
+
# Return to original branch/commit
|
|
70
|
+
echo -e "${GREEN}✓ Returning to ${current_branch}...${NC}"
|
|
71
|
+
git checkout "$current_branch" --quiet 2>/dev/null || git checkout "$current_commit" --quiet
|
|
72
|
+
|
|
73
|
+
echo ""
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
# Check if npm is authenticated
|
|
77
|
+
if ! npm whoami >/dev/null 2>&1; then
|
|
78
|
+
echo -e "${RED}❌ Not authenticated to npm. Please run 'npm login' first.${NC}"
|
|
79
|
+
exit 1
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
echo -e "${GREEN}✓ Authenticated as $(npm whoami)${NC}"
|
|
83
|
+
echo ""
|
|
84
|
+
|
|
85
|
+
# Get versions from arguments or use defaults
|
|
86
|
+
VERSIONS=("${@:-1.3.0 1.4.0}")
|
|
87
|
+
|
|
88
|
+
# Publish each version
|
|
89
|
+
for version in "${VERSIONS[@]}"; do
|
|
90
|
+
publish_version "$version"
|
|
91
|
+
done
|
|
92
|
+
|
|
93
|
+
echo -e "${GREEN}🎉 All versions published successfully!${NC}"
|
|
94
|
+
|
|
@@ -53,6 +53,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
53
53
|
private buildAST(openapi: OpenApiSpecType): ts.Statement[] {
|
|
54
54
|
const imports = this.importBuilder.buildImports();
|
|
55
55
|
const schemas = this.buildSchemas(openapi);
|
|
56
|
+
const schemaTypeAliases = this.buildSchemaTypeAliases(schemas);
|
|
56
57
|
const serverConfig = this.buildServerConfiguration(openapi);
|
|
57
58
|
const clientClass = this.buildClientClass(openapi, schemas);
|
|
58
59
|
|
|
@@ -61,6 +62,7 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
61
62
|
...imports,
|
|
62
63
|
this.createComment('Components schemas'),
|
|
63
64
|
...Object.values(schemas),
|
|
65
|
+
...schemaTypeAliases,
|
|
64
66
|
...serverConfig,
|
|
65
67
|
this.createComment('Client class'),
|
|
66
68
|
clientClass,
|
|
@@ -97,6 +99,21 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
97
99
|
}, {});
|
|
98
100
|
}
|
|
99
101
|
|
|
102
|
+
private buildSchemaTypeAliases(schemas: Record<string, ts.VariableStatement>): ts.TypeAliasDeclaration[] {
|
|
103
|
+
return Object.keys(schemas).map((name) => {
|
|
104
|
+
const sanitizedName = this.typeBuilder.sanitizeIdentifier(name);
|
|
105
|
+
return ts.factory.createTypeAliasDeclaration(
|
|
106
|
+
[ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
|
|
107
|
+
ts.factory.createIdentifier(sanitizedName),
|
|
108
|
+
undefined,
|
|
109
|
+
ts.factory.createTypeReferenceNode(
|
|
110
|
+
ts.factory.createQualifiedName(ts.factory.createIdentifier('z'), ts.factory.createIdentifier('infer')),
|
|
111
|
+
[ts.factory.createTypeQueryNode(ts.factory.createIdentifier(sanitizedName), undefined)],
|
|
112
|
+
),
|
|
113
|
+
);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
100
117
|
private buildClientClass(
|
|
101
118
|
openapi: OpenApiSpecType,
|
|
102
119
|
schemas: Record<string, ts.VariableStatement>,
|
|
@@ -1264,48 +1281,41 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
1264
1281
|
|
|
1265
1282
|
const responseSchema = response.content['application/json'].schema;
|
|
1266
1283
|
const typeName = this.getSchemaTypeName(responseSchema, schemas);
|
|
1267
|
-
const inferredType = this.wrapTypeWithZInfer(typeName, schemas);
|
|
1268
|
-
|
|
1269
|
-
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [inferredType]);
|
|
1270
|
-
}
|
|
1271
|
-
|
|
1272
|
-
private wrapTypeWithZInfer(typeName: string, schemas: Record<string, ts.VariableStatement>): ts.TypeNode {
|
|
1273
|
-
// Primitive types and Record types don't need z.infer
|
|
1274
|
-
const primitiveTypes = ['string', 'number', 'boolean', 'unknown'];
|
|
1275
|
-
if (primitiveTypes.includes(typeName) || typeName.startsWith('Record<')) {
|
|
1276
|
-
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined);
|
|
1277
|
-
}
|
|
1278
1284
|
|
|
1279
1285
|
// Handle array types like "Pet[]"
|
|
1280
1286
|
if (typeName.endsWith('[]')) {
|
|
1281
1287
|
const itemTypeName = typeName.slice(0, -2);
|
|
1282
1288
|
const sanitizedItemTypeName = this.typeBuilder.sanitizeIdentifier(itemTypeName);
|
|
1283
1289
|
|
|
1284
|
-
// Check if the item type is a custom schema
|
|
1290
|
+
// Check if the item type is a custom schema (we have a type alias for it)
|
|
1285
1291
|
if (schemas[sanitizedItemTypeName]) {
|
|
1286
|
-
//
|
|
1287
|
-
|
|
1288
|
-
ts.factory.
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
+
// Use the type alias directly (it already uses z.infer)
|
|
1293
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
1294
|
+
ts.factory.createArrayTypeNode(
|
|
1295
|
+
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedItemTypeName), undefined),
|
|
1296
|
+
),
|
|
1297
|
+
]);
|
|
1292
1298
|
}
|
|
1293
|
-
// If it's a primitive array,
|
|
1294
|
-
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(
|
|
1299
|
+
// If it's a primitive array, use the type name as-is
|
|
1300
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
1301
|
+
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined),
|
|
1302
|
+
]);
|
|
1295
1303
|
}
|
|
1296
1304
|
|
|
1297
|
-
// Handle custom schema types
|
|
1298
1305
|
const sanitizedTypeName = this.typeBuilder.sanitizeIdentifier(typeName);
|
|
1306
|
+
|
|
1307
|
+
// Check if it's a custom schema type (we have a type alias for it)
|
|
1299
1308
|
if (schemas[sanitizedTypeName]) {
|
|
1300
|
-
//
|
|
1301
|
-
return ts.factory.createTypeReferenceNode(
|
|
1302
|
-
ts.factory.
|
|
1303
|
-
|
|
1304
|
-
);
|
|
1309
|
+
// Use the type name directly (we have a type alias that already uses z.infer)
|
|
1310
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
1311
|
+
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(sanitizedTypeName), undefined),
|
|
1312
|
+
]);
|
|
1305
1313
|
}
|
|
1306
1314
|
|
|
1307
|
-
//
|
|
1308
|
-
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(
|
|
1315
|
+
// For primitive types and Record types, use the type name directly
|
|
1316
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('Promise'), [
|
|
1317
|
+
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(typeName), undefined),
|
|
1318
|
+
]);
|
|
1309
1319
|
}
|
|
1310
1320
|
|
|
1311
1321
|
private buildServerConfiguration(openapi: OpenApiSpecType): ts.Statement[] {
|
|
@@ -2276,7 +2286,10 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2276
2286
|
switch (prop['format']) {
|
|
2277
2287
|
case 'email':
|
|
2278
2288
|
stringSchema = ts.factory.createCallExpression(
|
|
2279
|
-
ts.factory.createPropertyAccessExpression(
|
|
2289
|
+
ts.factory.createPropertyAccessExpression(
|
|
2290
|
+
ts.factory.createIdentifier('z'),
|
|
2291
|
+
ts.factory.createIdentifier('email'),
|
|
2292
|
+
),
|
|
2280
2293
|
undefined,
|
|
2281
2294
|
[],
|
|
2282
2295
|
);
|
|
@@ -2284,28 +2297,46 @@ export class TypeScriptCodeGeneratorService implements CodeGenerator, SchemaBuil
|
|
|
2284
2297
|
case 'uri':
|
|
2285
2298
|
case 'url':
|
|
2286
2299
|
stringSchema = ts.factory.createCallExpression(
|
|
2287
|
-
ts.factory.createPropertyAccessExpression(
|
|
2300
|
+
ts.factory.createPropertyAccessExpression(
|
|
2301
|
+
ts.factory.createIdentifier('z'),
|
|
2302
|
+
ts.factory.createIdentifier('url'),
|
|
2303
|
+
),
|
|
2288
2304
|
undefined,
|
|
2289
2305
|
[],
|
|
2290
2306
|
);
|
|
2291
2307
|
break;
|
|
2292
2308
|
case 'uuid':
|
|
2293
2309
|
stringSchema = ts.factory.createCallExpression(
|
|
2294
|
-
ts.factory.createPropertyAccessExpression(
|
|
2310
|
+
ts.factory.createPropertyAccessExpression(
|
|
2311
|
+
ts.factory.createIdentifier('z'),
|
|
2312
|
+
ts.factory.createIdentifier('uuid'),
|
|
2313
|
+
),
|
|
2295
2314
|
undefined,
|
|
2296
2315
|
[],
|
|
2297
2316
|
);
|
|
2298
2317
|
break;
|
|
2299
2318
|
case 'date-time':
|
|
2300
2319
|
stringSchema = ts.factory.createCallExpression(
|
|
2301
|
-
ts.factory.createPropertyAccessExpression(
|
|
2320
|
+
ts.factory.createPropertyAccessExpression(
|
|
2321
|
+
ts.factory.createPropertyAccessExpression(
|
|
2322
|
+
ts.factory.createIdentifier('z'),
|
|
2323
|
+
ts.factory.createIdentifier('iso'),
|
|
2324
|
+
),
|
|
2325
|
+
ts.factory.createIdentifier('datetime'),
|
|
2326
|
+
),
|
|
2302
2327
|
undefined,
|
|
2303
|
-
[],
|
|
2328
|
+
[this.buildDefaultValue({local: true})],
|
|
2304
2329
|
);
|
|
2305
2330
|
break;
|
|
2306
2331
|
case 'date':
|
|
2307
2332
|
stringSchema = ts.factory.createCallExpression(
|
|
2308
|
-
ts.factory.createPropertyAccessExpression(
|
|
2333
|
+
ts.factory.createPropertyAccessExpression(
|
|
2334
|
+
ts.factory.createPropertyAccessExpression(
|
|
2335
|
+
ts.factory.createIdentifier('z'),
|
|
2336
|
+
ts.factory.createIdentifier('iso'),
|
|
2337
|
+
),
|
|
2338
|
+
ts.factory.createIdentifier('date'),
|
|
2339
|
+
),
|
|
2309
2340
|
undefined,
|
|
2310
2341
|
[],
|
|
2311
2342
|
);
|