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