@keq-request/cli 5.0.0-alpha.7 → 5.0.0-alpha.9

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.
Files changed (141) hide show
  1. package/.turbo/turbo-build.log +22 -0
  2. package/CHANGELOG.md +18 -0
  3. package/dist/cli.cjs +1949 -0
  4. package/dist/cli.cjs.map +1 -0
  5. package/dist/cli.d.ts +3 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +1926 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/constants/file-naming-style.d.ts +14 -0
  10. package/dist/constants/file-naming-style.d.ts.map +1 -0
  11. package/dist/constants/qs-array-format.d.ts +9 -0
  12. package/dist/constants/qs-array-format.d.ts.map +1 -0
  13. package/dist/constants/supported-methods.d.ts +2 -0
  14. package/dist/constants/supported-methods.d.ts.map +1 -0
  15. package/dist/define-keq-config.d.ts +3 -0
  16. package/dist/define-keq-config.d.ts.map +1 -0
  17. package/dist/exception.d.ts +6 -0
  18. package/dist/exception.d.ts.map +1 -0
  19. package/dist/index.cjs +1855 -0
  20. package/dist/index.cjs.map +1 -0
  21. package/dist/index.d.ts +4 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +1816 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/renderer/json-schema/index.d.ts +3 -0
  26. package/dist/renderer/json-schema/index.d.ts.map +1 -0
  27. package/dist/renderer/operation-request/index.d.ts +8 -0
  28. package/dist/renderer/operation-request/index.d.ts.map +1 -0
  29. package/dist/renderer/operation-type/index.d.ts +5 -0
  30. package/dist/renderer/operation-type/index.d.ts.map +1 -0
  31. package/dist/renderer/request/index.d.ts +2 -0
  32. package/dist/renderer/request/index.d.ts.map +1 -0
  33. package/dist/renderer/types/any-other-attribute.d.ts +5 -0
  34. package/dist/renderer/types/any-other-attribute.d.ts.map +1 -0
  35. package/dist/renderer/types/mixed-schema-object.d.ts +7 -0
  36. package/dist/renderer/types/mixed-schema-object.d.ts.map +1 -0
  37. package/dist/renderer/utils/generate-schema.d.ts +6 -0
  38. package/dist/renderer/utils/generate-schema.d.ts.map +1 -0
  39. package/dist/tasks/append-ignore-rule/index.d.ts +10 -0
  40. package/dist/tasks/append-ignore-rule/index.d.ts.map +1 -0
  41. package/dist/tasks/compile/index.d.ts +8 -0
  42. package/dist/tasks/compile/index.d.ts.map +1 -0
  43. package/dist/tasks/compile/utils/compile-operation-definition.d.ts +12 -0
  44. package/dist/tasks/compile/utils/compile-operation-definition.d.ts.map +1 -0
  45. package/dist/tasks/compile/utils/compile-schema-definition.d.ts +10 -0
  46. package/dist/tasks/compile/utils/compile-schema-definition.d.ts.map +1 -0
  47. package/dist/tasks/download/index.d.ts +10 -0
  48. package/dist/tasks/download/index.d.ts.map +1 -0
  49. package/dist/tasks/index.d.ts +12 -0
  50. package/dist/tasks/index.d.ts.map +1 -0
  51. package/dist/tasks/interactive/index.d.ts +12 -0
  52. package/dist/tasks/interactive/index.d.ts.map +1 -0
  53. package/dist/tasks/interactive/utils/select-operation-definitions.d.ts +5 -0
  54. package/dist/tasks/interactive/utils/select-operation-definitions.d.ts.map +1 -0
  55. package/dist/tasks/persist/index.d.ts +11 -0
  56. package/dist/tasks/persist/index.d.ts.map +1 -0
  57. package/dist/tasks/setup/index.d.ts +10 -0
  58. package/dist/tasks/setup/index.d.ts.map +1 -0
  59. package/dist/tasks/setup/utils/find-nearest-package-json.d.ts +6 -0
  60. package/dist/tasks/setup/utils/find-nearest-package-json.d.ts.map +1 -0
  61. package/dist/tasks/setup/utils/get-project-module-system.d.ts +5 -0
  62. package/dist/tasks/setup/utils/get-project-module-system.d.ts.map +1 -0
  63. package/dist/tasks/setup/utils/index.d.ts +4 -0
  64. package/dist/tasks/setup/utils/index.d.ts.map +1 -0
  65. package/dist/tasks/setup/utils/validate-modules.d.ts +2 -0
  66. package/dist/tasks/setup/utils/validate-modules.d.ts.map +1 -0
  67. package/dist/tasks/shaking/index.d.ts +11 -0
  68. package/dist/tasks/shaking/index.d.ts.map +1 -0
  69. package/dist/tasks/types/ignore-mode.d.ts +2 -0
  70. package/dist/tasks/types/ignore-mode.d.ts.map +1 -0
  71. package/dist/tasks/types/task-context.d.ts +24 -0
  72. package/dist/tasks/types/task-context.d.ts.map +1 -0
  73. package/dist/tasks/utils/api-document.d.ts +18 -0
  74. package/dist/tasks/utils/api-document.d.ts.map +1 -0
  75. package/dist/tasks/utils/api-document_v3_1.d.ts +16 -0
  76. package/dist/tasks/utils/api-document_v3_1.d.ts.map +1 -0
  77. package/dist/tasks/utils/artifact.d.ts +25 -0
  78. package/dist/tasks/utils/artifact.d.ts.map +1 -0
  79. package/dist/tasks/utils/dependency.d.ts +22 -0
  80. package/dist/tasks/utils/dependency.d.ts.map +1 -0
  81. package/dist/tasks/utils/json-schema.d.ts +8 -0
  82. package/dist/tasks/utils/json-schema.d.ts.map +1 -0
  83. package/dist/tasks/utils/module-definition.d.ts +6 -0
  84. package/dist/tasks/utils/module-definition.d.ts.map +1 -0
  85. package/dist/tasks/utils/operation-definition.d.ts +22 -0
  86. package/dist/tasks/utils/operation-definition.d.ts.map +1 -0
  87. package/dist/tasks/utils/schema-definition.d.ts +19 -0
  88. package/dist/tasks/utils/schema-definition.d.ts.map +1 -0
  89. package/dist/tasks/utils/to-comment.d.ts +2 -0
  90. package/dist/tasks/utils/to-comment.d.ts.map +1 -0
  91. package/dist/tasks/validate/index.d.ts +9 -0
  92. package/dist/tasks/validate/index.d.ts.map +1 -0
  93. package/dist/types/build-cli-options.d.ts +19 -0
  94. package/dist/types/build-cli-options.d.ts.map +1 -0
  95. package/dist/types/operation-id-factory.d.ts +10 -0
  96. package/dist/types/operation-id-factory.d.ts.map +1 -0
  97. package/dist/types/qs.d.ts +9 -0
  98. package/dist/types/qs.d.ts.map +1 -0
  99. package/dist/types/runtime-config.d.ts +44 -0
  100. package/dist/types/runtime-config.d.ts.map +1 -0
  101. package/dist/types/to-code-options.d.ts +4 -0
  102. package/dist/types/to-code-options.d.ts.map +1 -0
  103. package/dist/utils/debugger.d.ts +7 -0
  104. package/dist/utils/debugger.d.ts.map +1 -0
  105. package/dist/utils/ignore-matcher.d.ts +19 -0
  106. package/dist/utils/ignore-matcher.d.ts.map +1 -0
  107. package/dist/utils/is-keywords.d.ts +2 -0
  108. package/dist/utils/is-keywords.d.ts.map +1 -0
  109. package/dist/utils/is-reserved-word.d.ts +2 -0
  110. package/dist/utils/is-reserved-word.d.ts.map +1 -0
  111. package/dist/utils/json-schema-utils/index.d.ts +11 -0
  112. package/dist/utils/json-schema-utils/index.d.ts.map +1 -0
  113. package/dist/utils/json-schema-utils/is-array.d.ts +3 -0
  114. package/dist/utils/json-schema-utils/is-array.d.ts.map +1 -0
  115. package/dist/utils/json-schema-utils/is-mixed.d.ts +4 -0
  116. package/dist/utils/json-schema-utils/is-mixed.d.ts.map +1 -0
  117. package/dist/utils/json-schema-utils/is-non-array.d.ts +3 -0
  118. package/dist/utils/json-schema-utils/is-non-array.d.ts.map +1 -0
  119. package/dist/utils/json-schema-utils/is-ref.d.ts +3 -0
  120. package/dist/utils/json-schema-utils/is-ref.d.ts.map +1 -0
  121. package/dist/utils/json-schema-utils/types/any-other-attribute.d.ts +5 -0
  122. package/dist/utils/json-schema-utils/types/any-other-attribute.d.ts.map +1 -0
  123. package/dist/utils/json-schema-utils/types/mixed-schema-object.d.ts +7 -0
  124. package/dist/utils/json-schema-utils/types/mixed-schema-object.d.ts.map +1 -0
  125. package/dist/utils/logger.d.ts +6 -0
  126. package/dist/utils/logger.d.ts.map +1 -0
  127. package/dist/utils/swagger-utils/dereference-deep.d.ts +3 -0
  128. package/dist/utils/swagger-utils/dereference-deep.d.ts.map +1 -0
  129. package/dist/utils/swagger-utils/dereference-operation.d.ts +4 -0
  130. package/dist/utils/swagger-utils/dereference-operation.d.ts.map +1 -0
  131. package/dist/utils/swagger-utils/dereference.d.ts +3 -0
  132. package/dist/utils/swagger-utils/dereference.d.ts.map +1 -0
  133. package/dist/utils/swagger-utils/index.d.ts +15 -0
  134. package/dist/utils/swagger-utils/index.d.ts.map +1 -0
  135. package/dist/utils/swagger-utils/is-ref-defined.d.ts +3 -0
  136. package/dist/utils/swagger-utils/is-ref-defined.d.ts.map +1 -0
  137. package/dist/utils/swagger-utils/remove-undefined-ref.d.ts +3 -0
  138. package/dist/utils/swagger-utils/remove-undefined-ref.d.ts.map +1 -0
  139. package/dist/utils/swagger-utils/update-operation-id.d.ts +5 -0
  140. package/dist/utils/swagger-utils/update-operation-id.d.ts.map +1 -0
  141. package/package.json +3 -3
package/dist/index.cjs ADDED
@@ -0,0 +1,1855 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ FileNamingStyle: () => FileNamingStyle,
34
+ build: () => build,
35
+ defineKeqConfig: () => defineKeqConfig
36
+ });
37
+ module.exports = __toCommonJS(index_exports);
38
+
39
+ // src/tasks/index.ts
40
+ var import_listr22 = require("listr2");
41
+
42
+ // src/tasks/setup/index.ts
43
+ var R3 = __toESM(require("ramda"), 1);
44
+ var import_fs_extra2 = __toESM(require("fs-extra"), 1);
45
+ var import_path = __toESM(require("path"), 1);
46
+ var import_value = require("@sinclair/typebox/value");
47
+ var import_cosmiconfig = require("cosmiconfig");
48
+
49
+ // src/types/runtime-config.ts
50
+ var import_typebox2 = require("@sinclair/typebox");
51
+
52
+ // src/constants/file-naming-style.ts
53
+ var FileNamingStyle = /* @__PURE__ */ ((FileNamingStyle2) => {
54
+ FileNamingStyle2["camelCase"] = "camelCase";
55
+ FileNamingStyle2["capitalCase"] = "capitalCase";
56
+ FileNamingStyle2["constantCase"] = "constantCase";
57
+ FileNamingStyle2["dotCase"] = "dotCase";
58
+ FileNamingStyle2["headerCase"] = "headerCase";
59
+ FileNamingStyle2["noCase"] = "noCase";
60
+ FileNamingStyle2["paramCase"] = "paramCase";
61
+ FileNamingStyle2["pascalCase"] = "pascalCase";
62
+ FileNamingStyle2["pathCase"] = "pathCase";
63
+ FileNamingStyle2["sentenceCase"] = "sentenceCase";
64
+ FileNamingStyle2["snakeCase"] = "snakeCase";
65
+ return FileNamingStyle2;
66
+ })(FileNamingStyle || {});
67
+
68
+ // src/types/qs.ts
69
+ var import_typebox = require("@sinclair/typebox");
70
+
71
+ // src/constants/qs-array-format.ts
72
+ var QsArrayFormat = /* @__PURE__ */ ((QsArrayFormat2) => {
73
+ QsArrayFormat2["brackets"] = "brackets";
74
+ QsArrayFormat2["indices"] = "indices";
75
+ QsArrayFormat2["repeat"] = "repeat";
76
+ QsArrayFormat2["comma"] = "comma";
77
+ QsArrayFormat2["space"] = "space";
78
+ QsArrayFormat2["pipe"] = "pipe";
79
+ return QsArrayFormat2;
80
+ })(QsArrayFormat || {});
81
+
82
+ // src/types/qs.ts
83
+ var Qs = import_typebox.Type.Object({
84
+ indices: import_typebox.Type.Optional(import_typebox.Type.Boolean()),
85
+ arrayFormat: import_typebox.Type.Optional(import_typebox.Type.Enum(QsArrayFormat)),
86
+ allowDots: import_typebox.Type.Optional(import_typebox.Type.Boolean())
87
+ });
88
+
89
+ // src/types/runtime-config.ts
90
+ var RuntimeConfig = import_typebox2.Type.Object({
91
+ /**
92
+ * Whether to generate ES Module code
93
+ *
94
+ * If not specified, the module system will be inferred from the nearest package.json "type" field
95
+ * or defaults to "cjs" if no package.json is found.
96
+ */
97
+ esm: import_typebox2.Type.Optional(import_typebox2.Type.Boolean({ default: false })),
98
+ /**
99
+ * Output directory for generated files
100
+ */
101
+ outdir: import_typebox2.Type.String({ default: `${process.cwd()}/api` }),
102
+ /**
103
+ * File naming style for generated files
104
+ */
105
+ fileNamingStyle: import_typebox2.Type.Enum(FileNamingStyle, { default: "snakeCase" /* snakeCase */ }),
106
+ modules: import_typebox2.Type.Record(import_typebox2.Type.String(), import_typebox2.Type.String()),
107
+ operationIdFactory: import_typebox2.Type.Optional(import_typebox2.Type.Function([import_typebox2.Type.Any()], import_typebox2.Type.String())),
108
+ qs: import_typebox2.Type.Optional(import_typebox2.Type.Union([
109
+ Qs,
110
+ import_typebox2.Type.Function([import_typebox2.Type.Any()], Qs)
111
+ ])),
112
+ debug: import_typebox2.Type.Optional(import_typebox2.Type.Boolean({ default: false })),
113
+ /**
114
+ * Whether to tolerate wrong swagger structure
115
+ */
116
+ tolerant: import_typebox2.Type.Optional(import_typebox2.Type.Boolean({ default: false }))
117
+ });
118
+
119
+ // src/utils/ignore-matcher.ts
120
+ var R = __toESM(require("ramda"), 1);
121
+ var import_fs_extra = __toESM(require("fs-extra"), 1);
122
+ var IgnoreMatcher = class _IgnoreMatcher {
123
+ rules;
124
+ constructor(rules) {
125
+ this.rules = rules;
126
+ }
127
+ static async read(filepath) {
128
+ let content = await import_fs_extra.default.readFile(filepath, "utf-8");
129
+ content = content.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/#.*$/gm, "").replace(/\n+/g, "\n").trim();
130
+ let rules = content.split("\n").map((line) => line.trim()).filter((line) => line.length > 0).map((line) => {
131
+ const matched = line.match(/^(!)?\s*([^\s/]+)\s+([^\s/]+)\s+([^\s]+)$/);
132
+ if (!matched) throw new Error(`Invalid ignore rule: "${line}"`);
133
+ const [, flag, moduleName, operationMethod, operationPathname] = matched;
134
+ return {
135
+ persist: true,
136
+ ignore: !flag,
137
+ moduleName,
138
+ operationMethod: operationMethod.toLowerCase(),
139
+ operationPathname
140
+ };
141
+ });
142
+ rules = R.sortBy(
143
+ R.prop("ignore"),
144
+ rules
145
+ );
146
+ rules = R.uniqWith(
147
+ (a, b) => a.moduleName === b.moduleName && a.operationMethod === b.operationMethod && a.operationPathname === b.operationPathname,
148
+ rules
149
+ );
150
+ return new _IgnoreMatcher(rules);
151
+ }
152
+ async write(filepath) {
153
+ const ruleGroups = R.compose(
154
+ R.groupBy((rule) => rule.moduleName),
155
+ R.reverse,
156
+ R.uniqWith(
157
+ (a, b) => a.moduleName === b.moduleName && a.operationMethod === b.operationMethod && a.operationPathname === b.operationPathname
158
+ ),
159
+ R.filter((rule) => rule.persist)
160
+ )(this.rules);
161
+ const content = Object.entries(ruleGroups).sort((a, b) => {
162
+ const aModuleName = a[0];
163
+ const bModuleName = b[0];
164
+ if (aModuleName === "*") return -1;
165
+ if (bModuleName === "*") return 1;
166
+ return aModuleName.localeCompare(bModuleName);
167
+ }).map(([, rules]) => (rules || []).sort((a, b) => {
168
+ if (a.ignore !== b.ignore) return a.ignore ? -1 : 1;
169
+ if (a.operationMethod === "*") return -1;
170
+ if (b.operationMethod === "*") return 1;
171
+ if (a.operationPathname === "*") return -1;
172
+ if (b.operationPathname === "*") return 1;
173
+ if (a.operationMethod !== b.operationMethod) return a.operationMethod.localeCompare(b.operationMethod);
174
+ if (a.operationPathname !== b.operationPathname) return a.operationPathname.localeCompare(b.operationPathname);
175
+ return 0;
176
+ }).map((rule) => `${rule.ignore ? "" : "! "}${rule.moduleName} ${rule.operationMethod.toUpperCase()} ${rule.operationPathname}`).join("\n")).join("\n\n");
177
+ await import_fs_extra.default.writeFile(filepath, content, "utf-8");
178
+ }
179
+ append(rule) {
180
+ this.rules.unshift(rule);
181
+ }
182
+ // if operation is ignored, return true
183
+ isOperationIgnored(operationDefinition) {
184
+ const moduleName = operationDefinition.module.name;
185
+ const operationMethod = operationDefinition.method.toLowerCase();
186
+ const operationPathname = operationDefinition.pathname;
187
+ for (const rule of this.rules) {
188
+ if (rule.moduleName !== "*" && rule.moduleName !== moduleName) continue;
189
+ if (rule.operationMethod !== "*" && rule.operationMethod !== operationMethod) continue;
190
+ if (rule.operationPathname !== "*" && rule.operationPathname !== operationPathname) continue;
191
+ return rule.ignore;
192
+ }
193
+ return false;
194
+ }
195
+ isModuleIgnored(moduleDefinition) {
196
+ const moduleName = moduleDefinition.name;
197
+ for (const rule of this.rules) {
198
+ if (!rule.ignore) {
199
+ if (rule.moduleName === "*" || rule.moduleName === moduleName) return false;
200
+ continue;
201
+ }
202
+ if (rule.operationMethod !== "*") continue;
203
+ if (rule.operationPathname !== "*") continue;
204
+ if (rule.moduleName === "*" || rule.moduleName === moduleName) return true;
205
+ }
206
+ return false;
207
+ }
208
+ };
209
+
210
+ // src/tasks/setup/utils/validate-modules.ts
211
+ var R2 = __toESM(require("ramda"), 1);
212
+ var import_validator = __toESM(require("validator"), 1);
213
+ function validateModules(modules) {
214
+ const keys2 = Object.keys(modules);
215
+ for (const key of keys2) {
216
+ if (!/^[A-Za-z_][A-Za-z0-9_$]*$/.test(key)) {
217
+ throw new Error(`Module name "${key}" is not valid. It must start with a letter or underscore, and can only contain letters, numbers, and underscores.`);
218
+ }
219
+ }
220
+ const keysGroupByLowerCase = R2.groupBy(R2.toLower, keys2);
221
+ for (const groupKey in keysGroupByLowerCase) {
222
+ const keys3 = keysGroupByLowerCase[groupKey] || [];
223
+ if (keys3.length > 1) {
224
+ throw new Error(`Module names ${keys3.map((name) => `"${name}"`).join(", ")} are case-insensitively duplicated.`);
225
+ }
226
+ }
227
+ for (const key in modules) {
228
+ const address = modules[key];
229
+ if (import_validator.default.isURL(address, { require_host: true, require_protocol: true, protocols: ["http", "https"] })) {
230
+ continue;
231
+ }
232
+ if (/^(\/|\.\/|\.\.\/)/.test(address)) {
233
+ continue;
234
+ }
235
+ throw new Error(`Module address "${address}" of module "${key}" is not valid. It must be a URL or a local path.`);
236
+ }
237
+ }
238
+
239
+ // src/tasks/setup/utils/find-nearest-package-json.ts
240
+ var import_node_fs = __toESM(require("fs"), 1);
241
+ var import_node_path = __toESM(require("path"), 1);
242
+ function findNearestPackageJson(startDir = process.cwd()) {
243
+ let dir = startDir;
244
+ while (true) {
245
+ const pkgPath = import_node_path.default.join(dir, "package.json");
246
+ if (import_node_fs.default.existsSync(pkgPath)) {
247
+ const json = JSON.parse(import_node_fs.default.readFileSync(pkgPath, "utf8"));
248
+ return { json, path: pkgPath };
249
+ }
250
+ const parent = import_node_path.default.dirname(dir);
251
+ if (parent === dir) break;
252
+ dir = parent;
253
+ }
254
+ return null;
255
+ }
256
+
257
+ // src/tasks/setup/utils/get-project-module-system.ts
258
+ function getProjectModuleSystem(pkgInfo) {
259
+ if (!pkgInfo?.json) return "cjs";
260
+ const { json } = pkgInfo;
261
+ if (json.type === "module") return "esm";
262
+ return "cjs";
263
+ }
264
+
265
+ // src/tasks/setup/index.ts
266
+ var explore = (0, import_cosmiconfig.cosmiconfig)("keq");
267
+ function createSetupTask(options) {
268
+ return {
269
+ title: "Setup",
270
+ task: async (context, task) => {
271
+ const result = options?.config ? await explore.load(options.config) : await explore.search();
272
+ if (!result || "isEmpty" in result && result.isEmpty) {
273
+ throw new Error("Cannot find config file.");
274
+ }
275
+ if (!import_value.Value.Check(RuntimeConfig, result.config)) {
276
+ const errors = [...import_value.Value.Errors(RuntimeConfig, result.config)];
277
+ const message = errors.map(({ path: path9, message: message2 }) => `${path9}: ${message2}`).join("\n");
278
+ throw new Error(`Invalid Config: ${message}`);
279
+ }
280
+ const rc = import_value.Value.Default(RuntimeConfig, result.config);
281
+ validateModules(rc.modules);
282
+ if (options?.debug) {
283
+ await import_fs_extra2.default.ensureDir(".keq");
284
+ rc.debug = true;
285
+ }
286
+ if (options?.tolerant) {
287
+ rc.tolerant = true;
288
+ }
289
+ const packageJsonInfo = findNearestPackageJson();
290
+ if (packageJsonInfo) {
291
+ const moduleSystem = getProjectModuleSystem(packageJsonInfo);
292
+ rc.esm = moduleSystem === "esm";
293
+ }
294
+ let filter2 = new IgnoreMatcher([]);
295
+ if (result.filepath) {
296
+ const ignoreFilepath = import_path.default.resolve(import_path.default.dirname(result.filepath), ".keqignore");
297
+ if (await import_fs_extra2.default.exists(ignoreFilepath)) {
298
+ filter2 = await IgnoreMatcher.read(ignoreFilepath);
299
+ }
300
+ }
301
+ if (options?.modules && options.modules.length) {
302
+ const notExistModules = options.modules.filter((moduleName) => !(moduleName in rc.modules));
303
+ if (notExistModules.length) {
304
+ throw new Error(`Cannot find module(s) ${notExistModules.join(", ")} in config file.`);
305
+ }
306
+ const ignoredModules = R3.difference(R3.keys(rc.modules), options.modules);
307
+ for (const moduleName of ignoredModules) {
308
+ filter2.append({
309
+ persist: false,
310
+ ignore: true,
311
+ moduleName,
312
+ operationMethod: "*",
313
+ operationPathname: "*"
314
+ });
315
+ }
316
+ }
317
+ context.setup = { rc, matcher: filter2 };
318
+ }
319
+ };
320
+ }
321
+
322
+ // src/tasks/download/index.ts
323
+ var import_listr2 = require("listr2");
324
+
325
+ // src/tasks/utils/module-definition.ts
326
+ var ModuleDefinition = class {
327
+ name;
328
+ address;
329
+ constructor(name, address) {
330
+ this.name = name;
331
+ this.address = address;
332
+ }
333
+ };
334
+
335
+ // src/tasks/utils/api-document.ts
336
+ var import_fs_extra4 = __toESM(require("fs-extra"), 1);
337
+ var path5 = __toESM(require("path"), 1);
338
+ var yaml = __toESM(require("js-yaml"), 1);
339
+ var validUrl = __toESM(require("valid-url"), 1);
340
+ var import_keq = require("keq");
341
+ var import_openapi_parser = require("@scalar/openapi-parser");
342
+
343
+ // src/tasks/utils/api-document_v3_1.ts
344
+ var R6 = __toESM(require("ramda"), 1);
345
+
346
+ // src/constants/supported-methods.ts
347
+ var SupportedMethods = [
348
+ "get",
349
+ "post",
350
+ "put",
351
+ "delete",
352
+ "patch",
353
+ "head",
354
+ "options"
355
+ ];
356
+
357
+ // src/tasks/utils/operation-definition.ts
358
+ var R5 = __toESM(require("ramda"), 1);
359
+
360
+ // src/utils/is-keywords.ts
361
+ var keywords = [
362
+ "break",
363
+ "case",
364
+ "catch",
365
+ "continue",
366
+ "default",
367
+ "delete",
368
+ "do",
369
+ "else",
370
+ "finally",
371
+ "for",
372
+ "function",
373
+ "if",
374
+ "in",
375
+ "instanceof",
376
+ "new",
377
+ "return",
378
+ "switch",
379
+ "this",
380
+ "throw",
381
+ "try",
382
+ "typeof",
383
+ "var",
384
+ "void",
385
+ "while",
386
+ "with"
387
+ ];
388
+ function isKeywords(str) {
389
+ return keywords.includes(str);
390
+ }
391
+
392
+ // src/utils/is-reserved-word.ts
393
+ var reservedWords = [
394
+ "abstract",
395
+ "boolean",
396
+ "byte",
397
+ "char",
398
+ "class",
399
+ "const",
400
+ "debugger",
401
+ "double",
402
+ "enum",
403
+ "export",
404
+ "extends",
405
+ "final",
406
+ "float",
407
+ "goto",
408
+ "implements",
409
+ "import",
410
+ "int",
411
+ "interface",
412
+ "long",
413
+ "native",
414
+ "package",
415
+ "private",
416
+ "protected",
417
+ "public",
418
+ "short",
419
+ "static",
420
+ "super",
421
+ "synchronized",
422
+ "throws",
423
+ "transient",
424
+ "volatile"
425
+ ];
426
+ function isReservedWord(str) {
427
+ return reservedWords.includes(str);
428
+ }
429
+
430
+ // src/tasks/utils/operation-definition.ts
431
+ var import_jsonpath_plus2 = require("jsonpath-plus");
432
+
433
+ // src/tasks/utils/schema-definition.ts
434
+ var R4 = __toESM(require("ramda"), 1);
435
+ var import_jsonpath_plus = require("jsonpath-plus");
436
+ var SchemaDefinition = class _SchemaDefinition {
437
+ id;
438
+ name;
439
+ schema;
440
+ module;
441
+ document;
442
+ constructor(args) {
443
+ this.module = args.module;
444
+ this.name = args.name;
445
+ this.id = args.id;
446
+ this.schema = args.schema;
447
+ this.document = args.document;
448
+ }
449
+ getDependencies() {
450
+ const refs = R4.uniq((0, import_jsonpath_plus.JSONPath)({
451
+ path: "$..*['$ref']",
452
+ json: this.schema
453
+ }));
454
+ return refs.filter((ref) => typeof ref === "string" && !!ref.trim()).map((ref) => {
455
+ const definition = this.document.dereference(ref);
456
+ if (definition) return definition;
457
+ return new _SchemaDefinition({
458
+ id: ref,
459
+ name: "unknown",
460
+ schema: {},
461
+ module: this.module,
462
+ document: this.document
463
+ });
464
+ });
465
+ }
466
+ };
467
+
468
+ // src/tasks/utils/operation-definition.ts
469
+ var OperationDefinition = class {
470
+ module;
471
+ operationId;
472
+ method;
473
+ pathname;
474
+ operation;
475
+ document;
476
+ constructor(args) {
477
+ this.module = args.module;
478
+ this.method = args.method.toLowerCase();
479
+ this.pathname = args.pathname;
480
+ this.document = args.document;
481
+ this.operationId = this.formatOperationId(args.method, args.pathname, args.operation);
482
+ this.operation = {
483
+ ...args.operation,
484
+ operationId: this.operationId
485
+ };
486
+ }
487
+ formatOperationId(method, pathname, operation) {
488
+ const operationId = operation.operationId;
489
+ if (operationId && operationId !== "index" && !isKeywords(operationId) && !isReservedWord(operationId)) {
490
+ return operationId;
491
+ }
492
+ return `${method}_${pathname}`.replace(/\//g, "_").replace(/-/g, "_").replace(/:/g, "$$").replace(/{(.+)}/, "$$$1");
493
+ }
494
+ getDependencies() {
495
+ const refs = R5.uniq([
496
+ ...(0, import_jsonpath_plus2.JSONPath)({
497
+ path: "$.requestBody.content..schema..$ref",
498
+ json: this.operation
499
+ }),
500
+ ...(0, import_jsonpath_plus2.JSONPath)({
501
+ path: "$.responses..content..schema..$ref",
502
+ json: this.operation
503
+ }),
504
+ ...(0, import_jsonpath_plus2.JSONPath)({
505
+ path: "$.parameters..schema..$ref",
506
+ json: this.operation
507
+ })
508
+ ]);
509
+ const dependencies = refs.filter((ref) => typeof ref === "string" && ref).map((ref) => {
510
+ const schemaDefinition = this.document.dereference(ref);
511
+ if (schemaDefinition) return schemaDefinition;
512
+ return new SchemaDefinition({
513
+ id: ref,
514
+ name: "unknown",
515
+ schema: {},
516
+ module: this.module,
517
+ document: this.document
518
+ });
519
+ });
520
+ return dependencies;
521
+ }
522
+ };
523
+
524
+ // src/utils/logger.ts
525
+ var import_chalk = __toESM(require("chalk"), 1);
526
+ var logger = {
527
+ log: (str) => console.log(import_chalk.default.green(str)),
528
+ warn: (str) => console.warn(import_chalk.default.yellow(str)),
529
+ error: (str) => console.error(import_chalk.default.red(str))
530
+ };
531
+
532
+ // src/tasks/utils/api-document_v3_1.ts
533
+ var import_openapi_shaking = __toESM(require("@opendoc/openapi-shaking"), 1);
534
+ var ApiDocumentV3_1 = class _ApiDocumentV3_1 {
535
+ module;
536
+ swagger;
537
+ constructor(swagger, module2) {
538
+ this.module = module2;
539
+ this.swagger = swagger;
540
+ }
541
+ get schemas() {
542
+ const module2 = this.module;
543
+ return Object.entries(this.swagger.components?.schemas || {}).map(([name, schema]) => new SchemaDefinition({
544
+ id: `#/components/schemas/${name}`,
545
+ name,
546
+ schema,
547
+ module: module2,
548
+ document: this
549
+ }));
550
+ }
551
+ get operations() {
552
+ const module2 = this.module;
553
+ return Object.entries(this.swagger.paths || {}).flatMap(([pathname, pathItem]) => Object.entries(pathItem || {}).filter(([method]) => SupportedMethods.includes(method.toLowerCase())).map(([method, operation]) => new OperationDefinition({
554
+ method,
555
+ pathname,
556
+ operation,
557
+ module: module2,
558
+ document: this
559
+ })));
560
+ }
561
+ isEmpty() {
562
+ return R6.isEmpty(this.swagger.paths);
563
+ }
564
+ dereference($ref) {
565
+ if ($ref.startsWith("#/")) {
566
+ return this.schemas.find((schema) => schema.id === $ref);
567
+ }
568
+ logger.warn(`The $ref(${$ref}) is not defined in ${this.module.name} swagger.`);
569
+ }
570
+ isRefDefined($ref) {
571
+ if ($ref.startsWith("#/")) {
572
+ const path9 = $ref.replace("#/", "").split("/");
573
+ return R6.path(path9, this.swagger) !== void 0;
574
+ }
575
+ return false;
576
+ }
577
+ sharking(filter2) {
578
+ const isAccepted = (pathname, method, operation) => {
579
+ if (!SupportedMethods.includes(method)) return false;
580
+ const operationDefinition = new OperationDefinition({
581
+ method,
582
+ pathname,
583
+ operation,
584
+ module: this.module,
585
+ document: this
586
+ });
587
+ return filter2(operationDefinition);
588
+ };
589
+ const sharkedSwagger = import_openapi_shaking.default.openapiShakingSync(
590
+ this.swagger,
591
+ isAccepted,
592
+ { tolerant: true }
593
+ );
594
+ return new _ApiDocumentV3_1(
595
+ sharkedSwagger,
596
+ new ModuleDefinition(
597
+ this.module.name,
598
+ `file://${this.module.name}.v3_1.sharked.json`
599
+ )
600
+ );
601
+ }
602
+ };
603
+
604
+ // src/tasks/utils/api-document.ts
605
+ var import_swagger_fix = require("swagger-fix");
606
+
607
+ // src/utils/debugger.ts
608
+ var import_fs_extra3 = __toESM(require("fs-extra"), 1);
609
+ var Debugger = class {
610
+ constructor(rc) {
611
+ this.rc = rc;
612
+ }
613
+ writeSwagger(fullpath, swagger) {
614
+ if (this.rc?.debug) {
615
+ void import_fs_extra3.default.writeJSON(fullpath, swagger, { spaces: 2 });
616
+ }
617
+ }
618
+ };
619
+
620
+ // src/utils/swagger-utils/dereference.ts
621
+ function dereference($ref, swagger) {
622
+ let value;
623
+ for (const key of $ref.split("/")) {
624
+ if (key === "#") {
625
+ value = swagger;
626
+ } else {
627
+ value = value[key];
628
+ }
629
+ if (!value) break;
630
+ }
631
+ return value;
632
+ }
633
+
634
+ // src/utils/swagger-utils/dereference-operation.ts
635
+ var R9 = __toESM(require("ramda"), 1);
636
+ var import_jsonpointer2 = __toESM(require("jsonpointer"), 1);
637
+ var import_jsonpath_plus4 = require("jsonpath-plus");
638
+
639
+ // src/utils/swagger-utils/remove-undefined-ref.ts
640
+ var R8 = __toESM(require("ramda"), 1);
641
+ var import_jsonpointer = __toESM(require("jsonpointer"), 1);
642
+ var import_jsonpath_plus3 = require("jsonpath-plus");
643
+
644
+ // src/utils/swagger-utils/is-ref-defined.ts
645
+ var R7 = __toESM(require("ramda"), 1);
646
+ function isRefDefined($ref, swagger) {
647
+ if ($ref.startsWith("#/")) {
648
+ const path9 = $ref.replace("#/", "").split("/");
649
+ return R7.path(path9, swagger) !== void 0;
650
+ }
651
+ return false;
652
+ }
653
+
654
+ // src/utils/swagger-utils/remove-undefined-ref.ts
655
+ function removeUndefinedRef(swagger) {
656
+ const shadow = R8.clone(swagger);
657
+ const matches = (0, import_jsonpath_plus3.JSONPath)({
658
+ path: "$..*['$ref']^",
659
+ json: swagger,
660
+ resultType: "all"
661
+ });
662
+ for (const match of matches) {
663
+ if (match.value.$ref && !isRefDefined(match.value.$ref, swagger)) {
664
+ import_jsonpointer.default.set(shadow, match.pointer, R8.omit(["$ref"], match.value));
665
+ }
666
+ }
667
+ return shadow;
668
+ }
669
+
670
+ // src/utils/swagger-utils/dereference-operation.ts
671
+ function dereferencePathObject(swagger) {
672
+ const matches = (0, import_jsonpath_plus4.JSONPath)({
673
+ path: "$.paths.*.$ref^",
674
+ json: swagger,
675
+ resultType: "all"
676
+ });
677
+ for (const match of matches) {
678
+ const value = SwaggerUtils.dereference(match.value.$ref, swagger);
679
+ import_jsonpointer2.default.set(swagger, match.pointer, value);
680
+ }
681
+ }
682
+ function dereferenceRequestBody(swagger) {
683
+ const matches = (0, import_jsonpath_plus4.JSONPath)({
684
+ path: "$.paths.*.*.requestBody.$ref^",
685
+ json: swagger,
686
+ resultType: "all"
687
+ });
688
+ for (const match of matches) {
689
+ const value = SwaggerUtils.dereference(match.value.$ref, swagger);
690
+ import_jsonpointer2.default.set(swagger, match.pointer, value);
691
+ }
692
+ }
693
+ function dereferenceResponses(swagger) {
694
+ const matches = [
695
+ ...(0, import_jsonpath_plus4.JSONPath)({
696
+ path: "$.paths.*.*.responses.*.$ref^",
697
+ json: swagger,
698
+ resultType: "all"
699
+ }),
700
+ ...(0, import_jsonpath_plus4.JSONPath)({
701
+ path: "$.paths.*.*.responses.*.headers.*.$ref^",
702
+ json: swagger,
703
+ resultType: "all"
704
+ })
705
+ ];
706
+ for (const match of matches) {
707
+ const value = SwaggerUtils.dereference(match.value.$ref, swagger);
708
+ import_jsonpointer2.default.set(swagger, match.pointer, value);
709
+ }
710
+ }
711
+ function dereferenceParameters(swagger) {
712
+ const matches = (0, import_jsonpath_plus4.JSONPath)({
713
+ path: "$.paths.*.*.parameters.*.$ref^",
714
+ json: swagger,
715
+ resultType: "all"
716
+ });
717
+ for (const match of matches) {
718
+ const value = SwaggerUtils.dereference(match.value.$ref, swagger);
719
+ import_jsonpointer2.default.set(swagger, match.pointer, value);
720
+ }
721
+ }
722
+ function dereferenceOperation(swagger) {
723
+ const shadow = R9.clone(swagger);
724
+ dereferencePathObject(shadow);
725
+ dereferenceRequestBody(shadow);
726
+ dereferenceResponses(shadow);
727
+ dereferenceParameters(shadow);
728
+ return removeUndefinedRef(shadow);
729
+ }
730
+
731
+ // src/utils/swagger-utils/update-operation-id.ts
732
+ var R10 = __toESM(require("ramda"), 1);
733
+ function updateOperationId(swagger, fn) {
734
+ const shadow = R10.clone(swagger);
735
+ for (const [pathname, pathItem] of Object.entries(shadow.paths || {})) {
736
+ for (const m in pathItem) {
737
+ const method = m.toLowerCase();
738
+ if (!SupportedMethods.includes(method)) continue;
739
+ if (typeof pathItem[m] !== "object" || Array.isArray(pathItem[m]) || pathItem[m] === null) continue;
740
+ const operation = pathItem[m];
741
+ const operationId = fn(method, pathname, operation);
742
+ if (typeof operationId === "string" && operationId.length > 0) {
743
+ operation.operationId = operationId;
744
+ }
745
+ }
746
+ }
747
+ return shadow;
748
+ }
749
+
750
+ // src/utils/json-schema-utils/is-array.ts
751
+ function isArray(schema) {
752
+ return schema.type === "array";
753
+ }
754
+
755
+ // src/utils/json-schema-utils/is-mixed.ts
756
+ function isMixed(schema) {
757
+ return Array.isArray(schema.type);
758
+ }
759
+
760
+ // src/utils/json-schema-utils/is-non-array.ts
761
+ function isNonArray(schema) {
762
+ return typeof schema.type === "string" && schema.type !== "array";
763
+ }
764
+
765
+ // src/utils/json-schema-utils/is-ref.ts
766
+ function isRef(schema) {
767
+ return "$ref" in schema;
768
+ }
769
+
770
+ // src/utils/json-schema-utils/index.ts
771
+ var JsonSchemaUtils = class {
772
+ static isRef = isRef;
773
+ static isArray = isArray;
774
+ static isNonArray = isNonArray;
775
+ static isMixed = isMixed;
776
+ };
777
+
778
+ // src/utils/swagger-utils/dereference-deep.ts
779
+ function dereferenceDeep($ref, swagger) {
780
+ const stack = [$ref];
781
+ let value;
782
+ while (true) {
783
+ const last = stack[stack.length - 1];
784
+ value = dereference(last, swagger);
785
+ if (JsonSchemaUtils.isRef(value)) {
786
+ if (!stack.includes(value.$ref)) {
787
+ stack.push(value.$ref);
788
+ continue;
789
+ } else {
790
+ throw new Error(`Circular reference detected: ${stack.join(" -> ")} -> ${value.$ref}`);
791
+ }
792
+ }
793
+ break;
794
+ }
795
+ return value;
796
+ }
797
+
798
+ // src/utils/swagger-utils/index.ts
799
+ var SwaggerUtils = class {
800
+ static isRefDefined = isRefDefined;
801
+ static dereference = dereference;
802
+ static dereferenceDeep = dereferenceDeep;
803
+ static removeUndefinedRef = removeUndefinedRef;
804
+ static dereferenceOperation = dereferenceOperation;
805
+ static updateOperationId = updateOperationId;
806
+ };
807
+
808
+ // src/tasks/utils/api-document.ts
809
+ var ApiDocument = class _ApiDocument {
810
+ module;
811
+ swagger;
812
+ constructor(swagger, module2) {
813
+ this.module = module2;
814
+ this.swagger = swagger;
815
+ }
816
+ static cache = /* @__PURE__ */ new Map();
817
+ static async download(url) {
818
+ let content;
819
+ try {
820
+ const res = await import_keq.request.get(url).resolveWith("response");
821
+ if (res.status >= 400) throw new Error(`Request failed with status code ${res.status}`);
822
+ content = await res.text();
823
+ } catch (e) {
824
+ if (e instanceof Error) {
825
+ e.message = `Unable get the swagger file from ${url}: ${e.message}`;
826
+ }
827
+ throw e;
828
+ }
829
+ try {
830
+ return JSON.parse(content);
831
+ } catch (e) {
832
+ throw new Error(`The swagger file get from url isn't json: ${url}`);
833
+ }
834
+ }
835
+ static async read(filePath) {
836
+ const fileExt = path5.extname(filePath);
837
+ const content = await import_fs_extra4.default.readFile(filePath, "utf8");
838
+ if ([".yml", ".yaml"].includes(fileExt)) {
839
+ return yaml.load(content);
840
+ } else if (fileExt === ".json") {
841
+ return JSON.parse(content);
842
+ }
843
+ throw new Error(`File ${fileExt} not support.`);
844
+ }
845
+ static async create(moduleDefinition) {
846
+ const { address } = moduleDefinition;
847
+ if (this.cache.has(moduleDefinition.address)) {
848
+ return this.cache.get(moduleDefinition.address);
849
+ }
850
+ const swagger = validUrl.isUri(address) ? await this.download(address) : await this.read(address);
851
+ return new _ApiDocument(swagger, moduleDefinition);
852
+ }
853
+ async validate() {
854
+ return await (0, import_openapi_parser.validate)(this.swagger);
855
+ }
856
+ // remove chinese and special symbols
857
+ fix() {
858
+ const swagger = (0, import_swagger_fix.fixSwagger)(this.swagger);
859
+ return new _ApiDocument(
860
+ swagger,
861
+ new ModuleDefinition(
862
+ this.module.name,
863
+ `file://${this.module.name}.fixed.json`
864
+ )
865
+ );
866
+ }
867
+ // eslint-disable-next-line @typescript-eslint/require-await
868
+ async toV3_1(rc) {
869
+ const debug = new Debugger(rc);
870
+ let swagger = this.swagger;
871
+ const { specification } = (0, import_openapi_parser.upgrade)(swagger);
872
+ swagger = specification;
873
+ debug.writeSwagger(`.keq/${this.module.name}.3_1.json`, swagger);
874
+ swagger = SwaggerUtils.dereferenceOperation(swagger);
875
+ debug.writeSwagger(`.keq/${this.module.name}.3_1.sharked.json`, swagger);
876
+ if (rc?.operationIdFactory) {
877
+ const operationIdFactory = rc.operationIdFactory;
878
+ swagger = SwaggerUtils.updateOperationId(
879
+ swagger,
880
+ (method, pathname, operation) => operationIdFactory({ method, pathname, operation, module: this.module })
881
+ );
882
+ debug.writeSwagger(`.keq/${this.module.name}.3_1.formatted.json`, swagger);
883
+ }
884
+ return new ApiDocumentV3_1(
885
+ swagger,
886
+ new ModuleDefinition(
887
+ this.module.name,
888
+ `file://${this.module.name}.v3_1.json`
889
+ )
890
+ );
891
+ }
892
+ };
893
+
894
+ // src/tasks/download/index.ts
895
+ function createDownloadTask(options) {
896
+ return {
897
+ title: "Download",
898
+ enabled: options?.enabled,
899
+ skip: options?.skip,
900
+ task: (context, task) => {
901
+ if (!context.setup) {
902
+ throw new Error("Please run setup task first.");
903
+ }
904
+ const rc = context.setup.rc;
905
+ const matcher = context.setup.matcher;
906
+ context.downloaded = {
907
+ documents: []
908
+ };
909
+ return task.newListr(
910
+ Object.entries(rc.modules).map(([moduleName, address]) => new ModuleDefinition(moduleName, address)).map((moduleDefinition) => ({
911
+ title: moduleDefinition.name,
912
+ task: async (ctx, task2) => {
913
+ if (options?.skipIgnoredModules && matcher.isModuleIgnored(moduleDefinition)) {
914
+ task2.skip(`(${moduleDefinition.name}) is ignored`);
915
+ return;
916
+ }
917
+ task2.output = `Downloaded from ${moduleDefinition.address}`;
918
+ const document = await ApiDocument.create(moduleDefinition);
919
+ ctx.downloaded.documents.push(document);
920
+ }
921
+ })),
922
+ {
923
+ concurrent: true,
924
+ exitOnError: false,
925
+ collectErrors: "minimal",
926
+ rendererOptions: {
927
+ collapseSubtasks: false,
928
+ // collapseSkips: false,
929
+ suffixSkips: true,
930
+ timer: import_listr2.PRESET_TIMER
931
+ }
932
+ }
933
+ );
934
+ }
935
+ };
936
+ }
937
+
938
+ // src/tasks/validate/index.ts
939
+ function createValidateTask(options) {
940
+ return {
941
+ title: "Validate",
942
+ enabled: options?.enabled,
943
+ skip: options?.skip,
944
+ task: (context, task) => {
945
+ if (!context.setup) throw new Error("Please run setup task first.");
946
+ if (!context.downloaded) throw new Error("Please run download task first.");
947
+ const rc = context.setup.rc;
948
+ const downloadedDocuments = context.downloaded.documents;
949
+ const debug = new Debugger(rc);
950
+ context.validated = {
951
+ documents: []
952
+ };
953
+ return task.newListr(
954
+ downloadedDocuments.map((document) => ({
955
+ title: document.module.name,
956
+ task: async (ctx, task2) => {
957
+ const { valid, errors } = await document.validate();
958
+ if (!valid) {
959
+ const message = `${document.module.name} module swagger file does not conform to the openapi@3.1 standard specifications or have grammatical errors, which may cause unexpected errors:
960
+ ${errors?.map((e) => ` - ${e.message}`).join("\n")}`;
961
+ task2.output = message;
962
+ }
963
+ const fixedDocument = document.fix();
964
+ debug.writeSwagger(`.keq/${document.module.name}.fixed.json`, fixedDocument.swagger);
965
+ const v3_1Document = await fixedDocument.toV3_1(rc);
966
+ ctx.validated.documents.push(v3_1Document);
967
+ }
968
+ })),
969
+ {
970
+ concurrent: true,
971
+ rendererOptions: {
972
+ collapseSubtasks: false,
973
+ persistentOutput: true
974
+ }
975
+ }
976
+ );
977
+ }
978
+ };
979
+ }
980
+
981
+ // src/tasks/shaking/index.ts
982
+ function createShakingTask(options) {
983
+ return {
984
+ title: "Shaking",
985
+ enabled: options?.enabled,
986
+ skip: options?.skip,
987
+ task: (context, task) => {
988
+ if (!context.setup) throw new Error("Please run setup task first.");
989
+ if (!context.validated) throw new Error("Please run validate task first.");
990
+ const matcher = context.setup.matcher;
991
+ const documents = context.validated.documents;
992
+ context.shaken = {
993
+ documents: []
994
+ };
995
+ return task.newListr(
996
+ documents.map((document) => ({
997
+ title: document.module.name,
998
+ task: (ctx, task2) => {
999
+ if (options?.skipIgnoredModules && matcher.isModuleIgnored(document.module)) {
1000
+ task2.skip(`${document.module.name} module is ignored`);
1001
+ return;
1002
+ }
1003
+ const shakenDocument = document.sharking(
1004
+ (operationDefinition) => !matcher.isOperationIgnored(operationDefinition)
1005
+ );
1006
+ if (options?.skipEmptyDocuments && shakenDocument.isEmpty()) {
1007
+ task2.skip(`${document.module.name} module is empty`);
1008
+ return;
1009
+ }
1010
+ ctx.shaken.documents.push(shakenDocument);
1011
+ }
1012
+ })),
1013
+ {
1014
+ concurrent: true,
1015
+ rendererOptions: {
1016
+ collapseSubtasks: false,
1017
+ suffixSkips: true
1018
+ }
1019
+ }
1020
+ );
1021
+ }
1022
+ };
1023
+ }
1024
+
1025
+ // src/tasks/persist/index.ts
1026
+ var path6 = __toESM(require("path"), 1);
1027
+ var import_fs_extra5 = __toESM(require("fs-extra"), 1);
1028
+ function createPersistArtifactTask(options) {
1029
+ return {
1030
+ title: "Write files",
1031
+ enabled: options?.persistArtifacts,
1032
+ skip: options?.skip,
1033
+ task: async (context, task) => {
1034
+ if (!context.setup) throw new Error("Please run setup task first.");
1035
+ if (!context.compiled) throw new Error("Please run compile task first.");
1036
+ const rc = context.setup.rc;
1037
+ const artifacts = context.compiled.artifacts;
1038
+ for (const artifact of artifacts) {
1039
+ artifact.changeFileNameCase(rc.fileNamingStyle);
1040
+ }
1041
+ const total = artifacts.length;
1042
+ let completed = 0;
1043
+ await Promise.all(artifacts.map(async (artifact) => {
1044
+ const realpath = `./${path6.join(rc.outdir, artifact.filepath)}`;
1045
+ await import_fs_extra5.default.ensureFile(realpath);
1046
+ await import_fs_extra5.default.writeFile(realpath, artifact.toCode({ esm: !!rc.esm }));
1047
+ completed += 1;
1048
+ task.output = `Persisted ${completed}/${total} files`;
1049
+ }));
1050
+ }
1051
+ };
1052
+ }
1053
+ function createPersistIgnoreTask(options) {
1054
+ return {
1055
+ title: "Update .keqignore",
1056
+ enabled: options?.persistIgnore,
1057
+ skip: options?.skip,
1058
+ task: async (context, task) => {
1059
+ if (!context.setup) throw new Error("Please run setup task first.");
1060
+ const matcher = context.setup.matcher;
1061
+ await matcher.write(".keqignore");
1062
+ }
1063
+ };
1064
+ }
1065
+ function createPersistTask(options) {
1066
+ return {
1067
+ title: "Persist",
1068
+ enabled: options?.enabled,
1069
+ skip: options?.skip,
1070
+ task: (context, task) => task.newListr(
1071
+ [
1072
+ createPersistArtifactTask(options),
1073
+ createPersistIgnoreTask(options)
1074
+ ],
1075
+ {
1076
+ concurrent: true,
1077
+ rendererOptions: {
1078
+ collapseSubtasks: true
1079
+ }
1080
+ }
1081
+ )
1082
+ };
1083
+ }
1084
+
1085
+ // src/tasks/compile/utils/compile-schema-definition.ts
1086
+ var R12 = __toESM(require("ramda"), 1);
1087
+
1088
+ // src/renderer/utils/generate-schema.ts
1089
+ var R11 = __toESM(require("ramda"), 1);
1090
+ function generateComment(schema) {
1091
+ const lines = ["/**"];
1092
+ if (schema.description) {
1093
+ const description = schema.description.replace("*/", "*\\/");
1094
+ lines.push(...description.split("\n").map((line) => ` * ${line}`));
1095
+ }
1096
+ if (schema.deprecated) {
1097
+ lines.push(" * @deprecated");
1098
+ }
1099
+ if (schema.readOnly) {
1100
+ lines.push(" * @readonly");
1101
+ }
1102
+ if (schema.format) {
1103
+ lines.push(` * @format ${schema.format}`);
1104
+ }
1105
+ lines.push(" */");
1106
+ if (lines.length === 2) return "";
1107
+ return lines.join("\n");
1108
+ }
1109
+ function generateSchema(schema, alias = R11.identity) {
1110
+ if (typeof schema === "boolean") return "unknown";
1111
+ if (JsonSchemaUtils.isRef(schema)) return generateReference(schema, alias);
1112
+ if (JsonSchemaUtils.isMixed(schema)) return generateMixed(schema, alias);
1113
+ if (JsonSchemaUtils.isArray(schema)) return generateArray(schema, alias);
1114
+ if (schema.type === "object") return generateObject(schema, alias);
1115
+ if (schema.enum) return generateEnum(schema, alias);
1116
+ if (schema.oneOf) return generateOneOf(schema, alias);
1117
+ if (schema.anyOf) return generateAnyOf(schema, alias);
1118
+ if (schema.allOf) return generateAllOf(schema, alias);
1119
+ if (schema.type === "string") return generateString(schema, alias);
1120
+ if (schema.type === "number") return generateNumber(schema, alias);
1121
+ if (schema.type === "boolean") return generateBoolean(schema, alias);
1122
+ if (schema.type === "null") return generateNull(schema, alias);
1123
+ if (schema.type === "integer") return generateInteger(schema, alias);
1124
+ return "unknown";
1125
+ }
1126
+ function generateMixed(schema, alias) {
1127
+ if (Array.isArray(schema.type)) {
1128
+ schema.type.map((type) => ({ ...schema, type })).map((schema2) => generateSchema(schema2, alias)).join(" | ");
1129
+ }
1130
+ return "unknown";
1131
+ }
1132
+ function generateReference(schema, alias) {
1133
+ if (!schema.$ref || !schema.$ref.startsWith("#")) return `unknown /* ${schema.$ref.replace("*/", "*\\/")} */`;
1134
+ const parts = schema.$ref.split("/");
1135
+ return alias(parts[parts.length - 1]) || "unknown";
1136
+ }
1137
+ function generateArray(schema, alias) {
1138
+ if (schema.items && Array.isArray(schema.items)) {
1139
+ const items = schema.items.map((s) => generateSchema(s, alias)).join(", ");
1140
+ return `[${items}]`;
1141
+ }
1142
+ if (schema.items && typeof schema.items === "object") {
1143
+ return `${generateSchema(schema.items, alias)}[]`;
1144
+ }
1145
+ return "any[]";
1146
+ }
1147
+ function indent(space, text) {
1148
+ const indentation = " ".repeat(space);
1149
+ return text.split("\n").map((line) => `${indentation}${line}`).join("\n");
1150
+ }
1151
+ function generateObject(schema, alias) {
1152
+ if (!schema.properties || !Object.keys(schema.properties).length) {
1153
+ return "object";
1154
+ }
1155
+ const $properties = Object.entries(schema.properties || {}).map(([propertyName, propertySchema]) => {
1156
+ let $comment = generateComment(propertySchema);
1157
+ if ($comment) $comment += "\n";
1158
+ const $key = `"${propertyName}"${schema.required?.includes(propertyName) ? "" : "?"}`;
1159
+ const $value = generateSchema(propertySchema, alias);
1160
+ return indent(2, `${$comment}${$key}: ${$value}`);
1161
+ });
1162
+ if (schema.additionalProperties) {
1163
+ const $value = schema.additionalProperties === true ? "any" : generateSchema(schema.additionalProperties, alias);
1164
+ $properties.push(indent(2, `[key: string]: ${$value}`));
1165
+ }
1166
+ return [
1167
+ "{",
1168
+ ...$properties,
1169
+ "}"
1170
+ ].join("\n");
1171
+ }
1172
+ function generateOneOf(schema, alias) {
1173
+ if (!schema.oneOf) return "unknown";
1174
+ return schema.oneOf.map((s) => generateSchema(s, alias)).join(" | ");
1175
+ }
1176
+ function generateAnyOf(schema, alias) {
1177
+ if (!schema.anyOf) return "unknown";
1178
+ return schema.anyOf.map((s) => generateSchema(s, alias)).join(" | ");
1179
+ }
1180
+ function generateAllOf(schema, alias) {
1181
+ if (!schema.allOf) return "unknown";
1182
+ return schema.allOf.map((s) => generateSchema(s, alias)).join(" & ");
1183
+ }
1184
+ function generateEnum(schema, alias) {
1185
+ if (!schema.enum) return "unknown";
1186
+ return schema.enum.map((v) => JSON.stringify(v)).join(" | ");
1187
+ }
1188
+ function generateString(schema, alias) {
1189
+ if (schema.contentMediaType === "application/octet-stream") return "Blob | Buffer";
1190
+ if (schema.format === "binary") return "Blob | Buffer";
1191
+ return "string";
1192
+ }
1193
+ function generateNumber(schema, alias) {
1194
+ return "number";
1195
+ }
1196
+ function generateBoolean(schema, alias) {
1197
+ return "boolean";
1198
+ }
1199
+ function generateNull(schema, alias) {
1200
+ return "null";
1201
+ }
1202
+ function generateInteger(schema, alias) {
1203
+ return "number";
1204
+ }
1205
+
1206
+ // src/renderer/json-schema/index.ts
1207
+ async function jsonSchemaRenderer(schemaDefinition) {
1208
+ let $comment = generateComment(schemaDefinition.schema);
1209
+ if ($comment) $comment += "\n";
1210
+ if (typeof schemaDefinition.schema === "boolean") {
1211
+ return `${$comment}type ${schemaDefinition.name} = unknown`;
1212
+ }
1213
+ if (JsonSchemaUtils.isNonArray(schemaDefinition.schema) && schemaDefinition.schema.type === "object") {
1214
+ return `${$comment}export interface ${schemaDefinition.name} ${generateSchema(schemaDefinition.schema)}`;
1215
+ }
1216
+ return `${$comment}export type ${schemaDefinition.name} = ${generateSchema(schemaDefinition.schema)}`;
1217
+ }
1218
+
1219
+ // src/tasks/utils/artifact.ts
1220
+ var path8 = __toESM(require("path"), 1);
1221
+ var changeCase = __toESM(require("change-case"), 1);
1222
+
1223
+ // src/tasks/utils/dependency.ts
1224
+ var path7 = __toESM(require("path"), 1);
1225
+
1226
+ // src/tasks/utils/to-comment.ts
1227
+ function toComment(msg) {
1228
+ if (!msg) return "";
1229
+ return msg.split("\n").map((str) => `// ${str}`).join("\n");
1230
+ }
1231
+
1232
+ // src/tasks/utils/dependency.ts
1233
+ var DependencyIdentifier = class {
1234
+ constructor(name, alias) {
1235
+ this.name = name;
1236
+ this.alias = alias;
1237
+ }
1238
+ toCode() {
1239
+ if (this.alias) {
1240
+ return `${this.name} as ${this.alias}`;
1241
+ }
1242
+ return this.name;
1243
+ }
1244
+ };
1245
+ var Dependency = class {
1246
+ source;
1247
+ identifiers;
1248
+ export;
1249
+ belongTo;
1250
+ constructor(source, identifiers, belongTo, options) {
1251
+ this.source = source;
1252
+ this.identifiers = identifiers.map((i) => typeof i === "string" ? new DependencyIdentifier(i) : i);
1253
+ this.export = !!options?.export;
1254
+ this.belongTo = belongTo;
1255
+ }
1256
+ get realSource() {
1257
+ if (typeof this.source === "string") {
1258
+ if (this.source.startsWith(".")) return path7.relative(this.belongTo.filepath, this.source);
1259
+ return this.source;
1260
+ }
1261
+ return this.source.relativeTo(this.belongTo.dirname);
1262
+ }
1263
+ toCode(options) {
1264
+ const { esm } = options;
1265
+ try {
1266
+ let fullpath = this.realSource;
1267
+ if (fullpath.startsWith(".") && fullpath.endsWith(".ts")) {
1268
+ if (esm) {
1269
+ fullpath = fullpath.replace(/\.ts$/, ".js");
1270
+ } else {
1271
+ fullpath = fullpath.replace(/\.ts$/, "");
1272
+ }
1273
+ }
1274
+ if (this.identifiers.length > 0) {
1275
+ const $identifiers = this.identifiers.map((i) => i.toCode()).join(", ");
1276
+ return `${this.export ? "export" : "import"} { ${$identifiers} } from '${fullpath}'`;
1277
+ }
1278
+ if (this.export) {
1279
+ return `export * from '${fullpath}'`;
1280
+ }
1281
+ return `import '${fullpath}'`;
1282
+ } catch (err) {
1283
+ return toComment(String(err));
1284
+ }
1285
+ }
1286
+ };
1287
+
1288
+ // src/tasks/utils/artifact.ts
1289
+ var HeaderComment = [
1290
+ "// Code generated by keq-cli. DO NOT EDIT.",
1291
+ "// Code generated by keq-cli. DO NOT EDIT.",
1292
+ "// Code generated by keq-cli. DO NOT EDIT.",
1293
+ "",
1294
+ ""
1295
+ ].join("\n");
1296
+ var Artifact = class {
1297
+ id;
1298
+ filepath;
1299
+ dependencies = [];
1300
+ warns = [];
1301
+ content;
1302
+ extensionName;
1303
+ constructor(options) {
1304
+ this.id = options.id;
1305
+ this.filepath = options.filepath;
1306
+ this.extensionName = options.extensionName || path8.extname(options.filepath);
1307
+ this.content = options.content;
1308
+ if (options.dependencies) this.dependencies = options.dependencies;
1309
+ }
1310
+ get dirname() {
1311
+ return path8.dirname(this.filepath);
1312
+ }
1313
+ changeFileNameCase(style) {
1314
+ this.filepath = this.filepath.split("/").map((part, index, arr) => {
1315
+ if (part === "." || part === "..") return part;
1316
+ if (index !== arr.length - 1) {
1317
+ return `${changeCase[style](part)}`;
1318
+ }
1319
+ const baesname = path8.basename(part, this.extensionName);
1320
+ return `${changeCase[style](baesname)}${this.extensionName}`;
1321
+ }).join("/");
1322
+ return this;
1323
+ }
1324
+ relativeTo(filepath) {
1325
+ const relativePath = path8.relative(filepath, this.filepath);
1326
+ return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
1327
+ }
1328
+ addDependence(source, identifiers, options) {
1329
+ const dependence = new Dependency(
1330
+ source,
1331
+ identifiers,
1332
+ this,
1333
+ options
1334
+ );
1335
+ this.dependencies.push(dependence);
1336
+ return dependence;
1337
+ }
1338
+ addWarn(message) {
1339
+ this.warns.push(message);
1340
+ }
1341
+ toCode(options) {
1342
+ let $dependencies = this.dependencies.map((dependency) => dependency.toCode(options)).filter((line) => line.trim() !== "").join("\n");
1343
+ if ($dependencies) {
1344
+ $dependencies += "\n\n";
1345
+ }
1346
+ let $warns = "";
1347
+ if (this.warns.length) {
1348
+ $warns = toComment([
1349
+ "!!! Here is some Problems !!!",
1350
+ "",
1351
+ this.warns
1352
+ ].join("\n"));
1353
+ $warns += "\n\n";
1354
+ }
1355
+ return `${HeaderComment}${$warns}${$dependencies}${this.content}`;
1356
+ }
1357
+ };
1358
+
1359
+ // src/tasks/compile/utils/compile-schema-definition.ts
1360
+ function genSchemaDefinitionFilepath(schemaDefinition) {
1361
+ const filename = `${schemaDefinition.name}.schema.ts`;
1362
+ return [
1363
+ ".",
1364
+ schemaDefinition.module.name,
1365
+ "components",
1366
+ "schemas",
1367
+ filename
1368
+ ].join("/");
1369
+ }
1370
+ function genEntrypointFilepath(moduleName) {
1371
+ return [
1372
+ ".",
1373
+ moduleName,
1374
+ "components",
1375
+ "schemas",
1376
+ "index.ts"
1377
+ ].join("/");
1378
+ }
1379
+ var isArtifactCompiledBy = function(schemaDefinition) {
1380
+ return (artifact) => artifact.id === genSchemaDefinitionFilepath(schemaDefinition);
1381
+ };
1382
+ async function compileSchemaDefinition(options) {
1383
+ const { schemaDefinitions } = options;
1384
+ const artifacts = await Promise.all(
1385
+ schemaDefinitions.map(async (schemaDefinition) => {
1386
+ const content = await jsonSchemaRenderer(schemaDefinition);
1387
+ const filepath = genSchemaDefinitionFilepath(schemaDefinition);
1388
+ return new Artifact({
1389
+ id: filepath,
1390
+ filepath,
1391
+ content,
1392
+ extensionName: ".schema.ts"
1393
+ });
1394
+ })
1395
+ );
1396
+ for (const schemaDefinition of schemaDefinitions) {
1397
+ const artifact = artifacts.find(isArtifactCompiledBy(schemaDefinition));
1398
+ if (!artifact) continue;
1399
+ const dependentSchemaDefinitions = schemaDefinition.getDependencies();
1400
+ for (const dependentSchemaDefinition of dependentSchemaDefinitions) {
1401
+ const dependentArtifact = artifacts.find(isArtifactCompiledBy(dependentSchemaDefinition));
1402
+ if (!dependentArtifact) {
1403
+ artifact.addWarn(`Cannot find dependent $ref: ${dependentSchemaDefinition.id}`);
1404
+ continue;
1405
+ }
1406
+ artifact.addDependence(dependentArtifact, [dependentSchemaDefinition.name]);
1407
+ }
1408
+ }
1409
+ const schemaDefinitionsGroupByModuleName = R12.groupBy(
1410
+ (schemaDefinition) => schemaDefinition.module.name,
1411
+ schemaDefinitions
1412
+ );
1413
+ const entrypointArtifacts = Object.entries(schemaDefinitionsGroupByModuleName).map(([moduleName, schemaDefinitions2]) => {
1414
+ const filepath = genEntrypointFilepath(moduleName);
1415
+ const artifact = new Artifact({
1416
+ id: filepath,
1417
+ filepath,
1418
+ content: ""
1419
+ });
1420
+ for (const schemaDefinition of schemaDefinitions2 || []) {
1421
+ const dependentArtifact = artifacts.find(isArtifactCompiledBy(schemaDefinition));
1422
+ if (!dependentArtifact) {
1423
+ artifact.addWarn(`Cannot find dependent $ref: ${schemaDefinition.id}`);
1424
+ continue;
1425
+ }
1426
+ artifact.addDependence(dependentArtifact, [], { export: true });
1427
+ }
1428
+ return artifact;
1429
+ });
1430
+ return [...artifacts, ...entrypointArtifacts];
1431
+ }
1432
+
1433
+ // src/tasks/compile/utils/compile-operation-definition.ts
1434
+ var R15 = __toESM(require("ramda"), 1);
1435
+
1436
+ // src/renderer/operation-type/index.ts
1437
+ var R13 = __toESM(require("ramda"), 1);
1438
+ var changeCase2 = __toESM(require("change-case"), 1);
1439
+ function typeNameFactory(operationDefinition) {
1440
+ const pascalCaseOperationId = changeCase2.pascalCase(operationDefinition.operationId);
1441
+ return (name) => `${pascalCaseOperationId}${name}`;
1442
+ }
1443
+ async function operationTypeRenderer(operationDefinition, alias = R13.identity) {
1444
+ const { operation } = operationDefinition;
1445
+ if (!operation.responses) return "";
1446
+ const typeName = typeNameFactory(operationDefinition);
1447
+ const $responses = Object.entries(operation.responses).map(([statusCode, response]) => {
1448
+ if (!JsonSchemaUtils.isRef(response)) {
1449
+ const $value = Object.values(response.content || {}).map((mediaTypeObject) => mediaTypeObject.schema).filter((schema) => !!schema).map((schema) => generateSchema(schema, alias)).join(" | ");
1450
+ return indent(2, `${statusCode}: ${$value || "void"}`);
1451
+ }
1452
+ }).join("\n");
1453
+ let $requestBody = `export type ${typeName("RequestBody")} = {}`;
1454
+ if (operation.requestBody && !JsonSchemaUtils.isRef(operation.requestBody)) {
1455
+ const $value = Object.entries(operation.requestBody.content || {}).map(([mediaType, mediaTypeObject]) => [mediaType, mediaTypeObject.schema]).filter(([, schema]) => !!schema).map(([mediaType, schema]) => {
1456
+ if (mediaType === "multipart/form-data") {
1457
+ return `FormData | ${generateSchema(schema, alias)}`;
1458
+ } else if (mediaType === "application/x-www-form-urlencoded") {
1459
+ return `URLSearchParams | ${generateSchema(schema, alias)}`;
1460
+ }
1461
+ return generateSchema(schema, alias);
1462
+ }).join(" | ");
1463
+ $requestBody = `export type ${typeName("RequestBody")} = ${$value || "unknown"}`;
1464
+ }
1465
+ return [
1466
+ `export interface ${typeName("ResponseBodies")} {`,
1467
+ $responses,
1468
+ "}",
1469
+ "",
1470
+ generateParameters(`${typeName("RequestQuery")}`, operation.parameters?.filter((p) => !JsonSchemaUtils.isRef(p) && p.in === "query") || [], alias),
1471
+ "",
1472
+ generateParameters(`${typeName("RouteParameters")}`, operation.parameters?.filter((p) => !JsonSchemaUtils.isRef(p) && p.in === "path") || [], alias),
1473
+ "",
1474
+ generateParameters(`${typeName("RequestHeaders")}`, operation.parameters?.filter((p) => !JsonSchemaUtils.isRef(p) && p.in === "header") || [], alias),
1475
+ "",
1476
+ $requestBody,
1477
+ "",
1478
+ `export type ${typeName("RequestParameters")} = ${typeName("RequestQuery")} & ${typeName("RouteParameters")} & ${typeName("RequestHeaders")} & ${typeName("RequestBody")}`,
1479
+ "",
1480
+ `export interface Operation<STATUS extends keyof ${typeName("ResponseBodies")}> extends KeqOperation {`,
1481
+ ` requestParams: ${typeName("RouteParameters")} & { [key: string]: KeqParamValue }`,
1482
+ ` requestQuery: ${typeName("RequestQuery")} & { [key: string]: KeqQueryValue }`,
1483
+ ` requestHeaders: ${typeName("RequestHeaders")} & { [key: string]: string | number }`,
1484
+ ` requestBody: ${typeName("RequestBody")}`,
1485
+ ` responseBody: ${typeName("ResponseBodies")}[STATUS]`,
1486
+ "}"
1487
+ ].join("\n");
1488
+ }
1489
+ function generateParameters(name, parameters, alias) {
1490
+ if (parameters.length === 0) {
1491
+ return `export type ${name} = {}`;
1492
+ }
1493
+ const $parameters = parameters.map((parameter) => {
1494
+ const parameterName = `"${parameter.name}"`;
1495
+ const $key = parameter.required ? parameterName : `${parameterName}?`;
1496
+ const $value = generateSchema(parameter.schema || { type: "any" }, alias);
1497
+ return indent(2, `${$key}: ${$value}`);
1498
+ }).join("\n");
1499
+ return [
1500
+ `export type ${name} = {`,
1501
+ $parameters,
1502
+ "}"
1503
+ ].filter(Boolean).join("\n");
1504
+ }
1505
+
1506
+ // src/renderer/operation-request/index.ts
1507
+ var R14 = __toESM(require("ramda"), 1);
1508
+ function errorToComment(err, mediaType) {
1509
+ const $err = String(err).split("\n").map(((line) => ` * ${line}`)).join("\n");
1510
+ return [
1511
+ "/**",
1512
+ ` * Unable to dereference schema for media type ${mediaType}`,
1513
+ $err,
1514
+ " */"
1515
+ ].join("\n");
1516
+ }
1517
+ async function operationRequestRenderer(operationDefinition, options) {
1518
+ const { operation, operationId, method, pathname } = operationDefinition;
1519
+ const { qs } = options;
1520
+ if (!operation.responses) return "";
1521
+ const typeName = typeNameFactory(operationDefinition);
1522
+ const moduleName = operationDefinition.module.name;
1523
+ const parameters = operation.parameters?.filter((p) => !JsonSchemaUtils.isRef(p)) || [];
1524
+ const queryParameters = parameters.filter((p) => p.in === "query");
1525
+ const headersParameters = parameters.filter((p) => p.in === "header");
1526
+ const pathParameters = parameters.filter((p) => p.in === "path");
1527
+ const $queryParameters = queryParameters.map((p) => {
1528
+ const option = qs(p);
1529
+ const $option = !option || R14.isEmpty(option) ? "" : `, ${JSON.stringify(option)}`;
1530
+ return ` if (args && ${JSON.stringify(p.name)} in args) req.query(${JSON.stringify(p.name)}, args[${JSON.stringify(p.name)}]${$option})`;
1531
+ }).concat("").join("\n");
1532
+ const $headerParameters = headersParameters.map((p) => ` if (args && ${JSON.stringify(p.name)} in args) req.header(${JSON.stringify(p.name)}, args[${JSON.stringify(p.name)}])`).concat("").join("\n");
1533
+ const $pathParameters = pathParameters.map((p) => ` if (args && ${JSON.stringify(p.name)} in args) req.params(${JSON.stringify(p.name)}, args[${JSON.stringify(p.name)}])`).concat("").join("\n");
1534
+ const requestBodyContent = operation.requestBody?.content || {};
1535
+ const $requestBody = Object.entries(requestBodyContent).map(([mediaType, mediaTypeObject]) => {
1536
+ if (!mediaTypeObject.schema) return;
1537
+ try {
1538
+ const schema = JsonSchemaUtils.isRef(mediaTypeObject.schema) ? SwaggerUtils.dereferenceDeep(mediaTypeObject.schema.$ref, operationDefinition.document.swagger) : mediaTypeObject.schema;
1539
+ if (schema.type !== "object") return;
1540
+ const properties = schema.properties || {};
1541
+ return Object.entries(properties).map(([propertyName, propertySchema]) => {
1542
+ const $propertyName = JSON.stringify(propertyName);
1543
+ if (mediaType === "application/json") {
1544
+ return ` if (args && ${$propertyName} in args) req.send({ ${$propertyName}: args[${$propertyName}] })`;
1545
+ } else if (mediaType === "multipart/form-data") {
1546
+ try {
1547
+ const schema2 = JsonSchemaUtils.isRef(propertySchema) ? SwaggerUtils.dereferenceDeep(propertySchema.$ref, operationDefinition.document.swagger) : propertySchema;
1548
+ if (schema2.type === "string" && schema2.format === "binary" || schema2.contentMediaType === "application/octet-stream") {
1549
+ return ` if (args && ${$propertyName} in args && args[${$propertyName}]) req.attach(${$propertyName}, args[${$propertyName}])`;
1550
+ }
1551
+ return ` if (args && ${$propertyName} in args && args[${$propertyName}] !== undefined) req.field(${$propertyName}, args[${$propertyName}])`;
1552
+ } catch (err) {
1553
+ return indent(2, errorToComment(err, mediaType));
1554
+ }
1555
+ } else {
1556
+ throw new Error(`Unsupported media type: ${mediaType}`);
1557
+ }
1558
+ }).join("\n");
1559
+ } catch (err) {
1560
+ return indent(2, errorToComment(err, mediaType));
1561
+ }
1562
+ }).filter(R14.isNotNil).join("\n");
1563
+ return [
1564
+ `const moduleName = "${moduleName}"`,
1565
+ `const method = "${method}"`,
1566
+ `const pathname = "${pathname}"`,
1567
+ "",
1568
+ `export function ${operationId}<STATUS extends keyof ${typeName("ResponseBodies")}>(args?: ${typeName("RequestParameters")}): Keq<Operation<STATUS>> {`,
1569
+ ` const req = request.post<${typeName("ResponseBodies")}[STATUS]>("${pathname}")`,
1570
+ " .option('module', { name: moduleName, pathname, method })",
1571
+ "",
1572
+ $queryParameters || void 0,
1573
+ $headerParameters || void 0,
1574
+ $pathParameters || void 0,
1575
+ $requestBody ? `${$requestBody}
1576
+ ` : void 0,
1577
+ " return req",
1578
+ "}",
1579
+ "",
1580
+ `${operationId}.pathname = pathname`,
1581
+ `${operationId}.method = method`
1582
+ ].filter(R14.isNotNil).join("\n");
1583
+ }
1584
+
1585
+ // src/tasks/compile/utils/compile-operation-definition.ts
1586
+ function genOperationTypeFilepath(operationDefinition) {
1587
+ const filename = `${operationDefinition.operationId}.type.ts`;
1588
+ return [
1589
+ ".",
1590
+ operationDefinition.module.name,
1591
+ "types",
1592
+ filename
1593
+ ].join("/");
1594
+ }
1595
+ function genOperationRequestFilepath(operationDefinition) {
1596
+ const filename = `${operationDefinition.operationId}.request.ts`;
1597
+ return [
1598
+ ".",
1599
+ operationDefinition.module.name,
1600
+ "operations",
1601
+ filename
1602
+ ].join("/");
1603
+ }
1604
+ function genEntrypointFilepath2(moduleName) {
1605
+ return [
1606
+ ".",
1607
+ moduleName,
1608
+ "operations",
1609
+ "index.ts"
1610
+ ].join("/");
1611
+ }
1612
+ async function compileOperationDefinition(options) {
1613
+ const { rc, requestArtifact, schemaArtifacts, operationDefinitions } = options;
1614
+ const alias = (name) => `${name}Schema`;
1615
+ const qs = (parameter) => {
1616
+ if (typeof rc.qs === "function") {
1617
+ return rc.qs(parameter);
1618
+ } else if (typeof rc.qs === "object") {
1619
+ return rc.qs;
1620
+ }
1621
+ const style = parameter.style || "form";
1622
+ const explode = parameter.explode ?? true;
1623
+ if (style === "deepObject") {
1624
+ return { arrayFormat: "brackets" };
1625
+ } else if (explode) {
1626
+ return { arrayFormat: "repeat" };
1627
+ } else {
1628
+ if (style === "form") {
1629
+ return { arrayFormat: "comma" };
1630
+ } else if (style === "spaceDelimited") {
1631
+ return { arrayFormat: "space" };
1632
+ } else if (style === "pipeDelimited") {
1633
+ return { arrayFormat: "pipe" };
1634
+ }
1635
+ }
1636
+ return {};
1637
+ };
1638
+ async function createTypeArtifact(operationDefinition) {
1639
+ const content = await operationTypeRenderer(operationDefinition, alias);
1640
+ const filepath = genOperationTypeFilepath(operationDefinition);
1641
+ const typeArtifact = new Artifact({
1642
+ id: filepath,
1643
+ filepath,
1644
+ content,
1645
+ extensionName: ".type.ts"
1646
+ });
1647
+ typeArtifact.addDependence("keq", ["KeqOperation", "KeqQueryValue", "KeqParamValue"]);
1648
+ const dependentSchemaDefinitions = operationDefinition.getDependencies();
1649
+ for (const dependentSchemaDefinition of dependentSchemaDefinitions) {
1650
+ const dependentArtifact = schemaArtifacts.find(isArtifactCompiledBy(dependentSchemaDefinition));
1651
+ if (!dependentArtifact) {
1652
+ typeArtifact.addWarn(`Cannot find dependent $ref: ${dependentSchemaDefinition.id}`);
1653
+ continue;
1654
+ }
1655
+ typeArtifact.addDependence(dependentArtifact, [
1656
+ new DependencyIdentifier(dependentSchemaDefinition.name, alias(dependentSchemaDefinition.name))
1657
+ ]);
1658
+ }
1659
+ return typeArtifact;
1660
+ }
1661
+ async function createRequestArtifact(operationDefinition, typeArtifact) {
1662
+ const typeName = typeNameFactory(operationDefinition);
1663
+ const content = await operationRequestRenderer(operationDefinition, { qs });
1664
+ const filepath = genOperationRequestFilepath(operationDefinition);
1665
+ const artifact = new Artifact({
1666
+ id: filepath,
1667
+ filepath,
1668
+ content,
1669
+ extensionName: ".request.ts"
1670
+ });
1671
+ artifact.addDependence("keq", ["Keq"]);
1672
+ artifact.addDependence(requestArtifact, ["request"]);
1673
+ artifact.addDependence(
1674
+ typeArtifact,
1675
+ [
1676
+ "Operation",
1677
+ typeName("ResponseBodies"),
1678
+ typeName("RequestParameters")
1679
+ ]
1680
+ );
1681
+ artifact.addDependence(
1682
+ typeArtifact,
1683
+ [
1684
+ `${typeName("RequestQuery")}`,
1685
+ `${typeName("RequestHeaders")}`,
1686
+ `${typeName("RequestBody")}`
1687
+ ],
1688
+ { export: true }
1689
+ );
1690
+ return artifact;
1691
+ }
1692
+ const artifacts = R15.unnest(
1693
+ await Promise.all(
1694
+ operationDefinitions.map(async (operationDefinition) => {
1695
+ const typeArtifact = await createTypeArtifact(operationDefinition);
1696
+ const operationArtifact = await createRequestArtifact(operationDefinition, typeArtifact);
1697
+ return [typeArtifact, operationArtifact];
1698
+ })
1699
+ )
1700
+ );
1701
+ const operationDefinitionsGroupByModuleName = R15.groupBy(
1702
+ (operationDefinition) => operationDefinition.module.name,
1703
+ operationDefinitions
1704
+ );
1705
+ const entrypointArtifacts = Object.entries(operationDefinitionsGroupByModuleName).map(([moduleName, operationDefinitions2]) => {
1706
+ const filepath = genEntrypointFilepath2(moduleName);
1707
+ const artifact = new Artifact({
1708
+ id: filepath,
1709
+ filepath,
1710
+ content: ""
1711
+ });
1712
+ for (const operationDefinition of operationDefinitions2 || []) {
1713
+ const dependentArtifact = artifacts.find((artifact2) => artifact2.filepath === genOperationRequestFilepath(operationDefinition));
1714
+ if (!dependentArtifact) {
1715
+ artifact.addWarn(`Cannot find operation: operation = ${operationDefinition.operationId}, pathname = ${operationDefinition.pathname}, method = ${operationDefinition.method}`);
1716
+ continue;
1717
+ }
1718
+ artifact.addDependence(dependentArtifact, [], { export: true });
1719
+ }
1720
+ return artifact;
1721
+ });
1722
+ return [...artifacts, ...entrypointArtifacts];
1723
+ }
1724
+
1725
+ // src/renderer/request/index.ts
1726
+ async function requestRenderer() {
1727
+ return [
1728
+ "import { KeqRequest } from 'keq'",
1729
+ "export const request = new KeqRequest()"
1730
+ ].join("\n");
1731
+ }
1732
+
1733
+ // src/tasks/compile/index.ts
1734
+ function createCompileTask(options) {
1735
+ return {
1736
+ title: "Compile",
1737
+ enabled: options?.enabled,
1738
+ skip: options?.skip,
1739
+ task: async (context, task) => {
1740
+ if (!context.setup) throw new Error("Please run setup task first.");
1741
+ if (!context.shaken) throw new Error("Please run shaking task first.");
1742
+ const rc = context.setup.rc;
1743
+ const matcher = context.setup.matcher;
1744
+ const documents = context.shaken.documents.filter((document) => !matcher.isModuleIgnored(document.module));
1745
+ const requestArtifact = new Artifact({
1746
+ id: "request",
1747
+ filepath: "request",
1748
+ content: await requestRenderer(),
1749
+ extensionName: ".ts"
1750
+ });
1751
+ const schemaDefinitions = documents.flatMap((document) => document.schemas);
1752
+ const operationDefinitions = documents.flatMap((document) => document.operations);
1753
+ const schemaArtifacts = await compileSchemaDefinition({ schemaDefinitions });
1754
+ const operationArtifacts = await compileOperationDefinition({ rc, operationDefinitions, schemaArtifacts, requestArtifact });
1755
+ const artifacts = [requestArtifact, ...schemaArtifacts, ...operationArtifacts];
1756
+ context.compiled = {
1757
+ artifacts
1758
+ };
1759
+ }
1760
+ };
1761
+ }
1762
+
1763
+ // src/tasks/interactive/utils/select-operation-definitions.ts
1764
+ var import_inquirer_select_pro = require("inquirer-select-pro");
1765
+ var import_prompt_adapter_inquirer = require("@listr2/prompt-adapter-inquirer");
1766
+ async function selectOperationDefinitions(task, operationDefinitions) {
1767
+ const selectedOperationDefinitions = await task.prompt(import_prompt_adapter_inquirer.ListrInquirerPromptAdapter).run(
1768
+ import_inquirer_select_pro.select,
1769
+ {
1770
+ message: "Select Pathname",
1771
+ defaultValue: [],
1772
+ options: (input) => {
1773
+ const items = operationDefinitions.map((op) => ({ name: `${op.module.name} ${op.method.toUpperCase()} ${op.pathname}`, value: op }));
1774
+ if (!input) return items;
1775
+ const keys2 = input.trim().toLowerCase().split(/\s+/);
1776
+ return items.filter((i) => {
1777
+ const name = i.name.toLowerCase();
1778
+ return keys2.every((q) => name.includes(q));
1779
+ });
1780
+ }
1781
+ }
1782
+ );
1783
+ return selectedOperationDefinitions;
1784
+ }
1785
+
1786
+ // src/tasks/interactive/index.ts
1787
+ function createInteractiveTask(options) {
1788
+ return {
1789
+ enabled: options?.enabled,
1790
+ skip: options?.skip,
1791
+ task: async (context, task) => {
1792
+ if (!context.setup) throw new Error("Please run setup task first.");
1793
+ if (!context.validated) throw new Error("Please run validate task first.");
1794
+ const matcher = context.setup.matcher;
1795
+ const documents = context.validated.documents;
1796
+ const operationDefinitions = documents.flatMap((document) => document.operations);
1797
+ const selectedOperationDefinitions = await selectOperationDefinitions(task, operationDefinitions);
1798
+ if (options.override) {
1799
+ matcher.append({
1800
+ persist: false,
1801
+ ignore: true,
1802
+ moduleName: "*",
1803
+ operationMethod: "*",
1804
+ operationPathname: "*"
1805
+ });
1806
+ }
1807
+ for (const op of selectedOperationDefinitions) {
1808
+ matcher.append({
1809
+ persist: true,
1810
+ ignore: options.mode === "add",
1811
+ moduleName: op.module.name,
1812
+ operationMethod: op.method,
1813
+ operationPathname: op.pathname
1814
+ });
1815
+ }
1816
+ }
1817
+ };
1818
+ }
1819
+
1820
+ // src/tasks/index.ts
1821
+ async function build(options) {
1822
+ const tasks = new import_listr22.Listr(
1823
+ [
1824
+ createSetupTask(options),
1825
+ createDownloadTask({ skipIgnoredModules: !options.interactive }),
1826
+ createValidateTask(),
1827
+ createInteractiveTask({ mode: "except", override: true, enabled: !!options.interactive }),
1828
+ createShakingTask({ skipIgnoredModules: true, skipEmptyDocuments: true }),
1829
+ createCompileTask(),
1830
+ createPersistTask({ persistIgnore: false })
1831
+ ],
1832
+ {
1833
+ concurrent: false,
1834
+ renderer: "default",
1835
+ rendererOptions: {
1836
+ suffixSkips: true,
1837
+ collapseSubtasks: false,
1838
+ collapseErrors: false
1839
+ }
1840
+ }
1841
+ );
1842
+ await tasks.run({});
1843
+ }
1844
+
1845
+ // src/define-keq-config.ts
1846
+ function defineKeqConfig(config) {
1847
+ return config;
1848
+ }
1849
+ // Annotate the CommonJS export names for ESM import in node:
1850
+ 0 && (module.exports = {
1851
+ FileNamingStyle,
1852
+ build,
1853
+ defineKeqConfig
1854
+ });
1855
+ //# sourceMappingURL=index.cjs.map