Skip to content

Commit

Permalink
fix(cli): numerous improvments to the conjure importer (#4849)
Browse files Browse the repository at this point in the history
  • Loading branch information
dsinghvi authored Oct 11, 2024
1 parent 5ae618d commit 3007204
Show file tree
Hide file tree
Showing 54 changed files with 339 additions and 105 deletions.
4 changes: 4 additions & 0 deletions fern/pages/changelogs/cli/2024-10-11.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
## 0.45.0-rc3
**`(fix):`** Numerous fixes to the Conjure API Importer such as reading in request bodies and query parameters.


Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ types:
ConjureArgument:
discriminated: false
union:
- types.ConjureTypeReference
- string
- ConjureArgumentWithParamType

ConjureArgumentWithParamType:
extends:
- commons.WithDocs
properties:
param-type: ConjureParamType
type: types.ConjureTypeReference
type: string

ConjureParamType:
enum:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

import * as FernConjure from "../../../index";

export type ConjureArgument = FernConjure.ConjureTypeReference | FernConjure.ConjureArgumentWithParamType;
export type ConjureArgument = string | FernConjure.ConjureArgumentWithParamType;
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ import * as FernConjure from "../../../index";

export interface ConjureArgumentWithParamType extends FernConjure.WithDocs {
paramType: FernConjure.ConjureParamType;
type: FernConjure.ConjureTypeReference;
type: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@
import * as serializers from "../../../index";
import * as FernConjure from "../../../../api/index";
import * as core from "../../../../core";
import { ConjureTypeReference } from "../../types/types/ConjureTypeReference";
import { ConjureArgumentWithParamType } from "./ConjureArgumentWithParamType";

export const ConjureArgument: core.serialization.Schema<serializers.ConjureArgument.Raw, FernConjure.ConjureArgument> =
core.serialization.undiscriminatedUnion([ConjureTypeReference, ConjureArgumentWithParamType]);
core.serialization.undiscriminatedUnion([core.serialization.string(), ConjureArgumentWithParamType]);

export declare namespace ConjureArgument {
type Raw = ConjureTypeReference.Raw | ConjureArgumentWithParamType.Raw;
type Raw = string | ConjureArgumentWithParamType.Raw;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import * as serializers from "../../../index";
import * as FernConjure from "../../../../api/index";
import * as core from "../../../../core";
import { ConjureParamType } from "./ConjureParamType";
import { ConjureTypeReference } from "../../types/types/ConjureTypeReference";
import { WithDocs } from "../../commons/types/WithDocs";

export const ConjureArgumentWithParamType: core.serialization.ObjectSchema<
Expand All @@ -15,13 +14,13 @@ export const ConjureArgumentWithParamType: core.serialization.ObjectSchema<
> = core.serialization
.objectWithoutOptionalProperties({
paramType: core.serialization.property("param-type", ConjureParamType),
type: ConjureTypeReference,
type: core.serialization.string(),
})
.extend(WithDocs);

export declare namespace ConjureArgumentWithParamType {
interface Raw extends WithDocs.Raw {
"param-type": ConjureParamType.Raw;
type: ConjureTypeReference.Raw;
type: string;
}
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,23 @@ export class ConjureImporter extends APIDefinitionImporter<ConjureImporter.Args>
}
}

if (environmentOverrides != null) {
for (const [environment, environmentDeclaration] of Object.entries(
environmentOverrides.environments ?? {}
)) {
this.fernDefinitionBuilder.addEnvironment({
name: environment,
schema: environmentDeclaration
});
}
if (environmentOverrides["default-environment"] != null) {
this.fernDefinitionBuilder.setDefaultEnvironment(environmentOverrides["default-environment"]);
}
if (environmentOverrides["default-url"] != null) {
this.fernDefinitionBuilder.setDefaultUrl(environmentOverrides["default-url"]);
}
}

await visitAllConjureDefinitionFiles(absolutePathToConjureFolder, (absoluteFilepath, filepath, definition) => {
for (const [serviceName, _] of Object.entries(definition.services ?? {})) {
const unsuffixedServiceName = removeSuffix({ value: serviceName, suffix: "Service" });
Expand Down Expand Up @@ -134,6 +151,44 @@ export class ConjureImporter extends APIDefinitionImporter<ConjureImporter.Args>
endpoint["path-parameters"] = pathParameters;
}

for (const [arg, argDeclaration] of Object.entries(endpointDeclaration.args ?? {})) {
if (pathParameters[arg] != null) {
continue;
}
if (typeof argDeclaration === "string") {
endpoint.request = { body: { type: argDeclaration } };
} else {
switch (argDeclaration.paramType) {
case "body":
endpoint.request = { body: { type: argDeclaration.type } };
break;
case "query": {
if (endpoint.request == null) {
endpoint.request = { "query-parameters": { [arg]: argDeclaration.type } };
} else if (
typeof endpoint.request !== "string" &&
endpoint.request?.["query-parameters"] == null
) {
endpoint.request["query-parameters"] = { [arg]: argDeclaration.type };
} else if (
typeof endpoint.request !== "string" &&
endpoint.request?.["query-parameters"] != null
) {
endpoint.request["query-parameters"][arg] = argDeclaration.type;
}
}
}
}
}

if (
endpoint.request != null &&
typeof endpoint.request !== "string" &&
endpoint.request?.["query-parameters"] != null
) {
endpoint.request.name = `${endpointName}Request`;
}

this.fernDefinitionBuilder.addEndpoint(fernFilePath, {
name: endpointName,
schema: endpoint,
Expand Down
7 changes: 7 additions & 0 deletions packages/cli/cli/versions.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
- changelogEntry:
- summary: |
Numerous fixes to the Conjure API Importer such as reading in request bodies and query parameters.
type: fix
irVersion: 53
version: 0.45.0-rc3

- changelogEntry:
- summary: |
The CLI now generates endpoint examples for undiscriminated unions that are recusive.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46243,7 +46243,7 @@
"autogeneratedExamples": [
{
"example": {
"id": "1098fdcfaea938168857414480f1a1d770150714",
"id": "2fb134f8355d3f307bee50c4b06d8ccc5d10bd7d",
"url": "/primitive/datetime",
"name": null,
"endpointHeaders": [],
Expand All @@ -46262,7 +46262,7 @@
"raw": "2024-01-15T09:30:00Z"
}
},
"jsonExample": "SGVsbG8gd29ybGQh"
"jsonExample": "2024-01-15T09:30:00Z"
},
"response": {
"type": "ok",
Expand All @@ -46277,7 +46277,7 @@
"raw": "2024-01-15T09:30:00Z"
}
},
"jsonExample": "SGVsbG8gd29ybGQh"
"jsonExample": "2024-01-15T09:30:00Z"
}
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77462,7 +77462,7 @@
"autogeneratedExamples": [
{
"example": {
"id": "47927911911a8673e0447014d352b4aa1bdba9cf",
"id": "d5f74d6aca81f8fbde57d22610d6174dc01dc377",
"url": "/admin/store-test-submission-status-v2/d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32",
"name": null,
"endpointHeaders": [],
Expand Down Expand Up @@ -77681,7 +77681,7 @@
"raw": "2024-01-15T09:30:00Z"
}
},
"jsonExample": "SGVsbG8gd29ybGQh"
"jsonExample": "2024-01-15T09:30:00Z"
}
},
{
Expand Down Expand Up @@ -78062,7 +78062,7 @@
}
},
"jsonExample": {
"updateTime": "SGVsbG8gd29ybGQh",
"updateTime": "2024-01-15T09:30:00Z",
"updateInfo": {
"type": "running",
"value": "QUEUEING_SUBMISSION"
Expand Down Expand Up @@ -79170,7 +79170,7 @@
"autogeneratedExamples": [
{
"example": {
"id": "9315b9ffef1363fe8eb0438d1fea0a2440e6843b",
"id": "695f2ae954354fff386c246bc9d63d0191376534",
"url": "/admin/store-workspace-submission-status-v2/d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32",
"name": null,
"endpointHeaders": [],
Expand Down Expand Up @@ -79389,7 +79389,7 @@
"raw": "2024-01-15T09:30:00Z"
}
},
"jsonExample": "SGVsbG8gd29ybGQh"
"jsonExample": "2024-01-15T09:30:00Z"
}
},
{
Expand Down Expand Up @@ -79770,7 +79770,7 @@
}
},
"jsonExample": {
"updateTime": "SGVsbG8gd29ybGQh",
"updateTime": "2024-01-15T09:30:00Z",
"updateInfo": {
"type": "running",
"value": "QUEUEING_SUBMISSION"
Expand Down Expand Up @@ -98814,7 +98814,7 @@
"autogeneratedExamples": [
{
"example": {
"id": "77e20686361a9df7e8c08601d4d8c093fe99f419",
"id": "1812a5c575215caff117a68201869d94e742c42a",
"url": "/v2/playlist/1/create",
"name": null,
"endpointHeaders": [],
Expand Down Expand Up @@ -98855,7 +98855,7 @@
"raw": "2024-01-15T09:30:00Z"
}
},
"jsonExample": "SGVsbG8gd29ybGQh"
"jsonExample": "2024-01-15T09:30:00Z"
}
}
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function generatePrimitiveExample({
datetime: new Date(Examples.DATE_TIME),
raw: Examples.DATE_TIME
}),
jsonExample: Examples.BASE64
jsonExample: Examples.DATE_TIME
};
}
case "DOUBLE": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,35 @@ import {
ExampleHeader,
ExampleEndpointSuccessResponse,
ExampleRequestBody,
ExampleInlinedRequestBodyProperty
ExampleInlinedRequestBodyProperty,
ErrorDeclaration
} from "@fern-api/ir-sdk";
import { ExampleGenerationResult } from "./ExampleGenerationResult";
import { generateTypeReferenceExample } from "./generateTypeReferenceExample";
import { isOptional } from "./isTypeReferenceOptional";
import hash from "object-hash";

export declare namespace generateSuccessEndpointExample {
export declare namespace generateEndpointExample {
interface Args {
ir: Omit<IntermediateRepresentation, "sdkConfig" | "subpackages" | "rootPackage">;
service: HttpService;
endpoint: HttpEndpoint;
typeDeclarations: Record<TypeId, TypeDeclaration>;

skipOptionalRequestProperties: boolean;

generationResponse: GenerationResponseType;
}

type GenerationResponseType = SuccessResponseType | ErrorResponseType;

interface SuccessResponseType {
type: "success";
}

interface ErrorResponseType {
type: "error";
declaration: ErrorDeclaration;
}

interface ParameterGroup<T, K> {
Expand All @@ -37,13 +51,14 @@ export declare namespace generateSuccessEndpointExample {
}
}

export function generateSuccessEndpointExample({
export function generateEndpointExample({
ir,
endpoint,
service,
typeDeclarations,
skipOptionalRequestProperties
}: generateSuccessEndpointExample.Args): ExampleGenerationResult<ExampleEndpointCall> {
skipOptionalRequestProperties,
generationResponse
}: generateEndpointExample.Args): ExampleGenerationResult<ExampleEndpointCall> {
const result: Omit<ExampleEndpointCall, "id" | "url"> = {
name: undefined,
endpointHeaders: [],
Expand All @@ -57,7 +72,7 @@ export function generateSuccessEndpointExample({
docs: undefined
};

const pathParameterGroups: generateSuccessEndpointExample.ParameterGroup<PathParameter, ExamplePathParameter>[] = [
const pathParameterGroups: generateEndpointExample.ParameterGroup<PathParameter, ExamplePathParameter>[] = [
{
params: endpoint.pathParameters,
add: (example: ExamplePathParameter) => result.endpointPathParameters.push(example)
Expand Down Expand Up @@ -121,7 +136,7 @@ export function generateSuccessEndpointExample({
});
}

const headerGroup: generateSuccessEndpointExample.ParameterGroup<HttpHeader, ExampleHeader>[] = [
const headerGroup: generateEndpointExample.ParameterGroup<HttpHeader, ExampleHeader>[] = [
{
params: endpoint.headers,
add: (example: ExampleHeader) => result.endpointHeaders.push(example)
Expand Down Expand Up @@ -222,7 +237,7 @@ export function generateSuccessEndpointExample({
}
}

if (endpoint.response?.body != null) {
if (generationResponse.type === "success" && endpoint.response?.body != null) {
switch (endpoint.response.body.type) {
case "fileDownload":
return { type: "failure", message: "File download unsupported" };
Expand Down Expand Up @@ -250,6 +265,29 @@ export function generateSuccessEndpointExample({
default:
assertNever(endpoint.response.body);
}
} else if (generationResponse.type === "error") {
if (generationResponse.declaration.type == null) {
result.response = ExampleResponse.error({
body: undefined,
error: generationResponse.declaration.name
});
} else {
const generatedExample = generateTypeReferenceExample({
currentDepth: 0,
maxDepth: 10,
typeDeclarations,
typeReference: generationResponse.declaration.type,
skipOptionalProperties: skipOptionalRequestProperties
});
if (generatedExample.type === "failure") {
return generatedExample;
}
const { example } = generatedExample;
result.response = ExampleResponse.error({
body: example,
error: generationResponse.declaration.name
});
}
}

return {
Expand Down
Loading

0 comments on commit 3007204

Please sign in to comment.