@rokkit/cli 1.0.0-next.148 → 1.0.0-next.150

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.
@@ -1,16 +1,18 @@
1
- /**
2
- * Generate a Rokkit config object from user choices.
3
- * @param {{ palette: string, customColors?: Record<string, string>, icons: string, iconPath?: string, themes: string[], switcher: string }} opts
4
- * @returns {Record<string, unknown>}
5
- */
6
1
  export function generateConfig({ palette, customColors, icons, iconPath, themes, defaultTheme, switcher }: {
7
- palette: string;
8
- customColors?: Record<string, string>;
9
- icons: string;
10
- iconPath?: string;
11
- themes: string[];
12
- switcher: string;
13
- }): Record<string, unknown>;
2
+ palette: any;
3
+ customColors: any;
4
+ icons: any;
5
+ iconPath: any;
6
+ themes: any;
7
+ defaultTheme: any;
8
+ switcher: any;
9
+ }): {
10
+ colors: Record<string, unknown>;
11
+ themes: any;
12
+ defaultTheme: any;
13
+ switcher: any;
14
+ storageKey: string;
15
+ };
14
16
  /**
15
17
  * Generate the content for uno.config.js.
16
18
  * @returns {string}
@@ -16,31 +16,8 @@ export function addSkinToConfig(config: Record<string, unknown>, name: string):
16
16
  * @returns {string}
17
17
  */
18
18
  export function serializeConfig(config: Record<string, unknown>): string;
19
- /**
20
- * List all skins defined in rokkit.config.js.
21
- * @param {{
22
- * readConfig?: () => Record<string, unknown>,
23
- * cwd?: string
24
- * }} adapters
25
- */
26
- export function runSkinList(adapters?: {
27
- readConfig?: () => Record<string, unknown>;
28
- cwd?: string;
29
- }): Promise<void>;
30
- /**
31
- * Create a new skin entry in rokkit.config.js.
32
- * @param {string} name
33
- * @param {{
34
- * readConfig?: () => Record<string, unknown>,
35
- * writeConfig?: (config: Record<string, unknown>) => void,
36
- * cwd?: string
37
- * }} adapters
38
- */
39
- export function runSkinCreate(name: string, adapters?: {
40
- readConfig?: () => Record<string, unknown>;
41
- writeConfig?: (config: Record<string, unknown>) => void;
42
- cwd?: string;
43
- }): Promise<void>;
19
+ export function runSkinList(adapters?: {}): Promise<void>;
20
+ export function runSkinCreate(name: any, adapters?: {}): Promise<void>;
44
21
  /**
45
22
  * CLI entry point for `rokkit skin` subcommands.
46
23
  * @param {string} sub — 'list' | 'create'
@@ -5,35 +5,8 @@
5
5
  * @returns {string}
6
6
  */
7
7
  export function generateThemeStub(name: string): string;
8
- /**
9
- * List all theme styles defined in rokkit.config.js plus any custom CSS files in src/themes/.
10
- * @param {{
11
- * readConfig?: () => Record<string, unknown>,
12
- * listFiles?: (dir: string) => string[],
13
- * cwd?: string
14
- * }} adapters
15
- */
16
- export function runThemeList(adapters?: {
17
- readConfig?: () => Record<string, unknown>;
18
- listFiles?: (dir: string) => string[];
19
- cwd?: string;
20
- }): Promise<void>;
21
- /**
22
- * Create a new custom theme CSS stub at src/themes/<name>.css.
23
- * @param {string} name
24
- * @param {{
25
- * writeFile?: (path: string, content: string) => void,
26
- * exists?: (path: string) => boolean,
27
- * mkdir?: (dir: string) => void,
28
- * cwd?: string
29
- * }} adapters
30
- */
31
- export function runThemeCreate(name: string, adapters?: {
32
- writeFile?: (path: string, content: string) => void;
33
- exists?: (path: string) => boolean;
34
- mkdir?: (dir: string) => void;
35
- cwd?: string;
36
- }): Promise<void>;
8
+ export function runThemeList(adapters?: {}): Promise<void>;
9
+ export function runThemeCreate(name: any, adapters?: {}): void;
37
10
  /**
38
11
  * CLI entry point for `rokkit theme` subcommands.
39
12
  * @param {string} sub — 'list' | 'create'
@@ -23,25 +23,7 @@ export function buildInstallCommand(pm: "bun" | "pnpm" | "yarn" | "npm", package
23
23
  bin: string;
24
24
  args: string[];
25
25
  };
26
- /**
27
- * Run upgrade check and optionally apply it.
28
- *
29
- * @param {{ apply?: boolean }} opts
30
- * @param {{
31
- * readFile?: (p: string) => string,
32
- * exists?: (p: string) => boolean,
33
- * fetchVersion?: (name: string) => string | null,
34
- * runInstall?: (bin: string, args: string[]) => void
35
- * }} adapters — injectable for testing
36
- */
37
- export function runUpgrade(opts?: {
38
- apply?: boolean;
39
- }, adapters?: {
40
- readFile?: (p: string) => string;
41
- exists?: (p: string) => boolean;
42
- fetchVersion?: (name: string) => string | null;
43
- runInstall?: (bin: string, args: string[]) => void;
44
- }): void;
26
+ export function runUpgrade(opts?: {}, adapters?: {}): void;
45
27
  /**
46
28
  * CLI entry point for `rokkit upgrade`
47
29
  * @param {{ apply?: boolean }} opts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rokkit/cli",
3
- "version": "1.0.0-next.148",
3
+ "version": "1.0.0-next.150",
4
4
  "description": "Command line utilities for icon bundling and conversion.",
5
5
  "repository": {
6
6
  "type": "git",
package/src/init.js CHANGED
@@ -36,14 +36,14 @@ const DEFAULT_COLORS = {
36
36
  * @param {{ palette: string, customColors?: Record<string, string>, icons: string, iconPath?: string, themes: string[], switcher: string }} opts
37
37
  * @returns {Record<string, unknown>}
38
38
  */
39
- export function generateConfig({ palette, customColors, icons, iconPath, themes, defaultTheme, switcher }) {
40
- const colors =
41
- palette === 'custom'
42
- ? { ...DEFAULT_COLORS, ...customColors }
43
- : { ...DEFAULT_COLORS, ...(SKIN_PRESETS[palette] || {}) }
39
+ function resolveColors(palette, customColors) {
40
+ if (palette === 'custom') return { ...DEFAULT_COLORS, ...customColors }
41
+ return { ...DEFAULT_COLORS, ...(SKIN_PRESETS[palette] || {}) }
42
+ }
44
43
 
44
+ export function generateConfig({ palette, customColors, icons, iconPath, themes, defaultTheme, switcher }) {
45
45
  const config = {
46
- colors,
46
+ colors: resolveColors(palette, customColors),
47
47
  themes,
48
48
  defaultTheme: defaultTheme || themes[0],
49
49
  switcher,
package/src/skin.js CHANGED
@@ -53,13 +53,7 @@ export function serializeConfig(config) {
53
53
  * cwd?: string
54
54
  * }} adapters
55
55
  */
56
- export async function runSkinList(adapters = {}) {
57
- const config = await loadConfig(adapters)
58
- if (!config) {
59
- console.error('rokkit.config.js not found. Run `rokkit init` first.')
60
- return
61
- }
62
- const skins = config.skins ?? {}
56
+ function printSkinNames(skins) {
63
57
  const names = Object.keys(skins)
64
58
  if (names.length === 0) {
65
59
  console.info('No skins defined in rokkit.config.js.')
@@ -75,6 +69,15 @@ export async function runSkinList(adapters = {}) {
75
69
  }
76
70
  }
77
71
 
72
+ export async function runSkinList(adapters = {}) {
73
+ const config = await loadConfig(adapters)
74
+ if (!config) {
75
+ console.error('rokkit.config.js not found. Run `rokkit init` first.')
76
+ return
77
+ }
78
+ printSkinNames(config.skins ?? {})
79
+ }
80
+
78
81
  /**
79
82
  * Create a new skin entry in rokkit.config.js.
80
83
  * @param {string} name
@@ -84,25 +87,27 @@ export async function runSkinList(adapters = {}) {
84
87
  * cwd?: string
85
88
  * }} adapters
86
89
  */
87
- export async function runSkinCreate(name, adapters = {}) {
88
- if (!name) {
89
- console.error('Usage: rokkit skin create --name <name>')
90
- return
91
- }
90
+ function validateSkinCreate(name, config) {
91
+ if (!name) return 'Usage: rokkit skin create --name <name>'
92
+ if (!config) return 'rokkit.config.js not found. Run `rokkit init` first.'
93
+ if (config.skins?.[name]) return `Skin "${name}" already exists in rokkit.config.js.`
94
+ return null
95
+ }
92
96
 
97
+ export async function runSkinCreate(name, adapters = {}) {
93
98
  const config = await loadConfig(adapters)
94
- if (!config) {
95
- console.error('rokkit.config.js not found. Run `rokkit init` first.')
96
- return
97
- }
98
-
99
- if (config.skins?.[name]) {
100
- console.warn(`Skin "${name}" already exists in rokkit.config.js.`)
99
+ const error = validateSkinCreate(name, config)
100
+ if (error) {
101
+ if (error.includes('already exists')) {
102
+ console.warn(error)
103
+ } else {
104
+ console.error(error)
105
+ }
101
106
  return
102
107
  }
103
108
 
104
109
  const updated = addSkinToConfig(config, name)
105
- await saveConfig(updated, adapters)
110
+ saveConfig(updated, adapters)
106
111
 
107
112
  console.info(`Added skin "${name}" to rokkit.config.js`)
108
113
  console.info(
@@ -116,7 +121,7 @@ export async function runSkinCreate(name, adapters = {}) {
116
121
  * @param {Record<string, unknown>} config
117
122
  * @param {{ writeConfig?: (config: Record<string, unknown>) => void, cwd?: string }} adapters
118
123
  */
119
- async function saveConfig(config, adapters) {
124
+ function saveConfig(config, adapters) {
120
125
  if (adapters.writeConfig) {
121
126
  adapters.writeConfig(config)
122
127
  return
package/src/theme.js CHANGED
@@ -63,33 +63,38 @@ export function generateThemeStub(name) {
63
63
  * cwd?: string
64
64
  * }} adapters
65
65
  */
66
- export async function runThemeList(adapters = {}) {
67
- const config = await loadConfig(adapters)
68
- const builtIn = config?.themes ?? []
69
-
66
+ function getCustomThemes(adapters) {
70
67
  const cwd = adapters.cwd ?? process.cwd()
71
68
  const themesDir = resolve(cwd, 'src/themes')
72
69
  const listFiles = adapters.listFiles ?? ((dir) => (existsSync(dir) ? readdirSync(dir) : []))
73
- const custom = listFiles(themesDir)
70
+ return listFiles(themesDir)
74
71
  .filter((f) => f.endsWith('.css'))
75
72
  .map((f) => f.replace(/\.css$/, ''))
73
+ }
76
74
 
77
- console.info('Rokkit Themes\n')
75
+ function printThemeSection(label, items) {
76
+ if (items.length === 0) return
77
+ console.info(label)
78
+ for (const t of items) console.info(` ${t}`)
79
+ }
78
80
 
79
- if (builtIn.length > 0) {
80
- console.info(' Built-in (from @rokkit/themes):')
81
- for (const t of builtIn) console.info(` ${t}`)
82
- }
83
- if (custom.length > 0) {
84
- console.info('\n Custom (src/themes/):')
85
- for (const t of custom) console.info(` ${t}`)
86
- }
81
+ function printThemeList(builtIn, custom) {
82
+ console.info('Rokkit Themes\n')
83
+ printThemeSection(' Built-in (from @rokkit/themes):', builtIn)
84
+ printThemeSection('\n Custom (src/themes/):', custom)
87
85
  if (builtIn.length === 0 && custom.length === 0) {
88
86
  console.info(' No themes found.')
89
87
  console.info(' Run `rokkit theme create --name <name>` to scaffold a custom theme.')
90
88
  }
91
89
  }
92
90
 
91
+ export async function runThemeList(adapters = {}) {
92
+ const config = await loadConfig(adapters)
93
+ const builtIn = config?.themes ?? []
94
+ const custom = getCustomThemes(adapters)
95
+ printThemeList(builtIn, custom)
96
+ }
97
+
93
98
  /**
94
99
  * Create a new custom theme CSS stub at src/themes/<name>.css.
95
100
  * @param {string} name
@@ -100,17 +105,22 @@ export async function runThemeList(adapters = {}) {
100
105
  * cwd?: string
101
106
  * }} adapters
102
107
  */
103
- export async function runThemeCreate(name, adapters = {}) {
108
+ function resolveThemeAdapters(adapters) {
109
+ return {
110
+ cwd: adapters.cwd ?? process.cwd(),
111
+ writeFile: adapters.writeFile ?? writeFileSync,
112
+ exists: adapters.exists ?? existsSync,
113
+ mkdir: adapters.mkdir ?? ((dir) => mkdirSync(dir, { recursive: true }))
114
+ }
115
+ }
116
+
117
+ export function runThemeCreate(name, adapters = {}) {
104
118
  if (!name) {
105
119
  console.error('Usage: rokkit theme create --name <name>')
106
120
  return
107
121
  }
108
122
 
109
- const cwd = adapters.cwd ?? process.cwd()
110
- const writeFile = adapters.writeFile ?? writeFileSync
111
- const exists = adapters.exists ?? existsSync
112
- const mkdir = adapters.mkdir ?? ((dir) => mkdirSync(dir, { recursive: true }))
113
-
123
+ const { cwd, writeFile, exists, mkdir } = resolveThemeAdapters(adapters)
114
124
  const themesDir = resolve(cwd, 'src/themes')
115
125
  const filePath = join(themesDir, `${name}.css`)
116
126
 
@@ -136,7 +146,7 @@ export async function runThemeCreate(name, adapters = {}) {
136
146
  */
137
147
  export async function theme(sub, opts = {}) {
138
148
  if (sub === 'create') {
139
- await runThemeCreate(opts.name)
149
+ runThemeCreate(opts.name)
140
150
  } else {
141
151
  await runThemeList()
142
152
  }
package/src/upgrade.js CHANGED
@@ -51,69 +51,92 @@ export function buildInstallCommand(pm, packages) {
51
51
  * runInstall?: (bin: string, args: string[]) => void
52
52
  * }} adapters — injectable for testing
53
53
  */
54
- export function runUpgrade(opts = {}, adapters = {}) {
55
- const cwd = process.cwd()
56
- const readFile = adapters.readFile ?? ((p) => readFileSync(p, 'utf-8'))
57
- const exists = adapters.exists ?? ((p) => existsSync(p))
58
- const fetchVersion =
59
- adapters.fetchVersion ??
60
- ((name) => {
61
- try {
62
- return execFileSync('npm', ['view', name, 'version'], { encoding: 'utf-8' }).trim()
63
- } catch {
64
- return null
65
- }
66
- })
67
- const runInstall =
68
- adapters.runInstall ??
69
- ((bin, args) => execFileSync(bin, args, { stdio: 'inherit' }))
54
+ function resolveUpgradeAdapters(adapters) {
55
+ return {
56
+ readFile: adapters.readFile ?? ((p) => readFileSync(p, 'utf-8')),
57
+ exists: adapters.exists ?? ((p) => existsSync(p)),
58
+ fetchVersion:
59
+ adapters.fetchVersion ??
60
+ ((name) => {
61
+ try {
62
+ return execFileSync('npm', ['view', name, 'version'], { encoding: 'utf-8' }).trim()
63
+ } catch {
64
+ return null
65
+ }
66
+ }),
67
+ runInstall: adapters.runInstall ?? ((bin, args) => execFileSync(bin, args, { stdio: 'inherit' }))
68
+ }
69
+ }
70
+
71
+ function formatPackageStatus(pkg, latest) {
72
+ if (!latest) return `OK ${pkg.name} ${pkg.current}`
73
+ if (latest === pkg.current) return `OK ${pkg.name} ${pkg.current}`
74
+ return `OUT ${pkg.name} ${pkg.current} → ${latest}`
75
+ }
76
+
77
+ function checkPackageVersion(pkg, fetchVersion, upgrades) {
78
+ const latest = fetchVersion(pkg.name)
79
+ console.info(` ${formatPackageStatus(pkg, latest)}`)
80
+ if (latest && latest !== pkg.current) upgrades.push(`${pkg.name}@${latest}`)
81
+ }
82
+
83
+ function checkUpgrades(packages, fetchVersion) {
84
+ const upgrades = []
85
+ for (const pkg of packages) {
86
+ checkPackageVersion(pkg, fetchVersion, upgrades)
87
+ }
88
+ return upgrades
89
+ }
90
+
91
+ function applyUpgrades(upgrades, pm, apply, runInstall) {
92
+ const { bin, args } = buildInstallCommand(pm, upgrades)
93
+ const cmdStr = `${bin} ${args.join(' ')}`
94
+ if (apply) {
95
+ console.info(`\nRunning: ${cmdStr}\n`)
96
+ runInstall(bin, args)
97
+ console.info('\nUpgrade complete.')
98
+ } else {
99
+ console.info(`\n${upgrades.length} package(s) can be upgraded.`)
100
+ console.info(`Run with --apply to install, or manually:\n ${cmdStr}`)
101
+ }
102
+ }
70
103
 
104
+ function loadPackages(cwd, readFile, exists) {
71
105
  const pkgPath = resolve(cwd, 'package.json')
72
106
  if (!exists(pkgPath)) {
73
107
  console.error('No package.json found in current directory.')
74
- return
108
+ return null
75
109
  }
76
-
77
- const pkgJson = JSON.parse(readFile(pkgPath))
78
- const packages = getRokkitPackages(pkgJson)
79
-
110
+ const packages = getRokkitPackages(JSON.parse(readFile(pkgPath)))
80
111
  if (packages.length === 0) {
81
112
  console.info('No @rokkit/* packages found in package.json.')
82
- return
113
+ return null
83
114
  }
115
+ return packages
116
+ }
84
117
 
118
+ function detectPm(cwd, exists) {
85
119
  const LOCKFILES = ['bun.lock', 'bun.lockb', 'pnpm-lock.yaml', 'yarn.lock', 'package-lock.json']
86
- const presentLockfiles = LOCKFILES.filter((f) => exists(resolve(cwd, f)))
87
- const pm = detectPackageManager(presentLockfiles)
120
+ return detectPackageManager(LOCKFILES.filter((f) => exists(resolve(cwd, f))))
121
+ }
88
122
 
89
- console.info('Rokkit Upgrade\n')
123
+ export function runUpgrade(opts = {}, adapters = {}) {
124
+ const cwd = process.cwd()
125
+ const { readFile, exists, fetchVersion, runInstall } = resolveUpgradeAdapters(adapters)
90
126
 
91
- const upgrades = []
92
- for (const pkg of packages) {
93
- const latest = fetchVersion(pkg.name)
94
- const upToDate = latest && latest === pkg.current
95
- const status = !latest ? '?' : upToDate ? 'up-to-date' : 'outdated'
96
- const arrow = latest ? `${pkg.current} → ${latest}` : pkg.current
97
- console.info(` ${status === 'outdated' ? 'OUT' : 'OK '} ${pkg.name} ${arrow}`)
98
- if (!upToDate && latest) upgrades.push(`${pkg.name}@${latest}`)
99
- }
127
+ const packages = loadPackages(cwd, readFile, exists)
128
+ if (!packages) return
100
129
 
130
+ const pm = detectPm(cwd, exists)
131
+ console.info('Rokkit Upgrade\n')
132
+
133
+ const upgrades = checkUpgrades(packages, fetchVersion)
101
134
  if (upgrades.length === 0) {
102
135
  console.info('\nAll packages are up to date.')
103
136
  return
104
137
  }
105
138
 
106
- const { bin, args } = buildInstallCommand(pm, upgrades)
107
- const cmdStr = `${bin} ${args.join(' ')}`
108
-
109
- if (opts.apply) {
110
- console.info(`\nRunning: ${cmdStr}\n`)
111
- runInstall(bin, args)
112
- console.info('\nUpgrade complete.')
113
- } else {
114
- console.info(`\n${upgrades.length} package(s) can be upgraded.`)
115
- console.info(`Run with --apply to install, or manually:\n ${cmdStr}`)
116
- }
139
+ applyUpgrades(upgrades, pm, opts.apply, runInstall)
117
140
  }
118
141
 
119
142
  /**