@ng-openapi/http-resource 0.1.3 → 0.2.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/index.cjs +710 -84
- package/index.d.ts +5 -2
- package/index.js +710 -84
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -4,6 +4,238 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
|
|
|
4
4
|
// src/lib/http-resource.generator.ts
|
|
5
5
|
import { Scope } from "ts-morph";
|
|
6
6
|
|
|
7
|
+
// ../../shared/src/errors.ts
|
|
8
|
+
var NG_OPENAPI_ERROR_BRAND = "__ngOpenApiError";
|
|
9
|
+
var ERROR_LINEAGE = /* @__PURE__ */ new WeakMap();
|
|
10
|
+
var FALLBACK_LINEAGE = Object.freeze([
|
|
11
|
+
"NgOpenApiError"
|
|
12
|
+
]);
|
|
13
|
+
function registerError(cls, lineage) {
|
|
14
|
+
ERROR_LINEAGE.set(cls, Object.freeze([
|
|
15
|
+
...lineage
|
|
16
|
+
]));
|
|
17
|
+
return cls;
|
|
18
|
+
}
|
|
19
|
+
__name(registerError, "registerError");
|
|
20
|
+
function inheritedLineage(cls) {
|
|
21
|
+
for (let current = cls; typeof current === "function"; current = Object.getPrototypeOf(current)) {
|
|
22
|
+
const lineage = ERROR_LINEAGE.get(current);
|
|
23
|
+
if (lineage) {
|
|
24
|
+
return lineage;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return FALLBACK_LINEAGE;
|
|
28
|
+
}
|
|
29
|
+
__name(inheritedLineage, "inheritedLineage");
|
|
30
|
+
var NgOpenApiError = class extends Error {
|
|
31
|
+
static {
|
|
32
|
+
__name(this, "NgOpenApiError");
|
|
33
|
+
}
|
|
34
|
+
/** The underlying error that caused this one, when there is one. */
|
|
35
|
+
cause;
|
|
36
|
+
constructor(message, cause) {
|
|
37
|
+
super(message);
|
|
38
|
+
const lineage = inheritedLineage(new.target);
|
|
39
|
+
this.name = lineage[0];
|
|
40
|
+
this.cause = cause;
|
|
41
|
+
Object.defineProperty(this, NG_OPENAPI_ERROR_BRAND, {
|
|
42
|
+
value: lineage,
|
|
43
|
+
enumerable: false,
|
|
44
|
+
writable: false,
|
|
45
|
+
configurable: false
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* `message` and `name` are non-enumerable on Error, so the default
|
|
50
|
+
* JSON.stringify dropped both — the least useful possible serialization for
|
|
51
|
+
* something that exists to be logged.
|
|
52
|
+
*
|
|
53
|
+
* The payload is spread rather than enumerated: `source`, `issues`,
|
|
54
|
+
* `operation`, `names` and `placeholders` are why these classes are typed
|
|
55
|
+
* in the first place, and listing fields by hand silently drops whichever
|
|
56
|
+
* ones a later subclass adds.
|
|
57
|
+
*/
|
|
58
|
+
toJSON() {
|
|
59
|
+
const cause = this.cause instanceof Error ? this.cause.message : this.cause;
|
|
60
|
+
return {
|
|
61
|
+
name: this.name,
|
|
62
|
+
message: this.message,
|
|
63
|
+
...cause === void 0 ? {} : {
|
|
64
|
+
cause
|
|
65
|
+
},
|
|
66
|
+
// Own enumerable properties: the brand is deliberately not one.
|
|
67
|
+
...Object.fromEntries(Object.entries(this).filter(([key]) => key !== "cause"))
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Recognizes branded errors from another bundled copy of this module, so
|
|
72
|
+
* `error instanceof SpecLoadError` works for a plugin-thrown error too.
|
|
73
|
+
* The prototype chain is checked first, so a caller's own subclass of these
|
|
74
|
+
* classes still matches even though it carries no lineage entry.
|
|
75
|
+
*
|
|
76
|
+
* Never throws and never runs foreign code: both reflective reads sit
|
|
77
|
+
* inside the try, because a Proxy traps `getPrototypeOf` just as readily as
|
|
78
|
+
* `getOwnPropertyDescriptor`.
|
|
79
|
+
*/
|
|
80
|
+
static [Symbol.hasInstance](value) {
|
|
81
|
+
if (typeof value !== "object" || value === null) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
if (Object.prototype.isPrototypeOf.call(this.prototype, value)) {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
const expected = ERROR_LINEAGE.get(this)?.[0];
|
|
89
|
+
if (expected === void 0) {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, NG_OPENAPI_ERROR_BRAND);
|
|
93
|
+
if (!descriptor || descriptor.enumerable || !("value" in descriptor)) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
return Array.isArray(descriptor.value) && descriptor.value.includes(expected);
|
|
97
|
+
} catch {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
registerError(NgOpenApiError, [
|
|
103
|
+
"NgOpenApiError"
|
|
104
|
+
]);
|
|
105
|
+
var SpecLoadError = class extends NgOpenApiError {
|
|
106
|
+
static {
|
|
107
|
+
__name(this, "SpecLoadError");
|
|
108
|
+
}
|
|
109
|
+
/** The file path or URL that failed to load. */
|
|
110
|
+
source;
|
|
111
|
+
constructor(message, source, cause) {
|
|
112
|
+
super(message, cause);
|
|
113
|
+
this.source = source;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
registerError(SpecLoadError, [
|
|
117
|
+
"SpecLoadError",
|
|
118
|
+
"NgOpenApiError"
|
|
119
|
+
]);
|
|
120
|
+
var SpecParseError = class extends NgOpenApiError {
|
|
121
|
+
static {
|
|
122
|
+
__name(this, "SpecParseError");
|
|
123
|
+
}
|
|
124
|
+
/** The file path or URL the content came from, when known. */
|
|
125
|
+
source;
|
|
126
|
+
constructor(message, source, cause) {
|
|
127
|
+
super(message, cause);
|
|
128
|
+
this.source = source;
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
registerError(SpecParseError, [
|
|
132
|
+
"SpecParseError",
|
|
133
|
+
"NgOpenApiError"
|
|
134
|
+
]);
|
|
135
|
+
function describeOperation(operation) {
|
|
136
|
+
const location = `(${operation.method}) ${operation.path}`;
|
|
137
|
+
return operation.operationId ? `${operation.operationId} (${location})` : location;
|
|
138
|
+
}
|
|
139
|
+
__name(describeOperation, "describeOperation");
|
|
140
|
+
function captureOperation(operation) {
|
|
141
|
+
return Object.freeze({
|
|
142
|
+
operationId: operation.operationId,
|
|
143
|
+
method: operation.method,
|
|
144
|
+
path: operation.path
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
__name(captureOperation, "captureOperation");
|
|
148
|
+
var InvalidIdentifierError = class extends NgOpenApiError {
|
|
149
|
+
static {
|
|
150
|
+
__name(this, "InvalidIdentifierError");
|
|
151
|
+
}
|
|
152
|
+
/** The rejected name, verbatim; absent when no name could be derived. */
|
|
153
|
+
identifier;
|
|
154
|
+
/** The operation whose name was being derived. */
|
|
155
|
+
operation;
|
|
156
|
+
constructor(message, operation, identifier) {
|
|
157
|
+
super(message);
|
|
158
|
+
this.operation = captureOperation(operation);
|
|
159
|
+
this.identifier = identifier;
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
registerError(InvalidIdentifierError, [
|
|
163
|
+
"InvalidIdentifierError",
|
|
164
|
+
"NgOpenApiError"
|
|
165
|
+
]);
|
|
166
|
+
var DuplicateGeneratedNameError = class extends NgOpenApiError {
|
|
167
|
+
static {
|
|
168
|
+
__name(this, "DuplicateGeneratedNameError");
|
|
169
|
+
}
|
|
170
|
+
/** The colliding generated names. */
|
|
171
|
+
names;
|
|
172
|
+
/** The operations that produced them, when known. */
|
|
173
|
+
operations;
|
|
174
|
+
constructor(message, names, operations = []) {
|
|
175
|
+
super(message);
|
|
176
|
+
this.names = Object.freeze([
|
|
177
|
+
...names
|
|
178
|
+
]);
|
|
179
|
+
this.operations = Object.freeze(operations.map(captureOperation));
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
registerError(DuplicateGeneratedNameError, [
|
|
183
|
+
"DuplicateGeneratedNameError",
|
|
184
|
+
"NgOpenApiError"
|
|
185
|
+
]);
|
|
186
|
+
var UnresolvedPathTemplateError = class extends NgOpenApiError {
|
|
187
|
+
static {
|
|
188
|
+
__name(this, "UnresolvedPathTemplateError");
|
|
189
|
+
}
|
|
190
|
+
/** The path as written in the spec. */
|
|
191
|
+
path;
|
|
192
|
+
/** Placeholder names with no declared parameter. */
|
|
193
|
+
placeholders;
|
|
194
|
+
constructor(message, path3, placeholders) {
|
|
195
|
+
super(message);
|
|
196
|
+
this.path = path3;
|
|
197
|
+
this.placeholders = Object.freeze([
|
|
198
|
+
...placeholders
|
|
199
|
+
]);
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
registerError(UnresolvedPathTemplateError, [
|
|
203
|
+
"UnresolvedPathTemplateError",
|
|
204
|
+
"NgOpenApiError"
|
|
205
|
+
]);
|
|
206
|
+
var ConfigValidationError = class extends NgOpenApiError {
|
|
207
|
+
static {
|
|
208
|
+
__name(this, "ConfigValidationError");
|
|
209
|
+
}
|
|
210
|
+
issues;
|
|
211
|
+
constructor(issues) {
|
|
212
|
+
super(`Invalid ng-openapi configuration:
|
|
213
|
+
${issues.map((issue) => ` - ${issue}`).join("\n")}`);
|
|
214
|
+
this.issues = Object.freeze([
|
|
215
|
+
...issues
|
|
216
|
+
]);
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
registerError(ConfigValidationError, [
|
|
220
|
+
"ConfigValidationError",
|
|
221
|
+
"NgOpenApiError"
|
|
222
|
+
]);
|
|
223
|
+
var ConfigLoadError = class extends NgOpenApiError {
|
|
224
|
+
static {
|
|
225
|
+
__name(this, "ConfigLoadError");
|
|
226
|
+
}
|
|
227
|
+
/** Path of the config file that failed to load. */
|
|
228
|
+
source;
|
|
229
|
+
constructor(message, source, cause) {
|
|
230
|
+
super(message, cause);
|
|
231
|
+
this.source = source;
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
registerError(ConfigLoadError, [
|
|
235
|
+
"ConfigLoadError",
|
|
236
|
+
"NgOpenApiError"
|
|
237
|
+
]);
|
|
238
|
+
|
|
7
239
|
// ../../../node_modules/js-yaml/dist/js-yaml.mjs
|
|
8
240
|
function isNothing(subject) {
|
|
9
241
|
return typeof subject === "undefined" || subject === null;
|
|
@@ -2707,19 +2939,75 @@ var safeLoadAll = renamed("safeLoadAll", "loadAll");
|
|
|
2707
2939
|
var safeDump = renamed("safeDump", "dump");
|
|
2708
2940
|
|
|
2709
2941
|
// ../../shared/src/utils/string.utils.ts
|
|
2942
|
+
var IDENTIFIER_SEPARATORS = /(?:_|[^\p{ID_Continue}$])+(.)?/gu;
|
|
2943
|
+
var INVALID_IDENTIFIER_START = /^[^\p{ID_Start}$_]/u;
|
|
2944
|
+
function toIdentifier(converted) {
|
|
2945
|
+
if (converted === "") {
|
|
2946
|
+
return "_";
|
|
2947
|
+
}
|
|
2948
|
+
return converted.replace(INVALID_IDENTIFIER_START, (char) => `_${char}`);
|
|
2949
|
+
}
|
|
2950
|
+
__name(toIdentifier, "toIdentifier");
|
|
2951
|
+
function isValidIdentifier(name) {
|
|
2952
|
+
return /^[\p{ID_Start}$_][\p{ID_Continue}$]*$/u.test(name);
|
|
2953
|
+
}
|
|
2954
|
+
__name(isValidIdentifier, "isValidIdentifier");
|
|
2710
2955
|
function camelCase(str2) {
|
|
2711
|
-
|
|
2956
|
+
const converted = str2.replace(IDENTIFIER_SEPARATORS, (_, char) => char ? char.toUpperCase() : "").replace(/^./u, (char) => char.toLowerCase());
|
|
2957
|
+
return toIdentifier(converted);
|
|
2712
2958
|
}
|
|
2713
2959
|
__name(camelCase, "camelCase");
|
|
2714
2960
|
function pascalCase(str2) {
|
|
2715
|
-
|
|
2961
|
+
const converted = str2.replace(IDENTIFIER_SEPARATORS, (_, char) => char ? char.toUpperCase() : "").replace(/^./u, (char) => char.toUpperCase());
|
|
2962
|
+
return toIdentifier(converted);
|
|
2716
2963
|
}
|
|
2717
2964
|
__name(pascalCase, "pascalCase");
|
|
2718
2965
|
function pascalCaseForEnums(str2) {
|
|
2719
|
-
|
|
2966
|
+
const converted = str2.replace(/[^a-zA-Z0-9]/g, "_").replace(/(?:^|_)([a-z])/g, (_, char) => char.toUpperCase()).replace(/^([0-9])/, "_$1");
|
|
2967
|
+
return converted === "" ? "_" : converted;
|
|
2720
2968
|
}
|
|
2721
2969
|
__name(pascalCaseForEnums, "pascalCaseForEnums");
|
|
2722
2970
|
|
|
2971
|
+
// ../../shared/src/utils/content-types.constants.ts
|
|
2972
|
+
var CONTENT_TYPES = {
|
|
2973
|
+
MULTIPART: "multipart/form-data",
|
|
2974
|
+
FORM_URLENCODED: "application/x-www-form-urlencoded",
|
|
2975
|
+
JSON: "application/json"
|
|
2976
|
+
};
|
|
2977
|
+
|
|
2978
|
+
// ../../shared/src/emit/literal.emit.ts
|
|
2979
|
+
function quoteLiteral(value) {
|
|
2980
|
+
return `'${escapeSingleQuoted(value)}'`;
|
|
2981
|
+
}
|
|
2982
|
+
__name(quoteLiteral, "quoteLiteral");
|
|
2983
|
+
function escapeSingleQuoted(value) {
|
|
2984
|
+
return value.replace(/[\\']/g, (char) => `\\${char}`).replace(/\r/g, "\\r").replace(/\n/g, "\\n");
|
|
2985
|
+
}
|
|
2986
|
+
__name(escapeSingleQuoted, "escapeSingleQuoted");
|
|
2987
|
+
function escapeTemplateLiteral(value) {
|
|
2988
|
+
return value.replace(/[\\`]/g, (char) => `\\${char}`).replace(/\$\{/g, "\\${").replace(/\r/g, "\\r");
|
|
2989
|
+
}
|
|
2990
|
+
__name(escapeTemplateLiteral, "escapeTemplateLiteral");
|
|
2991
|
+
function emitObjectKey(name, quoteStyle = "double") {
|
|
2992
|
+
const quoted = quoteStyle === "single" ? quoteLiteral(name) : `"${escapeDoubleQuoted(name)}"`;
|
|
2993
|
+
return name === "__proto__" ? `[${quoted}]` : quoted;
|
|
2994
|
+
}
|
|
2995
|
+
__name(emitObjectKey, "emitObjectKey");
|
|
2996
|
+
function escapeDoubleQuoted(value) {
|
|
2997
|
+
return value.replace(/[\\"]/g, (char) => `\\${char}`).replace(/\r/g, "\\r").replace(/\n/g, "\\n");
|
|
2998
|
+
}
|
|
2999
|
+
__name(escapeDoubleQuoted, "escapeDoubleQuoted");
|
|
3000
|
+
function escapeJsDoc(text) {
|
|
3001
|
+
return text.replace(/\*\//g, "*\\/");
|
|
3002
|
+
}
|
|
3003
|
+
__name(escapeJsDoc, "escapeJsDoc");
|
|
3004
|
+
function emitDocs(description) {
|
|
3005
|
+
return typeof description === "string" && description ? [
|
|
3006
|
+
escapeJsDoc(description)
|
|
3007
|
+
] : void 0;
|
|
3008
|
+
}
|
|
3009
|
+
__name(emitDocs, "emitDocs");
|
|
3010
|
+
|
|
2723
3011
|
// ../../shared/src/utils/functions/class-names.ts
|
|
2724
3012
|
function decorate(base, defaultSuffix, naming) {
|
|
2725
3013
|
return `${naming?.prefix ?? ""}${base}${naming?.suffix ?? defaultSuffix}`;
|
|
@@ -2762,7 +3050,7 @@ function getTypeScriptType(schemaOrType, config, formatOrNullable, isNullable, c
|
|
|
2762
3050
|
switch (schema2.type) {
|
|
2763
3051
|
case "string":
|
|
2764
3052
|
if (schema2.enum) {
|
|
2765
|
-
return schema2.enum.map((value) => typeof value === "string" ? `'${
|
|
3053
|
+
return schema2.enum.map((value) => typeof value === "string" ? `'${escapeSingleQuoted(value)}'` : String(value)).join(" | ");
|
|
2766
3054
|
}
|
|
2767
3055
|
if (schema2.format === "date" || schema2.format === "date-time") {
|
|
2768
3056
|
const dateType = config.options.dateType === "Date" ? "Date" : "string";
|
|
@@ -2798,10 +3086,6 @@ function nullableType(type2, isNullable) {
|
|
|
2798
3086
|
return type2 + (isNullable ? " | null" : "");
|
|
2799
3087
|
}
|
|
2800
3088
|
__name(nullableType, "nullableType");
|
|
2801
|
-
function escapeString2(str2) {
|
|
2802
|
-
return str2.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
2803
|
-
}
|
|
2804
|
-
__name(escapeString2, "escapeString");
|
|
2805
3089
|
|
|
2806
3090
|
// ../../shared/src/utils/functions/extract-swagger-response-type.ts
|
|
2807
3091
|
function getResponseTypeFromResponse(response, responseTypeMapping) {
|
|
@@ -2950,7 +3234,7 @@ __name(getResponseType, "getResponseType");
|
|
|
2950
3234
|
|
|
2951
3235
|
// ../../shared/src/emit/headers.emit.ts
|
|
2952
3236
|
function emitDefaultHeadersMerge(optionsExpression, customHeaders) {
|
|
2953
|
-
const defaultsLiteral = Object.entries(customHeaders).map(([key, value]) =>
|
|
3237
|
+
const defaultsLiteral = Object.entries(customHeaders).map(([key, value]) => `${emitObjectKey(key, "single")}: ${quoteLiteral(value)}`).join(", ");
|
|
2954
3238
|
return `
|
|
2955
3239
|
// Add default headers if not already present
|
|
2956
3240
|
let headers = ${optionsExpression}?.headers;
|
|
@@ -2962,12 +3246,238 @@ ${emitDefaultHeaderGuards(customHeaders)}
|
|
|
2962
3246
|
}
|
|
2963
3247
|
__name(emitDefaultHeadersMerge, "emitDefaultHeadersMerge");
|
|
2964
3248
|
function emitDefaultHeaderGuards(customHeaders) {
|
|
2965
|
-
return Object.entries(customHeaders).map(([key, value]) =>
|
|
2966
|
-
|
|
2967
|
-
|
|
3249
|
+
return Object.entries(customHeaders).map(([key, value]) => {
|
|
3250
|
+
const name = quoteLiteral(key);
|
|
3251
|
+
return `if (!headers.has(${name})) {
|
|
3252
|
+
headers = headers.set(${name}, ${quoteLiteral(value)});
|
|
3253
|
+
}`;
|
|
3254
|
+
}).join("\n");
|
|
2968
3255
|
}
|
|
2969
3256
|
__name(emitDefaultHeaderGuards, "emitDefaultHeaderGuards");
|
|
2970
3257
|
|
|
3258
|
+
// ../../shared/src/utils/functions/get-request-body-type.ts
|
|
3259
|
+
function getRequestBodyType(requestBody, config) {
|
|
3260
|
+
const content = requestBody.content || {};
|
|
3261
|
+
const jsonContent = content[CONTENT_TYPES.JSON];
|
|
3262
|
+
if (jsonContent?.schema) {
|
|
3263
|
+
return getTypeScriptType(jsonContent.schema, config, jsonContent.schema.nullable);
|
|
3264
|
+
}
|
|
3265
|
+
return "any";
|
|
3266
|
+
}
|
|
3267
|
+
__name(getRequestBodyType, "getRequestBodyType");
|
|
3268
|
+
|
|
3269
|
+
// ../../shared/src/utils/functions/is-data-type-interface.ts
|
|
3270
|
+
function isDataTypeInterface(type2) {
|
|
3271
|
+
const invalidTypes = [
|
|
3272
|
+
"any",
|
|
3273
|
+
"File",
|
|
3274
|
+
"string",
|
|
3275
|
+
"number",
|
|
3276
|
+
"boolean",
|
|
3277
|
+
"object",
|
|
3278
|
+
"unknown",
|
|
3279
|
+
"[]",
|
|
3280
|
+
"Array"
|
|
3281
|
+
];
|
|
3282
|
+
return !invalidTypes.some((invalidType) => type2.includes(invalidType));
|
|
3283
|
+
}
|
|
3284
|
+
__name(isDataTypeInterface, "isDataTypeInterface");
|
|
3285
|
+
|
|
3286
|
+
// ../../shared/src/utils/functions/argument-names.ts
|
|
3287
|
+
var RESERVED_WORDS = [
|
|
3288
|
+
"arguments",
|
|
3289
|
+
"await",
|
|
3290
|
+
"break",
|
|
3291
|
+
"case",
|
|
3292
|
+
"catch",
|
|
3293
|
+
"class",
|
|
3294
|
+
"const",
|
|
3295
|
+
"continue",
|
|
3296
|
+
"debugger",
|
|
3297
|
+
"default",
|
|
3298
|
+
"delete",
|
|
3299
|
+
"do",
|
|
3300
|
+
"else",
|
|
3301
|
+
"enum",
|
|
3302
|
+
"eval",
|
|
3303
|
+
"export",
|
|
3304
|
+
"extends",
|
|
3305
|
+
"false",
|
|
3306
|
+
"finally",
|
|
3307
|
+
"for",
|
|
3308
|
+
"function",
|
|
3309
|
+
"if",
|
|
3310
|
+
"implements",
|
|
3311
|
+
"import",
|
|
3312
|
+
"in",
|
|
3313
|
+
"instanceof",
|
|
3314
|
+
"interface",
|
|
3315
|
+
"let",
|
|
3316
|
+
"new",
|
|
3317
|
+
"null",
|
|
3318
|
+
"package",
|
|
3319
|
+
"private",
|
|
3320
|
+
"protected",
|
|
3321
|
+
"public",
|
|
3322
|
+
"return",
|
|
3323
|
+
"static",
|
|
3324
|
+
"super",
|
|
3325
|
+
"switch",
|
|
3326
|
+
"this",
|
|
3327
|
+
"throw",
|
|
3328
|
+
"true",
|
|
3329
|
+
"try",
|
|
3330
|
+
"typeof",
|
|
3331
|
+
"var",
|
|
3332
|
+
"void",
|
|
3333
|
+
"while",
|
|
3334
|
+
"with",
|
|
3335
|
+
"yield"
|
|
3336
|
+
];
|
|
3337
|
+
var SERVICE_ARGUMENT_PROFILE = Object.freeze({
|
|
3338
|
+
reserved: Object.freeze([
|
|
3339
|
+
"observe",
|
|
3340
|
+
"options",
|
|
3341
|
+
"url",
|
|
3342
|
+
"params",
|
|
3343
|
+
"headers",
|
|
3344
|
+
"formData",
|
|
3345
|
+
"formBody"
|
|
3346
|
+
]),
|
|
3347
|
+
bindsRequestBody: true
|
|
3348
|
+
});
|
|
3349
|
+
var RESOURCE_ARGUMENT_PROFILE = Object.freeze({
|
|
3350
|
+
reserved: Object.freeze([
|
|
3351
|
+
"resourceOptions",
|
|
3352
|
+
"requestOptions",
|
|
3353
|
+
"params",
|
|
3354
|
+
"headers"
|
|
3355
|
+
]),
|
|
3356
|
+
bindsRequestBody: false
|
|
3357
|
+
});
|
|
3358
|
+
var REQUEST_BODY_KEY = /* @__PURE__ */ Symbol("requestBody");
|
|
3359
|
+
function resolveArgumentNames(operation, config, profile) {
|
|
3360
|
+
let byConfig = RESOLVED.get(operation);
|
|
3361
|
+
if (!byConfig) {
|
|
3362
|
+
byConfig = /* @__PURE__ */ new WeakMap();
|
|
3363
|
+
RESOLVED.set(operation, byConfig);
|
|
3364
|
+
}
|
|
3365
|
+
let byProfile = byConfig.get(config);
|
|
3366
|
+
if (!byProfile) {
|
|
3367
|
+
byProfile = /* @__PURE__ */ new WeakMap();
|
|
3368
|
+
byConfig.set(config, byProfile);
|
|
3369
|
+
}
|
|
3370
|
+
const cached = byProfile.get(profile);
|
|
3371
|
+
if (cached) {
|
|
3372
|
+
return cached;
|
|
3373
|
+
}
|
|
3374
|
+
const resolved = computeArgumentNames(operation, config, profile);
|
|
3375
|
+
byProfile.set(profile, resolved);
|
|
3376
|
+
return resolved;
|
|
3377
|
+
}
|
|
3378
|
+
__name(resolveArgumentNames, "resolveArgumentNames");
|
|
3379
|
+
var RESOLVED = /* @__PURE__ */ new WeakMap();
|
|
3380
|
+
function computeArgumentNames(operation, config, profile) {
|
|
3381
|
+
const entries = [
|
|
3382
|
+
...operation.pathParams.map((param) => ({
|
|
3383
|
+
key: param.name,
|
|
3384
|
+
base: camelCase(param.name)
|
|
3385
|
+
})),
|
|
3386
|
+
...operation.formDataFields.map((field) => ({
|
|
3387
|
+
key: field,
|
|
3388
|
+
base: camelCase(field)
|
|
3389
|
+
})),
|
|
3390
|
+
...operation.urlEncodedFields.map((field) => ({
|
|
3391
|
+
key: field,
|
|
3392
|
+
base: camelCase(field)
|
|
3393
|
+
}))
|
|
3394
|
+
];
|
|
3395
|
+
const bodyBase = profile.bindsRequestBody ? jsonBodyIdentifier(operation, config) : void 0;
|
|
3396
|
+
if (bodyBase !== void 0) {
|
|
3397
|
+
entries.push({
|
|
3398
|
+
key: REQUEST_BODY_KEY,
|
|
3399
|
+
base: bodyBase
|
|
3400
|
+
});
|
|
3401
|
+
}
|
|
3402
|
+
entries.push(...operation.queryParams.map((param) => ({
|
|
3403
|
+
key: param.name,
|
|
3404
|
+
base: camelCase(param.name)
|
|
3405
|
+
})));
|
|
3406
|
+
const identifiers = /* @__PURE__ */ new Map();
|
|
3407
|
+
const used = /* @__PURE__ */ new Set([
|
|
3408
|
+
...profile.reserved,
|
|
3409
|
+
...RESERVED_WORDS
|
|
3410
|
+
]);
|
|
3411
|
+
const renamed2 = [];
|
|
3412
|
+
const merged = /* @__PURE__ */ new Set();
|
|
3413
|
+
for (const { key, base } of entries) {
|
|
3414
|
+
if (identifiers.has(key)) {
|
|
3415
|
+
if (typeof key === "string") {
|
|
3416
|
+
merged.add(key);
|
|
3417
|
+
}
|
|
3418
|
+
continue;
|
|
3419
|
+
}
|
|
3420
|
+
let identifier = base;
|
|
3421
|
+
let suffix = 2;
|
|
3422
|
+
while (used.has(identifier)) {
|
|
3423
|
+
identifier = `${base}${suffix}`;
|
|
3424
|
+
suffix++;
|
|
3425
|
+
}
|
|
3426
|
+
if (identifier !== base) {
|
|
3427
|
+
renamed2.push(Object.freeze({
|
|
3428
|
+
source: typeof key === "string" ? key : base,
|
|
3429
|
+
identifier
|
|
3430
|
+
}));
|
|
3431
|
+
}
|
|
3432
|
+
used.add(identifier);
|
|
3433
|
+
identifiers.set(key, identifier);
|
|
3434
|
+
}
|
|
3435
|
+
return {
|
|
3436
|
+
// The fallback runs the *same* rules the resolver would have, rather
|
|
3437
|
+
// than a bare camelCase: an unregistered wire name otherwise came back
|
|
3438
|
+
// as `class` or `options`, names the resolver never assigns.
|
|
3439
|
+
// Uniquified against everything already assigned, not just the reserved
|
|
3440
|
+
// words: an unregistered wire name that camelCases onto an identifier
|
|
3441
|
+
// this operation already bound would otherwise alias it — compiling
|
|
3442
|
+
// fine and sending the wrong value. Only reachable for operations built
|
|
3443
|
+
// outside the normalizer, but the resolver is public API.
|
|
3444
|
+
of: /* @__PURE__ */ __name((wireName) => identifiers.get(wireName) ?? deriveLocalName(camelCase(wireName), [
|
|
3445
|
+
...used
|
|
3446
|
+
]), "of"),
|
|
3447
|
+
body: identifiers.get(REQUEST_BODY_KEY),
|
|
3448
|
+
all: Object.freeze([
|
|
3449
|
+
...identifiers.values()
|
|
3450
|
+
]),
|
|
3451
|
+
renamed: Object.freeze(renamed2),
|
|
3452
|
+
merged: Object.freeze([
|
|
3453
|
+
...merged
|
|
3454
|
+
])
|
|
3455
|
+
};
|
|
3456
|
+
}
|
|
3457
|
+
__name(computeArgumentNames, "computeArgumentNames");
|
|
3458
|
+
function jsonBodyIdentifier(operation, config) {
|
|
3459
|
+
if (!operation.requestBody || operation.isMultipart) {
|
|
3460
|
+
return void 0;
|
|
3461
|
+
}
|
|
3462
|
+
if (!operation.requestBody.content?.[CONTENT_TYPES.JSON]) {
|
|
3463
|
+
return void 0;
|
|
3464
|
+
}
|
|
3465
|
+
const bodyType = getRequestBodyType(operation.requestBody, config);
|
|
3466
|
+
return isDataTypeInterface(bodyType) ? camelCase(bodyType) : "requestBody";
|
|
3467
|
+
}
|
|
3468
|
+
__name(jsonBodyIdentifier, "jsonBodyIdentifier");
|
|
3469
|
+
function deriveLocalName(base, taken) {
|
|
3470
|
+
const used = new Set(taken);
|
|
3471
|
+
let name = base;
|
|
3472
|
+
let suffix = 2;
|
|
3473
|
+
while (used.has(name)) {
|
|
3474
|
+
name = `${base}${suffix}`;
|
|
3475
|
+
suffix++;
|
|
3476
|
+
}
|
|
3477
|
+
return name;
|
|
3478
|
+
}
|
|
3479
|
+
__name(deriveLocalName, "deriveLocalName");
|
|
3480
|
+
|
|
2971
3481
|
// ../../shared/src/emit/url.emit.ts
|
|
2972
3482
|
function plainParamValue(identifier) {
|
|
2973
3483
|
return identifier;
|
|
@@ -2977,24 +3487,34 @@ function signalAwareParamValue(identifier) {
|
|
|
2977
3487
|
return `typeof ${identifier} === 'function' ? ${identifier}() : ${identifier}`;
|
|
2978
3488
|
}
|
|
2979
3489
|
__name(signalAwareParamValue, "signalAwareParamValue");
|
|
2980
|
-
function emitUrlExpression(path3, pathParams, paramValue = plainParamValue) {
|
|
2981
|
-
|
|
3490
|
+
function emitUrlExpression(path3, pathParams, argumentNames, paramValue = plainParamValue) {
|
|
3491
|
+
const declared = new Set(pathParams.map((param) => param.name));
|
|
3492
|
+
const unresolved = (path3.match(/{([^{}]*)}/g) ?? []).map((placeholder) => placeholder.slice(1, -1)).filter((name) => !declared.has(name));
|
|
3493
|
+
if (unresolved.length > 0) {
|
|
3494
|
+
throw new UnresolvedPathTemplateError(`Path "${path3}" declares no parameter for ${unresolved.map((name) => `{${name}}`).join(", ")}. Declare each placeholder as a path parameter, or remove it from the path.`, path3, unresolved);
|
|
3495
|
+
}
|
|
3496
|
+
let urlExpression = "`${this.basePath}" + escapeTemplateLiteral(path3) + "`";
|
|
2982
3497
|
pathParams.forEach((param) => {
|
|
2983
|
-
|
|
3498
|
+
const replacement = "${" + paramValue(argumentNames.of(param.name)) + "}";
|
|
3499
|
+
urlExpression = urlExpression.split(`{${escapeTemplateLiteral(param.name)}}`).join(replacement);
|
|
2984
3500
|
});
|
|
2985
3501
|
return urlExpression;
|
|
2986
3502
|
}
|
|
2987
3503
|
__name(emitUrlExpression, "emitUrlExpression");
|
|
2988
3504
|
|
|
2989
3505
|
// ../../shared/src/emit/query-params.emit.ts
|
|
2990
|
-
function emitSignalAwareQueryParams(queryParams) {
|
|
3506
|
+
function emitSignalAwareQueryParams(queryParams, argumentNames) {
|
|
2991
3507
|
if (queryParams.length === 0) {
|
|
2992
3508
|
return "";
|
|
2993
3509
|
}
|
|
2994
|
-
const paramMappings = queryParams.map((param) =>
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
3510
|
+
const paramMappings = queryParams.map((param) => {
|
|
3511
|
+
const identifier = argumentNames.of(param.name);
|
|
3512
|
+
const local = deriveLocalName(`${identifier}Value`, argumentNames.all);
|
|
3513
|
+
return `const ${local} = ${signalAwareParamValue(identifier)};
|
|
3514
|
+
if (${local} != null) {
|
|
3515
|
+
params = HttpParamsBuilder.addToHttpParams(params, ${local}, ${quoteLiteral(param.name)});
|
|
3516
|
+
}`;
|
|
3517
|
+
}).join("\n");
|
|
2998
3518
|
return `
|
|
2999
3519
|
let params = new HttpParams();
|
|
3000
3520
|
${paramMappings}`;
|
|
@@ -3041,22 +3561,149 @@ function listGeneratedFileNames(project, directoryPath, suffix) {
|
|
|
3041
3561
|
__name(listGeneratedFileNames, "listGeneratedFileNames");
|
|
3042
3562
|
|
|
3043
3563
|
// ../../shared/src/utils/functions/token-names.ts
|
|
3044
|
-
function
|
|
3045
|
-
|
|
3564
|
+
function effectiveClientName(clientName) {
|
|
3565
|
+
return clientName ? clientName : "default";
|
|
3566
|
+
}
|
|
3567
|
+
__name(effectiveClientName, "effectiveClientName");
|
|
3568
|
+
function tokenSuffix(clientName) {
|
|
3569
|
+
return effectiveClientName(clientName).toUpperCase().replace(/[^A-Z0-9]/g, "_");
|
|
3570
|
+
}
|
|
3571
|
+
__name(tokenSuffix, "tokenSuffix");
|
|
3572
|
+
function getClientContextTokenName(clientName) {
|
|
3573
|
+
const clientSuffix = tokenSuffix(clientName);
|
|
3046
3574
|
return `CLIENT_CONTEXT_TOKEN_${clientSuffix}`;
|
|
3047
3575
|
}
|
|
3048
3576
|
__name(getClientContextTokenName, "getClientContextTokenName");
|
|
3049
|
-
function getBasePathTokenName(clientName
|
|
3050
|
-
const clientSuffix = clientName
|
|
3577
|
+
function getBasePathTokenName(clientName) {
|
|
3578
|
+
const clientSuffix = tokenSuffix(clientName);
|
|
3051
3579
|
return `BASE_PATH_${clientSuffix}`;
|
|
3052
3580
|
}
|
|
3053
3581
|
__name(getBasePathTokenName, "getBasePathTokenName");
|
|
3054
3582
|
|
|
3055
|
-
// ../../shared/src/utils/functions/
|
|
3056
|
-
function
|
|
3057
|
-
|
|
3583
|
+
// ../../shared/src/utils/functions/controller-groups.ts
|
|
3584
|
+
function groupOperationsByController(operations, onWarning) {
|
|
3585
|
+
const groups = {};
|
|
3586
|
+
const controllerByFold = /* @__PURE__ */ new Map();
|
|
3587
|
+
const tagSpellings = /* @__PURE__ */ new Map();
|
|
3588
|
+
const namelessTags = /* @__PURE__ */ new Set();
|
|
3589
|
+
operations.forEach((operation) => {
|
|
3590
|
+
const tag = operation.tags?.[0];
|
|
3591
|
+
let rawName = "Default";
|
|
3592
|
+
if (tag !== void 0) {
|
|
3593
|
+
rawName = tag;
|
|
3594
|
+
} else {
|
|
3595
|
+
const pathParts = operation.path.split("/").filter((part) => part && !part.startsWith("{"));
|
|
3596
|
+
if (pathParts.length > 1) {
|
|
3597
|
+
rawName = pathParts[1];
|
|
3598
|
+
}
|
|
3599
|
+
}
|
|
3600
|
+
const sanitized = pascalCase(rawName);
|
|
3601
|
+
const isNameless = !/\p{L}/u.test(sanitized);
|
|
3602
|
+
const candidate = isNameless ? "Default" : sanitized;
|
|
3603
|
+
const fold = candidate.toLowerCase();
|
|
3604
|
+
const controllerName = controllerByFold.get(fold) ?? candidate;
|
|
3605
|
+
controllerByFold.set(fold, controllerName);
|
|
3606
|
+
if (tag !== void 0 && isNameless) {
|
|
3607
|
+
namelessTags.add(tag);
|
|
3608
|
+
} else if (tag !== void 0) {
|
|
3609
|
+
const spellings = tagSpellings.get(controllerName) ?? /* @__PURE__ */ new Set();
|
|
3610
|
+
spellings.add(tag);
|
|
3611
|
+
tagSpellings.set(controllerName, spellings);
|
|
3612
|
+
}
|
|
3613
|
+
if (!groups[controllerName]) {
|
|
3614
|
+
groups[controllerName] = [];
|
|
3615
|
+
}
|
|
3616
|
+
groups[controllerName].push(operation);
|
|
3617
|
+
});
|
|
3618
|
+
for (const tag of namelessTags) {
|
|
3619
|
+
onWarning?.(`Tag "${tag}" contains no characters usable in a name \u2014 its operations are generated into the "Default" controller. Rename the tag to give them a file of their own.`);
|
|
3620
|
+
}
|
|
3621
|
+
for (const [controllerName, spellings] of tagSpellings) {
|
|
3622
|
+
if (spellings.size > 1) {
|
|
3623
|
+
onWarning?.(`Tags ${[
|
|
3624
|
+
...spellings
|
|
3625
|
+
].map((name) => `"${name}"`).join(" and ")} all map to the controller "${controllerName}" \u2014 their operations are generated into one file. Rename one tag to keep them apart.`);
|
|
3626
|
+
}
|
|
3627
|
+
}
|
|
3628
|
+
return groups;
|
|
3629
|
+
}
|
|
3630
|
+
__name(groupOperationsByController, "groupOperationsByController");
|
|
3631
|
+
|
|
3632
|
+
// ../../shared/src/utils/functions/method-names.ts
|
|
3633
|
+
var RESERVED_MEMBER_NAMES = Object.freeze([
|
|
3634
|
+
"constructor",
|
|
3635
|
+
"httpClient",
|
|
3636
|
+
"basePath",
|
|
3637
|
+
"clientContextToken",
|
|
3638
|
+
"createContextWithClientId"
|
|
3639
|
+
]);
|
|
3640
|
+
var RESERVED_MEMBER_SET = new Set(RESERVED_MEMBER_NAMES);
|
|
3641
|
+
function reservedMemberCollision(operation, config) {
|
|
3642
|
+
if (config.options.customizeMethodName || !operation.operationId) {
|
|
3643
|
+
return void 0;
|
|
3644
|
+
}
|
|
3645
|
+
const natural = camelCase(operation.operationId);
|
|
3646
|
+
return RESERVED_MEMBER_SET.has(natural) ? {
|
|
3647
|
+
from: natural,
|
|
3648
|
+
to: `_${natural}`
|
|
3649
|
+
} : void 0;
|
|
3058
3650
|
}
|
|
3059
|
-
__name(
|
|
3651
|
+
__name(reservedMemberCollision, "reservedMemberCollision");
|
|
3652
|
+
function getOperationMethodName(operation, config) {
|
|
3653
|
+
const customize = config.options.customizeMethodName;
|
|
3654
|
+
if (!customize) {
|
|
3655
|
+
return defaultOperationMethodName(operation);
|
|
3656
|
+
}
|
|
3657
|
+
if (operation.operationId == null) {
|
|
3658
|
+
throw new InvalidIdentifierError(`customizeMethodName needs an operationId, and ${describeOperation(operation)} has none. Add one to the spec, or drop customizeMethodName to use the derived name.`, operation);
|
|
3659
|
+
}
|
|
3660
|
+
const customName = customize(operation.operationId);
|
|
3661
|
+
if (!isValidIdentifier(customName) || RESERVED_MEMBER_SET.has(customName)) {
|
|
3662
|
+
throw new InvalidIdentifierError(`customizeMethodName returned "${customName}" for ${describeOperation(operation)}, which is not a usable TypeScript method name. Return an identifier \u2014 letters, digits, "_" and "$", not starting with a digit \u2014 and not one of ${RESERVED_MEMBER_NAMES.map((name) => `"${name}"`).join(", ")}.`, operation, customName);
|
|
3663
|
+
}
|
|
3664
|
+
return customName;
|
|
3665
|
+
}
|
|
3666
|
+
__name(getOperationMethodName, "getOperationMethodName");
|
|
3667
|
+
function defaultOperationMethodName(operation) {
|
|
3668
|
+
if (operation.operationId) {
|
|
3669
|
+
const name = camelCase(operation.operationId);
|
|
3670
|
+
return RESERVED_MEMBER_SET.has(name) ? `_${name}` : name;
|
|
3671
|
+
}
|
|
3672
|
+
const method = pascalCase(operation.method.toLowerCase());
|
|
3673
|
+
const pathParts = operation.path.split("/").filter((segment) => segment !== "").map((segment) => pascalCase(segment));
|
|
3674
|
+
const resource = pathParts.join("") || "resource";
|
|
3675
|
+
return `${camelCase(resource)}${method}`;
|
|
3676
|
+
}
|
|
3677
|
+
__name(defaultOperationMethodName, "defaultOperationMethodName");
|
|
3678
|
+
|
|
3679
|
+
// ../../shared/src/utils/functions/distinct-member-names.ts
|
|
3680
|
+
function assertDistinctMemberNames(serviceClass, className, operations, methodNameOf) {
|
|
3681
|
+
const methodNames = serviceClass.getMethods().map((method) => method.getName());
|
|
3682
|
+
const propertyNames = new Set(serviceClass.getProperties().map((property) => property.getName()));
|
|
3683
|
+
const duplicates = [
|
|
3684
|
+
...new Set(methodNames.filter((name, index) => methodNames.indexOf(name) !== index || propertyNames.has(name)))
|
|
3685
|
+
];
|
|
3686
|
+
if (duplicates.length === 0) {
|
|
3687
|
+
return;
|
|
3688
|
+
}
|
|
3689
|
+
const byName = new Map(duplicates.map((name) => [
|
|
3690
|
+
name,
|
|
3691
|
+
[]
|
|
3692
|
+
]));
|
|
3693
|
+
for (const operation of operations) {
|
|
3694
|
+
byName.get(methodNameOf(operation))?.push(operation);
|
|
3695
|
+
}
|
|
3696
|
+
const detail = [
|
|
3697
|
+
...byName
|
|
3698
|
+
].map(([name, ops]) => {
|
|
3699
|
+
const from = ops.map(describeOperation).join(" and ");
|
|
3700
|
+
return propertyNames.has(name) ? `"${name}" from ${from} (a property of ${className})` : `"${name}" from ${from}`;
|
|
3701
|
+
}).join("; ");
|
|
3702
|
+
throw new DuplicateGeneratedNameError(`Operations map to the same member name in ${className}: ${detail}. Ensure each operationId maps to a unique name.`, duplicates, [
|
|
3703
|
+
...byName.values()
|
|
3704
|
+
].flat());
|
|
3705
|
+
}
|
|
3706
|
+
__name(assertDistinctMemberNames, "assertDistinctMemberNames");
|
|
3060
3707
|
|
|
3061
3708
|
// ../../shared/src/config/constants.ts
|
|
3062
3709
|
var disableLinting = `// @ts-nocheck
|
|
@@ -3109,6 +3756,14 @@ var HttpResourceMethodBodyGenerator = class {
|
|
|
3109
3756
|
constructor(config) {
|
|
3110
3757
|
this.config = config;
|
|
3111
3758
|
}
|
|
3759
|
+
/**
|
|
3760
|
+
* The plugin reserves its own bindings (`resourceOptions`/`requestOptions`),
|
|
3761
|
+
* not the core service's — resolving against the wrong set would let a
|
|
3762
|
+
* `requestOptions` query parameter capture the plugin's own parameter.
|
|
3763
|
+
*/
|
|
3764
|
+
argumentNames(operation) {
|
|
3765
|
+
return resolveArgumentNames(operation, this.config, RESOURCE_ARGUMENT_PROFILE);
|
|
3766
|
+
}
|
|
3112
3767
|
generateMethodBody(operation) {
|
|
3113
3768
|
const bodyParts = [
|
|
3114
3769
|
this.generateDefaultHeaders(operation),
|
|
@@ -3140,7 +3795,7 @@ var HttpResourceMethodBodyGenerator = class {
|
|
|
3140
3795
|
}
|
|
3141
3796
|
generateRequestOptions(operation) {
|
|
3142
3797
|
const entries = [];
|
|
3143
|
-
const url = emitUrlExpression(operation.path, operation.pathParams, signalAwareParamValue);
|
|
3798
|
+
const url = emitUrlExpression(operation.path, operation.pathParams, this.argumentNames(operation), signalAwareParamValue);
|
|
3144
3799
|
entries.push(`url: ${url}`);
|
|
3145
3800
|
entries.push(`method: "GET"`);
|
|
3146
3801
|
entries.push("...requestOptions");
|
|
@@ -3158,7 +3813,7 @@ var HttpResourceMethodBodyGenerator = class {
|
|
|
3158
3813
|
}
|
|
3159
3814
|
generateHttpResource(operation) {
|
|
3160
3815
|
const resourceOptions = this.generateRequestOptions(operation);
|
|
3161
|
-
const queryParams = emitSignalAwareQueryParams(operation.queryParams);
|
|
3816
|
+
const queryParams = emitSignalAwareQueryParams(operation.queryParams, this.argumentNames(operation));
|
|
3162
3817
|
let httpResource = "httpResource";
|
|
3163
3818
|
switch (operation.responseType) {
|
|
3164
3819
|
case "blob":
|
|
@@ -3206,13 +3861,14 @@ var HttpResourceMethodParamsGenerator = class {
|
|
|
3206
3861
|
}
|
|
3207
3862
|
generateApiParameters(operation) {
|
|
3208
3863
|
const params = [];
|
|
3864
|
+
const argumentNames = resolveArgumentNames(operation, this.config, RESOURCE_ARGUMENT_PROFILE);
|
|
3209
3865
|
operation.pathParams.forEach((param) => {
|
|
3210
3866
|
const paramType = getTypeScriptType(param.schema || {
|
|
3211
3867
|
...param
|
|
3212
3868
|
}, this.config);
|
|
3213
3869
|
const signalParamType = param.required ? `Signal<${paramType}>` : `Signal<${paramType} | undefined>`;
|
|
3214
3870
|
params.push({
|
|
3215
|
-
name:
|
|
3871
|
+
name: argumentNames.of(param.name),
|
|
3216
3872
|
type: `${signalParamType} | ${paramType}`,
|
|
3217
3873
|
hasQuestionToken: !param.required
|
|
3218
3874
|
});
|
|
@@ -3223,7 +3879,7 @@ var HttpResourceMethodParamsGenerator = class {
|
|
|
3223
3879
|
}, this.config);
|
|
3224
3880
|
const signalParamType = param.required ? `Signal<${paramType}>` : `Signal<${paramType} | undefined>`;
|
|
3225
3881
|
params.push({
|
|
3226
|
-
name:
|
|
3882
|
+
name: argumentNames.of(param.name),
|
|
3227
3883
|
type: `${signalParamType} | ${paramType}`,
|
|
3228
3884
|
hasQuestionToken: !param.required
|
|
3229
3885
|
});
|
|
@@ -3294,31 +3950,11 @@ var HttpResourceMethodGenerator = class {
|
|
|
3294
3950
|
returnType,
|
|
3295
3951
|
statements: methodBody,
|
|
3296
3952
|
overloads,
|
|
3297
|
-
docs: operation.description
|
|
3298
|
-
operation.description
|
|
3299
|
-
] : void 0
|
|
3953
|
+
docs: emitDocs(operation.description)
|
|
3300
3954
|
});
|
|
3301
3955
|
}
|
|
3302
3956
|
generateMethodName(operation) {
|
|
3303
|
-
|
|
3304
|
-
if (operation.operationId == null) {
|
|
3305
|
-
throw new Error(`Operation ID is required for method name customization of operation: (${operation.method}) ${operation.path}`);
|
|
3306
|
-
}
|
|
3307
|
-
return this.config.options.customizeMethodName(operation.operationId);
|
|
3308
|
-
} else {
|
|
3309
|
-
return this.defaultNameGenerator(operation);
|
|
3310
|
-
}
|
|
3311
|
-
}
|
|
3312
|
-
defaultNameGenerator(operation) {
|
|
3313
|
-
if (operation.operationId) {
|
|
3314
|
-
return camelCase(operation.operationId);
|
|
3315
|
-
}
|
|
3316
|
-
const method = pascalCase(operation.method.toLowerCase());
|
|
3317
|
-
const pathParts = operation.path.split("/").map((str2) => {
|
|
3318
|
-
return pascalCase(pascalCase(str2).replace(/[^a-zA-Z0-9]/g, ""));
|
|
3319
|
-
});
|
|
3320
|
-
const resource = pathParts.join("") || "resource";
|
|
3321
|
-
return `${camelCase(resource)}${method}`;
|
|
3957
|
+
return getOperationMethodName(operation, this.config);
|
|
3322
3958
|
}
|
|
3323
3959
|
generateReturnType(operation) {
|
|
3324
3960
|
const response = operation.responses?.["200"] || operation.responses?.["201"] || operation.responses?.["204"];
|
|
@@ -3393,7 +4029,6 @@ var HttpResourceIndexGenerator = class {
|
|
|
3393
4029
|
});
|
|
3394
4030
|
});
|
|
3395
4031
|
sourceFile.formatText();
|
|
3396
|
-
sourceFile.saveSync();
|
|
3397
4032
|
}
|
|
3398
4033
|
};
|
|
3399
4034
|
|
|
@@ -3423,32 +4058,15 @@ var HttpResourceGenerator = class {
|
|
|
3423
4058
|
this.onWarning?.("No API paths found in the specification");
|
|
3424
4059
|
return;
|
|
3425
4060
|
}
|
|
3426
|
-
const controllerGroups = this.
|
|
3427
|
-
await Promise.all(
|
|
3428
|
-
|
|
3429
|
-
|
|
4061
|
+
const controllerGroups = groupOperationsByController(paths, this.onWarning);
|
|
4062
|
+
await Promise.all(
|
|
4063
|
+
// Must return the promise: without it Promise.all awaits [undefined],
|
|
4064
|
+
// and a generateServiceFile rejection escapes as an unhandled
|
|
4065
|
+
// rejection while generation reports success.
|
|
4066
|
+
Object.entries(controllerGroups).map(([controllerName, operations]) => this.generateServiceFile(controllerName, operations, outputDir))
|
|
4067
|
+
);
|
|
3430
4068
|
this.indexGenerator.generateIndex(outputRoot);
|
|
3431
4069
|
}
|
|
3432
|
-
groupPathsByController(paths) {
|
|
3433
|
-
const groups = {};
|
|
3434
|
-
paths.forEach((path3) => {
|
|
3435
|
-
let controllerName = "Default";
|
|
3436
|
-
if (path3.tags && path3.tags.length > 0) {
|
|
3437
|
-
controllerName = path3.tags[0];
|
|
3438
|
-
} else {
|
|
3439
|
-
const pathParts = path3.path.split("/").filter((p) => p && !p.startsWith("{"));
|
|
3440
|
-
if (pathParts.length > 1) {
|
|
3441
|
-
controllerName = pascalCase(pathParts[1]);
|
|
3442
|
-
}
|
|
3443
|
-
}
|
|
3444
|
-
controllerName = pascalCase(controllerName);
|
|
3445
|
-
if (!groups[controllerName]) {
|
|
3446
|
-
groups[controllerName] = [];
|
|
3447
|
-
}
|
|
3448
|
-
groups[controllerName].push(path3);
|
|
3449
|
-
});
|
|
3450
|
-
return groups;
|
|
3451
|
-
}
|
|
3452
4070
|
async generateServiceFile(controllerName, operations, outputDir) {
|
|
3453
4071
|
const fileName = `${camelCase(controllerName)}.resource.ts`;
|
|
3454
4072
|
const filePath = path2.join(outputDir, fileName);
|
|
@@ -3458,7 +4076,6 @@ var HttpResourceGenerator = class {
|
|
|
3458
4076
|
this.addServiceClass(sourceFile, controllerName, operations);
|
|
3459
4077
|
sourceFile.fixMissingImports().formatText();
|
|
3460
4078
|
sourceFile.insertText(0, HTTP_RESOURCE_GENERATOR_HEADER_COMMENT(getResourceClassName(controllerName, this.config.options.naming?.resources)));
|
|
3461
|
-
sourceFile.saveSync();
|
|
3462
4079
|
}
|
|
3463
4080
|
addServiceClass(sourceFile, controllerName, operations) {
|
|
3464
4081
|
const className = getResourceClassName(controllerName, this.config.options.naming?.resources);
|
|
@@ -3534,14 +4151,23 @@ var HttpResourceGenerator = class {
|
|
|
3534
4151
|
],
|
|
3535
4152
|
returnType: "HttpContext",
|
|
3536
4153
|
statements: `const context = existingContext || new HttpContext();
|
|
3537
|
-
return context.set(this.clientContextToken,
|
|
4154
|
+
return context.set(this.clientContextToken, ${quoteLiteral(effectiveClientName(this.config.clientName))});`
|
|
3538
4155
|
});
|
|
3539
4156
|
operations.forEach((operation) => {
|
|
4157
|
+
const { renamed: renamed2, merged } = resolveArgumentNames(operation, this.config, RESOURCE_ARGUMENT_PROFILE);
|
|
4158
|
+
for (const { source, identifier } of renamed2) {
|
|
4159
|
+
this.onWarning?.(`Parameter "${source}" of ${describeOperation(operation)} is exposed as "${identifier}" \u2014 its natural name is already taken by another parameter or by the resource method itself.`);
|
|
4160
|
+
}
|
|
4161
|
+
for (const wireName of merged) {
|
|
4162
|
+
this.onWarning?.(`Parameter "${wireName}" of ${describeOperation(operation)} is declared in more than one location; they collapse into one argument, so the first declaration's type wins and the same value is sent for both.`);
|
|
4163
|
+
}
|
|
4164
|
+
const collision = reservedMemberCollision(operation, this.config);
|
|
4165
|
+
if (collision) {
|
|
4166
|
+
this.onWarning?.(`Operation ${describeOperation(operation)} would be named "${collision.from}", which the generated class already binds \u2014 it is emitted as "${collision.to}". Rename the operationId to choose the name.`);
|
|
4167
|
+
}
|
|
3540
4168
|
this.methodGenerator.addResourceMethod(serviceClass, operation);
|
|
3541
4169
|
});
|
|
3542
|
-
|
|
3543
|
-
throw new Error(`Duplicate method names found in service class ${className}. Please ensure unique method names for each operation.`);
|
|
3544
|
-
}
|
|
4170
|
+
assertDistinctMemberNames(serviceClass, className, operations, (op) => this.methodGenerator.generateMethodName(op));
|
|
3545
4171
|
}
|
|
3546
4172
|
};
|
|
3547
4173
|
export {
|