@forsakringskassan/commitlint-config 2.0.5 → 3.0.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/install.js CHANGED
@@ -12,7 +12,13 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
12
  var __getOwnPropNames = Object.getOwnPropertyNames;
13
13
  var __getProtoOf = Object.getPrototypeOf;
14
14
  var __hasOwnProp = Object.prototype.hasOwnProperty;
15
- var __commonJS = (cb, mod) => function __require() {
15
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
16
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
17
+ }) : x)(function(x) {
18
+ if (typeof require !== "undefined") return require.apply(this, arguments);
19
+ throw Error('Dynamic require of "' + x + '" is not supported');
20
+ });
21
+ var __commonJS = (cb, mod) => function __require2() {
16
22
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
17
23
  };
18
24
  var __copyProps = (to, from, except, desc) => {
@@ -474,19 +480,353 @@ var require_is_ci = __commonJS({
474
480
  });
475
481
 
476
482
  // src/install.ts
477
- var import_is_ci = __toESM(require_is_ci(), 1);
478
- import fs from "node:fs";
479
- import path from "node:path";
483
+ import fs2 from "node:fs";
484
+ import path4 from "node:path";
480
485
  import { spawnSync } from "node:child_process";
486
+ import * as fsp from "fs/promises";
487
+
488
+ // node_modules/nano-spawn/source/context.js
489
+ import process2 from "node:process";
490
+ import { stripVTControlCharacters } from "node:util";
491
+ var getContext = (raw) => ({
492
+ start: process2.hrtime.bigint(),
493
+ command: raw.map((part) => getCommandPart(stripVTControlCharacters(part))).join(" "),
494
+ state: { stdout: "", stderr: "", output: "" }
495
+ });
496
+ var getCommandPart = (part) => /[^\w./-]/.test(part) ? `'${part.replaceAll("'", "'\\''")}'` : part;
497
+
498
+ // node_modules/nano-spawn/source/options.js
499
+ import path from "node:path";
500
+ import { fileURLToPath } from "node:url";
501
+ import process3 from "node:process";
502
+ var getOptions = ({
503
+ stdin,
504
+ stdout,
505
+ stderr,
506
+ stdio = [stdin, stdout, stderr],
507
+ env: envOption,
508
+ preferLocal,
509
+ cwd: cwdOption = ".",
510
+ ...options
511
+ }) => {
512
+ const cwd = cwdOption instanceof URL ? fileURLToPath(cwdOption) : path.resolve(cwdOption);
513
+ const env = envOption ? { ...process3.env, ...envOption } : void 0;
514
+ const input = stdio[0]?.string;
515
+ return {
516
+ ...options,
517
+ input,
518
+ stdio: input === void 0 ? stdio : ["pipe", ...stdio.slice(1)],
519
+ env: preferLocal ? addLocalPath(env ?? process3.env, cwd) : env,
520
+ cwd
521
+ };
522
+ };
523
+ var addLocalPath = ({ Path = "", PATH = Path, ...env }, cwd) => {
524
+ const pathParts = PATH.split(path.delimiter);
525
+ const localPaths = getLocalPaths([], path.resolve(cwd)).map((localPath) => path.join(localPath, "node_modules/.bin")).filter((localPath) => !pathParts.includes(localPath));
526
+ return { ...env, PATH: [...localPaths, PATH].filter(Boolean).join(path.delimiter) };
527
+ };
528
+ var getLocalPaths = (localPaths, localPath) => localPaths.at(-1) === localPath ? localPaths : getLocalPaths([...localPaths, localPath], path.resolve(localPath, ".."));
529
+
530
+ // node_modules/nano-spawn/source/spawn.js
531
+ import { spawn } from "node:child_process";
532
+ import { once as once2 } from "node:events";
533
+ import process6 from "node:process";
534
+
535
+ // node_modules/nano-spawn/source/windows.js
536
+ import fs from "node:fs/promises";
537
+ import path2 from "node:path";
538
+ import process4 from "node:process";
539
+ var applyForceShell = async (file, commandArguments, options) => await shouldForceShell(file, options) ? [escapeFile(file), commandArguments.map((argument) => escapeArgument(argument)), { ...options, shell: true }] : [file, commandArguments, options];
540
+ var shouldForceShell = async (file, { shell, cwd, env = process4.env }) => process4.platform === "win32" && !shell && !await isExe(file, cwd, env);
541
+ var isExe = (file, cwd, { Path = "", PATH = Path }) => (
542
+ // If the *.exe or *.com file extension was not omitted.
543
+ // Windows common file systems are case-insensitive.
544
+ exeExtensions.some((extension) => file.toLowerCase().endsWith(extension)) || mIsExe(file, cwd, PATH)
545
+ );
546
+ var EXE_MEMO = {};
547
+ var memoize = (function_) => (...arguments_) => (
548
+ // Use returned assignment to keep code small
549
+ EXE_MEMO[arguments_.join("\0")] ??= function_(...arguments_)
550
+ );
551
+ var access = memoize(fs.access);
552
+ var mIsExe = memoize(async (file, cwd, PATH) => {
553
+ const parts = PATH.split(path2.delimiter).filter(Boolean).map((part) => part.replace(/^"(.*)"$/, "$1"));
554
+ try {
555
+ await Promise.any(
556
+ [cwd, ...parts].flatMap(
557
+ (part) => exeExtensions.map((extension) => access(`${path2.resolve(part, file)}${extension}`))
558
+ )
559
+ );
560
+ } catch {
561
+ return false;
562
+ }
563
+ return true;
564
+ });
565
+ var exeExtensions = [".exe", ".com"];
566
+ var escapeArgument = (argument) => escapeFile(escapeFile(`"${argument.replaceAll(/(\\*)"/g, '$1$1\\"').replace(/(\\*)$/, "$1$1")}"`));
567
+ var escapeFile = (file) => file.replaceAll(/([()\][%!^"`<>&|;, *?])/g, "^$1");
568
+
569
+ // node_modules/nano-spawn/source/result.js
570
+ import { once, on } from "node:events";
571
+ import process5 from "node:process";
572
+ var getResult = async (nodeChildProcess, { input }, context) => {
573
+ const instance = await nodeChildProcess;
574
+ if (input !== void 0) {
575
+ instance.stdin.end(input);
576
+ }
577
+ const onClose = once(instance, "close");
578
+ try {
579
+ await Promise.race([
580
+ onClose,
581
+ ...instance.stdio.filter(Boolean).map((stream) => onStreamError(stream))
582
+ ]);
583
+ checkFailure(context, getErrorOutput(instance));
584
+ return getOutputs(context);
585
+ } catch (error) {
586
+ await Promise.allSettled([onClose]);
587
+ throw getResultError(error, instance, context);
588
+ }
589
+ };
590
+ var onStreamError = async (stream) => {
591
+ for await (const [error] of on(stream, "error")) {
592
+ if (!["ERR_STREAM_PREMATURE_CLOSE", "EPIPE"].includes(error?.code)) {
593
+ throw error;
594
+ }
595
+ }
596
+ };
597
+ var checkFailure = ({ command }, { exitCode, signalName }) => {
598
+ if (signalName !== void 0) {
599
+ throw new SubprocessError(`Command was terminated with ${signalName}: ${command}`);
600
+ }
601
+ if (exitCode !== void 0) {
602
+ throw new SubprocessError(`Command failed with exit code ${exitCode}: ${command}`);
603
+ }
604
+ };
605
+ var getResultError = (error, instance, context) => Object.assign(
606
+ getErrorInstance(error, context),
607
+ getErrorOutput(instance),
608
+ getOutputs(context)
609
+ );
610
+ var getErrorInstance = (error, { command }) => error instanceof SubprocessError ? error : new SubprocessError(`Command failed: ${command}`, { cause: error });
611
+ var SubprocessError = class extends Error {
612
+ name = "SubprocessError";
613
+ };
614
+ var getErrorOutput = ({ exitCode, signalCode }) => ({
615
+ // `exitCode` can be a negative number (`errno`) when the `error` event is emitted on the `instance`
616
+ ...exitCode < 1 ? {} : { exitCode },
617
+ ...signalCode === null ? {} : { signalName: signalCode }
618
+ });
619
+ var getOutputs = ({ state: { stdout, stderr, output }, command, start }) => ({
620
+ stdout: getOutput(stdout),
621
+ stderr: getOutput(stderr),
622
+ output: getOutput(output),
623
+ command,
624
+ durationMs: Number(process5.hrtime.bigint() - start) / 1e6
625
+ });
626
+ var getOutput = (output) => output.at(-1) === "\n" ? output.slice(0, output.at(-2) === "\r" ? -2 : -1) : output;
627
+
628
+ // node_modules/nano-spawn/source/spawn.js
629
+ var spawnSubprocess = async (file, commandArguments, options, context) => {
630
+ try {
631
+ if (["node", "node.exe"].includes(file.toLowerCase())) {
632
+ file = process6.execPath;
633
+ commandArguments = [...process6.execArgv.filter((flag) => !flag.startsWith("--inspect")), ...commandArguments];
634
+ }
635
+ [file, commandArguments, options] = await applyForceShell(file, commandArguments, options);
636
+ [file, commandArguments, options] = concatenateShell(file, commandArguments, options);
637
+ const instance = spawn(file, commandArguments, options);
638
+ bufferOutput(instance.stdout, context, "stdout");
639
+ bufferOutput(instance.stderr, context, "stderr");
640
+ instance.once("error", () => {
641
+ });
642
+ await once2(instance, "spawn");
643
+ return instance;
644
+ } catch (error) {
645
+ throw getResultError(error, {}, context);
646
+ }
647
+ };
648
+ var concatenateShell = (file, commandArguments, options) => options.shell && commandArguments.length > 0 ? [[file, ...commandArguments].join(" "), [], options] : [file, commandArguments, options];
649
+ var bufferOutput = (stream, { state }, streamName) => {
650
+ if (stream) {
651
+ stream.setEncoding("utf8");
652
+ if (!state.isIterating) {
653
+ state.isIterating = false;
654
+ stream.on("data", (chunk) => {
655
+ state[streamName] += chunk;
656
+ state.output += chunk;
657
+ });
658
+ }
659
+ }
660
+ };
661
+
662
+ // node_modules/nano-spawn/source/pipe.js
663
+ import { pipeline } from "node:stream/promises";
664
+ var handlePipe = async (subprocesses) => {
665
+ const [[from, to]] = await Promise.all([Promise.allSettled(subprocesses), pipeStreams(subprocesses)]);
666
+ if (to.reason) {
667
+ to.reason.pipedFrom = from.reason ?? from.value;
668
+ throw to.reason;
669
+ }
670
+ if (from.reason) {
671
+ throw from.reason;
672
+ }
673
+ return { ...to.value, pipedFrom: from.value };
674
+ };
675
+ var pipeStreams = async (subprocesses) => {
676
+ try {
677
+ const [{ stdout }, { stdin }] = await Promise.all(subprocesses.map(({ nodeChildProcess }) => nodeChildProcess));
678
+ if (stdin === null) {
679
+ throw new Error('The "stdin" option must be set on the first "spawn()" call in the pipeline.');
680
+ }
681
+ if (stdout === null) {
682
+ throw new Error('The "stdout" option must be set on the last "spawn()" call in the pipeline.');
683
+ }
684
+ pipeline(stdout, stdin).catch(() => {
685
+ });
686
+ } catch (error) {
687
+ await Promise.allSettled(subprocesses.map(({ nodeChildProcess }) => closeStdin(nodeChildProcess)));
688
+ throw error;
689
+ }
690
+ };
691
+ var closeStdin = async (nodeChildProcess) => {
692
+ const { stdin } = await nodeChildProcess;
693
+ stdin.end();
694
+ };
695
+
696
+ // node_modules/nano-spawn/source/iterable.js
697
+ import * as readline from "node:readline/promises";
698
+ var lineIterator = async function* (subprocess, { state }, streamName) {
699
+ if (state.isIterating === false) {
700
+ throw new Error(`The subprocess must be iterated right away, for example:
701
+ for await (const line of spawn(...)) { ... }`);
702
+ }
703
+ state.isIterating = true;
704
+ try {
705
+ const { [streamName]: stream } = await subprocess.nodeChildProcess;
706
+ if (!stream) {
707
+ return;
708
+ }
709
+ yield* readline.createInterface({ input: stream });
710
+ } finally {
711
+ await subprocess;
712
+ }
713
+ };
714
+ var combineAsyncIterators = async function* (...iterators) {
715
+ try {
716
+ let promises = [];
717
+ while (iterators.length > 0) {
718
+ promises = iterators.map((iterator2, index2) => promises[index2] ?? getNext(iterator2));
719
+ const [{ value, done }, index] = await Promise.race(promises.map((promise, index2) => Promise.all([promise, index2])));
720
+ const [iterator] = iterators.splice(index, 1);
721
+ promises.splice(index, 1);
722
+ if (!done) {
723
+ iterators.push(iterator);
724
+ yield value;
725
+ }
726
+ }
727
+ } finally {
728
+ await Promise.all(iterators.map((iterator) => iterator.return()));
729
+ }
730
+ };
731
+ var getNext = async (iterator) => {
732
+ try {
733
+ return await iterator.next();
734
+ } catch (error) {
735
+ await iterator.throw(error);
736
+ }
737
+ };
738
+
739
+ // node_modules/nano-spawn/source/index.js
740
+ function spawn2(file, second, third, previous) {
741
+ const [commandArguments = [], options = {}] = Array.isArray(second) ? [second, third] : [[], second];
742
+ const context = getContext([file, ...commandArguments]);
743
+ const spawnOptions = getOptions(options);
744
+ const nodeChildProcess = spawnSubprocess(file, commandArguments, spawnOptions, context);
745
+ let subprocess = getResult(nodeChildProcess, spawnOptions, context);
746
+ Object.assign(subprocess, { nodeChildProcess });
747
+ subprocess = previous ? handlePipe([previous, subprocess]) : subprocess;
748
+ const stdout = lineIterator(subprocess, context, "stdout");
749
+ const stderr = lineIterator(subprocess, context, "stderr");
750
+ return Object.assign(subprocess, {
751
+ nodeChildProcess,
752
+ stdout,
753
+ stderr,
754
+ [Symbol.asyncIterator]: () => combineAsyncIterators(stdout, stderr),
755
+ pipe: (file2, second2, third2) => spawn2(file2, second2, third2, subprocess)
756
+ });
757
+ }
758
+
759
+ // src/install.ts
760
+ var import_is_ci = __toESM(require_is_ci(), 1);
761
+
762
+ // src/verifyPackage.ts
763
+ import path3 from "node:path";
764
+ var nonAllowedPackages = ["husky", "simple-git-hooks", "lint-staged"];
765
+ function invalidInstalledPackages(packageJson) {
766
+ const dependencies = [
767
+ ...Object.keys(packageJson.dependencies),
768
+ ...Object.keys(packageJson.devDependencies)
769
+ ];
770
+ for (const item of nonAllowedPackages) {
771
+ if (dependencies.includes(item)) {
772
+ console.error(
773
+ `
774
+ @forsakringskassan/commitlint-config
775
+ You need to remove package ${item} before installing this package.
776
+
777
+ Unallowed dependencies:
778
+ ${nonAllowedPackages.join(" ")}
779
+
780
+ Command to uninstall:
781
+ npm uninstall ${nonAllowedPackages.join(" ")}
782
+ `
783
+ );
784
+ return true;
785
+ }
786
+ }
787
+ return false;
788
+ }
789
+ function existingSimpleGitConfig(packageJson) {
790
+ if ("simple-git-hooks" in packageJson) {
791
+ console.error(
792
+ `
793
+ @forsakringskassan/commitlint-config
794
+ You need to remove config in package.json for simple-git-hooks.
795
+
796
+ npm pkg delete "simple-git-hooks"
797
+ `
798
+ );
799
+ return true;
800
+ }
801
+ return false;
802
+ }
803
+ async function existingHuskyConfig(cwd, fileSystem) {
804
+ try {
805
+ await fileSystem.stat(path3.join(cwd, ".husky"));
806
+ console.error(
807
+ `
808
+ @forsakringskassan/commitlint-config
809
+ You need to remove husky folder before installing this package.
810
+
811
+ git rm -rf .husky
812
+ `
813
+ );
814
+ return true;
815
+ } catch {
816
+ }
817
+ return false;
818
+ }
819
+
820
+ // src/install.ts
481
821
  function findGit(cwd) {
482
822
  let current = cwd;
483
823
  while (true) {
484
- const search = path.join(current, ".git");
485
- if (fs.existsSync(search)) {
486
- return path.resolve(current);
824
+ const search = path4.join(current, ".git");
825
+ if (fs2.existsSync(search)) {
826
+ return path4.resolve(current);
487
827
  }
488
828
  const child = current;
489
- current = path.dirname(current);
829
+ current = path4.dirname(current);
490
830
  if (current === child) {
491
831
  break;
492
832
  }
@@ -499,12 +839,31 @@ function configureCommitTemplate() {
499
839
  console.warn("Failed to locate git directory, skipping gitmessage");
500
840
  return;
501
841
  }
502
- const relPath = path.relative(gitDir, path.join(__dirname, ".."));
503
- const gitmessage = path.join(relPath, "gitmessage");
842
+ const relPath = path4.relative(gitDir, path4.join(__dirname, ".."));
843
+ const gitmessage = path4.join(relPath, "gitmessage");
504
844
  const args = ["config", "commit.template", gitmessage];
505
845
  console.info(`git ${args.join(" ")}`);
506
846
  spawnSync("git", args);
507
847
  }
508
- if (!import_is_ci.default) {
848
+ if (!import_is_ci.default && process.env.FK_COMMITLINT_SKIP !== "1") {
509
849
  configureCommitTemplate();
850
+ const originCwd = process.env["INIT_CWD"] || "";
851
+ const packageJson = JSON.parse(
852
+ await fsp.readFile(path4.join(originCwd, "package.json"), {
853
+ encoding: "utf-8"
854
+ })
855
+ );
856
+ if (invalidInstalledPackages(packageJson) || existingSimpleGitConfig(packageJson) || await existingHuskyConfig(originCwd, fsp)) {
857
+ process.exit(1);
858
+ }
859
+ const result = await spawn2(
860
+ "npm",
861
+ [
862
+ "exec",
863
+ "simple-git-hooks",
864
+ __require.resolve("@forsakringskassan/commitlint-config/hooks.js")
865
+ ],
866
+ { cwd: process.env["INIT_CWD"] }
867
+ );
868
+ console.log(result.output);
510
869
  }
package/hooks.js ADDED
@@ -0,0 +1,8 @@
1
+ import { fileURLToPath } from "node:url";
2
+
3
+ const lintConfigPath = fileURLToPath.meta.resolve("./lint-staged.js");
4
+
5
+ export default {
6
+ "pre-commit": `npm exec lint-staged -- --config "${lintConfigPath}" "$@"`,
7
+ "commit-msg": 'npm exec commitlint -- --edit "$1"',
8
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forsakringskassan/commitlint-config",
3
- "version": "2.0.5",
3
+ "version": "3.0.0",
4
4
  "description": "FK commitlint shareable config",
5
5
  "keywords": [
6
6
  "commitlint"
@@ -18,7 +18,8 @@
18
18
  ".": "./dist/config/default.js",
19
19
  "./default": "./dist/config/default.js",
20
20
  "./no-jira": "./dist/config/no-jira.js",
21
- "./lint-staged": "./lint-staged.js"
21
+ "./lint-staged": "./lint-staged.js",
22
+ "./hooks.js": "./hooks.js"
22
23
  },
23
24
  "main": "dist/config/default.js",
24
25
  "bin": {
@@ -30,7 +31,8 @@
30
31
  "bin",
31
32
  "dist",
32
33
  "gitmessage",
33
- "lint-staged.js"
34
+ "lint-staged.js",
35
+ "hooks.js"
34
36
  ],
35
37
  "scripts": {
36
38
  "prebuild": "rimraf dist",
@@ -56,6 +58,7 @@
56
58
  "ts-node": "^10"
57
59
  },
58
60
  "engines": {
59
- "node": ">= 20.18"
61
+ "node": ">= 22.12.0",
62
+ "npm": ">= 10.0.0"
60
63
  }
61
64
  }