@keq-request/cli 5.0.0-alpha.26 → 5.0.0-alpha.28

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 (46) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/cli.cjs +132 -86
  3. package/dist/cli.cjs.map +1 -1
  4. package/dist/cli.js +132 -86
  5. package/dist/cli.js.map +1 -1
  6. package/dist/compiler/compiler.d.ts.map +1 -1
  7. package/dist/compiler/tasks/setup/index.d.ts.map +1 -1
  8. package/dist/compiler/tasks/setup/utils/index.d.ts +0 -1
  9. package/dist/compiler/tasks/setup/utils/index.d.ts.map +1 -1
  10. package/dist/compiler/tasks/setup/utils/parse-runtime-config.d.ts +3 -0
  11. package/dist/compiler/tasks/setup/utils/parse-runtime-config.d.ts.map +1 -0
  12. package/dist/compiler/types/compiler-context.d.ts +1 -1
  13. package/dist/compiler/types/compiler-context.d.ts.map +1 -1
  14. package/dist/compiler/types/compiler-hooks.d.ts +2 -1
  15. package/dist/compiler/types/compiler-hooks.d.ts.map +1 -1
  16. package/dist/define-config.d.ts +3 -0
  17. package/dist/define-config.d.ts.map +1 -0
  18. package/dist/index.cjs +137 -93
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.ts +2 -2
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +136 -91
  23. package/dist/index.js.map +1 -1
  24. package/dist/models/module-definition.d.ts +3 -2
  25. package/dist/models/module-definition.d.ts.map +1 -1
  26. package/dist/plugins/download-http-file/download-http-file.plugin.d.ts +2 -2
  27. package/dist/plugins/download-http-file/download-http-file.plugin.d.ts.map +1 -1
  28. package/dist/plugins/download-local-file/download-local-file.plugin.d.ts.map +1 -1
  29. package/dist/plugins/shaking/shaking.plugin.d.ts.map +1 -1
  30. package/dist/plugins.cjs +25 -12
  31. package/dist/plugins.cjs.map +1 -1
  32. package/dist/plugins.js +25 -12
  33. package/dist/plugins.js.map +1 -1
  34. package/dist/types/address.d.ts +8 -0
  35. package/dist/types/address.d.ts.map +1 -0
  36. package/dist/types/index.d.ts +2 -1
  37. package/dist/types/index.d.ts.map +1 -1
  38. package/dist/types/runtime-config.d.ts +16 -7
  39. package/dist/types/runtime-config.d.ts.map +1 -1
  40. package/dist/utils/is-valid-url.d.ts +16 -0
  41. package/dist/utils/is-valid-url.d.ts.map +1 -0
  42. package/package.json +3 -3
  43. package/dist/compiler/tasks/setup/utils/validate-modules.d.ts +0 -2
  44. package/dist/compiler/tasks/setup/utils/validate-modules.d.ts.map +0 -1
  45. package/dist/define-keq-config.d.ts +0 -3
  46. package/dist/define-keq-config.d.ts.map +0 -1
package/dist/cli.js CHANGED
@@ -30,7 +30,6 @@ import { AsyncParallelHook, AsyncSeriesBailHook, AsyncSeriesHook, SyncHook } fro
30
30
  // src/compiler/tasks/setup/index.ts
31
31
  import fs3 from "fs-extra";
32
32
  import path2 from "path";
33
- import { Value } from "@sinclair/typebox/value";
34
33
  import { cosmiconfig } from "cosmiconfig";
35
34
 
36
35
  // src/utils/ignore-matcher.ts
@@ -124,8 +123,51 @@ var IgnoreMatcher = class _IgnoreMatcher {
124
123
  }
125
124
  };
126
125
 
127
- // src/types/runtime-config.ts
126
+ // src/compiler/tasks/setup/utils/find-nearest-package-json.ts
127
+ import fs2 from "fs";
128
+ import path from "path";
129
+ function findNearestPackageJson(startDir = process.cwd()) {
130
+ let dir = startDir;
131
+ while (true) {
132
+ const pkgPath = path.join(dir, "package.json");
133
+ if (fs2.existsSync(pkgPath)) {
134
+ const json = JSON.parse(fs2.readFileSync(pkgPath, "utf8"));
135
+ return { json, path: pkgPath };
136
+ }
137
+ const parent = path.dirname(dir);
138
+ if (parent === dir) break;
139
+ dir = parent;
140
+ }
141
+ return null;
142
+ }
143
+
144
+ // src/compiler/tasks/setup/utils/get-project-module-system.ts
145
+ function getProjectModuleSystem(pkgInfo) {
146
+ if (!pkgInfo?.json) return "cjs";
147
+ const { json } = pkgInfo;
148
+ if (json.type === "module") return "esm";
149
+ return "cjs";
150
+ }
151
+
152
+ // src/compiler/tasks/setup/utils/parse-runtime-config.ts
153
+ import { Value } from "@sinclair/typebox/value";
154
+
155
+ // src/types/address.ts
128
156
  import { Type } from "@sinclair/typebox";
157
+ var Address = Type.Object({
158
+ url: Type.String(),
159
+ headers: Type.Optional(Type.Record(Type.String(), Type.String(), { default: {} })),
160
+ encoding: Type.Optional(
161
+ Type.Union([
162
+ Type.Literal("utf8"),
163
+ Type.Literal("ascii")
164
+ ], { default: "utf8" })
165
+ )
166
+ });
167
+
168
+ // src/types/runtime-config.ts
169
+ import * as R2 from "ramda";
170
+ import { Type as Type2 } from "@sinclair/typebox";
129
171
 
130
172
  // src/constants/file-naming-style.ts
131
173
  var FileNamingStyle = /* @__PURE__ */ ((FileNamingStyle2) => {
@@ -143,13 +185,48 @@ var FileNamingStyle = /* @__PURE__ */ ((FileNamingStyle2) => {
143
185
  return FileNamingStyle2;
144
186
  })(FileNamingStyle || {});
145
187
 
188
+ // src/utils/is-valid-url.ts
189
+ var URL_REGEX = /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\/(?:[^\s@]+@)?[^\s/:?#]*(?::\d+)?(?:\/[^\s?#]*)?(?:\?[^\s#]*)?(?:#[^\s]*)?$/;
190
+ function isValidURL(url) {
191
+ return URL_REGEX.test(url);
192
+ }
193
+
146
194
  // src/types/runtime-config.ts
147
- var RuntimeConfig = Type.Object({
148
- mode: Type.Optional(
149
- Type.Union([
150
- Type.Literal("micro-function"),
151
- Type.Literal("nestjs-module"),
152
- Type.Literal("none")
195
+ var Modules = Type2.Transform(
196
+ Type2.Record(
197
+ Type2.String(),
198
+ Type2.Union([Type2.String(), Address])
199
+ )
200
+ ).Decode((value) => {
201
+ const keys2 = Object.keys(value);
202
+ for (const key of keys2) {
203
+ if (!/^[A-Za-z_][A-Za-z0-9_$]*$/.test(key)) {
204
+ 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.`);
205
+ }
206
+ }
207
+ const keysGroupByLowerCase = R2.groupBy(R2.toLower, keys2);
208
+ for (const groupKey in keysGroupByLowerCase) {
209
+ const keys3 = keysGroupByLowerCase[groupKey] || [];
210
+ if (keys3.length > 1) {
211
+ throw new Error(`Module names ${keys3.map((name) => `"${name}"`).join(", ")} are case-insensitively duplicated.`);
212
+ }
213
+ }
214
+ for (const key in value) {
215
+ const url = typeof value[key] === "string" ? value[key] : value[key].url;
216
+ if (isValidURL(url)) continue;
217
+ throw new Error(`The ${JSON.stringify(url)} of module "${key}" is not a valid URL.`);
218
+ }
219
+ return R2.map(
220
+ (item) => typeof item !== "string" ? item : { url: item, headers: {}, encoding: "utf8" },
221
+ value
222
+ );
223
+ }).Encode((value) => value);
224
+ var RawConfig = Type2.Object({
225
+ mode: Type2.Optional(
226
+ Type2.Union([
227
+ Type2.Literal("micro-function"),
228
+ Type2.Literal("nestjs-module"),
229
+ Type2.Literal("none")
153
230
  ], { default: "micro-function" })
154
231
  ),
155
232
  /**
@@ -158,77 +235,39 @@ var RuntimeConfig = Type.Object({
158
235
  * If not specified, the module system will be inferred from the nearest package.json "type" field
159
236
  * or defaults to "cjs" if no package.json is found.
160
237
  */
161
- esm: Type.Optional(Type.Boolean({ default: false })),
238
+ esm: Type2.Optional(Type2.Boolean({ default: false })),
162
239
  /**
163
240
  * Output directory for generated files
164
241
  */
165
- outdir: Type.String({ default: `${process.cwd()}/api` }),
242
+ outdir: Type2.String({ default: `${process.cwd()}/api` }),
166
243
  /**
167
244
  * File naming style for generated files
168
245
  */
169
- fileNamingStyle: Type.Enum(FileNamingStyle, { default: "snakeCase" /* snakeCase */ }),
170
- modules: Type.Record(Type.String(), Type.String()),
171
- debug: Type.Optional(Type.Boolean({ default: false })),
246
+ fileNamingStyle: Type2.Enum(FileNamingStyle, { default: "snakeCase" /* snakeCase */ }),
247
+ modules: Modules,
248
+ debug: Type2.Optional(Type2.Boolean({ default: false })),
172
249
  /**
173
250
  * Whether to tolerate wrong openapi/swagger structure
174
251
  */
175
- tolerant: Type.Optional(Type.Boolean({ default: false })),
176
- plugins: Type.Optional(Type.Array(Type.Any(), { default: [] }))
252
+ tolerant: Type2.Optional(Type2.Boolean({ default: false })),
253
+ plugins: Type2.Optional(Type2.Array(Type2.Unsafe(Type2.Any()), { default: [] }))
177
254
  });
178
255
 
179
- // src/compiler/tasks/setup/utils/validate-modules.ts
180
- import * as R2 from "ramda";
181
- import validator from "validator";
182
- function validateModules(modules) {
183
- const keys2 = Object.keys(modules);
184
- for (const key of keys2) {
185
- if (!/^[A-Za-z_][A-Za-z0-9_$]*$/.test(key)) {
186
- 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.`);
187
- }
188
- }
189
- const keysGroupByLowerCase = R2.groupBy(R2.toLower, keys2);
190
- for (const groupKey in keysGroupByLowerCase) {
191
- const keys3 = keysGroupByLowerCase[groupKey] || [];
192
- if (keys3.length > 1) {
193
- throw new Error(`Module names ${keys3.map((name) => `"${name}"`).join(", ")} are case-insensitively duplicated.`);
194
- }
195
- }
196
- for (const key in modules) {
197
- const address = modules[key];
198
- if (validator.isURL(address, { require_host: true, require_protocol: true, protocols: ["http", "https"] })) {
199
- continue;
200
- }
201
- if (/^(\/|\.\/|\.\.\/)/.test(address)) {
202
- continue;
256
+ // src/compiler/tasks/setup/utils/parse-runtime-config.ts
257
+ function parseRuntimeConfig(data) {
258
+ try {
259
+ const originalPlugins = typeof data === "object" && data !== null && "plugins" in data ? data.plugins : void 0;
260
+ const parsed = Value.Parse(RawConfig, data);
261
+ if (originalPlugins !== void 0) {
262
+ parsed.plugins = originalPlugins;
203
263
  }
204
- throw new Error(`Module address "${address}" of module "${key}" is not valid. It must be a URL or a local path.`);
205
- }
206
- }
207
-
208
- // src/compiler/tasks/setup/utils/find-nearest-package-json.ts
209
- import fs2 from "fs";
210
- import path from "path";
211
- function findNearestPackageJson(startDir = process.cwd()) {
212
- let dir = startDir;
213
- while (true) {
214
- const pkgPath = path.join(dir, "package.json");
215
- if (fs2.existsSync(pkgPath)) {
216
- const json = JSON.parse(fs2.readFileSync(pkgPath, "utf8"));
217
- return { json, path: pkgPath };
264
+ return parsed;
265
+ } catch (error) {
266
+ if (error instanceof Error) {
267
+ error.message = `Invalid Config: ${error.message}`;
218
268
  }
219
- const parent = path.dirname(dir);
220
- if (parent === dir) break;
221
- dir = parent;
269
+ throw error;
222
270
  }
223
- return null;
224
- }
225
-
226
- // src/compiler/tasks/setup/utils/get-project-module-system.ts
227
- function getProjectModuleSystem(pkgInfo) {
228
- if (!pkgInfo?.json) return "cjs";
229
- const { json } = pkgInfo;
230
- if (json.type === "module") return "esm";
231
- return "cjs";
232
271
  }
233
272
 
234
273
  // src/compiler/tasks/setup/index.ts
@@ -240,13 +279,7 @@ function main(compiler, options) {
240
279
  if (!result || "isEmpty" in result && result.isEmpty) {
241
280
  throw new Error("Cannot find config file.");
242
281
  }
243
- if (!Value.Check(RuntimeConfig, result.config)) {
244
- const errors = [...Value.Errors(RuntimeConfig, result.config)];
245
- const message = errors.map(({ path: path13, message: message2 }) => `${path13}: ${message2}`).join("\n");
246
- throw new Error(`Invalid Config: ${message}`);
247
- }
248
- const rc = Value.Default(RuntimeConfig, result.config);
249
- validateModules(rc.modules);
282
+ const rc = parseRuntimeConfig(result.config);
250
283
  if (options?.debug) {
251
284
  await fs3.ensureDir(".keq");
252
285
  rc.debug = true;
@@ -410,10 +443,14 @@ var ModuleDefinition = class _ModuleDefinition {
410
443
  address;
411
444
  constructor(name, address) {
412
445
  this.name = name;
413
- this.address = address;
446
+ if (typeof address === "string") {
447
+ this.address = { url: address, headers: {}, encoding: "utf8" };
448
+ } else {
449
+ this.address = address;
450
+ }
414
451
  }
415
452
  static unknown() {
416
- return new _ModuleDefinition("", "");
453
+ return new _ModuleDefinition("", { url: "", headers: {}, encoding: "utf8" });
417
454
  }
418
455
  };
419
456
 
@@ -878,10 +915,10 @@ function main2(compiler, options) {
878
915
  task2.skip(`(${moduleDefinition.name}) is ignored`);
879
916
  return;
880
917
  }
881
- task2.output = `Downloaded from ${moduleDefinition.address}`;
918
+ task2.output = `Downloaded from ${moduleDefinition.address.url}`;
882
919
  const content = await compiler.hooks.download.promise(moduleDefinition.address, moduleDefinition, task2);
883
920
  if (!content) {
884
- throw new Exception(moduleDefinition, `Cannot download document from ${moduleDefinition.address}`);
921
+ throw new Exception(moduleDefinition, `Cannot download document from ${moduleDefinition.address.url}`);
885
922
  }
886
923
  const spec = JSON.parse(content);
887
924
  const { valid, errors } = await validate(spec);
@@ -2540,24 +2577,25 @@ var GenerateNestjsModulePlugin = class _GenerateNestjsModulePlugin {
2540
2577
  import { fixSwagger } from "swagger-fix";
2541
2578
 
2542
2579
  // src/plugins/download-http-file/download-http-file.plugin.ts
2543
- import * as validUrl from "valid-url";
2544
2580
  var DownloadHttpFilePlugin = class _DownloadHttpFilePlugin {
2545
2581
  apply(compiler) {
2546
2582
  compiler.hooks.download.tapPromise(_DownloadHttpFilePlugin.name, async (address, task) => {
2547
- if (!validUrl.isUri(address)) return void 0;
2583
+ const { url } = address;
2584
+ if (!url.startsWith("http://") && !url.startsWith("https://")) return void 0;
2548
2585
  const content = await this.download(address);
2549
2586
  const spec = this.deserialize(content);
2550
2587
  return JSON.stringify(spec);
2551
2588
  });
2552
2589
  }
2553
2590
  async download(address) {
2591
+ const { url, headers } = address;
2554
2592
  try {
2555
- const res = await fetch(address);
2593
+ const res = await fetch(url, { headers });
2556
2594
  if (res.status >= 400) throw new Error(`failed with status code ${res.status}`);
2557
2595
  return await res.text();
2558
2596
  } catch (e) {
2559
2597
  if (e instanceof Error) {
2560
- e.message = `Unable get the openapi/swagger file from ${address}: ${e.message}`;
2598
+ e.message = `Unable get the openapi/swagger file from ${url}: ${e.message}`;
2561
2599
  }
2562
2600
  throw e;
2563
2601
  }
@@ -2573,17 +2611,21 @@ var DownloadHttpFilePlugin = class _DownloadHttpFilePlugin {
2573
2611
  import * as path12 from "path";
2574
2612
  import * as fs5 from "fs/promises";
2575
2613
  import * as yaml from "js-yaml";
2614
+ import { fileURLToPath } from "url";
2576
2615
  var DownloadLocalFilePlugin = class _DownloadLocalFilePlugin {
2577
2616
  apply(compiler) {
2578
2617
  compiler.hooks.download.tapPromise(_DownloadLocalFilePlugin.name, async (address, task) => {
2579
- if (!address.startsWith("./") && !address.startsWith("/") && !address.startsWith("../")) return void 0;
2580
- const fileExt = path12.extname(address);
2581
- const content = await fs5.readFile(address, "utf8");
2618
+ const { url, encoding } = address;
2619
+ if (!url.startsWith("file://")) return void 0;
2620
+ const filepath = fileURLToPath(url);
2621
+ const fileExt = path12.extname(filepath);
2622
+ const content = await fs5.readFile(filepath, encoding);
2623
+ const str = typeof content === "string" ? content : content.toString(encoding);
2582
2624
  if ([".yml", ".yaml"].includes(fileExt)) {
2583
- const value = yaml.load(content);
2625
+ const value = yaml.load(str);
2584
2626
  return JSON.stringify(OpenapiUtils.to3_1(value));
2585
2627
  } else if (fileExt === ".json") {
2586
- return JSON.stringify(OpenapiUtils.to3_1(JSON.parse(content)));
2628
+ return JSON.stringify(OpenapiUtils.to3_1(JSON.parse(str)));
2587
2629
  }
2588
2630
  });
2589
2631
  }
@@ -2621,7 +2663,11 @@ var ShakingPlugin = class _ShakingPlugin {
2621
2663
  sharkedSwagger,
2622
2664
  new ModuleDefinition(
2623
2665
  document.module.name,
2624
- `file://${document.module.name}.v3_1.sharked.json`
2666
+ {
2667
+ url: `memory://${document.module.name}.v3_1.sharked.json`,
2668
+ headers: {},
2669
+ encoding: "utf8"
2670
+ }
2625
2671
  )
2626
2672
  );
2627
2673
  }