novaui-cli 1.1.2 → 1.1.3
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/README.md +111 -0
- package/package.json +33 -13
- package/src/__tests__/commands.test.js +491 -0
- package/src/__tests__/fuzzy.test.js +150 -0
- package/src/__tests__/helpers.test.js +520 -0
- package/src/__tests__/preflight.test.js +379 -0
- package/src/__tests__/version-check.test.js +58 -0
- package/src/bin.js +51 -46
- package/src/commands/add.js +33 -36
- package/src/commands/init.js +232 -137
- package/src/constants.js +86 -5
- package/src/themes/index.js +45 -14
- package/src/utils/config.js +11 -11
- package/src/utils/deps.js +24 -20
- package/src/utils/fetch.js +9 -9
- package/src/utils/fs-helpers.js +8 -8
- package/src/utils/fuzzy.js +99 -0
- package/src/utils/preflight.js +172 -0
- package/src/utils/version-check.js +136 -0
- package/src/components.json +0 -6
- package/src/global.css +0 -50
- package/src/tailwind.config.js +0 -54
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import pc from 'picocolors'
|
|
2
|
+
import { getCliVersion } from './version.js'
|
|
3
|
+
import { fetchWithTimeout } from './fetch.js'
|
|
4
|
+
|
|
5
|
+
const NPM_REGISTRY_URL = 'https://registry.npmjs.org/novaui-cli/latest'
|
|
6
|
+
const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000 // 24 hours
|
|
7
|
+
const CACHE_FILE = '.novaui-version-check'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Compare two semantic versions
|
|
11
|
+
* Returns: 1 if v1 > v2, -1 if v1 < v2, 0 if equal
|
|
12
|
+
*/
|
|
13
|
+
function compareVersions(v1, v2) {
|
|
14
|
+
const parts1 = v1.split('.').map(Number)
|
|
15
|
+
const parts2 = v2.split('.').map(Number)
|
|
16
|
+
|
|
17
|
+
for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
|
|
18
|
+
const part1 = parts1[i] || 0
|
|
19
|
+
const part2 = parts2[i] || 0
|
|
20
|
+
|
|
21
|
+
if (part1 > part2) return 1
|
|
22
|
+
if (part1 < part2) return -1
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return 0
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Fetch the latest version from npm registry
|
|
30
|
+
*/
|
|
31
|
+
async function getLatestVersion() {
|
|
32
|
+
try {
|
|
33
|
+
const response = await fetchWithTimeout(NPM_REGISTRY_URL)
|
|
34
|
+
if (!response.ok) return null
|
|
35
|
+
|
|
36
|
+
const data = await response.json()
|
|
37
|
+
return data.version || null
|
|
38
|
+
} catch {
|
|
39
|
+
return null
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Check if we should run the version check based on cache
|
|
45
|
+
*/
|
|
46
|
+
function shouldCheckVersion(cwd) {
|
|
47
|
+
const fs = require('node:fs')
|
|
48
|
+
const path = require('node:path')
|
|
49
|
+
const os = require('node:os')
|
|
50
|
+
|
|
51
|
+
const cacheDir = path.join(os.homedir(), '.novaui')
|
|
52
|
+
const cachePath = path.join(cacheDir, CACHE_FILE)
|
|
53
|
+
|
|
54
|
+
if (!fs.existsSync(cachePath)) {
|
|
55
|
+
return true
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const cache = JSON.parse(fs.readFileSync(cachePath, 'utf-8'))
|
|
60
|
+
const lastCheck = new Date(cache.lastCheck).getTime()
|
|
61
|
+
const now = Date.now()
|
|
62
|
+
|
|
63
|
+
return (now - lastCheck) > CHECK_INTERVAL_MS
|
|
64
|
+
} catch {
|
|
65
|
+
return true
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Update the version check cache
|
|
71
|
+
*/
|
|
72
|
+
function updateCache(latestVersion) {
|
|
73
|
+
const fs = require('node:fs')
|
|
74
|
+
const path = require('node:path')
|
|
75
|
+
const os = require('node:os')
|
|
76
|
+
|
|
77
|
+
const cacheDir = path.join(os.homedir(), '.novaui')
|
|
78
|
+
if (!fs.existsSync(cacheDir)) {
|
|
79
|
+
fs.mkdirSync(cacheDir, { recursive: true })
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const cachePath = path.join(cacheDir, CACHE_FILE)
|
|
83
|
+
const cache = {
|
|
84
|
+
lastCheck: new Date().toISOString(),
|
|
85
|
+
latestVersion,
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
fs.writeFileSync(cachePath, JSON.stringify(cache, null, 2), 'utf-8')
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Check for CLI updates and warn user if outdated
|
|
93
|
+
* Runs once per day to avoid slowing down commands
|
|
94
|
+
*/
|
|
95
|
+
export async function checkForUpdates() {
|
|
96
|
+
const currentVersion = getCliVersion()
|
|
97
|
+
|
|
98
|
+
if (currentVersion === 'unknown') {
|
|
99
|
+
return
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Only check once per day
|
|
103
|
+
const cwd = process.cwd()
|
|
104
|
+
if (!shouldCheckVersion(cwd)) {
|
|
105
|
+
return
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const latestVersion = await getLatestVersion()
|
|
109
|
+
|
|
110
|
+
if (!latestVersion) {
|
|
111
|
+
return
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
updateCache(latestVersion)
|
|
115
|
+
|
|
116
|
+
if (compareVersions(latestVersion, currentVersion) > 0) {
|
|
117
|
+
console.log('')
|
|
118
|
+
console.log(pc.yellow(` ⚠ A new version of novaui-cli is available!`))
|
|
119
|
+
console.log(pc.dim(` Current: ${currentVersion}`))
|
|
120
|
+
console.log(pc.dim(` Latest: ${latestVersion}`))
|
|
121
|
+
console.log('')
|
|
122
|
+
console.log(pc.cyan(` Update with: npm install -g novaui-cli@latest`))
|
|
123
|
+
console.log('')
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Get version info for error reporting
|
|
129
|
+
*/
|
|
130
|
+
export function getVersionInfo() {
|
|
131
|
+
const currentVersion = getCliVersion()
|
|
132
|
+
return {
|
|
133
|
+
cli: currentVersion,
|
|
134
|
+
node: process.version,
|
|
135
|
+
}
|
|
136
|
+
}
|
package/src/components.json
DELETED
package/src/global.css
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
@tailwind base;
|
|
2
|
-
@tailwind components;
|
|
3
|
-
@tailwind utilities;
|
|
4
|
-
|
|
5
|
-
@layer base {
|
|
6
|
-
:root {
|
|
7
|
-
--background: 210 40% 98%;
|
|
8
|
-
--foreground: 210 30% 16%;
|
|
9
|
-
--card: 0 0% 100%;
|
|
10
|
-
--card-foreground: 210 30% 16%;
|
|
11
|
-
--popover: 0 0% 100%;
|
|
12
|
-
--popover-foreground: 210 30% 16%;
|
|
13
|
-
--primary: 200 95% 46%;
|
|
14
|
-
--primary-foreground: 0 0% 100%;
|
|
15
|
-
--secondary: 197 46% 92%;
|
|
16
|
-
--secondary-foreground: 210 25% 24%;
|
|
17
|
-
--muted: 197 46% 92%;
|
|
18
|
-
--muted-foreground: 210 16% 42%;
|
|
19
|
-
--accent: 189 70% 88%;
|
|
20
|
-
--accent-foreground: 210 28% 20%;
|
|
21
|
-
--destructive: 0 75% 55%;
|
|
22
|
-
--destructive-foreground: 0 0% 100%;
|
|
23
|
-
--border: 197 30% 84%;
|
|
24
|
-
--input: 197 30% 84%;
|
|
25
|
-
--ring: 200 95% 46%;
|
|
26
|
-
--radius: 0.75rem;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
.dark {
|
|
30
|
-
--background: 212 48% 10%;
|
|
31
|
-
--foreground: 210 20% 94%;
|
|
32
|
-
--card: 212 45% 13%;
|
|
33
|
-
--card-foreground: 210 20% 94%;
|
|
34
|
-
--popover: 212 45% 13%;
|
|
35
|
-
--popover-foreground: 210 20% 94%;
|
|
36
|
-
--primary: 196 100% 60%;
|
|
37
|
-
--primary-foreground: 210 50% 12%;
|
|
38
|
-
--secondary: 212 30% 20%;
|
|
39
|
-
--secondary-foreground: 210 20% 94%;
|
|
40
|
-
--muted: 212 30% 20%;
|
|
41
|
-
--muted-foreground: 209 15% 68%;
|
|
42
|
-
--accent: 202 45% 24%;
|
|
43
|
-
--accent-foreground: 210 20% 94%;
|
|
44
|
-
--destructive: 0 65% 45%;
|
|
45
|
-
--destructive-foreground: 0 0% 100%;
|
|
46
|
-
--border: 212 28% 24%;
|
|
47
|
-
--input: 212 28% 24%;
|
|
48
|
-
--ring: 196 100% 60%;
|
|
49
|
-
}
|
|
50
|
-
}
|
package/src/tailwind.config.js
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/** @type {import('tailwindcss').Config} */
|
|
2
|
-
module.exports = {
|
|
3
|
-
content: [
|
|
4
|
-
"./App.{js,jsx,ts,tsx}",
|
|
5
|
-
"./src/**/*.{js,jsx,ts,tsx}",
|
|
6
|
-
"./components/ui/**/*.{js,jsx,ts,tsx}",
|
|
7
|
-
],
|
|
8
|
-
presets: [require("nativewind/preset")],
|
|
9
|
-
theme: {
|
|
10
|
-
extend: {
|
|
11
|
-
colors: {
|
|
12
|
-
border: "hsl(var(--border))",
|
|
13
|
-
input: "hsl(var(--input))",
|
|
14
|
-
ring: "hsl(var(--ring))",
|
|
15
|
-
background: "hsl(var(--background))",
|
|
16
|
-
foreground: "hsl(var(--foreground))",
|
|
17
|
-
primary: {
|
|
18
|
-
DEFAULT: "hsl(var(--primary))",
|
|
19
|
-
foreground: "hsl(var(--primary-foreground))",
|
|
20
|
-
},
|
|
21
|
-
secondary: {
|
|
22
|
-
DEFAULT: "hsl(var(--secondary))",
|
|
23
|
-
foreground: "hsl(var(--secondary-foreground))",
|
|
24
|
-
},
|
|
25
|
-
destructive: {
|
|
26
|
-
DEFAULT: "hsl(var(--destructive))",
|
|
27
|
-
foreground: "hsl(var(--destructive-foreground))",
|
|
28
|
-
},
|
|
29
|
-
muted: {
|
|
30
|
-
DEFAULT: "hsl(var(--muted))",
|
|
31
|
-
foreground: "hsl(var(--muted-foreground))",
|
|
32
|
-
},
|
|
33
|
-
accent: {
|
|
34
|
-
DEFAULT: "hsl(var(--accent))",
|
|
35
|
-
foreground: "hsl(var(--accent-foreground))",
|
|
36
|
-
},
|
|
37
|
-
popover: {
|
|
38
|
-
DEFAULT: "hsl(var(--popover))",
|
|
39
|
-
foreground: "hsl(var(--popover-foreground))",
|
|
40
|
-
},
|
|
41
|
-
card: {
|
|
42
|
-
DEFAULT: "hsl(var(--card))",
|
|
43
|
-
foreground: "hsl(var(--card-foreground))",
|
|
44
|
-
},
|
|
45
|
-
},
|
|
46
|
-
borderRadius: {
|
|
47
|
-
lg: "var(--radius)",
|
|
48
|
-
md: "calc(var(--radius) - 2px)",
|
|
49
|
-
sm: "calc(var(--radius) - 4px)",
|
|
50
|
-
},
|
|
51
|
-
},
|
|
52
|
-
},
|
|
53
|
-
plugins: [],
|
|
54
|
-
};
|