adorn-api 1.0.12 → 1.0.14

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 (171) hide show
  1. package/dist/adapter/express/auth.d.ts +8 -0
  2. package/dist/adapter/express/auth.d.ts.map +1 -1
  3. package/dist/adapter/express/bootstrap.d.ts +12 -0
  4. package/dist/adapter/express/bootstrap.d.ts.map +1 -1
  5. package/dist/adapter/express/coercion.d.ts +81 -1
  6. package/dist/adapter/express/coercion.d.ts.map +1 -1
  7. package/dist/adapter/express/index.d.ts +1 -0
  8. package/dist/adapter/express/index.d.ts.map +1 -1
  9. package/dist/adapter/express/merge.d.ts +17 -0
  10. package/dist/adapter/express/merge.d.ts.map +1 -1
  11. package/dist/adapter/express/openapi.d.ts +55 -0
  12. package/dist/adapter/express/openapi.d.ts.map +1 -1
  13. package/dist/adapter/express/router.d.ts +6 -0
  14. package/dist/adapter/express/router.d.ts.map +1 -1
  15. package/dist/adapter/express/swagger.d.ts +6 -0
  16. package/dist/adapter/express/swagger.d.ts.map +1 -1
  17. package/dist/adapter/express/types.d.ts +26 -0
  18. package/dist/adapter/express/types.d.ts.map +1 -1
  19. package/dist/adapter/express/validation.d.ts +19 -2
  20. package/dist/adapter/express/validation.d.ts.map +1 -1
  21. package/dist/cli.cjs +1016 -445
  22. package/dist/cli.cjs.map +1 -1
  23. package/dist/cli.js +1016 -445
  24. package/dist/cli.js.map +1 -1
  25. package/dist/compiler/analyze/index.d.ts +5 -0
  26. package/dist/compiler/analyze/index.d.ts.map +1 -0
  27. package/dist/compiler/analyze/scanControllers.d.ts +52 -0
  28. package/dist/compiler/analyze/scanControllers.d.ts.map +1 -1
  29. package/dist/compiler/cache/isStale.d.ts +26 -0
  30. package/dist/compiler/cache/isStale.d.ts.map +1 -1
  31. package/dist/compiler/cache/loadArtifacts.d.ts +36 -0
  32. package/dist/compiler/cache/loadArtifacts.d.ts.map +1 -1
  33. package/dist/compiler/cache/schema.d.ts +14 -0
  34. package/dist/compiler/cache/schema.d.ts.map +1 -1
  35. package/dist/compiler/cache/writeCache.d.ts +6 -0
  36. package/dist/compiler/cache/writeCache.d.ts.map +1 -1
  37. package/dist/compiler/gems.d.ts +75 -0
  38. package/dist/compiler/gems.d.ts.map +1 -0
  39. package/dist/compiler/generator/index.d.ts +7 -0
  40. package/dist/compiler/generator/index.d.ts.map +1 -0
  41. package/dist/compiler/generator/manifest.d.ts +23 -0
  42. package/dist/compiler/generator/manifest.d.ts.map +1 -0
  43. package/dist/compiler/generator/openapi.d.ts +118 -0
  44. package/dist/compiler/generator/openapi.d.ts.map +1 -0
  45. package/dist/compiler/graph/builder.d.ts +24 -0
  46. package/dist/compiler/graph/builder.d.ts.map +1 -0
  47. package/dist/compiler/graph/index.d.ts +7 -0
  48. package/dist/compiler/graph/index.d.ts.map +1 -0
  49. package/dist/compiler/graph/schemaGraph.d.ts +67 -0
  50. package/dist/compiler/graph/schemaGraph.d.ts.map +1 -0
  51. package/dist/compiler/graph/types.d.ts +203 -0
  52. package/dist/compiler/graph/types.d.ts.map +1 -0
  53. package/dist/compiler/index.d.ts +12 -0
  54. package/dist/compiler/index.d.ts.map +1 -0
  55. package/dist/compiler/ir/index.d.ts +7 -0
  56. package/dist/compiler/ir/index.d.ts.map +1 -0
  57. package/dist/compiler/ir/pipeline.d.ts +82 -0
  58. package/dist/compiler/ir/pipeline.d.ts.map +1 -0
  59. package/dist/compiler/ir/stages.d.ts +40 -0
  60. package/dist/compiler/ir/stages.d.ts.map +1 -0
  61. package/dist/compiler/ir/visitor.d.ts +98 -0
  62. package/dist/compiler/ir/visitor.d.ts.map +1 -0
  63. package/dist/compiler/manifest/emit.d.ts +14 -0
  64. package/dist/compiler/manifest/emit.d.ts.map +1 -1
  65. package/dist/compiler/manifest/format.d.ts +42 -0
  66. package/dist/compiler/manifest/format.d.ts.map +1 -1
  67. package/dist/compiler/manifest/index.d.ts +6 -0
  68. package/dist/compiler/manifest/index.d.ts.map +1 -0
  69. package/dist/compiler/runner/createProgram.d.ts +16 -0
  70. package/dist/compiler/runner/createProgram.d.ts.map +1 -1
  71. package/dist/compiler/runner/index.d.ts +5 -0
  72. package/dist/compiler/runner/index.d.ts.map +1 -0
  73. package/dist/compiler/schema/extractAnnotations.d.ts +47 -0
  74. package/dist/compiler/schema/extractAnnotations.d.ts.map +1 -1
  75. package/dist/compiler/schema/index.d.ts +6 -0
  76. package/dist/compiler/schema/index.d.ts.map +1 -0
  77. package/dist/compiler/schema/intersectionHandler.d.ts +44 -0
  78. package/dist/compiler/schema/intersectionHandler.d.ts.map +1 -0
  79. package/dist/compiler/schema/objectHandler.d.ts +106 -0
  80. package/dist/compiler/schema/objectHandler.d.ts.map +1 -0
  81. package/dist/compiler/schema/openapi.d.ts +16 -1
  82. package/dist/compiler/schema/openapi.d.ts.map +1 -1
  83. package/dist/compiler/schema/parameters.d.ts +90 -0
  84. package/dist/compiler/schema/parameters.d.ts.map +1 -0
  85. package/dist/compiler/schema/primitives.d.ts +68 -0
  86. package/dist/compiler/schema/primitives.d.ts.map +1 -0
  87. package/dist/compiler/schema/typeToJsonSchema.d.ts +22 -51
  88. package/dist/compiler/schema/typeToJsonSchema.d.ts.map +1 -1
  89. package/dist/compiler/schema/types.d.ts +69 -0
  90. package/dist/compiler/schema/types.d.ts.map +1 -0
  91. package/dist/compiler/schema/unionHandler.d.ts +70 -0
  92. package/dist/compiler/schema/unionHandler.d.ts.map +1 -0
  93. package/dist/compiler/transform/dedup.d.ts +35 -0
  94. package/dist/compiler/transform/dedup.d.ts.map +1 -0
  95. package/dist/compiler/transform/flatten.d.ts +50 -0
  96. package/dist/compiler/transform/flatten.d.ts.map +1 -0
  97. package/dist/compiler/transform/index.d.ts +7 -0
  98. package/dist/compiler/transform/index.d.ts.map +1 -0
  99. package/dist/compiler/transform/inline.d.ts +46 -0
  100. package/dist/compiler/transform/inline.d.ts.map +1 -0
  101. package/dist/compiler/validation/emitPrecompiledValidators.d.ts +16 -0
  102. package/dist/compiler/validation/emitPrecompiledValidators.d.ts.map +1 -1
  103. package/dist/compiler/validation/index.d.ts +5 -0
  104. package/dist/compiler/validation/index.d.ts.map +1 -0
  105. package/dist/decorators/Auth.d.ts +17 -0
  106. package/dist/decorators/Auth.d.ts.map +1 -1
  107. package/dist/decorators/Controller.d.ts +15 -0
  108. package/dist/decorators/Controller.d.ts.map +1 -1
  109. package/dist/decorators/Public.d.ts +13 -0
  110. package/dist/decorators/Public.d.ts.map +1 -1
  111. package/dist/decorators/Use.d.ts +18 -0
  112. package/dist/decorators/Use.d.ts.map +1 -1
  113. package/dist/decorators/methods.d.ts +20 -0
  114. package/dist/decorators/methods.d.ts.map +1 -1
  115. package/dist/express.cjs +73 -54
  116. package/dist/express.cjs.map +1 -1
  117. package/dist/express.js +73 -54
  118. package/dist/express.js.map +1 -1
  119. package/dist/http.d.ts +1 -2
  120. package/dist/http.d.ts.map +1 -1
  121. package/dist/index.cjs +161 -4
  122. package/dist/index.cjs.map +1 -1
  123. package/dist/index.d.ts +2 -0
  124. package/dist/index.d.ts.map +1 -1
  125. package/dist/index.js +156 -3
  126. package/dist/index.js.map +1 -1
  127. package/dist/metal/applyListQuery.d.ts +73 -0
  128. package/dist/metal/applyListQuery.d.ts.map +1 -1
  129. package/dist/metal/index.cjs +2 -2
  130. package/dist/metal/index.cjs.map +1 -1
  131. package/dist/metal/index.d.ts +4 -0
  132. package/dist/metal/index.d.ts.map +1 -1
  133. package/dist/metal/index.js +2 -2
  134. package/dist/metal/index.js.map +1 -1
  135. package/dist/metal/listQuery.d.ts +19 -0
  136. package/dist/metal/listQuery.d.ts.map +1 -1
  137. package/dist/metal/queryOptions.d.ts +8 -0
  138. package/dist/metal/queryOptions.d.ts.map +1 -1
  139. package/dist/metal/readMetalBag.d.ts +36 -0
  140. package/dist/metal/readMetalBag.d.ts.map +1 -1
  141. package/dist/metal/registerMetalEntities.d.ts +20 -0
  142. package/dist/metal/registerMetalEntities.d.ts.map +1 -1
  143. package/dist/metal/schemaFromEntity.d.ts +30 -0
  144. package/dist/metal/schemaFromEntity.d.ts.map +1 -1
  145. package/dist/metal/searchWhere.d.ts +39 -0
  146. package/dist/metal/searchWhere.d.ts.map +1 -1
  147. package/dist/metal/symbolMetadata.d.ts +6 -0
  148. package/dist/metal/symbolMetadata.d.ts.map +1 -1
  149. package/dist/runtime/auth/runtime.d.ts +155 -6
  150. package/dist/runtime/auth/runtime.d.ts.map +1 -1
  151. package/dist/runtime/metadata/bucket.d.ts +1 -2
  152. package/dist/runtime/metadata/bucket.d.ts.map +1 -1
  153. package/dist/runtime/metadata/key.d.ts +1 -1
  154. package/dist/runtime/metadata/key.d.ts.map +1 -1
  155. package/dist/runtime/metadata/read.d.ts +1 -2
  156. package/dist/runtime/metadata/read.d.ts.map +1 -1
  157. package/dist/runtime/metadata/types.d.ts +74 -0
  158. package/dist/runtime/metadata/types.d.ts.map +1 -1
  159. package/dist/runtime/polyfill.d.ts +1 -1
  160. package/dist/runtime/polyfill.d.ts.map +1 -1
  161. package/dist/runtime/upload.d.ts +37 -0
  162. package/dist/runtime/upload.d.ts.map +1 -1
  163. package/dist/runtime/validation/ajv.d.ts +100 -0
  164. package/dist/runtime/validation/ajv.d.ts.map +1 -1
  165. package/dist/runtime/validation/index.d.ts +9 -0
  166. package/dist/runtime/validation/index.d.ts.map +1 -1
  167. package/dist/scripts/adorn-example.cjs +238 -6
  168. package/dist/scripts/adorn-example.cjs.map +1 -1
  169. package/dist/utils/port.d.ts +9 -0
  170. package/dist/utils/port.d.ts.map +1 -0
  171. package/package.json +4 -1
@@ -1,7 +1,44 @@
1
+ /**
2
+ * Represents an uploaded file in the request.
3
+ *
4
+ * @remarks
5
+ * This interface describes the structure of a file uploaded via multipart/form-data
6
+ * requests. It provides metadata about the file as well as access to its contents
7
+ * through a readable stream.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * async function handleUpload(file: UploadFile) {
12
+ * console.log(`Received file: ${file.filename}`);
13
+ * console.log(`Type: ${file.mimeType}`);
14
+ * console.log(`Size: ${file.size} bytes`);
15
+ *
16
+ * // Process the file stream
17
+ * for await (const chunk of file.stream) {
18
+ * // Handle chunk...
19
+ * }
20
+ * }
21
+ * ```
22
+ *
23
+ * @public
24
+ */
1
25
  export interface UploadFile {
26
+ /**
27
+ * The original filename as sent by the client.
28
+ */
2
29
  filename: string;
30
+ /**
31
+ * The MIME type of the file (e.g., "image/png", "application/pdf").
32
+ */
3
33
  mimeType: string;
34
+ /**
35
+ * The file size in bytes, if available.
36
+ */
4
37
  size?: number;
38
+ /**
39
+ * A Node.js readable stream to read the file contents.
40
+ * Use this to pipe, transform, or buffer the file data.
41
+ */
5
42
  stream: NodeJS.ReadableStream;
6
43
  }
7
44
  //# sourceMappingURL=upload.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/runtime/upload.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;CAC/B"}
1
+ {"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/runtime/upload.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;CAC/B"}
@@ -1,20 +1,120 @@
1
1
  import Ajv from "ajv";
2
+ /**
3
+ * Runtime validation module using AJV.
4
+ *
5
+ * @remarks
6
+ * This module provides validation utilities using the AJV JSON schema validator.
7
+ * It includes interfaces for validation results, errors, and helper functions
8
+ * for creating validators and formatting error messages.
9
+ *
10
+ * @package
11
+ */
12
+ /**
13
+ * Represents a single validation error with details.
14
+ *
15
+ * @public
16
+ */
2
17
  export interface ValidationError {
18
+ /**
19
+ * The JSON path to the invalid property.
20
+ */
3
21
  path: string;
22
+ /**
23
+ * Human-readable error message.
24
+ */
4
25
  message: string;
26
+ /**
27
+ * The AJV keyword that failed validation.
28
+ */
5
29
  keyword: string;
30
+ /**
31
+ * Additional parameters from the validation error.
32
+ */
6
33
  params: Record<string, unknown>;
7
34
  }
35
+ /**
36
+ * Result of a validation operation.
37
+ *
38
+ * @public
39
+ */
8
40
  export interface ValidationResult {
41
+ /**
42
+ * Whether the data passed validation.
43
+ */
9
44
  valid: boolean;
45
+ /**
46
+ * Array of validation errors if validation failed, null otherwise.
47
+ */
10
48
  errors: ValidationError[] | null;
11
49
  }
50
+ /**
51
+ * Error thrown when request validation fails.
52
+ *
53
+ * @public
54
+ */
12
55
  export declare class ValidationErrorResponse extends Error {
56
+ /**
57
+ * HTTP status code for validation errors.
58
+ */
13
59
  statusCode: number;
60
+ /**
61
+ * Detailed validation errors.
62
+ */
14
63
  errors: ValidationError[];
64
+ /**
65
+ * Creates a new ValidationErrorResponse.
66
+ *
67
+ * @param statusCode - HTTP status code (typically 400)
68
+ * @param errors - Array of validation errors
69
+ */
15
70
  constructor(statusCode: number, errors: ValidationError[]);
16
71
  }
72
+ /**
73
+ * Creates a configured AJV validator instance.
74
+ *
75
+ * @remarks
76
+ * This function creates an AJV validator with adorn-api's default configuration,
77
+ * including support for custom formats like "br-phone" for Brazilian phone numbers.
78
+ *
79
+ * @returns A configured AJV validator instance
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * const validator = createValidator();
84
+ * const validate = validator.compile(mySchema);
85
+ * const result = validate(myData);
86
+ * ```
87
+ *
88
+ * @public
89
+ */
17
90
  export declare function createValidator(): Ajv.Ajv;
91
+ /**
92
+ * Validates data against a JSON schema.
93
+ *
94
+ * @remarks
95
+ * This function compiles the schema and validates the data, returning a
96
+ * structured result with formatted error messages.
97
+ *
98
+ * @param ajv - The AJV validator instance
99
+ * @param data - The data to validate
100
+ * @param schema - The JSON schema to validate against
101
+ * @param dataPath - Base path for error messages (default: "#")
102
+ * @returns ValidationResult with validity and any errors
103
+ *
104
+ * @public
105
+ */
18
106
  export declare function validateData(ajv: ReturnType<typeof createValidator>, data: unknown, schema: Record<string, unknown>, dataPath?: string): ValidationResult;
107
+ /**
108
+ * Formats validation errors into a structured API response.
109
+ *
110
+ * @remarks
111
+ * This function converts validation errors into a format suitable for API
112
+ * responses, grouping errors by their path.
113
+ *
114
+ * @param errors - Array of validation errors
115
+ * @returns Formatted error response object
116
+ *
117
+ * @public
118
+ */
19
119
  export declare function formatValidationErrors(errors: ValidationError[]): Record<string, unknown>;
20
120
  //# sourceMappingURL=ajv.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ajv.d.ts","sourceRoot":"","sources":["../../../src/runtime/validation/ajv.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AAItB,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC;CAClC;AAED,qBAAa,uBAAwB,SAAQ,KAAK;IAEvC,UAAU,EAAE,MAAM;IAClB,MAAM,EAAE,eAAe,EAAE;gBADzB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,eAAe,EAAE;CAKnC;AAED,wBAAgB,eAAe,YAa9B;AAED,wBAAgB,YAAY,CAC1B,GAAG,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,EACvC,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,QAAQ,GAAE,MAAY,GACrB,gBAAgB,CAgBlB;AAgBD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAezF"}
1
+ {"version":3,"file":"ajv.d.ts","sourceRoot":"","sources":["../../../src/runtime/validation/ajv.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AAItB;;;;;;;;;GASG;AAEH;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,KAAK,EAAE,OAAO,CAAC;IAEf;;OAEG;IACH,MAAM,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC;CAClC;AAED;;;;GAIG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IAChD;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,MAAM,EAAE,eAAe,EAAE,CAAC;IAE1B;;;;;OAKG;gBACS,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE;CAM1D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,YAa9B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,EACvC,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,QAAQ,GAAE,MAAY,GACrB,gBAAgB,CAgBlB;AAqBD;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAezF"}
@@ -1,2 +1,11 @@
1
+ /**
2
+ * Re-exports all validation utilities.
3
+ *
4
+ * @remarks
5
+ * This module re-exports the validation functionality provided by the AJV-based
6
+ * validation system, including validation results, errors, and helper functions.
7
+ *
8
+ * @package
9
+ */
1
10
  export * from "./ajv.js";
2
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime/validation/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime/validation/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,cAAc,UAAU,CAAC"}
@@ -24,10 +24,148 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // scripts/adorn-example.ts
27
- var import_child_process = require("child_process");
27
+ var import_child_process2 = require("child_process");
28
28
  var import_path = require("path");
29
29
  var import_fs = require("fs");
30
30
  var import_node_process = __toESM(require("process"), 1);
31
+ var readline = __toESM(require("readline"), 1);
32
+
33
+ // src/utils/port.ts
34
+ var import_net = require("net");
35
+ var import_child_process = require("child_process");
36
+ var import_util = require("util");
37
+ var execAsync = (0, import_util.promisify)(import_child_process.exec);
38
+ async function isPortAvailable(port, host = "0.0.0.0") {
39
+ return new Promise((resolve) => {
40
+ const server = (0, import_net.createServer)();
41
+ server.on("error", (err) => {
42
+ if (err.code === "EADDRINUSE") {
43
+ resolve(false);
44
+ } else {
45
+ resolve(false);
46
+ }
47
+ });
48
+ server.once("listening", () => {
49
+ server.close(() => {
50
+ resolve(true);
51
+ });
52
+ });
53
+ server.listen(port, host);
54
+ });
55
+ }
56
+ async function findProcessOnPort(port) {
57
+ try {
58
+ const platform = process.platform;
59
+ if (platform === "win32") {
60
+ const { stdout } = await execAsync(`netstat -ano | findstr :${port}`);
61
+ for (const line of stdout.split("\n")) {
62
+ const trimmed = line.trim();
63
+ if (!trimmed || trimmed.includes("PID")) continue;
64
+ const parts = trimmed.split(/\s+/);
65
+ if (parts.length >= 5) {
66
+ const address = parts[1];
67
+ const pid = parseInt(parts[parts.length - 1], 10);
68
+ if (address.includes(`:${port}`) && !isNaN(pid)) {
69
+ const command = await getProcessNameOnWindows(pid);
70
+ return { pid, command };
71
+ }
72
+ }
73
+ }
74
+ } else {
75
+ const { stdout } = await execAsync(`lsof -ti:${port}`);
76
+ const pids = stdout.trim().split("\n").filter(Boolean).map(Number);
77
+ if (pids.length > 0) {
78
+ const pid = pids[0];
79
+ const command = await getProcessNameOnUnix(pid);
80
+ return { pid, command };
81
+ }
82
+ }
83
+ return null;
84
+ } catch (error) {
85
+ if (error.message.includes("matches found")) {
86
+ return null;
87
+ }
88
+ return null;
89
+ }
90
+ }
91
+ async function getProcessNameOnWindows(pid) {
92
+ try {
93
+ const { stdout } = await execAsync(`tasklist /FI "PID eq ${pid}" /FO CSV /NH`);
94
+ const line = stdout.trim().split("\n")[0];
95
+ if (line) {
96
+ const parts = line.split('","');
97
+ if (parts.length >= 2) {
98
+ return parts[0].replace(/"/g, "");
99
+ }
100
+ }
101
+ } catch {
102
+ return void 0;
103
+ }
104
+ }
105
+ async function getProcessNameOnUnix(pid) {
106
+ try {
107
+ const { stdout } = await execAsync(`ps -p ${pid} -o comm=`);
108
+ return stdout.trim() || void 0;
109
+ } catch {
110
+ return void 0;
111
+ }
112
+ }
113
+ async function killProcess(pid) {
114
+ try {
115
+ process.kill(pid, "SIGTERM");
116
+ await new Promise((resolve, reject) => {
117
+ const timeout = setTimeout(() => {
118
+ reject(new Error("Process did not terminate gracefully"));
119
+ }, 5e3);
120
+ const check = () => {
121
+ try {
122
+ process.kill(pid, 0);
123
+ setTimeout(check, 500);
124
+ } catch {
125
+ clearInterval(interval);
126
+ clearTimeout(timeout);
127
+ resolve();
128
+ }
129
+ };
130
+ const interval = setInterval(check, 500);
131
+ });
132
+ return true;
133
+ } catch {
134
+ try {
135
+ process.kill(pid, "SIGKILL");
136
+ await new Promise((resolve, reject) => {
137
+ const timeout = setTimeout(() => {
138
+ reject(new Error("Process did not terminate"));
139
+ }, 3e3);
140
+ setTimeout(() => {
141
+ try {
142
+ process.kill(pid, 0);
143
+ clearTimeout(timeout);
144
+ reject(new Error("Process still running"));
145
+ } catch {
146
+ clearTimeout(timeout);
147
+ resolve();
148
+ }
149
+ }, 1e3);
150
+ });
151
+ return true;
152
+ } catch {
153
+ return false;
154
+ }
155
+ }
156
+ }
157
+ async function waitForPort(port, host = "0.0.0.0", timeout = 5e3) {
158
+ const start = Date.now();
159
+ while (Date.now() - start < timeout) {
160
+ if (await isPortAvailable(port, host)) {
161
+ return true;
162
+ }
163
+ await new Promise((resolve) => setTimeout(resolve, 200));
164
+ }
165
+ return false;
166
+ }
167
+
168
+ // scripts/adorn-example.ts
31
169
  function findRepoRoot(startDir) {
32
170
  let current = startDir;
33
171
  while (true) {
@@ -59,12 +197,12 @@ function isWindows() {
59
197
  }
60
198
  function runCommand(command, cwd) {
61
199
  const shell = isWindows() ? "cmd.exe" : "/bin/bash";
62
- (0, import_child_process.execSync)(command, { cwd, stdio: "inherit", shell });
200
+ (0, import_child_process2.execSync)(command, { cwd, stdio: "inherit", shell });
63
201
  }
64
202
  function spawnCommand(args, cwd) {
65
203
  return new Promise((resolve, reject) => {
66
204
  const cmd = isWindows() ? "npm.cmd" : "npm";
67
- const child = (0, import_child_process.spawn)(cmd, args, {
205
+ const child = (0, import_child_process2.spawn)(cmd, args, {
68
206
  cwd,
69
207
  stdio: "inherit",
70
208
  shell: isWindows()
@@ -98,10 +236,86 @@ ${getExamples().map((e) => ` - ${e}`).join("\n")}
98
236
  Options:
99
237
  -h, --help Show this help message
100
238
  -l, --list List all available examples
239
+ -f, --force Force kill process on port without prompting
240
+ -p, --port Specify port (default: 3000, env: ADORN_EXAMPLE_PORT)
101
241
 
102
242
  From the adorn-api project root, you can also use:
103
243
  npm run example <example-name>
104
- `);
244
+ `);
245
+ }
246
+ async function promptWithTimeout(question, timeout = 1e4) {
247
+ const rl = readline.createInterface({
248
+ input: import_node_process.default.stdin,
249
+ output: import_node_process.default.stdout
250
+ });
251
+ let timeoutId = null;
252
+ const timeoutPromise = new Promise((resolve) => {
253
+ timeoutId = setTimeout(() => {
254
+ rl.close();
255
+ console.log("\n\u23F0 Timed out waiting for input");
256
+ resolve(null);
257
+ }, timeout);
258
+ });
259
+ const inputPromise = new Promise((resolve) => {
260
+ rl.question(question, (answer) => {
261
+ if (timeoutId) clearTimeout(timeoutId);
262
+ rl.close();
263
+ resolve(answer.trim());
264
+ });
265
+ });
266
+ return Promise.race([inputPromise, timeoutPromise]);
267
+ }
268
+ async function ensurePortAvailable(targetPort, force) {
269
+ console.log(`
270
+ \u{1F50D} Checking port ${targetPort}...`);
271
+ if (await isPortAvailable(targetPort)) {
272
+ console.log(`\u2713 Port ${targetPort} is available`);
273
+ return;
274
+ }
275
+ console.log(`\u274C Port ${targetPort} is already in use.`);
276
+ const processInfo = await findProcessOnPort(targetPort);
277
+ if (!processInfo) {
278
+ console.error(" Could not determine process using this port");
279
+ console.error(" Please stop it manually or use a different port (ADORN_EXAMPLE_PORT env var)");
280
+ import_node_process.default.exit(1);
281
+ }
282
+ const { pid, command } = processInfo;
283
+ console.log(` Process PID: ${pid}`);
284
+ if (command) {
285
+ console.log(` Command: ${command}`);
286
+ }
287
+ if (force) {
288
+ console.log(`
289
+ Force flag enabled, killing process ${pid}...`);
290
+ } else {
291
+ const answer = await promptWithTimeout(" Kill existing process? (y/n): ", 1e4);
292
+ if (answer === null) {
293
+ console.log("\n\u274C Aborted. Please stop the process manually or use a different port");
294
+ import_node_process.default.exit(1);
295
+ }
296
+ if (answer.toLowerCase() !== "y" && answer.toLowerCase() !== "yes") {
297
+ console.log("\n\u274C Aborted. Please stop the process manually or use a different port");
298
+ console.log(" You can also use the --force flag to auto-kill");
299
+ import_node_process.default.exit(1);
300
+ }
301
+ }
302
+ console.log(` Terminating process ${pid}...`);
303
+ if (await killProcess(pid)) {
304
+ console.log(" \u2713 Process killed successfully");
305
+ console.log(` Waiting for port ${targetPort} to be released...`);
306
+ const released = await waitForPort(targetPort, "0.0.0.0", 3e3);
307
+ if (!released) {
308
+ console.error(`
309
+ \u274C Port ${targetPort} still in use after killing process`);
310
+ import_node_process.default.exit(1);
311
+ }
312
+ console.log(` \u2713 Port ${targetPort} is now available`);
313
+ } else {
314
+ console.error(`
315
+ \u274C Failed to kill process ${pid}`);
316
+ console.error(" You may need to kill it manually or choose a different port");
317
+ import_node_process.default.exit(1);
318
+ }
105
319
  }
106
320
  async function main() {
107
321
  const args = import_node_process.default.argv.slice(2);
@@ -114,7 +328,24 @@ async function main() {
114
328
  getExamples().forEach((ex) => console.log(` - ${ex}`));
115
329
  import_node_process.default.exit(0);
116
330
  }
117
- const example = args[0] || "basic";
331
+ const forceFlag = args.includes("-f") || args.includes("--force");
332
+ const portIndex = args.indexOf("-p") !== -1 ? args.indexOf("-p") : args.indexOf("--port");
333
+ let targetPort = Number(import_node_process.default.env.ADORN_EXAMPLE_PORT || 3e3);
334
+ if (portIndex !== -1 && args[portIndex + 1]) {
335
+ const portArg = Number(args[portIndex + 1]);
336
+ if (!isNaN(portArg) && portArg > 0 && portArg <= 65535) {
337
+ targetPort = portArg;
338
+ } else {
339
+ console.error(`
340
+ \u274C Invalid port number: ${args[portIndex + 1]}`);
341
+ console.error(" Port must be between 1 and 65535");
342
+ import_node_process.default.exit(1);
343
+ }
344
+ }
345
+ const filteredArgs = args.filter(
346
+ (arg) => !["-f", "--force", "-p", "--port"].includes(arg) && (portIndex === -1 || arg !== args[portIndex + 1])
347
+ );
348
+ const example = filteredArgs[0] || "basic";
118
349
  const examplePath = (0, import_path.join)(repoRoot, "examples", example);
119
350
  if (!(0, import_fs.existsSync)(examplePath)) {
120
351
  console.error(`
@@ -137,7 +368,8 @@ async function main() {
137
368
  }
138
369
  console.log("\u{1F4E6} Building artifacts...");
139
370
  runCommand("npm run build", examplePath);
140
- console.log("\u{1F310} Starting server...\n");
371
+ await ensurePortAvailable(targetPort, forceFlag);
372
+ console.log("\n\u{1F310} Starting server...\n");
141
373
  console.log("Press Ctrl+C to stop\n");
142
374
  child = await spawnCommand(["run", "dev"], examplePath);
143
375
  import_node_process.default.on("SIGINT", () => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../scripts/adorn-example.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * Adorn-API Example Runner\n * \n * Usage:\n * npx adorn-example <example-name>\n * npx adorn-example blog-platform\n * npx adorn-example task-manager\n * \n * Or from the adorn-api project root:\n * npm run example <example-name>\n */\n\nimport { execSync, spawn, ChildProcess } from \"child_process\";\nimport { dirname, join } from \"path\";\nimport { existsSync, readdirSync, statSync } from \"fs\";\nimport process from \"node:process\";\n\nfunction findRepoRoot(startDir: string): string | null {\n let current = startDir;\n while (true) {\n const examplesDir = join(current, \"examples\");\n const packageJson = join(current, \"package.json\");\n if (existsSync(examplesDir) && existsSync(packageJson)) {\n return current;\n }\n const parent = dirname(current);\n if (parent === current) {\n return null;\n }\n current = parent;\n }\n}\n\nfunction resolveRepoRoot(): string {\n const candidates = [process.env.INIT_CWD, process.cwd()].filter(\n (dir): dir is string => Boolean(dir),\n );\n\n for (const candidate of candidates) {\n const root = findRepoRoot(candidate);\n if (root) return root;\n }\n\n return process.cwd();\n}\n\nconst repoRoot = resolveRepoRoot();\n\nfunction isWindows(): boolean {\n return process.platform === \"win32\";\n}\n\nfunction runCommand(command: string, cwd: string): void {\n const shell = isWindows() ? \"cmd.exe\" : \"/bin/bash\";\n execSync(command, { cwd, stdio: \"inherit\", shell });\n}\n\nfunction spawnCommand(args: string[], cwd: string): Promise<ChildProcess> {\n return new Promise((resolve, reject) => {\n const cmd = isWindows() ? \"npm.cmd\" : \"npm\";\n const child = spawn(cmd, args, {\n cwd,\n stdio: \"inherit\",\n shell: isWindows(),\n });\n\n child.on(\"error\", reject);\n resolve(child);\n });\n}\n\nfunction getExamples(): string[] {\n const examplesDir = join(repoRoot, \"examples\");\n if (!existsSync(examplesDir)) return [];\n return readdirSync(examplesDir).filter(name => {\n const path = join(examplesDir, name);\n return statSync(path).isDirectory();\n });\n}\n\nfunction printHelp(): void {\n console.log(`\nUsage: npx adorn-example <example-name>\n\nRun an adorn-api example with automatic dependency installation.\n\nExamples:\n npx adorn-example blog-platform\n npx adorn-example task-manager\n npx adorn-example basic\n\nAvailable examples:\n${getExamples().map(e => ` - ${e}`).join(\"\\n\")}\n\nOptions:\n -h, --help Show this help message\n -l, --list List all available examples\n\nFrom the adorn-api project root, you can also use:\n npm run example <example-name>\n`);\n}\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n \n if (args.includes(\"-h\") || args.includes(\"--help\")) {\n printHelp();\n process.exit(0);\n }\n\n if (args.includes(\"-l\") || args.includes(\"--list\")) {\n console.log(\"Available examples:\");\n getExamples().forEach(ex => console.log(` - ${ex}`));\n process.exit(0);\n }\n\n const example = args[0] || \"basic\";\n const examplePath = join(repoRoot, \"examples\", example);\n\n if (!existsSync(examplePath)) {\n console.error(`\\nāŒ Example \"${example}\" not found.\\n`);\n console.log(\"Available examples:\");\n getExamples().forEach(ex => console.log(` - ${ex}`));\n process.exit(1);\n }\n\n console.log(`\\nšŸš€ Running \"${example}\" example...\\n`);\n\n let child: ChildProcess | null = null;\n\n try {\n const nodeModulesPath = join(examplePath, \"node_modules\");\n const nodeModulesExists = existsSync(nodeModulesPath);\n\n if (!nodeModulesExists) {\n console.log(\"šŸ“¦ Installing dependencies...\");\n runCommand(\"npm install\", examplePath);\n }\n\n console.log(\"šŸ“¦ Building artifacts...\");\n runCommand(\"npm run build\", examplePath);\n\n console.log(\"🌐 Starting server...\\n\");\n console.log(\"Press Ctrl+C to stop\\n\");\n\n child = await spawnCommand([\"run\", \"dev\"], examplePath);\n\n process.on(\"SIGINT\", () => {\n if (child) child.kill(\"SIGINT\");\n });\n\n process.on(\"SIGTERM\", () => {\n if (child) child.kill(\"SIGTERM\");\n });\n\n await new Promise<void>((resolve, reject) => {\n if (!child) {\n reject(new Error(\"Child process not started\"));\n return;\n }\n child.on(\"exit\", (code) => {\n if (code === 0 || code === null) {\n resolve();\n } else {\n reject(new Error(`Process exited with code ${code}`));\n }\n });\n child.on(\"error\", reject);\n });\n } catch (err: any) {\n if (err.code !== \"SIGINT\" && err.code !== \"SIGTERM\") {\n console.error(`\\nāŒ Error: ${err.message}`);\n process.exit(1);\n }\n }\n}\n\nmain();\n"],"mappings":"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","names":["process"]}
1
+ {"version":3,"sources":["../../scripts/adorn-example.ts","../../src/utils/port.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * Adorn-API Example Runner\n * \n * Usage:\n * npx adorn-example <example-name>\n * npx adorn-example blog-platform\n * npx adorn-example task-manager\n * \n * Or from the adorn-api project root:\n * npm run example <example-name>\n */\n\nimport { execSync, spawn, ChildProcess } from \"child_process\";\nimport { dirname, join } from \"path\";\nimport { existsSync, readdirSync, statSync } from \"fs\";\nimport process from \"node:process\";\nimport * as readline from \"readline\";\nimport { isPortAvailable, findProcessOnPort, killProcess, waitForPort } from \"../src/utils/port\";\n\nfunction findRepoRoot(startDir: string): string | null {\n let current = startDir;\n while (true) {\n const examplesDir = join(current, \"examples\");\n const packageJson = join(current, \"package.json\");\n if (existsSync(examplesDir) && existsSync(packageJson)) {\n return current;\n }\n const parent = dirname(current);\n if (parent === current) {\n return null;\n }\n current = parent;\n }\n}\n\nfunction resolveRepoRoot(): string {\n const candidates = [process.env.INIT_CWD, process.cwd()].filter(\n (dir): dir is string => Boolean(dir),\n );\n\n for (const candidate of candidates) {\n const root = findRepoRoot(candidate);\n if (root) return root;\n }\n\n return process.cwd();\n}\n\nconst repoRoot = resolveRepoRoot();\n\nfunction isWindows(): boolean {\n return process.platform === \"win32\";\n}\n\nfunction runCommand(command: string, cwd: string): void {\n const shell = isWindows() ? \"cmd.exe\" : \"/bin/bash\";\n execSync(command, { cwd, stdio: \"inherit\", shell });\n}\n\nfunction spawnCommand(args: string[], cwd: string): Promise<ChildProcess> {\n return new Promise((resolve, reject) => {\n const cmd = isWindows() ? \"npm.cmd\" : \"npm\";\n const child = spawn(cmd, args, {\n cwd,\n stdio: \"inherit\",\n shell: isWindows(),\n });\n\n child.on(\"error\", reject);\n resolve(child);\n });\n}\n\nfunction getExamples(): string[] {\n const examplesDir = join(repoRoot, \"examples\");\n if (!existsSync(examplesDir)) return [];\n return readdirSync(examplesDir).filter(name => {\n const path = join(examplesDir, name);\n return statSync(path).isDirectory();\n });\n}\n\nfunction printHelp(): void {\n console.log(`\nUsage: npx adorn-example <example-name>\n\nRun an adorn-api example with automatic dependency installation.\n\nExamples:\n npx adorn-example blog-platform\n npx adorn-example task-manager\n npx adorn-example basic\n\nAvailable examples:\n${getExamples().map(e => ` - ${e}`).join(\"\\n\")}\n\nOptions:\n -h, --help Show this help message\n -l, --list List all available examples\n -f, --force Force kill process on port without prompting\n -p, --port Specify port (default: 3000, env: ADORN_EXAMPLE_PORT)\n\nFrom the adorn-api project root, you can also use:\n npm run example <example-name>\n `);\n}\n\nasync function promptWithTimeout(question: string, timeout: number = 10000): Promise<string | null> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n let timeoutId: NodeJS.Timeout | null = null;\n\n const timeoutPromise = new Promise<string | null>((resolve) => {\n timeoutId = setTimeout(() => {\n rl.close();\n console.log(\"\\nā° Timed out waiting for input\");\n resolve(null);\n }, timeout);\n });\n\n const inputPromise = new Promise<string>((resolve) => {\n rl.question(question, (answer) => {\n if (timeoutId) clearTimeout(timeoutId);\n rl.close();\n resolve(answer.trim());\n });\n });\n\n return Promise.race([inputPromise, timeoutPromise]);\n}\n\nasync function ensurePortAvailable(targetPort: number, force: boolean): Promise<void> {\n console.log(`\\nšŸ” Checking port ${targetPort}...`);\n\n if (await isPortAvailable(targetPort)) {\n console.log(`āœ“ Port ${targetPort} is available`);\n return;\n }\n\n console.log(`āŒ Port ${targetPort} is already in use.`);\n\n const processInfo = await findProcessOnPort(targetPort);\n \n if (!processInfo) {\n console.error(\" Could not determine process using this port\");\n console.error(\" Please stop it manually or use a different port (ADORN_EXAMPLE_PORT env var)\");\n process.exit(1);\n }\n\n const { pid, command } = processInfo;\n console.log(` Process PID: ${pid}`);\n if (command) {\n console.log(` Command: ${command}`);\n }\n\n if (force) {\n console.log(`\\n Force flag enabled, killing process ${pid}...`);\n } else {\n const answer = await promptWithTimeout(\" Kill existing process? (y/n): \", 10000);\n\n if (answer === null) {\n console.log(\"\\nāŒ Aborted. Please stop the process manually or use a different port\");\n process.exit(1);\n }\n\n if (answer.toLowerCase() !== \"y\" && answer.toLowerCase() !== \"yes\") {\n console.log(\"\\nāŒ Aborted. Please stop the process manually or use a different port\");\n console.log(\" You can also use the --force flag to auto-kill\");\n process.exit(1);\n }\n }\n\n console.log(` Terminating process ${pid}...`);\n if (await killProcess(pid)) {\n console.log(\" āœ“ Process killed successfully\");\n\n console.log(` Waiting for port ${targetPort} to be released...`);\n const released = await waitForPort(targetPort, \"0.0.0.0\", 3000);\n\n if (!released) {\n console.error(`\\nāŒ Port ${targetPort} still in use after killing process`);\n process.exit(1);\n }\n \n console.log(` āœ“ Port ${targetPort} is now available`);\n } else {\n console.error(`\\nāŒ Failed to kill process ${pid}`);\n console.error(\" You may need to kill it manually or choose a different port\");\n process.exit(1);\n }\n}\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n \n if (args.includes(\"-h\") || args.includes(\"--help\")) {\n printHelp();\n process.exit(0);\n }\n\n if (args.includes(\"-l\") || args.includes(\"--list\")) {\n console.log(\"Available examples:\");\n getExamples().forEach(ex => console.log(` - ${ex}`));\n process.exit(0);\n }\n\n const forceFlag = args.includes(\"-f\") || args.includes(\"--force\");\n const portIndex = args.indexOf(\"-p\") !== -1 ? args.indexOf(\"-p\") : args.indexOf(\"--port\");\n let targetPort = Number(process.env.ADORN_EXAMPLE_PORT || 3000);\n \n if (portIndex !== -1 && args[portIndex + 1]) {\n const portArg = Number(args[portIndex + 1]);\n if (!isNaN(portArg) && portArg > 0 && portArg <= 65535) {\n targetPort = portArg;\n } else {\n console.error(`\\nāŒ Invalid port number: ${args[portIndex + 1]}`);\n console.error(\" Port must be between 1 and 65535\");\n process.exit(1);\n }\n }\n\n const filteredArgs = args.filter(arg => \n ![\"-f\", \"--force\", \"-p\", \"--port\"].includes(arg) &&\n (portIndex === -1 || arg !== args[portIndex + 1])\n );\n\n const example = filteredArgs[0] || \"basic\";\n const examplePath = join(repoRoot, \"examples\", example);\n\n if (!existsSync(examplePath)) {\n console.error(`\\nāŒ Example \"${example}\" not found.\\n`);\n console.log(\"Available examples:\");\n getExamples().forEach(ex => console.log(` - ${ex}`));\n process.exit(1);\n }\n\n console.log(`\\nšŸš€ Running \"${example}\" example...\\n`);\n\n let child: ChildProcess | null = null;\n\n try {\n const nodeModulesPath = join(examplePath, \"node_modules\");\n const nodeModulesExists = existsSync(nodeModulesPath);\n\n if (!nodeModulesExists) {\n console.log(\"šŸ“¦ Installing dependencies...\");\n runCommand(\"npm install\", examplePath);\n }\n\n console.log(\"šŸ“¦ Building artifacts...\");\n runCommand(\"npm run build\", examplePath);\n\n await ensurePortAvailable(targetPort, forceFlag);\n\n console.log(\"\\n🌐 Starting server...\\n\");\n console.log(\"Press Ctrl+C to stop\\n\");\n\n child = await spawnCommand([\"run\", \"dev\"], examplePath);\n\n process.on(\"SIGINT\", () => {\n if (child) child.kill(\"SIGINT\");\n });\n\n process.on(\"SIGTERM\", () => {\n if (child) child.kill(\"SIGTERM\");\n });\n\n await new Promise<void>((resolve, reject) => {\n if (!child) {\n reject(new Error(\"Child process not started\"));\n return;\n }\n child.on(\"exit\", (code) => {\n if (code === 0 || code === null) {\n resolve();\n } else {\n reject(new Error(`Process exited with code ${code}`));\n }\n });\n child.on(\"error\", reject);\n });\n } catch (err: any) {\n if (err.code !== \"SIGINT\" && err.code !== \"SIGTERM\") {\n console.error(`\\nāŒ Error: ${err.message}`);\n process.exit(1);\n }\n }\n}\n\nmain();\n","import { createServer, Server } from \"net\";\nimport { exec } from \"child_process\";\nimport { promisify } from \"util\";\n\nconst execAsync = promisify(exec);\n\nexport interface ProcessInfo {\n pid: number;\n command?: string;\n}\n\nexport async function isPortAvailable(port: number, host: string = \"0.0.0.0\"): Promise<boolean> {\n return new Promise<boolean>((resolve) => {\n const server: Server = createServer();\n\n server.on(\"error\", (err: any) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n } else {\n resolve(false);\n }\n });\n\n server.once(\"listening\", () => {\n server.close(() => {\n resolve(true);\n });\n });\n\n server.listen(port, host);\n });\n}\n\nexport async function findProcessOnPort(port: number): Promise<ProcessInfo | null> {\n try {\n const platform = process.platform;\n\n if (platform === \"win32\") {\n const { stdout } = await execAsync(`netstat -ano | findstr :${port}`);\n \n for (const line of stdout.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.includes(\"PID\")) continue;\n \n const parts = trimmed.split(/\\s+/);\n if (parts.length >= 5) {\n const address = parts[1];\n const pid = parseInt(parts[parts.length - 1], 10);\n \n if (address.includes(`:${port}`) && !isNaN(pid)) {\n const command = await getProcessNameOnWindows(pid);\n return { pid, command };\n }\n }\n }\n } else {\n const { stdout } = await execAsync(`lsof -ti:${port}`);\n const pids = stdout.trim().split(\"\\n\").filter(Boolean).map(Number);\n \n if (pids.length > 0) {\n const pid = pids[0];\n const command = await getProcessNameOnUnix(pid);\n return { pid, command };\n }\n }\n\n return null;\n } catch (error: any) {\n if (error.message.includes(\"matches found\")) {\n return null;\n }\n return null;\n }\n}\n\nasync function getProcessNameOnWindows(pid: number): Promise<string | undefined> {\n try {\n const { stdout } = await execAsync(`tasklist /FI \"PID eq ${pid}\" /FO CSV /NH`);\n const line = stdout.trim().split(\"\\n\")[0];\n if (line) {\n const parts = line.split('\",\"');\n if (parts.length >= 2) {\n return parts[0].replace(/\"/g, \"\");\n }\n }\n } catch {\n return undefined;\n }\n}\n\nasync function getProcessNameOnUnix(pid: number): Promise<string | undefined> {\n try {\n const { stdout } = await execAsync(`ps -p ${pid} -o comm=`);\n return stdout.trim() || undefined;\n } catch {\n return undefined;\n }\n}\n\nexport async function killProcess(pid: number): Promise<boolean> {\n try {\n process.kill(pid, \"SIGTERM\");\n \n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(\"Process did not terminate gracefully\"));\n }, 5000);\n \n const check = () => {\n try {\n process.kill(pid, 0);\n setTimeout(check, 500);\n } catch {\n clearInterval(interval);\n clearTimeout(timeout);\n resolve();\n }\n };\n \n const interval = setInterval(check, 500);\n });\n \n return true;\n } catch {\n try {\n process.kill(pid, \"SIGKILL\");\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(\"Process did not terminate\"));\n }, 3000);\n \n setTimeout(() => {\n try {\n process.kill(pid, 0);\n clearTimeout(timeout);\n reject(new Error(\"Process still running\"));\n } catch {\n clearTimeout(timeout);\n resolve();\n }\n }, 1000);\n });\n \n return true;\n } catch {\n return false;\n }\n }\n}\n\nexport async function waitForPort(port: number, host: string = \"0.0.0.0\", timeout: number = 5000): Promise<boolean> {\n const start = Date.now();\n \n while (Date.now() - start < timeout) {\n if (await isPortAvailable(port, host)) {\n return true;\n }\n await new Promise(resolve => setTimeout(resolve, 200));\n }\n \n return false;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAcA,IAAAA,wBAA8C;AAC9C,kBAA8B;AAC9B,gBAAkD;AAClD,0BAAoB;AACpB,eAA0B;;;AClB1B,iBAAqC;AACrC,2BAAqB;AACrB,kBAA0B;AAE1B,IAAM,gBAAY,uBAAU,yBAAI;AAOhC,eAAsB,gBAAgB,MAAc,OAAe,WAA6B;AAC9F,SAAO,IAAI,QAAiB,CAAC,YAAY;AACvC,UAAM,aAAiB,yBAAa;AAEpC,WAAO,GAAG,SAAS,CAAC,QAAa;AAC/B,UAAI,IAAI,SAAS,cAAc;AAC7B,gBAAQ,KAAK;AAAA,MACf,OAAO;AACL,gBAAQ,KAAK;AAAA,MACf;AAAA,IACF,CAAC;AAED,WAAO,KAAK,aAAa,MAAM;AAC7B,aAAO,MAAM,MAAM;AACjB,gBAAQ,IAAI;AAAA,MACd,CAAC;AAAA,IACH,CAAC;AAED,WAAO,OAAO,MAAM,IAAI;AAAA,EAC1B,CAAC;AACH;AAEA,eAAsB,kBAAkB,MAA2C;AACjF,MAAI;AACF,UAAM,WAAW,QAAQ;AAEzB,QAAI,aAAa,SAAS;AACxB,YAAM,EAAE,OAAO,IAAI,MAAM,UAAU,2BAA2B,IAAI,EAAE;AAEpE,iBAAW,QAAQ,OAAO,MAAM,IAAI,GAAG;AACrC,cAAM,UAAU,KAAK,KAAK;AAC1B,YAAI,CAAC,WAAW,QAAQ,SAAS,KAAK,EAAG;AAEzC,cAAM,QAAQ,QAAQ,MAAM,KAAK;AACjC,YAAI,MAAM,UAAU,GAAG;AACrB,gBAAM,UAAU,MAAM,CAAC;AACvB,gBAAM,MAAM,SAAS,MAAM,MAAM,SAAS,CAAC,GAAG,EAAE;AAEhD,cAAI,QAAQ,SAAS,IAAI,IAAI,EAAE,KAAK,CAAC,MAAM,GAAG,GAAG;AAC/C,kBAAM,UAAU,MAAM,wBAAwB,GAAG;AACjD,mBAAO,EAAE,KAAK,QAAQ;AAAA,UACxB;AAAA,QACF;AAAA,MACF;AAAA,IACF,OAAO;AACL,YAAM,EAAE,OAAO,IAAI,MAAM,UAAU,YAAY,IAAI,EAAE;AACrD,YAAM,OAAO,OAAO,KAAK,EAAE,MAAM,IAAI,EAAE,OAAO,OAAO,EAAE,IAAI,MAAM;AAEjE,UAAI,KAAK,SAAS,GAAG;AACnB,cAAM,MAAM,KAAK,CAAC;AAClB,cAAM,UAAU,MAAM,qBAAqB,GAAG;AAC9C,eAAO,EAAE,KAAK,QAAQ;AAAA,MACxB;AAAA,IACF;AAEA,WAAO;AAAA,EACT,SAAS,OAAY;AACnB,QAAI,MAAM,QAAQ,SAAS,eAAe,GAAG;AAC3C,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AACF;AAEA,eAAe,wBAAwB,KAA0C;AAC/E,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM,UAAU,wBAAwB,GAAG,eAAe;AAC7E,UAAM,OAAO,OAAO,KAAK,EAAE,MAAM,IAAI,EAAE,CAAC;AACxC,QAAI,MAAM;AACR,YAAM,QAAQ,KAAK,MAAM,KAAK;AAC9B,UAAI,MAAM,UAAU,GAAG;AACrB,eAAO,MAAM,CAAC,EAAE,QAAQ,MAAM,EAAE;AAAA,MAClC;AAAA,IACF;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,qBAAqB,KAA0C;AAC5E,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM,UAAU,SAAS,GAAG,WAAW;AAC1D,WAAO,OAAO,KAAK,KAAK;AAAA,EAC1B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,YAAY,KAA+B;AAC/D,MAAI;AACF,YAAQ,KAAK,KAAK,SAAS;AAE3B,UAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AAC3C,YAAM,UAAU,WAAW,MAAM;AAC/B,eAAO,IAAI,MAAM,sCAAsC,CAAC;AAAA,MAC1D,GAAG,GAAI;AAEP,YAAM,QAAQ,MAAM;AAClB,YAAI;AACF,kBAAQ,KAAK,KAAK,CAAC;AACnB,qBAAW,OAAO,GAAG;AAAA,QACvB,QAAQ;AACN,wBAAc,QAAQ;AACtB,uBAAa,OAAO;AACpB,kBAAQ;AAAA,QACV;AAAA,MACF;AAEA,YAAM,WAAW,YAAY,OAAO,GAAG;AAAA,IACzC,CAAC;AAED,WAAO;AAAA,EACT,QAAQ;AACN,QAAI;AACF,cAAQ,KAAK,KAAK,SAAS;AAC3B,YAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AAC3C,cAAM,UAAU,WAAW,MAAM;AAC/B,iBAAO,IAAI,MAAM,2BAA2B,CAAC;AAAA,QAC/C,GAAG,GAAI;AAEP,mBAAW,MAAM;AACf,cAAI;AACF,oBAAQ,KAAK,KAAK,CAAC;AACnB,yBAAa,OAAO;AACpB,mBAAO,IAAI,MAAM,uBAAuB,CAAC;AAAA,UAC3C,QAAQ;AACN,yBAAa,OAAO;AACpB,oBAAQ;AAAA,UACV;AAAA,QACF,GAAG,GAAI;AAAA,MACT,CAAC;AAED,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,eAAsB,YAAY,MAAc,OAAe,WAAW,UAAkB,KAAwB;AAClH,QAAM,QAAQ,KAAK,IAAI;AAEvB,SAAO,KAAK,IAAI,IAAI,QAAQ,SAAS;AACnC,QAAI,MAAM,gBAAgB,MAAM,IAAI,GAAG;AACrC,aAAO;AAAA,IACT;AACA,UAAM,IAAI,QAAQ,aAAW,WAAW,SAAS,GAAG,CAAC;AAAA,EACvD;AAEA,SAAO;AACT;;;AD5IA,SAAS,aAAa,UAAiC;AACrD,MAAI,UAAU;AACd,SAAO,MAAM;AACX,UAAM,kBAAc,kBAAK,SAAS,UAAU;AAC5C,UAAM,kBAAc,kBAAK,SAAS,cAAc;AAChD,YAAI,sBAAW,WAAW,SAAK,sBAAW,WAAW,GAAG;AACtD,aAAO;AAAA,IACT;AACA,UAAM,aAAS,qBAAQ,OAAO;AAC9B,QAAI,WAAW,SAAS;AACtB,aAAO;AAAA,IACT;AACA,cAAU;AAAA,EACZ;AACF;AAEA,SAAS,kBAA0B;AACjC,QAAM,aAAa,CAAC,oBAAAC,QAAQ,IAAI,UAAU,oBAAAA,QAAQ,IAAI,CAAC,EAAE;AAAA,IACvD,CAAC,QAAuB,QAAQ,GAAG;AAAA,EACrC;AAEA,aAAW,aAAa,YAAY;AAClC,UAAM,OAAO,aAAa,SAAS;AACnC,QAAI,KAAM,QAAO;AAAA,EACnB;AAEA,SAAO,oBAAAA,QAAQ,IAAI;AACrB;AAEA,IAAM,WAAW,gBAAgB;AAEjC,SAAS,YAAqB;AAC5B,SAAO,oBAAAA,QAAQ,aAAa;AAC9B;AAEA,SAAS,WAAW,SAAiB,KAAmB;AACtD,QAAM,QAAQ,UAAU,IAAI,YAAY;AACxC,sCAAS,SAAS,EAAE,KAAK,OAAO,WAAW,MAAM,CAAC;AACpD;AAEA,SAAS,aAAa,MAAgB,KAAoC;AACxE,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,MAAM,UAAU,IAAI,YAAY;AACtC,UAAM,YAAQ,6BAAM,KAAK,MAAM;AAAA,MAC7B;AAAA,MACA,OAAO;AAAA,MACP,OAAO,UAAU;AAAA,IACnB,CAAC;AAED,UAAM,GAAG,SAAS,MAAM;AACxB,YAAQ,KAAK;AAAA,EACf,CAAC;AACH;AAEA,SAAS,cAAwB;AAC/B,QAAM,kBAAc,kBAAK,UAAU,UAAU;AAC7C,MAAI,KAAC,sBAAW,WAAW,EAAG,QAAO,CAAC;AACtC,aAAO,uBAAY,WAAW,EAAE,OAAO,UAAQ;AAC7C,UAAM,WAAO,kBAAK,aAAa,IAAI;AACnC,eAAO,oBAAS,IAAI,EAAE,YAAY;AAAA,EACpC,CAAC;AACH;AAEA,SAAS,YAAkB;AACzB,UAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWZ,YAAY,EAAE,IAAI,OAAK,OAAO,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAU5C;AACH;AAEA,eAAe,kBAAkB,UAAkB,UAAkB,KAA+B;AAClG,QAAM,KAAc,yBAAgB;AAAA,IAClC,OAAO,oBAAAA,QAAQ;AAAA,IACf,QAAQ,oBAAAA,QAAQ;AAAA,EAClB,CAAC;AAED,MAAI,YAAmC;AAEvC,QAAM,iBAAiB,IAAI,QAAuB,CAAC,YAAY;AAC7D,gBAAY,WAAW,MAAM;AAC3B,SAAG,MAAM;AACT,cAAQ,IAAI,sCAAiC;AAC7C,cAAQ,IAAI;AAAA,IACd,GAAG,OAAO;AAAA,EACZ,CAAC;AAED,QAAM,eAAe,IAAI,QAAgB,CAAC,YAAY;AACpD,OAAG,SAAS,UAAU,CAAC,WAAW;AAChC,UAAI,UAAW,cAAa,SAAS;AACrC,SAAG,MAAM;AACT,cAAQ,OAAO,KAAK,CAAC;AAAA,IACvB,CAAC;AAAA,EACH,CAAC;AAED,SAAO,QAAQ,KAAK,CAAC,cAAc,cAAc,CAAC;AACpD;AAEA,eAAe,oBAAoB,YAAoB,OAA+B;AACpF,UAAQ,IAAI;AAAA,0BAAsB,UAAU,KAAK;AAEjD,MAAI,MAAM,gBAAgB,UAAU,GAAG;AACrC,YAAQ,IAAI,eAAU,UAAU,eAAe;AAC/C;AAAA,EACF;AAEA,UAAQ,IAAI,eAAU,UAAU,qBAAqB;AAErD,QAAM,cAAc,MAAM,kBAAkB,UAAU;AAEtD,MAAI,CAAC,aAAa;AAChB,YAAQ,MAAM,gDAAgD;AAC9D,YAAQ,MAAM,iFAAiF;AAC/F,wBAAAA,QAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,EAAE,KAAK,QAAQ,IAAI;AACzB,UAAQ,IAAI,mBAAmB,GAAG,EAAE;AACpC,MAAI,SAAS;AACX,YAAQ,IAAI,eAAe,OAAO,EAAE;AAAA,EACtC;AAEA,MAAI,OAAO;AACT,YAAQ,IAAI;AAAA,yCAA4C,GAAG,KAAK;AAAA,EAClE,OAAO;AACL,UAAM,SAAS,MAAM,kBAAkB,qCAAqC,GAAK;AAEjF,QAAI,WAAW,MAAM;AACnB,cAAQ,IAAI,4EAAuE;AACnF,0BAAAA,QAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,QAAI,OAAO,YAAY,MAAM,OAAO,OAAO,YAAY,MAAM,OAAO;AAClE,cAAQ,IAAI,4EAAuE;AACnF,cAAQ,IAAI,mDAAmD;AAC/D,0BAAAA,QAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAEA,UAAQ,IAAI,0BAA0B,GAAG,KAAK;AAC9C,MAAI,MAAM,YAAY,GAAG,GAAG;AAC1B,YAAQ,IAAI,uCAAkC;AAE9C,YAAQ,IAAI,uBAAuB,UAAU,oBAAoB;AACjE,UAAM,WAAW,MAAM,YAAY,YAAY,WAAW,GAAI;AAE9D,QAAI,CAAC,UAAU;AACb,cAAQ,MAAM;AAAA,cAAY,UAAU,qCAAqC;AACzE,0BAAAA,QAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,YAAQ,IAAI,kBAAa,UAAU,mBAAmB;AAAA,EACxD,OAAO;AACL,YAAQ,MAAM;AAAA,gCAA8B,GAAG,EAAE;AACjD,YAAQ,MAAM,gEAAgE;AAC9E,wBAAAA,QAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,eAAe,OAAsB;AACnC,QAAM,OAAO,oBAAAA,QAAQ,KAAK,MAAM,CAAC;AAEjC,MAAI,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,QAAQ,GAAG;AAClD,cAAU;AACV,wBAAAA,QAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,QAAQ,GAAG;AAClD,YAAQ,IAAI,qBAAqB;AACjC,gBAAY,EAAE,QAAQ,QAAM,QAAQ,IAAI,OAAO,EAAE,EAAE,CAAC;AACpD,wBAAAA,QAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,YAAY,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,SAAS;AAChE,QAAM,YAAY,KAAK,QAAQ,IAAI,MAAM,KAAK,KAAK,QAAQ,IAAI,IAAI,KAAK,QAAQ,QAAQ;AACxF,MAAI,aAAa,OAAO,oBAAAA,QAAQ,IAAI,sBAAsB,GAAI;AAE9D,MAAI,cAAc,MAAM,KAAK,YAAY,CAAC,GAAG;AAC3C,UAAM,UAAU,OAAO,KAAK,YAAY,CAAC,CAAC;AAC1C,QAAI,CAAC,MAAM,OAAO,KAAK,UAAU,KAAK,WAAW,OAAO;AACtD,mBAAa;AAAA,IACf,OAAO;AACL,cAAQ,MAAM;AAAA,8BAA4B,KAAK,YAAY,CAAC,CAAC,EAAE;AAC/D,cAAQ,MAAM,qCAAqC;AACnD,0BAAAA,QAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAEA,QAAM,eAAe,KAAK;AAAA,IAAO,SAC/B,CAAC,CAAC,MAAM,WAAW,MAAM,QAAQ,EAAE,SAAS,GAAG,MAC9C,cAAc,MAAM,QAAQ,KAAK,YAAY,CAAC;AAAA,EACjD;AAEA,QAAM,UAAU,aAAa,CAAC,KAAK;AACnC,QAAM,kBAAc,kBAAK,UAAU,YAAY,OAAO;AAEtD,MAAI,KAAC,sBAAW,WAAW,GAAG;AAC5B,YAAQ,MAAM;AAAA,kBAAgB,OAAO;AAAA,CAAgB;AACrD,YAAQ,IAAI,qBAAqB;AACjC,gBAAY,EAAE,QAAQ,QAAM,QAAQ,IAAI,OAAO,EAAE,EAAE,CAAC;AACpD,wBAAAA,QAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,IAAI;AAAA,qBAAiB,OAAO;AAAA,CAAgB;AAEpD,MAAI,QAA6B;AAEjC,MAAI;AACF,UAAM,sBAAkB,kBAAK,aAAa,cAAc;AACxD,UAAM,wBAAoB,sBAAW,eAAe;AAEpD,QAAI,CAAC,mBAAmB;AACtB,cAAQ,IAAI,sCAA+B;AAC3C,iBAAW,eAAe,WAAW;AAAA,IACvC;AAEA,YAAQ,IAAI,iCAA0B;AACtC,eAAW,iBAAiB,WAAW;AAEvC,UAAM,oBAAoB,YAAY,SAAS;AAE/C,YAAQ,IAAI,kCAA2B;AACvC,YAAQ,IAAI,wBAAwB;AAEpC,YAAQ,MAAM,aAAa,CAAC,OAAO,KAAK,GAAG,WAAW;AAEtD,wBAAAA,QAAQ,GAAG,UAAU,MAAM;AACzB,UAAI,MAAO,OAAM,KAAK,QAAQ;AAAA,IAChC,CAAC;AAED,wBAAAA,QAAQ,GAAG,WAAW,MAAM;AAC1B,UAAI,MAAO,OAAM,KAAK,SAAS;AAAA,IACjC,CAAC;AAED,UAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AAC3C,UAAI,CAAC,OAAO;AACV,eAAO,IAAI,MAAM,2BAA2B,CAAC;AAC7C;AAAA,MACF;AACA,YAAM,GAAG,QAAQ,CAAC,SAAS;AACzB,YAAI,SAAS,KAAK,SAAS,MAAM;AAC/B,kBAAQ;AAAA,QACV,OAAO;AACL,iBAAO,IAAI,MAAM,4BAA4B,IAAI,EAAE,CAAC;AAAA,QACtD;AAAA,MACF,CAAC;AACD,YAAM,GAAG,SAAS,MAAM;AAAA,IAC1B,CAAC;AAAA,EACH,SAAS,KAAU;AACjB,QAAI,IAAI,SAAS,YAAY,IAAI,SAAS,WAAW;AACnD,cAAQ,MAAM;AAAA,gBAAc,IAAI,OAAO,EAAE;AACzC,0BAAAA,QAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AACF;AAEA,KAAK;","names":["import_child_process","process"]}
@@ -0,0 +1,9 @@
1
+ export interface ProcessInfo {
2
+ pid: number;
3
+ command?: string;
4
+ }
5
+ export declare function isPortAvailable(port: number, host?: string): Promise<boolean>;
6
+ export declare function findProcessOnPort(port: number): Promise<ProcessInfo | null>;
7
+ export declare function killProcess(pid: number): Promise<boolean>;
8
+ export declare function waitForPort(port: number, host?: string, timeout?: number): Promise<boolean>;
9
+ //# sourceMappingURL=port.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"port.d.ts","sourceRoot":"","sources":["../../src/utils/port.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CAoB9F;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAwCjF;AA0BD,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAiD/D;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAkB,EAAE,OAAO,GAAE,MAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAWlH"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adorn-api",
3
- "version": "1.0.12",
3
+ "version": "1.0.14",
4
4
  "description": "Stage-3 decorator-first OpenAPI + routing toolkit",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -77,10 +77,13 @@
77
77
  }
78
78
  },
79
79
  "devDependencies": {
80
+ "@eslint/js": "^9.39.2",
80
81
  "@types/express": "^4.17.0",
81
82
  "@types/node": "^20.0.0",
82
83
  "@types/supertest": "^6.0.0",
83
84
  "@types/swagger-ui-express": "^4.1.6",
85
+ "@typescript-eslint/eslint-plugin": "^8.52.0",
86
+ "@typescript-eslint/parser": "^8.52.0",
84
87
  "eslint": "^9.39.2",
85
88
  "express": "^5.2.1",
86
89
  "rimraf": "^6.0.0",