@solvro/config 2.2.0 → 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.1.1",
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",
@@ -130,22 +130,54 @@ var package_default = {
130
130
  "@next/eslint-plugin-next": ">=12.3.0",
131
131
  eslint: ">=9.0.0 <10.0.0"
132
132
  },
133
- packageManager: "npm@11.11.0",
133
+ packageManager: "npm@11.11.1",
134
134
  engines: {
135
- node: "^20.19.0 || >=22.12.0"
135
+ node: "^20.19.0 || >=22.12.0",
136
+ npm: "^11.11.1"
136
137
  },
137
138
  volta: {
138
- node: "22.17.0"
139
+ node: "22.22.1",
140
+ npm: "11.11.1"
139
141
  },
140
142
  publishConfig: {
141
143
  access: "public"
142
144
  }
143
145
  };
144
146
 
145
- // src/constants/index.ts
147
+ // src/constants/github.ts
146
148
  var REPO_URL = "https://github.com/Solvro/lib-web-solvro-config";
147
149
  var BUG_TRACKER_URL = `${REPO_URL}/issues/new`;
148
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
+
149
181
  // src/utils/confirm-project-type.ts
150
182
  import * as p2 from "@clack/prompts";
151
183
 
@@ -192,12 +224,13 @@ function isGitClean() {
192
224
  }
193
225
 
194
226
  // src/utils/package-json.ts
195
- import * as p4 from "@clack/prompts";
227
+ import * as p7 from "@clack/prompts";
196
228
  import { getPackageInfo, isPackageListed, loadPackageJSON } from "local-pkg";
197
229
  import assert from "assert";
198
- import { writeFile } from "fs/promises";
230
+ import { stat, writeFile } from "fs/promises";
199
231
  import path2 from "path";
200
- import c from "picocolors";
232
+ import { getUserAgent } from "package-manager-detector/detect";
233
+ import c4 from "picocolors";
201
234
  import semver from "semver";
202
235
 
203
236
  // src/utils/git-root.ts
@@ -234,6 +267,9 @@ var $$ = (async (...arguments_) => {
234
267
  return cachedExeca(...arguments_);
235
268
  });
236
269
 
270
+ // src/utils/is-supported-package-manager.ts
271
+ var isSupportedPackageManager = (userAgent) => userAgent != null && SUPPORTED_PACKAGE_MANAGERS.includes(userAgent);
272
+
237
273
  // src/utils/run-with-spinner.ts
238
274
  import * as p3 from "@clack/prompts";
239
275
 
@@ -265,14 +301,128 @@ var runWithSpinner = async (options2) => {
265
301
  });
266
302
  };
267
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
+
268
380
  // src/utils/package-json.ts
269
381
  var PackageJson = class {
270
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
+ }
271
421
  async load() {
272
422
  const json = await loadPackageJSON(projectRoot());
273
423
  if (json === null) {
274
- p4.cancel(
275
- `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.`
276
426
  );
277
427
  process.exit(1);
278
428
  }
@@ -314,8 +464,8 @@ var PackageJson = class {
314
464
  const isReact = await isPackageListed("react");
315
465
  const isNestJs = await isPackageListed("@nestjs/core");
316
466
  if (isReact && isAdonis) {
317
- p4.cancel(
318
- `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.`
319
469
  );
320
470
  process.exit(1);
321
471
  }
@@ -350,13 +500,20 @@ var PackageJson = class {
350
500
  async install(package_, options2 = {}) {
351
501
  const isInstalled = await this.hasPackage(package_);
352
502
  const installVersion = options2.version ?? "latest";
503
+ const [installCommand, ...commandOptions] = this.manager.installPackage.split(" ");
504
+ if (options2.dev === true) {
505
+ commandOptions.push("-D");
506
+ }
353
507
  if (!isInstalled) {
354
508
  await runWithSpinner({
355
509
  start: `Instalowanie pakietu ${package_}`,
356
510
  stop: `${package_} zainstalowany \u{1F60D}`,
357
511
  error: `Instalacja pakietu ${package_} nie powiod\u0142a si\u0119 \u{1F976}`,
358
512
  callback: async () => {
359
- await $$`npm i ${options2.dev === true ? "-D" : ""} ${package_}@${installVersion}`;
513
+ await $$(installCommand, [
514
+ ...commandOptions,
515
+ `${package_}@${installVersion}`
516
+ ]);
360
517
  }
361
518
  });
362
519
  await this.load();
@@ -368,14 +525,46 @@ var PackageJson = class {
368
525
  stop: `${package_} zaktualizowany \u{1F60D}`,
369
526
  error: `Aktualizacja pakietu ${package_} nie powiod\u0142a si\u0119 \u{1F976}`,
370
527
  callback: async () => {
371
- await $$`npm i ${options2.dev === true ? "-D" : ""} ${package_}@${installVersion}`;
528
+ await $$(installCommand, [
529
+ ...commandOptions,
530
+ `${package_}@${installVersion}`
531
+ ]);
372
532
  }
373
533
  });
374
534
  await this.load();
375
535
  }
376
536
  }
537
+ async localExecute(...commandArguments) {
538
+ const [command, ...commandOptions] = this.manager.localExecute.split(" ");
539
+ const options2 = [...commandOptions, ...commandArguments];
540
+ await $$(command, options2);
541
+ }
377
542
  async clearInstall() {
378
- 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";
379
568
  }
380
569
  };
381
570
 
@@ -389,7 +578,7 @@ var packageJson = new PackageJson();
389
578
  var installHusky = async () => {
390
579
  if (!await packageJson.hasPackage("husky")) {
391
580
  await packageJson.install("husky", { dev: true });
392
- await $$`npx husky init`;
581
+ await packageJson.localExecute("husky", "init");
393
582
  }
394
583
  await packageJson.load();
395
584
  assert2.ok(packageJson.json !== null);
@@ -412,13 +601,14 @@ var installCommitLint = async () => {
412
601
  await packageJson2.install("@commitlint/cli", { dev: true });
413
602
  await writeFile2(
414
603
  path3.join(root, ".husky/commit-msg"),
415
- 'npx commitlint --edit "$1"\n'
604
+ `${packageJson2.manager.localExecute} commitlint --edit "$1"
605
+ `
416
606
  );
417
607
  await writeFile2(path3.join(root, ".commitlintrc.js"), commitlint());
418
608
  };
419
609
 
420
610
  // src/cli/install-eslint.ts
421
- import * as p5 from "@clack/prompts";
611
+ import * as p8 from "@clack/prompts";
422
612
  import { existsSync } from "fs";
423
613
  import * as fs from "fs/promises";
424
614
  import path4 from "path";
@@ -448,7 +638,7 @@ var installEslint = async (isNonInteractive2 = false) => {
448
638
  if (type === "react" && await packageJson3.isNextJs()) {
449
639
  const is15 = await packageJson3.doesSatisfy("next", ">=15");
450
640
  if (!is15) {
451
- p5.cancel(
641
+ p8.cancel(
452
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"
453
643
  );
454
644
  process.exit(1);
@@ -464,7 +654,7 @@ var installEslint = async (isNonInteractive2 = false) => {
464
654
  "utf8"
465
655
  );
466
656
  if (eslintContent.includes("export default solvro(")) {
467
- p5.note("Eslint jest ju\u017C skonfigurowany. Pomijam.");
657
+ p8.note("Eslint jest ju\u017C skonfigurowany. Pomijam.");
468
658
  return;
469
659
  } else {
470
660
  if (isNonInteractive2) {
@@ -473,8 +663,8 @@ var installEslint = async (isNonInteractive2 = false) => {
473
663
  const isConfirmed = await polishConfirm({
474
664
  message: `Znaleziono plik konfiguracyjny Eslint. Czy chcesz go nadpisa\u0107?`
475
665
  });
476
- if (p5.isCancel(isConfirmed) || !isConfirmed) {
477
- 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.");
478
668
  process.exit(1);
479
669
  }
480
670
  await fs.rm(path4.join(root2, eslintConfig));
@@ -490,26 +680,56 @@ var installEslint = async (isNonInteractive2 = false) => {
490
680
  export default solvro();
491
681
  `
492
682
  );
493
- p5.note("Plik konfiguracyjny Eslint zosta\u0142 utworzony.");
683
+ p8.note("Plik konfiguracyjny Eslint zosta\u0142 utworzony.");
494
684
  };
495
685
 
496
686
  // src/cli/install-ga.ts
497
- import * as p6 from "@clack/prompts";
687
+ import * as p9 from "@clack/prompts";
498
688
  import { existsSync as existsSync2 } from "fs";
499
689
  import * as fs2 from "fs/promises";
500
690
  import path5 from "path";
501
691
 
502
692
  // src/cli/templates/commit-lint-ci.ts
503
- var commitLintCi = () => `
693
+ var commitLintCi = ({
694
+ manager
695
+ }) => `
504
696
  - name: Check commit name
505
697
  if: github.event_name == 'pull_request'
506
- 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
507
699
  `;
508
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
+
509
727
  // src/cli/templates/adonis-ci.ts
510
728
  var adonisCi = ({
511
729
  nodeVersion,
512
- withCommitlint
730
+ withCommitlint,
731
+ manager,
732
+ pnpmVersion
513
733
  }) => `name: CI
514
734
 
515
735
  on:
@@ -521,48 +741,43 @@ jobs:
521
741
  lint:
522
742
  runs-on: ubuntu-latest
523
743
  steps:
524
- - name: Checkout
525
- uses: actions/checkout@v4
526
- with:
527
- fetch-depth: 0
528
-
529
- - name: Setup node
530
- uses: actions/setup-node@v4
531
- with:
532
- node-version: ${nodeVersion}
533
- cache: "npm"
744
+ ${nodeSetupCi({ nodeVersion, manager, pnpmVersion })}
534
745
 
535
746
  - name: Install dependencies
536
- run: npm ci
747
+ run: ${manager.cleanInstall}
537
748
 
538
749
  - name: Set up AdonisJS environment
539
750
  run: |
540
751
  cp .env.example .env
541
752
  node ace generate:key
542
- ${withCommitlint ? commitLintCi() : ""}
753
+ ${withCommitlint ? commitLintCi({ manager }) : ""}
543
754
  - name: Check formatting
544
- run: npm run format:check
755
+ run: ${manager.runScript} format:check
545
756
  if: always()
546
757
 
547
758
  - name: Lint code
548
- run: npm run lint
759
+ run: ${manager.runScript} lint
549
760
  if: always()
550
761
 
551
762
  - name: Check types
552
- run: npm run types:check
763
+ run: ${manager.runScript} types:check
553
764
  if: always()
554
765
 
555
766
  - name: Run tests
556
- run: npm test
767
+ run: ${manager.name} test
557
768
  if: always()
558
769
 
559
770
  - name: Build
560
- run: npm run build
771
+ run: ${manager.runScript} build
561
772
  if: always()
562
773
  `;
563
774
 
564
775
  // src/cli/templates/adonis-ci-migrations.ts
565
- var adonisMigrationsCi = () => `name: Migration check
776
+ var adonisMigrationsCi = ({
777
+ nodeVersion,
778
+ manager,
779
+ pnpmVersion
780
+ }) => `name: Migration check
566
781
 
567
782
  on:
568
783
  pull_request:
@@ -594,11 +809,10 @@ jobs:
594
809
  - 5432:5432
595
810
 
596
811
  steps:
597
- - name: Check out repository code
598
- uses: actions/checkout@v4
812
+ ${nodeSetupCi({ nodeVersion, manager, pnpmVersion })}
599
813
 
600
814
  - name: Install dependencies
601
- run: npm ci
815
+ run: ${manager.cleanInstall}
602
816
 
603
817
  - name: Set up AdonisJS environment
604
818
  run: |
@@ -626,7 +840,9 @@ updates:
626
840
  // src/cli/templates/nestjs-ci.ts
627
841
  var nestjsCi = ({
628
842
  nodeVersion,
629
- withCommitlint
843
+ withCommitlint,
844
+ manager,
845
+ pnpmVersion
630
846
  }) => `name: CI
631
847
 
632
848
  on:
@@ -638,61 +854,54 @@ jobs:
638
854
  lint:
639
855
  runs-on: ubuntu-latest
640
856
  steps:
641
- - name: Checkout
642
- uses: actions/checkout@v4
643
- with:
644
- fetch-depth: 0
645
-
646
- - name: Setup node
647
- uses: actions/setup-node@v4
648
- with:
649
- node-version: ${nodeVersion}
650
- cache: "npm"
857
+ ${nodeSetupCi({ nodeVersion, manager, pnpmVersion })}
651
858
 
652
859
  - name: Install dependencies
653
- run: npm ci
654
- ${withCommitlint ? commitLintCi() : ""}
860
+ run: ${manager.cleanInstall}
861
+ ${withCommitlint ? commitLintCi({ manager }) : ""}
655
862
  - name: Check formatting
656
- run: npm run format:check
863
+ run: ${manager.runScript} format:check
657
864
  if: always()
658
865
 
659
866
  - name: Lint code
660
- run: npm run lint
867
+ run: ${manager.runScript} lint
661
868
  if: always()
662
869
 
663
870
  - name: Check types
664
- run: npm run types:check
871
+ run: ${manager.runScript} types:check
665
872
  if: always()
666
873
 
667
874
  - name: Run tests
668
- run: npm test
875
+ run: ${manager.name} test
669
876
  if: always()
670
877
 
671
878
  - name: Run e2e tests
672
- run: npm run test:e2e
879
+ run: ${manager.runScript} test:e2e
673
880
  if: always()
674
881
 
675
882
  - name: Build
676
- run: npm run build
883
+ run: ${manager.runScript} build
677
884
  if: always()
678
885
  `;
679
886
 
680
887
  // src/cli/templates/nextjs-ci.ts
681
- var nextJsCi = () => `
888
+ var nextJsCi = ({ manager }) => `
682
889
  - name: Setup build cache
683
- uses: actions/cache@v4
890
+ uses: actions/cache@v5
684
891
  with:
685
892
  path: \${{ github.workspace }}/.next/cache
686
- key: \${{ runner.os }}-nextjs-\${{ hashFiles('**/package-lock.json') }}-\${{ hashFiles('**/*.ts', '**/*.tsx') }}
893
+ key: \${{ runner.os }}-nextjs-\${{ hashFiles('**/${manager.lockfile}') }}-\${{ hashFiles('**/*.ts', '**/*.tsx') }}
687
894
  restore-keys: |
688
- \${{ runner.os }}-nextjs-\${{ hashFiles('**/package-lock.json') }}-
895
+ \${{ runner.os }}-nextjs-\${{ hashFiles('**/${manager.lockfile}') }}-
689
896
  `;
690
897
 
691
898
  // src/cli/templates/react-ci.ts
692
899
  var reactCi = ({
693
900
  nodeVersion,
694
901
  withCommitlint,
695
- usingNextJs
902
+ manager,
903
+ usingNextJs,
904
+ pnpmVersion
696
905
  }) => `name: CI
697
906
 
698
907
  on:
@@ -704,34 +913,25 @@ jobs:
704
913
  lint:
705
914
  runs-on: ubuntu-latest
706
915
  steps:
707
- - name: Checkout
708
- uses: actions/checkout@v4
709
- with:
710
- fetch-depth: 0
711
-
712
- - name: Setup node
713
- uses: actions/setup-node@v4
714
- with:
715
- node-version: ${nodeVersion}
716
- cache: "npm"
717
- ${usingNextJs ? nextJsCi() : ""}
916
+ ${nodeSetupCi({ nodeVersion, manager, pnpmVersion })}
917
+ ${usingNextJs ? nextJsCi({ manager }) : ""}
718
918
  - name: Install dependencies
719
- run: npm ci
720
- ${withCommitlint ? commitLintCi() : ""}
919
+ run: ${manager.cleanInstall}
920
+ ${withCommitlint ? commitLintCi({ manager }) : ""}
721
921
  - name: Check formatting
722
- run: npm run format:check
922
+ run: ${manager.runScript} format:check
723
923
  if: always()
724
924
 
725
925
  - name: Lint code
726
- run: npm run lint
926
+ run: ${manager.runScript} lint
727
927
  if: always()
728
928
 
729
929
  - name: Check types
730
- run: npm run types:check
930
+ run: ${manager.runScript} types:check
731
931
  if: always()
732
932
 
733
933
  - name: Build
734
- run: npm run build
934
+ run: ${manager.runScript} build
735
935
  if: always()
736
936
  `;
737
937
 
@@ -744,10 +944,12 @@ var installGithubActions = async () => {
744
944
  const ghWorkflowsDirectory = path5.join(gitDirectory, ".github/workflows");
745
945
  await fs2.mkdir(ghWorkflowsDirectory, { recursive: true });
746
946
  const type = await packageJson4.getProjectType();
947
+ const manager = packageJson4.manager;
948
+ const pnpmVersion = manager.name === "pnpm" ? await packageJson4.getPnpmVersion() : void 0;
747
949
  const withCommitlint = await packageJson4.hasPackage("@commitlint/cli");
748
950
  if (type === "adonis") {
749
951
  if (!existsSync2(path5.join(projectDirectory, ".env.example"))) {
750
- p6.cancel(
952
+ p9.cancel(
751
953
  "Nie znaleziono pliku .env.example. Upewnij si\u0119, \u017Ce jeste\u015B w katalogu projektu Adonisa."
752
954
  );
753
955
  process.exit(1);
@@ -756,12 +958,14 @@ var installGithubActions = async () => {
756
958
  path5.join(ghWorkflowsDirectory, "ci.yml"),
757
959
  adonisCi({
758
960
  nodeVersion: "22",
759
- withCommitlint
961
+ withCommitlint,
962
+ manager,
963
+ pnpmVersion
760
964
  })
761
965
  );
762
966
  await fs2.writeFile(
763
967
  path5.join(ghWorkflowsDirectory, "db.yml"),
764
- adonisMigrationsCi()
968
+ adonisMigrationsCi({ nodeVersion: "22", manager, pnpmVersion })
765
969
  );
766
970
  }
767
971
  if (type === "react") {
@@ -771,7 +975,9 @@ var installGithubActions = async () => {
771
975
  reactCi({
772
976
  nodeVersion: "22",
773
977
  withCommitlint,
774
- usingNextJs
978
+ usingNextJs,
979
+ manager,
980
+ pnpmVersion
775
981
  })
776
982
  );
777
983
  if (usingNextJs) {
@@ -783,7 +989,9 @@ var installGithubActions = async () => {
783
989
  path5.join(ghWorkflowsDirectory, "ci.yml"),
784
990
  nestjsCi({
785
991
  nodeVersion: "22",
786
- withCommitlint
992
+ withCommitlint,
993
+ manager,
994
+ pnpmVersion
787
995
  })
788
996
  );
789
997
  }
@@ -797,19 +1005,24 @@ var installGithubActions = async () => {
797
1005
  await packageJson4.addScriptIfNotExists("lint", "eslint . --max-warnings=0");
798
1006
  await packageJson4.addScriptIfNotExists("format", "prettier --write .");
799
1007
  await packageJson4.addScriptIfNotExists("types:check", "tsc --noEmit");
800
- p6.note("Dodano konfiguracj\u0119 CI i skrypty.");
1008
+ p9.note("Dodano konfiguracj\u0119 CI i skrypty.");
801
1009
  };
802
1010
 
803
1011
  // src/cli/install-lint-staged.ts
804
1012
  import assert3 from "assert";
805
1013
  import { writeFile as writeFile5 } from "fs/promises";
1014
+ import path6 from "path";
806
1015
  var packageJson5 = new PackageJson();
807
1016
  var installLintStaged = async () => {
808
1017
  await packageJson5.load();
809
1018
  assert3.ok(packageJson5.json !== null);
810
1019
  await installHusky();
811
1020
  await packageJson5.install("lint-staged", { dev: true });
812
- 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
+ );
813
1026
  packageJson5.json["lint-staged"] = {
814
1027
  "*": "prettier -w --ignore-unknown"
815
1028
  };
@@ -817,11 +1030,11 @@ var installLintStaged = async () => {
817
1030
  };
818
1031
 
819
1032
  // src/cli/install-prettier.ts
820
- import * as p7 from "@clack/prompts";
1033
+ import * as p10 from "@clack/prompts";
821
1034
  import assert4 from "assert";
822
1035
  import { existsSync as existsSync3 } from "fs";
823
1036
  import * as fs3 from "fs/promises";
824
- import path6 from "path";
1037
+ import path7 from "path";
825
1038
  var prettierConfigNames = [
826
1039
  ".prettierrc.js",
827
1040
  ".prettierrc.cjs",
@@ -846,34 +1059,34 @@ var installPrettier = async (isNonInteractive2 = false) => {
846
1059
  version: ">=3"
847
1060
  });
848
1061
  const prettierConfig = prettierConfigNames.find(
849
- (configName) => existsSync3(path6.join(root2, configName))
1062
+ (configName) => existsSync3(path7.join(root2, configName))
850
1063
  );
851
1064
  const solvroPrettierPath = "@solvro/config/prettier";
852
1065
  if (prettierConfig !== void 0 || packageJson6.json.prettier !== void 0) {
853
1066
  if (packageJson6.json.prettier === solvroPrettierPath) {
854
- p7.note("Konfiguracja Prettiera jest ju\u017C ustawiona. Pomijam.");
1067
+ p10.note("Konfiguracja Prettiera jest ju\u017C ustawiona. Pomijam.");
855
1068
  return;
856
1069
  }
857
1070
  if (isNonInteractive2) {
858
1071
  for (const configName of prettierConfigNames) {
859
- await fs3.rm(path6.join(root2, configName)).catch(() => null);
1072
+ await fs3.rm(path7.join(root2, configName)).catch(() => null);
860
1073
  }
861
1074
  } else {
862
1075
  const isConfirmed = await polishConfirm({
863
1076
  message: `Znaleziono konfiguracj\u0119 Prettiera. Czy chcesz j\u0105 nadpisa\u0107?`
864
1077
  });
865
- if (p7.isCancel(isConfirmed) || !isConfirmed) {
866
- 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.");
867
1080
  process.exit(1);
868
1081
  }
869
1082
  for (const configName of prettierConfigNames) {
870
- await fs3.rm(path6.join(root2, configName)).catch(() => null);
1083
+ await fs3.rm(path7.join(root2, configName)).catch(() => null);
871
1084
  }
872
1085
  }
873
1086
  }
874
1087
  packageJson6.json.prettier = solvroPrettierPath;
875
1088
  await packageJson6.save();
876
- p7.note("Konfiguracja Prettiera zosta\u0142a dodana.");
1089
+ p10.note("Konfiguracja Prettiera zosta\u0142a dodana.");
877
1090
  };
878
1091
 
879
1092
  // src/cli/index.ts
@@ -881,31 +1094,15 @@ var program = new Command();
881
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);
882
1095
  program.parse();
883
1096
  var options = program.opts();
884
- var isNonInteractive = process.argv.length > 2;
1097
+ var isNonInteractive = checkIsNonInteractive();
885
1098
  async function main() {
886
1099
  if (!isNonInteractive) {
887
- p8.intro(c2.bold(c2.bgBlue(" @solvro/config ")));
888
- }
889
- const userAgent = getUserAgent();
890
- if (userAgent !== "npm") {
891
- const packageManager = userAgent ?? "unknown";
892
- const warningMessage = `${c2.red(c2.bold(`\u26A0\uFE0F OSTRZE\u017BENIE: ${packageManager} nie jest obs\u0142ugiwany \u26A0\uFE0F`))}
893
-
894
- Pr\xF3bujesz uruchomi\u0107 ten skrypt ${c2.yellow(packageManager)}'em, ale @solvro/config obecnie dzia\u0142a tylko z ${c2.green("npm")}'em.
895
-
896
- ${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")}!`)}
897
-
898
- ${c2.white(`W mi\u0119dzyczasie u\u017Cyj ${c2.green("npm")}'a:`)}
899
- ${c2.cyan("npx @solvro/config")}`;
900
- if (isNonInteractive) {
901
- console.error(warningMessage);
902
- } else {
903
- p8.cancel(warningMessage);
904
- }
905
- process.exit(1);
1100
+ p11.intro(c5.bold(c5.bgBlue(" @solvro/config ")));
906
1101
  }
907
1102
  const packageJson7 = new PackageJson();
1103
+ packageJson7.verifyPackageManager();
908
1104
  await packageJson7.load();
1105
+ await packageJson7.validateUserAgentConsistency();
909
1106
  if (options.force !== true && !isGitClean()) {
910
1107
  if (isNonInteractive) {
911
1108
  console.error(
@@ -916,15 +1113,15 @@ ${c2.cyan("npx @solvro/config")}`;
916
1113
  const isConfirmed = await polishConfirm({
917
1114
  message: `Masz niezapisane zmiany w Git. Czy chcesz kontynuowa\u0107?`
918
1115
  });
919
- if (p8.isCancel(isConfirmed) || !isConfirmed) {
920
- 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.");
921
1118
  process.exit(1);
922
1119
  }
923
1120
  }
924
1121
  if (await packageJson7.hasPackage("eslint") && !await packageJson7.doesSatisfy("eslint", "<10")) {
925
1122
  const eslint = await packageJson7.getPackageInfo("eslint");
926
- const versionInfo = eslint?.version == null ? "" : ` Obecnie zainstalowana jest wersja ${c2.yellow(eslint.version)}.`;
927
- 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}`;
928
1125
  const errorRetry = "Prosz\u0119 zainstalowa\u0107 wersj\u0119 9 i spr\xF3bowa\u0107 ponownie.";
929
1126
  if (isNonInteractive) {
930
1127
  console.error(errorMessage);
@@ -932,10 +1129,10 @@ ${c2.cyan("npx @solvro/config")}`;
932
1129
  process.exit(1);
933
1130
  }
934
1131
  const isConfirmed = await polishConfirm({
935
- 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)`
936
1133
  });
937
- if (p8.isCancel(isConfirmed) || !isConfirmed) {
938
- p8.cancel(errorRetry);
1134
+ if (p11.isCancel(isConfirmed) || !isConfirmed) {
1135
+ p11.cancel(errorRetry);
939
1136
  process.exit(1);
940
1137
  }
941
1138
  await packageJson7.install("eslint", { dev: true, version: "^9" });
@@ -943,17 +1140,17 @@ ${c2.cyan("npx @solvro/config")}`;
943
1140
  const projectType = await packageJson7.getProjectType();
944
1141
  if (!isNonInteractive) {
945
1142
  if (projectType === "adonis") {
946
- await confirmProjectType(c2.magenta("Adonis"));
1143
+ await confirmProjectType(c5.magenta("Adonis"));
947
1144
  }
948
1145
  if (projectType === "react") {
949
- await confirmProjectType(c2.cyan("React"));
1146
+ await confirmProjectType(c5.cyan("React"));
950
1147
  }
951
1148
  if (projectType === "nestjs") {
952
- await confirmProjectType(c2.red("NestJS"));
1149
+ await confirmProjectType(c5.red("NestJS"));
953
1150
  }
954
1151
  if (projectType === "node") {
955
- p8.cancel(
956
- `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.`
957
1154
  );
958
1155
  process.exit(1);
959
1156
  }
@@ -964,10 +1161,10 @@ ${c2.cyan("npx @solvro/config")}`;
964
1161
  } else {
965
1162
  if (!await packageJson7.isESM()) {
966
1163
  const isConfirmed = await polishConfirm({
967
- 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)`
968
1165
  });
969
- if (p8.isCancel(isConfirmed) || !isConfirmed) {
970
- 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.");
971
1168
  process.exit(1);
972
1169
  }
973
1170
  await packageJson7.ensureESM();
@@ -997,35 +1194,35 @@ ${c2.cyan("npx @solvro/config")}`;
997
1194
  process.exit(1);
998
1195
  }
999
1196
  } else {
1000
- const additionalTools = await p8.multiselect({
1001
- 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")}`,
1002
1199
  initialValues: ["eslint", "prettier", "gh-action", "commitlint"],
1003
1200
  options: [
1004
1201
  {
1005
1202
  value: "eslint",
1006
- label: c2.bold(c2.blueBright("ESLint")),
1203
+ label: c5.bold(c5.blueBright("ESLint")),
1007
1204
  hint: "sprawdzanie jako\u015Bci kodu"
1008
1205
  },
1009
1206
  {
1010
1207
  value: "prettier",
1011
- label: c2.bold(c2.yellowBright("Prettier")),
1208
+ label: c5.bold(c5.yellowBright("Prettier")),
1012
1209
  hint: "formatowanie"
1013
1210
  },
1014
1211
  {
1015
1212
  value: "gh-action",
1016
- label: c2.bold("GitHub Actions"),
1017
- hint: "automatyczne testy na Githubie"
1213
+ label: c5.bold("GitHub Actions"),
1214
+ hint: "automatyczne testy na GitHubie"
1018
1215
  },
1019
1216
  {
1020
1217
  value: "commitlint",
1021
- label: c2.bold("Commitlint"),
1218
+ label: c5.bold("Commitlint"),
1022
1219
  hint: "walidacja tre\u015Bci commit\xF3w"
1023
1220
  }
1024
1221
  ],
1025
1222
  required: false
1026
1223
  });
1027
- if (p8.isCancel(additionalTools) || additionalTools.length === 0) {
1028
- p8.cancel("Nie wybrano \u017Cadnych narz\u0119dzi.");
1224
+ if (p11.isCancel(additionalTools) || additionalTools.length === 0) {
1225
+ p11.cancel("Nie wybrano \u017Cadnych narz\u0119dzi.");
1029
1226
  process.exit(1);
1030
1227
  }
1031
1228
  toolsToInstall = additionalTools;
@@ -1048,7 +1245,10 @@ ${c2.cyan("npx @solvro/config")}`;
1048
1245
  await installGithubActions();
1049
1246
  }
1050
1247
  await packageJson7.clearInstall();
1051
- 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;
1052
1252
  printSuccess("\u2705 Konfiguracja zako\u0144czona pomy\u015Blnie!");
1053
1253
  }
1054
1254
  async function mainWrapper() {
@@ -1057,7 +1257,7 @@ async function mainWrapper() {
1057
1257
  } catch (error) {
1058
1258
  if (process.env.NODE_ENV === "development") {
1059
1259
  console.error(
1060
- c2.red("Unhandled error in main:"),
1260
+ c5.red("Unhandled error in main:"),
1061
1261
  error instanceof Error ? error.message : error
1062
1262
  );
1063
1263
  } else {
@@ -1066,7 +1266,7 @@ async function mainWrapper() {
1066
1266
  console.error(errorMessage);
1067
1267
  console.error(BUG_TRACKER_URL);
1068
1268
  } else {
1069
- p8.cancel(`${errorMessage} ${BUG_TRACKER_URL}`);
1269
+ p11.cancel(`${errorMessage} ${BUG_TRACKER_URL}`);
1070
1270
  }
1071
1271
  }
1072
1272
  process.exit(1);