@mayrlabs/setup-project 0.1.6 → 0.1.8

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
@@ -75,14 +75,14 @@ var init_options = __esm({
75
75
  { value: "husky", label: "Husky" },
76
76
  { value: "formatter", label: "Formatter (Prettier/Oxfmt)" },
77
77
  { value: "linter", label: "Linter (Eslint/Oxlint)" },
78
- { value: "lint-staged", label: "Lint-staged" },
78
+ { value: "lintStaged", label: "Lint-staged" },
79
79
  { value: "env", label: "Env Validation (@t3-oss/env)" },
80
80
  { value: "test", label: "Test Runner (Vitest/Jest)" },
81
81
  { value: "editorConfig", label: "EditorConfig" },
82
82
  { value: "license", label: "License" }
83
83
  ];
84
84
  HUSKY_HOOK_OPTIONS = [
85
- { value: "lint-staged", label: "lint-staged" },
85
+ { value: "lintStaged", label: "lint-staged" },
86
86
  { value: "custom", label: "Custom script" },
87
87
  { value: "none", label: "None" }
88
88
  ];
@@ -180,7 +180,7 @@ var init_handle_cancel = __esm({
180
180
  }
181
181
  });
182
182
 
183
- // src/services/husky.ts
183
+ // src/features/husky.ts
184
184
  import { select, log, text } from "@clack/prompts";
185
185
  import { execa as execa2 } from "execa";
186
186
  import fs from "fs-extra";
@@ -195,7 +195,7 @@ async function promptHusky(config2) {
195
195
  );
196
196
  const huskyConfig = config2.get("husky");
197
197
  huskyConfig.options = { hookType };
198
- if (hookType === "lint-staged") {
198
+ if (hookType === "lintStaged") {
199
199
  config2.enableTool("lintStaged");
200
200
  } else if (hookType === "custom") {
201
201
  const script = await withCancelHandling(
@@ -221,7 +221,7 @@ async function installHusky(config2) {
221
221
  const husky = config2.get("husky");
222
222
  const hookType = husky.options.hookType;
223
223
  const customScript = husky.options.customScript;
224
- if (hookType === "lint-staged") {
224
+ if (hookType === "lintStaged") {
225
225
  await fs.outputFile(".husky/pre-commit", "npx lint-staged\n", {
226
226
  mode: 493
227
227
  });
@@ -233,7 +233,7 @@ async function installHusky(config2) {
233
233
  }
234
234
  }
235
235
  var init_husky = __esm({
236
- "src/services/husky.ts"() {
236
+ "src/features/husky.ts"() {
237
237
  "use strict";
238
238
  init_esm_shims();
239
239
  init_pm();
@@ -242,15 +242,1392 @@ var init_husky = __esm({
242
242
  }
243
243
  });
244
244
 
245
- // src/services/formatter.ts
246
- import { select as select2, log as log2 } from "@clack/prompts";
245
+ // src/utils/config-file.ts
247
246
  import fs2 from "fs-extra";
247
+ import { select as select2 } from "@clack/prompts";
248
+ import path2 from "path";
249
+ async function resolveConfigFile(toolName, candidates) {
250
+ for (const file of candidates) {
251
+ if (await fs2.pathExists(file)) return file;
252
+ }
253
+ const response = await withCancelHandling(
254
+ async () => select2({
255
+ message: `Where do you want to store the ${toolName} config?`,
256
+ options: candidates.map((c) => ({ value: c, label: c })),
257
+ initialValue: candidates[0]
258
+ })
259
+ );
260
+ return response;
261
+ }
262
+ async function writeConfig(filePath, config2) {
263
+ const ext = path2.extname(filePath);
264
+ if (ext === ".json" || ext === "") {
265
+ await fs2.writeJson(filePath, config2, { spaces: 2 });
266
+ } else if (ext === ".js" || ext === ".cjs") {
267
+ const content = `module.exports = ${JSON.stringify(config2, null, 2)};`;
268
+ await fs2.writeFile(filePath, content);
269
+ } else if (ext === ".mjs") {
270
+ const content = `export default ${JSON.stringify(config2, null, 2)};`;
271
+ await fs2.writeFile(filePath, content);
272
+ } else {
273
+ await fs2.writeJson(filePath, config2, { spaces: 2 });
274
+ }
275
+ }
276
+ var init_config_file = __esm({
277
+ "src/utils/config-file.ts"() {
278
+ "use strict";
279
+ init_esm_shims();
280
+ init_handle_cancel();
281
+ }
282
+ });
283
+
284
+ // src/features/formatter/prettier.ts
285
+ import fs3 from "fs-extra";
286
+ async function installPrettier() {
287
+ await installPackages(["prettier"], true);
288
+ const configFile = await resolveConfigFile("Prettier", [
289
+ ".prettierrc",
290
+ ".prettierrc.json",
291
+ "prettier.config.js",
292
+ ".prettierrc.js"
293
+ ]);
294
+ if (!await fs3.pathExists(configFile)) {
295
+ await writeConfig(configFile, {
296
+ semi: true,
297
+ singleQuote: false,
298
+ tabWidth: 2,
299
+ trailingComma: "es5",
300
+ printWidth: 80,
301
+ plugins: []
302
+ });
303
+ }
304
+ if (!await fs3.pathExists(".prettierignore")) {
305
+ await fs3.writeFile(
306
+ ".prettierignore",
307
+ `node_modules
308
+ dist
309
+ coverage
310
+ .next
311
+ .nuxt
312
+ build
313
+ .astro
314
+ .output
315
+ `
316
+ );
317
+ }
318
+ }
319
+ async function configurePrettierPlugins(plugins) {
320
+ const configFile = await resolveConfigFile("Prettier", [
321
+ ".prettierrc",
322
+ ".prettierrc.json",
323
+ "prettier.config.js",
324
+ ".prettierrc.js"
325
+ ]);
326
+ let currentConfig = {};
327
+ if (await fs3.pathExists(configFile)) {
328
+ try {
329
+ if (configFile.endsWith(".js") || configFile.endsWith(".cjs")) {
330
+ return;
331
+ }
332
+ currentConfig = await fs3.readJson(configFile);
333
+ } catch (e) {
334
+ }
335
+ }
336
+ const existingPlugins = currentConfig.plugins || [];
337
+ const newPlugins = [.../* @__PURE__ */ new Set([...existingPlugins, ...plugins])];
338
+ currentConfig.plugins = newPlugins;
339
+ await writeConfig(configFile, currentConfig);
340
+ }
341
+ var init_prettier = __esm({
342
+ "src/features/formatter/prettier.ts"() {
343
+ "use strict";
344
+ init_esm_shims();
345
+ init_pm();
346
+ init_config_file();
347
+ }
348
+ });
349
+
350
+ // src/features/formatter/oxfmt.ts
351
+ async function installOxfmt() {
352
+ await installPackages(["oxfmt@latest"], true);
353
+ }
354
+ var init_oxfmt = __esm({
355
+ "src/features/formatter/oxfmt.ts"() {
356
+ "use strict";
357
+ init_esm_shims();
358
+ init_pm();
359
+ }
360
+ });
361
+
362
+ // src/constants/plugins.ts
363
+ var ESLINT_PLUGINS, PRETTIER_PLUGINS, PLUGINS, PLUGINABLE_TOOLS;
364
+ var init_plugins = __esm({
365
+ "src/constants/plugins.ts"() {
366
+ "use strict";
367
+ init_esm_shims();
368
+ ESLINT_PLUGINS = [
369
+ // Code Quality
370
+ {
371
+ value: "depend",
372
+ label: "depend",
373
+ package: "eslint-plugin-depend",
374
+ hint: "Detect junk dependencies"
375
+ },
376
+ {
377
+ value: "github",
378
+ label: "github",
379
+ package: "eslint-plugin-github",
380
+ hint: "GitHub's ESLint rules"
381
+ },
382
+ {
383
+ value: "sonarjs",
384
+ label: "sonarjs",
385
+ package: "eslint-plugin-sonarjs",
386
+ hint: "Detect bugs and suspicious patterns"
387
+ },
388
+ {
389
+ value: "unicorn",
390
+ label: "unicorn",
391
+ package: "eslint-plugin-unicorn",
392
+ hint: "Various awesome ESLint rules"
393
+ },
394
+ {
395
+ value: "mysticatea",
396
+ label: "mysticatea",
397
+ package: "@mysticatea/eslint-plugin",
398
+ hint: "Misc rules"
399
+ },
400
+ {
401
+ value: "brettz9",
402
+ label: "brettz9",
403
+ package: "@brettz9/eslint-plugin",
404
+ hint: "Misc rules without personal config"
405
+ },
406
+ {
407
+ value: "de-morgan",
408
+ label: "de-morgan",
409
+ package: "eslint-plugin-de-morgan",
410
+ hint: "Transform logical expressions"
411
+ },
412
+ {
413
+ value: "code-complete",
414
+ label: "code-complete",
415
+ package: "eslint-plugin-code-complete",
416
+ hint: "Clean, maintainable software design"
417
+ },
418
+ // Compatibility
419
+ {
420
+ value: "compat",
421
+ label: "compat",
422
+ package: "eslint-plugin-compat",
423
+ hint: "Browser compatibility checking"
424
+ },
425
+ {
426
+ value: "es-compat",
427
+ label: "es-compat",
428
+ package: "eslint-plugin-es-compat",
429
+ hint: "Disable unsupported ES features"
430
+ },
431
+ {
432
+ value: "es-x",
433
+ label: "es-x",
434
+ package: "eslint-plugin-es-x",
435
+ hint: "Disable specific ES versions"
436
+ },
437
+ {
438
+ value: "es5",
439
+ label: "es5",
440
+ package: "eslint-plugin-es5",
441
+ hint: "Forbid ES2015+ usage"
442
+ },
443
+ {
444
+ value: "ie11",
445
+ label: "ie11",
446
+ package: "eslint-plugin-ie11",
447
+ hint: "Detect unsupported ES6 features in IE11"
448
+ },
449
+ // CSS in JS
450
+ {
451
+ value: "css-modules",
452
+ label: "css-modules",
453
+ package: "eslint-plugin-css-modules",
454
+ hint: "Lint css modules"
455
+ },
456
+ {
457
+ value: "emotion",
458
+ label: "emotion",
459
+ package: "@emotion/eslint-plugin",
460
+ hint: "Rules for emotion"
461
+ },
462
+ {
463
+ value: "better-styled-components",
464
+ label: "better-styled-components",
465
+ package: "eslint-plugin-better-styled-components",
466
+ hint: "Auto fixable rules for styled components"
467
+ },
468
+ {
469
+ value: "styled-components-a11y",
470
+ label: "styled-components-a11y",
471
+ package: "eslint-plugin-styled-components-a11y",
472
+ hint: "A11y for Styled Components"
473
+ },
474
+ {
475
+ value: "vanilla-extract",
476
+ label: "vanilla-extract",
477
+ package: "@vanilla-extract/eslint-plugin",
478
+ hint: "Enforce CSS property ordering"
479
+ },
480
+ // Deprecation
481
+ {
482
+ value: "deprecate",
483
+ label: "deprecate",
484
+ package: "eslint-plugin-deprecate",
485
+ hint: "Mark functions/modules as deprecated"
486
+ },
487
+ {
488
+ value: "disable",
489
+ label: "disable",
490
+ package: "eslint-plugin-disable",
491
+ hint: "Disable plugins using patterns"
492
+ },
493
+ // Embedded
494
+ {
495
+ value: "html",
496
+ label: "html",
497
+ package: "eslint-plugin-html",
498
+ hint: "Linting JS inside HTML"
499
+ },
500
+ {
501
+ value: "markdown",
502
+ label: "markdown",
503
+ package: "eslint-plugin-markdown",
504
+ hint: "Linting JS inside Markdown"
505
+ },
506
+ // Frameworks
507
+ {
508
+ value: "angular",
509
+ label: "angular",
510
+ package: "@angular-eslint/eslint-plugin",
511
+ hint: "Linting for Angular"
512
+ },
513
+ {
514
+ value: "angularjs",
515
+ label: "angularjs",
516
+ package: "eslint-plugin-angular",
517
+ hint: "Linting for AngularJS"
518
+ },
519
+ {
520
+ value: "astro",
521
+ label: "astro",
522
+ package: "eslint-plugin-astro",
523
+ hint: "Linting for Astro"
524
+ },
525
+ {
526
+ value: "backbone",
527
+ label: "backbone",
528
+ package: "eslint-plugin-backbone",
529
+ hint: "Linting for Backbone"
530
+ },
531
+ {
532
+ value: "ember",
533
+ label: "ember",
534
+ package: "eslint-plugin-ember",
535
+ hint: "Linting for Ember"
536
+ },
537
+ {
538
+ value: "hapi",
539
+ label: "hapi",
540
+ package: "eslint-plugin-hapi",
541
+ hint: "Linting for Hapi"
542
+ },
543
+ {
544
+ value: "meteor",
545
+ label: "meteor",
546
+ package: "eslint-plugin-meteor",
547
+ hint: "Linting for Meteor"
548
+ },
549
+ {
550
+ value: "jsx-a11y",
551
+ label: "jsx-a11y",
552
+ package: "eslint-plugin-jsx-a11y",
553
+ hint: "Accessibility rules on JSX"
554
+ },
555
+ {
556
+ value: "react",
557
+ label: "react",
558
+ package: "eslint-plugin-react",
559
+ hint: "Linting for React/JSX"
560
+ },
561
+ {
562
+ value: "react-hooks",
563
+ label: "react-hooks",
564
+ package: "eslint-plugin-react-hooks",
565
+ hint: "Linting for React Hooks"
566
+ },
567
+ {
568
+ value: "react-native",
569
+ label: "react-native",
570
+ package: "eslint-plugin-react-native",
571
+ hint: "React Native specific rules"
572
+ },
573
+ {
574
+ value: "react-redux",
575
+ label: "react-redux",
576
+ package: "eslint-plugin-react-redux",
577
+ hint: "React-Redux specific rules"
578
+ },
579
+ {
580
+ value: "react-refresh",
581
+ label: "react-refresh",
582
+ package: "eslint-plugin-react-refresh",
583
+ hint: "Improve HMR with Vite"
584
+ },
585
+ {
586
+ value: "solid",
587
+ label: "solid",
588
+ package: "eslint-plugin-solid",
589
+ hint: "Linting for Solid"
590
+ },
591
+ {
592
+ value: "svelte",
593
+ label: "svelte",
594
+ package: "eslint-plugin-svelte",
595
+ hint: "Linting for Svelte"
596
+ },
597
+ {
598
+ value: "vuejs",
599
+ label: "vuejs",
600
+ package: "eslint-plugin-vue",
601
+ hint: "Linting for VueJS"
602
+ },
603
+ {
604
+ value: "vue-scoped-css",
605
+ label: "vue-scoped-css",
606
+ package: "eslint-plugin-vue-scoped-css",
607
+ hint: "Scoped CSS in VueJS"
608
+ },
609
+ // Languages and Environments
610
+ {
611
+ value: "babel",
612
+ label: "babel",
613
+ package: "@babel/eslint-plugin",
614
+ hint: "Babel features"
615
+ },
616
+ {
617
+ value: "flowtype",
618
+ label: "flowtype",
619
+ package: "eslint-plugin-flowtype",
620
+ hint: "Flow type linting"
621
+ },
622
+ {
623
+ value: "flowtype-errors",
624
+ label: "flowtype-errors",
625
+ package: "eslint-plugin-flowtype-errors",
626
+ hint: "Run Flow as plugin"
627
+ },
628
+ {
629
+ value: "html-eslint",
630
+ label: "html-eslint",
631
+ package: "@html-eslint/eslint-plugin",
632
+ hint: "Linting for HTML"
633
+ },
634
+ {
635
+ value: "json",
636
+ label: "json",
637
+ package: "eslint-plugin-json",
638
+ hint: "Lint JSON files"
639
+ },
640
+ {
641
+ value: "json-format",
642
+ label: "json-format",
643
+ package: "eslint-plugin-json-format",
644
+ hint: "Lint/Format/Fix JSON"
645
+ },
646
+ {
647
+ value: "jsonc",
648
+ label: "jsonc",
649
+ package: "eslint-plugin-jsonc",
650
+ hint: "JSON with comments"
651
+ },
652
+ {
653
+ value: "json-schema-validator",
654
+ label: "json-schema-validator",
655
+ package: "eslint-plugin-json-schema-validator",
656
+ hint: "Validate data using JSON Schema"
657
+ },
658
+ {
659
+ value: "package-json",
660
+ label: "package-json",
661
+ package: "eslint-plugin-package-json",
662
+ hint: "Rules for package.json"
663
+ },
664
+ {
665
+ value: "mdx",
666
+ label: "mdx",
667
+ package: "eslint-plugin-mdx",
668
+ hint: "Lint MDX"
669
+ },
670
+ { value: "n", label: "n", package: "eslint-plugin-n", hint: "Node.js rules" },
671
+ {
672
+ value: "sql",
673
+ label: "sql",
674
+ package: "eslint-plugin-sql",
675
+ hint: "SQL linting"
676
+ },
677
+ {
678
+ value: "toml",
679
+ label: "toml",
680
+ package: "eslint-plugin-toml",
681
+ hint: "Lint TOML"
682
+ },
683
+ {
684
+ value: "typescript",
685
+ label: "typescript",
686
+ package: "@typescript-eslint/eslint-plugin",
687
+ hint: "Lint TypeScript"
688
+ },
689
+ {
690
+ value: "erasable-syntax-only",
691
+ label: "erasable-syntax-only",
692
+ package: "eslint-plugin-erasable-syntax-only",
693
+ hint: "Enforce TS erasableSyntaxOnly"
694
+ },
695
+ {
696
+ value: "expect-type",
697
+ label: "expect-type",
698
+ package: "eslint-plugin-expect-type",
699
+ hint: "Type assertions"
700
+ },
701
+ {
702
+ value: "yaml",
703
+ label: "yaml",
704
+ package: "eslint-plugin-yml",
705
+ hint: "Lint YAML"
706
+ },
707
+ // Libraries
708
+ {
709
+ value: "graphql",
710
+ label: "graphql",
711
+ package: "@graphql-eslint/eslint-plugin",
712
+ hint: "Validate GraphQL operations/schema"
713
+ },
714
+ {
715
+ value: "graphql-schema",
716
+ label: "graphql-schema",
717
+ package: "eslint-plugin-graphql",
718
+ hint: "Check GraphQL queries against schema"
719
+ },
720
+ {
721
+ value: "type-graphql",
722
+ label: "type-graphql",
723
+ package: "eslint-plugin-type-graphql",
724
+ hint: "Lint TypeGraphQL"
725
+ },
726
+ {
727
+ value: "jquery",
728
+ label: "jquery",
729
+ package: "eslint-plugin-no-jquery",
730
+ hint: "Lint jQuery (deprecated features)"
731
+ },
732
+ {
733
+ value: "jsdoc",
734
+ label: "jsdoc",
735
+ package: "eslint-plugin-jsdoc",
736
+ hint: "Lint JSDoc comments"
737
+ },
738
+ {
739
+ value: "lodash",
740
+ label: "lodash",
741
+ package: "eslint-plugin-lodash",
742
+ hint: "Lodash rules"
743
+ },
744
+ {
745
+ value: "lodash-fp",
746
+ label: "lodash-fp",
747
+ package: "eslint-plugin-lodash-fp",
748
+ hint: "Lodash/fp rules"
749
+ },
750
+ {
751
+ value: "lodash-template",
752
+ label: "lodash-template",
753
+ package: "eslint-plugin-lodash-template",
754
+ hint: "Lodash template rules"
755
+ },
756
+ {
757
+ value: "microtemplates",
758
+ label: "microtemplates",
759
+ package: "eslint-plugin-microtemplates",
760
+ hint: "Microtemplates rules"
761
+ },
762
+ {
763
+ value: "mongodb",
764
+ label: "mongodb",
765
+ package: "eslint-plugin-mongodb",
766
+ hint: "MongoDB driver rules"
767
+ },
768
+ {
769
+ value: "ramda",
770
+ label: "ramda",
771
+ package: "eslint-plugin-ramda",
772
+ hint: "Ramda rules"
773
+ },
774
+ {
775
+ value: "requirejs",
776
+ label: "requirejs",
777
+ package: "eslint-plugin-requirejs",
778
+ hint: "RequireJS rules"
779
+ },
780
+ {
781
+ value: "tailwindcss",
782
+ label: "tailwindcss",
783
+ package: "eslint-plugin-tailwindcss",
784
+ hint: "Tailwind CSS rules"
785
+ },
786
+ {
787
+ value: "better-tailwindcss",
788
+ label: "better-tailwindcss",
789
+ package: "eslint-plugin-better-tailwindcss",
790
+ hint: "Improve readability/best practices"
791
+ },
792
+ // Misc
793
+ {
794
+ value: "diff",
795
+ label: "diff",
796
+ package: "eslint-plugin-diff",
797
+ hint: "Lint changed lines only"
798
+ },
799
+ {
800
+ value: "misc",
801
+ label: "misc",
802
+ package: "eslint-plugin-misc",
803
+ hint: "Miscellaneous rules"
804
+ },
805
+ {
806
+ value: "notice",
807
+ label: "notice",
808
+ package: "eslint-plugin-notice",
809
+ hint: "Check top of files"
810
+ },
811
+ {
812
+ value: "only-error",
813
+ label: "only-error",
814
+ package: "eslint-plugin-only-error",
815
+ hint: "Convert all rules to errors"
816
+ },
817
+ {
818
+ value: "only-warn",
819
+ label: "only-warn",
820
+ package: "eslint-plugin-only-warn",
821
+ hint: "Convert all rules to warnings"
822
+ },
823
+ {
824
+ value: "putout",
825
+ label: "putout",
826
+ package: "eslint-plugin-putout",
827
+ hint: "Integrate PutOut linter"
828
+ },
829
+ {
830
+ value: "typelint",
831
+ label: "typelint",
832
+ package: "eslint-plugin-typelint",
833
+ hint: "Introduce types based on schemas"
834
+ },
835
+ {
836
+ value: "woke",
837
+ label: "woke",
838
+ package: "eslint-plugin-woke",
839
+ hint: "Catch insensitive words"
840
+ },
841
+ // Practices and Specific ES Features
842
+ {
843
+ value: "array-func",
844
+ label: "array-func",
845
+ package: "eslint-plugin-array-func",
846
+ hint: "Avoid redundancy with array methods"
847
+ },
848
+ {
849
+ value: "proper-arrows",
850
+ label: "proper-arrows",
851
+ package: "eslint-plugin-proper-arrows",
852
+ hint: "Ensure proper arrow function definitions"
853
+ },
854
+ {
855
+ value: "boundaries",
856
+ label: "boundaries",
857
+ package: "eslint-plugin-boundaries",
858
+ hint: "Enforce architecture boundaries"
859
+ },
860
+ {
861
+ value: "eslint-comments",
862
+ label: "eslint-comments",
863
+ package: "eslint-plugin-eslint-comments",
864
+ hint: "Best practices for ESLint directives"
865
+ },
866
+ {
867
+ value: "error-cause",
868
+ label: "error-cause",
869
+ package: "eslint-plugin-error-cause",
870
+ hint: "Preserve error context"
871
+ },
872
+ {
873
+ value: "hexagonal-architecture",
874
+ label: "hexagonal-architecture",
875
+ package: "eslint-plugin-hexagonal-architecture",
876
+ hint: "Hexagonal architecture best practices"
877
+ },
878
+ {
879
+ value: "signature-design",
880
+ label: "signature-design",
881
+ package: "eslint-plugin-signature-design",
882
+ hint: "Enforce object-based signatures"
883
+ },
884
+ {
885
+ value: "write-good-comments",
886
+ label: "write-good-comments",
887
+ package: "eslint-plugin-write-good-comments",
888
+ hint: "Enforce good comment style"
889
+ },
890
+ {
891
+ value: "exception-handling",
892
+ label: "exception-handling",
893
+ package: "eslint-plugin-exception-handling",
894
+ hint: "Lint unhandled exceptions"
895
+ },
896
+ {
897
+ value: "fp",
898
+ label: "fp",
899
+ package: "eslint-plugin-fp",
900
+ hint: "Functional programming rules"
901
+ },
902
+ {
903
+ value: "functional",
904
+ label: "functional",
905
+ package: "eslint-plugin-functional",
906
+ hint: "Disable mutation, promote FP"
907
+ },
908
+ {
909
+ value: "mutate",
910
+ label: "mutate",
911
+ package: "eslint-plugin-mutate",
912
+ hint: "Prevent accidental mutations"
913
+ },
914
+ {
915
+ value: "immutable",
916
+ label: "immutable",
917
+ package: "eslint-plugin-immutable",
918
+ hint: "Disable all mutation"
919
+ },
920
+ {
921
+ value: "import",
922
+ label: "import",
923
+ package: "eslint-plugin-import",
924
+ hint: "Lint import/export syntax"
925
+ },
926
+ {
927
+ value: "import-x",
928
+ label: "import-x",
929
+ package: "eslint-plugin-import-x",
930
+ hint: "Lightweight fork of eslint-plugin-import"
931
+ },
932
+ {
933
+ value: "math",
934
+ label: "math",
935
+ package: "eslint-plugin-math",
936
+ hint: "Math object rules"
937
+ },
938
+ {
939
+ value: "new-with-error",
940
+ label: "new-with-error",
941
+ package: "eslint-plugin-new-with-error",
942
+ hint: "Require new with Error"
943
+ },
944
+ {
945
+ value: "no-argument-spread",
946
+ label: "no-argument-spread",
947
+ package: "eslint-plugin-no-argument-spread",
948
+ hint: "Lint against spread arguments"
949
+ },
950
+ {
951
+ value: "no-comments",
952
+ label: "no-comments",
953
+ package: "eslint-plugin-no-comments",
954
+ hint: "Prevent leaking comments"
955
+ },
956
+ {
957
+ value: "no-constructor-bind",
958
+ label: "no-constructor-bind",
959
+ package: "eslint-plugin-no-constructor-bind",
960
+ hint: "Encourage class properties"
961
+ },
962
+ {
963
+ value: "no-inferred-method-name",
964
+ label: "no-inferred-method-name",
965
+ package: "eslint-plugin-no-inferred-method-name",
966
+ hint: "Check inferred method names"
967
+ },
968
+ {
969
+ value: "no-loops",
970
+ label: "no-loops",
971
+ package: "eslint-plugin-no-loops",
972
+ hint: "Disallow loops"
973
+ },
974
+ {
975
+ value: "query",
976
+ label: "query",
977
+ package: "eslint-plugin-query",
978
+ hint: "Show queried syntax content"
979
+ },
980
+ {
981
+ value: "no-use-extend-native",
982
+ label: "no-use-extend-native",
983
+ package: "eslint-plugin-no-use-extend-native",
984
+ hint: "Prevent using extended native objects"
985
+ },
986
+ {
987
+ value: "promise",
988
+ label: "promise",
989
+ package: "eslint-plugin-promise",
990
+ hint: "Promise best practices"
991
+ },
992
+ {
993
+ value: "pure",
994
+ label: "pure",
995
+ package: "eslint-plugin-pure",
996
+ hint: "Enforce pure functions"
997
+ },
998
+ {
999
+ value: "redos",
1000
+ label: "redos",
1001
+ package: "eslint-plugin-redos",
1002
+ hint: "Find ReDoS vulnerabilities"
1003
+ },
1004
+ {
1005
+ value: "redos-detector",
1006
+ label: "redos-detector",
1007
+ package: "eslint-plugin-redos-detector",
1008
+ hint: "Find ReDoS vulnerabilities"
1009
+ },
1010
+ {
1011
+ value: "regexp",
1012
+ label: "regexp",
1013
+ package: "eslint-plugin-regexp",
1014
+ hint: "Find regexp mistakes"
1015
+ },
1016
+ {
1017
+ value: "sort-keys-fix",
1018
+ label: "sort-keys-fix",
1019
+ package: "eslint-plugin-sort-keys-fix",
1020
+ hint: "Fixer for sort-keys"
1021
+ },
1022
+ {
1023
+ value: "this",
1024
+ label: "this",
1025
+ package: "eslint-plugin-this",
1026
+ hint: "Disallow this"
1027
+ },
1028
+ {
1029
+ value: "toplevel",
1030
+ label: "toplevel",
1031
+ package: "eslint-plugin-toplevel",
1032
+ hint: "Disallow side effects at top level"
1033
+ },
1034
+ // Performance
1035
+ {
1036
+ value: "dom",
1037
+ label: "dom",
1038
+ package: "eslint-plugin-dom",
1039
+ hint: "DOM performance"
1040
+ },
1041
+ {
1042
+ value: "optimize-regex",
1043
+ label: "optimize-regex",
1044
+ package: "eslint-plugin-optimize-regex",
1045
+ hint: "Optimize regex literals"
1046
+ },
1047
+ {
1048
+ value: "perf-standard",
1049
+ label: "perf-standard",
1050
+ package: "eslint-plugin-perf-standard",
1051
+ hint: "Performance standard rules"
1052
+ },
1053
+ // Security
1054
+ {
1055
+ value: "no-secrets",
1056
+ label: "no-secrets",
1057
+ package: "eslint-plugin-no-secrets",
1058
+ hint: "Detect potential secrets"
1059
+ },
1060
+ {
1061
+ value: "no-unsanitized",
1062
+ label: "no-unsanitized",
1063
+ package: "eslint-plugin-no-unsanitized",
1064
+ hint: "Checks for innerHTML etc"
1065
+ },
1066
+ {
1067
+ value: "pii",
1068
+ label: "pii",
1069
+ package: "eslint-plugin-pii",
1070
+ hint: "Enforce PII compliance"
1071
+ },
1072
+ {
1073
+ value: "pg",
1074
+ label: "pg",
1075
+ package: "eslint-plugin-pg",
1076
+ hint: "PostgreSQL security"
1077
+ },
1078
+ {
1079
+ value: "security",
1080
+ label: "security",
1081
+ package: "eslint-plugin-security",
1082
+ hint: "Node Security rules"
1083
+ },
1084
+ {
1085
+ value: "xss",
1086
+ label: "xss",
1087
+ package: "eslint-plugin-xss",
1088
+ hint: "Detect XSS issues"
1089
+ },
1090
+ // Style
1091
+ {
1092
+ value: "stylistic",
1093
+ label: "stylistic",
1094
+ package: "@stylistic/eslint-plugin",
1095
+ hint: "Formatting and stylistic rules"
1096
+ },
1097
+ {
1098
+ value: "const-case",
1099
+ label: "const-case",
1100
+ package: "eslint-plugin-const-case",
1101
+ hint: "Enforce capitalization of constants"
1102
+ },
1103
+ {
1104
+ value: "editorconfig",
1105
+ label: "editorconfig",
1106
+ package: "eslint-plugin-editorconfig",
1107
+ hint: "Derive rules from .editorconfig"
1108
+ },
1109
+ {
1110
+ value: "simple-import-sort",
1111
+ label: "simple-import-sort",
1112
+ package: "eslint-plugin-simple-import-sort",
1113
+ hint: "Easy import sorting"
1114
+ },
1115
+ {
1116
+ value: "perfectionist",
1117
+ label: "perfectionist",
1118
+ package: "eslint-plugin-perfectionist",
1119
+ hint: "Sort objects, imports, etc."
1120
+ },
1121
+ {
1122
+ value: "split-and-sort-imports",
1123
+ label: "split-and-sort-imports",
1124
+ package: "eslint-plugin-split-and-sort-imports",
1125
+ hint: "Split and sort imports"
1126
+ },
1127
+ {
1128
+ value: "switch-case",
1129
+ label: "switch-case",
1130
+ package: "eslint-plugin-switch-case",
1131
+ hint: "Switch-case specific rules"
1132
+ },
1133
+ {
1134
+ value: "padding",
1135
+ label: "padding",
1136
+ package: "eslint-plugin-padding",
1137
+ hint: "Padding between statements"
1138
+ },
1139
+ {
1140
+ value: "paths",
1141
+ label: "paths",
1142
+ package: "eslint-plugin-paths",
1143
+ hint: "Use paths from tsconfig/jsconfig"
1144
+ },
1145
+ {
1146
+ value: "no-relative-imports",
1147
+ label: "no-relative-imports",
1148
+ package: "@gitbutler/no-relative-imports",
1149
+ hint: "Auto fix relative paths"
1150
+ },
1151
+ // Testing Tools
1152
+ {
1153
+ value: "ava",
1154
+ label: "ava",
1155
+ package: "eslint-plugin-ava",
1156
+ hint: "AVA rules"
1157
+ },
1158
+ {
1159
+ value: "chai-expect",
1160
+ label: "chai-expect",
1161
+ package: "eslint-plugin-chai-expect",
1162
+ hint: "Chai expect practices"
1163
+ },
1164
+ {
1165
+ value: "chai-friendly",
1166
+ label: "chai-friendly",
1167
+ package: "eslint-plugin-chai-friendly",
1168
+ hint: "Chai unused expressions"
1169
+ },
1170
+ {
1171
+ value: "chai-expect-keywords",
1172
+ label: "chai-expect-keywords",
1173
+ package: "eslint-plugin-chai-expect-keywords",
1174
+ hint: "Permitted keywords"
1175
+ },
1176
+ {
1177
+ value: "chai-as-promised",
1178
+ label: "chai-as-promised",
1179
+ package: "eslint-plugin-chai-as-promised",
1180
+ hint: "Chai as promised"
1181
+ },
1182
+ {
1183
+ value: "chai-assert-bdd",
1184
+ label: "chai-assert-bdd",
1185
+ package: "eslint-plugin-chai-assert-bdd",
1186
+ hint: "Chai globals"
1187
+ },
1188
+ {
1189
+ value: "cucumber",
1190
+ label: "cucumber",
1191
+ package: "eslint-plugin-cucumber",
1192
+ hint: "Cucumber rules"
1193
+ },
1194
+ {
1195
+ value: "cypress",
1196
+ label: "cypress",
1197
+ package: "eslint-plugin-cypress",
1198
+ hint: "Cypress rules"
1199
+ },
1200
+ {
1201
+ value: "jasmine",
1202
+ label: "jasmine",
1203
+ package: "eslint-plugin-jasmine",
1204
+ hint: "Jasmine rules"
1205
+ },
1206
+ {
1207
+ value: "jest",
1208
+ label: "jest",
1209
+ package: "eslint-plugin-jest",
1210
+ hint: "Jest practices"
1211
+ },
1212
+ {
1213
+ value: "jest-formatting",
1214
+ label: "jest-formatting",
1215
+ package: "eslint-plugin-jest-formatting",
1216
+ hint: "Jest formatting"
1217
+ },
1218
+ {
1219
+ value: "jest-async",
1220
+ label: "jest-async",
1221
+ package: "eslint-plugin-jest-async",
1222
+ hint: "Jest async rules"
1223
+ },
1224
+ {
1225
+ value: "jest-dom",
1226
+ label: "jest-dom",
1227
+ package: "eslint-plugin-jest-dom",
1228
+ hint: "Jest-DOM rules"
1229
+ },
1230
+ {
1231
+ value: "mocha",
1232
+ label: "mocha",
1233
+ package: "eslint-plugin-mocha",
1234
+ hint: "Mocha practices"
1235
+ },
1236
+ {
1237
+ value: "mocha-cleanup",
1238
+ label: "mocha-cleanup",
1239
+ package: "eslint-plugin-mocha-cleanup",
1240
+ hint: "Mocha cleanup"
1241
+ },
1242
+ {
1243
+ value: "playwright",
1244
+ label: "playwright",
1245
+ package: "eslint-plugin-playwright",
1246
+ hint: "Playwright rules"
1247
+ },
1248
+ {
1249
+ value: "qunit",
1250
+ label: "qunit",
1251
+ package: "eslint-plugin-qunit",
1252
+ hint: "QUnit rules"
1253
+ },
1254
+ {
1255
+ value: "testcafe-community",
1256
+ label: "testcafe-community",
1257
+ package: "eslint-plugin-testcafe-community",
1258
+ hint: "TestCafe rules"
1259
+ },
1260
+ {
1261
+ value: "testing-library",
1262
+ label: "testing-library",
1263
+ package: "eslint-plugin-testing-library",
1264
+ hint: "Testing Library rules"
1265
+ }
1266
+ ];
1267
+ PRETTIER_PLUGINS = [
1268
+ // Official
1269
+ {
1270
+ value: "php",
1271
+ label: "php",
1272
+ package: "@prettier/plugin-php",
1273
+ hint: "Prettier for PHP"
1274
+ },
1275
+ {
1276
+ value: "pug",
1277
+ label: "pug",
1278
+ package: "@prettier/plugin-pug",
1279
+ hint: "Prettier for Pug"
1280
+ },
1281
+ {
1282
+ value: "ruby",
1283
+ label: "ruby",
1284
+ package: "@prettier/plugin-ruby",
1285
+ hint: "Prettier for Ruby"
1286
+ },
1287
+ {
1288
+ value: "xml",
1289
+ label: "xml",
1290
+ package: "@prettier/plugin-xml",
1291
+ hint: "Prettier for XML"
1292
+ },
1293
+ // Community
1294
+ {
1295
+ value: "apex",
1296
+ label: "apex",
1297
+ package: "prettier-plugin-apex",
1298
+ hint: "Prettier for Apex"
1299
+ },
1300
+ {
1301
+ value: "astro",
1302
+ label: "astro",
1303
+ package: "prettier-plugin-astro",
1304
+ hint: "Prettier for Astro"
1305
+ },
1306
+ {
1307
+ value: "bigcommerce",
1308
+ label: "bigcommerce",
1309
+ package: "prettier-plugin-bigcommerce-stencil",
1310
+ hint: "Prettier for BigCommerce"
1311
+ },
1312
+ {
1313
+ value: "elm",
1314
+ label: "elm",
1315
+ package: "prettier-plugin-elm",
1316
+ hint: "Prettier for Elm"
1317
+ },
1318
+ {
1319
+ value: "erb",
1320
+ label: "erb",
1321
+ package: "prettier-plugin-erb",
1322
+ hint: "Prettier for ERB"
1323
+ },
1324
+ {
1325
+ value: "gherkin",
1326
+ label: "gherkin",
1327
+ package: "prettier-plugin-gherkin",
1328
+ hint: "Prettier for Gherkin"
1329
+ },
1330
+ {
1331
+ value: "glsl",
1332
+ label: "glsl",
1333
+ package: "prettier-plugin-glsl",
1334
+ hint: "Prettier for GLSL"
1335
+ },
1336
+ {
1337
+ value: "go-template",
1338
+ label: "go-template",
1339
+ package: "prettier-plugin-go-template",
1340
+ hint: "Prettier for Go Templates"
1341
+ },
1342
+ {
1343
+ value: "hugo",
1344
+ label: "hugo",
1345
+ package: "prettier-plugin-hugo-post",
1346
+ hint: "Prettier for Hugo"
1347
+ },
1348
+ {
1349
+ value: "java",
1350
+ label: "java",
1351
+ package: "prettier-plugin-java",
1352
+ hint: "Prettier for Java"
1353
+ },
1354
+ {
1355
+ value: "jinja",
1356
+ label: "jinja",
1357
+ package: "prettier-plugin-jinja-template",
1358
+ hint: "Prettier for Jinja"
1359
+ },
1360
+ {
1361
+ value: "jsonata",
1362
+ label: "jsonata",
1363
+ package: "prettier-plugin-jsonata",
1364
+ hint: "Prettier for JSONata"
1365
+ },
1366
+ {
1367
+ value: "kotlin",
1368
+ label: "kotlin",
1369
+ package: "prettier-plugin-kotlin",
1370
+ hint: "Prettier for Kotlin"
1371
+ },
1372
+ {
1373
+ value: "marko",
1374
+ label: "marko",
1375
+ package: "prettier-plugin-marko",
1376
+ hint: "Prettier for Marko"
1377
+ },
1378
+ {
1379
+ value: "motoko",
1380
+ label: "motoko",
1381
+ package: "prettier-plugin-motoko",
1382
+ hint: "Prettier for Motoko"
1383
+ },
1384
+ {
1385
+ value: "nginx",
1386
+ label: "nginx",
1387
+ package: "prettier-plugin-nginx",
1388
+ hint: "Prettier for Nginx"
1389
+ },
1390
+ {
1391
+ value: "prisma",
1392
+ label: "prisma",
1393
+ package: "prettier-plugin-prisma",
1394
+ hint: "Prettier for Prisma"
1395
+ },
1396
+ {
1397
+ value: "properties",
1398
+ label: "properties",
1399
+ package: "prettier-plugin-properties",
1400
+ hint: "Prettier for Properties"
1401
+ },
1402
+ {
1403
+ value: "rust",
1404
+ label: "rust",
1405
+ package: "prettier-plugin-rust",
1406
+ hint: "Prettier for Rust"
1407
+ },
1408
+ {
1409
+ value: "sh",
1410
+ label: "sh",
1411
+ package: "prettier-plugin-sh",
1412
+ hint: "Prettier for Shell"
1413
+ },
1414
+ {
1415
+ value: "sql",
1416
+ label: "sql",
1417
+ package: "prettier-plugin-sql",
1418
+ hint: "Prettier for SQL"
1419
+ },
1420
+ {
1421
+ value: "sql-cst",
1422
+ label: "sql-cst",
1423
+ package: "prettier-plugin-sql-cst",
1424
+ hint: "Prettier for SQL (CST)"
1425
+ },
1426
+ {
1427
+ value: "solidity",
1428
+ label: "solidity",
1429
+ package: "prettier-plugin-solidity",
1430
+ hint: "Prettier for Solidity"
1431
+ },
1432
+ {
1433
+ value: "svelte",
1434
+ label: "svelte",
1435
+ package: "prettier-plugin-svelte",
1436
+ hint: "Prettier for Svelte"
1437
+ },
1438
+ {
1439
+ value: "toml",
1440
+ label: "toml",
1441
+ package: "prettier-plugin-toml",
1442
+ hint: "Prettier for TOML"
1443
+ },
1444
+ {
1445
+ value: "xquery",
1446
+ label: "xquery",
1447
+ package: "prettier-plugin-xquery",
1448
+ hint: "Prettier for XQuery"
1449
+ },
1450
+ // Existing
1451
+ {
1452
+ value: "tailwindcss",
1453
+ label: "tailwindcss",
1454
+ package: "prettier-plugin-tailwindcss",
1455
+ hint: "Prettier for Tailwind CSS"
1456
+ },
1457
+ {
1458
+ value: "organize-imports",
1459
+ label: "organize-imports",
1460
+ package: "prettier-plugin-organize-imports",
1461
+ hint: "Organize imports"
1462
+ },
1463
+ {
1464
+ value: "sort-imports",
1465
+ label: "sort-imports",
1466
+ package: "@trivago/prettier-plugin-sort-imports",
1467
+ hint: "Sort imports"
1468
+ },
1469
+ {
1470
+ value: "pkg",
1471
+ label: "pkg",
1472
+ package: "prettier-plugin-pkg",
1473
+ hint: "Format package.json"
1474
+ }
1475
+ ];
1476
+ PLUGINS = {
1477
+ eslint: ESLINT_PLUGINS,
1478
+ prettier: PRETTIER_PLUGINS
1479
+ };
1480
+ PLUGINABLE_TOOLS = Object.keys(PLUGINS);
1481
+ }
1482
+ });
1483
+
1484
+ // src/features/linter/eslint.ts
1485
+ import fs4 from "fs-extra";
1486
+ async function installEslint() {
1487
+ const packages = ["eslint", "globals", "@eslint/js", "typescript-eslint"];
1488
+ await installPackages(packages, true);
1489
+ const configFile = await resolveConfigFile("ESLint", [
1490
+ "eslint.config.mjs",
1491
+ "eslint.config.js",
1492
+ "eslint.config.cjs"
1493
+ ]);
1494
+ if (!await fs4.pathExists(configFile)) {
1495
+ await fs4.writeFile(
1496
+ configFile,
1497
+ `import globals from "globals";
1498
+ import pluginJs from "@eslint/js";
1499
+ import tseslint from "typescript-eslint";
1500
+
1501
+
1502
+ export default [
1503
+ {files: ["**/*.{js,mjs,cjs,ts}"]},
1504
+ {languageOptions: { globals: globals.browser }},
1505
+ pluginJs.configs.recommended,
1506
+ ...tseslint.configs.recommended,
1507
+ ];`
1508
+ );
1509
+ }
1510
+ }
1511
+ async function configureEslintPlugins(plugins) {
1512
+ const configFile = await resolveConfigFile("ESLint", [
1513
+ "eslint.config.mjs",
1514
+ "eslint.config.js",
1515
+ "eslint.config.cjs"
1516
+ ]);
1517
+ if (!await fs4.pathExists(configFile)) {
1518
+ return;
1519
+ }
1520
+ let configContent = await fs4.readFile(configFile, "utf-8");
1521
+ const newImports = [];
1522
+ const newPluginConfigs = [];
1523
+ for (const pluginName of plugins) {
1524
+ const pluginDef = PLUGINS.eslint.find((p) => p.value === pluginName);
1525
+ const packageName = pluginDef?.package || `eslint-plugin-${pluginName}`;
1526
+ const safeVarName = pluginName.replace(/[^a-zA-Z0-9]/g, "") + "Plugin";
1527
+ if (!configContent.includes(`import ${safeVarName}`)) {
1528
+ newImports.push(`import ${safeVarName} from "${packageName}";`);
1529
+ }
1530
+ const shorPluginName = pluginName.replace(/^eslint-plugin-/, "");
1531
+ newPluginConfigs.push(`"${shorPluginName}": ${safeVarName}`);
1532
+ }
1533
+ if (newImports.length > 0) {
1534
+ const lastImportIndex = configContent.lastIndexOf("import ");
1535
+ const endOfLastImport = configContent.indexOf("\n", lastImportIndex) + 1;
1536
+ configContent = configContent.slice(0, endOfLastImport) + newImports.join("\n") + "\n" + configContent.slice(endOfLastImport);
1537
+ }
1538
+ if (newPluginConfigs.length > 0) {
1539
+ const exportDefaultStart = configContent.indexOf("export default [");
1540
+ if (exportDefaultStart !== -1) {
1541
+ const pluginsBlock = `
1542
+ {
1543
+ plugins: {
1544
+ ${newPluginConfigs.join(",\n ")}
1545
+ }
1546
+ },`;
1547
+ const insertPos = exportDefaultStart + "export default [".length;
1548
+ configContent = configContent.slice(0, insertPos) + pluginsBlock + configContent.slice(insertPos);
1549
+ }
1550
+ }
1551
+ await fs4.writeFile(configFile, configContent);
1552
+ }
1553
+ var init_eslint = __esm({
1554
+ "src/features/linter/eslint.ts"() {
1555
+ "use strict";
1556
+ init_esm_shims();
1557
+ init_pm();
1558
+ init_plugins();
1559
+ init_config_file();
1560
+ }
1561
+ });
1562
+
1563
+ // src/steps/install-plugin.ts
1564
+ import { multiselect, outro, confirm as confirm2 } from "@clack/prompts";
248
1565
  import pc2 from "picocolors";
1566
+ async function installPlugins(tool) {
1567
+ const pluginsList = PLUGINS[tool];
1568
+ const selectedPlugins = await withCancelHandling(
1569
+ async () => multiselect({
1570
+ message: `Select ${tool} plugins to install:`,
1571
+ options: pluginsList,
1572
+ required: true
1573
+ })
1574
+ );
1575
+ if (selectedPlugins.length === 0) {
1576
+ outro(pc2.yellow("No plugins selected."));
1577
+ return;
1578
+ }
1579
+ const packagesToInstall = selectedPlugins.map((val) => {
1580
+ const p = pluginsList.find((opt) => opt.value === val);
1581
+ return p ? p.package : val;
1582
+ });
1583
+ outro(
1584
+ pc2.blue(`Installing ${packagesToInstall.length} plugins for ${tool}...`)
1585
+ );
1586
+ await installPackages(packagesToInstall, true);
1587
+ await configurePlugins(tool, selectedPlugins);
1588
+ }
1589
+ async function configurePlugins(tool, plugins) {
1590
+ const shouldConfigure = await withCancelHandling(
1591
+ async () => confirm2({
1592
+ message: `Do you want to configure the selected plugins in your ${tool} config file?`,
1593
+ initialValue: true
1594
+ })
1595
+ );
1596
+ if (!shouldConfigure) {
1597
+ outro(pc2.yellow("Skipping configuration."));
1598
+ return;
1599
+ }
1600
+ switch (tool) {
1601
+ case "prettier":
1602
+ await configurePrettierPlugins(plugins);
1603
+ outro(pc2.green("Prettier plugins configured in .prettierrc"));
1604
+ break;
1605
+ case "eslint":
1606
+ await configureEslintPlugins(plugins);
1607
+ outro(pc2.green("ESLint plugins configured in .eslintrc.json"));
1608
+ break;
1609
+ }
1610
+ }
1611
+ var init_install_plugin = __esm({
1612
+ "src/steps/install-plugin.ts"() {
1613
+ "use strict";
1614
+ init_esm_shims();
1615
+ init_plugins();
1616
+ init_prettier();
1617
+ init_eslint();
1618
+ init_handle_cancel();
1619
+ init_pm();
1620
+ }
1621
+ });
1622
+
1623
+ // src/features/formatter.ts
1624
+ import { select as select3, log as log2, confirm as confirm3 } from "@clack/prompts";
1625
+ import pc3 from "picocolors";
249
1626
  async function promptFormatter(config2) {
250
1627
  const formatterConfig = config2.get("formatter");
251
- log2.message(pc2.bgBlue(pc2.black(" Formatter Configuration ")));
1628
+ log2.message(pc3.bgBlue(pc3.white(" Formatter Configuration ")));
252
1629
  const formatter = await withCancelHandling(
253
- async () => select2({
1630
+ async () => select3({
254
1631
  message: "Select a formatter:",
255
1632
  options: FORMATTER_OPTIONS,
256
1633
  initialValue: formatterConfig.options.choice
@@ -259,40 +1636,54 @@ async function promptFormatter(config2) {
259
1636
  formatterConfig.options = { choice: formatter };
260
1637
  }
261
1638
  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
- }
1639
+ const formatter = config2.get("formatter").options.choice;
1640
+ if (!formatter) return;
1641
+ log2.message(pc3.white(pc3.bgBlack(` Installing ${formatter}... `)));
1642
+ if (formatter === "prettier") await installPrettier();
1643
+ else if (formatter === "oxfmt") await installOxfmt();
1644
+ if (!PLUGINABLE_TOOLS.includes(formatter)) return;
1645
+ const shouldConfigure = await withCancelHandling(
1646
+ async () => confirm3({
1647
+ message: `Do you want to install plugins for ${formatter}?`,
1648
+ initialValue: true
1649
+ })
1650
+ );
1651
+ if (!shouldConfigure) return;
1652
+ await installPlugins(formatter);
276
1653
  }
277
1654
  var init_formatter = __esm({
278
- "src/services/formatter.ts"() {
1655
+ "src/features/formatter.ts"() {
279
1656
  "use strict";
280
1657
  init_esm_shims();
281
- init_pm();
282
1658
  init_options();
283
1659
  init_handle_cancel();
1660
+ init_prettier();
1661
+ init_oxfmt();
1662
+ init_plugins();
1663
+ init_install_plugin();
284
1664
  }
285
1665
  });
286
1666
 
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";
1667
+ // src/features/linter/oxlint.ts
1668
+ async function installOxlint() {
1669
+ await installPackages(["oxlint@latest"], true);
1670
+ }
1671
+ var init_oxlint = __esm({
1672
+ "src/features/linter/oxlint.ts"() {
1673
+ "use strict";
1674
+ init_esm_shims();
1675
+ init_pm();
1676
+ }
1677
+ });
1678
+
1679
+ // src/features/linter.ts
1680
+ import { select as select4, log as log3, confirm as confirm4 } from "@clack/prompts";
1681
+ import pc4 from "picocolors";
291
1682
  async function promptLinter(config2) {
292
1683
  const linterConfig = config2.get("linter");
293
- log3.message(pc3.bgYellow(pc3.black(" Linter Configuration ")));
1684
+ log3.message(pc4.bgYellow(pc4.black(" Linter Configuration ")));
294
1685
  const linter = await withCancelHandling(
295
- async () => select3({
1686
+ async () => select4({
296
1687
  message: "Select a linter:",
297
1688
  options: LINTER_OPTIONS,
298
1689
  initialValue: linterConfig.options.choice
@@ -301,50 +1692,48 @@ async function promptLinter(config2) {
301
1692
  linterConfig.options = { choice: linter };
302
1693
  }
303
1694
  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
- }
1695
+ const linter = config2.get("linter").options.choice;
1696
+ if (!linter) return;
1697
+ log3.message(pc4.white(pc4.bgBlack(` Installing ${linter}... `)));
1698
+ if (linter === "eslint") await installEslint();
1699
+ else if (linter === "oxlint") await installOxlint();
1700
+ if (!PLUGINABLE_TOOLS.includes(linter)) return;
1701
+ const shouldConfigure = await withCancelHandling(
1702
+ async () => confirm4({
1703
+ message: `Do you want to install plugins for ${linter}?`,
1704
+ initialValue: true
1705
+ })
1706
+ );
1707
+ if (!shouldConfigure) return;
1708
+ await installPlugins(linter);
322
1709
  }
323
1710
  var init_linter = __esm({
324
- "src/services/linter.ts"() {
1711
+ "src/features/linter.ts"() {
325
1712
  "use strict";
326
1713
  init_esm_shims();
327
- init_pm();
328
1714
  init_options();
329
1715
  init_handle_cancel();
1716
+ init_eslint();
1717
+ init_oxlint();
1718
+ init_plugins();
1719
+ init_install_plugin();
330
1720
  }
331
1721
  });
332
1722
 
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";
1723
+ // src/features/lint-staged.ts
1724
+ import { multiselect as multiselect2, log as log4 } from "@clack/prompts";
1725
+ import pc5 from "picocolors";
337
1726
  async function promptLintStaged(config2) {
338
- log4.message(pc4.bgGreen(pc4.black(" Lint-staged Configuration ")));
1727
+ log4.message(pc5.bgGreen(pc5.black(" Lint-staged Configuration ")));
339
1728
  const lintExtensions = await withCancelHandling(
340
- async () => multiselect({
1729
+ async () => multiselect2({
341
1730
  message: "Select extensions to lint:",
342
1731
  options: LINT_STAGED_EXTENSIONS,
343
1732
  required: false
344
1733
  })
345
1734
  );
346
1735
  const formatExtensions = await withCancelHandling(
347
- async () => multiselect({
1736
+ async () => multiselect2({
348
1737
  message: "Select extensions to format:",
349
1738
  options: LINT_STAGED_EXTENSIONS,
350
1739
  required: false
@@ -365,6 +1754,13 @@ async function promptLintStaged(config2) {
365
1754
  }
366
1755
  async function installLintStaged(config2) {
367
1756
  await installPackages(["lint-staged"], true);
1757
+ const configFile = await resolveConfigFile("Lint-Staged", [
1758
+ ".lintstagedrc",
1759
+ ".lintstagedrc.json",
1760
+ "lint-staged.config.js",
1761
+ ".lintstagedrc.js",
1762
+ ".lintstagedrc.mjs"
1763
+ ]);
368
1764
  const lintStagedConfig = {};
369
1765
  const lintStagedOptions = config2.get("lintStaged").options;
370
1766
  const lintExts = lintStagedOptions?.lintExtensions || [];
@@ -387,10 +1783,10 @@ async function installLintStaged(config2) {
387
1783
  lintStagedConfig[glob] = ["prettier --write"];
388
1784
  }
389
1785
  }
390
- await fs4.writeJson(".lintstagedrc", lintStagedConfig, { spaces: 2 });
1786
+ await writeConfig(configFile, lintStagedConfig);
391
1787
  }
392
1788
  var init_lint_staged = __esm({
393
- "src/services/lint-staged.ts"() {
1789
+ "src/features/lint-staged.ts"() {
394
1790
  "use strict";
395
1791
  init_esm_shims();
396
1792
  init_pm();
@@ -398,37 +1794,38 @@ var init_lint_staged = __esm({
398
1794
  init_linter();
399
1795
  init_options();
400
1796
  init_handle_cancel();
1797
+ init_config_file();
401
1798
  }
402
1799
  });
403
1800
 
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";
1801
+ // src/features/env.ts
1802
+ import { select as select5, confirm as confirm5, text as text2, multiselect as multiselect3, log as log5 } from "@clack/prompts";
406
1803
  import fs5 from "fs-extra";
407
- import path2 from "path";
408
- import pc5 from "picocolors";
1804
+ import path3 from "path";
1805
+ import pc6 from "picocolors";
409
1806
  async function promptEnv(config2) {
410
- log5.message(pc5.bgCyan(pc5.black(" Env Validation Configuration ")));
1807
+ log5.message(pc6.bgCyan(pc6.black(" Env Validation Configuration ")));
411
1808
  const variant = await withCancelHandling(
412
- async () => select4({
1809
+ async () => select5({
413
1810
  message: "Which @t3-oss/env variant?",
414
1811
  options: ENV_VARIANT_OPTIONS
415
1812
  })
416
1813
  );
417
1814
  const validator = await withCancelHandling(
418
- async () => select4({
1815
+ async () => select5({
419
1816
  message: "Which validator?",
420
1817
  options: ENV_VALIDATOR_OPTIONS
421
1818
  })
422
1819
  );
423
1820
  const installPresets = await withCancelHandling(
424
- async () => confirm2({
1821
+ async () => confirm5({
425
1822
  message: "Install presets?"
426
1823
  })
427
1824
  );
428
1825
  let presets;
429
1826
  if (installPresets) {
430
1827
  presets = await withCancelHandling(
431
- async () => multiselect2({
1828
+ async () => multiselect3({
432
1829
  message: "Select preset to extend:",
433
1830
  options: ENV_PRESET_OPTIONS,
434
1831
  required: false
@@ -436,7 +1833,7 @@ async function promptEnv(config2) {
436
1833
  );
437
1834
  }
438
1835
  const split = await withCancelHandling(
439
- async () => select4({
1836
+ async () => select5({
440
1837
  message: "Split or Joined env files?",
441
1838
  options: ENV_SPLIT_OPTIONS
442
1839
  })
@@ -460,7 +1857,7 @@ async function promptEnv(config2) {
460
1857
  async function installEnv(config2) {
461
1858
  const envOptions = config2.get("env").options;
462
1859
  const { variant, validator, location, presets, split } = envOptions;
463
- await installPackages([variant, validator], true);
1860
+ await installPackages([variant, validator], false);
464
1861
  await fs5.ensureDir(location);
465
1862
  const presetImport = presets && presets.length > 0 ? `// Presets: ${presets.join(", ")}
466
1863
  ` : "";
@@ -470,7 +1867,7 @@ import { ${validator} } from "${validator}";
470
1867
  ${presetImport}`;
471
1868
  if (split === "split") {
472
1869
  await fs5.outputFile(
473
- path2.join(location, "env/server.ts"),
1870
+ path3.join(location, "env/server.ts"),
474
1871
  `${content}
475
1872
  // Server env definition
476
1873
  export const env = createEnv({
@@ -481,7 +1878,7 @@ export const env = createEnv({
481
1878
  });`
482
1879
  );
483
1880
  await fs5.outputFile(
484
- path2.join(location, "env/client.ts"),
1881
+ path3.join(location, "env/client.ts"),
485
1882
  `${content}
486
1883
  // Client env definition
487
1884
  export const env = createEnv({
@@ -495,7 +1892,7 @@ export const env = createEnv({
495
1892
  );
496
1893
  } else {
497
1894
  await fs5.outputFile(
498
- path2.join(location, "env.ts"),
1895
+ path3.join(location, "env.ts"),
499
1896
  `${content}
500
1897
  // Joined env definition
501
1898
  export const env = createEnv({
@@ -513,7 +1910,7 @@ export const env = createEnv({
513
1910
  }
514
1911
  }
515
1912
  var init_env = __esm({
516
- "src/services/env.ts"() {
1913
+ "src/features/env.ts"() {
517
1914
  "use strict";
518
1915
  init_esm_shims();
519
1916
  init_pm();
@@ -522,14 +1919,14 @@ var init_env = __esm({
522
1919
  }
523
1920
  });
524
1921
 
525
- // src/services/test.ts
526
- import { select as select5, log as log6 } from "@clack/prompts";
1922
+ // src/features/test.ts
1923
+ import { select as select6, log as log6 } from "@clack/prompts";
527
1924
  import fs6 from "fs-extra";
528
- import pc6 from "picocolors";
1925
+ import pc7 from "picocolors";
529
1926
  async function promptTest(config2) {
530
- log6.message(pc6.bgRed(pc6.black(" Test Runner Configuration ")));
1927
+ log6.message(pc7.bgRed(pc7.white(" Test Runner Configuration ")));
531
1928
  const runner = await withCancelHandling(
532
- async () => select5({
1929
+ async () => select6({
533
1930
  message: "Select a test runner:",
534
1931
  options: TEST_RUNNER_OPTIONS
535
1932
  })
@@ -571,7 +1968,7 @@ module.exports = {
571
1968
  }
572
1969
  }
573
1970
  var init_test = __esm({
574
- "src/services/test.ts"() {
1971
+ "src/features/test.ts"() {
575
1972
  "use strict";
576
1973
  init_esm_shims();
577
1974
  init_pm();
@@ -580,15 +1977,15 @@ var init_test = __esm({
580
1977
  }
581
1978
  });
582
1979
 
583
- // src/services/editor-config.ts
584
- import { select as select6, log as log7 } from "@clack/prompts";
1980
+ // src/features/editor-config.ts
1981
+ import { select as select7, log as log7 } from "@clack/prompts";
585
1982
  import fs7 from "fs-extra";
586
- import pc7 from "picocolors";
1983
+ import pc8 from "picocolors";
587
1984
  async function promptEditorConfig(config2) {
588
- log7.message(pc7.bgWhite(pc7.black(" EditorConfig Configuration ")));
1985
+ log7.message(pc8.bgWhite(pc8.black(" EditorConfig Configuration ")));
589
1986
  const currentPreset = config2.get("editorConfig").options.preset;
590
1987
  const preset = await withCancelHandling(
591
- async () => select6({
1988
+ async () => select7({
592
1989
  message: "Select EditorConfig preset:",
593
1990
  options: EDITOR_CONFIG_OPTIONS,
594
1991
  initialValue: currentPreset
@@ -609,7 +2006,7 @@ async function installEditorConfig(config2) {
609
2006
  await fs7.outputFile(".editorconfig", content);
610
2007
  }
611
2008
  var init_editor_config = __esm({
612
- "src/services/editor-config.ts"() {
2009
+ "src/features/editor-config.ts"() {
613
2010
  "use strict";
614
2011
  init_esm_shims();
615
2012
  init_options();
@@ -617,13 +2014,13 @@ var init_editor_config = __esm({
617
2014
  }
618
2015
  });
619
2016
 
620
- // src/services/license.ts
621
- import { text as text3, select as select7, log as log8 } from "@clack/prompts";
2017
+ // src/features/license.ts
2018
+ import { text as text3, select as select8, log as log8 } from "@clack/prompts";
622
2019
  import fs8 from "fs-extra";
623
- import path3 from "path";
624
- import pc8 from "picocolors";
2020
+ import path4 from "path";
2021
+ import pc9 from "picocolors";
625
2022
  async function promptLicense(config2) {
626
- log8.message(pc8.bgGreen(pc8.black(" License Configuration ")));
2023
+ log8.message(pc9.bgGreen(pc9.black(" License Configuration ")));
627
2024
  const licenseOptions = config2.get("license").options;
628
2025
  licenseOptions.name = await withCancelHandling(
629
2026
  async () => text3({
@@ -647,7 +2044,7 @@ async function promptLicense(config2) {
647
2044
  })
648
2045
  );
649
2046
  licenseOptions.type = await withCancelHandling(
650
- async () => select7({
2047
+ async () => select8({
651
2048
  message: "Select License Type:",
652
2049
  options: LICENSE_TYPE_OPTIONS
653
2050
  })
@@ -658,7 +2055,7 @@ async function installLicense(config2) {
658
2055
  const { type, name, email, website } = licenseOptions;
659
2056
  if (type !== "UNLICENSED") {
660
2057
  const year = (/* @__PURE__ */ new Date()).getFullYear().toString();
661
- const templatePath = path3.join(__dirname, "licenses", `${type}.txt`);
2058
+ const templatePath = path4.join(__dirname, "licenses", `${type}.txt`);
662
2059
  if (await fs8.pathExists(templatePath)) {
663
2060
  let licenseContent = await fs8.readFile(templatePath, "utf-8");
664
2061
  licenseContent = licenseContent.replace(/{YEAR}/g, year);
@@ -682,7 +2079,7 @@ Licensed under ${type}`;
682
2079
  }
683
2080
  }
684
2081
  var init_license = __esm({
685
- "src/services/license.ts"() {
2082
+ "src/features/license.ts"() {
686
2083
  "use strict";
687
2084
  init_esm_shims();
688
2085
  init_options();
@@ -690,11 +2087,11 @@ var init_license = __esm({
690
2087
  }
691
2088
  });
692
2089
 
693
- // src/config/config.ts
694
- import pc9 from "picocolors";
2090
+ // src/core/config.ts
2091
+ import pc10 from "picocolors";
695
2092
  var Config, config;
696
2093
  var init_config = __esm({
697
- "src/config/config.ts"() {
2094
+ "src/core/config.ts"() {
698
2095
  "use strict";
699
2096
  init_esm_shims();
700
2097
  Config = class {
@@ -725,7 +2122,7 @@ var init_config = __esm({
725
2122
  installPresets: false,
726
2123
  presets: [],
727
2124
  split: "split",
728
- location: "src/env"
2125
+ location: "src/lib"
729
2126
  }
730
2127
  },
731
2128
  test: {
@@ -750,47 +2147,47 @@ var init_config = __esm({
750
2147
  }
751
2148
  get summary() {
752
2149
  const lines = [];
753
- lines.push(pc9.bold("The following actions will be performed:"));
2150
+ lines.push(pc10.bold("The following actions will be performed:"));
754
2151
  lines.push("");
755
2152
  if (this.data.husky.selected) {
756
- lines.push(pc9.magenta(`\u2022 Install and configure Husky`));
2153
+ lines.push(pc10.magenta(`\u2022 Install and configure Husky`));
757
2154
  if (this.data.husky.options.hookType === "custom") {
758
- lines.push(pc9.dim(` - Custom hook script`));
2155
+ lines.push(pc10.dim(` - Custom hook script`));
759
2156
  }
760
2157
  }
761
2158
  if (this.data.formatter.selected) {
762
2159
  const choice = this.data.formatter.options.choice;
763
- lines.push(pc9.blue(`\u2022 Install and configure ${choice || "Formatter"}`));
2160
+ lines.push(pc10.blue(`\u2022 Install and configure ${choice || "Formatter"}`));
764
2161
  }
765
2162
  if (this.data.linter.selected) {
766
2163
  const choice = this.data.linter.options.choice;
767
- lines.push(pc9.yellow(`\u2022 Install and configure ${choice || "Linter"}`));
2164
+ lines.push(pc10.yellow(`\u2022 Install and configure ${choice || "Linter"}`));
768
2165
  }
769
2166
  if (this.data.lintStaged.selected) {
770
- lines.push(pc9.green(`\u2022 Install and configure Lint-staged`));
2167
+ lines.push(pc10.green(`\u2022 Install and configure Lint-staged`));
771
2168
  const lintExts = this.data.lintStaged.options.lintExtensions.join(", ");
772
2169
  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}`));
2170
+ if (lintExts) lines.push(pc10.dim(` - Lint: ${lintExts}`));
2171
+ if (formatExts) lines.push(pc10.dim(` - Format: ${formatExts}`));
775
2172
  }
776
2173
  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}`));
2174
+ lines.push(pc10.cyan(`\u2022 Install and configure Env Validation`));
2175
+ lines.push(pc10.dim(` - Variant: ${this.data.env.options.variant}`));
2176
+ lines.push(pc10.dim(` - Validator: ${this.data.env.options.validator}`));
780
2177
  }
781
2178
  if (this.data.test.selected) {
782
2179
  const runner = this.data.test.options.runner;
783
- lines.push(pc9.red(`\u2022 Install and configure Test Runner (${runner})`));
2180
+ lines.push(pc10.red(`\u2022 Install and configure Test Runner (${runner})`));
784
2181
  }
785
2182
  if (this.data.editorConfig.selected) {
786
2183
  const preset = this.data.editorConfig.options.preset;
787
- lines.push(pc9.white(`\u2022 Create .editorconfig (${preset})`));
2184
+ lines.push(pc10.white(`\u2022 Create .editorconfig (${preset})`));
788
2185
  }
789
2186
  if (this.data.license.selected) {
790
2187
  const type = this.data.license.options.type;
791
2188
  const name = this.data.license.options.name;
792
- lines.push(pc9.green(`\u2022 Create LICENSE (${type})`));
793
- lines.push(pc9.dim(` - Holder: ${name}`));
2189
+ lines.push(pc10.green(`\u2022 Create LICENSE (${type})`));
2190
+ lines.push(pc10.dim(` - Holder: ${name}`));
794
2191
  }
795
2192
  return lines.join("\n");
796
2193
  }
@@ -864,16 +2261,16 @@ var init_execution = __esm({
864
2261
 
865
2262
  // src/utils/logger.ts
866
2263
  import fs9 from "fs-extra";
867
- import path4 from "path";
2264
+ import path5 from "path";
868
2265
  async function logError(error) {
869
2266
  try {
870
2267
  await fs9.ensureDir(ERRORS_DIR);
871
- const gitignorePath = path4.join(LOG_DIR, ".gitignore");
2268
+ const gitignorePath = path5.join(LOG_DIR, ".gitignore");
872
2269
  if (!await fs9.pathExists(gitignorePath)) {
873
2270
  await fs9.outputFile(gitignorePath, "*\n");
874
2271
  }
875
2272
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
876
- const logFile = path4.join(ERRORS_DIR, `log-${timestamp}.txt`);
2273
+ const logFile = path5.join(ERRORS_DIR, `log-${timestamp}.txt`);
877
2274
  const errorMessage = error instanceof Error ? error.stack || error.message : String(error);
878
2275
  const logContent = `Timestamp: ${(/* @__PURE__ */ new Date()).toISOString()}
879
2276
 
@@ -893,7 +2290,7 @@ var init_logger = __esm({
893
2290
  "use strict";
894
2291
  init_esm_shims();
895
2292
  LOG_DIR = ".mayrlabs/setup-project";
896
- ERRORS_DIR = path4.join(LOG_DIR, "errors");
2293
+ ERRORS_DIR = path5.join(LOG_DIR, "errors");
897
2294
  }
898
2295
  });
899
2296
 
@@ -927,11 +2324,11 @@ var init_git = __esm({
927
2324
  });
928
2325
 
929
2326
  // src/steps/git-check.ts
930
- import { confirm as confirm3, spinner as spinner2, text as text4 } from "@clack/prompts";
2327
+ import { confirm as confirm6, spinner as spinner2, text as text4 } from "@clack/prompts";
931
2328
  async function gitCheck() {
932
2329
  if (await isGitRepository()) {
933
2330
  if (await isGitDirty()) {
934
- const shouldCommit = await confirm3({
2331
+ const shouldCommit = await confirm6({
935
2332
  message: "Your working directory is dirty. Would you like to commit changes before proceeding?"
936
2333
  });
937
2334
  if (shouldCommit) {
@@ -966,7 +2363,7 @@ var init_package = __esm({
966
2363
  "package.json"() {
967
2364
  package_default = {
968
2365
  name: "@mayrlabs/setup-project",
969
- version: "0.1.6",
2366
+ version: "0.1.8",
970
2367
  description: "Interactive CLI to setup project tools",
971
2368
  private: false,
972
2369
  publishConfig: {
@@ -1008,7 +2405,8 @@ var init_package = __esm({
1008
2405
  main: "dist/index.js",
1009
2406
  scripts: {
1010
2407
  build: "tsup",
1011
- demo: "tsx src/index.ts",
2408
+ demo: "tsx src/cli/index.ts",
2409
+ test: "vitest",
1012
2410
  prepublishOnly: "npm run build"
1013
2411
  },
1014
2412
  dependencies: {
@@ -1024,21 +2422,23 @@ var init_package = __esm({
1024
2422
  "@types/figlet": "^1.7.0",
1025
2423
  "@types/fs-extra": "^11.0.4",
1026
2424
  "@types/node": "^20.11.16",
2425
+ "@vitest/coverage-v8": "^4.0.18",
1027
2426
  tsup: "^8.5.1",
1028
2427
  tsx: "^4.21.0",
1029
- typescript: "^5.3.3"
2428
+ typescript: "^5.3.3",
2429
+ vitest: "^4.0.18"
1030
2430
  }
1031
2431
  };
1032
2432
  }
1033
2433
  });
1034
2434
 
1035
2435
  // src/utils/display.ts
1036
- import pc10 from "picocolors";
2436
+ import pc11 from "picocolors";
1037
2437
  import figlet from "figlet";
1038
2438
  function introScreen() {
1039
2439
  console.log();
1040
2440
  console.log(
1041
- pc10.cyan(
2441
+ pc11.cyan(
1042
2442
  figlet.textSync("MayR\nLabs", {
1043
2443
  font: "Graceful",
1044
2444
  horizontalLayout: "default",
@@ -1048,39 +2448,41 @@ function introScreen() {
1048
2448
  })
1049
2449
  )
1050
2450
  );
1051
- console.log(pc10.cyan(`@mayrlabs/setup-project v${package_default.version}`));
2451
+ console.log(pc11.cyan(`${package_default.name} - v${package_default.version}`));
1052
2452
  console.log();
1053
2453
  }
1054
2454
  function showAbout() {
1055
2455
  introScreen();
1056
- console.log(pc10.bold("About:"));
2456
+ console.log(pc11.bold("About:"));
1057
2457
  console.log(
1058
2458
  " Interactive CLI to setup project tools like Husky, Prettier, ESLint, etc."
1059
2459
  );
1060
2460
  console.log("");
1061
- console.log(pc10.bold("How to use:"));
2461
+ console.log(pc11.bold("How to use:"));
1062
2462
  console.log(
1063
2463
  " Run 'npx @mayrlabs/setup-project' and follow the interactive prompts."
1064
2464
  );
1065
2465
  console.log("");
1066
2466
  }
1067
2467
  function showVisit() {
1068
- console.log(pc10.bold("Project Homepage:"));
1069
- console.log(pc10.underline(pc10.cyan(package_default.homepage)));
2468
+ console.log(pc11.bold("Project Homepage:"));
2469
+ console.log(pc11.underline(pc11.cyan(package_default.homepage)));
1070
2470
  console.log("");
1071
2471
  }
1072
2472
  function showManual() {
1073
2473
  introScreen();
1074
- console.log(pc10.bold("Usage:"));
2474
+ console.log(pc11.bold("Usage:"));
1075
2475
  console.log(" npx @mayrlabs/setup-project [command] [options]");
1076
2476
  console.log("");
1077
- console.log(pc10.bold("Commands:"));
2477
+ console.log(pc11.bold("Commands:"));
1078
2478
  console.log(" about Show project details");
1079
2479
  console.log(" version Show version information");
1080
2480
  console.log(" visit Visit project homepage");
1081
2481
  console.log(" help Show this help message");
2482
+ console.log(" configure [tool] Configure a specific tool");
2483
+ console.log(" plugin [tool] Manage plugins for tools");
1082
2484
  console.log("");
1083
- console.log(pc10.bold("Options:"));
2485
+ console.log(pc11.bold("Options:"));
1084
2486
  console.log(" -a, --about Show project details");
1085
2487
  console.log(" -v, --version Show version information");
1086
2488
  console.log(" -V, --visit Visit project homepage");
@@ -1095,12 +2497,134 @@ var init_display = __esm({
1095
2497
  }
1096
2498
  });
1097
2499
 
1098
- // src/index.ts
1099
- import { outro, multiselect as multiselect3, note, confirm as confirm4, intro } from "@clack/prompts";
1100
- import pc11 from "picocolors";
2500
+ // src/cli/commands/configure.ts
2501
+ import { intro, outro as outro2, select as select9 } from "@clack/prompts";
2502
+ import pc12 from "picocolors";
2503
+ async function configure(toolName) {
2504
+ introScreen();
2505
+ intro(pc12.inverse(pc12.bold(pc12.blue(" Configuration Mode "))));
2506
+ await gitCheck();
2507
+ let selectedTool;
2508
+ if (toolName) {
2509
+ const tool = TOOL_OPTIONS.find((t) => t.value === toolName);
2510
+ if (tool) {
2511
+ selectedTool = tool.value;
2512
+ } else {
2513
+ console.log(
2514
+ pc12.yellow(`Tool '${toolName}' not found or not configurable.`)
2515
+ );
2516
+ }
2517
+ }
2518
+ if (!selectedTool) {
2519
+ const selection = await withCancelHandling(
2520
+ async () => select9({
2521
+ message: "Select a tool to configure:",
2522
+ options: TOOL_OPTIONS
2523
+ })
2524
+ );
2525
+ selectedTool = selection;
2526
+ }
2527
+ config.enableTool(selectedTool);
2528
+ try {
2529
+ switch (selectedTool) {
2530
+ case "husky":
2531
+ await promptHusky(config);
2532
+ await installHusky(config);
2533
+ break;
2534
+ case "formatter":
2535
+ await promptFormatter(config);
2536
+ await installFormatter(config);
2537
+ break;
2538
+ case "linter":
2539
+ await promptLinter(config);
2540
+ await installLinter(config);
2541
+ break;
2542
+ case "lintStaged":
2543
+ await promptLintStaged(config);
2544
+ await installLintStaged(config);
2545
+ break;
2546
+ case "env":
2547
+ await promptEnv(config);
2548
+ await installEnv(config);
2549
+ break;
2550
+ case "test":
2551
+ await promptTest(config);
2552
+ await installTest(config);
2553
+ break;
2554
+ case "editorConfig":
2555
+ await promptEditorConfig(config);
2556
+ await installEditorConfig(config);
2557
+ break;
2558
+ case "license":
2559
+ await promptLicense(config);
2560
+ await installLicense(config);
2561
+ break;
2562
+ }
2563
+ outro2(pc12.green(`${selectedTool} configured successfully!`));
2564
+ } catch (error) {
2565
+ outro2(pc12.red(`Failed to configure ${selectedTool}.`));
2566
+ console.error(error);
2567
+ process.exit(1);
2568
+ }
2569
+ }
2570
+ var init_configure = __esm({
2571
+ "src/cli/commands/configure.ts"() {
2572
+ "use strict";
2573
+ init_esm_shims();
2574
+ init_config();
2575
+ init_options();
2576
+ init_husky();
2577
+ init_formatter();
2578
+ init_linter();
2579
+ init_lint_staged();
2580
+ init_env();
2581
+ init_test();
2582
+ init_editor_config();
2583
+ init_license();
2584
+ init_handle_cancel();
2585
+ init_display();
2586
+ init_git_check();
2587
+ }
2588
+ });
2589
+
2590
+ // src/cli/commands/plugin.ts
2591
+ import { intro as intro2, outro as outro3, select as select10 } from "@clack/prompts";
2592
+ import pc13 from "picocolors";
2593
+ async function plugin(toolName) {
2594
+ introScreen();
2595
+ intro2(pc13.inverse(pc13.bold(pc13.magenta(" Plugin Manager "))));
2596
+ await gitCheck();
2597
+ if (!toolName) {
2598
+ toolName = await withCancelHandling(
2599
+ async () => select10({
2600
+ message: "Select a tool to add plugins to:",
2601
+ options: [
2602
+ { value: "eslint", label: "ESLint" },
2603
+ { value: "prettier", label: "Prettier" }
2604
+ ]
2605
+ })
2606
+ );
2607
+ }
2608
+ await installPlugins(toolName);
2609
+ outro3(pc13.green("Plugins installed successfully!"));
2610
+ }
2611
+ var init_plugin = __esm({
2612
+ "src/cli/commands/plugin.ts"() {
2613
+ "use strict";
2614
+ init_esm_shims();
2615
+ init_handle_cancel();
2616
+ init_display();
2617
+ init_git_check();
2618
+ init_install_plugin();
2619
+ }
2620
+ });
2621
+
2622
+ // src/cli/index.ts
2623
+ import { outro as outro4, multiselect as multiselect4, note, confirm as confirm7, intro as intro3 } from "@clack/prompts";
2624
+ import pc14 from "picocolors";
1101
2625
  import { program } from "commander";
1102
2626
  var require_index = __commonJS({
1103
- "src/index.ts"() {
2627
+ "src/cli/index.ts"() {
1104
2628
  init_esm_shims();
1105
2629
  init_husky();
1106
2630
  init_formatter();
@@ -1117,15 +2641,17 @@ var require_index = __commonJS({
1117
2641
  init_logger();
1118
2642
  init_git_check();
1119
2643
  init_display();
2644
+ init_configure();
2645
+ init_plugin();
1120
2646
  async function main() {
1121
2647
  try {
1122
2648
  introScreen();
1123
- intro(
1124
- pc11.inverse(pc11.bold(pc11.cyan(" Welcome to the Project Setup Wizard ")))
2649
+ intro3(
2650
+ pc14.inverse(pc14.bold(pc14.cyan(" Welcome to the Project Setup Wizard ")))
1125
2651
  );
1126
2652
  await gitCheck();
1127
2653
  const tools = await withCancelHandling(
1128
- async () => multiselect3({
2654
+ async () => multiselect4({
1129
2655
  message: "Select tools to configure:",
1130
2656
  options: TOOL_OPTIONS,
1131
2657
  required: false
@@ -1142,19 +2668,19 @@ var require_index = __commonJS({
1142
2668
  if (config.get("license").selected) await promptLicense(config);
1143
2669
  note(config.summary, "Configuration Summary");
1144
2670
  const proceed = await withCancelHandling(
1145
- async () => confirm4({
2671
+ async () => confirm7({
1146
2672
  message: "Do you want to proceed with the installation?"
1147
2673
  })
1148
2674
  );
1149
2675
  if (!proceed) {
1150
- outro(pc11.yellow("Installation cancelled."));
2676
+ outro4(pc14.yellow("Installation cancelled."));
1151
2677
  process.exit(0);
1152
2678
  }
1153
2679
  await execution(config);
1154
- outro(pc11.green("Setup complete!"));
2680
+ outro4(pc14.green("Setup complete!"));
1155
2681
  } catch (error) {
1156
2682
  const logPath = await logError(error);
1157
- outro(pc11.red(`
2683
+ outro4(pc14.red(`
1158
2684
  Something went wrong!
1159
2685
  Error log saved to: ${logPath}`));
1160
2686
  process.exit(1);
@@ -1178,6 +2704,14 @@ Error log saved to: ${logPath}`));
1178
2704
  showManual();
1179
2705
  process.exit(0);
1180
2706
  });
2707
+ program.command("configure [tool]").description("Configure a specific tool").action(async (tool) => {
2708
+ await configure(tool);
2709
+ process.exit(0);
2710
+ });
2711
+ program.command("plugin [tool]").description("Manage plugins for tools").action(async (tool) => {
2712
+ await plugin(tool);
2713
+ process.exit(0);
2714
+ });
1181
2715
  program.action(async (options) => {
1182
2716
  if (options.about) {
1183
2717
  showAbout();