@hey-api/openapi-ts 0.90.0 → 0.90.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{config-DT26kmcq.d.cts → config-84ipCnU3.d.cts} +7854 -8947
- package/dist/{config-Dis5Gu6e.d.mts → config-BzR0jtGH.d.mts} +8436 -9528
- package/dist/index.cjs +23 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +4 -1
- package/dist/internal.cjs +5 -1
- package/dist/internal.d.cts +1 -1
- package/dist/internal.d.mts +1 -1
- package/dist/internal.mjs +3 -1
- package/dist/openApi-BwUPqtP_.cjs +21678 -0
- package/dist/openApi-BwUPqtP_.cjs.map +1 -0
- package/dist/openApi-PX3rDrOF.mjs +21448 -0
- package/dist/openApi-PX3rDrOF.mjs.map +1 -0
- package/dist/run.cjs +65 -1
- package/dist/run.cjs.map +1 -1
- package/dist/run.mjs +66 -1
- package/dist/run.mjs.map +1 -1
- package/dist/src-BCi83sdM.mjs +589 -0
- package/dist/src-BCi83sdM.mjs.map +1 -0
- package/dist/src-hU76ergi.cjs +616 -0
- package/dist/src-hU76ergi.cjs.map +1 -0
- package/package.json +2 -2
- package/dist/openApi-BU6F2oHy.mjs +0 -14
- package/dist/openApi-BU6F2oHy.mjs.map +0 -1
- package/dist/openApi-CcUF29dR.cjs +0 -14
- package/dist/openApi-CcUF29dR.cjs.map +0 -1
- package/dist/src-CHy94xdb.cjs +0 -20
- package/dist/src-CHy94xdb.cjs.map +0 -1
- package/dist/src-DnaJOx9H.mjs +0 -12
- package/dist/src-DnaJOx9H.mjs.map +0 -1
|
@@ -0,0 +1,589 @@
|
|
|
1
|
+
|
|
2
|
+
import { A as openGitHubIssueWithCrashReport, D as ConfigValidationError, E as ConfigError, M as shouldReportCrash, N as loadPackageJson, O as JobError, T as getLogs, i as initConfigs, j as printCrashReport, k as logCrashReport, n as buildGraph, r as getSpec, s as generateClientBundle, t as parseOpenApiSpec, u as toCase, w as postprocessOutput, y as getClientPlugin } from "./openApi-PX3rDrOF.mjs";
|
|
3
|
+
import "@hey-api/codegen-core";
|
|
4
|
+
import colors from "ansi-colors";
|
|
5
|
+
import colorSupport from "color-support";
|
|
6
|
+
import fs from "node:fs";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import { $RefParser } from "@hey-api/json-schema-ref-parser";
|
|
9
|
+
|
|
10
|
+
//#region src/config/engine.ts
|
|
11
|
+
const checkNodeVersion = () => {
|
|
12
|
+
if (typeof Bun !== "undefined") {
|
|
13
|
+
const [major] = Bun.version.split(".").map(Number);
|
|
14
|
+
if (major < 1) throw new ConfigError(`Unsupported Bun version ${Bun.version}. Please use Bun 1.0.0 or newer.`);
|
|
15
|
+
} else if (typeof process !== "undefined" && process.versions?.node) {
|
|
16
|
+
const [major] = process.versions.node.split(".").map(Number);
|
|
17
|
+
if (major < 20) throw new ConfigError(`Unsupported Node version ${process.versions.node}. Please use Node 20 or newer.`);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
//#region src/ir/intents.ts
|
|
23
|
+
var IntentContext = class {
|
|
24
|
+
spec;
|
|
25
|
+
constructor(spec) {
|
|
26
|
+
this.spec = spec;
|
|
27
|
+
}
|
|
28
|
+
getOperation(path$1, method) {
|
|
29
|
+
const paths = this.spec.paths;
|
|
30
|
+
if (!paths) return;
|
|
31
|
+
return paths[path$1]?.[method];
|
|
32
|
+
}
|
|
33
|
+
setExample(operation, example) {
|
|
34
|
+
const source = this.getOperation(operation.path, operation.method);
|
|
35
|
+
if (!source) return;
|
|
36
|
+
source["x-codeSamples"] ||= [];
|
|
37
|
+
source["x-codeSamples"].push(example);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/generate/output.ts
|
|
43
|
+
const generateOutput = async ({ context }) => {
|
|
44
|
+
const outputPath = path.resolve(context.config.output.path);
|
|
45
|
+
if (context.config.output.clean) {
|
|
46
|
+
if (fs.existsSync(outputPath)) fs.rmSync(outputPath, {
|
|
47
|
+
force: true,
|
|
48
|
+
recursive: true
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
const client = getClientPlugin(context.config);
|
|
52
|
+
if ("bundle" in client.config && client.config.bundle && !context.config.dryRun) context.config._FRAGILE_CLIENT_BUNDLE_RENAMED = generateClientBundle({
|
|
53
|
+
meta: { importFileExtension: context.config.output.importFileExtension },
|
|
54
|
+
outputPath,
|
|
55
|
+
plugin: client,
|
|
56
|
+
project: context.gen
|
|
57
|
+
});
|
|
58
|
+
for (const plugin of context.registerPlugins()) await plugin.run();
|
|
59
|
+
context.gen.plan();
|
|
60
|
+
const ctx = new IntentContext(context.spec);
|
|
61
|
+
for (const intent of context.intents) await intent.run(ctx);
|
|
62
|
+
for (const file of context.gen.render()) {
|
|
63
|
+
const filePath = path.resolve(outputPath, file.path);
|
|
64
|
+
const dir = path.dirname(filePath);
|
|
65
|
+
if (!context.config.dryRun) {
|
|
66
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
67
|
+
fs.writeFileSync(filePath, file.content, { encoding: "utf8" });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const { source } = context.config.output;
|
|
71
|
+
if (source.enabled) {
|
|
72
|
+
const sourcePath = source.path === null ? void 0 : path.resolve(outputPath, source.path);
|
|
73
|
+
if (!context.config.dryRun && sourcePath && sourcePath !== outputPath) fs.mkdirSync(sourcePath, { recursive: true });
|
|
74
|
+
const serialized = await source.serialize(context.spec);
|
|
75
|
+
if (!context.config.dryRun && sourcePath) fs.writeFileSync(path.resolve(sourcePath, `${source.fileName}.${source.extension}`), serialized, { encoding: "utf8" });
|
|
76
|
+
if (source.callback) await source.callback(serialized);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
//#endregion
|
|
81
|
+
//#region src/openApi/shared/utils/patch.ts
|
|
82
|
+
const patchOpenApiSpec = ({ patchOptions, spec: _spec }) => {
|
|
83
|
+
if (!patchOptions) return;
|
|
84
|
+
const spec = _spec;
|
|
85
|
+
if ("swagger" in spec) {
|
|
86
|
+
if (patchOptions.version && spec.swagger) spec.swagger = typeof patchOptions.version === "string" ? patchOptions.version : patchOptions.version(spec.swagger);
|
|
87
|
+
if (patchOptions.meta && spec.info) patchOptions.meta(spec.info);
|
|
88
|
+
if (patchOptions.schemas && spec.definitions) for (const key in patchOptions.schemas) {
|
|
89
|
+
const schema = spec.definitions[key];
|
|
90
|
+
if (!schema || typeof schema !== "object") continue;
|
|
91
|
+
const patchFn = patchOptions.schemas[key];
|
|
92
|
+
patchFn(schema);
|
|
93
|
+
}
|
|
94
|
+
if (patchOptions.operations && spec.paths) for (const key in patchOptions.operations) {
|
|
95
|
+
const [method, path$1] = key.split(" ");
|
|
96
|
+
if (!method || !path$1) continue;
|
|
97
|
+
const pathItem = spec.paths[path$1];
|
|
98
|
+
if (!pathItem) continue;
|
|
99
|
+
const operation = pathItem[method.toLocaleLowerCase()] || pathItem[method.toLocaleUpperCase()];
|
|
100
|
+
if (!operation || typeof operation !== "object") continue;
|
|
101
|
+
const patchFn = patchOptions.operations[key];
|
|
102
|
+
patchFn(operation);
|
|
103
|
+
}
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (patchOptions.version && spec.openapi) spec.openapi = typeof patchOptions.version === "string" ? patchOptions.version : patchOptions.version(spec.openapi);
|
|
107
|
+
if (patchOptions.meta && spec.info) patchOptions.meta(spec.info);
|
|
108
|
+
if (spec.components) {
|
|
109
|
+
if (patchOptions.schemas && spec.components.schemas) for (const key in patchOptions.schemas) {
|
|
110
|
+
const schema = spec.components.schemas[key];
|
|
111
|
+
if (!schema || typeof schema !== "object") continue;
|
|
112
|
+
const patchFn = patchOptions.schemas[key];
|
|
113
|
+
patchFn(schema);
|
|
114
|
+
}
|
|
115
|
+
if (patchOptions.parameters && spec.components.parameters) for (const key in patchOptions.parameters) {
|
|
116
|
+
const schema = spec.components.parameters[key];
|
|
117
|
+
if (!schema || typeof schema !== "object") continue;
|
|
118
|
+
const patchFn = patchOptions.parameters[key];
|
|
119
|
+
patchFn(schema);
|
|
120
|
+
}
|
|
121
|
+
if (patchOptions.requestBodies && spec.components.requestBodies) for (const key in patchOptions.requestBodies) {
|
|
122
|
+
const schema = spec.components.requestBodies[key];
|
|
123
|
+
if (!schema || typeof schema !== "object") continue;
|
|
124
|
+
const patchFn = patchOptions.requestBodies[key];
|
|
125
|
+
patchFn(schema);
|
|
126
|
+
}
|
|
127
|
+
if (patchOptions.responses && spec.components.responses) for (const key in patchOptions.responses) {
|
|
128
|
+
const schema = spec.components.responses[key];
|
|
129
|
+
if (!schema || typeof schema !== "object") continue;
|
|
130
|
+
const patchFn = patchOptions.responses[key];
|
|
131
|
+
patchFn(schema);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (patchOptions.operations && spec.paths) for (const key in patchOptions.operations) {
|
|
135
|
+
const [method, path$1] = key.split(" ");
|
|
136
|
+
if (!method || !path$1) continue;
|
|
137
|
+
const pathItem = spec.paths[path$1];
|
|
138
|
+
if (!pathItem) continue;
|
|
139
|
+
const operation = pathItem[method.toLocaleLowerCase()] || pathItem[method.toLocaleUpperCase()];
|
|
140
|
+
if (!operation || typeof operation !== "object") continue;
|
|
141
|
+
const patchFn = patchOptions.operations[key];
|
|
142
|
+
patchFn(operation);
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
//#endregion
|
|
147
|
+
//#region src/createClient.ts
|
|
148
|
+
const compileInputPath = (input) => {
|
|
149
|
+
const result = {
|
|
150
|
+
...input,
|
|
151
|
+
path: ""
|
|
152
|
+
};
|
|
153
|
+
if (input.path && (typeof input.path !== "string" || input.registry !== "hey-api")) {
|
|
154
|
+
result.path = input.path;
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
157
|
+
const [basePath, baseQuery] = input.path.split("?");
|
|
158
|
+
const queryPath = (baseQuery || "").split("&").map((part) => part.split("="));
|
|
159
|
+
let path$1 = basePath || "";
|
|
160
|
+
if (path$1.endsWith("/")) path$1 = path$1.slice(0, path$1.length - 1);
|
|
161
|
+
const [, pathUrl] = path$1.split("://");
|
|
162
|
+
const [baseUrl, organization, project] = (pathUrl || "").split("/");
|
|
163
|
+
result.organization = organization || input.organization;
|
|
164
|
+
result.project = project || input.project;
|
|
165
|
+
const queryParams = [];
|
|
166
|
+
const kApiKey = "api_key";
|
|
167
|
+
result.api_key = queryPath.find(([key]) => key === kApiKey)?.[1] || input.api_key || process.env.HEY_API_TOKEN;
|
|
168
|
+
if (result.api_key) queryParams.push(`${kApiKey}=${result.api_key}`);
|
|
169
|
+
const kBranch = "branch";
|
|
170
|
+
result.branch = queryPath.find(([key]) => key === kBranch)?.[1] || input.branch;
|
|
171
|
+
if (result.branch) queryParams.push(`${kBranch}=${result.branch}`);
|
|
172
|
+
const kCommitSha = "commit_sha";
|
|
173
|
+
result.commit_sha = queryPath.find(([key]) => key === kCommitSha)?.[1] || input.commit_sha;
|
|
174
|
+
if (result.commit_sha) queryParams.push(`${kCommitSha}=${result.commit_sha}`);
|
|
175
|
+
const kTags = "tags";
|
|
176
|
+
result.tags = queryPath.find(([key]) => key === kTags)?.[1]?.split(",") || input.tags;
|
|
177
|
+
if (result.tags?.length) queryParams.push(`${kTags}=${result.tags.join(",")}`);
|
|
178
|
+
const kVersion = "version";
|
|
179
|
+
result.version = queryPath.find(([key]) => key === kVersion)?.[1] || input.version;
|
|
180
|
+
if (result.version) queryParams.push(`${kVersion}=${result.version}`);
|
|
181
|
+
if (!result.organization) throw new Error("missing organization - from which Hey API Platform organization do you want to generate your output?");
|
|
182
|
+
if (!result.project) throw new Error("missing project - from which Hey API Platform project do you want to generate your output?");
|
|
183
|
+
const query = queryParams.join("&");
|
|
184
|
+
const platformUrl = baseUrl || "get.heyapi.dev";
|
|
185
|
+
const isLocalhost = platformUrl.startsWith("localhost");
|
|
186
|
+
const platformUrlWithProtocol = [isLocalhost ? "http" : "https", platformUrl].join("://");
|
|
187
|
+
const compiledPath = isLocalhost ? [
|
|
188
|
+
platformUrlWithProtocol,
|
|
189
|
+
"v1",
|
|
190
|
+
"get",
|
|
191
|
+
result.organization,
|
|
192
|
+
result.project
|
|
193
|
+
].join("/") : [
|
|
194
|
+
platformUrlWithProtocol,
|
|
195
|
+
result.organization,
|
|
196
|
+
result.project
|
|
197
|
+
].join("/");
|
|
198
|
+
result.path = query ? `${compiledPath}?${query}` : compiledPath;
|
|
199
|
+
return result;
|
|
200
|
+
};
|
|
201
|
+
const logInputPaths = (inputPaths, jobIndex) => {
|
|
202
|
+
const lines = [];
|
|
203
|
+
const jobPrefix = colors.gray(`[Job ${jobIndex + 1}] `);
|
|
204
|
+
const count = inputPaths.length;
|
|
205
|
+
const baseString = colors.cyan(`Generating from ${count} ${count === 1 ? "input" : "inputs"}:`);
|
|
206
|
+
lines.push(`${jobPrefix}⏳ ${baseString}`);
|
|
207
|
+
inputPaths.forEach((inputPath, index) => {
|
|
208
|
+
const itemPrefixStr = ` [${index + 1}] `;
|
|
209
|
+
const itemPrefix = colors.cyan(itemPrefixStr);
|
|
210
|
+
const detailIndent = " ".repeat(itemPrefixStr.length);
|
|
211
|
+
if (typeof inputPath.path !== "string") {
|
|
212
|
+
lines.push(`${jobPrefix}${itemPrefix}raw OpenAPI specification`);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
switch (inputPath.registry) {
|
|
216
|
+
case "hey-api": {
|
|
217
|
+
const baseInput = [inputPath.organization, inputPath.project].filter(Boolean).join("/");
|
|
218
|
+
lines.push(`${jobPrefix}${itemPrefix}${baseInput}`);
|
|
219
|
+
if (inputPath.branch) lines.push(`${jobPrefix}${detailIndent}${colors.gray("branch:")} ${colors.green(inputPath.branch)}`);
|
|
220
|
+
if (inputPath.commit_sha) lines.push(`${jobPrefix}${detailIndent}${colors.gray("commit:")} ${colors.green(inputPath.commit_sha)}`);
|
|
221
|
+
if (inputPath.tags?.length) lines.push(`${jobPrefix}${detailIndent}${colors.gray("tags:")} ${colors.green(inputPath.tags.join(", "))}`);
|
|
222
|
+
if (inputPath.version) lines.push(`${jobPrefix}${detailIndent}${colors.gray("version:")} ${colors.green(inputPath.version)}`);
|
|
223
|
+
lines.push(`${jobPrefix}${detailIndent}${colors.gray("registry:")} ${colors.green("Hey API")}`);
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
case "readme": {
|
|
227
|
+
const baseInput = [inputPath.organization, inputPath.project].filter(Boolean).join("/");
|
|
228
|
+
if (!baseInput) lines.push(`${jobPrefix}${itemPrefix}${inputPath.path}`);
|
|
229
|
+
else lines.push(`${jobPrefix}${itemPrefix}${baseInput}`);
|
|
230
|
+
if (inputPath.uuid) lines.push(`${jobPrefix}${detailIndent}${colors.gray("uuid:")} ${colors.green(inputPath.uuid)}`);
|
|
231
|
+
lines.push(`${jobPrefix}${detailIndent}${colors.gray("registry:")} ${colors.green("ReadMe")}`);
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
case "scalar": {
|
|
235
|
+
const baseInput = [inputPath.organization, inputPath.project].filter(Boolean).join("/");
|
|
236
|
+
lines.push(`${jobPrefix}${itemPrefix}${baseInput}`);
|
|
237
|
+
lines.push(`${jobPrefix}${detailIndent}${colors.gray("registry:")} ${colors.green("Scalar")}`);
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
default:
|
|
241
|
+
lines.push(`${jobPrefix}${itemPrefix}${inputPath.path}`);
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
for (const line of lines) console.log(line);
|
|
246
|
+
};
|
|
247
|
+
const createClient$1 = async ({ config, dependencies, jobIndex, logger, watches: _watches }) => {
|
|
248
|
+
const watches = _watches || Array.from({ length: config.input.length }, () => ({ headers: new Headers() }));
|
|
249
|
+
const inputPaths = config.input.map((input) => compileInputPath(input));
|
|
250
|
+
if (config.logs.level !== "silent" && !_watches) logInputPaths(inputPaths, jobIndex);
|
|
251
|
+
const getSpecData = async (input, index) => {
|
|
252
|
+
const eventSpec = logger.timeEvent("spec");
|
|
253
|
+
const { arrayBuffer, error, resolvedInput, response } = await getSpec({
|
|
254
|
+
fetchOptions: input.fetch,
|
|
255
|
+
inputPath: inputPaths[index].path,
|
|
256
|
+
timeout: input.watch.timeout,
|
|
257
|
+
watch: watches[index]
|
|
258
|
+
});
|
|
259
|
+
eventSpec.timeEnd();
|
|
260
|
+
if (error && !_watches) throw new Error(`Request failed with status ${response.status}: ${response.statusText}`);
|
|
261
|
+
return {
|
|
262
|
+
arrayBuffer,
|
|
263
|
+
resolvedInput
|
|
264
|
+
};
|
|
265
|
+
};
|
|
266
|
+
const specData = (await Promise.all(config.input.map((input, index) => getSpecData(input, index)))).filter((data) => data.arrayBuffer || data.resolvedInput);
|
|
267
|
+
let context;
|
|
268
|
+
if (specData.length) {
|
|
269
|
+
const refParser = new $RefParser();
|
|
270
|
+
const data = specData.length > 1 ? await refParser.bundleMany({
|
|
271
|
+
arrayBuffer: specData.map((data$1) => data$1.arrayBuffer),
|
|
272
|
+
pathOrUrlOrSchemas: [],
|
|
273
|
+
resolvedInputs: specData.map((data$1) => data$1.resolvedInput)
|
|
274
|
+
}) : await refParser.bundle({
|
|
275
|
+
arrayBuffer: specData[0].arrayBuffer,
|
|
276
|
+
pathOrUrlOrSchema: void 0,
|
|
277
|
+
resolvedInput: specData[0].resolvedInput
|
|
278
|
+
});
|
|
279
|
+
if (config.logs.level !== "silent" && _watches) {
|
|
280
|
+
console.clear();
|
|
281
|
+
logInputPaths(inputPaths, jobIndex);
|
|
282
|
+
}
|
|
283
|
+
const eventInputPatch = logger.timeEvent("input.patch");
|
|
284
|
+
patchOpenApiSpec({
|
|
285
|
+
patchOptions: config.parser.patch,
|
|
286
|
+
spec: data
|
|
287
|
+
});
|
|
288
|
+
eventInputPatch.timeEnd();
|
|
289
|
+
const eventParser = logger.timeEvent("parser");
|
|
290
|
+
context = parseOpenApiSpec({
|
|
291
|
+
config,
|
|
292
|
+
dependencies,
|
|
293
|
+
logger,
|
|
294
|
+
spec: data
|
|
295
|
+
});
|
|
296
|
+
context.graph = buildGraph(context.ir, logger).graph;
|
|
297
|
+
eventParser.timeEnd();
|
|
298
|
+
const eventGenerator = logger.timeEvent("generator");
|
|
299
|
+
await generateOutput({ context });
|
|
300
|
+
eventGenerator.timeEnd();
|
|
301
|
+
const eventPostprocess = logger.timeEvent("postprocess");
|
|
302
|
+
if (!config.dryRun) {
|
|
303
|
+
postprocessOutput(config.output);
|
|
304
|
+
if (config.logs.level !== "silent") {
|
|
305
|
+
const outputPath = process.env.INIT_CWD ? `./${path.relative(process.env.INIT_CWD, config.output.path)}` : config.output.path;
|
|
306
|
+
const jobPrefix = colors.gray(`[Job ${jobIndex + 1}] `);
|
|
307
|
+
console.log(`${jobPrefix}${colors.green("✅ Done!")} Your output is in ${colors.cyanBright(outputPath)}`);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
eventPostprocess.timeEnd();
|
|
311
|
+
}
|
|
312
|
+
const watchedInput = config.input.find((input, index) => input.watch.enabled && typeof inputPaths[index].path === "string");
|
|
313
|
+
if (watchedInput) setTimeout(() => {
|
|
314
|
+
createClient$1({
|
|
315
|
+
config,
|
|
316
|
+
dependencies,
|
|
317
|
+
jobIndex,
|
|
318
|
+
logger,
|
|
319
|
+
watches
|
|
320
|
+
});
|
|
321
|
+
}, watchedInput.watch.interval);
|
|
322
|
+
return context;
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
//#endregion
|
|
326
|
+
//#region src/utils/cli.ts
|
|
327
|
+
const textAscii = `
|
|
328
|
+
888 | e 888~-_ 888
|
|
329
|
+
888___| e88~~8e Y88b / d8b 888 \\ 888
|
|
330
|
+
888 | d888 88b Y888/ /Y88b 888 | 888
|
|
331
|
+
888 | 8888__888 Y8/ / Y88b 888 / 888
|
|
332
|
+
888 | Y888 , Y /____Y88b 888_-~ 888
|
|
333
|
+
888 | "88___/ / / Y88b 888 888
|
|
334
|
+
_/
|
|
335
|
+
`;
|
|
336
|
+
const asciiToLines = (ascii, options) => {
|
|
337
|
+
const lines = [];
|
|
338
|
+
const padding = Array.from({ length: options?.padding ?? 0 }).fill("");
|
|
339
|
+
lines.push(...padding);
|
|
340
|
+
let maxLineLength = 0;
|
|
341
|
+
let line = "";
|
|
342
|
+
for (const char of ascii) if (char === "\n") {
|
|
343
|
+
if (line) {
|
|
344
|
+
lines.push(line);
|
|
345
|
+
maxLineLength = Math.max(maxLineLength, line.length);
|
|
346
|
+
line = "";
|
|
347
|
+
}
|
|
348
|
+
} else line += char;
|
|
349
|
+
lines.push(...padding);
|
|
350
|
+
return {
|
|
351
|
+
lines,
|
|
352
|
+
maxLineLength
|
|
353
|
+
};
|
|
354
|
+
};
|
|
355
|
+
function printCliIntro() {
|
|
356
|
+
const packageJson = loadPackageJson();
|
|
357
|
+
const text = asciiToLines(textAscii, { padding: 1 });
|
|
358
|
+
for (const line of text.lines) console.log(colors.cyan(line));
|
|
359
|
+
console.log(colors.gray(`${packageJson.name} v${packageJson.version}`));
|
|
360
|
+
console.log("");
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
//#endregion
|
|
364
|
+
//#region src/utils/logger.ts
|
|
365
|
+
let loggerCounter = 0;
|
|
366
|
+
const nameToId = (name) => `${name}-${loggerCounter++}`;
|
|
367
|
+
const idEnd = (id) => `${id}-end`;
|
|
368
|
+
const idLength = (id) => `${id}-length`;
|
|
369
|
+
const idStart = (id) => `${id}-start`;
|
|
370
|
+
const getSeverity = (duration, percentage) => {
|
|
371
|
+
if (duration > 200) return {
|
|
372
|
+
color: colors.red,
|
|
373
|
+
type: "duration"
|
|
374
|
+
};
|
|
375
|
+
if (percentage > 30) return {
|
|
376
|
+
color: colors.red,
|
|
377
|
+
type: "percentage"
|
|
378
|
+
};
|
|
379
|
+
if (duration > 50) return {
|
|
380
|
+
color: colors.yellow,
|
|
381
|
+
type: "duration"
|
|
382
|
+
};
|
|
383
|
+
if (percentage > 10) return {
|
|
384
|
+
color: colors.yellow,
|
|
385
|
+
type: "percentage"
|
|
386
|
+
};
|
|
387
|
+
};
|
|
388
|
+
var Logger = class {
|
|
389
|
+
events = [];
|
|
390
|
+
end(result) {
|
|
391
|
+
let event;
|
|
392
|
+
let events = this.events;
|
|
393
|
+
for (const index of result.position) {
|
|
394
|
+
event = events[index];
|
|
395
|
+
if (event?.events) events = event.events;
|
|
396
|
+
}
|
|
397
|
+
if (event && !event.end) event.end = performance.mark(idEnd(event.id));
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Recursively end all unended events in the event tree.
|
|
401
|
+
* This ensures all events have end marks before measuring.
|
|
402
|
+
*/
|
|
403
|
+
endAllEvents(events) {
|
|
404
|
+
for (const event of events) {
|
|
405
|
+
if (!event.end) event.end = performance.mark(idEnd(event.id));
|
|
406
|
+
if (event.events.length > 0) this.endAllEvents(event.events);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
report(print = true) {
|
|
410
|
+
const firstEvent = this.events[0];
|
|
411
|
+
if (!firstEvent) return;
|
|
412
|
+
this.endAllEvents(this.events);
|
|
413
|
+
const lastEvent = this.events[this.events.length - 1];
|
|
414
|
+
const name = "root";
|
|
415
|
+
const id = nameToId(name);
|
|
416
|
+
try {
|
|
417
|
+
const measure = performance.measure(idLength(id), idStart(firstEvent.id), idEnd(lastEvent.id));
|
|
418
|
+
if (print) this.reportEvent({
|
|
419
|
+
end: lastEvent.end,
|
|
420
|
+
events: this.events,
|
|
421
|
+
id,
|
|
422
|
+
indent: 0,
|
|
423
|
+
measure,
|
|
424
|
+
name,
|
|
425
|
+
start: firstEvent.start
|
|
426
|
+
});
|
|
427
|
+
return measure;
|
|
428
|
+
} catch {
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
reportEvent({ indent, ...parent }) {
|
|
433
|
+
const color = !indent ? colors.cyan : colors.gray;
|
|
434
|
+
const lastIndex = parent.events.length - 1;
|
|
435
|
+
parent.events.forEach((event, index) => {
|
|
436
|
+
try {
|
|
437
|
+
const measure = performance.measure(idLength(event.id), idStart(event.id), idEnd(event.id));
|
|
438
|
+
const duration = Math.ceil(measure.duration * 100) / 100;
|
|
439
|
+
const percentage = Math.ceil(measure.duration / parent.measure.duration * 100 * 100) / 100;
|
|
440
|
+
const severity = indent ? getSeverity(duration, percentage) : void 0;
|
|
441
|
+
let durationLabel = `${duration.toFixed(2).padStart(8)}ms`;
|
|
442
|
+
if (severity?.type === "duration") durationLabel = severity.color(durationLabel);
|
|
443
|
+
const branch = index === lastIndex ? "└─ " : "├─ ";
|
|
444
|
+
const prefix = !indent ? "" : "│ ".repeat(indent - 1) + branch;
|
|
445
|
+
const maxLength = 38 - prefix.length;
|
|
446
|
+
const percentageBranch = !indent ? "" : "↳ ";
|
|
447
|
+
let percentageLabel = `${indent ? " ".repeat(indent - 1) + percentageBranch : ""}${percentage.toFixed(2)}%`;
|
|
448
|
+
if (severity?.type === "percentage") percentageLabel = severity.color(percentageLabel);
|
|
449
|
+
const jobPrefix = colors.gray("[root] ");
|
|
450
|
+
console.log(`${jobPrefix}${colors.gray(prefix)}${color(`${event.name.padEnd(maxLength)} ${durationLabel} (${percentageLabel})`)}`);
|
|
451
|
+
this.reportEvent({
|
|
452
|
+
...event,
|
|
453
|
+
indent: indent + 1,
|
|
454
|
+
measure
|
|
455
|
+
});
|
|
456
|
+
} catch {}
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
start(id) {
|
|
460
|
+
return performance.mark(idStart(id));
|
|
461
|
+
}
|
|
462
|
+
storeEvent({ result, ...event }) {
|
|
463
|
+
const lastEventIndex = event.events.length - 1;
|
|
464
|
+
const lastEvent = event.events[lastEventIndex];
|
|
465
|
+
if (lastEvent && !lastEvent.end) {
|
|
466
|
+
result.position = [...result.position, lastEventIndex];
|
|
467
|
+
this.storeEvent({
|
|
468
|
+
...event,
|
|
469
|
+
events: lastEvent.events,
|
|
470
|
+
result
|
|
471
|
+
});
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
const length = event.events.push({
|
|
475
|
+
...event,
|
|
476
|
+
events: []
|
|
477
|
+
});
|
|
478
|
+
result.position = [...result.position, length - 1];
|
|
479
|
+
}
|
|
480
|
+
timeEvent(name) {
|
|
481
|
+
const id = nameToId(name);
|
|
482
|
+
const start = this.start(id);
|
|
483
|
+
const event = {
|
|
484
|
+
events: this.events,
|
|
485
|
+
id,
|
|
486
|
+
name,
|
|
487
|
+
start
|
|
488
|
+
};
|
|
489
|
+
const result = { position: [] };
|
|
490
|
+
this.storeEvent({
|
|
491
|
+
...event,
|
|
492
|
+
result
|
|
493
|
+
});
|
|
494
|
+
return {
|
|
495
|
+
mark: start,
|
|
496
|
+
timeEnd: () => this.end(result)
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
//#endregion
|
|
502
|
+
//#region src/generate.ts
|
|
503
|
+
/**
|
|
504
|
+
* Generate a client from the provided configuration.
|
|
505
|
+
*
|
|
506
|
+
* @param userConfig User provided {@link UserConfig} configuration(s).
|
|
507
|
+
*/
|
|
508
|
+
const createClient = async (userConfig, logger = new Logger()) => {
|
|
509
|
+
const resolvedConfig = typeof userConfig === "function" ? await userConfig() : userConfig;
|
|
510
|
+
const userConfigs = resolvedConfig ? resolvedConfig instanceof Array ? resolvedConfig : [resolvedConfig] : [];
|
|
511
|
+
let rawLogs = userConfigs.find((config) => getLogs(config).level !== "silent")?.logs;
|
|
512
|
+
if (typeof rawLogs === "string") rawLogs = getLogs({ logs: rawLogs });
|
|
513
|
+
let configs;
|
|
514
|
+
try {
|
|
515
|
+
checkNodeVersion();
|
|
516
|
+
const eventCreateClient = logger.timeEvent("createClient");
|
|
517
|
+
const eventConfig = logger.timeEvent("config");
|
|
518
|
+
configs = await initConfigs({
|
|
519
|
+
logger,
|
|
520
|
+
userConfigs
|
|
521
|
+
});
|
|
522
|
+
if (configs.results.some((result$1) => result$1.config.logs.level !== "silent")) printCliIntro();
|
|
523
|
+
eventConfig.timeEnd();
|
|
524
|
+
const allConfigErrors = configs.results.flatMap((result$1) => result$1.errors.map((error) => ({
|
|
525
|
+
error,
|
|
526
|
+
jobIndex: result$1.jobIndex
|
|
527
|
+
})));
|
|
528
|
+
if (allConfigErrors.length) throw new ConfigValidationError(allConfigErrors);
|
|
529
|
+
const result = (await Promise.all(configs.results.map(async (result$1) => {
|
|
530
|
+
try {
|
|
531
|
+
return await createClient$1({
|
|
532
|
+
config: result$1.config,
|
|
533
|
+
dependencies: configs.dependencies,
|
|
534
|
+
jobIndex: result$1.jobIndex,
|
|
535
|
+
logger
|
|
536
|
+
});
|
|
537
|
+
} catch (error) {
|
|
538
|
+
throw new JobError("", {
|
|
539
|
+
error,
|
|
540
|
+
jobIndex: result$1.jobIndex
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
}))).filter((client) => Boolean(client));
|
|
544
|
+
eventCreateClient.timeEnd();
|
|
545
|
+
const printLogs = configs.results.some((result$1) => result$1.config.logs.level === "debug");
|
|
546
|
+
logger.report(printLogs);
|
|
547
|
+
return result;
|
|
548
|
+
} catch (error) {
|
|
549
|
+
const results = configs?.results ?? [];
|
|
550
|
+
const logs = results.find((result) => result.config.logs.level !== "silent")?.config.logs ?? results[0]?.config.logs ?? rawLogs;
|
|
551
|
+
const dryRun = results.some((result) => result.config.dryRun) ?? userConfigs.some((config) => config.dryRun) ?? false;
|
|
552
|
+
const logPath = logs?.file && !dryRun ? logCrashReport(error, logs.path ?? "") : void 0;
|
|
553
|
+
if (!logs || logs.level !== "silent") {
|
|
554
|
+
printCrashReport({
|
|
555
|
+
error,
|
|
556
|
+
logPath
|
|
557
|
+
});
|
|
558
|
+
if (await shouldReportCrash({
|
|
559
|
+
error,
|
|
560
|
+
isInteractive: results.some((result) => result.config.interactive) ?? userConfigs.some((config) => config.interactive) ?? false
|
|
561
|
+
})) await openGitHubIssueWithCrashReport(error);
|
|
562
|
+
}
|
|
563
|
+
throw error;
|
|
564
|
+
}
|
|
565
|
+
};
|
|
566
|
+
|
|
567
|
+
//#endregion
|
|
568
|
+
//#region src/utils/exports.ts
|
|
569
|
+
/**
|
|
570
|
+
* Utilities shared across the package.
|
|
571
|
+
*/
|
|
572
|
+
const utils = {
|
|
573
|
+
stringCase({ case: casing, stripLeadingSeparators, value }) {
|
|
574
|
+
return toCase(value, casing, { stripLeadingSeparators });
|
|
575
|
+
},
|
|
576
|
+
toCase
|
|
577
|
+
};
|
|
578
|
+
|
|
579
|
+
//#endregion
|
|
580
|
+
//#region src/index.ts
|
|
581
|
+
colors.enabled = colorSupport().hasBasic;
|
|
582
|
+
/**
|
|
583
|
+
* Type helper for openapi-ts.config.ts, returns {@link MaybeArray<UserConfig>} object(s)
|
|
584
|
+
*/
|
|
585
|
+
const defineConfig = async (config) => typeof config === "function" ? await config() : config;
|
|
586
|
+
|
|
587
|
+
//#endregion
|
|
588
|
+
export { Logger as i, utils as n, createClient as r, defineConfig as t };
|
|
589
|
+
//# sourceMappingURL=src-BCi83sdM.mjs.map
|