@kubb/cli 4.29.1 → 4.31.1

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 (56) hide show
  1. package/dist/{agent-BzD6f3mV.js → agent-BEWuKPyd.js} +2 -2
  2. package/dist/{agent-BzD6f3mV.js.map → agent-BEWuKPyd.js.map} +1 -1
  3. package/dist/{agent-NAhMf2ot.cjs → agent-D0ZFj8Cb.cjs} +2 -2
  4. package/dist/{agent-NAhMf2ot.cjs.map → agent-D0ZFj8Cb.cjs.map} +1 -1
  5. package/dist/{generate-CGEE6Etf.js → generate-3Djo2ofz.js} +32 -8
  6. package/dist/{generate-CGEE6Etf.js.map → generate-3Djo2ofz.js.map} +1 -1
  7. package/dist/{generate-b2shdOTg.cjs → generate-4ln2TBP8.cjs} +33 -9
  8. package/dist/generate-4ln2TBP8.cjs.map +1 -0
  9. package/dist/index.cjs +10 -7
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.js +10 -7
  12. package/dist/index.js.map +1 -1
  13. package/dist/{init-CPrROO67.js → init-8HRQ8_lW.js} +5 -38
  14. package/dist/init-8HRQ8_lW.js.map +1 -0
  15. package/dist/{init-CaoLbJ4R.cjs → init-Cm_kJUSx.cjs} +8 -41
  16. package/dist/init-Cm_kJUSx.cjs.map +1 -0
  17. package/dist/{mcp-Jboea6xH.js → mcp-CBr0iUwm.js} +19 -3
  18. package/dist/mcp-CBr0iUwm.js.map +1 -0
  19. package/dist/{mcp-97TXkJVX.cjs → mcp-uDyrcZFW.cjs} +21 -4
  20. package/dist/mcp-uDyrcZFW.cjs.map +1 -0
  21. package/dist/{package-DPA0iPrU.cjs → package-BLK3K956.cjs} +2 -2
  22. package/dist/package-BLK3K956.cjs.map +1 -0
  23. package/dist/package-P3yw_Wp4.js +6 -0
  24. package/dist/package-P3yw_Wp4.js.map +1 -0
  25. package/dist/{start-CYuU23PX.js → start-BOiwKVZd.js} +19 -4
  26. package/dist/{start-CYuU23PX.js.map → start-BOiwKVZd.js.map} +1 -1
  27. package/dist/{start-lrn1-P52.cjs → start-DWoUzCcX.cjs} +20 -5
  28. package/dist/start-DWoUzCcX.cjs.map +1 -0
  29. package/dist/telemetry-4xNBLqQy.js +152 -0
  30. package/dist/telemetry-4xNBLqQy.js.map +1 -0
  31. package/dist/telemetry-BcdCgNDv.cjs +171 -0
  32. package/dist/telemetry-BcdCgNDv.cjs.map +1 -0
  33. package/dist/{validate-BgYhe_55.cjs → validate-DSIGR8AG.cjs} +16 -1
  34. package/dist/validate-DSIGR8AG.cjs.map +1 -0
  35. package/dist/{validate-DOeZKiGx.js → validate-tLrVQqUL.js} +16 -1
  36. package/dist/validate-tLrVQqUL.js.map +1 -0
  37. package/package.json +8 -7
  38. package/src/commands/agent/start.ts +6 -1
  39. package/src/commands/init.ts +2 -1
  40. package/src/commands/mcp.ts +7 -1
  41. package/src/commands/validate.ts +5 -0
  42. package/src/index.ts +8 -0
  43. package/src/runners/generate.ts +28 -2
  44. package/src/utils/packageManager.ts +2 -60
  45. package/src/utils/telemetry.ts +278 -0
  46. package/dist/generate-b2shdOTg.cjs.map +0 -1
  47. package/dist/init-CPrROO67.js.map +0 -1
  48. package/dist/init-CaoLbJ4R.cjs.map +0 -1
  49. package/dist/mcp-97TXkJVX.cjs.map +0 -1
  50. package/dist/mcp-Jboea6xH.js.map +0 -1
  51. package/dist/package-1sFkRYXi.js +0 -6
  52. package/dist/package-1sFkRYXi.js.map +0 -1
  53. package/dist/package-DPA0iPrU.cjs.map +0 -1
  54. package/dist/start-lrn1-P52.cjs.map +0 -1
  55. package/dist/validate-BgYhe_55.cjs.map +0 -1
  56. package/dist/validate-DOeZKiGx.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry-BcdCgNDv.cjs","names":["process","os"],"sources":["../src/utils/telemetry.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto'\nimport os from 'node:os'\nimport process from 'node:process'\nimport { executeIfOnline } from '@kubb/core/utils'\n\nconst OTLP_ENDPOINT = 'https://otlp.kubb.dev'\n\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// ---------------------------------------------------------------------------\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 */\nexport type OtlpExportTraceServiceRequest = {\n resourceSpans: OtlpResourceSpans[]\n}\n\n// ---------------------------------------------------------------------------\n\nexport type TelemetryPlugin = {\n name: string\n options: Record<string, unknown>\n}\n\nexport type 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 by\n * checking the well-known environment variables set by all major CI systems.\n */\nexport function isCi(): 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 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] ?? 'unknown',\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,4 +1,6 @@
1
1
  const require_chunk = require('./chunk-CNbaEX1y.cjs');
2
+ const require_package = require('./package-BLK3K956.cjs');
3
+ const require_telemetry = require('./telemetry-BcdCgNDv.cjs');
2
4
  let citty = require("citty");
3
5
  let node_process = require("node:process");
4
6
  node_process = require_chunk.__toESM(node_process);
@@ -36,10 +38,23 @@ const command = (0, citty.defineCommand)({
36
38
  node_process.default.exit(1);
37
39
  }
38
40
  const { parse } = mod;
41
+ const hrStart = node_process.default.hrtime();
39
42
  try {
40
43
  await (await parse(args.input)).validate();
44
+ await require_telemetry.sendTelemetry(require_telemetry.buildTelemetryEvent({
45
+ command: "validate",
46
+ kubbVersion: require_package.version,
47
+ hrStart,
48
+ status: "success"
49
+ }));
41
50
  console.log("✅ Validation success");
42
51
  } catch (error) {
52
+ await require_telemetry.sendTelemetry(require_telemetry.buildTelemetryEvent({
53
+ command: "validate",
54
+ kubbVersion: require_package.version,
55
+ hrStart,
56
+ status: "failed"
57
+ }));
43
58
  console.error("❌ Validation failed");
44
59
  console.log(error?.message);
45
60
  node_process.default.exit(1);
@@ -50,4 +65,4 @@ const command = (0, citty.defineCommand)({
50
65
 
51
66
  //#endregion
52
67
  exports.default = command;
53
- //# sourceMappingURL=validate-BgYhe_55.cjs.map
68
+ //# sourceMappingURL=validate-DSIGR8AG.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-DSIGR8AG.cjs","names":["jiti","process","sendTelemetry","buildTelemetryEvent","version"],"sources":["../src/commands/validate.ts"],"sourcesContent":["import process from 'node:process'\nimport type { ArgsDef } from 'citty'\nimport { defineCommand, showUsage } from 'citty'\nimport { createJiti } from 'jiti'\nimport { version } from '../../package.json'\nimport { buildTelemetryEvent, sendTelemetry } from '../utils/telemetry.ts'\n\nconst jiti = createJiti(import.meta.url, {\n sourceMaps: true,\n})\n\nconst args = {\n input: {\n type: 'string',\n description: 'Path to Swagger/OpenAPI file',\n alias: 'i',\n },\n help: {\n type: 'boolean',\n description: 'Show help',\n alias: 'h',\n default: false,\n },\n} as const satisfies ArgsDef\n\nconst command = defineCommand({\n meta: {\n name: 'validate',\n description: 'Validate a Swagger/OpenAPI file',\n },\n args,\n async run(commandContext) {\n const { args } = commandContext\n\n if (args.help) {\n return showUsage(command)\n }\n\n if (args.input) {\n let mod: any\n try {\n mod = await jiti.import('@kubb/oas', { default: true })\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(args.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.log((error as Error)?.message)\n process.exit(1)\n }\n }\n },\n})\n\nexport default command\n"],"mappings":";;;;;;;;;AAOA,MAAMA,6EAAmC,EACvC,YAAY,MACb,CAAC;AAgBF,MAAM,mCAAwB;CAC5B,MAAM;EACJ,MAAM;EACN,aAAa;EACd;CACD,MAnBW;EACX,OAAO;GACL,MAAM;GACN,aAAa;GACb,OAAO;GACR;EACD,MAAM;GACJ,MAAM;GACN,aAAa;GACb,OAAO;GACP,SAAS;GACV;EACF;CAQC,MAAM,IAAI,gBAAgB;EACxB,MAAM,EAAE,SAAS;AAEjB,MAAI,KAAK,KACP,6BAAiB,QAAQ;AAG3B,MAAI,KAAK,OAAO;GACd,IAAI;AACJ,OAAI;AACF,UAAM,MAAMA,OAAK,OAAO,aAAa,EAAE,SAAS,MAAM,CAAC;YAChD,IAAI;AACX,YAAQ,MAAM,qDAAqD;AACnE,yBAAQ,KAAK,EAAE;;GAGjB,MAAM,EAAE,UAAU;GAClB,MAAM,UAAUC,qBAAQ,QAAQ;AAChC,OAAI;AAEF,WADY,MAAM,MAAM,KAAK,MAAM,EACzB,UAAU;AAEpB,UAAMC,gCAAcC,sCAAoB;KAAE,SAAS;KAAY,aAAaC;KAAS;KAAS,QAAQ;KAAW,CAAC,CAAC;AACnH,YAAQ,IAAI,uBAAuB;YAC5B,OAAO;AACd,UAAMF,gCAAcC,sCAAoB;KAAE,SAAS;KAAY,aAAaC;KAAS;KAAS,QAAQ;KAAU,CAAC,CAAC;AAClH,YAAQ,MAAM,sBAAsB;AACpC,YAAQ,IAAK,OAAiB,QAAQ;AACtC,yBAAQ,KAAK,EAAE;;;;CAItB,CAAC"}
@@ -1,4 +1,6 @@
1
1
  import { t as __name } from "./chunk-DKWOrOAv.js";
2
+ import { t as version } from "./package-P3yw_Wp4.js";
3
+ import { r as sendTelemetry, t as buildTelemetryEvent } from "./telemetry-4xNBLqQy.js";
2
4
  import { defineCommand, showUsage } from "citty";
3
5
  import process from "node:process";
4
6
  import { createJiti } from "jiti";
@@ -35,10 +37,23 @@ const command = defineCommand({
35
37
  process.exit(1);
36
38
  }
37
39
  const { parse } = mod;
40
+ const hrStart = process.hrtime();
38
41
  try {
39
42
  await (await parse(args.input)).validate();
43
+ await sendTelemetry(buildTelemetryEvent({
44
+ command: "validate",
45
+ kubbVersion: version,
46
+ hrStart,
47
+ status: "success"
48
+ }));
40
49
  console.log("✅ Validation success");
41
50
  } catch (error) {
51
+ await sendTelemetry(buildTelemetryEvent({
52
+ command: "validate",
53
+ kubbVersion: version,
54
+ hrStart,
55
+ status: "failed"
56
+ }));
42
57
  console.error("❌ Validation failed");
43
58
  console.log(error?.message);
44
59
  process.exit(1);
@@ -49,4 +64,4 @@ const command = defineCommand({
49
64
 
50
65
  //#endregion
51
66
  export { command as default };
52
- //# sourceMappingURL=validate-DOeZKiGx.js.map
67
+ //# sourceMappingURL=validate-tLrVQqUL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-tLrVQqUL.js","names":[],"sources":["../src/commands/validate.ts"],"sourcesContent":["import process from 'node:process'\nimport type { ArgsDef } from 'citty'\nimport { defineCommand, showUsage } from 'citty'\nimport { createJiti } from 'jiti'\nimport { version } from '../../package.json'\nimport { buildTelemetryEvent, sendTelemetry } from '../utils/telemetry.ts'\n\nconst jiti = createJiti(import.meta.url, {\n sourceMaps: true,\n})\n\nconst args = {\n input: {\n type: 'string',\n description: 'Path to Swagger/OpenAPI file',\n alias: 'i',\n },\n help: {\n type: 'boolean',\n description: 'Show help',\n alias: 'h',\n default: false,\n },\n} as const satisfies ArgsDef\n\nconst command = defineCommand({\n meta: {\n name: 'validate',\n description: 'Validate a Swagger/OpenAPI file',\n },\n args,\n async run(commandContext) {\n const { args } = commandContext\n\n if (args.help) {\n return showUsage(command)\n }\n\n if (args.input) {\n let mod: any\n try {\n mod = await jiti.import('@kubb/oas', { default: true })\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(args.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.log((error as Error)?.message)\n process.exit(1)\n }\n }\n },\n})\n\nexport default command\n"],"mappings":";;;;;;;;AAOA,MAAM,OAAO,WAAW,OAAO,KAAK,KAAK,EACvC,YAAY,MACb,CAAC;AAgBF,MAAM,UAAU,cAAc;CAC5B,MAAM;EACJ,MAAM;EACN,aAAa;EACd;CACD,MAnBW;EACX,OAAO;GACL,MAAM;GACN,aAAa;GACb,OAAO;GACR;EACD,MAAM;GACJ,MAAM;GACN,aAAa;GACb,OAAO;GACP,SAAS;GACV;EACF;CAQC,MAAM,IAAI,gBAAgB;EACxB,MAAM,EAAE,SAAS;AAEjB,MAAI,KAAK,KACP,QAAO,UAAU,QAAQ;AAG3B,MAAI,KAAK,OAAO;GACd,IAAI;AACJ,OAAI;AACF,UAAM,MAAM,KAAK,OAAO,aAAa,EAAE,SAAS,MAAM,CAAC;YAChD,IAAI;AACX,YAAQ,MAAM,qDAAqD;AACnE,YAAQ,KAAK,EAAE;;GAGjB,MAAM,EAAE,UAAU;GAClB,MAAM,UAAU,QAAQ,QAAQ;AAChC,OAAI;AAEF,WADY,MAAM,MAAM,KAAK,MAAM,EACzB,UAAU;AAEpB,UAAM,cAAc,oBAAoB;KAAE,SAAS;KAAY,aAAa;KAAS;KAAS,QAAQ;KAAW,CAAC,CAAC;AACnH,YAAQ,IAAI,uBAAuB;YAC5B,OAAO;AACd,UAAM,cAAc,oBAAoB;KAAE,SAAS;KAAY,aAAa;KAAS;KAAS,QAAQ;KAAU,CAAC,CAAC;AAClH,YAAQ,MAAM,sBAAsB;AACpC,YAAQ,IAAK,OAAiB,QAAQ;AACtC,YAAQ,KAAK,EAAE;;;;CAItB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/cli",
3
- "version": "4.29.1",
3
+ "version": "4.31.1",
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",
@@ -42,7 +42,8 @@
42
42
  "dist",
43
43
  "bin",
44
44
  "!/**/**.test.**",
45
- "!/**/__tests__/**"
45
+ "!/**/__tests__/**",
46
+ "!/**/__snapshots__/**"
46
47
  ],
47
48
  "size-limit": [
48
49
  {
@@ -55,16 +56,16 @@
55
56
  "@clack/prompts": "^1.0.1",
56
57
  "chokidar": "^5.0.0",
57
58
  "citty": "^0.1.6",
58
- "cosmiconfig": "^9.0.0",
59
+ "cosmiconfig": "^9.0.1",
59
60
  "jiti": "2.5.1",
60
61
  "tinyexec": "^1.0.2",
61
- "@kubb/core": "4.29.1"
62
+ "@kubb/core": "4.31.1"
62
63
  },
63
64
  "devDependencies": {
64
65
  "source-map-support": "^0.5.21",
65
- "@kubb/agent": "4.29.1",
66
- "@kubb/mcp": "4.29.1",
67
- "@kubb/oas": "4.29.1"
66
+ "@kubb/agent": "4.31.1",
67
+ "@kubb/mcp": "4.31.1",
68
+ "@kubb/oas": "4.31.1"
68
69
  },
69
70
  "engines": {
70
71
  "node": ">=20"
@@ -6,6 +6,8 @@ import { styleText } from 'node:util'
6
6
  import * as clack from '@clack/prompts'
7
7
  import type { ArgsDef } from 'citty'
8
8
  import { defineCommand } from 'citty'
9
+ import { version } from '../../../package.json'
10
+ import { buildTelemetryEvent, sendTelemetry } from '../../utils/telemetry.ts'
9
11
 
10
12
  const args = {
11
13
  config: {
@@ -122,6 +124,7 @@ const command = defineCommand({
122
124
  args,
123
125
  async run(commandContext) {
124
126
  const { args } = commandContext
127
+ const hrStart = process.hrtime()
125
128
 
126
129
  try {
127
130
  const configPath = path.resolve(process.cwd(), args.config || 'kubb.config.ts')
@@ -131,8 +134,10 @@ const command = defineCommand({
131
134
  const allowWrite = args['allow-write']
132
135
  const allowAll = args['allow-all']
133
136
 
134
- await startServer({ port, host, configPath, noCache, allowWrite, allowAll })
137
+ startServer({ port, host, configPath, noCache, allowWrite, allowAll })
138
+ await sendTelemetry(buildTelemetryEvent({ command: 'agent', kubbVersion: version, hrStart, status: 'success' }))
135
139
  } catch (error) {
140
+ await sendTelemetry(buildTelemetryEvent({ command: 'agent', kubbVersion: version, hrStart, status: 'failed' }))
136
141
  clack.log.error(styleText('red', 'Failed to start agent server'))
137
142
  console.error(error)
138
143
  process.exit(1)
@@ -3,9 +3,10 @@ import path from 'node:path'
3
3
  import process from 'node:process'
4
4
  import { styleText } from 'node:util'
5
5
  import * as clack from '@clack/prompts'
6
+ import { detectPackageManager, type PackageManagerInfo } from '@kubb/core'
6
7
  import { defineCommand } from 'citty'
7
8
  import { version } from '../../package.json'
8
- import { detectPackageManager, hasPackageJson, initPackageJson, installPackages, type PackageManagerInfo } from '../utils/packageManager.ts'
9
+ import { hasPackageJson, initPackageJson, installPackages } from '../utils/packageManager.ts'
9
10
 
10
11
  type PluginOption = {
11
12
  value: string
@@ -1,7 +1,10 @@
1
+ import process from 'node:process'
1
2
  import { styleText } from 'node:util'
2
3
  import type { ArgsDef } from 'citty'
3
4
  import { defineCommand, showUsage } from 'citty'
4
5
  import { createJiti } from 'jiti'
6
+ import { version } from '../../package.json'
7
+ import { buildTelemetryEvent, sendTelemetry } from '../utils/telemetry.ts'
5
8
 
6
9
  const jiti = createJiti(import.meta.url, {
7
10
  sourceMaps: true,
@@ -38,11 +41,14 @@ const command = defineCommand({
38
41
  }
39
42
 
40
43
  const { run } = mod
44
+ const hrStart = process.hrtime()
41
45
  try {
42
46
  console.log('⏳ Starting MCP server...')
43
47
  console.warn(styleText('yellow', 'This feature is still under development — use with caution'))
44
- await run()
48
+ run()
49
+ await sendTelemetry(buildTelemetryEvent({ command: 'mcp', kubbVersion: version, hrStart, status: 'success' }))
45
50
  } catch (error) {
51
+ await sendTelemetry(buildTelemetryEvent({ command: 'mcp', kubbVersion: version, hrStart, status: 'failed' }))
46
52
  console.error((error as Error)?.message)
47
53
  }
48
54
  },
@@ -2,6 +2,8 @@ import process from 'node:process'
2
2
  import type { ArgsDef } from 'citty'
3
3
  import { defineCommand, showUsage } from 'citty'
4
4
  import { createJiti } from 'jiti'
5
+ import { version } from '../../package.json'
6
+ import { buildTelemetryEvent, sendTelemetry } from '../utils/telemetry.ts'
5
7
 
6
8
  const jiti = createJiti(import.meta.url, {
7
9
  sourceMaps: true,
@@ -44,12 +46,15 @@ const command = defineCommand({
44
46
  }
45
47
 
46
48
  const { parse } = mod
49
+ const hrStart = process.hrtime()
47
50
  try {
48
51
  const oas = await parse(args.input)
49
52
  await oas.validate()
50
53
 
54
+ await sendTelemetry(buildTelemetryEvent({ command: 'validate', kubbVersion: version, hrStart, status: 'success' }))
51
55
  console.log('✅ Validation success')
52
56
  } catch (error) {
57
+ await sendTelemetry(buildTelemetryEvent({ command: 'validate', kubbVersion: version, hrStart, status: 'failed' }))
53
58
  console.error('❌ Validation failed')
54
59
  console.log((error as Error)?.message)
55
60
  process.exit(1)
package/src/index.ts CHANGED
@@ -1,5 +1,7 @@
1
+ import { styleText } from 'node:util'
1
2
  import { defineCommand, runCommand, runMain } from 'citty'
2
3
  import { version } from '../package.json'
4
+ import { isTelemetryDisabled } from './utils/telemetry.ts'
3
5
 
4
6
  const main = defineCommand({
5
7
  meta: {
@@ -20,6 +22,12 @@ const main = defineCommand({
20
22
  process.exit(0)
21
23
  }
22
24
 
25
+ if (!isTelemetryDisabled()) {
26
+ console.log(
27
+ `${styleText('yellow', 'Notice:')} Kubb collects anonymous telemetry data to help improve the tool. No personal data or file contents are collected. \nTo disable, set ${styleText('cyan', 'KUBB_DISABLE_TELEMETRY=1')}.\n`,
28
+ )
29
+ }
30
+
23
31
  if (!['generate', 'validate', 'mcp', 'agent', 'init'].includes(rawArgs[0] as string)) {
24
32
  // generate is not being used
25
33
  const generateCommand = await import('./commands/generate.ts').then((r) => r.default)
@@ -5,7 +5,9 @@ import { styleText } from 'node:util'
5
5
  import { type Config, type KubbEvents, LogLevel, safeBuild, setup } from '@kubb/core'
6
6
  import type { AsyncEventEmitter } from '@kubb/core/utils'
7
7
  import { detectFormatter, detectLinter, formatters, linters } from '@kubb/core/utils'
8
+ import { version } from '../../package.json'
8
9
  import { executeHooks } from '../utils/executeHooks.ts'
10
+ import { buildTelemetryEvent, sendTelemetry } from '../utils/telemetry.ts'
9
11
 
10
12
  type GenerateProps = {
11
13
  input?: string
@@ -80,11 +82,22 @@ export async function generate({ input, config: userConfig, events, logLevel }:
80
82
  await events.emit('generation:summary', config, {
81
83
  failedPlugins,
82
84
  filesCreated: files.length,
83
- status: failedPlugins.size > 0 || error ? 'failed' : 'success',
85
+ status: 'failed',
84
86
  hrStart,
85
87
  pluginTimings: logLevel >= LogLevel.verbose ? pluginTimings : undefined,
86
88
  })
87
89
 
90
+ await sendTelemetry(
91
+ buildTelemetryEvent({
92
+ command: 'generate',
93
+ kubbVersion: version,
94
+ plugins: pluginManager.plugins.map((p) => ({ name: p.name, options: p.options as Record<string, unknown> })),
95
+ hrStart,
96
+ filesCreated: files.length,
97
+ status: 'failed',
98
+ }),
99
+ )
100
+
88
101
  process.exit(1)
89
102
  }
90
103
 
@@ -194,11 +207,24 @@ export async function generate({ input, config: userConfig, events, logLevel }:
194
207
  await events.emit('hooks:end')
195
208
  }
196
209
 
210
+ const generationStatus = failedPlugins.size > 0 || error ? 'failed' : 'success'
211
+
197
212
  await events.emit('generation:summary', config, {
198
213
  failedPlugins,
199
214
  filesCreated: files.length,
200
- status: failedPlugins.size > 0 || error ? 'failed' : 'success',
215
+ status: generationStatus,
201
216
  hrStart,
202
217
  pluginTimings,
203
218
  })
219
+
220
+ const telemetryEvent = buildTelemetryEvent({
221
+ command: 'generate',
222
+ kubbVersion: version,
223
+ plugins: pluginManager.plugins.map((p) => ({ name: p.name, options: p.options as Record<string, unknown> })),
224
+ hrStart,
225
+ filesCreated: files.length,
226
+ status: generationStatus,
227
+ })
228
+
229
+ await sendTelemetry(telemetryEvent)
204
230
  }
@@ -1,72 +1,14 @@
1
1
  import { spawn } from 'node:child_process'
2
2
  import fs from 'node:fs'
3
3
  import path from 'node:path'
4
-
5
- export type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun'
6
-
7
- export interface PackageManagerInfo {
8
- name: PackageManager
9
- lockFile: string
10
- installCommand: string[]
11
- }
12
-
13
- const packageManagers: Record<PackageManager, PackageManagerInfo> = {
14
- pnpm: {
15
- name: 'pnpm',
16
- lockFile: 'pnpm-lock.yaml',
17
- installCommand: ['add', '-D'],
18
- },
19
- yarn: {
20
- name: 'yarn',
21
- lockFile: 'yarn.lock',
22
- installCommand: ['add', '-D'],
23
- },
24
- bun: {
25
- name: 'bun',
26
- lockFile: 'bun.lockb',
27
- installCommand: ['add', '-d'],
28
- },
29
- npm: {
30
- name: 'npm',
31
- lockFile: 'package-lock.json',
32
- installCommand: ['install', '--save-dev'],
33
- },
34
- }
35
-
36
- export function detectPackageManager(cwd: string = process.cwd()): PackageManagerInfo {
37
- // Check for packageManager field in package.json
38
- const packageJsonPath = path.join(cwd, 'package.json')
39
- if (fs.existsSync(packageJsonPath)) {
40
- try {
41
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))
42
- if (packageJson.packageManager) {
43
- const [name] = packageJson.packageManager.split('@')
44
- if (name in packageManagers) {
45
- return packageManagers[name as PackageManager]
46
- }
47
- }
48
- } catch {
49
- // Continue to lock file detection
50
- }
51
- }
52
-
53
- // Check for lock files
54
- for (const pm of Object.values(packageManagers)) {
55
- if (fs.existsSync(path.join(cwd, pm.lockFile))) {
56
- return pm
57
- }
58
- }
59
-
60
- // Default to npm
61
- return packageManagers.npm
62
- }
4
+ import type { PackageManagerInfo, PackageManagerName } from '@kubb/core'
63
5
 
64
6
  export function hasPackageJson(cwd: string = process.cwd()): boolean {
65
7
  return fs.existsSync(path.join(cwd, 'package.json'))
66
8
  }
67
9
 
68
10
  export async function initPackageJson(cwd: string, packageManager: PackageManagerInfo): Promise<void> {
69
- const commands: Record<PackageManager, string[]> = {
11
+ const commands: Record<PackageManagerName, string[]> = {
70
12
  npm: ['init', '-y'],
71
13
  pnpm: ['init'],
72
14
  yarn: ['init', '-y'],