persona-community-5/.pnpm-store/v3/files/2a/b085f82fa6be5c29eecfc66cdb4d3edb5b403d868c8ec9608dcf3c7f430546a7b3d63df447066c8745d672a0ff57219fee5f2bea95dc7b287f6f8c8e23ac8d
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

494 lines
20 KiB
Plaintext
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.

import { parseRef } from '@redocly/openapi-core/lib/ref-utils.js';
import ts from 'typescript';
import { NEVER, UNKNOWN, oapiRef, tsLiteral, tsEnum, tsUnion, NULL, tsArrayLiteralExpression, tsIntersection, tsIsPrimitive, tsRecord, STRING, tsNullable, UNDEFINED, NUMBER, BOOLEAN, QUESTION_TOKEN, tsModifiers, tsPropertyIndex, addJSDocComment, tsWithRequired, tsOmit } from '../lib/ts.mjs';
import { createRef, createDiscriminatorProperty, getEntries } from '../lib/utils.mjs';
function transformSchemaObject(schemaObject, options, fromAdditionalProperties = false) {
const type = transformSchemaObjectWithComposition(schemaObject, options, fromAdditionalProperties);
if (typeof options.ctx.postTransform === "function") {
const postTransformResult = options.ctx.postTransform(type, options);
if (postTransformResult) {
return postTransformResult;
}
}
return type;
}
function transformSchemaObjectWithComposition(schemaObject, options, fromAdditionalProperties = false) {
if (!schemaObject) {
return NEVER;
}
if (schemaObject === true) {
return UNKNOWN;
}
if (Array.isArray(schemaObject) || typeof schemaObject !== "object") {
throw new Error(
`Expected SchemaObject, received ${Array.isArray(schemaObject) ? "Array" : typeof schemaObject} at ${options.path}`
);
}
if ("$ref" in schemaObject) {
return oapiRef(schemaObject.$ref);
}
if (schemaObject.const !== null && schemaObject.const !== void 0) {
return tsLiteral(schemaObject.const);
}
if (Array.isArray(schemaObject.enum) && (!("type" in schemaObject) || schemaObject.type !== "object") && !("properties" in schemaObject) && !("additionalProperties" in schemaObject)) {
if (shouldTransformToTsEnum(options, schemaObject)) {
let enumName = parseRef(options.path ?? "").pointer.join("/");
enumName = enumName.replace("components/schemas", "");
const metadata = schemaObject.enum.map((_, i) => ({
name: schemaObject["x-enum-varnames"]?.[i] ?? schemaObject["x-enumNames"]?.[i],
description: schemaObject["x-enum-descriptions"]?.[i] ?? schemaObject["x-enumDescriptions"]?.[i]
}));
let hasNull = false;
const validSchemaEnums = schemaObject.enum.filter((enumValue) => {
if (enumValue === null) {
hasNull = true;
return false;
}
return true;
});
const enumType2 = tsEnum(enumName, validSchemaEnums, metadata, {
shouldCache: options.ctx.dedupeEnums,
export: true
// readonly: TS enum do not support the readonly modifier
});
if (!options.ctx.injectFooter.includes(enumType2)) {
options.ctx.injectFooter.push(enumType2);
}
const ref = ts.factory.createTypeReferenceNode(enumType2.name);
return hasNull ? tsUnion([ref, NULL]) : ref;
}
const enumType = schemaObject.enum.map(tsLiteral);
if (Array.isArray(schemaObject.type) && schemaObject.type.includes("null") || schemaObject.nullable) {
enumType.push(NULL);
}
const unionType = tsUnion(enumType);
if (options.ctx.enumValues && schemaObject.enum.every((v) => typeof v === "string" || typeof v === "number")) {
const parsed = parseRef(options.path ?? "");
let enumValuesVariableName = parsed.pointer.join("/");
enumValuesVariableName = enumValuesVariableName.replace("components/schemas", "");
enumValuesVariableName = `${enumValuesVariableName}Values`;
const cleanedPointer = [];
const extractProperties = [];
for (let i = 0; i < parsed.pointer.length; i++) {
const segment = parsed.pointer[i];
if ((segment === "anyOf" || segment === "oneOf") && i < parsed.pointer.length - 1) {
const next = parsed.pointer[i + 1];
if (/^\d+$/.test(next)) {
i++;
const remainingSegments = parsed.pointer.slice(i + 1);
for (const seg of remainingSegments) {
if (seg !== "anyOf" && seg !== "oneOf" && !/^\d+$/.test(seg)) {
extractProperties.push(seg);
}
}
continue;
}
}
cleanedPointer.push(segment);
}
const cleanedRefPath = createRef(cleanedPointer);
const enumValuesArray = tsArrayLiteralExpression(
enumValuesVariableName,
// If fromAdditionalProperties is true we are dealing with a record type and we should append [string] to the generated type
fromAdditionalProperties ? ts.factory.createIndexedAccessTypeNode(
oapiRef(cleanedRefPath, void 0, { deep: true, extractProperties }),
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("string"))
) : oapiRef(cleanedRefPath, void 0, { deep: true, extractProperties }),
schemaObject.enum,
{
export: true,
readonly: true,
injectFooter: options.ctx.injectFooter
}
);
options.ctx.injectFooter.push(enumValuesArray);
}
return unionType;
}
function collectUnionCompositions(items, unionKey) {
const output = [];
for (const [index, item] of items.entries()) {
output.push(
transformSchemaObject(item, {
...options,
// include index in path so generated names from nested enums/enumValues are unique
path: createRef([options.path, unionKey, String(index)])
})
);
}
return output;
}
function collectAllOfCompositions(items, required) {
const output = [];
for (const item of items) {
let itemType;
if ("$ref" in item) {
itemType = transformSchemaObject(item, options);
const resolved = options.ctx.resolve(item.$ref);
if (resolved && typeof resolved === "object" && "properties" in resolved && // we have already handled this item (discriminator property was already added as required)
!options.ctx.discriminators.refsHandled.includes(item.$ref)) {
const validRequired = (required ?? []).filter((key) => !!resolved.properties?.[key]);
if (validRequired.length) {
itemType = tsWithRequired(itemType, validRequired, options.ctx.injectFooter);
}
}
} else {
const itemRequired = [...required ?? []];
if (typeof item === "object" && Array.isArray(item.required)) {
itemRequired.push(...item.required);
}
itemType = transformSchemaObject({ ...item, required: itemRequired }, options);
}
const discriminator = "$ref" in item && options.ctx.discriminators.objects[item.$ref] || item.discriminator;
if (discriminator) {
output.push(tsOmit(itemType, [discriminator.propertyName]));
} else {
output.push(itemType);
}
}
return output;
}
let finalType;
const coreObjectType = transformSchemaObjectCore(schemaObject, options);
const allOfType = collectAllOfCompositions(schemaObject.allOf ?? [], schemaObject.required);
if (coreObjectType || allOfType.length) {
const allOf = allOfType.length ? tsIntersection(allOfType) : void 0;
finalType = tsIntersection([...coreObjectType ? [coreObjectType] : [], ...allOf ? [allOf] : []]);
}
const anyOfType = collectUnionCompositions(schemaObject.anyOf ?? [], "anyOf");
if (anyOfType.length) {
finalType = tsUnion([...finalType ? [finalType] : [], ...anyOfType]);
}
const oneOfType = collectUnionCompositions(
schemaObject.oneOf || "type" in schemaObject && schemaObject.type === "object" && schemaObject.enum || [],
"oneOf"
);
if (oneOfType.length) {
if (oneOfType.every(tsIsPrimitive)) {
finalType = tsUnion([...finalType ? [finalType] : [], ...oneOfType]);
} else {
finalType = tsIntersection([...finalType ? [finalType] : [], tsUnion(oneOfType)]);
}
}
if (!finalType) {
if ("type" in schemaObject) {
finalType = tsRecord(STRING, options.ctx.emptyObjectsUnknown ? UNKNOWN : NEVER);
} else {
finalType = UNKNOWN;
}
}
if (finalType !== UNKNOWN && schemaObject.nullable) {
finalType = tsNullable([finalType]);
}
return finalType;
}
function shouldTransformToTsEnum(options, schemaObject) {
if (!options.ctx.enum || !schemaObject.enum) {
return false;
}
if (!schemaObject.enum.every((v) => ["string", "number", null].includes(typeof v))) {
return false;
}
if (options.ctx.conditionalEnums) {
const hasEnumMetadata = Array.isArray(schemaObject["x-enum-varnames"]) || Array.isArray(schemaObject["x-enumNames"]) || Array.isArray(schemaObject["x-enum-descriptions"]) || Array.isArray(schemaObject["x-enumDescriptions"]);
if (!hasEnumMetadata) {
return false;
}
}
return true;
}
function transformSchemaObjectCore(schemaObject, options) {
if ("type" in schemaObject && schemaObject.type) {
if (typeof options.ctx.transform === "function") {
const result = options.ctx.transform(schemaObject, options);
if (result && typeof result === "object") {
if ("schema" in result) {
if (result.questionToken) {
return ts.factory.createUnionTypeNode([result.schema, UNDEFINED]);
} else {
return result.schema;
}
} else {
return result;
}
}
}
if (schemaObject.type === "null") {
return NULL;
}
if (schemaObject.type === "string") {
return STRING;
}
if (schemaObject.type === "number" || schemaObject.type === "integer") {
return NUMBER;
}
if (schemaObject.type === "boolean") {
return BOOLEAN;
}
if (schemaObject.type === "array") {
let itemType = UNKNOWN;
if (schemaObject.prefixItems || Array.isArray(schemaObject.items)) {
const prefixItems = schemaObject.prefixItems ?? schemaObject.items;
itemType = ts.factory.createTupleTypeNode(prefixItems.map((item) => transformSchemaObject(item, options)));
} else if (schemaObject.items) {
if (hasKey(schemaObject.items, "type") && schemaObject.items.type === "array") {
itemType = ts.factory.createArrayTypeNode(transformSchemaObject(schemaObject.items, options));
} else {
itemType = transformSchemaObject(schemaObject.items, options);
}
}
const min = typeof schemaObject.minItems === "number" && schemaObject.minItems >= 0 ? schemaObject.minItems : 0;
const max = typeof schemaObject.maxItems === "number" && schemaObject.maxItems >= 0 && min <= schemaObject.maxItems ? schemaObject.maxItems : void 0;
const estimateCodeSize = typeof max !== "number" ? min : (max * (max + 1) - min * (min - 1)) / 2;
if (options.ctx.arrayLength && (min !== 0 || max !== void 0) && estimateCodeSize < 30) {
if (min === max) {
const elements = [];
for (let i = 0; i < min; i++) {
elements.push(itemType);
}
return tsUnion([ts.factory.createTupleTypeNode(elements)]);
} else if (schemaObject.maxItems > 0) {
const members = [];
for (let i = 0; i <= (max ?? 0) - min; i++) {
const elements = [];
for (let j = min; j < i + min; j++) {
elements.push(itemType);
}
members.push(ts.factory.createTupleTypeNode(elements));
}
return tsUnion(members);
} else {
const elements = [];
for (let i = 0; i < min; i++) {
elements.push(itemType);
}
elements.push(ts.factory.createRestTypeNode(ts.factory.createArrayTypeNode(itemType)));
return ts.factory.createTupleTypeNode(elements);
}
}
const finalType = ts.isTupleTypeNode(itemType) || ts.isArrayTypeNode(itemType) ? itemType : ts.factory.createArrayTypeNode(itemType);
return options.ctx.immutable ? ts.factory.createTypeOperatorNode(ts.SyntaxKind.ReadonlyKeyword, finalType) : finalType;
}
if (Array.isArray(schemaObject.type) && !Array.isArray(schemaObject)) {
const uniqueTypes = [];
if (Array.isArray(schemaObject.oneOf)) {
for (const t of schemaObject.type) {
if ((t === "boolean" || t === "string" || t === "number" || t === "integer" || t === "null") && schemaObject.oneOf.find((o) => typeof o === "object" && "type" in o && o.type === t)) {
continue;
}
uniqueTypes.push(
t === "null" || t === null ? NULL : transformSchemaObject(
{ ...schemaObject, type: t, oneOf: void 0 },
// dont stack oneOf transforms
options
)
);
}
} else {
for (const t of schemaObject.type) {
if (t === "null" || t === null) {
uniqueTypes.push(NULL);
} else {
uniqueTypes.push(transformSchemaObject({ ...schemaObject, type: t }, options));
}
}
}
return tsUnion(uniqueTypes);
}
}
const coreObjectType = [];
for (const k of ["allOf", "anyOf"]) {
if (!schemaObject[k]) {
continue;
}
const discriminator = !schemaObject.discriminator && !options.ctx.discriminators.refsHandled.includes(options.path ?? "") && options.ctx.discriminators.objects[options.path ?? ""];
if (discriminator) {
coreObjectType.unshift(
createDiscriminatorProperty(discriminator, {
path: options.path ?? "",
readonly: options.ctx.immutable
})
);
break;
}
}
if ("properties" in schemaObject && schemaObject.properties && Object.keys(schemaObject.properties).length || "additionalProperties" in schemaObject && schemaObject.additionalProperties || "patternProperties" in schemaObject && schemaObject.patternProperties || "$defs" in schemaObject && schemaObject.$defs) {
if (Object.keys(schemaObject.properties ?? {}).length) {
for (const [k, v] of getEntries(schemaObject.properties ?? {}, options.ctx)) {
if (typeof v !== "object" && typeof v !== "boolean" || Array.isArray(v)) {
throw new Error(
`${options.path}: invalid property ${k}. Expected Schema Object or boolean, got ${Array.isArray(v) ? "Array" : typeof v}`
);
}
const { $ref, readOnly, writeOnly, hasDefault } = typeof v === "object" ? {
$ref: "$ref" in v && v.$ref,
readOnly: "readOnly" in v && v.readOnly,
writeOnly: "writeOnly" in v && v.writeOnly,
hasDefault: "default" in v && v.default !== void 0
} : {};
if (options.ctx.excludeDeprecated) {
const resolved = $ref ? options.ctx.resolve($ref) : v;
if (resolved?.deprecated) {
continue;
}
}
let optional = schemaObject.required?.includes(k) || schemaObject.required === void 0 && options.ctx.propertiesRequiredByDefault || hasDefault && options.ctx.defaultNonNullable && !options.path?.includes("parameters") && !options.path?.includes("requestBody") && !options.path?.includes("requestBodies") ? void 0 : QUESTION_TOKEN;
let type = $ref ? oapiRef($ref) : transformSchemaObject(v, {
...options,
path: createRef([options.path, k])
});
if (typeof options.ctx.transform === "function") {
const result = options.ctx.transform(v, options);
if (result && typeof result === "object") {
if ("schema" in result) {
type = result.schema;
optional = result.questionToken ? QUESTION_TOKEN : optional;
} else {
type = result;
}
}
}
type = wrapWithReadWriteMarker(type, !!readOnly, !!writeOnly, options.ctx);
let property = ts.factory.createPropertySignature(
/* modifiers */
tsModifiers({
readonly: options.ctx.immutable || !options.ctx.readWriteMarkers && readOnly
}),
/* name */
tsPropertyIndex(k),
/* questionToken */
optional,
/* type */
type
);
if (typeof options.ctx.transformProperty === "function") {
const result = options.ctx.transformProperty(property, v, {
...options,
path: createRef([options.path, k])
});
if (result) {
property = result;
}
}
addJSDocComment(v, property);
coreObjectType.push(property);
}
}
if (schemaObject.$defs && typeof schemaObject.$defs === "object" && Object.keys(schemaObject.$defs).length) {
const defKeys = [];
for (const [k, v] of Object.entries(schemaObject.$defs)) {
const defReadOnly = "readOnly" in v && !!v.readOnly;
const defWriteOnly = "writeOnly" in v && !!v.writeOnly;
const defType = wrapWithReadWriteMarker(
transformSchemaObject(v, { ...options, path: createRef([options.path, "$defs", k]) }),
defReadOnly,
defWriteOnly,
options.ctx
);
let property = ts.factory.createPropertySignature(
/* modifiers */
tsModifiers({
readonly: options.ctx.immutable || !options.ctx.readWriteMarkers && defReadOnly
}),
/* name */
tsPropertyIndex(k),
/* questionToken */
void 0,
/* type */
defType
);
if (typeof options.ctx.transformProperty === "function") {
const result = options.ctx.transformProperty(property, v, {
...options,
path: createRef([options.path, "$defs", k])
});
if (result) {
property = result;
}
}
addJSDocComment(v, property);
defKeys.push(property);
}
coreObjectType.push(
ts.factory.createPropertySignature(
/* modifiers */
void 0,
/* name */
tsPropertyIndex("$defs"),
/* questionToken */
void 0,
/* type */
ts.factory.createTypeLiteralNode(defKeys)
)
);
}
const hasExplicitAdditionalProperties = typeof schemaObject.additionalProperties === "object" && Object.keys(schemaObject.additionalProperties).length;
const hasImplicitAdditionalProperties = schemaObject.additionalProperties === true || typeof schemaObject.additionalProperties === "object" && Object.keys(schemaObject.additionalProperties).length === 0;
const hasExplicitPatternProperties = typeof schemaObject.patternProperties === "object" && Object.keys(schemaObject.patternProperties).length;
const stringIndexTypes = [];
if (hasExplicitAdditionalProperties) {
stringIndexTypes.push(transformSchemaObject(schemaObject.additionalProperties, options, true));
}
if (hasImplicitAdditionalProperties || !schemaObject.additionalProperties && options.ctx.additionalProperties) {
stringIndexTypes.push(UNKNOWN);
}
if (hasExplicitPatternProperties) {
for (const [_, v] of getEntries(schemaObject.patternProperties ?? {}, options.ctx)) {
stringIndexTypes.push(transformSchemaObject(v, options));
}
}
if (stringIndexTypes.length === 0) {
return coreObjectType.length ? ts.factory.createTypeLiteralNode(coreObjectType) : void 0;
}
const stringIndexType = tsUnion(stringIndexTypes);
return tsIntersection([
...coreObjectType.length ? [ts.factory.createTypeLiteralNode(coreObjectType)] : [],
ts.factory.createTypeLiteralNode([
ts.factory.createIndexSignature(
/* modifiers */
tsModifiers({
readonly: options.ctx.immutable
}),
/* parameters */
[
ts.factory.createParameterDeclaration(
/* modifiers */
void 0,
/* dotDotDotToken */
void 0,
/* name */
ts.factory.createIdentifier("key"),
/* questionToken */
void 0,
/* type */
STRING
)
],
/* type */
stringIndexType
)
])
]);
}
return coreObjectType.length ? ts.factory.createTypeLiteralNode(coreObjectType) : void 0;
}
function hasKey(possibleObject, key) {
return typeof possibleObject === "object" && possibleObject !== null && key in possibleObject;
}
function wrapWithReadWriteMarker(type, readOnly, writeOnly, ctx) {
if (!ctx.readWriteMarkers || readOnly && writeOnly) {
return type;
}
if (readOnly) {
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("$Read"), [type]);
}
if (writeOnly) {
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("$Write"), [type]);
}
return type;
}
export { transformSchemaObject as default, transformSchemaObjectWithComposition };
//# sourceMappingURL=schema-object.mjs.map