@orval/core 8.9.1 → 8.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +116 -22
- package/dist/index.mjs +389 -106
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -77,6 +77,10 @@ const Verbs = {
|
|
|
77
77
|
DELETE: "delete",
|
|
78
78
|
HEAD: "head"
|
|
79
79
|
};
|
|
80
|
+
/**
|
|
81
|
+
* Canonical tag name used for the generated bucket that collects untagged operations.
|
|
82
|
+
*/
|
|
83
|
+
const DefaultTag = "default";
|
|
80
84
|
const GetterPropType = {
|
|
81
85
|
PARAM: "param",
|
|
82
86
|
NAMED_PATH_PARAMS: "namedPathParams",
|
|
@@ -362,6 +366,29 @@ function createDebugger(ns, options = {}) {
|
|
|
362
366
|
const search = String.raw`\*/`;
|
|
363
367
|
const replacement = String.raw`*\/`;
|
|
364
368
|
const regex$1 = new RegExp(search, "g");
|
|
369
|
+
const itemValidationKeys = [
|
|
370
|
+
"minLength",
|
|
371
|
+
"maxLength",
|
|
372
|
+
"minimum",
|
|
373
|
+
"maximum",
|
|
374
|
+
"exclusiveMinimum",
|
|
375
|
+
"exclusiveMaximum",
|
|
376
|
+
"minItems",
|
|
377
|
+
"maxItems",
|
|
378
|
+
"pattern"
|
|
379
|
+
];
|
|
380
|
+
function getItemValidationDocEntries(schema, prefix = "items", visited = /* @__PURE__ */ new WeakSet()) {
|
|
381
|
+
if (!schema) return [];
|
|
382
|
+
if (visited.has(schema)) return [];
|
|
383
|
+
visited.add(schema);
|
|
384
|
+
return [...itemValidationKeys.flatMap((key) => {
|
|
385
|
+
const value = schema[key];
|
|
386
|
+
return value === void 0 ? [] : [{
|
|
387
|
+
key: `${prefix}.${key}`,
|
|
388
|
+
value
|
|
389
|
+
}];
|
|
390
|
+
}), ...getItemValidationDocEntries(schema.items, `${prefix}.items`, visited)];
|
|
391
|
+
}
|
|
365
392
|
function jsDoc(schema, tryOneLine = false, context) {
|
|
366
393
|
if (context?.output.override.jsDoc) {
|
|
367
394
|
const { filter } = context.output.override.jsDoc;
|
|
@@ -369,6 +396,7 @@ function jsDoc(schema, tryOneLine = false, context) {
|
|
|
369
396
|
}
|
|
370
397
|
const { description, deprecated, summary, minLength, maxLength, minimum, maximum, exclusiveMinimum, exclusiveMaximum, minItems, maxItems, pattern } = schema;
|
|
371
398
|
const isNullable = schema.type === "null" || Array.isArray(schema.type) && schema.type.includes("null");
|
|
399
|
+
const itemValidationDocEntries = getItemValidationDocEntries(schema.items);
|
|
372
400
|
const lines = (Array.isArray(description) ? description.filter((d) => !d.includes("eslint-disable")) : [description ?? ""]).map((line) => line.replaceAll(regex$1, replacement));
|
|
373
401
|
const count = [
|
|
374
402
|
description,
|
|
@@ -383,7 +411,8 @@ function jsDoc(schema, tryOneLine = false, context) {
|
|
|
383
411
|
minItems?.toString(),
|
|
384
412
|
maxItems?.toString(),
|
|
385
413
|
isNullable ? "null" : "",
|
|
386
|
-
pattern
|
|
414
|
+
pattern,
|
|
415
|
+
...itemValidationDocEntries.map(({ value }) => value.toString())
|
|
387
416
|
].filter(Boolean).length;
|
|
388
417
|
if (!count) return "";
|
|
389
418
|
const oneLine = count === 1 && tryOneLine;
|
|
@@ -426,6 +455,17 @@ function jsDoc(schema, tryOneLine = false, context) {
|
|
|
426
455
|
tryAppendNumberDocLine("maxItems", maxItems);
|
|
427
456
|
tryAppendBooleanDocLine("nullable", isNullable);
|
|
428
457
|
tryAppendStringDocLine("pattern", pattern);
|
|
458
|
+
for (const { key, value } of itemValidationDocEntries) {
|
|
459
|
+
if (typeof value === "string") {
|
|
460
|
+
tryAppendStringDocLine(key, value);
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
if (typeof value === "number") {
|
|
464
|
+
tryAppendNumberDocLine(key, value);
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
tryAppendBooleanDocLine(key, value);
|
|
468
|
+
}
|
|
429
469
|
doc += oneLine ? " " : `\n ${tryOneLine ? " " : ""}`;
|
|
430
470
|
doc += "*/\n";
|
|
431
471
|
return doc;
|
|
@@ -1001,6 +1041,24 @@ function isSyntheticDefaultImportsAllow(config) {
|
|
|
1001
1041
|
if (!config) return true;
|
|
1002
1042
|
return !!(config.compilerOptions?.allowSyntheticDefaultImports ?? config.compilerOptions?.esModuleInterop);
|
|
1003
1043
|
}
|
|
1044
|
+
const NODE_NEXT_MODULES = new Set(["nodenext", "node16"]);
|
|
1045
|
+
const NODE_NEXT_EXTENSION_MAP = [
|
|
1046
|
+
[".tsx", ".jsx"],
|
|
1047
|
+
[".mts", ".mjs"],
|
|
1048
|
+
[".cts", ".cjs"],
|
|
1049
|
+
[".ts", ".js"]
|
|
1050
|
+
];
|
|
1051
|
+
function getImportExtension(fileExtension, tsconfig) {
|
|
1052
|
+
const compilerOptions = tsconfig?.compilerOptions;
|
|
1053
|
+
if (compilerOptions?.allowImportingTsExtensions) return fileExtension;
|
|
1054
|
+
const module = compilerOptions?.module?.toLowerCase();
|
|
1055
|
+
const moduleResolution = compilerOptions?.moduleResolution?.toLowerCase();
|
|
1056
|
+
if (module && NODE_NEXT_MODULES.has(module) || moduleResolution && NODE_NEXT_MODULES.has(moduleResolution)) {
|
|
1057
|
+
for (const [from, to] of NODE_NEXT_EXTENSION_MAP) if (fileExtension.endsWith(from)) return `${fileExtension.slice(0, -from.length)}${to}`;
|
|
1058
|
+
return fileExtension;
|
|
1059
|
+
}
|
|
1060
|
+
return fileExtension.replace(/\.ts$/, "") || "";
|
|
1061
|
+
}
|
|
1004
1062
|
//#endregion
|
|
1005
1063
|
//#region src/getters/enum.ts
|
|
1006
1064
|
/**
|
|
@@ -1210,12 +1268,34 @@ function getCombinedEnumValue(inputs) {
|
|
|
1210
1268
|
}
|
|
1211
1269
|
//#endregion
|
|
1212
1270
|
//#region src/getters/ref.ts
|
|
1271
|
+
/**
|
|
1272
|
+
* `$ref`s targeting these sections under `#/components/...` are emitted as
|
|
1273
|
+
* named TypeScript imports (e.g. `import type { Pet } from './model'`).
|
|
1274
|
+
* Refs to any other location — for example `#/paths/.../schema` produced by
|
|
1275
|
+
* JSON-Schema-Ref-Parser `bundle()` — have no corresponding `export type`
|
|
1276
|
+
* and must be inlined by the resolver. See issue #398.
|
|
1277
|
+
*/
|
|
1278
|
+
const NAMED_COMPONENT_SECTIONS = [
|
|
1279
|
+
"schemas",
|
|
1280
|
+
"responses",
|
|
1281
|
+
"parameters",
|
|
1282
|
+
"requestBodies"
|
|
1283
|
+
];
|
|
1213
1284
|
const RefComponentSuffix = {
|
|
1214
1285
|
schemas: "",
|
|
1215
1286
|
responses: "Response",
|
|
1216
1287
|
parameters: "Parameter",
|
|
1217
1288
|
requestBodies: "Body"
|
|
1218
1289
|
};
|
|
1290
|
+
const COMPONENT_REF_PATTERN = new RegExp(String.raw`^#\/components\/(${NAMED_COMPONENT_SECTIONS.join("|")})\/[^/]+$`);
|
|
1291
|
+
/**
|
|
1292
|
+
* True iff `ref` targets a named slot eligible for emission as a TypeScript
|
|
1293
|
+
* import. Used by `resolveValue` to decide between named import vs inlining
|
|
1294
|
+
* the resolved schema.
|
|
1295
|
+
*/
|
|
1296
|
+
function isComponentRef(ref) {
|
|
1297
|
+
return COMPONENT_REF_PATTERN.test(ref);
|
|
1298
|
+
}
|
|
1219
1299
|
const regex = /* @__PURE__ */ new RegExp("~1", "g");
|
|
1220
1300
|
/**
|
|
1221
1301
|
* Return the output type from the $ref
|
|
@@ -1358,7 +1438,34 @@ function resolveExampleRefs(examples, context) {
|
|
|
1358
1438
|
//#region src/resolvers/value.ts
|
|
1359
1439
|
function resolveValue({ schema, name, context, formDataContext }) {
|
|
1360
1440
|
if (isReference(schema)) {
|
|
1441
|
+
const refValue = schema.$ref;
|
|
1361
1442
|
const { schema: schemaObject, imports } = resolveRef(schema, context);
|
|
1443
|
+
if (refValue && !isComponentRef(refValue)) {
|
|
1444
|
+
if (context.parents?.includes(refValue)) return {
|
|
1445
|
+
value: "unknown",
|
|
1446
|
+
imports: [],
|
|
1447
|
+
schemas: [],
|
|
1448
|
+
type: "unknown",
|
|
1449
|
+
isEnum: false,
|
|
1450
|
+
originalSchema: schemaObject,
|
|
1451
|
+
hasReadonlyProps: false,
|
|
1452
|
+
isRef: false,
|
|
1453
|
+
dependencies: []
|
|
1454
|
+
};
|
|
1455
|
+
return {
|
|
1456
|
+
...getScalar({
|
|
1457
|
+
item: schemaObject,
|
|
1458
|
+
name,
|
|
1459
|
+
context: {
|
|
1460
|
+
...context,
|
|
1461
|
+
parents: [...context.parents ?? [], refValue]
|
|
1462
|
+
},
|
|
1463
|
+
formDataContext
|
|
1464
|
+
}),
|
|
1465
|
+
originalSchema: schemaObject,
|
|
1466
|
+
isRef: false
|
|
1467
|
+
};
|
|
1468
|
+
}
|
|
1362
1469
|
const resolvedImport = imports[0];
|
|
1363
1470
|
let hasReadonlyProps = false;
|
|
1364
1471
|
const refName = resolvedImport.name;
|
|
@@ -1543,7 +1650,7 @@ function getArray({ schema, name, context, formDataContext }) {
|
|
|
1543
1650
|
formDataContext
|
|
1544
1651
|
});
|
|
1545
1652
|
return {
|
|
1546
|
-
value: `${schema.readOnly === true && !context.output.override.suppressReadonlyModifier ? "readonly " : ""}${resolvedObject.value.includes("|") ? `(${resolvedObject.value})[]` : `${resolvedObject.value}[]`}`,
|
|
1653
|
+
value: `${schema.readOnly === true && !context.output.override.suppressReadonlyModifier ? "readonly " : ""}${resolvedObject.value.includes("|") || resolvedObject.value.includes("&") ? `(${resolvedObject.value})[]` : `${resolvedObject.value}[]`}`,
|
|
1547
1654
|
imports: resolvedObject.imports,
|
|
1548
1655
|
schemas: resolvedObject.schemas,
|
|
1549
1656
|
dependencies: resolvedObject.dependencies,
|
|
@@ -1568,7 +1675,7 @@ function getArray({ schema, name, context, formDataContext }) {
|
|
|
1568
1675
|
}
|
|
1569
1676
|
//#endregion
|
|
1570
1677
|
//#region src/getters/res-req-types.ts
|
|
1571
|
-
const getSchemaType = (s) => s.type;
|
|
1678
|
+
const getSchemaType$1 = (s) => s.type;
|
|
1572
1679
|
const getSchemaCombined = (s) => s.oneOf ?? s.anyOf ?? s.allOf;
|
|
1573
1680
|
const getSchemaOneOf = (s) => s.oneOf;
|
|
1574
1681
|
const getSchemaAnyOf = (s) => s.anyOf;
|
|
@@ -1957,7 +2064,7 @@ function resolveSchemaPropertiesToFormData({ schema, variableName, propName, con
|
|
|
1957
2064
|
${resolvedValue}});\n`;
|
|
1958
2065
|
} else valueStr = "JSON.stringify(value)";
|
|
1959
2066
|
else {
|
|
1960
|
-
const itemType = getSchemaType(itemSchema);
|
|
2067
|
+
const itemType = getSchemaType$1(itemSchema);
|
|
1961
2068
|
if (itemType === "number" || Array.isArray(itemType) && itemType.includes("number") || itemType === "integer" || Array.isArray(itemType) && itemType.includes("integer") || itemType === "boolean" || Array.isArray(itemType) && itemType.includes("boolean")) valueStr = "value.toString()";
|
|
1962
2069
|
}
|
|
1963
2070
|
}
|
|
@@ -1965,7 +2072,7 @@ function resolveSchemaPropertiesToFormData({ schema, variableName, propName, con
|
|
|
1965
2072
|
if (!hasNonPrimitiveChild) formDataValue = `${valueKey}.forEach((value, index${depth > 0 ? depth : ""}) => ${variableName}.append(\`${keyPrefix}${key}[\${index${depth > 0 ? depth : ""}}]\`, ${valueStr}));\n`;
|
|
1966
2073
|
} else formDataValue = `${valueKey}.forEach(value => ${variableName}.append(\`${keyPrefix}${key}${context.output.override.formData.arrayHandling === FormDataArrayHandling.SERIALIZE_WITH_BRACKETS ? "[]" : ""}\`, ${valueStr}));\n`;
|
|
1967
2074
|
} else if ((() => {
|
|
1968
|
-
const propType = getSchemaType(property);
|
|
2075
|
+
const propType = getSchemaType$1(property);
|
|
1969
2076
|
return propType === "number" || Array.isArray(propType) && propType.includes("number") || propType === "integer" || Array.isArray(propType) && propType.includes("integer") || propType === "boolean" || Array.isArray(propType) && propType.includes("boolean");
|
|
1970
2077
|
})()) formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey}.toString())\n`;
|
|
1971
2078
|
else formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
|
|
@@ -1989,7 +2096,7 @@ function resolveSchemaPropertiesToFormData({ schema, variableName, propName, con
|
|
|
1989
2096
|
})) existSubSchemaNullable = true;
|
|
1990
2097
|
}
|
|
1991
2098
|
const isRequired = getSchemaRequired(schema)?.includes(key) && !isRequestBodyOptional;
|
|
1992
|
-
const propType = getSchemaType(property);
|
|
2099
|
+
const propType = getSchemaType$1(property);
|
|
1993
2100
|
if (property.nullable || Array.isArray(propType) && propType.includes("null") || existSubSchemaNullable) {
|
|
1994
2101
|
if (isRequired) {
|
|
1995
2102
|
formDataValues += `if(${valueKey} !== null) {\n ${formDataValue} }\n`;
|
|
@@ -2108,30 +2215,59 @@ function getKey(key) {
|
|
|
2108
2215
|
}
|
|
2109
2216
|
//#endregion
|
|
2110
2217
|
//#region src/getters/object.ts
|
|
2218
|
+
function getPropertyNamesEnumKeyType(item) {
|
|
2219
|
+
if (!("propertyNames" in item) || !item.propertyNames) return;
|
|
2220
|
+
const propertyNames = item.propertyNames;
|
|
2221
|
+
if (Array.isArray(propertyNames.enum)) {
|
|
2222
|
+
const enumValues = propertyNames.enum.filter((val) => isString(val));
|
|
2223
|
+
if (enumValues.length > 0) return {
|
|
2224
|
+
value: enumValues.map((val) => `'${escape(val)}'`).join(" | "),
|
|
2225
|
+
imports: [],
|
|
2226
|
+
dependencies: []
|
|
2227
|
+
};
|
|
2228
|
+
}
|
|
2229
|
+
if (isString(propertyNames.const)) return {
|
|
2230
|
+
value: `'${escape(propertyNames.const)}'`,
|
|
2231
|
+
imports: [],
|
|
2232
|
+
dependencies: []
|
|
2233
|
+
};
|
|
2234
|
+
}
|
|
2111
2235
|
/**
|
|
2112
|
-
*
|
|
2113
|
-
*
|
|
2114
|
-
* Returns undefined if propertyNames has neither
|
|
2236
|
+
* Resolve a narrowed key type from OpenAPI 3.1 propertyNames.
|
|
2237
|
+
* Supports inline enum/const and $ref string enums.
|
|
2115
2238
|
*/
|
|
2116
|
-
function
|
|
2117
|
-
|
|
2239
|
+
function getPropertyNamesKeyType(item, context) {
|
|
2240
|
+
const inlineKeyType = getPropertyNamesEnumKeyType(item);
|
|
2241
|
+
if (inlineKeyType) return inlineKeyType;
|
|
2118
2242
|
const propertyNames = item.propertyNames;
|
|
2119
|
-
if (
|
|
2120
|
-
|
|
2243
|
+
if (!propertyNames || !isReference(propertyNames)) return;
|
|
2244
|
+
const resolvedValue = resolveValue({
|
|
2245
|
+
schema: propertyNames,
|
|
2246
|
+
context
|
|
2247
|
+
});
|
|
2248
|
+
const resolvedConst = resolvedValue.originalSchema.const;
|
|
2249
|
+
const isStringConst = resolvedValue.type === "string" && isString(resolvedConst);
|
|
2250
|
+
if (!resolvedValue.isEnum && !isStringConst) return;
|
|
2251
|
+
return {
|
|
2252
|
+
value: resolvedValue.value,
|
|
2253
|
+
imports: resolvedValue.imports,
|
|
2254
|
+
dependencies: resolvedValue.dependencies
|
|
2255
|
+
};
|
|
2121
2256
|
}
|
|
2122
2257
|
/**
|
|
2123
2258
|
* Generate index signature key type based on propertyNames enum or const
|
|
2124
2259
|
* Returns union type string like "'foo' | 'bar'", "'x'", or 'string' if neither
|
|
2125
2260
|
*/
|
|
2126
2261
|
function getIndexSignatureKey(item) {
|
|
2127
|
-
|
|
2128
|
-
if (enumValues && enumValues.length > 0) return enumValues.map((val) => `'${val}'`).join(" | ");
|
|
2129
|
-
return "string";
|
|
2262
|
+
return getPropertyNamesEnumKeyType(item)?.value ?? "string";
|
|
2130
2263
|
}
|
|
2131
|
-
function getPropertyNamesRecordType(item, valueType) {
|
|
2132
|
-
const
|
|
2133
|
-
if (!
|
|
2134
|
-
return
|
|
2264
|
+
function getPropertyNamesRecordType(item, valueType, context) {
|
|
2265
|
+
const keyType = getPropertyNamesKeyType(item, context);
|
|
2266
|
+
if (!keyType) return;
|
|
2267
|
+
return {
|
|
2268
|
+
...keyType,
|
|
2269
|
+
value: `Partial<Record<${keyType.value}, ${valueType}>>`
|
|
2270
|
+
};
|
|
2135
2271
|
}
|
|
2136
2272
|
/**
|
|
2137
2273
|
* Return the output type from an object
|
|
@@ -2185,7 +2321,7 @@ function getObject({ item, name, context, nullable, formDataContext }) {
|
|
|
2185
2321
|
if (itemProperties && Object.entries(itemProperties).length > 0) {
|
|
2186
2322
|
const entries = Object.entries(itemProperties);
|
|
2187
2323
|
if (context.output.propertySortOrder === PropertySortOrder.ALPHABETICAL) entries.sort((a, b) => {
|
|
2188
|
-
return a[0].localeCompare(b[0]);
|
|
2324
|
+
return a[0].localeCompare(b[0], "en", { numeric: true });
|
|
2189
2325
|
});
|
|
2190
2326
|
const acc = {
|
|
2191
2327
|
imports: [],
|
|
@@ -2224,7 +2360,7 @@ function getObject({ item, name, context, nullable, formDataContext }) {
|
|
|
2224
2360
|
if (!index) acc.value += "{";
|
|
2225
2361
|
const doc = jsDoc(schema, true, context);
|
|
2226
2362
|
const propertyDoc = doc ? `${doc.trimEnd().split("\n").map((line) => ` ${line}`).join("\n")}\n` : "";
|
|
2227
|
-
if (isReadOnly) acc.hasReadonlyProps = true;
|
|
2363
|
+
if (isReadOnly || resolvedValue.hasReadonlyProps) acc.hasReadonlyProps = true;
|
|
2228
2364
|
const constValue = "const" in schema ? schema.const : void 0;
|
|
2229
2365
|
const hasConst = constValue !== void 0;
|
|
2230
2366
|
let constLiteral;
|
|
@@ -2257,11 +2393,13 @@ function getObject({ item, name, context, nullable, formDataContext }) {
|
|
|
2257
2393
|
if (entries.length - 1 === index) {
|
|
2258
2394
|
const additionalProps = schemaItem.additionalProperties;
|
|
2259
2395
|
if (additionalProps) if (additionalProps === true) {
|
|
2260
|
-
const recordType = getPropertyNamesRecordType(schemaItem, "unknown");
|
|
2396
|
+
const recordType = getPropertyNamesRecordType(schemaItem, "unknown", context);
|
|
2261
2397
|
if (recordType) {
|
|
2262
2398
|
acc.value += "\n}";
|
|
2263
|
-
acc.value += ` & ${recordType}`;
|
|
2399
|
+
acc.value += ` & ${recordType.value}`;
|
|
2264
2400
|
acc.useTypeAlias = true;
|
|
2401
|
+
acc.imports.push(...recordType.imports);
|
|
2402
|
+
acc.dependencies.push(...recordType.dependencies);
|
|
2265
2403
|
} else {
|
|
2266
2404
|
const keyType = getIndexSignatureKey(schemaItem);
|
|
2267
2405
|
acc.value += `\n [key: ${keyType}]: unknown;\n }`;
|
|
@@ -2272,11 +2410,13 @@ function getObject({ item, name, context, nullable, formDataContext }) {
|
|
|
2272
2410
|
name,
|
|
2273
2411
|
context
|
|
2274
2412
|
});
|
|
2275
|
-
const recordType = getPropertyNamesRecordType(schemaItem, resolvedValue.value);
|
|
2413
|
+
const recordType = getPropertyNamesRecordType(schemaItem, resolvedValue.value, context);
|
|
2276
2414
|
if (recordType) {
|
|
2277
2415
|
acc.value += "\n}";
|
|
2278
|
-
acc.value += ` & ${recordType}`;
|
|
2416
|
+
acc.value += ` & ${recordType.value}`;
|
|
2279
2417
|
acc.useTypeAlias = true;
|
|
2418
|
+
acc.imports.push(...recordType.imports);
|
|
2419
|
+
acc.dependencies.push(...recordType.dependencies);
|
|
2280
2420
|
} else {
|
|
2281
2421
|
const keyType = getIndexSignatureKey(schemaItem);
|
|
2282
2422
|
acc.value += `\n [key: ${keyType}]: ${resolvedValue.value};\n}`;
|
|
@@ -2295,17 +2435,17 @@ function getObject({ item, name, context, nullable, formDataContext }) {
|
|
|
2295
2435
|
const readOnlyFlag = schemaItem.readOnly;
|
|
2296
2436
|
if (outerAdditionalProps) {
|
|
2297
2437
|
if (outerAdditionalProps === true) {
|
|
2298
|
-
const recordType = getPropertyNamesRecordType(schemaItem, "unknown");
|
|
2438
|
+
const recordType = getPropertyNamesRecordType(schemaItem, "unknown", context);
|
|
2299
2439
|
if (recordType) return {
|
|
2300
|
-
value: recordType + nullable,
|
|
2301
|
-
imports:
|
|
2440
|
+
value: recordType.value + nullable,
|
|
2441
|
+
imports: recordType.imports,
|
|
2302
2442
|
schemas: [],
|
|
2303
2443
|
isEnum: false,
|
|
2304
2444
|
type: "object",
|
|
2305
2445
|
isRef: false,
|
|
2306
2446
|
hasReadonlyProps: readOnlyFlag ?? false,
|
|
2307
2447
|
useTypeAlias: true,
|
|
2308
|
-
dependencies:
|
|
2448
|
+
dependencies: recordType.dependencies
|
|
2309
2449
|
};
|
|
2310
2450
|
return {
|
|
2311
2451
|
value: `{ [key: ${getIndexSignatureKey(schemaItem)}]: unknown }` + nullable,
|
|
@@ -2324,17 +2464,17 @@ function getObject({ item, name, context, nullable, formDataContext }) {
|
|
|
2324
2464
|
name,
|
|
2325
2465
|
context
|
|
2326
2466
|
});
|
|
2327
|
-
const recordType = getPropertyNamesRecordType(schemaItem, resolvedValue.value);
|
|
2467
|
+
const recordType = getPropertyNamesRecordType(schemaItem, resolvedValue.value, context);
|
|
2328
2468
|
if (recordType) return {
|
|
2329
|
-
value: recordType + nullable,
|
|
2330
|
-
imports: resolvedValue.imports,
|
|
2469
|
+
value: recordType.value + nullable,
|
|
2470
|
+
imports: [...recordType.imports, ...resolvedValue.imports],
|
|
2331
2471
|
schemas: resolvedValue.schemas,
|
|
2332
2472
|
isEnum: false,
|
|
2333
2473
|
type: "object",
|
|
2334
2474
|
isRef: false,
|
|
2335
2475
|
hasReadonlyProps: resolvedValue.hasReadonlyProps,
|
|
2336
2476
|
useTypeAlias: true,
|
|
2337
|
-
dependencies: resolvedValue.dependencies
|
|
2477
|
+
dependencies: [...recordType.dependencies, ...resolvedValue.dependencies]
|
|
2338
2478
|
};
|
|
2339
2479
|
return {
|
|
2340
2480
|
value: `{[key: ${getIndexSignatureKey(schemaItem)}]: ${resolvedValue.value}}` + nullable,
|
|
@@ -2369,17 +2509,17 @@ function getObject({ item, name, context, nullable, formDataContext }) {
|
|
|
2369
2509
|
};
|
|
2370
2510
|
}
|
|
2371
2511
|
const keyType = itemType === "object" ? getIndexSignatureKey(schemaItem) : "string";
|
|
2372
|
-
const recordType = getPropertyNamesRecordType(schemaItem, "unknown");
|
|
2512
|
+
const recordType = getPropertyNamesRecordType(schemaItem, "unknown", context);
|
|
2373
2513
|
if (itemType === "object" && recordType) return {
|
|
2374
|
-
value: recordType + nullable,
|
|
2375
|
-
imports:
|
|
2514
|
+
value: recordType.value + nullable,
|
|
2515
|
+
imports: recordType.imports,
|
|
2376
2516
|
schemas: [],
|
|
2377
2517
|
isEnum: false,
|
|
2378
2518
|
type: "object",
|
|
2379
2519
|
isRef: false,
|
|
2380
2520
|
hasReadonlyProps: readOnlyFlag ?? false,
|
|
2381
2521
|
useTypeAlias: true,
|
|
2382
|
-
dependencies:
|
|
2522
|
+
dependencies: recordType.dependencies
|
|
2383
2523
|
};
|
|
2384
2524
|
return {
|
|
2385
2525
|
value: (itemType === "object" ? `{ [key: ${keyType}]: unknown }` : "unknown") + nullable,
|
|
@@ -2966,6 +3106,50 @@ const isOpenApiSchemaObject = (value) => {
|
|
|
2966
3106
|
if (!value || typeof value !== "object") return false;
|
|
2967
3107
|
return !("$ref" in value);
|
|
2968
3108
|
};
|
|
3109
|
+
/**
|
|
3110
|
+
* A `$ref` schema object (e.g. array `items` or a oneOf/anyOf/allOf variant
|
|
3111
|
+
* pointing at a component). We don't resolve the reference here, but a query
|
|
3112
|
+
* parameter behind a `$ref` is virtually always a complex (object-like) type,
|
|
3113
|
+
* so it must be treated as non-primitive. Over-flagging is harmless: the only
|
|
3114
|
+
* consumer (the Angular `nonPrimitiveKeys` passthrough) is gated on a
|
|
3115
|
+
* configured `paramsSerializer`, which is precisely what handles raw values.
|
|
3116
|
+
*/
|
|
3117
|
+
const isRefObject = (value) => !!value && typeof value === "object" && "$ref" in value;
|
|
3118
|
+
const getSchemaType = (schema) => {
|
|
3119
|
+
const type = schema.type;
|
|
3120
|
+
if (typeof type === "string") return type;
|
|
3121
|
+
if (Array.isArray(type) && type.every((variant) => typeof variant === "string")) return type;
|
|
3122
|
+
};
|
|
3123
|
+
/**
|
|
3124
|
+
* Detects whether a query parameter's resolved schema is non-primitive — i.e.
|
|
3125
|
+
* an object, an array of objects, or a composition (oneOf/anyOf/allOf) that
|
|
3126
|
+
* resolves to a non-primitive shape.
|
|
3127
|
+
*
|
|
3128
|
+
* Used by Angular generators so the default `filterParams` helper preserves
|
|
3129
|
+
* such values instead of silently dropping them. Angular's `HttpParams` only
|
|
3130
|
+
* accepts primitives, but a user-provided `paramsSerializer`, `mutator`, or
|
|
3131
|
+
* `paramsFilter` may need the raw object to flatten or stringify it.
|
|
3132
|
+
*/
|
|
3133
|
+
const isSchemaNonPrimitive = (schema) => {
|
|
3134
|
+
const schemaType = getSchemaType(schema);
|
|
3135
|
+
const type = Array.isArray(schemaType) ? schemaType.filter((variant) => variant !== "null") : schemaType;
|
|
3136
|
+
const additionalProperties = schema.additionalProperties;
|
|
3137
|
+
if (type === "object") return true;
|
|
3138
|
+
if (Array.isArray(type) && type.includes("object")) return true;
|
|
3139
|
+
if (type === "array" || Array.isArray(type) && type.includes("array")) {
|
|
3140
|
+
const items = schema.items;
|
|
3141
|
+
if (isOpenApiSchemaObject(items)) return isSchemaNonPrimitive(items);
|
|
3142
|
+
return true;
|
|
3143
|
+
}
|
|
3144
|
+
const compositions = [
|
|
3145
|
+
...Array.isArray(schema.oneOf) ? schema.oneOf : [],
|
|
3146
|
+
...Array.isArray(schema.anyOf) ? schema.anyOf : [],
|
|
3147
|
+
...Array.isArray(schema.allOf) ? schema.allOf : []
|
|
3148
|
+
];
|
|
3149
|
+
if (compositions.length > 0) return compositions.some((variant) => isOpenApiSchemaObject(variant) ? isSchemaNonPrimitive(variant) : isRefObject(variant));
|
|
3150
|
+
if (!type && (schema.properties !== void 0 || additionalProperties !== void 0 && additionalProperties !== false)) return true;
|
|
3151
|
+
return false;
|
|
3152
|
+
};
|
|
2969
3153
|
const isSchemaNullable = (schema) => {
|
|
2970
3154
|
if (schema.nullable === true) return true;
|
|
2971
3155
|
if (schema.type === "null") return true;
|
|
@@ -3043,6 +3227,7 @@ function getQueryParams({ queryParams, operationName, context, suffix = "params"
|
|
|
3043
3227
|
const type = types.map(({ definition }) => definition).join("\n");
|
|
3044
3228
|
const allOptional = queryParams.every(({ parameter }) => !parameter.required);
|
|
3045
3229
|
const requiredNullableKeys = types.filter(({ required, originalSchema }) => required && isSchemaNullable(originalSchema)).map(({ name }) => name);
|
|
3230
|
+
const nonPrimitiveKeys = types.filter(({ originalSchema }) => isSchemaNonPrimitive(originalSchema)).map(({ name }) => name);
|
|
3046
3231
|
return {
|
|
3047
3232
|
schema: {
|
|
3048
3233
|
name,
|
|
@@ -3051,7 +3236,8 @@ function getQueryParams({ queryParams, operationName, context, suffix = "params"
|
|
|
3051
3236
|
},
|
|
3052
3237
|
deps: schemas,
|
|
3053
3238
|
isOptional: allOptional,
|
|
3054
|
-
requiredNullableKeys
|
|
3239
|
+
requiredNullableKeys,
|
|
3240
|
+
...nonPrimitiveKeys.length > 0 ? { nonPrimitiveKeys } : {}
|
|
3055
3241
|
};
|
|
3056
3242
|
}
|
|
3057
3243
|
//#endregion
|
|
@@ -3076,7 +3262,7 @@ function getResponse({ responses, operationName, context, contentType }) {
|
|
|
3076
3262
|
success: success || (defaultType ?? "unknown"),
|
|
3077
3263
|
errors: errors || (defaultType ?? "unknown")
|
|
3078
3264
|
},
|
|
3079
|
-
isBlob: groupedByStatus.success.some((t) => !!t.contentType && isBinaryContentType(t.contentType)),
|
|
3265
|
+
isBlob: groupedByStatus.success.some((t) => !!t.contentType && isBinaryContentType(t.contentType) || t.value === "Blob" && !t.isRef),
|
|
3080
3266
|
types: groupedByStatus,
|
|
3081
3267
|
contentTypes,
|
|
3082
3268
|
schemas,
|
|
@@ -3207,13 +3393,13 @@ function generateComponentDefinition(responses = {}, context, suffix) {
|
|
|
3207
3393
|
}
|
|
3208
3394
|
//#endregion
|
|
3209
3395
|
//#region src/generators/imports.ts
|
|
3210
|
-
function generateImports({ imports, namingConvention = NamingConvention.CAMEL_CASE }) {
|
|
3396
|
+
function generateImports({ imports, namingConvention = NamingConvention.CAMEL_CASE, importExtension = "" }) {
|
|
3211
3397
|
if (imports.length === 0) return "";
|
|
3212
3398
|
const grouped = groupBy(uniqueWith(imports, (a, b) => a.name === b.name && a.default === b.default && a.alias === b.alias && a.values === b.values && a.isConstant === b.isConstant && a.namespaceImport === b.namespaceImport && a.syntheticDefaultImport === b.syntheticDefaultImport && a.importPath === b.importPath).map((imp) => ({
|
|
3213
3399
|
...imp,
|
|
3214
|
-
importPath: imp.importPath ?? `./${conventionName(imp.name, namingConvention)}`
|
|
3400
|
+
importPath: imp.importPath ?? `./${conventionName(imp.name, namingConvention)}${importExtension}`
|
|
3215
3401
|
})), (imp) => !imp.default && !imp.namespaceImport && !imp.syntheticDefaultImport && !imp.values && !imp.isConstant ? `aggregate|${imp.importPath}` : `single|${imp.importPath}|${imp.name}|${imp.alias ?? ""}|${String(imp.default)}|${String(imp.namespaceImport)}|${String(imp.syntheticDefaultImport)}|${String(imp.values)}|${String(imp.isConstant)}`);
|
|
3216
|
-
return Object.entries(grouped).toSorted(([a], [b]) => a.localeCompare(b)).map(([, group]) => {
|
|
3402
|
+
return Object.entries(grouped).toSorted(([a], [b]) => a.localeCompare(b, "en", { numeric: true })).map(([, group]) => {
|
|
3217
3403
|
const sample = group[0];
|
|
3218
3404
|
if (!sample.default && !sample.namespaceImport && !sample.syntheticDefaultImport && !sample.values && !sample.isConstant) return `import type { ${[...new Set(group.map(({ name, alias }) => `${name}${alias ? ` as ${alias}` : ""}`))].toSorted().join(", ")} } from '${sample.importPath}';`;
|
|
3219
3405
|
const { name, values, alias, isConstant, importPath } = sample;
|
|
@@ -3223,7 +3409,8 @@ function generateImports({ imports, namingConvention = NamingConvention.CAMEL_CA
|
|
|
3223
3409
|
function generateMutatorImports({ mutators, implementation, oneMore }) {
|
|
3224
3410
|
let imports = "";
|
|
3225
3411
|
for (const mutator of uniqueWith(mutators, (a, b) => a.name === b.name && a.default === b.default)) {
|
|
3226
|
-
const
|
|
3412
|
+
const isRelativeImport = mutator.path.startsWith(".");
|
|
3413
|
+
const path = `${oneMore && isRelativeImport ? "../" : ""}${mutator.path}`;
|
|
3227
3414
|
const importDefault = mutator.default ? mutator.name : `{ ${mutator.name} }`;
|
|
3228
3415
|
imports += `import ${importDefault} from '${path}';`;
|
|
3229
3416
|
imports += "\n";
|
|
@@ -3570,16 +3757,24 @@ function removeComments(file) {
|
|
|
3570
3757
|
* (e.g. observe-mode branches), prefer getAngularFilteredParamsCallExpression +
|
|
3571
3758
|
* getAngularFilteredParamsHelperBody instead.
|
|
3572
3759
|
*/
|
|
3573
|
-
const getAngularFilteredParamsExpression = (paramsExpression, requiredNullableParamKeys = [], preserveRequiredNullables = false) => {
|
|
3574
|
-
const
|
|
3760
|
+
const getAngularFilteredParamsExpression = (paramsExpression, requiredNullableParamKeys = [], preserveRequiredNullables = false, nonPrimitiveKeys = []) => {
|
|
3761
|
+
const hasPassthrough = nonPrimitiveKeys.length > 0;
|
|
3762
|
+
const filteredParamValueType = hasPassthrough ? "unknown" : `string | number | boolean${preserveRequiredNullables ? " | null" : ""} | Array<string | number | boolean>`;
|
|
3763
|
+
const passthroughBranch = hasPassthrough ? ` if (passthroughKeys.has(key)) {
|
|
3764
|
+
if (value !== undefined) {
|
|
3765
|
+
filteredParams[key] = value;
|
|
3766
|
+
}
|
|
3767
|
+
continue;
|
|
3768
|
+
}
|
|
3769
|
+
` : "";
|
|
3575
3770
|
const preserveNullableBranch = preserveRequiredNullables ? ` } else if (value === null && requiredNullableParamKeys.has(key)) {
|
|
3576
3771
|
filteredParams[key] = null;
|
|
3577
3772
|
` : "";
|
|
3578
3773
|
return `(() => {
|
|
3579
|
-
const requiredNullableParamKeys = new Set<string>(${JSON.stringify(requiredNullableParamKeys)});
|
|
3774
|
+
${hasPassthrough ? ` const passthroughKeys = new Set<string>(${JSON.stringify(nonPrimitiveKeys)});\n` : ""} const requiredNullableParamKeys = new Set<string>(${JSON.stringify(requiredNullableParamKeys)});
|
|
3580
3775
|
const filteredParams: Record<string, ${filteredParamValueType}> = {};
|
|
3581
3776
|
for (const [key, value] of Object.entries(${paramsExpression})) {
|
|
3582
|
-
if (Array.isArray(value)) {
|
|
3777
|
+
${passthroughBranch} if (Array.isArray(value)) {
|
|
3583
3778
|
const filtered = value.filter(
|
|
3584
3779
|
(item) =>
|
|
3585
3780
|
item != null &&
|
|
@@ -3614,19 +3809,34 @@ function filterParams(
|
|
|
3614
3809
|
params: Record<string, unknown>,
|
|
3615
3810
|
requiredNullableKeys?: ReadonlySet<string>,
|
|
3616
3811
|
preserveRequiredNullables?: false,
|
|
3812
|
+
passthroughKeys?: undefined,
|
|
3617
3813
|
): Record<string, AngularHttpParamValue>;
|
|
3618
3814
|
function filterParams(
|
|
3619
3815
|
params: Record<string, unknown>,
|
|
3620
3816
|
requiredNullableKeys: ReadonlySet<string> | undefined,
|
|
3621
3817
|
preserveRequiredNullables: true,
|
|
3818
|
+
passthroughKeys?: undefined,
|
|
3622
3819
|
): Record<string, AngularHttpParamValueWithNullable>;
|
|
3820
|
+
function filterParams(
|
|
3821
|
+
params: Record<string, unknown>,
|
|
3822
|
+
requiredNullableKeys: ReadonlySet<string> | undefined,
|
|
3823
|
+
preserveRequiredNullables: boolean | undefined,
|
|
3824
|
+
passthroughKeys: ReadonlySet<string>,
|
|
3825
|
+
): Record<string, unknown>;
|
|
3623
3826
|
function filterParams(
|
|
3624
3827
|
params: Record<string, unknown>,
|
|
3625
3828
|
requiredNullableKeys: ReadonlySet<string> = new Set(),
|
|
3626
3829
|
preserveRequiredNullables = false,
|
|
3627
|
-
|
|
3628
|
-
|
|
3830
|
+
passthroughKeys: ReadonlySet<string> = new Set(),
|
|
3831
|
+
): Record<string, unknown> {
|
|
3832
|
+
const filteredParams: Record<string, unknown> = {};
|
|
3629
3833
|
for (const [key, value] of Object.entries(params)) {
|
|
3834
|
+
if (passthroughKeys.has(key)) {
|
|
3835
|
+
if (value !== undefined) {
|
|
3836
|
+
filteredParams[key] = value;
|
|
3837
|
+
}
|
|
3838
|
+
continue;
|
|
3839
|
+
}
|
|
3630
3840
|
if (Array.isArray(value)) {
|
|
3631
3841
|
const filtered = value.filter(
|
|
3632
3842
|
(item) =>
|
|
@@ -3658,15 +3868,34 @@ function filterParams(
|
|
|
3658
3868
|
/**
|
|
3659
3869
|
* Returns a call expression to the `filterParams` helper function.
|
|
3660
3870
|
*/
|
|
3661
|
-
const getAngularFilteredParamsCallExpression = (paramsExpression, requiredNullableParamKeys = [], preserveRequiredNullables = false
|
|
3871
|
+
const getAngularFilteredParamsCallExpression = (paramsExpression, requiredNullableParamKeys = [], preserveRequiredNullables = false, nonPrimitiveKeys = []) => {
|
|
3872
|
+
const baseArgs = `${paramsExpression}, new Set<string>(${JSON.stringify(requiredNullableParamKeys)})`;
|
|
3873
|
+
if (nonPrimitiveKeys.length > 0) return `filterParams(${baseArgs}, ${preserveRequiredNullables}, new Set<string>(${JSON.stringify(nonPrimitiveKeys)}))`;
|
|
3874
|
+
return `filterParams(${baseArgs}${preserveRequiredNullables ? ", true" : ""})`;
|
|
3875
|
+
};
|
|
3876
|
+
/**
|
|
3877
|
+
* Returns the filter call/IIFE used to massage query params before passing
|
|
3878
|
+
* them to Angular's HttpParams. When the user supplied a `paramsFilter`
|
|
3879
|
+
* mutator, the built-in `filterParams` is bypassed entirely and the user's
|
|
3880
|
+
* function is called with the raw params — they own nullish-stripping and
|
|
3881
|
+
* any object/array handling. Otherwise the built-in filter is used (either
|
|
3882
|
+
* the shared helper or an inline IIFE), and callers should only pass
|
|
3883
|
+
* `nonPrimitiveKeys` when a downstream serializer or custom consumer can
|
|
3884
|
+
* legally handle raw object/array values.
|
|
3885
|
+
*/
|
|
3886
|
+
const buildAngularParamsFilterExpression = ({ paramsExpression, requiredNullableParamKeys = [], preserveRequiredNullables = false, nonPrimitiveKeys = [], paramsFilter, useSharedHelper }) => {
|
|
3887
|
+
if (paramsFilter) return `${paramsFilter.name}(${paramsExpression})`;
|
|
3888
|
+
if (useSharedHelper) return getAngularFilteredParamsCallExpression(paramsExpression, requiredNullableParamKeys, preserveRequiredNullables, nonPrimitiveKeys);
|
|
3889
|
+
return getAngularFilteredParamsExpression(paramsExpression, requiredNullableParamKeys, preserveRequiredNullables, nonPrimitiveKeys);
|
|
3890
|
+
};
|
|
3662
3891
|
function generateBodyOptions(body, isFormData, isFormUrlEncoded) {
|
|
3663
|
-
if (isFormData && body.formData) return "
|
|
3664
|
-
if (isFormUrlEncoded && body.formUrlEncoded) return "
|
|
3665
|
-
if (body.implementation) return
|
|
3666
|
-
return "";
|
|
3892
|
+
if (isFormData && body.formData) return "formData";
|
|
3893
|
+
if (isFormUrlEncoded && body.formUrlEncoded) return "formUrlEncoded";
|
|
3894
|
+
if (body.implementation) return body.implementation;
|
|
3667
3895
|
}
|
|
3668
|
-
function generateAxiosOptions({ response, isExactOptionalPropertyTypes, angularObserve, angularParamsRef, requiredNullableQueryParamKeys, queryParams, headers, requestOptions, hasSignal, hasSignalParam = false, isVue, isAngular, paramsSerializer, paramsSerializerOptions }) {
|
|
3896
|
+
function generateAxiosOptions({ response, isExactOptionalPropertyTypes, angularObserve, angularParamsRef, requiredNullableQueryParamKeys, nonPrimitiveQueryParamKeys, queryParams, headers, requestOptions, hasSignal, hasSignalParam = false, isVue, isAngular, paramsSerializer, paramsSerializerOptions, paramsFilter }) {
|
|
3669
3897
|
const isRequestOptions = requestOptions !== false;
|
|
3898
|
+
const angularPassthroughQueryParamKeys = paramsSerializer ? nonPrimitiveQueryParamKeys : [];
|
|
3670
3899
|
const signalVar = hasSignalParam ? "querySignal" : "signal";
|
|
3671
3900
|
const signalProp = hasSignalParam ? `signal: ${signalVar}` : "signal";
|
|
3672
3901
|
if (!queryParams && !headers && !response.isBlob && response.definition.success !== "string") {
|
|
@@ -3680,7 +3909,14 @@ function generateAxiosOptions({ response, isExactOptionalPropertyTypes, angularO
|
|
|
3680
3909
|
let value = "";
|
|
3681
3910
|
if (!isRequestOptions) {
|
|
3682
3911
|
if (queryParams) if (isAngular) {
|
|
3683
|
-
const iifeExpr =
|
|
3912
|
+
const iifeExpr = buildAngularParamsFilterExpression({
|
|
3913
|
+
paramsExpression: "params ?? {}",
|
|
3914
|
+
requiredNullableParamKeys: requiredNullableQueryParamKeys,
|
|
3915
|
+
preserveRequiredNullables: !!paramsSerializer,
|
|
3916
|
+
nonPrimitiveKeys: angularPassthroughQueryParamKeys,
|
|
3917
|
+
paramsFilter,
|
|
3918
|
+
useSharedHelper: false
|
|
3919
|
+
});
|
|
3684
3920
|
value += paramsSerializer ? `\n params: ${paramsSerializer.name}(${iifeExpr}),` : `\n params: ${iifeExpr},`;
|
|
3685
3921
|
} else value += "\n params,";
|
|
3686
3922
|
if (headers) value += "\n headers,";
|
|
@@ -3697,10 +3933,25 @@ function generateAxiosOptions({ response, isExactOptionalPropertyTypes, angularO
|
|
|
3697
3933
|
if (queryParams) if (isVue) value += "\n params: {...unref(params), ...options?.params},";
|
|
3698
3934
|
else if (isAngular && angularParamsRef) value += `\n params: ${angularParamsRef},`;
|
|
3699
3935
|
else if (isAngular && paramsSerializer) {
|
|
3700
|
-
const callExpr =
|
|
3936
|
+
const callExpr = buildAngularParamsFilterExpression({
|
|
3937
|
+
paramsExpression: "{...params, ...options?.params}",
|
|
3938
|
+
requiredNullableParamKeys: requiredNullableQueryParamKeys,
|
|
3939
|
+
preserveRequiredNullables: true,
|
|
3940
|
+
nonPrimitiveKeys: angularPassthroughQueryParamKeys,
|
|
3941
|
+
paramsFilter,
|
|
3942
|
+
useSharedHelper: true
|
|
3943
|
+
});
|
|
3701
3944
|
value += `\n params: ${paramsSerializer.name}(${callExpr}),`;
|
|
3702
|
-
} else if (isAngular)
|
|
3703
|
-
|
|
3945
|
+
} else if (isAngular) {
|
|
3946
|
+
const callExpr = buildAngularParamsFilterExpression({
|
|
3947
|
+
paramsExpression: "{...params, ...options?.params}",
|
|
3948
|
+
requiredNullableParamKeys: requiredNullableQueryParamKeys,
|
|
3949
|
+
nonPrimitiveKeys: angularPassthroughQueryParamKeys,
|
|
3950
|
+
paramsFilter,
|
|
3951
|
+
useSharedHelper: true
|
|
3952
|
+
});
|
|
3953
|
+
value += `\n params: ${callExpr},`;
|
|
3954
|
+
} else value += "\n params: {...params, ...options?.params},";
|
|
3704
3955
|
if (headers) value += "\n headers: {...headers, ...options?.headers},";
|
|
3705
3956
|
}
|
|
3706
3957
|
if (!isAngular && queryParams && (paramsSerializer || paramsSerializerOptions?.qs)) {
|
|
@@ -3709,13 +3960,14 @@ function generateAxiosOptions({ response, isExactOptionalPropertyTypes, angularO
|
|
|
3709
3960
|
}
|
|
3710
3961
|
return value;
|
|
3711
3962
|
}
|
|
3712
|
-
function generateOptions({ route, body, angularObserve, angularParamsRef, headers, queryParams, response, verb, requestOptions, isFormData, isFormUrlEncoded, isAngular, isExactOptionalPropertyTypes, hasSignal, hasSignalParam, isVue, paramsSerializer, paramsSerializerOptions }) {
|
|
3713
|
-
const
|
|
3963
|
+
function generateOptions({ route, body, angularObserve, angularParamsRef, headers, queryParams, response, verb, requestOptions, isFormData, isFormUrlEncoded, isAngular, isExactOptionalPropertyTypes, hasSignal, hasSignalParam, isVue, paramsSerializer, paramsSerializerOptions, paramsFilter }) {
|
|
3964
|
+
const bodyIdentifier = getIsBodyVerb(verb) ? generateBodyOptions(body, isFormData, isFormUrlEncoded) : void 0;
|
|
3714
3965
|
const axiosOptions = generateAxiosOptions({
|
|
3715
3966
|
response,
|
|
3716
3967
|
angularObserve,
|
|
3717
3968
|
angularParamsRef,
|
|
3718
3969
|
requiredNullableQueryParamKeys: queryParams?.requiredNullableKeys,
|
|
3970
|
+
nonPrimitiveQueryParamKeys: queryParams?.nonPrimitiveKeys,
|
|
3719
3971
|
queryParams: queryParams?.schema,
|
|
3720
3972
|
headers: headers?.schema,
|
|
3721
3973
|
requestOptions,
|
|
@@ -3725,17 +3977,18 @@ function generateOptions({ route, body, angularObserve, angularParamsRef, header
|
|
|
3725
3977
|
isVue: isVue ?? false,
|
|
3726
3978
|
isAngular: isAngular ?? false,
|
|
3727
3979
|
paramsSerializer,
|
|
3728
|
-
paramsSerializerOptions
|
|
3980
|
+
paramsSerializerOptions,
|
|
3981
|
+
paramsFilter
|
|
3729
3982
|
});
|
|
3730
3983
|
const trimmedAxiosOptions = axiosOptions.trim();
|
|
3731
3984
|
const isRawOptionsArgument = trimmedAxiosOptions === "options" || trimmedAxiosOptions.startsWith("(") && trimmedAxiosOptions.endsWith(")") || trimmedAxiosOptions.startsWith("{") && trimmedAxiosOptions.endsWith("}");
|
|
3732
3985
|
const optionsArgument = axiosOptions ? isRawOptionsArgument ? axiosOptions : `{${axiosOptions}}` : "";
|
|
3733
3986
|
if (verb === Verbs.DELETE) {
|
|
3734
|
-
if (!
|
|
3987
|
+
if (!bodyIdentifier) return `\n \`${route}\`${optionsArgument ? `,${optionsArgument}` : ""}\n `;
|
|
3735
3988
|
const deleteBodyOptions = isRawOptionsArgument ? `...${optionsArgument}` : axiosOptions;
|
|
3736
|
-
return `\n \`${route}\`,{${isAngular ? "body" : "data"}
|
|
3989
|
+
return `\n \`${route}\`,{${`${isAngular ? "body" : "data"}: ${bodyIdentifier}`}${axiosOptions ? `,${deleteBodyOptions}` : ""}}\n `;
|
|
3737
3990
|
}
|
|
3738
|
-
const bodyOrOptions = getIsBodyVerb(verb) ?
|
|
3991
|
+
const bodyOrOptions = getIsBodyVerb(verb) ? `\n ${bodyIdentifier ?? "undefined"},` : "";
|
|
3739
3992
|
return `\n \`${route}\`${bodyOrOptions || optionsArgument ? "," : ""}${bodyOrOptions}${optionsArgument}\n `;
|
|
3740
3993
|
}
|
|
3741
3994
|
function generateBodyMutatorConfig(body, isFormData, isFormUrlEncoded) {
|
|
@@ -3744,18 +3997,26 @@ function generateBodyMutatorConfig(body, isFormData, isFormUrlEncoded) {
|
|
|
3744
3997
|
if (body.implementation) return `,\n data: ${body.implementation}`;
|
|
3745
3998
|
return "";
|
|
3746
3999
|
}
|
|
3747
|
-
function generateQueryParamsAxiosConfig(response, isVue, isAngular, requiredNullableQueryParamKeys, queryParams) {
|
|
4000
|
+
function generateQueryParamsAxiosConfig(response, isVue, isAngular, requiredNullableQueryParamKeys, queryParams, paramsFilter) {
|
|
3748
4001
|
if (!queryParams && !response.isBlob) return "";
|
|
3749
4002
|
let value = "";
|
|
3750
4003
|
if (queryParams) if (isVue) value += ",\n params: unref(params)";
|
|
3751
|
-
else if (isAngular)
|
|
3752
|
-
|
|
4004
|
+
else if (isAngular) {
|
|
4005
|
+
const paramsExpr = buildAngularParamsFilterExpression({
|
|
4006
|
+
paramsExpression: "params ?? {}",
|
|
4007
|
+
requiredNullableParamKeys: requiredNullableQueryParamKeys,
|
|
4008
|
+
nonPrimitiveKeys: queryParams.nonPrimitiveKeys,
|
|
4009
|
+
paramsFilter,
|
|
4010
|
+
useSharedHelper: false
|
|
4011
|
+
});
|
|
4012
|
+
value += `,\n params: ${paramsExpr}`;
|
|
4013
|
+
} else value += ",\n params";
|
|
3753
4014
|
if (response.isBlob) value += `,\n responseType: 'blob'`;
|
|
3754
4015
|
return value;
|
|
3755
4016
|
}
|
|
3756
|
-
function generateMutatorConfig({ route, body, headers, queryParams, response, verb, isFormData, isFormUrlEncoded, hasSignal, hasSignalParam = false, isExactOptionalPropertyTypes, isVue, isAngular }) {
|
|
4017
|
+
function generateMutatorConfig({ route, body, headers, queryParams, response, verb, isFormData, isFormUrlEncoded, hasSignal, hasSignalParam = false, isExactOptionalPropertyTypes, isVue, isAngular, paramsFilter }) {
|
|
3757
4018
|
const bodyOptions = getIsBodyVerb(verb) ? generateBodyMutatorConfig(body, isFormData, isFormUrlEncoded) : "";
|
|
3758
|
-
const queryParamsOptions = generateQueryParamsAxiosConfig(response, isVue ?? false, isAngular ?? false, queryParams?.requiredNullableKeys, queryParams);
|
|
4019
|
+
const queryParamsOptions = generateQueryParamsAxiosConfig(response, isVue ?? false, isAngular ?? false, queryParams?.requiredNullableKeys, queryParams, paramsFilter);
|
|
3759
4020
|
const ignoreContentTypes = isAngular ? ["multipart/form-data"] : [];
|
|
3760
4021
|
const headerOptions = body.contentType && !ignoreContentTypes.includes(body.contentType) ? `,\n headers: {'Content-Type': '${body.contentType}', ${headers ? "...headers" : ""}}` : headers ? ",\n headers" : "";
|
|
3761
4022
|
const signalVar = hasSignalParam ? "querySignal" : "signal";
|
|
@@ -4068,6 +4329,13 @@ async function buildVerbOption({ verb, output, operation, route, pathRoute, verb
|
|
|
4068
4329
|
workspace: context.workspace,
|
|
4069
4330
|
tsconfig: context.output.tsconfig
|
|
4070
4331
|
}) : void 0,
|
|
4332
|
+
paramsFilter: isString(override.paramsFilter) || isObject(override.paramsFilter) ? await generateMutator({
|
|
4333
|
+
output: output.target,
|
|
4334
|
+
name: "paramsFilter",
|
|
4335
|
+
mutator: override.paramsFilter,
|
|
4336
|
+
workspace: context.workspace,
|
|
4337
|
+
tsconfig: context.output.tsconfig
|
|
4338
|
+
}) : void 0,
|
|
4071
4339
|
fetchReviver: isString(override.fetch.jsonReviver) || isObject(override.fetch.jsonReviver) ? await generateMutator({
|
|
4072
4340
|
output: output.target,
|
|
4073
4341
|
name: "fetchReviver",
|
|
@@ -4232,19 +4500,12 @@ function splitSchemasByType(schemas) {
|
|
|
4232
4500
|
};
|
|
4233
4501
|
}
|
|
4234
4502
|
/**
|
|
4235
|
-
* Get the import extension from a file extension.
|
|
4236
|
-
* Removes `.ts` suffix since TypeScript doesn't need it in imports.
|
|
4237
|
-
*/
|
|
4238
|
-
function getImportExtension(fileExtension) {
|
|
4239
|
-
return fileExtension.replace(/\.ts$/, "") || "";
|
|
4240
|
-
}
|
|
4241
|
-
/**
|
|
4242
4503
|
* Fix cross-directory imports when schemas reference other schemas in a different directory.
|
|
4243
4504
|
* Updates import paths to use correct relative paths between directories.
|
|
4244
4505
|
*/
|
|
4245
|
-
function fixSchemaImports(schemas, targetSchemaNames, fromPath, toPath, namingConvention, fileExtension) {
|
|
4506
|
+
function fixSchemaImports(schemas, targetSchemaNames, fromPath, toPath, namingConvention, fileExtension, tsconfig) {
|
|
4246
4507
|
const relativePath = relativeSafe(fromPath, toPath);
|
|
4247
|
-
const importExtension = getImportExtension(fileExtension);
|
|
4508
|
+
const importExtension = getImportExtension(fileExtension, tsconfig);
|
|
4248
4509
|
for (const schema of schemas) schema.imports = schema.imports.map((imp) => {
|
|
4249
4510
|
if (targetSchemaNames.has(imp.name)) {
|
|
4250
4511
|
const fileName = conventionName(imp.name, namingConvention);
|
|
@@ -4259,14 +4520,14 @@ function fixSchemaImports(schemas, targetSchemaNames, fromPath, toPath, namingCo
|
|
|
4259
4520
|
/**
|
|
4260
4521
|
* Fix imports in operation schemas that reference regular schemas.
|
|
4261
4522
|
*/
|
|
4262
|
-
function fixCrossDirectoryImports(operationSchemas, regularSchemaNames, schemaPath, operationSchemaPath, namingConvention, fileExtension) {
|
|
4263
|
-
fixSchemaImports(operationSchemas, regularSchemaNames, operationSchemaPath, schemaPath, namingConvention, fileExtension);
|
|
4523
|
+
function fixCrossDirectoryImports(operationSchemas, regularSchemaNames, schemaPath, operationSchemaPath, namingConvention, fileExtension, tsconfig) {
|
|
4524
|
+
fixSchemaImports(operationSchemas, regularSchemaNames, operationSchemaPath, schemaPath, namingConvention, fileExtension, tsconfig);
|
|
4264
4525
|
}
|
|
4265
4526
|
/**
|
|
4266
4527
|
* Fix imports in regular schemas that reference operation schemas.
|
|
4267
4528
|
*/
|
|
4268
|
-
function fixRegularSchemaImports(regularSchemas, operationSchemaNames, schemaPath, operationSchemaPath, namingConvention, fileExtension) {
|
|
4269
|
-
fixSchemaImports(regularSchemas, operationSchemaNames, schemaPath, operationSchemaPath, namingConvention, fileExtension);
|
|
4529
|
+
function fixRegularSchemaImports(regularSchemas, operationSchemaNames, schemaPath, operationSchemaPath, namingConvention, fileExtension, tsconfig) {
|
|
4530
|
+
fixSchemaImports(regularSchemas, operationSchemaNames, schemaPath, operationSchemaPath, namingConvention, fileExtension, tsconfig);
|
|
4270
4531
|
}
|
|
4271
4532
|
function getSchemaKey(schemaPath, schemaName, namingConvention, fileExtension) {
|
|
4272
4533
|
return getPath(schemaPath, conventionName(schemaName, namingConvention), fileExtension).toLowerCase().replaceAll("\\", "/");
|
|
@@ -4290,14 +4551,16 @@ function getCanonicalMap(schemaGroups, schemaPath, namingConvention, fileExtensi
|
|
|
4290
4551
|
canonicalNameMap
|
|
4291
4552
|
};
|
|
4292
4553
|
}
|
|
4293
|
-
function normalizeCanonicalImportPaths(schemas, canonicalPathMap, canonicalNameMap, schemaPath, namingConvention, fileExtension) {
|
|
4554
|
+
function normalizeCanonicalImportPaths(schemas, canonicalPathMap, canonicalNameMap, schemaPath, namingConvention, fileExtension, tsconfig) {
|
|
4555
|
+
const importExtension = getImportExtension(fileExtension, tsconfig);
|
|
4294
4556
|
for (const schema of schemas) schema.imports = schema.imports.map((imp) => {
|
|
4295
4557
|
const canonicalByName = canonicalNameMap.get(imp.name);
|
|
4296
4558
|
const resolvedImportKey = resolveImportKey(schemaPath, imp.importPath ?? `./${conventionName(imp.name, namingConvention)}`, fileExtension);
|
|
4297
4559
|
const canonicalByPath = canonicalPathMap.get(resolvedImportKey);
|
|
4298
4560
|
const canonical = canonicalByName ?? canonicalByPath;
|
|
4299
4561
|
if (!canonical?.importPath) return imp;
|
|
4300
|
-
const
|
|
4562
|
+
const relative = relativeSafe(schemaPath, canonical.importPath.replaceAll("\\", "/"));
|
|
4563
|
+
const importPath = `${relative.endsWith(fileExtension) ? relative.slice(0, -fileExtension.length) : relative.replace(/\.ts$/, "")}${importExtension}`;
|
|
4301
4564
|
return {
|
|
4302
4565
|
...imp,
|
|
4303
4566
|
importPath
|
|
@@ -4320,14 +4583,12 @@ function mergeSchemaGroup(schemas) {
|
|
|
4320
4583
|
function resolveImportKey(schemaPath, importPath, fileExtension) {
|
|
4321
4584
|
return join(schemaPath, `${importPath}${fileExtension}`).toLowerCase().replaceAll("\\", "/");
|
|
4322
4585
|
}
|
|
4323
|
-
function
|
|
4324
|
-
return path.endsWith(".ts") ? path.slice(0, -3) : path;
|
|
4325
|
-
}
|
|
4326
|
-
function getSchema({ schema: { imports, model }, header, namingConvention = NamingConvention.CAMEL_CASE }) {
|
|
4586
|
+
function getSchema({ schema: { imports, model }, header, namingConvention = NamingConvention.CAMEL_CASE, importExtension }) {
|
|
4327
4587
|
let file = header;
|
|
4328
4588
|
file += generateImports({
|
|
4329
4589
|
imports: imports.filter((imp) => !model.includes(`type ${imp.alias ?? imp.name} =`) && !model.includes(`interface ${imp.alias ?? imp.name} {`)),
|
|
4330
|
-
namingConvention
|
|
4590
|
+
namingConvention,
|
|
4591
|
+
importExtension
|
|
4331
4592
|
});
|
|
4332
4593
|
file += imports.length > 0 ? "\n\n" : "\n";
|
|
4333
4594
|
file += model;
|
|
@@ -4344,23 +4605,24 @@ function writeModelsInline(array) {
|
|
|
4344
4605
|
for (const { model } of array) acc = writeModelInline(acc, model);
|
|
4345
4606
|
return acc;
|
|
4346
4607
|
}
|
|
4347
|
-
async function writeSchema({ path, schema, target, namingConvention, fileExtension, header }) {
|
|
4608
|
+
async function writeSchema({ path, schema, target, namingConvention, fileExtension, header, tsconfig }) {
|
|
4348
4609
|
const name = conventionName(schema.name, namingConvention);
|
|
4349
4610
|
try {
|
|
4350
4611
|
await writeGeneratedFile(getPath(path, name, fileExtension), getSchema({
|
|
4351
4612
|
schema,
|
|
4352
4613
|
target,
|
|
4353
4614
|
header,
|
|
4354
|
-
namingConvention
|
|
4615
|
+
namingConvention,
|
|
4616
|
+
importExtension: getImportExtension(fileExtension, tsconfig)
|
|
4355
4617
|
}));
|
|
4356
4618
|
} catch (error) {
|
|
4357
4619
|
throw new Error(`Oups... 🍻. An Error occurred while writing schema ${name} => ${String(error)}`, { cause: error });
|
|
4358
4620
|
}
|
|
4359
4621
|
}
|
|
4360
|
-
async function writeSchemas({ schemaPath, schemas, target, namingConvention, fileExtension, header, indexFiles }) {
|
|
4622
|
+
async function writeSchemas({ schemaPath, schemas, target, namingConvention, fileExtension, header, indexFiles, tsconfig }) {
|
|
4361
4623
|
const schemaGroups = getSchemaGroups(schemaPath, schemas, namingConvention, fileExtension);
|
|
4362
4624
|
const { canonicalPathMap, canonicalNameMap } = getCanonicalMap(schemaGroups, schemaPath, namingConvention, fileExtension);
|
|
4363
|
-
normalizeCanonicalImportPaths(schemas, canonicalPathMap, canonicalNameMap, schemaPath, namingConvention, fileExtension);
|
|
4625
|
+
normalizeCanonicalImportPaths(schemas, canonicalPathMap, canonicalNameMap, schemaPath, namingConvention, fileExtension, tsconfig);
|
|
4364
4626
|
for (const groupSchemas of Object.values(schemaGroups)) {
|
|
4365
4627
|
if (groupSchemas.length === 1) {
|
|
4366
4628
|
await writeSchema({
|
|
@@ -4369,7 +4631,8 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
|
|
|
4369
4631
|
target,
|
|
4370
4632
|
namingConvention,
|
|
4371
4633
|
fileExtension,
|
|
4372
|
-
header
|
|
4634
|
+
header,
|
|
4635
|
+
tsconfig
|
|
4373
4636
|
});
|
|
4374
4637
|
continue;
|
|
4375
4638
|
}
|
|
@@ -4379,16 +4642,17 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
|
|
|
4379
4642
|
target,
|
|
4380
4643
|
namingConvention,
|
|
4381
4644
|
fileExtension,
|
|
4382
|
-
header
|
|
4645
|
+
header,
|
|
4646
|
+
tsconfig
|
|
4383
4647
|
});
|
|
4384
4648
|
}
|
|
4385
4649
|
if (indexFiles) {
|
|
4386
4650
|
const schemaFilePath = nodePath.join(schemaPath, `index.ts`);
|
|
4387
4651
|
await fs$1.ensureFile(schemaFilePath);
|
|
4388
|
-
const ext =
|
|
4652
|
+
const ext = getImportExtension(fileExtension, tsconfig);
|
|
4389
4653
|
const conventionNamesSet = new Set(Object.values(schemaGroups).map((group) => conventionName(group[0].name, namingConvention)));
|
|
4390
4654
|
try {
|
|
4391
|
-
await writeGeneratedFile(schemaFilePath, `${header}\n${[...conventionNamesSet].map((schemaName) => `export * from './${schemaName}${ext}';`).toSorted((a, b) => a.localeCompare(b)).join("\n")}\n`);
|
|
4655
|
+
await writeGeneratedFile(schemaFilePath, `${header}\n${[...conventionNamesSet].map((schemaName) => `export * from './${schemaName}${ext}';`).toSorted((a, b) => a.localeCompare(b, "en", { numeric: true })).join("\n")}\n`);
|
|
4392
4656
|
} catch (error) {
|
|
4393
4657
|
throw new Error(`Oups... 🍻. An Error occurred while writing schema index file ${schemaFilePath} => ${String(error)}`, { cause: error });
|
|
4394
4658
|
}
|
|
@@ -4409,7 +4673,7 @@ function generateImportsForBuilder(output, imports, relativeSchemasPath) {
|
|
|
4409
4673
|
else {
|
|
4410
4674
|
const importsByDependency = /* @__PURE__ */ new Map();
|
|
4411
4675
|
for (const schemaImport of imports.filter((i) => !i.importPath)) {
|
|
4412
|
-
const dependency = joinSafe(relativeSchemasPath, `${conventionName(isZodSchemaOutput ? schemaImport.name : schemaImport.schemaName ?? schemaImport.name, output.namingConvention)}${isZodSchemaOutput ? ".zod" : ""}${output.fileExtension.
|
|
4676
|
+
const dependency = joinSafe(relativeSchemasPath, `${conventionName(isZodSchemaOutput ? schemaImport.name : schemaImport.schemaName ?? schemaImport.name, output.namingConvention)}${isZodSchemaOutput ? ".zod" : ""}${getImportExtension(output.fileExtension, output.tsconfig)}`);
|
|
4413
4677
|
if (!importsByDependency.has(dependency)) importsByDependency.set(dependency, []);
|
|
4414
4678
|
importsByDependency.get(dependency)?.push(schemaImport);
|
|
4415
4679
|
}
|
|
@@ -4451,6 +4715,7 @@ function generateTarget(builder, options) {
|
|
|
4451
4715
|
formData: [],
|
|
4452
4716
|
formUrlEncoded: [],
|
|
4453
4717
|
paramsSerializer: [],
|
|
4718
|
+
paramsFilter: [],
|
|
4454
4719
|
fetchReviver: []
|
|
4455
4720
|
};
|
|
4456
4721
|
const operations = Object.values(builder.operations);
|
|
@@ -4466,6 +4731,7 @@ function generateTarget(builder, options) {
|
|
|
4466
4731
|
if (operation.formData) target.formData.push(operation.formData);
|
|
4467
4732
|
if (operation.formUrlEncoded) target.formUrlEncoded.push(operation.formUrlEncoded);
|
|
4468
4733
|
if (operation.paramsSerializer) target.paramsSerializer.push(operation.paramsSerializer);
|
|
4734
|
+
if (operation.paramsFilter) target.paramsFilter.push(operation.paramsFilter);
|
|
4469
4735
|
if (operation.clientMutators) target.clientMutators.push(...operation.clientMutators);
|
|
4470
4736
|
if (operation.fetchReviver) target.fetchReviver.push(operation.fetchReviver);
|
|
4471
4737
|
if (index === operations.length - 1) {
|
|
@@ -4548,7 +4814,7 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
|
|
|
4548
4814
|
backupFilename: conventionName(builder.info.title ?? "filename", output.namingConvention),
|
|
4549
4815
|
extension: output.fileExtension
|
|
4550
4816
|
});
|
|
4551
|
-
const { imports, importsMock, implementation, implementationMock, mutators, clientMutators, formData, formUrlEncoded, paramsSerializer, fetchReviver } = generateTarget(builder, output);
|
|
4817
|
+
const { imports, importsMock, implementation, implementationMock, mutators, clientMutators, formData, formUrlEncoded, paramsSerializer, paramsFilter, fetchReviver } = generateTarget(builder, output);
|
|
4552
4818
|
let data = header;
|
|
4553
4819
|
const schemasPath = output.schemas ? getRelativeImportPath(path, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : void 0;
|
|
4554
4820
|
const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
|
|
@@ -4596,6 +4862,7 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
|
|
|
4596
4862
|
if (formData) data += generateMutatorImports({ mutators: formData });
|
|
4597
4863
|
if (formUrlEncoded) data += generateMutatorImports({ mutators: formUrlEncoded });
|
|
4598
4864
|
if (paramsSerializer) data += generateMutatorImports({ mutators: paramsSerializer });
|
|
4865
|
+
if (paramsFilter) data += generateMutatorImports({ mutators: paramsFilter });
|
|
4599
4866
|
if (fetchReviver) data += generateMutatorImports({ mutators: fetchReviver });
|
|
4600
4867
|
if (implementation.includes("NonReadonly<")) {
|
|
4601
4868
|
data += getOrvalGeneratedTypes();
|
|
@@ -4626,7 +4893,7 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
4626
4893
|
backupFilename: conventionName(builder.info.title ?? "filename", output.namingConvention),
|
|
4627
4894
|
extension: output.fileExtension
|
|
4628
4895
|
});
|
|
4629
|
-
const { imports, implementation, implementationMock, importsMock, mutators, clientMutators, formData, formUrlEncoded, paramsSerializer, fetchReviver } = generateTarget(builder, output);
|
|
4896
|
+
const { imports, implementation, implementationMock, importsMock, mutators, clientMutators, formData, formUrlEncoded, paramsSerializer, paramsFilter, fetchReviver } = generateTarget(builder, output);
|
|
4630
4897
|
let implementationData = header;
|
|
4631
4898
|
let mockData = header;
|
|
4632
4899
|
const relativeSchemasPath = output.schemas ? getRelativeImportPath(targetPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas" + extension.replace(/\.ts$/, "");
|
|
@@ -4664,6 +4931,7 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
4664
4931
|
if (formData) implementationData += generateMutatorImports({ mutators: formData });
|
|
4665
4932
|
if (formUrlEncoded) implementationData += generateMutatorImports({ mutators: formUrlEncoded });
|
|
4666
4933
|
if (paramsSerializer) implementationData += generateMutatorImports({ mutators: paramsSerializer });
|
|
4934
|
+
if (paramsFilter) implementationData += generateMutatorImports({ mutators: paramsFilter });
|
|
4667
4935
|
if (fetchReviver) implementationData += generateMutatorImports({ mutators: fetchReviver });
|
|
4668
4936
|
if (implementation.includes("NonReadonly<")) {
|
|
4669
4937
|
implementationData += getOrvalGeneratedTypes();
|
|
@@ -4691,10 +4959,16 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
4691
4959
|
}
|
|
4692
4960
|
//#endregion
|
|
4693
4961
|
//#region src/writers/target-tags.ts
|
|
4962
|
+
/**
|
|
4963
|
+
* Ensures every operation has at least one tag by falling back to the
|
|
4964
|
+
* {@link DefaultTag} constant for untagged operations, so the tag-routing
|
|
4965
|
+
* logic in {@link generateTargetTags} always has a bucket to assign the
|
|
4966
|
+
* operation to.
|
|
4967
|
+
*/
|
|
4694
4968
|
function addDefaultTagIfEmpty(operation) {
|
|
4695
4969
|
return {
|
|
4696
4970
|
...operation,
|
|
4697
|
-
tags: operation.tags.length > 0 ? operation.tags : [
|
|
4971
|
+
tags: operation.tags.length > 0 ? operation.tags : [DefaultTag]
|
|
4698
4972
|
};
|
|
4699
4973
|
}
|
|
4700
4974
|
function generateTargetTags(currentAcc, operation) {
|
|
@@ -4708,6 +4982,7 @@ function generateTargetTags(currentAcc, operation) {
|
|
|
4708
4982
|
formData: operation.formData ? [operation.formData] : [],
|
|
4709
4983
|
formUrlEncoded: operation.formUrlEncoded ? [operation.formUrlEncoded] : [],
|
|
4710
4984
|
paramsSerializer: operation.paramsSerializer ? [operation.paramsSerializer] : [],
|
|
4985
|
+
paramsFilter: operation.paramsFilter ? [operation.paramsFilter] : [],
|
|
4711
4986
|
fetchReviver: operation.fetchReviver ? [operation.fetchReviver] : [],
|
|
4712
4987
|
implementation: operation.implementation,
|
|
4713
4988
|
implementationMock: {
|
|
@@ -4733,6 +5008,7 @@ function generateTargetTags(currentAcc, operation) {
|
|
|
4733
5008
|
formData: operation.formData ? [...currentOperation.formData ?? [], operation.formData] : currentOperation.formData,
|
|
4734
5009
|
formUrlEncoded: operation.formUrlEncoded ? [...currentOperation.formUrlEncoded ?? [], operation.formUrlEncoded] : currentOperation.formUrlEncoded,
|
|
4735
5010
|
paramsSerializer: operation.paramsSerializer ? [...currentOperation.paramsSerializer ?? [], operation.paramsSerializer] : currentOperation.paramsSerializer,
|
|
5011
|
+
paramsFilter: operation.paramsFilter ? [...currentOperation.paramsFilter ?? [], operation.paramsFilter] : currentOperation.paramsFilter,
|
|
4736
5012
|
fetchReviver: operation.fetchReviver ? [...currentOperation.fetchReviver ?? [], operation.fetchReviver] : currentOperation.fetchReviver
|
|
4737
5013
|
};
|
|
4738
5014
|
return currentAcc;
|
|
@@ -4774,6 +5050,7 @@ function generateTargetForTags(builder, options) {
|
|
|
4774
5050
|
output: options,
|
|
4775
5051
|
verbOptions: builder.verbOptions,
|
|
4776
5052
|
tag,
|
|
5053
|
+
isDefaultTagBucket: tag === "default" && Object.values(builder.operations).some((operation) => operation.tags.length === 0),
|
|
4777
5054
|
clientImplementation: target.implementation
|
|
4778
5055
|
});
|
|
4779
5056
|
transformed[tag] = {
|
|
@@ -4790,6 +5067,7 @@ function generateTargetForTags(builder, options) {
|
|
|
4790
5067
|
formData: target.formData,
|
|
4791
5068
|
formUrlEncoded: target.formUrlEncoded,
|
|
4792
5069
|
paramsSerializer: target.paramsSerializer,
|
|
5070
|
+
paramsFilter: target.paramsFilter,
|
|
4793
5071
|
fetchReviver: target.fetchReviver
|
|
4794
5072
|
};
|
|
4795
5073
|
}
|
|
@@ -4818,7 +5096,7 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
4818
5096
|
const tagEntries = Object.entries(target);
|
|
4819
5097
|
const generatedFilePathsArray = await Promise.all(tagEntries.map(async ([tag, target]) => {
|
|
4820
5098
|
try {
|
|
4821
|
-
const { imports, implementation, implementationMock, importsMock, mutators, clientMutators, formData, fetchReviver, formUrlEncoded, paramsSerializer } = target;
|
|
5099
|
+
const { imports, implementation, implementationMock, importsMock, mutators, clientMutators, formData, fetchReviver, formUrlEncoded, paramsSerializer, paramsFilter } = target;
|
|
4822
5100
|
let implementationData = header;
|
|
4823
5101
|
let mockData = header;
|
|
4824
5102
|
const importerPath = nodePath.join(dirname, tag, tag + extension);
|
|
@@ -4886,6 +5164,10 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
4886
5164
|
mutators: paramsSerializer,
|
|
4887
5165
|
oneMore: true
|
|
4888
5166
|
});
|
|
5167
|
+
if (paramsFilter) implementationData += generateMutatorImports({
|
|
5168
|
+
mutators: paramsFilter,
|
|
5169
|
+
oneMore: true
|
|
5170
|
+
});
|
|
4889
5171
|
if (fetchReviver) implementationData += generateMutatorImports({
|
|
4890
5172
|
mutators: fetchReviver,
|
|
4891
5173
|
oneMore: true
|
|
@@ -4934,7 +5216,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
4934
5216
|
const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
|
|
4935
5217
|
return (await Promise.all(Object.entries(target).map(async ([tag, target]) => {
|
|
4936
5218
|
try {
|
|
4937
|
-
const { imports, implementation, implementationMock, importsMock, mutators, clientMutators, formData, formUrlEncoded, fetchReviver, paramsSerializer } = target;
|
|
5219
|
+
const { imports, implementation, implementationMock, importsMock, mutators, clientMutators, formData, formUrlEncoded, fetchReviver, paramsSerializer, paramsFilter } = target;
|
|
4938
5220
|
let data = header;
|
|
4939
5221
|
const schemasPathRelative = output.schemas ? getRelativeImportPath(targetPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas" + extension.replace(/\.ts$/, "");
|
|
4940
5222
|
const normalizedImports = imports.filter((imp) => {
|
|
@@ -4982,6 +5264,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
4982
5264
|
if (formData) data += generateMutatorImports({ mutators: formData });
|
|
4983
5265
|
if (formUrlEncoded) data += generateMutatorImports({ mutators: formUrlEncoded });
|
|
4984
5266
|
if (paramsSerializer) data += generateMutatorImports({ mutators: paramsSerializer });
|
|
5267
|
+
if (paramsFilter) data += generateMutatorImports({ mutators: paramsFilter });
|
|
4985
5268
|
if (fetchReviver) data += generateMutatorImports({ mutators: fetchReviver });
|
|
4986
5269
|
data += "\n\n";
|
|
4987
5270
|
if (implementation.includes("NonReadonly<")) {
|
|
@@ -5006,6 +5289,6 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
5006
5289
|
}))).flat();
|
|
5007
5290
|
}
|
|
5008
5291
|
//#endregion
|
|
5009
|
-
export { BODY_TYPE_NAME, EnumGeneration, ErrorWithTag, FormDataArrayHandling, GetterPropType, LogLevels, NamingConvention, OutputClient, OutputHttpClient, OutputMockType, OutputMode, PropertySortOrder, RefComponentSuffix, SchemaType, SupportedFormatter, TEMPLATE_TAG_REGEX, URL_REGEX, VERBS_WITH_BODY, Verbs, addDependency, asyncReduce, camel, collectReferencedComponents, combineSchemas, compareVersions, conventionName, count, createDebugger, createLogger, createSuccessMessage, createTypeAliasIfNeeded, dedupeUnionType, dynamicImport, escape, escapeRegExp, filterByContentType, filteredVerbs, fixCrossDirectoryImports, fixRegularSchemaImports, generalJSTypes, generalJSTypesWithArray, generateAxiosOptions, generateBodyMutatorConfig, generateBodyOptions, generateComponentDefinition, generateDependencyImports, generateFormDataAndUrlEncodedFunction, generateImports, generateModelInline, generateModelsInline, generateMutator, generateMutatorConfig, generateMutatorImports, generateMutatorRequestOptions, generateOptions, generateParameterDefinition, generateQueryParamsAxiosConfig, generateSchemasDefinition, generateTarget, generateTargetForTags, generateVerbImports, generateVerbOptions, generateVerbsOptions, getAngularFilteredParamsCallExpression, getAngularFilteredParamsExpression, getAngularFilteredParamsHelperBody, getArray, getBaseUrlRuntimeImports, getBodiesByContentType, getBody, getCombinedEnumValue, getDefaultContentType, getEnum, getEnumDescriptions, getEnumImplementation, getEnumNames, getEnumUnionFromSchema, getExtension, getFileInfo, getFormDataFieldFileType, getFullRoute, getIsBodyVerb, getKey, getMockFileExtensionByTypeName, getNumberWord, getObject, getOperationId, getOrvalGeneratedTypes, getParameters, getParams, getParamsInPath, getPropertySafe, getProps, getQueryParams, getRefInfo, getResReqTypes, getResponse, getResponseTypeCategory, getRoute, getRouteAsArray, getScalar, getSuccessResponseType, getTypedResponse, getWarningCount, isBinaryContentType, isBoolean, isDirectory, isFunction, isModule, isNullish, isNumber, isNumeric, isObject, isReference, isSchema, isString, isStringLike, isSyntheticDefaultImportsAllow, isUrl, isVerb, isVerbose, jsDoc, jsStringEscape, kebab, keyValuePairsToJsDoc, log, logError, logVerbose, logWarning, mergeDeep, mismatchArgsMessage, pascal, removeFilesAndEmptyFolders, resetWarnings, resolveDiscriminators, resolveExampleRefs, resolveInstalledVersion, resolveInstalledVersions, resolveObject, resolveRef, resolveValue, sanitize, setVerbose, snake, sortByPriority, splitSchemasByType, startMessage, stringify, toObjectString, path_exports as upath, upper, writeModelInline, writeModelsInline, writeSchema, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode };
|
|
5292
|
+
export { BODY_TYPE_NAME, DefaultTag, EnumGeneration, ErrorWithTag, FormDataArrayHandling, GetterPropType, LogLevels, NAMED_COMPONENT_SECTIONS, NamingConvention, OutputClient, OutputHttpClient, OutputMockType, OutputMode, PropertySortOrder, RefComponentSuffix, SchemaType, SupportedFormatter, TEMPLATE_TAG_REGEX, URL_REGEX, VERBS_WITH_BODY, Verbs, addDependency, asyncReduce, buildAngularParamsFilterExpression, camel, collectReferencedComponents, combineSchemas, compareVersions, conventionName, count, createDebugger, createLogger, createSuccessMessage, createTypeAliasIfNeeded, dedupeUnionType, dynamicImport, escape, escapeRegExp, filterByContentType, filteredVerbs, fixCrossDirectoryImports, fixRegularSchemaImports, generalJSTypes, generalJSTypesWithArray, generateAxiosOptions, generateBodyMutatorConfig, generateBodyOptions, generateComponentDefinition, generateDependencyImports, generateFormDataAndUrlEncodedFunction, generateImports, generateModelInline, generateModelsInline, generateMutator, generateMutatorConfig, generateMutatorImports, generateMutatorRequestOptions, generateOptions, generateParameterDefinition, generateQueryParamsAxiosConfig, generateSchemasDefinition, generateTarget, generateTargetForTags, generateVerbImports, generateVerbOptions, generateVerbsOptions, getAngularFilteredParamsCallExpression, getAngularFilteredParamsExpression, getAngularFilteredParamsHelperBody, getArray, getBaseUrlRuntimeImports, getBodiesByContentType, getBody, getCombinedEnumValue, getDefaultContentType, getEnum, getEnumDescriptions, getEnumImplementation, getEnumNames, getEnumUnionFromSchema, getExtension, getFileInfo, getFormDataFieldFileType, getFullRoute, getImportExtension, getIsBodyVerb, getKey, getMockFileExtensionByTypeName, getNumberWord, getObject, getOperationId, getOrvalGeneratedTypes, getParameters, getParams, getParamsInPath, getPropertySafe, getProps, getQueryParams, getRefInfo, getResReqTypes, getResponse, getResponseTypeCategory, getRoute, getRouteAsArray, getScalar, getSuccessResponseType, getTypedResponse, getWarningCount, isBinaryContentType, isBoolean, isComponentRef, isDirectory, isFunction, isModule, isNullish, isNumber, isNumeric, isObject, isReference, isSchema, isString, isStringLike, isSyntheticDefaultImportsAllow, isUrl, isVerb, isVerbose, jsDoc, jsStringEscape, kebab, keyValuePairsToJsDoc, log, logError, logVerbose, logWarning, mergeDeep, mismatchArgsMessage, pascal, removeFilesAndEmptyFolders, resetWarnings, resolveDiscriminators, resolveExampleRefs, resolveInstalledVersion, resolveInstalledVersions, resolveObject, resolveRef, resolveValue, sanitize, setVerbose, snake, sortByPriority, splitSchemasByType, startMessage, stringify, toObjectString, path_exports as upath, upper, writeModelInline, writeModelsInline, writeSchema, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode };
|
|
5010
5293
|
|
|
5011
5294
|
//# sourceMappingURL=index.mjs.map
|