persona-community-5/.pnpm-store/v3/files/ce/e80828cb8239dcb5b58fe2900f161cf2e8688bed51184f9e615b6844de9c50c0888e8728f223a7e49daa6297120b094f326ac596168ae7c79faf4a4d4b0a5b-exec
rdev-worker a1d0d1bf1c
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
build: /implement-feature community-ui --requirements 'Build the React commu...
2026-02-24 08:22:30 +00:00

298 lines
11 KiB
JavaScript
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
import fs from "node:fs";
import path from "node:path";
import { performance } from "node:perf_hooks";
import { createConfig, findConfig, loadConfig } from "@redocly/openapi-core";
import parser from "yargs-parser";
import openapiTS, { astToString, COMMENT_HEADER, c, error, formatTime, warn } from "../dist/index.mjs";
const HELP = `Usage
$ openapi-typescript [input] [options]
Options
--help Display this
--version Display the version
--redocly [path], -c Specify path to Redocly config (default: redocly.yaml)
--output, -o Specify output file (if not specified in redocly.yaml)
--enum Export true TS enums instead of unions
--enum-values Export enum values as arrays
--conditional-enums Only generate true TS enums when enum metadata is available (default: false)
--dedupe-enums Dedupe enum types when \`--enum=true\` is set
--check Check that the generated types are up-to-date. (default: false)
--export-type, -t Export top-level \`type\` instead of \`interface\`
--immutable Generate readonly types
--additional-properties Treat schema objects as if \`additionalProperties: true\` is set
--empty-objects-unknown Generate \`unknown\` instead of \`Record<string, never>\` for empty objects
--default-non-nullable Set to \`false\` to ignore default values when generating non-nullable types
--properties-required-by-default
Treat schema objects as if \`required\` is set to all properties by default
--array-length Generate tuples using array minItems / maxItems
--path-params-as-types Convert paths to template literal types
--alphabetize Sort object keys alphabetically
--exclude-deprecated Exclude deprecated types
--root-types (optional) Export schemas types at root level
--root-types-no-schema-prefix (optional)
Do not add "Schema" prefix to types at the root level (should only be used with --root-types)
--root-types-keep-casing Keep casing of root types (should only be used with --root-types)
--make-paths-enum Generate ApiPaths enum for all paths
--read-write-markers Generate $Read/$Write markers for readOnly/writeOnly properties
`;
const OUTPUT_FILE = "FILE";
const OUTPUT_STDOUT = "STDOUT";
const CWD = new URL(`file://${process.cwd()}/`);
const REDOC_CONFIG_KEY = "x-openapi-ts";
const timeStart = performance.now();
const [, , ...args] = process.argv;
if (args.includes("-ap")) {
errorAndExit(`The -ap alias has been deprecated. Use "--additional-properties" instead.`);
}
if (args.includes("--immutable-types")) {
errorAndExit(`The --immutable-types flag has been renamed to "--immutable".`);
}
if (args.includes("--support-array-length")) {
errorAndExit(`The --support-array-length flag has been renamed to "--array-length".`);
}
if (args.includes("-it")) {
errorAndExit(`The -it alias has been deprecated. Use "--immutable-types" instead.`);
}
if (args.includes("--redoc")) {
errorAndExit(`The --redoc config flag has been renamed to "--redocly" (or -c as shorthand).`);
}
if (args.includes("--root-types-no-schema-prefix") && !args.includes("--root-types")) {
// biome-ignore lint/suspicious/noConsole: this is a CLI
console.warn("--root-types-no-schema-prefix has no effect without --root-types flag");
}
if (args.includes("--root-types-keep-casing") && !args.includes("--root-types")) {
// biome-ignore lint/suspicious/noConsole: this is a CLI
console.warn("--root-types-keep-casing has no effect without --root-types flag");
}
const flags = parser(args, {
boolean: [
"additionalProperties",
"alphabetize",
"arrayLength",
"contentNever",
"defaultNonNullable",
"propertiesRequiredByDefault",
"emptyObjectsUnknown",
"enum",
"enumValues",
"conditionalEnums",
"dedupeEnums",
"check",
"excludeDeprecated",
"exportType",
"help",
"immutable",
"pathParamsAsTypes",
"rootTypes",
"rootTypesNoSchemaPrefix",
"rootTypesKeepCasing",
"makePathsEnum",
"generatePathParams",
"readWriteMarkers",
],
string: ["output", "redocly"],
alias: {
redocly: ["c"],
exportType: ["t"],
output: ["o"],
},
});
/**
* Normalize the output path into a file URL.
* @param {string} output - The output path to be transformed.
* @returns {URL} The transformed file URL.
*/
function normalizeOutput(output) {
if (path.isAbsolute(output)) {
return new URL(`file://${output}`);
}
return new URL(output, CWD);
}
/**
* Check if the generated types are up-to-date.
* @param {string} current - The current generated types.
* @param {URL} outputPath - The path to the output file.
*/
function checkStaleOutput(current, outputPath) {
if (flags.check) {
const previous = fs.readFileSync(outputPath, "utf8");
if (current === previous) {
process.exit(0);
} else {
error("Generated types are not up-to-date!");
process.exit(1);
}
}
}
/**
* @param {string | URL} schema
* @param {@type import('@redocly/openapi-core').Config} redocly
*/
async function generateSchema(schema, { redocly, silent = false }) {
return `${COMMENT_HEADER}${astToString(
await openapiTS(schema, {
additionalProperties: flags.additionalProperties,
alphabetize: flags.alphabetize,
arrayLength: flags.arrayLength,
contentNever: flags.contentNever,
propertiesRequiredByDefault: flags.propertiesRequiredByDefault,
defaultNonNullable: flags.defaultNonNullable,
emptyObjectsUnknown: flags.emptyObjectsUnknown,
enum: flags.enum,
enumValues: flags.enumValues,
conditionalEnums: flags.conditionalEnums,
dedupeEnums: flags.dedupeEnums,
excludeDeprecated: flags.excludeDeprecated,
exportType: flags.exportType,
immutable: flags.immutable,
pathParamsAsTypes: flags.pathParamsAsTypes,
rootTypes: flags.rootTypes,
rootTypesNoSchemaPrefix: flags.rootTypesNoSchemaPrefix,
rootTypesKeepCasing: flags.rootTypesKeepCasing,
makePathsEnum: flags.makePathsEnum,
generatePathParams: flags.generatePathParams,
readWriteMarkers: flags.readWriteMarkers,
redocly,
silent,
}),
)}`;
}
/** pretty-format error message but also throw */
function errorAndExit(message) {
error(message);
throw new Error(message);
}
function done(input, output, time) {
// final console output
// biome-ignore lint/suspicious/noConsole: this is a CLI
console.log(`🚀 ${c.green(`${input}${c.bold(output)}`)} ${c.dim(`[${formatTime(time)}]`)}`);
}
function findRedocConfigPath() {
if (!flags.redocly) {
return findConfig();
}
const explicitPath = path.resolve(flags.redocly);
if (!fs.existsSync(explicitPath)) {
return undefined;
}
const stat = fs.statSync(explicitPath);
return stat.isDirectory() ? findConfig(explicitPath) : explicitPath;
}
async function main() {
if ("help" in flags) {
// biome-ignore lint/suspicious/noConsole: this is a CLI
console.info(HELP);
process.exit(0);
}
const packageJSON = JSON.parse(fs.readFileSync(new URL("../package.json", import.meta.url), "utf8"));
if ("version" in flags) {
// biome-ignore lint/suspicious/noConsole: this is a CLI
console.info(`v${packageJSON.version}`);
process.exit(0);
}
const outputType = flags.output ? OUTPUT_FILE : OUTPUT_STDOUT; // FILE or STDOU
if (outputType !== OUTPUT_STDOUT) {
// biome-ignore lint/suspicious/noConsole: this is a CLI
console.info(`${c.bold(`openapi-typescript ${packageJSON.version}`)}`);
}
const input = flags._[0];
const redocConfigPath = findRedocConfigPath();
if (flags.redocly && !redocConfigPath) {
errorAndExit(`Redocly config not found at: ${flags.redocly}`);
}
const redocly = redocConfigPath
? await loadConfig({ configPath: redocConfigPath })
: await createConfig({}, { extends: ["minimal"] });
// handle Redoc APIs
const hasRedoclyApis = Object.keys(redocly?.apis ?? {}).length > 0;
if (hasRedoclyApis) {
if (input) {
warn("APIs are specified both in Redocly Config and CLI argument. Only using Redocly config.");
}
await Promise.all(
Object.entries(redocly.apis).map(async ([name, api]) => {
let configRoot = CWD;
if (redocly.configFile) {
// note: this will be absolute if --redoc is passed; otherwise, relative
configRoot = path.isAbsolute(redocly.configFile)
? new URL(`file://${redocly.configFile}`)
: new URL(redocly.configFile, `file://${process.cwd()}/`);
}
if (!api[REDOC_CONFIG_KEY]?.output) {
errorAndExit(
`API ${name} is missing an \`${REDOC_CONFIG_KEY}.output\` key. See https://openapi-ts.dev/cli/#multiple-schemas.`,
);
}
const result = await generateSchema(new URL(api.root, configRoot), { redocly });
const outFile = new URL(api[REDOC_CONFIG_KEY].output, configRoot);
checkStaleOutput(result, outFile);
fs.mkdirSync(new URL(".", outFile), { recursive: true });
fs.writeFileSync(outFile, result, "utf8");
done(name, api[REDOC_CONFIG_KEY].output, performance.now() - timeStart);
}),
);
}
// handle stdin
else if (!input) {
const result = await generateSchema(process.stdin, {
redocly,
silent: outputType === OUTPUT_STDOUT,
});
if (outputType === OUTPUT_STDOUT) {
// if stdout, (still) dont log anything to console!
process.stdout.write(result);
} else {
const outFile = normalizeOutput(flags.output);
checkStaleOutput(result, outFile);
fs.mkdirSync(new URL(".", outFile), { recursive: true });
fs.writeFileSync(outFile, result, "utf8");
done("stdin", flags.output, performance.now() - timeStart);
}
}
// handle single file
else {
// throw error on glob
if (input.includes("*")) {
errorAndExit(
"Globbing has been deprecated in favor of redocly.yamls `apis` keys. See https://openapi-ts.dev/cli/#multiple-schemas",
);
}
const result = await generateSchema(new URL(input, CWD), {
redocly,
silent: outputType === OUTPUT_STDOUT,
});
if (outputType === OUTPUT_STDOUT) {
// if stdout, (still) dont log anything to console!
process.stdout.write(result);
} else {
const outFile = normalizeOutput(flags.output);
checkStaleOutput(result, outFile);
fs.mkdirSync(new URL(".", outFile), { recursive: true });
fs.writeFileSync(outFile, result, "utf8");
done(input, flags.output, performance.now() - timeStart);
}
}
}
main();