@ng-openapi/http-resource 0.1.3 → 0.2.1-pr-130-feat-npm-package-scaffold-0a3f1ed.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 +718 -88
- package/index.d.ts +50 -2
- package/index.js +714 -84
- package/package.json +1 -1
package/index.cjs
CHANGED
|
@@ -36,7 +36,239 @@ __export(index_exports, {
|
|
|
36
36
|
module.exports = __toCommonJS(index_exports);
|
|
37
37
|
|
|
38
38
|
// src/lib/http-resource.generator.ts
|
|
39
|
-
var
|
|
39
|
+
var import_ts_morph3 = require("ts-morph");
|
|
40
|
+
|
|
41
|
+
// ../../shared/src/errors.ts
|
|
42
|
+
var NG_OPENAPI_ERROR_BRAND = "__ngOpenApiError";
|
|
43
|
+
var ERROR_LINEAGE = /* @__PURE__ */ new WeakMap();
|
|
44
|
+
var FALLBACK_LINEAGE = Object.freeze([
|
|
45
|
+
"NgOpenApiError"
|
|
46
|
+
]);
|
|
47
|
+
function registerError(cls, lineage) {
|
|
48
|
+
ERROR_LINEAGE.set(cls, Object.freeze([
|
|
49
|
+
...lineage
|
|
50
|
+
]));
|
|
51
|
+
return cls;
|
|
52
|
+
}
|
|
53
|
+
__name(registerError, "registerError");
|
|
54
|
+
function inheritedLineage(cls) {
|
|
55
|
+
for (let current = cls; typeof current === "function"; current = Object.getPrototypeOf(current)) {
|
|
56
|
+
const lineage = ERROR_LINEAGE.get(current);
|
|
57
|
+
if (lineage) {
|
|
58
|
+
return lineage;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return FALLBACK_LINEAGE;
|
|
62
|
+
}
|
|
63
|
+
__name(inheritedLineage, "inheritedLineage");
|
|
64
|
+
var NgOpenApiError = class extends Error {
|
|
65
|
+
static {
|
|
66
|
+
__name(this, "NgOpenApiError");
|
|
67
|
+
}
|
|
68
|
+
/** The underlying error that caused this one, when there is one. */
|
|
69
|
+
cause;
|
|
70
|
+
constructor(message, cause) {
|
|
71
|
+
super(message);
|
|
72
|
+
const lineage = inheritedLineage(new.target);
|
|
73
|
+
this.name = lineage[0];
|
|
74
|
+
this.cause = cause;
|
|
75
|
+
Object.defineProperty(this, NG_OPENAPI_ERROR_BRAND, {
|
|
76
|
+
value: lineage,
|
|
77
|
+
enumerable: false,
|
|
78
|
+
writable: false,
|
|
79
|
+
configurable: false
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* `message` and `name` are non-enumerable on Error, so the default
|
|
84
|
+
* JSON.stringify dropped both — the least useful possible serialization for
|
|
85
|
+
* something that exists to be logged.
|
|
86
|
+
*
|
|
87
|
+
* The payload is spread rather than enumerated: `source`, `issues`,
|
|
88
|
+
* `operation`, `names` and `placeholders` are why these classes are typed
|
|
89
|
+
* in the first place, and listing fields by hand silently drops whichever
|
|
90
|
+
* ones a later subclass adds.
|
|
91
|
+
*/
|
|
92
|
+
toJSON() {
|
|
93
|
+
const cause = this.cause instanceof Error ? this.cause.message : this.cause;
|
|
94
|
+
return {
|
|
95
|
+
name: this.name,
|
|
96
|
+
message: this.message,
|
|
97
|
+
...cause === void 0 ? {} : {
|
|
98
|
+
cause
|
|
99
|
+
},
|
|
100
|
+
// Own enumerable properties: the brand is deliberately not one.
|
|
101
|
+
...Object.fromEntries(Object.entries(this).filter(([key]) => key !== "cause"))
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Recognizes branded errors from another bundled copy of this module, so
|
|
106
|
+
* `error instanceof SpecLoadError` works for a plugin-thrown error too.
|
|
107
|
+
* The prototype chain is checked first, so a caller's own subclass of these
|
|
108
|
+
* classes still matches even though it carries no lineage entry.
|
|
109
|
+
*
|
|
110
|
+
* Never throws and never runs foreign code: both reflective reads sit
|
|
111
|
+
* inside the try, because a Proxy traps `getPrototypeOf` just as readily as
|
|
112
|
+
* `getOwnPropertyDescriptor`.
|
|
113
|
+
*/
|
|
114
|
+
static [Symbol.hasInstance](value) {
|
|
115
|
+
if (typeof value !== "object" || value === null) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
if (Object.prototype.isPrototypeOf.call(this.prototype, value)) {
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
const expected = ERROR_LINEAGE.get(this)?.[0];
|
|
123
|
+
if (expected === void 0) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, NG_OPENAPI_ERROR_BRAND);
|
|
127
|
+
if (!descriptor || descriptor.enumerable || !("value" in descriptor)) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
return Array.isArray(descriptor.value) && descriptor.value.includes(expected);
|
|
131
|
+
} catch {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
registerError(NgOpenApiError, [
|
|
137
|
+
"NgOpenApiError"
|
|
138
|
+
]);
|
|
139
|
+
var SpecLoadError = class extends NgOpenApiError {
|
|
140
|
+
static {
|
|
141
|
+
__name(this, "SpecLoadError");
|
|
142
|
+
}
|
|
143
|
+
/** The file path or URL that failed to load. */
|
|
144
|
+
source;
|
|
145
|
+
constructor(message, source, cause) {
|
|
146
|
+
super(message, cause);
|
|
147
|
+
this.source = source;
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
registerError(SpecLoadError, [
|
|
151
|
+
"SpecLoadError",
|
|
152
|
+
"NgOpenApiError"
|
|
153
|
+
]);
|
|
154
|
+
var SpecParseError = class extends NgOpenApiError {
|
|
155
|
+
static {
|
|
156
|
+
__name(this, "SpecParseError");
|
|
157
|
+
}
|
|
158
|
+
/** The file path or URL the content came from, when known. */
|
|
159
|
+
source;
|
|
160
|
+
constructor(message, source, cause) {
|
|
161
|
+
super(message, cause);
|
|
162
|
+
this.source = source;
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
registerError(SpecParseError, [
|
|
166
|
+
"SpecParseError",
|
|
167
|
+
"NgOpenApiError"
|
|
168
|
+
]);
|
|
169
|
+
function describeOperation(operation) {
|
|
170
|
+
const location = `(${operation.method}) ${operation.path}`;
|
|
171
|
+
return operation.operationId ? `${operation.operationId} (${location})` : location;
|
|
172
|
+
}
|
|
173
|
+
__name(describeOperation, "describeOperation");
|
|
174
|
+
function captureOperation(operation) {
|
|
175
|
+
return Object.freeze({
|
|
176
|
+
operationId: operation.operationId,
|
|
177
|
+
method: operation.method,
|
|
178
|
+
path: operation.path
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
__name(captureOperation, "captureOperation");
|
|
182
|
+
var InvalidIdentifierError = class extends NgOpenApiError {
|
|
183
|
+
static {
|
|
184
|
+
__name(this, "InvalidIdentifierError");
|
|
185
|
+
}
|
|
186
|
+
/** The rejected name, verbatim; absent when no name could be derived. */
|
|
187
|
+
identifier;
|
|
188
|
+
/** The operation whose name was being derived. */
|
|
189
|
+
operation;
|
|
190
|
+
constructor(message, operation, identifier) {
|
|
191
|
+
super(message);
|
|
192
|
+
this.operation = captureOperation(operation);
|
|
193
|
+
this.identifier = identifier;
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
registerError(InvalidIdentifierError, [
|
|
197
|
+
"InvalidIdentifierError",
|
|
198
|
+
"NgOpenApiError"
|
|
199
|
+
]);
|
|
200
|
+
var DuplicateGeneratedNameError = class extends NgOpenApiError {
|
|
201
|
+
static {
|
|
202
|
+
__name(this, "DuplicateGeneratedNameError");
|
|
203
|
+
}
|
|
204
|
+
/** The colliding generated names. */
|
|
205
|
+
names;
|
|
206
|
+
/** The operations that produced them, when known. */
|
|
207
|
+
operations;
|
|
208
|
+
constructor(message, names, operations = []) {
|
|
209
|
+
super(message);
|
|
210
|
+
this.names = Object.freeze([
|
|
211
|
+
...names
|
|
212
|
+
]);
|
|
213
|
+
this.operations = Object.freeze(operations.map(captureOperation));
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
registerError(DuplicateGeneratedNameError, [
|
|
217
|
+
"DuplicateGeneratedNameError",
|
|
218
|
+
"NgOpenApiError"
|
|
219
|
+
]);
|
|
220
|
+
var UnresolvedPathTemplateError = class extends NgOpenApiError {
|
|
221
|
+
static {
|
|
222
|
+
__name(this, "UnresolvedPathTemplateError");
|
|
223
|
+
}
|
|
224
|
+
/** The path as written in the spec. */
|
|
225
|
+
path;
|
|
226
|
+
/** Placeholder names with no declared parameter. */
|
|
227
|
+
placeholders;
|
|
228
|
+
constructor(message, path3, placeholders) {
|
|
229
|
+
super(message);
|
|
230
|
+
this.path = path3;
|
|
231
|
+
this.placeholders = Object.freeze([
|
|
232
|
+
...placeholders
|
|
233
|
+
]);
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
registerError(UnresolvedPathTemplateError, [
|
|
237
|
+
"UnresolvedPathTemplateError",
|
|
238
|
+
"NgOpenApiError"
|
|
239
|
+
]);
|
|
240
|
+
var ConfigValidationError = class extends NgOpenApiError {
|
|
241
|
+
static {
|
|
242
|
+
__name(this, "ConfigValidationError");
|
|
243
|
+
}
|
|
244
|
+
issues;
|
|
245
|
+
constructor(issues) {
|
|
246
|
+
super(`Invalid ng-openapi configuration:
|
|
247
|
+
${issues.map((issue) => ` - ${issue}`).join("\n")}`);
|
|
248
|
+
this.issues = Object.freeze([
|
|
249
|
+
...issues
|
|
250
|
+
]);
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
registerError(ConfigValidationError, [
|
|
254
|
+
"ConfigValidationError",
|
|
255
|
+
"NgOpenApiError"
|
|
256
|
+
]);
|
|
257
|
+
var ConfigLoadError = class extends NgOpenApiError {
|
|
258
|
+
static {
|
|
259
|
+
__name(this, "ConfigLoadError");
|
|
260
|
+
}
|
|
261
|
+
/** Path of the config file that failed to load. */
|
|
262
|
+
source;
|
|
263
|
+
constructor(message, source, cause) {
|
|
264
|
+
super(message, cause);
|
|
265
|
+
this.source = source;
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
registerError(ConfigLoadError, [
|
|
269
|
+
"ConfigLoadError",
|
|
270
|
+
"NgOpenApiError"
|
|
271
|
+
]);
|
|
40
272
|
|
|
41
273
|
// ../../../node_modules/js-yaml/dist/js-yaml.mjs
|
|
42
274
|
function isNothing(subject) {
|
|
@@ -2741,19 +2973,75 @@ var safeLoadAll = renamed("safeLoadAll", "loadAll");
|
|
|
2741
2973
|
var safeDump = renamed("safeDump", "dump");
|
|
2742
2974
|
|
|
2743
2975
|
// ../../shared/src/utils/string.utils.ts
|
|
2976
|
+
var IDENTIFIER_SEPARATORS = /(?:_|[^\p{ID_Continue}$])+(.)?/gu;
|
|
2977
|
+
var INVALID_IDENTIFIER_START = /^[^\p{ID_Start}$_]/u;
|
|
2978
|
+
function toIdentifier(converted) {
|
|
2979
|
+
if (converted === "") {
|
|
2980
|
+
return "_";
|
|
2981
|
+
}
|
|
2982
|
+
return converted.replace(INVALID_IDENTIFIER_START, (char) => `_${char}`);
|
|
2983
|
+
}
|
|
2984
|
+
__name(toIdentifier, "toIdentifier");
|
|
2985
|
+
function isValidIdentifier(name) {
|
|
2986
|
+
return /^[\p{ID_Start}$_][\p{ID_Continue}$]*$/u.test(name);
|
|
2987
|
+
}
|
|
2988
|
+
__name(isValidIdentifier, "isValidIdentifier");
|
|
2744
2989
|
function camelCase(str2) {
|
|
2745
|
-
|
|
2990
|
+
const converted = str2.replace(IDENTIFIER_SEPARATORS, (_, char) => char ? char.toUpperCase() : "").replace(/^./u, (char) => char.toLowerCase());
|
|
2991
|
+
return toIdentifier(converted);
|
|
2746
2992
|
}
|
|
2747
2993
|
__name(camelCase, "camelCase");
|
|
2748
2994
|
function pascalCase(str2) {
|
|
2749
|
-
|
|
2995
|
+
const converted = str2.replace(IDENTIFIER_SEPARATORS, (_, char) => char ? char.toUpperCase() : "").replace(/^./u, (char) => char.toUpperCase());
|
|
2996
|
+
return toIdentifier(converted);
|
|
2750
2997
|
}
|
|
2751
2998
|
__name(pascalCase, "pascalCase");
|
|
2752
2999
|
function pascalCaseForEnums(str2) {
|
|
2753
|
-
|
|
3000
|
+
const converted = str2.replace(/[^a-zA-Z0-9]/g, "_").replace(/(?:^|_)([a-z])/g, (_, char) => char.toUpperCase()).replace(/^([0-9])/, "_$1");
|
|
3001
|
+
return converted === "" ? "_" : converted;
|
|
2754
3002
|
}
|
|
2755
3003
|
__name(pascalCaseForEnums, "pascalCaseForEnums");
|
|
2756
3004
|
|
|
3005
|
+
// ../../shared/src/utils/content-types.constants.ts
|
|
3006
|
+
var CONTENT_TYPES = {
|
|
3007
|
+
MULTIPART: "multipart/form-data",
|
|
3008
|
+
FORM_URLENCODED: "application/x-www-form-urlencoded",
|
|
3009
|
+
JSON: "application/json"
|
|
3010
|
+
};
|
|
3011
|
+
|
|
3012
|
+
// ../../shared/src/emit/literal.emit.ts
|
|
3013
|
+
function quoteLiteral(value) {
|
|
3014
|
+
return `'${escapeSingleQuoted(value)}'`;
|
|
3015
|
+
}
|
|
3016
|
+
__name(quoteLiteral, "quoteLiteral");
|
|
3017
|
+
function escapeSingleQuoted(value) {
|
|
3018
|
+
return value.replace(/[\\']/g, (char) => `\\${char}`).replace(/\r/g, "\\r").replace(/\n/g, "\\n");
|
|
3019
|
+
}
|
|
3020
|
+
__name(escapeSingleQuoted, "escapeSingleQuoted");
|
|
3021
|
+
function escapeTemplateLiteral(value) {
|
|
3022
|
+
return value.replace(/[\\`]/g, (char) => `\\${char}`).replace(/\$\{/g, "\\${").replace(/\r/g, "\\r");
|
|
3023
|
+
}
|
|
3024
|
+
__name(escapeTemplateLiteral, "escapeTemplateLiteral");
|
|
3025
|
+
function emitObjectKey(name, quoteStyle = "double") {
|
|
3026
|
+
const quoted = quoteStyle === "single" ? quoteLiteral(name) : `"${escapeDoubleQuoted(name)}"`;
|
|
3027
|
+
return name === "__proto__" ? `[${quoted}]` : quoted;
|
|
3028
|
+
}
|
|
3029
|
+
__name(emitObjectKey, "emitObjectKey");
|
|
3030
|
+
function escapeDoubleQuoted(value) {
|
|
3031
|
+
return value.replace(/[\\"]/g, (char) => `\\${char}`).replace(/\r/g, "\\r").replace(/\n/g, "\\n");
|
|
3032
|
+
}
|
|
3033
|
+
__name(escapeDoubleQuoted, "escapeDoubleQuoted");
|
|
3034
|
+
function escapeJsDoc(text) {
|
|
3035
|
+
return text.replace(/\*\//g, "*\\/");
|
|
3036
|
+
}
|
|
3037
|
+
__name(escapeJsDoc, "escapeJsDoc");
|
|
3038
|
+
function emitDocs(description) {
|
|
3039
|
+
return typeof description === "string" && description ? [
|
|
3040
|
+
escapeJsDoc(description)
|
|
3041
|
+
] : void 0;
|
|
3042
|
+
}
|
|
3043
|
+
__name(emitDocs, "emitDocs");
|
|
3044
|
+
|
|
2757
3045
|
// ../../shared/src/utils/functions/class-names.ts
|
|
2758
3046
|
function decorate(base, defaultSuffix, naming) {
|
|
2759
3047
|
return `${naming?.prefix ?? ""}${base}${naming?.suffix ?? defaultSuffix}`;
|
|
@@ -2796,7 +3084,7 @@ function getTypeScriptType(schemaOrType, config, formatOrNullable, isNullable, c
|
|
|
2796
3084
|
switch (schema2.type) {
|
|
2797
3085
|
case "string":
|
|
2798
3086
|
if (schema2.enum) {
|
|
2799
|
-
return schema2.enum.map((value) => typeof value === "string" ? `'${
|
|
3087
|
+
return schema2.enum.map((value) => typeof value === "string" ? `'${escapeSingleQuoted(value)}'` : String(value)).join(" | ");
|
|
2800
3088
|
}
|
|
2801
3089
|
if (schema2.format === "date" || schema2.format === "date-time") {
|
|
2802
3090
|
const dateType = config.options.dateType === "Date" ? "Date" : "string";
|
|
@@ -2832,10 +3120,6 @@ function nullableType(type2, isNullable) {
|
|
|
2832
3120
|
return type2 + (isNullable ? " | null" : "");
|
|
2833
3121
|
}
|
|
2834
3122
|
__name(nullableType, "nullableType");
|
|
2835
|
-
function escapeString2(str2) {
|
|
2836
|
-
return str2.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
2837
|
-
}
|
|
2838
|
-
__name(escapeString2, "escapeString");
|
|
2839
3123
|
|
|
2840
3124
|
// ../../shared/src/utils/functions/extract-swagger-response-type.ts
|
|
2841
3125
|
function getResponseTypeFromResponse(response, responseTypeMapping) {
|
|
@@ -2984,7 +3268,7 @@ __name(getResponseType, "getResponseType");
|
|
|
2984
3268
|
|
|
2985
3269
|
// ../../shared/src/emit/headers.emit.ts
|
|
2986
3270
|
function emitDefaultHeadersMerge(optionsExpression, customHeaders) {
|
|
2987
|
-
const defaultsLiteral = Object.entries(customHeaders).map(([key, value]) =>
|
|
3271
|
+
const defaultsLiteral = Object.entries(customHeaders).map(([key, value]) => `${emitObjectKey(key, "single")}: ${quoteLiteral(value)}`).join(", ");
|
|
2988
3272
|
return `
|
|
2989
3273
|
// Add default headers if not already present
|
|
2990
3274
|
let headers = ${optionsExpression}?.headers;
|
|
@@ -2996,12 +3280,238 @@ ${emitDefaultHeaderGuards(customHeaders)}
|
|
|
2996
3280
|
}
|
|
2997
3281
|
__name(emitDefaultHeadersMerge, "emitDefaultHeadersMerge");
|
|
2998
3282
|
function emitDefaultHeaderGuards(customHeaders) {
|
|
2999
|
-
return Object.entries(customHeaders).map(([key, value]) =>
|
|
3000
|
-
|
|
3001
|
-
|
|
3283
|
+
return Object.entries(customHeaders).map(([key, value]) => {
|
|
3284
|
+
const name = quoteLiteral(key);
|
|
3285
|
+
return `if (!headers.has(${name})) {
|
|
3286
|
+
headers = headers.set(${name}, ${quoteLiteral(value)});
|
|
3287
|
+
}`;
|
|
3288
|
+
}).join("\n");
|
|
3002
3289
|
}
|
|
3003
3290
|
__name(emitDefaultHeaderGuards, "emitDefaultHeaderGuards");
|
|
3004
3291
|
|
|
3292
|
+
// ../../shared/src/utils/functions/get-request-body-type.ts
|
|
3293
|
+
function getRequestBodyType(requestBody, config) {
|
|
3294
|
+
const content = requestBody.content || {};
|
|
3295
|
+
const jsonContent = content[CONTENT_TYPES.JSON];
|
|
3296
|
+
if (jsonContent?.schema) {
|
|
3297
|
+
return getTypeScriptType(jsonContent.schema, config, jsonContent.schema.nullable);
|
|
3298
|
+
}
|
|
3299
|
+
return "any";
|
|
3300
|
+
}
|
|
3301
|
+
__name(getRequestBodyType, "getRequestBodyType");
|
|
3302
|
+
|
|
3303
|
+
// ../../shared/src/utils/functions/is-data-type-interface.ts
|
|
3304
|
+
function isDataTypeInterface(type2) {
|
|
3305
|
+
const invalidTypes = [
|
|
3306
|
+
"any",
|
|
3307
|
+
"File",
|
|
3308
|
+
"string",
|
|
3309
|
+
"number",
|
|
3310
|
+
"boolean",
|
|
3311
|
+
"object",
|
|
3312
|
+
"unknown",
|
|
3313
|
+
"[]",
|
|
3314
|
+
"Array"
|
|
3315
|
+
];
|
|
3316
|
+
return !invalidTypes.some((invalidType) => type2.includes(invalidType));
|
|
3317
|
+
}
|
|
3318
|
+
__name(isDataTypeInterface, "isDataTypeInterface");
|
|
3319
|
+
|
|
3320
|
+
// ../../shared/src/utils/functions/argument-names.ts
|
|
3321
|
+
var RESERVED_WORDS = [
|
|
3322
|
+
"arguments",
|
|
3323
|
+
"await",
|
|
3324
|
+
"break",
|
|
3325
|
+
"case",
|
|
3326
|
+
"catch",
|
|
3327
|
+
"class",
|
|
3328
|
+
"const",
|
|
3329
|
+
"continue",
|
|
3330
|
+
"debugger",
|
|
3331
|
+
"default",
|
|
3332
|
+
"delete",
|
|
3333
|
+
"do",
|
|
3334
|
+
"else",
|
|
3335
|
+
"enum",
|
|
3336
|
+
"eval",
|
|
3337
|
+
"export",
|
|
3338
|
+
"extends",
|
|
3339
|
+
"false",
|
|
3340
|
+
"finally",
|
|
3341
|
+
"for",
|
|
3342
|
+
"function",
|
|
3343
|
+
"if",
|
|
3344
|
+
"implements",
|
|
3345
|
+
"import",
|
|
3346
|
+
"in",
|
|
3347
|
+
"instanceof",
|
|
3348
|
+
"interface",
|
|
3349
|
+
"let",
|
|
3350
|
+
"new",
|
|
3351
|
+
"null",
|
|
3352
|
+
"package",
|
|
3353
|
+
"private",
|
|
3354
|
+
"protected",
|
|
3355
|
+
"public",
|
|
3356
|
+
"return",
|
|
3357
|
+
"static",
|
|
3358
|
+
"super",
|
|
3359
|
+
"switch",
|
|
3360
|
+
"this",
|
|
3361
|
+
"throw",
|
|
3362
|
+
"true",
|
|
3363
|
+
"try",
|
|
3364
|
+
"typeof",
|
|
3365
|
+
"var",
|
|
3366
|
+
"void",
|
|
3367
|
+
"while",
|
|
3368
|
+
"with",
|
|
3369
|
+
"yield"
|
|
3370
|
+
];
|
|
3371
|
+
var SERVICE_ARGUMENT_PROFILE = Object.freeze({
|
|
3372
|
+
reserved: Object.freeze([
|
|
3373
|
+
"observe",
|
|
3374
|
+
"options",
|
|
3375
|
+
"url",
|
|
3376
|
+
"params",
|
|
3377
|
+
"headers",
|
|
3378
|
+
"formData",
|
|
3379
|
+
"formBody"
|
|
3380
|
+
]),
|
|
3381
|
+
bindsRequestBody: true
|
|
3382
|
+
});
|
|
3383
|
+
var RESOURCE_ARGUMENT_PROFILE = Object.freeze({
|
|
3384
|
+
reserved: Object.freeze([
|
|
3385
|
+
"resourceOptions",
|
|
3386
|
+
"requestOptions",
|
|
3387
|
+
"params",
|
|
3388
|
+
"headers"
|
|
3389
|
+
]),
|
|
3390
|
+
bindsRequestBody: false
|
|
3391
|
+
});
|
|
3392
|
+
var REQUEST_BODY_KEY = /* @__PURE__ */ Symbol("requestBody");
|
|
3393
|
+
function resolveArgumentNames(operation, config, profile) {
|
|
3394
|
+
let byConfig = RESOLVED.get(operation);
|
|
3395
|
+
if (!byConfig) {
|
|
3396
|
+
byConfig = /* @__PURE__ */ new WeakMap();
|
|
3397
|
+
RESOLVED.set(operation, byConfig);
|
|
3398
|
+
}
|
|
3399
|
+
let byProfile = byConfig.get(config);
|
|
3400
|
+
if (!byProfile) {
|
|
3401
|
+
byProfile = /* @__PURE__ */ new WeakMap();
|
|
3402
|
+
byConfig.set(config, byProfile);
|
|
3403
|
+
}
|
|
3404
|
+
const cached = byProfile.get(profile);
|
|
3405
|
+
if (cached) {
|
|
3406
|
+
return cached;
|
|
3407
|
+
}
|
|
3408
|
+
const resolved = computeArgumentNames(operation, config, profile);
|
|
3409
|
+
byProfile.set(profile, resolved);
|
|
3410
|
+
return resolved;
|
|
3411
|
+
}
|
|
3412
|
+
__name(resolveArgumentNames, "resolveArgumentNames");
|
|
3413
|
+
var RESOLVED = /* @__PURE__ */ new WeakMap();
|
|
3414
|
+
function computeArgumentNames(operation, config, profile) {
|
|
3415
|
+
const entries = [
|
|
3416
|
+
...operation.pathParams.map((param) => ({
|
|
3417
|
+
key: param.name,
|
|
3418
|
+
base: camelCase(param.name)
|
|
3419
|
+
})),
|
|
3420
|
+
...operation.formDataFields.map((field) => ({
|
|
3421
|
+
key: field,
|
|
3422
|
+
base: camelCase(field)
|
|
3423
|
+
})),
|
|
3424
|
+
...operation.urlEncodedFields.map((field) => ({
|
|
3425
|
+
key: field,
|
|
3426
|
+
base: camelCase(field)
|
|
3427
|
+
}))
|
|
3428
|
+
];
|
|
3429
|
+
const bodyBase = profile.bindsRequestBody ? jsonBodyIdentifier(operation, config) : void 0;
|
|
3430
|
+
if (bodyBase !== void 0) {
|
|
3431
|
+
entries.push({
|
|
3432
|
+
key: REQUEST_BODY_KEY,
|
|
3433
|
+
base: bodyBase
|
|
3434
|
+
});
|
|
3435
|
+
}
|
|
3436
|
+
entries.push(...operation.queryParams.map((param) => ({
|
|
3437
|
+
key: param.name,
|
|
3438
|
+
base: camelCase(param.name)
|
|
3439
|
+
})));
|
|
3440
|
+
const identifiers = /* @__PURE__ */ new Map();
|
|
3441
|
+
const used = /* @__PURE__ */ new Set([
|
|
3442
|
+
...profile.reserved,
|
|
3443
|
+
...RESERVED_WORDS
|
|
3444
|
+
]);
|
|
3445
|
+
const renamed2 = [];
|
|
3446
|
+
const merged = /* @__PURE__ */ new Set();
|
|
3447
|
+
for (const { key, base } of entries) {
|
|
3448
|
+
if (identifiers.has(key)) {
|
|
3449
|
+
if (typeof key === "string") {
|
|
3450
|
+
merged.add(key);
|
|
3451
|
+
}
|
|
3452
|
+
continue;
|
|
3453
|
+
}
|
|
3454
|
+
let identifier = base;
|
|
3455
|
+
let suffix = 2;
|
|
3456
|
+
while (used.has(identifier)) {
|
|
3457
|
+
identifier = `${base}${suffix}`;
|
|
3458
|
+
suffix++;
|
|
3459
|
+
}
|
|
3460
|
+
if (identifier !== base) {
|
|
3461
|
+
renamed2.push(Object.freeze({
|
|
3462
|
+
source: typeof key === "string" ? key : base,
|
|
3463
|
+
identifier
|
|
3464
|
+
}));
|
|
3465
|
+
}
|
|
3466
|
+
used.add(identifier);
|
|
3467
|
+
identifiers.set(key, identifier);
|
|
3468
|
+
}
|
|
3469
|
+
return {
|
|
3470
|
+
// The fallback runs the *same* rules the resolver would have, rather
|
|
3471
|
+
// than a bare camelCase: an unregistered wire name otherwise came back
|
|
3472
|
+
// as `class` or `options`, names the resolver never assigns.
|
|
3473
|
+
// Uniquified against everything already assigned, not just the reserved
|
|
3474
|
+
// words: an unregistered wire name that camelCases onto an identifier
|
|
3475
|
+
// this operation already bound would otherwise alias it — compiling
|
|
3476
|
+
// fine and sending the wrong value. Only reachable for operations built
|
|
3477
|
+
// outside the normalizer, but the resolver is public API.
|
|
3478
|
+
of: /* @__PURE__ */ __name((wireName) => identifiers.get(wireName) ?? deriveLocalName(camelCase(wireName), [
|
|
3479
|
+
...used
|
|
3480
|
+
]), "of"),
|
|
3481
|
+
body: identifiers.get(REQUEST_BODY_KEY),
|
|
3482
|
+
all: Object.freeze([
|
|
3483
|
+
...identifiers.values()
|
|
3484
|
+
]),
|
|
3485
|
+
renamed: Object.freeze(renamed2),
|
|
3486
|
+
merged: Object.freeze([
|
|
3487
|
+
...merged
|
|
3488
|
+
])
|
|
3489
|
+
};
|
|
3490
|
+
}
|
|
3491
|
+
__name(computeArgumentNames, "computeArgumentNames");
|
|
3492
|
+
function jsonBodyIdentifier(operation, config) {
|
|
3493
|
+
if (!operation.requestBody || operation.isMultipart) {
|
|
3494
|
+
return void 0;
|
|
3495
|
+
}
|
|
3496
|
+
if (!operation.requestBody.content?.[CONTENT_TYPES.JSON]) {
|
|
3497
|
+
return void 0;
|
|
3498
|
+
}
|
|
3499
|
+
const bodyType = getRequestBodyType(operation.requestBody, config);
|
|
3500
|
+
return isDataTypeInterface(bodyType) ? camelCase(bodyType) : "requestBody";
|
|
3501
|
+
}
|
|
3502
|
+
__name(jsonBodyIdentifier, "jsonBodyIdentifier");
|
|
3503
|
+
function deriveLocalName(base, taken) {
|
|
3504
|
+
const used = new Set(taken);
|
|
3505
|
+
let name = base;
|
|
3506
|
+
let suffix = 2;
|
|
3507
|
+
while (used.has(name)) {
|
|
3508
|
+
name = `${base}${suffix}`;
|
|
3509
|
+
suffix++;
|
|
3510
|
+
}
|
|
3511
|
+
return name;
|
|
3512
|
+
}
|
|
3513
|
+
__name(deriveLocalName, "deriveLocalName");
|
|
3514
|
+
|
|
3005
3515
|
// ../../shared/src/emit/url.emit.ts
|
|
3006
3516
|
function plainParamValue(identifier) {
|
|
3007
3517
|
return identifier;
|
|
@@ -3011,24 +3521,34 @@ function signalAwareParamValue(identifier) {
|
|
|
3011
3521
|
return `typeof ${identifier} === 'function' ? ${identifier}() : ${identifier}`;
|
|
3012
3522
|
}
|
|
3013
3523
|
__name(signalAwareParamValue, "signalAwareParamValue");
|
|
3014
|
-
function emitUrlExpression(path3, pathParams, paramValue = plainParamValue) {
|
|
3015
|
-
|
|
3524
|
+
function emitUrlExpression(path3, pathParams, argumentNames, paramValue = plainParamValue) {
|
|
3525
|
+
const declared = new Set(pathParams.map((param) => param.name));
|
|
3526
|
+
const unresolved = (path3.match(/{([^{}]*)}/g) ?? []).map((placeholder) => placeholder.slice(1, -1)).filter((name) => !declared.has(name));
|
|
3527
|
+
if (unresolved.length > 0) {
|
|
3528
|
+
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);
|
|
3529
|
+
}
|
|
3530
|
+
let urlExpression = "`${this.basePath}" + escapeTemplateLiteral(path3) + "`";
|
|
3016
3531
|
pathParams.forEach((param) => {
|
|
3017
|
-
|
|
3532
|
+
const replacement = "${" + paramValue(argumentNames.of(param.name)) + "}";
|
|
3533
|
+
urlExpression = urlExpression.split(`{${escapeTemplateLiteral(param.name)}}`).join(replacement);
|
|
3018
3534
|
});
|
|
3019
3535
|
return urlExpression;
|
|
3020
3536
|
}
|
|
3021
3537
|
__name(emitUrlExpression, "emitUrlExpression");
|
|
3022
3538
|
|
|
3023
3539
|
// ../../shared/src/emit/query-params.emit.ts
|
|
3024
|
-
function emitSignalAwareQueryParams(queryParams) {
|
|
3540
|
+
function emitSignalAwareQueryParams(queryParams, argumentNames) {
|
|
3025
3541
|
if (queryParams.length === 0) {
|
|
3026
3542
|
return "";
|
|
3027
3543
|
}
|
|
3028
|
-
const paramMappings = queryParams.map((param) =>
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3544
|
+
const paramMappings = queryParams.map((param) => {
|
|
3545
|
+
const identifier = argumentNames.of(param.name);
|
|
3546
|
+
const local = deriveLocalName(`${identifier}Value`, argumentNames.all);
|
|
3547
|
+
return `const ${local} = ${signalAwareParamValue(identifier)};
|
|
3548
|
+
if (${local} != null) {
|
|
3549
|
+
params = HttpParamsBuilder.addToHttpParams(params, ${local}, ${quoteLiteral(param.name)});
|
|
3550
|
+
}`;
|
|
3551
|
+
}).join("\n");
|
|
3032
3552
|
return `
|
|
3033
3553
|
let params = new HttpParams();
|
|
3034
3554
|
${paramMappings}`;
|
|
@@ -3064,7 +3584,11 @@ function joinRequestOptionEntries(entries) {
|
|
|
3064
3584
|
}
|
|
3065
3585
|
__name(joinRequestOptionEntries, "joinRequestOptionEntries");
|
|
3066
3586
|
|
|
3587
|
+
// ../../shared/src/emit/text-file.emit.ts
|
|
3588
|
+
var import_ts_morph = require("ts-morph");
|
|
3589
|
+
|
|
3067
3590
|
// ../../shared/src/utils/project.utils.ts
|
|
3591
|
+
var import_ts_morph2 = require("ts-morph");
|
|
3068
3592
|
function listGeneratedFileNames(project, directoryPath, suffix) {
|
|
3069
3593
|
const directory = project.getDirectory(directoryPath);
|
|
3070
3594
|
if (!directory) {
|
|
@@ -3075,22 +3599,149 @@ function listGeneratedFileNames(project, directoryPath, suffix) {
|
|
|
3075
3599
|
__name(listGeneratedFileNames, "listGeneratedFileNames");
|
|
3076
3600
|
|
|
3077
3601
|
// ../../shared/src/utils/functions/token-names.ts
|
|
3078
|
-
function
|
|
3079
|
-
|
|
3602
|
+
function effectiveClientName(clientName) {
|
|
3603
|
+
return clientName ? clientName : "default";
|
|
3604
|
+
}
|
|
3605
|
+
__name(effectiveClientName, "effectiveClientName");
|
|
3606
|
+
function tokenSuffix(clientName) {
|
|
3607
|
+
return effectiveClientName(clientName).toUpperCase().replace(/[^A-Z0-9]/g, "_");
|
|
3608
|
+
}
|
|
3609
|
+
__name(tokenSuffix, "tokenSuffix");
|
|
3610
|
+
function getClientContextTokenName(clientName) {
|
|
3611
|
+
const clientSuffix = tokenSuffix(clientName);
|
|
3080
3612
|
return `CLIENT_CONTEXT_TOKEN_${clientSuffix}`;
|
|
3081
3613
|
}
|
|
3082
3614
|
__name(getClientContextTokenName, "getClientContextTokenName");
|
|
3083
|
-
function getBasePathTokenName(clientName
|
|
3084
|
-
const clientSuffix = clientName
|
|
3615
|
+
function getBasePathTokenName(clientName) {
|
|
3616
|
+
const clientSuffix = tokenSuffix(clientName);
|
|
3085
3617
|
return `BASE_PATH_${clientSuffix}`;
|
|
3086
3618
|
}
|
|
3087
3619
|
__name(getBasePathTokenName, "getBasePathTokenName");
|
|
3088
3620
|
|
|
3089
|
-
// ../../shared/src/utils/functions/
|
|
3090
|
-
function
|
|
3091
|
-
|
|
3621
|
+
// ../../shared/src/utils/functions/controller-groups.ts
|
|
3622
|
+
function groupOperationsByController(operations, onWarning) {
|
|
3623
|
+
const groups = {};
|
|
3624
|
+
const controllerByFold = /* @__PURE__ */ new Map();
|
|
3625
|
+
const tagSpellings = /* @__PURE__ */ new Map();
|
|
3626
|
+
const namelessTags = /* @__PURE__ */ new Set();
|
|
3627
|
+
operations.forEach((operation) => {
|
|
3628
|
+
const tag = operation.tags?.[0];
|
|
3629
|
+
let rawName = "Default";
|
|
3630
|
+
if (tag !== void 0) {
|
|
3631
|
+
rawName = tag;
|
|
3632
|
+
} else {
|
|
3633
|
+
const pathParts = operation.path.split("/").filter((part) => part && !part.startsWith("{"));
|
|
3634
|
+
if (pathParts.length > 1) {
|
|
3635
|
+
rawName = pathParts[1];
|
|
3636
|
+
}
|
|
3637
|
+
}
|
|
3638
|
+
const sanitized = pascalCase(rawName);
|
|
3639
|
+
const isNameless = !/\p{L}/u.test(sanitized);
|
|
3640
|
+
const candidate = isNameless ? "Default" : sanitized;
|
|
3641
|
+
const fold = candidate.toLowerCase();
|
|
3642
|
+
const controllerName = controllerByFold.get(fold) ?? candidate;
|
|
3643
|
+
controllerByFold.set(fold, controllerName);
|
|
3644
|
+
if (tag !== void 0 && isNameless) {
|
|
3645
|
+
namelessTags.add(tag);
|
|
3646
|
+
} else if (tag !== void 0) {
|
|
3647
|
+
const spellings = tagSpellings.get(controllerName) ?? /* @__PURE__ */ new Set();
|
|
3648
|
+
spellings.add(tag);
|
|
3649
|
+
tagSpellings.set(controllerName, spellings);
|
|
3650
|
+
}
|
|
3651
|
+
if (!groups[controllerName]) {
|
|
3652
|
+
groups[controllerName] = [];
|
|
3653
|
+
}
|
|
3654
|
+
groups[controllerName].push(operation);
|
|
3655
|
+
});
|
|
3656
|
+
for (const tag of namelessTags) {
|
|
3657
|
+
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.`);
|
|
3658
|
+
}
|
|
3659
|
+
for (const [controllerName, spellings] of tagSpellings) {
|
|
3660
|
+
if (spellings.size > 1) {
|
|
3661
|
+
onWarning?.(`Tags ${[
|
|
3662
|
+
...spellings
|
|
3663
|
+
].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.`);
|
|
3664
|
+
}
|
|
3665
|
+
}
|
|
3666
|
+
return groups;
|
|
3092
3667
|
}
|
|
3093
|
-
__name(
|
|
3668
|
+
__name(groupOperationsByController, "groupOperationsByController");
|
|
3669
|
+
|
|
3670
|
+
// ../../shared/src/utils/functions/method-names.ts
|
|
3671
|
+
var RESERVED_MEMBER_NAMES = Object.freeze([
|
|
3672
|
+
"constructor",
|
|
3673
|
+
"httpClient",
|
|
3674
|
+
"basePath",
|
|
3675
|
+
"clientContextToken",
|
|
3676
|
+
"createContextWithClientId"
|
|
3677
|
+
]);
|
|
3678
|
+
var RESERVED_MEMBER_SET = new Set(RESERVED_MEMBER_NAMES);
|
|
3679
|
+
function reservedMemberCollision(operation, config) {
|
|
3680
|
+
if (config.options.customizeMethodName || !operation.operationId) {
|
|
3681
|
+
return void 0;
|
|
3682
|
+
}
|
|
3683
|
+
const natural = camelCase(operation.operationId);
|
|
3684
|
+
return RESERVED_MEMBER_SET.has(natural) ? {
|
|
3685
|
+
from: natural,
|
|
3686
|
+
to: `_${natural}`
|
|
3687
|
+
} : void 0;
|
|
3688
|
+
}
|
|
3689
|
+
__name(reservedMemberCollision, "reservedMemberCollision");
|
|
3690
|
+
function getOperationMethodName(operation, config) {
|
|
3691
|
+
const customize = config.options.customizeMethodName;
|
|
3692
|
+
if (!customize) {
|
|
3693
|
+
return defaultOperationMethodName(operation);
|
|
3694
|
+
}
|
|
3695
|
+
if (operation.operationId == null) {
|
|
3696
|
+
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);
|
|
3697
|
+
}
|
|
3698
|
+
const customName = customize(operation.operationId);
|
|
3699
|
+
if (!isValidIdentifier(customName) || RESERVED_MEMBER_SET.has(customName)) {
|
|
3700
|
+
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);
|
|
3701
|
+
}
|
|
3702
|
+
return customName;
|
|
3703
|
+
}
|
|
3704
|
+
__name(getOperationMethodName, "getOperationMethodName");
|
|
3705
|
+
function defaultOperationMethodName(operation) {
|
|
3706
|
+
if (operation.operationId) {
|
|
3707
|
+
const name = camelCase(operation.operationId);
|
|
3708
|
+
return RESERVED_MEMBER_SET.has(name) ? `_${name}` : name;
|
|
3709
|
+
}
|
|
3710
|
+
const method = pascalCase(operation.method.toLowerCase());
|
|
3711
|
+
const pathParts = operation.path.split("/").filter((segment) => segment !== "").map((segment) => pascalCase(segment));
|
|
3712
|
+
const resource = pathParts.join("") || "resource";
|
|
3713
|
+
return `${camelCase(resource)}${method}`;
|
|
3714
|
+
}
|
|
3715
|
+
__name(defaultOperationMethodName, "defaultOperationMethodName");
|
|
3716
|
+
|
|
3717
|
+
// ../../shared/src/utils/functions/distinct-member-names.ts
|
|
3718
|
+
function assertDistinctMemberNames(serviceClass, className, operations, methodNameOf) {
|
|
3719
|
+
const methodNames = serviceClass.getMethods().map((method) => method.getName());
|
|
3720
|
+
const propertyNames = new Set(serviceClass.getProperties().map((property) => property.getName()));
|
|
3721
|
+
const duplicates = [
|
|
3722
|
+
...new Set(methodNames.filter((name, index) => methodNames.indexOf(name) !== index || propertyNames.has(name)))
|
|
3723
|
+
];
|
|
3724
|
+
if (duplicates.length === 0) {
|
|
3725
|
+
return;
|
|
3726
|
+
}
|
|
3727
|
+
const byName = new Map(duplicates.map((name) => [
|
|
3728
|
+
name,
|
|
3729
|
+
[]
|
|
3730
|
+
]));
|
|
3731
|
+
for (const operation of operations) {
|
|
3732
|
+
byName.get(methodNameOf(operation))?.push(operation);
|
|
3733
|
+
}
|
|
3734
|
+
const detail = [
|
|
3735
|
+
...byName
|
|
3736
|
+
].map(([name, ops]) => {
|
|
3737
|
+
const from = ops.map(describeOperation).join(" and ");
|
|
3738
|
+
return propertyNames.has(name) ? `"${name}" from ${from} (a property of ${className})` : `"${name}" from ${from}`;
|
|
3739
|
+
}).join("; ");
|
|
3740
|
+
throw new DuplicateGeneratedNameError(`Operations map to the same member name in ${className}: ${detail}. Ensure each operationId maps to a unique name.`, duplicates, [
|
|
3741
|
+
...byName.values()
|
|
3742
|
+
].flat());
|
|
3743
|
+
}
|
|
3744
|
+
__name(assertDistinctMemberNames, "assertDistinctMemberNames");
|
|
3094
3745
|
|
|
3095
3746
|
// ../../shared/src/config/constants.ts
|
|
3096
3747
|
var disableLinting = `// @ts-nocheck
|
|
@@ -3143,6 +3794,14 @@ var HttpResourceMethodBodyGenerator = class {
|
|
|
3143
3794
|
constructor(config) {
|
|
3144
3795
|
this.config = config;
|
|
3145
3796
|
}
|
|
3797
|
+
/**
|
|
3798
|
+
* The plugin reserves its own bindings (`resourceOptions`/`requestOptions`),
|
|
3799
|
+
* not the core service's — resolving against the wrong set would let a
|
|
3800
|
+
* `requestOptions` query parameter capture the plugin's own parameter.
|
|
3801
|
+
*/
|
|
3802
|
+
argumentNames(operation) {
|
|
3803
|
+
return resolveArgumentNames(operation, this.config, RESOURCE_ARGUMENT_PROFILE);
|
|
3804
|
+
}
|
|
3146
3805
|
generateMethodBody(operation) {
|
|
3147
3806
|
const bodyParts = [
|
|
3148
3807
|
this.generateDefaultHeaders(operation),
|
|
@@ -3174,7 +3833,7 @@ var HttpResourceMethodBodyGenerator = class {
|
|
|
3174
3833
|
}
|
|
3175
3834
|
generateRequestOptions(operation) {
|
|
3176
3835
|
const entries = [];
|
|
3177
|
-
const url = emitUrlExpression(operation.path, operation.pathParams, signalAwareParamValue);
|
|
3836
|
+
const url = emitUrlExpression(operation.path, operation.pathParams, this.argumentNames(operation), signalAwareParamValue);
|
|
3178
3837
|
entries.push(`url: ${url}`);
|
|
3179
3838
|
entries.push(`method: "GET"`);
|
|
3180
3839
|
entries.push("...requestOptions");
|
|
@@ -3192,7 +3851,7 @@ var HttpResourceMethodBodyGenerator = class {
|
|
|
3192
3851
|
}
|
|
3193
3852
|
generateHttpResource(operation) {
|
|
3194
3853
|
const resourceOptions = this.generateRequestOptions(operation);
|
|
3195
|
-
const queryParams = emitSignalAwareQueryParams(operation.queryParams);
|
|
3854
|
+
const queryParams = emitSignalAwareQueryParams(operation.queryParams, this.argumentNames(operation));
|
|
3196
3855
|
let httpResource = "httpResource";
|
|
3197
3856
|
switch (operation.responseType) {
|
|
3198
3857
|
case "blob":
|
|
@@ -3240,13 +3899,14 @@ var HttpResourceMethodParamsGenerator = class {
|
|
|
3240
3899
|
}
|
|
3241
3900
|
generateApiParameters(operation) {
|
|
3242
3901
|
const params = [];
|
|
3902
|
+
const argumentNames = resolveArgumentNames(operation, this.config, RESOURCE_ARGUMENT_PROFILE);
|
|
3243
3903
|
operation.pathParams.forEach((param) => {
|
|
3244
3904
|
const paramType = getTypeScriptType(param.schema || {
|
|
3245
3905
|
...param
|
|
3246
3906
|
}, this.config);
|
|
3247
3907
|
const signalParamType = param.required ? `Signal<${paramType}>` : `Signal<${paramType} | undefined>`;
|
|
3248
3908
|
params.push({
|
|
3249
|
-
name:
|
|
3909
|
+
name: argumentNames.of(param.name),
|
|
3250
3910
|
type: `${signalParamType} | ${paramType}`,
|
|
3251
3911
|
hasQuestionToken: !param.required
|
|
3252
3912
|
});
|
|
@@ -3257,7 +3917,7 @@ var HttpResourceMethodParamsGenerator = class {
|
|
|
3257
3917
|
}, this.config);
|
|
3258
3918
|
const signalParamType = param.required ? `Signal<${paramType}>` : `Signal<${paramType} | undefined>`;
|
|
3259
3919
|
params.push({
|
|
3260
|
-
name:
|
|
3920
|
+
name: argumentNames.of(param.name),
|
|
3261
3921
|
type: `${signalParamType} | ${paramType}`,
|
|
3262
3922
|
hasQuestionToken: !param.required
|
|
3263
3923
|
});
|
|
@@ -3328,31 +3988,11 @@ var HttpResourceMethodGenerator = class {
|
|
|
3328
3988
|
returnType,
|
|
3329
3989
|
statements: methodBody,
|
|
3330
3990
|
overloads,
|
|
3331
|
-
docs: operation.description
|
|
3332
|
-
operation.description
|
|
3333
|
-
] : void 0
|
|
3991
|
+
docs: emitDocs(operation.description)
|
|
3334
3992
|
});
|
|
3335
3993
|
}
|
|
3336
3994
|
generateMethodName(operation) {
|
|
3337
|
-
|
|
3338
|
-
if (operation.operationId == null) {
|
|
3339
|
-
throw new Error(`Operation ID is required for method name customization of operation: (${operation.method}) ${operation.path}`);
|
|
3340
|
-
}
|
|
3341
|
-
return this.config.options.customizeMethodName(operation.operationId);
|
|
3342
|
-
} else {
|
|
3343
|
-
return this.defaultNameGenerator(operation);
|
|
3344
|
-
}
|
|
3345
|
-
}
|
|
3346
|
-
defaultNameGenerator(operation) {
|
|
3347
|
-
if (operation.operationId) {
|
|
3348
|
-
return camelCase(operation.operationId);
|
|
3349
|
-
}
|
|
3350
|
-
const method = pascalCase(operation.method.toLowerCase());
|
|
3351
|
-
const pathParts = operation.path.split("/").map((str2) => {
|
|
3352
|
-
return pascalCase(pascalCase(str2).replace(/[^a-zA-Z0-9]/g, ""));
|
|
3353
|
-
});
|
|
3354
|
-
const resource = pathParts.join("") || "resource";
|
|
3355
|
-
return `${camelCase(resource)}${method}`;
|
|
3995
|
+
return getOperationMethodName(operation, this.config);
|
|
3356
3996
|
}
|
|
3357
3997
|
generateReturnType(operation) {
|
|
3358
3998
|
const response = operation.responses?.["200"] || operation.responses?.["201"] || operation.responses?.["204"];
|
|
@@ -3427,7 +4067,6 @@ var HttpResourceIndexGenerator = class {
|
|
|
3427
4067
|
});
|
|
3428
4068
|
});
|
|
3429
4069
|
sourceFile.formatText();
|
|
3430
|
-
sourceFile.saveSync();
|
|
3431
4070
|
}
|
|
3432
4071
|
};
|
|
3433
4072
|
|
|
@@ -3457,32 +4096,15 @@ var HttpResourceGenerator = class {
|
|
|
3457
4096
|
this.onWarning?.("No API paths found in the specification");
|
|
3458
4097
|
return;
|
|
3459
4098
|
}
|
|
3460
|
-
const controllerGroups = this.
|
|
3461
|
-
await Promise.all(
|
|
3462
|
-
|
|
3463
|
-
|
|
4099
|
+
const controllerGroups = groupOperationsByController(paths, this.onWarning);
|
|
4100
|
+
await Promise.all(
|
|
4101
|
+
// Must return the promise: without it Promise.all awaits [undefined],
|
|
4102
|
+
// and a generateServiceFile rejection escapes as an unhandled
|
|
4103
|
+
// rejection while generation reports success.
|
|
4104
|
+
Object.entries(controllerGroups).map(([controllerName, operations]) => this.generateServiceFile(controllerName, operations, outputDir))
|
|
4105
|
+
);
|
|
3464
4106
|
this.indexGenerator.generateIndex(outputRoot);
|
|
3465
4107
|
}
|
|
3466
|
-
groupPathsByController(paths) {
|
|
3467
|
-
const groups = {};
|
|
3468
|
-
paths.forEach((path3) => {
|
|
3469
|
-
let controllerName = "Default";
|
|
3470
|
-
if (path3.tags && path3.tags.length > 0) {
|
|
3471
|
-
controllerName = path3.tags[0];
|
|
3472
|
-
} else {
|
|
3473
|
-
const pathParts = path3.path.split("/").filter((p) => p && !p.startsWith("{"));
|
|
3474
|
-
if (pathParts.length > 1) {
|
|
3475
|
-
controllerName = pascalCase(pathParts[1]);
|
|
3476
|
-
}
|
|
3477
|
-
}
|
|
3478
|
-
controllerName = pascalCase(controllerName);
|
|
3479
|
-
if (!groups[controllerName]) {
|
|
3480
|
-
groups[controllerName] = [];
|
|
3481
|
-
}
|
|
3482
|
-
groups[controllerName].push(path3);
|
|
3483
|
-
});
|
|
3484
|
-
return groups;
|
|
3485
|
-
}
|
|
3486
4108
|
async generateServiceFile(controllerName, operations, outputDir) {
|
|
3487
4109
|
const fileName = `${camelCase(controllerName)}.resource.ts`;
|
|
3488
4110
|
const filePath = path2.join(outputDir, fileName);
|
|
@@ -3492,7 +4114,6 @@ var HttpResourceGenerator = class {
|
|
|
3492
4114
|
this.addServiceClass(sourceFile, controllerName, operations);
|
|
3493
4115
|
sourceFile.fixMissingImports().formatText();
|
|
3494
4116
|
sourceFile.insertText(0, HTTP_RESOURCE_GENERATOR_HEADER_COMMENT(getResourceClassName(controllerName, this.config.options.naming?.resources)));
|
|
3495
|
-
sourceFile.saveSync();
|
|
3496
4117
|
}
|
|
3497
4118
|
addServiceClass(sourceFile, controllerName, operations) {
|
|
3498
4119
|
const className = getResourceClassName(controllerName, this.config.options.naming?.resources);
|
|
@@ -3545,20 +4166,20 @@ var HttpResourceGenerator = class {
|
|
|
3545
4166
|
serviceClass.addProperty({
|
|
3546
4167
|
name: "basePath",
|
|
3547
4168
|
type: "string",
|
|
3548
|
-
scope:
|
|
4169
|
+
scope: import_ts_morph3.Scope.Private,
|
|
3549
4170
|
isReadonly: true,
|
|
3550
4171
|
initializer: `inject(${basePathTokenName})`
|
|
3551
4172
|
});
|
|
3552
4173
|
serviceClass.addProperty({
|
|
3553
4174
|
name: "clientContextToken",
|
|
3554
4175
|
type: "HttpContextToken<string>",
|
|
3555
|
-
scope:
|
|
4176
|
+
scope: import_ts_morph3.Scope.Private,
|
|
3556
4177
|
isReadonly: true,
|
|
3557
4178
|
initializer: clientContextTokenName
|
|
3558
4179
|
});
|
|
3559
4180
|
serviceClass.addMethod({
|
|
3560
4181
|
name: "createContextWithClientId",
|
|
3561
|
-
scope:
|
|
4182
|
+
scope: import_ts_morph3.Scope.Private,
|
|
3562
4183
|
parameters: [
|
|
3563
4184
|
{
|
|
3564
4185
|
name: "existingContext",
|
|
@@ -3568,14 +4189,23 @@ var HttpResourceGenerator = class {
|
|
|
3568
4189
|
],
|
|
3569
4190
|
returnType: "HttpContext",
|
|
3570
4191
|
statements: `const context = existingContext || new HttpContext();
|
|
3571
|
-
return context.set(this.clientContextToken,
|
|
4192
|
+
return context.set(this.clientContextToken, ${quoteLiteral(effectiveClientName(this.config.clientName))});`
|
|
3572
4193
|
});
|
|
3573
4194
|
operations.forEach((operation) => {
|
|
4195
|
+
const { renamed: renamed2, merged } = resolveArgumentNames(operation, this.config, RESOURCE_ARGUMENT_PROFILE);
|
|
4196
|
+
for (const { source, identifier } of renamed2) {
|
|
4197
|
+
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.`);
|
|
4198
|
+
}
|
|
4199
|
+
for (const wireName of merged) {
|
|
4200
|
+
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.`);
|
|
4201
|
+
}
|
|
4202
|
+
const collision = reservedMemberCollision(operation, this.config);
|
|
4203
|
+
if (collision) {
|
|
4204
|
+
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.`);
|
|
4205
|
+
}
|
|
3574
4206
|
this.methodGenerator.addResourceMethod(serviceClass, operation);
|
|
3575
4207
|
});
|
|
3576
|
-
|
|
3577
|
-
throw new Error(`Duplicate method names found in service class ${className}. Please ensure unique method names for each operation.`);
|
|
3578
|
-
}
|
|
4208
|
+
assertDistinctMemberNames(serviceClass, className, operations, (op) => this.methodGenerator.generateMethodName(op));
|
|
3579
4209
|
}
|
|
3580
4210
|
};
|
|
3581
4211
|
// Annotate the CommonJS export names for ESM import in node:
|