@solvro/config 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -1,13 +1,12 @@
1
1
  // src/cli/index.ts
2
- import * as p8 from "@clack/prompts";
2
+ import * as p11 from "@clack/prompts";
3
3
  import { Command } from "commander";
4
- import { getUserAgent } from "package-manager-detector/detect";
5
- import c2 from "picocolors";
4
+ import c5 from "picocolors";
6
5
 
7
6
  // package.json
8
7
  var package_default = {
9
8
  name: "@solvro/config",
10
- version: "2.2.0",
9
+ version: "2.2.1",
11
10
  description: "Solvro's engineering style guide",
12
11
  keywords: [
13
12
  "eslint",
@@ -73,6 +72,7 @@ var package_default = {
73
72
  "@eslint-community/eslint-plugin-eslint-comments": "^4.7.1",
74
73
  "@eslint/config-helpers": "^0.4.2",
75
74
  "@eslint/js": "^9.37.0",
75
+ "@solvro/utils": "^1.5.0",
76
76
  "@tanstack/eslint-plugin-query": "^5.91.4",
77
77
  "@trivago/prettier-plugin-sort-imports": "^6.0.2",
78
78
  "@typescript-eslint/eslint-plugin": "^8.46.0",
@@ -144,10 +144,40 @@ var package_default = {
144
144
  }
145
145
  };
146
146
 
147
- // src/constants/index.ts
147
+ // src/constants/github.ts
148
148
  var REPO_URL = "https://github.com/Solvro/lib-web-solvro-config";
149
149
  var BUG_TRACKER_URL = `${REPO_URL}/issues/new`;
150
150
 
151
+ // src/constants/package-managers.ts
152
+ var PACKAGE_MANAGER_CONFIGS = {
153
+ npm: {
154
+ name: "npm",
155
+ lockfile: "package-lock.json",
156
+ installPackage: "npm install",
157
+ installDependencies: "npm install",
158
+ cleanInstall: "npm ci",
159
+ downloadExecute: "npx",
160
+ localExecute: "npx",
161
+ runScript: "npm run",
162
+ create: "npm create"
163
+ },
164
+ pnpm: {
165
+ name: "pnpm",
166
+ lockfile: "pnpm-lock.yaml",
167
+ installPackage: "pnpm add",
168
+ installDependencies: "pnpm install",
169
+ cleanInstall: "pnpm install --frozen-lockfile",
170
+ downloadExecute: "pnpm dlx",
171
+ localExecute: "pnpm exec",
172
+ runScript: "pnpm run",
173
+ create: "pnpm create"
174
+ }
175
+ };
176
+ var SUPPORTED_PACKAGE_MANAGERS = Object.keys(PACKAGE_MANAGER_CONFIGS);
177
+
178
+ // src/utils/check-is-non-interactive.ts
179
+ var checkIsNonInteractive = () => process.argv.length > 2;
180
+
151
181
  // src/utils/confirm-project-type.ts
152
182
  import * as p2 from "@clack/prompts";
153
183
 
@@ -194,12 +224,13 @@ function isGitClean() {
194
224
  }
195
225
 
196
226
  // src/utils/package-json.ts
197
- import * as p4 from "@clack/prompts";
227
+ import * as p7 from "@clack/prompts";
198
228
  import { getPackageInfo, isPackageListed, loadPackageJSON } from "local-pkg";
199
229
  import assert from "assert";
200
- import { writeFile } from "fs/promises";
230
+ import { stat, writeFile } from "fs/promises";
201
231
  import path2 from "path";
202
- import c from "picocolors";
232
+ import { getUserAgent } from "package-manager-detector/detect";
233
+ import c4 from "picocolors";
203
234
  import semver from "semver";
204
235
 
205
236
  // src/utils/git-root.ts
@@ -236,6 +267,9 @@ var $$ = (async (...arguments_) => {
236
267
  return cachedExeca(...arguments_);
237
268
  });
238
269
 
270
+ // src/utils/is-supported-package-manager.ts
271
+ var isSupportedPackageManager = (userAgent) => userAgent != null && SUPPORTED_PACKAGE_MANAGERS.includes(userAgent);
272
+
239
273
  // src/utils/run-with-spinner.ts
240
274
  import * as p3 from "@clack/prompts";
241
275
 
@@ -267,14 +301,128 @@ var runWithSpinner = async (options2) => {
267
301
  });
268
302
  };
269
303
 
304
+ // src/utils/warn-inconsistent-user-agent.ts
305
+ import * as p4 from "@clack/prompts";
306
+ import c from "picocolors";
307
+ var hintInstallWithDetected = (manager) => `
308
+ ${c.white(`Upewnij si\u0119, \u017Ce u\u017Cywasz w\u0142a\u015Bciwej komendy. Spr\xF3buj jeszcze raz za pomoc\u0105 ${c.yellow(manager.name)}-a:`)}
309
+
310
+ ${c.cyan(`${manager.downloadExecute} @solvro/config@latest`)}`;
311
+ var warnUnsupported = (manager) => `
312
+ ${c.white("@solvro/config obecnie dzia\u0142a tylko z nast\u0119puj\u0105cymi mened\u017Cerami pakiet\xF3w:")}
313
+
314
+ ${SUPPORTED_PACKAGE_MANAGERS.map((supportedManager) => c.white(`- ${c.cyan(supportedManager)}`)).join("\n")}
315
+
316
+ Niestety, ${c.yellow(manager)} nie jest wspierany.`;
317
+ var warnInconsistentUserAgent = ({
318
+ userAgent,
319
+ detectedPackageManager
320
+ }) => {
321
+ const warningMessage = `${c.red(c.bold(`\u26A0\uFE0F OSTRZE\u017BENIE: niesp\xF3jny mened\u017Cer pakiet\xF3w \u26A0\uFE0F`))}
322
+
323
+ Pr\xF3bujesz uruchomi\u0107 ten skrypt ${c.yellow(userAgent.name)}-em, ale w tym projekcie wykryto mened\u017Cer pakiet\xF3w ${c.yellow(detectedPackageManager)}.
324
+ ${isSupportedPackageManager(detectedPackageManager) ? hintInstallWithDetected(PACKAGE_MANAGER_CONFIGS[detectedPackageManager]) : warnUnsupported(detectedPackageManager)}`;
325
+ if (checkIsNonInteractive()) {
326
+ console.error(warningMessage);
327
+ } else {
328
+ p4.cancel(warningMessage);
329
+ }
330
+ };
331
+
332
+ // src/utils/warn-missing-lockfile.ts
333
+ import * as p5 from "@clack/prompts";
334
+ import c2 from "picocolors";
335
+ var warnMissingLockfile = ({
336
+ manager
337
+ }) => {
338
+ const warningMessage = `${c2.red(c2.bold(`\u26A0\uFE0F OSTRZE\u017BENIE: brak pliku blokady \u26A0\uFE0F`))}
339
+
340
+ Pr\xF3bujesz uruchomi\u0107 ten skrypt ${c2.yellow(manager.name)}-em, ale nie wykryto pliku ${c2.yellow(manager.lockfile)}.
341
+
342
+ ${c2.white(`Sprawd\u017A, czy ten projekt na pewno korzysta z mened\u017Cera pakiet\xF3w ${c2.yellow(manager.name)}.`)}
343
+ ${c2.white("Je\u015Bli to si\u0119 zgadza, zainstaluj najpierw zale\u017Cno\u015Bci projektu i spr\xF3buj ponownie:")}
344
+
345
+ ${c2.cyan(manager.installDependencies)}
346
+ ${c2.cyan(`${manager.downloadExecute} @solvro/config@latest`)}`;
347
+ if (checkIsNonInteractive()) {
348
+ console.error(warningMessage);
349
+ } else {
350
+ p5.cancel(warningMessage);
351
+ }
352
+ };
353
+
354
+ // src/utils/warn-unsupported-package-manager.ts
355
+ import * as p6 from "@clack/prompts";
356
+ import c3 from "picocolors";
357
+ var warnUnsupportedPackageManager = ({
358
+ userAgent
359
+ }) => {
360
+ const packageManager = userAgent ?? "<nieznany>";
361
+ const warningMessage = `${c3.red(c3.bold(`\u26A0\uFE0F OSTRZE\u017BENIE: ${packageManager} nie jest obs\u0142ugiwany \u26A0\uFE0F`))}
362
+
363
+ Pr\xF3bujesz uruchomi\u0107 ten skrypt ${c3.yellow(packageManager)}-em, ale @solvro/config obecnie dzia\u0142a tylko z nast\u0119puj\u0105cymi mened\u017Cerami pakiet\xF3w:
364
+
365
+ ${SUPPORTED_PACKAGE_MANAGERS.map((manager) => c3.white(`- ${c3.cyan(manager)}`)).join("\n")}
366
+
367
+ ${c3.white(`Chcesz, aby dodano wsparcie dla ${c3.yellow(packageManager)}-a? Daj nam zna\u0107!`)}
368
+ ${c3.white(c3.underline(BUG_TRACKER_URL))}
369
+
370
+ ${c3.white(`W mi\u0119dzyczasie u\u017Cyj innego mened\u017Cera:`)}
371
+
372
+ ${Object.values(PACKAGE_MANAGER_CONFIGS).map((config) => c3.cyan(`${config.downloadExecute} @solvro/config`)).join(c3.white("\nlub\n"))}`;
373
+ if (checkIsNonInteractive()) {
374
+ console.error(warningMessage);
375
+ } else {
376
+ p6.cancel(warningMessage);
377
+ }
378
+ };
379
+
270
380
  // src/utils/package-json.ts
271
381
  var PackageJson = class {
272
382
  json = null;
383
+ _manager = null;
384
+ /** Checks if the process is run from a supported package manager */
385
+ verifyPackageManager() {
386
+ const userAgent = getUserAgent();
387
+ if (!isSupportedPackageManager(userAgent)) {
388
+ warnUnsupportedPackageManager({ userAgent });
389
+ process.exit(1);
390
+ }
391
+ return userAgent;
392
+ }
393
+ /** Checks if the user agent is consistent with the project's package manager */
394
+ async validateUserAgentConsistency() {
395
+ if (this.json?.packageManager != null) {
396
+ const [detectedPackageManager] = this.json.packageManager.split("@");
397
+ if (detectedPackageManager !== this.manager.name) {
398
+ warnInconsistentUserAgent({
399
+ userAgent: this.manager,
400
+ detectedPackageManager
401
+ });
402
+ process.exit(1);
403
+ }
404
+ }
405
+ const lockfilePath = path2.join(projectRoot(), this.manager.lockfile);
406
+ try {
407
+ await stat(lockfilePath);
408
+ } catch {
409
+ warnMissingLockfile({ manager: this.manager });
410
+ process.exit(1);
411
+ }
412
+ }
413
+ // use a cached getter to avoid premature exits on importing a file with a toplevel construction
414
+ get manager() {
415
+ if (this._manager == null) {
416
+ const userAgent = this.verifyPackageManager();
417
+ this._manager = PACKAGE_MANAGER_CONFIGS[userAgent];
418
+ }
419
+ return this._manager;
420
+ }
273
421
  async load() {
274
422
  const json = await loadPackageJSON(projectRoot());
275
423
  if (json === null) {
276
- p4.cancel(
277
- `Nie znaleziono pliku ${c.cyan("package.json")}. Upewnij si\u0119, \u017Ce jeste\u015B w katalogu projektu.`
424
+ p7.cancel(
425
+ `Nie znaleziono pliku ${c4.cyan("package.json")}. Upewnij si\u0119, \u017Ce jeste\u015B w katalogu projektu.`
278
426
  );
279
427
  process.exit(1);
280
428
  }
@@ -316,8 +464,8 @@ var PackageJson = class {
316
464
  const isReact = await isPackageListed("react");
317
465
  const isNestJs = await isPackageListed("@nestjs/core");
318
466
  if (isReact && isAdonis) {
319
- p4.cancel(
320
- `Projekty korzystaj\u0105ce zar\xF3wno z ${c.magenta("Adonis")}a jak i ${c.cyan("React")}a nie s\u0105 wspierane.`
467
+ p7.cancel(
468
+ `Projekty korzystaj\u0105ce zar\xF3wno z ${c4.magenta("Adonis")}a jak i ${c4.cyan("React")}a nie s\u0105 wspierane.`
321
469
  );
322
470
  process.exit(1);
323
471
  }
@@ -352,13 +500,20 @@ var PackageJson = class {
352
500
  async install(package_, options2 = {}) {
353
501
  const isInstalled = await this.hasPackage(package_);
354
502
  const installVersion = options2.version ?? "latest";
503
+ const [installCommand, ...commandOptions] = this.manager.installPackage.split(" ");
504
+ if (options2.dev === true) {
505
+ commandOptions.push("-D");
506
+ }
355
507
  if (!isInstalled) {
356
508
  await runWithSpinner({
357
509
  start: `Instalowanie pakietu ${package_}`,
358
510
  stop: `${package_} zainstalowany \u{1F60D}`,
359
511
  error: `Instalacja pakietu ${package_} nie powiod\u0142a si\u0119 \u{1F976}`,
360
512
  callback: async () => {
361
- await $$`npm i ${options2.dev === true ? "-D" : ""} ${package_}@${installVersion}`;
513
+ await $$(installCommand, [
514
+ ...commandOptions,
515
+ `${package_}@${installVersion}`
516
+ ]);
362
517
  }
363
518
  });
364
519
  await this.load();
@@ -370,14 +525,46 @@ var PackageJson = class {
370
525
  stop: `${package_} zaktualizowany \u{1F60D}`,
371
526
  error: `Aktualizacja pakietu ${package_} nie powiod\u0142a si\u0119 \u{1F976}`,
372
527
  callback: async () => {
373
- await $$`npm i ${options2.dev === true ? "-D" : ""} ${package_}@${installVersion}`;
528
+ await $$(installCommand, [
529
+ ...commandOptions,
530
+ `${package_}@${installVersion}`
531
+ ]);
374
532
  }
375
533
  });
376
534
  await this.load();
377
535
  }
378
536
  }
537
+ async localExecute(...commandArguments) {
538
+ const [command, ...commandOptions] = this.manager.localExecute.split(" ");
539
+ const options2 = [...commandOptions, ...commandArguments];
540
+ await $$(command, options2);
541
+ }
379
542
  async clearInstall() {
380
- await $$`npm ci`;
543
+ const [command, ...options2] = this.manager.cleanInstall.split(" ");
544
+ await $$(command, options2);
545
+ }
546
+ /**
547
+ * Gets the pnpm major version from package.json packageManager field or user agent.
548
+ * Falls back to version "10" if neither source is available.
549
+ * Returns only the major version for CI stability.
550
+ */
551
+ async getPnpmVersion() {
552
+ await this.load();
553
+ if (this.json?.packageManager?.startsWith("pnpm@") === true) {
554
+ const version = this.json.packageManager.split("@")[1];
555
+ const majorVersion = version.split(".")[0];
556
+ if (/^\d+$/.test(majorVersion)) {
557
+ return majorVersion;
558
+ }
559
+ }
560
+ const userAgent = process.env.npm_config_user_agent;
561
+ if (userAgent != null) {
562
+ const match = /pnpm\/(\d+)(?:\.\d+)*/.exec(userAgent);
563
+ if (match?.[1] != null) {
564
+ return match[1];
565
+ }
566
+ }
567
+ return "10";
381
568
  }
382
569
  };
383
570
 
@@ -391,7 +578,7 @@ var packageJson = new PackageJson();
391
578
  var installHusky = async () => {
392
579
  if (!await packageJson.hasPackage("husky")) {
393
580
  await packageJson.install("husky", { dev: true });
394
- await $$`npx husky init`;
581
+ await packageJson.localExecute("husky", "init");
395
582
  }
396
583
  await packageJson.load();
397
584
  assert2.ok(packageJson.json !== null);
@@ -414,13 +601,14 @@ var installCommitLint = async () => {
414
601
  await packageJson2.install("@commitlint/cli", { dev: true });
415
602
  await writeFile2(
416
603
  path3.join(root, ".husky/commit-msg"),
417
- 'npx commitlint --edit "$1"\n'
604
+ `${packageJson2.manager.localExecute} commitlint --edit "$1"
605
+ `
418
606
  );
419
607
  await writeFile2(path3.join(root, ".commitlintrc.js"), commitlint());
420
608
  };
421
609
 
422
610
  // src/cli/install-eslint.ts
423
- import * as p5 from "@clack/prompts";
611
+ import * as p8 from "@clack/prompts";
424
612
  import { existsSync } from "fs";
425
613
  import * as fs from "fs/promises";
426
614
  import path4 from "path";
@@ -450,7 +638,7 @@ var installEslint = async (isNonInteractive2 = false) => {
450
638
  if (type === "react" && await packageJson3.isNextJs()) {
451
639
  const is15 = await packageJson3.doesSatisfy("next", ">=15");
452
640
  if (!is15) {
453
- p5.cancel(
641
+ p8.cancel(
454
642
  "Next.js musi by\u0107 w conajmniej wersji 15. Zaktualizuj Next.js i spr\xF3buj ponownie.\nWi\u0119cej informacji tutaj: https://nextjs.org/docs/app/building-your-application/upgrading/version-15"
455
643
  );
456
644
  process.exit(1);
@@ -466,7 +654,7 @@ var installEslint = async (isNonInteractive2 = false) => {
466
654
  "utf8"
467
655
  );
468
656
  if (eslintContent.includes("export default solvro(")) {
469
- p5.note("Eslint jest ju\u017C skonfigurowany. Pomijam.");
657
+ p8.note("Eslint jest ju\u017C skonfigurowany. Pomijam.");
470
658
  return;
471
659
  } else {
472
660
  if (isNonInteractive2) {
@@ -475,8 +663,8 @@ var installEslint = async (isNonInteractive2 = false) => {
475
663
  const isConfirmed = await polishConfirm({
476
664
  message: `Znaleziono plik konfiguracyjny Eslint. Czy chcesz go nadpisa\u0107?`
477
665
  });
478
- if (p5.isCancel(isConfirmed) || !isConfirmed) {
479
- p5.cancel("Nadpisz plik konfiguracyjny Eslint i spr\xF3buj ponownie.");
666
+ if (p8.isCancel(isConfirmed) || !isConfirmed) {
667
+ p8.cancel("Nadpisz plik konfiguracyjny Eslint i spr\xF3buj ponownie.");
480
668
  process.exit(1);
481
669
  }
482
670
  await fs.rm(path4.join(root2, eslintConfig));
@@ -492,26 +680,56 @@ var installEslint = async (isNonInteractive2 = false) => {
492
680
  export default solvro();
493
681
  `
494
682
  );
495
- p5.note("Plik konfiguracyjny Eslint zosta\u0142 utworzony.");
683
+ p8.note("Plik konfiguracyjny Eslint zosta\u0142 utworzony.");
496
684
  };
497
685
 
498
686
  // src/cli/install-ga.ts
499
- import * as p6 from "@clack/prompts";
687
+ import * as p9 from "@clack/prompts";
500
688
  import { existsSync as existsSync2 } from "fs";
501
689
  import * as fs2 from "fs/promises";
502
690
  import path5 from "path";
503
691
 
504
692
  // src/cli/templates/commit-lint-ci.ts
505
- var commitLintCi = () => `
693
+ var commitLintCi = ({
694
+ manager
695
+ }) => `
506
696
  - name: Check commit name
507
697
  if: github.event_name == 'pull_request'
508
- run: npx commitlint --from \${{ github.event.pull_request.base.sha }} --to \${{ github.event.pull_request.head.sha }} --verbose
698
+ run: ${manager.localExecute} commitlint --from \${{ github.event.pull_request.base.sha }} --to \${{ github.event.pull_request.head.sha }} --verbose
509
699
  `;
510
700
 
701
+ // src/cli/templates/pnpm-setup-ci.ts
702
+ var pnpmSetupCi = ({
703
+ pnpmVersion = "10"
704
+ } = {}) => `
705
+
706
+ - name: Setup pnpm
707
+ uses: pnpm/action-setup@v4
708
+ with:
709
+ version: ${pnpmVersion}`;
710
+
711
+ // src/cli/templates/node-setup-ci.ts
712
+ var nodeSetupCi = ({
713
+ nodeVersion,
714
+ manager,
715
+ pnpmVersion
716
+ }) => ` - name: Checkout
717
+ uses: actions/checkout@v6
718
+ with:
719
+ fetch-depth: 0
720
+
721
+ - name: Setup node
722
+ uses: actions/setup-node@v6
723
+ with:
724
+ node-version: ${nodeVersion}
725
+ cache: "${manager.name}"${manager.name === "pnpm" ? pnpmSetupCi({ pnpmVersion }) : ""}`;
726
+
511
727
  // src/cli/templates/adonis-ci.ts
512
728
  var adonisCi = ({
513
729
  nodeVersion,
514
- withCommitlint
730
+ withCommitlint,
731
+ manager,
732
+ pnpmVersion
515
733
  }) => `name: CI
516
734
 
517
735
  on:
@@ -523,48 +741,43 @@ jobs:
523
741
  lint:
524
742
  runs-on: ubuntu-latest
525
743
  steps:
526
- - name: Checkout
527
- uses: actions/checkout@v4
528
- with:
529
- fetch-depth: 0
530
-
531
- - name: Setup node
532
- uses: actions/setup-node@v4
533
- with:
534
- node-version: ${nodeVersion}
535
- cache: "npm"
744
+ ${nodeSetupCi({ nodeVersion, manager, pnpmVersion })}
536
745
 
537
746
  - name: Install dependencies
538
- run: npm ci
747
+ run: ${manager.cleanInstall}
539
748
 
540
749
  - name: Set up AdonisJS environment
541
750
  run: |
542
751
  cp .env.example .env
543
752
  node ace generate:key
544
- ${withCommitlint ? commitLintCi() : ""}
753
+ ${withCommitlint ? commitLintCi({ manager }) : ""}
545
754
  - name: Check formatting
546
- run: npm run format:check
755
+ run: ${manager.runScript} format:check
547
756
  if: always()
548
757
 
549
758
  - name: Lint code
550
- run: npm run lint
759
+ run: ${manager.runScript} lint
551
760
  if: always()
552
761
 
553
762
  - name: Check types
554
- run: npm run types:check
763
+ run: ${manager.runScript} types:check
555
764
  if: always()
556
765
 
557
766
  - name: Run tests
558
- run: npm test
767
+ run: ${manager.name} test
559
768
  if: always()
560
769
 
561
770
  - name: Build
562
- run: npm run build
771
+ run: ${manager.runScript} build
563
772
  if: always()
564
773
  `;
565
774
 
566
775
  // src/cli/templates/adonis-ci-migrations.ts
567
- var adonisMigrationsCi = () => `name: Migration check
776
+ var adonisMigrationsCi = ({
777
+ nodeVersion,
778
+ manager,
779
+ pnpmVersion
780
+ }) => `name: Migration check
568
781
 
569
782
  on:
570
783
  pull_request:
@@ -596,11 +809,10 @@ jobs:
596
809
  - 5432:5432
597
810
 
598
811
  steps:
599
- - name: Check out repository code
600
- uses: actions/checkout@v4
812
+ ${nodeSetupCi({ nodeVersion, manager, pnpmVersion })}
601
813
 
602
814
  - name: Install dependencies
603
- run: npm ci
815
+ run: ${manager.cleanInstall}
604
816
 
605
817
  - name: Set up AdonisJS environment
606
818
  run: |
@@ -628,7 +840,9 @@ updates:
628
840
  // src/cli/templates/nestjs-ci.ts
629
841
  var nestjsCi = ({
630
842
  nodeVersion,
631
- withCommitlint
843
+ withCommitlint,
844
+ manager,
845
+ pnpmVersion
632
846
  }) => `name: CI
633
847
 
634
848
  on:
@@ -640,61 +854,54 @@ jobs:
640
854
  lint:
641
855
  runs-on: ubuntu-latest
642
856
  steps:
643
- - name: Checkout
644
- uses: actions/checkout@v4
645
- with:
646
- fetch-depth: 0
647
-
648
- - name: Setup node
649
- uses: actions/setup-node@v4
650
- with:
651
- node-version: ${nodeVersion}
652
- cache: "npm"
857
+ ${nodeSetupCi({ nodeVersion, manager, pnpmVersion })}
653
858
 
654
859
  - name: Install dependencies
655
- run: npm ci
656
- ${withCommitlint ? commitLintCi() : ""}
860
+ run: ${manager.cleanInstall}
861
+ ${withCommitlint ? commitLintCi({ manager }) : ""}
657
862
  - name: Check formatting
658
- run: npm run format:check
863
+ run: ${manager.runScript} format:check
659
864
  if: always()
660
865
 
661
866
  - name: Lint code
662
- run: npm run lint
867
+ run: ${manager.runScript} lint
663
868
  if: always()
664
869
 
665
870
  - name: Check types
666
- run: npm run types:check
871
+ run: ${manager.runScript} types:check
667
872
  if: always()
668
873
 
669
874
  - name: Run tests
670
- run: npm test
875
+ run: ${manager.name} test
671
876
  if: always()
672
877
 
673
878
  - name: Run e2e tests
674
- run: npm run test:e2e
879
+ run: ${manager.runScript} test:e2e
675
880
  if: always()
676
881
 
677
882
  - name: Build
678
- run: npm run build
883
+ run: ${manager.runScript} build
679
884
  if: always()
680
885
  `;
681
886
 
682
887
  // src/cli/templates/nextjs-ci.ts
683
- var nextJsCi = () => `
888
+ var nextJsCi = ({ manager }) => `
684
889
  - name: Setup build cache
685
- uses: actions/cache@v4
890
+ uses: actions/cache@v5
686
891
  with:
687
892
  path: \${{ github.workspace }}/.next/cache
688
- key: \${{ runner.os }}-nextjs-\${{ hashFiles('**/package-lock.json') }}-\${{ hashFiles('**/*.ts', '**/*.tsx') }}
893
+ key: \${{ runner.os }}-nextjs-\${{ hashFiles('**/${manager.lockfile}') }}-\${{ hashFiles('**/*.ts', '**/*.tsx') }}
689
894
  restore-keys: |
690
- \${{ runner.os }}-nextjs-\${{ hashFiles('**/package-lock.json') }}-
895
+ \${{ runner.os }}-nextjs-\${{ hashFiles('**/${manager.lockfile}') }}-
691
896
  `;
692
897
 
693
898
  // src/cli/templates/react-ci.ts
694
899
  var reactCi = ({
695
900
  nodeVersion,
696
901
  withCommitlint,
697
- usingNextJs
902
+ manager,
903
+ usingNextJs,
904
+ pnpmVersion
698
905
  }) => `name: CI
699
906
 
700
907
  on:
@@ -706,34 +913,25 @@ jobs:
706
913
  lint:
707
914
  runs-on: ubuntu-latest
708
915
  steps:
709
- - name: Checkout
710
- uses: actions/checkout@v4
711
- with:
712
- fetch-depth: 0
713
-
714
- - name: Setup node
715
- uses: actions/setup-node@v4
716
- with:
717
- node-version: ${nodeVersion}
718
- cache: "npm"
719
- ${usingNextJs ? nextJsCi() : ""}
916
+ ${nodeSetupCi({ nodeVersion, manager, pnpmVersion })}
917
+ ${usingNextJs ? nextJsCi({ manager }) : ""}
720
918
  - name: Install dependencies
721
- run: npm ci
722
- ${withCommitlint ? commitLintCi() : ""}
919
+ run: ${manager.cleanInstall}
920
+ ${withCommitlint ? commitLintCi({ manager }) : ""}
723
921
  - name: Check formatting
724
- run: npm run format:check
922
+ run: ${manager.runScript} format:check
725
923
  if: always()
726
924
 
727
925
  - name: Lint code
728
- run: npm run lint
926
+ run: ${manager.runScript} lint
729
927
  if: always()
730
928
 
731
929
  - name: Check types
732
- run: npm run types:check
930
+ run: ${manager.runScript} types:check
733
931
  if: always()
734
932
 
735
933
  - name: Build
736
- run: npm run build
934
+ run: ${manager.runScript} build
737
935
  if: always()
738
936
  `;
739
937
 
@@ -746,10 +944,12 @@ var installGithubActions = async () => {
746
944
  const ghWorkflowsDirectory = path5.join(gitDirectory, ".github/workflows");
747
945
  await fs2.mkdir(ghWorkflowsDirectory, { recursive: true });
748
946
  const type = await packageJson4.getProjectType();
947
+ const manager = packageJson4.manager;
948
+ const pnpmVersion = manager.name === "pnpm" ? await packageJson4.getPnpmVersion() : void 0;
749
949
  const withCommitlint = await packageJson4.hasPackage("@commitlint/cli");
750
950
  if (type === "adonis") {
751
951
  if (!existsSync2(path5.join(projectDirectory, ".env.example"))) {
752
- p6.cancel(
952
+ p9.cancel(
753
953
  "Nie znaleziono pliku .env.example. Upewnij si\u0119, \u017Ce jeste\u015B w katalogu projektu Adonisa."
754
954
  );
755
955
  process.exit(1);
@@ -758,12 +958,14 @@ var installGithubActions = async () => {
758
958
  path5.join(ghWorkflowsDirectory, "ci.yml"),
759
959
  adonisCi({
760
960
  nodeVersion: "22",
761
- withCommitlint
961
+ withCommitlint,
962
+ manager,
963
+ pnpmVersion
762
964
  })
763
965
  );
764
966
  await fs2.writeFile(
765
967
  path5.join(ghWorkflowsDirectory, "db.yml"),
766
- adonisMigrationsCi()
968
+ adonisMigrationsCi({ nodeVersion: "22", manager, pnpmVersion })
767
969
  );
768
970
  }
769
971
  if (type === "react") {
@@ -773,7 +975,9 @@ var installGithubActions = async () => {
773
975
  reactCi({
774
976
  nodeVersion: "22",
775
977
  withCommitlint,
776
- usingNextJs
978
+ usingNextJs,
979
+ manager,
980
+ pnpmVersion
777
981
  })
778
982
  );
779
983
  if (usingNextJs) {
@@ -785,7 +989,9 @@ var installGithubActions = async () => {
785
989
  path5.join(ghWorkflowsDirectory, "ci.yml"),
786
990
  nestjsCi({
787
991
  nodeVersion: "22",
788
- withCommitlint
992
+ withCommitlint,
993
+ manager,
994
+ pnpmVersion
789
995
  })
790
996
  );
791
997
  }
@@ -799,19 +1005,24 @@ var installGithubActions = async () => {
799
1005
  await packageJson4.addScriptIfNotExists("lint", "eslint . --max-warnings=0");
800
1006
  await packageJson4.addScriptIfNotExists("format", "prettier --write .");
801
1007
  await packageJson4.addScriptIfNotExists("types:check", "tsc --noEmit");
802
- p6.note("Dodano konfiguracj\u0119 CI i skrypty.");
1008
+ p9.note("Dodano konfiguracj\u0119 CI i skrypty.");
803
1009
  };
804
1010
 
805
1011
  // src/cli/install-lint-staged.ts
806
1012
  import assert3 from "assert";
807
1013
  import { writeFile as writeFile5 } from "fs/promises";
1014
+ import path6 from "path";
808
1015
  var packageJson5 = new PackageJson();
809
1016
  var installLintStaged = async () => {
810
1017
  await packageJson5.load();
811
1018
  assert3.ok(packageJson5.json !== null);
812
1019
  await installHusky();
813
1020
  await packageJson5.install("lint-staged", { dev: true });
814
- await writeFile5(".husky/pre-commit", "npx lint-staged\n");
1021
+ await writeFile5(
1022
+ path6.join(projectRoot(), ".husky/pre-commit"),
1023
+ `${packageJson5.manager.localExecute} lint-staged
1024
+ `
1025
+ );
815
1026
  packageJson5.json["lint-staged"] = {
816
1027
  "*": "prettier -w --ignore-unknown"
817
1028
  };
@@ -819,11 +1030,11 @@ var installLintStaged = async () => {
819
1030
  };
820
1031
 
821
1032
  // src/cli/install-prettier.ts
822
- import * as p7 from "@clack/prompts";
1033
+ import * as p10 from "@clack/prompts";
823
1034
  import assert4 from "assert";
824
1035
  import { existsSync as existsSync3 } from "fs";
825
1036
  import * as fs3 from "fs/promises";
826
- import path6 from "path";
1037
+ import path7 from "path";
827
1038
  var prettierConfigNames = [
828
1039
  ".prettierrc.js",
829
1040
  ".prettierrc.cjs",
@@ -848,34 +1059,34 @@ var installPrettier = async (isNonInteractive2 = false) => {
848
1059
  version: ">=3"
849
1060
  });
850
1061
  const prettierConfig = prettierConfigNames.find(
851
- (configName) => existsSync3(path6.join(root2, configName))
1062
+ (configName) => existsSync3(path7.join(root2, configName))
852
1063
  );
853
1064
  const solvroPrettierPath = "@solvro/config/prettier";
854
1065
  if (prettierConfig !== void 0 || packageJson6.json.prettier !== void 0) {
855
1066
  if (packageJson6.json.prettier === solvroPrettierPath) {
856
- p7.note("Konfiguracja Prettiera jest ju\u017C ustawiona. Pomijam.");
1067
+ p10.note("Konfiguracja Prettiera jest ju\u017C ustawiona. Pomijam.");
857
1068
  return;
858
1069
  }
859
1070
  if (isNonInteractive2) {
860
1071
  for (const configName of prettierConfigNames) {
861
- await fs3.rm(path6.join(root2, configName)).catch(() => null);
1072
+ await fs3.rm(path7.join(root2, configName)).catch(() => null);
862
1073
  }
863
1074
  } else {
864
1075
  const isConfirmed = await polishConfirm({
865
1076
  message: `Znaleziono konfiguracj\u0119 Prettiera. Czy chcesz j\u0105 nadpisa\u0107?`
866
1077
  });
867
- if (p7.isCancel(isConfirmed) || !isConfirmed) {
868
- p7.cancel("Usu\u0144 konfiguracje Prettiera i spr\xF3buj ponownie.");
1078
+ if (p10.isCancel(isConfirmed) || !isConfirmed) {
1079
+ p10.cancel("Usu\u0144 konfiguracje Prettiera i spr\xF3buj ponownie.");
869
1080
  process.exit(1);
870
1081
  }
871
1082
  for (const configName of prettierConfigNames) {
872
- await fs3.rm(path6.join(root2, configName)).catch(() => null);
1083
+ await fs3.rm(path7.join(root2, configName)).catch(() => null);
873
1084
  }
874
1085
  }
875
1086
  }
876
1087
  packageJson6.json.prettier = solvroPrettierPath;
877
1088
  await packageJson6.save();
878
- p7.note("Konfiguracja Prettiera zosta\u0142a dodana.");
1089
+ p10.note("Konfiguracja Prettiera zosta\u0142a dodana.");
879
1090
  };
880
1091
 
881
1092
  // src/cli/index.ts
@@ -883,31 +1094,15 @@ var program = new Command();
883
1094
  program.name("@solvro/config").description("Solvro's engineering style guide setup").version(package_default.version).option("-f, --force", "Skip git clean check", false).option("--eslint", "Install ESLint configuration", false).option("--prettier", "Install Prettier configuration", false).option("--gh-action", "Install GitHub Actions", false).option("--commitlint", "Install Commitlint configuration", false).option("-a, --all", "Install all tools", false);
884
1095
  program.parse();
885
1096
  var options = program.opts();
886
- var isNonInteractive = process.argv.length > 2;
1097
+ var isNonInteractive = checkIsNonInteractive();
887
1098
  async function main() {
888
1099
  if (!isNonInteractive) {
889
- p8.intro(c2.bold(c2.bgBlue(" @solvro/config ")));
890
- }
891
- const userAgent = getUserAgent();
892
- if (userAgent !== "npm") {
893
- const packageManager = userAgent ?? "unknown";
894
- const warningMessage = `${c2.red(c2.bold(`\u26A0\uFE0F OSTRZE\u017BENIE: ${packageManager} nie jest obs\u0142ugiwany \u26A0\uFE0F`))}
895
-
896
- Pr\xF3bujesz uruchomi\u0107 ten skrypt ${c2.yellow(packageManager)}'em, ale @solvro/config obecnie dzia\u0142a tylko z ${c2.green("npm")}'em.
897
-
898
- ${c2.white(`Support dla innych mened\u017Cer\xF3w pakiet\xF3w jest planowany w nadchodz\u0105cych wersjach - ${c2.yellow("zagwiazdkuj i spr\xF3buj ponownie wkr\xF3tce")}!`)}
899
-
900
- ${c2.white(`W mi\u0119dzyczasie u\u017Cyj ${c2.green("npm")}'a:`)}
901
- ${c2.cyan("npx @solvro/config")}`;
902
- if (isNonInteractive) {
903
- console.error(warningMessage);
904
- } else {
905
- p8.cancel(warningMessage);
906
- }
907
- process.exit(1);
1100
+ p11.intro(c5.bold(c5.bgBlue(" @solvro/config ")));
908
1101
  }
909
1102
  const packageJson7 = new PackageJson();
1103
+ packageJson7.verifyPackageManager();
910
1104
  await packageJson7.load();
1105
+ await packageJson7.validateUserAgentConsistency();
911
1106
  if (options.force !== true && !isGitClean()) {
912
1107
  if (isNonInteractive) {
913
1108
  console.error(
@@ -918,15 +1113,15 @@ ${c2.cyan("npx @solvro/config")}`;
918
1113
  const isConfirmed = await polishConfirm({
919
1114
  message: `Masz niezapisane zmiany w Git. Czy chcesz kontynuowa\u0107?`
920
1115
  });
921
- if (p8.isCancel(isConfirmed) || !isConfirmed) {
922
- p8.cancel("Zapisz zmiany w Git i spr\xF3buj ponownie.");
1116
+ if (p11.isCancel(isConfirmed) || !isConfirmed) {
1117
+ p11.cancel("Zapisz zmiany w Git i spr\xF3buj ponownie.");
923
1118
  process.exit(1);
924
1119
  }
925
1120
  }
926
1121
  if (await packageJson7.hasPackage("eslint") && !await packageJson7.doesSatisfy("eslint", "<10")) {
927
1122
  const eslint = await packageJson7.getPackageInfo("eslint");
928
- const versionInfo = eslint?.version == null ? "" : ` Obecnie zainstalowana jest wersja ${c2.yellow(eslint.version)}.`;
929
- const errorMessage = `ESLint w wersji powy\u017Cej 9 ${c2.red("nie jest jeszcze wspierany")}.${versionInfo}`;
1123
+ const versionInfo = eslint?.version == null ? "" : ` Obecnie zainstalowana jest wersja ${c5.yellow(eslint.version)}.`;
1124
+ const errorMessage = `ESLint w wersji powy\u017Cej 9 ${c5.red("nie jest jeszcze wspierany")}.${versionInfo}`;
930
1125
  const errorRetry = "Prosz\u0119 zainstalowa\u0107 wersj\u0119 9 i spr\xF3bowa\u0107 ponownie.";
931
1126
  if (isNonInteractive) {
932
1127
  console.error(errorMessage);
@@ -934,10 +1129,10 @@ ${c2.cyan("npx @solvro/config")}`;
934
1129
  process.exit(1);
935
1130
  }
936
1131
  const isConfirmed = await polishConfirm({
937
- message: `${errorMessage} Zainstalowa\u0107 starsz\u0105 wersj\u0119 ${c2.magenta("ESLint")}'a? (Wymagane by kontynuowa\u0107)`
1132
+ message: `${errorMessage} Zainstalowa\u0107 starsz\u0105 wersj\u0119 ${c5.magenta("ESLint")}'a? (Wymagane by kontynuowa\u0107)`
938
1133
  });
939
- if (p8.isCancel(isConfirmed) || !isConfirmed) {
940
- p8.cancel(errorRetry);
1134
+ if (p11.isCancel(isConfirmed) || !isConfirmed) {
1135
+ p11.cancel(errorRetry);
941
1136
  process.exit(1);
942
1137
  }
943
1138
  await packageJson7.install("eslint", { dev: true, version: "^9" });
@@ -945,17 +1140,17 @@ ${c2.cyan("npx @solvro/config")}`;
945
1140
  const projectType = await packageJson7.getProjectType();
946
1141
  if (!isNonInteractive) {
947
1142
  if (projectType === "adonis") {
948
- await confirmProjectType(c2.magenta("Adonis"));
1143
+ await confirmProjectType(c5.magenta("Adonis"));
949
1144
  }
950
1145
  if (projectType === "react") {
951
- await confirmProjectType(c2.cyan("React"));
1146
+ await confirmProjectType(c5.cyan("React"));
952
1147
  }
953
1148
  if (projectType === "nestjs") {
954
- await confirmProjectType(c2.red("NestJS"));
1149
+ await confirmProjectType(c5.red("NestJS"));
955
1150
  }
956
1151
  if (projectType === "node") {
957
- p8.cancel(
958
- `Nie znaleziono ani ${c2.magenta("Adonis")}'a, ${c2.cyan("React")}'a, ani ${c2.white("NestJS")}'a. Musisz r\u0119cznie konfigurowa\u0107 projekt.`
1152
+ p11.cancel(
1153
+ `Nie znaleziono ani ${c5.magenta("Adonis")}-a, ${c5.cyan("React")}-a, ani ${c5.white("NestJS")}-a. Musisz r\u0119cznie konfigurowa\u0107 projekt.`
959
1154
  );
960
1155
  process.exit(1);
961
1156
  }
@@ -966,10 +1161,10 @@ ${c2.cyan("npx @solvro/config")}`;
966
1161
  } else {
967
1162
  if (!await packageJson7.isESM()) {
968
1163
  const isConfirmed = await polishConfirm({
969
- message: `Tw\xF3j projekt nie u\u017Cywa ESM (brak type: "module" w package.json). Czy chcesz to doda\u0107? (Wymagane by kontynuowa\u0107)`
1164
+ message: `Tw\xF3j projekt nie u\u017Cywa ESM (brak "type": "module" w package.json). Czy chcesz to doda\u0107? (Wymagane by kontynuowa\u0107)`
970
1165
  });
971
- if (p8.isCancel(isConfirmed) || !isConfirmed) {
972
- p8.cancel("Zmie\u0144 projekt na ESM i spr\xF3buj ponownie.");
1166
+ if (p11.isCancel(isConfirmed) || !isConfirmed) {
1167
+ p11.cancel("Zmie\u0144 projekt na ESM i spr\xF3buj ponownie.");
973
1168
  process.exit(1);
974
1169
  }
975
1170
  await packageJson7.ensureESM();
@@ -999,35 +1194,35 @@ ${c2.cyan("npx @solvro/config")}`;
999
1194
  process.exit(1);
1000
1195
  }
1001
1196
  } else {
1002
- const additionalTools = await p8.multiselect({
1003
- message: `Kt\xF3re rzeczy Ci\u0119 interesuj\u0105? ${c2.gray("zaznacz spacj\u0105, potwierd\u017A enterem")}`,
1197
+ const additionalTools = await p11.multiselect({
1198
+ message: `Kt\xF3re rzeczy Ci\u0119 interesuj\u0105? ${c5.gray("zaznacz spacj\u0105, potwierd\u017A enterem")}`,
1004
1199
  initialValues: ["eslint", "prettier", "gh-action", "commitlint"],
1005
1200
  options: [
1006
1201
  {
1007
1202
  value: "eslint",
1008
- label: c2.bold(c2.blueBright("ESLint")),
1203
+ label: c5.bold(c5.blueBright("ESLint")),
1009
1204
  hint: "sprawdzanie jako\u015Bci kodu"
1010
1205
  },
1011
1206
  {
1012
1207
  value: "prettier",
1013
- label: c2.bold(c2.yellowBright("Prettier")),
1208
+ label: c5.bold(c5.yellowBright("Prettier")),
1014
1209
  hint: "formatowanie"
1015
1210
  },
1016
1211
  {
1017
1212
  value: "gh-action",
1018
- label: c2.bold("GitHub Actions"),
1019
- hint: "automatyczne testy na Githubie"
1213
+ label: c5.bold("GitHub Actions"),
1214
+ hint: "automatyczne testy na GitHubie"
1020
1215
  },
1021
1216
  {
1022
1217
  value: "commitlint",
1023
- label: c2.bold("Commitlint"),
1218
+ label: c5.bold("Commitlint"),
1024
1219
  hint: "walidacja tre\u015Bci commit\xF3w"
1025
1220
  }
1026
1221
  ],
1027
1222
  required: false
1028
1223
  });
1029
- if (p8.isCancel(additionalTools) || additionalTools.length === 0) {
1030
- p8.cancel("Nie wybrano \u017Cadnych narz\u0119dzi.");
1224
+ if (p11.isCancel(additionalTools) || additionalTools.length === 0) {
1225
+ p11.cancel("Nie wybrano \u017Cadnych narz\u0119dzi.");
1031
1226
  process.exit(1);
1032
1227
  }
1033
1228
  toolsToInstall = additionalTools;
@@ -1050,7 +1245,10 @@ ${c2.cyan("npx @solvro/config")}`;
1050
1245
  await installGithubActions();
1051
1246
  }
1052
1247
  await packageJson7.clearInstall();
1053
- const printSuccess = isNonInteractive ? console.info : p8.outro;
1248
+ if (toolsToInstall.includes("prettier")) {
1249
+ await packageJson7.localExecute("prettier", "--write", "package.json");
1250
+ }
1251
+ const printSuccess = isNonInteractive ? console.info : p11.outro;
1054
1252
  printSuccess("\u2705 Konfiguracja zako\u0144czona pomy\u015Blnie!");
1055
1253
  }
1056
1254
  async function mainWrapper() {
@@ -1059,7 +1257,7 @@ async function mainWrapper() {
1059
1257
  } catch (error) {
1060
1258
  if (process.env.NODE_ENV === "development") {
1061
1259
  console.error(
1062
- c2.red("Unhandled error in main:"),
1260
+ c5.red("Unhandled error in main:"),
1063
1261
  error instanceof Error ? error.message : error
1064
1262
  );
1065
1263
  } else {
@@ -1068,7 +1266,7 @@ async function mainWrapper() {
1068
1266
  console.error(errorMessage);
1069
1267
  console.error(BUG_TRACKER_URL);
1070
1268
  } else {
1071
- p8.cancel(`${errorMessage} ${BUG_TRACKER_URL}`);
1269
+ p11.cancel(`${errorMessage} ${BUG_TRACKER_URL}`);
1072
1270
  }
1073
1271
  }
1074
1272
  process.exit(1);