adorn-api 1.0.16 → 1.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -8,7 +8,8 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
8
8
 
9
9
  // src/cli.ts
10
10
  import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, rmSync, existsSync as existsSync2, readFileSync as readFileSync3, statSync } from "fs";
11
- import { resolve as resolve3 } from "path";
11
+ import { resolve as resolve3, dirname as dirname3 } from "path";
12
+ import { fileURLToPath } from "url";
12
13
 
13
14
  // src/compiler/runner/createProgram.ts
14
15
  import ts from "typescript";
@@ -977,7 +978,7 @@ function handleMetalOrmWrapper(type, ctx) {
977
978
  required: ["id"]
978
979
  };
979
980
  if (wrapperName === "ManyToManyCollection" && typeArgs?.[1]) {
980
- wrapperRel.pivot = typeArgs[1];
981
+ wrapperRel.pivot = ctx.checker.typeToString(typeArgs[1]);
981
982
  }
982
983
  return {
983
984
  type: "array",
@@ -987,7 +988,7 @@ function handleMetalOrmWrapper(type, ctx) {
987
988
  }
988
989
  const items = targetType ? typeToJsonSchema(targetType, ctx) : {};
989
990
  if (wrapperName === "ManyToManyCollection" && typeArgs?.[1]) {
990
- wrapperRel.pivot = typeArgs[1];
991
+ wrapperRel.pivot = ctx.checker.typeToString(typeArgs[1]);
991
992
  }
992
993
  return {
993
994
  type: "array",
@@ -1573,7 +1574,12 @@ function generateOpenAPI(controllers, checker, options = {}) {
1573
1574
  mode: "response"
1574
1575
  };
1575
1576
  const paths = {};
1576
- for (const controller of controllers) {
1577
+ const { onProgress } = options;
1578
+ for (let i = 0; i < controllers.length; i++) {
1579
+ const controller = controllers[i];
1580
+ if (onProgress) {
1581
+ onProgress(`Processing controller ${controller.className}`, i + 1, controllers.length);
1582
+ }
1577
1583
  for (const operation of controller.operations) {
1578
1584
  const fullPath = convertToOpenApiPath(controller.basePath, operation.path);
1579
1585
  if (!paths[fullPath]) {
@@ -1584,6 +1590,9 @@ function generateOpenAPI(controllers, checker, options = {}) {
1584
1590
  }
1585
1591
  }
1586
1592
  const schemas = Object.fromEntries(components);
1593
+ if (onProgress) {
1594
+ onProgress("Generating and cleaning schemas", controllers.length, controllers.length);
1595
+ }
1587
1596
  cleanupMetalOrmWrappers(schemas, paths);
1588
1597
  return {
1589
1598
  openapi: "3.1.0",
@@ -2372,7 +2381,7 @@ var ProgressTracker = class {
2372
2381
  }
2373
2382
  if (!this.quiet) {
2374
2383
  const elapsed = phase ? this.formatElapsed(phase.startTime, phase.endTime) : "";
2375
- const status = this.verbose ? `\u2713 ${message || name} ${elapsed}` : `\u2713 ${message || name}`;
2384
+ const status = this.verbose ? `\u2713 ${message || name} ${elapsed}` : `\u2713 ${message || name} ${elapsed}`;
2376
2385
  this.log(status);
2377
2386
  }
2378
2387
  }
@@ -2444,7 +2453,6 @@ var ProgressTracker = class {
2444
2453
  */
2445
2454
  printSummary(stats) {
2446
2455
  if (this.quiet) return;
2447
- const totalTime = this.getTotalElapsed();
2448
2456
  this.log("");
2449
2457
  this.log("Build Summary:");
2450
2458
  this.log(` Controllers: ${stats.controllers}`);
@@ -2481,6 +2489,9 @@ var Spinner = class {
2481
2489
  frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u28B0", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
2482
2490
  interval;
2483
2491
  message;
2492
+ current = 0;
2493
+ total = 0;
2494
+ customStatus;
2484
2495
  constructor(message = "") {
2485
2496
  this.message = message;
2486
2497
  }
@@ -2491,10 +2502,45 @@ var Spinner = class {
2491
2502
  let frameIndex = 0;
2492
2503
  this.interval = setInterval(() => {
2493
2504
  const frame = this.frames[frameIndex];
2494
- process.stdout.write(`\r${frame} ${this.message}`);
2505
+ let output;
2506
+ if (this.customStatus) {
2507
+ output = `\r${frame} ${this.customStatus}`;
2508
+ } else if (this.total > 0) {
2509
+ output = `\r${frame} ${this.message} (${this.current}/${this.total})`;
2510
+ } else {
2511
+ output = `\r${frame} ${this.message}`;
2512
+ }
2513
+ process.stdout.write(output);
2514
+ if (process.stdout.writable) {
2515
+ process.stdout.write("");
2516
+ }
2495
2517
  frameIndex = (frameIndex + 1) % this.frames.length;
2496
2518
  }, 80);
2497
2519
  }
2520
+ /**
2521
+ * Set progress counters.
2522
+ */
2523
+ setProgress(current, total) {
2524
+ this.current = current;
2525
+ this.total = total;
2526
+ }
2527
+ /**
2528
+ * Set a custom status message (overrides counters).
2529
+ */
2530
+ setStatus(status) {
2531
+ this.customStatus = status;
2532
+ const frame = this.frames[this.current];
2533
+ process.stdout.write(`\r${frame} ${status}`);
2534
+ if (process.stdout.writable) {
2535
+ process.stdout.write("");
2536
+ }
2537
+ }
2538
+ /**
2539
+ * Clear the custom status message.
2540
+ */
2541
+ clearStatus() {
2542
+ this.customStatus = void 0;
2543
+ }
2498
2544
  /**
2499
2545
  * Stop the spinner with a completion message.
2500
2546
  */
@@ -2503,10 +2549,13 @@ var Spinner = class {
2503
2549
  clearInterval(this.interval);
2504
2550
  this.interval = void 0;
2505
2551
  }
2506
- process.stdout.write("\r" + " ".repeat(50) + "\r");
2552
+ process.stdout.write("\r" + " ".repeat(60) + "\r");
2507
2553
  if (completedMessage) {
2508
2554
  process.stdout.write(completedMessage + "\n");
2509
2555
  }
2556
+ if (process.stdout.writable) {
2557
+ process.stdout.write("");
2558
+ }
2510
2559
  }
2511
2560
  /**
2512
2561
  * Stop the spinner with a failure message.
@@ -2901,12 +2950,17 @@ function generateModularOpenAPI(openapi, partitioning, config) {
2901
2950
  outputDir,
2902
2951
  schemasDir = "schemas",
2903
2952
  createIndexFile = true,
2904
- prettyPrint = true
2953
+ prettyPrint = true,
2954
+ onProgress
2905
2955
  } = config;
2906
2956
  const indent = prettyPrint ? 2 : 0;
2907
2957
  let totalSize = 0;
2908
2958
  const schemaFiles = [];
2959
+ mkdirSync(outputDir, { recursive: true });
2909
2960
  if (!partitioning.shouldSplit || partitioning.groups.length === 1) {
2961
+ if (onProgress) {
2962
+ onProgress("Writing single OpenAPI file", 1, 1);
2963
+ }
2910
2964
  const mainPath2 = resolve2(outputDir, "openapi.json");
2911
2965
  writeFileSync(mainPath2, JSON.stringify(openapi, null, indent));
2912
2966
  totalSize = Buffer.byteLength(JSON.stringify(openapi));
@@ -2919,9 +2973,16 @@ function generateModularOpenAPI(openapi, partitioning, config) {
2919
2973
  }
2920
2974
  const schemasPath = resolve2(outputDir, schemasDir);
2921
2975
  mkdirSync(schemasPath, { recursive: true });
2976
+ if (onProgress) {
2977
+ onProgress("Creating schemas directory", 0, partitioning.groups.length + 2);
2978
+ }
2922
2979
  const schemaMap = collectAllSchemas(partitioning.groups);
2923
2980
  const schemaToFile = /* @__PURE__ */ new Map();
2924
- for (const group of partitioning.groups) {
2981
+ for (let i = 0; i < partitioning.groups.length; i++) {
2982
+ const group = partitioning.groups[i];
2983
+ if (onProgress) {
2984
+ onProgress(`Writing schema group ${group.name} (${group.schemas.size} schemas)`, i + 1, partitioning.groups.length + 2);
2985
+ }
2925
2986
  const filename = getSchemaFilename(group);
2926
2987
  const filePath = resolve2(outputDir, filename);
2927
2988
  const content = generateSchemaFileContent(group, schemaMap);
@@ -2934,12 +2995,18 @@ function generateModularOpenAPI(openapi, partitioning, config) {
2934
2995
  }
2935
2996
  let indexFile;
2936
2997
  if (createIndexFile) {
2998
+ if (onProgress) {
2999
+ onProgress("Generating index file", partitioning.groups.length + 1, partitioning.groups.length + 2);
3000
+ }
2937
3001
  const indexPath = resolve2(outputDir, "schemas/index.json");
2938
3002
  const indexContent = generateSchemaIndex(partitioning.groups, schemaMap);
2939
3003
  writeFileSync(indexPath, JSON.stringify(indexContent, null, indent));
2940
3004
  totalSize += Buffer.byteLength(JSON.stringify(indexContent));
2941
3005
  indexFile = indexPath;
2942
3006
  }
3007
+ if (onProgress) {
3008
+ onProgress("Generating main OpenAPI spec", partitioning.groups.length + 2, partitioning.groups.length + 2);
3009
+ }
2943
3010
  const mainSpec = generateMainSpec(openapi, schemaMap, schemaToFile);
2944
3011
  const mainPath = resolve2(outputDir, "openapi.json");
2945
3012
  writeFileSync(mainPath, JSON.stringify(mainSpec, null, indent));
@@ -3270,7 +3337,27 @@ var SchemaGraph = class {
3270
3337
  // src/cli.ts
3271
3338
  import ts13 from "typescript";
3272
3339
  import process2 from "process";
3273
- var ADORN_VERSION = "0.1.0";
3340
+ var ADORN_VERSION = (() => {
3341
+ const tryReadPackageJson = (filePath) => {
3342
+ try {
3343
+ const pkg = JSON.parse(readFileSync3(filePath, "utf-8"));
3344
+ return pkg.version ?? null;
3345
+ } catch {
3346
+ return null;
3347
+ }
3348
+ };
3349
+ const cliDir = dirname3(fileURLToPath(import.meta.url));
3350
+ const bundledPkgPath = resolve3(cliDir, "..", "package.json");
3351
+ const bundledVersion = tryReadPackageJson(bundledPkgPath);
3352
+ if (bundledVersion) return bundledVersion;
3353
+ const localPkgPath = resolve3(process2.cwd(), "package.json");
3354
+ const localVersion = tryReadPackageJson(localPkgPath);
3355
+ if (localVersion) return localVersion;
3356
+ const nodeModulesPath = resolve3(cliDir, "..", "package.json");
3357
+ const nodeModulesVersion = tryReadPackageJson(nodeModulesPath);
3358
+ if (nodeModulesVersion) return nodeModulesVersion;
3359
+ return "0.0.0";
3360
+ })();
3274
3361
  function log(msg, options) {
3275
3362
  if (options?.indent) {
3276
3363
  process2.stdout.write(" " + msg + "\n");
@@ -3463,10 +3550,21 @@ async function buildCommand(args) {
3463
3550
  }
3464
3551
  }
3465
3552
  progress.startPhase("openapi", "Generating OpenAPI schema");
3466
- if (verbose) {
3467
- progress.verboseLog("Processing schemas from type definitions");
3553
+ const openapiSpinner = new Spinner("Processing schemas");
3554
+ if (!quiet) openapiSpinner.start();
3555
+ const openapi = generateOpenAPI(controllers, checker, {
3556
+ title: "API",
3557
+ version: "1.0.0",
3558
+ onProgress: (message, current, total) => {
3559
+ if (!quiet) {
3560
+ openapiSpinner.setStatus(`${message} (${current}/${total})`);
3561
+ }
3562
+ }
3563
+ });
3564
+ if (!quiet) {
3565
+ openapiSpinner.setStatus(`Processed ${controllers.length} controllers, ${totalOperations} operations`);
3468
3566
  }
3469
- const openapi = generateOpenAPI(controllers, checker, { title: "API", version: "1.0.0" });
3567
+ if (!quiet) openapiSpinner.stop();
3470
3568
  const schemaCount = Object.keys(openapi.components?.schemas || {}).length;
3471
3569
  let splitEnabled = false;
3472
3570
  if (!noSplit && schemaCount >= splitThreshold) {
@@ -3484,14 +3582,24 @@ async function buildCommand(args) {
3484
3582
  if (splitEnabled) {
3485
3583
  progress.verboseLog(`Partitioning result: ${partitioning.strategy} strategy`);
3486
3584
  progress.verboseLog(`Recommendation: ${partitioning.recommendation}`);
3585
+ if (!quiet) {
3586
+ log(` Auto-split enabled: ${partitioning.strategy} strategy`);
3587
+ }
3588
+ const splitSpinner = new Spinner("Writing split schema files");
3589
+ if (!quiet) splitSpinner.start();
3487
3590
  generateModularOpenAPI(openapi, partitioning, {
3488
3591
  outputDir: outputPath,
3489
3592
  schemasDir: "schemas",
3490
3593
  createIndexFile: true,
3491
- prettyPrint: true
3594
+ prettyPrint: true,
3595
+ onProgress: (step, index, total) => {
3596
+ if (!quiet) {
3597
+ progress.logSub(`${step} (${index}/${total})`);
3598
+ }
3599
+ }
3492
3600
  });
3601
+ if (!quiet) splitSpinner.stop();
3493
3602
  if (!quiet) {
3494
- log(` Auto-split enabled: ${partitioning.strategy} strategy`);
3495
3603
  log(` Schema groups: ${partitioning.groups.length}`);
3496
3604
  }
3497
3605
  } else {