@ps-aux/api-client-gen 0.7.0-rc.2 → 0.7.0-rc.4
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/README.md +14 -6
- package/dist/bin.cjs +78 -10
- package/dist/bin.mjs +60 -11
- package/dist/generateApiClient.cjs +2023 -1372
- package/dist/generateApiClient.mjs +2024 -1376
- package/dist/index.cjs +4 -3
- package/dist/index.d.cts +2177 -19
- package/dist/index.d.mts +2177 -19
- package/dist/index.d.ts +2177 -19
- package/dist/index.mjs +4 -4
- package/package.json +8 -5
- package/templates/http-client.eta +10 -1
- package/templates/procedure-call.ejs +2 -2
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var Path
|
|
3
|
+
var Path = require('path');
|
|
4
4
|
var fs$2 = require('fs');
|
|
5
5
|
var fs = require('fs/promises');
|
|
6
|
-
var Path = require('node:path');
|
|
7
|
-
var promises = require('node:fs/promises');
|
|
8
|
-
var fs$1 = require('node:fs');
|
|
9
6
|
var swaggerTypescriptApi = require('swagger-typescript-api');
|
|
10
7
|
var node_url = require('node:url');
|
|
8
|
+
var promises = require('node:fs/promises');
|
|
9
|
+
var Path$1 = require('node:path');
|
|
10
|
+
var fs$1 = require('node:fs');
|
|
11
11
|
var tsToZod = require('ts-to-zod');
|
|
12
12
|
|
|
13
13
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
@@ -572,69 +572,6 @@ function formatError(error, mapper = (issue) => issue.message) {
|
|
|
572
572
|
processError(error);
|
|
573
573
|
return fieldErrors;
|
|
574
574
|
}
|
|
575
|
-
/** Format a ZodError as a human-readable string in the following form.
|
|
576
|
-
*
|
|
577
|
-
* From
|
|
578
|
-
*
|
|
579
|
-
* ```ts
|
|
580
|
-
* ZodError {
|
|
581
|
-
* issues: [
|
|
582
|
-
* {
|
|
583
|
-
* expected: 'string',
|
|
584
|
-
* code: 'invalid_type',
|
|
585
|
-
* path: [ 'username' ],
|
|
586
|
-
* message: 'Invalid input: expected string'
|
|
587
|
-
* },
|
|
588
|
-
* {
|
|
589
|
-
* expected: 'number',
|
|
590
|
-
* code: 'invalid_type',
|
|
591
|
-
* path: [ 'favoriteNumbers', 1 ],
|
|
592
|
-
* message: 'Invalid input: expected number'
|
|
593
|
-
* }
|
|
594
|
-
* ];
|
|
595
|
-
* }
|
|
596
|
-
* ```
|
|
597
|
-
*
|
|
598
|
-
* to
|
|
599
|
-
*
|
|
600
|
-
* ```
|
|
601
|
-
* username
|
|
602
|
-
* ✖ Expected number, received string at "username
|
|
603
|
-
* favoriteNumbers[0]
|
|
604
|
-
* ✖ Invalid input: expected number
|
|
605
|
-
* ```
|
|
606
|
-
*/
|
|
607
|
-
function toDotPath(_path) {
|
|
608
|
-
const segs = [];
|
|
609
|
-
const path = _path.map((seg) => (typeof seg === "object" ? seg.key : seg));
|
|
610
|
-
for (const seg of path) {
|
|
611
|
-
if (typeof seg === "number")
|
|
612
|
-
segs.push(`[${seg}]`);
|
|
613
|
-
else if (typeof seg === "symbol")
|
|
614
|
-
segs.push(`[${JSON.stringify(String(seg))}]`);
|
|
615
|
-
else if (/[^\w$]/.test(seg))
|
|
616
|
-
segs.push(`[${JSON.stringify(seg)}]`);
|
|
617
|
-
else {
|
|
618
|
-
if (segs.length)
|
|
619
|
-
segs.push(".");
|
|
620
|
-
segs.push(seg);
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
return segs.join("");
|
|
624
|
-
}
|
|
625
|
-
function prettifyError(error) {
|
|
626
|
-
const lines = [];
|
|
627
|
-
// sort by path length
|
|
628
|
-
const issues = [...error.issues].sort((a, b) => (a.path ?? []).length - (b.path ?? []).length);
|
|
629
|
-
// Process each issue
|
|
630
|
-
for (const issue of issues) {
|
|
631
|
-
lines.push(`✖ ${issue.message}`);
|
|
632
|
-
if (issue.path?.length)
|
|
633
|
-
lines.push(` → at ${toDotPath(issue.path)}`);
|
|
634
|
-
}
|
|
635
|
-
// Convert Map to formatted string
|
|
636
|
-
return lines.join("\n");
|
|
637
|
-
}
|
|
638
575
|
|
|
639
576
|
const _parse = (_Err) => (schema, value, _ctx, _params) => {
|
|
640
577
|
const ctx = _ctx ? Object.assign(_ctx, { async: false }) : { async: false };
|
|
@@ -785,6 +722,7 @@ const string$1 = (params) => {
|
|
|
785
722
|
const regex = params ? `[\\s\\S]{${params?.minimum ?? 0},${params?.maximum ?? ""}}` : `[\\s\\S]*`;
|
|
786
723
|
return new RegExp(`^${regex}$`);
|
|
787
724
|
};
|
|
725
|
+
const number = /^-?\d+(?:\.\d+)?$/;
|
|
788
726
|
const boolean$1 = /^(?:true|false)$/i;
|
|
789
727
|
// regex for string with no uppercase letters
|
|
790
728
|
const lowercase = /^[^A-Z]*$/;
|
|
@@ -1981,6 +1919,122 @@ function handleIntersectionResults(result, left, right) {
|
|
|
1981
1919
|
result.value = merged.data;
|
|
1982
1920
|
return result;
|
|
1983
1921
|
}
|
|
1922
|
+
const $ZodRecord = /*@__PURE__*/ $constructor("$ZodRecord", (inst, def) => {
|
|
1923
|
+
$ZodType.init(inst, def);
|
|
1924
|
+
inst._zod.parse = (payload, ctx) => {
|
|
1925
|
+
const input = payload.value;
|
|
1926
|
+
if (!isPlainObject(input)) {
|
|
1927
|
+
payload.issues.push({
|
|
1928
|
+
expected: "record",
|
|
1929
|
+
code: "invalid_type",
|
|
1930
|
+
input,
|
|
1931
|
+
inst,
|
|
1932
|
+
});
|
|
1933
|
+
return payload;
|
|
1934
|
+
}
|
|
1935
|
+
const proms = [];
|
|
1936
|
+
const values = def.keyType._zod.values;
|
|
1937
|
+
if (values) {
|
|
1938
|
+
payload.value = {};
|
|
1939
|
+
const recordKeys = new Set();
|
|
1940
|
+
for (const key of values) {
|
|
1941
|
+
if (typeof key === "string" || typeof key === "number" || typeof key === "symbol") {
|
|
1942
|
+
recordKeys.add(typeof key === "number" ? key.toString() : key);
|
|
1943
|
+
const result = def.valueType._zod.run({ value: input[key], issues: [] }, ctx);
|
|
1944
|
+
if (result instanceof Promise) {
|
|
1945
|
+
proms.push(result.then((result) => {
|
|
1946
|
+
if (result.issues.length) {
|
|
1947
|
+
payload.issues.push(...prefixIssues(key, result.issues));
|
|
1948
|
+
}
|
|
1949
|
+
payload.value[key] = result.value;
|
|
1950
|
+
}));
|
|
1951
|
+
}
|
|
1952
|
+
else {
|
|
1953
|
+
if (result.issues.length) {
|
|
1954
|
+
payload.issues.push(...prefixIssues(key, result.issues));
|
|
1955
|
+
}
|
|
1956
|
+
payload.value[key] = result.value;
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
let unrecognized;
|
|
1961
|
+
for (const key in input) {
|
|
1962
|
+
if (!recordKeys.has(key)) {
|
|
1963
|
+
unrecognized = unrecognized ?? [];
|
|
1964
|
+
unrecognized.push(key);
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
if (unrecognized && unrecognized.length > 0) {
|
|
1968
|
+
payload.issues.push({
|
|
1969
|
+
code: "unrecognized_keys",
|
|
1970
|
+
input,
|
|
1971
|
+
inst,
|
|
1972
|
+
keys: unrecognized,
|
|
1973
|
+
});
|
|
1974
|
+
}
|
|
1975
|
+
}
|
|
1976
|
+
else {
|
|
1977
|
+
payload.value = {};
|
|
1978
|
+
for (const key of Reflect.ownKeys(input)) {
|
|
1979
|
+
if (key === "__proto__")
|
|
1980
|
+
continue;
|
|
1981
|
+
let keyResult = def.keyType._zod.run({ value: key, issues: [] }, ctx);
|
|
1982
|
+
if (keyResult instanceof Promise) {
|
|
1983
|
+
throw new Error("Async schemas not supported in object keys currently");
|
|
1984
|
+
}
|
|
1985
|
+
// Numeric string fallback: if key is a numeric string and failed, retry with Number(key)
|
|
1986
|
+
// This handles z.number(), z.literal([1, 2, 3]), and unions containing numeric literals
|
|
1987
|
+
const checkNumericKey = typeof key === "string" && number.test(key) && keyResult.issues.length;
|
|
1988
|
+
if (checkNumericKey) {
|
|
1989
|
+
const retryResult = def.keyType._zod.run({ value: Number(key), issues: [] }, ctx);
|
|
1990
|
+
if (retryResult instanceof Promise) {
|
|
1991
|
+
throw new Error("Async schemas not supported in object keys currently");
|
|
1992
|
+
}
|
|
1993
|
+
if (retryResult.issues.length === 0) {
|
|
1994
|
+
keyResult = retryResult;
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
if (keyResult.issues.length) {
|
|
1998
|
+
if (def.mode === "loose") {
|
|
1999
|
+
// Pass through unchanged
|
|
2000
|
+
payload.value[key] = input[key];
|
|
2001
|
+
}
|
|
2002
|
+
else {
|
|
2003
|
+
// Default "strict" behavior: error on invalid key
|
|
2004
|
+
payload.issues.push({
|
|
2005
|
+
code: "invalid_key",
|
|
2006
|
+
origin: "record",
|
|
2007
|
+
issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),
|
|
2008
|
+
input: key,
|
|
2009
|
+
path: [key],
|
|
2010
|
+
inst,
|
|
2011
|
+
});
|
|
2012
|
+
}
|
|
2013
|
+
continue;
|
|
2014
|
+
}
|
|
2015
|
+
const result = def.valueType._zod.run({ value: input[key], issues: [] }, ctx);
|
|
2016
|
+
if (result instanceof Promise) {
|
|
2017
|
+
proms.push(result.then((result) => {
|
|
2018
|
+
if (result.issues.length) {
|
|
2019
|
+
payload.issues.push(...prefixIssues(key, result.issues));
|
|
2020
|
+
}
|
|
2021
|
+
payload.value[keyResult.value] = result.value;
|
|
2022
|
+
}));
|
|
2023
|
+
}
|
|
2024
|
+
else {
|
|
2025
|
+
if (result.issues.length) {
|
|
2026
|
+
payload.issues.push(...prefixIssues(key, result.issues));
|
|
2027
|
+
}
|
|
2028
|
+
payload.value[keyResult.value] = result.value;
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2032
|
+
if (proms.length) {
|
|
2033
|
+
return Promise.all(proms).then(() => payload);
|
|
2034
|
+
}
|
|
2035
|
+
return payload;
|
|
2036
|
+
};
|
|
2037
|
+
});
|
|
1984
2038
|
const $ZodEnum = /*@__PURE__*/ $constructor("$ZodEnum", (inst, def) => {
|
|
1985
2039
|
$ZodType.init(inst, def);
|
|
1986
2040
|
const values = getEnumValues(def.entries);
|
|
@@ -3377,6 +3431,49 @@ const intersectionProcessor = (schema, ctx, json, params) => {
|
|
|
3377
3431
|
];
|
|
3378
3432
|
json.allOf = allOf;
|
|
3379
3433
|
};
|
|
3434
|
+
const recordProcessor = (schema, ctx, _json, params) => {
|
|
3435
|
+
const json = _json;
|
|
3436
|
+
const def = schema._zod.def;
|
|
3437
|
+
json.type = "object";
|
|
3438
|
+
// For looseRecord with regex patterns, use patternProperties
|
|
3439
|
+
// This correctly represents "only validate keys matching the pattern" semantics
|
|
3440
|
+
// and composes well with allOf (intersections)
|
|
3441
|
+
const keyType = def.keyType;
|
|
3442
|
+
const keyBag = keyType._zod.bag;
|
|
3443
|
+
const patterns = keyBag?.patterns;
|
|
3444
|
+
if (def.mode === "loose" && patterns && patterns.size > 0) {
|
|
3445
|
+
// Use patternProperties for looseRecord with regex patterns
|
|
3446
|
+
const valueSchema = process(def.valueType, ctx, {
|
|
3447
|
+
...params,
|
|
3448
|
+
path: [...params.path, "patternProperties", "*"],
|
|
3449
|
+
});
|
|
3450
|
+
json.patternProperties = {};
|
|
3451
|
+
for (const pattern of patterns) {
|
|
3452
|
+
json.patternProperties[pattern.source] = valueSchema;
|
|
3453
|
+
}
|
|
3454
|
+
}
|
|
3455
|
+
else {
|
|
3456
|
+
// Default behavior: use propertyNames + additionalProperties
|
|
3457
|
+
if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
|
|
3458
|
+
json.propertyNames = process(def.keyType, ctx, {
|
|
3459
|
+
...params,
|
|
3460
|
+
path: [...params.path, "propertyNames"],
|
|
3461
|
+
});
|
|
3462
|
+
}
|
|
3463
|
+
json.additionalProperties = process(def.valueType, ctx, {
|
|
3464
|
+
...params,
|
|
3465
|
+
path: [...params.path, "additionalProperties"],
|
|
3466
|
+
});
|
|
3467
|
+
}
|
|
3468
|
+
// Add required for keys with discrete values (enum, literal, etc.)
|
|
3469
|
+
const keyValues = keyType._zod.values;
|
|
3470
|
+
if (keyValues) {
|
|
3471
|
+
const validKeyValues = [...keyValues].filter((v) => typeof v === "string" || typeof v === "number");
|
|
3472
|
+
if (validKeyValues.length > 0) {
|
|
3473
|
+
json.required = validKeyValues;
|
|
3474
|
+
}
|
|
3475
|
+
}
|
|
3476
|
+
};
|
|
3380
3477
|
const nullableProcessor = (schema, ctx, json, params) => {
|
|
3381
3478
|
const def = schema._zod.def;
|
|
3382
3479
|
const inner = process(def.innerType, ctx, params);
|
|
@@ -3880,6 +3977,21 @@ function intersection(left, right) {
|
|
|
3880
3977
|
right: right,
|
|
3881
3978
|
});
|
|
3882
3979
|
}
|
|
3980
|
+
const ZodRecord = /*@__PURE__*/ $constructor("ZodRecord", (inst, def) => {
|
|
3981
|
+
$ZodRecord.init(inst, def);
|
|
3982
|
+
ZodType.init(inst, def);
|
|
3983
|
+
inst._zod.processJSONSchema = (ctx, json, params) => recordProcessor(inst, ctx, json, params);
|
|
3984
|
+
inst.keyType = def.keyType;
|
|
3985
|
+
inst.valueType = def.valueType;
|
|
3986
|
+
});
|
|
3987
|
+
function record(keyType, valueType, params) {
|
|
3988
|
+
return new ZodRecord({
|
|
3989
|
+
type: "record",
|
|
3990
|
+
keyType,
|
|
3991
|
+
valueType: valueType,
|
|
3992
|
+
...normalizeParams(params),
|
|
3993
|
+
});
|
|
3994
|
+
}
|
|
3883
3995
|
const ZodEnum = /*@__PURE__*/ $constructor("ZodEnum", (inst, def) => {
|
|
3884
3996
|
$ZodEnum.init(inst, def);
|
|
3885
3997
|
ZodType.init(inst, def);
|
|
@@ -4103,6 +4215,73 @@ function superRefine(fn) {
|
|
|
4103
4215
|
return _superRefine(fn);
|
|
4104
4216
|
}
|
|
4105
4217
|
|
|
4218
|
+
const vNextOasGeneratorSchema = strictObject({
|
|
4219
|
+
selection: strictObject({
|
|
4220
|
+
ignoreOperationsWithTags: array(string()).default([]),
|
|
4221
|
+
allSchemas: boolean().default(true)
|
|
4222
|
+
}).optional(),
|
|
4223
|
+
codegen: strictObject({
|
|
4224
|
+
unwrap: boolean().default(true),
|
|
4225
|
+
withRequestParams: boolean().default(false),
|
|
4226
|
+
pathParamsStyle: _enum(["object", "positional"]).default("positional"),
|
|
4227
|
+
enumStyle: _enum(["enum", "union"]).default("enum"),
|
|
4228
|
+
comments: strictObject({
|
|
4229
|
+
enabled: boolean().default(true),
|
|
4230
|
+
operation: strictObject({
|
|
4231
|
+
tags: boolean().default(true),
|
|
4232
|
+
summary: boolean().default(true),
|
|
4233
|
+
description: boolean().default(true)
|
|
4234
|
+
}).prefault({}),
|
|
4235
|
+
schema: strictObject({
|
|
4236
|
+
metadata: boolean().default(true)
|
|
4237
|
+
}).prefault({})
|
|
4238
|
+
}).prefault({})
|
|
4239
|
+
}).prefault({}),
|
|
4240
|
+
compat: strictObject({
|
|
4241
|
+
uppercaseEnumKeys: boolean(),
|
|
4242
|
+
swaggerTsApiRequiredBooleans: boolean()
|
|
4243
|
+
}).optional()
|
|
4244
|
+
});
|
|
4245
|
+
const legacyOasGeneratorSchema = strictObject({
|
|
4246
|
+
legacy: strictObject({
|
|
4247
|
+
ignoreOperationsWithTags: array(string()).optional()
|
|
4248
|
+
})
|
|
4249
|
+
});
|
|
4250
|
+
const profileConfigSchema = strictObject({
|
|
4251
|
+
srcSpec: string().trim().min(1),
|
|
4252
|
+
dstDir: string().trim().min(1),
|
|
4253
|
+
apiName: string().trim().min(1),
|
|
4254
|
+
openApiGenerator: union([
|
|
4255
|
+
vNextOasGeneratorSchema,
|
|
4256
|
+
legacyOasGeneratorSchema
|
|
4257
|
+
]),
|
|
4258
|
+
responseWrapper: strictObject({
|
|
4259
|
+
symbol: string().trim().min(1),
|
|
4260
|
+
import: string().trim().min(1).optional(),
|
|
4261
|
+
unwrapExpr: string().optional()
|
|
4262
|
+
}).optional(),
|
|
4263
|
+
zodSchemas: strictObject({
|
|
4264
|
+
enabled: boolean().optional(),
|
|
4265
|
+
localDateTimes: boolean().optional()
|
|
4266
|
+
}).optional()
|
|
4267
|
+
});
|
|
4268
|
+
const configSchema = record(string(), profileConfigSchema);
|
|
4269
|
+
const defineConfig = (config) => config;
|
|
4270
|
+
const parseConfig = (userConfig, filePath) => {
|
|
4271
|
+
const parsed = configSchema.safeParse(userConfig);
|
|
4272
|
+
if (parsed.success) return parsed.data;
|
|
4273
|
+
throw new Error(`Invalid config at ${filePath}: ${parsed.error.message}`, {
|
|
4274
|
+
cause: parsed.error
|
|
4275
|
+
});
|
|
4276
|
+
};
|
|
4277
|
+
const parseProfileConfig = (userConfig, filePath) => {
|
|
4278
|
+
const parsed = profileConfigSchema.safeParse(userConfig);
|
|
4279
|
+
if (parsed.success) return parsed.data;
|
|
4280
|
+
throw new Error(`Invalid config at ${filePath}: ${parsed.error.message}`, {
|
|
4281
|
+
cause: parsed.error
|
|
4282
|
+
});
|
|
4283
|
+
};
|
|
4284
|
+
|
|
4106
4285
|
const downloadSpec = async (path, url) => {
|
|
4107
4286
|
let response;
|
|
4108
4287
|
try {
|
|
@@ -4122,6 +4301,86 @@ const downloadSpec = async (path, url) => {
|
|
|
4122
4301
|
await fs.writeFile(path, content);
|
|
4123
4302
|
};
|
|
4124
4303
|
|
|
4304
|
+
const toPascalCaseIdentifier = (str) => {
|
|
4305
|
+
const words = str.replace(/([a-z0-9])([A-Z])/g, "$1 $2").split(/[^a-zA-Z0-9]+/).filter(Boolean);
|
|
4306
|
+
const pascalCase = words.map((word) => word[0].toUpperCase() + word.substring(1)).join("");
|
|
4307
|
+
if (!pascalCase.length) return "Api";
|
|
4308
|
+
if (/^[0-9]/.test(pascalCase)) return `Api${pascalCase}`;
|
|
4309
|
+
return pascalCase;
|
|
4310
|
+
};
|
|
4311
|
+
const groupBy = (values, getKey) => {
|
|
4312
|
+
const groups = /* @__PURE__ */ new Map();
|
|
4313
|
+
for (const value of values) {
|
|
4314
|
+
const key = getKey(value);
|
|
4315
|
+
const existing = groups.get(key);
|
|
4316
|
+
if (existing) {
|
|
4317
|
+
existing.push(value);
|
|
4318
|
+
} else {
|
|
4319
|
+
groups.set(key, [value]);
|
|
4320
|
+
}
|
|
4321
|
+
}
|
|
4322
|
+
return groups;
|
|
4323
|
+
};
|
|
4324
|
+
|
|
4325
|
+
const generateOpenApiClient = async (inputFile, {
|
|
4326
|
+
name,
|
|
4327
|
+
outputDir,
|
|
4328
|
+
ignoreOperationsWithTags
|
|
4329
|
+
}, log) => {
|
|
4330
|
+
log(`Will generate API client name=${name} to ${outputDir}`);
|
|
4331
|
+
const fileName = "index";
|
|
4332
|
+
const dstFile = Path.join(outputDir, `${fileName}.ts`);
|
|
4333
|
+
const prettier = await import('prettier');
|
|
4334
|
+
const prettierConfig = await prettier.resolveConfig(dstFile) ?? {};
|
|
4335
|
+
const prettierConfigForGenerator = {
|
|
4336
|
+
...prettierConfig,
|
|
4337
|
+
// swagger-typescript-api defaults to printWidth=120; keep Prettier default 80 unless explicitly configured.
|
|
4338
|
+
printWidth: prettierConfig.printWidth ?? 80
|
|
4339
|
+
};
|
|
4340
|
+
const ignoreTags = ignoreOperationsWithTags && new Set(ignoreOperationsWithTags);
|
|
4341
|
+
await swaggerTypescriptApi.generateApi({
|
|
4342
|
+
name: "index",
|
|
4343
|
+
output: outputDir,
|
|
4344
|
+
input: inputFile,
|
|
4345
|
+
// modular: true,
|
|
4346
|
+
httpClientType: "axios",
|
|
4347
|
+
templates: getTemplatesDir(),
|
|
4348
|
+
defaultResponseAsSuccess: true,
|
|
4349
|
+
sortTypes: true,
|
|
4350
|
+
// generateRouteTypes: true,
|
|
4351
|
+
singleHttpClient: true,
|
|
4352
|
+
// extractRequestBody: true,
|
|
4353
|
+
prettier: prettierConfigForGenerator,
|
|
4354
|
+
moduleNameFirstTag: true,
|
|
4355
|
+
apiClassName: toPascalCaseIdentifier(name),
|
|
4356
|
+
hooks: {
|
|
4357
|
+
onCreateRoute: (routeData) => {
|
|
4358
|
+
if (ignoreTags) {
|
|
4359
|
+
const ignore = routeData.raw.tags?.find(
|
|
4360
|
+
(t) => ignoreTags.has(t)
|
|
4361
|
+
);
|
|
4362
|
+
if (ignore) return false;
|
|
4363
|
+
}
|
|
4364
|
+
return routeData;
|
|
4365
|
+
}
|
|
4366
|
+
},
|
|
4367
|
+
// @ts-ignore
|
|
4368
|
+
codeGenConstructs: () => ({
|
|
4369
|
+
Keyword: {}
|
|
4370
|
+
})
|
|
4371
|
+
// extractRequestParams: true,
|
|
4372
|
+
});
|
|
4373
|
+
return { types: dstFile, promiseWrapper: [dstFile] };
|
|
4374
|
+
};
|
|
4375
|
+
const getThisScriptDirname = () => {
|
|
4376
|
+
return Path.dirname(node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('generateApiClient.cjs', document.baseURI).href))));
|
|
4377
|
+
};
|
|
4378
|
+
const getTemplatesDir = () => {
|
|
4379
|
+
const currentDir = getThisScriptDirname();
|
|
4380
|
+
const templatesRelativePath = Path.basename(currentDir) === "dist" ? "../templates" : "../../../templates";
|
|
4381
|
+
return Path.resolve(currentDir, templatesRelativePath);
|
|
4382
|
+
};
|
|
4383
|
+
|
|
4125
4384
|
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4126
4385
|
const asRecord = (value) => {
|
|
4127
4386
|
return isRecord(value) ? value : void 0;
|
|
@@ -4176,9 +4435,9 @@ const resolveLocalRef = (root, ref) => {
|
|
|
4176
4435
|
return current;
|
|
4177
4436
|
};
|
|
4178
4437
|
|
|
4179
|
-
var __defProp$
|
|
4180
|
-
var __defNormalProp$
|
|
4181
|
-
var __publicField$
|
|
4438
|
+
var __defProp$a = Object.defineProperty;
|
|
4439
|
+
var __defNormalProp$a = (obj, key, value) => key in obj ? __defProp$a(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4440
|
+
var __publicField$a = (obj, key, value) => __defNormalProp$a(obj, key + "" , value);
|
|
4182
4441
|
const PARAMETER_LOCATIONS = [
|
|
4183
4442
|
"path",
|
|
4184
4443
|
"query",
|
|
@@ -4204,7 +4463,7 @@ const mergeParameters = (base, override) => {
|
|
|
4204
4463
|
class OpenApiNormalizer {
|
|
4205
4464
|
constructor(doc) {
|
|
4206
4465
|
this.doc = doc;
|
|
4207
|
-
__publicField$
|
|
4466
|
+
__publicField$a(this, "problems", []);
|
|
4208
4467
|
}
|
|
4209
4468
|
load() {
|
|
4210
4469
|
const info = readRecord(this.doc, "info");
|
|
@@ -4547,44 +4806,24 @@ const syntheticOperationId = (method, path) => {
|
|
|
4547
4806
|
return `_${compact}`;
|
|
4548
4807
|
};
|
|
4549
4808
|
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
if (!pascalCase.length) return "Api";
|
|
4554
|
-
if (/^[0-9]/.test(pascalCase)) return `Api${pascalCase}`;
|
|
4555
|
-
return pascalCase;
|
|
4556
|
-
};
|
|
4557
|
-
const groupBy = (values, getKey) => {
|
|
4558
|
-
const groups = /* @__PURE__ */ new Map();
|
|
4559
|
-
for (const value of values) {
|
|
4560
|
-
const key = getKey(value);
|
|
4561
|
-
const existing = groups.get(key);
|
|
4562
|
-
if (existing) {
|
|
4563
|
-
existing.push(value);
|
|
4564
|
-
} else {
|
|
4565
|
-
groups.set(key, [value]);
|
|
4566
|
-
}
|
|
4567
|
-
}
|
|
4568
|
-
return groups;
|
|
4569
|
-
};
|
|
4570
|
-
|
|
4571
|
-
var httpClientCommonTypesSource = "export type KnownRequestContentType =\n | 'application/json'\n | 'multipart/form-data'\n | 'application/x-www-form-urlencoded'\n\nexport type RequestContentType = KnownRequestContentType | string\n\nexport type QueryValue =\n | string\n | number\n | boolean\n | null\n | undefined\n | QueryValue[]\n | Record<string, any>\n // Empty schema support\n | unknown\n\nexport type QueryParams = Record<string, QueryValue>\n\nexport type Request = {\n path: string\n method: 'GET' | 'POST' | 'PUT' | 'DELETE'\n format?: 'json' | 'document'\n headers?: Record<string, string>\n query?: QueryParams\n body?: any\n requestContentType?: RequestContentType\n}\n\nexport type QuerySerializer = (params: QueryParams) => string\n";
|
|
4572
|
-
|
|
4573
|
-
var httpClientPromiseTypesSource = "import type { Request } from './common-types'\n\nexport type HttpClient<RequestParams = never> = {\n request: <Data>(req: Request, params?: RequestParams) => Promise<Data>\n}\n";
|
|
4574
|
-
|
|
4575
|
-
var __defProp$8 = Object.defineProperty;
|
|
4576
|
-
var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4577
|
-
var __publicField$8 = (obj, key, value) => __defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4809
|
+
var __defProp$9 = Object.defineProperty;
|
|
4810
|
+
var __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4811
|
+
var __publicField$9 = (obj, key, value) => __defNormalProp$9(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4578
4812
|
class TsCodegen {
|
|
4579
|
-
constructor(typeExprCodegen) {
|
|
4813
|
+
constructor(typeExprCodegen, docRenderer) {
|
|
4580
4814
|
this.typeExprCodegen = typeExprCodegen;
|
|
4581
|
-
__publicField$
|
|
4582
|
-
__publicField$
|
|
4583
|
-
__publicField$
|
|
4815
|
+
__publicField$9(this, "usedTypeRefs", []);
|
|
4816
|
+
__publicField$9(this, "usedTypeRefKeys", /* @__PURE__ */ new Set());
|
|
4817
|
+
__publicField$9(this, "docRenderer");
|
|
4818
|
+
__publicField$9(this, "typeExpr", (typeExpr) => {
|
|
4584
4819
|
this.collectTypeRefsFromExpr(typeExpr);
|
|
4585
4820
|
return this.typeExprCodegen.toCode(typeExpr).code;
|
|
4586
4821
|
});
|
|
4587
|
-
__publicField$
|
|
4822
|
+
__publicField$9(this, "declaration", (name, declaration, options = {}) => {
|
|
4823
|
+
this.collectTypeRefsFromDeclaration(declaration);
|
|
4824
|
+
return this.toDeclarationCode(name, declaration, options);
|
|
4825
|
+
});
|
|
4826
|
+
__publicField$9(this, "toChunk", (name, code, exports$1) => {
|
|
4588
4827
|
const exportedSymbols = new Set(exports$1);
|
|
4589
4828
|
const refs = this.getTypeRefs().filter((ref) => {
|
|
4590
4829
|
return ref.kind !== "internal" || !exportedSymbols.has(ref.name);
|
|
@@ -4596,9 +4835,44 @@ class TsCodegen {
|
|
|
4596
4835
|
refs
|
|
4597
4836
|
};
|
|
4598
4837
|
});
|
|
4599
|
-
__publicField$
|
|
4838
|
+
__publicField$9(this, "getTypeRefs", () => {
|
|
4600
4839
|
return this.usedTypeRefs.map((ref) => ({ ...ref }));
|
|
4601
4840
|
});
|
|
4841
|
+
__publicField$9(this, "toDeclarationCode", (name, d, o) => {
|
|
4842
|
+
let code = this.toDeclarationBodyCode(name, d);
|
|
4843
|
+
if (o.exported) {
|
|
4844
|
+
code = `export ${code}`;
|
|
4845
|
+
}
|
|
4846
|
+
return this.addDoc(code, d.doc);
|
|
4847
|
+
});
|
|
4848
|
+
__publicField$9(this, "toDeclarationBodyCode", (name, declaration) => {
|
|
4849
|
+
switch (declaration.kind) {
|
|
4850
|
+
case "typeAlias":
|
|
4851
|
+
return `type ${name} = ${this.typeExprCodegen.toCode(declaration.typeExpr).code}`;
|
|
4852
|
+
case "enum": {
|
|
4853
|
+
const members = declaration.members.map((member) => {
|
|
4854
|
+
const code = `${member.name} = ${JSON.stringify(member.value)}`;
|
|
4855
|
+
return this.addDoc(code, member.doc);
|
|
4856
|
+
}).join(",\n");
|
|
4857
|
+
return `enum ${name} {
|
|
4858
|
+
${members}
|
|
4859
|
+
}`;
|
|
4860
|
+
}
|
|
4861
|
+
default: {
|
|
4862
|
+
const exhaustive = declaration;
|
|
4863
|
+
throw new Error(
|
|
4864
|
+
`Unsupported TypeScript declaration: ${String(exhaustive)}`
|
|
4865
|
+
);
|
|
4866
|
+
}
|
|
4867
|
+
}
|
|
4868
|
+
});
|
|
4869
|
+
__publicField$9(this, "addDoc", (code, doc) => {
|
|
4870
|
+
if (!doc) return code;
|
|
4871
|
+
const rendered = this.docRenderer.render(doc);
|
|
4872
|
+
return rendered ? `${rendered}
|
|
4873
|
+
${code}` : code;
|
|
4874
|
+
});
|
|
4875
|
+
this.docRenderer = docRenderer;
|
|
4602
4876
|
}
|
|
4603
4877
|
collectTypeRef(typeRef) {
|
|
4604
4878
|
if (typeRef.kind === "builtin") return;
|
|
@@ -4607,6 +4881,11 @@ class TsCodegen {
|
|
|
4607
4881
|
this.usedTypeRefKeys.add(key);
|
|
4608
4882
|
this.usedTypeRefs.push({ ...typeRef });
|
|
4609
4883
|
}
|
|
4884
|
+
collectTypeRefsFromDeclaration(declaration) {
|
|
4885
|
+
if (declaration.kind === "typeAlias") {
|
|
4886
|
+
this.collectTypeRefsFromExpr(declaration.typeExpr);
|
|
4887
|
+
}
|
|
4888
|
+
}
|
|
4610
4889
|
collectTypeRefsFromExpr(typeExpr) {
|
|
4611
4890
|
if (typeExpr.kind === "reference") {
|
|
4612
4891
|
this.collectTypeRef(typeExpr.ref);
|
|
@@ -4687,20 +4966,45 @@ const RESERVED_WORDS = /* @__PURE__ */ new Set([
|
|
|
4687
4966
|
"with",
|
|
4688
4967
|
"yield"
|
|
4689
4968
|
]);
|
|
4690
|
-
const TS_IDENTIFIER_PATTERN = /^[$A-Z_][0-9A-Z_$]*$/i;
|
|
4969
|
+
const TS_IDENTIFIER_PATTERN$1 = /^[$A-Z_][0-9A-Z_$]*$/i;
|
|
4691
4970
|
const isTsIdentifier = (value) => {
|
|
4692
|
-
return TS_IDENTIFIER_PATTERN.test(value);
|
|
4971
|
+
return TS_IDENTIFIER_PATTERN$1.test(value);
|
|
4972
|
+
};
|
|
4973
|
+
const splitIdentifierWords = (value) => {
|
|
4974
|
+
return value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").split(/[^a-zA-Z0-9]+/).filter(Boolean);
|
|
4975
|
+
};
|
|
4976
|
+
const toTsCamelIdentifier = (value, opts = {}) => {
|
|
4977
|
+
const words = splitIdentifierWords(value);
|
|
4978
|
+
if (!words.length) {
|
|
4979
|
+
throw new Error(
|
|
4980
|
+
`Could not derive a TypeScript identifier from "${value}".`
|
|
4981
|
+
);
|
|
4982
|
+
}
|
|
4983
|
+
const [firstWord, ...restWords] = words;
|
|
4984
|
+
let identifier = [
|
|
4985
|
+
firstWord[0].toLowerCase() + firstWord.substring(1),
|
|
4986
|
+
...restWords.map((word) => word[0].toUpperCase() + word.substring(1))
|
|
4987
|
+
].join("");
|
|
4988
|
+
if (/^[0-9]/.test(identifier)) {
|
|
4989
|
+
const prefix = opts.leadingDigitPrefix ?? "value";
|
|
4990
|
+
identifier = `${prefix}${identifier[0].toUpperCase()}${identifier.substring(1)}`;
|
|
4991
|
+
}
|
|
4992
|
+
if (RESERVED_WORDS.has(identifier)) {
|
|
4993
|
+
identifier = `${identifier}_`;
|
|
4994
|
+
}
|
|
4995
|
+
return identifier;
|
|
4693
4996
|
};
|
|
4694
4997
|
const toTsPropertyKey = (value) => {
|
|
4695
4998
|
return isTsIdentifier(value) ? value : JSON.stringify(value);
|
|
4696
4999
|
};
|
|
4697
5000
|
|
|
4698
|
-
var __defProp$
|
|
4699
|
-
var __defNormalProp$
|
|
4700
|
-
var __publicField$
|
|
5001
|
+
var __defProp$8 = Object.defineProperty;
|
|
5002
|
+
var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
5003
|
+
var __publicField$8 = (obj, key, value) => __defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4701
5004
|
class TypeExprCodegen {
|
|
4702
|
-
constructor() {
|
|
4703
|
-
__publicField$
|
|
5005
|
+
constructor(docRenderer) {
|
|
5006
|
+
__publicField$8(this, "docRenderer");
|
|
5007
|
+
__publicField$8(this, "toCode", (typeExpr) => {
|
|
4704
5008
|
switch (typeExpr.kind) {
|
|
4705
5009
|
case "reference":
|
|
4706
5010
|
return this.toReferenceCode(typeExpr);
|
|
@@ -4716,7 +5020,7 @@ class TypeExprCodegen {
|
|
|
4716
5020
|
}
|
|
4717
5021
|
}
|
|
4718
5022
|
});
|
|
4719
|
-
__publicField$
|
|
5023
|
+
__publicField$8(this, "toReferenceCode", (typeExpr) => {
|
|
4720
5024
|
if (!typeExpr.typeArgs?.length) {
|
|
4721
5025
|
return {
|
|
4722
5026
|
code: typeExpr.ref.name,
|
|
@@ -4729,7 +5033,7 @@ class TypeExprCodegen {
|
|
|
4729
5033
|
ref: typeExpr.ref
|
|
4730
5034
|
};
|
|
4731
5035
|
});
|
|
4732
|
-
__publicField$
|
|
5036
|
+
__publicField$8(this, "toInlineCode", (expr) => {
|
|
4733
5037
|
switch (expr.node) {
|
|
4734
5038
|
case "scalar":
|
|
4735
5039
|
return expr.name === "integer" ? "number" : expr.name;
|
|
@@ -4754,1054 +5058,1583 @@ class TypeExprCodegen {
|
|
|
4754
5058
|
}
|
|
4755
5059
|
}
|
|
4756
5060
|
});
|
|
4757
|
-
__publicField$
|
|
5061
|
+
__publicField$8(this, "toIntersectionMemberCode", (typeExpr) => {
|
|
4758
5062
|
const rendered = this.toCode(typeExpr).code;
|
|
4759
5063
|
return this.isUnion(typeExpr) ? `(${rendered})` : rendered;
|
|
4760
5064
|
});
|
|
4761
|
-
__publicField$
|
|
5065
|
+
__publicField$8(this, "toArrayElementCode", (typeExpr) => {
|
|
4762
5066
|
const rendered = this.toCode(typeExpr).code;
|
|
4763
5067
|
return this.needsGroupingForArrayElement(typeExpr) ? `(${rendered})` : rendered;
|
|
4764
5068
|
});
|
|
4765
|
-
__publicField$
|
|
5069
|
+
__publicField$8(this, "isUnion", (typeExpr) => {
|
|
4766
5070
|
return typeExpr.kind === "inline" && typeExpr.expr.node === "union";
|
|
4767
5071
|
});
|
|
4768
|
-
__publicField$
|
|
5072
|
+
__publicField$8(this, "needsGroupingForArrayElement", (typeExpr) => {
|
|
4769
5073
|
return typeExpr.kind === "inline" && (typeExpr.expr.node === "union" || typeExpr.expr.node === "intersection");
|
|
4770
5074
|
});
|
|
4771
|
-
__publicField$
|
|
5075
|
+
__publicField$8(this, "toLiteralCode", (value) => {
|
|
4772
5076
|
if (value === null) return "null";
|
|
4773
5077
|
return JSON.stringify(value);
|
|
4774
5078
|
});
|
|
4775
|
-
__publicField$
|
|
5079
|
+
__publicField$8(this, "toObjectCode", (properties, additionalProperties) => {
|
|
4776
5080
|
const members = properties.map(
|
|
4777
5081
|
(property) => this.toPropertyCode(property)
|
|
4778
5082
|
);
|
|
4779
5083
|
if (additionalProperties === true) {
|
|
4780
|
-
members.push("[key: string]: unknown");
|
|
5084
|
+
members.push("[key: string]: unknown;");
|
|
4781
5085
|
} else if (additionalProperties !== void 0 && additionalProperties !== false) {
|
|
4782
5086
|
members.push(
|
|
4783
|
-
`[key: string]: ${this.toCode(additionalProperties).code}
|
|
5087
|
+
`[key: string]: ${this.toCode(additionalProperties).code};`
|
|
4784
5088
|
);
|
|
4785
5089
|
}
|
|
4786
|
-
|
|
4787
|
-
|
|
5090
|
+
return `{
|
|
5091
|
+
${members.join("\n")}
|
|
5092
|
+
}`;
|
|
4788
5093
|
});
|
|
4789
|
-
__publicField$
|
|
5094
|
+
__publicField$8(this, "toPropertyCode", (property) => {
|
|
4790
5095
|
const name = toTsPropertyKey(property.name);
|
|
4791
5096
|
const optional = property.required ? "" : "?";
|
|
4792
|
-
|
|
4793
|
-
|
|
5097
|
+
const propertyCode = `${name}${optional}: ${this.toCode(property.typeExpr).code}`;
|
|
5098
|
+
const docCode = property.doc ? this.docRenderer.render(property.doc, {
|
|
5099
|
+
compactText: true
|
|
5100
|
+
}) : "";
|
|
5101
|
+
const renderedProperty = `${propertyCode};`;
|
|
5102
|
+
return docCode ? `${docCode}
|
|
5103
|
+
${renderedProperty}` : renderedProperty;
|
|
5104
|
+
});
|
|
5105
|
+
this.docRenderer = docRenderer;
|
|
4794
5106
|
}
|
|
4795
5107
|
}
|
|
4796
5108
|
|
|
4797
|
-
var __defProp$
|
|
4798
|
-
var __defNormalProp$
|
|
4799
|
-
var __publicField$
|
|
5109
|
+
var __defProp$7 = Object.defineProperty;
|
|
5110
|
+
var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
5111
|
+
var __publicField$7 = (obj, key, value) => __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4800
5112
|
class TsCodegenFactory {
|
|
4801
|
-
constructor() {
|
|
4802
|
-
__publicField$
|
|
4803
|
-
__publicField$
|
|
4804
|
-
|
|
4805
|
-
|
|
5113
|
+
constructor(docRenderer) {
|
|
5114
|
+
__publicField$7(this, "typeExprCodegen");
|
|
5115
|
+
__publicField$7(this, "docRenderer");
|
|
5116
|
+
__publicField$7(this, "forNewChunk", () => {
|
|
5117
|
+
return new TsCodegen(this.typeExprCodegen, this.docRenderer);
|
|
5118
|
+
});
|
|
5119
|
+
this.docRenderer = docRenderer;
|
|
5120
|
+
this.typeExprCodegen = new TypeExprCodegen(this.docRenderer);
|
|
4806
5121
|
}
|
|
4807
5122
|
}
|
|
4808
5123
|
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
}
|
|
4874
|
-
};
|
|
4875
|
-
});
|
|
4876
|
-
__publicField$5(this, "literal", (value) => ({
|
|
4877
|
-
kind: "inline",
|
|
4878
|
-
expr: {
|
|
4879
|
-
node: "literal",
|
|
4880
|
-
value
|
|
4881
|
-
}
|
|
4882
|
-
}));
|
|
4883
|
-
__publicField$5(this, "ref", (id) => {
|
|
4884
|
-
const name = this.refNameFromPath(id);
|
|
5124
|
+
const buildPathParamBindings = (paramNames) => {
|
|
5125
|
+
const usedBindings = /* @__PURE__ */ new Set();
|
|
5126
|
+
return paramNames.reduce((acc, paramName) => {
|
|
5127
|
+
acc[paramName] = toUniqueBindingName(paramName, usedBindings);
|
|
5128
|
+
return acc;
|
|
5129
|
+
}, {});
|
|
5130
|
+
};
|
|
5131
|
+
const toUniqueBindingName = (paramName, usedBindings) => {
|
|
5132
|
+
let base = toBindingBase(paramName);
|
|
5133
|
+
if (isReservedWord(base)) {
|
|
5134
|
+
base = `${base}_param`;
|
|
5135
|
+
}
|
|
5136
|
+
if (!usedBindings.has(base)) {
|
|
5137
|
+
usedBindings.add(base);
|
|
5138
|
+
return base;
|
|
5139
|
+
}
|
|
5140
|
+
let suffix = 2;
|
|
5141
|
+
let candidate = `${base}_${suffix}`;
|
|
5142
|
+
while (usedBindings.has(candidate)) {
|
|
5143
|
+
suffix += 1;
|
|
5144
|
+
candidate = `${base}_${suffix}`;
|
|
5145
|
+
}
|
|
5146
|
+
usedBindings.add(candidate);
|
|
5147
|
+
return candidate;
|
|
5148
|
+
};
|
|
5149
|
+
const toBindingBase = (paramName) => {
|
|
5150
|
+
if (isIdentifier(paramName)) {
|
|
5151
|
+
return paramName;
|
|
5152
|
+
}
|
|
5153
|
+
const sanitized = paramName.replace(/[^0-9A-Za-z_$]/g, "_");
|
|
5154
|
+
if (!sanitized.length) {
|
|
5155
|
+
return "pathParam";
|
|
5156
|
+
}
|
|
5157
|
+
if (/^[A-Za-z_$]/.test(sanitized)) {
|
|
5158
|
+
return sanitized;
|
|
5159
|
+
}
|
|
5160
|
+
return `_${sanitized}`;
|
|
5161
|
+
};
|
|
5162
|
+
const isIdentifier = (value) => {
|
|
5163
|
+
return /^[$A-Z_][0-9A-Z_$]*$/i.test(value);
|
|
5164
|
+
};
|
|
5165
|
+
const isReservedWord = (value) => {
|
|
5166
|
+
return RESERVED_WORDS.has(value);
|
|
5167
|
+
};
|
|
5168
|
+
|
|
5169
|
+
var __defProp$6 = Object.defineProperty;
|
|
5170
|
+
var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
5171
|
+
var __publicField$6 = (obj, key, value) => __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5172
|
+
class ParamsConstructor {
|
|
5173
|
+
constructor(options) {
|
|
5174
|
+
this.options = options;
|
|
5175
|
+
__publicField$6(this, "process", (params, httpPath) => {
|
|
5176
|
+
const pathParamSpec = validatePathParams(params, httpPath);
|
|
5177
|
+
const pathParamBindings = pathParamSpec?.bindings;
|
|
5178
|
+
const funParams = params.flatMap(
|
|
5179
|
+
(param) => this.renderOperationParams(param, pathParamSpec)
|
|
5180
|
+
);
|
|
5181
|
+
const hasBody = params.some((p) => p.kind === "body");
|
|
5182
|
+
const hasQuery = params.some((p) => p.kind === "query");
|
|
5183
|
+
const path = this.renderPathTemplateLiteral(
|
|
5184
|
+
httpPath,
|
|
5185
|
+
this.options.paramNames.path,
|
|
5186
|
+
pathParamBindings
|
|
5187
|
+
);
|
|
4885
5188
|
return {
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
}
|
|
5189
|
+
funParams,
|
|
5190
|
+
path,
|
|
5191
|
+
hasBody,
|
|
5192
|
+
hasQuery
|
|
4891
5193
|
};
|
|
4892
5194
|
});
|
|
4893
|
-
__publicField$
|
|
4894
|
-
kind
|
|
4895
|
-
|
|
4896
|
-
|
|
4897
|
-
|
|
5195
|
+
__publicField$6(this, "renderOperationParams", (param, pathParamSpec) => {
|
|
5196
|
+
if (param.kind !== "path" || !pathParamSpec) {
|
|
5197
|
+
return [
|
|
5198
|
+
{
|
|
5199
|
+
identifier: this.paramName(param),
|
|
5200
|
+
typeExpr: param.typeExpr
|
|
5201
|
+
}
|
|
5202
|
+
];
|
|
4898
5203
|
}
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
throw new Error(`Unsupported schema reference: ${ref}`);
|
|
5204
|
+
if (this.options.pathParamsStyle === "positional") {
|
|
5205
|
+
return pathParamSpec.placeholderNames.map((name) => ({
|
|
5206
|
+
identifier: pathParamSpec.bindings[name] ?? name,
|
|
5207
|
+
typeExpr: pathParamSpec.propertiesByName[name].typeExpr
|
|
5208
|
+
}));
|
|
4905
5209
|
}
|
|
4906
|
-
return
|
|
4907
|
-
|
|
4908
|
-
|
|
4909
|
-
|
|
5210
|
+
return [
|
|
5211
|
+
{
|
|
5212
|
+
identifier: this.renderPathParamDestructuring(
|
|
5213
|
+
pathParamSpec.bindings
|
|
5214
|
+
),
|
|
5215
|
+
typeExpr: param.typeExpr
|
|
5216
|
+
}
|
|
5217
|
+
];
|
|
4910
5218
|
});
|
|
4911
|
-
__publicField$
|
|
4912
|
-
const
|
|
4913
|
-
|
|
5219
|
+
__publicField$6(this, "renderPathTemplateLiteral", (path, pathParamVarName, pathParamBindings) => {
|
|
5220
|
+
const escapedPath = path.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
5221
|
+
const pathWithParams = escapedPath.replace(
|
|
5222
|
+
/\{([^}]+)\}/g,
|
|
5223
|
+
(_, paramName) => {
|
|
5224
|
+
const binding = pathParamBindings?.[paramName];
|
|
5225
|
+
if (binding !== void 0) {
|
|
5226
|
+
return `\${${binding}}`;
|
|
5227
|
+
}
|
|
5228
|
+
return `\${${pathParamVarName}[${JSON.stringify(paramName)}]}`;
|
|
5229
|
+
}
|
|
4914
5230
|
);
|
|
4915
|
-
return
|
|
4916
|
-
});
|
|
4917
|
-
__publicField$5(this, "ensureSchemaDefinition", (refId) => {
|
|
4918
|
-
if (this.schemaDefinitionsById.has(refId) || this.schemaDefinitionsInProgress.has(refId)) {
|
|
4919
|
-
return;
|
|
4920
|
-
}
|
|
4921
|
-
const schemaName = this.refNameFromPath(refId);
|
|
4922
|
-
const schema = this.schemas[schemaName];
|
|
4923
|
-
if (!schema) {
|
|
4924
|
-
return;
|
|
4925
|
-
}
|
|
4926
|
-
this.schemaDefinitionsInProgress.add(refId);
|
|
4927
|
-
try {
|
|
4928
|
-
const definition = {
|
|
4929
|
-
name: schemaName,
|
|
4930
|
-
typeExpr: this.fromSchema(schema)
|
|
4931
|
-
};
|
|
4932
|
-
this.schemaDefinitionsById.set(refId, definition);
|
|
4933
|
-
this.schemaDefinitions.push(definition);
|
|
4934
|
-
} finally {
|
|
4935
|
-
this.schemaDefinitionsInProgress.delete(refId);
|
|
4936
|
-
}
|
|
5231
|
+
return `\`${pathWithParams}\``;
|
|
4937
5232
|
});
|
|
4938
|
-
__publicField$
|
|
4939
|
-
|
|
4940
|
-
|
|
5233
|
+
__publicField$6(this, "renderPathParamDestructuring", (pathParamBindings) => {
|
|
5234
|
+
const members = Object.entries(pathParamBindings).map(
|
|
5235
|
+
([paramName, binding]) => {
|
|
5236
|
+
const key = toTsPropertyKey(paramName);
|
|
5237
|
+
return binding === paramName ? key : `${key}: ${binding}`;
|
|
5238
|
+
}
|
|
4941
5239
|
);
|
|
5240
|
+
return `{ ${members.join(", ")} }`;
|
|
4942
5241
|
});
|
|
4943
|
-
__publicField$
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
case "any":
|
|
4958
|
-
case "never":
|
|
4959
|
-
case "void":
|
|
4960
|
-
return true;
|
|
4961
|
-
default:
|
|
4962
|
-
return false;
|
|
4963
|
-
}
|
|
4964
|
-
});
|
|
4965
|
-
__publicField$5(this, "hasNullMember", (expr) => {
|
|
4966
|
-
if (expr.kind !== "inline") return false;
|
|
4967
|
-
if (expr.expr.node === "scalar") {
|
|
4968
|
-
return expr.expr.name === "null";
|
|
4969
|
-
}
|
|
4970
|
-
if (expr.expr.node === "union") {
|
|
4971
|
-
return expr.expr.members.some((member) => this.hasNullMember(member));
|
|
4972
|
-
}
|
|
4973
|
-
return false;
|
|
4974
|
-
});
|
|
4975
|
-
__publicField$5(this, "withNullable", (expr) => {
|
|
4976
|
-
if (this.hasNullMember(expr)) {
|
|
4977
|
-
return expr;
|
|
5242
|
+
__publicField$6(this, "paramName", (p) => {
|
|
5243
|
+
switch (p.kind) {
|
|
5244
|
+
case "body":
|
|
5245
|
+
return this.options.paramNames.body;
|
|
5246
|
+
case "query":
|
|
5247
|
+
return this.options.paramNames.query;
|
|
5248
|
+
case "path":
|
|
5249
|
+
return this.options.paramNames.path;
|
|
5250
|
+
default: {
|
|
5251
|
+
const exhaustive = p;
|
|
5252
|
+
throw new Error(
|
|
5253
|
+
`Unsupported operation parameter kind: ${String(exhaustive)}`
|
|
5254
|
+
);
|
|
5255
|
+
}
|
|
4978
5256
|
}
|
|
4979
|
-
return this.union([expr, this.scalar("null")]);
|
|
4980
|
-
});
|
|
4981
|
-
__publicField$5(this, "projectObjectType", (schema) => {
|
|
4982
|
-
const requiredRaw = schema.required;
|
|
4983
|
-
if (requiredRaw !== void 0 && !Array.isArray(requiredRaw)) {
|
|
4984
|
-
throw new Error(
|
|
4985
|
-
"Unsupported object schema: required must be an array"
|
|
4986
|
-
);
|
|
4987
|
-
}
|
|
4988
|
-
const required = new Set(
|
|
4989
|
-
(requiredRaw ?? []).map((item) => {
|
|
4990
|
-
if (typeof item !== "string") {
|
|
4991
|
-
throw new Error(
|
|
4992
|
-
"Unsupported object schema: required items must be strings"
|
|
4993
|
-
);
|
|
4994
|
-
}
|
|
4995
|
-
return item;
|
|
4996
|
-
})
|
|
4997
|
-
);
|
|
4998
|
-
const propertiesRaw = schema.properties;
|
|
4999
|
-
if (propertiesRaw !== void 0 && (!propertiesRaw || typeof propertiesRaw !== "object" || Array.isArray(propertiesRaw))) {
|
|
5000
|
-
throw new Error(
|
|
5001
|
-
"Unsupported object schema: properties must be an object"
|
|
5002
|
-
);
|
|
5003
|
-
}
|
|
5004
|
-
const properties = Object.entries(propertiesRaw ?? {}).map(
|
|
5005
|
-
([name, propertySchema]) => {
|
|
5006
|
-
if (!this.isSchemaNode(propertySchema)) {
|
|
5007
|
-
throw new Error(
|
|
5008
|
-
`Unsupported object property schema for "${name}"`
|
|
5009
|
-
);
|
|
5010
|
-
}
|
|
5011
|
-
return {
|
|
5012
|
-
name,
|
|
5013
|
-
required: this.isRequiredProperty(
|
|
5014
|
-
name,
|
|
5015
|
-
required,
|
|
5016
|
-
propertySchema
|
|
5017
|
-
),
|
|
5018
|
-
typeExpr: this.fromSchema(propertySchema)
|
|
5019
|
-
};
|
|
5020
|
-
}
|
|
5021
|
-
);
|
|
5022
|
-
let additionalProperties;
|
|
5023
|
-
if (schema.additionalProperties !== void 0) {
|
|
5024
|
-
if (typeof schema.additionalProperties === "boolean") {
|
|
5025
|
-
additionalProperties = schema.additionalProperties;
|
|
5026
|
-
} else if (this.isSchemaNode(schema.additionalProperties)) {
|
|
5027
|
-
additionalProperties = this.fromSchema(
|
|
5028
|
-
schema.additionalProperties
|
|
5029
|
-
);
|
|
5030
|
-
} else {
|
|
5031
|
-
throw new Error(
|
|
5032
|
-
"Unsupported object schema: additionalProperties must be boolean or schema object"
|
|
5033
|
-
);
|
|
5034
|
-
}
|
|
5035
|
-
}
|
|
5036
|
-
return {
|
|
5037
|
-
kind: "inline",
|
|
5038
|
-
expr: {
|
|
5039
|
-
node: "object",
|
|
5040
|
-
properties,
|
|
5041
|
-
additionalProperties
|
|
5042
|
-
}
|
|
5043
|
-
};
|
|
5044
|
-
});
|
|
5045
|
-
__publicField$5(this, "isRequiredProperty", (name, required, propertySchema) => {
|
|
5046
|
-
if (required.has(name)) {
|
|
5047
|
-
return true;
|
|
5048
|
-
}
|
|
5049
|
-
if (!this.options.quirks?.swaggerTsApiRequiredBooleans) {
|
|
5050
|
-
return false;
|
|
5051
|
-
}
|
|
5052
|
-
return propertySchema.required === true;
|
|
5053
|
-
});
|
|
5054
|
-
__publicField$5(this, "mapSchemaArrayMembers", (value, kind) => {
|
|
5055
|
-
if (!Array.isArray(value) || !value.length) {
|
|
5056
|
-
throw new Error(
|
|
5057
|
-
`Unsupported schema: ${kind} must be a non-empty array`
|
|
5058
|
-
);
|
|
5059
|
-
}
|
|
5060
|
-
return value.map((entry, index) => {
|
|
5061
|
-
if (!this.isSchemaNode(entry)) {
|
|
5062
|
-
throw new Error(
|
|
5063
|
-
`Unsupported schema: ${kind}[${index}] must be a schema object`
|
|
5064
|
-
);
|
|
5065
|
-
}
|
|
5066
|
-
return this.fromSchema(entry);
|
|
5067
|
-
});
|
|
5068
|
-
});
|
|
5069
|
-
__publicField$5(this, "isBinaryFileSchema", (schema) => {
|
|
5070
|
-
return schema.type === "string" && schema.format === "binary";
|
|
5071
|
-
});
|
|
5072
|
-
__publicField$5(this, "fromSchemaCore", (schema) => {
|
|
5073
|
-
if (this.isUnconstrainedSchema(schema)) {
|
|
5074
|
-
return this.scalar("unknown");
|
|
5075
|
-
}
|
|
5076
|
-
if (typeof schema.$ref === "string") {
|
|
5077
|
-
this.ensureSchemaDefinition(schema.$ref);
|
|
5078
|
-
return this.ref(schema.$ref);
|
|
5079
|
-
}
|
|
5080
|
-
if (schema.const !== void 0) {
|
|
5081
|
-
return this.literal(this.toLiteralValue(schema.const));
|
|
5082
|
-
}
|
|
5083
|
-
if (Array.isArray(schema.enum)) {
|
|
5084
|
-
if (!schema.enum.length) {
|
|
5085
|
-
throw new Error(
|
|
5086
|
-
"Unsupported enum schema: enum must be non-empty"
|
|
5087
|
-
);
|
|
5088
|
-
}
|
|
5089
|
-
return this.union(
|
|
5090
|
-
schema.enum.map(
|
|
5091
|
-
(value) => this.literal(this.toLiteralValue(value))
|
|
5092
|
-
)
|
|
5093
|
-
);
|
|
5094
|
-
}
|
|
5095
|
-
if (schema.type === "array") {
|
|
5096
|
-
if (schema.items === void 0) {
|
|
5097
|
-
return {
|
|
5098
|
-
kind: "inline",
|
|
5099
|
-
expr: {
|
|
5100
|
-
node: "array",
|
|
5101
|
-
element: this.scalar("unknown")
|
|
5102
|
-
}
|
|
5103
|
-
};
|
|
5104
|
-
}
|
|
5105
|
-
if (Array.isArray(schema.items)) {
|
|
5106
|
-
throw new Error("Unsupported array schema: tuple-style items");
|
|
5107
|
-
}
|
|
5108
|
-
if (!this.isSchemaNode(schema.items)) {
|
|
5109
|
-
throw new Error(
|
|
5110
|
-
"Unsupported array schema: items must be a schema"
|
|
5111
|
-
);
|
|
5112
|
-
}
|
|
5113
|
-
return {
|
|
5114
|
-
kind: "inline",
|
|
5115
|
-
expr: {
|
|
5116
|
-
node: "array",
|
|
5117
|
-
element: this.fromSchema(schema.items)
|
|
5118
|
-
}
|
|
5119
|
-
};
|
|
5120
|
-
}
|
|
5121
|
-
if (schema.type === "object") {
|
|
5122
|
-
return this.projectObjectType(schema);
|
|
5123
|
-
}
|
|
5124
|
-
if (schema.oneOf !== void 0) {
|
|
5125
|
-
return this.union(this.mapSchemaArrayMembers(schema.oneOf, "oneOf"));
|
|
5126
|
-
}
|
|
5127
|
-
if (schema.anyOf !== void 0) {
|
|
5128
|
-
return this.union(this.mapSchemaArrayMembers(schema.anyOf, "anyOf"));
|
|
5129
|
-
}
|
|
5130
|
-
if (schema.allOf !== void 0) {
|
|
5131
|
-
return {
|
|
5132
|
-
kind: "inline",
|
|
5133
|
-
expr: {
|
|
5134
|
-
node: "intersection",
|
|
5135
|
-
members: this.mapSchemaArrayMembers(schema.allOf, "allOf")
|
|
5136
|
-
}
|
|
5137
|
-
};
|
|
5138
|
-
}
|
|
5139
|
-
if (this.isBinaryFileSchema(schema)) {
|
|
5140
|
-
return this.builtinRef("File");
|
|
5141
|
-
}
|
|
5142
|
-
if (this.isScalarName(schema.type)) {
|
|
5143
|
-
return this.scalar(schema.type);
|
|
5144
|
-
}
|
|
5145
|
-
throw new Error(
|
|
5146
|
-
`Unsupported schema construct: ${JSON.stringify(schema, null, 2)}`
|
|
5147
|
-
);
|
|
5148
5257
|
});
|
|
5149
5258
|
}
|
|
5150
5259
|
}
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
return mediaTypes[0];
|
|
5260
|
+
const extractPathPlaceholderNames = (pathTemplate) => {
|
|
5261
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5262
|
+
const names = [];
|
|
5263
|
+
const matcher = /\{([^}]+)\}/g;
|
|
5264
|
+
let match = matcher.exec(pathTemplate);
|
|
5265
|
+
while (match) {
|
|
5266
|
+
const name = match[1];
|
|
5267
|
+
if (!seen.has(name)) {
|
|
5268
|
+
seen.add(name);
|
|
5269
|
+
names.push(name);
|
|
5270
|
+
}
|
|
5271
|
+
match = matcher.exec(pathTemplate);
|
|
5272
|
+
}
|
|
5273
|
+
return names;
|
|
5166
5274
|
};
|
|
5167
|
-
const
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5275
|
+
const isPathParam = (param) => {
|
|
5276
|
+
return param.kind === "path";
|
|
5277
|
+
};
|
|
5278
|
+
const isInlineObjectType = (typeExpr) => typeExpr.kind === "inline" && typeExpr.expr.node === "object";
|
|
5279
|
+
const renderNameList = (items) => {
|
|
5280
|
+
const values = [...items];
|
|
5281
|
+
if (!values.length) {
|
|
5282
|
+
return "(none)";
|
|
5171
5283
|
}
|
|
5172
|
-
|
|
5173
|
-
return Number.isFinite(numericCode) && numericCode >= 200 && numericCode < 300;
|
|
5284
|
+
return values.map((v) => JSON.stringify(v)).join(", ");
|
|
5174
5285
|
};
|
|
5175
|
-
const
|
|
5176
|
-
const
|
|
5177
|
-
|
|
5178
|
-
|
|
5286
|
+
const validatePathParams = (params, httpPath) => {
|
|
5287
|
+
const placeholders = extractPathPlaceholderNames(httpPath);
|
|
5288
|
+
const placeholderSet = new Set(placeholders);
|
|
5289
|
+
const pathParams = params.filter(isPathParam);
|
|
5290
|
+
if (pathParams.length > 1) {
|
|
5291
|
+
throw new Error(
|
|
5292
|
+
`Path "${httpPath}" has ${pathParams.length} path parameter objects; expected at most one.`
|
|
5293
|
+
);
|
|
5179
5294
|
}
|
|
5180
|
-
const
|
|
5181
|
-
if (
|
|
5182
|
-
|
|
5295
|
+
const pathParam = pathParams[0];
|
|
5296
|
+
if (!pathParam) {
|
|
5297
|
+
if (placeholderSet.size > 0) {
|
|
5298
|
+
throw new Error(
|
|
5299
|
+
`Path "${httpPath}" is missing a path parameter object for placeholders: ${renderNameList(
|
|
5300
|
+
placeholderSet
|
|
5301
|
+
)}.`
|
|
5302
|
+
);
|
|
5303
|
+
}
|
|
5304
|
+
return void 0;
|
|
5183
5305
|
}
|
|
5184
|
-
const
|
|
5185
|
-
|
|
5306
|
+
const pathParamExpr = pathParam.typeExpr.expr;
|
|
5307
|
+
if (pathParamExpr.additionalProperties !== void 0 && pathParamExpr.additionalProperties !== false) {
|
|
5308
|
+
throw new Error(
|
|
5309
|
+
`Path "${httpPath}" path parameter object must not declare additionalProperties.`
|
|
5310
|
+
);
|
|
5311
|
+
}
|
|
5312
|
+
const nestedObjectProps = pathParamExpr.properties.filter((prop) => isInlineObjectType(prop.typeExpr)).map((prop) => prop.name);
|
|
5313
|
+
if (nestedObjectProps.length > 0) {
|
|
5314
|
+
throw new Error(
|
|
5315
|
+
`Path "${httpPath}" path parameters must be depth-1. Nested object properties: ${renderNameList(
|
|
5316
|
+
nestedObjectProps
|
|
5317
|
+
)}.`
|
|
5318
|
+
);
|
|
5319
|
+
}
|
|
5320
|
+
const optionalPathProps = pathParamExpr.properties.filter((prop) => !prop.required).map((prop) => prop.name);
|
|
5321
|
+
if (optionalPathProps.length > 0) {
|
|
5322
|
+
throw new Error(
|
|
5323
|
+
`Path "${httpPath}" path parameters must all be required. Optional properties: ${renderNameList(
|
|
5324
|
+
optionalPathProps
|
|
5325
|
+
)}.`
|
|
5326
|
+
);
|
|
5327
|
+
}
|
|
5328
|
+
const declaredNames = pathParamExpr.properties.map((prop) => prop.name);
|
|
5329
|
+
const declaredNameSet = new Set(declaredNames);
|
|
5330
|
+
const missingInObject = [...placeholderSet].filter(
|
|
5331
|
+
(name) => !declaredNameSet.has(name)
|
|
5186
5332
|
);
|
|
5187
|
-
|
|
5188
|
-
|
|
5333
|
+
const missingInPath = declaredNames.filter(
|
|
5334
|
+
(name) => !placeholderSet.has(name)
|
|
5335
|
+
);
|
|
5336
|
+
if (missingInObject.length > 0 || missingInPath.length > 0) {
|
|
5337
|
+
throw new Error(
|
|
5338
|
+
`Path "${httpPath}" placeholders and path parameter object keys must match exactly. Missing in object: ${renderNameList(
|
|
5339
|
+
missingInObject
|
|
5340
|
+
)}. Missing in path: ${renderNameList(missingInPath)}.`
|
|
5341
|
+
);
|
|
5189
5342
|
}
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
if (!mediaType) return {};
|
|
5343
|
+
const bindings = buildPathParamBindings(placeholders);
|
|
5344
|
+
const propertiesByName = Object.fromEntries(
|
|
5345
|
+
pathParamExpr.properties.map((prop) => [prop.name, prop])
|
|
5346
|
+
);
|
|
5195
5347
|
return {
|
|
5196
|
-
|
|
5197
|
-
|
|
5348
|
+
placeholderNames: placeholders,
|
|
5349
|
+
bindings,
|
|
5350
|
+
propertiesByName
|
|
5198
5351
|
};
|
|
5199
5352
|
};
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
const isJsonLikeMediaType = (mediaType) => {
|
|
5205
|
-
return mediaType === "application/json" || typeof mediaType === "string" && /\+json$/i.test(mediaType);
|
|
5206
|
-
};
|
|
5207
|
-
const toHttpMethodUpper = (method) => {
|
|
5208
|
-
switch (method) {
|
|
5209
|
-
case "get":
|
|
5210
|
-
return "GET";
|
|
5211
|
-
case "post":
|
|
5212
|
-
return "POST";
|
|
5213
|
-
case "put":
|
|
5214
|
-
return "PUT";
|
|
5215
|
-
case "delete":
|
|
5216
|
-
return "DELETE";
|
|
5217
|
-
case "patch":
|
|
5218
|
-
return "PATCH";
|
|
5219
|
-
case "options":
|
|
5220
|
-
return "OPTIONS";
|
|
5221
|
-
case "head":
|
|
5222
|
-
return "HEAD";
|
|
5223
|
-
case "trace":
|
|
5224
|
-
return "TRACE";
|
|
5225
|
-
default: {
|
|
5226
|
-
const exhaustive = method;
|
|
5227
|
-
throw new Error(`Unsupported HTTP method: ${String(exhaustive)}`);
|
|
5228
|
-
}
|
|
5353
|
+
|
|
5354
|
+
const indentBlock = (value, indent) => {
|
|
5355
|
+
if (!value || !indent) {
|
|
5356
|
+
return value;
|
|
5229
5357
|
}
|
|
5358
|
+
return value.split("\n").map((line) => `${indent}${line}`).join("\n");
|
|
5230
5359
|
};
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5360
|
+
|
|
5361
|
+
const EMPTY_LINE_MARKER = "/*__EMPTY_LINE_MARKER__*/";
|
|
5362
|
+
|
|
5363
|
+
var __defProp$5 = Object.defineProperty;
|
|
5364
|
+
var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
5365
|
+
var __publicField$5 = (obj, key, value) => __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5366
|
+
const REQUEST_PARAMS_TYPE = "RequestParams";
|
|
5367
|
+
const REQUEST_PARAMS_DEFAULT = "never";
|
|
5368
|
+
const REQUEST_PARAMS_ARG = "params";
|
|
5369
|
+
class ApiClientCodegen {
|
|
5370
|
+
constructor(opts, tsCodegenFactory, docRenderer) {
|
|
5371
|
+
this.opts = opts;
|
|
5372
|
+
this.tsCodegenFactory = tsCodegenFactory;
|
|
5373
|
+
this.docRenderer = docRenderer;
|
|
5374
|
+
__publicField$5(this, "generate", (apiName, operations, doc) => {
|
|
5375
|
+
const tsCodegen = this.tsCodegenFactory.forNewChunk();
|
|
5376
|
+
const httpClientType = tsCodegen.typeExpr(this.opts.httpClient.typeName);
|
|
5377
|
+
let clientType = httpClientType;
|
|
5378
|
+
let classTypeParams = "";
|
|
5379
|
+
if (this.opts.withRequestParams) {
|
|
5380
|
+
clientType = `${httpClientType}<${REQUEST_PARAMS_TYPE}>`;
|
|
5381
|
+
classTypeParams = `<${REQUEST_PARAMS_TYPE} = ${REQUEST_PARAMS_DEFAULT}>`;
|
|
5382
|
+
}
|
|
5383
|
+
const methodsCode = Array.isArray(operations) ? this.opsCode(tsCodegen, operations) : this.groupsOpsCode(tsCodegen, operations);
|
|
5384
|
+
const classDocCode = this.renderApiClientDoc(doc, "");
|
|
5385
|
+
const code = `
|
|
5386
|
+
${classDocCode ? `${classDocCode}
|
|
5387
|
+
` : ""}export class ${apiName}${classTypeParams} {
|
|
5388
|
+
constructor(private readonly http: ${clientType}) {}
|
|
5389
|
+
|
|
5390
|
+
${methodsCode}
|
|
5391
|
+
}
|
|
5392
|
+
`;
|
|
5393
|
+
return tsCodegen.toChunk("api", code, [apiName]);
|
|
5394
|
+
});
|
|
5395
|
+
__publicField$5(this, "groupsOpsCode", (codegen, groupedOps) => Object.entries(groupedOps).map(([groupName, ops]) => {
|
|
5396
|
+
const methodsCode = this.opsCode(codegen, ops, "object");
|
|
5397
|
+
return `
|
|
5398
|
+
${toTsPropertyKey(groupName)} = {
|
|
5399
|
+
${methodsCode}
|
|
5400
|
+
}
|
|
5401
|
+
`;
|
|
5402
|
+
}).join("\n\n"));
|
|
5403
|
+
__publicField$5(this, "opsCode", (codegen, operations, target = "class") => {
|
|
5404
|
+
const separator = target === "object" ? `,
|
|
5405
|
+
${EMPTY_LINE_MARKER}
|
|
5406
|
+
` : "\n\n";
|
|
5407
|
+
const methodsCode = operations.map((op) => this.renderOp(op, codegen, target)).join(separator);
|
|
5408
|
+
return methodsCode;
|
|
5409
|
+
});
|
|
5410
|
+
__publicField$5(this, "renderOp", (op, tsCodegen, target) => {
|
|
5411
|
+
const { signature: sig, http } = op;
|
|
5412
|
+
const invocationVars = this.opts.httpClient.invocation.vars;
|
|
5413
|
+
const paramNames = {
|
|
5414
|
+
path: "path",
|
|
5415
|
+
query: invocationVars.query,
|
|
5416
|
+
body: invocationVars.body
|
|
5417
|
+
};
|
|
5418
|
+
const paramsHelper = new ParamsConstructor({
|
|
5419
|
+
paramNames,
|
|
5420
|
+
pathParamsStyle: this.opts.pathParamsStyle
|
|
5240
5421
|
});
|
|
5241
|
-
const
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5422
|
+
const { path, funParams, hasBody, hasQuery } = paramsHelper.process(
|
|
5423
|
+
sig.parameters,
|
|
5424
|
+
http.path
|
|
5425
|
+
);
|
|
5426
|
+
const params = funParams.map(
|
|
5427
|
+
(r) => `${r.identifier}: ${tsCodegen.typeExpr(r.typeExpr)}`
|
|
5428
|
+
);
|
|
5429
|
+
if (this.opts.withRequestParams) {
|
|
5430
|
+
params.push(`${REQUEST_PARAMS_ARG}?: ${REQUEST_PARAMS_TYPE}`);
|
|
5431
|
+
}
|
|
5432
|
+
const paramsCode = params.join(", ");
|
|
5433
|
+
const responseType = tsCodegen.typeExpr(sig.returnType);
|
|
5434
|
+
const returnType = this.wrapInResponseWrapper(sig.returnType, tsCodegen);
|
|
5435
|
+
return this.renderFunctionCode({
|
|
5436
|
+
doc: sig.doc,
|
|
5437
|
+
funName: sig.name,
|
|
5438
|
+
responseType,
|
|
5439
|
+
returnType,
|
|
5440
|
+
params: paramsCode,
|
|
5441
|
+
path,
|
|
5442
|
+
method: http.method,
|
|
5443
|
+
hasQuery,
|
|
5444
|
+
hasBody,
|
|
5445
|
+
requestContentType: http.requestContentType,
|
|
5446
|
+
responseFormat: http.responseFormat,
|
|
5447
|
+
requestParamsVar: this.opts.withRequestParams ? REQUEST_PARAMS_ARG : void 0,
|
|
5448
|
+
unwrap: this.opts.unwrap,
|
|
5449
|
+
target
|
|
5252
5450
|
});
|
|
5253
|
-
return {
|
|
5254
|
-
operations,
|
|
5255
|
-
schemaDefinitions: this.typeExprConverter.getSchemaDefinitions()
|
|
5256
|
-
};
|
|
5257
5451
|
});
|
|
5258
|
-
__publicField$
|
|
5259
|
-
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
const bodyParameter = this.projectBodyParameter(operation);
|
|
5264
|
-
if (pathParameter) parameters.push(pathParameter);
|
|
5265
|
-
if (queryParameter) parameters.push(queryParameter);
|
|
5266
|
-
if (bodyParameter) parameters.push(bodyParameter);
|
|
5267
|
-
return {
|
|
5268
|
-
op: {
|
|
5269
|
-
signature: {
|
|
5270
|
-
name: operationName,
|
|
5271
|
-
parameters,
|
|
5272
|
-
returnType: this.projectReturnType(operation)
|
|
5273
|
-
},
|
|
5274
|
-
http: {
|
|
5275
|
-
method: toHttpMethodUpper(operation.method),
|
|
5276
|
-
path: operation.path,
|
|
5277
|
-
requestContentType: this.projectRequestContentType(
|
|
5278
|
-
operation.requestBody
|
|
5279
|
-
),
|
|
5280
|
-
responseFormat: this.projectResponseFormat(operation)
|
|
5281
|
-
}
|
|
5282
|
-
},
|
|
5283
|
-
tags: [...operation.tags]
|
|
5284
|
-
};
|
|
5452
|
+
__publicField$5(this, "wrapInResponseWrapper", (typeExpr, tsCodegen) => {
|
|
5453
|
+
return tsCodegen.typeExpr({
|
|
5454
|
+
...this.opts.httpClient.responseWrapper,
|
|
5455
|
+
typeArgs: [typeExpr]
|
|
5456
|
+
});
|
|
5285
5457
|
});
|
|
5286
|
-
__publicField$
|
|
5287
|
-
|
|
5288
|
-
|
|
5458
|
+
__publicField$5(this, "renderFunctionCode", ({
|
|
5459
|
+
doc,
|
|
5460
|
+
funName,
|
|
5461
|
+
responseType,
|
|
5462
|
+
returnType,
|
|
5463
|
+
params,
|
|
5464
|
+
path,
|
|
5465
|
+
method,
|
|
5466
|
+
hasQuery,
|
|
5467
|
+
hasBody,
|
|
5468
|
+
requestContentType,
|
|
5469
|
+
responseFormat,
|
|
5470
|
+
requestParamsVar,
|
|
5471
|
+
unwrap,
|
|
5472
|
+
target
|
|
5473
|
+
}) => {
|
|
5474
|
+
let invocation = this.opts.httpClient.invocation.expr({
|
|
5475
|
+
funName,
|
|
5476
|
+
returnType,
|
|
5477
|
+
responseType,
|
|
5478
|
+
params,
|
|
5479
|
+
path,
|
|
5480
|
+
method,
|
|
5481
|
+
hasQuery,
|
|
5482
|
+
hasBody,
|
|
5483
|
+
requestContentType,
|
|
5484
|
+
responseFormat,
|
|
5485
|
+
requestParamsVar,
|
|
5486
|
+
unwrap
|
|
5487
|
+
});
|
|
5488
|
+
invocation = invocation.replaceAll("\n", "");
|
|
5489
|
+
const operator = target === "object" ? ":" : "=";
|
|
5490
|
+
const returnTypeCode = this.opts.httpClient.inferMethodReturnType ? "" : `:${returnType}`;
|
|
5491
|
+
const functionCode = `${funName} ${operator} (${params})${returnTypeCode} =>
|
|
5492
|
+
this.http${invocation}
|
|
5493
|
+
`;
|
|
5494
|
+
const docCode = this.renderOperationDoc(
|
|
5495
|
+
doc,
|
|
5496
|
+
this.opts.comments,
|
|
5497
|
+
target === "object" ? " " : " "
|
|
5498
|
+
);
|
|
5499
|
+
return docCode ? `${docCode}
|
|
5500
|
+
${functionCode}` : functionCode;
|
|
5501
|
+
});
|
|
5502
|
+
__publicField$5(this, "renderOperationDoc", (doc, comments, indent = "") => {
|
|
5503
|
+
if (!doc) return null;
|
|
5504
|
+
return indentBlock(this.docRenderer.render(this.toTsDoc(doc)), indent);
|
|
5505
|
+
});
|
|
5506
|
+
__publicField$5(this, "renderApiClientDoc", (doc, indent = "") => {
|
|
5507
|
+
if (!doc) return "";
|
|
5508
|
+
return indentBlock(
|
|
5509
|
+
this.docRenderer.render({
|
|
5510
|
+
nodes: [
|
|
5511
|
+
{
|
|
5512
|
+
key: "title",
|
|
5513
|
+
value: doc.title
|
|
5514
|
+
},
|
|
5515
|
+
{
|
|
5516
|
+
key: "version",
|
|
5517
|
+
value: doc.version
|
|
5518
|
+
},
|
|
5519
|
+
...doc.description ? [doc.description] : []
|
|
5520
|
+
]
|
|
5521
|
+
}),
|
|
5522
|
+
indent
|
|
5289
5523
|
);
|
|
5290
|
-
switch (mediaType) {
|
|
5291
|
-
case "application/json":
|
|
5292
|
-
case "multipart/form-data":
|
|
5293
|
-
case "application/x-www-form-urlencoded":
|
|
5294
|
-
return mediaType;
|
|
5295
|
-
default:
|
|
5296
|
-
return void 0;
|
|
5297
|
-
}
|
|
5298
5524
|
});
|
|
5299
|
-
__publicField$
|
|
5300
|
-
const
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5525
|
+
__publicField$5(this, "toTsDoc", (doc) => {
|
|
5526
|
+
const nodes = [
|
|
5527
|
+
{
|
|
5528
|
+
key: "id",
|
|
5529
|
+
value: doc.id
|
|
5530
|
+
}
|
|
5531
|
+
];
|
|
5532
|
+
const comms = this.opts.comments;
|
|
5533
|
+
if ((comms.summary ?? true) && doc.summary) {
|
|
5534
|
+
nodes.push({
|
|
5535
|
+
key: "summary",
|
|
5536
|
+
value: doc.summary
|
|
5537
|
+
});
|
|
5306
5538
|
}
|
|
5307
|
-
if (
|
|
5308
|
-
(
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
return "json";
|
|
5539
|
+
if ((comms.description ?? true) && doc.description) {
|
|
5540
|
+
nodes.push({
|
|
5541
|
+
key: "description",
|
|
5542
|
+
value: doc.description
|
|
5543
|
+
});
|
|
5313
5544
|
}
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
)
|
|
5323
|
-
}));
|
|
5324
|
-
return {
|
|
5325
|
-
kind: "inline",
|
|
5326
|
-
expr: {
|
|
5327
|
-
node: "object",
|
|
5328
|
-
properties
|
|
5329
|
-
}
|
|
5330
|
-
};
|
|
5331
|
-
});
|
|
5332
|
-
__publicField$4(this, "projectPathParameter", (operation) => {
|
|
5333
|
-
const params = operation.parameters.path;
|
|
5334
|
-
const entries = Object.values(params);
|
|
5335
|
-
if (!entries.length) return null;
|
|
5336
|
-
if (entries.some((parameter) => !parameter.required)) {
|
|
5337
|
-
throw new Error("Unsupported path parameters: all must be required");
|
|
5545
|
+
nodes.push({
|
|
5546
|
+
key: "request",
|
|
5547
|
+
value: doc.request
|
|
5548
|
+
});
|
|
5549
|
+
if ((comms.tags ?? true) && doc.tags.length) {
|
|
5550
|
+
nodes.push({
|
|
5551
|
+
key: "tags",
|
|
5552
|
+
value: doc.tags.join(", ")
|
|
5553
|
+
});
|
|
5338
5554
|
}
|
|
5339
5555
|
return {
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
typeExpr: this.projectParameterGroupTypeExpr(params)
|
|
5343
|
-
};
|
|
5344
|
-
});
|
|
5345
|
-
__publicField$4(this, "projectQueryParameter", (operation) => {
|
|
5346
|
-
const params = operation.parameters.query;
|
|
5347
|
-
const entries = Object.values(params);
|
|
5348
|
-
if (!entries.length) return null;
|
|
5349
|
-
return {
|
|
5350
|
-
kind: "query",
|
|
5351
|
-
optional: !entries.some((parameter) => parameter.required),
|
|
5352
|
-
typeExpr: this.projectParameterGroupTypeExpr(params)
|
|
5556
|
+
deprecated: doc.deprecated,
|
|
5557
|
+
nodes
|
|
5353
5558
|
};
|
|
5354
5559
|
});
|
|
5355
|
-
__publicField$4(this, "projectBodyParameter", (operation) => {
|
|
5356
|
-
const requestBody = operation.requestBody;
|
|
5357
|
-
if (!requestBody) return null;
|
|
5358
|
-
return {
|
|
5359
|
-
kind: "body",
|
|
5360
|
-
optional: !requestBody.required,
|
|
5361
|
-
typeExpr: this.typeExprConverter.fromSchema(
|
|
5362
|
-
this.selectRequestBodySchema(requestBody)
|
|
5363
|
-
)
|
|
5364
|
-
};
|
|
5365
|
-
});
|
|
5366
|
-
__publicField$4(this, "projectReturnType", (operation) => {
|
|
5367
|
-
const selectedResponses = selectReturnResponses(operation.responses);
|
|
5368
|
-
if (!selectedResponses.length) {
|
|
5369
|
-
return this.typeExprConverter.scalar("void");
|
|
5370
|
-
}
|
|
5371
|
-
const responseTypes = selectedResponses.map((response) => {
|
|
5372
|
-
const schema = this.selectResponseSchema(response);
|
|
5373
|
-
if (!schema) {
|
|
5374
|
-
return this.typeExprConverter.scalar("void");
|
|
5375
|
-
}
|
|
5376
|
-
return this.typeExprConverter.fromSchema(schema);
|
|
5377
|
-
});
|
|
5378
|
-
return this.typeExprConverter.union(responseTypes);
|
|
5379
|
-
});
|
|
5380
|
-
__publicField$4(this, "selectParameterSchema", (parameter) => {
|
|
5381
|
-
if (parameter.schema) return parameter.schema;
|
|
5382
|
-
return getPreferredMediaTypeEntry(parameter.content).media?.schema;
|
|
5383
|
-
});
|
|
5384
|
-
__publicField$4(this, "selectRequestBodySchema", (requestBody) => {
|
|
5385
|
-
return getPreferredMediaTypeEntry(requestBody.content).media?.schema;
|
|
5386
|
-
});
|
|
5387
|
-
__publicField$4(this, "selectResponseSchema", (response) => {
|
|
5388
|
-
return getPreferredMediaTypeEntry(response.content).media?.schema;
|
|
5389
|
-
});
|
|
5390
|
-
this.typeExprConverter = new ToTypeExprConverter(void 0, {
|
|
5391
|
-
quirks: this.options.quirks
|
|
5392
|
-
});
|
|
5393
5560
|
}
|
|
5394
5561
|
}
|
|
5395
5562
|
|
|
5396
|
-
const
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
}
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5563
|
+
const promiseHttpClientCodegenSpec = () => ({
|
|
5564
|
+
typeName: {
|
|
5565
|
+
kind: "reference",
|
|
5566
|
+
ref: {
|
|
5567
|
+
kind: "internal",
|
|
5568
|
+
name: "HttpClient"
|
|
5569
|
+
}
|
|
5570
|
+
},
|
|
5571
|
+
responseWrapper: {
|
|
5572
|
+
kind: "reference",
|
|
5573
|
+
ref: {
|
|
5574
|
+
kind: "builtin",
|
|
5575
|
+
name: "Promise"
|
|
5576
|
+
}
|
|
5577
|
+
},
|
|
5578
|
+
inferMethodReturnType: true,
|
|
5579
|
+
invocation: {
|
|
5580
|
+
vars: {
|
|
5581
|
+
body: "body",
|
|
5582
|
+
query: "query"
|
|
5583
|
+
},
|
|
5584
|
+
expr: ({
|
|
5585
|
+
responseType,
|
|
5586
|
+
path,
|
|
5587
|
+
method,
|
|
5588
|
+
hasBody,
|
|
5589
|
+
hasQuery,
|
|
5590
|
+
requestContentType,
|
|
5591
|
+
responseFormat,
|
|
5592
|
+
requestParamsVar,
|
|
5593
|
+
unwrap
|
|
5594
|
+
}) => `.request<${responseType}>({
|
|
5595
|
+
method: '${method}',
|
|
5596
|
+
path: ${path}
|
|
5597
|
+
${hasQuery ? `,
|
|
5598
|
+
query` : ""}
|
|
5599
|
+
${hasBody ? `,
|
|
5600
|
+
body` : ""}
|
|
5601
|
+
${requestContentType ? `,
|
|
5602
|
+
requestContentType: '${requestContentType}'` : ""}
|
|
5603
|
+
${responseFormat ? `,
|
|
5604
|
+
format: '${responseFormat}'` : ""}
|
|
5605
|
+
}${requestParamsVar ? `,
|
|
5606
|
+
${requestParamsVar}` : ""})${unwrap ? `.then(res => res.body)` : ""}
|
|
5607
|
+
`
|
|
5407
5608
|
}
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5609
|
+
});
|
|
5610
|
+
|
|
5611
|
+
const mergeChunks = (name, chunks, options = {}) => {
|
|
5612
|
+
if (chunks.length === 0) {
|
|
5613
|
+
if (options.allowEmpty) {
|
|
5614
|
+
return {
|
|
5615
|
+
name,
|
|
5616
|
+
code: "export {}",
|
|
5617
|
+
exports: [],
|
|
5618
|
+
refs: []
|
|
5619
|
+
};
|
|
5620
|
+
}
|
|
5621
|
+
throw new Error("Cannot merge empty chunk list.");
|
|
5411
5622
|
}
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5623
|
+
const orderedChunks = options.preserveChunkOrder ? chunks : orderByInternalDependencies(chunks);
|
|
5624
|
+
const mergedCode = orderedChunks.map((chunk) => chunk.code).join("\n\n");
|
|
5625
|
+
const exportedSymbols = /* @__PURE__ */ new Set();
|
|
5626
|
+
const mergedExports = [];
|
|
5627
|
+
for (const chunk of orderedChunks) {
|
|
5628
|
+
for (const symbol of chunk.exports) {
|
|
5629
|
+
if (exportedSymbols.has(symbol)) continue;
|
|
5630
|
+
exportedSymbols.add(symbol);
|
|
5631
|
+
mergedExports.push(symbol);
|
|
5632
|
+
}
|
|
5417
5633
|
}
|
|
5418
|
-
|
|
5419
|
-
|
|
5634
|
+
const seenRefKeys = /* @__PURE__ */ new Set();
|
|
5635
|
+
const mergedRefs = orderedChunks.flatMap((chunk) => chunk.refs).filter((ref) => {
|
|
5636
|
+
if (ref.kind === "internal" && exportedSymbols.has(ref.name)) {
|
|
5637
|
+
return false;
|
|
5638
|
+
}
|
|
5639
|
+
const key = ref.kind === "internal" ? `internal:${ref.name}` : ref.kind === "external" ? `external:${ref.package}:${ref.name}` : `builtin:${ref.name}`;
|
|
5640
|
+
if (seenRefKeys.has(key)) return false;
|
|
5641
|
+
seenRefKeys.add(key);
|
|
5642
|
+
return true;
|
|
5643
|
+
});
|
|
5644
|
+
return {
|
|
5645
|
+
name,
|
|
5646
|
+
code: mergedCode,
|
|
5647
|
+
exports: mergedExports,
|
|
5648
|
+
refs: mergedRefs
|
|
5649
|
+
};
|
|
5420
5650
|
};
|
|
5421
|
-
const
|
|
5422
|
-
|
|
5423
|
-
|
|
5651
|
+
const orderByInternalDependencies = (chunks) => {
|
|
5652
|
+
const chunkIndex = /* @__PURE__ */ new Map();
|
|
5653
|
+
const exportOwnerBySymbol = /* @__PURE__ */ new Map();
|
|
5654
|
+
chunks.forEach((chunk, index) => {
|
|
5655
|
+
chunkIndex.set(chunk.name, index);
|
|
5656
|
+
for (const symbol of chunk.exports) {
|
|
5657
|
+
if (exportOwnerBySymbol.has(symbol)) {
|
|
5658
|
+
throw new Error(
|
|
5659
|
+
`Assertion error. Symbol "${symbol}" exported multiple times while ordering chunks.`
|
|
5660
|
+
);
|
|
5661
|
+
}
|
|
5662
|
+
exportOwnerBySymbol.set(symbol, chunk);
|
|
5663
|
+
}
|
|
5664
|
+
});
|
|
5665
|
+
const dependentsByProvider = /* @__PURE__ */ new Map();
|
|
5666
|
+
const inDegreeByChunk = /* @__PURE__ */ new Map();
|
|
5667
|
+
for (const chunk of chunks) {
|
|
5668
|
+
dependentsByProvider.set(chunk, /* @__PURE__ */ new Set());
|
|
5669
|
+
inDegreeByChunk.set(chunk, 0);
|
|
5424
5670
|
}
|
|
5425
|
-
const
|
|
5426
|
-
|
|
5427
|
-
|
|
5671
|
+
for (const chunk of chunks) {
|
|
5672
|
+
const providers = /* @__PURE__ */ new Set();
|
|
5673
|
+
for (const ref of chunk.refs) {
|
|
5674
|
+
if (ref.kind !== "internal") continue;
|
|
5675
|
+
const provider = exportOwnerBySymbol.get(ref.name);
|
|
5676
|
+
if (!provider || provider === chunk) continue;
|
|
5677
|
+
providers.add(provider);
|
|
5678
|
+
}
|
|
5679
|
+
for (const provider of providers) {
|
|
5680
|
+
dependentsByProvider.get(provider).add(chunk);
|
|
5681
|
+
inDegreeByChunk.set(chunk, inDegreeByChunk.get(chunk) + 1);
|
|
5682
|
+
}
|
|
5428
5683
|
}
|
|
5429
|
-
|
|
5430
|
-
|
|
5684
|
+
const ready = chunks.filter((chunk) => inDegreeByChunk.get(chunk) === 0).sort((a, b) => chunkIndex.get(a.name) - chunkIndex.get(b.name));
|
|
5685
|
+
const ordered = [];
|
|
5686
|
+
while (ready.length > 0) {
|
|
5687
|
+
const provider = ready.shift();
|
|
5688
|
+
ordered.push(provider);
|
|
5689
|
+
for (const dependent of dependentsByProvider.get(provider)) {
|
|
5690
|
+
const nextInDegree = inDegreeByChunk.get(dependent) - 1;
|
|
5691
|
+
inDegreeByChunk.set(dependent, nextInDegree);
|
|
5692
|
+
if (nextInDegree === 0) {
|
|
5693
|
+
ready.push(dependent);
|
|
5694
|
+
}
|
|
5695
|
+
}
|
|
5696
|
+
ready.sort((a, b) => chunkIndex.get(a.name) - chunkIndex.get(b.name));
|
|
5431
5697
|
}
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
return
|
|
5698
|
+
if (ordered.length !== chunks.length) {
|
|
5699
|
+
const cycleChunkNames = chunks.filter((chunk) => inDegreeByChunk.get(chunk) > 0).map((chunk) => chunk.name).join(", ");
|
|
5700
|
+
throw new Error(
|
|
5701
|
+
`Cannot order chunks with cyclic internal dependencies: ${cycleChunkNames}`
|
|
5702
|
+
);
|
|
5703
|
+
}
|
|
5704
|
+
return ordered;
|
|
5439
5705
|
};
|
|
5440
5706
|
|
|
5441
|
-
var
|
|
5442
|
-
|
|
5443
|
-
var
|
|
5444
|
-
|
|
5707
|
+
var httpClientCommonTypesSource = "export type KnownRequestContentType =\n | 'application/json'\n | 'multipart/form-data'\n | 'application/x-www-form-urlencoded'\n\nexport type RequestContentType = KnownRequestContentType | string\n\nexport type QueryValue =\n | string\n | number\n | boolean\n | null\n | undefined\n | QueryValue[]\n | Record<string, any>\n // Empty schema support\n | unknown\n\nexport type QueryParams = Record<string, QueryValue>\n\nexport type Request = {\n path: string\n method: 'GET' | 'POST' | 'PUT' | 'DELETE'\n format?: 'json' | 'document'\n headers?: Record<string, string>\n query?: QueryParams\n body?: any\n requestContentType?: RequestContentType\n}\n\nexport type HttpResponse<Data> = {\n body: Data\n headers: Record<string, string | string[]>\n status: number\n}\n\nexport type QuerySerializer = (params: QueryParams) => string\n";
|
|
5708
|
+
|
|
5709
|
+
var httpClientPromiseTypesSource = "import type { HttpResponse, Request } from './common-types'\n\nexport type HttpClient<RequestParams = never> = {\n request: <Data>(\n req: Request,\n params?: RequestParams\n ) => Promise<HttpResponse<Data>>\n}\n";
|
|
5710
|
+
|
|
5711
|
+
const commonTypesCode = httpClientCommonTypesSource;
|
|
5712
|
+
const promiseHttpClientCode = httpClientPromiseTypesSource;
|
|
5713
|
+
const stripImports = (code) => code.replace(/^import[\s\S]*?from\s+['"][^'"]+['"]\s*;?\n?/gm, "").trim();
|
|
5714
|
+
const stripRequestParams = (code) => code.replace(/<RequestParams\s*=\s*never>/g, "").replace(/,\s*params\?:\s*RequestParams/g, "");
|
|
5715
|
+
const getHttpClientCode = (opts) => [
|
|
5716
|
+
commonTypesCode,
|
|
5717
|
+
opts.withRequestParams ? promiseHttpClientCode : stripRequestParams(promiseHttpClientCode)
|
|
5718
|
+
].map(stripImports).join("\n\n");
|
|
5719
|
+
const provideHttpClientCode = (gen, opts) => gen.toChunk(
|
|
5720
|
+
"HttpClient",
|
|
5721
|
+
getHttpClientCode({
|
|
5722
|
+
withRequestParams: opts.withRequestParams
|
|
5723
|
+
}),
|
|
5724
|
+
["HttpRequest", "HttpResponse", "HttpClient"]
|
|
5725
|
+
);
|
|
5726
|
+
|
|
5727
|
+
var __defProp$4 = Object.defineProperty;
|
|
5728
|
+
var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
5729
|
+
var __publicField$4 = (obj, key, value) => __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5730
|
+
class TsDocRenderer {
|
|
5445
5731
|
constructor(options) {
|
|
5446
5732
|
this.options = options;
|
|
5447
|
-
__publicField$
|
|
5448
|
-
|
|
5449
|
-
const
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
const path = this.renderPathTemplateLiteral(
|
|
5456
|
-
httpPath,
|
|
5457
|
-
this.options.paramNames.path,
|
|
5458
|
-
pathParamBindings
|
|
5459
|
-
);
|
|
5460
|
-
return {
|
|
5461
|
-
funParams,
|
|
5462
|
-
path,
|
|
5463
|
-
hasBody,
|
|
5464
|
-
hasQuery
|
|
5465
|
-
};
|
|
5733
|
+
__publicField$4(this, "render", (doc, options = {}) => {
|
|
5734
|
+
if (!this.options.enabled) return "";
|
|
5735
|
+
const lines = [];
|
|
5736
|
+
this.appendNodes(lines, doc.nodes, options);
|
|
5737
|
+
if (doc.deprecated) {
|
|
5738
|
+
this.appendDeprecated(lines, { separate: lines.length > 0 });
|
|
5739
|
+
}
|
|
5740
|
+
return this.renderComment(lines);
|
|
5466
5741
|
});
|
|
5467
|
-
__publicField$
|
|
5468
|
-
if (
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
typeExpr: param.typeExpr
|
|
5473
|
-
}
|
|
5474
|
-
];
|
|
5742
|
+
__publicField$4(this, "renderComment", (lines) => {
|
|
5743
|
+
if (!this.options.enabled) return "";
|
|
5744
|
+
if (!lines.length) return "";
|
|
5745
|
+
if (lines.length === 1) {
|
|
5746
|
+
return `/** ${lines[0]} */`;
|
|
5475
5747
|
}
|
|
5476
|
-
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
|
|
5480
|
-
|
|
5748
|
+
const body = lines.map((line) => line ? ` * ${line}` : " *").join("\n");
|
|
5749
|
+
return `/**
|
|
5750
|
+
${body}
|
|
5751
|
+
*/`;
|
|
5752
|
+
});
|
|
5753
|
+
__publicField$4(this, "appendDocText", (lines, value) => {
|
|
5754
|
+
const normalized = this.normalizeLines(value);
|
|
5755
|
+
if (!normalized.length) return;
|
|
5756
|
+
if (lines.length > 0) {
|
|
5757
|
+
lines.push("");
|
|
5481
5758
|
}
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5759
|
+
lines.push(...normalized);
|
|
5760
|
+
});
|
|
5761
|
+
__publicField$4(this, "appendField", (lines, key, value) => {
|
|
5762
|
+
const normalized = this.normalizeLines(value);
|
|
5763
|
+
if (!normalized.length) return;
|
|
5764
|
+
lines.push(`@${key} ${normalized[0]}`.trimEnd());
|
|
5765
|
+
lines.push(...normalized.slice(1));
|
|
5766
|
+
});
|
|
5767
|
+
__publicField$4(this, "appendDeprecated", (lines, options) => {
|
|
5768
|
+
if (options.separate) {
|
|
5769
|
+
lines.push("");
|
|
5770
|
+
}
|
|
5771
|
+
lines.push("@deprecated");
|
|
5772
|
+
});
|
|
5773
|
+
__publicField$4(this, "appendNodes", (lines, nodes = [], options = {}) => {
|
|
5774
|
+
nodes.forEach((node) => {
|
|
5775
|
+
if (typeof node === "string") {
|
|
5776
|
+
if (options.compactText) {
|
|
5777
|
+
lines.push(...this.normalizeNonEmptyLines(node));
|
|
5778
|
+
return;
|
|
5779
|
+
}
|
|
5780
|
+
this.appendDocText(lines, node);
|
|
5781
|
+
return;
|
|
5488
5782
|
}
|
|
5489
|
-
|
|
5783
|
+
this.appendField(lines, node.key, node.value);
|
|
5784
|
+
});
|
|
5490
5785
|
});
|
|
5491
|
-
__publicField$
|
|
5492
|
-
const
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
(_, paramName) => {
|
|
5496
|
-
const binding = pathParamBindings?.[paramName];
|
|
5497
|
-
if (binding !== void 0) {
|
|
5498
|
-
return `\${${binding}}`;
|
|
5499
|
-
}
|
|
5500
|
-
return `\${${pathParamVarName}[${JSON.stringify(paramName)}]}`;
|
|
5501
|
-
}
|
|
5502
|
-
);
|
|
5503
|
-
return `\`${pathWithParams}\``;
|
|
5504
|
-
});
|
|
5505
|
-
__publicField$3(this, "renderPathParamDestructuring", (pathParamBindings) => {
|
|
5506
|
-
const members = Object.entries(pathParamBindings).map(
|
|
5507
|
-
([paramName, binding]) => {
|
|
5508
|
-
const key = toTsPropertyKey(paramName);
|
|
5509
|
-
return binding === paramName ? key : `${key}: ${binding}`;
|
|
5510
|
-
}
|
|
5511
|
-
);
|
|
5512
|
-
return `{ ${members.join(", ")} }`;
|
|
5513
|
-
});
|
|
5514
|
-
__publicField$3(this, "paramName", (p) => {
|
|
5515
|
-
switch (p.kind) {
|
|
5516
|
-
case "body":
|
|
5517
|
-
return this.options.paramNames.body;
|
|
5518
|
-
case "query":
|
|
5519
|
-
return this.options.paramNames.query;
|
|
5520
|
-
case "path":
|
|
5521
|
-
return this.options.paramNames.path;
|
|
5522
|
-
default: {
|
|
5523
|
-
const exhaustive = p;
|
|
5524
|
-
throw new Error(
|
|
5525
|
-
`Unsupported operation parameter kind: ${String(exhaustive)}`
|
|
5526
|
-
);
|
|
5527
|
-
}
|
|
5528
|
-
}
|
|
5786
|
+
__publicField$4(this, "normalizeLines", (value) => {
|
|
5787
|
+
const trimmed = value?.trim();
|
|
5788
|
+
if (!trimmed) return [];
|
|
5789
|
+
return trimmed.split(/\r?\n/u).map((line) => line.trimEnd().replaceAll("*/", "*\\/"));
|
|
5529
5790
|
});
|
|
5791
|
+
__publicField$4(this, "normalizeNonEmptyLines", (value) => this.normalizeLines(value).filter((line) => line.length > 0));
|
|
5530
5792
|
}
|
|
5531
5793
|
}
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
const
|
|
5535
|
-
|
|
5536
|
-
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
|
|
5553
|
-
|
|
5554
|
-
|
|
5555
|
-
|
|
5556
|
-
return values.map((v) => JSON.stringify(v)).join(", ");
|
|
5557
|
-
};
|
|
5558
|
-
const validatePathParams = (params, httpPath) => {
|
|
5559
|
-
const placeholders = extractPathPlaceholderNames(httpPath);
|
|
5560
|
-
const placeholderSet = new Set(placeholders);
|
|
5561
|
-
const pathParams = params.filter(isPathParam);
|
|
5562
|
-
if (pathParams.length > 1) {
|
|
5563
|
-
throw new Error(
|
|
5564
|
-
`Path "${httpPath}" has ${pathParams.length} path parameter objects; expected at most one.`
|
|
5565
|
-
);
|
|
5566
|
-
}
|
|
5567
|
-
const pathParam = pathParams[0];
|
|
5568
|
-
if (!pathParam) {
|
|
5569
|
-
if (placeholderSet.size > 0) {
|
|
5570
|
-
throw new Error(
|
|
5571
|
-
`Path "${httpPath}" is missing a path parameter object for placeholders: ${renderNameList(
|
|
5572
|
-
placeholderSet
|
|
5573
|
-
)}.`
|
|
5574
|
-
);
|
|
5575
|
-
}
|
|
5576
|
-
return void 0;
|
|
5577
|
-
}
|
|
5578
|
-
const pathParamExpr = pathParam.typeExpr.expr;
|
|
5579
|
-
if (pathParamExpr.additionalProperties !== void 0 && pathParamExpr.additionalProperties !== false) {
|
|
5580
|
-
throw new Error(
|
|
5581
|
-
`Path "${httpPath}" path parameter object must not declare additionalProperties.`
|
|
5582
|
-
);
|
|
5583
|
-
}
|
|
5584
|
-
const nestedObjectProps = pathParamExpr.properties.filter((prop) => isInlineObjectType(prop.typeExpr)).map((prop) => prop.name);
|
|
5585
|
-
if (nestedObjectProps.length > 0) {
|
|
5586
|
-
throw new Error(
|
|
5587
|
-
`Path "${httpPath}" path parameters must be depth-1. Nested object properties: ${renderNameList(
|
|
5588
|
-
nestedObjectProps
|
|
5589
|
-
)}.`
|
|
5590
|
-
);
|
|
5591
|
-
}
|
|
5592
|
-
const optionalPathProps = pathParamExpr.properties.filter((prop) => !prop.required).map((prop) => prop.name);
|
|
5593
|
-
if (optionalPathProps.length > 0) {
|
|
5594
|
-
throw new Error(
|
|
5595
|
-
`Path "${httpPath}" path parameters must all be required. Optional properties: ${renderNameList(
|
|
5596
|
-
optionalPathProps
|
|
5597
|
-
)}.`
|
|
5598
|
-
);
|
|
5599
|
-
}
|
|
5600
|
-
const declaredNames = pathParamExpr.properties.map((prop) => prop.name);
|
|
5601
|
-
const declaredNameSet = new Set(declaredNames);
|
|
5602
|
-
const missingInObject = [...placeholderSet].filter(
|
|
5603
|
-
(name) => !declaredNameSet.has(name)
|
|
5794
|
+
|
|
5795
|
+
const generateTsCode = (clientName, projectResult, opts) => {
|
|
5796
|
+
const docRenderer = new TsDocRenderer({
|
|
5797
|
+
enabled: opts.comments.enabled
|
|
5798
|
+
});
|
|
5799
|
+
const tsCodegenFac = new TsCodegenFactory(docRenderer);
|
|
5800
|
+
const { schemaDefinitions } = projectResult;
|
|
5801
|
+
const types = [...schemaDefinitions].sort((a, b) => a.name.localeCompare(b.name)).map((def) => {
|
|
5802
|
+
const cg = tsCodegenFac.forNewChunk();
|
|
5803
|
+
const code = cg.declaration(def.name, def.declaration, {
|
|
5804
|
+
exported: true
|
|
5805
|
+
});
|
|
5806
|
+
return cg.toChunk(def.name, code, [def.name]);
|
|
5807
|
+
});
|
|
5808
|
+
const clientCodegen = new ApiClientCodegen(
|
|
5809
|
+
{
|
|
5810
|
+
httpClient: promiseHttpClientCodegenSpec(),
|
|
5811
|
+
comments: opts.comments.operation,
|
|
5812
|
+
unwrap: opts.unwrap,
|
|
5813
|
+
pathParamsStyle: opts.pathParamsStyle,
|
|
5814
|
+
withRequestParams: opts.withRequestParams
|
|
5815
|
+
},
|
|
5816
|
+
tsCodegenFac,
|
|
5817
|
+
docRenderer
|
|
5604
5818
|
);
|
|
5605
|
-
const
|
|
5606
|
-
|
|
5819
|
+
const generated = clientCodegen.generate(
|
|
5820
|
+
clientName,
|
|
5821
|
+
groupsOpsByTag(projectResult.operations),
|
|
5822
|
+
projectResult.api
|
|
5607
5823
|
);
|
|
5608
|
-
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
)
|
|
5614
|
-
|
|
5615
|
-
const bindings = buildPathParamBindings(placeholders);
|
|
5616
|
-
const propertiesByName = Object.fromEntries(
|
|
5617
|
-
pathParamExpr.properties.map((prop) => [prop.name, prop])
|
|
5824
|
+
const clientChunk = {
|
|
5825
|
+
...generated,
|
|
5826
|
+
name: `${clientName}.client`
|
|
5827
|
+
};
|
|
5828
|
+
const httpClientChunk = provideHttpClientCode(
|
|
5829
|
+
tsCodegenFac.forNewChunk(),
|
|
5830
|
+
opts
|
|
5618
5831
|
);
|
|
5832
|
+
const typesChunk = mergeChunks(`${clientName}.types`, types, {
|
|
5833
|
+
preserveChunkOrder: true,
|
|
5834
|
+
allowEmpty: true
|
|
5835
|
+
});
|
|
5836
|
+
const indexChunk = createIndexChunk(clientName);
|
|
5837
|
+
const all = [typesChunk, httpClientChunk, clientChunk, indexChunk];
|
|
5619
5838
|
return {
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5839
|
+
all,
|
|
5840
|
+
typesName: typesChunk.name,
|
|
5841
|
+
promiseWrappersNames: [httpClientChunk.name, clientChunk.name]
|
|
5623
5842
|
};
|
|
5624
5843
|
};
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
clientType = `${httpClientType}<${REQUEST_PARAMS_TYPE}>`;
|
|
5645
|
-
classTypeParams = `<${REQUEST_PARAMS_TYPE} = ${REQUEST_PARAMS_DEFAULT}>`;
|
|
5646
|
-
}
|
|
5647
|
-
const methodsCode = Array.isArray(operations) ? this.opsCode(tsCodegen, operations) : this.groupsOpsCode(tsCodegen, operations);
|
|
5648
|
-
const code = `
|
|
5649
|
-
export class ${apiName}${classTypeParams} {
|
|
5650
|
-
constructor(private readonly client: ${clientType}) {}
|
|
5651
|
-
|
|
5652
|
-
${methodsCode}
|
|
5653
|
-
}
|
|
5654
|
-
`;
|
|
5655
|
-
return tsCodegen.toChunk("api", code, [apiName]);
|
|
5656
|
-
});
|
|
5657
|
-
__publicField$2(this, "groupsOpsCode", (codegen, groupedOps) => Object.entries(groupedOps).map(([groupName, ops]) => {
|
|
5658
|
-
const methodsCode = this.opsCode(codegen, ops, "object");
|
|
5659
|
-
return `
|
|
5660
|
-
${toTsPropertyKey(groupName)} = {
|
|
5661
|
-
${methodsCode}
|
|
5662
|
-
}
|
|
5663
|
-
`;
|
|
5664
|
-
}).join("\n\n"));
|
|
5665
|
-
__publicField$2(this, "opsCode", (codegen, operations, target = "class") => {
|
|
5666
|
-
const separator = target === "object" ? `,
|
|
5667
|
-
${EMPTY_LINE_MARKER}
|
|
5668
|
-
` : "\n\n";
|
|
5669
|
-
const methodsCode = operations.map((op) => this.renderOp(op, codegen, target)).join(separator);
|
|
5670
|
-
return methodsCode;
|
|
5671
|
-
});
|
|
5672
|
-
__publicField$2(this, "renderOp", (op, tsCodegen, target) => {
|
|
5673
|
-
const { signature: sig, http } = op;
|
|
5674
|
-
const invocationVars = this.opts.httpClient.invocation.vars;
|
|
5675
|
-
const paramNames = {
|
|
5676
|
-
path: "path",
|
|
5677
|
-
query: invocationVars.query,
|
|
5678
|
-
body: invocationVars.body
|
|
5679
|
-
};
|
|
5680
|
-
const paramsHelper = new ParamsConstructor({
|
|
5681
|
-
paramNames,
|
|
5682
|
-
pathParamsStyle: this.opts.pathParamsStyle
|
|
5844
|
+
const createIndexChunk = (clientName) => ({
|
|
5845
|
+
name: "index",
|
|
5846
|
+
code: [
|
|
5847
|
+
`export { ${clientName} } from './${clientName}.client'`,
|
|
5848
|
+
`export * from './${clientName}.types'`,
|
|
5849
|
+
"export * from './HttpClient'"
|
|
5850
|
+
].join("\n"),
|
|
5851
|
+
exports: [],
|
|
5852
|
+
refs: []
|
|
5853
|
+
});
|
|
5854
|
+
const groupsOpsByTag = (operations) => {
|
|
5855
|
+
const groupedOps = {};
|
|
5856
|
+
const rawTagsByNormalizedName = /* @__PURE__ */ new Map();
|
|
5857
|
+
operations.forEach((operation) => {
|
|
5858
|
+
const rawTag = operation.tags.find((tag) => tag.trim())?.trim() || "root";
|
|
5859
|
+
let groupName;
|
|
5860
|
+
try {
|
|
5861
|
+
groupName = toTsCamelIdentifier(rawTag, {
|
|
5862
|
+
leadingDigitPrefix: "tag"
|
|
5683
5863
|
});
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5864
|
+
} catch {
|
|
5865
|
+
throw new Error(
|
|
5866
|
+
`Invalid OpenAPI tag "${rawTag}": could not derive a client group name.`
|
|
5687
5867
|
);
|
|
5688
|
-
|
|
5689
|
-
|
|
5868
|
+
}
|
|
5869
|
+
const existingRawTag = rawTagsByNormalizedName.get(groupName);
|
|
5870
|
+
if (existingRawTag && existingRawTag !== rawTag) {
|
|
5871
|
+
throw new Error(
|
|
5872
|
+
`Tag naming collision: "${existingRawTag}" and "${rawTag}" both normalize to "${groupName}". Rename one of these OpenAPI tags to continue.`
|
|
5690
5873
|
);
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5874
|
+
}
|
|
5875
|
+
rawTagsByNormalizedName.set(groupName, rawTag);
|
|
5876
|
+
const bucket = groupedOps[groupName] ?? [];
|
|
5877
|
+
bucket.push(operation.op);
|
|
5878
|
+
groupedOps[groupName] = bucket;
|
|
5879
|
+
});
|
|
5880
|
+
return groupedOps;
|
|
5881
|
+
};
|
|
5882
|
+
|
|
5883
|
+
var __defProp$3 = Object.defineProperty;
|
|
5884
|
+
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
5885
|
+
var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5886
|
+
const TS_IDENTIFIER_PATTERN = /^[$A-Z_][0-9A-Z_$]*$/i;
|
|
5887
|
+
class ToTypeExprConverter {
|
|
5888
|
+
constructor(schemas = {}, options) {
|
|
5889
|
+
this.schemas = schemas;
|
|
5890
|
+
this.options = options;
|
|
5891
|
+
__publicField$3(this, "schemaCache", /* @__PURE__ */ new WeakMap());
|
|
5892
|
+
__publicField$3(this, "refCache", /* @__PURE__ */ new Map());
|
|
5893
|
+
__publicField$3(this, "schemaDefinitions", []);
|
|
5894
|
+
__publicField$3(this, "schemaDefinitionsById", /* @__PURE__ */ new Map());
|
|
5895
|
+
__publicField$3(this, "schemaDefinitionsInProgress", /* @__PURE__ */ new Set());
|
|
5896
|
+
__publicField$3(this, "getSchemaDefinitions", () => this.schemaDefinitions);
|
|
5897
|
+
__publicField$3(this, "registerAllSchemaDefinitions", () => {
|
|
5898
|
+
Object.keys(this.schemas).forEach((schemaName) => {
|
|
5899
|
+
this.ensureSchemaDefinition(`#/components/schemas/${schemaName}`);
|
|
5711
5900
|
});
|
|
5712
5901
|
});
|
|
5713
|
-
__publicField$
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
|
|
5902
|
+
__publicField$3(this, "fromTypeExpr", (schema) => {
|
|
5903
|
+
if (!schema) {
|
|
5904
|
+
return this.scalar("unknown");
|
|
5905
|
+
}
|
|
5906
|
+
const bySchema = this.schemaCache.get(schema);
|
|
5907
|
+
if (bySchema) {
|
|
5908
|
+
return bySchema;
|
|
5909
|
+
}
|
|
5910
|
+
if (typeof schema.$ref === "string") {
|
|
5911
|
+
const byRef = this.refCache.get(this.refCacheKey(schema));
|
|
5912
|
+
if (byRef) {
|
|
5913
|
+
this.schemaCache.set(schema, byRef);
|
|
5914
|
+
return byRef;
|
|
5915
|
+
}
|
|
5916
|
+
}
|
|
5917
|
+
const projected = this.fromSchemaCore(schema);
|
|
5918
|
+
const result = schema.nullable === true ? this.withNullable(projected) : projected;
|
|
5919
|
+
this.schemaCache.set(schema, result);
|
|
5920
|
+
if (typeof schema.$ref === "string") {
|
|
5921
|
+
this.refCache.set(this.refCacheKey(schema), result);
|
|
5922
|
+
}
|
|
5923
|
+
return result;
|
|
5718
5924
|
});
|
|
5719
|
-
__publicField$
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5925
|
+
__publicField$3(this, "scalar", (name) => ({
|
|
5926
|
+
kind: "inline",
|
|
5927
|
+
expr: {
|
|
5928
|
+
node: "scalar",
|
|
5929
|
+
name
|
|
5930
|
+
}
|
|
5931
|
+
}));
|
|
5932
|
+
__publicField$3(this, "union", (members) => {
|
|
5933
|
+
const flatMembers = [];
|
|
5934
|
+
for (const member of members) {
|
|
5935
|
+
if (member.kind === "inline" && member.expr.node === "union") {
|
|
5936
|
+
flatMembers.push(...member.expr.members);
|
|
5937
|
+
} else {
|
|
5938
|
+
flatMembers.push(member);
|
|
5939
|
+
}
|
|
5940
|
+
}
|
|
5941
|
+
if (flatMembers.length === 1) {
|
|
5942
|
+
return flatMembers[0];
|
|
5943
|
+
}
|
|
5944
|
+
return {
|
|
5945
|
+
kind: "inline",
|
|
5946
|
+
expr: {
|
|
5947
|
+
node: "union",
|
|
5948
|
+
members: flatMembers
|
|
5949
|
+
}
|
|
5950
|
+
};
|
|
5951
|
+
});
|
|
5952
|
+
__publicField$3(this, "literal", (value) => ({
|
|
5953
|
+
kind: "inline",
|
|
5954
|
+
expr: {
|
|
5955
|
+
node: "literal",
|
|
5956
|
+
value
|
|
5957
|
+
}
|
|
5958
|
+
}));
|
|
5959
|
+
__publicField$3(this, "ref", (id) => {
|
|
5960
|
+
const name = this.refNameFromPath(id);
|
|
5961
|
+
return {
|
|
5962
|
+
kind: "reference",
|
|
5963
|
+
ref: {
|
|
5964
|
+
kind: "internal",
|
|
5965
|
+
name
|
|
5966
|
+
}
|
|
5967
|
+
};
|
|
5968
|
+
});
|
|
5969
|
+
__publicField$3(this, "builtinRef", (name) => ({
|
|
5970
|
+
kind: "reference",
|
|
5971
|
+
ref: {
|
|
5972
|
+
kind: "builtin",
|
|
5973
|
+
name
|
|
5974
|
+
}
|
|
5975
|
+
}));
|
|
5976
|
+
__publicField$3(this, "refNameFromPath", (ref) => {
|
|
5977
|
+
const parts = ref.split("/");
|
|
5978
|
+
const name = parts[parts.length - 1];
|
|
5979
|
+
if (!name) {
|
|
5980
|
+
throw new Error(`Unsupported schema reference: ${ref}`);
|
|
5981
|
+
}
|
|
5982
|
+
return name;
|
|
5983
|
+
});
|
|
5984
|
+
__publicField$3(this, "refCacheKey", (schema) => {
|
|
5985
|
+
return `${schema.$ref}|nullable:${schema.nullable === true}`;
|
|
5986
|
+
});
|
|
5987
|
+
__publicField$3(this, "isUnconstrainedSchema", (schema) => {
|
|
5988
|
+
const meaningfulKeys = Object.keys(schema).filter(
|
|
5989
|
+
(key) => key !== "nullable"
|
|
5990
|
+
);
|
|
5991
|
+
return meaningfulKeys.length === 0;
|
|
5992
|
+
});
|
|
5993
|
+
__publicField$3(this, "ensureSchemaDefinition", (refId) => {
|
|
5994
|
+
if (this.schemaDefinitionsById.has(refId) || this.schemaDefinitionsInProgress.has(refId)) {
|
|
5995
|
+
return;
|
|
5996
|
+
}
|
|
5997
|
+
const schemaName = this.refNameFromPath(refId);
|
|
5998
|
+
const schema = this.schemas[schemaName];
|
|
5999
|
+
if (!schema) {
|
|
6000
|
+
return;
|
|
6001
|
+
}
|
|
6002
|
+
this.schemaDefinitionsInProgress.add(refId);
|
|
6003
|
+
try {
|
|
6004
|
+
const definition = {
|
|
6005
|
+
name: schemaName,
|
|
6006
|
+
declaration: this.toDeclaration(schema)
|
|
6007
|
+
};
|
|
6008
|
+
this.schemaDefinitionsById.set(refId, definition);
|
|
6009
|
+
this.schemaDefinitions.push(definition);
|
|
6010
|
+
} finally {
|
|
6011
|
+
this.schemaDefinitionsInProgress.delete(refId);
|
|
6012
|
+
}
|
|
6013
|
+
});
|
|
6014
|
+
__publicField$3(this, "isSchemaNode", (value) => {
|
|
6015
|
+
return Boolean(
|
|
6016
|
+
value && typeof value === "object" && !Array.isArray(value)
|
|
6017
|
+
);
|
|
6018
|
+
});
|
|
6019
|
+
__publicField$3(this, "toLiteralValue", (value) => {
|
|
6020
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
6021
|
+
return value;
|
|
6022
|
+
}
|
|
6023
|
+
throw new Error(`Unsupported literal value: ${String(value)}`);
|
|
6024
|
+
});
|
|
6025
|
+
__publicField$3(this, "toDeclaration", (schema) => {
|
|
6026
|
+
const enumDeclaration = this.toEnumDeclaration(schema);
|
|
6027
|
+
if (enumDeclaration) {
|
|
6028
|
+
return enumDeclaration;
|
|
6029
|
+
}
|
|
6030
|
+
return {
|
|
6031
|
+
kind: "typeAlias",
|
|
6032
|
+
doc: this.getSchemaDoc(schema),
|
|
6033
|
+
typeExpr: this.fromTypeExpr(schema)
|
|
6034
|
+
};
|
|
6035
|
+
});
|
|
6036
|
+
__publicField$3(this, "toEnumDeclaration", (schema) => {
|
|
6037
|
+
if (this.options.enumStyle !== "enum" || !Array.isArray(schema.enum)) {
|
|
6038
|
+
return void 0;
|
|
6039
|
+
}
|
|
6040
|
+
const valueType = this.getEnumValueType(schema.enum);
|
|
6041
|
+
if (!valueType) {
|
|
6042
|
+
return void 0;
|
|
6043
|
+
}
|
|
6044
|
+
return {
|
|
6045
|
+
kind: "enum",
|
|
6046
|
+
doc: this.getSchemaDoc(schema),
|
|
6047
|
+
valueType,
|
|
6048
|
+
members: this.toEnumMembers(schema.enum)
|
|
6049
|
+
};
|
|
6050
|
+
});
|
|
6051
|
+
__publicField$3(this, "getEnumValueType", (values) => {
|
|
6052
|
+
if (!values.length) {
|
|
6053
|
+
return void 0;
|
|
6054
|
+
}
|
|
6055
|
+
if (values.every((value) => typeof value === "string")) {
|
|
6056
|
+
return "string";
|
|
6057
|
+
}
|
|
6058
|
+
if (values.every((value) => typeof value === "number")) {
|
|
6059
|
+
return "number";
|
|
6060
|
+
}
|
|
6061
|
+
return void 0;
|
|
6062
|
+
});
|
|
6063
|
+
__publicField$3(this, "toEnumMembers", (values) => {
|
|
6064
|
+
const usedNames = /* @__PURE__ */ new Map();
|
|
6065
|
+
return values.map((value, index) => {
|
|
6066
|
+
const enumValue = value;
|
|
6067
|
+
const baseName = this.toEnumMemberBaseName(enumValue, index);
|
|
6068
|
+
const nextCount = (usedNames.get(baseName) ?? 0) + 1;
|
|
6069
|
+
usedNames.set(baseName, nextCount);
|
|
6070
|
+
return {
|
|
6071
|
+
name: nextCount === 1 ? baseName : `${baseName}${nextCount}`,
|
|
6072
|
+
value: enumValue
|
|
6073
|
+
};
|
|
5747
6074
|
});
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
6075
|
+
});
|
|
6076
|
+
__publicField$3(this, "toEnumMemberBaseName", (value, index) => {
|
|
6077
|
+
if (typeof value === "string" && this.options.uppercaseEnumKeys) {
|
|
6078
|
+
const compatName = this.toCompatEnumMemberName(value);
|
|
6079
|
+
if (compatName) {
|
|
6080
|
+
return compatName;
|
|
6081
|
+
}
|
|
6082
|
+
}
|
|
6083
|
+
if (typeof value === "string" && TS_IDENTIFIER_PATTERN.test(value) && !RESERVED_WORDS.has(value)) {
|
|
6084
|
+
return value;
|
|
6085
|
+
}
|
|
6086
|
+
if (typeof value === "number" && Number.isInteger(value) && value >= 0) {
|
|
6087
|
+
return `Value${value}`;
|
|
6088
|
+
}
|
|
6089
|
+
const pascalName = toPascalCaseIdentifier(String(value));
|
|
6090
|
+
return pascalName === "Api" ? `Value${index + 1}` : pascalName;
|
|
6091
|
+
});
|
|
6092
|
+
__publicField$3(this, "toCompatEnumMemberName", (value) => {
|
|
6093
|
+
if (/^([A-Z_]{1,})$/g.test(value)) {
|
|
6094
|
+
return value;
|
|
6095
|
+
}
|
|
6096
|
+
const pascalName = toPascalCaseIdentifier(value);
|
|
6097
|
+
return pascalName === "Api" ? void 0 : pascalName;
|
|
6098
|
+
});
|
|
6099
|
+
__publicField$3(this, "isScalarName", (value) => {
|
|
6100
|
+
switch (value) {
|
|
6101
|
+
case "string":
|
|
6102
|
+
case "number":
|
|
6103
|
+
case "boolean":
|
|
6104
|
+
case "integer":
|
|
6105
|
+
case "null":
|
|
6106
|
+
case "unknown":
|
|
6107
|
+
case "any":
|
|
6108
|
+
case "never":
|
|
6109
|
+
case "void":
|
|
6110
|
+
return true;
|
|
6111
|
+
default:
|
|
6112
|
+
return false;
|
|
6113
|
+
}
|
|
6114
|
+
});
|
|
6115
|
+
__publicField$3(this, "hasNullMember", (expr) => {
|
|
6116
|
+
if (expr.kind !== "inline") return false;
|
|
6117
|
+
if (expr.expr.node === "scalar") {
|
|
6118
|
+
return expr.expr.name === "null";
|
|
6119
|
+
}
|
|
6120
|
+
if (expr.expr.node === "union") {
|
|
6121
|
+
return expr.expr.members.some((member) => this.hasNullMember(member));
|
|
6122
|
+
}
|
|
6123
|
+
return false;
|
|
6124
|
+
});
|
|
6125
|
+
__publicField$3(this, "withNullable", (expr) => {
|
|
6126
|
+
if (this.hasNullMember(expr)) {
|
|
6127
|
+
return expr;
|
|
6128
|
+
}
|
|
6129
|
+
return this.union([expr, this.scalar("null")]);
|
|
6130
|
+
});
|
|
6131
|
+
__publicField$3(this, "projectObjectType", (schema) => {
|
|
6132
|
+
const requiredRaw = schema.required;
|
|
6133
|
+
if (requiredRaw !== void 0 && !Array.isArray(requiredRaw)) {
|
|
6134
|
+
throw new Error(
|
|
6135
|
+
"Unsupported object schema: required must be an array"
|
|
6136
|
+
);
|
|
6137
|
+
}
|
|
6138
|
+
const required = new Set(
|
|
6139
|
+
(requiredRaw ?? []).map((item) => {
|
|
6140
|
+
if (typeof item !== "string") {
|
|
6141
|
+
throw new Error(
|
|
6142
|
+
"Unsupported object schema: required items must be strings"
|
|
6143
|
+
);
|
|
6144
|
+
}
|
|
6145
|
+
return item;
|
|
6146
|
+
})
|
|
6147
|
+
);
|
|
6148
|
+
const propertiesRaw = schema.properties;
|
|
6149
|
+
if (propertiesRaw !== void 0 && (!propertiesRaw || typeof propertiesRaw !== "object" || Array.isArray(propertiesRaw))) {
|
|
6150
|
+
throw new Error(
|
|
6151
|
+
"Unsupported object schema: properties must be an object"
|
|
6152
|
+
);
|
|
6153
|
+
}
|
|
6154
|
+
const properties = Object.entries(propertiesRaw ?? {}).map(
|
|
6155
|
+
([name, propertySchema]) => {
|
|
6156
|
+
if (!this.isSchemaNode(propertySchema)) {
|
|
6157
|
+
throw new Error(
|
|
6158
|
+
`Unsupported object property schema for "${name}"`
|
|
6159
|
+
);
|
|
6160
|
+
}
|
|
6161
|
+
return {
|
|
6162
|
+
doc: this.getSchemaDoc(propertySchema),
|
|
6163
|
+
name,
|
|
6164
|
+
required: this.isRequiredProperty(
|
|
6165
|
+
name,
|
|
6166
|
+
required,
|
|
6167
|
+
propertySchema
|
|
6168
|
+
),
|
|
6169
|
+
typeExpr: this.fromTypeExpr(propertySchema)
|
|
6170
|
+
};
|
|
6171
|
+
}
|
|
6172
|
+
);
|
|
6173
|
+
let additionalProperties;
|
|
6174
|
+
if (schema.additionalProperties !== void 0) {
|
|
6175
|
+
if (typeof schema.additionalProperties === "boolean") {
|
|
6176
|
+
additionalProperties = schema.additionalProperties;
|
|
6177
|
+
} else if (this.isSchemaNode(schema.additionalProperties)) {
|
|
6178
|
+
additionalProperties = this.fromTypeExpr(
|
|
6179
|
+
schema.additionalProperties
|
|
6180
|
+
);
|
|
6181
|
+
} else {
|
|
6182
|
+
throw new Error(
|
|
6183
|
+
"Unsupported object schema: additionalProperties must be boolean or schema object"
|
|
6184
|
+
);
|
|
6185
|
+
}
|
|
6186
|
+
}
|
|
6187
|
+
return {
|
|
6188
|
+
kind: "inline",
|
|
6189
|
+
expr: {
|
|
6190
|
+
node: "object",
|
|
6191
|
+
properties,
|
|
6192
|
+
additionalProperties
|
|
6193
|
+
}
|
|
6194
|
+
};
|
|
6195
|
+
});
|
|
6196
|
+
__publicField$3(this, "isRequiredProperty", (name, required, propertySchema) => {
|
|
6197
|
+
if (required.has(name)) {
|
|
6198
|
+
return true;
|
|
6199
|
+
}
|
|
6200
|
+
if (!this.options.swaggerTsApiRequiredBooleans) {
|
|
6201
|
+
return false;
|
|
6202
|
+
}
|
|
6203
|
+
return propertySchema.required === true;
|
|
6204
|
+
});
|
|
6205
|
+
__publicField$3(this, "mapSchemaArrayMembers", (value, kind) => {
|
|
6206
|
+
if (!Array.isArray(value) || !value.length) {
|
|
6207
|
+
throw new Error(
|
|
6208
|
+
`Unsupported schema: ${kind} must be a non-empty array`
|
|
6209
|
+
);
|
|
6210
|
+
}
|
|
6211
|
+
return value.map((entry, index) => {
|
|
6212
|
+
if (!this.isSchemaNode(entry)) {
|
|
6213
|
+
throw new Error(
|
|
6214
|
+
`Unsupported schema: ${kind}[${index}] must be a schema object`
|
|
6215
|
+
);
|
|
6216
|
+
}
|
|
6217
|
+
return this.fromTypeExpr(entry);
|
|
6218
|
+
});
|
|
6219
|
+
});
|
|
6220
|
+
__publicField$3(this, "isBinaryFileSchema", (schema) => {
|
|
6221
|
+
return schema.type === "string" && schema.format === "binary";
|
|
6222
|
+
});
|
|
6223
|
+
__publicField$3(this, "getSchemaDoc", (schema) => {
|
|
6224
|
+
const summary = typeof schema.summary === "string" ? schema.summary : void 0;
|
|
6225
|
+
const description = typeof schema.description === "string" ? schema.description : void 0;
|
|
6226
|
+
const deprecated = typeof schema.deprecated === "boolean" ? schema.deprecated : void 0;
|
|
6227
|
+
const annotations = this.getSchemaAnnotations(schema);
|
|
6228
|
+
if (!summary && !description && !deprecated && !annotations.length) {
|
|
6229
|
+
return void 0;
|
|
6230
|
+
}
|
|
6231
|
+
const nodes = [];
|
|
6232
|
+
if (summary) {
|
|
6233
|
+
nodes.push(summary);
|
|
6234
|
+
}
|
|
6235
|
+
if (description) {
|
|
6236
|
+
nodes.push(description);
|
|
6237
|
+
}
|
|
6238
|
+
nodes.push(...annotations);
|
|
6239
|
+
return {
|
|
6240
|
+
deprecated,
|
|
6241
|
+
nodes
|
|
6242
|
+
};
|
|
6243
|
+
});
|
|
6244
|
+
__publicField$3(this, "getSchemaAnnotations", (schema) => {
|
|
6245
|
+
if (this.options.comments?.metadata === false) return [];
|
|
6246
|
+
return [
|
|
6247
|
+
this.annotationNode("format", schema.format),
|
|
6248
|
+
this.annotationNode("min", schema.minimum),
|
|
6249
|
+
this.annotationNode("multipleOf", schema.multipleOf),
|
|
6250
|
+
this.annotationNode("exclusiveMin", schema.exclusiveMinimum),
|
|
6251
|
+
this.annotationNode("max", schema.maximum),
|
|
6252
|
+
this.annotationNode("minLength", schema.minLength),
|
|
6253
|
+
this.annotationNode("maxLength", schema.maxLength),
|
|
6254
|
+
this.annotationNode("exclusiveMax", schema.exclusiveMaximum),
|
|
6255
|
+
this.annotationNode("maxItems", schema.maxItems),
|
|
6256
|
+
this.annotationNode("minItems", schema.minItems),
|
|
6257
|
+
this.annotationNode("uniqueItems", schema.uniqueItems),
|
|
6258
|
+
this.annotationNode(
|
|
6259
|
+
"default",
|
|
6260
|
+
this.stringifyAnnotationValue(schema.default)
|
|
6261
|
+
),
|
|
6262
|
+
this.annotationNode("pattern", schema.pattern),
|
|
6263
|
+
this.annotationNode(
|
|
6264
|
+
"example",
|
|
6265
|
+
this.stringifyAnnotationValue(schema.example)
|
|
6266
|
+
)
|
|
6267
|
+
].filter(
|
|
6268
|
+
(value) => value !== void 0
|
|
6269
|
+
);
|
|
6270
|
+
});
|
|
6271
|
+
__publicField$3(this, "annotationNode", (name, value) => {
|
|
6272
|
+
if (value === void 0) return void 0;
|
|
6273
|
+
return {
|
|
6274
|
+
key: name,
|
|
6275
|
+
value: String(value)
|
|
6276
|
+
};
|
|
6277
|
+
});
|
|
6278
|
+
__publicField$3(this, "stringifyAnnotationValue", (value) => {
|
|
6279
|
+
if (value === void 0) return void 0;
|
|
6280
|
+
if (value && typeof value === "object") {
|
|
6281
|
+
return JSON.stringify(value);
|
|
6282
|
+
}
|
|
6283
|
+
if (typeof value === "string") {
|
|
6284
|
+
return JSON.stringify(value);
|
|
6285
|
+
}
|
|
6286
|
+
return String(value);
|
|
6287
|
+
});
|
|
6288
|
+
__publicField$3(this, "fromSchemaCore", (schema) => {
|
|
6289
|
+
if (this.isUnconstrainedSchema(schema)) {
|
|
6290
|
+
return this.scalar("unknown");
|
|
6291
|
+
}
|
|
6292
|
+
if (typeof schema.$ref === "string") {
|
|
6293
|
+
this.ensureSchemaDefinition(schema.$ref);
|
|
6294
|
+
return this.ref(schema.$ref);
|
|
6295
|
+
}
|
|
6296
|
+
if (schema.const !== void 0) {
|
|
6297
|
+
return this.literal(this.toLiteralValue(schema.const));
|
|
6298
|
+
}
|
|
6299
|
+
if (Array.isArray(schema.enum)) {
|
|
6300
|
+
if (!schema.enum.length) {
|
|
6301
|
+
throw new Error(
|
|
6302
|
+
"Unsupported enum schema: enum must be non-empty"
|
|
6303
|
+
);
|
|
6304
|
+
}
|
|
6305
|
+
return this.union(
|
|
6306
|
+
schema.enum.map(
|
|
6307
|
+
(value) => this.literal(this.toLiteralValue(value))
|
|
6308
|
+
)
|
|
6309
|
+
);
|
|
6310
|
+
}
|
|
6311
|
+
if (schema.type === "array") {
|
|
6312
|
+
if (schema.items === void 0) {
|
|
6313
|
+
return {
|
|
6314
|
+
kind: "inline",
|
|
6315
|
+
expr: {
|
|
6316
|
+
node: "array",
|
|
6317
|
+
element: this.scalar("unknown")
|
|
6318
|
+
}
|
|
6319
|
+
};
|
|
6320
|
+
}
|
|
6321
|
+
if (Array.isArray(schema.items)) {
|
|
6322
|
+
throw new Error("Unsupported array schema: tuple-style items");
|
|
6323
|
+
}
|
|
6324
|
+
if (!this.isSchemaNode(schema.items)) {
|
|
6325
|
+
throw new Error(
|
|
6326
|
+
"Unsupported array schema: items must be a schema"
|
|
6327
|
+
);
|
|
6328
|
+
}
|
|
6329
|
+
return {
|
|
6330
|
+
kind: "inline",
|
|
6331
|
+
expr: {
|
|
6332
|
+
node: "array",
|
|
6333
|
+
element: this.fromTypeExpr(schema.items)
|
|
6334
|
+
}
|
|
6335
|
+
};
|
|
6336
|
+
}
|
|
6337
|
+
if (schema.type === "object") {
|
|
6338
|
+
return this.projectObjectType(schema);
|
|
6339
|
+
}
|
|
6340
|
+
if (schema.oneOf !== void 0) {
|
|
6341
|
+
return this.union(this.mapSchemaArrayMembers(schema.oneOf, "oneOf"));
|
|
6342
|
+
}
|
|
6343
|
+
if (schema.anyOf !== void 0) {
|
|
6344
|
+
return this.union(this.mapSchemaArrayMembers(schema.anyOf, "anyOf"));
|
|
6345
|
+
}
|
|
6346
|
+
if (schema.allOf !== void 0) {
|
|
6347
|
+
return {
|
|
6348
|
+
kind: "inline",
|
|
6349
|
+
expr: {
|
|
6350
|
+
node: "intersection",
|
|
6351
|
+
members: this.mapSchemaArrayMembers(schema.allOf, "allOf")
|
|
6352
|
+
}
|
|
6353
|
+
};
|
|
6354
|
+
}
|
|
6355
|
+
if (this.isBinaryFileSchema(schema)) {
|
|
6356
|
+
return this.builtinRef("File");
|
|
6357
|
+
}
|
|
6358
|
+
if (this.isScalarName(schema.type)) {
|
|
6359
|
+
return this.scalar(schema.type);
|
|
6360
|
+
}
|
|
6361
|
+
throw new Error(
|
|
6362
|
+
`Unsupported schema construct: ${JSON.stringify(schema, null, 2)}`
|
|
6363
|
+
);
|
|
5754
6364
|
});
|
|
5755
6365
|
}
|
|
5756
6366
|
}
|
|
5757
6367
|
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
|
|
5768
|
-
|
|
5769
|
-
|
|
5770
|
-
|
|
6368
|
+
var __defProp$2 = Object.defineProperty;
|
|
6369
|
+
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6370
|
+
var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
6371
|
+
const pickPreferredMediaType = (mediaTypes) => {
|
|
6372
|
+
if (!mediaTypes.length) return void 0;
|
|
6373
|
+
const exactJson = mediaTypes.find((media) => media === "application/json");
|
|
6374
|
+
if (exactJson) return exactJson;
|
|
6375
|
+
const jsonLike = mediaTypes.find((media) => /\+json$/i.test(media));
|
|
6376
|
+
if (jsonLike) return jsonLike;
|
|
6377
|
+
const wildcardJson = mediaTypes.find(
|
|
6378
|
+
(media) => /application\/\*\+json/i.test(media)
|
|
6379
|
+
);
|
|
6380
|
+
if (wildcardJson) return wildcardJson;
|
|
6381
|
+
return mediaTypes[0];
|
|
6382
|
+
};
|
|
6383
|
+
const isSuccessStatusCode = (statusCode) => {
|
|
6384
|
+
const upper = statusCode.toUpperCase();
|
|
6385
|
+
if (/^2XX$/.test(upper)) {
|
|
6386
|
+
return true;
|
|
6387
|
+
}
|
|
6388
|
+
const numericCode = Number(statusCode);
|
|
6389
|
+
return Number.isFinite(numericCode) && numericCode >= 200 && numericCode < 300;
|
|
6390
|
+
};
|
|
6391
|
+
const selectReturnResponses = (responses) => {
|
|
6392
|
+
const entries = Object.entries(responses);
|
|
6393
|
+
if (!entries.length) {
|
|
6394
|
+
return [];
|
|
6395
|
+
}
|
|
6396
|
+
const success = entries.filter(([statusCode]) => isSuccessStatusCode(statusCode)).map(([, response]) => response);
|
|
6397
|
+
if (success.length) {
|
|
6398
|
+
return success;
|
|
6399
|
+
}
|
|
6400
|
+
const defaultResponse = entries.find(
|
|
6401
|
+
([statusCode]) => statusCode.toLowerCase() === "default"
|
|
6402
|
+
);
|
|
6403
|
+
if (defaultResponse) {
|
|
6404
|
+
return [defaultResponse[1]];
|
|
6405
|
+
}
|
|
6406
|
+
return entries.map(([, response]) => response);
|
|
6407
|
+
};
|
|
6408
|
+
const getPreferredMediaTypeEntry = (content) => {
|
|
6409
|
+
const mediaType = pickPreferredMediaType(Object.keys(content));
|
|
6410
|
+
if (!mediaType) return {};
|
|
6411
|
+
return {
|
|
6412
|
+
mediaType,
|
|
6413
|
+
media: content[mediaType]
|
|
6414
|
+
};
|
|
6415
|
+
};
|
|
6416
|
+
const isBinaryFileResponse = (response) => {
|
|
6417
|
+
const { mediaType, media } = getPreferredMediaTypeEntry(response.content);
|
|
6418
|
+
return media?.schema?.type === "string" && media.schema?.format === "binary" && mediaType !== "multipart/form-data";
|
|
6419
|
+
};
|
|
6420
|
+
const isJsonLikeMediaType = (mediaType) => {
|
|
6421
|
+
return mediaType === "application/json" || typeof mediaType === "string" && /\+json$/i.test(mediaType);
|
|
6422
|
+
};
|
|
6423
|
+
const toHttpMethodUpper = (method) => {
|
|
6424
|
+
switch (method) {
|
|
6425
|
+
case "get":
|
|
6426
|
+
return "GET";
|
|
6427
|
+
case "post":
|
|
6428
|
+
return "POST";
|
|
6429
|
+
case "put":
|
|
6430
|
+
return "PUT";
|
|
6431
|
+
case "delete":
|
|
6432
|
+
return "DELETE";
|
|
6433
|
+
case "patch":
|
|
6434
|
+
return "PATCH";
|
|
6435
|
+
case "options":
|
|
6436
|
+
return "OPTIONS";
|
|
6437
|
+
case "head":
|
|
6438
|
+
return "HEAD";
|
|
6439
|
+
case "trace":
|
|
6440
|
+
return "TRACE";
|
|
6441
|
+
default: {
|
|
6442
|
+
const exhaustive = method;
|
|
6443
|
+
throw new Error(`Unsupported HTTP method: ${String(exhaustive)}`);
|
|
5771
6444
|
}
|
|
5772
|
-
},
|
|
5773
|
-
inferMethodReturnType: true,
|
|
5774
|
-
invocation: {
|
|
5775
|
-
vars: {
|
|
5776
|
-
body: "body",
|
|
5777
|
-
query: "query"
|
|
5778
|
-
},
|
|
5779
|
-
expr: ({
|
|
5780
|
-
responseType,
|
|
5781
|
-
path,
|
|
5782
|
-
method,
|
|
5783
|
-
hasBody,
|
|
5784
|
-
hasQuery,
|
|
5785
|
-
requestContentType,
|
|
5786
|
-
responseFormat,
|
|
5787
|
-
requestParamsVar,
|
|
5788
|
-
unwrap
|
|
5789
|
-
}) => `.request<${responseType}>({
|
|
5790
|
-
method: '${method}',
|
|
5791
|
-
path: ${path}
|
|
5792
|
-
${hasQuery ? `,
|
|
5793
|
-
query` : ""}
|
|
5794
|
-
${hasBody ? `,
|
|
5795
|
-
body` : ""}
|
|
5796
|
-
${requestContentType ? `,
|
|
5797
|
-
requestContentType: '${requestContentType}'` : ""}
|
|
5798
|
-
${responseFormat ? `,
|
|
5799
|
-
format: '${responseFormat}'` : ""}
|
|
5800
|
-
}${requestParamsVar ? `,
|
|
5801
|
-
${requestParamsVar}` : ""})${unwrap ? `.then(res => res.body)` : ""}
|
|
5802
|
-
`
|
|
5803
6445
|
}
|
|
5804
|
-
}
|
|
6446
|
+
};
|
|
6447
|
+
class OperationProjector {
|
|
6448
|
+
constructor(options) {
|
|
6449
|
+
this.options = options;
|
|
6450
|
+
__publicField$2(this, "seenOperationIds", /* @__PURE__ */ new Set());
|
|
6451
|
+
__publicField$2(this, "typeExprConverter");
|
|
6452
|
+
__publicField$2(this, "project", (openApi) => {
|
|
6453
|
+
this.seenOperationIds.clear();
|
|
6454
|
+
this.typeExprConverter = new ToTypeExprConverter(
|
|
6455
|
+
openApi.schemas,
|
|
6456
|
+
this.options.typeExtraction
|
|
6457
|
+
);
|
|
6458
|
+
if (this.options.includeAllSchema) {
|
|
6459
|
+
this.typeExprConverter.registerAllSchemaDefinitions();
|
|
6460
|
+
}
|
|
6461
|
+
const operations = openApi.operations.map((operation) => {
|
|
6462
|
+
const operationName = (operation.operationId ?? syntheticOperationId(operation.method, operation.path)).trim();
|
|
6463
|
+
if (!operationName) {
|
|
6464
|
+
throw new Error(
|
|
6465
|
+
`Operation id is empty for ${operation.method.toUpperCase()} ${operation.path}`
|
|
6466
|
+
);
|
|
6467
|
+
}
|
|
6468
|
+
if (this.seenOperationIds.has(operationName)) {
|
|
6469
|
+
throw new Error(`Duplicate operation id: ${operationName}`);
|
|
6470
|
+
}
|
|
6471
|
+
return this.projectOne(operationName, operation);
|
|
6472
|
+
});
|
|
6473
|
+
return {
|
|
6474
|
+
api: {
|
|
6475
|
+
title: openApi.info.title,
|
|
6476
|
+
version: openApi.info.version,
|
|
6477
|
+
description: openApi.info.description
|
|
6478
|
+
},
|
|
6479
|
+
operations,
|
|
6480
|
+
schemaDefinitions: this.typeExprConverter.getSchemaDefinitions()
|
|
6481
|
+
};
|
|
6482
|
+
});
|
|
6483
|
+
__publicField$2(this, "projectOne", (operationName, operation) => {
|
|
6484
|
+
this.seenOperationIds.add(operationName);
|
|
6485
|
+
const parameters = [];
|
|
6486
|
+
const pathParameter = this.projectPathParameter(operation);
|
|
6487
|
+
const queryParameter = this.projectQueryParameter(operation);
|
|
6488
|
+
const bodyParameter = this.projectBodyParameter(operation);
|
|
6489
|
+
if (pathParameter) parameters.push(pathParameter);
|
|
6490
|
+
if (queryParameter) parameters.push(queryParameter);
|
|
6491
|
+
if (bodyParameter) parameters.push(bodyParameter);
|
|
6492
|
+
return {
|
|
6493
|
+
op: {
|
|
6494
|
+
signature: {
|
|
6495
|
+
doc: this.toOperationDoc(operationName, operation),
|
|
6496
|
+
name: operationName,
|
|
6497
|
+
parameters,
|
|
6498
|
+
returnType: this.projectReturnType(operation)
|
|
6499
|
+
},
|
|
6500
|
+
http: {
|
|
6501
|
+
method: toHttpMethodUpper(operation.method),
|
|
6502
|
+
path: operation.path,
|
|
6503
|
+
requestContentType: this.projectRequestContentType(
|
|
6504
|
+
operation.requestBody
|
|
6505
|
+
),
|
|
6506
|
+
responseFormat: this.projectResponseFormat(operation)
|
|
6507
|
+
}
|
|
6508
|
+
},
|
|
6509
|
+
tags: [...operation.tags]
|
|
6510
|
+
};
|
|
6511
|
+
});
|
|
6512
|
+
__publicField$2(this, "projectRequestContentType", (requestBody) => {
|
|
6513
|
+
const { mediaType } = getPreferredMediaTypeEntry(
|
|
6514
|
+
requestBody?.content ?? {}
|
|
6515
|
+
);
|
|
6516
|
+
switch (mediaType) {
|
|
6517
|
+
case "application/json":
|
|
6518
|
+
case "multipart/form-data":
|
|
6519
|
+
case "application/x-www-form-urlencoded":
|
|
6520
|
+
return mediaType;
|
|
6521
|
+
default:
|
|
6522
|
+
return void 0;
|
|
6523
|
+
}
|
|
6524
|
+
});
|
|
6525
|
+
__publicField$2(this, "projectResponseFormat", (operation) => {
|
|
6526
|
+
const selectedResponses = selectReturnResponses(operation.responses);
|
|
6527
|
+
if (!selectedResponses.length) {
|
|
6528
|
+
return void 0;
|
|
6529
|
+
}
|
|
6530
|
+
if (selectedResponses.some((response) => isBinaryFileResponse(response))) {
|
|
6531
|
+
return "document";
|
|
6532
|
+
}
|
|
6533
|
+
if (selectedResponses.some(
|
|
6534
|
+
(response) => isJsonLikeMediaType(
|
|
6535
|
+
getPreferredMediaTypeEntry(response.content).mediaType
|
|
6536
|
+
)
|
|
6537
|
+
)) {
|
|
6538
|
+
return "json";
|
|
6539
|
+
}
|
|
6540
|
+
return void 0;
|
|
6541
|
+
});
|
|
6542
|
+
__publicField$2(this, "projectParameterGroupTypeExpr", (params) => {
|
|
6543
|
+
const properties = Object.entries(params).map(([name, parameter]) => ({
|
|
6544
|
+
doc: this.toParameterDoc(parameter),
|
|
6545
|
+
name,
|
|
6546
|
+
required: parameter.required,
|
|
6547
|
+
typeExpr: this.typeExprConverter.fromTypeExpr(
|
|
6548
|
+
this.selectParameterSchema(parameter)
|
|
6549
|
+
)
|
|
6550
|
+
}));
|
|
6551
|
+
return {
|
|
6552
|
+
kind: "inline",
|
|
6553
|
+
expr: {
|
|
6554
|
+
node: "object",
|
|
6555
|
+
properties
|
|
6556
|
+
}
|
|
6557
|
+
};
|
|
6558
|
+
});
|
|
6559
|
+
__publicField$2(this, "projectPathParameter", (operation) => {
|
|
6560
|
+
const params = operation.parameters.path;
|
|
6561
|
+
const entries = Object.values(params);
|
|
6562
|
+
if (!entries.length) return null;
|
|
6563
|
+
if (entries.some((parameter) => !parameter.required)) {
|
|
6564
|
+
throw new Error("Unsupported path parameters: all must be required");
|
|
6565
|
+
}
|
|
6566
|
+
return {
|
|
6567
|
+
kind: "path",
|
|
6568
|
+
optional: false,
|
|
6569
|
+
typeExpr: this.projectParameterGroupTypeExpr(params)
|
|
6570
|
+
};
|
|
6571
|
+
});
|
|
6572
|
+
__publicField$2(this, "projectQueryParameter", (operation) => {
|
|
6573
|
+
const params = operation.parameters.query;
|
|
6574
|
+
const entries = Object.values(params);
|
|
6575
|
+
if (!entries.length) return null;
|
|
6576
|
+
return {
|
|
6577
|
+
kind: "query",
|
|
6578
|
+
optional: !entries.some((parameter) => parameter.required),
|
|
6579
|
+
typeExpr: this.projectParameterGroupTypeExpr(params)
|
|
6580
|
+
};
|
|
6581
|
+
});
|
|
6582
|
+
__publicField$2(this, "projectBodyParameter", (operation) => {
|
|
6583
|
+
const requestBody = operation.requestBody;
|
|
6584
|
+
if (!requestBody) return null;
|
|
6585
|
+
return {
|
|
6586
|
+
kind: "body",
|
|
6587
|
+
optional: !requestBody.required,
|
|
6588
|
+
typeExpr: this.typeExprConverter.fromTypeExpr(
|
|
6589
|
+
this.selectRequestBodySchema(requestBody)
|
|
6590
|
+
)
|
|
6591
|
+
};
|
|
6592
|
+
});
|
|
6593
|
+
__publicField$2(this, "projectReturnType", (operation) => {
|
|
6594
|
+
const selectedResponses = selectReturnResponses(operation.responses);
|
|
6595
|
+
if (!selectedResponses.length) {
|
|
6596
|
+
return this.typeExprConverter.scalar("void");
|
|
6597
|
+
}
|
|
6598
|
+
const responseTypes = selectedResponses.map((response) => {
|
|
6599
|
+
const schema = this.selectResponseSchema(response);
|
|
6600
|
+
if (!schema) {
|
|
6601
|
+
return this.typeExprConverter.scalar("void");
|
|
6602
|
+
}
|
|
6603
|
+
return this.typeExprConverter.fromTypeExpr(schema);
|
|
6604
|
+
});
|
|
6605
|
+
return this.typeExprConverter.union(responseTypes);
|
|
6606
|
+
});
|
|
6607
|
+
__publicField$2(this, "selectParameterSchema", (parameter) => {
|
|
6608
|
+
if (parameter.schema) return parameter.schema;
|
|
6609
|
+
return getPreferredMediaTypeEntry(parameter.content).media?.schema;
|
|
6610
|
+
});
|
|
6611
|
+
__publicField$2(this, "selectRequestBodySchema", (requestBody) => {
|
|
6612
|
+
return getPreferredMediaTypeEntry(requestBody.content).media?.schema;
|
|
6613
|
+
});
|
|
6614
|
+
__publicField$2(this, "selectResponseSchema", (response) => {
|
|
6615
|
+
return getPreferredMediaTypeEntry(response.content).media?.schema;
|
|
6616
|
+
});
|
|
6617
|
+
__publicField$2(this, "toParameterDoc", (parameter) => {
|
|
6618
|
+
if (!parameter.description && !parameter.deprecated) {
|
|
6619
|
+
return void 0;
|
|
6620
|
+
}
|
|
6621
|
+
return {
|
|
6622
|
+
deprecated: parameter.deprecated,
|
|
6623
|
+
nodes: parameter.description ? [parameter.description] : []
|
|
6624
|
+
};
|
|
6625
|
+
});
|
|
6626
|
+
__publicField$2(this, "toOperationDoc", (operationName, operation) => {
|
|
6627
|
+
return {
|
|
6628
|
+
id: operationName,
|
|
6629
|
+
request: `${toHttpMethodUpper(operation.method)}:${operation.path}`,
|
|
6630
|
+
summary: operation.summary,
|
|
6631
|
+
description: operation.description,
|
|
6632
|
+
deprecated: operation.deprecated,
|
|
6633
|
+
tags: operation.tags.map((tag) => tag.trim()).filter(Boolean)
|
|
6634
|
+
};
|
|
6635
|
+
});
|
|
6636
|
+
}
|
|
6637
|
+
}
|
|
5805
6638
|
|
|
5806
6639
|
var __defProp$1 = Object.defineProperty;
|
|
5807
6640
|
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -5817,7 +6650,7 @@ class CodeFormatter {
|
|
|
5817
6650
|
constructor(opts) {
|
|
5818
6651
|
this.opts = opts;
|
|
5819
6652
|
__publicField$1(this, "format", async (code) => {
|
|
5820
|
-
const filePath = Path.resolve(this.opts.resolveConfFrom, "generated.ts");
|
|
6653
|
+
const filePath = Path$1.resolve(this.opts.resolveConfFrom, "generated.ts");
|
|
5821
6654
|
const prettier = await import('prettier');
|
|
5822
6655
|
const prettierConfig = await prettier.resolveConfig(filePath) ?? {};
|
|
5823
6656
|
const formattedCode = await prettier.format(code, {
|
|
@@ -5911,185 +6744,77 @@ class CodeWriter {
|
|
|
5911
6744
|
}
|
|
5912
6745
|
const ensureSingleTrailingNewline = (code) => code.replace(/\n+$/u, "\n");
|
|
5913
6746
|
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
|
|
5918
|
-
const orderedChunks = orderByInternalDependencies(chunks);
|
|
5919
|
-
const mergedCode = orderedChunks.map((chunk) => chunk.code).join("\n\n");
|
|
5920
|
-
const exportedSymbols = /* @__PURE__ */ new Set();
|
|
5921
|
-
const mergedExports = [];
|
|
5922
|
-
for (const chunk of orderedChunks) {
|
|
5923
|
-
for (const symbol of chunk.exports) {
|
|
5924
|
-
if (exportedSymbols.has(symbol)) continue;
|
|
5925
|
-
exportedSymbols.add(symbol);
|
|
5926
|
-
mergedExports.push(symbol);
|
|
5927
|
-
}
|
|
5928
|
-
}
|
|
5929
|
-
const seenRefKeys = /* @__PURE__ */ new Set();
|
|
5930
|
-
const mergedRefs = orderedChunks.flatMap((chunk) => chunk.refs).filter((ref) => {
|
|
5931
|
-
if (ref.kind === "internal" && exportedSymbols.has(ref.name)) {
|
|
5932
|
-
return false;
|
|
5933
|
-
}
|
|
5934
|
-
const key = ref.kind === "internal" ? `internal:${ref.name}` : ref.kind === "external" ? `external:${ref.package}:${ref.name}` : `builtin:${ref.name}`;
|
|
5935
|
-
if (seenRefKeys.has(key)) return false;
|
|
5936
|
-
seenRefKeys.add(key);
|
|
5937
|
-
return true;
|
|
5938
|
-
});
|
|
5939
|
-
return {
|
|
5940
|
-
name,
|
|
5941
|
-
code: mergedCode,
|
|
5942
|
-
exports: mergedExports,
|
|
5943
|
-
refs: mergedRefs
|
|
5944
|
-
};
|
|
5945
|
-
};
|
|
5946
|
-
const orderByInternalDependencies = (chunks) => {
|
|
5947
|
-
const chunkIndex = /* @__PURE__ */ new Map();
|
|
5948
|
-
const exportOwnerBySymbol = /* @__PURE__ */ new Map();
|
|
5949
|
-
chunks.forEach((chunk, index) => {
|
|
5950
|
-
chunkIndex.set(chunk.name, index);
|
|
5951
|
-
for (const symbol of chunk.exports) {
|
|
5952
|
-
if (exportOwnerBySymbol.has(symbol)) {
|
|
5953
|
-
throw new Error(
|
|
5954
|
-
`Assertion error. Symbol "${symbol}" exported multiple times while ordering chunks.`
|
|
5955
|
-
);
|
|
5956
|
-
}
|
|
5957
|
-
exportOwnerBySymbol.set(symbol, chunk);
|
|
5958
|
-
}
|
|
5959
|
-
});
|
|
5960
|
-
const dependentsByProvider = /* @__PURE__ */ new Map();
|
|
5961
|
-
const inDegreeByChunk = /* @__PURE__ */ new Map();
|
|
5962
|
-
for (const chunk of chunks) {
|
|
5963
|
-
dependentsByProvider.set(chunk, /* @__PURE__ */ new Set());
|
|
5964
|
-
inDegreeByChunk.set(chunk, 0);
|
|
5965
|
-
}
|
|
5966
|
-
for (const chunk of chunks) {
|
|
5967
|
-
const providers = /* @__PURE__ */ new Set();
|
|
5968
|
-
for (const ref of chunk.refs) {
|
|
5969
|
-
if (ref.kind !== "internal") continue;
|
|
5970
|
-
const provider = exportOwnerBySymbol.get(ref.name);
|
|
5971
|
-
if (!provider || provider === chunk) continue;
|
|
5972
|
-
providers.add(provider);
|
|
5973
|
-
}
|
|
5974
|
-
for (const provider of providers) {
|
|
5975
|
-
dependentsByProvider.get(provider).add(chunk);
|
|
5976
|
-
inDegreeByChunk.set(chunk, inDegreeByChunk.get(chunk) + 1);
|
|
5977
|
-
}
|
|
6747
|
+
class VNextOasClientGenerator {
|
|
6748
|
+
constructor(options, log) {
|
|
6749
|
+
this.options = options;
|
|
6750
|
+
this.log = log;
|
|
5978
6751
|
}
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
const
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
6752
|
+
async generate(cmd) {
|
|
6753
|
+
const { inputFile, outputDir, apiName } = cmd;
|
|
6754
|
+
this.log(`Will generate API client name=${apiName} to ${outputDir}`);
|
|
6755
|
+
const sourceSchema = await loadSourceSchema(inputFile);
|
|
6756
|
+
const normalizedSchema = this.normalizeSchema(sourceSchema, inputFile);
|
|
6757
|
+
const openApiIr = this.filterOperations(normalizedSchema);
|
|
6758
|
+
const projectResult = new OperationProjector({
|
|
6759
|
+
includeAllSchema: this.options.selection?.allSchemas === true,
|
|
6760
|
+
typeExtraction: {
|
|
6761
|
+
comments: this.options.codegen.comments.schema,
|
|
6762
|
+
enumStyle: this.options.codegen.enumStyle,
|
|
6763
|
+
uppercaseEnumKeys: this.options.compat?.uppercaseEnumKeys,
|
|
6764
|
+
swaggerTsApiRequiredBooleans: this.options.compat?.swaggerTsApiRequiredBooleans
|
|
5989
6765
|
}
|
|
5990
|
-
}
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
`Cannot order chunks with cyclic internal dependencies: ${cycleChunkNames}`
|
|
6766
|
+
}).project(openApiIr);
|
|
6767
|
+
const clientName = toPascalCaseIdentifier(apiName);
|
|
6768
|
+
const chunks = generateTsCode(
|
|
6769
|
+
clientName,
|
|
6770
|
+
projectResult,
|
|
6771
|
+
this.options.codegen
|
|
5997
6772
|
);
|
|
6773
|
+
const codeFormatter = new CodeFormatter({
|
|
6774
|
+
resolveConfFrom: outputDir
|
|
6775
|
+
});
|
|
6776
|
+
const writer = new CodeWriter(codeFormatter);
|
|
6777
|
+
await writer.write(outputDir, chunks.all);
|
|
6778
|
+
const tsFilePath = (name) => Path.join(outputDir, `${name}.ts`);
|
|
6779
|
+
return {
|
|
6780
|
+
promiseWrapper: chunks.promiseWrappersNames.map(tsFilePath),
|
|
6781
|
+
types: tsFilePath(chunks.typesName)
|
|
6782
|
+
};
|
|
5998
6783
|
}
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
const generateFromIr = async ({
|
|
6003
|
-
openApiIr,
|
|
6004
|
-
clientName,
|
|
6005
|
-
outputDir,
|
|
6006
|
-
outputFilename,
|
|
6007
|
-
codeFormattingConfigDir,
|
|
6008
|
-
quirks,
|
|
6009
|
-
requestParams: withRequestParams
|
|
6010
|
-
}) => {
|
|
6011
|
-
const tsCodegenFac = new TsCodegenFactory();
|
|
6012
|
-
const projectResult = new OperationProjector({
|
|
6013
|
-
quirks
|
|
6014
|
-
}).project(openApiIr);
|
|
6015
|
-
const { schemaDefinitions } = projectResult;
|
|
6016
|
-
const requestParams = withRequestParams;
|
|
6017
|
-
const types = schemaDefinitions.map((def) => {
|
|
6018
|
-
const cg = tsCodegenFac.forNewChunk();
|
|
6019
|
-
const typeName = def.name;
|
|
6020
|
-
const code = `export type ${typeName} = ${cg.toCode(def.typeExpr)}`;
|
|
6021
|
-
return cg.toChunk(typeName, code, [typeName]);
|
|
6022
|
-
});
|
|
6023
|
-
const clientCodegen = new ApiClientCodegen(
|
|
6024
|
-
{
|
|
6025
|
-
httpClient: promiseHttpClientCodegenSpec(),
|
|
6026
|
-
requestParams,
|
|
6027
|
-
// TODO make configurable
|
|
6028
|
-
pathParamsStyle: "positional"
|
|
6029
|
-
},
|
|
6030
|
-
tsCodegenFac
|
|
6031
|
-
);
|
|
6032
|
-
const generated = clientCodegen.generate(
|
|
6033
|
-
clientName,
|
|
6034
|
-
groupsOpsByTag(projectResult.operations)
|
|
6035
|
-
);
|
|
6036
|
-
const httpClientChunk = tsCodegenFac.forNewChunk().toChunk(
|
|
6037
|
-
"HttpClient",
|
|
6038
|
-
getHttpClientCode(),
|
|
6039
|
-
["HttpRequest", "HttpResponse", "HttpClient"]
|
|
6040
|
-
);
|
|
6041
|
-
const codeFormatter = new CodeFormatter({
|
|
6042
|
-
resolveConfFrom: codeFormattingConfigDir
|
|
6043
|
-
});
|
|
6044
|
-
const writer = new CodeWriter(codeFormatter);
|
|
6045
|
-
let chunks = [...types, httpClientChunk, generated];
|
|
6046
|
-
chunks = [mergeChunks(outputFilename, chunks)];
|
|
6047
|
-
await writer.write(outputDir, chunks);
|
|
6048
|
-
};
|
|
6049
|
-
const groupsOpsByTag = (operations) => {
|
|
6050
|
-
const groupedOps = {};
|
|
6051
|
-
operations.forEach((operation) => {
|
|
6052
|
-
const groupName = operation.tags[0]?.trim() || "root";
|
|
6053
|
-
const bucket = groupedOps[groupName] ?? [];
|
|
6054
|
-
bucket.push(operation.op);
|
|
6055
|
-
groupedOps[groupName] = bucket;
|
|
6056
|
-
});
|
|
6057
|
-
return groupedOps;
|
|
6058
|
-
};
|
|
6059
|
-
const commonTypesCode = httpClientCommonTypesSource;
|
|
6060
|
-
const promiseHttpClientCode = httpClientPromiseTypesSource;
|
|
6061
|
-
const stripImports = (code) => code.replace(/^import[\s\S]*?from\s+['"][^'"]+['"]\s*;?\n?/gm, "").trim();
|
|
6062
|
-
const getHttpClientCode = (opts) => [
|
|
6063
|
-
commonTypesCode,
|
|
6064
|
-
promiseHttpClientCode
|
|
6065
|
-
].map(stripImports).join("\n\n");
|
|
6066
|
-
|
|
6067
|
-
const generateOpenApiClient$1 = async ({ input, name, outputDir, quirks, ignoreOperationsWithTags }, log) => {
|
|
6068
|
-
log(`Will generate API client name=${name} to ${outputDir}`);
|
|
6069
|
-
const sourceSchema = await loadSourceSchema(input);
|
|
6070
|
-
const { result, problems } = new OpenApiNormalizer(sourceSchema).load();
|
|
6071
|
-
problems.forEach((problem) => {
|
|
6072
|
-
log(`[open-api:${problem.level}] ${problem.path}: ${problem.message}`);
|
|
6073
|
-
});
|
|
6074
|
-
const errors = problems.filter((problem) => problem.level === "error");
|
|
6075
|
-
if (errors.length) {
|
|
6076
|
-
throw new Error(
|
|
6077
|
-
`Failed to load OpenAPI IR from ${input}: ${errors.length} error(s).`
|
|
6784
|
+
filterOperations(openApiIr) {
|
|
6785
|
+
const ignoreTags = new Set(
|
|
6786
|
+
this.options.selection?.ignoreOperationsWithTags || []
|
|
6078
6787
|
);
|
|
6788
|
+
return {
|
|
6789
|
+
...openApiIr,
|
|
6790
|
+
operations: openApiIr.operations.filter((operation) => {
|
|
6791
|
+
const hasUsableTags = operation.tags.some((tag) => tag.trim());
|
|
6792
|
+
if (!hasUsableTags) {
|
|
6793
|
+
this.log(
|
|
6794
|
+
`[open-api:warning] Ignoring operation ${operation.method.toUpperCase()} ${operation.path} (${operation.operationId ?? "<missing operationId>"}): no tags`
|
|
6795
|
+
);
|
|
6796
|
+
return false;
|
|
6797
|
+
}
|
|
6798
|
+
return !operation.tags.some((tag) => ignoreTags.has(tag));
|
|
6799
|
+
})
|
|
6800
|
+
};
|
|
6079
6801
|
}
|
|
6080
|
-
|
|
6081
|
-
|
|
6082
|
-
|
|
6083
|
-
|
|
6084
|
-
|
|
6085
|
-
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
}
|
|
6802
|
+
normalizeSchema(rawSchema, inputFile) {
|
|
6803
|
+
const { result, problems } = new OpenApiNormalizer(rawSchema).load();
|
|
6804
|
+
problems.forEach((problem) => {
|
|
6805
|
+
this.log(
|
|
6806
|
+
`[open-api:${problem.level}] ${problem.path}: ${problem.message}`
|
|
6807
|
+
);
|
|
6808
|
+
});
|
|
6809
|
+
const errors = problems.filter((problem) => problem.level === "error");
|
|
6810
|
+
if (errors.length) {
|
|
6811
|
+
throw new Error(
|
|
6812
|
+
`Failed to load OpenAPI IR from ${inputFile}: ${errors.length} error(s).`
|
|
6813
|
+
);
|
|
6814
|
+
}
|
|
6815
|
+
return result;
|
|
6816
|
+
}
|
|
6817
|
+
}
|
|
6093
6818
|
const loadSourceSchema = async (input) => {
|
|
6094
6819
|
let rawContent;
|
|
6095
6820
|
try {
|
|
@@ -6112,109 +6837,60 @@ const loadSourceSchema = async (input) => {
|
|
|
6112
6837
|
}
|
|
6113
6838
|
return parsed;
|
|
6114
6839
|
};
|
|
6115
|
-
const filterOperations = (openApiIr, log, ignoreOperationsWithTags) => {
|
|
6116
|
-
const ignoreTags = new Set(ignoreOperationsWithTags);
|
|
6117
|
-
return {
|
|
6118
|
-
...openApiIr,
|
|
6119
|
-
operations: openApiIr.operations.filter((operation) => {
|
|
6120
|
-
const hasUsableTags = operation.tags.some((tag) => tag.trim());
|
|
6121
|
-
if (!hasUsableTags) {
|
|
6122
|
-
log(
|
|
6123
|
-
`[open-api:warning] Ignoring operation ${operation.method.toUpperCase()} ${operation.path} (${operation.operationId ?? "<missing operationId>"}): no tags`
|
|
6124
|
-
);
|
|
6125
|
-
return false;
|
|
6126
|
-
}
|
|
6127
|
-
return !operation.tags.some((tag) => ignoreTags.has(tag));
|
|
6128
|
-
})
|
|
6129
|
-
};
|
|
6130
|
-
};
|
|
6131
6840
|
const toErrorMessage = (error) => {
|
|
6132
6841
|
return error instanceof Error ? error.message : String(error);
|
|
6133
6842
|
};
|
|
6134
6843
|
|
|
6135
|
-
const
|
|
6136
|
-
|
|
6137
|
-
const
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
|
|
6143
|
-
|
|
6144
|
-
|
|
6145
|
-
|
|
6146
|
-
|
|
6147
|
-
|
|
6148
|
-
|
|
6149
|
-
|
|
6150
|
-
|
|
6151
|
-
|
|
6152
|
-
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
|
|
6158
|
-
|
|
6159
|
-
|
|
6160
|
-
|
|
6161
|
-
|
|
6162
|
-
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
(t) => ignoreTags.has(t)
|
|
6167
|
-
);
|
|
6168
|
-
if (ignore) return false;
|
|
6169
|
-
}
|
|
6170
|
-
return routeData;
|
|
6171
|
-
}
|
|
6172
|
-
},
|
|
6173
|
-
// @ts-ignore
|
|
6174
|
-
codeGenConstructs: () => ({
|
|
6175
|
-
Keyword: {}
|
|
6176
|
-
})
|
|
6177
|
-
// extractRequestParams: true,
|
|
6178
|
-
});
|
|
6179
|
-
return dstFile;
|
|
6180
|
-
};
|
|
6181
|
-
const getThisScriptDirname = () => {
|
|
6182
|
-
return Path$1.dirname(node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('generateApiClient.cjs', document.baseURI).href))));
|
|
6183
|
-
};
|
|
6184
|
-
const getTemplatesDir = () => {
|
|
6185
|
-
const currentDir = getThisScriptDirname();
|
|
6186
|
-
const templatesRelativePath = Path$1.basename(currentDir) === "dist" ? "../templates" : "../../../templates";
|
|
6187
|
-
return Path$1.resolve(currentDir, templatesRelativePath);
|
|
6188
|
-
};
|
|
6189
|
-
|
|
6190
|
-
const SUPPORTED_GENERATORS = [
|
|
6191
|
-
"swagger-ts-api",
|
|
6192
|
-
"api-client-generator"
|
|
6193
|
-
];
|
|
6194
|
-
const OPEN_API_MODEL_GENERATORS = {
|
|
6195
|
-
"swagger-ts-api": generateOpenApiClient,
|
|
6196
|
-
"api-client-generator": generateOpenApiClient$1
|
|
6197
|
-
};
|
|
6198
|
-
const generateOpenApiModel = async (generator, cmd, log) => {
|
|
6199
|
-
const generatorFun = OPEN_API_MODEL_GENERATORS[generator];
|
|
6200
|
-
const outputPath = await generatorFun(cmd, log);
|
|
6201
|
-
const outputModifiers = getOutputModifiers(cmd, log);
|
|
6202
|
-
log(`Will modify the outputs ${JSON.stringify(outputModifiers)}`);
|
|
6203
|
-
await modifyOutput(outputPath, outputModifiers);
|
|
6204
|
-
return outputPath;
|
|
6844
|
+
const generateOpenApiModel = async (spectPath, config, log) => {
|
|
6845
|
+
let outFiles;
|
|
6846
|
+
const { openApiGenerator, responseWrapper } = config;
|
|
6847
|
+
if ("legacy" in openApiGenerator) {
|
|
6848
|
+
outFiles = await generateOpenApiClient(
|
|
6849
|
+
spectPath,
|
|
6850
|
+
{
|
|
6851
|
+
ignoreOperationsWithTags: openApiGenerator.legacy.ignoreOperationsWithTags,
|
|
6852
|
+
name: config.apiName,
|
|
6853
|
+
outputDir: config.dstDir
|
|
6854
|
+
},
|
|
6855
|
+
log
|
|
6856
|
+
);
|
|
6857
|
+
} else {
|
|
6858
|
+
outFiles = await new VNextOasClientGenerator(
|
|
6859
|
+
openApiGenerator,
|
|
6860
|
+
log
|
|
6861
|
+
).generate({
|
|
6862
|
+
inputFile: spectPath,
|
|
6863
|
+
apiName: config.apiName,
|
|
6864
|
+
outputDir: config.dstDir
|
|
6865
|
+
});
|
|
6866
|
+
}
|
|
6867
|
+
if (responseWrapper) {
|
|
6868
|
+
await modifyHttpClientAsyncWrapper(
|
|
6869
|
+
outFiles.promiseWrapper,
|
|
6870
|
+
responseWrapper,
|
|
6871
|
+
log
|
|
6872
|
+
);
|
|
6873
|
+
}
|
|
6874
|
+
return { typesFilePath: outFiles.types };
|
|
6205
6875
|
};
|
|
6206
|
-
const
|
|
6876
|
+
const modifyHttpClientAsyncWrapper = async (filePaths, responseWrapper, log) => {
|
|
6877
|
+
log(
|
|
6878
|
+
`Will use response wrapper '${JSON.stringify(responseWrapper)}' on file ${filePaths.join(", ")}`
|
|
6879
|
+
);
|
|
6207
6880
|
const addImports = [];
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6881
|
+
if (responseWrapper.import) {
|
|
6882
|
+
addImports.push(responseWrapper.import);
|
|
6883
|
+
}
|
|
6884
|
+
const replaces = [["Promise", responseWrapper.symbol]];
|
|
6885
|
+
if (responseWrapper.unwrapExpr) {
|
|
6886
|
+
replaces.push([".then(res => res.body)", responseWrapper.unwrapExpr]);
|
|
6887
|
+
}
|
|
6888
|
+
for (const filePath of filePaths) {
|
|
6889
|
+
await modifyOutput(filePath, {
|
|
6890
|
+
addImports,
|
|
6891
|
+
replaces
|
|
6892
|
+
});
|
|
6213
6893
|
}
|
|
6214
|
-
return {
|
|
6215
|
-
addImports,
|
|
6216
|
-
replaces
|
|
6217
|
-
};
|
|
6218
6894
|
};
|
|
6219
6895
|
const modifyOutput = async (path, cmd) => {
|
|
6220
6896
|
let content = await fs.readFile(path).then((r) => r.toString());
|
|
@@ -6280,9 +6956,7 @@ const generateSchemas = async (inputFile, outputFile, opts = {}) => {
|
|
|
6280
6956
|
const { getZodSchemasFile } = tsToZod.generate({
|
|
6281
6957
|
sourceText: removeGenericTypes(code)
|
|
6282
6958
|
});
|
|
6283
|
-
|
|
6284
|
-
let f = getZodSchemasFile(`./${fileName.replace(".ts", "")}`);
|
|
6285
|
-
f = f.replaceAll('"./index";', '"./client"');
|
|
6959
|
+
let f = getZodSchemasFile(getModuleImportPath(inputFile, outputFile));
|
|
6286
6960
|
f = f.replaceAll(".optional()", ".nullable()");
|
|
6287
6961
|
if (opts.localDateTimes) {
|
|
6288
6962
|
f = f.replaceAll(
|
|
@@ -6298,50 +6972,28 @@ const generateSchemas = async (inputFile, outputFile, opts = {}) => {
|
|
|
6298
6972
|
});
|
|
6299
6973
|
fs$2.writeFileSync(outputFile, formatted);
|
|
6300
6974
|
};
|
|
6975
|
+
const getModuleImportPath = (inputFile, outputFile) => {
|
|
6976
|
+
const sourceDir = Path.dirname(outputFile);
|
|
6977
|
+
const relativePath = Path.relative(sourceDir, inputFile);
|
|
6978
|
+
const withoutExtension = relativePath.replace(/\.ts$/u, "");
|
|
6979
|
+
const normalizedPath = withoutExtension.split(Path.sep).join("/");
|
|
6980
|
+
return normalizedPath.startsWith(".") ? normalizedPath : `./${normalizedPath}`;
|
|
6981
|
+
};
|
|
6301
6982
|
|
|
6302
|
-
const
|
|
6303
|
-
const
|
|
6304
|
-
|
|
6305
|
-
dstDir: string().trim().min(1),
|
|
6306
|
-
apiName: string().trim().min(1),
|
|
6307
|
-
generator: _enum(SUPPORTED_GENERATORS).default(DEFAULT_GENERATOR),
|
|
6308
|
-
quirks: strictObject({
|
|
6309
|
-
swaggerTsApiRequiredBooleans: boolean().optional()
|
|
6310
|
-
}).optional(),
|
|
6311
|
-
responseWrapper: strictObject({
|
|
6312
|
-
symbol: string().trim().min(1),
|
|
6313
|
-
import: string().trim().min(1).optional()
|
|
6314
|
-
}).optional(),
|
|
6315
|
-
ignoreOperationsWithTags: array(string()).optional(),
|
|
6316
|
-
zodSchemas: strictObject({
|
|
6317
|
-
enabled: boolean().optional(),
|
|
6318
|
-
localDateTimes: boolean().optional()
|
|
6319
|
-
}).optional()
|
|
6320
|
-
});
|
|
6321
|
-
const parseGenerateApiClientParams = (params) => {
|
|
6322
|
-
const parsed = generateApiClientParamsSchema.safeParse(params);
|
|
6323
|
-
if (parsed.success) return parsed.data;
|
|
6324
|
-
throw new Error(prettifyError(parsed.error));
|
|
6983
|
+
const generateApiClient = async (params, configFilePath, log = console.log) => {
|
|
6984
|
+
const config = parseProfileConfig(params, configFilePath);
|
|
6985
|
+
return generateApiClientFromConfig(config, log);
|
|
6325
6986
|
};
|
|
6326
|
-
const
|
|
6327
|
-
const {
|
|
6328
|
-
|
|
6329
|
-
apiName,
|
|
6330
|
-
srcSpec,
|
|
6331
|
-
quirks,
|
|
6332
|
-
responseWrapper,
|
|
6333
|
-
ignoreOperationsWithTags,
|
|
6334
|
-
zodSchemas,
|
|
6335
|
-
generator
|
|
6336
|
-
} = parseGenerateApiClientParams(params);
|
|
6337
|
-
const dir = Path$1.resolve(dstDir, apiName);
|
|
6987
|
+
const generateApiClientFromConfig = async (config, log = console.log) => {
|
|
6988
|
+
const { dstDir, apiName, srcSpec, zodSchemas } = config;
|
|
6989
|
+
const dir = Path.resolve(dstDir, apiName);
|
|
6338
6990
|
if (!fs__namespace.existsSync(dir)) {
|
|
6339
6991
|
log(`Creating dir ${dir}`);
|
|
6340
6992
|
fs__namespace.mkdirSync(dir, {
|
|
6341
6993
|
recursive: true
|
|
6342
6994
|
});
|
|
6343
6995
|
}
|
|
6344
|
-
const clientDir = Path
|
|
6996
|
+
const clientDir = Path.resolve(dir, "client");
|
|
6345
6997
|
const specPath = await getSpecPath(srcSpec, dir, log);
|
|
6346
6998
|
log(`Cleaning client output dir ${clientDir}`);
|
|
6347
6999
|
fs__namespace.rmSync(clientDir, {
|
|
@@ -6351,23 +7003,19 @@ const generateApiClient = async (params, log = console.log) => {
|
|
|
6351
7003
|
fs__namespace.mkdirSync(clientDir, {
|
|
6352
7004
|
recursive: true
|
|
6353
7005
|
});
|
|
6354
|
-
const
|
|
6355
|
-
|
|
7006
|
+
const { typesFilePath } = await generateOpenApiModel(
|
|
7007
|
+
specPath,
|
|
6356
7008
|
{
|
|
6357
|
-
|
|
6358
|
-
|
|
6359
|
-
outputDir: clientDir,
|
|
6360
|
-
quirks,
|
|
6361
|
-
ignoreOperationsWithTags,
|
|
6362
|
-
responseWrapper
|
|
7009
|
+
...config,
|
|
7010
|
+
dstDir: clientDir
|
|
6363
7011
|
},
|
|
6364
7012
|
log
|
|
6365
7013
|
);
|
|
6366
7014
|
if (zodSchemas?.enabled === false) return;
|
|
6367
7015
|
log("Generating Zod schemas");
|
|
6368
7016
|
await generateSchemas(
|
|
6369
|
-
|
|
6370
|
-
Path
|
|
7017
|
+
typesFilePath,
|
|
7018
|
+
Path.resolve(dir, "./zod.ts"),
|
|
6371
7019
|
zodSchemas
|
|
6372
7020
|
);
|
|
6373
7021
|
};
|
|
@@ -6377,10 +7025,13 @@ const getSpecPath = async (urlOrPath, dir, log) => {
|
|
|
6377
7025
|
throw new Error(`Spec file ${urlOrPath} does not exists`);
|
|
6378
7026
|
return urlOrPath;
|
|
6379
7027
|
}
|
|
6380
|
-
const specPath = Path
|
|
7028
|
+
const specPath = Path.resolve(dir, `spec.json`);
|
|
6381
7029
|
log(`Will download the API spec from ${urlOrPath} to ${specPath}`);
|
|
6382
7030
|
await downloadSpec(specPath, urlOrPath);
|
|
6383
7031
|
return specPath;
|
|
6384
7032
|
};
|
|
6385
7033
|
|
|
7034
|
+
exports.defineConfig = defineConfig;
|
|
6386
7035
|
exports.generateApiClient = generateApiClient;
|
|
7036
|
+
exports.generateApiClientFromConfig = generateApiClientFromConfig;
|
|
7037
|
+
exports.parseConfig = parseConfig;
|