@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.js CHANGED
@@ -32,13 +32,222 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
32
32
  mod
33
33
  ));
34
34
 
35
- // src/index.ts
36
- var import_prompts12 = require("@clack/prompts");
37
- var import_picocolors11 = __toESM(require("picocolors"));
38
- var import_commander = require("commander");
35
+ // src/utils/prompts/clack.ts
36
+ var import_prompts = require("@clack/prompts");
37
+ var ClackProvider = class {
38
+ intro(message) {
39
+ (0, import_prompts.intro)(message);
40
+ }
41
+ outro(message) {
42
+ (0, import_prompts.outro)(message);
43
+ }
44
+ async text(opts) {
45
+ return (0, import_prompts.text)(opts);
46
+ }
47
+ async confirm(opts) {
48
+ return (0, import_prompts.confirm)(opts);
49
+ }
50
+ async select(opts) {
51
+ return (0, import_prompts.select)({
52
+ message: opts.message,
53
+ options: opts.options.map((o) => ({
54
+ label: o.label,
55
+ value: o.value,
56
+ hint: o.hint
57
+ }))
58
+ });
59
+ }
60
+ async multiselect(opts) {
61
+ return (0, import_prompts.multiselect)({
62
+ message: opts.message,
63
+ options: opts.options.map((o) => ({
64
+ label: o.label,
65
+ value: o.value,
66
+ hint: o.hint
67
+ }))
68
+ });
69
+ }
70
+ note(message, title) {
71
+ (0, import_prompts.note)(message, title);
72
+ }
73
+ isCancel(value) {
74
+ return (0, import_prompts.isCancel)(value);
75
+ }
76
+ cancel(message) {
77
+ (0, import_prompts.cancel)(message);
78
+ }
79
+ log = {
80
+ message: (msg) => import_prompts.log.message(msg),
81
+ info: (msg) => import_prompts.log.info(msg),
82
+ success: (msg) => import_prompts.log.success(msg),
83
+ warn: (msg) => import_prompts.log.warn(msg),
84
+ error: (msg) => import_prompts.log.error(msg)
85
+ };
86
+ };
87
+
88
+ // src/utils/prompts/top.ts
89
+ var import_prompts2 = require("@topcli/prompts");
90
+ var import_picocolors = __toESM(require("picocolors"));
91
+ var CANCEL_SYMBOL = /* @__PURE__ */ Symbol("cancel");
92
+ var TopCliProvider = class {
93
+ intro(message) {
94
+ console.log(import_picocolors.default.bgCyan(import_picocolors.default.black(` ${message} `)));
95
+ }
96
+ outro(message) {
97
+ console.log(import_picocolors.default.bgCyan(import_picocolors.default.black(` ${message} `)));
98
+ }
99
+ async text(opts) {
100
+ try {
101
+ return await (0, import_prompts2.question)(opts.message, {
102
+ defaultValue: opts.initialValue || opts.defaultValue,
103
+ validators: [
104
+ {
105
+ validate: (value) => opts.validate?.(value) || ""
106
+ }
107
+ ]
108
+ });
109
+ } catch {
110
+ return CANCEL_SYMBOL;
111
+ }
112
+ }
113
+ async confirm(opts) {
114
+ try {
115
+ return await (0, import_prompts2.confirm)(opts.message, {
116
+ initial: opts.initialValue
117
+ });
118
+ } catch {
119
+ return CANCEL_SYMBOL;
120
+ }
121
+ }
122
+ async select(opts) {
123
+ try {
124
+ const optionMap = /* @__PURE__ */ new Map();
125
+ const choices = opts.options.map((o) => {
126
+ const key = String(o.value);
127
+ optionMap.set(key, o.value);
128
+ const isSelected = opts.initialValue === o.value;
129
+ return {
130
+ label: o.label,
131
+ value: key,
132
+ description: o.hint,
133
+ selected: isSelected
134
+ };
135
+ });
136
+ const resultKey = await (0, import_prompts2.select)(opts.message, {
137
+ choices,
138
+ autocomplete: true,
139
+ maxVisible: 10
140
+ });
141
+ return optionMap.get(resultKey);
142
+ } catch {
143
+ return CANCEL_SYMBOL;
144
+ }
145
+ }
146
+ async multiselect(opts) {
147
+ try {
148
+ const optionMap = /* @__PURE__ */ new Map();
149
+ const choices = opts.options.map((o) => {
150
+ const key = String(o.value);
151
+ optionMap.set(key, o.value);
152
+ const isSelected = opts.initialValue?.some((iv) => iv === o.value);
153
+ return {
154
+ label: o.label,
155
+ value: key,
156
+ description: o.hint,
157
+ selected: isSelected
158
+ };
159
+ });
160
+ const resultKeys = await (0, import_prompts2.multiselect)(opts.message, {
161
+ choices,
162
+ autocomplete: true,
163
+ maxVisible: 10,
164
+ showHint: true
165
+ });
166
+ return resultKeys.map((k) => optionMap.get(k));
167
+ } catch {
168
+ return CANCEL_SYMBOL;
169
+ }
170
+ }
171
+ note(message, title) {
172
+ if (title) {
173
+ console.log(import_picocolors.default.blue(import_picocolors.default.bold(`${title}`)));
174
+ }
175
+ console.log(import_picocolors.default.dim(message));
176
+ }
177
+ isCancel(value) {
178
+ return value === CANCEL_SYMBOL;
179
+ }
180
+ cancel(message) {
181
+ if (message) console.log(import_picocolors.default.red(import_picocolors.default.bold("\xD7")) + " " + message);
182
+ else console.log(import_picocolors.default.red(import_picocolors.default.bold("\xD7")) + " Operation cancelled.");
183
+ }
184
+ log = {
185
+ message: (msg) => console.log(msg),
186
+ info: (msg) => console.log(import_picocolors.default.blue(import_picocolors.default.bold("INFO")) + " " + msg),
187
+ success: (msg) => console.log(import_picocolors.default.green(import_picocolors.default.bold("SUCCESS")) + " " + msg),
188
+ warn: (msg) => console.log(import_picocolors.default.yellow(import_picocolors.default.bold("WARN")) + " " + msg),
189
+ error: (msg) => console.log(import_picocolors.default.red(import_picocolors.default.bold("ERROR")) + " " + msg)
190
+ };
191
+ };
192
+
193
+ // src/utils/prompts/index.ts
194
+ var Prompts = class _Prompts {
195
+ provider;
196
+ static instance;
197
+ constructor() {
198
+ this.provider = new TopCliProvider();
199
+ }
200
+ static getInstance() {
201
+ if (!_Prompts.instance) {
202
+ _Prompts.instance = new _Prompts();
203
+ }
204
+ return _Prompts.instance;
205
+ }
206
+ setProvider(provider) {
207
+ this.provider = provider;
208
+ }
209
+ useClack() {
210
+ this.provider = new ClackProvider();
211
+ }
212
+ useTopCli() {
213
+ this.provider = new TopCliProvider();
214
+ }
215
+ intro(message) {
216
+ this.provider.intro(message);
217
+ }
218
+ outro(message) {
219
+ this.provider.outro(message);
220
+ }
221
+ text(opts) {
222
+ return this.provider.text(opts);
223
+ }
224
+ confirm(opts) {
225
+ return this.provider.confirm(opts);
226
+ }
227
+ select(opts) {
228
+ return this.provider.select(opts);
229
+ }
230
+ multiselect(opts) {
231
+ return this.provider.multiselect(opts);
232
+ }
233
+ note(message, title) {
234
+ this.provider.note(message, title);
235
+ }
236
+ isCancel(value) {
237
+ return this.provider.isCancel(value);
238
+ }
239
+ cancel(message) {
240
+ this.provider.cancel(message);
241
+ }
242
+ get log() {
243
+ return this.provider.log;
244
+ }
245
+ };
246
+ var prompts = Prompts.getInstance();
39
247
 
40
- // src/services/husky.ts
41
- var import_prompts2 = require("@clack/prompts");
248
+ // src/cli/index.ts
249
+ var import_picocolors16 = __toESM(require("picocolors"));
250
+ var import_commander = require("commander");
42
251
 
43
252
  // src/utils/pm.ts
44
253
  var import_execa = require("execa");
@@ -70,10 +279,10 @@ async function installPackages(packages, dev = false) {
70
279
  await (0, import_execa.execa)(pm, [...args, ...packages]);
71
280
  }
72
281
 
73
- // src/services/husky.ts
282
+ // src/features/husky.ts
74
283
  var import_execa2 = require("execa");
75
284
  var import_fs_extra = __toESM(require("fs-extra"));
76
- var import_picocolors = __toESM(require("picocolors"));
285
+ var import_picocolors2 = __toESM(require("picocolors"));
77
286
 
78
287
  // src/constants/options.ts
79
288
  var TOOL_OPTIONS = [
@@ -158,16 +367,15 @@ var LICENSE_TYPE_OPTIONS = [
158
367
  ];
159
368
 
160
369
  // src/utils/handle-cancel.ts
161
- var import_prompts = require("@clack/prompts");
162
370
  async function withCancelHandling(promptFn, cancelMessage = "Operation cancelled.") {
163
371
  while (true) {
164
372
  const response = await promptFn();
165
- if ((0, import_prompts.isCancel)(response)) {
166
- const shouldCancel = await (0, import_prompts.confirm)({
373
+ if (prompts.isCancel(response)) {
374
+ const shouldCancel = await prompts.confirm({
167
375
  message: "Do you really want to cancel options selection?"
168
376
  });
169
- if ((0, import_prompts.isCancel)(shouldCancel) || shouldCancel) {
170
- (0, import_prompts.cancel)(cancelMessage);
377
+ if (prompts.isCancel(shouldCancel) || shouldCancel) {
378
+ prompts.cancel(cancelMessage);
171
379
  process.exit(0);
172
380
  }
173
381
  continue;
@@ -177,11 +385,11 @@ async function withCancelHandling(promptFn, cancelMessage = "Operation cancelled
177
385
  }
178
386
  }
179
387
 
180
- // src/services/husky.ts
388
+ // src/features/husky.ts
181
389
  async function promptHusky(config2) {
182
- import_prompts2.log.message(import_picocolors.default.bgMagenta(import_picocolors.default.black(" Husky Configuration ")));
390
+ prompts.log.message(import_picocolors2.default.bgMagenta(import_picocolors2.default.black(" Husky Configuration ")));
183
391
  const hookType = await withCancelHandling(
184
- async () => (0, import_prompts2.select)({
392
+ async () => prompts.select({
185
393
  message: "What pre-commit hook would you like to use?",
186
394
  options: HUSKY_HOOK_OPTIONS
187
395
  })
@@ -192,7 +400,7 @@ async function promptHusky(config2) {
192
400
  config2.enableTool("lintStaged");
193
401
  } else if (hookType === "custom") {
194
402
  const script = await withCancelHandling(
195
- async () => (0, import_prompts2.text)({
403
+ async () => prompts.text({
196
404
  message: "Enter your custom pre-commit script:",
197
405
  placeholder: huskyConfig.options.customScript,
198
406
  validate(value) {
@@ -207,7 +415,7 @@ async function installHusky(config2) {
207
415
  await installPackages(["husky"], true);
208
416
  try {
209
417
  await (0, import_execa2.execa)("npx", ["husky", "init"]);
210
- } catch (e) {
418
+ } catch {
211
419
  await (0, import_execa2.execa)("npm", ["pkg", "set", "scripts.prepare=husky"]);
212
420
  await (0, import_execa2.execa)("npm", ["run", "prepare"]);
213
421
  }
@@ -226,15 +434,1345 @@ async function installHusky(config2) {
226
434
  }
227
435
  }
228
436
 
229
- // src/services/formatter.ts
230
- var import_prompts3 = require("@clack/prompts");
437
+ // src/features/formatter.ts
438
+ var import_picocolors4 = __toESM(require("picocolors"));
439
+
440
+ // src/features/formatter/prettier.ts
441
+ var import_fs_extra3 = __toESM(require("fs-extra"));
442
+
443
+ // src/utils/config-file.ts
231
444
  var import_fs_extra2 = __toESM(require("fs-extra"));
232
- var import_picocolors2 = __toESM(require("picocolors"));
445
+ var import_node_path = __toESM(require("path"));
446
+ async function resolveConfigFile(toolName, candidates) {
447
+ for (const file of candidates) {
448
+ if (await import_fs_extra2.default.pathExists(file)) return file;
449
+ }
450
+ const response = await withCancelHandling(
451
+ async () => prompts.select({
452
+ message: `Where do you want to store the ${toolName} config?`,
453
+ options: candidates.map((c) => ({ value: c, label: c })),
454
+ initialValue: candidates[0]
455
+ })
456
+ );
457
+ return response;
458
+ }
459
+ async function writeConfig(filePath, config2) {
460
+ const ext = import_node_path.default.extname(filePath);
461
+ if (ext === ".json" || ext === "") {
462
+ await import_fs_extra2.default.writeJson(filePath, config2, { spaces: 2 });
463
+ } else if (ext === ".js" || ext === ".cjs") {
464
+ const content = `module.exports = ${JSON.stringify(config2, null, 2)};`;
465
+ await import_fs_extra2.default.writeFile(filePath, content);
466
+ } else if (ext === ".mjs") {
467
+ const content = `export default ${JSON.stringify(config2, null, 2)};`;
468
+ await import_fs_extra2.default.writeFile(filePath, content);
469
+ } else {
470
+ await import_fs_extra2.default.writeJson(filePath, config2, { spaces: 2 });
471
+ }
472
+ }
473
+
474
+ // src/features/formatter/prettier.ts
475
+ async function installPrettier() {
476
+ await installPackages(["prettier"], true);
477
+ const configFile = await resolveConfigFile("Prettier", [
478
+ ".prettierrc",
479
+ ".prettierrc.json",
480
+ "prettier.config.js",
481
+ ".prettierrc.js"
482
+ ]);
483
+ if (!await import_fs_extra3.default.pathExists(configFile)) {
484
+ await writeConfig(configFile, {
485
+ semi: true,
486
+ singleQuote: false,
487
+ tabWidth: 2,
488
+ trailingComma: "es5",
489
+ printWidth: 80,
490
+ plugins: []
491
+ });
492
+ }
493
+ if (!await import_fs_extra3.default.pathExists(".prettierignore")) {
494
+ await import_fs_extra3.default.writeFile(
495
+ ".prettierignore",
496
+ `node_modules
497
+ dist
498
+ coverage
499
+ .next
500
+ .nuxt
501
+ build
502
+ .astro
503
+ .output
504
+ `
505
+ );
506
+ }
507
+ }
508
+ async function configurePrettierPlugins(plugins) {
509
+ const configFile = await resolveConfigFile("Prettier", [
510
+ ".prettierrc",
511
+ ".prettierrc.json",
512
+ "prettier.config.js",
513
+ ".prettierrc.js"
514
+ ]);
515
+ let currentConfig = {};
516
+ if (await import_fs_extra3.default.pathExists(configFile)) {
517
+ try {
518
+ if (configFile.endsWith(".js") || configFile.endsWith(".cjs")) {
519
+ return;
520
+ }
521
+ currentConfig = await import_fs_extra3.default.readJson(configFile);
522
+ } catch {
523
+ }
524
+ }
525
+ const existingPlugins = currentConfig.plugins || [];
526
+ const newPlugins = [.../* @__PURE__ */ new Set([...existingPlugins, ...plugins])];
527
+ currentConfig.plugins = newPlugins;
528
+ await writeConfig(configFile, currentConfig);
529
+ }
530
+
531
+ // src/features/formatter/oxfmt.ts
532
+ async function installOxfmt() {
533
+ await installPackages(["oxfmt@latest"], true);
534
+ }
535
+
536
+ // src/constants/plugins.ts
537
+ var ESLINT_PLUGINS = [
538
+ // Code Quality
539
+ {
540
+ value: "depend",
541
+ label: "depend",
542
+ package: "eslint-plugin-depend",
543
+ hint: "Detect junk dependencies"
544
+ },
545
+ {
546
+ value: "github",
547
+ label: "github",
548
+ package: "eslint-plugin-github",
549
+ hint: "GitHub's ESLint rules"
550
+ },
551
+ {
552
+ value: "sonarjs",
553
+ label: "sonarjs",
554
+ package: "eslint-plugin-sonarjs",
555
+ hint: "Detect bugs and suspicious patterns"
556
+ },
557
+ {
558
+ value: "unicorn",
559
+ label: "unicorn",
560
+ package: "eslint-plugin-unicorn",
561
+ hint: "Various awesome ESLint rules"
562
+ },
563
+ {
564
+ value: "mysticatea",
565
+ label: "mysticatea",
566
+ package: "@mysticatea/eslint-plugin",
567
+ hint: "Misc rules"
568
+ },
569
+ {
570
+ value: "brettz9",
571
+ label: "brettz9",
572
+ package: "@brettz9/eslint-plugin",
573
+ hint: "Misc rules without personal config"
574
+ },
575
+ {
576
+ value: "de-morgan",
577
+ label: "de-morgan",
578
+ package: "eslint-plugin-de-morgan",
579
+ hint: "Transform logical expressions"
580
+ },
581
+ {
582
+ value: "code-complete",
583
+ label: "code-complete",
584
+ package: "eslint-plugin-code-complete",
585
+ hint: "Clean, maintainable software design"
586
+ },
587
+ // Compatibility
588
+ {
589
+ value: "compat",
590
+ label: "compat",
591
+ package: "eslint-plugin-compat",
592
+ hint: "Browser compatibility checking"
593
+ },
594
+ {
595
+ value: "es-compat",
596
+ label: "es-compat",
597
+ package: "eslint-plugin-es-compat",
598
+ hint: "Disable unsupported ES features"
599
+ },
600
+ {
601
+ value: "es-x",
602
+ label: "es-x",
603
+ package: "eslint-plugin-es-x",
604
+ hint: "Disable specific ES versions"
605
+ },
606
+ {
607
+ value: "es5",
608
+ label: "es5",
609
+ package: "eslint-plugin-es5",
610
+ hint: "Forbid ES2015+ usage"
611
+ },
612
+ {
613
+ value: "ie11",
614
+ label: "ie11",
615
+ package: "eslint-plugin-ie11",
616
+ hint: "Detect unsupported ES6 features in IE11"
617
+ },
618
+ // CSS in JS
619
+ {
620
+ value: "css-modules",
621
+ label: "css-modules",
622
+ package: "eslint-plugin-css-modules",
623
+ hint: "Lint css modules"
624
+ },
625
+ {
626
+ value: "emotion",
627
+ label: "emotion",
628
+ package: "@emotion/eslint-plugin",
629
+ hint: "Rules for emotion"
630
+ },
631
+ {
632
+ value: "better-styled-components",
633
+ label: "better-styled-components",
634
+ package: "eslint-plugin-better-styled-components",
635
+ hint: "Auto fixable rules for styled components"
636
+ },
637
+ {
638
+ value: "styled-components-a11y",
639
+ label: "styled-components-a11y",
640
+ package: "eslint-plugin-styled-components-a11y",
641
+ hint: "A11y for Styled Components"
642
+ },
643
+ {
644
+ value: "vanilla-extract",
645
+ label: "vanilla-extract",
646
+ package: "@vanilla-extract/eslint-plugin",
647
+ hint: "Enforce CSS property ordering"
648
+ },
649
+ // Deprecation
650
+ {
651
+ value: "deprecate",
652
+ label: "deprecate",
653
+ package: "eslint-plugin-deprecate",
654
+ hint: "Mark functions/modules as deprecated"
655
+ },
656
+ {
657
+ value: "disable",
658
+ label: "disable",
659
+ package: "eslint-plugin-disable",
660
+ hint: "Disable plugins using patterns"
661
+ },
662
+ // Embedded
663
+ {
664
+ value: "html",
665
+ label: "html",
666
+ package: "eslint-plugin-html",
667
+ hint: "Linting JS inside HTML"
668
+ },
669
+ {
670
+ value: "markdown",
671
+ label: "markdown",
672
+ package: "eslint-plugin-markdown",
673
+ hint: "Linting JS inside Markdown"
674
+ },
675
+ // Frameworks
676
+ {
677
+ value: "angular",
678
+ label: "angular",
679
+ package: "@angular-eslint/eslint-plugin",
680
+ hint: "Linting for Angular"
681
+ },
682
+ {
683
+ value: "angularjs",
684
+ label: "angularjs",
685
+ package: "eslint-plugin-angular",
686
+ hint: "Linting for AngularJS"
687
+ },
688
+ {
689
+ value: "astro",
690
+ label: "astro",
691
+ package: "eslint-plugin-astro",
692
+ hint: "Linting for Astro"
693
+ },
694
+ {
695
+ value: "backbone",
696
+ label: "backbone",
697
+ package: "eslint-plugin-backbone",
698
+ hint: "Linting for Backbone"
699
+ },
700
+ {
701
+ value: "ember",
702
+ label: "ember",
703
+ package: "eslint-plugin-ember",
704
+ hint: "Linting for Ember"
705
+ },
706
+ {
707
+ value: "hapi",
708
+ label: "hapi",
709
+ package: "eslint-plugin-hapi",
710
+ hint: "Linting for Hapi"
711
+ },
712
+ {
713
+ value: "meteor",
714
+ label: "meteor",
715
+ package: "eslint-plugin-meteor",
716
+ hint: "Linting for Meteor"
717
+ },
718
+ {
719
+ value: "jsx-a11y",
720
+ label: "jsx-a11y",
721
+ package: "eslint-plugin-jsx-a11y",
722
+ hint: "Accessibility rules on JSX"
723
+ },
724
+ {
725
+ value: "react",
726
+ label: "react",
727
+ package: "eslint-plugin-react",
728
+ hint: "Linting for React/JSX"
729
+ },
730
+ {
731
+ value: "react-hooks",
732
+ label: "react-hooks",
733
+ package: "eslint-plugin-react-hooks",
734
+ hint: "Linting for React Hooks"
735
+ },
736
+ {
737
+ value: "react-native",
738
+ label: "react-native",
739
+ package: "eslint-plugin-react-native",
740
+ hint: "React Native specific rules"
741
+ },
742
+ {
743
+ value: "react-redux",
744
+ label: "react-redux",
745
+ package: "eslint-plugin-react-redux",
746
+ hint: "React-Redux specific rules"
747
+ },
748
+ {
749
+ value: "react-refresh",
750
+ label: "react-refresh",
751
+ package: "eslint-plugin-react-refresh",
752
+ hint: "Improve HMR with Vite"
753
+ },
754
+ {
755
+ value: "solid",
756
+ label: "solid",
757
+ package: "eslint-plugin-solid",
758
+ hint: "Linting for Solid"
759
+ },
760
+ {
761
+ value: "svelte",
762
+ label: "svelte",
763
+ package: "eslint-plugin-svelte",
764
+ hint: "Linting for Svelte"
765
+ },
766
+ {
767
+ value: "vuejs",
768
+ label: "vuejs",
769
+ package: "eslint-plugin-vue",
770
+ hint: "Linting for VueJS"
771
+ },
772
+ {
773
+ value: "vue-scoped-css",
774
+ label: "vue-scoped-css",
775
+ package: "eslint-plugin-vue-scoped-css",
776
+ hint: "Scoped CSS in VueJS"
777
+ },
778
+ // Languages and Environments
779
+ {
780
+ value: "babel",
781
+ label: "babel",
782
+ package: "@babel/eslint-plugin",
783
+ hint: "Babel features"
784
+ },
785
+ {
786
+ value: "flowtype",
787
+ label: "flowtype",
788
+ package: "eslint-plugin-flowtype",
789
+ hint: "Flow type linting"
790
+ },
791
+ {
792
+ value: "flowtype-errors",
793
+ label: "flowtype-errors",
794
+ package: "eslint-plugin-flowtype-errors",
795
+ hint: "Run Flow as plugin"
796
+ },
797
+ {
798
+ value: "html-eslint",
799
+ label: "html-eslint",
800
+ package: "@html-eslint/eslint-plugin",
801
+ hint: "Linting for HTML"
802
+ },
803
+ {
804
+ value: "json",
805
+ label: "json",
806
+ package: "eslint-plugin-json",
807
+ hint: "Lint JSON files"
808
+ },
809
+ {
810
+ value: "json-format",
811
+ label: "json-format",
812
+ package: "eslint-plugin-json-format",
813
+ hint: "Lint/Format/Fix JSON"
814
+ },
815
+ {
816
+ value: "jsonc",
817
+ label: "jsonc",
818
+ package: "eslint-plugin-jsonc",
819
+ hint: "JSON with comments"
820
+ },
821
+ {
822
+ value: "json-schema-validator",
823
+ label: "json-schema-validator",
824
+ package: "eslint-plugin-json-schema-validator",
825
+ hint: "Validate data using JSON Schema"
826
+ },
827
+ {
828
+ value: "package-json",
829
+ label: "package-json",
830
+ package: "eslint-plugin-package-json",
831
+ hint: "Rules for package.json"
832
+ },
833
+ {
834
+ value: "mdx",
835
+ label: "mdx",
836
+ package: "eslint-plugin-mdx",
837
+ hint: "Lint MDX"
838
+ },
839
+ { value: "n", label: "n", package: "eslint-plugin-n", hint: "Node.js rules" },
840
+ {
841
+ value: "sql",
842
+ label: "sql",
843
+ package: "eslint-plugin-sql",
844
+ hint: "SQL linting"
845
+ },
846
+ {
847
+ value: "toml",
848
+ label: "toml",
849
+ package: "eslint-plugin-toml",
850
+ hint: "Lint TOML"
851
+ },
852
+ {
853
+ value: "typescript",
854
+ label: "typescript",
855
+ package: "@typescript-eslint/eslint-plugin",
856
+ hint: "Lint TypeScript"
857
+ },
858
+ {
859
+ value: "erasable-syntax-only",
860
+ label: "erasable-syntax-only",
861
+ package: "eslint-plugin-erasable-syntax-only",
862
+ hint: "Enforce TS erasableSyntaxOnly"
863
+ },
864
+ {
865
+ value: "expect-type",
866
+ label: "expect-type",
867
+ package: "eslint-plugin-expect-type",
868
+ hint: "Type assertions"
869
+ },
870
+ {
871
+ value: "yaml",
872
+ label: "yaml",
873
+ package: "eslint-plugin-yml",
874
+ hint: "Lint YAML"
875
+ },
876
+ // Libraries
877
+ {
878
+ value: "graphql",
879
+ label: "graphql",
880
+ package: "@graphql-eslint/eslint-plugin",
881
+ hint: "Validate GraphQL operations/schema"
882
+ },
883
+ {
884
+ value: "graphql-schema",
885
+ label: "graphql-schema",
886
+ package: "eslint-plugin-graphql",
887
+ hint: "Check GraphQL queries against schema"
888
+ },
889
+ {
890
+ value: "type-graphql",
891
+ label: "type-graphql",
892
+ package: "eslint-plugin-type-graphql",
893
+ hint: "Lint TypeGraphQL"
894
+ },
895
+ {
896
+ value: "jquery",
897
+ label: "jquery",
898
+ package: "eslint-plugin-no-jquery",
899
+ hint: "Lint jQuery (deprecated features)"
900
+ },
901
+ {
902
+ value: "jsdoc",
903
+ label: "jsdoc",
904
+ package: "eslint-plugin-jsdoc",
905
+ hint: "Lint JSDoc comments"
906
+ },
907
+ {
908
+ value: "lodash",
909
+ label: "lodash",
910
+ package: "eslint-plugin-lodash",
911
+ hint: "Lodash rules"
912
+ },
913
+ {
914
+ value: "lodash-fp",
915
+ label: "lodash-fp",
916
+ package: "eslint-plugin-lodash-fp",
917
+ hint: "Lodash/fp rules"
918
+ },
919
+ {
920
+ value: "lodash-template",
921
+ label: "lodash-template",
922
+ package: "eslint-plugin-lodash-template",
923
+ hint: "Lodash template rules"
924
+ },
925
+ {
926
+ value: "microtemplates",
927
+ label: "microtemplates",
928
+ package: "eslint-plugin-microtemplates",
929
+ hint: "Microtemplates rules"
930
+ },
931
+ {
932
+ value: "mongodb",
933
+ label: "mongodb",
934
+ package: "eslint-plugin-mongodb",
935
+ hint: "MongoDB driver rules"
936
+ },
937
+ {
938
+ value: "ramda",
939
+ label: "ramda",
940
+ package: "eslint-plugin-ramda",
941
+ hint: "Ramda rules"
942
+ },
943
+ {
944
+ value: "requirejs",
945
+ label: "requirejs",
946
+ package: "eslint-plugin-requirejs",
947
+ hint: "RequireJS rules"
948
+ },
949
+ {
950
+ value: "tailwindcss",
951
+ label: "tailwindcss",
952
+ package: "eslint-plugin-tailwindcss",
953
+ hint: "Tailwind CSS rules"
954
+ },
955
+ {
956
+ value: "better-tailwindcss",
957
+ label: "better-tailwindcss",
958
+ package: "eslint-plugin-better-tailwindcss",
959
+ hint: "Improve readability/best practices"
960
+ },
961
+ // Misc
962
+ {
963
+ value: "diff",
964
+ label: "diff",
965
+ package: "eslint-plugin-diff",
966
+ hint: "Lint changed lines only"
967
+ },
968
+ {
969
+ value: "misc",
970
+ label: "misc",
971
+ package: "eslint-plugin-misc",
972
+ hint: "Miscellaneous rules"
973
+ },
974
+ {
975
+ value: "notice",
976
+ label: "notice",
977
+ package: "eslint-plugin-notice",
978
+ hint: "Check top of files"
979
+ },
980
+ {
981
+ value: "only-error",
982
+ label: "only-error",
983
+ package: "eslint-plugin-only-error",
984
+ hint: "Convert all rules to errors"
985
+ },
986
+ {
987
+ value: "only-warn",
988
+ label: "only-warn",
989
+ package: "eslint-plugin-only-warn",
990
+ hint: "Convert all rules to warnings"
991
+ },
992
+ {
993
+ value: "putout",
994
+ label: "putout",
995
+ package: "eslint-plugin-putout",
996
+ hint: "Integrate PutOut linter"
997
+ },
998
+ {
999
+ value: "typelint",
1000
+ label: "typelint",
1001
+ package: "eslint-plugin-typelint",
1002
+ hint: "Introduce types based on schemas"
1003
+ },
1004
+ {
1005
+ value: "woke",
1006
+ label: "woke",
1007
+ package: "eslint-plugin-woke",
1008
+ hint: "Catch insensitive words"
1009
+ },
1010
+ // Practices and Specific ES Features
1011
+ {
1012
+ value: "array-func",
1013
+ label: "array-func",
1014
+ package: "eslint-plugin-array-func",
1015
+ hint: "Avoid redundancy with array methods"
1016
+ },
1017
+ {
1018
+ value: "proper-arrows",
1019
+ label: "proper-arrows",
1020
+ package: "eslint-plugin-proper-arrows",
1021
+ hint: "Ensure proper arrow function definitions"
1022
+ },
1023
+ {
1024
+ value: "boundaries",
1025
+ label: "boundaries",
1026
+ package: "eslint-plugin-boundaries",
1027
+ hint: "Enforce architecture boundaries"
1028
+ },
1029
+ {
1030
+ value: "eslint-comments",
1031
+ label: "eslint-comments",
1032
+ package: "eslint-plugin-eslint-comments",
1033
+ hint: "Best practices for ESLint directives"
1034
+ },
1035
+ {
1036
+ value: "error-cause",
1037
+ label: "error-cause",
1038
+ package: "eslint-plugin-error-cause",
1039
+ hint: "Preserve error context"
1040
+ },
1041
+ {
1042
+ value: "hexagonal-architecture",
1043
+ label: "hexagonal-architecture",
1044
+ package: "eslint-plugin-hexagonal-architecture",
1045
+ hint: "Hexagonal architecture best practices"
1046
+ },
1047
+ {
1048
+ value: "signature-design",
1049
+ label: "signature-design",
1050
+ package: "eslint-plugin-signature-design",
1051
+ hint: "Enforce object-based signatures"
1052
+ },
1053
+ {
1054
+ value: "write-good-comments",
1055
+ label: "write-good-comments",
1056
+ package: "eslint-plugin-write-good-comments",
1057
+ hint: "Enforce good comment style"
1058
+ },
1059
+ {
1060
+ value: "exception-handling",
1061
+ label: "exception-handling",
1062
+ package: "eslint-plugin-exception-handling",
1063
+ hint: "Lint unhandled exceptions"
1064
+ },
1065
+ {
1066
+ value: "fp",
1067
+ label: "fp",
1068
+ package: "eslint-plugin-fp",
1069
+ hint: "Functional programming rules"
1070
+ },
1071
+ {
1072
+ value: "functional",
1073
+ label: "functional",
1074
+ package: "eslint-plugin-functional",
1075
+ hint: "Disable mutation, promote FP"
1076
+ },
1077
+ {
1078
+ value: "mutate",
1079
+ label: "mutate",
1080
+ package: "eslint-plugin-mutate",
1081
+ hint: "Prevent accidental mutations"
1082
+ },
1083
+ {
1084
+ value: "immutable",
1085
+ label: "immutable",
1086
+ package: "eslint-plugin-immutable",
1087
+ hint: "Disable all mutation"
1088
+ },
1089
+ {
1090
+ value: "import",
1091
+ label: "import",
1092
+ package: "eslint-plugin-import",
1093
+ hint: "Lint import/export syntax"
1094
+ },
1095
+ {
1096
+ value: "import-x",
1097
+ label: "import-x",
1098
+ package: "eslint-plugin-import-x",
1099
+ hint: "Lightweight fork of eslint-plugin-import"
1100
+ },
1101
+ {
1102
+ value: "math",
1103
+ label: "math",
1104
+ package: "eslint-plugin-math",
1105
+ hint: "Math object rules"
1106
+ },
1107
+ {
1108
+ value: "new-with-error",
1109
+ label: "new-with-error",
1110
+ package: "eslint-plugin-new-with-error",
1111
+ hint: "Require new with Error"
1112
+ },
1113
+ {
1114
+ value: "no-argument-spread",
1115
+ label: "no-argument-spread",
1116
+ package: "eslint-plugin-no-argument-spread",
1117
+ hint: "Lint against spread arguments"
1118
+ },
1119
+ {
1120
+ value: "no-comments",
1121
+ label: "no-comments",
1122
+ package: "eslint-plugin-no-comments",
1123
+ hint: "Prevent leaking comments"
1124
+ },
1125
+ {
1126
+ value: "no-constructor-bind",
1127
+ label: "no-constructor-bind",
1128
+ package: "eslint-plugin-no-constructor-bind",
1129
+ hint: "Encourage class properties"
1130
+ },
1131
+ {
1132
+ value: "no-inferred-method-name",
1133
+ label: "no-inferred-method-name",
1134
+ package: "eslint-plugin-no-inferred-method-name",
1135
+ hint: "Check inferred method names"
1136
+ },
1137
+ {
1138
+ value: "no-loops",
1139
+ label: "no-loops",
1140
+ package: "eslint-plugin-no-loops",
1141
+ hint: "Disallow loops"
1142
+ },
1143
+ {
1144
+ value: "query",
1145
+ label: "query",
1146
+ package: "eslint-plugin-query",
1147
+ hint: "Show queried syntax content"
1148
+ },
1149
+ {
1150
+ value: "no-use-extend-native",
1151
+ label: "no-use-extend-native",
1152
+ package: "eslint-plugin-no-use-extend-native",
1153
+ hint: "Prevent using extended native objects"
1154
+ },
1155
+ {
1156
+ value: "promise",
1157
+ label: "promise",
1158
+ package: "eslint-plugin-promise",
1159
+ hint: "Promise best practices"
1160
+ },
1161
+ {
1162
+ value: "pure",
1163
+ label: "pure",
1164
+ package: "eslint-plugin-pure",
1165
+ hint: "Enforce pure functions"
1166
+ },
1167
+ {
1168
+ value: "redos",
1169
+ label: "redos",
1170
+ package: "eslint-plugin-redos",
1171
+ hint: "Find ReDoS vulnerabilities"
1172
+ },
1173
+ {
1174
+ value: "redos-detector",
1175
+ label: "redos-detector",
1176
+ package: "eslint-plugin-redos-detector",
1177
+ hint: "Find ReDoS vulnerabilities"
1178
+ },
1179
+ {
1180
+ value: "regexp",
1181
+ label: "regexp",
1182
+ package: "eslint-plugin-regexp",
1183
+ hint: "Find regexp mistakes"
1184
+ },
1185
+ {
1186
+ value: "sort-keys-fix",
1187
+ label: "sort-keys-fix",
1188
+ package: "eslint-plugin-sort-keys-fix",
1189
+ hint: "Fixer for sort-keys"
1190
+ },
1191
+ {
1192
+ value: "this",
1193
+ label: "this",
1194
+ package: "eslint-plugin-this",
1195
+ hint: "Disallow this"
1196
+ },
1197
+ {
1198
+ value: "toplevel",
1199
+ label: "toplevel",
1200
+ package: "eslint-plugin-toplevel",
1201
+ hint: "Disallow side effects at top level"
1202
+ },
1203
+ // Performance
1204
+ {
1205
+ value: "dom",
1206
+ label: "dom",
1207
+ package: "eslint-plugin-dom",
1208
+ hint: "DOM performance"
1209
+ },
1210
+ {
1211
+ value: "optimize-regex",
1212
+ label: "optimize-regex",
1213
+ package: "eslint-plugin-optimize-regex",
1214
+ hint: "Optimize regex literals"
1215
+ },
1216
+ {
1217
+ value: "perf-standard",
1218
+ label: "perf-standard",
1219
+ package: "eslint-plugin-perf-standard",
1220
+ hint: "Performance standard rules"
1221
+ },
1222
+ // Security
1223
+ {
1224
+ value: "no-secrets",
1225
+ label: "no-secrets",
1226
+ package: "eslint-plugin-no-secrets",
1227
+ hint: "Detect potential secrets"
1228
+ },
1229
+ {
1230
+ value: "no-unsanitized",
1231
+ label: "no-unsanitized",
1232
+ package: "eslint-plugin-no-unsanitized",
1233
+ hint: "Checks for innerHTML etc"
1234
+ },
1235
+ {
1236
+ value: "pii",
1237
+ label: "pii",
1238
+ package: "eslint-plugin-pii",
1239
+ hint: "Enforce PII compliance"
1240
+ },
1241
+ {
1242
+ value: "pg",
1243
+ label: "pg",
1244
+ package: "eslint-plugin-pg",
1245
+ hint: "PostgreSQL security"
1246
+ },
1247
+ {
1248
+ value: "security",
1249
+ label: "security",
1250
+ package: "eslint-plugin-security",
1251
+ hint: "Node Security rules"
1252
+ },
1253
+ {
1254
+ value: "xss",
1255
+ label: "xss",
1256
+ package: "eslint-plugin-xss",
1257
+ hint: "Detect XSS issues"
1258
+ },
1259
+ // Style
1260
+ {
1261
+ value: "stylistic",
1262
+ label: "stylistic",
1263
+ package: "@stylistic/eslint-plugin",
1264
+ hint: "Formatting and stylistic rules"
1265
+ },
1266
+ {
1267
+ value: "const-case",
1268
+ label: "const-case",
1269
+ package: "eslint-plugin-const-case",
1270
+ hint: "Enforce capitalization of constants"
1271
+ },
1272
+ {
1273
+ value: "editorconfig",
1274
+ label: "editorconfig",
1275
+ package: "eslint-plugin-editorconfig",
1276
+ hint: "Derive rules from .editorconfig"
1277
+ },
1278
+ {
1279
+ value: "simple-import-sort",
1280
+ label: "simple-import-sort",
1281
+ package: "eslint-plugin-simple-import-sort",
1282
+ hint: "Easy import sorting"
1283
+ },
1284
+ {
1285
+ value: "perfectionist",
1286
+ label: "perfectionist",
1287
+ package: "eslint-plugin-perfectionist",
1288
+ hint: "Sort objects, imports, etc."
1289
+ },
1290
+ {
1291
+ value: "split-and-sort-imports",
1292
+ label: "split-and-sort-imports",
1293
+ package: "eslint-plugin-split-and-sort-imports",
1294
+ hint: "Split and sort imports"
1295
+ },
1296
+ {
1297
+ value: "switch-case",
1298
+ label: "switch-case",
1299
+ package: "eslint-plugin-switch-case",
1300
+ hint: "Switch-case specific rules"
1301
+ },
1302
+ {
1303
+ value: "padding",
1304
+ label: "padding",
1305
+ package: "eslint-plugin-padding",
1306
+ hint: "Padding between statements"
1307
+ },
1308
+ {
1309
+ value: "paths",
1310
+ label: "paths",
1311
+ package: "eslint-plugin-paths",
1312
+ hint: "Use paths from tsconfig/jsconfig"
1313
+ },
1314
+ {
1315
+ value: "no-relative-imports",
1316
+ label: "no-relative-imports",
1317
+ package: "@gitbutler/no-relative-imports",
1318
+ hint: "Auto fix relative paths"
1319
+ },
1320
+ // Testing Tools
1321
+ {
1322
+ value: "ava",
1323
+ label: "ava",
1324
+ package: "eslint-plugin-ava",
1325
+ hint: "AVA rules"
1326
+ },
1327
+ {
1328
+ value: "chai-expect",
1329
+ label: "chai-expect",
1330
+ package: "eslint-plugin-chai-expect",
1331
+ hint: "Chai expect practices"
1332
+ },
1333
+ {
1334
+ value: "chai-friendly",
1335
+ label: "chai-friendly",
1336
+ package: "eslint-plugin-chai-friendly",
1337
+ hint: "Chai unused expressions"
1338
+ },
1339
+ {
1340
+ value: "chai-expect-keywords",
1341
+ label: "chai-expect-keywords",
1342
+ package: "eslint-plugin-chai-expect-keywords",
1343
+ hint: "Permitted keywords"
1344
+ },
1345
+ {
1346
+ value: "chai-as-promised",
1347
+ label: "chai-as-promised",
1348
+ package: "eslint-plugin-chai-as-promised",
1349
+ hint: "Chai as promised"
1350
+ },
1351
+ {
1352
+ value: "chai-assert-bdd",
1353
+ label: "chai-assert-bdd",
1354
+ package: "eslint-plugin-chai-assert-bdd",
1355
+ hint: "Chai globals"
1356
+ },
1357
+ {
1358
+ value: "cucumber",
1359
+ label: "cucumber",
1360
+ package: "eslint-plugin-cucumber",
1361
+ hint: "Cucumber rules"
1362
+ },
1363
+ {
1364
+ value: "cypress",
1365
+ label: "cypress",
1366
+ package: "eslint-plugin-cypress",
1367
+ hint: "Cypress rules"
1368
+ },
1369
+ {
1370
+ value: "jasmine",
1371
+ label: "jasmine",
1372
+ package: "eslint-plugin-jasmine",
1373
+ hint: "Jasmine rules"
1374
+ },
1375
+ {
1376
+ value: "jest",
1377
+ label: "jest",
1378
+ package: "eslint-plugin-jest",
1379
+ hint: "Jest practices"
1380
+ },
1381
+ {
1382
+ value: "jest-formatting",
1383
+ label: "jest-formatting",
1384
+ package: "eslint-plugin-jest-formatting",
1385
+ hint: "Jest formatting"
1386
+ },
1387
+ {
1388
+ value: "jest-async",
1389
+ label: "jest-async",
1390
+ package: "eslint-plugin-jest-async",
1391
+ hint: "Jest async rules"
1392
+ },
1393
+ {
1394
+ value: "jest-dom",
1395
+ label: "jest-dom",
1396
+ package: "eslint-plugin-jest-dom",
1397
+ hint: "Jest-DOM rules"
1398
+ },
1399
+ {
1400
+ value: "mocha",
1401
+ label: "mocha",
1402
+ package: "eslint-plugin-mocha",
1403
+ hint: "Mocha practices"
1404
+ },
1405
+ {
1406
+ value: "mocha-cleanup",
1407
+ label: "mocha-cleanup",
1408
+ package: "eslint-plugin-mocha-cleanup",
1409
+ hint: "Mocha cleanup"
1410
+ },
1411
+ {
1412
+ value: "playwright",
1413
+ label: "playwright",
1414
+ package: "eslint-plugin-playwright",
1415
+ hint: "Playwright rules"
1416
+ },
1417
+ {
1418
+ value: "qunit",
1419
+ label: "qunit",
1420
+ package: "eslint-plugin-qunit",
1421
+ hint: "QUnit rules"
1422
+ },
1423
+ {
1424
+ value: "testcafe-community",
1425
+ label: "testcafe-community",
1426
+ package: "eslint-plugin-testcafe-community",
1427
+ hint: "TestCafe rules"
1428
+ },
1429
+ {
1430
+ value: "testing-library",
1431
+ label: "testing-library",
1432
+ package: "eslint-plugin-testing-library",
1433
+ hint: "Testing Library rules"
1434
+ }
1435
+ ];
1436
+ var PRETTIER_PLUGINS = [
1437
+ // Official
1438
+ {
1439
+ value: "php",
1440
+ label: "php",
1441
+ package: "@prettier/plugin-php",
1442
+ hint: "Prettier for PHP"
1443
+ },
1444
+ {
1445
+ value: "pug",
1446
+ label: "pug",
1447
+ package: "@prettier/plugin-pug",
1448
+ hint: "Prettier for Pug"
1449
+ },
1450
+ {
1451
+ value: "ruby",
1452
+ label: "ruby",
1453
+ package: "@prettier/plugin-ruby",
1454
+ hint: "Prettier for Ruby"
1455
+ },
1456
+ {
1457
+ value: "xml",
1458
+ label: "xml",
1459
+ package: "@prettier/plugin-xml",
1460
+ hint: "Prettier for XML"
1461
+ },
1462
+ // Community
1463
+ {
1464
+ value: "apex",
1465
+ label: "apex",
1466
+ package: "prettier-plugin-apex",
1467
+ hint: "Prettier for Apex"
1468
+ },
1469
+ {
1470
+ value: "astro",
1471
+ label: "astro",
1472
+ package: "prettier-plugin-astro",
1473
+ hint: "Prettier for Astro"
1474
+ },
1475
+ {
1476
+ value: "bigcommerce",
1477
+ label: "bigcommerce",
1478
+ package: "prettier-plugin-bigcommerce-stencil",
1479
+ hint: "Prettier for BigCommerce"
1480
+ },
1481
+ {
1482
+ value: "elm",
1483
+ label: "elm",
1484
+ package: "prettier-plugin-elm",
1485
+ hint: "Prettier for Elm"
1486
+ },
1487
+ {
1488
+ value: "erb",
1489
+ label: "erb",
1490
+ package: "prettier-plugin-erb",
1491
+ hint: "Prettier for ERB"
1492
+ },
1493
+ {
1494
+ value: "gherkin",
1495
+ label: "gherkin",
1496
+ package: "prettier-plugin-gherkin",
1497
+ hint: "Prettier for Gherkin"
1498
+ },
1499
+ {
1500
+ value: "glsl",
1501
+ label: "glsl",
1502
+ package: "prettier-plugin-glsl",
1503
+ hint: "Prettier for GLSL"
1504
+ },
1505
+ {
1506
+ value: "go-template",
1507
+ label: "go-template",
1508
+ package: "prettier-plugin-go-template",
1509
+ hint: "Prettier for Go Templates"
1510
+ },
1511
+ {
1512
+ value: "hugo",
1513
+ label: "hugo",
1514
+ package: "prettier-plugin-hugo-post",
1515
+ hint: "Prettier for Hugo"
1516
+ },
1517
+ {
1518
+ value: "java",
1519
+ label: "java",
1520
+ package: "prettier-plugin-java",
1521
+ hint: "Prettier for Java"
1522
+ },
1523
+ {
1524
+ value: "jinja",
1525
+ label: "jinja",
1526
+ package: "prettier-plugin-jinja-template",
1527
+ hint: "Prettier for Jinja"
1528
+ },
1529
+ {
1530
+ value: "jsonata",
1531
+ label: "jsonata",
1532
+ package: "prettier-plugin-jsonata",
1533
+ hint: "Prettier for JSONata"
1534
+ },
1535
+ {
1536
+ value: "kotlin",
1537
+ label: "kotlin",
1538
+ package: "prettier-plugin-kotlin",
1539
+ hint: "Prettier for Kotlin"
1540
+ },
1541
+ {
1542
+ value: "marko",
1543
+ label: "marko",
1544
+ package: "prettier-plugin-marko",
1545
+ hint: "Prettier for Marko"
1546
+ },
1547
+ {
1548
+ value: "motoko",
1549
+ label: "motoko",
1550
+ package: "prettier-plugin-motoko",
1551
+ hint: "Prettier for Motoko"
1552
+ },
1553
+ {
1554
+ value: "nginx",
1555
+ label: "nginx",
1556
+ package: "prettier-plugin-nginx",
1557
+ hint: "Prettier for Nginx"
1558
+ },
1559
+ {
1560
+ value: "prisma",
1561
+ label: "prisma",
1562
+ package: "prettier-plugin-prisma",
1563
+ hint: "Prettier for Prisma"
1564
+ },
1565
+ {
1566
+ value: "properties",
1567
+ label: "properties",
1568
+ package: "prettier-plugin-properties",
1569
+ hint: "Prettier for Properties"
1570
+ },
1571
+ {
1572
+ value: "rust",
1573
+ label: "rust",
1574
+ package: "prettier-plugin-rust",
1575
+ hint: "Prettier for Rust"
1576
+ },
1577
+ {
1578
+ value: "sh",
1579
+ label: "sh",
1580
+ package: "prettier-plugin-sh",
1581
+ hint: "Prettier for Shell"
1582
+ },
1583
+ {
1584
+ value: "sql",
1585
+ label: "sql",
1586
+ package: "prettier-plugin-sql",
1587
+ hint: "Prettier for SQL"
1588
+ },
1589
+ {
1590
+ value: "sql-cst",
1591
+ label: "sql-cst",
1592
+ package: "prettier-plugin-sql-cst",
1593
+ hint: "Prettier for SQL (CST)"
1594
+ },
1595
+ {
1596
+ value: "solidity",
1597
+ label: "solidity",
1598
+ package: "prettier-plugin-solidity",
1599
+ hint: "Prettier for Solidity"
1600
+ },
1601
+ {
1602
+ value: "svelte",
1603
+ label: "svelte",
1604
+ package: "prettier-plugin-svelte",
1605
+ hint: "Prettier for Svelte"
1606
+ },
1607
+ {
1608
+ value: "toml",
1609
+ label: "toml",
1610
+ package: "prettier-plugin-toml",
1611
+ hint: "Prettier for TOML"
1612
+ },
1613
+ {
1614
+ value: "xquery",
1615
+ label: "xquery",
1616
+ package: "prettier-plugin-xquery",
1617
+ hint: "Prettier for XQuery"
1618
+ },
1619
+ // Existing
1620
+ {
1621
+ value: "tailwindcss",
1622
+ label: "tailwindcss",
1623
+ package: "prettier-plugin-tailwindcss",
1624
+ hint: "Prettier for Tailwind CSS"
1625
+ },
1626
+ {
1627
+ value: "organize-imports",
1628
+ label: "organize-imports",
1629
+ package: "prettier-plugin-organize-imports",
1630
+ hint: "Organize imports"
1631
+ },
1632
+ {
1633
+ value: "sort-imports",
1634
+ label: "sort-imports",
1635
+ package: "@trivago/prettier-plugin-sort-imports",
1636
+ hint: "Sort imports"
1637
+ },
1638
+ {
1639
+ value: "pkg",
1640
+ label: "pkg",
1641
+ package: "prettier-plugin-pkg",
1642
+ hint: "Format package.json"
1643
+ }
1644
+ ];
1645
+ var PLUGINS = {
1646
+ eslint: ESLINT_PLUGINS,
1647
+ prettier: PRETTIER_PLUGINS
1648
+ };
1649
+ var PLUGINABLE_TOOLS = Object.keys(PLUGINS);
1650
+
1651
+ // src/features/linter/eslint.ts
1652
+ var import_fs_extra4 = __toESM(require("fs-extra"));
1653
+ async function installEslint() {
1654
+ const packages = ["eslint", "globals", "@eslint/js", "typescript-eslint"];
1655
+ await installPackages(packages, true);
1656
+ const configFile = await resolveConfigFile("ESLint", [
1657
+ "eslint.config.mjs",
1658
+ "eslint.config.js",
1659
+ "eslint.config.cjs"
1660
+ ]);
1661
+ if (!await import_fs_extra4.default.pathExists(configFile)) {
1662
+ await import_fs_extra4.default.writeFile(
1663
+ configFile,
1664
+ `import globals from "globals";
1665
+ import pluginJs from "@eslint/js";
1666
+ import tseslint from "typescript-eslint";
1667
+
1668
+
1669
+ export default [
1670
+ {files: ["**/*.{js,mjs,cjs,ts}"]},
1671
+ {languageOptions: { globals: globals.browser }},
1672
+ pluginJs.configs.recommended,
1673
+ ...tseslint.configs.recommended,
1674
+ ];`
1675
+ );
1676
+ }
1677
+ }
1678
+ async function configureEslintPlugins(plugins) {
1679
+ const configFile = await resolveConfigFile("ESLint", [
1680
+ "eslint.config.mjs",
1681
+ "eslint.config.js",
1682
+ "eslint.config.cjs"
1683
+ ]);
1684
+ if (!await import_fs_extra4.default.pathExists(configFile)) {
1685
+ return;
1686
+ }
1687
+ let configContent = await import_fs_extra4.default.readFile(configFile, "utf-8");
1688
+ const newImports = [];
1689
+ const newPluginConfigs = [];
1690
+ for (const pluginName of plugins) {
1691
+ const pluginDef = PLUGINS.eslint.find((p) => p.value === pluginName);
1692
+ const packageName = pluginDef?.package || `eslint-plugin-${pluginName}`;
1693
+ const safeVarName = pluginName.replace(/[^a-zA-Z0-9]/g, "") + "Plugin";
1694
+ if (!configContent.includes(`import ${safeVarName}`)) {
1695
+ newImports.push(`import ${safeVarName} from "${packageName}";`);
1696
+ }
1697
+ const shorPluginName = pluginName.replace(/^eslint-plugin-/, "");
1698
+ newPluginConfigs.push(`"${shorPluginName}": ${safeVarName}`);
1699
+ }
1700
+ if (newImports.length > 0) {
1701
+ const lastImportIndex = configContent.lastIndexOf("import ");
1702
+ const endOfLastImport = configContent.indexOf("\n", lastImportIndex) + 1;
1703
+ configContent = configContent.slice(0, endOfLastImport) + newImports.join("\n") + "\n" + configContent.slice(endOfLastImport);
1704
+ }
1705
+ if (newPluginConfigs.length > 0) {
1706
+ const exportDefaultStart = configContent.indexOf("export default [");
1707
+ if (exportDefaultStart !== -1) {
1708
+ const pluginsBlock = `
1709
+ {
1710
+ plugins: {
1711
+ ${newPluginConfigs.join(",\n ")}
1712
+ }
1713
+ },`;
1714
+ const insertPos = exportDefaultStart + "export default [".length;
1715
+ configContent = configContent.slice(0, insertPos) + pluginsBlock + configContent.slice(insertPos);
1716
+ }
1717
+ }
1718
+ await import_fs_extra4.default.writeFile(configFile, configContent);
1719
+ }
1720
+
1721
+ // src/steps/install-plugin.ts
1722
+ var import_picocolors3 = __toESM(require("picocolors"));
1723
+ async function installPlugins(tool) {
1724
+ const pluginsList = PLUGINS[tool];
1725
+ const selectedPlugins = await withCancelHandling(
1726
+ async () => prompts.multiselect({
1727
+ message: `Select ${tool} plugins to install:`,
1728
+ options: pluginsList,
1729
+ required: true,
1730
+ initialValue: []
1731
+ })
1732
+ );
1733
+ if (selectedPlugins.length === 0) {
1734
+ prompts.outro(import_picocolors3.default.yellow("No plugins selected."));
1735
+ return;
1736
+ }
1737
+ const packagesToInstall = selectedPlugins.map((val) => {
1738
+ const p = pluginsList.find((opt) => opt.value === val);
1739
+ return p ? p.package : val;
1740
+ });
1741
+ prompts.outro(
1742
+ import_picocolors3.default.blue(`Installing ${packagesToInstall.length} plugins for ${tool}...`)
1743
+ );
1744
+ await installPackages(packagesToInstall, true);
1745
+ await configurePlugins(tool, selectedPlugins);
1746
+ }
1747
+ async function configurePlugins(tool, plugins) {
1748
+ const shouldConfigure = await withCancelHandling(
1749
+ async () => prompts.confirm({
1750
+ message: `Do you want to configure the selected plugins in your ${tool} config file?`,
1751
+ initialValue: true
1752
+ })
1753
+ );
1754
+ if (!shouldConfigure) {
1755
+ prompts.outro(import_picocolors3.default.yellow("Skipping configuration."));
1756
+ return;
1757
+ }
1758
+ switch (tool) {
1759
+ case "prettier":
1760
+ await configurePrettierPlugins(plugins);
1761
+ prompts.outro(import_picocolors3.default.green("Prettier plugins configured in .prettierrc"));
1762
+ break;
1763
+ case "eslint":
1764
+ await configureEslintPlugins(plugins);
1765
+ prompts.outro(import_picocolors3.default.green("ESLint plugins configured in .eslintrc.json"));
1766
+ break;
1767
+ }
1768
+ }
1769
+
1770
+ // src/features/formatter.ts
233
1771
  async function promptFormatter(config2) {
234
1772
  const formatterConfig = config2.get("formatter");
235
- import_prompts3.log.message(import_picocolors2.default.bgBlue(import_picocolors2.default.black(" Formatter Configuration ")));
1773
+ prompts.log.message(import_picocolors4.default.bgBlue(import_picocolors4.default.white(" Formatter Configuration ")));
236
1774
  const formatter = await withCancelHandling(
237
- async () => (0, import_prompts3.select)({
1775
+ async () => prompts.select({
238
1776
  message: "Select a formatter:",
239
1777
  options: FORMATTER_OPTIONS,
240
1778
  initialValue: formatterConfig.options.choice
@@ -243,31 +1781,36 @@ async function promptFormatter(config2) {
243
1781
  formatterConfig.options = { choice: formatter };
244
1782
  }
245
1783
  async function installFormatter(config2) {
246
- const choice = config2.get("formatter").options.choice;
247
- if (choice === "prettier") {
248
- await installPackages(["prettier"], true);
249
- const configContent = {
250
- semi: true,
251
- singleQuote: true,
252
- trailingComma: "all",
253
- printWidth: 80,
254
- tabWidth: 2
255
- };
256
- await import_fs_extra2.default.writeJson(".prettierrc", configContent, { spaces: 2 });
257
- } else if (choice === "oxfmt") {
258
- await installPackages(["oxfmt"], true);
259
- }
1784
+ const formatter = config2.get("formatter").options.choice;
1785
+ if (!formatter) return;
1786
+ prompts.log.message(import_picocolors4.default.white(import_picocolors4.default.bgBlack(` Installing ${formatter}... `)));
1787
+ if (formatter === "prettier") await installPrettier();
1788
+ else if (formatter === "oxfmt") await installOxfmt();
1789
+ if (!PLUGINABLE_TOOLS.includes(formatter)) return;
1790
+ const shouldConfigure = await withCancelHandling(
1791
+ async () => prompts.confirm({
1792
+ message: `Do you want to install plugins for ${formatter}?`,
1793
+ initialValue: true
1794
+ })
1795
+ );
1796
+ if (!shouldConfigure) return;
1797
+ await installPlugins(formatter);
260
1798
  }
261
1799
 
262
- // src/services/linter.ts
263
- var import_prompts4 = require("@clack/prompts");
264
- var import_fs_extra3 = __toESM(require("fs-extra"));
265
- var import_picocolors3 = __toESM(require("picocolors"));
1800
+ // src/features/linter.ts
1801
+ var import_picocolors5 = __toESM(require("picocolors"));
1802
+
1803
+ // src/features/linter/oxlint.ts
1804
+ async function installOxlint() {
1805
+ await installPackages(["oxlint@latest"], true);
1806
+ }
1807
+
1808
+ // src/features/linter.ts
266
1809
  async function promptLinter(config2) {
267
1810
  const linterConfig = config2.get("linter");
268
- import_prompts4.log.message(import_picocolors3.default.bgYellow(import_picocolors3.default.black(" Linter Configuration ")));
1811
+ prompts.log.message(import_picocolors5.default.bgYellow(import_picocolors5.default.black(" Linter Configuration ")));
269
1812
  const linter = await withCancelHandling(
270
- async () => (0, import_prompts4.select)({
1813
+ async () => prompts.select({
271
1814
  message: "Select a linter:",
272
1815
  options: LINTER_OPTIONS,
273
1816
  initialValue: linterConfig.options.choice
@@ -276,41 +1819,35 @@ async function promptLinter(config2) {
276
1819
  linterConfig.options = { choice: linter };
277
1820
  }
278
1821
  async function installLinter(config2) {
279
- const choice = config2.get("linter").options.choice;
280
- if (choice === "eslint") {
281
- await installPackages(["eslint"], true);
282
- const configContent = {
283
- extends: ["eslint:recommended"],
284
- env: {
285
- node: true,
286
- es2021: true
287
- },
288
- parserOptions: {
289
- ecmaVersion: "latest",
290
- sourceType: "module"
291
- }
292
- };
293
- await import_fs_extra3.default.writeJson(".eslintrc.json", configContent, { spaces: 2 });
294
- } else if (choice === "oxlint") {
295
- await installPackages(["oxlint"], true);
296
- }
1822
+ const linter = config2.get("linter").options.choice;
1823
+ if (!linter) return;
1824
+ prompts.log.message(import_picocolors5.default.white(import_picocolors5.default.bgBlack(` Installing ${linter}... `)));
1825
+ if (linter === "eslint") await installEslint();
1826
+ else if (linter === "oxlint") await installOxlint();
1827
+ if (!PLUGINABLE_TOOLS.includes(linter)) return;
1828
+ const shouldConfigure = await withCancelHandling(
1829
+ async () => prompts.confirm({
1830
+ message: `Do you want to install plugins for ${linter}?`,
1831
+ initialValue: true
1832
+ })
1833
+ );
1834
+ if (!shouldConfigure) return;
1835
+ await installPlugins(linter);
297
1836
  }
298
1837
 
299
- // src/services/lint-staged.ts
300
- var import_prompts5 = require("@clack/prompts");
301
- var import_fs_extra4 = __toESM(require("fs-extra"));
302
- var import_picocolors4 = __toESM(require("picocolors"));
1838
+ // src/features/lint-staged.ts
1839
+ var import_picocolors6 = __toESM(require("picocolors"));
303
1840
  async function promptLintStaged(config2) {
304
- import_prompts5.log.message(import_picocolors4.default.bgGreen(import_picocolors4.default.black(" Lint-staged Configuration ")));
1841
+ prompts.log.message(import_picocolors6.default.bgGreen(import_picocolors6.default.black(" Lint-staged Configuration ")));
305
1842
  const lintExtensions = await withCancelHandling(
306
- async () => (0, import_prompts5.multiselect)({
1843
+ async () => prompts.multiselect({
307
1844
  message: "Select extensions to lint:",
308
1845
  options: LINT_STAGED_EXTENSIONS,
309
1846
  required: false
310
1847
  })
311
1848
  );
312
1849
  const formatExtensions = await withCancelHandling(
313
- async () => (0, import_prompts5.multiselect)({
1850
+ async () => prompts.multiselect({
314
1851
  message: "Select extensions to format:",
315
1852
  options: LINT_STAGED_EXTENSIONS,
316
1853
  required: false
@@ -331,6 +1868,13 @@ async function promptLintStaged(config2) {
331
1868
  }
332
1869
  async function installLintStaged(config2) {
333
1870
  await installPackages(["lint-staged"], true);
1871
+ const configFile = await resolveConfigFile("Lint-Staged", [
1872
+ ".lintstagedrc",
1873
+ ".lintstagedrc.json",
1874
+ "lint-staged.config.js",
1875
+ ".lintstagedrc.js",
1876
+ ".lintstagedrc.mjs"
1877
+ ]);
334
1878
  const lintStagedConfig = {};
335
1879
  const lintStagedOptions = config2.get("lintStaged").options;
336
1880
  const lintExts = lintStagedOptions?.lintExtensions || [];
@@ -353,37 +1897,36 @@ async function installLintStaged(config2) {
353
1897
  lintStagedConfig[glob] = ["prettier --write"];
354
1898
  }
355
1899
  }
356
- await import_fs_extra4.default.writeJson(".lintstagedrc", lintStagedConfig, { spaces: 2 });
1900
+ await writeConfig(configFile, lintStagedConfig);
357
1901
  }
358
1902
 
359
- // src/services/env.ts
360
- var import_prompts6 = require("@clack/prompts");
1903
+ // src/features/env.ts
361
1904
  var import_fs_extra5 = __toESM(require("fs-extra"));
362
1905
  var import_path = __toESM(require("path"));
363
- var import_picocolors5 = __toESM(require("picocolors"));
1906
+ var import_picocolors7 = __toESM(require("picocolors"));
364
1907
  async function promptEnv(config2) {
365
- import_prompts6.log.message(import_picocolors5.default.bgCyan(import_picocolors5.default.black(" Env Validation Configuration ")));
1908
+ prompts.log.message(import_picocolors7.default.bgCyan(import_picocolors7.default.black(" Env Validation Configuration ")));
366
1909
  const variant = await withCancelHandling(
367
- async () => (0, import_prompts6.select)({
1910
+ async () => prompts.select({
368
1911
  message: "Which @t3-oss/env variant?",
369
1912
  options: ENV_VARIANT_OPTIONS
370
1913
  })
371
1914
  );
372
1915
  const validator = await withCancelHandling(
373
- async () => (0, import_prompts6.select)({
1916
+ async () => prompts.select({
374
1917
  message: "Which validator?",
375
1918
  options: ENV_VALIDATOR_OPTIONS
376
1919
  })
377
1920
  );
378
1921
  const installPresets = await withCancelHandling(
379
- async () => (0, import_prompts6.confirm)({
1922
+ async () => prompts.confirm({
380
1923
  message: "Install presets?"
381
1924
  })
382
1925
  );
383
1926
  let presets;
384
1927
  if (installPresets) {
385
1928
  presets = await withCancelHandling(
386
- async () => (0, import_prompts6.multiselect)({
1929
+ async () => prompts.multiselect({
387
1930
  message: "Select preset to extend:",
388
1931
  options: ENV_PRESET_OPTIONS,
389
1932
  required: false
@@ -391,13 +1934,13 @@ async function promptEnv(config2) {
391
1934
  );
392
1935
  }
393
1936
  const split = await withCancelHandling(
394
- async () => (0, import_prompts6.select)({
1937
+ async () => prompts.select({
395
1938
  message: "Split or Joined env files?",
396
1939
  options: ENV_SPLIT_OPTIONS
397
1940
  })
398
1941
  );
399
1942
  const location = await withCancelHandling(
400
- async () => (0, import_prompts6.text)({
1943
+ async () => prompts.text({
401
1944
  message: "Where should the environment files be created?",
402
1945
  initialValue: config2.get("env").options.location || "src/lib",
403
1946
  placeholder: "src/lib"
@@ -415,7 +1958,7 @@ async function promptEnv(config2) {
415
1958
  async function installEnv(config2) {
416
1959
  const envOptions = config2.get("env").options;
417
1960
  const { variant, validator, location, presets, split } = envOptions;
418
- await installPackages([variant, validator], true);
1961
+ await installPackages([variant, validator], false);
419
1962
  await import_fs_extra5.default.ensureDir(location);
420
1963
  const presetImport = presets && presets.length > 0 ? `// Presets: ${presets.join(", ")}
421
1964
  ` : "";
@@ -468,14 +2011,13 @@ export const env = createEnv({
468
2011
  }
469
2012
  }
470
2013
 
471
- // src/services/test.ts
472
- var import_prompts7 = require("@clack/prompts");
2014
+ // src/features/test.ts
473
2015
  var import_fs_extra6 = __toESM(require("fs-extra"));
474
- var import_picocolors6 = __toESM(require("picocolors"));
2016
+ var import_picocolors8 = __toESM(require("picocolors"));
475
2017
  async function promptTest(config2) {
476
- import_prompts7.log.message(import_picocolors6.default.bgRed(import_picocolors6.default.black(" Test Runner Configuration ")));
2018
+ prompts.log.message(import_picocolors8.default.bgRed(import_picocolors8.default.white(" Test Runner Configuration ")));
477
2019
  const runner = await withCancelHandling(
478
- async () => (0, import_prompts7.select)({
2020
+ async () => prompts.select({
479
2021
  message: "Select a test runner:",
480
2022
  options: TEST_RUNNER_OPTIONS
481
2023
  })
@@ -517,15 +2059,14 @@ module.exports = {
517
2059
  }
518
2060
  }
519
2061
 
520
- // src/services/editor-config.ts
521
- var import_prompts8 = require("@clack/prompts");
2062
+ // src/features/editor-config.ts
522
2063
  var import_fs_extra7 = __toESM(require("fs-extra"));
523
- var import_picocolors7 = __toESM(require("picocolors"));
2064
+ var import_picocolors9 = __toESM(require("picocolors"));
524
2065
  async function promptEditorConfig(config2) {
525
- import_prompts8.log.message(import_picocolors7.default.bgWhite(import_picocolors7.default.black(" EditorConfig Configuration ")));
2066
+ prompts.log.message(import_picocolors9.default.bgWhite(import_picocolors9.default.black(" EditorConfig Configuration ")));
526
2067
  const currentPreset = config2.get("editorConfig").options.preset;
527
2068
  const preset = await withCancelHandling(
528
- async () => (0, import_prompts8.select)({
2069
+ async () => prompts.select({
529
2070
  message: "Select EditorConfig preset:",
530
2071
  options: EDITOR_CONFIG_OPTIONS,
531
2072
  initialValue: currentPreset
@@ -546,37 +2087,36 @@ async function installEditorConfig(config2) {
546
2087
  await import_fs_extra7.default.outputFile(".editorconfig", content);
547
2088
  }
548
2089
 
549
- // src/services/license.ts
550
- var import_prompts9 = require("@clack/prompts");
2090
+ // src/features/license.ts
551
2091
  var import_fs_extra8 = __toESM(require("fs-extra"));
552
2092
  var import_path2 = __toESM(require("path"));
553
- var import_picocolors8 = __toESM(require("picocolors"));
2093
+ var import_picocolors10 = __toESM(require("picocolors"));
554
2094
  async function promptLicense(config2) {
555
- import_prompts9.log.message(import_picocolors8.default.bgGreen(import_picocolors8.default.black(" License Configuration ")));
2095
+ prompts.log.message(import_picocolors10.default.bgGreen(import_picocolors10.default.black(" License Configuration ")));
556
2096
  const licenseOptions = config2.get("license").options;
557
2097
  licenseOptions.name = await withCancelHandling(
558
- async () => (0, import_prompts9.text)({
2098
+ async () => prompts.text({
559
2099
  message: "License Holder Name:",
560
2100
  placeholder: "John Doe",
561
2101
  initialValue: licenseOptions.name
562
2102
  })
563
2103
  );
564
2104
  licenseOptions.email = await withCancelHandling(
565
- async () => (0, import_prompts9.text)({
2105
+ async () => prompts.text({
566
2106
  message: "License Holder Email:",
567
2107
  placeholder: "john@example.com",
568
2108
  initialValue: licenseOptions.email
569
2109
  })
570
2110
  );
571
2111
  licenseOptions.website = await withCancelHandling(
572
- async () => (0, import_prompts9.text)({
2112
+ async () => prompts.text({
573
2113
  message: "License Holder Website:",
574
2114
  placeholder: "https://example.com",
575
2115
  initialValue: licenseOptions.website
576
2116
  })
577
2117
  );
578
2118
  licenseOptions.type = await withCancelHandling(
579
- async () => (0, import_prompts9.select)({
2119
+ async () => prompts.select({
580
2120
  message: "Select License Type:",
581
2121
  options: LICENSE_TYPE_OPTIONS
582
2122
  })
@@ -611,8 +2151,8 @@ Licensed under ${type}`;
611
2151
  }
612
2152
  }
613
2153
 
614
- // src/config/config.ts
615
- var import_picocolors9 = __toESM(require("picocolors"));
2154
+ // src/core/config.ts
2155
+ var import_picocolors11 = __toESM(require("picocolors"));
616
2156
  var Config = class {
617
2157
  data;
618
2158
  constructor() {
@@ -641,7 +2181,50 @@ var Config = class {
641
2181
  installPresets: false,
642
2182
  presets: [],
643
2183
  split: "split",
644
- location: "src/env"
2184
+ location: "src/lib"
2185
+ }
2186
+ },
2187
+ test: {
2188
+ selected: false,
2189
+ options: { runner: "vitest" }
2190
+ },
2191
+ editorConfig: {
2192
+ selected: false,
2193
+ options: { preset: "default" }
2194
+ },
2195
+ license: {
2196
+ selected: false,
2197
+ options: { name: "", email: "", website: "", type: "MIT" }
2198
+ }
2199
+ };
2200
+ }
2201
+ clear() {
2202
+ this.data = {
2203
+ husky: {
2204
+ selected: false,
2205
+ options: { hookType: "none", customScript: "npm run test" }
2206
+ },
2207
+ formatter: {
2208
+ selected: false,
2209
+ options: { choice: "prettier" }
2210
+ },
2211
+ linter: {
2212
+ selected: false,
2213
+ options: { choice: "eslint" }
2214
+ },
2215
+ lintStaged: {
2216
+ selected: false,
2217
+ options: { lintExtensions: [], formatExtensions: [] }
2218
+ },
2219
+ env: {
2220
+ selected: false,
2221
+ options: {
2222
+ variant: "@t3-oss/env-nextjs",
2223
+ validator: "zod",
2224
+ installPresets: false,
2225
+ presets: [],
2226
+ split: "split",
2227
+ location: "src/lib"
645
2228
  }
646
2229
  },
647
2230
  test: {
@@ -666,57 +2249,98 @@ var Config = class {
666
2249
  }
667
2250
  get summary() {
668
2251
  const lines = [];
669
- lines.push(import_picocolors9.default.bold("The following actions will be performed:"));
2252
+ lines.push(import_picocolors11.default.bold("The following actions will be performed:"));
670
2253
  lines.push("");
671
2254
  if (this.data.husky.selected) {
672
- lines.push(import_picocolors9.default.magenta(`\u2022 Install and configure Husky`));
2255
+ lines.push(import_picocolors11.default.magenta(`\u2022 Install and configure Husky`));
673
2256
  if (this.data.husky.options.hookType === "custom") {
674
- lines.push(import_picocolors9.default.dim(` - Custom hook script`));
2257
+ lines.push(import_picocolors11.default.dim(` - Custom hook script`));
675
2258
  }
676
2259
  }
677
2260
  if (this.data.formatter.selected) {
678
2261
  const choice = this.data.formatter.options.choice;
679
- lines.push(import_picocolors9.default.blue(`\u2022 Install and configure ${choice || "Formatter"}`));
2262
+ lines.push(import_picocolors11.default.blue(`\u2022 Install and configure ${choice || "Formatter"}`));
680
2263
  }
681
2264
  if (this.data.linter.selected) {
682
2265
  const choice = this.data.linter.options.choice;
683
- lines.push(import_picocolors9.default.yellow(`\u2022 Install and configure ${choice || "Linter"}`));
2266
+ lines.push(import_picocolors11.default.yellow(`\u2022 Install and configure ${choice || "Linter"}`));
684
2267
  }
685
2268
  if (this.data.lintStaged.selected) {
686
- lines.push(import_picocolors9.default.green(`\u2022 Install and configure Lint-staged`));
2269
+ lines.push(import_picocolors11.default.green(`\u2022 Install and configure Lint-staged`));
687
2270
  const lintExts = this.data.lintStaged.options.lintExtensions.join(", ");
688
2271
  const formatExts = this.data.lintStaged.options.formatExtensions.join(", ");
689
- if (lintExts) lines.push(import_picocolors9.default.dim(` - Lint: ${lintExts}`));
690
- if (formatExts) lines.push(import_picocolors9.default.dim(` - Format: ${formatExts}`));
2272
+ if (lintExts) lines.push(import_picocolors11.default.dim(` - Lint: ${lintExts}`));
2273
+ if (formatExts) lines.push(import_picocolors11.default.dim(` - Format: ${formatExts}`));
691
2274
  }
692
2275
  if (this.data.env.selected) {
693
- lines.push(import_picocolors9.default.cyan(`\u2022 Install and configure Env Validation`));
694
- lines.push(import_picocolors9.default.dim(` - Variant: ${this.data.env.options.variant}`));
695
- lines.push(import_picocolors9.default.dim(` - Validator: ${this.data.env.options.validator}`));
2276
+ lines.push(import_picocolors11.default.cyan(`\u2022 Install and configure Env Validation`));
2277
+ lines.push(import_picocolors11.default.dim(` - Variant: ${this.data.env.options.variant}`));
2278
+ lines.push(import_picocolors11.default.dim(` - Validator: ${this.data.env.options.validator}`));
696
2279
  }
697
2280
  if (this.data.test.selected) {
698
2281
  const runner = this.data.test.options.runner;
699
- lines.push(import_picocolors9.default.red(`\u2022 Install and configure Test Runner (${runner})`));
2282
+ lines.push(import_picocolors11.default.red(`\u2022 Install and configure Test Runner (${runner})`));
700
2283
  }
701
2284
  if (this.data.editorConfig.selected) {
702
2285
  const preset = this.data.editorConfig.options.preset;
703
- lines.push(import_picocolors9.default.white(`\u2022 Create .editorconfig (${preset})`));
2286
+ lines.push(import_picocolors11.default.white(`\u2022 Create .editorconfig (${preset})`));
704
2287
  }
705
2288
  if (this.data.license.selected) {
706
2289
  const type = this.data.license.options.type;
707
2290
  const name = this.data.license.options.name;
708
- lines.push(import_picocolors9.default.green(`\u2022 Create LICENSE (${type})`));
709
- lines.push(import_picocolors9.default.dim(` - Holder: ${name}`));
2291
+ lines.push(import_picocolors11.default.green(`\u2022 Create LICENSE (${type})`));
2292
+ lines.push(import_picocolors11.default.dim(` - Holder: ${name}`));
710
2293
  }
711
2294
  return lines.join("\n");
712
2295
  }
713
2296
  };
714
2297
  var config = new Config();
715
2298
 
2299
+ // src/utils/spinner.ts
2300
+ var import_cli_spinners = __toESM(require("cli-spinners"));
2301
+ var import_picocolors12 = __toESM(require("picocolors"));
2302
+ var Spinner = class {
2303
+ timer = null;
2304
+ frameIndex = 0;
2305
+ spinner = import_cli_spinners.default.dots;
2306
+ text = "";
2307
+ start(text2) {
2308
+ this.text = text2;
2309
+ this.frameIndex = 0;
2310
+ if (this.timer) clearInterval(this.timer);
2311
+ this.timer = setInterval(() => {
2312
+ const frame = this.spinner.frames[this.frameIndex];
2313
+ process.stdout.write(`\r${import_picocolors12.default.magenta(frame)} ${this.text}`);
2314
+ this.frameIndex = (this.frameIndex + 1) % this.spinner.frames.length;
2315
+ }, this.spinner.interval);
2316
+ }
2317
+ stop(text2) {
2318
+ if (this.timer) {
2319
+ clearInterval(this.timer);
2320
+ this.timer = null;
2321
+ process.stdout.write("\r\x1B[K");
2322
+ if (text2) {
2323
+ console.log(text2);
2324
+ }
2325
+ }
2326
+ }
2327
+ success(text2) {
2328
+ this.stop();
2329
+ console.log(`${import_picocolors12.default.green("\u2714")} ${text2 || this.text}`);
2330
+ }
2331
+ fail(text2) {
2332
+ this.stop();
2333
+ console.log(`${import_picocolors12.default.red("\u2716")} ${text2 || this.text}`);
2334
+ }
2335
+ message(text2) {
2336
+ this.text = text2;
2337
+ }
2338
+ };
2339
+ var spinner = () => new Spinner();
2340
+
716
2341
  // src/steps/execution.ts
717
- var import_prompts10 = require("@clack/prompts");
718
2342
  async function execution(config2) {
719
- const s = (0, import_prompts10.spinner)();
2343
+ const s = spinner();
720
2344
  if (config2.get("husky").selected) {
721
2345
  s.start("Setting up Husky...");
722
2346
  await installHusky(config2);
@@ -814,15 +2438,14 @@ async function commitChanges(message) {
814
2438
  }
815
2439
 
816
2440
  // src/steps/git-check.ts
817
- var import_prompts11 = require("@clack/prompts");
818
2441
  async function gitCheck() {
819
2442
  if (await isGitRepository()) {
820
2443
  if (await isGitDirty()) {
821
- const shouldCommit = await (0, import_prompts11.confirm)({
2444
+ const shouldCommit = await prompts.confirm({
822
2445
  message: "Your working directory is dirty. Would you like to commit changes before proceeding?"
823
2446
  });
824
2447
  if (shouldCommit) {
825
- const message = await (0, import_prompts11.text)({
2448
+ const message = await prompts.text({
826
2449
  message: "Enter commit message:",
827
2450
  placeholder: "wip: pre-setup commit",
828
2451
  validate(value) {
@@ -830,7 +2453,7 @@ async function gitCheck() {
830
2453
  }
831
2454
  });
832
2455
  if (typeof message === "string") {
833
- const s = (0, import_prompts11.spinner)();
2456
+ const s = spinner();
834
2457
  s.start("Committing changes...");
835
2458
  await commitChanges(message);
836
2459
  s.stop("Changes committed.");
@@ -841,59 +2464,63 @@ async function gitCheck() {
841
2464
  }
842
2465
 
843
2466
  // src/utils/display.ts
844
- var import_picocolors10 = __toESM(require("picocolors"));
2467
+ var import_picocolors13 = __toESM(require("picocolors"));
845
2468
  var import_figlet = __toESM(require("figlet"));
846
2469
 
847
2470
  // package.json
848
2471
  var package_default = {
849
2472
  name: "@mayrlabs/setup-project",
850
- version: "0.1.7",
851
- description: "Interactive CLI to setup project tools",
2473
+ version: "0.1.9",
852
2474
  private: false,
853
- publishConfig: {
854
- access: "public"
855
- },
2475
+ description: "Interactive CLI to setup project tools",
856
2476
  keywords: [
857
- "setup",
858
2477
  "cli",
859
- "scaffold",
2478
+ "eslint",
860
2479
  "husky",
861
2480
  "prettier",
862
- "eslint"
863
- ],
864
- bin: {
865
- "setup-project": "dist/index.js"
866
- },
867
- files: [
868
- "dist",
869
- "README.md",
870
- "CHANGELOG.md",
871
- "package.json"
2481
+ "scaffold",
2482
+ "setup"
872
2483
  ],
873
2484
  homepage: "https://github.com/MayR-Labs/mayrlabs-js/tree/main/packages/setup-project#readme",
874
2485
  bugs: {
875
2486
  url: "https://github.com/MayR-Labs/mayrlabs-js/issues"
876
2487
  },
877
- repository: {
878
- type: "git",
879
- url: "git+https://github.com/MayR-Labs/mayrlabs-js.git",
880
- directory: "packages/setup-project"
881
- },
882
2488
  license: "MIT",
883
2489
  author: {
884
2490
  name: "Aghogho Meyoron",
885
2491
  email: "youngmayor.dev@gmail.com",
886
2492
  url: "https://mayrlabs.com"
887
2493
  },
2494
+ repository: {
2495
+ type: "git",
2496
+ url: "git+https://github.com/MayR-Labs/mayrlabs-js.git",
2497
+ directory: "packages/setup-project"
2498
+ },
2499
+ bin: {
2500
+ "setup-project": "dist/index.js"
2501
+ },
2502
+ files: [
2503
+ "dist",
2504
+ "README.md",
2505
+ "CHANGELOG.md",
2506
+ "package.json"
2507
+ ],
888
2508
  type: "commonjs",
889
2509
  main: "dist/index.js",
2510
+ publishConfig: {
2511
+ access: "public"
2512
+ },
890
2513
  scripts: {
891
2514
  build: "tsup",
892
- demo: "tsx src/index.ts",
2515
+ lint: "eslint . --max-warnings 0",
2516
+ demo: "tsx src/cli/index.ts",
2517
+ test: "vitest",
893
2518
  prepublishOnly: "npm run build"
894
2519
  },
895
2520
  dependencies: {
896
2521
  "@clack/prompts": "^0.7.0",
2522
+ "@topcli/prompts": "^2.4.1",
2523
+ "cli-spinners": "^3.4.0",
897
2524
  commander: "^11.1.0",
898
2525
  execa: "^8.0.1",
899
2526
  figlet: "^1.10.0",
@@ -902,12 +2529,16 @@ var package_default = {
902
2529
  zod: "^3.22.4"
903
2530
  },
904
2531
  devDependencies: {
2532
+ "@repo/eslint-config": "^0.0.0",
905
2533
  "@types/figlet": "^1.7.0",
906
2534
  "@types/fs-extra": "^11.0.4",
907
2535
  "@types/node": "^20.11.16",
2536
+ "@vitest/coverage-v8": "^4.0.18",
2537
+ eslint: "^9.39.2",
908
2538
  tsup: "^8.5.1",
909
2539
  tsx: "^4.21.0",
910
- typescript: "^5.3.3"
2540
+ typescript: "^5.3.3",
2541
+ vitest: "^4.0.18"
911
2542
  }
912
2543
  };
913
2544
 
@@ -915,7 +2546,7 @@ var package_default = {
915
2546
  function introScreen() {
916
2547
  console.log();
917
2548
  console.log(
918
- import_picocolors10.default.cyan(
2549
+ import_picocolors13.default.cyan(
919
2550
  import_figlet.default.textSync("MayR\nLabs", {
920
2551
  font: "Graceful",
921
2552
  horizontalLayout: "default",
@@ -925,39 +2556,41 @@ function introScreen() {
925
2556
  })
926
2557
  )
927
2558
  );
928
- console.log(import_picocolors10.default.cyan(`@mayrlabs/setup-project v${package_default.version}`));
2559
+ console.log(import_picocolors13.default.cyan(`${package_default.name} - v${package_default.version}`));
929
2560
  console.log();
930
2561
  }
931
2562
  function showAbout() {
932
2563
  introScreen();
933
- console.log(import_picocolors10.default.bold("About:"));
2564
+ console.log(import_picocolors13.default.bold("About:"));
934
2565
  console.log(
935
2566
  " Interactive CLI to setup project tools like Husky, Prettier, ESLint, etc."
936
2567
  );
937
2568
  console.log("");
938
- console.log(import_picocolors10.default.bold("How to use:"));
2569
+ console.log(import_picocolors13.default.bold("How to use:"));
939
2570
  console.log(
940
2571
  " Run 'npx @mayrlabs/setup-project' and follow the interactive prompts."
941
2572
  );
942
2573
  console.log("");
943
2574
  }
944
2575
  function showVisit() {
945
- console.log(import_picocolors10.default.bold("Project Homepage:"));
946
- console.log(import_picocolors10.default.underline(import_picocolors10.default.cyan(package_default.homepage)));
2576
+ console.log(import_picocolors13.default.bold("Project Homepage:"));
2577
+ console.log(import_picocolors13.default.underline(import_picocolors13.default.cyan(package_default.homepage)));
947
2578
  console.log("");
948
2579
  }
949
2580
  function showManual() {
950
2581
  introScreen();
951
- console.log(import_picocolors10.default.bold("Usage:"));
2582
+ console.log(import_picocolors13.default.bold("Usage:"));
952
2583
  console.log(" npx @mayrlabs/setup-project [command] [options]");
953
2584
  console.log("");
954
- console.log(import_picocolors10.default.bold("Commands:"));
2585
+ console.log(import_picocolors13.default.bold("Commands:"));
955
2586
  console.log(" about Show project details");
956
2587
  console.log(" version Show version information");
957
2588
  console.log(" visit Visit project homepage");
958
2589
  console.log(" help Show this help message");
2590
+ console.log(" configure [tool] Configure a specific tool");
2591
+ console.log(" plugin [tool] Manage plugins for tools");
959
2592
  console.log("");
960
- console.log(import_picocolors10.default.bold("Options:"));
2593
+ console.log(import_picocolors13.default.bold("Options:"));
961
2594
  console.log(" -a, --about Show project details");
962
2595
  console.log(" -v, --version Show version information");
963
2596
  console.log(" -V, --visit Visit project homepage");
@@ -965,16 +2598,107 @@ function showManual() {
965
2598
  console.log("");
966
2599
  }
967
2600
 
968
- // src/index.ts
2601
+ // src/cli/commands/configure.ts
2602
+ var import_picocolors14 = __toESM(require("picocolors"));
2603
+ async function configure(toolName) {
2604
+ introScreen();
2605
+ prompts.intro(import_picocolors14.default.inverse(import_picocolors14.default.bold(import_picocolors14.default.blue(" Configuration Mode "))));
2606
+ await gitCheck();
2607
+ let selectedTool;
2608
+ if (toolName) {
2609
+ const tool = TOOL_OPTIONS.find((t) => t.value === toolName);
2610
+ if (tool) {
2611
+ selectedTool = tool.value;
2612
+ } else {
2613
+ console.log(
2614
+ import_picocolors14.default.yellow(`Tool '${toolName}' not found or not configurable.`)
2615
+ );
2616
+ }
2617
+ }
2618
+ if (!selectedTool) {
2619
+ const selection = await withCancelHandling(
2620
+ async () => prompts.select({
2621
+ message: "Select a tool to configure:",
2622
+ options: TOOL_OPTIONS
2623
+ })
2624
+ );
2625
+ selectedTool = selection;
2626
+ }
2627
+ config.enableTool(selectedTool);
2628
+ try {
2629
+ switch (selectedTool) {
2630
+ case "husky":
2631
+ await promptHusky(config);
2632
+ await installHusky(config);
2633
+ break;
2634
+ case "formatter":
2635
+ await promptFormatter(config);
2636
+ await installFormatter(config);
2637
+ break;
2638
+ case "linter":
2639
+ await promptLinter(config);
2640
+ await installLinter(config);
2641
+ break;
2642
+ case "lintStaged":
2643
+ await promptLintStaged(config);
2644
+ await installLintStaged(config);
2645
+ break;
2646
+ case "env":
2647
+ await promptEnv(config);
2648
+ await installEnv(config);
2649
+ break;
2650
+ case "test":
2651
+ await promptTest(config);
2652
+ await installTest(config);
2653
+ break;
2654
+ case "editorConfig":
2655
+ await promptEditorConfig(config);
2656
+ await installEditorConfig(config);
2657
+ break;
2658
+ case "license":
2659
+ await promptLicense(config);
2660
+ await installLicense(config);
2661
+ break;
2662
+ }
2663
+ prompts.outro(import_picocolors14.default.green(`${selectedTool} configured successfully!`));
2664
+ } catch (error) {
2665
+ prompts.outro(import_picocolors14.default.red(`Failed to configure ${selectedTool}.`));
2666
+ console.error(error);
2667
+ process.exit(1);
2668
+ }
2669
+ }
2670
+
2671
+ // src/cli/commands/plugin.ts
2672
+ var import_picocolors15 = __toESM(require("picocolors"));
2673
+ async function plugin(toolName) {
2674
+ introScreen();
2675
+ prompts.intro(import_picocolors15.default.inverse(import_picocolors15.default.bold(import_picocolors15.default.magenta(" Plugin Manager "))));
2676
+ await gitCheck();
2677
+ if (!toolName) {
2678
+ toolName = await withCancelHandling(
2679
+ async () => prompts.select({
2680
+ message: "Select a tool to add plugins to:",
2681
+ options: [
2682
+ { value: "eslint", label: "ESLint" },
2683
+ { value: "prettier", label: "Prettier" }
2684
+ ]
2685
+ })
2686
+ );
2687
+ }
2688
+ await installPlugins(toolName);
2689
+ prompts.outro(import_picocolors15.default.green("Plugins installed successfully!"));
2690
+ }
2691
+
2692
+ // src/cli/index.ts
969
2693
  async function main() {
970
2694
  try {
971
2695
  introScreen();
972
- (0, import_prompts12.intro)(
973
- import_picocolors11.default.inverse(import_picocolors11.default.bold(import_picocolors11.default.cyan(" Welcome to the Project Setup Wizard ")))
2696
+ prompts.intro(
2697
+ import_picocolors16.default.inverse(import_picocolors16.default.bold(import_picocolors16.default.cyan(" Welcome to the Project Setup Wizard ")))
974
2698
  );
975
2699
  await gitCheck();
976
2700
  const tools = await withCancelHandling(
977
- async () => (0, import_prompts12.multiselect)({
2701
+ async () => prompts.multiselect({
978
2702
  message: "Select tools to configure:",
979
2703
  options: TOOL_OPTIONS,
980
2704
  required: false
@@ -989,23 +2713,25 @@ async function main() {
989
2713
  if (config.get("test").selected) await promptTest(config);
990
2714
  if (config.get("editorConfig").selected) await promptEditorConfig(config);
991
2715
  if (config.get("license").selected) await promptLicense(config);
992
- (0, import_prompts12.note)(config.summary, "Configuration Summary");
2716
+ prompts.note(config.summary, "Configuration Summary");
993
2717
  const proceed = await withCancelHandling(
994
- async () => (0, import_prompts12.confirm)({
2718
+ async () => prompts.confirm({
995
2719
  message: "Do you want to proceed with the installation?"
996
2720
  })
997
2721
  );
998
2722
  if (!proceed) {
999
- (0, import_prompts12.outro)(import_picocolors11.default.yellow("Installation cancelled."));
2723
+ prompts.outro(import_picocolors16.default.yellow("Installation cancelled."));
1000
2724
  process.exit(0);
1001
2725
  }
1002
2726
  await execution(config);
1003
- (0, import_prompts12.outro)(import_picocolors11.default.green("Setup complete!"));
2727
+ prompts.outro(import_picocolors16.default.green("Setup complete!"));
1004
2728
  } catch (error) {
1005
2729
  const logPath = await logError(error);
1006
- (0, import_prompts12.outro)(import_picocolors11.default.red(`
2730
+ prompts.outro(
2731
+ import_picocolors16.default.red(`
1007
2732
  Something went wrong!
1008
- Error log saved to: ${logPath}`));
2733
+ Error log saved to: ${logPath}`)
2734
+ );
1009
2735
  process.exit(1);
1010
2736
  }
1011
2737
  }
@@ -1027,6 +2753,14 @@ import_commander.program.command("help").action(() => {
1027
2753
  showManual();
1028
2754
  process.exit(0);
1029
2755
  });
2756
+ import_commander.program.command("configure [tool]").description("Configure a specific tool").action(async (tool) => {
2757
+ await configure(tool);
2758
+ process.exit(0);
2759
+ });
2760
+ import_commander.program.command("plugin [tool]").description("Manage plugins for tools").action(async (tool) => {
2761
+ await plugin(tool);
2762
+ process.exit(0);
2763
+ });
1030
2764
  import_commander.program.action(async (options) => {
1031
2765
  if (options.about) {
1032
2766
  showAbout();