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, csharp): generate Environments.cs and populate default BaseURL #3677

Merged
merged 3 commits into from
May 22, 2024
Merged
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
2 changes: 1 addition & 1 deletion generators/csharp/codegen/src/asIs/RawClient.Template.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public class ApiResponse

private string BuildUrl(string path, Dictionary<string, object> query)
{
var url = $"{_clientOptions.BaseUrl}/{path}";
var url = $"{_clientOptions.BaseUrl}{path}";
if (query.Count > 0)
{
url += "?";
Expand Down
20 changes: 19 additions & 1 deletion generators/csharp/codegen/src/ast/Field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export declare namespace Field {
init?: boolean;
/* The access level of the method */
access: Access;
/* Whether the field is static */
static_?: boolean;
/* Field annotations */
annotations?: Annotation[];
/* The initializer for the field */
Expand All @@ -39,8 +41,20 @@ export class Field extends AstNode {
private initializer: CodeBlock | undefined;
private summary: string | undefined;
private jsonPropertyName: string | undefined;
private static_: boolean | undefined;

constructor({ name, type, get, init, access, annotations, initializer, summary, jsonPropertyName }: Field.Args) {
constructor({
name,
type,
get,
init,
access,
annotations,
initializer,
summary,
jsonPropertyName,
static_
}: Field.Args) {
super();
this.name = name;
this.type = type;
Expand All @@ -51,6 +65,7 @@ export class Field extends AstNode {
this.initializer = initializer;
this.summary = summary;
this.jsonPropertyName = jsonPropertyName;
this.static_ = static_;

if (this.jsonPropertyName != null) {
this.annotations = [
Expand Down Expand Up @@ -84,6 +99,9 @@ export class Field extends AstNode {
}

writer.write(`${this.access} `);
if (this.static_) {
writer.write("static ");
}
writer.writeNode(this.type);
writer.write(` ${this.name}`);

Expand Down
3 changes: 2 additions & 1 deletion generators/csharp/codegen/src/csharp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,12 @@ export const Types = Type;
export {
Annotation,
Class,
ClassReference,
ClassInstantiation,
ClassReference,
CodeBlock,
Dictionary,
Enum,
Field,
Method,
MethodInvocation,
Parameter,
Expand Down
20 changes: 18 additions & 2 deletions generators/csharp/sdk/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,26 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.0.12 - 2024-05-22]

- Improvement: The C# generator now generates an `Environments.cs` file which contains
URLs for the different environments. If a default environment is present, then
the `BaseURL` in `ClientOptions.cs` will be initialized to this value.

```csharp
class Environments {

public static string PRODUCTION = "https://api.production.com";

public static string STAGING = "https://api.staging.com";

}
```

## [0.0.11 - 2024-05-20]

- Fix: The C# generator now generates a proper `.csproj` file with version, GitHub url, and
a reference to the SDK README.
- Fix: The C# generator now generates a proper `.csproj` file with version, GitHub url, and
a reference to the SDK README.

## [0.0.10 - 2024-05-15]

Expand Down
2 changes: 1 addition & 1 deletion generators/csharp/sdk/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.0.11
0.0.12
9 changes: 9 additions & 0 deletions generators/csharp/sdk/src/SdkGeneratorCli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { GeneratorNotificationService } from "@fern-api/generator-commons";
import { FernGeneratorExec } from "@fern-fern/generator-exec-sdk";
import { IntermediateRepresentation } from "@fern-fern/ir-sdk/api";
import { ClientOptionsGenerator } from "./client-options/ClientOptionsGenerator";
import { EnvironmentGenerator } from "./environment/EnvironmentGenerator";
import { RootClientGenerator } from "./root-client/RootClientGenerator";
import { SdkCustomConfigSchema } from "./SdkCustomConfig";
import { SdkGeneratorContext } from "./SdkGeneratorContext";
Expand Down Expand Up @@ -79,6 +80,14 @@ export class SdkGeneratorCLI extends AbstractCsharpGeneratorCli<SdkCustomConfigS
const rootClient = new RootClientGenerator(context);
context.project.addSourceFiles(rootClient.generate());

if (context.ir.environments?.environments.type === "singleBaseUrl") {
const environments = new EnvironmentGenerator({
context,
singleUrlEnvironments: context.ir.environments?.environments
});
context.project.addSourceFiles(environments.generate());
}

const testGenerator = new TestFileGenerator(context);
const test = testGenerator.generate();
context.project.addTestFiles(test);
Expand Down
7 changes: 7 additions & 0 deletions generators/csharp/sdk/src/SdkGeneratorContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ export class SdkGeneratorContext extends AbstractCsharpGeneratorContext<SdkCusto
});
}

public getEnvironmentsClassReference(): csharp.ClassReference {
return csharp.classReference({
name: "Environments",
namespace: this.getCoreNamespace()
});
}

public getClientOptionsClassReference(): csharp.ClassReference {
return csharp.classReference({
name: CLIENT_OPTIONS_CLASS_NAME,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
import { csharp, CSharpFile, FileGenerator } from "@fern-api/csharp-codegen";
import { join, RelativeFilePath } from "@fern-api/fs-utils";
import { SingleBaseUrlEnvironment } from "@fern-fern/ir-sdk/api";
import { SdkCustomConfigSchema } from "../SdkCustomConfig";
import { SdkGeneratorContext } from "../SdkGeneratorContext";

export const BASE_URL_FIELD = csharp.field({
access: "public",
name: "BaseUrl",
get: true,
init: true,
type: csharp.Type.optional(csharp.Type.string()),
summary: "The Base URL for the API."
});

export const HTTP_CLIENT_FIELD = csharp.field({
access: "public",
name: "HttpClient",
Expand Down Expand Up @@ -56,7 +48,7 @@ export class ClientOptionsGenerator extends FileGenerator<CSharpFile, SdkCustomC
partial: true,
access: "public"
});
class_.addField(BASE_URL_FIELD);
class_.addField(this.getBaseUrlField());
class_.addField(HTTP_CLIENT_FIELD);
class_.addField(MAX_RETRIES_FIELD);
class_.addField(TIMEOUT_IN_SECONDS);
Expand All @@ -72,4 +64,36 @@ export class ClientOptionsGenerator extends FileGenerator<CSharpFile, SdkCustomC
RelativeFilePath.of(`${CLIENT_OPTIONS_CLASS_NAME}.cs`)
);
}

private getBaseUrlField(): csharp.Field {
let defaultEnvironment: SingleBaseUrlEnvironment | undefined = undefined;
if (
this.context.ir.environments?.defaultEnvironment != null &&
this.context.ir.environments?.environments.type === "singleBaseUrl"
) {
const singleBaseUrlDefault = this.context.ir.environments.environments.environments.filter(
(singleBaseUrl) => {
return singleBaseUrl.id === this.context.ir.environments?.defaultEnvironment;
}
);
if (singleBaseUrlDefault[0] != null) {
defaultEnvironment = singleBaseUrlDefault[0];
}
}
return csharp.field({
access: "public",
name: "BaseUrl",
get: true,
init: true,
type: csharp.Type.string(),
summary: "The Base URL for the API.",
initializer:
defaultEnvironment != null
? csharp.codeblock((writer) => {
writer.writeNode(this.context.getEnvironmentsClassReference());
writer.write(`.${defaultEnvironment?.name.screamingSnakeCase.safeName}`);
})
: undefined
});
}
}
53 changes: 53 additions & 0 deletions generators/csharp/sdk/src/environment/EnvironmentGenerator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { csharp, CSharpFile, FileGenerator } from "@fern-api/csharp-codegen";
import { join, RelativeFilePath } from "@fern-api/fs-utils";
import { SingleBaseUrlEnvironments } from "@fern-fern/ir-sdk/api";
import { SdkCustomConfigSchema } from "../SdkCustomConfig";
import { SdkGeneratorContext } from "../SdkGeneratorContext";

export declare namespace EnvironmentGenerator {
interface Args {
context: SdkGeneratorContext;
singleUrlEnvironments: SingleBaseUrlEnvironments;
}
}

export class EnvironmentGenerator extends FileGenerator<CSharpFile, SdkCustomConfigSchema, SdkGeneratorContext> {
private singleUrlEnvironments: SingleBaseUrlEnvironments;

constructor({ context, singleUrlEnvironments }: EnvironmentGenerator.Args) {
super(context);
this.singleUrlEnvironments = singleUrlEnvironments;
}

public doGenerate(): CSharpFile {
const class_ = csharp.class_({
...this.context.getEnvironmentsClassReference(),
partial: false,
access: "public"
});

for (const environment of this.singleUrlEnvironments.environments) {
class_.addField(
csharp.field({
access: "public",
name: environment.name.screamingSnakeCase.safeName,
static_: true,
type: csharp.Type.string(),
initializer: csharp.codeblock(`"${environment.url}"`)
})
);
}

return new CSharpFile({
clazz: class_,
directory: RelativeFilePath.of(this.context.getCoreDirectory())
});
}

protected getFilepath(): RelativeFilePath {
return join(
this.context.project.filepaths.getCoreFilesDirectory(),
RelativeFilePath.of(`${this.context.getEnvironmentsClassReference().name}.cs`)
);
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion seed/csharp-sdk/alias/src/SeedAlias/Core/RawClient.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading