Skip to content

Commit bcf0186

Browse files
authored
fix(cli): handle breaking errors at top level (#9982)
* handle breaking errors at top level * versions.yml and format
1 parent d001eb4 commit bcf0186

File tree

6 files changed

+81
-75
lines changed

6 files changed

+81
-75
lines changed

packages/cli/api-importers/openapi/openapi-ir-parser/src/openapi/v3/converters/ExampleEndpointFactory.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,6 @@ export class ExampleEndpointFactory {
4242
}
4343

4444
public buildEndpointExample(endpoint: EndpointWithExample): EndpointExample[] {
45-
this.logger.debug(`Building endpoint example for ${endpoint.method.toUpperCase()} ${endpoint.path}`);
46-
4745
// pares down the request/response to only multipart or json schemas.
4846
// other types are not supported in the builder.
4947
const requestSchemaIdResponse = getRequestSchema(endpoint.request);

packages/cli/api-importers/openapi/openapi-ir-parser/src/openapi/v3/generateIr.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ export function generateIr({
120120
if (pathItem == null) {
121121
return;
122122
}
123-
taskContext.logger.debug(`Converting path ${path}`);
124123
const convertedOperations = convertPathItem(path, pathItem, openApi, context);
125124
for (const operation of convertedOperations) {
126125
const operationAudiences = getAudiences({ operation });
@@ -205,7 +204,6 @@ export function generateIr({
205204
continue;
206205
}
207206
schemas[key] = schema;
208-
taskContext.logger.debug(`Converted schema ${key}`);
209207
}
210208

211209
const exampleTypeFactory = new ExampleTypeFactory(

packages/cli/api-importers/openapi/openapi-ir-parser/src/parse.ts

Lines changed: 56 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -71,56 +71,65 @@ export function parse({
7171
};
7272
let documentIndex = 0;
7373
for (const document of documents) {
74-
const source = document.source != null ? document.source : OpenApiIrSource.openapi({ file: "<memory>" });
75-
switch (document.type) {
76-
case "openapi": {
77-
const openapiIr = generateIrFromV3({
78-
taskContext: context,
79-
openApi: document.value,
80-
options: getParseOptions({ options: document.settings, overrides: options }),
81-
source,
82-
namespace: document.namespace
83-
});
84-
ir = merge(ir, openapiIr, getParseOptions({ options: document.settings, overrides: options }));
85-
documentIndex++;
86-
break;
87-
}
88-
case "asyncapi": {
89-
const parsedAsyncAPI = parseAsyncAPI({
90-
document: document.value,
91-
taskContext: context,
92-
options: getParseOptions({ options: document.settings, overrides: options }),
93-
source,
94-
asyncApiOptions: getParseAsyncOptions({ options: document.settings }),
95-
namespace: document.namespace
96-
});
97-
if (parsedAsyncAPI.servers != null) {
98-
ir.websocketServers = [
99-
...ir.websocketServers,
100-
...parsedAsyncAPI.servers.map((server) => ({
101-
...server,
102-
audiences: undefined,
103-
description: undefined
104-
}))
105-
];
106-
}
107-
if (parsedAsyncAPI.channels != null) {
108-
ir.channels = {
109-
...ir.channels,
110-
...parsedAsyncAPI.channels
111-
};
74+
try {
75+
const source = document.source != null ? document.source : OpenApiIrSource.openapi({ file: "<memory>" });
76+
switch (document.type) {
77+
case "openapi": {
78+
const openapiIr = generateIrFromV3({
79+
taskContext: context,
80+
openApi: document.value,
81+
options: getParseOptions({ options: document.settings, overrides: options }),
82+
source,
83+
namespace: document.namespace
84+
});
85+
ir = merge(ir, openapiIr, getParseOptions({ options: document.settings, overrides: options }));
86+
documentIndex++;
87+
break;
11288
}
113-
if (parsedAsyncAPI.groupedSchemas != null) {
114-
ir.groupedSchemas = mergeSchemaMaps(ir.groupedSchemas, parsedAsyncAPI.groupedSchemas);
89+
case "asyncapi": {
90+
const parsedAsyncAPI = parseAsyncAPI({
91+
document: document.value,
92+
taskContext: context,
93+
options: getParseOptions({ options: document.settings, overrides: options }),
94+
source,
95+
asyncApiOptions: getParseAsyncOptions({ options: document.settings }),
96+
namespace: document.namespace
97+
});
98+
if (parsedAsyncAPI.servers != null) {
99+
ir.websocketServers = [
100+
...ir.websocketServers,
101+
...parsedAsyncAPI.servers.map((server) => ({
102+
...server,
103+
audiences: undefined,
104+
description: undefined
105+
}))
106+
];
107+
}
108+
if (parsedAsyncAPI.channels != null) {
109+
ir.channels = {
110+
...ir.channels,
111+
...parsedAsyncAPI.channels
112+
};
113+
}
114+
if (parsedAsyncAPI.groupedSchemas != null) {
115+
ir.groupedSchemas = mergeSchemaMaps(ir.groupedSchemas, parsedAsyncAPI.groupedSchemas);
116+
}
117+
if (parsedAsyncAPI.basePath != null) {
118+
ir.basePath = parsedAsyncAPI.basePath;
119+
}
120+
documentIndex++;
121+
break;
115122
}
116-
if (parsedAsyncAPI.basePath != null) {
117-
ir.basePath = parsedAsyncAPI.basePath;
118-
}
119-
documentIndex++;
120-
break;
123+
default:
124+
assertNever(document);
125+
}
126+
} catch (error) {
127+
context.logger.error(
128+
`Skipping parsing document ${document.type === "openapi" ? document.value.info?.title : document.source?.file}`
129+
);
130+
if (error instanceof Error) {
131+
context.logger.debug(error.message, error.stack ? "\n" + error.stack : "");
121132
}
122-
default:
123-
assertNever(document);
124133
}
125134
}
126135
return ir;

packages/cli/cli/versions.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
# yaml-language-server: $schema=../../../fern-versions-yml.schema.json
2+
- changelogEntry:
3+
- summary: |
4+
If API publishing fails, alert and continue to next in fern generate --docs.
5+
type: fix
6+
irVersion: 61
7+
createdAt: "2025-10-20"
8+
version: 0.93.2
9+
210
- changelogEntry:
311
- summary: |
412
Fix errors related to:

packages/cli/generation/remote-generation/remote-workspace-runner/src/publishDocs.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ export async function publishDocs({
202202
});
203203

204204
if (response.ok) {
205-
context.logger.debug(`Registered API Definition ${response.body.apiDefinitionId}`);
205+
context.logger.debug(`Registered API Definition ${apiName}: ${response.body.apiDefinitionId}`);
206206

207207
if (response.body.dynamicIRs && dynamicIRsByLanguage) {
208208
if (skipUpload) {

packages/cli/workspace/lazy-fern-workspace/src/utils/parseOpenAPI.ts

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,28 +14,21 @@ export async function parseOpenAPI({
1414
absolutePathToOpenAPIOverrides?: AbsoluteFilePath;
1515
parsed?: OpenAPI.Document;
1616
}): Promise<OpenAPI.Document> {
17-
try {
18-
const result =
19-
parsed != null
20-
? await bundle({
21-
...DEFAULT_OPENAPI_BUNDLE_OPTIONS,
22-
doc: {
23-
source: new Source(absolutePathToOpenAPI, "<openapi>"),
24-
parsed
25-
},
26-
externalRefResolver: new OpenAPIRefResolver(absolutePathToOpenAPIOverrides)
27-
})
28-
: await bundle({
29-
...DEFAULT_OPENAPI_BUNDLE_OPTIONS,
30-
ref: absolutePathToOpenAPI,
31-
externalRefResolver: new OpenAPIRefResolver(absolutePathToOpenAPIOverrides)
32-
});
17+
const result =
18+
parsed != null
19+
? await bundle({
20+
...DEFAULT_OPENAPI_BUNDLE_OPTIONS,
21+
doc: {
22+
source: new Source(absolutePathToOpenAPI, "<openapi>"),
23+
parsed
24+
},
25+
externalRefResolver: new OpenAPIRefResolver(absolutePathToOpenAPIOverrides)
26+
})
27+
: await bundle({
28+
...DEFAULT_OPENAPI_BUNDLE_OPTIONS,
29+
ref: absolutePathToOpenAPI,
30+
externalRefResolver: new OpenAPIRefResolver(absolutePathToOpenAPIOverrides)
31+
});
3332

34-
return result.bundle.parsed;
35-
} catch (error) {
36-
if (error instanceof Error) {
37-
throw new Error(`Failed to parse OpenAPI document at ${absolutePathToOpenAPI}: ${error.message}`);
38-
}
39-
throw new Error(`Failed to parse OpenAPI document at ${absolutePathToOpenAPI}: ${String(error)}`);
40-
}
33+
return result.bundle.parsed;
4134
}

0 commit comments

Comments
 (0)