ui-thing 0.0.30 → 0.1.2

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": "ui-thing",
3
- "version": "0.0.30",
3
+ "version": "0.1.2",
4
4
  "description": "CLI used to add Nuxt 3 components to a project",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",
@@ -62,7 +62,7 @@
62
62
  "@types/figlet": "^1.5.8",
63
63
  "@types/fs-extra": "^11.0.4",
64
64
  "@types/lodash": "^4.14.202",
65
- "@types/node": "^20.11.20",
65
+ "@types/node": "^20.11.24",
66
66
  "@types/prompts": "^2.4.9",
67
67
  "@vitest/coverage-v8": "^1.3.1",
68
68
  "magicast": "^0.3.3",
@@ -1,317 +1,317 @@
1
- import { readFileSync } from "fs";
2
- import path from "node:path";
3
- import { Command } from "commander";
4
- import { consola } from "consola";
5
- import { defu } from "defu";
6
- import kleur from "kleur";
7
- import _ from "lodash";
8
- import prompts from "prompts";
9
-
10
- import allComponents from "../comps";
11
- import { Component } from "../types";
12
- import { compareUIConfig } from "../utils/compareUIConfig";
13
- import { addModuleToConfig, getNuxtConfig, getUIConfig, updateConfig } from "../utils/config";
14
- import { fileExists } from "../utils/fileExists";
15
- import { installPackages } from "../utils/installPackages";
16
- import { printFancyBoxMessage } from "../utils/printFancyBoxMessage";
17
- import { promptUserForComponents } from "../utils/promptForComponents";
18
- import { writeFile } from "../utils/writeFile";
19
-
20
- const currentDirectory = process.cwd();
21
-
22
- const findComponent = (name: string) => {
23
- return allComponents.find((c) => c.value.toLowerCase() === name.toLowerCase());
24
- };
25
-
26
- /**
27
- * Adds a component to your project
28
- */
29
- export const add = new Command()
30
- .name("add")
31
- .command("add")
32
- .description("Add a list of components to your project.")
33
- .option("-a --all", "Add all components to your project.", false)
34
- .argument("[componentNames...]", "Components that you want to add.")
35
- .action(async (components: Array<string>, options: { all?: boolean }) => {
36
- // Get nuxt config
37
- const cfg = await getNuxtConfig();
38
- // Get ui config
39
- let uiConfig = await getUIConfig();
40
- let uiConfigIsCorrect = await compareUIConfig();
41
- if (!uiConfigIsCorrect) {
42
- uiConfig = await getUIConfig({ force: true });
43
- }
44
- if (_.isEmpty(uiConfig)) {
45
- consola.info("Config file not set. Exiting...");
46
- process.exit(0);
47
- }
48
-
49
- let componentNames = components;
50
- // if no components are passed, prompt the user to select components
51
- if (componentNames.length === 0) {
52
- const response = await promptUserForComponents(options.all);
53
- if ((response && response.length === 0) || !response) {
54
- consola.info("No components selected. Exiting...");
55
- process.exit(0);
56
- }
57
- componentNames = response;
58
- }
59
-
60
- // store the components that are not found
61
- let notFound: string[] = [];
62
- componentNames.forEach((c) => {
63
- if (!findComponent(c)) {
64
- notFound.push(c);
65
- }
66
- });
67
- if (notFound.length > 0) {
68
- consola.error(`The following components were not found: ${kleur.bgRed(notFound.join(", "))}`);
69
- }
70
-
71
- // store the components that are found
72
- let found: Component[] = [];
73
- componentNames.forEach((c) => {
74
- if (findComponent(c)) {
75
- found.push(findComponent(c)!);
76
- }
77
- });
78
- // check if the found components depends on other components and add them to the list
79
- for (let i = 0; i < found.length; i++) {
80
- const component = found[i];
81
- if (component.components) {
82
- for (let j = 0; j < component.components.length; j++) {
83
- const comp = component.components[j];
84
- if (!found.find((c) => c.value === comp)) {
85
- found.push(findComponent(comp)!);
86
- }
87
- }
88
- }
89
- }
90
-
91
- // add the components & files associated with them
92
- for (let i = 0; i < found.length; i++) {
93
- const component = found[i];
94
- loop2: for (let k = 0; k < component.files.length; k++) {
95
- const file = component.files[k];
96
- let fileName = file.fileName;
97
- let dirPath = uiConfig.componentsLocation;
98
- let filePath = path.join(currentDirectory, dirPath, fileName);
99
- if (!uiConfig.useDefaultFilename) {
100
- const res = await prompts({
101
- type: "text",
102
- name: "value",
103
- message: `Where should we add the file`,
104
- initial: dirPath,
105
- onRender(kleur) {
106
- //@ts-ignore
107
- this.msg =
108
- kleur.bgCyan(" Location ") +
109
- ` Where should we add the file ${kleur.cyan(`${fileName}`)} `;
110
- },
111
- });
112
- if (res.value) {
113
- dirPath = res.value;
114
- filePath = path.join(currentDirectory, res.value, fileName);
115
- }
116
- }
117
- // Check if the file exists
118
- const exists = await fileExists(filePath);
119
- // if it exists & the force option was not passed, ask the user to confirm overwriting the file
120
- if (exists && !uiConfig.force) {
121
- const res = await prompts({
122
- type: "confirm",
123
- name: "value",
124
- message: `The file that we are trying to add ${kleur.bold(
125
- fileName
126
- )} to is already taken. Overwrite?`,
127
- initial: false,
128
- });
129
- if (!res.value) {
130
- consola.info(`We will not overwrite the file for ${kleur.cyan(fileName)}`);
131
- continue loop2;
132
- }
133
- }
134
- await writeFile(filePath, file.fileContent);
135
-
136
- // @not-scalable
137
- if (component.value === "vue-sonner") {
138
- // Update the nuxt config
139
- cfg.defaultExport.imports ||= {};
140
- cfg.defaultExport.build ||= {};
141
- cfg.defaultExport.imports.imports ||= [];
142
- cfg.defaultExport.build.transpile ||= [];
143
- const sonnerExists = cfg.defaultExport.imports.imports.find(
144
- (i: any) => i.from === "vue-sonner" && i.name === "toast"
145
- );
146
- if (!sonnerExists) {
147
- cfg.defaultExport.imports.imports.push({
148
- from: "vue-sonner",
149
- name: "toast",
150
- as: "useSonner",
151
- });
152
- }
153
- const transpileExists = cfg.defaultExport.build.transpile.find((i: any) => "vue-sonner");
154
- if (!transpileExists) {
155
- cfg.defaultExport.build.transpile.push("vue-sonner");
156
- }
157
- }
158
- // @not-scalable
159
- if (component.value === "datatable") {
160
- cfg.defaultExport.app ||= {};
161
- cfg.defaultExport.app.head ||= {};
162
- cfg.defaultExport.app.head.script ||= [];
163
- const scriptOneExists = cfg.defaultExport.app.head.script.find(
164
- (i: any) =>
165
- i.src === "https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.9/pdfmake.min.js"
166
- );
167
- if (!scriptOneExists) {
168
- cfg.defaultExport.app.head.script.push({
169
- src: "https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.9/pdfmake.min.js",
170
- defer: true,
171
- });
172
- }
173
- const scriptTwoExists = cfg.defaultExport.app.head.script.find(
174
- (i: any) =>
175
- i.src === "https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.9/vfs_fonts.min.js"
176
- );
177
- if (!scriptTwoExists) {
178
- cfg.defaultExport.app.head.script.push({
179
- src: "https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.9/vfs_fonts.min.js",
180
- defer: true,
181
- });
182
- }
183
- // Get package.json and add the overrides
184
- const packageJson = readFileSync(path.join(currentDirectory, "package.json"), "utf-8");
185
- // if no package.json file, do nothing
186
- if (packageJson) {
187
- const parsedPackageJson = JSON.parse(packageJson);
188
- parsedPackageJson.overrides = defu(
189
- {},
190
- parsedPackageJson.overrides,
191
- component.overrides
192
- );
193
- await writeFile(
194
- path.join(currentDirectory, "package.json"),
195
- JSON.stringify(parsedPackageJson, null, 2)
196
- );
197
- }
198
- }
199
-
200
- // add utils attached to the component
201
- loop3: for (let j = 0; j < component.utils.length; j++) {
202
- const util = component.utils[j];
203
- const filePath = path.join(currentDirectory, uiConfig.utilsLocation, util.fileName);
204
- // Check if the file exists
205
- const exists = await fileExists(filePath);
206
- if (exists && !uiConfig.force) {
207
- const res = await prompts({
208
- type: "confirm",
209
- name: "value",
210
- message: `The utils file that we are trying to add ${kleur.bold(
211
- util.fileName
212
- )} already exists. Overwrite?`,
213
- initial: true,
214
- });
215
- if (!res.value) {
216
- consola.info(`We will not overwrite the file for ${kleur.cyan(util.fileName)}`);
217
- continue loop3;
218
- }
219
- }
220
- await writeFile(filePath, util.fileContent);
221
- }
222
- // add composables attached to the component
223
- loop4: for (let j = 0; j < component.composables.length; j++) {
224
- const composable = component.composables[j];
225
- const filePath = path.join(
226
- currentDirectory,
227
- uiConfig.composablesLocation,
228
- composable.fileName
229
- );
230
- // Check if the file exists
231
- const exists = await fileExists(filePath);
232
- if (exists && !uiConfig.force) {
233
- const res = await prompts({
234
- type: "confirm",
235
- name: "value",
236
- message: `The composables file that we are trying to add ${kleur.bold(
237
- composable.fileName
238
- )} already exists. Overwrite?`,
239
- initial: true,
240
- });
241
- if (!res.value) {
242
- consola.info(`We will not overwrite the file for ${kleur.cyan(composable.fileName)}`);
243
- continue loop4;
244
- }
245
- }
246
- await writeFile(filePath, composable.fileContent);
247
- }
248
- // add plugins attached to the component
249
- loop5: for (let j = 0; j < component.plugins.length; j++) {
250
- const plugin = component.plugins[j];
251
- const filePath = path.join(currentDirectory, plugin.dirPath, plugin.fileName);
252
- // Check if the file exists
253
- const exists = await fileExists(filePath);
254
- if (exists && !uiConfig.force) {
255
- const res = await prompts({
256
- type: "confirm",
257
- name: "value",
258
- message: `The plugins file that we are trying to add ${kleur.bold(
259
- plugin.fileName
260
- )} already exists. Overwrite?`,
261
- initial: true,
262
- });
263
- if (!res.value) {
264
- consola.info(`We will not overwrite the file for ${kleur.cyan(plugin.fileName)}`);
265
- continue loop5;
266
- }
267
- }
268
- await writeFile(filePath, plugin.fileContent);
269
- }
270
- }
271
- }
272
- // Add modules to nuxt config
273
- addModuleToConfig(cfg.nuxtConfig, _.uniq(found.map((c) => c.nuxtModules || []).flat()));
274
- // Write the changes to the nuxt config
275
- await updateConfig(cfg.nuxtConfig, "nuxt.config.ts");
276
- const foundDeps = _.uniq(found.map((c) => c.deps || []).flat());
277
- const foundDevDeps = _.uniq(found.map((c) => c.devDeps || []).flat());
278
-
279
- // check if the foundDeps & foundDevDeps lists are not empty, ask the user to install them
280
- if (foundDeps.length > 0 || foundDevDeps.length > 0) {
281
- // if the all option was passed, install the packages without asking
282
- if (options.all) {
283
- await installPackages(uiConfig.packageManager, foundDeps, foundDevDeps);
284
- } else {
285
- // Ask the user to install the packages
286
- const { confirmInstall } = await prompts({
287
- type: "confirm",
288
- name: "confirmInstall",
289
- message: `Do you want to install the following packages: ${kleur.cyan(
290
- foundDeps.join(", ")
291
- )} ${kleur.cyan(foundDevDeps.join(", "))}`,
292
- initial: true,
293
- });
294
- if (confirmInstall) {
295
- await installPackages(uiConfig.packageManager, foundDeps, foundDevDeps);
296
- }
297
- }
298
- }
299
-
300
- printFancyBoxMessage(
301
- "All Done!",
302
- { title: "Components Added" },
303
- `Run the ${kleur.cyan("ui-thing@latest --help")} command to learn more.\n`
304
- );
305
- const combinedInstructions = found.map((c) => c.instructions).flat();
306
- // remove undefined from the array
307
- _.remove(combinedInstructions, (i) => !i);
308
-
309
- // print the instructions if there are any
310
- if (combinedInstructions.length > 0) {
311
- console.log("");
312
- console.log(kleur.bgCyan(" Instructions "));
313
- combinedInstructions.forEach((i) => {
314
- console.log(`${kleur.cyan("-")} ${i}`);
315
- });
316
- }
317
- });
1
+ import { readFileSync } from "fs";
2
+ import path from "node:path";
3
+ import { Command } from "commander";
4
+ import { consola } from "consola";
5
+ import { defu } from "defu";
6
+ import kleur from "kleur";
7
+ import _ from "lodash";
8
+ import prompts from "prompts";
9
+
10
+ import allComponents from "../comps";
11
+ import { Component } from "../types";
12
+ import { compareUIConfig } from "../utils/compareUIConfig";
13
+ import { addModuleToConfig, getNuxtConfig, getUIConfig, updateConfig } from "../utils/config";
14
+ import { fileExists } from "../utils/fileExists";
15
+ import { installPackages } from "../utils/installPackages";
16
+ import { printFancyBoxMessage } from "../utils/printFancyBoxMessage";
17
+ import { promptUserForComponents } from "../utils/promptForComponents";
18
+ import { writeFile } from "../utils/writeFile";
19
+
20
+ const currentDirectory = process.cwd();
21
+
22
+ const findComponent = (name: string) => {
23
+ return allComponents.find((c) => c.value.toLowerCase() === name.toLowerCase());
24
+ };
25
+
26
+ /**
27
+ * Adds a component to your project
28
+ */
29
+ export const add = new Command()
30
+ .name("add")
31
+ .command("add")
32
+ .description("Add a list of components to your project.")
33
+ .option("-a --all", "Add all components to your project.", false)
34
+ .argument("[componentNames...]", "Components that you want to add.")
35
+ .action(async (components: Array<string>, options: { all?: boolean }) => {
36
+ // Get nuxt config
37
+ const cfg = await getNuxtConfig();
38
+ // Get ui config
39
+ let uiConfig = await getUIConfig();
40
+ let uiConfigIsCorrect = await compareUIConfig();
41
+ if (!uiConfigIsCorrect) {
42
+ uiConfig = await getUIConfig({ force: true });
43
+ }
44
+ if (_.isEmpty(uiConfig)) {
45
+ consola.info("Config file not set. Exiting...");
46
+ process.exit(0);
47
+ }
48
+
49
+ let componentNames = components;
50
+ // if no components are passed, prompt the user to select components
51
+ if (componentNames.length === 0) {
52
+ const response = await promptUserForComponents(options.all);
53
+ if ((response && response.length === 0) || !response) {
54
+ consola.info("No components selected. Exiting...");
55
+ process.exit(0);
56
+ }
57
+ componentNames = response;
58
+ }
59
+
60
+ // store the components that are not found
61
+ let notFound: string[] = [];
62
+ componentNames.forEach((c) => {
63
+ if (!findComponent(c)) {
64
+ notFound.push(c);
65
+ }
66
+ });
67
+ if (notFound.length > 0) {
68
+ consola.error(`The following components were not found: ${kleur.bgRed(notFound.join(", "))}`);
69
+ }
70
+
71
+ // store the components that are found
72
+ let found: Component[] = [];
73
+ componentNames.forEach((c) => {
74
+ if (findComponent(c)) {
75
+ found.push(findComponent(c)!);
76
+ }
77
+ });
78
+ // check if the found components depends on other components and add them to the list
79
+ for (let i = 0; i < found.length; i++) {
80
+ const component = found[i];
81
+ if (component.components) {
82
+ for (let j = 0; j < component.components.length; j++) {
83
+ const comp = component.components[j];
84
+ if (!found.find((c) => c.value === comp)) {
85
+ found.push(findComponent(comp)!);
86
+ }
87
+ }
88
+ }
89
+ }
90
+
91
+ // add the components & files associated with them
92
+ for (let i = 0; i < found.length; i++) {
93
+ const component = found[i];
94
+ loop2: for (let k = 0; k < component.files.length; k++) {
95
+ const file = component.files[k];
96
+ let fileName = file.fileName;
97
+ let dirPath = uiConfig.componentsLocation;
98
+ let filePath = path.join(currentDirectory, dirPath, fileName);
99
+ if (!uiConfig.useDefaultFilename) {
100
+ const res = await prompts({
101
+ type: "text",
102
+ name: "value",
103
+ message: `Where should we add the file`,
104
+ initial: dirPath,
105
+ onRender(kleur) {
106
+ //@ts-ignore
107
+ this.msg =
108
+ kleur.bgCyan(" Location ") +
109
+ ` Where should we add the file ${kleur.cyan(`${fileName}`)} `;
110
+ },
111
+ });
112
+ if (res.value) {
113
+ dirPath = res.value;
114
+ filePath = path.join(currentDirectory, res.value, fileName);
115
+ }
116
+ }
117
+ // Check if the file exists
118
+ const exists = await fileExists(filePath);
119
+ // if it exists & the force option was not passed, ask the user to confirm overwriting the file
120
+ if (exists && !uiConfig.force) {
121
+ const res = await prompts({
122
+ type: "confirm",
123
+ name: "value",
124
+ message: `The file that we are trying to add ${kleur.bold(
125
+ fileName
126
+ )} to is already taken. Overwrite?`,
127
+ initial: false,
128
+ });
129
+ if (!res.value) {
130
+ consola.info(`We will not overwrite the file for ${kleur.cyan(fileName)}`);
131
+ continue loop2;
132
+ }
133
+ }
134
+ await writeFile(filePath, file.fileContent);
135
+
136
+ // @not-scalable
137
+ if (component.value === "vue-sonner") {
138
+ // Update the nuxt config
139
+ cfg.defaultExport.imports ||= {};
140
+ cfg.defaultExport.build ||= {};
141
+ cfg.defaultExport.imports.imports ||= [];
142
+ cfg.defaultExport.build.transpile ||= [];
143
+ const sonnerExists = cfg.defaultExport.imports.imports.find(
144
+ (i: any) => i.from === "vue-sonner" && i.name === "toast"
145
+ );
146
+ if (!sonnerExists) {
147
+ cfg.defaultExport.imports.imports.push({
148
+ from: "vue-sonner",
149
+ name: "toast",
150
+ as: "useSonner",
151
+ });
152
+ }
153
+ const transpileExists = cfg.defaultExport.build.transpile.find((i: any) => "vue-sonner");
154
+ if (!transpileExists) {
155
+ cfg.defaultExport.build.transpile.push("vue-sonner");
156
+ }
157
+ }
158
+ // @not-scalable
159
+ if (component.value === "datatable") {
160
+ cfg.defaultExport.app ||= {};
161
+ cfg.defaultExport.app.head ||= {};
162
+ cfg.defaultExport.app.head.script ||= [];
163
+ const scriptOneExists = cfg.defaultExport.app.head.script.find(
164
+ (i: any) =>
165
+ i.src === "https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.9/pdfmake.min.js"
166
+ );
167
+ if (!scriptOneExists) {
168
+ cfg.defaultExport.app.head.script.push({
169
+ src: "https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.9/pdfmake.min.js",
170
+ defer: true,
171
+ });
172
+ }
173
+ const scriptTwoExists = cfg.defaultExport.app.head.script.find(
174
+ (i: any) =>
175
+ i.src === "https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.9/vfs_fonts.min.js"
176
+ );
177
+ if (!scriptTwoExists) {
178
+ cfg.defaultExport.app.head.script.push({
179
+ src: "https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.9/vfs_fonts.min.js",
180
+ defer: true,
181
+ });
182
+ }
183
+ // Get package.json and add the overrides
184
+ const packageJson = readFileSync(path.join(currentDirectory, "package.json"), "utf-8");
185
+ // if no package.json file, do nothing
186
+ if (packageJson) {
187
+ const parsedPackageJson = JSON.parse(packageJson);
188
+ parsedPackageJson.overrides = defu(
189
+ {},
190
+ parsedPackageJson.overrides,
191
+ component.overrides
192
+ );
193
+ await writeFile(
194
+ path.join(currentDirectory, "package.json"),
195
+ JSON.stringify(parsedPackageJson, null, 2)
196
+ );
197
+ }
198
+ }
199
+
200
+ // add utils attached to the component
201
+ loop3: for (let j = 0; j < component.utils.length; j++) {
202
+ const util = component.utils[j];
203
+ const filePath = path.join(currentDirectory, uiConfig.utilsLocation, util.fileName);
204
+ // Check if the file exists
205
+ const exists = await fileExists(filePath);
206
+ if (exists && !uiConfig.force) {
207
+ const res = await prompts({
208
+ type: "confirm",
209
+ name: "value",
210
+ message: `The utils file that we are trying to add ${kleur.bold(
211
+ util.fileName
212
+ )} already exists. Overwrite?`,
213
+ initial: true,
214
+ });
215
+ if (!res.value) {
216
+ consola.info(`We will not overwrite the file for ${kleur.cyan(util.fileName)}`);
217
+ continue loop3;
218
+ }
219
+ }
220
+ await writeFile(filePath, util.fileContent);
221
+ }
222
+ // add composables attached to the component
223
+ loop4: for (let j = 0; j < component.composables.length; j++) {
224
+ const composable = component.composables[j];
225
+ const filePath = path.join(
226
+ currentDirectory,
227
+ uiConfig.composablesLocation,
228
+ composable.fileName
229
+ );
230
+ // Check if the file exists
231
+ const exists = await fileExists(filePath);
232
+ if (exists && !uiConfig.force) {
233
+ const res = await prompts({
234
+ type: "confirm",
235
+ name: "value",
236
+ message: `The composables file that we are trying to add ${kleur.bold(
237
+ composable.fileName
238
+ )} already exists. Overwrite?`,
239
+ initial: true,
240
+ });
241
+ if (!res.value) {
242
+ consola.info(`We will not overwrite the file for ${kleur.cyan(composable.fileName)}`);
243
+ continue loop4;
244
+ }
245
+ }
246
+ await writeFile(filePath, composable.fileContent);
247
+ }
248
+ // add plugins attached to the component
249
+ loop5: for (let j = 0; j < component.plugins.length; j++) {
250
+ const plugin = component.plugins[j];
251
+ const filePath = path.join(currentDirectory, plugin.dirPath, plugin.fileName);
252
+ // Check if the file exists
253
+ const exists = await fileExists(filePath);
254
+ if (exists && !uiConfig.force) {
255
+ const res = await prompts({
256
+ type: "confirm",
257
+ name: "value",
258
+ message: `The plugins file that we are trying to add ${kleur.bold(
259
+ plugin.fileName
260
+ )} already exists. Overwrite?`,
261
+ initial: true,
262
+ });
263
+ if (!res.value) {
264
+ consola.info(`We will not overwrite the file for ${kleur.cyan(plugin.fileName)}`);
265
+ continue loop5;
266
+ }
267
+ }
268
+ await writeFile(filePath, plugin.fileContent);
269
+ }
270
+ }
271
+ }
272
+ // Add modules to nuxt config
273
+ addModuleToConfig(cfg.nuxtConfig, _.uniq(found.map((c) => c.nuxtModules || []).flat()));
274
+ // Write the changes to the nuxt config
275
+ await updateConfig(cfg.nuxtConfig, "nuxt.config.ts");
276
+ const foundDeps = _.uniq(found.map((c) => c.deps || []).flat());
277
+ const foundDevDeps = _.uniq(found.map((c) => c.devDeps || []).flat());
278
+
279
+ // check if the foundDeps & foundDevDeps lists are not empty, ask the user to install them
280
+ if (foundDeps.length > 0 || foundDevDeps.length > 0) {
281
+ // if the all option was passed, install the packages without asking
282
+ if (options.all) {
283
+ await installPackages(uiConfig.packageManager, foundDeps, foundDevDeps);
284
+ } else {
285
+ // Ask the user to install the packages
286
+ const { confirmInstall } = await prompts({
287
+ type: "confirm",
288
+ name: "confirmInstall",
289
+ message: `Do you want to install the following packages: ${kleur.cyan(
290
+ foundDeps.join(", ")
291
+ )} ${kleur.cyan(foundDevDeps.join(", "))}`,
292
+ initial: true,
293
+ });
294
+ if (confirmInstall) {
295
+ await installPackages(uiConfig.packageManager, foundDeps, foundDevDeps);
296
+ }
297
+ }
298
+ }
299
+
300
+ printFancyBoxMessage(
301
+ "All Done!",
302
+ { title: "Components Added" },
303
+ `Run the ${kleur.cyan("ui-thing@latest --help")} command to learn more.\n`
304
+ );
305
+ const combinedInstructions = found.map((c) => c.instructions).flat();
306
+ // remove undefined from the array
307
+ _.remove(combinedInstructions, (i) => !i);
308
+
309
+ // print the instructions if there are any
310
+ if (combinedInstructions.length > 0) {
311
+ console.log("");
312
+ console.log(kleur.bgCyan(" Instructions "));
313
+ combinedInstructions.forEach((i) => {
314
+ console.log(`${kleur.cyan("-")} ${i}`);
315
+ });
316
+ }
317
+ });