@kubb/cli 2.18.2 → 2.18.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/cli",
3
- "version": "2.18.2",
3
+ "version": "2.18.4",
4
4
  "description": "Generator cli",
5
5
  "keywords": [
6
6
  "typescript",
@@ -41,26 +41,29 @@
41
41
  ],
42
42
  "dependencies": {
43
43
  "bundle-require": "^4.1.0",
44
- "cac": "^6.7.14",
45
44
  "chokidar": "^3.6.0",
45
+ "citty": "^0.1.6",
46
+ "consola": "^3.2.3",
46
47
  "cosmiconfig": "^9.0.0",
47
48
  "esbuild": "^0.20.2",
48
49
  "execa": "^8.0.1",
49
50
  "js-runtime": "^0.0.8",
51
+ "latest-version": "^9.0.0",
50
52
  "ora": "^8.0.1",
51
- "pretty-error": "^4.0.0",
53
+ "semver": "^7.6.2",
52
54
  "string-argv": "^0.3.2",
53
55
  "tinyrainbow": "^1.1.1",
54
- "@kubb/core": "2.18.2"
56
+ "@kubb/core": "2.18.4"
55
57
  },
56
58
  "devDependencies": {
57
59
  "@types/node": "^20.12.11",
60
+ "@types/semver": "^7.5.8",
58
61
  "source-map-support": "^0.5.21",
59
62
  "tsup": "^8.0.2",
60
63
  "typescript": "^5.4.5",
61
- "@kubb/config-ts": "2.18.2",
62
- "@kubb/config-tsup": "2.18.2",
63
- "@kubb/swagger": "2.18.2"
64
+ "@kubb/config-ts": "2.18.4",
65
+ "@kubb/config-tsup": "2.18.4",
66
+ "@kubb/plugin-oas": "2.18.4"
64
67
  },
65
68
  "engines": {
66
69
  "node": ">=18",
@@ -0,0 +1,116 @@
1
+ import { LogLevel } from '@kubb/core/logger'
2
+ import { defineCommand, showUsage } from 'citty'
3
+ import type { ArgsDef, ParsedArgs } from 'citty'
4
+ import consola from 'consola'
5
+ import { execa } from 'execa'
6
+ import c from 'tinyrainbow'
7
+
8
+ import path from 'node:path'
9
+ import { getConfig } from '../utils/getConfig.ts'
10
+ import { getCosmiConfig } from '../utils/getCosmiConfig.ts'
11
+ import { spinner } from '../utils/spinner.ts'
12
+ import { startWatcher } from '../utils/watcher.ts'
13
+
14
+ import { PromiseManager, isInputPath } from '@kubb/core'
15
+ import { generate } from '../generate.ts'
16
+
17
+ const args = {
18
+ config: {
19
+ type: 'string',
20
+ description: 'Path to the Kubb config',
21
+ alias: 'c',
22
+ },
23
+ logLevel: {
24
+ type: 'string',
25
+ description: 'Info, silent or debug',
26
+ alias: 'l',
27
+ default: LogLevel.info,
28
+ valueHint: `${LogLevel.silent}|${LogLevel.info}|${LogLevel.debug}`,
29
+ },
30
+ watch: {
31
+ type: 'boolean',
32
+ description: 'Watch mode based on the input file',
33
+ alias: 'w',
34
+ default: false,
35
+ },
36
+ bun: {
37
+ type: 'boolean',
38
+ description: 'Run Kubb with Bun',
39
+ alias: 'b',
40
+ default: false,
41
+ },
42
+ debug: {
43
+ type: 'boolean',
44
+ description: 'Override logLevel to debug',
45
+ alias: 'd',
46
+ default: false,
47
+ },
48
+ help: {
49
+ type: 'boolean',
50
+ description: 'Show help',
51
+ alias: 'h',
52
+ default: false,
53
+ },
54
+ } as const satisfies ArgsDef
55
+
56
+ export type Args = ParsedArgs<typeof args>
57
+
58
+ const command = defineCommand({
59
+ meta: {
60
+ name: 'generate',
61
+ description: "[input] Generate files based on a 'kubb.config.ts' file",
62
+ },
63
+ args,
64
+ setup() {
65
+ spinner.start('🔍 Loading config')
66
+ },
67
+ async run({ args }) {
68
+ const input = args._[0]
69
+
70
+ if (args.help) {
71
+ showUsage(command)
72
+ return
73
+ }
74
+
75
+ if (args.debug) {
76
+ args.logLevel = LogLevel.debug
77
+ }
78
+
79
+ if (args.bun) {
80
+ const command = process.argv.splice(2).filter((item) => item !== '--bun')
81
+
82
+ await execa('bkubb', command, { stdout: process.stdout, stderr: process.stderr })
83
+ return
84
+ }
85
+
86
+ const result = await getCosmiConfig('kubb', args.config)
87
+ spinner.succeed(`🔍 Config loaded(${c.dim(path.relative(process.cwd(), result.filepath))})`)
88
+
89
+ const config = await getConfig(result, args)
90
+
91
+ if (args.watch) {
92
+ if (Array.isArray(config)) {
93
+ throw new Error('Cannot use watcher with multiple Configs(array)')
94
+ }
95
+
96
+ if (isInputPath(config)) {
97
+ return startWatcher([input || config.input.path], async (paths) => {
98
+ await generate({ config, args })
99
+ spinner.spinner = 'simpleDotsScrolling'
100
+ spinner.start(c.yellow(c.bold(`Watching for changes in ${paths.join(' and ')}`)))
101
+ })
102
+ }
103
+ }
104
+
105
+ if (Array.isArray(config)) {
106
+ const promiseManager = new PromiseManager()
107
+ const promises = config.map((item) => () => generate({ input, config: item, args }))
108
+
109
+ return promiseManager.run('seq', promises)
110
+ }
111
+
112
+ await generate({ input, config, args })
113
+ },
114
+ })
115
+
116
+ export default command
package/src/generate.ts CHANGED
@@ -1,91 +1,42 @@
1
- import { LogLevel, createLogger, randomCliColour } from '@kubb/core/logger'
1
+ import { LogLevel, LogMapper, createLogger, randomCliColour } from '@kubb/core/logger'
2
2
 
3
- import { execa } from 'execa'
4
- import { get } from 'js-runtime'
5
- import { parseArgsStringToArgv } from 'string-argv'
6
3
  import c from 'tinyrainbow'
7
4
 
8
- import { OraWritable } from './utils/OraWritable.ts'
9
5
  import { spinner } from './utils/spinner.ts'
10
6
 
11
- import type { Writable } from 'node:stream'
12
- import { type CLIOptions, type Config, safeBuild } from '@kubb/core'
7
+ import { type Config, Warning, safeBuild } from '@kubb/core'
8
+ import { createConsola } from 'consola'
9
+ import type { Args } from './commands/generate.ts'
10
+ import { executeHooks } from './utils/executeHooks.ts'
11
+ import { getErrorCauses } from './utils/getErrorCauses.ts'
13
12
  import { getSummary } from './utils/getSummary.ts'
14
13
 
15
14
  type GenerateProps = {
16
15
  input?: string
17
16
  config: Config
18
- CLIOptions: CLIOptions
17
+ args: Args
19
18
  }
20
19
 
21
- type ExecutingHooksProps = {
22
- hooks: Config['hooks']
23
- logLevel: LogLevel
24
- }
25
-
26
- async function executeHooks({ hooks, logLevel }: ExecutingHooksProps): Promise<void> {
27
- if (!hooks?.done) {
28
- return
29
- }
30
-
31
- const commands = Array.isArray(hooks.done) ? hooks.done : [hooks.done]
32
-
33
- if (logLevel === LogLevel.silent) {
34
- spinner.start('Executing hooks')
35
- }
36
-
37
- const executers = commands
38
- .map(async (command) => {
39
- const oraWritable = new OraWritable(spinner, command)
40
- const abortController = new AbortController()
41
- const [cmd, ..._args] = [...parseArgsStringToArgv(command)]
42
-
43
- if (!cmd) {
44
- return null
45
- }
46
-
47
- spinner.start(`Executing hook ${logLevel !== 'silent' ? c.dim(command) : ''}`)
48
-
49
- const subProcess = await execa(cmd, _args, {
50
- detached: true,
51
- signal: abortController.signal,
52
- }).pipeStdout?.(oraWritable as Writable)
53
- spinner.suffixText = ''
54
-
55
- if (logLevel === LogLevel.silent) {
56
- spinner.succeed(`Executing hook ${logLevel !== 'silent' ? c.dim(command) : ''}`)
57
-
58
- if (subProcess) {
59
- console.log(subProcess.stdout)
60
- }
61
- }
62
-
63
- oraWritable.destroy()
64
- return { subProcess, abort: abortController.abort.bind(abortController) }
65
- })
66
- .filter(Boolean)
67
-
68
- await Promise.all(executers)
69
-
70
- if (logLevel === LogLevel.silent) {
71
- spinner.succeed('Executing hooks')
72
- }
73
- }
74
-
75
- export async function generate({ input, config, CLIOptions }: GenerateProps): Promise<void> {
20
+ export async function generate({ input, config, args }: GenerateProps): Promise<void> {
21
+ const logLevel = (args.logLevel as LogLevel) || LogLevel.silent
76
22
  const logger = createLogger({
77
- logLevel: CLIOptions.logLevel || LogLevel.silent,
23
+ logLevel,
78
24
  name: config.name,
79
25
  spinner,
26
+ consola: createConsola({
27
+ level: LogMapper[logLevel] || 3,
28
+ }),
80
29
  })
81
30
 
31
+ logger.consola?.wrapConsole()
32
+
82
33
  if (logger.name) {
83
34
  spinner.prefixText = randomCliColour(logger.name)
84
35
  }
85
36
 
86
37
  const hrstart = process.hrtime()
87
38
 
88
- if (CLIOptions.logLevel === LogLevel.debug) {
39
+ if (args.logLevel === LogLevel.debug) {
89
40
  const { performance, PerformanceObserver } = await import('node:perf_hooks')
90
41
 
91
42
  const performanceOpserver = new PerformanceObserver((items) => {
@@ -100,10 +51,9 @@ export async function generate({ input, config, CLIOptions }: GenerateProps): Pr
100
51
  }
101
52
 
102
53
  const { root: _root, ...userConfig } = config
103
- const logLevel = logger.logLevel
104
54
  const inputPath = input ?? ('path' in userConfig.input ? userConfig.input.path : undefined)
105
55
 
106
- spinner.start(`🚀 Building with ${get()} ${logLevel !== 'silent' ? c.dim(inputPath) : ''}`)
56
+ spinner.start(`🚀 Building ${logLevel !== 'silent' ? c.dim(inputPath) : ''}`)
107
57
 
108
58
  const definedConfig: Config = {
109
59
  root: process.cwd(),
@@ -138,13 +88,27 @@ export async function generate({ input, config, CLIOptions }: GenerateProps): Pr
138
88
 
139
89
  console.log(summary.join(''))
140
90
 
141
- throw error
91
+ if (error instanceof Warning) {
92
+ spinner.warn(c.yellow(error.message))
93
+ process.exit(0)
94
+ }
95
+
96
+ const errors = getErrorCauses([error])
97
+ if (logger.consola && errors.length && logLevel === LogLevel.debug) {
98
+ errors.forEach((err) => {
99
+ logger.consola!.error(err)
100
+ })
101
+ }
102
+
103
+ logger.consola?.error(error)
104
+
105
+ process.exit(0)
142
106
  }
143
107
 
144
108
  await executeHooks({ hooks: config.hooks, logLevel })
145
109
 
146
110
  spinner.suffixText = ''
147
- spinner.succeed(`🚀 Build completed with ${get()} ${logLevel !== 'silent' ? c.dim(inputPath) : ''}`)
111
+ spinner.succeed(`🚀 Build completed ${logLevel !== 'silent' ? c.dim(inputPath) : ''}`)
148
112
 
149
113
  console.log(summary.join(''))
150
114
  }
package/src/index.ts CHANGED
@@ -1,110 +1,52 @@
1
- import path from 'node:path'
2
-
3
- import { PromiseManager, Warning, isInputPath } from '@kubb/core'
4
-
5
- import { cac } from 'cac'
6
- import c from 'tinyrainbow'
1
+ import { defineCommand, runCommand, runMain } from 'citty'
2
+ import getLatestVersion from 'latest-version'
3
+ import { lt } from 'semver'
7
4
 
5
+ import consola from 'consola'
8
6
  import { version } from '../package.json'
9
- import { generate } from './generate.ts'
10
- import { init } from './init.ts'
11
- import { getConfig } from './utils/getConfig.ts'
12
- import { getCosmiConfig } from './utils/getCosmiConfig.ts'
13
- import { renderErrors } from './utils/renderErrors.ts'
14
- import { spinner } from './utils/spinner.ts'
15
- import { startWatcher } from './utils/watcher.ts'
16
-
17
- import type { CLIOptions } from '@kubb/core'
18
- import { execa } from 'execa'
19
-
20
- const moduleName = 'kubb'
21
-
22
- function programCatcher(e: unknown, CLIOptions: CLIOptions): void {
23
- const error = e as Error
24
- const message = renderErrors(error, { logLevel: CLIOptions.logLevel })
25
-
26
- if (error instanceof Warning) {
27
- spinner.warn(c.yellow(error.message))
28
- process.exit(0)
29
- }
30
- spinner.fail(message)
31
- process.exit(1)
32
- }
33
-
34
- async function generateAction(input: string, CLIOptions: CLIOptions) {
35
- if (CLIOptions.bun) {
36
- const command = process.argv.splice(2).filter((item) => item !== '--bun')
37
-
38
- await execa('bkubb', command, { stdout: process.stdout, stderr: process.stderr })
39
- return
40
- }
41
-
42
- spinner.start('🔍 Loading config')
43
- const result = await getCosmiConfig(moduleName, CLIOptions.config)
44
- spinner.succeed(`🔍 Config loaded(${c.dim(path.relative(process.cwd(), result.filepath))})`)
45
-
46
- const config = await getConfig(result, CLIOptions)
47
-
48
- if (CLIOptions.watch) {
49
- if (Array.isArray(config)) {
50
- throw new Error('Cannot use watcher with multiple Configs(array)')
51
- }
52
7
 
53
- if (isInputPath(config)) {
54
- return startWatcher([input || config.input.path], async (paths) => {
55
- await generate({ config, CLIOptions })
56
- spinner.spinner = 'simpleDotsScrolling'
57
- spinner.start(c.yellow(c.bold(`Watching for changes in ${paths.join(' and ')}`)))
58
- })
8
+ const name = 'kubb'
9
+
10
+ const main = defineCommand({
11
+ meta: {
12
+ name,
13
+ version,
14
+ description: 'Kubb generation',
15
+ },
16
+ async setup({ rawArgs }) {
17
+ try{
18
+ const latestVersion = await getLatestVersion('@kubb/cli')
19
+
20
+ if (lt(version, latestVersion)) {
21
+ consola.box({
22
+ title: 'Update available for `Kubb` ',
23
+ message: `\`v${version}\` → \`v${latestVersion}\`
24
+ Run \`npm install -g @kubb/cli\` to update`,
25
+ style: {
26
+ padding: 2,
27
+ borderColor: 'yellow',
28
+ borderStyle: 'rounded',
29
+ },
30
+ })
31
+ }
32
+ }catch(_e){
33
+
34
+ }
35
+
36
+ if (rawArgs[0] !== 'generate') {
37
+ // generate is not being used
38
+ const generateCommand = await import('./commands/generate.ts').then((r) => r.default)
39
+
40
+ await runCommand(generateCommand, { rawArgs })
41
+
42
+ process.exit(0)
59
43
  }
60
- }
61
-
62
- if (Array.isArray(config)) {
63
- const promiseManager = new PromiseManager()
64
- const promises = config.map((item) => () => generate({ input, config: item, CLIOptions }))
65
-
66
- await promiseManager.run('seq', promises)
67
-
68
- return
69
- }
70
-
71
- await generate({ input, config, CLIOptions })
44
+ },
45
+ subCommands: {
46
+ generate: () => import('./commands/generate.ts').then((r) => r.default),
47
+ },
48
+ })
49
+
50
+ export async function run(_argv?: string[]): Promise<void> {
51
+ await runMain(main)
72
52
  }
73
-
74
- export async function run(argv?: string[]): Promise<void> {
75
- const program = cac(moduleName)
76
-
77
- program
78
- .command('[input]', 'Path of the input file(overrides the one in `kubb.config.js`)')
79
- .option('-c, --config <path>', 'Path to the Kubb config')
80
- .option('-l, --log-level <type>', 'Info, silent or debug')
81
- .option('-w, --watch', 'Watch mode based on the input file')
82
- .option('-b, --bun', 'Run Kubb with Bun')
83
- .action(generateAction)
84
-
85
- program
86
- .command('generate [input]', 'Path of the input file(overrides the one in `kubb.config.js`)')
87
- .option('-c, --config <path>', 'Path to the Kubb config')
88
- .option('-l, --log-level <type>', 'Info, silent or debug')
89
- .option('-w, --watch', 'Watch mode based on the input file')
90
- .option('-b, --bun', 'Run Kubb with Bun')
91
- .action(generateAction)
92
-
93
- program.command('init', 'Init Kubb').action(async () => {
94
- return init({ logLevel: 'info' })
95
- })
96
-
97
- program.help()
98
- program.version(version)
99
- program.parse(argv, { run: false })
100
-
101
- try {
102
- await program.runMatchedCommand()
103
-
104
- process.exit(0)
105
- } catch (e) {
106
- programCatcher(e, program.options)
107
- }
108
- }
109
-
110
- export default run
@@ -0,0 +1,64 @@
1
+ import { LogLevel } from '@kubb/core/logger'
2
+ import { execa } from 'execa'
3
+ import { parseArgsStringToArgv } from 'string-argv'
4
+ import c from 'tinyrainbow'
5
+
6
+ import { OraWritable } from './OraWritable.ts'
7
+ import { spinner } from './spinner.ts'
8
+
9
+ import type { Writable } from 'node:stream'
10
+ import type { Config } from '@kubb/core'
11
+
12
+ type ExecutingHooksProps = {
13
+ hooks: Config['hooks']
14
+ logLevel: LogLevel
15
+ }
16
+
17
+ export async function executeHooks({ hooks, logLevel }: ExecutingHooksProps): Promise<void> {
18
+ if (!hooks?.done) {
19
+ return
20
+ }
21
+
22
+ const commands = Array.isArray(hooks.done) ? hooks.done : [hooks.done]
23
+
24
+ if (logLevel === LogLevel.silent) {
25
+ spinner.start('Executing hooks')
26
+ }
27
+
28
+ const executers = commands
29
+ .map(async (command) => {
30
+ const oraWritable = new OraWritable(spinner, command)
31
+ const abortController = new AbortController()
32
+ const [cmd, ..._args] = [...parseArgsStringToArgv(command)]
33
+
34
+ if (!cmd) {
35
+ return null
36
+ }
37
+
38
+ spinner.start(`Executing hook ${logLevel !== 'silent' ? c.dim(command) : ''}`)
39
+
40
+ const subProcess = await execa(cmd, _args, {
41
+ detached: true,
42
+ signal: abortController.signal,
43
+ }).pipeStdout?.(oraWritable as Writable)
44
+ spinner.suffixText = ''
45
+
46
+ if (logLevel === LogLevel.silent) {
47
+ spinner.succeed(`Executing hook ${logLevel !== 'silent' ? c.dim(command) : ''}`)
48
+
49
+ if (subProcess) {
50
+ console.log(subProcess.stdout)
51
+ }
52
+ }
53
+
54
+ oraWritable.destroy()
55
+ return { subProcess, abort: abortController.abort.bind(abortController) }
56
+ })
57
+ .filter(Boolean)
58
+
59
+ await Promise.all(executers)
60
+
61
+ if (logLevel === LogLevel.silent) {
62
+ spinner.succeed('Executing hooks')
63
+ }
64
+ }
@@ -2,19 +2,20 @@ import { isPromise } from '@kubb/core/utils'
2
2
 
3
3
  import { getPlugins } from './getPlugins.ts'
4
4
 
5
- import type { CLIOptions, Config, UserConfig, defineConfig } from '@kubb/core'
5
+ import type { Config, UserConfig } from '@kubb/core'
6
+ import type { Args } from '../commands/generate.ts'
6
7
  import type { CosmiconfigResult } from './getCosmiConfig.ts'
7
8
 
8
9
  /**
9
10
  * Converting UserConfig to Config without a change in the object beside the JSON convert.
10
11
  */
11
- export async function getConfig(result: CosmiconfigResult, CLIOptions: CLIOptions): Promise<Array<Config> | Config> {
12
+ export async function getConfig(result: CosmiconfigResult, args: Args): Promise<Array<Config> | Config> {
12
13
  const config = result?.config
13
14
  let kubbUserConfig = Promise.resolve(config) as Promise<UserConfig | Array<UserConfig>>
14
15
 
15
16
  // for ts or js files
16
17
  if (typeof config === 'function') {
17
- const possiblePromise = config(CLIOptions)
18
+ const possiblePromise = config(args)
18
19
  if (isPromise(possiblePromise)) {
19
20
  kubbUserConfig = possiblePromise
20
21
  }
@@ -0,0 +1,14 @@
1
+ export function getErrorCauses(errors: Error[]): Error[] {
2
+ return errors
3
+ .reduce((prev, error) => {
4
+ const causedError = error?.cause as Error
5
+ if (causedError) {
6
+ prev = [...prev, ...getErrorCauses([causedError])]
7
+ return prev
8
+ }
9
+ prev = [...prev, error]
10
+
11
+ return prev
12
+ }, [] as Error[])
13
+ .filter(Boolean)
14
+ }
@@ -72,7 +72,6 @@ export function getSummary({ pluginManager, status, hrstart, config, logger }: S
72
72
  [` ${c.bold('Time:')} ${meta.time}`, true],
73
73
  [` ${c.bold('Ended:')} ${meta.endTime}`, true],
74
74
  [` ${c.bold('Output:')} ${meta.output}`, true],
75
- ['\n', true],
76
75
  ]
77
76
  .map((item) => {
78
77
  if (item.at(1)) {
package/src/init.ts DELETED
@@ -1,97 +0,0 @@
1
- import path from 'node:path'
2
-
3
- import { write } from '@kubb/core/fs'
4
- import { LogLevel } from '@kubb/core/logger'
5
- import { isPromiseFulfilledResult } from '@kubb/core/utils'
6
-
7
- import { $ } from 'execa'
8
- import c from 'tinyrainbow'
9
-
10
- import { spinner } from './utils/spinner.ts'
11
-
12
- type Preset = 'simple'
13
-
14
- type PackageManager = 'pnpm' | 'npm' | 'yarn'
15
-
16
- type PresetMeta = {
17
- 'kubb.config': string
18
- packages: string[]
19
- }
20
-
21
- type InitProps = {
22
- /**
23
- * @default `'silent'`
24
- */
25
- logLevel?: LogLevel
26
- /**
27
- * @default `'simple'`
28
- */
29
- preset?: Preset
30
- /**
31
- * @default `'pnpm'`
32
- */
33
- packageManager?: PackageManager
34
- }
35
-
36
- const presets: Record<Preset, PresetMeta> = {
37
- simple: {
38
- 'kubb.config': `
39
- import { defineConfig } from '@kubb/core'
40
- import { pluginSwagger } from '@kubb/swagger'
41
- import { pluginTs } from '@kubb/swagger-ts'
42
- import { pluginTanstackQuery } from '@kubb/swagger-tanstack-query'
43
-
44
- export default defineConfig({
45
- root: '.',
46
- input: {
47
- path: 'https://petstore3.swagger.io/api/v3/openapi.json',
48
- },
49
- output: {
50
- path: './src/gen',
51
- clean: true,
52
- },
53
- hooks: {
54
- done: ['echo "🎉 done"'],
55
- },
56
- plugins: [pluginSwagger({}), pluginTs({ output: { path: 'models'}, enumType: 'enum' }), pluginTanstackQuery({ output: { path: './hooks' } })],
57
- })
58
- `,
59
- packages: ['@kubb/core', '@kubb/cli', '@kubb/swagger', '@kubb/swagger-ts', '@kubb/swagger-tanstack-query'],
60
- },
61
- }
62
-
63
- export async function init({ preset = 'simple', logLevel = LogLevel.silent, packageManager = 'pnpm' }: InitProps): Promise<undefined> {
64
- spinner.start('📦 Initializing Kubb')
65
-
66
- const presetMeta = presets[preset]
67
- const configPath = path.resolve(process.cwd(), './kubb.config.js')
68
- const installCommand = packageManager === 'npm' ? 'install' : 'add'
69
-
70
- spinner.start(`📀 Writing \`kubb.config.js\` ${c.dim(configPath)}`)
71
- await write(presetMeta['kubb.config'], configPath)
72
- spinner.succeed(`📀 Wrote \`kubb.config.js\` ${c.dim(configPath)}`)
73
-
74
- const results = await Promise.allSettled([
75
- $`npm init es6 -y`,
76
- ...presetMeta.packages.map(async (pack) => {
77
- spinner.start(`📀 Installing ${c.dim(pack)}`)
78
- const { stdout } = await $({
79
- preferLocal: false,
80
- })`${packageManager} ${installCommand} ${pack}`
81
- spinner.succeed(`📀 Installed ${c.dim(pack)}`)
82
-
83
- return stdout
84
- }),
85
- ])
86
-
87
- if (logLevel === LogLevel.info) {
88
- results.forEach((result) => {
89
- if (isPromiseFulfilledResult(result)) {
90
- console.log(result.value)
91
- }
92
- })
93
- }
94
- spinner.succeed('📦 initialized Kubb')
95
-
96
- return
97
- }