ui-thing 0.1.56 → 0.2.0
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/.husky/pre-commit +1 -0
- package/CHANGELOG.md +64 -0
- package/README.md +4 -3
- package/dist/index.js +1273 -15771
- package/dist/index.js.map +1 -1
- package/package.json +33 -21
- package/src/commands/add.ts +218 -274
- package/src/commands/init.ts +107 -58
- package/src/commands/prettier.ts +6 -8
- package/src/commands/shortcuts.ts +13 -13
- package/src/commands/theme.ts +9 -6
- package/src/index.ts +2 -2
- package/src/templates/css.ts +958 -773
- package/src/templates/prettier.ts +14 -16
- package/src/templates/shortcuts.ts +225 -126
- package/src/templates/tw-helper.ts +8 -0
- package/src/templates/vs-code.ts +24 -0
- package/src/types.ts +74 -3
- package/src/utils/addPrettierConfig.ts +49 -6
- package/src/utils/addShortcutFiles.ts +5 -4
- package/src/utils/addTailwindVitePlugin.ts +35 -0
- package/src/utils/addVSCodeFiles.ts +13 -0
- package/src/utils/compareUIConfig.ts +1 -2
- package/src/utils/config.ts +59 -86
- package/src/utils/constants.ts +67 -13
- package/src/utils/detectNuxtVersion.ts +20 -0
- package/src/utils/fetchComponents.ts +14 -1
- package/src/utils/installPackages.ts +3 -27
- package/src/utils/mergeJsonFile.ts +28 -0
- package/src/utils/printFancyBoxMessage.ts +62 -16
- package/src/utils/promptForComponents.ts +8 -6
- package/src/utils/uiConfigPrompt.ts +12 -37
- package/tsconfig.json +2 -1
- package/dist/chunk-FW4363Y4.js +0 -2
- package/dist/chunk-FW4363Y4.js.map +0 -1
- package/dist/prompt-4NXDAQWE.js +0 -46
- package/dist/prompt-4NXDAQWE.js.map +0 -1
- package/src/comps.ts +0 -3237
- package/src/templates/tailwind.ts +0 -142
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
import fse from "fs-extra";
|
|
3
3
|
|
|
4
|
-
import { DEFINE_SHORTCUT
|
|
4
|
+
import { DEFINE_SHORTCUT } from "../templates/shortcuts";
|
|
5
5
|
import { UIConfig } from "../types";
|
|
6
6
|
import { getUIConfig } from "./config";
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Adds shortcut files to the specified directory.
|
|
10
|
+
*/
|
|
8
11
|
export const addShortcutFiles = async (cwd = process.cwd()) => {
|
|
9
12
|
// get config
|
|
10
13
|
let userConfig: UIConfig = await getUIConfig();
|
|
@@ -12,7 +15,5 @@ export const addShortcutFiles = async (cwd = process.cwd()) => {
|
|
|
12
15
|
// ensure that the composable folder exists
|
|
13
16
|
await fse.ensureDir(composablesLocation);
|
|
14
17
|
// write the defineShortcuts composable
|
|
15
|
-
await fse.writeFile(join(composablesLocation, "
|
|
16
|
-
// write the useShortcuts composable
|
|
17
|
-
await fse.writeFile(join(composablesLocation, "useShortcuts.ts"), USE_SHORTCUTS, "utf-8");
|
|
18
|
+
await fse.writeFile(join(composablesLocation, "shortcuts.ts"), DEFINE_SHORTCUT, "utf-8");
|
|
18
19
|
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { builders, loadFile, writeFile } from "magicast";
|
|
3
|
+
import { getDefaultExportOptions } from "magicast/helpers";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Adds the Tailwind CSS Vite plugin to the Nuxt config.
|
|
7
|
+
*/
|
|
8
|
+
export const addTailwindVitePlugin = async () => {
|
|
9
|
+
// Get the path to nuxt config
|
|
10
|
+
const CONFIG_PATH = join(process.cwd(), "nuxt.config.ts");
|
|
11
|
+
// Load the nuxt config file
|
|
12
|
+
const cfg = await loadFile(CONFIG_PATH);
|
|
13
|
+
// check if `tailwindcss()` is already present in the code
|
|
14
|
+
|
|
15
|
+
if (!cfg.$code.includes("tailwindcss()")) {
|
|
16
|
+
// get the exported config object
|
|
17
|
+
const defaultExport = getDefaultExportOptions(cfg);
|
|
18
|
+
// ensure vite and plugins are defined
|
|
19
|
+
defaultExport.vite ||= {};
|
|
20
|
+
defaultExport.vite.plugins ||= [];
|
|
21
|
+
// push the function to the plugins array
|
|
22
|
+
defaultExport.vite.plugins.push(builders.functionCall("tailwindcss"));
|
|
23
|
+
}
|
|
24
|
+
// check if tailwind plugin is already imported
|
|
25
|
+
if (!cfg.imports.$items.find((i) => i.local === "tailwindcss")) {
|
|
26
|
+
// prepend the import for tailwindcss
|
|
27
|
+
cfg.imports.$prepend({
|
|
28
|
+
from: "@tailwindcss/vite",
|
|
29
|
+
local: "tailwindcss",
|
|
30
|
+
imported: "default",
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
// write the changes to the `nuxt.config.ts` file
|
|
34
|
+
await writeFile(cfg, CONFIG_PATH);
|
|
35
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import fse from "fs-extra";
|
|
2
|
+
|
|
3
|
+
import { VS_CODE_RECOMMENDATIONS, VS_CODE_SETTINGS } from "../templates/vs-code";
|
|
4
|
+
import { mergeJsonFile } from "./mergeJsonFile";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Adds the necessary VS Code configuration files.
|
|
8
|
+
*/
|
|
9
|
+
export const addVSCodeFiles = (VS_CODE_FOLDER = ".vscode") => {
|
|
10
|
+
fse.ensureDirSync(VS_CODE_FOLDER);
|
|
11
|
+
mergeJsonFile(`${VS_CODE_FOLDER}/extensions.json`, VS_CODE_RECOMMENDATIONS);
|
|
12
|
+
mergeJsonFile(`${VS_CODE_FOLDER}/settings.json`, VS_CODE_SETTINGS);
|
|
13
|
+
};
|
|
@@ -12,7 +12,6 @@ export const compareUIConfig = async () => {
|
|
|
12
12
|
nuxtVersion: 3,
|
|
13
13
|
theme: "string",
|
|
14
14
|
tailwindCSSLocation: "string",
|
|
15
|
-
tailwindConfigLocation: "string",
|
|
16
15
|
componentsLocation: "string",
|
|
17
16
|
composablesLocation: "string",
|
|
18
17
|
utilsLocation: "string",
|
|
@@ -29,7 +28,7 @@ export const compareUIConfig = async () => {
|
|
|
29
28
|
}
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
if (missingProperties.length >
|
|
31
|
+
if (missingProperties.length > 1) {
|
|
33
32
|
return false;
|
|
34
33
|
}
|
|
35
34
|
return true;
|
package/src/utils/config.ts
CHANGED
|
@@ -1,120 +1,93 @@
|
|
|
1
|
-
import { join } from "path";
|
|
1
|
+
import { join } from "node:path";
|
|
2
2
|
import { loadConfig } from "c12";
|
|
3
3
|
import fse from "fs-extra";
|
|
4
|
-
import kleur from "kleur";
|
|
5
4
|
import _ from "lodash";
|
|
6
|
-
import { loadFile,
|
|
7
|
-
import { addNuxtModule
|
|
5
|
+
import { loadFile, writeFile } from "magicast";
|
|
6
|
+
import { addNuxtModule } from "magicast/helpers";
|
|
8
7
|
import prompts from "prompts";
|
|
9
8
|
|
|
10
9
|
import { InitOptions, UIConfig } from "../types";
|
|
11
|
-
import {
|
|
10
|
+
import { DEFAULT_CONFIG, DEFAULT_CONFIG_NUXT4, UI_CONFIG_FILENAME } from "./constants";
|
|
11
|
+
import { detectNuxtVersion } from "./detectNuxtVersion";
|
|
12
|
+
import { initPrompts } from "./uiConfigPrompt";
|
|
12
13
|
|
|
13
14
|
const currentDir = process.cwd();
|
|
14
|
-
const uiConfigFilename = "ui-thing.config.ts";
|
|
15
|
-
const defaultConfig: UIConfig = {
|
|
16
|
-
nuxtVersion: 3,
|
|
17
|
-
theme: "zinc",
|
|
18
|
-
tailwindCSSLocation: "assets/css/tailwind.css",
|
|
19
|
-
tailwindConfigLocation: "tailwind.config.js",
|
|
20
|
-
componentsLocation: "components/Ui",
|
|
21
|
-
composablesLocation: "composables",
|
|
22
|
-
pluginsLocation: "plugins",
|
|
23
|
-
utilsLocation: "utils",
|
|
24
|
-
force: true,
|
|
25
|
-
useDefaultFilename: true,
|
|
26
|
-
packageManager: "npm",
|
|
27
|
-
};
|
|
28
|
-
const defaultNuxt4Config: UIConfig = {
|
|
29
|
-
nuxtVersion: 4,
|
|
30
|
-
theme: "zinc",
|
|
31
|
-
tailwindCSSLocation: "app/assets/css/tailwind.css",
|
|
32
|
-
tailwindConfigLocation: "tailwind.config.js",
|
|
33
|
-
componentsLocation: "app/components/Ui",
|
|
34
|
-
composablesLocation: "app/composables",
|
|
35
|
-
pluginsLocation: "app/plugins",
|
|
36
|
-
utilsLocation: "app/utils",
|
|
37
|
-
force: true,
|
|
38
|
-
useDefaultFilename: true,
|
|
39
|
-
packageManager: "npm",
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export const getNuxtConfig = async () => {
|
|
43
|
-
if (!fse.existsSync("nuxt.config.ts")) {
|
|
44
|
-
console.log(kleur.red(`No ${kleur.bgWhite(`nuxt.config.ts`)} file found. Exiting...`));
|
|
45
|
-
return process.exit(0);
|
|
46
|
-
}
|
|
47
|
-
const nuxtConfig = await loadFile(join(currentDir, "nuxt.config.ts"));
|
|
48
|
-
const defaultExport = getDefaultExportOptions(nuxtConfig);
|
|
49
|
-
return { nuxtConfig, defaultExport };
|
|
50
|
-
};
|
|
51
15
|
|
|
52
|
-
|
|
53
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Creates or retrieves the UI Thing config.
|
|
18
|
+
*/
|
|
19
|
+
export const getUIConfig = async (options?: InitOptions): Promise<UIConfig> => {
|
|
20
|
+
const configExists = fse.existsSync(UI_CONFIG_FILENAME);
|
|
54
21
|
let uiConfig: UIConfig = {} as UIConfig;
|
|
55
|
-
|
|
22
|
+
const nuxtVersion = Number(options?.nuxtVersion) || detectNuxtVersion();
|
|
56
23
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
// Check if user chose pnpm as package manager
|
|
24
|
+
// Force creation or first-time setup
|
|
25
|
+
if (!configExists || options?.force) {
|
|
26
|
+
uiConfig = options?.yes
|
|
27
|
+
? nuxtVersion === 4
|
|
28
|
+
? DEFAULT_CONFIG_NUXT4
|
|
29
|
+
: DEFAULT_CONFIG
|
|
30
|
+
: await initPrompts(nuxtVersion);
|
|
31
|
+
|
|
32
|
+
await fse.writeFile(UI_CONFIG_FILENAME, `export default ${JSON.stringify(uiConfig, null, 2)}`);
|
|
33
|
+
|
|
34
|
+
// Handle pnpm special case
|
|
69
35
|
if (uiConfig.packageManager === "pnpm") {
|
|
70
|
-
// check if a .npmrc file exists
|
|
71
36
|
const npmrcExists = fse.existsSync(".npmrc");
|
|
72
|
-
|
|
37
|
+
let shouldWrite = true;
|
|
38
|
+
|
|
73
39
|
if (npmrcExists) {
|
|
74
40
|
const { confirmCreateNpmrc } = await prompts({
|
|
75
41
|
type: "confirm",
|
|
76
42
|
name: "confirmCreateNpmrc",
|
|
77
|
-
message: "A .npmrc file already exists.
|
|
43
|
+
message: "A .npmrc file already exists. Overwrite it?",
|
|
78
44
|
initial: false,
|
|
79
45
|
});
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
46
|
+
shouldWrite = confirmCreateNpmrc;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (shouldWrite) {
|
|
84
50
|
await fse.writeFile(".npmrc", "shamefully-hoist=true\nstrict-peer-dependencies=false\n");
|
|
85
51
|
}
|
|
86
52
|
}
|
|
87
53
|
} else {
|
|
88
|
-
const data = await loadConfig({
|
|
89
|
-
configFile:
|
|
54
|
+
const data = await loadConfig<UIConfig>({
|
|
55
|
+
configFile: UI_CONFIG_FILENAME.replace(".ts", ""),
|
|
90
56
|
});
|
|
91
57
|
uiConfig = data.config as UIConfig;
|
|
92
58
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
59
|
+
|
|
60
|
+
// Ensure valid config
|
|
61
|
+
if (_.isEmpty(uiConfig)) return getUIConfig({ force: true });
|
|
62
|
+
|
|
96
63
|
createConfigPaths(uiConfig);
|
|
97
64
|
return uiConfig;
|
|
98
65
|
};
|
|
99
66
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
};
|
|
67
|
+
/**
|
|
68
|
+
* Ensures all required paths exist for UI Thing.
|
|
69
|
+
*/
|
|
70
|
+
const createConfigPaths = (uiConfig: UIConfig) => {
|
|
71
|
+
const ensureFileOrDir = (pathValue?: string, isDir = false) => {
|
|
72
|
+
if (!pathValue) return;
|
|
73
|
+
isDir ? fse.ensureDirSync(pathValue) : fse.ensureFileSync(pathValue);
|
|
74
|
+
};
|
|
109
75
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
return cfg;
|
|
76
|
+
ensureFileOrDir(uiConfig.tailwindCSSLocation);
|
|
77
|
+
ensureFileOrDir(uiConfig.pluginsLocation, true);
|
|
78
|
+
ensureFileOrDir(uiConfig.componentsLocation, true);
|
|
79
|
+
ensureFileOrDir(uiConfig.composablesLocation, true);
|
|
80
|
+
ensureFileOrDir(uiConfig.utilsLocation, true);
|
|
116
81
|
};
|
|
117
82
|
|
|
118
|
-
|
|
119
|
-
|
|
83
|
+
/**
|
|
84
|
+
* Adds one or multiple Nuxt modules to nuxt.config.ts safely.
|
|
85
|
+
*/
|
|
86
|
+
export const addModuleToConfig = async (modules: string[] | string) => {
|
|
87
|
+
if (!modules) return;
|
|
88
|
+
const modulesArray = typeof modules === "string" ? [modules] : modules;
|
|
89
|
+
|
|
90
|
+
const proxy = await loadFile(join(currentDir, "nuxt.config.ts"));
|
|
91
|
+
modulesArray.forEach((m) => addNuxtModule(proxy, m));
|
|
92
|
+
await writeFile(proxy, join(currentDir, "nuxt.config.ts"));
|
|
120
93
|
};
|
package/src/utils/constants.ts
CHANGED
|
@@ -1,41 +1,95 @@
|
|
|
1
|
+
import { UIConfig } from "../types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The filename of the UI Thing configuration file.
|
|
5
|
+
*/
|
|
6
|
+
export const UI_CONFIG_FILENAME = "ui-thing.config.ts";
|
|
7
|
+
/**
|
|
8
|
+
* The default UI Thing configuration.
|
|
9
|
+
*
|
|
10
|
+
* Used when Nuxt 3 is detected
|
|
11
|
+
*/
|
|
12
|
+
export const DEFAULT_CONFIG: UIConfig = {
|
|
13
|
+
theme: "zinc",
|
|
14
|
+
tailwindCSSLocation: "assets/css/tailwind.css",
|
|
15
|
+
componentsLocation: "components/Ui",
|
|
16
|
+
composablesLocation: "composables",
|
|
17
|
+
pluginsLocation: "plugins",
|
|
18
|
+
utilsLocation: "utils",
|
|
19
|
+
force: true,
|
|
20
|
+
useDefaultFilename: true,
|
|
21
|
+
packageManager: "npm",
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The default UI Thing configuration.
|
|
26
|
+
*
|
|
27
|
+
* Used when Nuxt 4 is detected
|
|
28
|
+
*/
|
|
29
|
+
export const DEFAULT_CONFIG_NUXT4: UIConfig = {
|
|
30
|
+
theme: "zinc",
|
|
31
|
+
tailwindCSSLocation: "app/assets/css/tailwind.css",
|
|
32
|
+
componentsLocation: "app/components/Ui",
|
|
33
|
+
composablesLocation: "app/composables",
|
|
34
|
+
pluginsLocation: "app/plugins",
|
|
35
|
+
utilsLocation: "app/utils",
|
|
36
|
+
force: true,
|
|
37
|
+
useDefaultFilename: true,
|
|
38
|
+
packageManager: "npm",
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The initial core dependencies
|
|
43
|
+
*/
|
|
1
44
|
export const INIT_DEPS = [
|
|
2
|
-
"
|
|
45
|
+
"tailwindcss",
|
|
46
|
+
"motion-v",
|
|
47
|
+
"@tailwindcss/vite",
|
|
48
|
+
"reka-ui",
|
|
3
49
|
"tailwind-variants",
|
|
50
|
+
"tailwind-merge",
|
|
4
51
|
"@nuxt/fonts",
|
|
5
|
-
"@nuxtjs/tailwindcss",
|
|
6
52
|
"@nuxtjs/color-mode",
|
|
7
53
|
"@nuxt/icon",
|
|
8
54
|
"@vueuse/nuxt",
|
|
9
55
|
"@tailwindcss/forms",
|
|
10
|
-
"tailwindcss-animate",
|
|
11
56
|
];
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The initial development dependencies
|
|
60
|
+
*/
|
|
12
61
|
export const INIT_DEV_DEPS = [
|
|
13
62
|
"typescript",
|
|
14
63
|
"prettier-plugin-tailwindcss",
|
|
15
64
|
"prettier",
|
|
16
65
|
"@ianvs/prettier-plugin-sort-imports",
|
|
66
|
+
"tw-animate-css",
|
|
17
67
|
];
|
|
18
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Initial modules that are needed
|
|
71
|
+
*/
|
|
19
72
|
export const INIT_MODULES = [
|
|
20
|
-
"@nuxtjs/tailwindcss",
|
|
21
73
|
"@nuxtjs/color-mode",
|
|
74
|
+
"motion-v/nuxt",
|
|
22
75
|
"@vueuse/nuxt",
|
|
23
76
|
"@nuxt/icon",
|
|
24
77
|
"@nuxt/fonts",
|
|
25
78
|
];
|
|
26
79
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
];
|
|
31
|
-
|
|
80
|
+
/**
|
|
81
|
+
* List of available package managers to chose from
|
|
82
|
+
*/
|
|
32
83
|
export const PACKAGE_MANAGER_CHOICES = [
|
|
33
|
-
{ title: "
|
|
34
|
-
{ title: "
|
|
35
|
-
{ title: "
|
|
36
|
-
{ title: "
|
|
84
|
+
{ title: "Npm", value: "npm" },
|
|
85
|
+
{ title: "Yarn", value: "yarn" },
|
|
86
|
+
{ title: "Pnpm", value: "pnpm" },
|
|
87
|
+
{ title: "Bun", value: "bun" },
|
|
37
88
|
];
|
|
38
89
|
|
|
90
|
+
/**
|
|
91
|
+
* List of available CSS themes to choose from
|
|
92
|
+
*/
|
|
39
93
|
export const CSS_THEME_OPTIONS = [
|
|
40
94
|
{ title: "Zinc", value: "zinc" },
|
|
41
95
|
{ title: "Slate", value: "slate" },
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Detect the Nuxt.js version from package.json.
|
|
5
|
+
*/
|
|
6
|
+
export function detectNuxtVersion() {
|
|
7
|
+
try {
|
|
8
|
+
const pkg = JSON.parse(fs.readFileSync("package.json", "utf-8"));
|
|
9
|
+
const nuxtVer = pkg.dependencies?.nuxt || pkg.devDependencies?.nuxt;
|
|
10
|
+
if (nuxtVer) {
|
|
11
|
+
// check if version is 4.x
|
|
12
|
+
// check for all possible formats with a regex
|
|
13
|
+
if (/^[~^>=<\s]*4/.test(nuxtVer)) return 4;
|
|
14
|
+
return 3;
|
|
15
|
+
}
|
|
16
|
+
} catch {
|
|
17
|
+
return 4;
|
|
18
|
+
}
|
|
19
|
+
return 4;
|
|
20
|
+
}
|
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
|
+
import dotenv from "dotenv";
|
|
3
|
+
import ora from "ora";
|
|
2
4
|
|
|
3
5
|
import { Component } from "../types";
|
|
4
6
|
|
|
7
|
+
dotenv.config();
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Function used to fetch components from the API.
|
|
11
|
+
*/
|
|
5
12
|
export const fetchComponents = async () => {
|
|
6
|
-
const
|
|
13
|
+
const spinner = ora("Fetching components...").start();
|
|
14
|
+
|
|
15
|
+
const { data } = await axios.get<Component[]>(
|
|
16
|
+
process.env.COMPONENTS_API || "https://uithing.com/api/components"
|
|
17
|
+
);
|
|
18
|
+
spinner.succeed("Components fetched.");
|
|
19
|
+
|
|
7
20
|
return data;
|
|
8
21
|
};
|
|
@@ -1,28 +1,7 @@
|
|
|
1
|
-
import * as fs from "fs";
|
|
2
|
-
import * as path from "path";
|
|
3
1
|
import { execa } from "execa";
|
|
4
2
|
import _ from "lodash";
|
|
5
3
|
import ora from "ora";
|
|
6
4
|
|
|
7
|
-
function checkPackageJson() {
|
|
8
|
-
const packageJsonPath = path.join(process.cwd(), "package.json");
|
|
9
|
-
let scriptExists = false;
|
|
10
|
-
|
|
11
|
-
// Check if package.json file exists
|
|
12
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
13
|
-
// Read the package.json file
|
|
14
|
-
const packageJsonContent = fs.readFileSync(packageJsonPath, "utf-8");
|
|
15
|
-
const packageJson = JSON.parse(packageJsonContent);
|
|
16
|
-
|
|
17
|
-
// Check if "postinstall" script is defined
|
|
18
|
-
const postinstallScript = packageJson.scripts?.postinstall;
|
|
19
|
-
if (postinstallScript) {
|
|
20
|
-
scriptExists = true;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return scriptExists;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
5
|
export const installPackages = async (
|
|
27
6
|
packageManager: string,
|
|
28
7
|
deps?: string[] | string,
|
|
@@ -44,12 +23,9 @@ export const installPackages = async (
|
|
|
44
23
|
await execa(packageManager, [packageManager === "yarn" ? "add" : "install", "-D", ...devDeps]);
|
|
45
24
|
}
|
|
46
25
|
|
|
47
|
-
//
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
depsSpinner.text = "Running postinstall script...";
|
|
51
|
-
await execa(packageManager, ["run", "postinstall"]);
|
|
52
|
-
}
|
|
26
|
+
// we should check to see if there is a postinstall script and run it
|
|
27
|
+
depsSpinner.text = "Running nuxt prepare...";
|
|
28
|
+
await execa`npx -y nuxt prepare`;
|
|
53
29
|
|
|
54
30
|
depsSpinner.succeed("Installed dependencies!");
|
|
55
31
|
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { merge } from "es-toolkit";
|
|
2
|
+
import fse from "fs-extra";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Merges JSON data into a file without overwriting existing keys.
|
|
6
|
+
* Creates the file if it does not exist.
|
|
7
|
+
*
|
|
8
|
+
* @param filePath - Path to the JSON file to update.
|
|
9
|
+
* @param newData - The new JSON data to merge in.
|
|
10
|
+
*/
|
|
11
|
+
export function mergeJsonFile(filePath: string, newData: Record<string, any>) {
|
|
12
|
+
let currentData: Record<string, any> = {};
|
|
13
|
+
|
|
14
|
+
// Read current JSON if it exists
|
|
15
|
+
if (fse.existsSync(filePath)) {
|
|
16
|
+
try {
|
|
17
|
+
currentData = fse.readJsonSync(filePath);
|
|
18
|
+
} catch {
|
|
19
|
+
console.warn(`⚠️ Could not parse ${filePath}, starting fresh.`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Merge existing and new data
|
|
24
|
+
const merged = merge(currentData, newData);
|
|
25
|
+
|
|
26
|
+
// Write merged JSON with pretty formatting
|
|
27
|
+
fse.writeJsonSync(filePath, merged, { spaces: 2 });
|
|
28
|
+
}
|
|
@@ -1,19 +1,65 @@
|
|
|
1
|
-
import boxen from "boxen";
|
|
1
|
+
import boxen, { Options as BoxOptions } from "boxen";
|
|
2
2
|
import figlet from "figlet";
|
|
3
|
-
import type { Options } from "boxen";
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Extra configuration options for the fancy box.
|
|
6
|
+
*/
|
|
7
|
+
interface FancyBoxOptions {
|
|
8
|
+
box?: BoxOptions; // Overrides for boxen (border style, color, etc.)
|
|
9
|
+
figletFont?: figlet.Fonts; // Optional font name for ASCII art
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Creates the ASCII-art box as a string (pure function — does not log).
|
|
14
|
+
* Useful for testing because it avoids side effects like console output.
|
|
15
|
+
*
|
|
16
|
+
* @param title - The main text to display in big ASCII font
|
|
17
|
+
* @param description - Optional subtitle or extra info below the box
|
|
18
|
+
* @param options - Styling and font configuration
|
|
19
|
+
* @returns A fully formatted string with ASCII title inside a box
|
|
20
|
+
*/
|
|
21
|
+
const createFancyBoxMessage = (
|
|
22
|
+
title: string,
|
|
23
|
+
description?: string,
|
|
24
|
+
options: FancyBoxOptions = {}
|
|
25
|
+
): string => {
|
|
26
|
+
const { box, figletFont } = options;
|
|
27
|
+
|
|
28
|
+
// Generate the ASCII art title using figlet
|
|
29
|
+
const asciiTitle = figlet.textSync(title, {
|
|
30
|
+
font: figletFont || "Standard", // Default font if none provided
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Default box styling so all boxes look consistent
|
|
34
|
+
const defaultBoxOptions: BoxOptions = {
|
|
35
|
+
borderColor: "greenBright",
|
|
36
|
+
padding: 1,
|
|
37
|
+
borderStyle: "round",
|
|
38
|
+
titleAlignment: "center",
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// Wrap ASCII art in a decorative box
|
|
42
|
+
const boxMessage = boxen(asciiTitle, {
|
|
43
|
+
...defaultBoxOptions, // Base styles
|
|
44
|
+
...box, // User overrides
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Append description if provided
|
|
48
|
+
return description ? `${boxMessage}\n${description}` : boxMessage;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* CLI-friendly helper that prints the fancy box directly to the terminal.
|
|
53
|
+
* This simply calls `createFancyBoxMessage` and logs the result.
|
|
54
|
+
*
|
|
55
|
+
* @param title - The main title to display
|
|
56
|
+
* @param description - Optional extra info under the box
|
|
57
|
+
* @param options - Font and box customization
|
|
58
|
+
*/
|
|
59
|
+
export const printFancyBoxMessage = (
|
|
60
|
+
title: string,
|
|
61
|
+
description?: string,
|
|
62
|
+
options?: FancyBoxOptions
|
|
63
|
+
) => {
|
|
64
|
+
console.log("\n" + createFancyBoxMessage(title, description, options));
|
|
19
65
|
};
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import prompts from "prompts";
|
|
2
2
|
|
|
3
|
-
import allComponents from "../comps";
|
|
4
3
|
import { Component } from "../types";
|
|
4
|
+
import { fetchComponents } from "./fetchComponents";
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Prompts the user to select components to add.
|
|
8
|
+
*/
|
|
9
|
+
export const promptUserForComponents = async (
|
|
10
|
+
all?: boolean,
|
|
11
|
+
allComponents: Component[] = []
|
|
12
|
+
): Promise<string[]> => {
|
|
7
13
|
// If all is true, return all components
|
|
8
14
|
if (all) return allComponents.map((c: Component) => c.value);
|
|
9
15
|
const { components } = await prompts({
|
|
@@ -11,10 +17,6 @@ export const promptUserForComponents = async (all?: boolean): Promise<string[]>
|
|
|
11
17
|
name: "components",
|
|
12
18
|
message: "Select the components you want to add",
|
|
13
19
|
choices: allComponents.map((c: Component) => ({ title: c.name, value: c.value })),
|
|
14
|
-
onRender(kleur) {
|
|
15
|
-
// @ts-ignore
|
|
16
|
-
this.msg = kleur.bgCyan(" Choose components ") + " Select the components you want to add";
|
|
17
|
-
},
|
|
18
20
|
});
|
|
19
21
|
return components;
|
|
20
22
|
};
|