Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(typescript): Support inline types in TypeScript generator #5350

Merged
merged 32 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
de0bcc9
Implement inline types (WIP)
Swimburger Dec 1, 2024
35c42dd
Add support for undiscriminated unions deep
Swimburger Dec 5, 2024
837b55b
Clean up type reference generation
Swimburger Dec 5, 2024
54b73e9
Refactor to converters
Swimburger Dec 5, 2024
50d5b24
Fix imports
Swimburger Dec 5, 2024
f695c5e
reduce code duplication
Swimburger Dec 5, 2024
4576d44
improve request generator
Swimburger Dec 5, 2024
0df0f1e
Remove duplicate writeFile functions
Swimburger Dec 5, 2024
d00d27e
Add feature flag
Swimburger Dec 6, 2024
f0d2eeb
merge from main
Swimburger Dec 6, 2024
4d900c2
Fix docs & eslint
Swimburger Dec 7, 2024
89e8351
fix missing client class
Swimburger Dec 7, 2024
a3dd964
Fix eslint issues
Swimburger Dec 7, 2024
dd501a5
Merge branch 'main' of https://github.com/fern-api/fern into niels/ts…
Swimburger Dec 9, 2024
cd630d5
Use latest Fern IR for TypeScript package.json's
Swimburger Dec 9, 2024
fa21a0d
export inline array type
Swimburger Dec 9, 2024
a254712
Fix Fern CLI OpenAPI to Fern inline enum
Swimburger Dec 9, 2024
0bb4d6b
chore: update changelog
Swimburger Dec 9, 2024
e0e3580
eslint cleanup
Swimburger Dec 9, 2024
8f3de1f
Update schemas and express generator to explicitly say it doesn't sup…
Swimburger Dec 9, 2024
120e60b
Set `inline: true` for maps generated from OpenAPI additionalProperties.
Swimburger Dec 10, 2024
f0f7811
Add inline alias implementation + fix inline bugs
Swimburger Dec 10, 2024
8bedc09
DRY up inline module generation
Swimburger Dec 11, 2024
655f564
Incorporate PR feedback
Swimburger Dec 11, 2024
fe3c553
Merge branch 'main' into niels/ts/inline-types
Swimburger Dec 11, 2024
febf26f
chore: update changelog
Swimburger Dec 11, 2024
0c9732b
Fix linting issues
Swimburger Dec 11, 2024
4d0fb84
Merge branch 'niels/ts/inline-types' of https://github.com/fern-api/f…
Swimburger Dec 11, 2024
81ef80d
Write changelog entry for TS SDK
Swimburger Dec 11, 2024
8bb8e7c
Update test snapshots
Swimburger Dec 11, 2024
970d79d
Merge branch 'main' into niels/ts/inline-types
dsinghvi Dec 11, 2024
76eb20c
Merge branch 'niels/ts/inline-types' of https://github.com/fern-api/f…
Swimburger Dec 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
9 changes: 2 additions & 7 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,7 @@ module.exports = {
ignoreRestSiblings: true
}
],
"@typescript-eslint/no-namespace": [
"error",
{
allowDeclarations: true
}
],
"@typescript-eslint/no-namespace": "off",
Swimburger marked this conversation as resolved.
Show resolved Hide resolved
"@typescript-eslint/explicit-module-boundary-types": [
"error",
{
Expand Down Expand Up @@ -129,7 +124,7 @@ module.exports = {
{
files: ['**/*.test.ts', '**/*.spec.ts'],
rules: {
'no-console': 'off'
'no-console': 'off'
}
}
]
Expand Down
2 changes: 1 addition & 1 deletion fern/pages/changelogs/cli/2024-12-05.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## 0.45.3
**`(fix):`** Unknown schemas are no longer incorrectly marked as `additionalProperties: true`.
**`(fix):`** Unknown schemas are no longer incorrectly marked as `additionalProperties: true`.


4 changes: 4 additions & 0 deletions fern/pages/changelogs/cli/2024-12-09.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
## 0.45.4
**`(fix):`** Set `inline: true` for inline enums imported from OpenAPI


4 changes: 4 additions & 0 deletions fern/pages/changelogs/python-sdk/2024-12-08.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
## 4.3.9
**`(fix):`** Fix indentation in generated README.md sections to ensure proper formatting and readability.


2 changes: 1 addition & 1 deletion generators/typescript/codegen/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"devDependencies": {
"@fern-api/core-utils": "workspace:*",
"@fern-api/base-generator": "workspace:*",
"@fern-fern/ir-sdk": "53.8.0",
"@fern-fern/ir-sdk": "53.23.0",
"@types/jest": "^29.5.12",
"@types/node": "18.7.18",
"depcheck": "^1.4.6",
Expand Down
2 changes: 1 addition & 1 deletion generators/typescript/express/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
},
"devDependencies": {
"@fern-fern/generator-exec-sdk": "^0.0.898",
"@fern-fern/ir-sdk": "53.8.0",
"@fern-fern/ir-sdk": "53.23.0",
"@fern-typescript/abstract-generator-cli": "workspace:*",
"@fern-typescript/commons": "workspace:*",
"@fern-typescript/contexts": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import { NpmPackage, PersistedTypescriptProject } from "@fern-typescript/commons
import { GeneratorContext } from "@fern-typescript/contexts";
import { ExpressGenerator } from "@fern-typescript/express-generator";
import { camelCase, upperFirst } from "lodash-es";
import { custom } from "zod";
import { ExpressCustomConfig } from "./custom-config/ExpressCustomConfig";
import { ExpressCustomConfigSchema } from "./custom-config/schema/ExpressCustomConfigSchema";

export class ExpressGeneratorCli extends AbstractGeneratorCli<ExpressCustomConfig> {
protected parseCustomConfig(customConfig: unknown): ExpressCustomConfig {
const parsed = customConfig != null ? ExpressCustomConfigSchema.parse(customConfig) : undefined;
const noSerdeLayer = parsed?.noSerdeLayer ?? false;
const inlineInlineTypes = false; // hardcode, not supported in Express
return {
useBrandedStringAliases: parsed?.useBrandedStringAliases ?? false,
areImplementationsOptional: parsed?.optionalImplementations ?? false,
Expand All @@ -29,7 +29,8 @@ export class ExpressGeneratorCli extends AbstractGeneratorCli<ExpressCustomConfi
skipRequestValidation: parsed?.skipRequestValidation ?? false,
skipResponseValidation: parsed?.skipResponseValidation ?? false,
useBigInt: parsed?.useBigInt ?? false,
noOptionalProperties: parsed?.noOptionalProperties ?? false
noOptionalProperties: parsed?.noOptionalProperties ?? false,
inlineInlineTypes
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ export interface ExpressCustomConfig {
allowExtraFields: boolean;
useBigInt: boolean;
noOptionalProperties: boolean;
inlineInlineTypes: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
},
"dependencies": {
"@fern-api/core-utils": "workspace:*",
"@fern-fern/ir-sdk": "53.8.0",
"@fern-fern/ir-sdk": "53.23.0",
"@fern-typescript/abstract-schema-generator": "workspace:*",
"@fern-typescript/commons": "workspace:*",
"@fern-typescript/contexts": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"depcheck": "depcheck"
},
"dependencies": {
"@fern-fern/ir-sdk": "53.8.0",
"@fern-fern/ir-sdk": "53.23.0",
"@fern-typescript/abstract-error-class-generator": "workspace:*",
"@fern-typescript/commons": "workspace:*",
"@fern-typescript/contexts": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
},
"dependencies": {
"@fern-api/core-utils": "workspace:*",
"@fern-fern/ir-sdk": "53.8.0",
"@fern-fern/ir-sdk": "53.23.0",
"@fern-typescript/abstract-schema-generator": "workspace:*",
"@fern-typescript/commons": "workspace:*",
"@fern-typescript/contexts": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"depcheck": "depcheck"
},
"dependencies": {
"@fern-fern/ir-sdk": "53.8.0",
"@fern-fern/ir-sdk": "53.23.0",
"@fern-typescript/commons": "workspace:*",
"@fern-typescript/contexts": "workspace:*"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"depcheck": "depcheck"
},
"dependencies": {
"@fern-fern/ir-sdk": "53.8.0",
"@fern-fern/ir-sdk": "53.23.0",
"@fern-typescript/abstract-schema-generator": "workspace:*",
"@fern-typescript/commons": "workspace:*",
"@fern-typescript/contexts": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"depcheck": "depcheck"
},
"dependencies": {
"@fern-fern/ir-sdk": "53.8.0",
"@fern-fern/ir-sdk": "53.23.0",
"@fern-typescript/commons": "workspace:*",
"@fern-typescript/contexts": "workspace:*",
"@fern-typescript/resolvers": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"depcheck": "depcheck"
},
"dependencies": {
"@fern-fern/ir-sdk": "53.8.0",
"@fern-fern/ir-sdk": "53.23.0",
"@fern-typescript/commons": "workspace:*",
"@fern-typescript/contexts": "workspace:*",
"@fern-typescript/resolvers": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
Package,
PathParameter
} from "@fern-fern/ir-sdk/api";
import { convertHttpPathToExpressRoute, getTextOfTsNode, maybeAddDocs, PackageId } from "@fern-typescript/commons";
import { convertHttpPathToExpressRoute, getTextOfTsNode, maybeAddDocsNode, PackageId } from "@fern-typescript/commons";
import { ExpressContext, GeneratedExpressService } from "@fern-typescript/contexts";
import { ClassDeclaration, InterfaceDeclaration, Scope, ts } from "ts-morph";

Expand Down Expand Up @@ -82,7 +82,7 @@ export class GeneratedExpressServiceImpl implements GeneratedExpressService {
name: this.serviceClassName,
isExported: true
});
maybeAddDocs(serviceClass, this.package_.docs);
maybeAddDocsNode(serviceClass, this.package_.docs);

serviceClass.addProperty({
scope: Scope.Private,
Expand Down
3 changes: 2 additions & 1 deletion generators/typescript/express/generator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
"dependencies": {
"@fern-api/core-utils": "workspace:*",
"@fern-api/fs-utils": "workspace:*",
"@fern-fern/ir-sdk": "53.8.0",
"@fern-api/logger": "workspace:*",
"@fern-fern/ir-sdk": "53.23.0",
"@fern-typescript/commons": "workspace:*",
"@fern-typescript/contexts": "workspace:*",
"@fern-typescript/express-endpoint-type-schemas-generator": "workspace:*",
Expand Down
80 changes: 65 additions & 15 deletions generators/typescript/express/generator/src/ExpressGenerator.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { AbsoluteFilePath } from "@fern-api/fs-utils";
import { HttpService, IntermediateRepresentation } from "@fern-fern/ir-sdk/api";
import { HttpService, IntermediateRepresentation, TypeDeclaration, TypeId } from "@fern-fern/ir-sdk/api";
import {
convertExportedFilePathToFilePath,
CoreUtilitiesManager,
Expand Down Expand Up @@ -27,6 +27,7 @@ import { TypeGenerator } from "@fern-typescript/type-generator";
import { TypeReferenceExampleGenerator } from "@fern-typescript/type-reference-example-generator";
import { TypeSchemaGenerator } from "@fern-typescript/type-schema-generator";
import { Directory, Project, SourceFile } from "ts-morph";
import { Logger } from "@fern-api/logger";
import { ExpressContextImpl } from "./contexts/ExpressContextImpl";
import { EndpointDeclarationReferencer } from "./declaration-referencers/EndpointDeclarationReferencer";
import { ExpressErrorDeclarationReferencer } from "./declaration-referencers/ExpressErrorDeclarationReferencer";
Expand Down Expand Up @@ -188,7 +189,8 @@ export class ExpressGenerator {
includeOtherInUnionTypes: config.includeOtherInUnionTypes,
includeSerdeLayer: config.includeSerdeLayer,
retainOriginalCasing: config.retainOriginalCasing,
noOptionalProperties: config.noOptionalProperties
noOptionalProperties: config.noOptionalProperties,
inlineInlineTypes: false
});
this.typeSchemaGenerator = new TypeSchemaGenerator({
includeUtilsOnUnionMembers: config.includeUtilsOnUnionMembers,
Expand Down Expand Up @@ -276,24 +278,36 @@ export class ExpressGenerator {
await this.coreUtilitiesManager.copyCoreUtilities({ pathToSrc, pathToRoot });
}

private getTypesToGenerate(): Record<TypeId, TypeDeclaration> {
return this.intermediateRepresentation.types;
}

private generateTypeDeclarations() {
for (const typeDeclaration of Object.values(this.intermediateRepresentation.types)) {
for (const typeDeclaration of Object.values(this.getTypesToGenerate())) {
this.withSourceFile({
filepath: this.typeDeclarationReferencer.getExportedFilepath(typeDeclaration.name),
run: ({ sourceFile, importsManager }) => {
const context = this.generateExpressContext({ sourceFile, importsManager });
const context = this.generateExpressContext({
logger: this.context.logger,
sourceFile,
importsManager
});
context.type.getGeneratedType(typeDeclaration.name).writeToFile(context);
}
});
}
}

private generateTypeSchemas() {
for (const typeDeclaration of Object.values(this.intermediateRepresentation.types)) {
for (const typeDeclaration of Object.values(this.getTypesToGenerate())) {
this.withSourceFile({
filepath: this.typeSchemaDeclarationReferencer.getExportedFilepath(typeDeclaration.name),
run: ({ sourceFile, importsManager }) => {
const context = this.generateExpressContext({ sourceFile, importsManager });
const context = this.generateExpressContext({
logger: this.context.logger,
sourceFile,
importsManager
});
context.typeSchema.getGeneratedTypeSchema(typeDeclaration.name).writeToFile(context);
}
});
Expand All @@ -305,7 +319,11 @@ export class ExpressGenerator {
this.withSourceFile({
filepath: this.expressErrorDeclarationReferencer.getExportedFilepath(errorDeclaration.name),
run: ({ sourceFile, importsManager }) => {
const context = this.generateExpressContext({ sourceFile, importsManager });
const context = this.generateExpressContext({
logger: this.context.logger,
sourceFile,
importsManager
});
context.expressError.getGeneratedExpressError(errorDeclaration.name).writeToFile(context);
}
});
Expand All @@ -317,7 +335,11 @@ export class ExpressGenerator {
this.withSourceFile({
filepath: this.expressErrorSchemaDeclarationReferencer.getExportedFilepath(errorDeclaration.name),
run: ({ sourceFile, importsManager }) => {
const context = this.generateExpressContext({ sourceFile, importsManager });
const context = this.generateExpressContext({
logger: this.context.logger,
sourceFile,
importsManager
});
context.expressErrorSchema
.getGeneratedExpressErrorSchema(errorDeclaration.name)
?.writeToFile(context);
Expand All @@ -336,7 +358,11 @@ export class ExpressGenerator {
endpoint
}),
run: ({ sourceFile, importsManager }) => {
const context = this.generateExpressContext({ sourceFile, importsManager });
const context = this.generateExpressContext({
logger: this.context.logger,
sourceFile,
importsManager
});
context.expressInlinedRequestBody
.getGeneratedInlinedRequestBody(packageId, endpoint.name)
.writeToFile(context);
Expand All @@ -357,7 +383,11 @@ export class ExpressGenerator {
endpoint
}),
run: ({ sourceFile, importsManager }) => {
const context = this.generateExpressContext({ sourceFile, importsManager });
const context = this.generateExpressContext({
logger: this.context.logger,
sourceFile,
importsManager
});
context.expressInlinedRequestBodySchema
.getGeneratedInlinedRequestBodySchema(packageId, endpoint.name)
.writeToFile(context);
Expand All @@ -377,7 +407,11 @@ export class ExpressGenerator {
endpoint
}),
run: ({ sourceFile, importsManager }) => {
const context = this.generateExpressContext({ sourceFile, importsManager });
const context = this.generateExpressContext({
logger: this.context.logger,
sourceFile,
importsManager
});
context.expressEndpointTypeSchemas
.getGeneratedEndpointTypeSchemas(packageId, endpoint.name)
.writeToFile(context);
Expand All @@ -392,7 +426,11 @@ export class ExpressGenerator {
this.withSourceFile({
filepath: this.expressServiceDeclarationReferencer.getExportedFilepath(packageId),
run: ({ sourceFile, importsManager }) => {
const context = this.generateExpressContext({ sourceFile, importsManager });
const context = this.generateExpressContext({
logger: this.context.logger,
sourceFile,
importsManager
});
context.expressService.getGeneratedExpressService(packageId).writeToFile(context);
}
});
Expand All @@ -403,7 +441,11 @@ export class ExpressGenerator {
this.withSourceFile({
filepath: this.expressRegisterDeclarationReferencer.getExportedFilepath(),
run: ({ sourceFile, importsManager }) => {
const context = this.generateExpressContext({ sourceFile, importsManager });
const context = this.generateExpressContext({
logger: this.context.logger,
sourceFile,
importsManager
});
context.expressRegister.getGeneratedExpressRegister()?.writeToFile(context);
}
});
Expand All @@ -413,7 +455,11 @@ export class ExpressGenerator {
this.withSourceFile({
filepath: this.genericApiExpressErrorDeclarationReferencer.getExportedFilepath(),
run: ({ sourceFile, importsManager }) => {
const context = this.generateExpressContext({ sourceFile, importsManager });
const context = this.generateExpressContext({
logger: this.context.logger,
sourceFile,
importsManager
});
context.genericAPIExpressError.getGeneratedGenericAPIExpressError().writeToFile(context);
}
});
Expand Down Expand Up @@ -470,13 +516,16 @@ export class ExpressGenerator {
}

private generateExpressContext({
logger,
sourceFile,
importsManager
}: {
logger: Logger;
sourceFile: SourceFile;
importsManager: ImportsManager;
}): ExpressContextImpl {
return new ExpressContextImpl({
logger,
sourceFile,
coreUtilitiesManager: this.coreUtilitiesManager,
dependencyManager: this.dependencyManager,
Expand Down Expand Up @@ -509,7 +558,8 @@ export class ExpressGenerator {
expressErrorSchemaGenerator: this.expressErrorSchemaGenerator,
includeSerdeLayer: this.config.includeSerdeLayer,
retainOriginalCasing: this.config.retainOriginalCasing,
useBigInt: this.config.useBigInt
useBigInt: this.config.useBigInt,
inlineInlineTypes: false
});
}
}
Loading
Loading