diff --git a/src/rest/scripts/utils/get-body-params.js b/src/rest/scripts/utils/get-body-params.js index 389f9d914d..2d76636e4c 100644 --- a/src/rest/scripts/utils/get-body-params.js +++ b/src/rest/scripts/utils/get-body-params.js @@ -101,7 +101,7 @@ export async function getBodyParams(schema, topLevel = false) { } keyParam.childParamsGroups.push(...(await getBodyParams(param.additionalProperties, false))) childParamsGroups.push(keyParam) - } else if (paramType && paramType.includes('array')) { + } else if (paramType && paramType.includes('array') && param.items) { if (param.items && param.items.oneOf) { if (param.items.oneOf.every((object) => object.type === 'object')) { paramType.splice(paramType.indexOf('array'), 1, `array of objects`) diff --git a/src/rest/scripts/utils/operation.js b/src/rest/scripts/utils/operation.js index ad655d6fcd..1c05d59f67 100644 --- a/src/rest/scripts/utils/operation.js +++ b/src/rest/scripts/utils/operation.js @@ -67,18 +67,28 @@ export default class Operation { } async renderDescription() { - this.descriptionHTML = await renderContent(this.#operation.description) - return this + try { + this.descriptionHTML = await renderContent(this.#operation.description) + return this + } catch (error) { + console.error(error) + throw new Error(`Error rendering description for ${this.verb} ${this.requestPath}`) + } } async codeExamples() { this.codeExamples = await getCodeSamples(this.#operation) - return await Promise.all( - this.codeExamples.map(async (codeExample) => { - codeExample.response.description = await renderContent(codeExample.response.description) - return codeExample - }), - ) + try { + return await Promise.all( + this.codeExamples.map(async (codeExample) => { + codeExample.response.description = await renderContent(codeExample.response.description) + return codeExample + }), + ) + } catch (error) { + console.error(error) + throw new Error(`Error generating code examples for ${this.verb} ${this.requestPath}`) + } } async renderStatusCodes() { @@ -86,38 +96,49 @@ export default class Operation { const responseKeys = Object.keys(responses) if (responseKeys.length === 0) return [] - this.statusCodes = await Promise.all( - responseKeys.map(async (responseCode) => { - const response = responses[responseCode] - const httpStatusCode = responseCode - const httpStatusMessage = httpStatusCodes.getMessage(Number(responseCode), 'HTTP/2') - // The OpenAPI should be updated to provide better descriptions, but - // until then, we can catch some known generic descriptions and replace - // them with the default http status message. - const responseDescription = - response.description.toLowerCase() === 'response' - ? await renderContent(httpStatusMessage) - : await renderContent(response.description) + try { + this.statusCodes = await Promise.all( + responseKeys.map(async (responseCode) => { + const response = responses[responseCode] + const httpStatusCode = responseCode + const httpStatusMessage = httpStatusCodes.getMessage(Number(responseCode), 'HTTP/2') + // The OpenAPI should be updated to provide better descriptions, but + // until then, we can catch some known generic descriptions and replace + // them with the default http status message. + const responseDescription = + response.description.toLowerCase() === 'response' + ? await renderContent(httpStatusMessage) + : await renderContent(response.description) - return { - httpStatusCode, - description: responseDescription, - } - }), - ) + return { + httpStatusCode, + description: responseDescription, + } + }), + ) + } catch (error) { + console.error(error) + throw new Error(`Error rendering status codes for ${this.verb} ${this.requestPath}`) + } } async renderParameterDescriptions() { - return Promise.all( - this.parameters.map(async (param) => { - param.description = await renderContent(param.description) - return param - }), - ) + try { + return Promise.all( + this.parameters.map(async (param) => { + param.description = await renderContent(param.description) + return param + }), + ) + } catch (error) { + console.error(error) + throw new Error(`Error rendering parameter descriptions for ${this.verb} ${this.requestPath}`) + } } async renderBodyParameterDescriptions() { if (!this.#operation.requestBody) return [] + // There is currently only one operation with more than one content type // and the request body parameter types are the same for both. // Operation Id: markdown/render-raw @@ -129,26 +150,40 @@ export default class Operation { } // Merges any instances of allOf in the schema using a deep merge const mergedAllofSchema = mergeAllOf(schema) - this.bodyParameters = isPlainObject(schema) ? await getBodyParams(mergedAllofSchema, true) : [] + try { + this.bodyParameters = isPlainObject(schema) + ? await getBodyParams(mergedAllofSchema, true) + : [] + } catch (error) { + console.error(error) + throw new Error( + `Error rendering body parameter descriptions for ${this.verb} ${this.requestPath}`, + ) + } } async renderPreviewNotes() { const previews = get(this.#operation, 'x-github.previews', []) - this.previews = await Promise.all( - previews.map(async (preview) => { - const note = preview.note - // remove extra leading and trailing newlines - .replace(/```\n\n\n/gm, '```\n') - .replace(/```\n\n/gm, '```\n') - .replace(/\n\n\n```/gm, '\n```') - .replace(/\n\n```/gm, '\n```') + try { + this.previews = await Promise.all( + previews.map(async (preview) => { + const note = preview.note + // remove extra leading and trailing newlines + .replace(/```\n\n\n/gm, '```\n') + .replace(/```\n\n/gm, '```\n') + .replace(/\n\n\n```/gm, '\n```') + .replace(/\n\n```/gm, '\n```') - // convert single-backtick code snippets to fully fenced triple-backtick blocks - // example: This is the description.\n\n`application/vnd.github.machine-man-preview+json` - .replace(/\n`application/, '\n```\napplication') - .replace(/json`$/, 'json\n```') - return await renderContent(note) - }), - ) + // convert single-backtick code snippets to fully fenced triple-backtick blocks + // example: This is the description.\n\n`application/vnd.github.machine-man-preview+json` + .replace(/\n`application/, '\n```\napplication') + .replace(/json`$/, 'json\n```') + return await renderContent(note) + }), + ) + } catch (error) { + console.error(error) + throw new Error(`Error rendering preview notes for ${this.verb} ${this.requestPath}`) + } } } diff --git a/src/rest/scripts/utils/sync.js b/src/rest/scripts/utils/sync.js index 0d2bdac458..d7e878c11b 100644 --- a/src/rest/scripts/utils/sync.js +++ b/src/rest/scripts/utils/sync.js @@ -23,12 +23,13 @@ export async function syncRestData(sourceDirectory, restSchemas) { const operations = [] try { + console.log('Proccessing operations for version ', schemaName) const newOperations = await createOperations(schema) operations.push(...newOperations) await processOperations(operations) } catch (error) { throw new Error( - "šŸ› Whoops! It looks like the script wasn't able to parse the dereferenced schema. A recent change may not yet be supported by the decorator. Please reach out in the #docs-engineering slack channel for help.", + `${error}\n\nšŸ› Whoops! It looks like the script wasn't able to parse the dereferenced schema. A recent change may not yet be supported by the decorator. Please reach out in the #docs-engineering slack channel for help.`, ) } const formattedOperations = await formatRestData(operations)