@mayrlabs/setup-project 0.1.7 → 0.1.9

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/dist/index.mjs CHANGED
@@ -29,6 +29,262 @@ var init_esm_shims = __esm({
29
29
  }
30
30
  });
31
31
 
32
+ // src/utils/prompts/clack.ts
33
+ import {
34
+ intro,
35
+ outro,
36
+ text,
37
+ confirm,
38
+ select,
39
+ multiselect,
40
+ note,
41
+ isCancel,
42
+ cancel,
43
+ log
44
+ } from "@clack/prompts";
45
+ var ClackProvider;
46
+ var init_clack = __esm({
47
+ "src/utils/prompts/clack.ts"() {
48
+ "use strict";
49
+ init_esm_shims();
50
+ ClackProvider = class {
51
+ intro(message) {
52
+ intro(message);
53
+ }
54
+ outro(message) {
55
+ outro(message);
56
+ }
57
+ async text(opts) {
58
+ return text(opts);
59
+ }
60
+ async confirm(opts) {
61
+ return confirm(opts);
62
+ }
63
+ async select(opts) {
64
+ return select({
65
+ message: opts.message,
66
+ options: opts.options.map((o) => ({
67
+ label: o.label,
68
+ value: o.value,
69
+ hint: o.hint
70
+ }))
71
+ });
72
+ }
73
+ async multiselect(opts) {
74
+ return multiselect({
75
+ message: opts.message,
76
+ options: opts.options.map((o) => ({
77
+ label: o.label,
78
+ value: o.value,
79
+ hint: o.hint
80
+ }))
81
+ });
82
+ }
83
+ note(message, title) {
84
+ note(message, title);
85
+ }
86
+ isCancel(value) {
87
+ return isCancel(value);
88
+ }
89
+ cancel(message) {
90
+ cancel(message);
91
+ }
92
+ log = {
93
+ message: (msg) => log.message(msg),
94
+ info: (msg) => log.info(msg),
95
+ success: (msg) => log.success(msg),
96
+ warn: (msg) => log.warn(msg),
97
+ error: (msg) => log.error(msg)
98
+ };
99
+ };
100
+ }
101
+ });
102
+
103
+ // src/utils/prompts/top.ts
104
+ import { confirm as confirm2, question, select as select2, multiselect as multiselect2 } from "@topcli/prompts";
105
+ import pc from "picocolors";
106
+ var CANCEL_SYMBOL, TopCliProvider;
107
+ var init_top = __esm({
108
+ "src/utils/prompts/top.ts"() {
109
+ "use strict";
110
+ init_esm_shims();
111
+ CANCEL_SYMBOL = /* @__PURE__ */ Symbol("cancel");
112
+ TopCliProvider = class {
113
+ intro(message) {
114
+ console.log(pc.bgCyan(pc.black(` ${message} `)));
115
+ }
116
+ outro(message) {
117
+ console.log(pc.bgCyan(pc.black(` ${message} `)));
118
+ }
119
+ async text(opts) {
120
+ try {
121
+ return await question(opts.message, {
122
+ defaultValue: opts.initialValue || opts.defaultValue,
123
+ validators: [
124
+ {
125
+ validate: (value) => opts.validate?.(value) || ""
126
+ }
127
+ ]
128
+ });
129
+ } catch {
130
+ return CANCEL_SYMBOL;
131
+ }
132
+ }
133
+ async confirm(opts) {
134
+ try {
135
+ return await confirm2(opts.message, {
136
+ initial: opts.initialValue
137
+ });
138
+ } catch {
139
+ return CANCEL_SYMBOL;
140
+ }
141
+ }
142
+ async select(opts) {
143
+ try {
144
+ const optionMap = /* @__PURE__ */ new Map();
145
+ const choices = opts.options.map((o) => {
146
+ const key = String(o.value);
147
+ optionMap.set(key, o.value);
148
+ const isSelected = opts.initialValue === o.value;
149
+ return {
150
+ label: o.label,
151
+ value: key,
152
+ description: o.hint,
153
+ selected: isSelected
154
+ };
155
+ });
156
+ const resultKey = await select2(opts.message, {
157
+ choices,
158
+ autocomplete: true,
159
+ maxVisible: 10
160
+ });
161
+ return optionMap.get(resultKey);
162
+ } catch {
163
+ return CANCEL_SYMBOL;
164
+ }
165
+ }
166
+ async multiselect(opts) {
167
+ try {
168
+ const optionMap = /* @__PURE__ */ new Map();
169
+ const choices = opts.options.map((o) => {
170
+ const key = String(o.value);
171
+ optionMap.set(key, o.value);
172
+ const isSelected = opts.initialValue?.some((iv) => iv === o.value);
173
+ return {
174
+ label: o.label,
175
+ value: key,
176
+ description: o.hint,
177
+ selected: isSelected
178
+ };
179
+ });
180
+ const resultKeys = await multiselect2(opts.message, {
181
+ choices,
182
+ autocomplete: true,
183
+ maxVisible: 10,
184
+ showHint: true
185
+ });
186
+ return resultKeys.map((k) => optionMap.get(k));
187
+ } catch {
188
+ return CANCEL_SYMBOL;
189
+ }
190
+ }
191
+ note(message, title) {
192
+ if (title) {
193
+ console.log(pc.blue(pc.bold(`${title}`)));
194
+ }
195
+ console.log(pc.dim(message));
196
+ }
197
+ isCancel(value) {
198
+ return value === CANCEL_SYMBOL;
199
+ }
200
+ cancel(message) {
201
+ if (message) console.log(pc.red(pc.bold("\xD7")) + " " + message);
202
+ else console.log(pc.red(pc.bold("\xD7")) + " Operation cancelled.");
203
+ }
204
+ log = {
205
+ message: (msg) => console.log(msg),
206
+ info: (msg) => console.log(pc.blue(pc.bold("INFO")) + " " + msg),
207
+ success: (msg) => console.log(pc.green(pc.bold("SUCCESS")) + " " + msg),
208
+ warn: (msg) => console.log(pc.yellow(pc.bold("WARN")) + " " + msg),
209
+ error: (msg) => console.log(pc.red(pc.bold("ERROR")) + " " + msg)
210
+ };
211
+ };
212
+ }
213
+ });
214
+
215
+ // src/utils/prompts/types.ts
216
+ var init_types = __esm({
217
+ "src/utils/prompts/types.ts"() {
218
+ "use strict";
219
+ init_esm_shims();
220
+ }
221
+ });
222
+
223
+ // src/utils/prompts/index.ts
224
+ var Prompts, prompts;
225
+ var init_prompts = __esm({
226
+ "src/utils/prompts/index.ts"() {
227
+ "use strict";
228
+ init_esm_shims();
229
+ init_clack();
230
+ init_top();
231
+ init_types();
232
+ Prompts = class _Prompts {
233
+ provider;
234
+ static instance;
235
+ constructor() {
236
+ this.provider = new TopCliProvider();
237
+ }
238
+ static getInstance() {
239
+ if (!_Prompts.instance) {
240
+ _Prompts.instance = new _Prompts();
241
+ }
242
+ return _Prompts.instance;
243
+ }
244
+ setProvider(provider) {
245
+ this.provider = provider;
246
+ }
247
+ useClack() {
248
+ this.provider = new ClackProvider();
249
+ }
250
+ useTopCli() {
251
+ this.provider = new TopCliProvider();
252
+ }
253
+ intro(message) {
254
+ this.provider.intro(message);
255
+ }
256
+ outro(message) {
257
+ this.provider.outro(message);
258
+ }
259
+ text(opts) {
260
+ return this.provider.text(opts);
261
+ }
262
+ confirm(opts) {
263
+ return this.provider.confirm(opts);
264
+ }
265
+ select(opts) {
266
+ return this.provider.select(opts);
267
+ }
268
+ multiselect(opts) {
269
+ return this.provider.multiselect(opts);
270
+ }
271
+ note(message, title) {
272
+ this.provider.note(message, title);
273
+ }
274
+ isCancel(value) {
275
+ return this.provider.isCancel(value);
276
+ }
277
+ cancel(message) {
278
+ this.provider.cancel(message);
279
+ }
280
+ get log() {
281
+ return this.provider.log;
282
+ }
283
+ };
284
+ prompts = Prompts.getInstance();
285
+ }
286
+ });
287
+
32
288
  // src/utils/pm.ts
33
289
  import { execa } from "execa";
34
290
  async function getPackageManager() {
@@ -155,102 +411,1479 @@ var init_options = __esm({
155
411
  });
156
412
 
157
413
  // src/utils/handle-cancel.ts
158
- import { cancel, isCancel, confirm } from "@clack/prompts";
159
414
  async function withCancelHandling(promptFn, cancelMessage = "Operation cancelled.") {
160
415
  while (true) {
161
416
  const response = await promptFn();
162
- if (isCancel(response)) {
163
- const shouldCancel = await confirm({
417
+ if (prompts.isCancel(response)) {
418
+ const shouldCancel = await prompts.confirm({
164
419
  message: "Do you really want to cancel options selection?"
165
420
  });
166
- if (isCancel(shouldCancel) || shouldCancel) {
167
- cancel(cancelMessage);
421
+ if (prompts.isCancel(shouldCancel) || shouldCancel) {
422
+ prompts.cancel(cancelMessage);
168
423
  process.exit(0);
169
424
  }
170
- continue;
171
- } else {
172
- return response;
425
+ continue;
426
+ } else {
427
+ return response;
428
+ }
429
+ }
430
+ }
431
+ var init_handle_cancel = __esm({
432
+ "src/utils/handle-cancel.ts"() {
433
+ "use strict";
434
+ init_esm_shims();
435
+ init_prompts();
436
+ }
437
+ });
438
+
439
+ // src/features/husky.ts
440
+ import { execa as execa2 } from "execa";
441
+ import fs from "fs-extra";
442
+ import pc2 from "picocolors";
443
+ async function promptHusky(config2) {
444
+ prompts.log.message(pc2.bgMagenta(pc2.black(" Husky Configuration ")));
445
+ const hookType = await withCancelHandling(
446
+ async () => prompts.select({
447
+ message: "What pre-commit hook would you like to use?",
448
+ options: HUSKY_HOOK_OPTIONS
449
+ })
450
+ );
451
+ const huskyConfig = config2.get("husky");
452
+ huskyConfig.options = { hookType };
453
+ if (hookType === "lintStaged") {
454
+ config2.enableTool("lintStaged");
455
+ } else if (hookType === "custom") {
456
+ const script = await withCancelHandling(
457
+ async () => prompts.text({
458
+ message: "Enter your custom pre-commit script:",
459
+ placeholder: huskyConfig.options.customScript,
460
+ validate(value) {
461
+ if (value.length === 0) return "Value is required!";
462
+ }
463
+ })
464
+ );
465
+ huskyConfig.options.customScript = script;
466
+ }
467
+ }
468
+ async function installHusky(config2) {
469
+ await installPackages(["husky"], true);
470
+ try {
471
+ await execa2("npx", ["husky", "init"]);
472
+ } catch {
473
+ await execa2("npm", ["pkg", "set", "scripts.prepare=husky"]);
474
+ await execa2("npm", ["run", "prepare"]);
475
+ }
476
+ const husky = config2.get("husky");
477
+ const hookType = husky.options.hookType;
478
+ const customScript = husky.options.customScript;
479
+ if (hookType === "lintStaged") {
480
+ await fs.outputFile(".husky/pre-commit", "npx lint-staged\n", {
481
+ mode: 493
482
+ });
483
+ } else if (hookType === "custom" && customScript) {
484
+ await fs.outputFile(".husky/pre-commit", `${customScript}
485
+ `, {
486
+ mode: 493
487
+ });
488
+ }
489
+ }
490
+ var init_husky = __esm({
491
+ "src/features/husky.ts"() {
492
+ "use strict";
493
+ init_esm_shims();
494
+ init_prompts();
495
+ init_pm();
496
+ init_options();
497
+ init_handle_cancel();
498
+ }
499
+ });
500
+
501
+ // src/utils/config-file.ts
502
+ import fs2 from "fs-extra";
503
+ import path2 from "path";
504
+ async function resolveConfigFile(toolName, candidates) {
505
+ for (const file of candidates) {
506
+ if (await fs2.pathExists(file)) return file;
507
+ }
508
+ const response = await withCancelHandling(
509
+ async () => prompts.select({
510
+ message: `Where do you want to store the ${toolName} config?`,
511
+ options: candidates.map((c) => ({ value: c, label: c })),
512
+ initialValue: candidates[0]
513
+ })
514
+ );
515
+ return response;
516
+ }
517
+ async function writeConfig(filePath, config2) {
518
+ const ext = path2.extname(filePath);
519
+ if (ext === ".json" || ext === "") {
520
+ await fs2.writeJson(filePath, config2, { spaces: 2 });
521
+ } else if (ext === ".js" || ext === ".cjs") {
522
+ const content = `module.exports = ${JSON.stringify(config2, null, 2)};`;
523
+ await fs2.writeFile(filePath, content);
524
+ } else if (ext === ".mjs") {
525
+ const content = `export default ${JSON.stringify(config2, null, 2)};`;
526
+ await fs2.writeFile(filePath, content);
527
+ } else {
528
+ await fs2.writeJson(filePath, config2, { spaces: 2 });
529
+ }
530
+ }
531
+ var init_config_file = __esm({
532
+ "src/utils/config-file.ts"() {
533
+ "use strict";
534
+ init_esm_shims();
535
+ init_prompts();
536
+ init_handle_cancel();
537
+ }
538
+ });
539
+
540
+ // src/features/formatter/prettier.ts
541
+ import fs3 from "fs-extra";
542
+ async function installPrettier() {
543
+ await installPackages(["prettier"], true);
544
+ const configFile = await resolveConfigFile("Prettier", [
545
+ ".prettierrc",
546
+ ".prettierrc.json",
547
+ "prettier.config.js",
548
+ ".prettierrc.js"
549
+ ]);
550
+ if (!await fs3.pathExists(configFile)) {
551
+ await writeConfig(configFile, {
552
+ semi: true,
553
+ singleQuote: false,
554
+ tabWidth: 2,
555
+ trailingComma: "es5",
556
+ printWidth: 80,
557
+ plugins: []
558
+ });
559
+ }
560
+ if (!await fs3.pathExists(".prettierignore")) {
561
+ await fs3.writeFile(
562
+ ".prettierignore",
563
+ `node_modules
564
+ dist
565
+ coverage
566
+ .next
567
+ .nuxt
568
+ build
569
+ .astro
570
+ .output
571
+ `
572
+ );
573
+ }
574
+ }
575
+ async function configurePrettierPlugins(plugins) {
576
+ const configFile = await resolveConfigFile("Prettier", [
577
+ ".prettierrc",
578
+ ".prettierrc.json",
579
+ "prettier.config.js",
580
+ ".prettierrc.js"
581
+ ]);
582
+ let currentConfig = {};
583
+ if (await fs3.pathExists(configFile)) {
584
+ try {
585
+ if (configFile.endsWith(".js") || configFile.endsWith(".cjs")) {
586
+ return;
587
+ }
588
+ currentConfig = await fs3.readJson(configFile);
589
+ } catch {
590
+ }
591
+ }
592
+ const existingPlugins = currentConfig.plugins || [];
593
+ const newPlugins = [.../* @__PURE__ */ new Set([...existingPlugins, ...plugins])];
594
+ currentConfig.plugins = newPlugins;
595
+ await writeConfig(configFile, currentConfig);
596
+ }
597
+ var init_prettier = __esm({
598
+ "src/features/formatter/prettier.ts"() {
599
+ "use strict";
600
+ init_esm_shims();
601
+ init_pm();
602
+ init_config_file();
603
+ }
604
+ });
605
+
606
+ // src/features/formatter/oxfmt.ts
607
+ async function installOxfmt() {
608
+ await installPackages(["oxfmt@latest"], true);
609
+ }
610
+ var init_oxfmt = __esm({
611
+ "src/features/formatter/oxfmt.ts"() {
612
+ "use strict";
613
+ init_esm_shims();
614
+ init_pm();
615
+ }
616
+ });
617
+
618
+ // src/constants/plugins.ts
619
+ var ESLINT_PLUGINS, PRETTIER_PLUGINS, PLUGINS, PLUGINABLE_TOOLS;
620
+ var init_plugins = __esm({
621
+ "src/constants/plugins.ts"() {
622
+ "use strict";
623
+ init_esm_shims();
624
+ ESLINT_PLUGINS = [
625
+ // Code Quality
626
+ {
627
+ value: "depend",
628
+ label: "depend",
629
+ package: "eslint-plugin-depend",
630
+ hint: "Detect junk dependencies"
631
+ },
632
+ {
633
+ value: "github",
634
+ label: "github",
635
+ package: "eslint-plugin-github",
636
+ hint: "GitHub's ESLint rules"
637
+ },
638
+ {
639
+ value: "sonarjs",
640
+ label: "sonarjs",
641
+ package: "eslint-plugin-sonarjs",
642
+ hint: "Detect bugs and suspicious patterns"
643
+ },
644
+ {
645
+ value: "unicorn",
646
+ label: "unicorn",
647
+ package: "eslint-plugin-unicorn",
648
+ hint: "Various awesome ESLint rules"
649
+ },
650
+ {
651
+ value: "mysticatea",
652
+ label: "mysticatea",
653
+ package: "@mysticatea/eslint-plugin",
654
+ hint: "Misc rules"
655
+ },
656
+ {
657
+ value: "brettz9",
658
+ label: "brettz9",
659
+ package: "@brettz9/eslint-plugin",
660
+ hint: "Misc rules without personal config"
661
+ },
662
+ {
663
+ value: "de-morgan",
664
+ label: "de-morgan",
665
+ package: "eslint-plugin-de-morgan",
666
+ hint: "Transform logical expressions"
667
+ },
668
+ {
669
+ value: "code-complete",
670
+ label: "code-complete",
671
+ package: "eslint-plugin-code-complete",
672
+ hint: "Clean, maintainable software design"
673
+ },
674
+ // Compatibility
675
+ {
676
+ value: "compat",
677
+ label: "compat",
678
+ package: "eslint-plugin-compat",
679
+ hint: "Browser compatibility checking"
680
+ },
681
+ {
682
+ value: "es-compat",
683
+ label: "es-compat",
684
+ package: "eslint-plugin-es-compat",
685
+ hint: "Disable unsupported ES features"
686
+ },
687
+ {
688
+ value: "es-x",
689
+ label: "es-x",
690
+ package: "eslint-plugin-es-x",
691
+ hint: "Disable specific ES versions"
692
+ },
693
+ {
694
+ value: "es5",
695
+ label: "es5",
696
+ package: "eslint-plugin-es5",
697
+ hint: "Forbid ES2015+ usage"
698
+ },
699
+ {
700
+ value: "ie11",
701
+ label: "ie11",
702
+ package: "eslint-plugin-ie11",
703
+ hint: "Detect unsupported ES6 features in IE11"
704
+ },
705
+ // CSS in JS
706
+ {
707
+ value: "css-modules",
708
+ label: "css-modules",
709
+ package: "eslint-plugin-css-modules",
710
+ hint: "Lint css modules"
711
+ },
712
+ {
713
+ value: "emotion",
714
+ label: "emotion",
715
+ package: "@emotion/eslint-plugin",
716
+ hint: "Rules for emotion"
717
+ },
718
+ {
719
+ value: "better-styled-components",
720
+ label: "better-styled-components",
721
+ package: "eslint-plugin-better-styled-components",
722
+ hint: "Auto fixable rules for styled components"
723
+ },
724
+ {
725
+ value: "styled-components-a11y",
726
+ label: "styled-components-a11y",
727
+ package: "eslint-plugin-styled-components-a11y",
728
+ hint: "A11y for Styled Components"
729
+ },
730
+ {
731
+ value: "vanilla-extract",
732
+ label: "vanilla-extract",
733
+ package: "@vanilla-extract/eslint-plugin",
734
+ hint: "Enforce CSS property ordering"
735
+ },
736
+ // Deprecation
737
+ {
738
+ value: "deprecate",
739
+ label: "deprecate",
740
+ package: "eslint-plugin-deprecate",
741
+ hint: "Mark functions/modules as deprecated"
742
+ },
743
+ {
744
+ value: "disable",
745
+ label: "disable",
746
+ package: "eslint-plugin-disable",
747
+ hint: "Disable plugins using patterns"
748
+ },
749
+ // Embedded
750
+ {
751
+ value: "html",
752
+ label: "html",
753
+ package: "eslint-plugin-html",
754
+ hint: "Linting JS inside HTML"
755
+ },
756
+ {
757
+ value: "markdown",
758
+ label: "markdown",
759
+ package: "eslint-plugin-markdown",
760
+ hint: "Linting JS inside Markdown"
761
+ },
762
+ // Frameworks
763
+ {
764
+ value: "angular",
765
+ label: "angular",
766
+ package: "@angular-eslint/eslint-plugin",
767
+ hint: "Linting for Angular"
768
+ },
769
+ {
770
+ value: "angularjs",
771
+ label: "angularjs",
772
+ package: "eslint-plugin-angular",
773
+ hint: "Linting for AngularJS"
774
+ },
775
+ {
776
+ value: "astro",
777
+ label: "astro",
778
+ package: "eslint-plugin-astro",
779
+ hint: "Linting for Astro"
780
+ },
781
+ {
782
+ value: "backbone",
783
+ label: "backbone",
784
+ package: "eslint-plugin-backbone",
785
+ hint: "Linting for Backbone"
786
+ },
787
+ {
788
+ value: "ember",
789
+ label: "ember",
790
+ package: "eslint-plugin-ember",
791
+ hint: "Linting for Ember"
792
+ },
793
+ {
794
+ value: "hapi",
795
+ label: "hapi",
796
+ package: "eslint-plugin-hapi",
797
+ hint: "Linting for Hapi"
798
+ },
799
+ {
800
+ value: "meteor",
801
+ label: "meteor",
802
+ package: "eslint-plugin-meteor",
803
+ hint: "Linting for Meteor"
804
+ },
805
+ {
806
+ value: "jsx-a11y",
807
+ label: "jsx-a11y",
808
+ package: "eslint-plugin-jsx-a11y",
809
+ hint: "Accessibility rules on JSX"
810
+ },
811
+ {
812
+ value: "react",
813
+ label: "react",
814
+ package: "eslint-plugin-react",
815
+ hint: "Linting for React/JSX"
816
+ },
817
+ {
818
+ value: "react-hooks",
819
+ label: "react-hooks",
820
+ package: "eslint-plugin-react-hooks",
821
+ hint: "Linting for React Hooks"
822
+ },
823
+ {
824
+ value: "react-native",
825
+ label: "react-native",
826
+ package: "eslint-plugin-react-native",
827
+ hint: "React Native specific rules"
828
+ },
829
+ {
830
+ value: "react-redux",
831
+ label: "react-redux",
832
+ package: "eslint-plugin-react-redux",
833
+ hint: "React-Redux specific rules"
834
+ },
835
+ {
836
+ value: "react-refresh",
837
+ label: "react-refresh",
838
+ package: "eslint-plugin-react-refresh",
839
+ hint: "Improve HMR with Vite"
840
+ },
841
+ {
842
+ value: "solid",
843
+ label: "solid",
844
+ package: "eslint-plugin-solid",
845
+ hint: "Linting for Solid"
846
+ },
847
+ {
848
+ value: "svelte",
849
+ label: "svelte",
850
+ package: "eslint-plugin-svelte",
851
+ hint: "Linting for Svelte"
852
+ },
853
+ {
854
+ value: "vuejs",
855
+ label: "vuejs",
856
+ package: "eslint-plugin-vue",
857
+ hint: "Linting for VueJS"
858
+ },
859
+ {
860
+ value: "vue-scoped-css",
861
+ label: "vue-scoped-css",
862
+ package: "eslint-plugin-vue-scoped-css",
863
+ hint: "Scoped CSS in VueJS"
864
+ },
865
+ // Languages and Environments
866
+ {
867
+ value: "babel",
868
+ label: "babel",
869
+ package: "@babel/eslint-plugin",
870
+ hint: "Babel features"
871
+ },
872
+ {
873
+ value: "flowtype",
874
+ label: "flowtype",
875
+ package: "eslint-plugin-flowtype",
876
+ hint: "Flow type linting"
877
+ },
878
+ {
879
+ value: "flowtype-errors",
880
+ label: "flowtype-errors",
881
+ package: "eslint-plugin-flowtype-errors",
882
+ hint: "Run Flow as plugin"
883
+ },
884
+ {
885
+ value: "html-eslint",
886
+ label: "html-eslint",
887
+ package: "@html-eslint/eslint-plugin",
888
+ hint: "Linting for HTML"
889
+ },
890
+ {
891
+ value: "json",
892
+ label: "json",
893
+ package: "eslint-plugin-json",
894
+ hint: "Lint JSON files"
895
+ },
896
+ {
897
+ value: "json-format",
898
+ label: "json-format",
899
+ package: "eslint-plugin-json-format",
900
+ hint: "Lint/Format/Fix JSON"
901
+ },
902
+ {
903
+ value: "jsonc",
904
+ label: "jsonc",
905
+ package: "eslint-plugin-jsonc",
906
+ hint: "JSON with comments"
907
+ },
908
+ {
909
+ value: "json-schema-validator",
910
+ label: "json-schema-validator",
911
+ package: "eslint-plugin-json-schema-validator",
912
+ hint: "Validate data using JSON Schema"
913
+ },
914
+ {
915
+ value: "package-json",
916
+ label: "package-json",
917
+ package: "eslint-plugin-package-json",
918
+ hint: "Rules for package.json"
919
+ },
920
+ {
921
+ value: "mdx",
922
+ label: "mdx",
923
+ package: "eslint-plugin-mdx",
924
+ hint: "Lint MDX"
925
+ },
926
+ { value: "n", label: "n", package: "eslint-plugin-n", hint: "Node.js rules" },
927
+ {
928
+ value: "sql",
929
+ label: "sql",
930
+ package: "eslint-plugin-sql",
931
+ hint: "SQL linting"
932
+ },
933
+ {
934
+ value: "toml",
935
+ label: "toml",
936
+ package: "eslint-plugin-toml",
937
+ hint: "Lint TOML"
938
+ },
939
+ {
940
+ value: "typescript",
941
+ label: "typescript",
942
+ package: "@typescript-eslint/eslint-plugin",
943
+ hint: "Lint TypeScript"
944
+ },
945
+ {
946
+ value: "erasable-syntax-only",
947
+ label: "erasable-syntax-only",
948
+ package: "eslint-plugin-erasable-syntax-only",
949
+ hint: "Enforce TS erasableSyntaxOnly"
950
+ },
951
+ {
952
+ value: "expect-type",
953
+ label: "expect-type",
954
+ package: "eslint-plugin-expect-type",
955
+ hint: "Type assertions"
956
+ },
957
+ {
958
+ value: "yaml",
959
+ label: "yaml",
960
+ package: "eslint-plugin-yml",
961
+ hint: "Lint YAML"
962
+ },
963
+ // Libraries
964
+ {
965
+ value: "graphql",
966
+ label: "graphql",
967
+ package: "@graphql-eslint/eslint-plugin",
968
+ hint: "Validate GraphQL operations/schema"
969
+ },
970
+ {
971
+ value: "graphql-schema",
972
+ label: "graphql-schema",
973
+ package: "eslint-plugin-graphql",
974
+ hint: "Check GraphQL queries against schema"
975
+ },
976
+ {
977
+ value: "type-graphql",
978
+ label: "type-graphql",
979
+ package: "eslint-plugin-type-graphql",
980
+ hint: "Lint TypeGraphQL"
981
+ },
982
+ {
983
+ value: "jquery",
984
+ label: "jquery",
985
+ package: "eslint-plugin-no-jquery",
986
+ hint: "Lint jQuery (deprecated features)"
987
+ },
988
+ {
989
+ value: "jsdoc",
990
+ label: "jsdoc",
991
+ package: "eslint-plugin-jsdoc",
992
+ hint: "Lint JSDoc comments"
993
+ },
994
+ {
995
+ value: "lodash",
996
+ label: "lodash",
997
+ package: "eslint-plugin-lodash",
998
+ hint: "Lodash rules"
999
+ },
1000
+ {
1001
+ value: "lodash-fp",
1002
+ label: "lodash-fp",
1003
+ package: "eslint-plugin-lodash-fp",
1004
+ hint: "Lodash/fp rules"
1005
+ },
1006
+ {
1007
+ value: "lodash-template",
1008
+ label: "lodash-template",
1009
+ package: "eslint-plugin-lodash-template",
1010
+ hint: "Lodash template rules"
1011
+ },
1012
+ {
1013
+ value: "microtemplates",
1014
+ label: "microtemplates",
1015
+ package: "eslint-plugin-microtemplates",
1016
+ hint: "Microtemplates rules"
1017
+ },
1018
+ {
1019
+ value: "mongodb",
1020
+ label: "mongodb",
1021
+ package: "eslint-plugin-mongodb",
1022
+ hint: "MongoDB driver rules"
1023
+ },
1024
+ {
1025
+ value: "ramda",
1026
+ label: "ramda",
1027
+ package: "eslint-plugin-ramda",
1028
+ hint: "Ramda rules"
1029
+ },
1030
+ {
1031
+ value: "requirejs",
1032
+ label: "requirejs",
1033
+ package: "eslint-plugin-requirejs",
1034
+ hint: "RequireJS rules"
1035
+ },
1036
+ {
1037
+ value: "tailwindcss",
1038
+ label: "tailwindcss",
1039
+ package: "eslint-plugin-tailwindcss",
1040
+ hint: "Tailwind CSS rules"
1041
+ },
1042
+ {
1043
+ value: "better-tailwindcss",
1044
+ label: "better-tailwindcss",
1045
+ package: "eslint-plugin-better-tailwindcss",
1046
+ hint: "Improve readability/best practices"
1047
+ },
1048
+ // Misc
1049
+ {
1050
+ value: "diff",
1051
+ label: "diff",
1052
+ package: "eslint-plugin-diff",
1053
+ hint: "Lint changed lines only"
1054
+ },
1055
+ {
1056
+ value: "misc",
1057
+ label: "misc",
1058
+ package: "eslint-plugin-misc",
1059
+ hint: "Miscellaneous rules"
1060
+ },
1061
+ {
1062
+ value: "notice",
1063
+ label: "notice",
1064
+ package: "eslint-plugin-notice",
1065
+ hint: "Check top of files"
1066
+ },
1067
+ {
1068
+ value: "only-error",
1069
+ label: "only-error",
1070
+ package: "eslint-plugin-only-error",
1071
+ hint: "Convert all rules to errors"
1072
+ },
1073
+ {
1074
+ value: "only-warn",
1075
+ label: "only-warn",
1076
+ package: "eslint-plugin-only-warn",
1077
+ hint: "Convert all rules to warnings"
1078
+ },
1079
+ {
1080
+ value: "putout",
1081
+ label: "putout",
1082
+ package: "eslint-plugin-putout",
1083
+ hint: "Integrate PutOut linter"
1084
+ },
1085
+ {
1086
+ value: "typelint",
1087
+ label: "typelint",
1088
+ package: "eslint-plugin-typelint",
1089
+ hint: "Introduce types based on schemas"
1090
+ },
1091
+ {
1092
+ value: "woke",
1093
+ label: "woke",
1094
+ package: "eslint-plugin-woke",
1095
+ hint: "Catch insensitive words"
1096
+ },
1097
+ // Practices and Specific ES Features
1098
+ {
1099
+ value: "array-func",
1100
+ label: "array-func",
1101
+ package: "eslint-plugin-array-func",
1102
+ hint: "Avoid redundancy with array methods"
1103
+ },
1104
+ {
1105
+ value: "proper-arrows",
1106
+ label: "proper-arrows",
1107
+ package: "eslint-plugin-proper-arrows",
1108
+ hint: "Ensure proper arrow function definitions"
1109
+ },
1110
+ {
1111
+ value: "boundaries",
1112
+ label: "boundaries",
1113
+ package: "eslint-plugin-boundaries",
1114
+ hint: "Enforce architecture boundaries"
1115
+ },
1116
+ {
1117
+ value: "eslint-comments",
1118
+ label: "eslint-comments",
1119
+ package: "eslint-plugin-eslint-comments",
1120
+ hint: "Best practices for ESLint directives"
1121
+ },
1122
+ {
1123
+ value: "error-cause",
1124
+ label: "error-cause",
1125
+ package: "eslint-plugin-error-cause",
1126
+ hint: "Preserve error context"
1127
+ },
1128
+ {
1129
+ value: "hexagonal-architecture",
1130
+ label: "hexagonal-architecture",
1131
+ package: "eslint-plugin-hexagonal-architecture",
1132
+ hint: "Hexagonal architecture best practices"
1133
+ },
1134
+ {
1135
+ value: "signature-design",
1136
+ label: "signature-design",
1137
+ package: "eslint-plugin-signature-design",
1138
+ hint: "Enforce object-based signatures"
1139
+ },
1140
+ {
1141
+ value: "write-good-comments",
1142
+ label: "write-good-comments",
1143
+ package: "eslint-plugin-write-good-comments",
1144
+ hint: "Enforce good comment style"
1145
+ },
1146
+ {
1147
+ value: "exception-handling",
1148
+ label: "exception-handling",
1149
+ package: "eslint-plugin-exception-handling",
1150
+ hint: "Lint unhandled exceptions"
1151
+ },
1152
+ {
1153
+ value: "fp",
1154
+ label: "fp",
1155
+ package: "eslint-plugin-fp",
1156
+ hint: "Functional programming rules"
1157
+ },
1158
+ {
1159
+ value: "functional",
1160
+ label: "functional",
1161
+ package: "eslint-plugin-functional",
1162
+ hint: "Disable mutation, promote FP"
1163
+ },
1164
+ {
1165
+ value: "mutate",
1166
+ label: "mutate",
1167
+ package: "eslint-plugin-mutate",
1168
+ hint: "Prevent accidental mutations"
1169
+ },
1170
+ {
1171
+ value: "immutable",
1172
+ label: "immutable",
1173
+ package: "eslint-plugin-immutable",
1174
+ hint: "Disable all mutation"
1175
+ },
1176
+ {
1177
+ value: "import",
1178
+ label: "import",
1179
+ package: "eslint-plugin-import",
1180
+ hint: "Lint import/export syntax"
1181
+ },
1182
+ {
1183
+ value: "import-x",
1184
+ label: "import-x",
1185
+ package: "eslint-plugin-import-x",
1186
+ hint: "Lightweight fork of eslint-plugin-import"
1187
+ },
1188
+ {
1189
+ value: "math",
1190
+ label: "math",
1191
+ package: "eslint-plugin-math",
1192
+ hint: "Math object rules"
1193
+ },
1194
+ {
1195
+ value: "new-with-error",
1196
+ label: "new-with-error",
1197
+ package: "eslint-plugin-new-with-error",
1198
+ hint: "Require new with Error"
1199
+ },
1200
+ {
1201
+ value: "no-argument-spread",
1202
+ label: "no-argument-spread",
1203
+ package: "eslint-plugin-no-argument-spread",
1204
+ hint: "Lint against spread arguments"
1205
+ },
1206
+ {
1207
+ value: "no-comments",
1208
+ label: "no-comments",
1209
+ package: "eslint-plugin-no-comments",
1210
+ hint: "Prevent leaking comments"
1211
+ },
1212
+ {
1213
+ value: "no-constructor-bind",
1214
+ label: "no-constructor-bind",
1215
+ package: "eslint-plugin-no-constructor-bind",
1216
+ hint: "Encourage class properties"
1217
+ },
1218
+ {
1219
+ value: "no-inferred-method-name",
1220
+ label: "no-inferred-method-name",
1221
+ package: "eslint-plugin-no-inferred-method-name",
1222
+ hint: "Check inferred method names"
1223
+ },
1224
+ {
1225
+ value: "no-loops",
1226
+ label: "no-loops",
1227
+ package: "eslint-plugin-no-loops",
1228
+ hint: "Disallow loops"
1229
+ },
1230
+ {
1231
+ value: "query",
1232
+ label: "query",
1233
+ package: "eslint-plugin-query",
1234
+ hint: "Show queried syntax content"
1235
+ },
1236
+ {
1237
+ value: "no-use-extend-native",
1238
+ label: "no-use-extend-native",
1239
+ package: "eslint-plugin-no-use-extend-native",
1240
+ hint: "Prevent using extended native objects"
1241
+ },
1242
+ {
1243
+ value: "promise",
1244
+ label: "promise",
1245
+ package: "eslint-plugin-promise",
1246
+ hint: "Promise best practices"
1247
+ },
1248
+ {
1249
+ value: "pure",
1250
+ label: "pure",
1251
+ package: "eslint-plugin-pure",
1252
+ hint: "Enforce pure functions"
1253
+ },
1254
+ {
1255
+ value: "redos",
1256
+ label: "redos",
1257
+ package: "eslint-plugin-redos",
1258
+ hint: "Find ReDoS vulnerabilities"
1259
+ },
1260
+ {
1261
+ value: "redos-detector",
1262
+ label: "redos-detector",
1263
+ package: "eslint-plugin-redos-detector",
1264
+ hint: "Find ReDoS vulnerabilities"
1265
+ },
1266
+ {
1267
+ value: "regexp",
1268
+ label: "regexp",
1269
+ package: "eslint-plugin-regexp",
1270
+ hint: "Find regexp mistakes"
1271
+ },
1272
+ {
1273
+ value: "sort-keys-fix",
1274
+ label: "sort-keys-fix",
1275
+ package: "eslint-plugin-sort-keys-fix",
1276
+ hint: "Fixer for sort-keys"
1277
+ },
1278
+ {
1279
+ value: "this",
1280
+ label: "this",
1281
+ package: "eslint-plugin-this",
1282
+ hint: "Disallow this"
1283
+ },
1284
+ {
1285
+ value: "toplevel",
1286
+ label: "toplevel",
1287
+ package: "eslint-plugin-toplevel",
1288
+ hint: "Disallow side effects at top level"
1289
+ },
1290
+ // Performance
1291
+ {
1292
+ value: "dom",
1293
+ label: "dom",
1294
+ package: "eslint-plugin-dom",
1295
+ hint: "DOM performance"
1296
+ },
1297
+ {
1298
+ value: "optimize-regex",
1299
+ label: "optimize-regex",
1300
+ package: "eslint-plugin-optimize-regex",
1301
+ hint: "Optimize regex literals"
1302
+ },
1303
+ {
1304
+ value: "perf-standard",
1305
+ label: "perf-standard",
1306
+ package: "eslint-plugin-perf-standard",
1307
+ hint: "Performance standard rules"
1308
+ },
1309
+ // Security
1310
+ {
1311
+ value: "no-secrets",
1312
+ label: "no-secrets",
1313
+ package: "eslint-plugin-no-secrets",
1314
+ hint: "Detect potential secrets"
1315
+ },
1316
+ {
1317
+ value: "no-unsanitized",
1318
+ label: "no-unsanitized",
1319
+ package: "eslint-plugin-no-unsanitized",
1320
+ hint: "Checks for innerHTML etc"
1321
+ },
1322
+ {
1323
+ value: "pii",
1324
+ label: "pii",
1325
+ package: "eslint-plugin-pii",
1326
+ hint: "Enforce PII compliance"
1327
+ },
1328
+ {
1329
+ value: "pg",
1330
+ label: "pg",
1331
+ package: "eslint-plugin-pg",
1332
+ hint: "PostgreSQL security"
1333
+ },
1334
+ {
1335
+ value: "security",
1336
+ label: "security",
1337
+ package: "eslint-plugin-security",
1338
+ hint: "Node Security rules"
1339
+ },
1340
+ {
1341
+ value: "xss",
1342
+ label: "xss",
1343
+ package: "eslint-plugin-xss",
1344
+ hint: "Detect XSS issues"
1345
+ },
1346
+ // Style
1347
+ {
1348
+ value: "stylistic",
1349
+ label: "stylistic",
1350
+ package: "@stylistic/eslint-plugin",
1351
+ hint: "Formatting and stylistic rules"
1352
+ },
1353
+ {
1354
+ value: "const-case",
1355
+ label: "const-case",
1356
+ package: "eslint-plugin-const-case",
1357
+ hint: "Enforce capitalization of constants"
1358
+ },
1359
+ {
1360
+ value: "editorconfig",
1361
+ label: "editorconfig",
1362
+ package: "eslint-plugin-editorconfig",
1363
+ hint: "Derive rules from .editorconfig"
1364
+ },
1365
+ {
1366
+ value: "simple-import-sort",
1367
+ label: "simple-import-sort",
1368
+ package: "eslint-plugin-simple-import-sort",
1369
+ hint: "Easy import sorting"
1370
+ },
1371
+ {
1372
+ value: "perfectionist",
1373
+ label: "perfectionist",
1374
+ package: "eslint-plugin-perfectionist",
1375
+ hint: "Sort objects, imports, etc."
1376
+ },
1377
+ {
1378
+ value: "split-and-sort-imports",
1379
+ label: "split-and-sort-imports",
1380
+ package: "eslint-plugin-split-and-sort-imports",
1381
+ hint: "Split and sort imports"
1382
+ },
1383
+ {
1384
+ value: "switch-case",
1385
+ label: "switch-case",
1386
+ package: "eslint-plugin-switch-case",
1387
+ hint: "Switch-case specific rules"
1388
+ },
1389
+ {
1390
+ value: "padding",
1391
+ label: "padding",
1392
+ package: "eslint-plugin-padding",
1393
+ hint: "Padding between statements"
1394
+ },
1395
+ {
1396
+ value: "paths",
1397
+ label: "paths",
1398
+ package: "eslint-plugin-paths",
1399
+ hint: "Use paths from tsconfig/jsconfig"
1400
+ },
1401
+ {
1402
+ value: "no-relative-imports",
1403
+ label: "no-relative-imports",
1404
+ package: "@gitbutler/no-relative-imports",
1405
+ hint: "Auto fix relative paths"
1406
+ },
1407
+ // Testing Tools
1408
+ {
1409
+ value: "ava",
1410
+ label: "ava",
1411
+ package: "eslint-plugin-ava",
1412
+ hint: "AVA rules"
1413
+ },
1414
+ {
1415
+ value: "chai-expect",
1416
+ label: "chai-expect",
1417
+ package: "eslint-plugin-chai-expect",
1418
+ hint: "Chai expect practices"
1419
+ },
1420
+ {
1421
+ value: "chai-friendly",
1422
+ label: "chai-friendly",
1423
+ package: "eslint-plugin-chai-friendly",
1424
+ hint: "Chai unused expressions"
1425
+ },
1426
+ {
1427
+ value: "chai-expect-keywords",
1428
+ label: "chai-expect-keywords",
1429
+ package: "eslint-plugin-chai-expect-keywords",
1430
+ hint: "Permitted keywords"
1431
+ },
1432
+ {
1433
+ value: "chai-as-promised",
1434
+ label: "chai-as-promised",
1435
+ package: "eslint-plugin-chai-as-promised",
1436
+ hint: "Chai as promised"
1437
+ },
1438
+ {
1439
+ value: "chai-assert-bdd",
1440
+ label: "chai-assert-bdd",
1441
+ package: "eslint-plugin-chai-assert-bdd",
1442
+ hint: "Chai globals"
1443
+ },
1444
+ {
1445
+ value: "cucumber",
1446
+ label: "cucumber",
1447
+ package: "eslint-plugin-cucumber",
1448
+ hint: "Cucumber rules"
1449
+ },
1450
+ {
1451
+ value: "cypress",
1452
+ label: "cypress",
1453
+ package: "eslint-plugin-cypress",
1454
+ hint: "Cypress rules"
1455
+ },
1456
+ {
1457
+ value: "jasmine",
1458
+ label: "jasmine",
1459
+ package: "eslint-plugin-jasmine",
1460
+ hint: "Jasmine rules"
1461
+ },
1462
+ {
1463
+ value: "jest",
1464
+ label: "jest",
1465
+ package: "eslint-plugin-jest",
1466
+ hint: "Jest practices"
1467
+ },
1468
+ {
1469
+ value: "jest-formatting",
1470
+ label: "jest-formatting",
1471
+ package: "eslint-plugin-jest-formatting",
1472
+ hint: "Jest formatting"
1473
+ },
1474
+ {
1475
+ value: "jest-async",
1476
+ label: "jest-async",
1477
+ package: "eslint-plugin-jest-async",
1478
+ hint: "Jest async rules"
1479
+ },
1480
+ {
1481
+ value: "jest-dom",
1482
+ label: "jest-dom",
1483
+ package: "eslint-plugin-jest-dom",
1484
+ hint: "Jest-DOM rules"
1485
+ },
1486
+ {
1487
+ value: "mocha",
1488
+ label: "mocha",
1489
+ package: "eslint-plugin-mocha",
1490
+ hint: "Mocha practices"
1491
+ },
1492
+ {
1493
+ value: "mocha-cleanup",
1494
+ label: "mocha-cleanup",
1495
+ package: "eslint-plugin-mocha-cleanup",
1496
+ hint: "Mocha cleanup"
1497
+ },
1498
+ {
1499
+ value: "playwright",
1500
+ label: "playwright",
1501
+ package: "eslint-plugin-playwright",
1502
+ hint: "Playwright rules"
1503
+ },
1504
+ {
1505
+ value: "qunit",
1506
+ label: "qunit",
1507
+ package: "eslint-plugin-qunit",
1508
+ hint: "QUnit rules"
1509
+ },
1510
+ {
1511
+ value: "testcafe-community",
1512
+ label: "testcafe-community",
1513
+ package: "eslint-plugin-testcafe-community",
1514
+ hint: "TestCafe rules"
1515
+ },
1516
+ {
1517
+ value: "testing-library",
1518
+ label: "testing-library",
1519
+ package: "eslint-plugin-testing-library",
1520
+ hint: "Testing Library rules"
1521
+ }
1522
+ ];
1523
+ PRETTIER_PLUGINS = [
1524
+ // Official
1525
+ {
1526
+ value: "php",
1527
+ label: "php",
1528
+ package: "@prettier/plugin-php",
1529
+ hint: "Prettier for PHP"
1530
+ },
1531
+ {
1532
+ value: "pug",
1533
+ label: "pug",
1534
+ package: "@prettier/plugin-pug",
1535
+ hint: "Prettier for Pug"
1536
+ },
1537
+ {
1538
+ value: "ruby",
1539
+ label: "ruby",
1540
+ package: "@prettier/plugin-ruby",
1541
+ hint: "Prettier for Ruby"
1542
+ },
1543
+ {
1544
+ value: "xml",
1545
+ label: "xml",
1546
+ package: "@prettier/plugin-xml",
1547
+ hint: "Prettier for XML"
1548
+ },
1549
+ // Community
1550
+ {
1551
+ value: "apex",
1552
+ label: "apex",
1553
+ package: "prettier-plugin-apex",
1554
+ hint: "Prettier for Apex"
1555
+ },
1556
+ {
1557
+ value: "astro",
1558
+ label: "astro",
1559
+ package: "prettier-plugin-astro",
1560
+ hint: "Prettier for Astro"
1561
+ },
1562
+ {
1563
+ value: "bigcommerce",
1564
+ label: "bigcommerce",
1565
+ package: "prettier-plugin-bigcommerce-stencil",
1566
+ hint: "Prettier for BigCommerce"
1567
+ },
1568
+ {
1569
+ value: "elm",
1570
+ label: "elm",
1571
+ package: "prettier-plugin-elm",
1572
+ hint: "Prettier for Elm"
1573
+ },
1574
+ {
1575
+ value: "erb",
1576
+ label: "erb",
1577
+ package: "prettier-plugin-erb",
1578
+ hint: "Prettier for ERB"
1579
+ },
1580
+ {
1581
+ value: "gherkin",
1582
+ label: "gherkin",
1583
+ package: "prettier-plugin-gherkin",
1584
+ hint: "Prettier for Gherkin"
1585
+ },
1586
+ {
1587
+ value: "glsl",
1588
+ label: "glsl",
1589
+ package: "prettier-plugin-glsl",
1590
+ hint: "Prettier for GLSL"
1591
+ },
1592
+ {
1593
+ value: "go-template",
1594
+ label: "go-template",
1595
+ package: "prettier-plugin-go-template",
1596
+ hint: "Prettier for Go Templates"
1597
+ },
1598
+ {
1599
+ value: "hugo",
1600
+ label: "hugo",
1601
+ package: "prettier-plugin-hugo-post",
1602
+ hint: "Prettier for Hugo"
1603
+ },
1604
+ {
1605
+ value: "java",
1606
+ label: "java",
1607
+ package: "prettier-plugin-java",
1608
+ hint: "Prettier for Java"
1609
+ },
1610
+ {
1611
+ value: "jinja",
1612
+ label: "jinja",
1613
+ package: "prettier-plugin-jinja-template",
1614
+ hint: "Prettier for Jinja"
1615
+ },
1616
+ {
1617
+ value: "jsonata",
1618
+ label: "jsonata",
1619
+ package: "prettier-plugin-jsonata",
1620
+ hint: "Prettier for JSONata"
1621
+ },
1622
+ {
1623
+ value: "kotlin",
1624
+ label: "kotlin",
1625
+ package: "prettier-plugin-kotlin",
1626
+ hint: "Prettier for Kotlin"
1627
+ },
1628
+ {
1629
+ value: "marko",
1630
+ label: "marko",
1631
+ package: "prettier-plugin-marko",
1632
+ hint: "Prettier for Marko"
1633
+ },
1634
+ {
1635
+ value: "motoko",
1636
+ label: "motoko",
1637
+ package: "prettier-plugin-motoko",
1638
+ hint: "Prettier for Motoko"
1639
+ },
1640
+ {
1641
+ value: "nginx",
1642
+ label: "nginx",
1643
+ package: "prettier-plugin-nginx",
1644
+ hint: "Prettier for Nginx"
1645
+ },
1646
+ {
1647
+ value: "prisma",
1648
+ label: "prisma",
1649
+ package: "prettier-plugin-prisma",
1650
+ hint: "Prettier for Prisma"
1651
+ },
1652
+ {
1653
+ value: "properties",
1654
+ label: "properties",
1655
+ package: "prettier-plugin-properties",
1656
+ hint: "Prettier for Properties"
1657
+ },
1658
+ {
1659
+ value: "rust",
1660
+ label: "rust",
1661
+ package: "prettier-plugin-rust",
1662
+ hint: "Prettier for Rust"
1663
+ },
1664
+ {
1665
+ value: "sh",
1666
+ label: "sh",
1667
+ package: "prettier-plugin-sh",
1668
+ hint: "Prettier for Shell"
1669
+ },
1670
+ {
1671
+ value: "sql",
1672
+ label: "sql",
1673
+ package: "prettier-plugin-sql",
1674
+ hint: "Prettier for SQL"
1675
+ },
1676
+ {
1677
+ value: "sql-cst",
1678
+ label: "sql-cst",
1679
+ package: "prettier-plugin-sql-cst",
1680
+ hint: "Prettier for SQL (CST)"
1681
+ },
1682
+ {
1683
+ value: "solidity",
1684
+ label: "solidity",
1685
+ package: "prettier-plugin-solidity",
1686
+ hint: "Prettier for Solidity"
1687
+ },
1688
+ {
1689
+ value: "svelte",
1690
+ label: "svelte",
1691
+ package: "prettier-plugin-svelte",
1692
+ hint: "Prettier for Svelte"
1693
+ },
1694
+ {
1695
+ value: "toml",
1696
+ label: "toml",
1697
+ package: "prettier-plugin-toml",
1698
+ hint: "Prettier for TOML"
1699
+ },
1700
+ {
1701
+ value: "xquery",
1702
+ label: "xquery",
1703
+ package: "prettier-plugin-xquery",
1704
+ hint: "Prettier for XQuery"
1705
+ },
1706
+ // Existing
1707
+ {
1708
+ value: "tailwindcss",
1709
+ label: "tailwindcss",
1710
+ package: "prettier-plugin-tailwindcss",
1711
+ hint: "Prettier for Tailwind CSS"
1712
+ },
1713
+ {
1714
+ value: "organize-imports",
1715
+ label: "organize-imports",
1716
+ package: "prettier-plugin-organize-imports",
1717
+ hint: "Organize imports"
1718
+ },
1719
+ {
1720
+ value: "sort-imports",
1721
+ label: "sort-imports",
1722
+ package: "@trivago/prettier-plugin-sort-imports",
1723
+ hint: "Sort imports"
1724
+ },
1725
+ {
1726
+ value: "pkg",
1727
+ label: "pkg",
1728
+ package: "prettier-plugin-pkg",
1729
+ hint: "Format package.json"
1730
+ }
1731
+ ];
1732
+ PLUGINS = {
1733
+ eslint: ESLINT_PLUGINS,
1734
+ prettier: PRETTIER_PLUGINS
1735
+ };
1736
+ PLUGINABLE_TOOLS = Object.keys(PLUGINS);
1737
+ }
1738
+ });
1739
+
1740
+ // src/features/linter/eslint.ts
1741
+ import fs4 from "fs-extra";
1742
+ async function installEslint() {
1743
+ const packages = ["eslint", "globals", "@eslint/js", "typescript-eslint"];
1744
+ await installPackages(packages, true);
1745
+ const configFile = await resolveConfigFile("ESLint", [
1746
+ "eslint.config.mjs",
1747
+ "eslint.config.js",
1748
+ "eslint.config.cjs"
1749
+ ]);
1750
+ if (!await fs4.pathExists(configFile)) {
1751
+ await fs4.writeFile(
1752
+ configFile,
1753
+ `import globals from "globals";
1754
+ import pluginJs from "@eslint/js";
1755
+ import tseslint from "typescript-eslint";
1756
+
1757
+
1758
+ export default [
1759
+ {files: ["**/*.{js,mjs,cjs,ts}"]},
1760
+ {languageOptions: { globals: globals.browser }},
1761
+ pluginJs.configs.recommended,
1762
+ ...tseslint.configs.recommended,
1763
+ ];`
1764
+ );
1765
+ }
1766
+ }
1767
+ async function configureEslintPlugins(plugins) {
1768
+ const configFile = await resolveConfigFile("ESLint", [
1769
+ "eslint.config.mjs",
1770
+ "eslint.config.js",
1771
+ "eslint.config.cjs"
1772
+ ]);
1773
+ if (!await fs4.pathExists(configFile)) {
1774
+ return;
1775
+ }
1776
+ let configContent = await fs4.readFile(configFile, "utf-8");
1777
+ const newImports = [];
1778
+ const newPluginConfigs = [];
1779
+ for (const pluginName of plugins) {
1780
+ const pluginDef = PLUGINS.eslint.find((p) => p.value === pluginName);
1781
+ const packageName = pluginDef?.package || `eslint-plugin-${pluginName}`;
1782
+ const safeVarName = pluginName.replace(/[^a-zA-Z0-9]/g, "") + "Plugin";
1783
+ if (!configContent.includes(`import ${safeVarName}`)) {
1784
+ newImports.push(`import ${safeVarName} from "${packageName}";`);
1785
+ }
1786
+ const shorPluginName = pluginName.replace(/^eslint-plugin-/, "");
1787
+ newPluginConfigs.push(`"${shorPluginName}": ${safeVarName}`);
1788
+ }
1789
+ if (newImports.length > 0) {
1790
+ const lastImportIndex = configContent.lastIndexOf("import ");
1791
+ const endOfLastImport = configContent.indexOf("\n", lastImportIndex) + 1;
1792
+ configContent = configContent.slice(0, endOfLastImport) + newImports.join("\n") + "\n" + configContent.slice(endOfLastImport);
1793
+ }
1794
+ if (newPluginConfigs.length > 0) {
1795
+ const exportDefaultStart = configContent.indexOf("export default [");
1796
+ if (exportDefaultStart !== -1) {
1797
+ const pluginsBlock = `
1798
+ {
1799
+ plugins: {
1800
+ ${newPluginConfigs.join(",\n ")}
1801
+ }
1802
+ },`;
1803
+ const insertPos = exportDefaultStart + "export default [".length;
1804
+ configContent = configContent.slice(0, insertPos) + pluginsBlock + configContent.slice(insertPos);
173
1805
  }
174
1806
  }
1807
+ await fs4.writeFile(configFile, configContent);
175
1808
  }
176
- var init_handle_cancel = __esm({
177
- "src/utils/handle-cancel.ts"() {
1809
+ var init_eslint = __esm({
1810
+ "src/features/linter/eslint.ts"() {
178
1811
  "use strict";
179
1812
  init_esm_shims();
1813
+ init_pm();
1814
+ init_plugins();
1815
+ init_config_file();
180
1816
  }
181
1817
  });
182
1818
 
183
- // src/services/husky.ts
184
- import { select, log, text } from "@clack/prompts";
185
- import { execa as execa2 } from "execa";
186
- import fs from "fs-extra";
187
- import pc from "picocolors";
188
- async function promptHusky(config2) {
189
- log.message(pc.bgMagenta(pc.black(" Husky Configuration ")));
190
- const hookType = await withCancelHandling(
191
- async () => select({
192
- message: "What pre-commit hook would you like to use?",
193
- options: HUSKY_HOOK_OPTIONS
1819
+ // src/steps/install-plugin.ts
1820
+ import pc3 from "picocolors";
1821
+ async function installPlugins(tool) {
1822
+ const pluginsList = PLUGINS[tool];
1823
+ const selectedPlugins = await withCancelHandling(
1824
+ async () => prompts.multiselect({
1825
+ message: `Select ${tool} plugins to install:`,
1826
+ options: pluginsList,
1827
+ required: true,
1828
+ initialValue: []
194
1829
  })
195
1830
  );
196
- const huskyConfig = config2.get("husky");
197
- huskyConfig.options = { hookType };
198
- if (hookType === "lintStaged") {
199
- config2.enableTool("lintStaged");
200
- } else if (hookType === "custom") {
201
- const script = await withCancelHandling(
202
- async () => text({
203
- message: "Enter your custom pre-commit script:",
204
- placeholder: huskyConfig.options.customScript,
205
- validate(value) {
206
- if (value.length === 0) return "Value is required!";
207
- }
208
- })
209
- );
210
- huskyConfig.options.customScript = script;
1831
+ if (selectedPlugins.length === 0) {
1832
+ prompts.outro(pc3.yellow("No plugins selected."));
1833
+ return;
211
1834
  }
1835
+ const packagesToInstall = selectedPlugins.map((val) => {
1836
+ const p = pluginsList.find((opt) => opt.value === val);
1837
+ return p ? p.package : val;
1838
+ });
1839
+ prompts.outro(
1840
+ pc3.blue(`Installing ${packagesToInstall.length} plugins for ${tool}...`)
1841
+ );
1842
+ await installPackages(packagesToInstall, true);
1843
+ await configurePlugins(tool, selectedPlugins);
212
1844
  }
213
- async function installHusky(config2) {
214
- await installPackages(["husky"], true);
215
- try {
216
- await execa2("npx", ["husky", "init"]);
217
- } catch (e) {
218
- await execa2("npm", ["pkg", "set", "scripts.prepare=husky"]);
219
- await execa2("npm", ["run", "prepare"]);
1845
+ async function configurePlugins(tool, plugins) {
1846
+ const shouldConfigure = await withCancelHandling(
1847
+ async () => prompts.confirm({
1848
+ message: `Do you want to configure the selected plugins in your ${tool} config file?`,
1849
+ initialValue: true
1850
+ })
1851
+ );
1852
+ if (!shouldConfigure) {
1853
+ prompts.outro(pc3.yellow("Skipping configuration."));
1854
+ return;
220
1855
  }
221
- const husky = config2.get("husky");
222
- const hookType = husky.options.hookType;
223
- const customScript = husky.options.customScript;
224
- if (hookType === "lintStaged") {
225
- await fs.outputFile(".husky/pre-commit", "npx lint-staged\n", {
226
- mode: 493
227
- });
228
- } else if (hookType === "custom" && customScript) {
229
- await fs.outputFile(".husky/pre-commit", `${customScript}
230
- `, {
231
- mode: 493
232
- });
1856
+ switch (tool) {
1857
+ case "prettier":
1858
+ await configurePrettierPlugins(plugins);
1859
+ prompts.outro(pc3.green("Prettier plugins configured in .prettierrc"));
1860
+ break;
1861
+ case "eslint":
1862
+ await configureEslintPlugins(plugins);
1863
+ prompts.outro(pc3.green("ESLint plugins configured in .eslintrc.json"));
1864
+ break;
233
1865
  }
234
1866
  }
235
- var init_husky = __esm({
236
- "src/services/husky.ts"() {
1867
+ var init_install_plugin = __esm({
1868
+ "src/steps/install-plugin.ts"() {
237
1869
  "use strict";
238
1870
  init_esm_shims();
239
- init_pm();
240
- init_options();
1871
+ init_plugins();
1872
+ init_prettier();
1873
+ init_eslint();
241
1874
  init_handle_cancel();
1875
+ init_pm();
1876
+ init_prompts();
242
1877
  }
243
1878
  });
244
1879
 
245
- // src/services/formatter.ts
246
- import { select as select2, log as log2 } from "@clack/prompts";
247
- import fs2 from "fs-extra";
248
- import pc2 from "picocolors";
1880
+ // src/features/formatter.ts
1881
+ import pc4 from "picocolors";
249
1882
  async function promptFormatter(config2) {
250
1883
  const formatterConfig = config2.get("formatter");
251
- log2.message(pc2.bgBlue(pc2.black(" Formatter Configuration ")));
1884
+ prompts.log.message(pc4.bgBlue(pc4.white(" Formatter Configuration ")));
252
1885
  const formatter = await withCancelHandling(
253
- async () => select2({
1886
+ async () => prompts.select({
254
1887
  message: "Select a formatter:",
255
1888
  options: FORMATTER_OPTIONS,
256
1889
  initialValue: formatterConfig.options.choice
@@ -259,40 +1892,54 @@ async function promptFormatter(config2) {
259
1892
  formatterConfig.options = { choice: formatter };
260
1893
  }
261
1894
  async function installFormatter(config2) {
262
- const choice = config2.get("formatter").options.choice;
263
- if (choice === "prettier") {
264
- await installPackages(["prettier"], true);
265
- const configContent = {
266
- semi: true,
267
- singleQuote: true,
268
- trailingComma: "all",
269
- printWidth: 80,
270
- tabWidth: 2
271
- };
272
- await fs2.writeJson(".prettierrc", configContent, { spaces: 2 });
273
- } else if (choice === "oxfmt") {
274
- await installPackages(["oxfmt"], true);
275
- }
1895
+ const formatter = config2.get("formatter").options.choice;
1896
+ if (!formatter) return;
1897
+ prompts.log.message(pc4.white(pc4.bgBlack(` Installing ${formatter}... `)));
1898
+ if (formatter === "prettier") await installPrettier();
1899
+ else if (formatter === "oxfmt") await installOxfmt();
1900
+ if (!PLUGINABLE_TOOLS.includes(formatter)) return;
1901
+ const shouldConfigure = await withCancelHandling(
1902
+ async () => prompts.confirm({
1903
+ message: `Do you want to install plugins for ${formatter}?`,
1904
+ initialValue: true
1905
+ })
1906
+ );
1907
+ if (!shouldConfigure) return;
1908
+ await installPlugins(formatter);
276
1909
  }
277
1910
  var init_formatter = __esm({
278
- "src/services/formatter.ts"() {
1911
+ "src/features/formatter.ts"() {
279
1912
  "use strict";
280
1913
  init_esm_shims();
281
- init_pm();
1914
+ init_prompts();
282
1915
  init_options();
283
1916
  init_handle_cancel();
1917
+ init_prettier();
1918
+ init_oxfmt();
1919
+ init_plugins();
1920
+ init_install_plugin();
284
1921
  }
285
1922
  });
286
1923
 
287
- // src/services/linter.ts
288
- import { select as select3, log as log3 } from "@clack/prompts";
289
- import fs3 from "fs-extra";
290
- import pc3 from "picocolors";
1924
+ // src/features/linter/oxlint.ts
1925
+ async function installOxlint() {
1926
+ await installPackages(["oxlint@latest"], true);
1927
+ }
1928
+ var init_oxlint = __esm({
1929
+ "src/features/linter/oxlint.ts"() {
1930
+ "use strict";
1931
+ init_esm_shims();
1932
+ init_pm();
1933
+ }
1934
+ });
1935
+
1936
+ // src/features/linter.ts
1937
+ import pc5 from "picocolors";
291
1938
  async function promptLinter(config2) {
292
1939
  const linterConfig = config2.get("linter");
293
- log3.message(pc3.bgYellow(pc3.black(" Linter Configuration ")));
1940
+ prompts.log.message(pc5.bgYellow(pc5.black(" Linter Configuration ")));
294
1941
  const linter = await withCancelHandling(
295
- async () => select3({
1942
+ async () => prompts.select({
296
1943
  message: "Select a linter:",
297
1944
  options: LINTER_OPTIONS,
298
1945
  initialValue: linterConfig.options.choice
@@ -301,50 +1948,48 @@ async function promptLinter(config2) {
301
1948
  linterConfig.options = { choice: linter };
302
1949
  }
303
1950
  async function installLinter(config2) {
304
- const choice = config2.get("linter").options.choice;
305
- if (choice === "eslint") {
306
- await installPackages(["eslint"], true);
307
- const configContent = {
308
- extends: ["eslint:recommended"],
309
- env: {
310
- node: true,
311
- es2021: true
312
- },
313
- parserOptions: {
314
- ecmaVersion: "latest",
315
- sourceType: "module"
316
- }
317
- };
318
- await fs3.writeJson(".eslintrc.json", configContent, { spaces: 2 });
319
- } else if (choice === "oxlint") {
320
- await installPackages(["oxlint"], true);
321
- }
1951
+ const linter = config2.get("linter").options.choice;
1952
+ if (!linter) return;
1953
+ prompts.log.message(pc5.white(pc5.bgBlack(` Installing ${linter}... `)));
1954
+ if (linter === "eslint") await installEslint();
1955
+ else if (linter === "oxlint") await installOxlint();
1956
+ if (!PLUGINABLE_TOOLS.includes(linter)) return;
1957
+ const shouldConfigure = await withCancelHandling(
1958
+ async () => prompts.confirm({
1959
+ message: `Do you want to install plugins for ${linter}?`,
1960
+ initialValue: true
1961
+ })
1962
+ );
1963
+ if (!shouldConfigure) return;
1964
+ await installPlugins(linter);
322
1965
  }
323
1966
  var init_linter = __esm({
324
- "src/services/linter.ts"() {
1967
+ "src/features/linter.ts"() {
325
1968
  "use strict";
326
1969
  init_esm_shims();
327
- init_pm();
1970
+ init_prompts();
328
1971
  init_options();
329
1972
  init_handle_cancel();
1973
+ init_eslint();
1974
+ init_oxlint();
1975
+ init_plugins();
1976
+ init_install_plugin();
330
1977
  }
331
1978
  });
332
1979
 
333
- // src/services/lint-staged.ts
334
- import { multiselect, log as log4 } from "@clack/prompts";
335
- import fs4 from "fs-extra";
336
- import pc4 from "picocolors";
1980
+ // src/features/lint-staged.ts
1981
+ import pc6 from "picocolors";
337
1982
  async function promptLintStaged(config2) {
338
- log4.message(pc4.bgGreen(pc4.black(" Lint-staged Configuration ")));
1983
+ prompts.log.message(pc6.bgGreen(pc6.black(" Lint-staged Configuration ")));
339
1984
  const lintExtensions = await withCancelHandling(
340
- async () => multiselect({
1985
+ async () => prompts.multiselect({
341
1986
  message: "Select extensions to lint:",
342
1987
  options: LINT_STAGED_EXTENSIONS,
343
1988
  required: false
344
1989
  })
345
1990
  );
346
1991
  const formatExtensions = await withCancelHandling(
347
- async () => multiselect({
1992
+ async () => prompts.multiselect({
348
1993
  message: "Select extensions to format:",
349
1994
  options: LINT_STAGED_EXTENSIONS,
350
1995
  required: false
@@ -365,6 +2010,13 @@ async function promptLintStaged(config2) {
365
2010
  }
366
2011
  async function installLintStaged(config2) {
367
2012
  await installPackages(["lint-staged"], true);
2013
+ const configFile = await resolveConfigFile("Lint-Staged", [
2014
+ ".lintstagedrc",
2015
+ ".lintstagedrc.json",
2016
+ "lint-staged.config.js",
2017
+ ".lintstagedrc.js",
2018
+ ".lintstagedrc.mjs"
2019
+ ]);
368
2020
  const lintStagedConfig = {};
369
2021
  const lintStagedOptions = config2.get("lintStaged").options;
370
2022
  const lintExts = lintStagedOptions?.lintExtensions || [];
@@ -387,48 +2039,49 @@ async function installLintStaged(config2) {
387
2039
  lintStagedConfig[glob] = ["prettier --write"];
388
2040
  }
389
2041
  }
390
- await fs4.writeJson(".lintstagedrc", lintStagedConfig, { spaces: 2 });
2042
+ await writeConfig(configFile, lintStagedConfig);
391
2043
  }
392
2044
  var init_lint_staged = __esm({
393
- "src/services/lint-staged.ts"() {
2045
+ "src/features/lint-staged.ts"() {
394
2046
  "use strict";
395
2047
  init_esm_shims();
2048
+ init_prompts();
396
2049
  init_pm();
397
2050
  init_formatter();
398
2051
  init_linter();
399
2052
  init_options();
400
2053
  init_handle_cancel();
2054
+ init_config_file();
401
2055
  }
402
2056
  });
403
2057
 
404
- // src/services/env.ts
405
- import { select as select4, confirm as confirm2, text as text2, multiselect as multiselect2, log as log5 } from "@clack/prompts";
2058
+ // src/features/env.ts
406
2059
  import fs5 from "fs-extra";
407
- import path2 from "path";
408
- import pc5 from "picocolors";
2060
+ import path3 from "path";
2061
+ import pc7 from "picocolors";
409
2062
  async function promptEnv(config2) {
410
- log5.message(pc5.bgCyan(pc5.black(" Env Validation Configuration ")));
2063
+ prompts.log.message(pc7.bgCyan(pc7.black(" Env Validation Configuration ")));
411
2064
  const variant = await withCancelHandling(
412
- async () => select4({
2065
+ async () => prompts.select({
413
2066
  message: "Which @t3-oss/env variant?",
414
2067
  options: ENV_VARIANT_OPTIONS
415
2068
  })
416
2069
  );
417
2070
  const validator = await withCancelHandling(
418
- async () => select4({
2071
+ async () => prompts.select({
419
2072
  message: "Which validator?",
420
2073
  options: ENV_VALIDATOR_OPTIONS
421
2074
  })
422
2075
  );
423
2076
  const installPresets = await withCancelHandling(
424
- async () => confirm2({
2077
+ async () => prompts.confirm({
425
2078
  message: "Install presets?"
426
2079
  })
427
2080
  );
428
2081
  let presets;
429
2082
  if (installPresets) {
430
2083
  presets = await withCancelHandling(
431
- async () => multiselect2({
2084
+ async () => prompts.multiselect({
432
2085
  message: "Select preset to extend:",
433
2086
  options: ENV_PRESET_OPTIONS,
434
2087
  required: false
@@ -436,13 +2089,13 @@ async function promptEnv(config2) {
436
2089
  );
437
2090
  }
438
2091
  const split = await withCancelHandling(
439
- async () => select4({
2092
+ async () => prompts.select({
440
2093
  message: "Split or Joined env files?",
441
2094
  options: ENV_SPLIT_OPTIONS
442
2095
  })
443
2096
  );
444
2097
  const location = await withCancelHandling(
445
- async () => text2({
2098
+ async () => prompts.text({
446
2099
  message: "Where should the environment files be created?",
447
2100
  initialValue: config2.get("env").options.location || "src/lib",
448
2101
  placeholder: "src/lib"
@@ -460,7 +2113,7 @@ async function promptEnv(config2) {
460
2113
  async function installEnv(config2) {
461
2114
  const envOptions = config2.get("env").options;
462
2115
  const { variant, validator, location, presets, split } = envOptions;
463
- await installPackages([variant, validator], true);
2116
+ await installPackages([variant, validator], false);
464
2117
  await fs5.ensureDir(location);
465
2118
  const presetImport = presets && presets.length > 0 ? `// Presets: ${presets.join(", ")}
466
2119
  ` : "";
@@ -470,7 +2123,7 @@ import { ${validator} } from "${validator}";
470
2123
  ${presetImport}`;
471
2124
  if (split === "split") {
472
2125
  await fs5.outputFile(
473
- path2.join(location, "env/server.ts"),
2126
+ path3.join(location, "env/server.ts"),
474
2127
  `${content}
475
2128
  // Server env definition
476
2129
  export const env = createEnv({
@@ -481,7 +2134,7 @@ export const env = createEnv({
481
2134
  });`
482
2135
  );
483
2136
  await fs5.outputFile(
484
- path2.join(location, "env/client.ts"),
2137
+ path3.join(location, "env/client.ts"),
485
2138
  `${content}
486
2139
  // Client env definition
487
2140
  export const env = createEnv({
@@ -495,7 +2148,7 @@ export const env = createEnv({
495
2148
  );
496
2149
  } else {
497
2150
  await fs5.outputFile(
498
- path2.join(location, "env.ts"),
2151
+ path3.join(location, "env.ts"),
499
2152
  `${content}
500
2153
  // Joined env definition
501
2154
  export const env = createEnv({
@@ -513,23 +2166,23 @@ export const env = createEnv({
513
2166
  }
514
2167
  }
515
2168
  var init_env = __esm({
516
- "src/services/env.ts"() {
2169
+ "src/features/env.ts"() {
517
2170
  "use strict";
518
2171
  init_esm_shims();
2172
+ init_prompts();
519
2173
  init_pm();
520
2174
  init_options();
521
2175
  init_handle_cancel();
522
2176
  }
523
2177
  });
524
2178
 
525
- // src/services/test.ts
526
- import { select as select5, log as log6 } from "@clack/prompts";
2179
+ // src/features/test.ts
527
2180
  import fs6 from "fs-extra";
528
- import pc6 from "picocolors";
2181
+ import pc8 from "picocolors";
529
2182
  async function promptTest(config2) {
530
- log6.message(pc6.bgRed(pc6.black(" Test Runner Configuration ")));
2183
+ prompts.log.message(pc8.bgRed(pc8.white(" Test Runner Configuration ")));
531
2184
  const runner = await withCancelHandling(
532
- async () => select5({
2185
+ async () => prompts.select({
533
2186
  message: "Select a test runner:",
534
2187
  options: TEST_RUNNER_OPTIONS
535
2188
  })
@@ -571,24 +2224,24 @@ module.exports = {
571
2224
  }
572
2225
  }
573
2226
  var init_test = __esm({
574
- "src/services/test.ts"() {
2227
+ "src/features/test.ts"() {
575
2228
  "use strict";
576
2229
  init_esm_shims();
2230
+ init_prompts();
577
2231
  init_pm();
578
2232
  init_options();
579
2233
  init_handle_cancel();
580
2234
  }
581
2235
  });
582
2236
 
583
- // src/services/editor-config.ts
584
- import { select as select6, log as log7 } from "@clack/prompts";
2237
+ // src/features/editor-config.ts
585
2238
  import fs7 from "fs-extra";
586
- import pc7 from "picocolors";
2239
+ import pc9 from "picocolors";
587
2240
  async function promptEditorConfig(config2) {
588
- log7.message(pc7.bgWhite(pc7.black(" EditorConfig Configuration ")));
2241
+ prompts.log.message(pc9.bgWhite(pc9.black(" EditorConfig Configuration ")));
589
2242
  const currentPreset = config2.get("editorConfig").options.preset;
590
2243
  const preset = await withCancelHandling(
591
- async () => select6({
2244
+ async () => prompts.select({
592
2245
  message: "Select EditorConfig preset:",
593
2246
  options: EDITOR_CONFIG_OPTIONS,
594
2247
  initialValue: currentPreset
@@ -609,45 +2262,45 @@ async function installEditorConfig(config2) {
609
2262
  await fs7.outputFile(".editorconfig", content);
610
2263
  }
611
2264
  var init_editor_config = __esm({
612
- "src/services/editor-config.ts"() {
2265
+ "src/features/editor-config.ts"() {
613
2266
  "use strict";
614
2267
  init_esm_shims();
2268
+ init_prompts();
615
2269
  init_options();
616
2270
  init_handle_cancel();
617
2271
  }
618
2272
  });
619
2273
 
620
- // src/services/license.ts
621
- import { text as text3, select as select7, log as log8 } from "@clack/prompts";
2274
+ // src/features/license.ts
622
2275
  import fs8 from "fs-extra";
623
- import path3 from "path";
624
- import pc8 from "picocolors";
2276
+ import path4 from "path";
2277
+ import pc10 from "picocolors";
625
2278
  async function promptLicense(config2) {
626
- log8.message(pc8.bgGreen(pc8.black(" License Configuration ")));
2279
+ prompts.log.message(pc10.bgGreen(pc10.black(" License Configuration ")));
627
2280
  const licenseOptions = config2.get("license").options;
628
2281
  licenseOptions.name = await withCancelHandling(
629
- async () => text3({
2282
+ async () => prompts.text({
630
2283
  message: "License Holder Name:",
631
2284
  placeholder: "John Doe",
632
2285
  initialValue: licenseOptions.name
633
2286
  })
634
2287
  );
635
2288
  licenseOptions.email = await withCancelHandling(
636
- async () => text3({
2289
+ async () => prompts.text({
637
2290
  message: "License Holder Email:",
638
2291
  placeholder: "john@example.com",
639
2292
  initialValue: licenseOptions.email
640
2293
  })
641
2294
  );
642
2295
  licenseOptions.website = await withCancelHandling(
643
- async () => text3({
2296
+ async () => prompts.text({
644
2297
  message: "License Holder Website:",
645
2298
  placeholder: "https://example.com",
646
2299
  initialValue: licenseOptions.website
647
2300
  })
648
2301
  );
649
2302
  licenseOptions.type = await withCancelHandling(
650
- async () => select7({
2303
+ async () => prompts.select({
651
2304
  message: "Select License Type:",
652
2305
  options: LICENSE_TYPE_OPTIONS
653
2306
  })
@@ -658,7 +2311,7 @@ async function installLicense(config2) {
658
2311
  const { type, name, email, website } = licenseOptions;
659
2312
  if (type !== "UNLICENSED") {
660
2313
  const year = (/* @__PURE__ */ new Date()).getFullYear().toString();
661
- const templatePath = path3.join(__dirname, "licenses", `${type}.txt`);
2314
+ const templatePath = path4.join(__dirname, "licenses", `${type}.txt`);
662
2315
  if (await fs8.pathExists(templatePath)) {
663
2316
  let licenseContent = await fs8.readFile(templatePath, "utf-8");
664
2317
  licenseContent = licenseContent.replace(/{YEAR}/g, year);
@@ -682,19 +2335,20 @@ Licensed under ${type}`;
682
2335
  }
683
2336
  }
684
2337
  var init_license = __esm({
685
- "src/services/license.ts"() {
2338
+ "src/features/license.ts"() {
686
2339
  "use strict";
687
2340
  init_esm_shims();
2341
+ init_prompts();
688
2342
  init_options();
689
2343
  init_handle_cancel();
690
2344
  }
691
2345
  });
692
2346
 
693
- // src/config/config.ts
694
- import pc9 from "picocolors";
2347
+ // src/core/config.ts
2348
+ import pc11 from "picocolors";
695
2349
  var Config, config;
696
2350
  var init_config = __esm({
697
- "src/config/config.ts"() {
2351
+ "src/core/config.ts"() {
698
2352
  "use strict";
699
2353
  init_esm_shims();
700
2354
  Config = class {
@@ -725,7 +2379,50 @@ var init_config = __esm({
725
2379
  installPresets: false,
726
2380
  presets: [],
727
2381
  split: "split",
728
- location: "src/env"
2382
+ location: "src/lib"
2383
+ }
2384
+ },
2385
+ test: {
2386
+ selected: false,
2387
+ options: { runner: "vitest" }
2388
+ },
2389
+ editorConfig: {
2390
+ selected: false,
2391
+ options: { preset: "default" }
2392
+ },
2393
+ license: {
2394
+ selected: false,
2395
+ options: { name: "", email: "", website: "", type: "MIT" }
2396
+ }
2397
+ };
2398
+ }
2399
+ clear() {
2400
+ this.data = {
2401
+ husky: {
2402
+ selected: false,
2403
+ options: { hookType: "none", customScript: "npm run test" }
2404
+ },
2405
+ formatter: {
2406
+ selected: false,
2407
+ options: { choice: "prettier" }
2408
+ },
2409
+ linter: {
2410
+ selected: false,
2411
+ options: { choice: "eslint" }
2412
+ },
2413
+ lintStaged: {
2414
+ selected: false,
2415
+ options: { lintExtensions: [], formatExtensions: [] }
2416
+ },
2417
+ env: {
2418
+ selected: false,
2419
+ options: {
2420
+ variant: "@t3-oss/env-nextjs",
2421
+ validator: "zod",
2422
+ installPresets: false,
2423
+ presets: [],
2424
+ split: "split",
2425
+ location: "src/lib"
729
2426
  }
730
2427
  },
731
2428
  test: {
@@ -750,47 +2447,47 @@ var init_config = __esm({
750
2447
  }
751
2448
  get summary() {
752
2449
  const lines = [];
753
- lines.push(pc9.bold("The following actions will be performed:"));
2450
+ lines.push(pc11.bold("The following actions will be performed:"));
754
2451
  lines.push("");
755
2452
  if (this.data.husky.selected) {
756
- lines.push(pc9.magenta(`\u2022 Install and configure Husky`));
2453
+ lines.push(pc11.magenta(`\u2022 Install and configure Husky`));
757
2454
  if (this.data.husky.options.hookType === "custom") {
758
- lines.push(pc9.dim(` - Custom hook script`));
2455
+ lines.push(pc11.dim(` - Custom hook script`));
759
2456
  }
760
2457
  }
761
2458
  if (this.data.formatter.selected) {
762
2459
  const choice = this.data.formatter.options.choice;
763
- lines.push(pc9.blue(`\u2022 Install and configure ${choice || "Formatter"}`));
2460
+ lines.push(pc11.blue(`\u2022 Install and configure ${choice || "Formatter"}`));
764
2461
  }
765
2462
  if (this.data.linter.selected) {
766
2463
  const choice = this.data.linter.options.choice;
767
- lines.push(pc9.yellow(`\u2022 Install and configure ${choice || "Linter"}`));
2464
+ lines.push(pc11.yellow(`\u2022 Install and configure ${choice || "Linter"}`));
768
2465
  }
769
2466
  if (this.data.lintStaged.selected) {
770
- lines.push(pc9.green(`\u2022 Install and configure Lint-staged`));
2467
+ lines.push(pc11.green(`\u2022 Install and configure Lint-staged`));
771
2468
  const lintExts = this.data.lintStaged.options.lintExtensions.join(", ");
772
2469
  const formatExts = this.data.lintStaged.options.formatExtensions.join(", ");
773
- if (lintExts) lines.push(pc9.dim(` - Lint: ${lintExts}`));
774
- if (formatExts) lines.push(pc9.dim(` - Format: ${formatExts}`));
2470
+ if (lintExts) lines.push(pc11.dim(` - Lint: ${lintExts}`));
2471
+ if (formatExts) lines.push(pc11.dim(` - Format: ${formatExts}`));
775
2472
  }
776
2473
  if (this.data.env.selected) {
777
- lines.push(pc9.cyan(`\u2022 Install and configure Env Validation`));
778
- lines.push(pc9.dim(` - Variant: ${this.data.env.options.variant}`));
779
- lines.push(pc9.dim(` - Validator: ${this.data.env.options.validator}`));
2474
+ lines.push(pc11.cyan(`\u2022 Install and configure Env Validation`));
2475
+ lines.push(pc11.dim(` - Variant: ${this.data.env.options.variant}`));
2476
+ lines.push(pc11.dim(` - Validator: ${this.data.env.options.validator}`));
780
2477
  }
781
2478
  if (this.data.test.selected) {
782
2479
  const runner = this.data.test.options.runner;
783
- lines.push(pc9.red(`\u2022 Install and configure Test Runner (${runner})`));
2480
+ lines.push(pc11.red(`\u2022 Install and configure Test Runner (${runner})`));
784
2481
  }
785
2482
  if (this.data.editorConfig.selected) {
786
2483
  const preset = this.data.editorConfig.options.preset;
787
- lines.push(pc9.white(`\u2022 Create .editorconfig (${preset})`));
2484
+ lines.push(pc11.white(`\u2022 Create .editorconfig (${preset})`));
788
2485
  }
789
2486
  if (this.data.license.selected) {
790
2487
  const type = this.data.license.options.type;
791
2488
  const name = this.data.license.options.name;
792
- lines.push(pc9.green(`\u2022 Create LICENSE (${type})`));
793
- lines.push(pc9.dim(` - Holder: ${name}`));
2489
+ lines.push(pc11.green(`\u2022 Create LICENSE (${type})`));
2490
+ lines.push(pc11.dim(` - Holder: ${name}`));
794
2491
  }
795
2492
  return lines.join("\n");
796
2493
  }
@@ -799,8 +2496,56 @@ var init_config = __esm({
799
2496
  }
800
2497
  });
801
2498
 
2499
+ // src/utils/spinner.ts
2500
+ import spinners from "cli-spinners";
2501
+ import pc12 from "picocolors";
2502
+ var Spinner, spinner;
2503
+ var init_spinner = __esm({
2504
+ "src/utils/spinner.ts"() {
2505
+ "use strict";
2506
+ init_esm_shims();
2507
+ Spinner = class {
2508
+ timer = null;
2509
+ frameIndex = 0;
2510
+ spinner = spinners.dots;
2511
+ text = "";
2512
+ start(text2) {
2513
+ this.text = text2;
2514
+ this.frameIndex = 0;
2515
+ if (this.timer) clearInterval(this.timer);
2516
+ this.timer = setInterval(() => {
2517
+ const frame = this.spinner.frames[this.frameIndex];
2518
+ process.stdout.write(`\r${pc12.magenta(frame)} ${this.text}`);
2519
+ this.frameIndex = (this.frameIndex + 1) % this.spinner.frames.length;
2520
+ }, this.spinner.interval);
2521
+ }
2522
+ stop(text2) {
2523
+ if (this.timer) {
2524
+ clearInterval(this.timer);
2525
+ this.timer = null;
2526
+ process.stdout.write("\r\x1B[K");
2527
+ if (text2) {
2528
+ console.log(text2);
2529
+ }
2530
+ }
2531
+ }
2532
+ success(text2) {
2533
+ this.stop();
2534
+ console.log(`${pc12.green("\u2714")} ${text2 || this.text}`);
2535
+ }
2536
+ fail(text2) {
2537
+ this.stop();
2538
+ console.log(`${pc12.red("\u2716")} ${text2 || this.text}`);
2539
+ }
2540
+ message(text2) {
2541
+ this.text = text2;
2542
+ }
2543
+ };
2544
+ spinner = () => new Spinner();
2545
+ }
2546
+ });
2547
+
802
2548
  // src/steps/execution.ts
803
- import { spinner } from "@clack/prompts";
804
2549
  async function execution(config2) {
805
2550
  const s = spinner();
806
2551
  if (config2.get("husky").selected) {
@@ -851,6 +2596,7 @@ var init_execution = __esm({
851
2596
  "src/steps/execution.ts"() {
852
2597
  "use strict";
853
2598
  init_esm_shims();
2599
+ init_spinner();
854
2600
  init_husky();
855
2601
  init_formatter();
856
2602
  init_linter();
@@ -864,16 +2610,16 @@ var init_execution = __esm({
864
2610
 
865
2611
  // src/utils/logger.ts
866
2612
  import fs9 from "fs-extra";
867
- import path4 from "path";
2613
+ import path5 from "path";
868
2614
  async function logError(error) {
869
2615
  try {
870
2616
  await fs9.ensureDir(ERRORS_DIR);
871
- const gitignorePath = path4.join(LOG_DIR, ".gitignore");
2617
+ const gitignorePath = path5.join(LOG_DIR, ".gitignore");
872
2618
  if (!await fs9.pathExists(gitignorePath)) {
873
2619
  await fs9.outputFile(gitignorePath, "*\n");
874
2620
  }
875
2621
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
876
- const logFile = path4.join(ERRORS_DIR, `log-${timestamp}.txt`);
2622
+ const logFile = path5.join(ERRORS_DIR, `log-${timestamp}.txt`);
877
2623
  const errorMessage = error instanceof Error ? error.stack || error.message : String(error);
878
2624
  const logContent = `Timestamp: ${(/* @__PURE__ */ new Date()).toISOString()}
879
2625
 
@@ -893,7 +2639,7 @@ var init_logger = __esm({
893
2639
  "use strict";
894
2640
  init_esm_shims();
895
2641
  LOG_DIR = ".mayrlabs/setup-project";
896
- ERRORS_DIR = path4.join(LOG_DIR, "errors");
2642
+ ERRORS_DIR = path5.join(LOG_DIR, "errors");
897
2643
  }
898
2644
  });
899
2645
 
@@ -927,15 +2673,14 @@ var init_git = __esm({
927
2673
  });
928
2674
 
929
2675
  // src/steps/git-check.ts
930
- import { confirm as confirm3, spinner as spinner2, text as text4 } from "@clack/prompts";
931
2676
  async function gitCheck() {
932
2677
  if (await isGitRepository()) {
933
2678
  if (await isGitDirty()) {
934
- const shouldCommit = await confirm3({
2679
+ const shouldCommit = await prompts.confirm({
935
2680
  message: "Your working directory is dirty. Would you like to commit changes before proceeding?"
936
2681
  });
937
2682
  if (shouldCommit) {
938
- const message = await text4({
2683
+ const message = await prompts.text({
939
2684
  message: "Enter commit message:",
940
2685
  placeholder: "wip: pre-setup commit",
941
2686
  validate(value) {
@@ -943,7 +2688,7 @@ async function gitCheck() {
943
2688
  }
944
2689
  });
945
2690
  if (typeof message === "string") {
946
- const s = spinner2();
2691
+ const s = spinner();
947
2692
  s.start("Committing changes...");
948
2693
  await commitChanges(message);
949
2694
  s.stop("Changes committed.");
@@ -957,6 +2702,8 @@ var init_git_check = __esm({
957
2702
  "use strict";
958
2703
  init_esm_shims();
959
2704
  init_git();
2705
+ init_prompts();
2706
+ init_spinner();
960
2707
  }
961
2708
  });
962
2709
 
@@ -966,53 +2713,57 @@ var init_package = __esm({
966
2713
  "package.json"() {
967
2714
  package_default = {
968
2715
  name: "@mayrlabs/setup-project",
969
- version: "0.1.7",
970
- description: "Interactive CLI to setup project tools",
2716
+ version: "0.1.9",
971
2717
  private: false,
972
- publishConfig: {
973
- access: "public"
974
- },
2718
+ description: "Interactive CLI to setup project tools",
975
2719
  keywords: [
976
- "setup",
977
2720
  "cli",
978
- "scaffold",
2721
+ "eslint",
979
2722
  "husky",
980
2723
  "prettier",
981
- "eslint"
982
- ],
983
- bin: {
984
- "setup-project": "dist/index.js"
985
- },
986
- files: [
987
- "dist",
988
- "README.md",
989
- "CHANGELOG.md",
990
- "package.json"
2724
+ "scaffold",
2725
+ "setup"
991
2726
  ],
992
2727
  homepage: "https://github.com/MayR-Labs/mayrlabs-js/tree/main/packages/setup-project#readme",
993
2728
  bugs: {
994
2729
  url: "https://github.com/MayR-Labs/mayrlabs-js/issues"
995
2730
  },
996
- repository: {
997
- type: "git",
998
- url: "git+https://github.com/MayR-Labs/mayrlabs-js.git",
999
- directory: "packages/setup-project"
1000
- },
1001
2731
  license: "MIT",
1002
2732
  author: {
1003
2733
  name: "Aghogho Meyoron",
1004
2734
  email: "youngmayor.dev@gmail.com",
1005
2735
  url: "https://mayrlabs.com"
1006
2736
  },
2737
+ repository: {
2738
+ type: "git",
2739
+ url: "git+https://github.com/MayR-Labs/mayrlabs-js.git",
2740
+ directory: "packages/setup-project"
2741
+ },
2742
+ bin: {
2743
+ "setup-project": "dist/index.js"
2744
+ },
2745
+ files: [
2746
+ "dist",
2747
+ "README.md",
2748
+ "CHANGELOG.md",
2749
+ "package.json"
2750
+ ],
1007
2751
  type: "commonjs",
1008
2752
  main: "dist/index.js",
2753
+ publishConfig: {
2754
+ access: "public"
2755
+ },
1009
2756
  scripts: {
1010
2757
  build: "tsup",
1011
- demo: "tsx src/index.ts",
2758
+ lint: "eslint . --max-warnings 0",
2759
+ demo: "tsx src/cli/index.ts",
2760
+ test: "vitest",
1012
2761
  prepublishOnly: "npm run build"
1013
2762
  },
1014
2763
  dependencies: {
1015
2764
  "@clack/prompts": "^0.7.0",
2765
+ "@topcli/prompts": "^2.4.1",
2766
+ "cli-spinners": "^3.4.0",
1016
2767
  commander: "^11.1.0",
1017
2768
  execa: "^8.0.1",
1018
2769
  figlet: "^1.10.0",
@@ -1021,24 +2772,28 @@ var init_package = __esm({
1021
2772
  zod: "^3.22.4"
1022
2773
  },
1023
2774
  devDependencies: {
2775
+ "@repo/eslint-config": "^0.0.0",
1024
2776
  "@types/figlet": "^1.7.0",
1025
2777
  "@types/fs-extra": "^11.0.4",
1026
2778
  "@types/node": "^20.11.16",
2779
+ "@vitest/coverage-v8": "^4.0.18",
2780
+ eslint: "^9.39.2",
1027
2781
  tsup: "^8.5.1",
1028
2782
  tsx: "^4.21.0",
1029
- typescript: "^5.3.3"
2783
+ typescript: "^5.3.3",
2784
+ vitest: "^4.0.18"
1030
2785
  }
1031
2786
  };
1032
2787
  }
1033
2788
  });
1034
2789
 
1035
2790
  // src/utils/display.ts
1036
- import pc10 from "picocolors";
2791
+ import pc13 from "picocolors";
1037
2792
  import figlet from "figlet";
1038
2793
  function introScreen() {
1039
2794
  console.log();
1040
2795
  console.log(
1041
- pc10.cyan(
2796
+ pc13.cyan(
1042
2797
  figlet.textSync("MayR\nLabs", {
1043
2798
  font: "Graceful",
1044
2799
  horizontalLayout: "default",
@@ -1048,39 +2803,41 @@ function introScreen() {
1048
2803
  })
1049
2804
  )
1050
2805
  );
1051
- console.log(pc10.cyan(`@mayrlabs/setup-project v${package_default.version}`));
2806
+ console.log(pc13.cyan(`${package_default.name} - v${package_default.version}`));
1052
2807
  console.log();
1053
2808
  }
1054
2809
  function showAbout() {
1055
2810
  introScreen();
1056
- console.log(pc10.bold("About:"));
2811
+ console.log(pc13.bold("About:"));
1057
2812
  console.log(
1058
2813
  " Interactive CLI to setup project tools like Husky, Prettier, ESLint, etc."
1059
2814
  );
1060
2815
  console.log("");
1061
- console.log(pc10.bold("How to use:"));
2816
+ console.log(pc13.bold("How to use:"));
1062
2817
  console.log(
1063
2818
  " Run 'npx @mayrlabs/setup-project' and follow the interactive prompts."
1064
2819
  );
1065
2820
  console.log("");
1066
2821
  }
1067
2822
  function showVisit() {
1068
- console.log(pc10.bold("Project Homepage:"));
1069
- console.log(pc10.underline(pc10.cyan(package_default.homepage)));
2823
+ console.log(pc13.bold("Project Homepage:"));
2824
+ console.log(pc13.underline(pc13.cyan(package_default.homepage)));
1070
2825
  console.log("");
1071
2826
  }
1072
2827
  function showManual() {
1073
2828
  introScreen();
1074
- console.log(pc10.bold("Usage:"));
2829
+ console.log(pc13.bold("Usage:"));
1075
2830
  console.log(" npx @mayrlabs/setup-project [command] [options]");
1076
2831
  console.log("");
1077
- console.log(pc10.bold("Commands:"));
2832
+ console.log(pc13.bold("Commands:"));
1078
2833
  console.log(" about Show project details");
1079
2834
  console.log(" version Show version information");
1080
2835
  console.log(" visit Visit project homepage");
1081
2836
  console.log(" help Show this help message");
2837
+ console.log(" configure [tool] Configure a specific tool");
2838
+ console.log(" plugin [tool] Manage plugins for tools");
1082
2839
  console.log("");
1083
- console.log(pc10.bold("Options:"));
2840
+ console.log(pc13.bold("Options:"));
1084
2841
  console.log(" -a, --about Show project details");
1085
2842
  console.log(" -v, --version Show version information");
1086
2843
  console.log(" -V, --visit Visit project homepage");
@@ -1095,13 +2852,135 @@ var init_display = __esm({
1095
2852
  }
1096
2853
  });
1097
2854
 
1098
- // src/index.ts
1099
- import { outro, multiselect as multiselect3, note, confirm as confirm4, intro } from "@clack/prompts";
1100
- import pc11 from "picocolors";
2855
+ // src/cli/commands/configure.ts
2856
+ import pc14 from "picocolors";
2857
+ async function configure(toolName) {
2858
+ introScreen();
2859
+ prompts.intro(pc14.inverse(pc14.bold(pc14.blue(" Configuration Mode "))));
2860
+ await gitCheck();
2861
+ let selectedTool;
2862
+ if (toolName) {
2863
+ const tool = TOOL_OPTIONS.find((t) => t.value === toolName);
2864
+ if (tool) {
2865
+ selectedTool = tool.value;
2866
+ } else {
2867
+ console.log(
2868
+ pc14.yellow(`Tool '${toolName}' not found or not configurable.`)
2869
+ );
2870
+ }
2871
+ }
2872
+ if (!selectedTool) {
2873
+ const selection = await withCancelHandling(
2874
+ async () => prompts.select({
2875
+ message: "Select a tool to configure:",
2876
+ options: TOOL_OPTIONS
2877
+ })
2878
+ );
2879
+ selectedTool = selection;
2880
+ }
2881
+ config.enableTool(selectedTool);
2882
+ try {
2883
+ switch (selectedTool) {
2884
+ case "husky":
2885
+ await promptHusky(config);
2886
+ await installHusky(config);
2887
+ break;
2888
+ case "formatter":
2889
+ await promptFormatter(config);
2890
+ await installFormatter(config);
2891
+ break;
2892
+ case "linter":
2893
+ await promptLinter(config);
2894
+ await installLinter(config);
2895
+ break;
2896
+ case "lintStaged":
2897
+ await promptLintStaged(config);
2898
+ await installLintStaged(config);
2899
+ break;
2900
+ case "env":
2901
+ await promptEnv(config);
2902
+ await installEnv(config);
2903
+ break;
2904
+ case "test":
2905
+ await promptTest(config);
2906
+ await installTest(config);
2907
+ break;
2908
+ case "editorConfig":
2909
+ await promptEditorConfig(config);
2910
+ await installEditorConfig(config);
2911
+ break;
2912
+ case "license":
2913
+ await promptLicense(config);
2914
+ await installLicense(config);
2915
+ break;
2916
+ }
2917
+ prompts.outro(pc14.green(`${selectedTool} configured successfully!`));
2918
+ } catch (error) {
2919
+ prompts.outro(pc14.red(`Failed to configure ${selectedTool}.`));
2920
+ console.error(error);
2921
+ process.exit(1);
2922
+ }
2923
+ }
2924
+ var init_configure = __esm({
2925
+ "src/cli/commands/configure.ts"() {
2926
+ "use strict";
2927
+ init_esm_shims();
2928
+ init_prompts();
2929
+ init_config();
2930
+ init_options();
2931
+ init_husky();
2932
+ init_formatter();
2933
+ init_linter();
2934
+ init_lint_staged();
2935
+ init_env();
2936
+ init_test();
2937
+ init_editor_config();
2938
+ init_license();
2939
+ init_handle_cancel();
2940
+ init_display();
2941
+ init_git_check();
2942
+ }
2943
+ });
2944
+
2945
+ // src/cli/commands/plugin.ts
2946
+ import pc15 from "picocolors";
2947
+ async function plugin(toolName) {
2948
+ introScreen();
2949
+ prompts.intro(pc15.inverse(pc15.bold(pc15.magenta(" Plugin Manager "))));
2950
+ await gitCheck();
2951
+ if (!toolName) {
2952
+ toolName = await withCancelHandling(
2953
+ async () => prompts.select({
2954
+ message: "Select a tool to add plugins to:",
2955
+ options: [
2956
+ { value: "eslint", label: "ESLint" },
2957
+ { value: "prettier", label: "Prettier" }
2958
+ ]
2959
+ })
2960
+ );
2961
+ }
2962
+ await installPlugins(toolName);
2963
+ prompts.outro(pc15.green("Plugins installed successfully!"));
2964
+ }
2965
+ var init_plugin = __esm({
2966
+ "src/cli/commands/plugin.ts"() {
2967
+ "use strict";
2968
+ init_esm_shims();
2969
+ init_prompts();
2970
+ init_handle_cancel();
2971
+ init_display();
2972
+ init_git_check();
2973
+ init_install_plugin();
2974
+ }
2975
+ });
2976
+
2977
+ // src/cli/index.ts
2978
+ import pc16 from "picocolors";
1101
2979
  import { program } from "commander";
1102
2980
  var require_index = __commonJS({
1103
- "src/index.ts"() {
2981
+ "src/cli/index.ts"() {
1104
2982
  init_esm_shims();
2983
+ init_prompts();
1105
2984
  init_husky();
1106
2985
  init_formatter();
1107
2986
  init_linter();
@@ -1117,15 +2996,17 @@ var require_index = __commonJS({
1117
2996
  init_logger();
1118
2997
  init_git_check();
1119
2998
  init_display();
2999
+ init_configure();
3000
+ init_plugin();
1120
3001
  async function main() {
1121
3002
  try {
1122
3003
  introScreen();
1123
- intro(
1124
- pc11.inverse(pc11.bold(pc11.cyan(" Welcome to the Project Setup Wizard ")))
3004
+ prompts.intro(
3005
+ pc16.inverse(pc16.bold(pc16.cyan(" Welcome to the Project Setup Wizard ")))
1125
3006
  );
1126
3007
  await gitCheck();
1127
3008
  const tools = await withCancelHandling(
1128
- async () => multiselect3({
3009
+ async () => prompts.multiselect({
1129
3010
  message: "Select tools to configure:",
1130
3011
  options: TOOL_OPTIONS,
1131
3012
  required: false
@@ -1140,23 +3021,25 @@ var require_index = __commonJS({
1140
3021
  if (config.get("test").selected) await promptTest(config);
1141
3022
  if (config.get("editorConfig").selected) await promptEditorConfig(config);
1142
3023
  if (config.get("license").selected) await promptLicense(config);
1143
- note(config.summary, "Configuration Summary");
3024
+ prompts.note(config.summary, "Configuration Summary");
1144
3025
  const proceed = await withCancelHandling(
1145
- async () => confirm4({
3026
+ async () => prompts.confirm({
1146
3027
  message: "Do you want to proceed with the installation?"
1147
3028
  })
1148
3029
  );
1149
3030
  if (!proceed) {
1150
- outro(pc11.yellow("Installation cancelled."));
3031
+ prompts.outro(pc16.yellow("Installation cancelled."));
1151
3032
  process.exit(0);
1152
3033
  }
1153
3034
  await execution(config);
1154
- outro(pc11.green("Setup complete!"));
3035
+ prompts.outro(pc16.green("Setup complete!"));
1155
3036
  } catch (error) {
1156
3037
  const logPath = await logError(error);
1157
- outro(pc11.red(`
3038
+ prompts.outro(
3039
+ pc16.red(`
1158
3040
  Something went wrong!
1159
- Error log saved to: ${logPath}`));
3041
+ Error log saved to: ${logPath}`)
3042
+ );
1160
3043
  process.exit(1);
1161
3044
  }
1162
3045
  }
@@ -1178,6 +3061,14 @@ Error log saved to: ${logPath}`));
1178
3061
  showManual();
1179
3062
  process.exit(0);
1180
3063
  });
3064
+ program.command("configure [tool]").description("Configure a specific tool").action(async (tool) => {
3065
+ await configure(tool);
3066
+ process.exit(0);
3067
+ });
3068
+ program.command("plugin [tool]").description("Manage plugins for tools").action(async (tool) => {
3069
+ await plugin(tool);
3070
+ process.exit(0);
3071
+ });
1181
3072
  program.action(async (options) => {
1182
3073
  if (options.about) {
1183
3074
  showAbout();