@kubb/cli 5.0.0-beta.6 → 5.0.0-beta.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +17 -10
- package/README.md +170 -51
- package/dist/Telemetry-CVdyJarO.js +283 -0
- package/dist/Telemetry-CVdyJarO.js.map +1 -0
- package/dist/Telemetry-DrppRqqW.cjs +320 -0
- package/dist/Telemetry-DrppRqqW.cjs.map +1 -0
- package/dist/{define-Bdn8j5VM.cjs → define-C4AB3POr.cjs} +2 -2
- package/dist/{define-Bdn8j5VM.cjs.map → define-C4AB3POr.cjs.map} +1 -1
- package/dist/{define-Ctii4bel.js → define-C63T4jp6.js} +2 -2
- package/dist/{define-Ctii4bel.js.map → define-C63T4jp6.js.map} +1 -1
- package/dist/{errors-CjPmyZHy.js → errors-BsemQCMn.js} +2 -2
- package/dist/{errors-CjPmyZHy.js.map → errors-BsemQCMn.js.map} +1 -1
- package/dist/{errors-CLCjoSg0.cjs → errors-DykI11xo.cjs} +2 -2
- package/dist/{errors-CLCjoSg0.cjs.map → errors-DykI11xo.cjs.map} +1 -1
- package/dist/{generate-BB2Q7I9s.cjs → generate-CJuBlTeJ.cjs} +22 -17
- package/dist/generate-CJuBlTeJ.cjs.map +1 -0
- package/dist/{generate-BmulGxIM.js → generate-DAePC4G2.js} +22 -17
- package/dist/generate-DAePC4G2.js.map +1 -0
- package/dist/index.cjs +10 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +10 -27
- package/dist/index.js.map +1 -1
- package/dist/{init-BTp9if7K.js → init-C8m7Z_W8.js} +6 -6
- package/dist/{init-BTp9if7K.js.map → init-C8m7Z_W8.js.map} +1 -1
- package/dist/{init-Dpg8e1HN.cjs → init-T1DC44PT.cjs} +6 -6
- package/dist/{init-Dpg8e1HN.cjs.map → init-T1DC44PT.cjs.map} +1 -1
- package/dist/{mcp-wpl6sYYR.cjs → mcp-B60MeTmD.cjs} +6 -6
- package/dist/{mcp-wpl6sYYR.cjs.map → mcp-B60MeTmD.cjs.map} +1 -1
- package/dist/{mcp-C9RoU-Dg.js → mcp-lEYflz1a.js} +6 -6
- package/dist/{mcp-C9RoU-Dg.js.map → mcp-lEYflz1a.js.map} +1 -1
- package/dist/package-BynuV_3t.js +6 -0
- package/dist/package-BynuV_3t.js.map +1 -0
- package/dist/{package-iheSdfas.cjs → package-QUV6JOtx.cjs} +2 -2
- package/dist/package-QUV6JOtx.cjs.map +1 -0
- package/dist/run-9ZhHuNZQ.cjs +33 -0
- package/dist/run-9ZhHuNZQ.cjs.map +1 -0
- package/dist/run-BG7Giryi.js +296 -0
- package/dist/run-BG7Giryi.js.map +1 -0
- package/dist/{validate-BU4fPTMc.cjs → run-BQO_tPlc.cjs} +25 -20
- package/dist/run-BQO_tPlc.cjs.map +1 -0
- package/dist/run-C-5oRB_f.cjs +1380 -0
- package/dist/run-C-5oRB_f.cjs.map +1 -0
- package/dist/run-CYnDu3ch.js +51 -0
- package/dist/run-CYnDu3ch.js.map +1 -0
- package/dist/run-Da0AZlgo.js +1377 -0
- package/dist/run-Da0AZlgo.js.map +1 -0
- package/dist/run-DpKny2hT.cjs +300 -0
- package/dist/run-DpKny2hT.cjs.map +1 -0
- package/dist/run-h8NTawHO.js +32 -0
- package/dist/run-h8NTawHO.js.map +1 -0
- package/dist/tools-BU99bhi8.js +152 -0
- package/dist/tools-BU99bhi8.js.map +1 -0
- package/dist/tools-_Xp8-_zy.cjs +175 -0
- package/dist/tools-_Xp8-_zy.cjs.map +1 -0
- package/dist/{validate-BfJoCxrC.js → validate-BhDi3x5e.js} +6 -6
- package/dist/{validate-BfJoCxrC.js.map → validate-BhDi3x5e.js.map} +1 -1
- package/dist/{validate-DIDBROB2.cjs → validate-CUEvWAyG.cjs} +6 -6
- package/dist/{validate-DIDBROB2.cjs.map → validate-CUEvWAyG.cjs.map} +1 -1
- package/package.json +12 -27
- package/src/Telemetry.ts +297 -0
- package/src/commands/generate.ts +18 -12
- package/src/commands/init.ts +2 -2
- package/src/commands/mcp.ts +2 -2
- package/src/commands/validate.ts +2 -2
- package/src/constants.ts +2 -35
- package/src/index.ts +5 -21
- package/src/loggers/clackLogger.ts +136 -202
- package/src/loggers/defineLogger.ts +59 -0
- package/src/loggers/plainLogger.ts +48 -103
- package/src/loggers/types.ts +6 -1
- package/src/loggers/utils.ts +167 -24
- package/src/runners/generate/run.ts +399 -0
- package/src/runners/generate/utils.ts +229 -0
- package/src/runners/{init.ts → init/run.ts} +81 -78
- package/src/runners/init/utils.ts +39 -0
- package/src/runners/mcp/run.ts +37 -0
- package/src/runners/{validate.ts → validate/run.ts} +25 -20
- package/dist/agent-BJEvbSiP.js +0 -68
- package/dist/agent-BJEvbSiP.js.map +0 -1
- package/dist/agent-CXNO6dgj.cjs +0 -70
- package/dist/agent-CXNO6dgj.cjs.map +0 -1
- package/dist/agent-D9CKYh4K.cjs +0 -122
- package/dist/agent-D9CKYh4K.cjs.map +0 -1
- package/dist/agent-VXKxLCho.js +0 -118
- package/dist/agent-VXKxLCho.js.map +0 -1
- package/dist/constants-BPJBMT_6.js +0 -45
- package/dist/constants-BPJBMT_6.js.map +0 -1
- package/dist/constants-BYGmiFs0.cjs +0 -139
- package/dist/constants-BYGmiFs0.cjs.map +0 -1
- package/dist/constants-DSJ-Xrbv.js +0 -116
- package/dist/constants-DSJ-Xrbv.js.map +0 -1
- package/dist/constants-Rcaqzyd-.cjs +0 -80
- package/dist/constants-Rcaqzyd-.cjs.map +0 -1
- package/dist/generate-BB2Q7I9s.cjs.map +0 -1
- package/dist/generate-B_p5dl68.cjs +0 -1755
- package/dist/generate-B_p5dl68.cjs.map +0 -1
- package/dist/generate-BmulGxIM.js.map +0 -1
- package/dist/generate-DAsdUw3z.js +0 -1752
- package/dist/generate-DAsdUw3z.js.map +0 -1
- package/dist/init-CJ80lKSP.cjs +0 -239
- package/dist/init-CJ80lKSP.cjs.map +0 -1
- package/dist/init-DCqcEq86.js +0 -235
- package/dist/init-DCqcEq86.js.map +0 -1
- package/dist/mcp-D1llTaRM.cjs +0 -50
- package/dist/mcp-D1llTaRM.cjs.map +0 -1
- package/dist/mcp-DNUw8nqb.js +0 -49
- package/dist/mcp-DNUw8nqb.js.map +0 -1
- package/dist/package-iheSdfas.cjs.map +0 -1
- package/dist/package-vLafMWCe.js +0 -6
- package/dist/package-vLafMWCe.js.map +0 -1
- package/dist/shell-475fQKaX.cjs +0 -62
- package/dist/shell-475fQKaX.cjs.map +0 -1
- package/dist/shell-DLzN4fRo.js +0 -51
- package/dist/shell-DLzN4fRo.js.map +0 -1
- package/dist/telemetry-BLX0NzRk.cjs +0 -282
- package/dist/telemetry-BLX0NzRk.cjs.map +0 -1
- package/dist/telemetry-juq4QBf7.js +0 -245
- package/dist/telemetry-juq4QBf7.js.map +0 -1
- package/dist/validate-BU4fPTMc.cjs.map +0 -1
- package/dist/validate-k9s_hFah.js +0 -46
- package/dist/validate-k9s_hFah.js.map +0 -1
- package/src/commands/agent/start.ts +0 -50
- package/src/commands/agent.ts +0 -10
- package/src/loggers/fileSystemLogger.ts +0 -138
- package/src/loggers/githubActionsLogger.ts +0 -379
- package/src/runners/agent.ts +0 -155
- package/src/runners/generate.ts +0 -333
- package/src/runners/mcp.ts +0 -56
- package/src/types.ts +0 -11
- package/src/utils/Writables.ts +0 -17
- package/src/utils/executeHooks.ts +0 -45
- package/src/utils/flags.ts +0 -9
- package/src/utils/getConfig.ts +0 -10
- package/src/utils/getCosmiConfig.ts +0 -75
- package/src/utils/getSummary.ts +0 -68
- package/src/utils/packageManager.ts +0 -23
- package/src/utils/runHook.ts +0 -91
- package/src/utils/telemetry.ts +0 -273
- package/src/utils/watcher.ts +0 -19
- /package/dist/{chunk-ByKO4r7w.cjs → chunk-Bx3C2hgW.cjs} +0 -0
- /package/dist/{chunk--u3MIqq1.js → chunk-C0LytTxp.js} +0 -0
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import type { Config } from '@kubb/core'
|
|
2
|
-
import { cosmiconfig } from 'cosmiconfig'
|
|
3
|
-
import { createJiti } from 'jiti'
|
|
4
|
-
|
|
5
|
-
type CosmiconfigResult = {
|
|
6
|
-
filepath: string
|
|
7
|
-
isEmpty?: boolean
|
|
8
|
-
config: Config
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const jiti = createJiti(import.meta.url, {
|
|
12
|
-
jsx: {
|
|
13
|
-
runtime: 'automatic',
|
|
14
|
-
importSource: '@kubb/renderer-jsx',
|
|
15
|
-
},
|
|
16
|
-
moduleCache: false,
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
const tsLoader = async (configFile: string) => {
|
|
20
|
-
return jiti.import(configFile, { default: true })
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export async function getCosmiConfig(moduleName: string, config?: string): Promise<CosmiconfigResult> {
|
|
24
|
-
let result: CosmiconfigResult
|
|
25
|
-
const searchPlaces = [
|
|
26
|
-
'package.json',
|
|
27
|
-
`.${moduleName}rc`,
|
|
28
|
-
`.${moduleName}rc.json`,
|
|
29
|
-
`.${moduleName}rc.yaml`,
|
|
30
|
-
`.${moduleName}rc.yml`,
|
|
31
|
-
|
|
32
|
-
`.${moduleName}rc.ts`,
|
|
33
|
-
`.${moduleName}rc.mts`,
|
|
34
|
-
`.${moduleName}rc.cts`,
|
|
35
|
-
`.${moduleName}rc.js`,
|
|
36
|
-
`.${moduleName}rc.mjs`,
|
|
37
|
-
`.${moduleName}rc.cjs`,
|
|
38
|
-
|
|
39
|
-
`${moduleName}.config.ts`,
|
|
40
|
-
`${moduleName}.config.mts`,
|
|
41
|
-
`${moduleName}.config.cts`,
|
|
42
|
-
`${moduleName}.config.js`,
|
|
43
|
-
`${moduleName}.config.mjs`,
|
|
44
|
-
`${moduleName}.config.cjs`,
|
|
45
|
-
]
|
|
46
|
-
const explorer = cosmiconfig(moduleName, {
|
|
47
|
-
cache: false,
|
|
48
|
-
searchPlaces: [
|
|
49
|
-
...searchPlaces.map((searchPlace) => {
|
|
50
|
-
return `.config/${searchPlace}`
|
|
51
|
-
}),
|
|
52
|
-
...searchPlaces.map((searchPlace) => {
|
|
53
|
-
return `configs/${searchPlace}`
|
|
54
|
-
}),
|
|
55
|
-
...searchPlaces,
|
|
56
|
-
],
|
|
57
|
-
loaders: {
|
|
58
|
-
'.ts': tsLoader,
|
|
59
|
-
'.mts': tsLoader,
|
|
60
|
-
'.cts': tsLoader,
|
|
61
|
-
},
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
try {
|
|
65
|
-
result = config ? ((await explorer.load(config)) as CosmiconfigResult) : ((await explorer.search()) as CosmiconfigResult)
|
|
66
|
-
} catch (error) {
|
|
67
|
-
throw new Error('Config failed loading', { cause: error })
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (result?.isEmpty || !result || !result.config) {
|
|
71
|
-
throw new Error('Config not defined, create a kubb.config.js or pass through your config with the option --config')
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return result as CosmiconfigResult
|
|
75
|
-
}
|
package/src/utils/getSummary.ts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import path from 'node:path'
|
|
2
|
-
import { styleText } from 'node:util'
|
|
3
|
-
import { formatHrtime, randomCliColor } from '@internals/utils'
|
|
4
|
-
import type { Config, Plugin } from '@kubb/core'
|
|
5
|
-
import { SUMMARY_MAX_BAR_LENGTH, SUMMARY_TIME_SCALE_DIVISOR } from '../constants.ts'
|
|
6
|
-
|
|
7
|
-
type SummaryProps = {
|
|
8
|
-
failedPlugins: Set<{ plugin: Plugin; error: Error }>
|
|
9
|
-
status: 'success' | 'failed'
|
|
10
|
-
hrStart: [number, number]
|
|
11
|
-
filesCreated: number
|
|
12
|
-
config: Config
|
|
13
|
-
pluginTimings?: Map<string, number>
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function getSummary({ failedPlugins, filesCreated, status, hrStart, config, pluginTimings }: SummaryProps): string[] {
|
|
17
|
-
const duration = formatHrtime(hrStart)
|
|
18
|
-
|
|
19
|
-
const pluginsCount = config.plugins?.length ?? 0
|
|
20
|
-
const successCount = pluginsCount - failedPlugins.size
|
|
21
|
-
|
|
22
|
-
const meta = {
|
|
23
|
-
plugins:
|
|
24
|
-
status === 'success'
|
|
25
|
-
? `${styleText('green', `${successCount} successful`)}, ${pluginsCount} total`
|
|
26
|
-
: `${styleText('green', `${successCount} successful`)}, ${styleText('red', `${failedPlugins.size} failed`)}, ${pluginsCount} total`,
|
|
27
|
-
pluginsFailed: status === 'failed' ? [...failedPlugins].map(({ plugin }) => randomCliColor(plugin.name)).join(', ') : undefined,
|
|
28
|
-
filesCreated,
|
|
29
|
-
time: styleText('green', duration),
|
|
30
|
-
output: path.resolve(config.root, config.output.path),
|
|
31
|
-
} as const
|
|
32
|
-
|
|
33
|
-
const labels = {
|
|
34
|
-
plugins: 'Plugins:',
|
|
35
|
-
failed: 'Failed:',
|
|
36
|
-
generated: 'Generated:',
|
|
37
|
-
pluginTimings: 'Plugin Timings:',
|
|
38
|
-
output: 'Output:',
|
|
39
|
-
}
|
|
40
|
-
const maxLength = Math.max(0, ...[...Object.values(labels), ...(pluginTimings ? Array.from(pluginTimings.keys()) : [])].map((s) => s.length))
|
|
41
|
-
|
|
42
|
-
const summaryLines: string[] = []
|
|
43
|
-
summaryLines.push(`${labels.plugins.padEnd(maxLength + 2)} ${meta.plugins}`)
|
|
44
|
-
|
|
45
|
-
if (meta.pluginsFailed) {
|
|
46
|
-
summaryLines.push(`${labels.failed.padEnd(maxLength + 2)} ${meta.pluginsFailed}`)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
summaryLines.push(`${labels.generated.padEnd(maxLength + 2)} ${meta.filesCreated} files in ${meta.time}`)
|
|
50
|
-
|
|
51
|
-
if (pluginTimings && pluginTimings.size > 0) {
|
|
52
|
-
const sortedTimings = Array.from(pluginTimings.entries()).sort((a, b) => b[1] - a[1])
|
|
53
|
-
|
|
54
|
-
summaryLines.push(`${labels.pluginTimings}`)
|
|
55
|
-
|
|
56
|
-
sortedTimings.forEach(([name, time]) => {
|
|
57
|
-
const timeStr = time >= 1000 ? `${(time / 1000).toFixed(2)}s` : `${Math.round(time)}ms`
|
|
58
|
-
const barLength = Math.min(Math.ceil(time / SUMMARY_TIME_SCALE_DIVISOR), SUMMARY_MAX_BAR_LENGTH)
|
|
59
|
-
const bar = styleText('dim', '█'.repeat(barLength))
|
|
60
|
-
|
|
61
|
-
summaryLines.push(`${styleText('dim', '•')} ${name.padEnd(maxLength + 1)}${bar} ${timeStr}`)
|
|
62
|
-
})
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
summaryLines.push(`${labels.output.padEnd(maxLength + 2)} ${meta.output}`)
|
|
66
|
-
|
|
67
|
-
return summaryLines
|
|
68
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
import type { PackageManagerInfo, PackageManagerName } from '@internals/utils'
|
|
4
|
-
import { spawnAsync } from '@internals/utils'
|
|
5
|
-
|
|
6
|
-
export function hasPackageJson(cwd: string = process.cwd()): boolean {
|
|
7
|
-
return fs.existsSync(path.join(cwd, 'package.json'))
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export async function initPackageJson(cwd: string, packageManager: PackageManagerInfo): Promise<void> {
|
|
11
|
-
const commands: Record<PackageManagerName, string[]> = {
|
|
12
|
-
npm: ['init', '-y'],
|
|
13
|
-
pnpm: ['init'],
|
|
14
|
-
yarn: ['init', '-y'],
|
|
15
|
-
bun: ['init', '-y'],
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
await spawnAsync(packageManager.name, commands[packageManager.name], { cwd })
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export async function installPackages(packages: string[], packageManager: PackageManagerInfo, cwd: string = process.cwd()): Promise<void> {
|
|
22
|
-
await spawnAsync(packageManager.name, [...packageManager.installCommand, ...packages], { cwd })
|
|
23
|
-
}
|
package/src/utils/runHook.ts
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import type { AsyncEventEmitter } from '@internals/utils'
|
|
2
|
-
import { toError } from '@internals/utils'
|
|
3
|
-
import type { KubbHooks } from '@kubb/core'
|
|
4
|
-
import { NonZeroExitError, x } from 'tinyexec'
|
|
5
|
-
|
|
6
|
-
type HookOutputSink = {
|
|
7
|
-
/** Called for each streamed stdout line while the hook runs (optional). */
|
|
8
|
-
onLine?: (line: string) => void
|
|
9
|
-
/** Called on stderr after failure (optional). */
|
|
10
|
-
onStderr?: (text: string) => void
|
|
11
|
-
/** Called on stdout after failure (optional). */
|
|
12
|
-
onStdout?: (text: string) => void
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
type RunHookOptions = {
|
|
16
|
-
id: string
|
|
17
|
-
command: string
|
|
18
|
-
args?: readonly string[]
|
|
19
|
-
commandWithArgs: string
|
|
20
|
-
context: AsyncEventEmitter<KubbHooks>
|
|
21
|
-
/** When true the process output is streamed line-by-line via onLine. */
|
|
22
|
-
stream?: boolean
|
|
23
|
-
sink?: HookOutputSink
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Executes a hook command, emits debug and completion events, and forwards output to an optional sink.
|
|
28
|
-
*/
|
|
29
|
-
export async function runHook({ id, command, args, commandWithArgs, context, stream = false, sink }: RunHookOptions): Promise<void> {
|
|
30
|
-
try {
|
|
31
|
-
const proc = x(command, [...(args ?? [])], {
|
|
32
|
-
nodeOptions: { detached: process.platform !== 'win32' },
|
|
33
|
-
throwOnError: true,
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
if (stream && sink?.onLine) {
|
|
37
|
-
for await (const line of proc) {
|
|
38
|
-
sink.onLine(line)
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const result = await proc
|
|
43
|
-
|
|
44
|
-
await context.emit('kubb:debug', {
|
|
45
|
-
date: new Date(),
|
|
46
|
-
logs: [result.stdout.trimEnd()],
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
await context.emit('kubb:hook:end', {
|
|
50
|
-
command,
|
|
51
|
-
args,
|
|
52
|
-
id,
|
|
53
|
-
success: true,
|
|
54
|
-
error: null,
|
|
55
|
-
})
|
|
56
|
-
} catch (err) {
|
|
57
|
-
if (!(err instanceof NonZeroExitError)) {
|
|
58
|
-
await context.emit('kubb:hook:end', {
|
|
59
|
-
command,
|
|
60
|
-
args,
|
|
61
|
-
id,
|
|
62
|
-
success: false,
|
|
63
|
-
error: toError(err),
|
|
64
|
-
})
|
|
65
|
-
await context.emit('kubb:error', { error: toError(err) })
|
|
66
|
-
return
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const stderr = err.output?.stderr ?? ''
|
|
70
|
-
const stdout = err.output?.stdout ?? ''
|
|
71
|
-
|
|
72
|
-
await context.emit('kubb:debug', {
|
|
73
|
-
date: new Date(),
|
|
74
|
-
logs: [stdout, stderr].filter(Boolean),
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
if (stderr) sink?.onStderr?.(stderr)
|
|
78
|
-
if (stdout) sink?.onStdout?.(stdout)
|
|
79
|
-
|
|
80
|
-
const errorMessage = new Error(`Hook execute failed: ${commandWithArgs}`)
|
|
81
|
-
|
|
82
|
-
await context.emit('kubb:hook:end', {
|
|
83
|
-
command,
|
|
84
|
-
args,
|
|
85
|
-
id,
|
|
86
|
-
success: false,
|
|
87
|
-
error: errorMessage,
|
|
88
|
-
})
|
|
89
|
-
await context.emit('kubb:error', { error: errorMessage })
|
|
90
|
-
}
|
|
91
|
-
}
|
package/src/utils/telemetry.ts
DELETED
|
@@ -1,273 +0,0 @@
|
|
|
1
|
-
import { randomBytes } from 'node:crypto'
|
|
2
|
-
import os from 'node:os'
|
|
3
|
-
import process from 'node:process'
|
|
4
|
-
import { executeIfOnline, isCIEnvironment } from '@internals/utils'
|
|
5
|
-
import { OTLP_ENDPOINT } from '../constants.ts'
|
|
6
|
-
|
|
7
|
-
// OpenTelemetry OTLP JSON types
|
|
8
|
-
// https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/trace/v1/trace.proto
|
|
9
|
-
// https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/common/v1/common.proto
|
|
10
|
-
|
|
11
|
-
type OtlpStringValue = { stringValue: string }
|
|
12
|
-
type OtlpBoolValue = { boolValue: boolean }
|
|
13
|
-
type OtlpIntValue = { intValue: number }
|
|
14
|
-
type OtlpDoubleValue = { doubleValue: number }
|
|
15
|
-
type OtlpBytesValue = { bytesValue: string }
|
|
16
|
-
type OtlpArrayValue = { arrayValue: { values: OtlpAnyValue[] } }
|
|
17
|
-
type OtlpKvListValue = { kvlistValue: { values: OtlpKeyValue[] } }
|
|
18
|
-
|
|
19
|
-
type OtlpAnyValue = OtlpStringValue | OtlpBoolValue | OtlpIntValue | OtlpDoubleValue | OtlpBytesValue | OtlpArrayValue | OtlpKvListValue
|
|
20
|
-
|
|
21
|
-
type OtlpKeyValue = {
|
|
22
|
-
key: string
|
|
23
|
-
value: OtlpAnyValue
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
type OtlpResource = {
|
|
27
|
-
attributes: OtlpKeyValue[]
|
|
28
|
-
droppedAttributesCount?: number
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
type OtlpInstrumentationScope = {
|
|
32
|
-
name: string
|
|
33
|
-
version?: string
|
|
34
|
-
attributes?: OtlpKeyValue[]
|
|
35
|
-
droppedAttributesCount?: number
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/** https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/trace/v1/trace.proto#L103 */
|
|
39
|
-
type OtlpSpanKind = 0 | 1 | 2 | 3 | 4 | 5
|
|
40
|
-
|
|
41
|
-
/** 0 = STATUS_CODE_UNSET, 1 = STATUS_CODE_OK, 2 = STATUS_CODE_ERROR */
|
|
42
|
-
type OtlpStatusCode = 0 | 1 | 2
|
|
43
|
-
|
|
44
|
-
type OtlpStatus = {
|
|
45
|
-
code: OtlpStatusCode
|
|
46
|
-
message?: string
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
type OtlpSpan = {
|
|
50
|
-
traceId: string
|
|
51
|
-
spanId: string
|
|
52
|
-
traceState?: string
|
|
53
|
-
parentSpanId?: string
|
|
54
|
-
name: string
|
|
55
|
-
kind: OtlpSpanKind
|
|
56
|
-
startTimeUnixNano: string
|
|
57
|
-
endTimeUnixNano: string
|
|
58
|
-
attributes?: OtlpKeyValue[]
|
|
59
|
-
droppedAttributesCount?: number
|
|
60
|
-
events?: OtlpSpanEvent[]
|
|
61
|
-
droppedEventsCount?: number
|
|
62
|
-
links?: OtlpSpanLink[]
|
|
63
|
-
droppedLinksCount?: number
|
|
64
|
-
status?: OtlpStatus
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
type OtlpSpanEvent = {
|
|
68
|
-
timeUnixNano: string
|
|
69
|
-
name: string
|
|
70
|
-
attributes?: OtlpKeyValue[]
|
|
71
|
-
droppedAttributesCount?: number
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
type OtlpSpanLink = {
|
|
75
|
-
traceId: string
|
|
76
|
-
spanId: string
|
|
77
|
-
traceState?: string
|
|
78
|
-
attributes?: OtlpKeyValue[]
|
|
79
|
-
droppedAttributesCount?: number
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
type OtlpScopeSpans = {
|
|
83
|
-
scope: OtlpInstrumentationScope
|
|
84
|
-
spans: OtlpSpan[]
|
|
85
|
-
schemaUrl?: string
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
type OtlpResourceSpans = {
|
|
89
|
-
resource: OtlpResource
|
|
90
|
-
scopeSpans: OtlpScopeSpans[]
|
|
91
|
-
schemaUrl?: string
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/** Root payload sent to POST /v1/traces */
|
|
95
|
-
type OtlpExportTraceServiceRequest = {
|
|
96
|
-
resourceSpans: OtlpResourceSpans[]
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export type TelemetryPlugin = {
|
|
100
|
-
name: string
|
|
101
|
-
options: Record<string, unknown>
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
type TelemetryEvent = {
|
|
105
|
-
command: string
|
|
106
|
-
kubbVersion: string
|
|
107
|
-
nodeVersion: string
|
|
108
|
-
platform: string
|
|
109
|
-
ci: boolean
|
|
110
|
-
plugins: TelemetryPlugin[]
|
|
111
|
-
duration: number
|
|
112
|
-
filesCreated: number
|
|
113
|
-
status: 'success' | 'failed'
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Detect whether the current process is running inside a CI environment.
|
|
118
|
-
* Delegates to the canonical isCIEnvironment() from envDetection.
|
|
119
|
-
*/
|
|
120
|
-
export function isCi(): boolean {
|
|
121
|
-
return isCIEnvironment()
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Check if telemetry is disabled via DO_NOT_TRACK or KUBB_DISABLE_TELEMETRY.
|
|
126
|
-
* Respects the standard DO_NOT_TRACK convention used across development tools.
|
|
127
|
-
*/
|
|
128
|
-
export function isTelemetryDisabled(): boolean {
|
|
129
|
-
return (
|
|
130
|
-
process.env['DO_NOT_TRACK'] === '1' ||
|
|
131
|
-
process.env['DO_NOT_TRACK'] === 'true' ||
|
|
132
|
-
process.env['KUBB_DISABLE_TELEMETRY'] === '1' ||
|
|
133
|
-
process.env['KUBB_DISABLE_TELEMETRY'] === 'true'
|
|
134
|
-
)
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Convert a TelemetryEvent into an OTLP-compatible JSON trace payload.
|
|
139
|
-
* See https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/
|
|
140
|
-
*/
|
|
141
|
-
export function buildOtlpPayload(event: TelemetryEvent): OtlpExportTraceServiceRequest {
|
|
142
|
-
const traceId = randomBytes(16).toString('hex')
|
|
143
|
-
const spanId = randomBytes(8).toString('hex')
|
|
144
|
-
const endTimeNs = BigInt(Date.now()) * 1_000_000n
|
|
145
|
-
const startTimeNs = endTimeNs - BigInt(event.duration) * 1_000_000n
|
|
146
|
-
|
|
147
|
-
const attributes: OtlpKeyValue[] = [
|
|
148
|
-
{ key: 'kubb.command', value: { stringValue: event.command } },
|
|
149
|
-
{ key: 'kubb.version', value: { stringValue: event.kubbVersion } },
|
|
150
|
-
{ key: 'kubb.node_version', value: { stringValue: event.nodeVersion } },
|
|
151
|
-
{ key: 'kubb.platform', value: { stringValue: event.platform } },
|
|
152
|
-
{ key: 'kubb.ci', value: { boolValue: event.ci } },
|
|
153
|
-
{ key: 'kubb.files_created', value: { intValue: event.filesCreated } },
|
|
154
|
-
{ key: 'kubb.status', value: { stringValue: event.status } },
|
|
155
|
-
{
|
|
156
|
-
key: 'kubb.plugins',
|
|
157
|
-
value: {
|
|
158
|
-
arrayValue: {
|
|
159
|
-
values: event.plugins.map(
|
|
160
|
-
(p): OtlpKvListValue => ({
|
|
161
|
-
kvlistValue: {
|
|
162
|
-
values: [
|
|
163
|
-
{ key: 'name', value: { stringValue: p.name } },
|
|
164
|
-
{
|
|
165
|
-
key: 'options',
|
|
166
|
-
value: {
|
|
167
|
-
stringValue: JSON.stringify({
|
|
168
|
-
...p.options,
|
|
169
|
-
usedEnumNames: undefined,
|
|
170
|
-
}),
|
|
171
|
-
},
|
|
172
|
-
},
|
|
173
|
-
],
|
|
174
|
-
},
|
|
175
|
-
}),
|
|
176
|
-
),
|
|
177
|
-
},
|
|
178
|
-
},
|
|
179
|
-
},
|
|
180
|
-
]
|
|
181
|
-
|
|
182
|
-
return {
|
|
183
|
-
resourceSpans: [
|
|
184
|
-
{
|
|
185
|
-
resource: {
|
|
186
|
-
attributes: [
|
|
187
|
-
{ key: 'service.name', value: { stringValue: 'kubb-cli' } },
|
|
188
|
-
{
|
|
189
|
-
key: 'service.version',
|
|
190
|
-
value: { stringValue: event.kubbVersion },
|
|
191
|
-
},
|
|
192
|
-
{ key: 'telemetry.sdk.language', value: { stringValue: 'nodejs' } },
|
|
193
|
-
],
|
|
194
|
-
},
|
|
195
|
-
scopeSpans: [
|
|
196
|
-
{
|
|
197
|
-
scope: { name: 'kubb-cli', version: event.kubbVersion },
|
|
198
|
-
spans: [
|
|
199
|
-
{
|
|
200
|
-
traceId,
|
|
201
|
-
spanId,
|
|
202
|
-
name: event.command,
|
|
203
|
-
kind: 1 satisfies OtlpSpanKind,
|
|
204
|
-
startTimeUnixNano: String(startTimeNs),
|
|
205
|
-
endTimeUnixNano: String(endTimeNs),
|
|
206
|
-
attributes,
|
|
207
|
-
status: {
|
|
208
|
-
code: (event.status === 'success' ? 1 : 2) satisfies OtlpStatusCode,
|
|
209
|
-
},
|
|
210
|
-
},
|
|
211
|
-
],
|
|
212
|
-
},
|
|
213
|
-
],
|
|
214
|
-
},
|
|
215
|
-
],
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Send an anonymous telemetry event to the Kubb OTLP endpoint.
|
|
221
|
-
* Respects DO_NOT_TRACK and KUBB_DISABLE_TELEMETRY environment variables.
|
|
222
|
-
* Fails silently to never interrupt the generation process.
|
|
223
|
-
*/
|
|
224
|
-
export async function sendTelemetry(event: TelemetryEvent): Promise<void> {
|
|
225
|
-
if (isTelemetryDisabled()) {
|
|
226
|
-
return
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
await executeIfOnline(async () => {
|
|
230
|
-
try {
|
|
231
|
-
await fetch(`${OTLP_ENDPOINT}/v1/traces`, {
|
|
232
|
-
method: 'POST',
|
|
233
|
-
headers: {
|
|
234
|
-
'Content-Type': 'application/json',
|
|
235
|
-
'Kubb-Telemetry-Version': '1',
|
|
236
|
-
'Kubb-Telemetry-Source': 'kubb-cli',
|
|
237
|
-
},
|
|
238
|
-
body: JSON.stringify(buildOtlpPayload(event)),
|
|
239
|
-
signal: AbortSignal.timeout(5_000),
|
|
240
|
-
})
|
|
241
|
-
} catch (_e) {
|
|
242
|
-
// Fail silently – telemetry must never break the CLI
|
|
243
|
-
}
|
|
244
|
-
})
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Build an anonymous telemetry payload from a completed generation run.
|
|
249
|
-
* No file paths, OpenAPI specs, or secrets are included.
|
|
250
|
-
*/
|
|
251
|
-
export function buildTelemetryEvent(options: {
|
|
252
|
-
command: 'generate' | 'mcp' | 'validate' | 'agent'
|
|
253
|
-
kubbVersion: string
|
|
254
|
-
plugins?: TelemetryPlugin[]
|
|
255
|
-
hrStart: [number, number]
|
|
256
|
-
filesCreated?: number
|
|
257
|
-
status: 'success' | 'failed'
|
|
258
|
-
}): TelemetryEvent {
|
|
259
|
-
const [seconds, nanoseconds] = process.hrtime(options.hrStart)
|
|
260
|
-
const duration = Math.round(seconds * 1000 + nanoseconds / 1e6)
|
|
261
|
-
|
|
262
|
-
return {
|
|
263
|
-
command: options.command,
|
|
264
|
-
kubbVersion: options.kubbVersion,
|
|
265
|
-
nodeVersion: process.versions.node.split('.')[0] as string,
|
|
266
|
-
platform: os.platform(),
|
|
267
|
-
ci: isCi(),
|
|
268
|
-
plugins: options.plugins ?? [],
|
|
269
|
-
duration,
|
|
270
|
-
filesCreated: options.filesCreated ?? 0,
|
|
271
|
-
status: options.status,
|
|
272
|
-
}
|
|
273
|
-
}
|
package/src/utils/watcher.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { styleText } from 'node:util'
|
|
2
|
-
import { WATCHER_IGNORED_PATHS } from '../constants.ts'
|
|
3
|
-
|
|
4
|
-
export async function startWatcher(path: string[], cb: (path: string[]) => Promise<void>): Promise<void> {
|
|
5
|
-
const { watch } = await import('chokidar')
|
|
6
|
-
const watcher = watch(path, {
|
|
7
|
-
ignorePermissionErrors: true,
|
|
8
|
-
ignored: WATCHER_IGNORED_PATHS,
|
|
9
|
-
})
|
|
10
|
-
watcher.on('all', async (type, file) => {
|
|
11
|
-
console.log(styleText('yellow', styleText('bold', `Change detected: ${type} ${file}`)))
|
|
12
|
-
|
|
13
|
-
try {
|
|
14
|
-
await cb(path)
|
|
15
|
-
} catch (_e) {
|
|
16
|
-
console.log(styleText('red', 'Watcher failed'))
|
|
17
|
-
}
|
|
18
|
-
})
|
|
19
|
-
}
|
|
File without changes
|
|
File without changes
|