@keq-request/cli 5.0.0-alpha.10 → 5.0.0-alpha.11

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 (83) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/cli.cjs +673 -222
  3. package/dist/cli.cjs.map +1 -1
  4. package/dist/cli.js +673 -222
  5. package/dist/cli.js.map +1 -1
  6. package/dist/compiler/compiler.d.ts +29 -0
  7. package/dist/compiler/compiler.d.ts.map +1 -0
  8. package/dist/compiler/index.d.ts +2 -0
  9. package/dist/compiler/index.d.ts.map +1 -0
  10. package/dist/compiler/intercepter/perfect-error-message.d.ts +3 -0
  11. package/dist/compiler/intercepter/perfect-error-message.d.ts.map +1 -0
  12. package/dist/compiler/intercepter/print-information.d.ts +5 -0
  13. package/dist/compiler/intercepter/print-information.d.ts.map +1 -0
  14. package/dist/index.cjs +620 -154
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.ts +9 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +609 -150
  19. package/dist/index.js.map +1 -1
  20. package/dist/plugins/body-fallback/index.d.ts +6 -0
  21. package/dist/plugins/body-fallback/index.d.ts.map +1 -0
  22. package/dist/plugins/eslint/index.d.ts +15 -0
  23. package/dist/plugins/eslint/index.d.ts.map +1 -0
  24. package/dist/plugins/index.d.ts +4 -0
  25. package/dist/plugins/index.d.ts.map +1 -0
  26. package/dist/plugins/prettier/index.d.ts +6 -0
  27. package/dist/plugins/prettier/index.d.ts.map +1 -0
  28. package/dist/plugins.cjs +159 -0
  29. package/dist/plugins.cjs.map +1 -0
  30. package/dist/plugins.js +120 -0
  31. package/dist/plugins.js.map +1 -0
  32. package/dist/renderer/json-schema/index.d.ts.map +1 -1
  33. package/dist/renderer/operation-request/index.d.ts.map +1 -1
  34. package/dist/renderer/operation-type/index.d.ts +2 -1
  35. package/dist/renderer/operation-type/index.d.ts.map +1 -1
  36. package/dist/renderer/request/index.d.ts.map +1 -1
  37. package/dist/tasks/compile/index.d.ts +3 -5
  38. package/dist/tasks/compile/index.d.ts.map +1 -1
  39. package/dist/tasks/compile/utils/compile-operation-definition.d.ts +5 -2
  40. package/dist/tasks/compile/utils/compile-operation-definition.d.ts.map +1 -1
  41. package/dist/tasks/compile/utils/compile-schema-definition.d.ts +5 -2
  42. package/dist/tasks/compile/utils/compile-schema-definition.d.ts.map +1 -1
  43. package/dist/tasks/download/index.d.ts +3 -3
  44. package/dist/tasks/download/index.d.ts.map +1 -1
  45. package/dist/tasks/index.d.ts +9 -11
  46. package/dist/tasks/index.d.ts.map +1 -1
  47. package/dist/tasks/interactive/index.d.ts +9 -6
  48. package/dist/tasks/interactive/index.d.ts.map +1 -1
  49. package/dist/tasks/persist/index.d.ts +3 -8
  50. package/dist/tasks/persist/index.d.ts.map +1 -1
  51. package/dist/tasks/setup/index.d.ts +7 -1
  52. package/dist/tasks/setup/index.d.ts.map +1 -1
  53. package/dist/tasks/shaking/index.d.ts +4 -5
  54. package/dist/tasks/shaking/index.d.ts.map +1 -1
  55. package/dist/tasks/types/base-task-options.d.ts +6 -0
  56. package/dist/tasks/types/base-task-options.d.ts.map +1 -0
  57. package/dist/tasks/types/file.d.ts +4 -0
  58. package/dist/tasks/types/file.d.ts.map +1 -0
  59. package/dist/tasks/types/index.d.ts +6 -0
  60. package/dist/tasks/types/index.d.ts.map +1 -0
  61. package/dist/tasks/types/task-context.d.ts +4 -0
  62. package/dist/tasks/types/task-context.d.ts.map +1 -1
  63. package/dist/tasks/types/task-wrapper.d.ts +4 -0
  64. package/dist/tasks/types/task-wrapper.d.ts.map +1 -0
  65. package/dist/tasks/utils/anchor.d.ts +20 -0
  66. package/dist/tasks/utils/anchor.d.ts.map +1 -0
  67. package/dist/tasks/utils/artifact.d.ts +2 -0
  68. package/dist/tasks/utils/artifact.d.ts.map +1 -1
  69. package/dist/tasks/utils/index.d.ts +11 -0
  70. package/dist/tasks/utils/index.d.ts.map +1 -0
  71. package/dist/tasks/utils/proxy-task-wrapper.d.ts +3 -0
  72. package/dist/tasks/utils/proxy-task-wrapper.d.ts.map +1 -0
  73. package/dist/tasks/validate/index.d.ts +3 -6
  74. package/dist/tasks/validate/index.d.ts.map +1 -1
  75. package/dist/types/index.d.ts +7 -0
  76. package/dist/types/index.d.ts.map +1 -0
  77. package/dist/types/plugin.d.ts +5 -0
  78. package/dist/types/plugin.d.ts.map +1 -0
  79. package/dist/types/runtime-config.d.ts +4 -1
  80. package/dist/types/runtime-config.d.ts.map +1 -1
  81. package/package.json +20 -4
  82. package/dist/tasks/append-ignore-rule/index.d.ts +0 -10
  83. package/dist/tasks/append-ignore-rule/index.d.ts.map +0 -1
package/dist/cli.cjs CHANGED
@@ -27,7 +27,27 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  var import_semver = __toESM(require("semver"), 1);
28
28
  var import_commander = require("commander");
29
29
 
30
- // src/tasks/index.ts
30
+ // src/constants/supported-methods.ts
31
+ var SupportedMethods = [
32
+ "get",
33
+ "post",
34
+ "put",
35
+ "delete",
36
+ "patch",
37
+ "head",
38
+ "options"
39
+ ];
40
+
41
+ // src/utils/logger.ts
42
+ var import_chalk = __toESM(require("chalk"), 1);
43
+ var logger = {
44
+ log: (str) => console.log(import_chalk.default.green(str)),
45
+ warn: (str) => console.warn(import_chalk.default.yellow(str)),
46
+ error: (str) => console.error(import_chalk.default.red(str))
47
+ };
48
+
49
+ // src/compiler/compiler.ts
50
+ var import_tapable = require("tapable");
31
51
  var import_listr22 = require("listr2");
32
52
 
33
53
  // src/tasks/setup/index.ts
@@ -104,7 +124,8 @@ var RuntimeConfig = import_typebox2.Type.Object({
104
124
  /**
105
125
  * Whether to tolerate wrong swagger structure
106
126
  */
107
- tolerant: import_typebox2.Type.Optional(import_typebox2.Type.Boolean({ default: false }))
127
+ tolerant: import_typebox2.Type.Optional(import_typebox2.Type.Boolean({ default: false })),
128
+ plugins: import_typebox2.Type.Optional(import_typebox2.Type.Array(import_typebox2.Type.Any(), { default: [] }))
108
129
  });
109
130
 
110
131
  // src/utils/ignore-matcher.ts
@@ -255,9 +276,8 @@ function getProjectModuleSystem(pkgInfo) {
255
276
 
256
277
  // src/tasks/setup/index.ts
257
278
  var explore = (0, import_cosmiconfig.cosmiconfig)("keq");
258
- function createSetupTask(options) {
279
+ function main(compiler, options) {
259
280
  return {
260
- title: "Setup",
261
281
  task: async (context, task) => {
262
282
  const result = options?.config ? await explore.load(options.config) : await explore.search();
263
283
  if (!result || "isEmpty" in result && result.isEmpty) {
@@ -282,13 +302,23 @@ function createSetupTask(options) {
282
302
  const moduleSystem = getProjectModuleSystem(packageJsonInfo);
283
303
  rc.esm = moduleSystem === "esm";
284
304
  }
285
- let filter2 = new IgnoreMatcher([]);
305
+ let matcher = new IgnoreMatcher([]);
286
306
  if (result.filepath) {
287
307
  const ignoreFilepath = import_path.default.resolve(import_path.default.dirname(result.filepath), ".keqignore");
288
308
  if (await import_fs_extra2.default.exists(ignoreFilepath)) {
289
- filter2 = await IgnoreMatcher.read(ignoreFilepath);
309
+ matcher = await IgnoreMatcher.read(ignoreFilepath);
290
310
  }
291
311
  }
312
+ const ignoreRules = options.ignore === false ? [] : options.ignore?.rules || [];
313
+ for (const rule of ignoreRules) {
314
+ matcher.append({
315
+ persist: !!rule.persist,
316
+ ignore: rule.ignore,
317
+ moduleName: rule.moduleName,
318
+ operationMethod: rule.operationMethod,
319
+ operationPathname: rule.operationPathname
320
+ });
321
+ }
292
322
  if (options?.modules && options.modules.length) {
293
323
  const notExistModules = options.modules.filter((moduleName) => !(moduleName in rc.modules));
294
324
  if (notExistModules.length) {
@@ -296,7 +326,7 @@ function createSetupTask(options) {
296
326
  }
297
327
  const ignoredModules = R3.difference(R3.keys(rc.modules), options.modules);
298
328
  for (const moduleName of ignoredModules) {
299
- filter2.append({
329
+ matcher.append({
300
330
  persist: false,
301
331
  ignore: true,
302
332
  moduleName,
@@ -305,10 +335,33 @@ function createSetupTask(options) {
305
335
  });
306
336
  }
307
337
  }
308
- context.setup = { rc, matcher: filter2 };
338
+ context.setup = { rc, matcher };
339
+ if (rc.plugins && rc.plugins.length) {
340
+ for (const plugin of rc.plugins) {
341
+ plugin.apply(compiler);
342
+ }
343
+ }
309
344
  }
310
345
  };
311
346
  }
347
+ function createSetupTask(compiler, options) {
348
+ return {
349
+ title: "Setup",
350
+ enabled: options?.enabled,
351
+ skip: options?.skip,
352
+ task: (context, task) => task.newListr(
353
+ [
354
+ main(compiler, options),
355
+ {
356
+ task: (context2, task2) => compiler.hooks.afterSetup.promise(task2)
357
+ }
358
+ ],
359
+ {
360
+ concurrent: false
361
+ }
362
+ )
363
+ };
364
+ }
312
365
 
313
366
  // src/tasks/download/index.ts
314
367
  var import_listr2 = require("listr2");
@@ -334,17 +387,6 @@ var import_openapi_parser = require("@scalar/openapi-parser");
334
387
  // src/tasks/utils/api-document_v3_1.ts
335
388
  var R6 = __toESM(require("ramda"), 1);
336
389
 
337
- // src/constants/supported-methods.ts
338
- var SupportedMethods = [
339
- "get",
340
- "post",
341
- "put",
342
- "delete",
343
- "patch",
344
- "head",
345
- "options"
346
- ];
347
-
348
390
  // src/tasks/utils/operation-definition.ts
349
391
  var R5 = __toESM(require("ramda"), 1);
350
392
 
@@ -512,16 +554,8 @@ var OperationDefinition = class {
512
554
  }
513
555
  };
514
556
 
515
- // src/utils/logger.ts
516
- var import_chalk = __toESM(require("chalk"), 1);
517
- var logger = {
518
- log: (str) => console.log(import_chalk.default.green(str)),
519
- warn: (str) => console.warn(import_chalk.default.yellow(str)),
520
- error: (str) => console.error(import_chalk.default.red(str))
521
- };
522
-
523
557
  // src/tasks/utils/api-document_v3_1.ts
524
- var import_openapi_shaking = __toESM(require("@opendoc/openapi-shaking"), 1);
558
+ var import_openapi_shaking = require("@opendoc/openapi-shaking");
525
559
  var ApiDocumentV3_1 = class _ApiDocumentV3_1 {
526
560
  module;
527
561
  swagger;
@@ -577,7 +611,7 @@ var ApiDocumentV3_1 = class _ApiDocumentV3_1 {
577
611
  });
578
612
  return filter2(operationDefinition);
579
613
  };
580
- const sharkedSwagger = import_openapi_shaking.default.openapiShakingSync(
614
+ const sharkedSwagger = (0, import_openapi_shaking.openapiShakingSync)(
581
615
  this.swagger,
582
616
  isAccepted,
583
617
  { tolerant: true }
@@ -771,8 +805,8 @@ function dereferenceDeep($ref, swagger) {
771
805
  const stack = [$ref];
772
806
  let value;
773
807
  while (true) {
774
- const last = stack[stack.length - 1];
775
- value = dereference(last, swagger);
808
+ const last2 = stack[stack.length - 1];
809
+ value = dereference(last2, swagger);
776
810
  if (JsonSchemaUtils.isRef(value)) {
777
811
  if (!stack.includes(value.$ref)) {
778
812
  stack.push(value.$ref);
@@ -883,11 +917,8 @@ var ApiDocument = class _ApiDocument {
883
917
  };
884
918
 
885
919
  // src/tasks/download/index.ts
886
- function createDownloadTask(options) {
920
+ function main2(compiler, options) {
887
921
  return {
888
- title: "Download",
889
- enabled: options?.enabled,
890
- skip: options?.skip,
891
922
  task: (context, task) => {
892
923
  if (!context.setup) {
893
924
  throw new Error("Please run setup task first.");
@@ -925,13 +956,28 @@ function createDownloadTask(options) {
925
956
  }
926
957
  };
927
958
  }
928
-
929
- // src/tasks/validate/index.ts
930
- function createValidateTask(options) {
959
+ function createDownloadTask(compiler, options) {
931
960
  return {
932
- title: "Validate",
961
+ title: "Download",
933
962
  enabled: options?.enabled,
934
963
  skip: options?.skip,
964
+ task: (_, task) => task.newListr(
965
+ [
966
+ main2(compiler, options),
967
+ {
968
+ task: (context, task2) => compiler.hooks.afterDownload.promise(task2)
969
+ }
970
+ ],
971
+ {
972
+ concurrent: false
973
+ }
974
+ )
975
+ };
976
+ }
977
+
978
+ // src/tasks/validate/index.ts
979
+ function main3() {
980
+ return {
935
981
  task: (context, task) => {
936
982
  if (!context.setup) throw new Error("Please run setup task first.");
937
983
  if (!context.downloaded) throw new Error("Please run download task first.");
@@ -968,13 +1014,28 @@ ${errors?.map((e) => ` - ${e.message}`).join("\n")}`;
968
1014
  }
969
1015
  };
970
1016
  }
971
-
972
- // src/tasks/shaking/index.ts
973
- function createShakingTask(options) {
1017
+ function createValidateTask(compiler, options) {
974
1018
  return {
975
- title: "Shaking",
1019
+ title: "Validate",
976
1020
  enabled: options?.enabled,
977
1021
  skip: options?.skip,
1022
+ task: (context, task) => task.newListr(
1023
+ [
1024
+ main3(),
1025
+ {
1026
+ task: (context2, task2) => compiler.hooks.afterValidate.promise(task2)
1027
+ }
1028
+ ],
1029
+ {
1030
+ concurrent: false
1031
+ }
1032
+ )
1033
+ };
1034
+ }
1035
+
1036
+ // src/tasks/shaking/index.ts
1037
+ function main4(compiler, options) {
1038
+ return {
978
1039
  task: (context, task) => {
979
1040
  if (!context.setup) throw new Error("Please run setup task first.");
980
1041
  if (!context.validated) throw new Error("Please run validate task first.");
@@ -1012,15 +1073,31 @@ function createShakingTask(options) {
1012
1073
  }
1013
1074
  };
1014
1075
  }
1076
+ function createShakingTask(compiler, options) {
1077
+ return {
1078
+ title: "Shaking",
1079
+ enabled: options?.enabled,
1080
+ skip: options?.skip,
1081
+ task: (context, task) => task.newListr(
1082
+ [
1083
+ main4(compiler, options),
1084
+ {
1085
+ task: (context2, task2) => compiler.hooks.afterShaking.promise(task2)
1086
+ }
1087
+ ],
1088
+ {
1089
+ concurrent: false
1090
+ }
1091
+ )
1092
+ };
1093
+ }
1015
1094
 
1016
1095
  // src/tasks/persist/index.ts
1017
1096
  var path6 = __toESM(require("path"), 1);
1018
1097
  var import_fs_extra5 = __toESM(require("fs-extra"), 1);
1019
- function createPersistArtifactTask(options) {
1098
+ function createPersistArtifactTask() {
1020
1099
  return {
1021
1100
  title: "Write files",
1022
- enabled: options?.persistArtifacts,
1023
- skip: options?.skip,
1024
1101
  task: async (context, task) => {
1025
1102
  if (!context.setup) throw new Error("Please run setup task first.");
1026
1103
  if (!context.compiled) throw new Error("Please run compile task first.");
@@ -1031,21 +1108,21 @@ function createPersistArtifactTask(options) {
1031
1108
  }
1032
1109
  const total = artifacts.length;
1033
1110
  let completed = 0;
1034
- await Promise.all(artifacts.map(async (artifact) => {
1111
+ const files = await Promise.all(artifacts.map(async (artifact) => {
1035
1112
  const realpath = `./${path6.join(rc.outdir, artifact.filepath)}`;
1036
1113
  await import_fs_extra5.default.ensureFile(realpath);
1037
1114
  await import_fs_extra5.default.writeFile(realpath, artifact.toCode({ esm: !!rc.esm }));
1038
1115
  completed += 1;
1039
1116
  task.output = `Persisted ${completed}/${total} files`;
1117
+ return { path: path6.resolve(realpath) };
1040
1118
  }));
1119
+ context.persisted = { files };
1041
1120
  }
1042
1121
  };
1043
1122
  }
1044
- function createPersistIgnoreTask(options) {
1123
+ function createPersistIgnoreTask() {
1045
1124
  return {
1046
1125
  title: "Update .keqignore",
1047
- enabled: options?.persistIgnore,
1048
- skip: options?.skip,
1049
1126
  task: async (context, task) => {
1050
1127
  if (!context.setup) throw new Error("Please run setup task first.");
1051
1128
  const matcher = context.setup.matcher;
@@ -1053,15 +1130,12 @@ function createPersistIgnoreTask(options) {
1053
1130
  }
1054
1131
  };
1055
1132
  }
1056
- function createPersistTask(options) {
1133
+ function main5() {
1057
1134
  return {
1058
- title: "Persist",
1059
- enabled: options?.enabled,
1060
- skip: options?.skip,
1061
1135
  task: (context, task) => task.newListr(
1062
1136
  [
1063
- createPersistArtifactTask(options),
1064
- createPersistIgnoreTask(options)
1137
+ createPersistArtifactTask(),
1138
+ createPersistIgnoreTask()
1065
1139
  ],
1066
1140
  {
1067
1141
  concurrent: true,
@@ -1072,8 +1146,29 @@ function createPersistTask(options) {
1072
1146
  )
1073
1147
  };
1074
1148
  }
1149
+ function createPersistTask(compiler, options) {
1150
+ return {
1151
+ title: "Persist",
1152
+ enabled: options?.enabled,
1153
+ skip: options?.skip,
1154
+ task: (context, task) => task.newListr(
1155
+ [
1156
+ main5(),
1157
+ {
1158
+ task: (context2, task2) => compiler.hooks.afterPersist.promise(task2)
1159
+ }
1160
+ ],
1161
+ {
1162
+ concurrent: false
1163
+ }
1164
+ )
1165
+ };
1166
+ }
1075
1167
 
1076
1168
  // src/tasks/compile/utils/compile-schema-definition.ts
1169
+ var R14 = __toESM(require("ramda"), 1);
1170
+
1171
+ // src/renderer/json-schema/index.ts
1077
1172
  var R12 = __toESM(require("ramda"), 1);
1078
1173
 
1079
1174
  // src/renderer/utils/generate-schema.ts
@@ -1199,14 +1294,102 @@ async function jsonSchemaRenderer(schemaDefinition) {
1199
1294
  let $comment = generateComment(schemaDefinition.schema);
1200
1295
  if ($comment) $comment += "\n";
1201
1296
  if (typeof schemaDefinition.schema === "boolean") {
1202
- return `${$comment}type ${schemaDefinition.name} = unknown`;
1297
+ return [
1298
+ "/* @anchor:file:start */",
1299
+ "",
1300
+ $comment || void 0,
1301
+ `type ${schemaDefinition.name} = unknown`,
1302
+ "",
1303
+ "/* @anchor:file:end */"
1304
+ ].filter(R12.isNotNil).join("\n");
1203
1305
  }
1204
1306
  if (JsonSchemaUtils.isNonArray(schemaDefinition.schema) && schemaDefinition.schema.type === "object") {
1205
- return `${$comment}export interface ${schemaDefinition.name} ${generateSchema(schemaDefinition.schema)}`;
1307
+ return [
1308
+ "/* @anchor:file:start */",
1309
+ "",
1310
+ $comment || void 0,
1311
+ `export interface ${schemaDefinition.name} ${generateSchema(schemaDefinition.schema)}`,
1312
+ "",
1313
+ "/* @anchor:file:end */"
1314
+ ].filter(R12.isNotNil).join("\n");
1206
1315
  }
1207
- return `${$comment}export type ${schemaDefinition.name} = ${generateSchema(schemaDefinition.schema)}`;
1316
+ return [
1317
+ "/* @anchor:file:start */",
1318
+ "",
1319
+ $comment || void 0,
1320
+ `export type ${schemaDefinition.name} = ${generateSchema(schemaDefinition.schema)}`,
1321
+ "",
1322
+ "/* @anchor:file:end */"
1323
+ ].filter(R12.isNotNil).join("\n");
1208
1324
  }
1209
1325
 
1326
+ // src/tasks/utils/anchor.ts
1327
+ var AnchorBlock = class {
1328
+ constructor(artifact) {
1329
+ this.artifact = artifact;
1330
+ }
1331
+ /**
1332
+ * Append content to the end of the anchor block.
1333
+ */
1334
+ append(anchorName, content) {
1335
+ const lines = this.artifact.content.split("\n");
1336
+ const anchor = `@anchor:${anchorName}:end`;
1337
+ const anchorIndex = lines.findIndex((line) => line.includes(`/* ${anchor} */`));
1338
+ if (anchorIndex === -1) {
1339
+ throw new Error(`"${anchor}" not found in artifact "${this.artifact.filepath}".`);
1340
+ }
1341
+ lines.splice(anchorIndex, 0, content);
1342
+ this.artifact.content = lines.join("\n");
1343
+ }
1344
+ prepend(anchorName, content) {
1345
+ const lines = this.artifact.content.split("\n");
1346
+ const anchor = `@anchor:${anchorName}:start`;
1347
+ const anchorIndex = lines.findIndex((line) => line.includes(`/* ${anchor} */`));
1348
+ if (anchorIndex === -1) {
1349
+ throw new Error(`"${anchor}" not found in artifact "${this.artifact.filepath}".`);
1350
+ }
1351
+ lines.splice(anchorIndex + 1, 0, content);
1352
+ this.artifact.content = lines.join("\n");
1353
+ }
1354
+ replace(anchorName, content) {
1355
+ const lines = this.artifact.content.split("\n");
1356
+ const startIndex = lines.findIndex((line) => line.includes(`/* @anchor:${anchorName}:start */`));
1357
+ const endIndex = lines.findIndex((line) => line.includes(`/* @anchor:${anchorName}:end */`));
1358
+ if (startIndex === -1 || endIndex === -1 || endIndex <= startIndex) {
1359
+ throw new Error(`"@anchor:${anchorName}:start" or "@anchor:${anchorName}:end" not found in artifact "${this.artifact.filepath}".`);
1360
+ }
1361
+ lines.splice(startIndex + 1, endIndex - startIndex - 1, content);
1362
+ this.artifact.content = lines.join("\n");
1363
+ }
1364
+ };
1365
+ var Anchor = class {
1366
+ constructor(artifact) {
1367
+ this.artifact = artifact;
1368
+ this.block = new AnchorBlock(artifact);
1369
+ }
1370
+ block;
1371
+ append(anchorName, content) {
1372
+ const lines = this.artifact.content.split("\n");
1373
+ const anchor = `@anchor:${anchorName}`;
1374
+ const anchorIndex = lines.findIndex((line) => line.includes(`/* ${anchor} */`));
1375
+ if (anchorIndex === -1) {
1376
+ throw new Error(`"${anchor}" not found in artifact "${this.artifact.filepath}".`);
1377
+ }
1378
+ lines.splice(anchorIndex + 1, 0, content);
1379
+ this.artifact.content = lines.join("\n");
1380
+ }
1381
+ prepend(anchorName, content) {
1382
+ const lines = this.artifact.content.split("\n");
1383
+ const anchor = `@anchor:${anchorName}`;
1384
+ const anchorIndex = lines.findIndex((line) => line.includes(`/* ${anchor} */`));
1385
+ if (anchorIndex === -1) {
1386
+ throw new Error(`"${anchor}" not found in artifact "${this.artifact.filepath}".`);
1387
+ }
1388
+ lines.splice(anchorIndex, 0, content);
1389
+ this.artifact.content = lines.join("\n");
1390
+ }
1391
+ };
1392
+
1210
1393
  // src/tasks/utils/artifact.ts
1211
1394
  var path8 = __toESM(require("path"), 1);
1212
1395
  var changeCase = __toESM(require("change-case"), 1);
@@ -1291,6 +1474,7 @@ var Artifact = class {
1291
1474
  warns = [];
1292
1475
  content;
1293
1476
  extensionName;
1477
+ anchor = new Anchor(this);
1294
1478
  constructor(options) {
1295
1479
  this.id = options.id;
1296
1480
  this.filepath = options.filepath;
@@ -1347,6 +1531,10 @@ var Artifact = class {
1347
1531
  }
1348
1532
  };
1349
1533
 
1534
+ // src/tasks/utils/json-schema.ts
1535
+ var R13 = __toESM(require("ramda"), 1);
1536
+ var import_jsonpath_plus5 = require("jsonpath-plus");
1537
+
1350
1538
  // src/tasks/compile/utils/compile-schema-definition.ts
1351
1539
  function genSchemaDefinitionFilepath(schemaDefinition) {
1352
1540
  const filename = `${schemaDefinition.name}.schema.ts`;
@@ -1371,17 +1559,18 @@ var isArtifactCompiledBy = function(schemaDefinition) {
1371
1559
  return (artifact) => artifact.id === genSchemaDefinitionFilepath(schemaDefinition);
1372
1560
  };
1373
1561
  async function compileSchemaDefinition(options) {
1374
- const { schemaDefinitions } = options;
1562
+ const { task, compiler, schemaDefinitions } = options;
1375
1563
  const artifacts = await Promise.all(
1376
1564
  schemaDefinitions.map(async (schemaDefinition) => {
1377
1565
  const content = await jsonSchemaRenderer(schemaDefinition);
1378
1566
  const filepath = genSchemaDefinitionFilepath(schemaDefinition);
1379
- return new Artifact({
1567
+ const artifact = new Artifact({
1380
1568
  id: filepath,
1381
1569
  filepath,
1382
1570
  content,
1383
1571
  extensionName: ".schema.ts"
1384
1572
  });
1573
+ return await compiler.hooks.afterCompileSchema.promise(artifact, schemaDefinition, task);
1385
1574
  })
1386
1575
  );
1387
1576
  for (const schemaDefinition of schemaDefinitions) {
@@ -1397,7 +1586,7 @@ async function compileSchemaDefinition(options) {
1397
1586
  artifact.addDependence(dependentArtifact, [dependentSchemaDefinition.name]);
1398
1587
  }
1399
1588
  }
1400
- const schemaDefinitionsGroupByModuleName = R12.groupBy(
1589
+ const schemaDefinitionsGroupByModuleName = R14.groupBy(
1401
1590
  (schemaDefinition) => schemaDefinition.module.name,
1402
1591
  schemaDefinitions
1403
1592
  );
@@ -1422,41 +1611,93 @@ async function compileSchemaDefinition(options) {
1422
1611
  }
1423
1612
 
1424
1613
  // src/tasks/compile/utils/compile-operation-definition.ts
1425
- var R15 = __toESM(require("ramda"), 1);
1614
+ var R17 = __toESM(require("ramda"), 1);
1426
1615
 
1427
1616
  // src/renderer/operation-type/index.ts
1428
- var R13 = __toESM(require("ramda"), 1);
1617
+ var R15 = __toESM(require("ramda"), 1);
1429
1618
  var changeCase2 = __toESM(require("change-case"), 1);
1430
1619
  function typeNameFactory(operationDefinition) {
1431
1620
  const pascalCaseOperationId = changeCase2.pascalCase(operationDefinition.operationId);
1432
1621
  return (name) => `${pascalCaseOperationId}${name}`;
1433
1622
  }
1434
- async function operationTypeRenderer(operationDefinition, alias = R13.identity) {
1435
- const { operation } = operationDefinition;
1436
- if (!operation.responses) return "";
1437
- const typeName = typeNameFactory(operationDefinition);
1623
+ function responseBodies(operation, alias = R15.identity, typeName) {
1624
+ if (!operation.responses || R15.isEmpty(operation.responses)) {
1625
+ return `export interface ${typeName("ResponseBodies")} {}`;
1626
+ }
1438
1627
  const $responses = Object.entries(operation.responses).map(([statusCode, response]) => {
1439
1628
  if (!JsonSchemaUtils.isRef(response)) {
1440
1629
  const $value = Object.values(response.content || {}).map((mediaTypeObject) => mediaTypeObject.schema).filter((schema) => !!schema).map((schema) => generateSchema(schema, alias)).join(" | ");
1441
1630
  return indent(2, `${statusCode}: ${$value || "void"}`);
1442
1631
  }
1443
1632
  }).join("\n");
1444
- let $requestBody = `export type ${typeName("RequestBody")} = {}`;
1445
- if (operation.requestBody && !JsonSchemaUtils.isRef(operation.requestBody)) {
1446
- const $value = Object.entries(operation.requestBody.content || {}).map(([mediaType, mediaTypeObject]) => [mediaType, mediaTypeObject.schema]).filter(([, schema]) => !!schema).map(([mediaType, schema]) => {
1447
- if (mediaType === "multipart/form-data") {
1448
- return `FormData | ${generateSchema(schema, alias)}`;
1449
- } else if (mediaType === "application/x-www-form-urlencoded") {
1450
- return `URLSearchParams | ${generateSchema(schema, alias)}`;
1451
- }
1452
- return generateSchema(schema, alias);
1453
- }).join(" | ");
1454
- $requestBody = `export type ${typeName("RequestBody")} = ${$value || "unknown"}`;
1455
- }
1456
1633
  return [
1457
1634
  `export interface ${typeName("ResponseBodies")} {`,
1458
1635
  $responses,
1459
- "}",
1636
+ "}"
1637
+ ].join("\n");
1638
+ }
1639
+ function requestBodies(operation, alias = R15.identity, typeName) {
1640
+ let $requestBodies = `export interface ${typeName("RequestBodies")} {}`;
1641
+ if (operation.requestBody && !JsonSchemaUtils.isRef(operation.requestBody)) {
1642
+ const $mediaTypes = Object.entries(operation.requestBody.content || {}).map(([mediaType, mediaTypeObject]) => [mediaType, mediaTypeObject.schema]).map(([mediaType, schema]) => {
1643
+ if (!schema) return `${JSON.stringify(mediaType)}: unknown`;
1644
+ return `${JSON.stringify(mediaType)}: ${generateSchema(schema, alias)}`;
1645
+ }).map((pair) => indent(2, pair));
1646
+ $requestBodies = [
1647
+ `export interface ${typeName("RequestBodies")} {`,
1648
+ ...$mediaTypes,
1649
+ "}"
1650
+ ].join("\n");
1651
+ }
1652
+ return $requestBodies;
1653
+ }
1654
+ function parameterBodies(operationDefinition, alias = R15.identity, typeName) {
1655
+ const { operation } = operationDefinition;
1656
+ let parameterBodies2 = "";
1657
+ if (operation.requestBody && !JsonSchemaUtils.isRef(operation.requestBody)) {
1658
+ const $mediaTypes = Object.entries(operation.requestBody.content || {}).map(([mediaType, mediaTypeObject]) => [mediaType, mediaTypeObject.schema]).map(([mediaType, schemaOrRef]) => {
1659
+ if (!schemaOrRef) return `${JSON.stringify(mediaType)}: unknown`;
1660
+ const schema = JsonSchemaUtils.isRef(schemaOrRef) ? SwaggerUtils.dereferenceDeep(schemaOrRef.$ref, operationDefinition.document.swagger) : schemaOrRef;
1661
+ if (schema.type === "object" || schema.properties) {
1662
+ return `${JSON.stringify(mediaType)}: ${generateSchema(schemaOrRef, alias)} & { [key: string]: any }`;
1663
+ }
1664
+ return `${JSON.stringify(mediaType)}: { [key: string]: any }`;
1665
+ }).map((pair) => indent(2, pair));
1666
+ parameterBodies2 = [
1667
+ `interface ${typeName("ParameterBodies")} {`,
1668
+ ...$mediaTypes,
1669
+ "}",
1670
+ ""
1671
+ ].join("\n");
1672
+ }
1673
+ return parameterBodies2;
1674
+ }
1675
+ function requestParameters(operation, alias = R15.identity, typeName) {
1676
+ const mediaTypes = operation.requestBody && !JsonSchemaUtils.isRef(operation.requestBody) ? Object.keys(operation.requestBody.content || {}) : [];
1677
+ const base = `${typeName("RequestQuery")} & ${typeName("RouteParameters")} & ${typeName("RequestHeaders")}`;
1678
+ if (mediaTypes.length === 1) {
1679
+ return `export type ${typeName("RequestParameters")} = ${base} & ${typeName("RequestBodies")}[${JSON.stringify(mediaTypes[0])}]`;
1680
+ }
1681
+ if (mediaTypes.length > 1) {
1682
+ const unions = mediaTypes.map((mediaType) => `(${base} & ${typeName("RequestBodies")}[${JSON.stringify(mediaType)}] & { "content-type": ${JSON.stringify(mediaType)} })`).join("\n| ");
1683
+ return `export type ${typeName("RequestParameters")} = ${unions}`;
1684
+ }
1685
+ return `export type ${typeName("RequestParameters")} = ${base}`;
1686
+ }
1687
+ async function operationTypeRenderer(operationDefinition, alias = R15.identity) {
1688
+ const { operation } = operationDefinition;
1689
+ if (!operation.responses) return "";
1690
+ const typeName = typeNameFactory(operationDefinition);
1691
+ const $responseBodies = responseBodies(operation, alias, typeName);
1692
+ const $requestBodies = requestBodies(operation, alias, typeName);
1693
+ const $parameterBodies = parameterBodies(operationDefinition, alias, typeName);
1694
+ const $requestParameters = requestParameters(operation, alias, typeName);
1695
+ return [
1696
+ "/* @anchor:file:start */",
1697
+ "",
1698
+ $responseBodies,
1699
+ "",
1700
+ $requestBodies,
1460
1701
  "",
1461
1702
  generateParameters(`${typeName("RequestQuery")}`, operation.parameters?.filter((p) => !JsonSchemaUtils.isRef(p) && p.in === "query") || [], alias),
1462
1703
  "",
@@ -1464,18 +1705,19 @@ async function operationTypeRenderer(operationDefinition, alias = R13.identity)
1464
1705
  "",
1465
1706
  generateParameters(`${typeName("RequestHeaders")}`, operation.parameters?.filter((p) => !JsonSchemaUtils.isRef(p) && p.in === "header") || [], alias),
1466
1707
  "",
1467
- $requestBody,
1708
+ $parameterBodies || void 0,
1709
+ $requestParameters,
1468
1710
  "",
1469
- `export type ${typeName("RequestParameters")} = ${typeName("RequestQuery")} & ${typeName("RouteParameters")} & ${typeName("RequestHeaders")} & ${typeName("RequestBody")}`,
1470
- "",
1471
- `export interface Operation<STATUS extends keyof ${typeName("ResponseBodies")}> extends KeqOperation {`,
1472
- ` requestParams: ${typeName("RouteParameters")} & { [key: string]: KeqParamValue }`,
1473
- ` requestQuery: ${typeName("RequestQuery")} & { [key: string]: KeqQueryValue }`,
1711
+ `export interface Operation<STATUS extends keyof ${typeName("ResponseBodies")}, CONTENT_TYPE extends keyof ${typeName("ParameterBodies")}> extends KeqOperation {`,
1712
+ ` requestParams: ${typeName("RouteParameters")} & { [key: string]: KeqPathParameterInit }`,
1713
+ ` requestQuery: ${typeName("RequestQuery")} & { [key: string]: KeqQueryInit }`,
1474
1714
  ` requestHeaders: ${typeName("RequestHeaders")} & { [key: string]: string | number }`,
1475
- ` requestBody: ${typeName("RequestBody")}`,
1715
+ ` requestBody: ${$parameterBodies ? `${typeName("ParameterBodies")}[CONTENT_TYPE] | ` : "object | "}BodyInit`,
1476
1716
  ` responseBody: ${typeName("ResponseBodies")}[STATUS]`,
1477
- "}"
1478
- ].join("\n");
1717
+ "}",
1718
+ "",
1719
+ "/* @anchor:file:end */"
1720
+ ].filter(R15.isNotNil).join("\n");
1479
1721
  }
1480
1722
  function generateParameters(name, parameters, alias) {
1481
1723
  if (parameters.length === 0) {
@@ -1495,7 +1737,7 @@ function generateParameters(name, parameters, alias) {
1495
1737
  }
1496
1738
 
1497
1739
  // src/renderer/operation-request/index.ts
1498
- var R14 = __toESM(require("ramda"), 1);
1740
+ var R16 = __toESM(require("ramda"), 1);
1499
1741
  function errorToComment(err, mediaType) {
1500
1742
  const $err = String(err).split("\n").map(((line) => ` * ${line}`)).join("\n");
1501
1743
  return [
@@ -1505,23 +1747,8 @@ function errorToComment(err, mediaType) {
1505
1747
  " */"
1506
1748
  ].join("\n");
1507
1749
  }
1508
- async function operationRequestRenderer(operationDefinition, options) {
1509
- const { operation, operationId, method, pathname } = operationDefinition;
1510
- const { qs } = options;
1511
- if (!operation.responses) return "";
1512
- const typeName = typeNameFactory(operationDefinition);
1513
- const moduleName = operationDefinition.module.name;
1514
- const parameters = operation.parameters?.filter((p) => !JsonSchemaUtils.isRef(p)) || [];
1515
- const queryParameters = parameters.filter((p) => p.in === "query");
1516
- const headersParameters = parameters.filter((p) => p.in === "header");
1517
- const pathParameters = parameters.filter((p) => p.in === "path");
1518
- const $queryParameters = queryParameters.map((p) => {
1519
- const option = qs(p);
1520
- const $option = !option || R14.isEmpty(option) ? "" : `, ${JSON.stringify(option)}`;
1521
- return ` if (args && ${JSON.stringify(p.name)} in args) req.query(${JSON.stringify(p.name)}, args[${JSON.stringify(p.name)}]${$option})`;
1522
- }).concat("").join("\n");
1523
- 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");
1524
- 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");
1750
+ function requestBodyRenderer(operationDefinition, typeName) {
1751
+ const { operation } = operationDefinition;
1525
1752
  const requestBodyContent = operation.requestBody?.content || {};
1526
1753
  const $requestBody = Object.entries(requestBodyContent).map(([mediaType, mediaTypeObject]) => {
1527
1754
  if (!mediaTypeObject.schema) return;
@@ -1550,27 +1777,107 @@ async function operationRequestRenderer(operationDefinition, options) {
1550
1777
  } catch (err) {
1551
1778
  return indent(2, errorToComment(err, mediaType));
1552
1779
  }
1553
- }).filter(R14.isNotNil).join("\n");
1780
+ }).filter(R16.isNotNil).join("\n");
1781
+ return $requestBody;
1782
+ }
1783
+ function requestHeadersRenderer(operationDefinition, typeName) {
1784
+ const { operation } = operationDefinition;
1785
+ const $headers = (operation.parameters || []).filter((p) => !JsonSchemaUtils.isRef(p)).filter((p) => p.in === "header").map((p) => ` if (args && ${JSON.stringify(p.name)} in args) req.header(${JSON.stringify(p.name)}, args[${JSON.stringify(p.name)}])`).concat("").join("\n");
1786
+ return $headers;
1787
+ }
1788
+ function requestQueryRenderer(operationDefinition, qs, typeName) {
1789
+ const { operation } = operationDefinition;
1790
+ const $query = (operation.parameters || []).filter((p) => !JsonSchemaUtils.isRef(p)).filter((p) => p.in === "query").map((p) => {
1791
+ const option = qs(p);
1792
+ const $option = !option || R16.isEmpty(option) ? "" : `, ${JSON.stringify(option)}`;
1793
+ return ` if (args && ${JSON.stringify(p.name)} in args) req.query(${JSON.stringify(p.name)}, args[${JSON.stringify(p.name)}]${$option})`;
1794
+ }).concat("").join("\n");
1795
+ return $query;
1796
+ }
1797
+ function requestPathParametersRenderer(operationDefinition, typeName) {
1798
+ const { operation } = operationDefinition;
1799
+ const $pathParameters = (operation.parameters || []).filter((p) => !JsonSchemaUtils.isRef(p)).filter((p) => p.in === "path").map((p) => ` if (args && ${JSON.stringify(p.name)} in args) req.params(${JSON.stringify(p.name)}, args[${JSON.stringify(p.name)}])`).concat("").join("\n");
1800
+ return $pathParameters;
1801
+ }
1802
+ function getRequestMediaTypes(operationDefinition) {
1803
+ const { operation } = operationDefinition;
1804
+ const requestBodyContent = operation.requestBody?.content || {};
1805
+ return Object.keys(requestBodyContent);
1806
+ }
1807
+ function mediaTypeRenderer(operationDefinition) {
1808
+ const mediaTypes = getRequestMediaTypes(operationDefinition);
1809
+ if (mediaTypes.length === 1 && !mediaTypes[0].endsWith("/*")) {
1810
+ return ` req.type("${mediaTypes[0]}")
1811
+ `;
1812
+ } else if (mediaTypes.some((mediaType) => mediaType === "*/*")) {
1813
+ } else if (mediaTypes.some((mediaType) => mediaType.endsWith("/*"))) {
1814
+ return ' if(args?.["content-type"]) req.type(args["content-type"])\n';
1815
+ } else if (mediaTypes.length > 1) {
1816
+ return ' if(args?.["content-type"]) req.type(args["content-type"])\n';
1817
+ }
1818
+ return "";
1819
+ }
1820
+ function operationDeclarationRenderer(operationDefinition, typeName) {
1821
+ const { operationId } = operationDefinition;
1822
+ const mediaTypes = getRequestMediaTypes(operationDefinition);
1823
+ if (mediaTypes.length === 0) {
1824
+ return `function ${operationId}<STATUS extends keyof ${typeName("ResponseBodies")}>(args?: ${typeName("RequestParameters")}): Keq<Operation<STATUS, never>>`;
1825
+ } else if (mediaTypes.length === 1) {
1826
+ return `function ${operationId}<STATUS extends keyof ${typeName("ResponseBodies")}>(args?: ${typeName("RequestParameters")}): Keq<Operation<STATUS, ${JSON.stringify(mediaTypes[0])}>>`;
1827
+ } else if (mediaTypes.length > 1) {
1828
+ return `function ${operationId}<STATUS extends keyof ${typeName("ResponseBodies")}, CONTENT_TYPE extends ${typeName("RequestParameters")}["content-type"]>(args?: Extract<${typeName("RequestParameters")}, { "content-type": CONTENT_TYPE }>): Keq<Operation<STATUS, CONTENT_TYPE>>`;
1829
+ }
1830
+ throw new Error("[operationDeclarationRenderer] Unreachable");
1831
+ }
1832
+ async function operationRequestRenderer(operationDefinition, options) {
1833
+ const { operation, operationId, method, pathname } = operationDefinition;
1834
+ const { qs } = options;
1835
+ if (!operation.responses) return "";
1836
+ const typeName = typeNameFactory(operationDefinition);
1837
+ const moduleName = operationDefinition.module.name;
1838
+ const $queryParameters = requestQueryRenderer(operationDefinition, qs, typeName);
1839
+ const $headerParameters = requestHeadersRenderer(operationDefinition, typeName);
1840
+ const $pathParameters = requestPathParametersRenderer(operationDefinition, typeName);
1841
+ const $mediaType = mediaTypeRenderer(operationDefinition);
1842
+ const $requestBody = requestBodyRenderer(operationDefinition, typeName);
1843
+ const $operationDeclaration = operationDeclarationRenderer(operationDefinition, typeName);
1554
1844
  return [
1845
+ "/* @anchor:file:start */",
1846
+ "",
1555
1847
  `const moduleName = "${moduleName}"`,
1556
1848
  `const method = "${method}"`,
1557
1849
  `const pathname = "${pathname}"`,
1558
1850
  "",
1559
- `export function ${operationId}<STATUS extends keyof ${typeName("ResponseBodies")}>(args?: ${typeName("RequestParameters")}): Keq<Operation<STATUS>> {`,
1851
+ "/* @anchor:operation-declaration */",
1852
+ `export ${$operationDeclaration} {`,
1560
1853
  ` const req = request.post<${typeName("ResponseBodies")}[STATUS]>("${pathname}")`,
1561
1854
  " .option('module', { name: moduleName, pathname, method })",
1562
1855
  "",
1856
+ $mediaType || void 0,
1857
+ " /* @anchor:query:start */",
1563
1858
  $queryParameters || void 0,
1859
+ " /* @anchor:query:end */",
1860
+ "",
1861
+ " /* @anchor:headers:start */",
1564
1862
  $headerParameters || void 0,
1863
+ " /* @anchor:headers:end */",
1864
+ "",
1865
+ " /* @anchor:path-parameters:start */",
1565
1866
  $pathParameters || void 0,
1566
- $requestBody ? `${$requestBody}
1567
- ` : void 0,
1568
- " return req",
1867
+ " /* @anchor:path-parameters:end */",
1868
+ "",
1869
+ " /* @anchor:body:start */",
1870
+ $requestBody || void 0,
1871
+ " /* @anchor:body:end */",
1872
+ "",
1873
+ " /* @anchor:operation-return */",
1874
+ ` return req as ReturnType<typeof ${operationId}>`,
1569
1875
  "}",
1570
1876
  "",
1571
1877
  `${operationId}.pathname = pathname`,
1572
- `${operationId}.method = method`
1573
- ].filter(R14.isNotNil).join("\n");
1878
+ `${operationId}.method = method`,
1879
+ "/* @anchor:file:end */"
1880
+ ].filter(R16.isNotNil).join("\n");
1574
1881
  }
1575
1882
 
1576
1883
  // src/tasks/compile/utils/compile-operation-definition.ts
@@ -1601,7 +1908,7 @@ function genEntrypointFilepath2(moduleName) {
1601
1908
  ].join("/");
1602
1909
  }
1603
1910
  async function compileOperationDefinition(options) {
1604
- const { rc, requestArtifact, schemaArtifacts, operationDefinitions } = options;
1911
+ const { compiler, task, rc, requestArtifact, schemaArtifacts, operationDefinitions } = options;
1605
1912
  const alias = (name) => `${name}Schema`;
1606
1913
  const qs = (parameter) => {
1607
1914
  if (typeof rc.qs === "function") {
@@ -1635,7 +1942,7 @@ async function compileOperationDefinition(options) {
1635
1942
  content,
1636
1943
  extensionName: ".type.ts"
1637
1944
  });
1638
- typeArtifact.addDependence("keq", ["KeqOperation", "KeqQueryValue", "KeqParamValue"]);
1945
+ typeArtifact.addDependence("keq", ["KeqOperation", "KeqQueryInit", "KeqPathParameterInit"]);
1639
1946
  const dependentSchemaDefinitions = operationDefinition.getDependencies();
1640
1947
  for (const dependentSchemaDefinition of dependentSchemaDefinitions) {
1641
1948
  const dependentArtifact = schemaArtifacts.find(isArtifactCompiledBy(dependentSchemaDefinition));
@@ -1647,7 +1954,7 @@ async function compileOperationDefinition(options) {
1647
1954
  new DependencyIdentifier(dependentSchemaDefinition.name, alias(dependentSchemaDefinition.name))
1648
1955
  ]);
1649
1956
  }
1650
- return typeArtifact;
1957
+ return await compiler.hooks.afterCompileOperationType.promise(typeArtifact, operationDefinition, task);
1651
1958
  }
1652
1959
  async function createRequestArtifact(operationDefinition, typeArtifact) {
1653
1960
  const typeName = typeNameFactory(operationDefinition);
@@ -1674,13 +1981,13 @@ async function compileOperationDefinition(options) {
1674
1981
  [
1675
1982
  `${typeName("RequestQuery")}`,
1676
1983
  `${typeName("RequestHeaders")}`,
1677
- `${typeName("RequestBody")}`
1984
+ `${typeName("RequestBodies")}`
1678
1985
  ],
1679
1986
  { export: true }
1680
1987
  );
1681
- return artifact;
1988
+ return await compiler.hooks.afterCompileOperationRequest.promise(artifact, operationDefinition, task);
1682
1989
  }
1683
- const artifacts = R15.unnest(
1990
+ const artifacts = R17.unnest(
1684
1991
  await Promise.all(
1685
1992
  operationDefinitions.map(async (operationDefinition) => {
1686
1993
  const typeArtifact = await createTypeArtifact(operationDefinition);
@@ -1689,7 +1996,7 @@ async function compileOperationDefinition(options) {
1689
1996
  })
1690
1997
  )
1691
1998
  );
1692
- const operationDefinitionsGroupByModuleName = R15.groupBy(
1999
+ const operationDefinitionsGroupByModuleName = R17.groupBy(
1693
2000
  (operationDefinition) => operationDefinition.module.name,
1694
2001
  operationDefinitions
1695
2002
  );
@@ -1717,32 +2024,38 @@ async function compileOperationDefinition(options) {
1717
2024
  async function requestRenderer() {
1718
2025
  return [
1719
2026
  "import { KeqRequest } from 'keq'",
1720
- "export const request = new KeqRequest()"
2027
+ "",
2028
+ "/* @anchor:file:start */",
2029
+ "",
2030
+ "/* @anchor:request-declaration */",
2031
+ "export const request = new KeqRequest()",
2032
+ "",
2033
+ "/* @anchor:file:end"
1721
2034
  ].join("\n");
1722
2035
  }
1723
2036
 
1724
2037
  // src/tasks/compile/index.ts
1725
- function createCompileTask(options) {
2038
+ function main6(compiler) {
1726
2039
  return {
1727
- title: "Compile",
1728
- enabled: options?.enabled,
1729
- skip: options?.skip,
1730
2040
  task: async (context, task) => {
1731
2041
  if (!context.setup) throw new Error("Please run setup task first.");
1732
2042
  if (!context.shaken) throw new Error("Please run shaking task first.");
1733
2043
  const rc = context.setup.rc;
1734
2044
  const matcher = context.setup.matcher;
1735
2045
  const documents = context.shaken.documents.filter((document) => !matcher.isModuleIgnored(document.module));
1736
- const requestArtifact = new Artifact({
1737
- id: "request",
1738
- filepath: "request",
1739
- content: await requestRenderer(),
1740
- extensionName: ".ts"
1741
- });
2046
+ const requestArtifact = await compiler.hooks.afterCompileKeqRequest.promise(
2047
+ new Artifact({
2048
+ id: "request",
2049
+ filepath: "request",
2050
+ content: await requestRenderer(),
2051
+ extensionName: ".ts"
2052
+ }),
2053
+ task
2054
+ );
1742
2055
  const schemaDefinitions = documents.flatMap((document) => document.schemas);
1743
2056
  const operationDefinitions = documents.flatMap((document) => document.operations);
1744
- const schemaArtifacts = await compileSchemaDefinition({ schemaDefinitions });
1745
- const operationArtifacts = await compileOperationDefinition({ rc, operationDefinitions, schemaArtifacts, requestArtifact });
2057
+ const schemaArtifacts = await compileSchemaDefinition({ compiler, task, schemaDefinitions });
2058
+ const operationArtifacts = await compileOperationDefinition({ compiler, task, rc, operationDefinitions, schemaArtifacts, requestArtifact });
1746
2059
  const artifacts = [requestArtifact, ...schemaArtifacts, ...operationArtifacts];
1747
2060
  context.compiled = {
1748
2061
  artifacts
@@ -1750,24 +2063,22 @@ function createCompileTask(options) {
1750
2063
  }
1751
2064
  };
1752
2065
  }
1753
-
1754
- // src/tasks/append-ignore-rule/index.ts
1755
- function createAppendIgnoreRulesTask(options) {
2066
+ function createCompileTask(compiler, options) {
1756
2067
  return {
1757
- title: "Update .keqignore file",
1758
- task: (context, task) => {
1759
- if (!context.setup) throw new Error("Setup task has not been executed.");
1760
- const matcher = context.setup.matcher;
1761
- for (const rule of options.rules) {
1762
- matcher.append({
1763
- persist: true,
1764
- ignore: options.mode === "add",
1765
- moduleName: rule.moduleName,
1766
- operationMethod: rule.operationMethod,
1767
- operationPathname: rule.operationPathname
1768
- });
2068
+ title: "Compile",
2069
+ enabled: options?.enabled,
2070
+ skip: options?.skip,
2071
+ task: (context, task) => task.newListr(
2072
+ [
2073
+ main6(compiler),
2074
+ {
2075
+ task: (context2, task2) => compiler.hooks.afterCompile.promise(task2)
2076
+ }
2077
+ ],
2078
+ {
2079
+ concurrent: false
1769
2080
  }
1770
- }
2081
+ )
1771
2082
  };
1772
2083
  }
1773
2084
 
@@ -1806,7 +2117,7 @@ function createInteractiveTask(options) {
1806
2117
  const documents = context.validated.documents;
1807
2118
  const operationDefinitions = documents.flatMap((document) => document.operations);
1808
2119
  const selectedOperationDefinitions = await selectOperationDefinitions(task, operationDefinitions);
1809
- if (options.override) {
2120
+ if (options.clear) {
1810
2121
  matcher.append({
1811
2122
  persist: false,
1812
2123
  ignore: true,
@@ -1817,7 +2128,7 @@ function createInteractiveTask(options) {
1817
2128
  }
1818
2129
  for (const op of selectedOperationDefinitions) {
1819
2130
  matcher.append({
1820
- persist: true,
2131
+ persist: !!options.persist,
1821
2132
  ignore: options.mode === "add",
1822
2133
  moduleName: op.module.name,
1823
2134
  operationMethod: op.method,
@@ -1828,110 +2139,250 @@ function createInteractiveTask(options) {
1828
2139
  };
1829
2140
  }
1830
2141
 
1831
- // src/tasks/index.ts
1832
- async function build(options) {
1833
- const tasks = new import_listr22.Listr(
1834
- [
1835
- createSetupTask(options),
1836
- createDownloadTask({ skipIgnoredModules: !options.interactive }),
1837
- createValidateTask(),
1838
- createInteractiveTask({ mode: "except", override: true, enabled: !!options.interactive }),
1839
- createShakingTask({ skipIgnoredModules: true, skipEmptyDocuments: true }),
1840
- createCompileTask(),
1841
- createPersistTask({ persistIgnore: false })
1842
- ],
1843
- {
1844
- concurrent: false,
1845
- renderer: "default",
1846
- rendererOptions: {
1847
- suffixSkips: true,
1848
- collapseSubtasks: false,
1849
- collapseErrors: false
2142
+ // src/compiler/intercepter/perfect-error-message.ts
2143
+ var R18 = __toESM(require("ramda"), 1);
2144
+ function perfectErrorMessage() {
2145
+ return {
2146
+ register: (tap) => {
2147
+ const fn = tap.fn;
2148
+ function prefix(err) {
2149
+ if (err instanceof Error) {
2150
+ err.message = `[Plugin: ${tap.name}] ${err.message}`;
2151
+ }
2152
+ }
2153
+ if (tap.type === "promise") {
2154
+ tap.fn = async (...args) => {
2155
+ try {
2156
+ return await fn(...args);
2157
+ } catch (err) {
2158
+ prefix(err);
2159
+ throw err;
2160
+ }
2161
+ };
1850
2162
  }
2163
+ if (tap.type === "sync") {
2164
+ tap.fn = (...args) => {
2165
+ try {
2166
+ return fn(...args);
2167
+ } catch (err) {
2168
+ prefix(err);
2169
+ throw err;
2170
+ }
2171
+ };
2172
+ }
2173
+ if (tap.type === "async") {
2174
+ tap.fn = (...args) => {
2175
+ const callback = R18.last(args);
2176
+ return fn(...R18.init(args), (err, result) => {
2177
+ prefix(err);
2178
+ return callback(err, result);
2179
+ });
2180
+ };
2181
+ }
2182
+ return tap;
1851
2183
  }
1852
- );
1853
- await tasks.run({});
1854
- }
1855
- async function ignore(options) {
1856
- const tasks = new import_listr22.Listr(
1857
- [
1858
- createSetupTask(options),
1859
- createAppendIgnoreRulesTask(options),
1860
- createDownloadTask({ enabled: !!options.interactive }),
1861
- createValidateTask({ enabled: !!options.interactive }),
1862
- createInteractiveTask({ mode: options.mode, override: false, enabled: !!options.interactive }),
1863
- createShakingTask({ enabled: !!options.build, skipIgnoredModules: true, skipEmptyDocuments: true }),
1864
- createCompileTask({ enabled: !!options.build }),
1865
- createPersistTask({ persistArtifacts: !!options.build, persistIgnore: true })
1866
- ],
1867
- {
1868
- concurrent: false,
1869
- renderer: "default",
1870
- rendererOptions: {
1871
- suffixSkips: true,
1872
- collapseSubtasks: false,
1873
- collapseErrors: false
2184
+ };
2185
+ }
2186
+
2187
+ // src/compiler/intercepter/print-information.ts
2188
+ function proxyTaskWrapper(pluginName, task) {
2189
+ return new Proxy(task, {
2190
+ set(target, prop2, value) {
2191
+ if (prop2 !== "output") {
2192
+ return Reflect.set(target, prop2, value);
1874
2193
  }
2194
+ target.output = `[Plugin: ${pluginName}] ${value}`;
2195
+ return true;
1875
2196
  }
1876
- );
1877
- await tasks.run({});
2197
+ });
2198
+ }
2199
+ function printInformation(taskIndex) {
2200
+ return {
2201
+ register: (tap) => {
2202
+ const fn = tap.fn;
2203
+ if (tap.type === "promise") {
2204
+ tap.fn = (...args) => {
2205
+ const task = args[taskIndex];
2206
+ const proxyTask = proxyTaskWrapper(tap.name, task);
2207
+ args[taskIndex] = proxyTask;
2208
+ proxyTask.output = "Processing...";
2209
+ return fn(...args);
2210
+ };
2211
+ }
2212
+ if (tap.type === "sync") {
2213
+ tap.fn = (...args) => {
2214
+ const task = args[taskIndex];
2215
+ const proxyTask = proxyTaskWrapper(tap.name, task);
2216
+ args[taskIndex] = proxyTask;
2217
+ proxyTask.output = "Processing...";
2218
+ return fn(...args);
2219
+ };
2220
+ }
2221
+ if (tap.type === "async") {
2222
+ tap.fn = (...args) => {
2223
+ const task = args[taskIndex];
2224
+ const proxyTask = proxyTaskWrapper(tap.name, task);
2225
+ args[taskIndex] = proxyTask;
2226
+ proxyTask.output = "Processing...";
2227
+ return fn(...args);
2228
+ };
2229
+ }
2230
+ return tap;
2231
+ }
2232
+ };
1878
2233
  }
1879
2234
 
2235
+ // src/compiler/compiler.ts
2236
+ var Compiler = class {
2237
+ constructor(options) {
2238
+ this.options = options;
2239
+ for (const hook of Object.values(this.hooks)) {
2240
+ hook.intercept(perfectErrorMessage());
2241
+ }
2242
+ this.hooks.afterSetup.intercept(printInformation(0));
2243
+ this.hooks.afterPersist.intercept(printInformation(0));
2244
+ }
2245
+ context = {};
2246
+ hooks = {
2247
+ // core
2248
+ afterSetup: new import_tapable.AsyncSeriesHook(["task"]),
2249
+ afterDownload: new import_tapable.AsyncSeriesHook(["task"]),
2250
+ afterValidate: new import_tapable.AsyncSeriesHook(["task"]),
2251
+ afterShaking: new import_tapable.AsyncSeriesHook(["task"]),
2252
+ afterCompile: new import_tapable.AsyncSeriesHook(["task"]),
2253
+ afterPersist: new import_tapable.AsyncSeriesHook(["task"]),
2254
+ done: new import_tapable.SyncHook(),
2255
+ // compile
2256
+ afterCompileKeqRequest: new import_tapable.AsyncSeriesWaterfallHook(["artifact", "task"]),
2257
+ afterCompileSchema: new import_tapable.AsyncSeriesWaterfallHook(["artifact", "schema", "task"]),
2258
+ afterCompileOperationType: new import_tapable.AsyncSeriesWaterfallHook(["artifact", "operation", "task"]),
2259
+ afterCompileOperationRequest: new import_tapable.AsyncSeriesWaterfallHook(["artifact", "operation", "task"])
2260
+ };
2261
+ async run() {
2262
+ const options = this.options;
2263
+ const tasks = new import_listr22.Listr(
2264
+ [
2265
+ createSetupTask(this, options),
2266
+ createDownloadTask(this, { skipIgnoredModules: !options.interactive }),
2267
+ createValidateTask(this, { enabled: !!options.build }),
2268
+ createInteractiveTask({ enabled: !!options.interactive, ...typeof options.interactive === "object" ? options.interactive : { mode: "except" } }),
2269
+ createShakingTask(this, { enabled: !!options.build, ...typeof options.build === "object" ? options.build.shaking : void 0 }),
2270
+ createCompileTask(this, { enabled: !!options.build }),
2271
+ createPersistTask(this, { enabled: !!options.build })
2272
+ ],
2273
+ {
2274
+ concurrent: false,
2275
+ renderer: "default",
2276
+ rendererOptions: {
2277
+ suffixSkips: true,
2278
+ collapseSubtasks: false,
2279
+ collapseErrors: false
2280
+ }
2281
+ }
2282
+ );
2283
+ await tasks.run(this.context);
2284
+ await this.hooks.done.promise();
2285
+ }
2286
+ };
2287
+
1880
2288
  // src/cli.ts
1881
2289
  if (import_semver.default.lt(process.version, "18.0.0")) {
1882
2290
  throw new Error("Node.js version must be greater than 18");
1883
2291
  }
1884
2292
  var program = new import_commander.Command();
1885
2293
  program.command("build").option("-c --config <config>", "The keq-cli config file").option("--module <modules...>", "Filter module(s) to generate").option("--debug", "Print debug information").option("--tolerant", "Tolerate wrong swagger structure").option("-i --interactive", "Interactive select the scope of generation").action(async (options) => {
1886
- await build({
2294
+ const compiler = new Compiler({
2295
+ build: {
2296
+ shaking: {
2297
+ skipIgnoredModules: true,
2298
+ skipEmptyDocuments: true
2299
+ }
2300
+ },
1887
2301
  config: options.config,
1888
2302
  modules: options.module,
1889
- debug: options.debug,
1890
- tolerant: options.tolerant,
1891
- interactive: options.interactive
2303
+ debug: !!options.debug,
2304
+ tolerant: !!options.tolerant,
2305
+ interactive: !!options.interactive
1892
2306
  });
2307
+ await compiler.run();
1893
2308
  });
1894
2309
  program.command("ignore").addArgument(
1895
- new import_commander.Argument("<mode>", "The ignore mode").choices(["add", "except"]).argRequired()
2310
+ new import_commander.Argument("<mode>", "The ignore mode").choices(["all", "add", "except"]).argRequired()
1896
2311
  ).option("-c --config <config>", "The keq-cli config file").option("--debug", "Print debug information").option("--module <modules...>").option("--build", "Build after updating .keqignore file").addOption(
1897
2312
  new import_commander.Option("--method <method>", "Only generate files of the specified operation method").choices([
1898
2313
  ...SupportedMethods,
1899
2314
  ...SupportedMethods.map((method) => method.toUpperCase())
1900
2315
  ])
1901
2316
  ).option("--pathname <pathnames>", "Only generate files of the specified operation pathname").option("-i --interactive", "Interactive select the scope of generation").action(async (mode, options) => {
1902
- if (options.interactive) {
2317
+ let compiler;
2318
+ if (mode === "all") {
2319
+ if (options.build) throw new Error("'--build' cannot be used with 'all' mode");
2320
+ compiler = new Compiler({
2321
+ build: false,
2322
+ config: options.config,
2323
+ modules: options.module,
2324
+ debug: !!options.debug,
2325
+ interactive: false,
2326
+ ignore: {
2327
+ rules: [{
2328
+ persist: true,
2329
+ ignore: true,
2330
+ moduleName: "*",
2331
+ operationMethod: "*",
2332
+ operationPathname: "*"
2333
+ }]
2334
+ }
2335
+ });
2336
+ } else if (options.interactive) {
1903
2337
  if (options.interactive) {
1904
2338
  if (options.method) throw new Error("'--method' cannot be used with '--interactive'");
1905
2339
  if (options.pathname) throw new Error("'--pathname' cannot be used with '--interactive'");
1906
2340
  }
1907
- await ignore({
1908
- mode,
1909
- interactive: options.interactive,
2341
+ compiler = new Compiler({
2342
+ build: !!options.build && {
2343
+ shaking: {
2344
+ skipIgnoredModules: true,
2345
+ skipEmptyDocuments: true
2346
+ }
2347
+ },
1910
2348
  config: options.config,
1911
- debug: options.debug,
1912
2349
  modules: options.module,
1913
- rules: [],
1914
- build: options.build
2350
+ debug: !!options.debug,
2351
+ interactive: {
2352
+ mode,
2353
+ persist: true
2354
+ }
1915
2355
  });
1916
2356
  } else {
1917
- if (!options.module) throw new Error("required option '--module <module>' not specified");
1918
- if (!options.method) throw new Error("required option '--method <method>' not specified");
1919
- if (!options.pathname) throw new Error("required option '--pathname <pathnames>' not specified");
1920
- await ignore({
1921
- mode,
2357
+ if (!options.module && !options.method && !options.pathname) {
2358
+ throw new Error("at least one of '--module', '--method' or '--pathname' must be specified");
2359
+ }
2360
+ const moduleNames = options.module || ["*"];
2361
+ compiler = new Compiler({
2362
+ build: !!options.build && {
2363
+ shaking: {
2364
+ skipIgnoredModules: true,
2365
+ skipEmptyDocuments: true
2366
+ }
2367
+ },
1922
2368
  config: options.config,
1923
- debug: options.debug,
2369
+ debug: !!options.debug,
1924
2370
  modules: options.module,
1925
- rules: options.module.map((moduleName) => ({
1926
- moduleName,
1927
- operationMethod: options.method,
1928
- operationPathname: options.pathname
1929
- })),
1930
- build: options.build
2371
+ ignore: {
2372
+ rules: moduleNames.map((moduleNames2) => ({
2373
+ persist: true,
2374
+ ignore: mode === "add",
2375
+ moduleName: moduleNames2,
2376
+ operationMethod: options.method,
2377
+ operationPathname: options.pathname
2378
+ }))
2379
+ },
2380
+ interactive: false
1931
2381
  });
1932
2382
  }
2383
+ await compiler.run();
1933
2384
  });
1934
- async function main() {
2385
+ async function main7() {
1935
2386
  program.on("command:*", function(operands) {
1936
2387
  throw new Error(`Unknown command '${String(operands[0])}'`);
1937
2388
  });
@@ -1945,5 +2396,5 @@ async function main() {
1945
2396
  }
1946
2397
  }
1947
2398
  }
1948
- void main();
2399
+ void main7();
1949
2400
  //# sourceMappingURL=cli.cjs.map