Files
cfw-autumn/packages/openapi/v2.3/openapi2.3.ts
2026-05-26 12:39:37 +01:00

174 lines
5.3 KiB
TypeScript

import { writeFileSync } from "node:fs";
import { SuccessResponseSchema } from "@api/common/commonResponses.js";
import {
ApiBalanceV1Schema,
ApiCustomerV5Schema,
ApiEventsListV2_3ParamsSchema,
ApiPlanV1Schema,
AttachParamsV1Schema,
AttachPreviewResponseSchema,
BaseApiCustomerSchema,
BillingResponseSchema,
CheckParamsSchema,
CheckResponseV3Schema,
CreateBalanceParamsV0Schema,
CreateCustomerParamsV1Schema,
CustomerDataSchema,
CustomerExpandEnum,
CustomerIdSchema,
GetCustomerParamsV1Schema,
LATEST_VERSION,
PreviewUpdateSubscriptionResponseSchema,
SetupPaymentParamsV1Schema,
SetupPaymentResponseV1Schema,
TrackParamsSchema,
TrackResponseV3Schema,
TrackTokensParamsSchema,
UpdateBalanceParamsV0Schema,
UpdateSubscriptionV1ParamsSchema,
} from "@autumn/shared";
import { OpenAPIGenerator } from "@orpc/openapi";
import { ZodToJsonSchemaConverter } from "@orpc/zod/zod4";
import yaml from "yaml";
import { transformNode } from "../utils/mintlifyTransform/index.js";
import {
applyPaginationExtensions,
applySpeakeasySettings,
injectGlobalHeaderParameters,
removeInternalFields,
} from "../utils/openapiTransform/index.js";
import { registerInternalSchemas } from "../utils/registerInternalSchemas.js";
import { v2_3ContractRouter } from "./contracts/index.js";
import { injectWebhooks } from "./webhooks/injectWebhooks.js";
const generator = new OpenAPIGenerator({
schemaConverters: [new ZodToJsonSchemaConverter()],
});
const OPENAPI_DOC_VERSION = LATEST_VERSION;
/**
* Generates the OpenAPI document with all transformations applied.
* Internal helper used by both writeOpenApi_2_3_0 and writeOpenApi_2_3_0_Stripped.
*/
async function generateOpenApiDocument(): Promise<Record<string, unknown>> {
// Register internal schemas before generation so they get x-internal: true
// in the OpenAPI output, which removeInternalFields() will then strip
registerInternalSchemas(BaseApiCustomerSchema);
registerInternalSchemas(CreateCustomerParamsV1Schema);
registerInternalSchemas(GetCustomerParamsV1Schema);
registerInternalSchemas(AttachParamsV1Schema);
registerInternalSchemas(UpdateSubscriptionV1ParamsSchema);
registerInternalSchemas(SetupPaymentParamsV1Schema);
registerInternalSchemas(CreateBalanceParamsV0Schema);
registerInternalSchemas(UpdateBalanceParamsV0Schema);
registerInternalSchemas(CheckParamsSchema);
registerInternalSchemas(TrackParamsSchema);
registerInternalSchemas(TrackTokensParamsSchema);
registerInternalSchemas(BillingResponseSchema);
registerInternalSchemas(AttachPreviewResponseSchema);
registerInternalSchemas(PreviewUpdateSubscriptionResponseSchema);
registerInternalSchemas(SetupPaymentResponseV1Schema);
registerInternalSchemas(SuccessResponseSchema);
registerInternalSchemas(ApiCustomerV5Schema);
registerInternalSchemas(ApiBalanceV1Schema);
registerInternalSchemas(ApiPlanV1Schema);
registerInternalSchemas(CheckResponseV3Schema);
registerInternalSchemas(TrackResponseV3Schema);
registerInternalSchemas(CustomerDataSchema);
registerInternalSchemas(ApiEventsListV2_3ParamsSchema);
const openApiDocument = (await generator.generate(v2_3ContractRouter, {
info: {
title: "Autumn API",
version: OPENAPI_DOC_VERSION,
},
commonSchemas: {
CustomerId: {
schema: CustomerIdSchema,
strategy: "input",
},
CustomerData: {
schema: CustomerDataSchema,
strategy: "input",
},
CustomerExpand: {
schema: CustomerExpandEnum,
strategy: "input",
},
Customer: {
schema: ApiCustomerV5Schema,
strategy: "output",
},
Plan: {
schema: ApiPlanV1Schema,
strategy: "output",
},
Balance: {
schema: ApiBalanceV1Schema,
strategy: "output",
},
},
servers: [
{
// url: "http://localhost:8080",
url: "https://api.useautumn.com",
description: "Production server",
},
],
})) as Record<string, unknown>;
// Mintlify only supports OpenAPI 3.0 and 3.1.0; @orpc/openapi defaults to 3.1.1.
openApiDocument.openapi = "3.1.0";
applySpeakeasySettings({
openApiDocument,
version: OPENAPI_DOC_VERSION,
});
injectGlobalHeaderParameters({
openApiDocument,
version: OPENAPI_DOC_VERSION,
});
removeInternalFields({ openApiDocument });
applyPaginationExtensions({ openApiDocument });
injectWebhooks({ openApiDocument });
return openApiDocument;
}
/**
* Generates and writes the full OpenAPI spec (with TypeScript JSDoc examples).
* Used for the TypeScript SDK generation.
*/
export const writeOpenApi_2_3_0 = async ({
outputFilePath,
}: {
outputFilePath: string;
}) => {
const openApiDocument = await generateOpenApiDocument();
const yamlContent = yaml.stringify(openApiDocument);
writeFileSync(outputFilePath, yamlContent, "utf8");
};
/**
* Generates and writes the stripped OpenAPI spec (JSDoc examples removed).
* Used for non-TypeScript SDK generation (Python, etc.) where TS examples
* in descriptions would be confusing.
*/
export const writeOpenApi_2_3_0_Stripped = async ({
outputFilePath,
}: {
outputFilePath: string;
}) => {
const openApiDocument = await generateOpenApiDocument();
// Strip JSDoc tags (@example, @param, etc.) from descriptions
const schemas = (openApiDocument.components as Record<string, unknown>)
?.schemas as Record<string, unknown> | undefined;
transformNode(openApiDocument, schemas);
const yamlContent = yaml.stringify(openApiDocument);
writeFileSync(outputFilePath, yamlContent, "utf8");
};