@kubb/cli 4.32.3 → 4.33.0

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 (137) hide show
  1. package/dist/agent-CJ69TqoO.js +87 -0
  2. package/dist/agent-CJ69TqoO.js.map +1 -0
  3. package/dist/agent-CduUX7Ye.cjs +91 -0
  4. package/dist/agent-CduUX7Ye.cjs.map +1 -0
  5. package/dist/agent-D0A3RQho.js +57 -0
  6. package/dist/agent-D0A3RQho.js.map +1 -0
  7. package/dist/agent-DrnwQBZf.cjs +60 -0
  8. package/dist/agent-DrnwQBZf.cjs.map +1 -0
  9. package/dist/constants-CEKRremI.js +79 -0
  10. package/dist/constants-CEKRremI.js.map +1 -0
  11. package/dist/constants-CnPOlsJq.cjs +126 -0
  12. package/dist/constants-CnPOlsJq.cjs.map +1 -0
  13. package/dist/errors-BUjJsNoe.cjs +44 -0
  14. package/dist/errors-BUjJsNoe.cjs.map +1 -0
  15. package/dist/errors-bSLTEh4e.js +27 -0
  16. package/dist/errors-bSLTEh4e.js.map +1 -0
  17. package/dist/{generate-DFdkL6Kp.cjs → generate-ByMgAV76.cjs} +423 -577
  18. package/dist/generate-ByMgAV76.cjs.map +1 -0
  19. package/dist/generate-CiUPO5ds.cjs +65 -0
  20. package/dist/generate-CiUPO5ds.cjs.map +1 -0
  21. package/dist/generate-DIIxtkWT.js +66 -0
  22. package/dist/generate-DIIxtkWT.js.map +1 -0
  23. package/dist/{generate-zZuxBP8z.js → generate-HP5ySfjV.js} +422 -577
  24. package/dist/generate-HP5ySfjV.js.map +1 -0
  25. package/dist/index.cjs +226 -35
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.ts +1 -1
  28. package/dist/index.js +226 -35
  29. package/dist/index.js.map +1 -1
  30. package/dist/init-Cd1hCb7q.cjs +296 -0
  31. package/dist/init-Cd1hCb7q.cjs.map +1 -0
  32. package/dist/init-DLNrkDF4.js +25 -0
  33. package/dist/init-DLNrkDF4.js.map +1 -0
  34. package/dist/init-Df_aXezV.cjs +24 -0
  35. package/dist/init-Df_aXezV.cjs.map +1 -0
  36. package/dist/init-DyKK2fTp.js +291 -0
  37. package/dist/init-DyKK2fTp.js.map +1 -0
  38. package/dist/jiti-BdskUHhD.cjs +16 -0
  39. package/dist/jiti-BdskUHhD.cjs.map +1 -0
  40. package/dist/jiti-Cl7t20dO.js +11 -0
  41. package/dist/jiti-Cl7t20dO.js.map +1 -0
  42. package/dist/mcp-B73FC8dF.cjs +42 -0
  43. package/dist/mcp-B73FC8dF.cjs.map +1 -0
  44. package/dist/mcp-Bd9LITaI.js +16 -0
  45. package/dist/mcp-Bd9LITaI.js.map +1 -0
  46. package/dist/mcp-Cf-1dsB-.js +41 -0
  47. package/dist/mcp-Cf-1dsB-.js.map +1 -0
  48. package/dist/mcp-Clg-Qnkr.cjs +15 -0
  49. package/dist/mcp-Clg-Qnkr.cjs.map +1 -0
  50. package/dist/package-681jTtCk.js +6 -0
  51. package/dist/package-681jTtCk.js.map +1 -0
  52. package/dist/{package-C2pulzfz.cjs → package-aKgzEJtp.cjs} +2 -2
  53. package/dist/package-aKgzEJtp.cjs.map +1 -0
  54. package/dist/{telemetry-DYWvlxqs.js → telemetry-C4gOKX2x.js} +31 -10
  55. package/dist/telemetry-C4gOKX2x.js.map +1 -0
  56. package/dist/{telemetry-BDSSqUiG.cjs → telemetry-T5IA2dWA.cjs} +40 -7
  57. package/dist/telemetry-T5IA2dWA.cjs.map +1 -0
  58. package/dist/types-CLtz0jem.js +25 -0
  59. package/dist/types-CLtz0jem.js.map +1 -0
  60. package/dist/types-Ck2lzFON.cjs +36 -0
  61. package/dist/types-Ck2lzFON.cjs.map +1 -0
  62. package/dist/validate-Chjg23AE.js +41 -0
  63. package/dist/validate-Chjg23AE.js.map +1 -0
  64. package/dist/validate-Cr26q5xX.js +25 -0
  65. package/dist/validate-Cr26q5xX.js.map +1 -0
  66. package/dist/validate-DURmg-2Q.cjs +24 -0
  67. package/dist/validate-DURmg-2Q.cjs.map +1 -0
  68. package/dist/validate-Dqi9T_c4.cjs +42 -0
  69. package/dist/validate-Dqi9T_c4.cjs.map +1 -0
  70. package/package.json +5 -6
  71. package/src/cli/adapters/nodeAdapter.ts +159 -0
  72. package/src/cli/help.ts +36 -0
  73. package/src/cli/index.ts +16 -0
  74. package/src/cli/parse.ts +18 -0
  75. package/src/cli/schema.ts +38 -0
  76. package/src/cli/types.ts +95 -0
  77. package/src/commands/agent/start.ts +27 -136
  78. package/src/commands/agent.ts +6 -25
  79. package/src/commands/generate.ts +26 -158
  80. package/src/commands/init.ts +9 -360
  81. package/src/commands/mcp.ts +7 -52
  82. package/src/commands/validate.ts +9 -60
  83. package/src/constants.ts +77 -0
  84. package/src/index.ts +36 -42
  85. package/src/loggers/clackLogger.ts +42 -140
  86. package/src/loggers/fileSystemLogger.ts +1 -12
  87. package/src/loggers/githubActionsLogger.ts +36 -101
  88. package/src/loggers/plainLogger.ts +23 -70
  89. package/src/loggers/utils.ts +66 -2
  90. package/src/runners/agent.ts +100 -0
  91. package/src/runners/generate.ts +208 -100
  92. package/src/runners/init.ts +322 -0
  93. package/src/runners/mcp.ts +32 -0
  94. package/src/runners/validate.ts +35 -0
  95. package/src/utils/Writables.ts +2 -2
  96. package/src/utils/envDetection.ts +34 -0
  97. package/src/utils/errors.ts +23 -0
  98. package/src/utils/executeHooks.ts +18 -6
  99. package/src/utils/getCosmiConfig.ts +10 -11
  100. package/src/utils/getIntro.ts +17 -18
  101. package/src/utils/getSummary.ts +11 -15
  102. package/src/utils/jiti.ts +9 -0
  103. package/src/utils/packageManager.ts +3 -3
  104. package/src/utils/randomColor.ts +3 -12
  105. package/src/utils/runHook.ts +75 -0
  106. package/src/utils/spawnAsync.ts +47 -0
  107. package/src/utils/telemetry.ts +8 -25
  108. package/src/utils/watcher.ts +2 -4
  109. package/dist/agent-BuijLPSZ.cjs +0 -20
  110. package/dist/agent-BuijLPSZ.cjs.map +0 -1
  111. package/dist/agent-Dswt_kxP.js +0 -20
  112. package/dist/agent-Dswt_kxP.js.map +0 -1
  113. package/dist/generate-DFdkL6Kp.cjs.map +0 -1
  114. package/dist/generate-zZuxBP8z.js.map +0 -1
  115. package/dist/init-CNLk2fNd.js +0 -304
  116. package/dist/init-CNLk2fNd.js.map +0 -1
  117. package/dist/init-CSP6FGaW.cjs +0 -308
  118. package/dist/init-CSP6FGaW.cjs.map +0 -1
  119. package/dist/mcp-44Od-yig.cjs +0 -57
  120. package/dist/mcp-44Od-yig.cjs.map +0 -1
  121. package/dist/mcp-CgaHrkDs.js +0 -57
  122. package/dist/mcp-CgaHrkDs.js.map +0 -1
  123. package/dist/package--eaEMq2R.js +0 -6
  124. package/dist/package--eaEMq2R.js.map +0 -1
  125. package/dist/package-C2pulzfz.cjs.map +0 -1
  126. package/dist/start-CB8afXV6.cjs +0 -134
  127. package/dist/start-CB8afXV6.cjs.map +0 -1
  128. package/dist/start-DHPjtHJj.js +0 -131
  129. package/dist/start-DHPjtHJj.js.map +0 -1
  130. package/dist/telemetry-BDSSqUiG.cjs.map +0 -1
  131. package/dist/telemetry-DYWvlxqs.js.map +0 -1
  132. package/dist/validate-C7s0cFnp.cjs +0 -66
  133. package/dist/validate-C7s0cFnp.cjs.map +0 -1
  134. package/dist/validate-_7cmvjg_.js +0 -66
  135. package/dist/validate-_7cmvjg_.js.map +0 -1
  136. package/src/loggers/envDetection.ts +0 -28
  137. package/src/loggers/index.ts +0 -5
@@ -1,23 +1,44 @@
1
1
  import "./chunk--u3MIqq1.js";
2
+ import { n as OTLP_ENDPOINT } from "./constants-CEKRremI.js";
2
3
  import { randomBytes } from "node:crypto";
3
4
  import os from "node:os";
4
- import process from "node:process";
5
+ import process$1 from "node:process";
5
6
  import { executeIfOnline } from "@kubb/core/utils";
7
+ //#region src/utils/envDetection.ts
8
+ /**
9
+ * Check if running in GitHub Actions environment
10
+ */
11
+ function isGitHubActions() {
12
+ return !!process.env.GITHUB_ACTIONS;
13
+ }
14
+ /**
15
+ * Check if running in any CI environment.
16
+ * Covers all major CI systems via their well-known environment variables.
17
+ */
18
+ function isCIEnvironment() {
19
+ return !!(process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITLAB_CI || process.env.BITBUCKET_BUILD_NUMBER || process.env.JENKINS_URL || process.env.CIRCLECI || process.env.TRAVIS || process.env.TEAMCITY_VERSION || process.env.BUILDKITE || process.env.TF_BUILD);
20
+ }
21
+ /**
22
+ * Check if TTY is available for interactive output
23
+ */
24
+ function canUseTTY() {
25
+ return !!process.stdout.isTTY && !isCIEnvironment();
26
+ }
27
+ //#endregion
6
28
  //#region src/utils/telemetry.ts
7
- const OTLP_ENDPOINT = "https://otlp.kubb.dev";
8
29
  /**
9
- * Detect whether the current process is running inside a CI environment by
10
- * checking the well-known environment variables set by all major CI systems.
30
+ * Detect whether the current process is running inside a CI environment.
31
+ * Delegates to the canonical isCIEnvironment() from envDetection.
11
32
  */
12
33
  function isCi() {
13
- return !!(process.env["CI"] || process.env["GITHUB_ACTIONS"] || process.env["GITLAB_CI"] || process.env["BITBUCKET_BUILD_NUMBER"] || process.env["JENKINS_URL"] || process.env["CIRCLECI"] || process.env["TRAVIS"] || process.env["TEAMCITY_VERSION"] || process.env["BUILDKITE"] || process.env["TF_BUILD"]);
34
+ return isCIEnvironment();
14
35
  }
15
36
  /**
16
37
  * Check if telemetry is disabled via DO_NOT_TRACK or KUBB_DISABLE_TELEMETRY.
17
38
  * Respects the standard DO_NOT_TRACK convention used across development tools.
18
39
  */
19
40
  function isTelemetryDisabled() {
20
- return process.env["DO_NOT_TRACK"] === "1" || process.env["DO_NOT_TRACK"] === "true" || process.env["KUBB_DISABLE_TELEMETRY"] === "1" || process.env["KUBB_DISABLE_TELEMETRY"] === "true";
41
+ return process$1.env["DO_NOT_TRACK"] === "1" || process$1.env["DO_NOT_TRACK"] === "true" || process$1.env["KUBB_DISABLE_TELEMETRY"] === "1" || process$1.env["KUBB_DISABLE_TELEMETRY"] === "true";
21
42
  }
22
43
  /**
23
44
  * Convert a TelemetryEvent into an OTLP-compatible JSON trace payload.
@@ -131,12 +152,12 @@ async function sendTelemetry(event) {
131
152
  * No file paths, OpenAPI specs, or secrets are included.
132
153
  */
133
154
  function buildTelemetryEvent(options) {
134
- const [seconds, nanoseconds] = process.hrtime(options.hrStart);
155
+ const [seconds, nanoseconds] = process$1.hrtime(options.hrStart);
135
156
  const duration = Math.round(seconds * 1e3 + nanoseconds / 1e6);
136
157
  return {
137
158
  command: options.command,
138
159
  kubbVersion: options.kubbVersion,
139
- nodeVersion: process.versions.node.split(".")[0] ?? "unknown",
160
+ nodeVersion: process$1.versions.node.split(".")[0],
140
161
  platform: os.platform(),
141
162
  ci: isCi(),
142
163
  plugins: options.plugins ?? [],
@@ -146,6 +167,6 @@ function buildTelemetryEvent(options) {
146
167
  };
147
168
  }
148
169
  //#endregion
149
- export { isTelemetryDisabled as n, sendTelemetry as r, buildTelemetryEvent as t };
170
+ export { isGitHubActions as a, canUseTTY as i, isTelemetryDisabled as n, sendTelemetry as r, buildTelemetryEvent as t };
150
171
 
151
- //# sourceMappingURL=telemetry-DYWvlxqs.js.map
172
+ //# sourceMappingURL=telemetry-C4gOKX2x.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry-C4gOKX2x.js","names":["process"],"sources":["../src/utils/envDetection.ts","../src/utils/telemetry.ts"],"sourcesContent":["/**\n * Check if running in GitHub Actions environment\n */\nexport function isGitHubActions(): boolean {\n return !!process.env.GITHUB_ACTIONS\n}\n\n/**\n * Check if running in any CI environment.\n * Covers all major CI systems via their well-known environment variables.\n */\nexport function isCIEnvironment(): boolean {\n return !!(\n (\n process.env.CI || // Generic (GitHub Actions, GitLab CI, CircleCI, Travis CI, etc.)\n process.env.GITHUB_ACTIONS || // GitHub Actions\n process.env.GITLAB_CI || // GitLab CI\n process.env.BITBUCKET_BUILD_NUMBER || // Bitbucket Pipelines\n process.env.JENKINS_URL || // Jenkins\n process.env.CIRCLECI || // CircleCI\n process.env.TRAVIS || // Travis CI\n process.env.TEAMCITY_VERSION || // TeamCity\n process.env.BUILDKITE || // Buildkite\n process.env.TF_BUILD\n ) // Azure Pipelines\n )\n}\n\n/**\n * Check if TTY is available for interactive output\n */\nexport function canUseTTY(): boolean {\n return !!process.stdout.isTTY && !isCIEnvironment()\n}\n","import { randomBytes } from 'node:crypto'\nimport os from 'node:os'\nimport process from 'node:process'\nimport { executeIfOnline } from '@kubb/core/utils'\nimport { OTLP_ENDPOINT } from '../constants.ts'\nimport { isCIEnvironment } from './envDetection.ts'\n\n// OpenTelemetry OTLP JSON types\n// https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/trace/v1/trace.proto\n// https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/common/v1/common.proto\n\ntype OtlpStringValue = { stringValue: string }\ntype OtlpBoolValue = { boolValue: boolean }\ntype OtlpIntValue = { intValue: number }\ntype OtlpDoubleValue = { doubleValue: number }\ntype OtlpBytesValue = { bytesValue: string }\ntype OtlpArrayValue = { arrayValue: { values: OtlpAnyValue[] } }\ntype OtlpKvListValue = { kvlistValue: { values: OtlpKeyValue[] } }\n\ntype OtlpAnyValue = OtlpStringValue | OtlpBoolValue | OtlpIntValue | OtlpDoubleValue | OtlpBytesValue | OtlpArrayValue | OtlpKvListValue\n\ntype OtlpKeyValue = {\n key: string\n value: OtlpAnyValue\n}\n\ntype OtlpResource = {\n attributes: OtlpKeyValue[]\n droppedAttributesCount?: number\n}\n\ntype OtlpInstrumentationScope = {\n name: string\n version?: string\n attributes?: OtlpKeyValue[]\n droppedAttributesCount?: number\n}\n\n/** https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/trace/v1/trace.proto#L103 */\ntype OtlpSpanKind = 0 | 1 | 2 | 3 | 4 | 5\n\n/** 0 = STATUS_CODE_UNSET, 1 = STATUS_CODE_OK, 2 = STATUS_CODE_ERROR */\ntype OtlpStatusCode = 0 | 1 | 2\n\ntype OtlpStatus = {\n code: OtlpStatusCode\n message?: string\n}\n\ntype OtlpSpan = {\n traceId: string\n spanId: string\n traceState?: string\n parentSpanId?: string\n name: string\n kind: OtlpSpanKind\n startTimeUnixNano: string\n endTimeUnixNano: string\n attributes?: OtlpKeyValue[]\n droppedAttributesCount?: number\n events?: OtlpSpanEvent[]\n droppedEventsCount?: number\n links?: OtlpSpanLink[]\n droppedLinksCount?: number\n status?: OtlpStatus\n}\n\ntype OtlpSpanEvent = {\n timeUnixNano: string\n name: string\n attributes?: OtlpKeyValue[]\n droppedAttributesCount?: number\n}\n\ntype OtlpSpanLink = {\n traceId: string\n spanId: string\n traceState?: string\n attributes?: OtlpKeyValue[]\n droppedAttributesCount?: number\n}\n\ntype OtlpScopeSpans = {\n scope: OtlpInstrumentationScope\n spans: OtlpSpan[]\n schemaUrl?: string\n}\n\ntype OtlpResourceSpans = {\n resource: OtlpResource\n scopeSpans: OtlpScopeSpans[]\n schemaUrl?: string\n}\n\n/** Root payload sent to POST /v1/traces */\ntype OtlpExportTraceServiceRequest = {\n resourceSpans: OtlpResourceSpans[]\n}\n\nexport type TelemetryPlugin = {\n name: string\n options: Record<string, unknown>\n}\n\ntype TelemetryEvent = {\n command: string\n kubbVersion: string\n nodeVersion: string\n platform: string\n ci: boolean\n plugins: TelemetryPlugin[]\n duration: number\n filesCreated: number\n status: 'success' | 'failed'\n}\n\n/**\n * Detect whether the current process is running inside a CI environment.\n * Delegates to the canonical isCIEnvironment() from envDetection.\n */\nexport function isCi(): boolean {\n return isCIEnvironment()\n}\n\n/**\n * Check if telemetry is disabled via DO_NOT_TRACK or KUBB_DISABLE_TELEMETRY.\n * Respects the standard DO_NOT_TRACK convention used across development tools.\n */\nexport function isTelemetryDisabled(): boolean {\n return (\n process.env['DO_NOT_TRACK'] === '1' ||\n process.env['DO_NOT_TRACK'] === 'true' ||\n process.env['KUBB_DISABLE_TELEMETRY'] === '1' ||\n process.env['KUBB_DISABLE_TELEMETRY'] === 'true'\n )\n}\n\n/**\n * Convert a TelemetryEvent into an OTLP-compatible JSON trace payload.\n * See https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/\n */\nexport function buildOtlpPayload(event: TelemetryEvent): OtlpExportTraceServiceRequest {\n const traceId = randomBytes(16).toString('hex')\n const spanId = randomBytes(8).toString('hex')\n const endTimeNs = BigInt(Date.now()) * 1_000_000n\n const startTimeNs = endTimeNs - BigInt(event.duration) * 1_000_000n\n\n const attributes: OtlpKeyValue[] = [\n { key: 'kubb.command', value: { stringValue: event.command } },\n { key: 'kubb.version', value: { stringValue: event.kubbVersion } },\n { key: 'kubb.node_version', value: { stringValue: event.nodeVersion } },\n { key: 'kubb.platform', value: { stringValue: event.platform } },\n { key: 'kubb.ci', value: { boolValue: event.ci } },\n { key: 'kubb.files_created', value: { intValue: event.filesCreated } },\n { key: 'kubb.status', value: { stringValue: event.status } },\n {\n key: 'kubb.plugins',\n value: {\n arrayValue: {\n values: event.plugins.map(\n (p): OtlpKvListValue => ({\n kvlistValue: {\n values: [\n { key: 'name', value: { stringValue: p.name } },\n { key: 'options', value: { stringValue: JSON.stringify({ ...p.options, usedEnumNames: undefined }) } },\n ],\n },\n }),\n ),\n },\n },\n },\n ]\n\n return {\n resourceSpans: [\n {\n resource: {\n attributes: [\n { key: 'service.name', value: { stringValue: 'kubb-cli' } },\n { key: 'service.version', value: { stringValue: event.kubbVersion } },\n { key: 'telemetry.sdk.language', value: { stringValue: 'nodejs' } },\n ],\n },\n scopeSpans: [\n {\n scope: { name: 'kubb-cli', version: event.kubbVersion },\n spans: [\n {\n traceId,\n spanId,\n name: event.command,\n kind: 1 satisfies OtlpSpanKind,\n startTimeUnixNano: String(startTimeNs),\n endTimeUnixNano: String(endTimeNs),\n attributes,\n status: { code: (event.status === 'success' ? 1 : 2) satisfies OtlpStatusCode },\n },\n ],\n },\n ],\n },\n ],\n }\n}\n\n/**\n * Send an anonymous telemetry event to the Kubb OTLP endpoint.\n * Respects DO_NOT_TRACK and KUBB_DISABLE_TELEMETRY environment variables.\n * Fails silently to never interrupt the generation process.\n */\nexport async function sendTelemetry(event: TelemetryEvent): Promise<void> {\n if (isTelemetryDisabled()) {\n return\n }\n\n await executeIfOnline(async () => {\n try {\n await fetch(`${OTLP_ENDPOINT}/v1/traces`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Kubb-Telemetry-Version': '1',\n 'Kubb-Telemetry-Source': 'kubb-cli',\n },\n body: JSON.stringify(buildOtlpPayload(event)),\n signal: AbortSignal.timeout(5_000),\n })\n } catch (_e) {\n // Fail silently – telemetry must never break the CLI\n }\n })\n}\n\n/**\n * Build an anonymous telemetry payload from a completed generation run.\n * No file paths, OpenAPI specs, or secrets are included.\n */\nexport function buildTelemetryEvent(options: {\n command: 'generate' | 'mcp' | 'validate' | 'agent'\n kubbVersion: string\n plugins?: TelemetryPlugin[]\n hrStart: [number, number]\n filesCreated?: number\n status: 'success' | 'failed'\n}): TelemetryEvent {\n const [seconds, nanoseconds] = process.hrtime(options.hrStart)\n const duration = Math.round(seconds * 1000 + nanoseconds / 1e6)\n\n return {\n command: options.command,\n kubbVersion: options.kubbVersion,\n nodeVersion: process.versions.node.split('.')[0] as string,\n platform: os.platform(),\n ci: isCi(),\n plugins: options.plugins ?? [],\n duration,\n filesCreated: options.filesCreated ?? 0,\n status: options.status,\n }\n}\n"],"mappings":"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"}
@@ -1,18 +1,39 @@
1
1
  const require_chunk = require("./chunk-ByKO4r7w.cjs");
2
+ const require_constants = require("./constants-CnPOlsJq.cjs");
2
3
  let node_crypto = require("node:crypto");
3
4
  let node_os = require("node:os");
4
5
  node_os = require_chunk.__toESM(node_os);
5
6
  let node_process = require("node:process");
6
7
  node_process = require_chunk.__toESM(node_process);
7
8
  let _kubb_core_utils = require("@kubb/core/utils");
9
+ //#region src/utils/envDetection.ts
10
+ /**
11
+ * Check if running in GitHub Actions environment
12
+ */
13
+ function isGitHubActions() {
14
+ return !!process.env.GITHUB_ACTIONS;
15
+ }
16
+ /**
17
+ * Check if running in any CI environment.
18
+ * Covers all major CI systems via their well-known environment variables.
19
+ */
20
+ function isCIEnvironment() {
21
+ return !!(process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITLAB_CI || process.env.BITBUCKET_BUILD_NUMBER || process.env.JENKINS_URL || process.env.CIRCLECI || process.env.TRAVIS || process.env.TEAMCITY_VERSION || process.env.BUILDKITE || process.env.TF_BUILD);
22
+ }
23
+ /**
24
+ * Check if TTY is available for interactive output
25
+ */
26
+ function canUseTTY() {
27
+ return !!process.stdout.isTTY && !isCIEnvironment();
28
+ }
29
+ //#endregion
8
30
  //#region src/utils/telemetry.ts
9
- const OTLP_ENDPOINT = "https://otlp.kubb.dev";
10
31
  /**
11
- * Detect whether the current process is running inside a CI environment by
12
- * checking the well-known environment variables set by all major CI systems.
32
+ * Detect whether the current process is running inside a CI environment.
33
+ * Delegates to the canonical isCIEnvironment() from envDetection.
13
34
  */
14
35
  function isCi() {
15
- return !!(node_process.default.env["CI"] || node_process.default.env["GITHUB_ACTIONS"] || node_process.default.env["GITLAB_CI"] || node_process.default.env["BITBUCKET_BUILD_NUMBER"] || node_process.default.env["JENKINS_URL"] || node_process.default.env["CIRCLECI"] || node_process.default.env["TRAVIS"] || node_process.default.env["TEAMCITY_VERSION"] || node_process.default.env["BUILDKITE"] || node_process.default.env["TF_BUILD"]);
36
+ return isCIEnvironment();
16
37
  }
17
38
  /**
18
39
  * Check if telemetry is disabled via DO_NOT_TRACK or KUBB_DISABLE_TELEMETRY.
@@ -115,7 +136,7 @@ async function sendTelemetry(event) {
115
136
  if (isTelemetryDisabled()) return;
116
137
  await (0, _kubb_core_utils.executeIfOnline)(async () => {
117
138
  try {
118
- await fetch(`${OTLP_ENDPOINT}/v1/traces`, {
139
+ await fetch(`${require_constants.OTLP_ENDPOINT}/v1/traces`, {
119
140
  method: "POST",
120
141
  headers: {
121
142
  "Content-Type": "application/json",
@@ -138,7 +159,7 @@ function buildTelemetryEvent(options) {
138
159
  return {
139
160
  command: options.command,
140
161
  kubbVersion: options.kubbVersion,
141
- nodeVersion: node_process.default.versions.node.split(".")[0] ?? "unknown",
162
+ nodeVersion: node_process.default.versions.node.split(".")[0],
142
163
  platform: node_os.default.platform(),
143
164
  ci: isCi(),
144
165
  plugins: options.plugins ?? [],
@@ -154,6 +175,18 @@ Object.defineProperty(exports, "buildTelemetryEvent", {
154
175
  return buildTelemetryEvent;
155
176
  }
156
177
  });
178
+ Object.defineProperty(exports, "canUseTTY", {
179
+ enumerable: true,
180
+ get: function() {
181
+ return canUseTTY;
182
+ }
183
+ });
184
+ Object.defineProperty(exports, "isGitHubActions", {
185
+ enumerable: true,
186
+ get: function() {
187
+ return isGitHubActions;
188
+ }
189
+ });
157
190
  Object.defineProperty(exports, "isTelemetryDisabled", {
158
191
  enumerable: true,
159
192
  get: function() {
@@ -167,4 +200,4 @@ Object.defineProperty(exports, "sendTelemetry", {
167
200
  }
168
201
  });
169
202
 
170
- //# sourceMappingURL=telemetry-BDSSqUiG.cjs.map
203
+ //# sourceMappingURL=telemetry-T5IA2dWA.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry-T5IA2dWA.cjs","names":["process","OTLP_ENDPOINT","os"],"sources":["../src/utils/envDetection.ts","../src/utils/telemetry.ts"],"sourcesContent":["/**\n * Check if running in GitHub Actions environment\n */\nexport function isGitHubActions(): boolean {\n return !!process.env.GITHUB_ACTIONS\n}\n\n/**\n * Check if running in any CI environment.\n * Covers all major CI systems via their well-known environment variables.\n */\nexport function isCIEnvironment(): boolean {\n return !!(\n (\n process.env.CI || // Generic (GitHub Actions, GitLab CI, CircleCI, Travis CI, etc.)\n process.env.GITHUB_ACTIONS || // GitHub Actions\n process.env.GITLAB_CI || // GitLab CI\n process.env.BITBUCKET_BUILD_NUMBER || // Bitbucket Pipelines\n process.env.JENKINS_URL || // Jenkins\n process.env.CIRCLECI || // CircleCI\n process.env.TRAVIS || // Travis CI\n process.env.TEAMCITY_VERSION || // TeamCity\n process.env.BUILDKITE || // Buildkite\n process.env.TF_BUILD\n ) // Azure Pipelines\n )\n}\n\n/**\n * Check if TTY is available for interactive output\n */\nexport function canUseTTY(): boolean {\n return !!process.stdout.isTTY && !isCIEnvironment()\n}\n","import { randomBytes } from 'node:crypto'\nimport os from 'node:os'\nimport process from 'node:process'\nimport { executeIfOnline } from '@kubb/core/utils'\nimport { OTLP_ENDPOINT } from '../constants.ts'\nimport { isCIEnvironment } from './envDetection.ts'\n\n// OpenTelemetry OTLP JSON types\n// https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/trace/v1/trace.proto\n// https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/common/v1/common.proto\n\ntype OtlpStringValue = { stringValue: string }\ntype OtlpBoolValue = { boolValue: boolean }\ntype OtlpIntValue = { intValue: number }\ntype OtlpDoubleValue = { doubleValue: number }\ntype OtlpBytesValue = { bytesValue: string }\ntype OtlpArrayValue = { arrayValue: { values: OtlpAnyValue[] } }\ntype OtlpKvListValue = { kvlistValue: { values: OtlpKeyValue[] } }\n\ntype OtlpAnyValue = OtlpStringValue | OtlpBoolValue | OtlpIntValue | OtlpDoubleValue | OtlpBytesValue | OtlpArrayValue | OtlpKvListValue\n\ntype OtlpKeyValue = {\n key: string\n value: OtlpAnyValue\n}\n\ntype OtlpResource = {\n attributes: OtlpKeyValue[]\n droppedAttributesCount?: number\n}\n\ntype OtlpInstrumentationScope = {\n name: string\n version?: string\n attributes?: OtlpKeyValue[]\n droppedAttributesCount?: number\n}\n\n/** https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/trace/v1/trace.proto#L103 */\ntype OtlpSpanKind = 0 | 1 | 2 | 3 | 4 | 5\n\n/** 0 = STATUS_CODE_UNSET, 1 = STATUS_CODE_OK, 2 = STATUS_CODE_ERROR */\ntype OtlpStatusCode = 0 | 1 | 2\n\ntype OtlpStatus = {\n code: OtlpStatusCode\n message?: string\n}\n\ntype OtlpSpan = {\n traceId: string\n spanId: string\n traceState?: string\n parentSpanId?: string\n name: string\n kind: OtlpSpanKind\n startTimeUnixNano: string\n endTimeUnixNano: string\n attributes?: OtlpKeyValue[]\n droppedAttributesCount?: number\n events?: OtlpSpanEvent[]\n droppedEventsCount?: number\n links?: OtlpSpanLink[]\n droppedLinksCount?: number\n status?: OtlpStatus\n}\n\ntype OtlpSpanEvent = {\n timeUnixNano: string\n name: string\n attributes?: OtlpKeyValue[]\n droppedAttributesCount?: number\n}\n\ntype OtlpSpanLink = {\n traceId: string\n spanId: string\n traceState?: string\n attributes?: OtlpKeyValue[]\n droppedAttributesCount?: number\n}\n\ntype OtlpScopeSpans = {\n scope: OtlpInstrumentationScope\n spans: OtlpSpan[]\n schemaUrl?: string\n}\n\ntype OtlpResourceSpans = {\n resource: OtlpResource\n scopeSpans: OtlpScopeSpans[]\n schemaUrl?: string\n}\n\n/** Root payload sent to POST /v1/traces */\ntype OtlpExportTraceServiceRequest = {\n resourceSpans: OtlpResourceSpans[]\n}\n\nexport type TelemetryPlugin = {\n name: string\n options: Record<string, unknown>\n}\n\ntype TelemetryEvent = {\n command: string\n kubbVersion: string\n nodeVersion: string\n platform: string\n ci: boolean\n plugins: TelemetryPlugin[]\n duration: number\n filesCreated: number\n status: 'success' | 'failed'\n}\n\n/**\n * Detect whether the current process is running inside a CI environment.\n * Delegates to the canonical isCIEnvironment() from envDetection.\n */\nexport function isCi(): boolean {\n return isCIEnvironment()\n}\n\n/**\n * Check if telemetry is disabled via DO_NOT_TRACK or KUBB_DISABLE_TELEMETRY.\n * Respects the standard DO_NOT_TRACK convention used across development tools.\n */\nexport function isTelemetryDisabled(): boolean {\n return (\n process.env['DO_NOT_TRACK'] === '1' ||\n process.env['DO_NOT_TRACK'] === 'true' ||\n process.env['KUBB_DISABLE_TELEMETRY'] === '1' ||\n process.env['KUBB_DISABLE_TELEMETRY'] === 'true'\n )\n}\n\n/**\n * Convert a TelemetryEvent into an OTLP-compatible JSON trace payload.\n * See https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/\n */\nexport function buildOtlpPayload(event: TelemetryEvent): OtlpExportTraceServiceRequest {\n const traceId = randomBytes(16).toString('hex')\n const spanId = randomBytes(8).toString('hex')\n const endTimeNs = BigInt(Date.now()) * 1_000_000n\n const startTimeNs = endTimeNs - BigInt(event.duration) * 1_000_000n\n\n const attributes: OtlpKeyValue[] = [\n { key: 'kubb.command', value: { stringValue: event.command } },\n { key: 'kubb.version', value: { stringValue: event.kubbVersion } },\n { key: 'kubb.node_version', value: { stringValue: event.nodeVersion } },\n { key: 'kubb.platform', value: { stringValue: event.platform } },\n { key: 'kubb.ci', value: { boolValue: event.ci } },\n { key: 'kubb.files_created', value: { intValue: event.filesCreated } },\n { key: 'kubb.status', value: { stringValue: event.status } },\n {\n key: 'kubb.plugins',\n value: {\n arrayValue: {\n values: event.plugins.map(\n (p): OtlpKvListValue => ({\n kvlistValue: {\n values: [\n { key: 'name', value: { stringValue: p.name } },\n { key: 'options', value: { stringValue: JSON.stringify({ ...p.options, usedEnumNames: undefined }) } },\n ],\n },\n }),\n ),\n },\n },\n },\n ]\n\n return {\n resourceSpans: [\n {\n resource: {\n attributes: [\n { key: 'service.name', value: { stringValue: 'kubb-cli' } },\n { key: 'service.version', value: { stringValue: event.kubbVersion } },\n { key: 'telemetry.sdk.language', value: { stringValue: 'nodejs' } },\n ],\n },\n scopeSpans: [\n {\n scope: { name: 'kubb-cli', version: event.kubbVersion },\n spans: [\n {\n traceId,\n spanId,\n name: event.command,\n kind: 1 satisfies OtlpSpanKind,\n startTimeUnixNano: String(startTimeNs),\n endTimeUnixNano: String(endTimeNs),\n attributes,\n status: { code: (event.status === 'success' ? 1 : 2) satisfies OtlpStatusCode },\n },\n ],\n },\n ],\n },\n ],\n }\n}\n\n/**\n * Send an anonymous telemetry event to the Kubb OTLP endpoint.\n * Respects DO_NOT_TRACK and KUBB_DISABLE_TELEMETRY environment variables.\n * Fails silently to never interrupt the generation process.\n */\nexport async function sendTelemetry(event: TelemetryEvent): Promise<void> {\n if (isTelemetryDisabled()) {\n return\n }\n\n await executeIfOnline(async () => {\n try {\n await fetch(`${OTLP_ENDPOINT}/v1/traces`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Kubb-Telemetry-Version': '1',\n 'Kubb-Telemetry-Source': 'kubb-cli',\n },\n body: JSON.stringify(buildOtlpPayload(event)),\n signal: AbortSignal.timeout(5_000),\n })\n } catch (_e) {\n // Fail silently – telemetry must never break the CLI\n }\n })\n}\n\n/**\n * Build an anonymous telemetry payload from a completed generation run.\n * No file paths, OpenAPI specs, or secrets are included.\n */\nexport function buildTelemetryEvent(options: {\n command: 'generate' | 'mcp' | 'validate' | 'agent'\n kubbVersion: string\n plugins?: TelemetryPlugin[]\n hrStart: [number, number]\n filesCreated?: number\n status: 'success' | 'failed'\n}): TelemetryEvent {\n const [seconds, nanoseconds] = process.hrtime(options.hrStart)\n const duration = Math.round(seconds * 1000 + nanoseconds / 1e6)\n\n return {\n command: options.command,\n kubbVersion: options.kubbVersion,\n nodeVersion: process.versions.node.split('.')[0] as string,\n platform: os.platform(),\n ci: isCi(),\n plugins: options.plugins ?? [],\n duration,\n filesCreated: options.filesCreated ?? 0,\n status: options.status,\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import "./chunk--u3MIqq1.js";
2
+ //#region src/cli/types.ts
3
+ /**
4
+ * Returns a `CommandDefinition` with typed `values` in `run()`.
5
+ * The callback receives `values` typed from the declared options — no casts needed.
6
+ */
7
+ function defineCommand(def) {
8
+ const { run, ...rest } = def;
9
+ if (!run) return rest;
10
+ return {
11
+ ...rest,
12
+ run: (args) => run({
13
+ values: args.values,
14
+ positionals: args.positionals
15
+ })
16
+ };
17
+ }
18
+ /** Returns a `CLIAdapter` with type inference. Pass a different adapter to `createCLI` to swap the CLI engine. */
19
+ function defineCLIAdapter(adapter) {
20
+ return adapter;
21
+ }
22
+ //#endregion
23
+ export { defineCommand as n, defineCLIAdapter as t };
24
+
25
+ //# sourceMappingURL=types-CLtz0jem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-CLtz0jem.js","names":[],"sources":["../src/cli/types.ts"],"sourcesContent":["type BaseOption = {\n /** Single-character short alias, e.g. `'c'` for `--config`. */\n short?: string\n description: string\n hint?: string\n required?: boolean\n /** Allowed values for string options. Used in help output and AI/MCP tool schemas. */\n enum?: string[]\n}\n\nexport type StringOption = BaseOption & { type: 'string'; default?: string }\nexport type BooleanOption = BaseOption & { type: 'boolean'; default?: boolean }\nexport type OptionDefinition = StringOption | BooleanOption\nexport type OptionType = OptionDefinition['type']\n\ntype OptionTypeMap = { string: string; boolean: boolean }\n\ntype IsRequired<O extends OptionDefinition> = O['default'] extends string | boolean ? true : O['required'] extends true ? true : false\n\n/** Infers typed values from an options record. Options with a `default` or `required: true` are always defined. */\ntype InferValues<O extends Record<string, OptionDefinition>> = {\n [K in keyof O as IsRequired<O[K]> extends true ? K : never]: OptionTypeMap[O[K]['type']]\n} & {\n [K in keyof O as IsRequired<O[K]> extends true ? never : K]?: OptionTypeMap[O[K]['type']]\n}\n\nexport type ParsedArgs = {\n values: Record<string, string | boolean | undefined>\n positionals: string[]\n}\n\nexport type CommandDefinition = {\n name: string\n description: string\n /** Positional argument labels shown in usage line, e.g. `['[input]']`. */\n arguments?: string[]\n options?: Record<string, OptionDefinition>\n subCommands?: CommandDefinition[]\n run?: (args: ParsedArgs) => Promise<void>\n}\n\n/**\n * Returns a `CommandDefinition` with typed `values` in `run()`.\n * The callback receives `values` typed from the declared options — no casts needed.\n */\nexport function defineCommand<O extends Record<string, OptionDefinition>>(def: {\n name: string\n description: string\n arguments?: string[]\n options?: O\n subCommands?: CommandDefinition[]\n run?: (args: { values: InferValues<O>; positionals: string[] }) => Promise<void>\n}): CommandDefinition {\n const { run, ...rest } = def\n if (!run) return rest\n return {\n ...rest,\n run: (args) => run({ values: args.values as InferValues<O>, positionals: args.positionals }),\n }\n}\n\nexport type RunOptions = {\n programName: string\n defaultCommandName: string\n version: string\n}\n\nexport type CLIAdapter = {\n run(commands: CommandDefinition[], argv: string[], opts: RunOptions): Promise<void>\n renderHelp(def: CommandDefinition, parentName?: string): void\n}\n\n/** Returns a `CLIAdapter` with type inference. Pass a different adapter to `createCLI` to swap the CLI engine. */\nexport function defineCLIAdapter(adapter: CLIAdapter): CLIAdapter {\n return adapter\n}\n\nexport type OptionSchema = {\n name: string\n flags: string\n type: OptionType\n description: string\n default?: string | boolean\n hint?: string\n required?: boolean\n enum?: string[]\n}\n\nexport type CommandSchema = {\n name: string\n description: string\n arguments?: string[]\n options: OptionSchema[]\n subCommands: CommandSchema[]\n}\n"],"mappings":";;;;;;AA6CA,SAAgB,cAA0D,KAOpD;CACpB,MAAM,EAAE,KAAK,GAAG,SAAS;AACzB,KAAI,CAAC,IAAK,QAAO;AACjB,QAAO;EACL,GAAG;EACH,MAAM,SAAS,IAAI;GAAE,QAAQ,KAAK;GAA0B,aAAa,KAAK;GAAa,CAAC;EAC7F;;;AAeH,SAAgB,iBAAiB,SAAiC;AAChE,QAAO"}
@@ -0,0 +1,36 @@
1
+ require("./chunk-ByKO4r7w.cjs");
2
+ //#region src/cli/types.ts
3
+ /**
4
+ * Returns a `CommandDefinition` with typed `values` in `run()`.
5
+ * The callback receives `values` typed from the declared options — no casts needed.
6
+ */
7
+ function defineCommand(def) {
8
+ const { run, ...rest } = def;
9
+ if (!run) return rest;
10
+ return {
11
+ ...rest,
12
+ run: (args) => run({
13
+ values: args.values,
14
+ positionals: args.positionals
15
+ })
16
+ };
17
+ }
18
+ /** Returns a `CLIAdapter` with type inference. Pass a different adapter to `createCLI` to swap the CLI engine. */
19
+ function defineCLIAdapter(adapter) {
20
+ return adapter;
21
+ }
22
+ //#endregion
23
+ Object.defineProperty(exports, "defineCLIAdapter", {
24
+ enumerable: true,
25
+ get: function() {
26
+ return defineCLIAdapter;
27
+ }
28
+ });
29
+ Object.defineProperty(exports, "defineCommand", {
30
+ enumerable: true,
31
+ get: function() {
32
+ return defineCommand;
33
+ }
34
+ });
35
+
36
+ //# sourceMappingURL=types-Ck2lzFON.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-Ck2lzFON.cjs","names":[],"sources":["../src/cli/types.ts"],"sourcesContent":["type BaseOption = {\n /** Single-character short alias, e.g. `'c'` for `--config`. */\n short?: string\n description: string\n hint?: string\n required?: boolean\n /** Allowed values for string options. Used in help output and AI/MCP tool schemas. */\n enum?: string[]\n}\n\nexport type StringOption = BaseOption & { type: 'string'; default?: string }\nexport type BooleanOption = BaseOption & { type: 'boolean'; default?: boolean }\nexport type OptionDefinition = StringOption | BooleanOption\nexport type OptionType = OptionDefinition['type']\n\ntype OptionTypeMap = { string: string; boolean: boolean }\n\ntype IsRequired<O extends OptionDefinition> = O['default'] extends string | boolean ? true : O['required'] extends true ? true : false\n\n/** Infers typed values from an options record. Options with a `default` or `required: true` are always defined. */\ntype InferValues<O extends Record<string, OptionDefinition>> = {\n [K in keyof O as IsRequired<O[K]> extends true ? K : never]: OptionTypeMap[O[K]['type']]\n} & {\n [K in keyof O as IsRequired<O[K]> extends true ? never : K]?: OptionTypeMap[O[K]['type']]\n}\n\nexport type ParsedArgs = {\n values: Record<string, string | boolean | undefined>\n positionals: string[]\n}\n\nexport type CommandDefinition = {\n name: string\n description: string\n /** Positional argument labels shown in usage line, e.g. `['[input]']`. */\n arguments?: string[]\n options?: Record<string, OptionDefinition>\n subCommands?: CommandDefinition[]\n run?: (args: ParsedArgs) => Promise<void>\n}\n\n/**\n * Returns a `CommandDefinition` with typed `values` in `run()`.\n * The callback receives `values` typed from the declared options — no casts needed.\n */\nexport function defineCommand<O extends Record<string, OptionDefinition>>(def: {\n name: string\n description: string\n arguments?: string[]\n options?: O\n subCommands?: CommandDefinition[]\n run?: (args: { values: InferValues<O>; positionals: string[] }) => Promise<void>\n}): CommandDefinition {\n const { run, ...rest } = def\n if (!run) return rest\n return {\n ...rest,\n run: (args) => run({ values: args.values as InferValues<O>, positionals: args.positionals }),\n }\n}\n\nexport type RunOptions = {\n programName: string\n defaultCommandName: string\n version: string\n}\n\nexport type CLIAdapter = {\n run(commands: CommandDefinition[], argv: string[], opts: RunOptions): Promise<void>\n renderHelp(def: CommandDefinition, parentName?: string): void\n}\n\n/** Returns a `CLIAdapter` with type inference. Pass a different adapter to `createCLI` to swap the CLI engine. */\nexport function defineCLIAdapter(adapter: CLIAdapter): CLIAdapter {\n return adapter\n}\n\nexport type OptionSchema = {\n name: string\n flags: string\n type: OptionType\n description: string\n default?: string | boolean\n hint?: string\n required?: boolean\n enum?: string[]\n}\n\nexport type CommandSchema = {\n name: string\n description: string\n arguments?: string[]\n options: OptionSchema[]\n subCommands: CommandSchema[]\n}\n"],"mappings":";;;;;;AA6CA,SAAgB,cAA0D,KAOpD;CACpB,MAAM,EAAE,KAAK,GAAG,SAAS;AACzB,KAAI,CAAC,IAAK,QAAO;AACjB,QAAO;EACL,GAAG;EACH,MAAM,SAAS,IAAI;GAAE,QAAQ,KAAK;GAA0B,aAAa,KAAK;GAAa,CAAC;EAC7F;;;AAeH,SAAgB,iBAAiB,SAAiC;AAChE,QAAO"}
@@ -0,0 +1,41 @@
1
+ import "./chunk--u3MIqq1.js";
2
+ import { r as sendTelemetry, t as buildTelemetryEvent } from "./telemetry-C4gOKX2x.js";
3
+ import { t as getErrorMessage } from "./errors-bSLTEh4e.js";
4
+ import { t as jiti } from "./jiti-Cl7t20dO.js";
5
+ import process from "node:process";
6
+ //#region src/runners/validate.ts
7
+ async function runValidate({ input, version }) {
8
+ let mod;
9
+ try {
10
+ mod = await jiti.import("@kubb/oas", { default: true });
11
+ } catch (_e) {
12
+ console.error(`Import of '@kubb/oas' is required to do validation`);
13
+ process.exit(1);
14
+ }
15
+ const { parse } = mod;
16
+ const hrStart = process.hrtime();
17
+ try {
18
+ await (await parse(input)).validate();
19
+ await sendTelemetry(buildTelemetryEvent({
20
+ command: "validate",
21
+ kubbVersion: version,
22
+ hrStart,
23
+ status: "success"
24
+ }));
25
+ console.log("✅ Validation success");
26
+ } catch (error) {
27
+ await sendTelemetry(buildTelemetryEvent({
28
+ command: "validate",
29
+ kubbVersion: version,
30
+ hrStart,
31
+ status: "failed"
32
+ }));
33
+ console.error("❌ Validation failed");
34
+ console.error(getErrorMessage(error));
35
+ process.exit(1);
36
+ }
37
+ }
38
+ //#endregion
39
+ export { runValidate };
40
+
41
+ //# sourceMappingURL=validate-Chjg23AE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-Chjg23AE.js","names":[],"sources":["../src/runners/validate.ts"],"sourcesContent":["import process from 'node:process'\nimport type * as OasModule from '@kubb/oas'\nimport { getErrorMessage } from '../utils/errors.ts'\nimport { jiti } from '../utils/jiti.ts'\nimport { buildTelemetryEvent, sendTelemetry } from '../utils/telemetry.ts'\n\ntype ValidateOptions = {\n input: string\n version: string\n}\n\nexport async function runValidate({ input, version }: ValidateOptions): Promise<void> {\n let mod: typeof OasModule\n try {\n mod = (await jiti.import('@kubb/oas', { default: true })) as typeof OasModule\n } catch (_e) {\n console.error(`Import of '@kubb/oas' is required to do validation`)\n process.exit(1)\n }\n\n const { parse } = mod\n const hrStart = process.hrtime()\n try {\n const oas = await parse(input)\n await oas.validate()\n\n await sendTelemetry(buildTelemetryEvent({ command: 'validate', kubbVersion: version, hrStart, status: 'success' }))\n console.log('✅ Validation success')\n } catch (error) {\n await sendTelemetry(buildTelemetryEvent({ command: 'validate', kubbVersion: version, hrStart, status: 'failed' }))\n console.error('❌ Validation failed')\n console.error(getErrorMessage(error))\n process.exit(1)\n }\n}\n"],"mappings":";;;;;;AAWA,eAAsB,YAAY,EAAE,OAAO,WAA2C;CACpF,IAAI;AACJ,KAAI;AACF,QAAO,MAAM,KAAK,OAAO,aAAa,EAAE,SAAS,MAAM,CAAC;UACjD,IAAI;AACX,UAAQ,MAAM,qDAAqD;AACnE,UAAQ,KAAK,EAAE;;CAGjB,MAAM,EAAE,UAAU;CAClB,MAAM,UAAU,QAAQ,QAAQ;AAChC,KAAI;AAEF,SADY,MAAM,MAAM,MAAM,EACpB,UAAU;AAEpB,QAAM,cAAc,oBAAoB;GAAE,SAAS;GAAY,aAAa;GAAS;GAAS,QAAQ;GAAW,CAAC,CAAC;AACnH,UAAQ,IAAI,uBAAuB;UAC5B,OAAO;AACd,QAAM,cAAc,oBAAoB;GAAE,SAAS;GAAY,aAAa;GAAS;GAAS,QAAQ;GAAU,CAAC,CAAC;AAClH,UAAQ,MAAM,sBAAsB;AACpC,UAAQ,MAAM,gBAAgB,MAAM,CAAC;AACrC,UAAQ,KAAK,EAAE"}
@@ -0,0 +1,25 @@
1
+ import "./chunk--u3MIqq1.js";
2
+ import { t as version } from "./package-681jTtCk.js";
3
+ import { n as defineCommand } from "./types-CLtz0jem.js";
4
+ //#region src/commands/validate.ts
5
+ const command = defineCommand({
6
+ name: "validate",
7
+ description: "Validate a Swagger/OpenAPI file",
8
+ options: { input: {
9
+ type: "string",
10
+ description: "Path to Swagger/OpenAPI file",
11
+ short: "i",
12
+ required: true
13
+ } },
14
+ async run({ values }) {
15
+ const { runValidate } = await import("./validate-Chjg23AE.js");
16
+ await runValidate({
17
+ input: values.input,
18
+ version
19
+ });
20
+ }
21
+ });
22
+ //#endregion
23
+ export { command };
24
+
25
+ //# sourceMappingURL=validate-Cr26q5xX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-Cr26q5xX.js","names":[],"sources":["../src/commands/validate.ts"],"sourcesContent":["import { version } from '../../package.json'\nimport { defineCommand } from '../cli/index.ts'\n\nexport const command = defineCommand({\n name: 'validate',\n description: 'Validate a Swagger/OpenAPI file',\n options: {\n input: { type: 'string', description: 'Path to Swagger/OpenAPI file', short: 'i', required: true },\n },\n async run({ values }) {\n const { runValidate } = await import('../runners/validate.ts')\n\n await runValidate({ input: values.input, version })\n },\n})\n"],"mappings":";;;;AAGA,MAAa,UAAU,cAAc;CACnC,MAAM;CACN,aAAa;CACb,SAAS,EACP,OAAO;EAAE,MAAM;EAAU,aAAa;EAAgC,OAAO;EAAK,UAAU;EAAM,EACnG;CACD,MAAM,IAAI,EAAE,UAAU;EACpB,MAAM,EAAE,gBAAgB,MAAM,OAAO;AAErC,QAAM,YAAY;GAAE,OAAO,OAAO;GAAO;GAAS,CAAC;;CAEtD,CAAC"}
@@ -0,0 +1,24 @@
1
+ require("./chunk-ByKO4r7w.cjs");
2
+ const require_package = require("./package-aKgzEJtp.cjs");
3
+ //#region src/commands/validate.ts
4
+ const command = require("./types-Ck2lzFON.cjs").defineCommand({
5
+ name: "validate",
6
+ description: "Validate a Swagger/OpenAPI file",
7
+ options: { input: {
8
+ type: "string",
9
+ description: "Path to Swagger/OpenAPI file",
10
+ short: "i",
11
+ required: true
12
+ } },
13
+ async run({ values }) {
14
+ const { runValidate } = await Promise.resolve().then(() => require("./validate-Dqi9T_c4.cjs"));
15
+ await runValidate({
16
+ input: values.input,
17
+ version: require_package.version
18
+ });
19
+ }
20
+ });
21
+ //#endregion
22
+ exports.command = command;
23
+
24
+ //# sourceMappingURL=validate-DURmg-2Q.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-DURmg-2Q.cjs","names":["defineCommand"],"sources":["../src/commands/validate.ts"],"sourcesContent":["import { version } from '../../package.json'\nimport { defineCommand } from '../cli/index.ts'\n\nexport const command = defineCommand({\n name: 'validate',\n description: 'Validate a Swagger/OpenAPI file',\n options: {\n input: { type: 'string', description: 'Path to Swagger/OpenAPI file', short: 'i', required: true },\n },\n async run({ values }) {\n const { runValidate } = await import('../runners/validate.ts')\n\n await runValidate({ input: values.input, version })\n },\n})\n"],"mappings":";;;AAGA,MAAa,0CAAUA,cAAc;CACnC,MAAM;CACN,aAAa;CACb,SAAS,EACP,OAAO;EAAE,MAAM;EAAU,aAAa;EAAgC,OAAO;EAAK,UAAU;EAAM,EACnG;CACD,MAAM,IAAI,EAAE,UAAU;EACpB,MAAM,EAAE,gBAAgB,MAAA,QAAA,SAAA,CAAA,WAAA,QAAM,0BAAA,CAAA;AAE9B,QAAM,YAAY;GAAE,OAAO,OAAO;GAAO,SAAA,gBAAA;GAAS,CAAC;;CAEtD,CAAC"}
@@ -0,0 +1,42 @@
1
+ const require_chunk = require("./chunk-ByKO4r7w.cjs");
2
+ const require_telemetry = require("./telemetry-T5IA2dWA.cjs");
3
+ const require_errors = require("./errors-BUjJsNoe.cjs");
4
+ const require_jiti = require("./jiti-BdskUHhD.cjs");
5
+ let node_process = require("node:process");
6
+ node_process = require_chunk.__toESM(node_process);
7
+ //#region src/runners/validate.ts
8
+ async function runValidate({ input, version }) {
9
+ let mod;
10
+ try {
11
+ mod = await require_jiti.jiti.import("@kubb/oas", { default: true });
12
+ } catch (_e) {
13
+ console.error(`Import of '@kubb/oas' is required to do validation`);
14
+ node_process.default.exit(1);
15
+ }
16
+ const { parse } = mod;
17
+ const hrStart = node_process.default.hrtime();
18
+ try {
19
+ await (await parse(input)).validate();
20
+ await require_telemetry.sendTelemetry(require_telemetry.buildTelemetryEvent({
21
+ command: "validate",
22
+ kubbVersion: version,
23
+ hrStart,
24
+ status: "success"
25
+ }));
26
+ console.log("✅ Validation success");
27
+ } catch (error) {
28
+ await require_telemetry.sendTelemetry(require_telemetry.buildTelemetryEvent({
29
+ command: "validate",
30
+ kubbVersion: version,
31
+ hrStart,
32
+ status: "failed"
33
+ }));
34
+ console.error("❌ Validation failed");
35
+ console.error(require_errors.getErrorMessage(error));
36
+ node_process.default.exit(1);
37
+ }
38
+ }
39
+ //#endregion
40
+ exports.runValidate = runValidate;
41
+
42
+ //# sourceMappingURL=validate-Dqi9T_c4.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-Dqi9T_c4.cjs","names":["jiti","process","sendTelemetry","buildTelemetryEvent","getErrorMessage"],"sources":["../src/runners/validate.ts"],"sourcesContent":["import process from 'node:process'\nimport type * as OasModule from '@kubb/oas'\nimport { getErrorMessage } from '../utils/errors.ts'\nimport { jiti } from '../utils/jiti.ts'\nimport { buildTelemetryEvent, sendTelemetry } from '../utils/telemetry.ts'\n\ntype ValidateOptions = {\n input: string\n version: string\n}\n\nexport async function runValidate({ input, version }: ValidateOptions): Promise<void> {\n let mod: typeof OasModule\n try {\n mod = (await jiti.import('@kubb/oas', { default: true })) as typeof OasModule\n } catch (_e) {\n console.error(`Import of '@kubb/oas' is required to do validation`)\n process.exit(1)\n }\n\n const { parse } = mod\n const hrStart = process.hrtime()\n try {\n const oas = await parse(input)\n await oas.validate()\n\n await sendTelemetry(buildTelemetryEvent({ command: 'validate', kubbVersion: version, hrStart, status: 'success' }))\n console.log('✅ Validation success')\n } catch (error) {\n await sendTelemetry(buildTelemetryEvent({ command: 'validate', kubbVersion: version, hrStart, status: 'failed' }))\n console.error('❌ Validation failed')\n console.error(getErrorMessage(error))\n process.exit(1)\n }\n}\n"],"mappings":";;;;;;;AAWA,eAAsB,YAAY,EAAE,OAAO,WAA2C;CACpF,IAAI;AACJ,KAAI;AACF,QAAO,MAAMA,aAAAA,KAAK,OAAO,aAAa,EAAE,SAAS,MAAM,CAAC;UACjD,IAAI;AACX,UAAQ,MAAM,qDAAqD;AACnE,eAAA,QAAQ,KAAK,EAAE;;CAGjB,MAAM,EAAE,UAAU;CAClB,MAAM,UAAUC,aAAAA,QAAQ,QAAQ;AAChC,KAAI;AAEF,SADY,MAAM,MAAM,MAAM,EACpB,UAAU;AAEpB,QAAMC,kBAAAA,cAAcC,kBAAAA,oBAAoB;GAAE,SAAS;GAAY,aAAa;GAAS;GAAS,QAAQ;GAAW,CAAC,CAAC;AACnH,UAAQ,IAAI,uBAAuB;UAC5B,OAAO;AACd,QAAMD,kBAAAA,cAAcC,kBAAAA,oBAAoB;GAAE,SAAS;GAAY,aAAa;GAAS;GAAS,QAAQ;GAAU,CAAC,CAAC;AAClH,UAAQ,MAAM,sBAAsB;AACpC,UAAQ,MAAMC,eAAAA,gBAAgB,MAAM,CAAC;AACrC,eAAA,QAAQ,KAAK,EAAE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/cli",
3
- "version": "4.32.3",
3
+ "version": "4.33.0",
4
4
  "description": "Command-line interface for Kubb, enabling easy generation of TypeScript, React-Query, Zod, and other code from OpenAPI specifications.",
5
5
  "keywords": [
6
6
  "cli",
@@ -55,17 +55,16 @@
55
55
  "dependencies": {
56
56
  "@clack/prompts": "^1.1.0",
57
57
  "chokidar": "^5.0.0",
58
- "citty": "^0.1.6",
59
58
  "cosmiconfig": "^9.0.1",
60
59
  "jiti": "2.5.1",
61
60
  "tinyexec": "^1.0.2",
62
- "@kubb/core": "4.32.3"
61
+ "@kubb/core": "4.33.0"
63
62
  },
64
63
  "devDependencies": {
65
64
  "source-map-support": "^0.5.21",
66
- "@kubb/agent": "4.32.3",
67
- "@kubb/mcp": "4.32.3",
68
- "@kubb/oas": "4.32.3"
65
+ "@kubb/agent": "4.33.0",
66
+ "@kubb/mcp": "4.33.0",
67
+ "@kubb/oas": "4.33.0"
69
68
  },
70
69
  "engines": {
71
70
  "node": ">=20"
@@ -0,0 +1,159 @@
1
+ import { parseArgs, styleText } from 'node:util'
2
+ import { renderHelp } from '../help.ts'
3
+ import type { CommandDefinition, OptionType, ParsedArgs, RunOptions } from '../types.ts'
4
+ import { defineCLIAdapter } from '../types.ts'
5
+
6
+ type ParseOption = { type: OptionType; short?: string; default?: string | boolean }
7
+ type ParseOptions = Record<string, ParseOption>
8
+
9
+ function buildParseOptions(def: CommandDefinition): ParseOptions {
10
+ const result: ParseOptions = {
11
+ help: { type: 'boolean', short: 'h' },
12
+ }
13
+
14
+ for (const [name, opt] of Object.entries(def.options ?? {})) {
15
+ result[name] = {
16
+ type: opt.type,
17
+ ...(opt.short ? { short: opt.short } : {}),
18
+ ...(opt.default !== undefined ? { default: opt.default } : {}),
19
+ }
20
+ }
21
+
22
+ return result
23
+ }
24
+
25
+ async function runCommand(def: CommandDefinition, argv: string[], parentName?: string): Promise<void> {
26
+ const parseOptions = buildParseOptions(def)
27
+
28
+ let parsed: ParsedArgs
29
+ try {
30
+ const result = parseArgs({
31
+ args: argv,
32
+ options: parseOptions,
33
+ allowPositionals: true,
34
+ strict: false,
35
+ })
36
+ parsed = { values: result.values as ParsedArgs['values'], positionals: result.positionals }
37
+ } catch {
38
+ renderHelp(def, parentName)
39
+ process.exit(1)
40
+ }
41
+
42
+ if (parsed.values['help']) {
43
+ renderHelp(def, parentName)
44
+ process.exit(0)
45
+ }
46
+
47
+ // Validate required options before running the command
48
+ for (const [name, opt] of Object.entries(def.options ?? {})) {
49
+ if (opt.required && parsed.values[name] === undefined) {
50
+ console.error(styleText('red', `Error: --${name} is required`))
51
+ renderHelp(def, parentName)
52
+ process.exit(1)
53
+ }
54
+ }
55
+
56
+ if (!def.run) {
57
+ renderHelp(def, parentName)
58
+ process.exit(0)
59
+ }
60
+
61
+ try {
62
+ await def.run(parsed)
63
+ } catch (err) {
64
+ console.error(styleText('red', `Error: ${err instanceof Error ? err.message : String(err)}`))
65
+ renderHelp(def, parentName)
66
+ process.exit(1)
67
+ }
68
+ }
69
+
70
+ function printRootHelp(programName: string, version: string, defs: CommandDefinition[]): void {
71
+ console.log(`\n${styleText('bold', 'Usage:')} ${programName} <command> [options]\n`)
72
+ console.log(` Kubb generation — v${version}\n`)
73
+ console.log(styleText('bold', 'Commands:'))
74
+ for (const def of defs) {
75
+ console.log(` ${styleText('cyan', def.name.padEnd(16))}${def.description}`)
76
+ }
77
+ console.log()
78
+ console.log(styleText('bold', 'Options:'))
79
+ console.log(` ${styleText('cyan', '-v, --version'.padEnd(30))}Show version number`)
80
+ console.log(` ${styleText('cyan', '-h, --help'.padEnd(30))}Show help`)
81
+ console.log()
82
+ console.log(`Run ${styleText('cyan', `${programName} <command> --help`)} for command-specific help.\n`)
83
+ }
84
+
85
+ /** CLI adapter using `node:util parseArgs`. No external dependencies. */
86
+ export const nodeAdapter = defineCLIAdapter({
87
+ renderHelp(def: CommandDefinition, parentName?: string): void {
88
+ renderHelp(def, parentName)
89
+ },
90
+
91
+ async run(defs: CommandDefinition[], argv: string[], opts: RunOptions): Promise<void> {
92
+ const { programName, defaultCommandName, version } = opts
93
+
94
+ const args = argv.length >= 2 && argv[0]?.includes('node') ? argv.slice(2) : argv
95
+
96
+ if (args[0] === '--version' || args[0] === '-v') {
97
+ console.log(version)
98
+ process.exit(0)
99
+ }
100
+
101
+ if (args[0] === '--help' || args[0] === '-h') {
102
+ printRootHelp(programName, version, defs)
103
+ process.exit(0)
104
+ }
105
+
106
+ if (args.length === 0) {
107
+ const defaultDef = defs.find((d) => d.name === defaultCommandName)
108
+ if (defaultDef?.run) {
109
+ await runCommand(defaultDef, [], programName)
110
+ } else {
111
+ printRootHelp(programName, version, defs)
112
+ }
113
+ return
114
+ }
115
+
116
+ const [first, ...rest] = args
117
+ const isKnownSubcommand = defs.some((d) => d.name === first)
118
+
119
+ let def: CommandDefinition | undefined
120
+ let commandArgv: string[]
121
+ let parentName: string | undefined
122
+
123
+ if (isKnownSubcommand) {
124
+ def = defs.find((d) => d.name === first)
125
+ commandArgv = rest
126
+ parentName = programName
127
+ } else {
128
+ def = defs.find((d) => d.name === defaultCommandName)
129
+ commandArgv = args
130
+ parentName = programName
131
+ }
132
+
133
+ if (!def) {
134
+ console.error(`Unknown command: ${first}`)
135
+ printRootHelp(programName, version, defs)
136
+ process.exit(1)
137
+ }
138
+
139
+ if (def.subCommands?.length) {
140
+ const [subName, ...subRest] = commandArgv
141
+ const subDef = def.subCommands.find((s) => s.name === subName)
142
+
143
+ if (subName === '--help' || subName === '-h') {
144
+ renderHelp(def, parentName)
145
+ process.exit(0)
146
+ }
147
+
148
+ if (!subDef) {
149
+ renderHelp(def, parentName)
150
+ process.exit(subName ? 1 : 0)
151
+ }
152
+
153
+ await runCommand(subDef, subRest, `${parentName} ${def.name}`)
154
+ return
155
+ }
156
+
157
+ await runCommand(def, commandArgv, parentName)
158
+ },
159
+ })