diff --git a/README.md b/README.md
index 6964ab31..9c9e9289 100644
--- a/README.md
+++ b/README.md
@@ -25,6 +25,7 @@ Check the README for each package within the `packages` directory for specific u
| Package | Version | Description |
|---------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------|
| [multi-semantic-release](packages/multi-semantic-release/README.md) | ![npm](https://img.shields.io/npm/v/@anolilab/multi-semantic-release?style=flat-square&labelColor=292a44&color=663399&label=v) | A hacky semantic-release for monorepos based on qiwi/multi-semantic-release | | |
+| [semantic-release-pnpm](packages/semantic-release-pnpm/README.md) | ![npm](https://img.shields.io/npm/v/@anolilab/semantic-release-pnpm?style=flat-square&labelColor=292a44&color=663399&label=v) | Semantic-release plugin to publish a npm package with pnpm | | |
## How We Version
diff --git a/packages/rc/.eslintignore b/packages/rc/.eslintignore
new file mode 100644
index 00000000..e3f5dd77
--- /dev/null
+++ b/packages/rc/.eslintignore
@@ -0,0 +1,15 @@
+dist
+node_modules
+coverage
+
+__fixtures__
+__docs__
+
+vitest.config.ts
+.prettierrc.cjs
+tsup.config.ts
+.secretlintrc.cjs
+tsconfig.eslint.json
+
+README.md
+
diff --git a/packages/rc/.eslintrc.cjs b/packages/rc/.eslintrc.cjs
new file mode 100644
index 00000000..9c2fe8fe
--- /dev/null
+++ b/packages/rc/.eslintrc.cjs
@@ -0,0 +1,90 @@
+/** @ts-check */
+// eslint-disable-next-line import/no-commonjs,import/no-unused-modules
+const { defineConfig } = require("@anolilab/eslint-config/define-config");
+// eslint-disable-next-line import/no-commonjs
+const globals = require("@anolilab/eslint-config/globals");
+
+///
+///
+///
+///
+///
+
+/** @type {import('eslint').Linter.Config} */
+module.exports = defineConfig({
+ env: {
+ // Your environments (which contains several predefined global variables)
+ // Most environments are loaded automatically if our rules are added
+ },
+ extends: ["@anolilab/eslint-config", "@anolilab/eslint-config/typescript-type-checking"],
+ globals: {
+ ...globals.es2021,
+ // Your global variables (setting to false means it's not allowed to be reassigned)
+ // myGlobal: false
+ },
+ ignorePatterns: ["!**/*"],
+ overrides: [
+ {
+ files: ["*.ts", "*.tsx", "*.mts", "*.cts", "*.js", "*.jsx"],
+ // Set parserOptions.project for the project to allow TypeScript to create the type-checker behind the scenes when we run linting
+ parserOptions: {},
+ rules: {},
+ },
+ {
+ files: ["*.ts", "*.tsx", "*.mts", "*.cts"],
+ // Set parserOptions.project for the project to allow TypeScript to create the type-checker behind the scenes when we run linting
+ parserOptions: {},
+ rules: {
+ "@typescript-eslint/no-unsafe-argument": "off",
+ "@typescript-eslint/no-unsafe-assignment": "off",
+ "@typescript-eslint/no-unsafe-call": "off",
+ "@typescript-eslint/no-unsafe-member-access": "off",
+ "@typescript-eslint/no-unsafe-return": "off",
+ "prefer-template": "off",
+ },
+ },
+ {
+ files: ["*.js", "*.jsx"],
+ rules: {},
+ },
+ {
+ files: ["*.mdx"],
+ rules: {
+ "jsx-a11y/anchor-has-content": "off",
+ // @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/issues/917
+ "jsx-a11y/heading-has-content": "off",
+ },
+ },
+ {
+ files: ["src/index.ts"],
+ rules: {
+ "import/no-unused-modules": "off",
+ },
+ },
+ {
+ files: ["__docs__/**"],
+ rules: {
+ "import/no-unresolved": "off",
+ "import/no-unused-modules": "off",
+ "no-console": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "unicorn/prefer-top-level-await": "off",
+ },
+ },
+ {
+ files: ["__tests__/**"],
+ rules: {
+ "import/no-unused-modules": "off",
+ },
+ },
+ ],
+ parserOptions: {
+ ecmaVersion: 2021,
+ project: "./tsconfig.eslint.json",
+ sourceType: "module",
+ },
+ // Report unused `eslint-disable` comments.
+ reportUnusedDisableDirectives: true,
+ root: true,
+});
diff --git a/packages/rc/.npmignore b/packages/rc/.npmignore
new file mode 100644
index 00000000..ff4abfc4
--- /dev/null
+++ b/packages/rc/.npmignore
@@ -0,0 +1,9 @@
+package-lock.json
+
+src
+__tests__
+__stories__
+__fixtures__
+.rpt2_cache
+fixup.sh
+.releaserc.json
diff --git a/packages/rc/.prettierignore b/packages/rc/.prettierignore
new file mode 100644
index 00000000..ebf52909
--- /dev/null
+++ b/packages/rc/.prettierignore
@@ -0,0 +1,9 @@
+.gitkeep
+.env*
+*.ico
+*.lock
+dist
+CHANGELOG.md
+coverage
+node_modules
+.eslintcache
diff --git a/packages/rc/.prettierrc.cjs b/packages/rc/.prettierrc.cjs
new file mode 100644
index 00000000..32f893c0
--- /dev/null
+++ b/packages/rc/.prettierrc.cjs
@@ -0,0 +1,5 @@
+const config = require("@anolilab/prettier-config");
+
+module.exports = {
+ ...config,
+};
diff --git a/packages/rc/.releaserc.json b/packages/rc/.releaserc.json
new file mode 100644
index 00000000..dbc778df
--- /dev/null
+++ b/packages/rc/.releaserc.json
@@ -0,0 +1,3 @@
+{
+ "extends": "@anolilab/semantic-release-preset/npm"
+}
diff --git a/packages/rc/.secretlintignore b/packages/rc/.secretlintignore
new file mode 100644
index 00000000..8d4c427f
--- /dev/null
+++ b/packages/rc/.secretlintignore
@@ -0,0 +1,3 @@
+.pnpm-store
+packages/**/node_modules
+node_modules
diff --git a/packages/rc/.secretlintrc.cjs b/packages/rc/.secretlintrc.cjs
new file mode 100644
index 00000000..418ad9ce
--- /dev/null
+++ b/packages/rc/.secretlintrc.cjs
@@ -0,0 +1,7 @@
+module.exports = {
+ rules: [
+ {
+ id: "@secretlint/secretlint-rule-preset-recommend",
+ },
+ ],
+};
diff --git a/packages/rc/CHANGELOG.md b/packages/rc/CHANGELOG.md
new file mode 100644
index 00000000..e69de29b
diff --git a/packages/rc/LICENSE.md b/packages/rc/LICENSE.md
new file mode 100644
index 00000000..a6b1fdfc
--- /dev/null
+++ b/packages/rc/LICENSE.md
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2024 anolilab
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/packages/rc/README.md b/packages/rc/README.md
new file mode 100644
index 00000000..c251e2e1
--- /dev/null
+++ b/packages/rc/README.md
@@ -0,0 +1,112 @@
+
+
anolilab rc
+
+ This module provides a utility function to load rc configuration settings from various sources, including environment variables, default values, and configuration files located in multiple standard directories. It merges these settings into a single configuration object.
+
+
+
+
+
+
+
+[![typescript-image]][typescript-url] [![npm-image]][npm-url] [![license-image]][license-url]
+
+
+
+---
+
+
+
+
+ Daniel Bannert's open source work is supported by the community on GitHub Sponsors
+
+
+
+
+---
+
+## Install
+
+```sh
+npm install @anolilab/rc
+```
+
+```sh
+yarn add @anolilab/rc
+```
+
+```sh
+pnpm add @anolilab/rc
+```
+
+## Usage
+
+The main function provided by this module is rc. It allows you to load configuration settings for your application from different sources.
+
+```ts
+import { rc } from "@anolilab/rc";
+
+const { config, files } = rc("npm");
+
+// returns a merged config object with all found npmrc files and a files list what files where found.
+```
+
+### Api
+
+- name (string): The application name. This is used to locate configuration files and environment variables.
+- options (object, optional): An object with the following properties:
+ - config (string, optional): Path to a specific configuration file.
+ - cwd (string, optional): The current working directory to start searching for configuration files. Defaults to process.cwd().
+ - defaults (object, optional): Default configuration values.
+ - home (string, optional): The home directory to use. Defaults to os.homedir().
+ - stopAt (string, optional): Directory to stop searching for configuration files.
+
+## Standards
+
+Given your application name (appname), rc will look in all the obvious places for configuration.
+
+- The defaults object you passed in
+- `/etc/${appname}/config`
+- `/etc/${appname}rc`
+- `$HOME/.config/${appname}/config`
+- `$HOME/.config/${appname}`
+- `$HOME/.${appname}/config`
+- `$HOME/.${appname}rc`
+- a local `.${appname}/config` and `.${appname}rc` and all found looking in `../../../ ../../ ../ ./` etc.
+- if you passed environment variable `${appname}_config` then from that file
+- if you passed options.config variable, then from that file
+- environment variables prefixed with `${appname}_`
+ or use "\_\_" to indicate nested properties
_(e.g. `appname_foo__bar__baz` => `foo.bar.baz`)_
+
+All configuration sources that were found will be flattened into one object, in this exact order.
+
+## Related
+
+- [rc](https://github.com/dominictarr/rc) - The non-configurable configuration loader for lazy people.
+
+## Supported Node.js Versions
+
+Libraries in this ecosystem make the best effort to track [Node.js’ release schedule](https://github.com/nodejs/release#release-schedule).
+Here’s [a post on why we think this is important](https://medium.com/the-node-js-collection/maintainers-should-consider-following-node-js-release-schedule-ab08ed4de71a).
+
+## Contributing
+
+If you would like to help take a look at the [list of issues](https://github.com/anolilab/semantic-release/issues) and check our [Contributing](.github/CONTRIBUTING.md) guidelines.
+
+> **Note:** please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.
+
+## Credits
+
+- [Daniel Bannert](https://github.com/prisis)
+- [All Contributors](https://github.com/anolilab/semantic-release/graphs/contributors)
+
+## License
+
+The anolilab rc is open-sourced software licensed under the [MIT][license-url]
+
+[typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript
+[typescript-url]: "typescript"
+[license-image]: https://img.shields.io/npm/l/@anolilab/rc?color=blueviolet&style=for-the-badge
+[license-url]: LICENSE.md "license"
+[npm-image]: https://img.shields.io/npm/v/@anolilab/rc/latest.svg?style=for-the-badge&logo=npm
+[npm-url]: https://www.npmjs.com/package/@anolilab/rc/v/latest "npm"
diff --git a/packages/rc/__tests__/rc-unmocked.test.ts b/packages/rc/__tests__/rc-unmocked.test.ts
new file mode 100644
index 00000000..b6e9a282
--- /dev/null
+++ b/packages/rc/__tests__/rc-unmocked.test.ts
@@ -0,0 +1,104 @@
+import { rm } from "node:fs/promises";
+import { env } from "node:process";
+
+import { writeJsonSync } from "@visulima/fs";
+import { join } from "@visulima/path";
+import { temporaryDirectory } from "tempy";
+import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
+
+import { rc } from "../src";
+
+const mocks = vi.hoisted(() => {
+ return { mockedCwd: vi.fn(), mockedFindUpSync: vi.fn(), mockedHomeDir: vi.fn(), mockedIsAccessibleSync: vi.fn(), mockedReadFileSync: vi.fn() };
+});
+
+vi.mock("node:os", () => {
+ return {
+ homedir: mocks.mockedHomeDir,
+ };
+});
+
+vi.mock("node:process", async () => {
+ const actual = await vi.importActual("node:process");
+
+ return {
+ ...actual,
+ cwd: mocks.mockedCwd,
+ };
+});
+
+describe("rc-unmocked", () => {
+ let cwdPath: string;
+ let homePath: string;
+
+ const npmEnvironment: Record = {};
+
+ beforeEach(async () => {
+ cwdPath = temporaryDirectory();
+ homePath = temporaryDirectory();
+
+ mocks.mockedCwd.mockReturnValue(cwdPath);
+ mocks.mockedHomeDir.mockReturnValue(homePath);
+
+ // eslint-disable-next-line no-loops/no-loops,no-restricted-syntax
+ for (const key in env) {
+ if (key.startsWith("npm_")) {
+ // eslint-disable-next-line security/detect-object-injection
+ npmEnvironment[key as keyof typeof env] = env[key];
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete,security/detect-object-injection
+ delete env[key];
+ }
+ }
+ });
+
+ afterEach(async () => {
+ // eslint-disable-next-line no-loops/no-loops,no-restricted-syntax,guard-for-in
+ for (const key in npmEnvironment) {
+ // eslint-disable-next-line security/detect-object-injection
+ env[key] = npmEnvironment[key];
+ }
+
+ await rm(cwdPath, { recursive: true });
+ await rm(homePath, { recursive: true });
+ });
+
+ it("should find configs in different folders", () => {
+ expect.assertions(1);
+
+ const files = [join("grandparent", "parent", "cwd", ".bemrc"), join("grandparent", "parent", ".bemrc"), join("grandparent", ".bemrc")];
+
+ files.forEach((file, index) => {
+ writeJsonSync(join(cwdPath, file), { test: index });
+ });
+
+ mocks.mockedCwd.mockReturnValue(join(cwdPath, "grandparent", "parent", "cwd"));
+
+ expect(rc("bem")).toStrictEqual({
+ config: {
+ test: 0,
+ },
+ files: files.map((file) => join(cwdPath, file)).reverse(),
+ });
+ });
+
+ it("should find configs in custom cwd", () => {
+ expect.assertions(1);
+
+ const files = [join("grandparent", "parent", "cwd", ".bemrc"), join("grandparent", "parent", ".bemrc"), join("grandparent", ".bemrc")];
+
+ files.forEach((file, index) => {
+ writeJsonSync(join(cwdPath, file), { test: index });
+ });
+
+ expect(
+ rc("bem", {
+ cwd: join(cwdPath, "grandparent", "parent", "cwd"),
+ }),
+ ).toStrictEqual({
+ config: {
+ test: 0,
+ },
+ files: files.map((file) => join(cwdPath, file)).reverse(),
+ });
+ });
+});
diff --git a/packages/rc/__tests__/rc.test.ts b/packages/rc/__tests__/rc.test.ts
new file mode 100644
index 00000000..9659effc
--- /dev/null
+++ b/packages/rc/__tests__/rc.test.ts
@@ -0,0 +1,393 @@
+import { rm } from "node:fs/promises";
+import { env } from "node:process";
+
+import { join } from "@visulima/path";
+import { temporaryDirectory } from "tempy";
+import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
+
+import { rc } from "../src";
+
+// Adds extention to the last item of an array representing fs path
+const addExtensions = (sources: string[][]) =>
+ // eslint-disable-next-line unicorn/no-array-reduce
+ sources.reduce((accumulator, pathArray) => {
+ ["", ".json"].forEach((extension) => {
+ const current = [pathArray].flat();
+ current[current.length - 1] += extension;
+ accumulator.push(current);
+ });
+
+ return accumulator;
+ }, []);
+
+const mocks = vi.hoisted(() => {
+ return { mockedCwd: vi.fn(), mockedHomeDir: vi.fn(), mockedIsAccessibleSync: vi.fn(), mockedReadFileSync: vi.fn() };
+});
+
+vi.mock("@visulima/fs", async () => {
+ const actual = await vi.importActual("@visulima/fs");
+
+ return {
+ ...actual,
+ isAccessibleSync: mocks.mockedIsAccessibleSync,
+ readFileSync: mocks.mockedReadFileSync,
+ };
+});
+
+vi.mock("node:os", () => {
+ return {
+ homedir: mocks.mockedHomeDir,
+ };
+});
+
+vi.mock("node:process", async () => {
+ const actual = await vi.importActual("node:process");
+
+ return {
+ ...actual,
+ cwd: mocks.mockedCwd,
+ };
+});
+
+describe("rc", () => {
+ let cwdPath: string;
+ let homePath: string;
+ const npmEnvironment: Record = {};
+
+ beforeEach(async () => {
+ cwdPath = temporaryDirectory();
+ homePath = temporaryDirectory();
+
+ mocks.mockedCwd.mockReturnValue(cwdPath);
+ mocks.mockedHomeDir.mockReturnValue(homePath);
+
+ // eslint-disable-next-line no-loops/no-loops,no-restricted-syntax
+ for (const key in env) {
+ if (key.startsWith("npm_")) {
+ // eslint-disable-next-line security/detect-object-injection
+ npmEnvironment[key as keyof typeof env] = env[key];
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete,security/detect-object-injection
+ delete env[key];
+ }
+ }
+ });
+
+ afterEach(async () => {
+ // eslint-disable-next-line no-loops/no-loops,no-restricted-syntax,guard-for-in
+ for (const key in npmEnvironment) {
+ // eslint-disable-next-line security/detect-object-injection
+ env[key] = npmEnvironment[key];
+ }
+
+ await rm(cwdPath, { recursive: true });
+ await rm(homePath, { recursive: true });
+ });
+
+ it("should return config defaults", () => {
+ expect.assertions(1);
+
+ mocks.mockedIsAccessibleSync.mockReturnValue(false);
+
+ expect(rc("npm", { defaults: { test: 1 } })).toStrictEqual({
+ config: {
+ test: 1,
+ },
+ files: [],
+ });
+ });
+
+ it("should find configs in home dir", () => {
+ expect.assertions(1);
+
+ const sources = addExtensions([
+ [".config", "bem", "config"], // ~/.config/bem/config
+ [".config", "bem"], // ~/.config/bem
+ [".bem", "config"], // ~/.bem/config
+ [".bemrc"], // ~/.bemrc
+ ]);
+
+ sources.forEach((pathToConfig: string[], index: number) => {
+ mocks.mockedIsAccessibleSync.mockImplementation((file) => file === join(homePath, ...pathToConfig));
+ mocks.mockedReadFileSync.mockImplementation((file) => {
+ if (file === join(homePath, ...pathToConfig)) {
+ return JSON.stringify({ test: index });
+ }
+
+ return "";
+ });
+ });
+
+ expect(rc("bem")).toStrictEqual({
+ config: {
+ test: 7,
+ },
+ files: [join(homePath, ".bemrc.json")],
+ });
+ });
+
+ it("should find config by ENV", () => {
+ expect.assertions(1);
+
+ const filePath = "/test/.bemrc";
+
+ mocks.mockedIsAccessibleSync.mockImplementation((file) => file === filePath);
+ mocks.mockedReadFileSync.mockImplementation((file) => {
+ if (file === filePath) {
+ return JSON.stringify({ test: 1 });
+ }
+
+ return "";
+ });
+
+ env.bem_config = filePath;
+
+ expect(rc("bem")).toStrictEqual({
+ config: {
+ test: 1,
+ },
+ files: ["/test/.bemrc"],
+ });
+
+ delete env.bem_config;
+ });
+
+ it("should use config field passed via ENV", () => {
+ expect.assertions(1);
+
+ env.bem_test = "1";
+
+ mocks.mockedIsAccessibleSync.mockReturnValue(false);
+
+ expect(rc("bem")).toStrictEqual({ config: { test: "1" }, files: [] });
+
+ delete env.bem_test;
+ });
+
+ it("should find config by ENV with different name", () => {
+ expect.assertions(1);
+
+ const name = "ololo";
+
+ const filePath = "/test/.npmrc";
+
+ mocks.mockedIsAccessibleSync.mockImplementation((file) => file === filePath);
+ mocks.mockedReadFileSync.mockImplementation((file) => {
+ if (file === filePath) {
+ return JSON.stringify({ test: 2 });
+ }
+
+ return "";
+ });
+
+ env[name + "_test"] = "1";
+ env[name + "_something__subtest"] = "1";
+
+ expect(rc(name)).toStrictEqual({
+ config: {
+ something: {
+ subtest: "1",
+ },
+ test: "1",
+ },
+ files: [],
+ });
+
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
+ delete env[name + "_test"];
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
+ delete env[name + "_something__subtest"];
+ });
+
+ it("should find config in current folder", () => {
+ expect.assertions(1);
+
+ const filePath = ".bemrc";
+
+ mocks.mockedIsAccessibleSync.mockImplementation((file) => file === join(cwdPath, filePath));
+ mocks.mockedReadFileSync.mockImplementation((file) => {
+ if (file === join(cwdPath, filePath)) {
+ return JSON.stringify({ test: 1 });
+ }
+
+ return "";
+ });
+
+ expect(rc("bem")).toStrictEqual({
+ config: {
+ test: 1,
+ },
+ files: [join(cwdPath, filePath)],
+ });
+ });
+
+ it("should find configs with different exts in current folder", () => {
+ expect.assertions(1);
+
+ const files = [".bem/config", ".bem/config.json", ".bemrc", ".bemrc.json"];
+
+ mocks.mockedIsAccessibleSync.mockImplementation((file) => {
+ // eslint-disable-next-line no-loops/no-loops,no-restricted-syntax
+ for (const path of files) {
+ if (file === join(cwdPath, path)) {
+ return true;
+ }
+ }
+
+ return false;
+ });
+ mocks.mockedReadFileSync.mockImplementation((file) =>
+ files
+ .map((path, index) => {
+ if (file === join(cwdPath, path)) {
+ return JSON.stringify({ test: index });
+ }
+
+ return undefined;
+ })
+ .filter(Boolean)
+ .join(""),
+ );
+
+ expect(rc("bem")).toStrictEqual({
+ config: { test: 1 },
+ files: [join(cwdPath, ".bemrc"), join(cwdPath, ".bemrc.json"), join(cwdPath, ".bem/config"), join(cwdPath, ".bem/config.json")],
+ });
+ });
+
+ it("should find config with custom name in current folder", () => {
+ expect.assertions(1);
+
+ const filePath = ".ololorc";
+
+ mocks.mockedIsAccessibleSync.mockImplementation((file) => file === join(cwdPath, filePath));
+ mocks.mockedReadFileSync.mockImplementation((file) => {
+ if (file === join(cwdPath, filePath)) {
+ return JSON.stringify({ test: 1 });
+ }
+
+ return "";
+ });
+
+ expect(rc("ololo")).toStrictEqual({
+ config: {
+ test: 1,
+ },
+ files: [join(cwdPath, filePath)],
+ });
+ });
+
+ it("should use .bemrc from /", () => {
+ expect.assertions(1);
+
+ const filePath = ".bemrc";
+
+ mocks.mockedIsAccessibleSync.mockImplementation((file) => file === join("/", filePath));
+ mocks.mockedReadFileSync.mockImplementation(() => JSON.stringify({ test: "root" }));
+
+ expect(rc("bem")).toStrictEqual({ config: { test: "root" }, files: ["/.bemrc"] });
+ });
+
+ it("should filter same configs in proper order", () => {
+ expect.assertions(1);
+
+ const filePath = ".bemrc";
+
+ mocks.mockedIsAccessibleSync.mockImplementation((file) => file === join("/", filePath) || file === join(homePath, filePath));
+ mocks.mockedReadFileSync.mockImplementation((file) => {
+ if (file === join("/", filePath)) {
+ return JSON.stringify({ test: "root" });
+ }
+
+ if (file === join(homePath, filePath)) {
+ return JSON.stringify({ test: 1 });
+ }
+
+ return "";
+ });
+
+ expect(rc("bem")).toStrictEqual({
+ config: {
+ test: "root",
+ },
+ files: [join(homePath, filePath), "/.bemrc"],
+ });
+ });
+
+ it("should find different types of configs", () => {
+ expect.assertions(1);
+
+ const files = {
+ "1": join(cwdPath, "grandparent", "parent", "cwd", ".bemrc"),
+ "2": join(cwdPath, "grandparent", "parent", ".bemrc"),
+ "3": join(cwdPath, "grandparent", ".bemrc"),
+ config: "/config/testfile",
+ env_config: "/env/config/.bemrc",
+ etc: "/etc/bemrc",
+ home: join(homePath, ".bemrc"),
+ root: "/.bemrc",
+ };
+
+ mocks.mockedCwd.mockReturnValue(join(cwdPath, "grandparent", "parent", "cwd"));
+ mocks.mockedIsAccessibleSync.mockImplementation((file) => {
+ // eslint-disable-next-line no-loops/no-loops,no-restricted-syntax
+ for (const path of Object.values(files)) {
+ if (file === path) {
+ return true;
+ }
+ }
+
+ return false;
+ });
+ mocks.mockedReadFileSync.mockImplementation((file) =>
+ Object.entries(files)
+ .map(([value, path]) => {
+ if (file === path) {
+ return JSON.stringify({ last: value });
+ }
+
+ return undefined;
+ })
+ .filter(Boolean)
+ .join(""),
+ );
+
+ env.bem_test = "env";
+ env.bem_config = "/env/config/.bemrc";
+
+ /**
+ * 1 The defaults object you passed in
+ * 2 `/etc/${appname}/config`
+ * 3 `/etc/${appname}rc`
+ * 4 `$HOME/.config/${appname}/config`
+ * 5 `$HOME/.config/${appname}`
+ * 6 `$HOME/.${appname}/config`
+ * 7 `$HOME/.${appname}rc`
+ * 8 a local `.${appname}/config` and `.${appname}rc` and all found looking in `./ ../ ../../ ../../../` etc.
+ * 9 if you passed environment variable `${appname}_config` then from that file
+ * 10 if you passed options.config variable, then from that file
+ * 11 environment variables prefixed with `${appname}_`
+ * or use "\_\_" to indicate nested properties
_(e.g. `appname_foo__bar__baz` => `foo.bar.baz`)_
+ */
+ expect(rc("bem", { config: "/config/testfile", defaults: { default: "default" } })).toStrictEqual({
+ config: {
+ default: "default",
+ last: "config",
+ test: "env",
+ },
+ files: [
+ // defaults
+ join("/", "etc", "bemrc"), // home
+ join(homePath, ".bemrc"), // home
+ join("/", ".bemrc"), // root or 1
+ join(cwdPath, "grandparent", ".bemrc"), // 2
+ join(cwdPath, "grandparent", "parent", ".bemrc"), // 3
+ join(cwdPath, "grandparent", "parent", "cwd", ".bemrc"), // 4
+ join("/", "env", "config", ".bemrc"), // env
+ "/config/testfile", // config
+ ],
+ });
+
+ delete env.bem_test;
+ delete env.bem_config;
+ });
+});
diff --git a/packages/rc/__tests__/utils/is-json.test.ts b/packages/rc/__tests__/utils/is-json.test.ts
new file mode 100644
index 00000000..def16b3e
--- /dev/null
+++ b/packages/rc/__tests__/utils/is-json.test.ts
@@ -0,0 +1,21 @@
+import { describe, expect, it } from "vitest";
+
+import isJson from "../../src/utils/is-json";
+
+describe("isJson", () => {
+ it.each([5, "5", "true", "null", "{}", '{"foo": "bar"}', "[1, 2, 3]", '{"foo": "bar", "baz": "qux"}'])("should return true for valid JSON", (value) => {
+ expect.assertions(1);
+
+ expect(isJson(value)).toBeTruthy();
+ });
+
+ // eslint-disable-next-line no-void
+ it.each(["NaN", "[", "{", "]", "}", "[{", "]}", "{[", "}]", void 0, Number.NaN, function noop() {}, [], {}, '{a":5}'])(
+ "should return false for invalid JSON %s",
+ (value) => {
+ expect.assertions(1);
+
+ expect(isJson(value)).toBeFalsy();
+ },
+ );
+});
diff --git a/packages/rc/package.json b/packages/rc/package.json
new file mode 100644
index 00000000..f55c5c3f
--- /dev/null
+++ b/packages/rc/package.json
@@ -0,0 +1,129 @@
+{
+ "name": "@anolilab/rc",
+ "version": "0.0.0",
+ "description": "The runtime configuration loader.",
+ "keywords": [
+ "anolilab",
+ "rc"
+ ],
+ "homepage": "https://github.com/anolilab/semantic-release/tree/main/packages/rc",
+ "bugs": {
+ "url": "https://github.com/anolilab/semantic-release/issues"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/anolilab/semantic-release.git",
+ "directory": "packages/rc"
+ },
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/prisis"
+ },
+ {
+ "type": "consulting",
+ "url": "https://anolilab.com/support"
+ }
+ ],
+ "license": "MIT",
+ "author": {
+ "name": "Daniel Bannert",
+ "email": "d.bannert@anolilab.de"
+ },
+ "sideEffects": false,
+ "type": "module",
+ "exports": {
+ ".": {
+ "require": {
+ "types": "./dist/index.d.cts",
+ "default": "./dist/index.cjs"
+ },
+ "import": {
+ "types": "./dist/index.d.ts",
+ "default": "./dist/index.js"
+ }
+ },
+ "./package.json": "./package.json"
+ },
+ "main": "dist/index.cjs",
+ "module": "dist/index.js",
+ "source": "src/index.ts",
+ "browser": "./dist/index.js",
+ "types": "dist/index.d.ts",
+ "files": [
+ "dist",
+ "README.md",
+ "CHANGELOG.md"
+ ],
+ "scripts": {
+ "build": "cross-env NODE_ENV=development tsup",
+ "build:prod": "cross-env NODE_ENV=production tsup",
+ "clean": "rimraf node_modules dist .eslintcache",
+ "dev": "pnpm run build --watch",
+ "lint:eslint": "eslint . --ext js,cjs,mjs,jsx,ts,tsx,json,yaml,yml,md,mdx --max-warnings=0 --config .eslintrc.cjs",
+ "lint:eslint:fix": "eslint . --ext js,cjs,mjs,jsx,ts,tsx,json,yaml,yml,md,mdx --max-warnings=0 --config .eslintrc.cjs --fix",
+ "lint:package-json": "publint --strict",
+ "lint:prettier": "prettier --config=.prettierrc.cjs --check .",
+ "lint:prettier:fix": "prettier --config=.prettierrc.cjs --write .",
+ "lint:types": "tsc --noEmit",
+ "test": "vitest run",
+ "test:coverage": "vitest run --coverage",
+ "test:ui": "vitest --ui --coverage.enabled=true",
+ "test:watch": "vitest"
+ },
+ "dependencies": {
+ "@visulima/fs": "^2.1.1",
+ "ini": "^4.1.3",
+ "ts-deepmerge": "^7.0.0"
+ },
+ "devDependencies": {
+ "@anolilab/eslint-config": "^15.0.3",
+ "@anolilab/prettier-config": "^5.0.14",
+ "@anolilab/semantic-release-preset": "^8.0.3",
+ "@babel/core": "^7.24.3",
+ "@rushstack/eslint-plugin-security": "^0.8.1",
+ "@secretlint/secretlint-rule-preset-recommend": "^8.1.2",
+ "@types/ini": "^4.1.0",
+ "@types/node": "18.18.14",
+ "@visulima/path": "^1.0.0",
+ "@vitest/coverage-v8": "^1.4.0",
+ "@vitest/ui": "^1.4.0",
+ "cross-env": "^7.0.3",
+ "eslint": "^8.57.0",
+ "eslint-plugin-deprecation": "^2.0.0",
+ "eslint-plugin-etc": "^2.0.3",
+ "eslint-plugin-import": "npm:eslint-plugin-i@^2.29.1",
+ "eslint-plugin-mdx": "^3.1.5",
+ "eslint-plugin-vitest": "^0.4.1",
+ "eslint-plugin-vitest-globals": "^1.5.0",
+ "prettier": "^3.2.5",
+ "rimraf": "^5.0.5",
+ "secretlint": "8.1.2",
+ "semantic-release": "^23.0.5",
+ "sort-package-json": "^2.8.0",
+ "tempy": "^3.1.0",
+ "tsup": "^8.0.2",
+ "typescript": "^5.4.3",
+ "vitest": "^1.4.0"
+ },
+ "engines": {
+ "node": ">=18.* <=21.*"
+ },
+ "publishConfig": {
+ "access": "public",
+ "provenance": true
+ },
+ "anolilab": {
+ "eslint-config": {
+ "plugin": {
+ "tsdoc": false,
+ "etc": false
+ },
+ "warn_on_unsupported_typescript_version": false,
+ "info_on_disabling_jsx_react_rule": false,
+ "info_on_disabling_prettier_conflict_rule": false,
+ "info_on_disabling_jsonc_sort_keys_rule": false,
+ "info_on_disabling_etc_no_deprecated": false
+ }
+ }
+}
diff --git a/packages/rc/project.json b/packages/rc/project.json
new file mode 100644
index 00000000..668269cd
--- /dev/null
+++ b/packages/rc/project.json
@@ -0,0 +1,8 @@
+{
+ "name": "rc",
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
+ "sourceRoot": "packages/rc/src",
+ "projectType": "library",
+ "tags": ["rc", "type:package"],
+ "implicitDependencies": []
+}
diff --git a/packages/rc/src/index.ts b/packages/rc/src/index.ts
new file mode 100644
index 00000000..14da96f5
--- /dev/null
+++ b/packages/rc/src/index.ts
@@ -0,0 +1,213 @@
+import { homedir } from "node:os";
+import { cwd, env } from "node:process";
+
+import { isAccessibleSync, readFileSync } from "@visulima/fs";
+import { parseJson, stripJsonComments } from "@visulima/fs/utils";
+// eslint-disable-next-line import/no-extraneous-dependencies
+import { dirname, join } from "@visulima/path";
+import { parse } from "ini";
+import { merge } from "ts-deepmerge";
+
+import isJson from "./utils/is-json";
+
+// eslint-disable-next-line no-secrets/no-secrets
+/**
+ * Modified copy of the env function from https://github.com/dominictarr/rc/blob/a97f6adcc37ee1cad06ab7dc9b0bd842bbc5c664/lib/utils.js#L42
+ *
+ * @license https://github.com/dominictarr/rc/blob/master/LICENSE.APACHE2
+ * @license https://github.com/dominictarr/rc/blob/master/LICENSE.BSD
+ * @license https://github.com/dominictarr/rc/blob/master/LICENSE.MIT
+ *
+ * @param {string} prefix
+ * @param {Record} environment
+ *
+ * @returns {Record}
+ */
+// eslint-disable-next-line sonarjs/cognitive-complexity,@typescript-eslint/no-explicit-any
+const getEnvironment = (prefix: string, environment: Record = env): Record => {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const returnValue: Record = {};
+ const l = prefix.length;
+
+ // eslint-disable-next-line no-loops/no-loops,no-restricted-syntax
+ for (const k in environment) {
+ if (k.toLowerCase().startsWith(prefix.toLowerCase())) {
+ const keypath = k.slice(Math.max(0, l)).split("__");
+
+ // Trim empty strings from keypath array
+ let emptyStringIndex;
+
+ // eslint-disable-next-line no-loops/no-loops,no-cond-assign
+ while ((emptyStringIndex = keypath.indexOf("")) > -1) {
+ keypath.splice(emptyStringIndex, 1);
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ let cursor: Record = returnValue;
+
+ keypath.forEach((subkey, index) => {
+ // (check for subkey first so we ignore empty strings)
+ // (check for cursor to avoid assignment to primitive objects)
+ if (!subkey || typeof cursor !== "object") {
+ return;
+ }
+
+ // If this is the last key, just stuff the value in there
+ // Assigns actual value from env variable to final key
+ // (unless it's just an empty string- in that case use the last valid key)
+ if (index === keypath.length - 1) {
+ // eslint-disable-next-line security/detect-object-injection
+ cursor[subkey] = environment[k];
+ }
+
+ // Build sub-object if nothing already exists at the keypath
+ // eslint-disable-next-line security/detect-object-injection
+ if (cursor[subkey] === undefined) {
+ // eslint-disable-next-line security/detect-object-injection
+ cursor[subkey] = {};
+ }
+
+ // Increment cursor used to track the object at the current depth
+ // eslint-disable-next-line security/detect-object-injection
+ cursor = cursor[subkey];
+ });
+ }
+ }
+
+ return returnValue;
+};
+
+/**
+ * Will look in all the obvious places for configuration:
+ *
+ * - The defaults object you passed in
+ * - `/etc/${appname}/config`
+ * - `/etc/${appname}rc`
+ * - `$HOME/.config/${appname}/config`
+ * - `$HOME/.config/${appname}`
+ * - `$HOME/.${appname}/config`
+ * - `$HOME/.${appname}rc`
+ * - a local `.${appname}/config` and `.${appname}rc` and all found looking in `../../../ ../../ ../ ./` etc.
+ * - if you passed environment variable `${appname}_config` then from that file
+ * - if you passed options.config variable, then from that file
+ * - environment variables prefixed with `${appname}_`
+ * or use "\_\_" to indicate nested properties
_(e.g. `appname_foo__bar__baz` => `foo.bar.baz`)_
+ *
+ * @param {string} name
+ * @param {string} home
+ * @param {string} internalCwd
+ * @param {string | undefined} stopAt
+ * @param {string | undefined} environmentConfig
+ * @param {string | undefined} optionConfig
+ * @returns {Array}
+ */
+// eslint-disable-next-line sonarjs/cognitive-complexity
+const getConfigFiles = (name: string, home: string, internalCwd: string, stopAt?: string, environmentConfig?: string, optionConfig?: string): string[] => {
+ const configFiles = new Set();
+
+ // eslint-disable-next-line no-loops/no-loops,no-restricted-syntax
+ for (const file of [`/etc/${name}/config`, `/etc/${name}rc`]) {
+ if (isAccessibleSync(file)) {
+ configFiles.add(file);
+ }
+ }
+
+ // eslint-disable-next-line no-loops/no-loops,no-restricted-syntax
+ for (const file of [join(home, ".config", name, "config"), join(home, ".config", name), join(home, `.${name}`, "config"), join(home, `.${name}rc`)]) {
+ if (isAccessibleSync(file)) {
+ configFiles.add(file);
+ }
+
+ if (isAccessibleSync(`${file}.json`)) {
+ configFiles.add(`${file}.json`);
+ }
+ }
+
+ let start = internalCwd;
+ let endOfLoop = false;
+
+ const files = [join("." + name, "config.json"), join("." + name, "config"), join("." + name + "rc.json"), join("." + name + "rc")];
+
+ const traversedFiles: string[] = [];
+
+ // eslint-disable-next-line no-loops/no-loops
+ do {
+ // eslint-disable-next-line no-loops/no-loops,no-restricted-syntax
+ for (const file of files) {
+ const traverseFile = join(start, file);
+
+ if (isAccessibleSync(traverseFile)) {
+ traversedFiles.push(traverseFile);
+ }
+ }
+
+ start = dirname(start);
+
+ if (endOfLoop) {
+ break;
+ }
+
+ endOfLoop = dirname(start) === start;
+ } while (stopAt ? start === stopAt : true); // root
+
+ // reverse the traversedFiles so its starts with root
+ // eslint-disable-next-line no-loops/no-loops,no-restricted-syntax
+ for (const file of traversedFiles.reverse()) {
+ configFiles.add(file);
+ }
+
+ if (typeof environmentConfig === "string" && isAccessibleSync(environmentConfig)) {
+ configFiles.add(environmentConfig);
+ }
+
+ if (optionConfig && isAccessibleSync(optionConfig)) {
+ configFiles.add(optionConfig);
+ }
+
+ return [...configFiles];
+};
+
+// eslint-disable-next-line import/prefer-default-export
+export const rc = (
+ name: string,
+ options: {
+ config?: string;
+ cwd?: string;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ defaults?: Record;
+ home?: string;
+ stopAt?: string;
+ } = {},
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+): { config: Record; files: string[] } => {
+ // eslint-disable-next-line no-param-reassign
+ options = {
+ cwd: cwd(),
+ home: homedir(),
+ ...options,
+ };
+
+ const { config: environmentConfig, ...environment } = getEnvironment(`${name}_`);
+
+ const configFiles = getConfigFiles(name, options.home as string, options.cwd as string, options.stopAt, env[`${name}_config`], options.config);
+
+ const configs: object[] = [];
+
+ // eslint-disable-next-line no-loops/no-loops,no-restricted-syntax
+ for (const file of configFiles) {
+ const content = readFileSync(file);
+
+ if (isJson(content)) {
+ configs.push(parseJson(stripJsonComments(content)));
+ } else {
+ configs.push(parse(content));
+ }
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ if (environment) {
+ configs.push(environment);
+ }
+
+ return { config: merge(options.defaults ?? {}, ...configs), files: configFiles };
+};
diff --git a/packages/rc/src/utils/is-json.ts b/packages/rc/src/utils/is-json.ts
new file mode 100644
index 00000000..62d32676
--- /dev/null
+++ b/packages/rc/src/utils/is-json.ts
@@ -0,0 +1,17 @@
+/**
+ * Checks if string is a parseable JSON string.
+ *
+ * @param {string} value
+ * @returns {boolean}
+ */
+const isJson = (value: string): boolean => {
+ try {
+ JSON.parse(value);
+ } catch {
+ return false;
+ }
+
+ return true;
+};
+
+export default isJson;
diff --git a/packages/rc/tsconfig.eslint.json b/packages/rc/tsconfig.eslint.json
new file mode 100644
index 00000000..39eaefbf
--- /dev/null
+++ b/packages/rc/tsconfig.eslint.json
@@ -0,0 +1,8 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "baseUrl": "."
+ },
+ "include": ["__docs__/**/*", "__tests__/**/*", "src/**/*", "*.d.ts", "tsup.config.ts"]
+}
diff --git a/packages/rc/tsconfig.json b/packages/rc/tsconfig.json
new file mode 100644
index 00000000..f0ee80dc
--- /dev/null
+++ b/packages/rc/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "extends": "../../tsconfig.base.json",
+ "include": ["src/**/*", "*.d.ts"],
+ "compilerOptions": {
+ "moduleResolution": "bundler"
+ }
+}
diff --git a/packages/rc/tsup.config.ts b/packages/rc/tsup.config.ts
new file mode 100644
index 00000000..bc5cb8dc
--- /dev/null
+++ b/packages/rc/tsup.config.ts
@@ -0,0 +1,25 @@
+import type { Options } from "tsup";
+import { defineConfig } from "tsup";
+
+// @ts-ignore
+export default defineConfig((options: Options) => {
+ return {
+ ...options,
+ treeshake: true,
+ // react external https://github.com/vercel/turborepo/issues/360#issuecomment-1013885148
+ external: ["semantic-release"],
+ silent: !options.watch,
+ minify: process.env["NODE_ENV"] === "production",
+ minifyWhitespace: process.env["NODE_ENV"] === "production",
+ incremental: !options.watch,
+ dts: true,
+ sourcemap: true,
+ clean: true,
+ splitting: true,
+ shims: true,
+ target: ["es2022", "node18"],
+ declaration: true,
+ entry: ["src/index.ts"],
+ format: ["esm", "cjs"],
+ };
+});
diff --git a/packages/rc/vitest.config.ts b/packages/rc/vitest.config.ts
new file mode 100644
index 00000000..59d88c72
--- /dev/null
+++ b/packages/rc/vitest.config.ts
@@ -0,0 +1,5 @@
+import { getVitestConfig } from "../../tools/get-vitest-config";
+
+const config = getVitestConfig();
+
+export default config;
diff --git a/packages/semantic-release-pnpm/.eslintignore b/packages/semantic-release-pnpm/.eslintignore
new file mode 100644
index 00000000..207d83d7
--- /dev/null
+++ b/packages/semantic-release-pnpm/.eslintignore
@@ -0,0 +1,16 @@
+node_modules
+
+vitest.config.ts
+.prettierrc.cjs
+_meta.*.json
+.secretlintrc.cjs
+
+coverage
+__fixtures__
+dist
+
+tsup.config.ts
+
+src/definitions/context.ts
+
+__tests__/intigration/semantic-release-integration.test.ts
diff --git a/packages/semantic-release-pnpm/.eslintrc.cjs b/packages/semantic-release-pnpm/.eslintrc.cjs
new file mode 100644
index 00000000..d3fbfb8e
--- /dev/null
+++ b/packages/semantic-release-pnpm/.eslintrc.cjs
@@ -0,0 +1,90 @@
+/** @ts-check */
+// eslint-disable-next-line import/no-commonjs
+const { defineConfig } = require("@anolilab/eslint-config/define-config");
+// eslint-disable-next-line import/no-commonjs
+const globals = require("@anolilab/eslint-config/globals");
+
+///
+///
+///
+///
+///
+
+/** @type {import('eslint').Linter.Config} */
+module.exports = defineConfig({
+ env: {
+ // Your environments (which contains several predefined global variables)
+ // Most environments are loaded automatically if our rules are added
+ },
+ extends: ["@anolilab/eslint-config", "@anolilab/eslint-config/typescript-type-checking"],
+ globals: {
+ ...globals.es2021,
+ // Your global variables (setting to false means it's not allowed to be reassigned)
+ // myGlobal: false
+ },
+ ignorePatterns: ["!**/*"],
+ overrides: [
+ {
+ files: ["*.ts", "*.tsx", "*.mts", "*.cts", "*.js", "*.jsx"],
+ // Set parserOptions.project for the project to allow TypeScript to create the type-checker behind the scenes when we run linting
+ parserOptions: {},
+ rules: {},
+ },
+ {
+ files: ["*.ts", "*.tsx", "*.mts", "*.cts"],
+ // Set parserOptions.project for the project to allow TypeScript to create the type-checker behind the scenes when we run linting
+ parserOptions: {},
+ rules: {
+ "@typescript-eslint/no-unsafe-argument": "off",
+ "@typescript-eslint/no-unsafe-assignment": "off",
+ "@typescript-eslint/no-unsafe-call": "off",
+ "@typescript-eslint/no-unsafe-member-access": "off",
+ "@typescript-eslint/no-unsafe-return": "off",
+ "prefer-template": "off",
+ },
+ },
+ {
+ files: ["*.js", "*.jsx"],
+ rules: {},
+ },
+ {
+ files: ["*.mdx"],
+ rules: {
+ "jsx-a11y/anchor-has-content": "off",
+ // @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/issues/917
+ "jsx-a11y/heading-has-content": "off",
+ },
+ },
+ {
+ files: ["src/index.ts"],
+ rules: {
+ "import/no-unused-modules": "off",
+ },
+ },
+ {
+ files: ["__docs__/**"],
+ rules: {
+ "import/no-unresolved": "off",
+ "import/no-unused-modules": "off",
+ "no-console": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "unicorn/prefer-top-level-await": "off",
+ },
+ },
+ {
+ files: ["__tests__/**"],
+ rules: {
+ "import/no-unused-modules": "off",
+ },
+ },
+ ],
+ parserOptions: {
+ ecmaVersion: 2021,
+ project: "./tsconfig.eslint.json",
+ sourceType: "module",
+ },
+ // Report unused `eslint-disable` comments.
+ reportUnusedDisableDirectives: true,
+ root: true,
+});
diff --git a/packages/semantic-release-pnpm/.npmignore b/packages/semantic-release-pnpm/.npmignore
new file mode 100644
index 00000000..ff4abfc4
--- /dev/null
+++ b/packages/semantic-release-pnpm/.npmignore
@@ -0,0 +1,9 @@
+package-lock.json
+
+src
+__tests__
+__stories__
+__fixtures__
+.rpt2_cache
+fixup.sh
+.releaserc.json
diff --git a/packages/semantic-release-pnpm/.prettierignore b/packages/semantic-release-pnpm/.prettierignore
new file mode 100644
index 00000000..ebf52909
--- /dev/null
+++ b/packages/semantic-release-pnpm/.prettierignore
@@ -0,0 +1,9 @@
+.gitkeep
+.env*
+*.ico
+*.lock
+dist
+CHANGELOG.md
+coverage
+node_modules
+.eslintcache
diff --git a/packages/semantic-release-pnpm/.prettierrc.cjs b/packages/semantic-release-pnpm/.prettierrc.cjs
new file mode 100644
index 00000000..32f893c0
--- /dev/null
+++ b/packages/semantic-release-pnpm/.prettierrc.cjs
@@ -0,0 +1,5 @@
+const config = require("@anolilab/prettier-config");
+
+module.exports = {
+ ...config,
+};
diff --git a/packages/semantic-release-pnpm/.releaserc.json b/packages/semantic-release-pnpm/.releaserc.json
new file mode 100644
index 00000000..dbc778df
--- /dev/null
+++ b/packages/semantic-release-pnpm/.releaserc.json
@@ -0,0 +1,3 @@
+{
+ "extends": "@anolilab/semantic-release-preset/npm"
+}
diff --git a/packages/semantic-release-pnpm/.secretlintignore b/packages/semantic-release-pnpm/.secretlintignore
new file mode 100644
index 00000000..8d4c427f
--- /dev/null
+++ b/packages/semantic-release-pnpm/.secretlintignore
@@ -0,0 +1,3 @@
+.pnpm-store
+packages/**/node_modules
+node_modules
diff --git a/packages/semantic-release-pnpm/.secretlintrc.cjs b/packages/semantic-release-pnpm/.secretlintrc.cjs
new file mode 100644
index 00000000..418ad9ce
--- /dev/null
+++ b/packages/semantic-release-pnpm/.secretlintrc.cjs
@@ -0,0 +1,7 @@
+module.exports = {
+ rules: [
+ {
+ id: "@secretlint/secretlint-rule-preset-recommend",
+ },
+ ],
+};
diff --git a/packages/semantic-release-pnpm/CHANGELOG.md b/packages/semantic-release-pnpm/CHANGELOG.md
new file mode 100644
index 00000000..e69de29b
diff --git a/packages/semantic-release-pnpm/LICENSE.md b/packages/semantic-release-pnpm/LICENSE.md
new file mode 100644
index 00000000..a6b1fdfc
--- /dev/null
+++ b/packages/semantic-release-pnpm/LICENSE.md
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2024 anolilab
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/packages/semantic-release-pnpm/README.md b/packages/semantic-release-pnpm/README.md
new file mode 100644
index 00000000..884037f8
--- /dev/null
+++ b/packages/semantic-release-pnpm/README.md
@@ -0,0 +1,228 @@
+
+
anolilab semantic-release-pnpm
+
+ Semantic-release plugin to publish a npm package with pnpm.
+
+
+
+
+
+
+
+[![typescript-image]][typescript-url] [![npm-image]][npm-url] [![license-image]][license-url]
+
+
+
+---
+
+
+
+
+ Daniel Bannert's open source work is supported by the community on GitHub Sponsors
+
+
+
+
+---
+
+## Install
+
+```sh
+npm install @anolilab/semantic-release-pnpm
+```
+
+```sh
+yarn add @anolilab/semantic-release-pnpm
+```
+
+```sh
+pnpm add @anolilab/semantic-release-pnpm
+```
+
+## Usage
+
+The plugin can be configured in the [**semantic-release** configuration file](https://github.com/semantic-release/semantic-release/blob/master/docs/usage/configuration.md#configuration):
+
+```json
+{
+ "plugins": ["@semantic-release/commit-analyzer", "@semantic-release/release-notes-generator", "@anolilab/semantic-release-pnpm"]
+}
+```
+
+## Steps that are used
+
+| Step | Description |
+| ------------------ | -------------------------------------------------------------------------------------------------------------------------------- |
+| `verifyConditions` | Verify the presence of the `NPM_TOKEN` environment variable, or an `.npmrc` file, and verify the authentication method is valid. |
+| `prepare` | Update the `package.json` version and [create](https://docs.npmjs.com/cli/pack) the npm package tarball. |
+| `addChannel` | [Add a release to a dist-tag](https://docs.npmjs.com/cli/dist-tag). |
+| `publish` | [Publish the npm package](https://docs.npmjs.com/cli/publish) to the registry. |
+
+## Configuration
+
+### npm registry authentication
+
+The npm [token](https://docs.npmjs.com/about-access-tokens) authentication configuration is **required** and can be set via [environment variables](#environment-variables).
+
+Automation tokens are recommended since they can be used for an automated workflow, even when your account is configured to use the [`auth-and-writes` level of 2FA](https://docs.npmjs.com/about-two-factor-authentication#authorization-and-writes).
+
+### npm provenance
+
+If you are publishing to the official registry and your pipeline is on a [provider that is supported by npm for provenance](https://docs.npmjs.com/generating-provenance-statements#provenance-limitations), npm can be configured to [publish with provenance](https://docs.npmjs.com/generating-provenance-statements).
+
+Since semantic-release wraps the npm publish command, configuring provenance is not exposed directly.
+Instead, provenance can be configured through the [other configuration options exposed by npm](https://docs.npmjs.com/generating-provenance-statements#using-third-party-package-publishing-tools).
+Provenance applies specifically to publishing, so our recommendation is to configure under `publishConfig` within the `package.json`.
+
+#### npm provenance on GitHub Actions
+
+For package provenance to be signed on the GitHub Actions CI the following permission is required
+to be enabled on the job:
+
+```yaml
+permissions:
+ id-token: write # to enable use of OIDC for npm provenance
+```
+
+It's worth noting that if you are using semantic-release to its fullest with a GitHub release, GitHub comments,
+and other features, then [more permissions are required](https://github.com/semantic-release/github#github-authentication) to be enabled on this job:
+
+```yaml
+permissions:
+ contents: write # to be able to publish a GitHub release
+ issues: write # to be able to comment on released issues
+ pull-requests: write # to be able to comment on released pull requests
+ id-token: write # to enable use of OIDC for npm provenance
+```
+
+Refer to the [GitHub Actions recipe for npm package provenance](https://semantic-release.gitbook.io/semantic-release/recipes/ci-configurations/github-actions#.github-workflows-release.yml-configuration-for-node-projects) for the full CI job's YAML code example.
+
+### Environment variables
+
+| Variable | Description |
+| ----------- | ----------------------------------------------------------------------------------------------------------------------------- |
+| `NPM_TOKEN` | Npm token created via [npm token create](https://docs.npmjs.com/getting-started/working_with_tokens#how-to-create-new-tokens) |
+
+### Options
+
+| Options | Description | Default |
+| --------------- | ------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------- |
+| `npmPublish` | Whether to publish the `npm` package to the registry. If `false` the `package.json` version will still be updated. | `false` if the `package.json` [private](https://docs.npmjs.com/files/package.json#private) property is `true`, `true` otherwise. |
+| `pkgRoot` | Directory path to publish. | `.` |
+| `tarballDir` | Directory path in which to write the package tarball. If `false` the tarball is not be kept on the file system. | `false` |
+| `publishBranch` | The primary branch of the repository which is used for publishing the latest changes. | [master and main](https://pnpm.io/cli/publish#--publish-branch-branch) |
+
+**Note**: The `pkgRoot` directory must contain a `package.json`. The version will be updated only in the `package.json` and `npm-shrinkwrap.json` within the `pkgRoot` directory.
+
+**Note**: If you use a [shareable configuration](https://github.com/semantic-release/semantic-release/blob/master/docs/usage/shareable-configurations.md#shareable-configurations) that defines one of these options you can set it to `false` in your [**semantic-release** configuration](https://github.com/semantic-release/semantic-release/blob/master/docs/usage/configuration.md#configuration) in order to use the default value.
+
+### npm configuration
+
+The plugin uses the [`npm` CLI](https://github.com/npm/cli) which will read the configuration from [`.npmrc`](https://docs.npmjs.com/files/npmrc). See [`npm config`](https://docs.npmjs.com/misc/config) for the option list.
+
+The [`registry`](https://docs.npmjs.com/misc/registry) can be configured via the npm environment variable `NPM_CONFIG_REGISTRY` and will take precedence over the configuration in `.npmrc`.
+
+The [`registry`](https://docs.npmjs.com/misc/registry) and [`dist-tag`](https://docs.npmjs.com/cli/dist-tag) can be configured under `publishConfig` in the `package.json`:
+
+```json
+{
+ "publishConfig": {
+ "registry": "https://registry.npmjs.org/",
+ "tag": "latest"
+ }
+}
+```
+
+**Notes**:
+
+- The presence of an `.npmrc` file will override any specified environment variables.
+- The presence of `registry` or `dist-tag` under `publishConfig` in the `package.json` will take precedence over the configuration in `.npmrc` and `NPM_CONFIG_REGISTRY`
+
+### Examples
+
+The `npmPublish` and `tarballDir` option can be used to skip the publishing to the `npm` registry and instead, release the package tarball with another plugin. For example with the [@semantic-release/github](https://github.com/semantic-release/github) plugin:
+
+```json
+{
+ "plugins": [
+ "@semantic-release/commit-analyzer",
+ "@semantic-release/release-notes-generator",
+ [
+ "@anolilab/semantic-release-pnpm",
+ {
+ "npmPublish": false,
+ "tarballDir": "dist"
+ }
+ ],
+ [
+ "@semantic-release/github",
+ {
+ "assets": "dist/*.tgz"
+ }
+ ]
+ ]
+}
+```
+
+When publishing from a sub-directory with the `pkgRoot` option, the `package.json` and `npm-shrinkwrap.json` updated with the new version can be moved to another directory with a `postversion`. For example with the [@semantic-release/git](https://github.com/semantic-release/git) plugin:
+
+```json
+{
+ "plugins": [
+ "@semantic-release/commit-analyzer",
+ "@semantic-release/release-notes-generator",
+ [
+ "@anolilab/semantic-release-pnpm",
+ {
+ "pkgRoot": "dist"
+ }
+ ],
+ [
+ "@semantic-release/git",
+ {
+ "assets": ["package.json", "npm-shrinkwrap.json"]
+ }
+ ]
+ ]
+}
+```
+
+```json
+{
+ "scripts": {
+ "postversion": "cp -r package.json .. && cp -r npm-shrinkwrap.json .."
+ }
+}
+```
+
+## Related
+
+- [@semantic-release/npm](https://github.com/semantic-release/npm) - 🚢 semantic-release plugin to publish a npm package
+- [semantic-release-yarn](https://github.com/hongaar/semantic-release-yarn) - 🧶 A semantic-release plugin to publish npm packages with Yarn. Comes with built-in support for monorepos.
+
+## Supported Node.js Versions
+
+Libraries in this ecosystem make the best effort to track [Node.js’ release schedule](https://github.com/nodejs/release#release-schedule).
+Here’s [a post on why we think this is important](https://medium.com/the-node-js-collection/maintainers-should-consider-following-node-js-release-schedule-ab08ed4de71a).
+
+## Contributing
+
+If you would like to help take a look at the [list of issues](https://github.com/anolilab/semantic-release/issues) and check our [Contributing](.github/CONTRIBUTING.md) guidelines.
+
+> **Note:** please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.
+
+## Credits
+
+- [Daniel Bannert](https://github.com/prisis)
+- [All Contributors](https://github.com/anolilab/semantic-release/graphs/contributors)
+
+## License
+
+The anolilab semantic-release-pnpm is open-sourced software licensed under the [MIT][license-url]
+
+[typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript
+[typescript-url]: "typescript"
+[license-image]: https://img.shields.io/npm/l/@anolilab/semantic-release-pnpm?color=blueviolet&style=for-the-badge
+[license-url]: LICENSE.md "license"
+[npm-image]: https://img.shields.io/npm/v/@anolilab/semantic-release-pnpm/latest.svg?style=for-the-badge&logo=npm
+[npm-url]: https://www.npmjs.com/package/@anolilab/semantic-release-pnpm/v/latest "npm"
diff --git a/packages/semantic-release-pnpm/__tests__/intigration/helpers/config.yaml b/packages/semantic-release-pnpm/__tests__/intigration/helpers/config.yaml
new file mode 100644
index 00000000..ba3ebe7d
--- /dev/null
+++ b/packages/semantic-release-pnpm/__tests__/intigration/helpers/config.yaml
@@ -0,0 +1,23 @@
+storage: "/verdaccio/storage/data"
+plugins: "/verdaccio/plugins"
+web:
+ title: "Verdaccio"
+auth:
+ htpasswd:
+ file: "/verdaccio/storage/htpasswd"
+packages:
+ "@*/*":
+ access: "$all"
+ publish: "$authenticated"
+ unpublish: "$authenticated"
+ "**":
+ access: "$all"
+ publish: "$authenticated"
+ unpublish: "$authenticated"
+server:
+ keepAliveTimeout: 60
+middlewares:
+ audit:
+ enabled: true
+logs:
+ - { type: "stdout", format: "pretty", level: "http" }
diff --git a/packages/semantic-release-pnpm/__tests__/intigration/helpers/npm-registry.ts b/packages/semantic-release-pnpm/__tests__/intigration/helpers/npm-registry.ts
new file mode 100644
index 00000000..bea75eac
--- /dev/null
+++ b/packages/semantic-release-pnpm/__tests__/intigration/helpers/npm-registry.ts
@@ -0,0 +1,79 @@
+import { setTimeout } from "node:timers/promises";
+import { fileURLToPath } from "node:url";
+
+import { dirname, join } from "@visulima/path";
+import Docker from "dockerode";
+import getStream from "get-stream";
+import { got } from "got";
+import pRetry from "p-retry";
+
+const IMAGE = "verdaccio/verdaccio:4";
+const REGISTRY_PORT = 4873;
+const REGISTRY_HOST = "localhost";
+const NPM_USERNAME = "integration";
+const NPM_PASSWORD = "suchsecure";
+const NPM_EMAIL = "integration@test.com";
+
+const docker = new Docker();
+
+let container: Docker.Container;
+
+/**
+ * Download the `npm-registry-docker` Docker image, create a new container and start it.
+ */
+
+export const start = async (): Promise => {
+ await getStream(await docker.pull(IMAGE));
+
+ container = await docker.createContainer({
+ Binds: [`${join(dirname(fileURLToPath(import.meta.url)), "config.yaml")}:/verdaccio/conf/config.yaml`],
+ Image: IMAGE,
+ PortBindings: { [`${REGISTRY_PORT}/tcp`]: [{ HostPort: `${REGISTRY_PORT}` }] },
+ Tty: true,
+ });
+
+ await container.start();
+ await setTimeout(4000);
+
+ try {
+ // Wait for the registry to be ready
+ await pRetry(async () => await got(`http://${REGISTRY_HOST}:${REGISTRY_PORT}/`, { cache: false }), {
+ factor: 2,
+ minTimeout: 1000,
+ retries: 7,
+ });
+ } catch {
+ throw new Error(`Couldn't start npm-docker-couchdb after 2 min`);
+ }
+
+ // Create user
+ await got(`http://${REGISTRY_HOST}:${REGISTRY_PORT}/-/user/org.couchdb.user:${NPM_USERNAME}`, {
+ json: {
+ _id: `org.couchdb.user:${NPM_USERNAME}`,
+ email: NPM_EMAIL,
+ name: NPM_USERNAME,
+ password: NPM_PASSWORD,
+ roles: [],
+ type: "user",
+ },
+ method: "PUT",
+ });
+};
+
+export const url = `http://${REGISTRY_HOST}:${REGISTRY_PORT}/`;
+
+export const authEnvironment = {
+ NPM_EMAIL,
+ NPM_PASSWORD,
+ NPM_USERNAME,
+ npm_config_registry: url,
+};
+
+/**
+ * Stop and remote the `npm-registry-docker` Docker container.
+ */
+
+export const stop = async (): Promise => {
+ await container.stop();
+ await container.remove();
+};
diff --git a/packages/semantic-release-pnpm/__tests__/intigration/semantic-release-integration.test.ts b/packages/semantic-release-pnpm/__tests__/intigration/semantic-release-integration.test.ts
new file mode 100644
index 00000000..82b71847
--- /dev/null
+++ b/packages/semantic-release-pnpm/__tests__/intigration/semantic-release-integration.test.ts
@@ -0,0 +1,771 @@
+import { rm } from "node:fs/promises";
+
+import { writeJson } from "@visulima/fs";
+import { join } from "@visulima/path";
+import { WritableStreamBuffer } from "stream-buffers";
+import { temporaryDirectory } from "tempy";
+import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
+
+import { start, stop, url as npmRegistryUrl } from "./helpers/npm-registry";
+
+const logSpy = vi.fn();
+const logger = { error: vi.fn(), log: logSpy, success: vi.fn() };
+
+// @TODO: port all test and try to run them
+describe("semantic-release-integration", () => {
+ let cwd: string;
+
+ beforeEach(async () => {
+ cwd = temporaryDirectory();
+
+ // Start the local NPM registry
+ await start();
+ });
+
+ afterEach(async () => {
+ await rm(cwd, { recursive: true });
+
+ // Stop the local NPM registry
+ await stop();
+ });
+
+ // eslint-disable-next-line vitest/no-disabled-tests
+ it.skip('should skip npm auth verification if "npmPublish" is false', async () => {
+ expect.assertions(1);
+
+ await writeJson(join(cwd, "package.json"), { name: "published", publishConfig: { registry: npmRegistryUrl }, version: "1.0.0" });
+
+ const { verifyConditions } = await import("../../src");
+
+ await expect(
+ async () =>
+ await verifyConditions(
+ { npmPublish: false },
+ {
+ cwd,
+ env: { NPM_TOKEN: "wrong_token" },
+ logger,
+ options: {},
+ stderr: new WritableStreamBuffer(),
+ stdout: new WritableStreamBuffer(),
+ },
+ ),
+ ).rejects.not.toThrow("Invalid npm token.");
+ });
+});
+
+// const path = require("node:path");
+// const test = require("ava");
+// const { outputJson, pathExists, readJson } = require("fs-extra");
+// const execa = require("execa");
+// const { spy } = require("sinon");
+// const tempy = require("tempy");
+// const clearModule = require("clear-module");
+// const { WritableStreamBuffer } = require("stream-buffers");
+// const npmRegistry = require("./helpers/npm-registry");
+//
+// // Environment variables used only for the local npm command used to do verification
+// const testEnvironment = {
+// ...process.env,
+// ...npmRegistry.authEnv,
+// LEGACY_TOKEN: Buffer.from(`${npmRegistry.authEnv.NPM_USERNAME}:${npmRegistry.authEnv.NPM_PASSWORD}`, "utf8").toString("base64"),
+// npm_config_registry: npmRegistry.url,
+// };
+
+//
+// test('Skip npm auth verification if "package.private" is true', async (t) => {
+// const cwd = tempy.directory();
+// const package_ = { name: "published", private: true, publishConfig: { registry: npmRegistry.url }, version: "1.0.0" };
+// await outputJson(path.resolve(cwd, "package.json"), package_);
+//
+// await t.notThrowsAsync(
+// t.context.m.verifyConditions(
+// { npmPublish: false },
+// {
+// cwd,
+// env: {},
+// logger: t.context.logger,
+// options: { publish: ["@semantic-release/npm"] },
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// ),
+// );
+// });
+//
+// test('Skip npm token verification if "package.private" is true', async (t) => {
+// const cwd = tempy.directory();
+// const package_ = { name: "published", private: true, publishConfig: { registry: npmRegistry.url }, version: "1.0.0" };
+// await outputJson(path.resolve(cwd, "package.json"), package_);
+// await t.notThrowsAsync(
+// t.context.m.verifyConditions(
+// {},
+// {
+// cwd,
+// env: {},
+// logger: t.context.logger,
+// options: { publish: ["@semantic-release/npm"] },
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// ),
+// );
+// });
+//
+// test("Throws error if NPM token is invalid", async (t) => {
+// const cwd = tempy.directory();
+// const environment = { DEFAULT_NPM_REGISTRY: npmRegistry.url, NPM_TOKEN: "wrong_token" };
+// const package_ = { name: "published", publishConfig: { registry: npmRegistry.url }, version: "1.0.0" };
+// await outputJson(path.resolve(cwd, "package.json"), package_);
+//
+// const [error] = await t.throwsAsync(
+// t.context.m.verifyConditions({}, { cwd, env: environment, logger: t.context.logger, options: {}, stderr: t.context.stderr, stdout: t.context.stdout }),
+// );
+//
+// t.is(error.name, "SemanticReleaseError");
+// t.is(error.code, "EINVALIDNPMTOKEN");
+// t.is(error.message, "Invalid npm token.");
+// });
+//
+// test("Skip Token validation if the registry configured is not the default one", async (t) => {
+// const cwd = tempy.directory();
+// const environment = { NPM_TOKEN: "wrong_token" };
+// const package_ = { name: "published", publishConfig: { registry: "http://custom-registry.com/" }, version: "1.0.0" };
+// await outputJson(path.resolve(cwd, "package.json"), package_);
+// await t.notThrowsAsync(
+// t.context.m.verifyConditions({}, { cwd, env: environment, logger: t.context.logger, options: {}, stderr: t.context.stderr, stdout: t.context.stdout }),
+// );
+// });
+//
+// test("Verify npm auth and package", async (t) => {
+// const cwd = tempy.directory();
+// const package_ = { name: "valid-token", publishConfig: { registry: npmRegistry.url }, version: "0.0.0-dev" };
+// await outputJson(path.resolve(cwd, "package.json"), package_);
+// await t.notThrowsAsync(
+// t.context.m.verifyConditions(
+// {},
+// {
+// cwd,
+// env: npmRegistry.authEnv,
+// logger: t.context.logger,
+// options: {},
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// ),
+// );
+// });
+//
+// test("Verify npm auth and package from a sub-directory", async (t) => {
+// const cwd = tempy.directory();
+// const package_ = { name: "valid-token", publishConfig: { registry: npmRegistry.url }, version: "0.0.0-dev" };
+// await outputJson(path.resolve(cwd, "dist/package.json"), package_);
+// await t.notThrowsAsync(
+// t.context.m.verifyConditions(
+// { pkgRoot: "dist" },
+// {
+// cwd,
+// env: npmRegistry.authEnv,
+// logger: t.context.logger,
+// options: {},
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// ),
+// );
+// });
+//
+// test('Verify npm auth and package with "npm_config_registry" env var set by yarn', async (t) => {
+// const cwd = tempy.directory();
+// const package_ = { name: "valid-token", publishConfig: { registry: npmRegistry.url }, version: "0.0.0-dev" };
+// await outputJson(path.resolve(cwd, "package.json"), package_);
+// await t.notThrowsAsync(
+// t.context.m.verifyConditions(
+// {},
+// {
+// cwd,
+// env: { ...npmRegistry.authEnv, npm_config_registry: "https://registry.yarnpkg.com" },
+// logger: t.context.logger,
+// options: { publish: [] },
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// ),
+// );
+// });
+//
+// test("Throw SemanticReleaseError Array if config option are not valid in verifyConditions", async (t) => {
+// const cwd = tempy.directory();
+// const package_ = { publishConfig: { registry: npmRegistry.url } };
+// await outputJson(path.resolve(cwd, "package.json"), package_);
+// const npmPublish = 42;
+// const tarballDir = 42;
+// const packageRoot = 42;
+// const errors = [
+// ...(await t.throwsAsync(
+// t.context.m.verifyConditions(
+// {},
+// {
+// cwd,
+// env: {},
+// logger: t.context.logger,
+// options: {
+// publish: ["@semantic-release/github", { npmPublish, path: "@semantic-release/npm", pkgRoot: packageRoot, tarballDir }],
+// },
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// ),
+// )),
+// ];
+//
+// t.is(errors[0].name, "SemanticReleaseError");
+// t.is(errors[0].code, "EINVALIDNPMPUBLISH");
+// t.is(errors[1].name, "SemanticReleaseError");
+// t.is(errors[1].code, "EINVALIDTARBALLDIR");
+// t.is(errors[2].name, "SemanticReleaseError");
+// t.is(errors[2].code, "EINVALIDPKGROOT");
+// t.is(errors[3].name, "SemanticReleaseError");
+// t.is(errors[3].code, "ENOPKG");
+// });
+//
+// test("Publish the package", async (t) => {
+// const cwd = tempy.directory();
+// const environment = npmRegistry.authEnv;
+// const package_ = { name: "publish", publishConfig: { registry: npmRegistry.url }, version: "0.0.0" };
+// await outputJson(path.resolve(cwd, "package.json"), package_);
+//
+// const result = await t.context.m.publish(
+// {},
+// {
+// cwd,
+// env: environment,
+// logger: t.context.logger,
+// nextRelease: { version: "1.0.0" },
+// options: {},
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// );
+//
+// t.deepEqual(result, { channel: "latest", name: "npm package (@latest dist-tag)", url: undefined });
+// t.is((await readJson(path.resolve(cwd, "package.json"))).version, "1.0.0");
+// t.false(await pathExists(path.resolve(cwd, `${package_.name}-1.0.0.tgz`)));
+// t.is((await execa("npm", ["view", package_.name, "version"], { cwd, env: testEnvironment })).stdout, "1.0.0");
+// });
+//
+// test("Publish the package on a dist-tag", async (t) => {
+// const cwd = tempy.directory();
+// const environment = { ...npmRegistry.authEnv, DEFAULT_NPM_REGISTRY: npmRegistry.url };
+// const package_ = { name: "publish-tag", publishConfig: { registry: npmRegistry.url, tag: "next" }, version: "0.0.0" };
+// await outputJson(path.resolve(cwd, "package.json"), package_);
+//
+// const result = await t.context.m.publish(
+// {},
+// {
+// cwd,
+// env: environment,
+// logger: t.context.logger,
+// nextRelease: { channel: "next", version: "1.0.0" },
+// options: {},
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// );
+//
+// t.deepEqual(result, {
+// channel: "next",
+// name: "npm package (@next dist-tag)",
+// url: "https://www.npmjs.com/package/publish-tag/v/1.0.0",
+// });
+// t.is((await readJson(path.resolve(cwd, "package.json"))).version, "1.0.0");
+// t.false(await pathExists(path.resolve(cwd, `${package_.name}-1.0.0.tgz`)));
+// t.is((await execa("npm", ["view", package_.name, "version"], { cwd, env: testEnvironment })).stdout, "1.0.0");
+// });
+//
+// test("Publish the package from a sub-directory", async (t) => {
+// const cwd = tempy.directory();
+// const environment = npmRegistry.authEnv;
+// const package_ = { name: "publish-sub-dir", publishConfig: { registry: npmRegistry.url }, version: "0.0.0" };
+// await outputJson(path.resolve(cwd, "dist/package.json"), package_);
+//
+// const result = await t.context.m.publish(
+// { pkgRoot: "dist" },
+// {
+// cwd,
+// env: environment,
+// logger: t.context.logger,
+// nextRelease: { version: "1.0.0" },
+// options: {},
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// );
+//
+// t.deepEqual(result, { channel: "latest", name: "npm package (@latest dist-tag)", url: undefined });
+// t.is((await readJson(path.resolve(cwd, "dist/package.json"))).version, "1.0.0");
+// t.false(await pathExists(path.resolve(cwd, `${package_.name}-1.0.0.tgz`)));
+// t.is((await execa("npm", ["view", package_.name, "version"], { cwd, env: testEnvironment })).stdout, "1.0.0");
+// });
+//
+// test('Create the package and skip publish ("npmPublish" is false)', async (t) => {
+// const cwd = tempy.directory();
+// const environment = npmRegistry.authEnv;
+// const package_ = { name: "skip-publish", publishConfig: { registry: npmRegistry.url }, version: "0.0.0" };
+// await outputJson(path.resolve(cwd, "package.json"), package_);
+//
+// const result = await t.context.m.publish(
+// { npmPublish: false, tarballDir: "tarball" },
+// {
+// cwd,
+// env: environment,
+// logger: t.context.logger,
+// nextRelease: { version: "1.0.0" },
+// options: {},
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// );
+//
+// t.false(result);
+// t.is((await readJson(path.resolve(cwd, "package.json"))).version, "1.0.0");
+// t.true(await pathExists(path.resolve(cwd, `tarball/${package_.name}-1.0.0.tgz`)));
+// await t.throwsAsync(execa("npm", ["view", package_.name, "version"], { cwd, env: testEnvironment }));
+// });
+//
+// test('Create the package and skip publish ("package.private" is true)', async (t) => {
+// const cwd = tempy.directory();
+// const environment = npmRegistry.authEnv;
+// const package_ = {
+// name: "skip-publish-private",
+// private: true,
+// publishConfig: { registry: npmRegistry.url },
+// version: "0.0.0",
+// };
+// await outputJson(path.resolve(cwd, "package.json"), package_);
+//
+// const result = await t.context.m.publish(
+// { tarballDir: "tarball" },
+// {
+// cwd,
+// env: environment,
+// logger: t.context.logger,
+// nextRelease: { version: "1.0.0" },
+// options: {},
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// );
+//
+// t.false(result);
+// t.is((await readJson(path.resolve(cwd, "package.json"))).version, "1.0.0");
+// t.true(await pathExists(path.resolve(cwd, `tarball/${package_.name}-1.0.0.tgz`)));
+// await t.throwsAsync(execa("npm", ["view", package_.name, "version"], { cwd, env: testEnvironment }));
+// });
+//
+// test('Create the package and skip publish from a sub-directory ("npmPublish" is false)', async (t) => {
+// const cwd = tempy.directory();
+// const environment = npmRegistry.authEnv;
+// const package_ = { name: "skip-publish-sub-dir", publishConfig: { registry: npmRegistry.url }, version: "0.0.0" };
+// await outputJson(path.resolve(cwd, "dist/package.json"), package_);
+//
+// const result = await t.context.m.publish(
+// { npmPublish: false, pkgRoot: "./dist", tarballDir: "./tarball" },
+// {
+// cwd,
+// env: environment,
+// logger: t.context.logger,
+// nextRelease: { version: "1.0.0" },
+// options: {},
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// );
+//
+// t.false(result);
+// t.is((await readJson(path.resolve(cwd, "dist/package.json"))).version, "1.0.0");
+// t.true(await pathExists(path.resolve(cwd, `tarball/${package_.name}-1.0.0.tgz`)));
+// await t.throwsAsync(execa("npm", ["view", package_.name, "version"], { cwd, env: testEnvironment }));
+// });
+//
+// test('Create the package and skip publish from a sub-directory ("package.private" is true)', async (t) => {
+// const cwd = tempy.directory();
+// const environment = npmRegistry.authEnv;
+// const package_ = {
+// name: "skip-publish-sub-dir-private",
+// private: true,
+// publishConfig: { registry: npmRegistry.url },
+// version: "0.0.0",
+// };
+// await outputJson(path.resolve(cwd, "dist/package.json"), package_);
+//
+// const result = await t.context.m.publish(
+// { pkgRoot: "./dist", tarballDir: "./tarball" },
+// {
+// cwd,
+// env: environment,
+// logger: t.context.logger,
+// nextRelease: { version: "1.0.0" },
+// options: {},
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// );
+//
+// t.false(result);
+// t.is((await readJson(path.resolve(cwd, "dist/package.json"))).version, "1.0.0");
+// t.true(await pathExists(path.resolve(cwd, `tarball/${package_.name}-1.0.0.tgz`)));
+// await t.throwsAsync(execa("npm", ["view", package_.name, "version"], { cwd, env: testEnvironment }));
+// });
+//
+// test("Throw SemanticReleaseError Array if config option are not valid in publish", async (t) => {
+// const cwd = tempy.directory();
+// const package_ = { publishConfig: { registry: npmRegistry.url } };
+// await outputJson(path.resolve(cwd, "package.json"), package_);
+// const npmPublish = 42;
+// const tarballDir = 42;
+// const packageRoot = 42;
+//
+// const errors = [
+// ...(await t.throwsAsync(
+// t.context.m.publish(
+// { npmPublish, pkgRoot: packageRoot, tarballDir },
+// {
+// cwd,
+// env: {},
+// logger: t.context.logger,
+// nextRelease: { version: "1.0.0" },
+// options: { publish: ["@semantic-release/github", "@semantic-release/npm"] },
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// ),
+// )),
+// ];
+//
+// t.is(errors[0].name, "SemanticReleaseError");
+// t.is(errors[0].code, "EINVALIDNPMPUBLISH");
+// t.is(errors[1].name, "SemanticReleaseError");
+// t.is(errors[1].code, "EINVALIDTARBALLDIR");
+// t.is(errors[2].name, "SemanticReleaseError");
+// t.is(errors[2].code, "EINVALIDPKGROOT");
+// t.is(errors[3].name, "SemanticReleaseError");
+// t.is(errors[3].code, "ENOPKG");
+// });
+//
+// test("Prepare the package", async (t) => {
+// const cwd = tempy.directory();
+// const environment = npmRegistry.authEnv;
+// const package_ = { name: "prepare", publishConfig: { registry: npmRegistry.url }, version: "0.0.0" };
+// await outputJson(path.resolve(cwd, "package.json"), package_);
+//
+// await t.context.m.prepare(
+// {},
+// {
+// cwd,
+// env: environment,
+// logger: t.context.logger,
+// nextRelease: { version: "1.0.0" },
+// options: {},
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// );
+//
+// t.is((await readJson(path.resolve(cwd, "package.json"))).version, "1.0.0");
+// t.false(await pathExists(path.resolve(cwd, `${package_.name}-1.0.0.tgz`)));
+// });
+//
+// test("Prepare the package from a sub-directory", async (t) => {
+// const cwd = tempy.directory();
+// const environment = npmRegistry.authEnv;
+// const package_ = { name: "prepare-sub-dir", publishConfig: { registry: npmRegistry.url }, version: "0.0.0" };
+// await outputJson(path.resolve(cwd, "dist/package.json"), package_);
+//
+// await t.context.m.prepare(
+// { pkgRoot: "dist" },
+// {
+// cwd,
+// env: environment,
+// logger: t.context.logger,
+// nextRelease: { version: "1.0.0" },
+// options: {},
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// );
+//
+// t.is((await readJson(path.resolve(cwd, "dist/package.json"))).version, "1.0.0");
+// t.false(await pathExists(path.resolve(cwd, `${package_.name}-1.0.0.tgz`)));
+// });
+//
+// test("Throw SemanticReleaseError Array if config option are not valid in prepare", async (t) => {
+// const cwd = tempy.directory();
+// const package_ = { publishConfig: { registry: npmRegistry.url } };
+// await outputJson(path.resolve(cwd, "package.json"), package_);
+// const npmPublish = 42;
+// const tarballDir = 42;
+// const packageRoot = 42;
+//
+// const errors = [
+// ...(await t.throwsAsync(
+// t.context.m.prepare(
+// { npmPublish, pkgRoot: packageRoot, tarballDir },
+// {
+// cwd,
+// env: {},
+// logger: t.context.logger,
+// nextRelease: { version: "1.0.0" },
+// options: { publish: ["@semantic-release/github", "@semantic-release/npm"] },
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// ),
+// )),
+// ];
+//
+// t.is(errors[0].name, "SemanticReleaseError");
+// t.is(errors[0].code, "EINVALIDNPMPUBLISH");
+// t.is(errors[1].name, "SemanticReleaseError");
+// t.is(errors[1].code, "EINVALIDTARBALLDIR");
+// t.is(errors[2].name, "SemanticReleaseError");
+// t.is(errors[2].code, "EINVALIDPKGROOT");
+// t.is(errors[3].name, "SemanticReleaseError");
+// t.is(errors[3].code, "ENOPKG");
+// });
+//
+// test("Publish the package and add to default dist-tag", async (t) => {
+// const cwd = tempy.directory();
+// const environment = npmRegistry.authEnv;
+// const package_ = { name: "add-channel", publishConfig: { registry: npmRegistry.url }, version: "0.0.0" };
+// await outputJson(path.resolve(cwd, "package.json"), package_);
+//
+// await t.context.m.publish(
+// {},
+// {
+// cwd,
+// env: environment,
+// logger: t.context.logger,
+// nextRelease: { channel: "next", version: "1.0.0" },
+// options: {},
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// );
+//
+// const result = await t.context.m.addChannel(
+// {},
+// {
+// cwd,
+// env: environment,
+// logger: t.context.logger,
+// nextRelease: { version: "1.0.0" },
+// options: {},
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// );
+//
+// t.deepEqual(result, { channel: "latest", name: "npm package (@latest dist-tag)", url: undefined });
+// t.is((await execa("npm", ["view", package_.name, "dist-tags.latest"], { cwd, env: environment })).stdout, "1.0.0");
+// });
+//
+// test("Publish the package and add to lts dist-tag", async (t) => {
+// const cwd = tempy.directory();
+// const environment = npmRegistry.authEnv;
+// const package_ = { name: "add-channel-legacy", publishConfig: { registry: npmRegistry.url }, version: "1.0.0" };
+// await outputJson(path.resolve(cwd, "package.json"), package_);
+//
+// await t.context.m.publish(
+// {},
+// {
+// cwd,
+// env: environment,
+// logger: t.context.logger,
+// nextRelease: { channel: "latest", version: "1.0.0" },
+// options: {},
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// );
+//
+// const result = await t.context.m.addChannel(
+// {},
+// {
+// cwd,
+// env: environment,
+// logger: t.context.logger,
+// nextRelease: { channel: "1.x", version: "1.0.0" },
+// options: {},
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// );
+//
+// t.deepEqual(result, { channel: "release-1.x", name: "npm package (@release-1.x dist-tag)", url: undefined });
+// t.is((await execa("npm", ["view", package_.name, "dist-tags"], { cwd, env: environment })).stdout, "{ latest: '1.0.0', 'release-1.x': '1.0.0' }");
+// });
+//
+// test('Skip adding the package to a channel ("npmPublish" is false)', async (t) => {
+// const cwd = tempy.directory();
+// const environment = npmRegistry.authEnv;
+// const package_ = { name: "skip-add-channel", publishConfig: { registry: npmRegistry.url }, version: "0.0.0" };
+// await outputJson(path.resolve(cwd, "package.json"), package_);
+//
+// const result = await t.context.m.addChannel(
+// { npmPublish: false },
+// {
+// cwd,
+// env: environment,
+// logger: t.context.logger,
+// nextRelease: { version: "1.0.0" },
+// options: {},
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// );
+//
+// t.false(result);
+// await t.throwsAsync(execa("npm", ["view", package_.name, "version"], { cwd, env: environment }));
+// });
+//
+// test('Skip adding the package to a channel ("package.private" is true)', async (t) => {
+// const cwd = tempy.directory();
+// const environment = npmRegistry.authEnv;
+// const package_ = {
+// name: "skip-add-channel-private",
+// private: true,
+// publishConfig: { registry: npmRegistry.url },
+// version: "0.0.0",
+// };
+// await outputJson(path.resolve(cwd, "package.json"), package_);
+//
+// const result = await t.context.m.addChannel(
+// {},
+// {
+// cwd,
+// env: environment,
+// logger: t.context.logger,
+// nextRelease: { version: "1.0.0" },
+// options: {},
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// );
+//
+// t.false(result);
+// await t.throwsAsync(execa("npm", ["view", package_.name, "version"], { cwd, env: environment }));
+// });
+//
+// test("Create the package in addChannel step", async (t) => {
+// const cwd = tempy.directory();
+// const environment = npmRegistry.authEnv;
+// const package_ = { name: "add-channel-pkg", publishConfig: { registry: npmRegistry.url }, version: "0.0.0" };
+// await outputJson(path.resolve(cwd, "package.json"), package_);
+//
+// await t.context.m.prepare(
+// { npmPublish: false, tarballDir: "tarball" },
+// {
+// cwd,
+// env: environment,
+// logger: t.context.logger,
+// nextRelease: { version: "1.0.0" },
+// options: {},
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// );
+//
+// t.is((await readJson(path.resolve(cwd, "package.json"))).version, "1.0.0");
+// t.true(await pathExists(path.resolve(cwd, `tarball/${package_.name}-1.0.0.tgz`)));
+// });
+//
+// test("Throw SemanticReleaseError Array if config option are not valid in addChannel", async (t) => {
+// const cwd = tempy.directory();
+// const environment = npmRegistry.authEnv;
+// const package_ = { publishConfig: { registry: npmRegistry.url } };
+// await outputJson(path.resolve(cwd, "package.json"), package_);
+// const npmPublish = 42;
+// const tarballDir = 42;
+// const packageRoot = 42;
+//
+// const errors = [
+// ...(await t.throwsAsync(
+// t.context.m.addChannel(
+// { npmPublish, pkgRoot: packageRoot, tarballDir },
+// {
+// cwd,
+// env: environment,
+// logger: t.context.logger,
+// nextRelease: { version: "1.0.0" },
+// options: { publish: ["@semantic-release/github", "@semantic-release/npm"] },
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// ),
+// )),
+// ];
+//
+// t.is(errors[0].name, "SemanticReleaseError");
+// t.is(errors[0].code, "EINVALIDNPMPUBLISH");
+// t.is(errors[1].name, "SemanticReleaseError");
+// t.is(errors[1].code, "EINVALIDTARBALLDIR");
+// t.is(errors[2].name, "SemanticReleaseError");
+// t.is(errors[2].code, "EINVALIDPKGROOT");
+// t.is(errors[3].name, "SemanticReleaseError");
+// t.is(errors[3].code, "ENOPKG");
+// });
+//
+// test("Verify token and set up auth only on the fist call, then prepare on prepare call only", async (t) => {
+// const cwd = tempy.directory();
+// const environment = npmRegistry.authEnv;
+// const package_ = { name: "test-module", publishConfig: { registry: npmRegistry.url }, version: "0.0.0-dev" };
+// await outputJson(path.resolve(cwd, "package.json"), package_);
+//
+// await t.notThrowsAsync(
+// t.context.m.verifyConditions({}, { cwd, env: environment, logger: t.context.logger, options: {}, stderr: t.context.stderr, stdout: t.context.stdout }),
+// );
+// await t.context.m.prepare(
+// {},
+// {
+// cwd,
+// env: environment,
+// logger: t.context.logger,
+// nextRelease: { version: "1.0.0" },
+// options: {},
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// );
+//
+// let result = await t.context.m.publish(
+// {},
+// {
+// cwd,
+// env: environment,
+// logger: t.context.logger,
+// nextRelease: { channel: "next", version: "1.0.0" },
+// options: {},
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// );
+// t.deepEqual(result, { channel: "next", name: "npm package (@next dist-tag)", url: undefined });
+// t.is((await execa("npm", ["view", package_.name, "dist-tags.next"], { cwd, env: environment })).stdout, "1.0.0");
+//
+// result = await t.context.m.addChannel(
+// {},
+// {
+// cwd,
+// env: environment,
+// logger: t.context.logger,
+// nextRelease: { version: "1.0.0" },
+// options: {},
+// stderr: t.context.stderr,
+// stdout: t.context.stdout,
+// },
+// );
+//
+// t.deepEqual(result, { channel: "latest", name: "npm package (@latest dist-tag)", url: undefined });
+// t.is((await execa("npm", ["view", package_.name, "dist-tags.latest"], { cwd, env: environment })).stdout, "1.0.0");
+// });
diff --git a/packages/semantic-release-pnpm/__tests__/unit/prepare.test.ts b/packages/semantic-release-pnpm/__tests__/unit/prepare.test.ts
new file mode 100644
index 00000000..cdc4ee74
--- /dev/null
+++ b/packages/semantic-release-pnpm/__tests__/unit/prepare.test.ts
@@ -0,0 +1,147 @@
+import { rm } from "node:fs/promises";
+
+import { isAccessible, readFile, readJson, writeFile, writeJson } from "@visulima/fs";
+import type { PackageJson } from "@visulima/package";
+import { join } from "@visulima/path";
+import { execa } from "execa";
+import { WritableStreamBuffer } from "stream-buffers";
+import { temporaryDirectory } from "tempy";
+import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
+
+import type { PrepareContext } from "../../src/definitions/context";
+import prepare from "../../src/prepare";
+
+const logSpy = vi.fn();
+const logger = { error: vi.fn(), log: logSpy, success: vi.fn() };
+
+describe("prepare", () => {
+ let cwd: string;
+
+ beforeEach(async () => {
+ cwd = temporaryDirectory();
+ });
+
+ afterEach(async () => {
+ await rm(cwd, { recursive: true });
+ });
+
+ it("should update package.json", async () => {
+ expect.assertions(2);
+
+ const packagePath = join(cwd, "package.json");
+
+ await writeJson(packagePath, { name: "test", version: "0.0.0-dev" });
+
+ await prepare({}, {
+ cwd,
+ env: {},
+ logger,
+ nextRelease: { version: "1.0.0" },
+ stderr: new WritableStreamBuffer(),
+ stdout: new WritableStreamBuffer(),
+ } as unknown as PrepareContext);
+
+ const packageJson = await readJson(packagePath);
+
+ expect(packageJson.version).toBe("1.0.0");
+ expect(logSpy).toHaveBeenCalledWith("Write version %s to package.json in %s", "1.0.0", cwd);
+ });
+
+ it("should update package.json and npm-shrinkwrap.json", async () => {
+ expect.assertions(3);
+
+ const packagePath = join(cwd, "package.json");
+ const shrinkwrapPath = join(cwd, "npm-shrinkwrap.json");
+
+ await writeJson(packagePath, { version: "0.0.0-dev" });
+ // Create a npm-shrinkwrap.json file
+ await execa("npm", ["shrinkwrap"], { cwd });
+
+ await prepare({}, {
+ cwd,
+ env: {},
+ logger,
+ nextRelease: { version: "1.0.0" },
+ stderr: new WritableStreamBuffer(),
+ stdout: new WritableStreamBuffer(),
+ } as unknown as PrepareContext);
+
+ const packageJson = await readJson(packagePath);
+ const shrinkwrap = await readJson>(shrinkwrapPath);
+
+ expect(packageJson.version).toBe("1.0.0");
+ expect(shrinkwrap.version).toBe("1.0.0");
+ expect(logSpy).toHaveBeenCalledWith("Write version %s to package.json in %s", "1.0.0", cwd);
+ });
+
+ it("should preserve indentation and newline", async () => {
+ expect.assertions(2);
+
+ const packagePath = join(cwd, "package.json");
+ await writeFile(packagePath, `{\r\n "name": "package-name",\r\n "version": "0.0.0-dev"\r\n}\r\n`);
+
+ await prepare({}, {
+ cwd,
+ env: {},
+ logger,
+ nextRelease: { version: "1.0.0" },
+ stderr: new WritableStreamBuffer(),
+ stdout: new WritableStreamBuffer(),
+ } as unknown as PrepareContext);
+
+ const expectedContent = `{\r\n "name": "package-name",\r\n "version": "1.0.0"\r\n}\r\n`;
+
+ expect(logSpy).toHaveBeenCalledWith("Write version %s to package.json in %s", "1.0.0", cwd);
+ await expect(readFile(packagePath)).resolves.toStrictEqual(expectedContent);
+ });
+
+ it('should create the package in the "tarballDir" directory', async () => {
+ expect.assertions(3);
+
+ const packagePath = join(cwd, "package.json");
+ const packageInfo = { name: "my-pkg", version: "0.0.0-dev" };
+
+ await writeJson(packagePath, packageInfo);
+
+ await prepare({ tarballDir: "tarball" }, {
+ cwd,
+ env: {},
+ logger,
+ nextRelease: { version: "1.0.0" },
+ stderr: new WritableStreamBuffer(),
+ stdout: new WritableStreamBuffer(),
+ } as unknown as PrepareContext);
+
+ const tarballPath = join(cwd, `tarball/${packageInfo.name}-1.0.0.tgz`);
+ const packageJson = await readJson(packagePath);
+
+ expect(logSpy).toHaveBeenCalledWith("Write version %s to package.json in %s", "1.0.0", cwd);
+ expect(packageJson.version).toBe("1.0.0");
+ await expect(isAccessible(tarballPath)).resolves.toBeTruthy();
+ });
+
+ it('should only move the created tarball if the "tarballDir" directory is not the CWD', async () => {
+ expect.assertions(3);
+
+ const packagePath = join(cwd, "package.json");
+ const packageInfo = { name: "my-pkg", version: "0.0.0-dev" };
+
+ await writeJson(packagePath, packageInfo);
+
+ await prepare({ tarballDir: "." }, {
+ cwd,
+ env: {},
+ logger,
+ nextRelease: { version: "1.0.0" },
+ stderr: new WritableStreamBuffer(),
+ stdout: new WritableStreamBuffer(),
+ } as unknown as PrepareContext);
+
+ const tarballPath = join(cwd, `${packageInfo.name}-1.0.0.tgz`);
+ const packageJson = await readJson(packagePath);
+
+ expect(logSpy).toHaveBeenCalledWith("Write version %s to package.json in %s", "1.0.0", cwd);
+ expect(packageJson.version).toBe("1.0.0");
+ await expect(isAccessible(tarballPath)).resolves.toBeTruthy();
+ });
+});
diff --git a/packages/semantic-release-pnpm/__tests__/unit/utils/get-channel.test.ts b/packages/semantic-release-pnpm/__tests__/unit/utils/get-channel.test.ts
new file mode 100644
index 00000000..a8bc5ac5
--- /dev/null
+++ b/packages/semantic-release-pnpm/__tests__/unit/utils/get-channel.test.ts
@@ -0,0 +1,24 @@
+import { describe, expect, it } from "vitest";
+
+import getChannel from "../../../src/utils/get-channel";
+
+describe("getChannel", () => {
+ it("get default channel", () => {
+ expect.assertions(1);
+
+ expect(getChannel(undefined)).toBe("latest");
+ });
+
+ it("get passed channel if valid", () => {
+ expect.assertions(1);
+
+ expect(getChannel("next")).toBe("next");
+ });
+
+ it('prefix channel with "release-" if invalid', () => {
+ expect.assertions(2);
+
+ expect(getChannel("1.x")).toBe("release-1.x");
+ expect(getChannel("1.0.0")).toBe("release-1.0.0");
+ });
+});
diff --git a/packages/semantic-release-pnpm/__tests__/unit/utils/get-npmrc-path.test.ts b/packages/semantic-release-pnpm/__tests__/unit/utils/get-npmrc-path.test.ts
new file mode 100644
index 00000000..1f3efb1d
--- /dev/null
+++ b/packages/semantic-release-pnpm/__tests__/unit/utils/get-npmrc-path.test.ts
@@ -0,0 +1,108 @@
+import type SemanticReleaseError from "@semantic-release/error";
+import { ensureFileSync } from "@visulima/fs";
+import type AggregateError from "aggregate-error";
+import { beforeEach, describe, expect, it, vi } from "vitest";
+
+import getNpmrcPath from "../../../src/utils/get-npmrc-path";
+
+const mocks = vi.hoisted(() => {
+ return {
+ mockedEnsureFileSync: vi.fn(),
+ mockedFindCacheDirectorySync: vi.fn(),
+ mockedIsAccessibleSync: vi.fn(),
+ mockedResolve: vi.fn(),
+ };
+});
+
+vi.mock("@visulima/fs", () => {
+ return {
+ ensureFileSync: mocks.mockedEnsureFileSync,
+ isAccessibleSync: mocks.mockedIsAccessibleSync,
+ };
+});
+
+vi.mock("@visulima/package", () => {
+ return {
+ findCacheDirectorySync: mocks.mockedFindCacheDirectorySync,
+ };
+});
+
+vi.mock("@visulima/path", () => {
+ return {
+ resolve: mocks.mockedResolve,
+ };
+});
+
+describe("getNpmrcPath", () => {
+ const cwd = "/test/directory";
+ const npmrcPath = "/test/directory/.npmrc";
+
+ beforeEach(() => {
+ vi.clearAllMocks();
+
+ mocks.mockedResolve.mockReturnValue(npmrcPath);
+ });
+
+ it("should return NPM_CONFIG_USERCONFIG if it is set and accessible", () => {
+ expect.assertions(2);
+
+ const environment = { NPM_CONFIG_USERCONFIG: "/custom/path/.npmrc" };
+
+ mocks.mockedIsAccessibleSync.mockReturnValueOnce(true);
+
+ const result = getNpmrcPath(cwd, environment);
+
+ expect(result).toBe(environment.NPM_CONFIG_USERCONFIG);
+ expect(mocks.mockedIsAccessibleSync).toHaveBeenCalledWith(environment.NPM_CONFIG_USERCONFIG);
+ });
+
+ it("should return the resolved .npmrc path if it is accessible", () => {
+ expect.assertions(2);
+
+ const environment = {};
+
+ mocks.mockedIsAccessibleSync.mockImplementation((path: string) => path === npmrcPath);
+
+ const result = getNpmrcPath(cwd, environment);
+
+ expect(result).toBe(npmrcPath);
+ expect(mocks.mockedIsAccessibleSync).toHaveBeenCalledWith(npmrcPath);
+ });
+
+ it("should create and return a temporary npmrc path if no other .npmrc is accessible", () => {
+ expect.assertions(3);
+
+ const environment = {};
+ const temporaryNpmrcPath = "/temporary/directory/.npmrc";
+
+ mocks.mockedIsAccessibleSync.mockReturnValue(false);
+ mocks.mockedFindCacheDirectorySync.mockReturnValue(temporaryNpmrcPath);
+
+ const result = getNpmrcPath(cwd, environment);
+
+ expect(result).toBe(temporaryNpmrcPath);
+ expect(mocks.mockedFindCacheDirectorySync).toHaveBeenCalledWith("semantic-release-pnpm", { create: true, cwd });
+ expect(ensureFileSync).toHaveBeenCalledWith(temporaryNpmrcPath);
+ });
+
+ it("should throw an error if no .npmrc is found or accessible", () => {
+ expect.assertions(2);
+
+ const environment = {};
+
+ mocks.mockedIsAccessibleSync.mockReturnValue(false);
+ mocks.mockedFindCacheDirectorySync.mockReturnValue(undefined);
+
+ try {
+ getNpmrcPath(cwd, environment);
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (error: any) {
+ const typedError = error as AggregateError;
+
+ // eslint-disable-next-line vitest/no-conditional-expect
+ expect((typedError.errors[0] as SemanticReleaseError).message).toBe("Missing `.npmrc` file.");
+ // eslint-disable-next-line vitest/no-conditional-expect
+ expect((typedError.errors[0] as SemanticReleaseError).code).toBe("ENOPNPMRC");
+ }
+ });
+});
diff --git a/packages/semantic-release-pnpm/__tests__/unit/utils/get-pkg.test.ts b/packages/semantic-release-pnpm/__tests__/unit/utils/get-pkg.test.ts
new file mode 100644
index 00000000..d9dc5901
--- /dev/null
+++ b/packages/semantic-release-pnpm/__tests__/unit/utils/get-pkg.test.ts
@@ -0,0 +1,92 @@
+// eslint-disable-next-line unicorn/prevent-abbreviations
+import { rm } from "node:fs/promises";
+
+import { writeFile, writeJson } from "@visulima/fs";
+import { resolve } from "@visulima/path";
+import { temporaryDirectory } from "tempy";
+import { afterEach, beforeEach, describe, expect, it } from "vitest";
+
+import getPackage from "../../../src/utils/get-pkg";
+
+describe("get-pkg", () => {
+ let cwd: string;
+
+ beforeEach(async () => {
+ cwd = temporaryDirectory();
+ });
+
+ afterEach(async () => {
+ await rm(cwd, { recursive: true });
+ });
+
+ it("verify name and version then return parsed package.json", async () => {
+ expect.assertions(2);
+
+ const packageJson = { name: "package", version: "0.0.0" };
+ await writeJson(resolve(cwd, "package.json"), packageJson);
+
+ const result = await getPackage({}, { cwd });
+
+ expect(result.name).toBe(packageJson.name);
+ expect(result.version).toBe(packageJson.version);
+ });
+
+ it("verify name and version then return parsed package.json from a sub-directory", async () => {
+ expect.assertions(2);
+
+ const packageRoot = "dist";
+ const packageJson = { name: "package", version: "0.0.0" };
+ await writeJson(resolve(cwd, packageRoot, "package.json"), packageJson);
+
+ const result = await getPackage({ pkgRoot: packageRoot }, { cwd });
+
+ expect(result.name).toBe(packageJson.name);
+ expect(result.version).toBe(packageJson.version);
+ });
+
+ it("throw error if missing package.json", async () => {
+ expect.assertions(3);
+
+ try {
+ await getPackage({}, { cwd });
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (error: any) {
+ const typeError = error as AggregateError;
+
+ // eslint-disable-next-line vitest/no-conditional-expect
+ expect(typeError.name).toBe("AggregateError");
+ // eslint-disable-next-line vitest/no-conditional-expect
+ expect(typeError.message).toContain("Missing `package.json` file.");
+ // eslint-disable-next-line vitest/no-conditional-expect
+ expect(typeError.errors[0].code).toBe("ENOPKG");
+ }
+ });
+
+ it("throw error if missing package name", async () => {
+ expect.assertions(3);
+
+ await writeJson(resolve(cwd, "package.json"), { version: "0.0.0" });
+
+ try {
+ await getPackage({}, { cwd });
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (error: any) {
+ const typeError = error as AggregateError;
+
+ // eslint-disable-next-line vitest/no-conditional-expect
+ expect(typeError.name).toBe("AggregateError");
+ // eslint-disable-next-line vitest/no-conditional-expect
+ expect(typeError.message).toContain("Missing `name` property in `package.json`");
+ // eslint-disable-next-line vitest/no-conditional-expect
+ expect(typeError.errors[0].code).toBe("ENOPKGNAME");
+ }
+ });
+
+ it("throw error if package.json is malformed", async () => {
+ expect.assertions(1);
+
+ await writeFile(resolve(cwd, "package.json"), "{name: 'package',}");
+
+ await expect(getPackage({}, { cwd })).rejects.toThrow("JSON at position 1");
+ });
+});
diff --git a/packages/semantic-release-pnpm/__tests__/unit/utils/get-registry.test.ts b/packages/semantic-release-pnpm/__tests__/unit/utils/get-registry.test.ts
new file mode 100644
index 00000000..9c821f3d
--- /dev/null
+++ b/packages/semantic-release-pnpm/__tests__/unit/utils/get-registry.test.ts
@@ -0,0 +1,78 @@
+import { rm } from "node:fs/promises";
+
+import { writeFile } from "@visulima/fs";
+import { resolve } from "@visulima/path";
+import { temporaryDirectory } from "tempy";
+import { afterEach, beforeEach, describe, expect, it } from "vitest";
+
+import getRegistry from "../../../src/utils/get-registry";
+
+describe("getRegistry", () => {
+ let cwd: string;
+
+ beforeEach(async () => {
+ cwd = temporaryDirectory();
+ });
+
+ afterEach(async () => {
+ await rm(cwd, { recursive: true });
+ });
+
+ it("get default registry", () => {
+ expect.assertions(2);
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ expect(getRegistry({ name: "package-name" }, { cwd, env: {} } as any)).toBe("https://registry.npmjs.org/");
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ expect(getRegistry({ name: "package-name", publishConfig: {} }, { cwd, env: {} } as any)).toBe("https://registry.npmjs.org/");
+ });
+
+ it('get the registry configured in ".npmrc" and normalize trailing slash', async () => {
+ expect.assertions(1);
+
+ await writeFile(resolve(cwd, ".npmrc"), "registry = https://custom1.registry.com");
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ expect(getRegistry({ name: "package-name" }, { cwd, env: {} } as any)).toBe("https://custom1.registry.com/");
+ });
+
+ it('get the registry configured from "publishConfig"', async () => {
+ expect.assertions(1);
+
+ await writeFile(resolve(cwd, ".npmrc"), "registry = https://custom2.registry.com");
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ expect(getRegistry({ name: "package-name", publishConfig: { registry: "https://custom3.registry.com/" } }, { cwd, env: {} } as any)).toBe(
+ "https://custom3.registry.com/",
+ );
+ });
+
+ it('get the registry configured in "NPM_CONFIG_REGISTRY"', () => {
+ expect.assertions(1);
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ expect(getRegistry({ name: "package-name" }, { cwd, env: { NPM_CONFIG_REGISTRY: "https://custom1.registry.com/" } } as any)).toBe(
+ "https://custom1.registry.com/",
+ );
+ });
+
+ it('get the registry configured in ".npmrc" for scoped package', async () => {
+ expect.assertions(1);
+
+ await writeFile(resolve(cwd, ".npmrc"), "@scope:registry = https://custom3.registry.com");
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ expect(getRegistry({ name: "@scope/package-name" }, { cwd, env: {} } as any)).toBe("https://custom3.registry.com/");
+ });
+
+ it('get the registry configured via "NPM_CONFIG_USERCONFIG" for scoped package', async () => {
+ expect.assertions(1);
+
+ await writeFile(resolve(cwd, ".custom-npmrc"), "@scope:registry = https://custom4.registry.com");
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ expect(getRegistry({ name: "@scope/package-name" }, { cwd, env: { NPM_CONFIG_USERCONFIG: resolve(cwd, ".custom-npmrc") } } as any)).toBe(
+ "https://custom4.registry.com/",
+ );
+ });
+});
diff --git a/packages/semantic-release-pnpm/__tests__/unit/utils/get-release-info.test.ts b/packages/semantic-release-pnpm/__tests__/unit/utils/get-release-info.test.ts
new file mode 100644
index 00000000..e0b26e32
--- /dev/null
+++ b/packages/semantic-release-pnpm/__tests__/unit/utils/get-release-info.test.ts
@@ -0,0 +1,40 @@
+import { describe, expect, it } from "vitest";
+
+import type { PublishContext } from "../../../src/definitions/context";
+import { getReleaseInfo } from "../../../src/utils/get-release-info";
+
+describe("getReleaseInfo", () => {
+ it("default registry and scoped module", async () => {
+ expect.assertions(1);
+
+ expect(
+ getReleaseInfo(
+ { name: "@scope/module" },
+ { env: {}, nextRelease: { version: "1.0.0" } } as PublishContext,
+ "latest",
+ "https://registry.npmjs.org/",
+ ),
+ ).toStrictEqual({
+ channel: "latest",
+ name: "pnpm package (@latest dist-tag)",
+ url: "https://www.npmjs.com/package/@scope/module/v/1.0.0",
+ });
+ });
+
+ it("custom registry and scoped module", async () => {
+ expect.assertions(1);
+
+ expect(
+ getReleaseInfo(
+ { name: "@scope/module" },
+ { env: {}, nextRelease: { version: "1.0.0" } } as PublishContext,
+ "latest",
+ "https://custom.registry.org/",
+ ),
+ ).toStrictEqual({
+ channel: "latest",
+ name: "pnpm package (@latest dist-tag)",
+ url: undefined,
+ });
+ });
+});
diff --git a/packages/semantic-release-pnpm/__tests__/unit/utils/set-npmrc-auth.test.ts b/packages/semantic-release-pnpm/__tests__/unit/utils/set-npmrc-auth.test.ts
new file mode 100644
index 00000000..4029ad9f
--- /dev/null
+++ b/packages/semantic-release-pnpm/__tests__/unit/utils/set-npmrc-auth.test.ts
@@ -0,0 +1,311 @@
+import { rm } from "node:fs/promises";
+import { env } from "node:process";
+
+import { readFile, writeFile } from "@visulima/fs";
+import { resolve } from "@visulima/path";
+import { temporaryDirectory, temporaryFile } from "tempy";
+import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
+
+const setNpmrcAuthFilePath = "../../../src/utils/set-npmrc-auth";
+
+const logSpy = vi.fn();
+const logger = { log: logSpy };
+
+const homeDirectorySpy = vi.fn();
+
+vi.mock("node:os", () => {
+ return {
+ homedir: homeDirectorySpy,
+ };
+});
+
+describe("set-npmrc-auth", () => {
+ let cwd: string;
+ let home: string;
+ const npmEnvironment: Record = {};
+
+ beforeEach(() => {
+ cwd = temporaryDirectory();
+ home = temporaryDirectory();
+
+ homeDirectorySpy.mockReturnValue(home);
+
+ // eslint-disable-next-line no-loops/no-loops,no-restricted-syntax
+ for (const key in env) {
+ if (key.startsWith("npm_")) {
+ // eslint-disable-next-line security/detect-object-injection
+ npmEnvironment[key as keyof typeof env] = env[key];
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete,security/detect-object-injection
+ delete env[key];
+ }
+ }
+ });
+
+ afterEach(async () => {
+ vi.resetAllMocks();
+
+ // eslint-disable-next-line no-loops/no-loops,no-restricted-syntax,guard-for-in
+ for (const key in npmEnvironment) {
+ // eslint-disable-next-line security/detect-object-injection
+ env[key] = npmEnvironment[key];
+ }
+
+ await rm(cwd, { recursive: true });
+ await rm(home, { recursive: true });
+ });
+
+ it('should set auth with "NPM_TOKEN"', async () => {
+ expect.assertions(2);
+
+ const npmrc = temporaryFile({ name: ".npmrc" });
+
+ const setNpmrcAuth = await import(setNpmrcAuthFilePath).then((m) => m.default);
+
+ await setNpmrcAuth(npmrc, "http://custom.registry.com", { cwd, env: { NPM_TOKEN: "npm_token" }, logger });
+
+ expect(logSpy).toHaveBeenCalledWith(`Wrote NPM_TOKEN to ${npmrc}`);
+
+ // eslint-disable-next-line no-template-curly-in-string
+ await expect(readFile(npmrc)).resolves.toBe("registry=https://registry.npmjs.org/\n\n//custom.registry.com/:_authToken = ${NPM_TOKEN}");
+ });
+
+ it('should set auth with "NPM_USERNAME", "NPM_PASSWORD" and "NPM_EMAIL"', async () => {
+ expect.assertions(2);
+
+ const npmrc = temporaryFile({ name: ".npmrc" });
+
+ const setNpmrcAuth = await import(setNpmrcAuthFilePath).then((m) => m.default);
+
+ await setNpmrcAuth(npmrc, "http://custom.registry.com", {
+ cwd,
+ env: { NPM_EMAIL: "npm_email", NPM_PASSWORD: "npm_pasword", NPM_USERNAME: "npm_username" },
+ logger,
+ });
+
+ expect(logSpy).toHaveBeenCalledWith(`Wrote NPM_USERNAME, NPM_PASSWORD, and NPM_EMAIL to ${npmrc}`);
+
+ await expect(readFile(npmrc)).resolves.toBe(`registry=https://registry.npmjs.org/\n\n_auth = \${LEGACY_TOKEN}\nemail = \${NPM_EMAIL}`);
+ });
+
+ it('should preserve home ".npmrc"', async () => {
+ expect.assertions(3);
+
+ const npmrc = temporaryFile({ name: ".npmrc" });
+
+ await writeFile(resolve(home, ".npmrc"), "home_config = test");
+
+ const setNpmrcAuth = await import(setNpmrcAuthFilePath).then((m) => m.default);
+
+ await setNpmrcAuth(npmrc, "http://custom.registry.com", { cwd, env: { NPM_TOKEN: "npm_token" }, logger });
+
+ expect(logSpy.mock.calls[1]).toStrictEqual(["Reading npm config from %s", [resolve(home, ".npmrc")].join(", ")]);
+ expect(logSpy.mock.calls[2]).toStrictEqual([`Wrote NPM_TOKEN to ${npmrc}`]);
+
+ await expect(readFile(npmrc)).resolves.toBe(
+ `registry=https://registry.npmjs.org/\nhome_config=test\n\n//custom.registry.com/:_authToken = \${NPM_TOKEN}`,
+ );
+ });
+
+ it('should preserve home and local ".npmrc"', async () => {
+ expect.assertions(3);
+
+ const npmrc = temporaryFile({ name: ".npmrc" });
+
+ await writeFile(resolve(cwd, ".npmrc"), "cwd_config = test");
+ await writeFile(resolve(home, ".npmrc"), "home_config = test");
+
+ const setNpmrcAuth = await import(setNpmrcAuthFilePath).then((m) => m.default);
+
+ await setNpmrcAuth(npmrc, "http://custom.registry.com", { cwd, env: { NPM_TOKEN: "npm_token" }, logger });
+
+ expect(logSpy.mock.calls[1]).toStrictEqual(["Reading npm config from %s", [resolve(home, ".npmrc"), resolve(cwd, ".npmrc")].join(", ")]);
+ expect(logSpy.mock.calls[2]).toStrictEqual([`Wrote NPM_TOKEN to ${npmrc}`]);
+
+ await expect(readFile(npmrc)).resolves.toBe(
+ `registry=https://registry.npmjs.org/\nhome_config=test\ncwd_config=test\n\n//custom.registry.com/:_authToken = \${NPM_TOKEN}`,
+ );
+ });
+
+ it('should preserve all ".npmrc" if auth is already configured', async () => {
+ expect.assertions(2);
+
+ const npmrc = temporaryFile({ name: ".npmrc" });
+
+ await writeFile(resolve(cwd, ".npmrc"), `//custom.registry.com/:_authToken = \${NPM_TOKEN}`);
+ await writeFile(resolve(home, ".npmrc"), "home_config = test");
+
+ const setNpmrcAuth = await import(setNpmrcAuthFilePath).then((m) => m.default);
+
+ await setNpmrcAuth(npmrc, "http://custom.registry.com", { cwd, env: {}, logger });
+
+ expect(logSpy.mock.calls[1]).toStrictEqual(["Reading npm config from %s", [resolve(home, ".npmrc"), resolve(cwd, ".npmrc")].join(", ")]);
+ await expect(readFile(npmrc)).resolves.toBe(
+ `registry=https://registry.npmjs.org/\nhome_config=test\n//custom.registry.com/:_authToken=\${NPM_TOKEN}\n`,
+ );
+ });
+
+ it('should preserve ".npmrc" if auth is already configured for a scoped package', async () => {
+ expect.assertions(2);
+
+ const npmrc = temporaryFile({ name: ".npmrc" });
+
+ await writeFile(resolve(cwd, ".npmrc"), `@scope:registry=http://custom.registry.com\n//custom.registry.com/:_authToken = \${NPM_TOKEN}`);
+ await writeFile(resolve(home, ".npmrc"), "home_config = test");
+
+ const setNpmrcAuth = await import(setNpmrcAuthFilePath).then((m) => m.default);
+
+ await setNpmrcAuth(npmrc, "http://custom.registry.com", { cwd, env: {}, logger });
+
+ expect(logSpy.mock.calls[1]).toStrictEqual(["Reading npm config from %s", [resolve(home, ".npmrc"), resolve(cwd, ".npmrc")].join(", ")]);
+ await expect(readFile(npmrc)).resolves.toBe(
+ `registry=https://registry.npmjs.org/\nhome_config=test\n@scope:registry=http://custom.registry.com\n//custom.registry.com/:_authToken=\${NPM_TOKEN}\n`,
+ );
+ });
+
+ it('should throw error if "NPM_TOKEN" is missing', async () => {
+ expect.assertions(3);
+
+ const npmrc = temporaryFile({ name: ".npmrc" });
+
+ const errorMessage = "No npm token specified.";
+
+ try {
+ const setNpmrcAuth = await import(setNpmrcAuthFilePath).then((m) => m.default);
+
+ await setNpmrcAuth(npmrc, "http://custom.registry.com", { cwd, env: {}, logger });
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (error: any) {
+ const typeError = error as AggregateError;
+
+ // eslint-disable-next-line vitest/no-conditional-expect
+ expect(typeError.name).toBe("AggregateError");
+ // eslint-disable-next-line vitest/no-conditional-expect
+ expect(typeError.message).toContain(errorMessage);
+ // eslint-disable-next-line vitest/no-conditional-expect
+ expect(typeError.errors[0].code).toBe("ENONPMTOKEN");
+ }
+ });
+
+ it('should emulate npm config resolution if "NPM_CONFIG_USERCONFIG" is set', async () => {
+ expect.assertions(2);
+
+ const npmrc = temporaryFile({ name: ".npmrc" });
+
+ const customNpmrcPath = resolve(cwd, ".custom-npmrc");
+ await writeFile(customNpmrcPath, `//custom.registry.com/:_authToken = \${NPM_TOKEN}`);
+
+ const environment = { NPM_CONFIG_USERCONFIG: customNpmrcPath };
+
+ const setNpmrcAuth = await import(setNpmrcAuthFilePath).then((m) => m.default);
+
+ await setNpmrcAuth(npmrc, "http://custom.registry.com", {
+ cwd,
+ env: environment,
+ logger,
+ });
+
+ expect(logSpy.mock.calls[1]).toStrictEqual(["Reading npm config from %s", customNpmrcPath]);
+ await expect(readFile(npmrc)).resolves.toBe(`registry=https://registry.npmjs.org/\n//custom.registry.com/:_authToken=\${NPM_TOKEN}\n`);
+ });
+
+ it('should throw error if "NPM_USERNAME" is missing', async () => {
+ expect.assertions(3);
+
+ const npmrc = temporaryFile({ name: ".npmrc" });
+ const environment = { NPM_EMAIL: "npm_email", NPM_PASSWORD: "npm_password" };
+
+ const errorMessage = "No npm token specified.";
+
+ try {
+ const setNpmrcAuth = await import(setNpmrcAuthFilePath).then((m) => m.default);
+
+ await setNpmrcAuth(npmrc, "http://custom.registry.com", { cwd, env: environment, logger });
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (error: any) {
+ const typeError = error as AggregateError;
+
+ // eslint-disable-next-line vitest/no-conditional-expect
+ expect(typeError.name).toBe("AggregateError");
+ // eslint-disable-next-line vitest/no-conditional-expect
+ expect(typeError.message).toContain(errorMessage);
+ // eslint-disable-next-line vitest/no-conditional-expect
+ expect(typeError.errors[0].code).toBe("ENONPMTOKEN");
+ }
+ });
+
+ it('should throw error if "NPM_PASSWORD" is missing', async () => {
+ expect.assertions(3);
+
+ const npmrc = temporaryFile({ name: ".npmrc" });
+ const environment = { NPM_EMAIL: "npm_email", NPM_USERNAME: "npm_username" };
+
+ const errorMessage = "No npm token specified.";
+
+ try {
+ const setNpmrcAuth = await import(setNpmrcAuthFilePath).then((m) => m.default);
+
+ await setNpmrcAuth(npmrc, "http://custom.registry.com", { cwd, env: environment, logger });
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (error: any) {
+ const typeError = error as AggregateError;
+
+ // eslint-disable-next-line vitest/no-conditional-expect
+ expect(typeError.name).toBe("AggregateError");
+ // eslint-disable-next-line vitest/no-conditional-expect
+ expect(typeError.message).toContain(errorMessage);
+ // eslint-disable-next-line vitest/no-conditional-expect
+ expect(typeError.errors[0].code).toBe("ENONPMTOKEN");
+ }
+ });
+
+ it('should throw error if "NPM_EMAIL" is missing', async () => {
+ expect.assertions(3);
+
+ const npmrc = temporaryFile({ name: ".npmrc" });
+ const environment = { NPM_PASSWORD: "npm_password", NPM_USERNAME: "npm_username" };
+
+ const errorMessage = "No npm token specified.";
+
+ try {
+ const setNpmrcAuth = await import(setNpmrcAuthFilePath).then((m) => m.default);
+
+ await setNpmrcAuth(npmrc, "http://custom.registry.com", { cwd, env: environment, logger });
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (error: any) {
+ const typeError = error as AggregateError;
+
+ // eslint-disable-next-line vitest/no-conditional-expect
+ expect(typeError.name).toBe("AggregateError");
+ // eslint-disable-next-line vitest/no-conditional-expect
+ expect(typeError.message).toContain(errorMessage);
+ // eslint-disable-next-line vitest/no-conditional-expect
+ expect(typeError.errors[0].code).toBe("ENONPMTOKEN");
+ }
+ });
+
+ it("prefer .npmrc over environment variables", async () => {
+ expect.assertions(4);
+
+ const npmrc = temporaryFile({ name: ".npmrc" });
+ // Specify an NPM token environment variable
+ const environment = { NPM_TOKEN: "env_npm_token" };
+
+ await writeFile(resolve(cwd, ".npmrc"), "//registry.npmjs.org/:_authToken=npmrc_npm_token");
+
+ const setNpmrcAuth = await import(setNpmrcAuthFilePath).then((m) => m.default);
+
+ await setNpmrcAuth(npmrc, "http://registry.npmjs.org", { cwd, env: environment, logger });
+
+ // Assert that the token from .npmrc is used
+ await expect(readFile(npmrc)).resolves.toBe(`registry=https://registry.npmjs.org/\n//registry.npmjs.org/:_authToken=npmrc_npm_token\n`);
+
+ // Assert that the log indicates reading from .npmrc
+ expect(logSpy.mock.calls[1]).toStrictEqual(["Reading npm config from %s", resolve(cwd, ".npmrc")]);
+
+ // Assert that NPM_TOKEN is not written
+ // eslint-disable-next-line no-loops/no-loops,no-restricted-syntax
+ for (const log of logSpy.mock.calls) {
+ expect(log).not.toStrictEqual(expect.stringContaining("Wrote NPM_TOKEN"));
+ }
+ });
+});
diff --git a/packages/semantic-release-pnpm/__tests__/unit/utils/should-publish.test.ts b/packages/semantic-release-pnpm/__tests__/unit/utils/should-publish.test.ts
new file mode 100644
index 00000000..21dac8a3
--- /dev/null
+++ b/packages/semantic-release-pnpm/__tests__/unit/utils/should-publish.test.ts
@@ -0,0 +1,97 @@
+import type { PackageJson } from "@visulima/package";
+import { describe, expect, it } from "vitest";
+
+import type { PluginConfig } from "../../../src/definitions/plugin-config";
+import { reasonToNotPublish, shouldPublish } from "../../../src/utils/should-publish";
+
+describe("reasonToNotPublish", () => {
+ it('should return "npmPublish plugin option is false" when npmPublish is false', () => {
+ expect.assertions(1);
+
+ const pluginConfig: PluginConfig = { npmPublish: false };
+ const packageJson: PackageJson = { name: "test-package" };
+
+ const result = reasonToNotPublish(pluginConfig, packageJson);
+
+ expect(result).toBe("npmPublish plugin option is false");
+ });
+
+ it('should return "package is private and has no workspaces" when package is private and has no workspaces', () => {
+ expect.assertions(1);
+
+ const pluginConfig: PluginConfig = { npmPublish: true };
+ const packageJson: PackageJson = { name: "test-package", private: true };
+
+ const result = reasonToNotPublish(pluginConfig, packageJson);
+
+ expect(result).toBe("package is private and has no workspaces");
+ });
+
+ it("should return null when npmPublish is true, package is not private, and has no workspaces", () => {
+ expect.assertions(1);
+
+ const pluginConfig: PluginConfig = { npmPublish: true };
+ const packageJson: PackageJson = { name: "test-package" };
+
+ const result = reasonToNotPublish(pluginConfig, packageJson);
+
+ expect(result).toBeNull();
+ });
+
+ it("should return null when package is private but has workspaces", () => {
+ expect.assertions(1);
+
+ const pluginConfig: PluginConfig = { npmPublish: true };
+ const packageJson: PackageJson = { name: "test-package", private: true, workspaces: ["packages/*"] };
+
+ const result = reasonToNotPublish(pluginConfig, packageJson);
+
+ expect(result).toBeNull();
+ });
+});
+
+describe("shouldPublish", () => {
+ it("should return false when npmPublish is false", () => {
+ expect.assertions(1);
+
+ const pluginConfig: PluginConfig = { npmPublish: false };
+ const packageJson: PackageJson = { name: "test-package" };
+
+ const result = shouldPublish(pluginConfig, packageJson);
+
+ expect(result).toBeFalsy();
+ });
+
+ it("should return false when package is private and has no workspaces", () => {
+ expect.assertions(1);
+
+ const pluginConfig: PluginConfig = { npmPublish: true };
+ const packageJson: PackageJson = { name: "test-package", private: true };
+
+ const result = shouldPublish(pluginConfig, packageJson);
+
+ expect(result).toBeFalsy();
+ });
+
+ it("should return true when npmPublish is true, package is not private, and has no workspaces", () => {
+ expect.assertions(1);
+
+ const pluginConfig: PluginConfig = { npmPublish: true };
+ const packageJson: PackageJson = { name: "test-package" };
+
+ const result = shouldPublish(pluginConfig, packageJson);
+
+ expect(result).toBeTruthy();
+ });
+
+ it("should return true when package is private but has workspaces", () => {
+ expect.assertions(1);
+
+ const pluginConfig: PluginConfig = { npmPublish: true };
+ const packageJson: PackageJson = { name: "test-package", private: true, workspaces: ["packages/*"] };
+
+ const result = shouldPublish(pluginConfig, packageJson);
+
+ expect(result).toBeTruthy();
+ });
+});
diff --git a/packages/semantic-release-pnpm/__tests__/unit/verify/verify-config.test.ts b/packages/semantic-release-pnpm/__tests__/unit/verify/verify-config.test.ts
new file mode 100644
index 00000000..0d1f5df7
--- /dev/null
+++ b/packages/semantic-release-pnpm/__tests__/unit/verify/verify-config.test.ts
@@ -0,0 +1,81 @@
+import type SemanticReleaseError from "@semantic-release/error";
+import { describe, expect, it } from "vitest";
+
+import type { PluginConfig } from "../../../src/definitions/plugin-config";
+import verifyConfig from "../../../src/verify/verify-config";
+
+describe("verify-config", () => {
+ it('verify "npmPublish", "tarballDir" and "pkgRoot" options', async () => {
+ expect.assertions(1);
+
+ expect(verifyConfig({ npmPublish: true, pkgRoot: "dist", tarballDir: "release" })).toStrictEqual([]);
+ });
+
+ it('return SemanticReleaseError if "npmPublish" option is not a Boolean', async () => {
+ expect.assertions(3);
+
+ const npmPublish = 42;
+ const [error, ...errors] = verifyConfig({ npmPublish } as unknown as PluginConfig);
+
+ expect(errors).toHaveLength(0);
+ expect((error as SemanticReleaseError).name).toBe("SemanticReleaseError");
+ expect((error as SemanticReleaseError).code).toBe("EINVALIDNPMPUBLISH");
+ });
+
+ it('return SemanticReleaseError if "tarballDir" option is not a String', async () => {
+ expect.assertions(3);
+
+ // eslint-disable-next-line unicorn/prevent-abbreviations
+ const tarballDir = 42;
+ const [error, ...errors] = verifyConfig({ tarballDir } as unknown as PluginConfig);
+
+ expect(errors).toHaveLength(0);
+ expect((error as SemanticReleaseError).name).toBe("SemanticReleaseError");
+ expect((error as SemanticReleaseError).code).toBe("EINVALIDTARBALLDIR");
+ });
+
+ it('return SemanticReleaseError if "pkgRoot" option is not a String', async () => {
+ expect.assertions(3);
+
+ const packageRoot = 42;
+ const [error, ...errors] = verifyConfig({ pkgRoot: packageRoot } as unknown as PluginConfig);
+
+ expect(errors).toHaveLength(0);
+ expect((error as SemanticReleaseError).name).toBe("SemanticReleaseError");
+ expect((error as SemanticReleaseError).code).toBe("EINVALIDPKGROOT");
+ });
+
+ it('return SemanticReleaseError if "publishBranch" option is not a String', async () => {
+ expect.assertions(3);
+
+ const publishBranch = 42;
+ const [error, ...errors] = verifyConfig({ publishBranch } as unknown as PluginConfig);
+
+ expect(errors).toHaveLength(0);
+ expect((error as SemanticReleaseError).name).toBe("SemanticReleaseError");
+ expect((error as SemanticReleaseError).code).toBe("EINVALIDPUBLISHBRANCH");
+ });
+
+ it("return SemanticReleaseError Array if multiple config are invalid", async () => {
+ expect.assertions(8);
+
+ const npmPublish = 42;
+ // eslint-disable-next-line unicorn/prevent-abbreviations
+ const tarballDir = 42;
+ const packageRoot = 42;
+ const publishBranch = 42;
+ const [error1, error2, error3, error4] = verifyConfig({ npmPublish, pkgRoot: packageRoot, publishBranch, tarballDir } as unknown as PluginConfig);
+
+ expect((error1 as SemanticReleaseError).name).toBe("SemanticReleaseError");
+ expect((error1 as SemanticReleaseError).code).toBe("EINVALIDNPMPUBLISH");
+
+ expect((error2 as SemanticReleaseError).name).toBe("SemanticReleaseError");
+ expect((error2 as SemanticReleaseError).code).toBe("EINVALIDPKGROOT");
+
+ expect((error3 as SemanticReleaseError).name).toBe("SemanticReleaseError");
+ expect((error3 as SemanticReleaseError).code).toBe("EINVALIDPUBLISHBRANCH");
+
+ expect((error4 as SemanticReleaseError).name).toBe("SemanticReleaseError");
+ expect((error4 as SemanticReleaseError).code).toBe("EINVALIDTARBALLDIR");
+ });
+});
diff --git a/packages/semantic-release-pnpm/package.json b/packages/semantic-release-pnpm/package.json
new file mode 100644
index 00000000..aba66263
--- /dev/null
+++ b/packages/semantic-release-pnpm/package.json
@@ -0,0 +1,144 @@
+{
+ "name": "@anolilab/semantic-release-pnpm",
+ "version": "0.0.0",
+ "description": "Semantic-release plugin to publish a npm package with pnpm.",
+ "keywords": [
+ "anolilab",
+ "npm",
+ "pnpm",
+ "publish",
+ "monorepo",
+ "semantic-release",
+ "semantic-release-plugin",
+ "semantic-release-pnpm"
+ ],
+ "homepage": "https://github.com/anolilab/semantic-release/tree/main/packages/semantic-release-pnpm",
+ "bugs": {
+ "url": "https://github.com/anolilab/semantic-release/issues"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/anolilab/semantic-release.git",
+ "directory": "packages/semantic-release-pnpm"
+ },
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/prisis"
+ },
+ {
+ "type": "consulting",
+ "url": "https://anolilab.com/support"
+ }
+ ],
+ "license": "MIT",
+ "author": {
+ "name": "Daniel Bannert",
+ "email": "d.bannert@anolilab.de"
+ },
+ "sideEffects": false,
+ "type": "module",
+ "exports": "./dist/index.js",
+ "main": "dist/index.js",
+ "types": "dist/index.d.ts",
+ "files": [
+ "dist",
+ "README.md",
+ "CHANGELOG.md"
+ ],
+ "scripts": {
+ "build": "cross-env NODE_ENV=development tsup",
+ "build:prod": "cross-env NODE_ENV=production tsup",
+ "clean": "rimraf node_modules dist .eslintcache",
+ "dev": "pnpm run build --watch",
+ "lint:eslint": "eslint . --ext js,cjs,mjs,jsx,ts,tsx,json,yaml,yml,md,mdx --max-warnings=0 --config .eslintrc.cjs",
+ "lint:eslint:fix": "eslint . --ext js,cjs,mjs,jsx,ts,tsx,json,yaml,yml,md,mdx --max-warnings=0 --config .eslintrc.cjs --fix",
+ "lint:package-json": "publint --strict",
+ "lint:prettier": "prettier --config=.prettierrc.cjs --check .",
+ "lint:prettier:fix": "prettier --config=.prettierrc.cjs --write .",
+ "lint:types": "tsc --noEmit",
+ "test": "vitest run",
+ "test:coverage": "vitest run --coverage",
+ "test:ui": "vitest --ui --coverage.enabled=true",
+ "test:watch": "vitest"
+ },
+ "dependencies": {
+ "@anolilab/rc": "workspace:*",
+ "@semantic-release/error": "^4.0.0",
+ "@visulima/fs": "^2.1.1",
+ "@visulima/package": "1.8.1",
+ "@visulima/path": "^1.0.0",
+ "aggregate-error": "^5.0.0",
+ "execa": "^9.1.0",
+ "ini": "4.1.2",
+ "move-file": "^3.1.0",
+ "normalize-url": "^8.0.1",
+ "registry-auth-token": "^5.0.2",
+ "semver": "^7.6.2"
+ },
+ "devDependencies": {
+ "@anolilab/eslint-config": "^15.0.3",
+ "@anolilab/prettier-config": "^5.0.14",
+ "@anolilab/semantic-release-preset": "^8.0.3",
+ "@babel/core": "^7.24.3",
+ "@rushstack/eslint-plugin-security": "^0.8.1",
+ "@secretlint/secretlint-rule-preset-recommend": "^8.1.2",
+ "@semantic-release/changelog": "^6.0.3",
+ "@semantic-release/git": "^10.0.1",
+ "@semantic-release/github": "^10.0.4",
+ "@types/dockerode": "^3.3.29",
+ "@types/ini": "^4.1.0",
+ "@types/node": "18.18.14",
+ "@types/semantic-release__error": "3.0.3",
+ "@types/semver": "7.5.8",
+ "@types/stream-buffers": "^3.0.7",
+ "@vitest/coverage-v8": "^1.4.0",
+ "@vitest/ui": "^1.4.0",
+ "cross-env": "^7.0.3",
+ "dockerode": "4.0.2",
+ "eslint": "^8.57.0",
+ "eslint-plugin-deprecation": "^2.0.0",
+ "eslint-plugin-editorconfig": "^4.0.3",
+ "eslint-plugin-import": "npm:eslint-plugin-i@2.29.1",
+ "eslint-plugin-mdx": "^3.1.5",
+ "eslint-plugin-n": "^17.7.0",
+ "eslint-plugin-vitest": "^0.4.1",
+ "eslint-plugin-vitest-globals": "^1.5.0",
+ "eslint-plugin-you-dont-need-lodash-underscore": "^6.14.0",
+ "get-stream": "9.0.1",
+ "got": "^14.2.1",
+ "p-retry": "^6.2.0",
+ "prettier": "^3.2.5",
+ "rimraf": "^5.0.5",
+ "secretlint": "8.1.2",
+ "semantic-release": "^23.0.5",
+ "sort-package-json": "^2.8.0",
+ "stream-buffers": "^3.0.2",
+ "tempy": "^3.1.0",
+ "tsup": "^8.0.2",
+ "typescript": "^5.4.3",
+ "vitest": "^1.4.0"
+ },
+ "engines": {
+ "node": ">=18.* <=21.*"
+ },
+ "publishConfig": {
+ "access": "public",
+ "provenance": true
+ },
+ "anolilab": {
+ "eslint-config": {
+ "plugin": {
+ "etc": false,
+ "tsdoc": false
+ },
+ "warn_on_unsupported_typescript_version": false,
+ "info_on_disabling_jsx_react_rule": false,
+ "info_on_disabling_prettier_conflict_rule": false,
+ "info_on_disabling_jsonc_sort_keys_rule": false,
+ "import_ignore_exports": [
+ "**/*.cjs"
+ ]
+ }
+ }
+}
diff --git a/packages/semantic-release-pnpm/project.json b/packages/semantic-release-pnpm/project.json
new file mode 100644
index 00000000..218504a0
--- /dev/null
+++ b/packages/semantic-release-pnpm/project.json
@@ -0,0 +1,8 @@
+{
+ "name": "semantic-release-pnpm",
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
+ "sourceRoot": "packages/semantic-release-pnpm/src",
+ "projectType": "library",
+ "tags": ["semantic-release-pnpm", "type:package"],
+ "implicitDependencies": ["rc"]
+}
diff --git a/packages/semantic-release-pnpm/src/add-channel.ts b/packages/semantic-release-pnpm/src/add-channel.ts
new file mode 100644
index 00000000..19bcfb8c
--- /dev/null
+++ b/packages/semantic-release-pnpm/src/add-channel.ts
@@ -0,0 +1,50 @@
+import type { PackageJson } from "@visulima/package";
+import { execa } from "execa";
+
+import type { AddChannelContext } from "./definitions/context";
+import type { PluginConfig } from "./definitions/plugin-config";
+import getChannel from "./utils/get-channel";
+import getNpmrcPath from "./utils/get-npmrc-path";
+import getRegistry from "./utils/get-registry";
+import type { ReleaseInfo } from "./utils/get-release-info";
+import { getReleaseInfo } from "./utils/get-release-info";
+import { reasonToNotPublish, shouldPublish } from "./utils/should-publish";
+
+export default async (pluginConfig: PluginConfig, package_: PackageJson, context: AddChannelContext): Promise => {
+ const {
+ cwd,
+ env,
+ logger,
+ nextRelease: { channel, version },
+ stderr,
+ stdout,
+ } = context;
+
+ if (shouldPublish(pluginConfig, package_)) {
+ const registry = getRegistry(package_, context);
+ const distributionTag = getChannel(channel);
+
+ logger.log(`Adding version ${version} to npm registry on dist-tag ${distributionTag}`);
+
+ const npmrc = getNpmrcPath(cwd, env);
+
+ const result = execa("pnpm", ["dist-tag", "add", `${package_.name}@${version}`, distributionTag, "--userconfig", npmrc, "--registry", registry], {
+ cwd,
+ env,
+ preferLocal: true,
+ });
+
+ result.stdout.pipe(stdout, { end: false });
+ result.stderr.pipe(stderr, { end: false });
+
+ await result;
+
+ logger.log(`Added ${package_.name}@${version} to dist-tag @${distributionTag} on ${registry}`);
+
+ return getReleaseInfo(package_, context, distributionTag, registry);
+ }
+
+ logger.log(`Skip adding to npm channel as ${reasonToNotPublish(pluginConfig, package_)}`);
+
+ return false;
+};
diff --git a/packages/semantic-release-pnpm/src/definitions/constants.ts b/packages/semantic-release-pnpm/src/definitions/constants.ts
new file mode 100644
index 00000000..28c85eaa
--- /dev/null
+++ b/packages/semantic-release-pnpm/src/definitions/constants.ts
@@ -0,0 +1,2 @@
+// eslint-disable-next-line import/prefer-default-export
+export const DEFAULT_NPM_REGISTRY = "https://registry.npmjs.org/";
diff --git a/packages/semantic-release-pnpm/src/definitions/context.ts b/packages/semantic-release-pnpm/src/definitions/context.ts
new file mode 100644
index 00000000..a5c51e66
--- /dev/null
+++ b/packages/semantic-release-pnpm/src/definitions/context.ts
@@ -0,0 +1,135 @@
+import type stream from "node:stream";
+
+import type { Commit, Options } from "semantic-release";
+
+// @todo these types need testing
+
+/**
+ * Define context types. Documentation seems to not be up to date with the
+ * source code.
+ *
+ * Source: https://github.com/semantic-release/semantic-release/blob/master/index.js
+ * Docs: https://semantic-release.gitbook.io/semantic-release/developer-guide/plugin#context
+ */
+export interface CommonContext {
+ // https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/index.js#L66
+ branch: BranchSpec;
+ // https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/index.js#L65
+ branches: BranchSpec[];
+ // https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/index.js#L256-L260
+ cwd: string;
+ env: typeof process.env;
+
+ // https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/index.js#L262
+ logger: {
+ // https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/lib/get-logger.js#L12-L14
+ error: (...message: string[]) => void;
+ log: (...message: string[]) => void;
+ success: (...message: string[]) => void;
+ };
+
+ // https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/index.js#L267
+ options: Options;
+
+ stderr: stream.Writable;
+
+ stdout: stream.Writable;
+}
+
+// https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/index.js#L103
+export type VerifyConditionsContext = CommonContext;
+
+type CommonContext2 = CommonContext & {
+ // https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/index.js#L106
+ releases: Release[];
+};
+
+// https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/index.js#L118
+type GenerateNotesContext1 = CommonContext2 & {
+ commits: Commit[];
+ lastRelease: Release;
+ nextRelease: Release;
+};
+
+// https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/index.js#L140
+export type AddChannelContext = CommonContext2 & {
+ commits: Commit[];
+ currentRelease: Release;
+ lastRelease: Release;
+ nextRelease: Release;
+};
+
+// https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/index.js#L142
+type SuccessContext1 = CommonContext2 & {
+ commits: Commit[];
+ lastRelease: Release;
+ nextRelease: Release;
+};
+
+type CommonContext3 = CommonContext2 & {
+ // https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/index.js#L163
+ commits: Commit[];
+
+ // https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/index.js#LL150C3-L150C10
+ lastRelease: Release;
+};
+
+// https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/index.js#L166
+export type AnalyzeCommitsContext = CommonContext3;
+
+type CommonContext4 = CommonContext3 & {
+ // https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/index.js#L163
+ commits: Commit[];
+
+ // https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/index.js#L175
+ nextRelease: Release;
+};
+
+// https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/index.js#L189
+export type VerifyReleaseContext = CommonContext4;
+
+// https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/index.js#L191
+type GenerateNotesContext2 = CommonContext4;
+
+export type GenerateNotesContext = GenerateNotesContext1 | GenerateNotesContext2;
+
+// https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/index.js#L193
+export type PrepareContext = CommonContext4;
+
+// https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/index.js#L206
+export type PublishContext = CommonContext4;
+
+// https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/index.js#L209
+type SuccessContext2 = CommonContext4;
+
+export type SuccessContext = SuccessContext1 | SuccessContext2;
+
+// https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/index.js#L243
+export type FailContext = CommonContext & {
+ errors: unknown[];
+};
+
+// @todo infer return type from https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/lib/branches/index.js#L70
+export interface BranchSpec {
+ name: string;
+ tags?: Tag[];
+}
+
+// https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/index.js#L133
+export interface Tag {
+ channel?: string;
+ gitHead?: string;
+ gitTag?: string;
+ version?: string;
+}
+
+// https://github.com/semantic-release/semantic-release/blob/27b105337b16dfdffb0dfa36d1178015e7ba68a3/lib/get-release-to-add.js#LL51C9-L56C25
+export interface Release {
+ channel?: string | null;
+ gitHead?: string;
+ gitTag?: string;
+ name?: string;
+ // https://github.com/sindresorhus/semver-diff#semverdiffversiona-versionb
+ type?: "build" | "major" | "minor" | "patch" | "premajor" | "preminor" | "prepatch" | "prerelease" | undefined;
+ version: string;
+}
diff --git a/packages/semantic-release-pnpm/src/definitions/errors.ts b/packages/semantic-release-pnpm/src/definitions/errors.ts
new file mode 100644
index 00000000..34d835f2
--- /dev/null
+++ b/packages/semantic-release-pnpm/src/definitions/errors.ts
@@ -0,0 +1,126 @@
+import package_ from "../../package.json";
+
+const linkify = (file: string) => `${package_.homepage}/blob/main/${file}`;
+
+interface ErrorDetails {
+ details: string;
+ message: string;
+}
+
+export type ErrorDefinition = (context: ErrorContext) => ErrorDetails;
+
+export interface ErrorContext {
+ npmPublish?: boolean;
+ npmrc?: string;
+ pkgRoot?: string;
+ publishBranch?: string;
+ registry?: string;
+ tarballDir?: string;
+ version?: string;
+}
+
+export const errors: {
+ EINVALIDBRANCHES: (branches: string[]) => { details: string; message: string };
+ EINVALIDNPMPUBLISH: ({ npmPublish }: ErrorContext) => { details: string; message: string };
+ EINVALIDNPMTOKEN: ({ registry }: ErrorContext) => { details: string; message: string };
+ EINVALIDPKGROOT: ({ pkgRoot }: ErrorContext) => { details: string; message: string };
+ EINVALIDPNPM: ({ version }: ErrorContext) => { details: string; message: string };
+ EINVALIDPUBLISHBRANCH: ({ publishBranch }: ErrorContext) => { details: string; message: string };
+ EINVALIDTARBALLDIR: ({ tarballDir }: ErrorContext) => { details: string; message: string };
+ ENONPMTOKEN: ({ registry }: ErrorContext) => { details: string; message: string };
+ ENOPKG: () => { details: string; message: string };
+ ENOPKGNAME: () => { details: string; message: string };
+ ENOPNPM: () => { details: string; message: string };
+ ENOPNPMRC: () => { details: string; message: string };
+} = {
+ EINVALIDBRANCHES: (branches: string[]) => {
+ return {
+ details: `The [branches option](${linkify("README.md#branches")}) option, if defined, must be an array of \`String\`.
+Your configuration for the \`branches\` option is \`${branches.join(",")}\`.`,
+ message: "Invalid `branches` option.",
+ };
+ },
+ EINVALIDNPMPUBLISH: ({ npmPublish }: ErrorContext) => {
+ return {
+ details: `The [npmPublish option](${linkify("README.md#npmpublish")}) option, if defined, must be a \`Boolean\`.
+Your configuration for the \`npmPublish\` option is \`${npmPublish}\`.`,
+ message: "Invalid `npmPublish` option.",
+ };
+ },
+ EINVALIDNPMTOKEN: ({ registry }: ErrorContext) => {
+ return {
+ details: `The [npm token](${linkify(
+ "README.md#npm-registry-authentication",
+ )}) configured in the \`NPM_TOKEN\` environment variable must be a valid [token](https://docs.npmjs.com/getting-started/working_with_tokens) allowing to publish to the registry \`${registry}\`.
+If you are using Two Factor Authentication for your account, set its level to ["Authorization only"](https://docs.npmjs.com/getting-started/using-two-factor-authentication#levels-of-authentication) in your account settings. **semantic-release** cannot publish with the default "Authorization and writes" level.
+Please make sure to set the \`NPM_TOKEN\` environment variable in your CI with the exact value of the npm token.`,
+ message: "Invalid npm token.",
+ };
+ },
+ EINVALIDPKGROOT: ({ pkgRoot }: ErrorContext) => {
+ return {
+ details: `The [pkgRoot option](${linkify("README.md#pkgroot")}) option, if defined, must be a \`String\`.
+Your configuration for the \`pkgRoot\` option is \`${pkgRoot}\`.`,
+ message: "Invalid `pkgRoot` option.",
+ };
+ },
+ EINVALIDPNPM: ({ version }: ErrorContext) => {
+ return {
+ details: `The version of Pnpm that you are using is not compatible. Please refer to [the README](${linkify(
+ "README.md#install",
+ )}) to review which versions of Pnpm are currently supported
+
+Your version of Pnpm is "${version}".`,
+ message: "Incompatible Pnpm version detected.",
+ };
+ },
+ EINVALIDPUBLISHBRANCH: ({ publishBranch }: ErrorContext) => {
+ return {
+ details: `The [publishBranch option](${linkify("README.md#publishBranch")}) option, if defined, must be a \`String\`.
+Your configuration for the \`publishBranch\` option is \`${publishBranch}\`.`,
+ message: "Invalid `publishBranch` option.",
+ };
+ },
+ EINVALIDTARBALLDIR: ({ tarballDir }: ErrorContext) => {
+ return {
+ details: `The [tarballDir option](${linkify("README.md#tarballdir")}) option, if defined, must be a \`String\`.
+Your configuration for the \`tarballDir\` option is \`${tarballDir}\`.`,
+ message: "Invalid `tarballDir` option.",
+ };
+ },
+ ENONPMTOKEN: ({ registry }: ErrorContext) => {
+ return {
+ details: `An [npm token](${linkify(
+ "README.md#npm-registry-authentication",
+ )}) must be created and set in the \`NPM_TOKEN\` environment variable on your CI environment.
+Please make sure to create an [npm token](https://docs.npmjs.com/getting-started/working_with_tokens#how-to-create-new-tokens) and to set it in the \`NPM_TOKEN\` environment variable on your CI environment. The token must allow to publish to the registry \`${registry}\`.`,
+ message: "No npm token specified.",
+ };
+ },
+ ENOPKG: () => {
+ return {
+ details: `A [package.json file](https://docs.npmjs.com/files/package.json) at the root of your project is required to release on npm.
+Please follow the [npm guideline](https://docs.npmjs.com/getting-started/creating-node-modules) to create a valid \`package.json\` file.`,
+ message: "Missing `package.json` file.",
+ };
+ },
+ ENOPKGNAME: () => {
+ return {
+ details: `The \`package.json\`'s [name](https://docs.npmjs.com/files/package.json#name) property is required in order to publish a package to the npm registry.
+Please make sure to add a valid \`name\` for your package in your \`package.json\`.`,
+ message: "Missing `name` property in `package.json`.",
+ };
+ },
+ ENOPNPM: () => {
+ return {
+ details: `The Pnpm CLI could not be found in your PATH. Make sure Pnpm is installed and try again.`,
+ message: "Pnpm not found.",
+ };
+ },
+ ENOPNPMRC: () => {
+ return {
+ details: `Didnt find a \`.npmrc\` file or it was not possible to create , in the root of your project.`,
+ message: "Missing `.npmrc` file.",
+ };
+ },
+};
diff --git a/packages/semantic-release-pnpm/src/definitions/plugin-config.ts b/packages/semantic-release-pnpm/src/definitions/plugin-config.ts
new file mode 100644
index 00000000..e48551f0
--- /dev/null
+++ b/packages/semantic-release-pnpm/src/definitions/plugin-config.ts
@@ -0,0 +1,8 @@
+export interface PluginConfig {
+ branches?: (string | { name: string; prerelease: boolean })[];
+ disableScripts?: boolean;
+ npmPublish?: boolean;
+ pkgRoot?: string;
+ publishBranch?: string;
+ tarballDir?: string;
+}
diff --git a/packages/semantic-release-pnpm/src/index.ts b/packages/semantic-release-pnpm/src/index.ts
new file mode 100644
index 00000000..e19ee089
--- /dev/null
+++ b/packages/semantic-release-pnpm/src/index.ts
@@ -0,0 +1,75 @@
+import addChannelNpm from "./add-channel";
+import type { AddChannelContext, PrepareContext, PublishContext, VerifyConditionsContext } from "./definitions/context";
+import type { PluginConfig } from "./definitions/plugin-config";
+import prepareNpm from "./prepare";
+import publishNpm from "./publish";
+import getPackage from "./utils/get-pkg";
+import type { ReleaseInfo } from "./utils/get-release-info";
+import verify from "./verify";
+
+const PLUGIN_NAME = "semantic-release-pnpm";
+
+let verified: boolean;
+let prepared: boolean;
+
+export const verifyConditions = async (pluginConfig: PluginConfig, context: VerifyConditionsContext): Promise => {
+ /**
+ * If the plugin is used and has `npmPublish`, `tarballDir` or
+ * `pkgRoot` configured, validate them now in order to prevent any release if
+ * the configuration is wrong
+ */
+ if (context.options.publish) {
+ const publish = Array.isArray(context.options.publish) ? context.options.publish : [context.options.publish];
+
+ const publishPlugin = publish.find((config) => config.path && config.path === PLUGIN_NAME) || {};
+
+ // eslint-disable-next-line no-param-reassign
+ pluginConfig.npmPublish = pluginConfig.npmPublish ?? publishPlugin.npmPublish;
+ // eslint-disable-next-line no-param-reassign
+ pluginConfig.tarballDir = pluginConfig.tarballDir ?? publishPlugin.tarballDir;
+ // eslint-disable-next-line no-param-reassign
+ pluginConfig.pkgRoot = pluginConfig.pkgRoot ?? publishPlugin.pkgRoot;
+ // eslint-disable-next-line no-param-reassign
+ pluginConfig.disableScripts = pluginConfig.disableScripts ?? publishPlugin.disableScripts;
+ // eslint-disable-next-line no-param-reassign
+ pluginConfig.branches = pluginConfig.branches ?? publishPlugin.branches;
+ }
+
+ await verify(pluginConfig, context);
+
+ verified = true;
+};
+
+export const prepare = async (pluginConfig: PluginConfig, context: PrepareContext): Promise => {
+ if (!verified) {
+ await verify(pluginConfig, context);
+ }
+
+ await prepareNpm(pluginConfig, context);
+
+ prepared = true;
+};
+
+export const publish = async (pluginConfig: PluginConfig, context: PublishContext): Promise => {
+ const packageJson = await getPackage(pluginConfig, context);
+
+ if (!verified) {
+ await verify(pluginConfig, context);
+ }
+
+ if (!prepared) {
+ await prepareNpm(pluginConfig, context);
+ }
+
+ return await publishNpm(pluginConfig, packageJson, context);
+};
+
+export const addChannel = async (pluginConfig: PluginConfig, context: AddChannelContext): Promise => {
+ if (!verified) {
+ await verify(pluginConfig, context);
+ }
+
+ const packageJson = await getPackage(pluginConfig, context);
+
+ return await addChannelNpm(pluginConfig, packageJson, context);
+};
diff --git a/packages/semantic-release-pnpm/src/prepare.ts b/packages/semantic-release-pnpm/src/prepare.ts
new file mode 100644
index 00000000..ac713ec7
--- /dev/null
+++ b/packages/semantic-release-pnpm/src/prepare.ts
@@ -0,0 +1,43 @@
+import { resolve } from "@visulima/path";
+import { execa } from "execa";
+import { moveFile } from "move-file";
+
+import type { PrepareContext } from "./definitions/context";
+import type { PluginConfig } from "./definitions/plugin-config";
+
+export default async ({ pkgRoot, tarballDir }: PluginConfig, { cwd, env, logger, nextRelease: { version }, stderr, stdout }: PrepareContext): Promise => {
+ const basePath = pkgRoot ? resolve(cwd, pkgRoot) : cwd;
+
+ logger.log("Write version %s to package.json in %s", version, basePath);
+
+ const versionResult = execa("pnpm", ["version", version, "--no-git-tag-version", "--allow-same-version"], {
+ cwd: basePath,
+ env,
+ preferLocal: true,
+ });
+
+ versionResult.stdout.pipe(stdout, { end: false });
+ versionResult.stderr.pipe(stderr, { end: false });
+
+ await versionResult;
+
+ if (tarballDir) {
+ logger.log("Creating npm package version %s", version);
+
+ const packResult = execa("pnpm", ["pack", basePath], { cwd, env, preferLocal: true });
+
+ packResult.stdout.pipe(stdout, { end: false });
+ packResult.stderr.pipe(stderr, { end: false });
+
+ // eslint-disable-next-line unicorn/no-await-expression-member
+ const tarball = (await packResult).stdout.split("\n").pop() as string;
+ const tarballSource = resolve(cwd, tarball);
+ const tarballDestination = resolve(cwd, tarballDir.trim(), tarball);
+
+ // Only move the tarball if we need to
+ // Fixes: https://github.com/semantic-release/npm/issues/169
+ if (tarballSource !== tarballDestination) {
+ await moveFile(tarballSource, tarballDestination);
+ }
+ }
+};
diff --git a/packages/semantic-release-pnpm/src/publish.ts b/packages/semantic-release-pnpm/src/publish.ts
new file mode 100644
index 00000000..f230fe5f
--- /dev/null
+++ b/packages/semantic-release-pnpm/src/publish.ts
@@ -0,0 +1,73 @@
+import type { PackageJson } from "@visulima/package";
+import { resolve } from "@visulima/path";
+import AggregateError from "aggregate-error";
+import { execa } from "execa";
+
+import type { PublishContext } from "./definitions/context";
+import type { PluginConfig } from "./definitions/plugin-config";
+import getChannel from "./utils/get-channel";
+import getRegistry from "./utils/get-registry";
+import type { ReleaseInfo } from "./utils/get-release-info";
+import { getReleaseInfo } from "./utils/get-release-info";
+import { reasonToNotPublish, shouldPublish } from "./utils/should-publish";
+
+export default async (pluginConfig: PluginConfig, package_: PackageJson, context: PublishContext): Promise => {
+ const {
+ cwd,
+ env,
+ logger,
+ nextRelease: { channel, version },
+ stderr,
+ stdout,
+ } = context;
+ const { pkgRoot, publishBranch: publishBranchConfig } = pluginConfig;
+
+ if (shouldPublish(pluginConfig, package_)) {
+ const basePath = pkgRoot ? resolve(cwd, pkgRoot) : cwd;
+ const registry = getRegistry(package_, context);
+ const distributionTag = getChannel(channel);
+
+ const { stdout: currentBranch } = await execa("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
+ cwd,
+ env,
+ preferLocal: true,
+ });
+ const publishBranches = typeof publishBranchConfig === "string" && publishBranchConfig.split("|");
+ const isPublishBranch = publishBranches && publishBranches.includes(currentBranch);
+ const publishBranch = isPublishBranch ? currentBranch : "main";
+
+ logger.log(`Publishing version ${version} on branch ${publishBranch} to npm registry on dist-tag ${distributionTag}`);
+
+ const pnpmArguments = ["publish", basePath, "--publish-branch", publishBranch, "--tag", distributionTag, "--registry", registry, "--no-git-checks"];
+
+ if (pluginConfig.disableScripts) {
+ pnpmArguments.push("--ignore-scripts");
+ }
+
+ const result = execa("pnpm", pnpmArguments, {
+ cwd,
+ env,
+ preferLocal: true,
+ });
+
+ result.stdout.pipe(stdout, { end: false });
+ result.stderr.pipe(stderr, { end: false });
+
+ try {
+ await result;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (error: any) {
+ logger.log(`Failed to publish ${package_.name}@${version} to dist-tag @${distributionTag} on ${registry}: ${error.message ?? error}`);
+
+ throw new AggregateError([error]);
+ }
+
+ logger.log(`Published ${package_.name}@${version} to dist-tag @${distributionTag} on ${registry}`);
+
+ return getReleaseInfo(package_, context, distributionTag, registry);
+ }
+
+ logger.log(`Skip publishing to npm registry as ${reasonToNotPublish(pluginConfig, package_)}`);
+
+ return false;
+};
diff --git a/packages/semantic-release-pnpm/src/utils/get-channel.ts b/packages/semantic-release-pnpm/src/utils/get-channel.ts
new file mode 100644
index 00000000..aafc32e6
--- /dev/null
+++ b/packages/semantic-release-pnpm/src/utils/get-channel.ts
@@ -0,0 +1,3 @@
+import { validRange } from "semver";
+
+export default (channel: string | null | undefined): string => (channel ? (validRange(channel) ? `release-${channel}` : channel) : "latest");
diff --git a/packages/semantic-release-pnpm/src/utils/get-error.ts b/packages/semantic-release-pnpm/src/utils/get-error.ts
new file mode 100644
index 00000000..595107e9
--- /dev/null
+++ b/packages/semantic-release-pnpm/src/utils/get-error.ts
@@ -0,0 +1,11 @@
+import SemanticReleaseError from "@semantic-release/error";
+
+import type { ErrorContext, ErrorDefinition } from "../definitions/errors";
+import { errors } from "../definitions/errors";
+
+export default (code: T, context: ErrorContext = {}): SemanticReleaseError => {
+ // eslint-disable-next-line security/detect-object-injection
+ const { details, message }: { details?: string; message: string } = (errors[code] as ErrorDefinition)(context);
+
+ return new SemanticReleaseError(message, code, details);
+};
diff --git a/packages/semantic-release-pnpm/src/utils/get-npmrc-path.ts b/packages/semantic-release-pnpm/src/utils/get-npmrc-path.ts
new file mode 100644
index 00000000..77fdb4ac
--- /dev/null
+++ b/packages/semantic-release-pnpm/src/utils/get-npmrc-path.ts
@@ -0,0 +1,38 @@
+import { ensureFileSync, isAccessibleSync } from "@visulima/fs";
+import { findCacheDirectorySync } from "@visulima/package";
+import { resolve } from "@visulima/path";
+
+import getError from "./get-error";
+
+const getNpmrcPath = (cwd: string, environment: NodeJS.ProcessEnv): string => {
+ let npmrc: string | undefined;
+
+ const npmrcPath = resolve(cwd, ".npmrc");
+
+ if (environment.NPM_CONFIG_USERCONFIG && isAccessibleSync(environment.NPM_CONFIG_USERCONFIG)) {
+ npmrc = environment.NPM_CONFIG_USERCONFIG;
+ } else if (isAccessibleSync(npmrcPath)) {
+ npmrc = npmrcPath;
+ } else {
+ const temporaryNpmrcPath = findCacheDirectorySync("semantic-release-pnpm", { create: true, cwd });
+
+ if (temporaryNpmrcPath) {
+ ensureFileSync(temporaryNpmrcPath);
+
+ npmrc = temporaryNpmrcPath;
+ }
+ }
+
+ if (npmrc === undefined) {
+ // eslint-disable-next-line unicorn/error-message
+ throw new AggregateError([
+ getError("ENOPNPMRC", {
+ npmrc: npmrcPath,
+ }),
+ ]);
+ }
+
+ return npmrc;
+};
+
+export default getNpmrcPath;
diff --git a/packages/semantic-release-pnpm/src/utils/get-pkg.ts b/packages/semantic-release-pnpm/src/utils/get-pkg.ts
new file mode 100644
index 00000000..02f347c4
--- /dev/null
+++ b/packages/semantic-release-pnpm/src/utils/get-pkg.ts
@@ -0,0 +1,31 @@
+// eslint-disable-next-line unicorn/prevent-abbreviations
+import type { PackageJson } from "@visulima/package";
+import { findPackageJson } from "@visulima/package";
+import { resolve } from "@visulima/path";
+import AggregateError from "aggregate-error";
+
+import type { CommonContext } from "../definitions/context";
+import getError from "./get-error";
+
+interface Options {
+ pkgRoot?: string;
+}
+
+export default async ({ pkgRoot }: Options, { cwd }: { cwd: CommonContext["cwd"] }): Promise => {
+ try {
+ const { packageJson } = await findPackageJson(pkgRoot ? resolve(cwd, pkgRoot) : cwd);
+
+ if (!packageJson.name) {
+ throw new AggregateError([getError("ENOPKGNAME")]);
+ }
+
+ return packageJson;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (error: any) {
+ if (error.code === "ENOENT") {
+ throw new AggregateError([getError("ENOPKG")]);
+ }
+
+ throw error;
+ }
+};
diff --git a/packages/semantic-release-pnpm/src/utils/get-registry.ts b/packages/semantic-release-pnpm/src/utils/get-registry.ts
new file mode 100644
index 00000000..26dc5a34
--- /dev/null
+++ b/packages/semantic-release-pnpm/src/utils/get-registry.ts
@@ -0,0 +1,33 @@
+import { rc } from "@anolilab/rc";
+import type { PackageJson } from "@visulima/package";
+import { resolve } from "@visulima/path";
+import type { AuthOptions } from "registry-auth-token";
+
+import { DEFAULT_NPM_REGISTRY } from "../definitions/constants";
+import type { CommonContext } from "../definitions/context";
+
+const getRegistryUrl = (scope: string, npmrc: AuthOptions["npmrc"]): string => {
+ let url: string = DEFAULT_NPM_REGISTRY;
+
+ if (npmrc) {
+ const registryUrl = npmrc[`${scope}:registry`] ?? npmrc.registry;
+
+ if (registryUrl) {
+ url = registryUrl;
+ }
+ }
+
+ return url.endsWith("/") ? url : `${url}/`;
+};
+
+export default ({ name, publishConfig: { registry } = {} }: PackageJson, { cwd, env }: CommonContext): string =>
+ registry ??
+ env.NPM_CONFIG_REGISTRY ??
+ getRegistryUrl(
+ (name as string).split("/")[0] as string,
+ rc("npm", {
+ config: env.NPM_CONFIG_USERCONFIG ?? resolve(cwd, ".npmrc"),
+ cwd,
+ defaults: { registry: "https://registry.npmjs.org/" },
+ }).config as AuthOptions["npmrc"],
+ );
diff --git a/packages/semantic-release-pnpm/src/utils/get-release-info.ts b/packages/semantic-release-pnpm/src/utils/get-release-info.ts
new file mode 100644
index 00000000..7a14bf47
--- /dev/null
+++ b/packages/semantic-release-pnpm/src/utils/get-release-info.ts
@@ -0,0 +1,23 @@
+import type { PackageJson } from "@visulima/package";
+import normalizeUrl from "normalize-url";
+
+import type { PublishContext } from "../definitions/context";
+
+export interface ReleaseInfo {
+ channel: string;
+ name: string;
+ url?: string;
+}
+
+export const getReleaseInfo = (
+ { name }: PackageJson,
+ { env: { DEFAULT_NPM_REGISTRY = "https://registry.npmjs.org/" }, nextRelease: { version } }: PublishContext,
+ distributionTag: string,
+ registry: string,
+): ReleaseInfo => {
+ return {
+ channel: distributionTag,
+ name: `pnpm package (@${distributionTag} dist-tag)`,
+ url: normalizeUrl(registry) === normalizeUrl(DEFAULT_NPM_REGISTRY) ? `https://www.npmjs.com/package/${name}/v/${version}` : undefined,
+ };
+};
diff --git a/packages/semantic-release-pnpm/src/utils/nerf-dart.ts b/packages/semantic-release-pnpm/src/utils/nerf-dart.ts
new file mode 100644
index 00000000..278b3da6
--- /dev/null
+++ b/packages/semantic-release-pnpm/src/utils/nerf-dart.ts
@@ -0,0 +1,23 @@
+import { URL } from "node:url";
+
+/**
+ * Maps a URL to an identifier.
+ *
+ * The ISC License
+ * Copyright (c) npm, Inc.
+ *
+ * Name courtesy schiffertronix media LLC, a New Jersey corporation
+ *
+ * @param {String} url The URL to be nerfed.
+ *
+ * @returns {String} A nerfed URL.
+ */
+const nerfDart = (url: string): string => {
+ const parsed = new URL(url);
+ const from = `${parsed.protocol}//${parsed.host}${parsed.pathname}`;
+ const real = new URL(".", from);
+
+ return `//${real.host}${real.pathname}`;
+};
+
+export default nerfDart;
diff --git a/packages/semantic-release-pnpm/src/utils/set-npmrc-auth.ts b/packages/semantic-release-pnpm/src/utils/set-npmrc-auth.ts
new file mode 100644
index 00000000..e71a5fc0
--- /dev/null
+++ b/packages/semantic-release-pnpm/src/utils/set-npmrc-auth.ts
@@ -0,0 +1,48 @@
+import { rc } from "@anolilab/rc";
+import { writeFile } from "@visulima/fs";
+import { resolve } from "@visulima/path";
+import AggregateError from "aggregate-error";
+import { stringify } from "ini";
+import type { AuthOptions } from "registry-auth-token";
+import getAuthToken from "registry-auth-token";
+
+import { DEFAULT_NPM_REGISTRY } from "../definitions/constants";
+import type { CommonContext } from "../definitions/context";
+import getError from "./get-error";
+import nerfDart from "./nerf-dart";
+
+export default async (
+ npmrc: string,
+ registry: string,
+ { cwd, env: { NPM_CONFIG_USERCONFIG, NPM_EMAIL, NPM_PASSWORD, NPM_TOKEN, NPM_USERNAME }, logger }: CommonContext,
+): Promise => {
+ logger.log("Verify authentication for registry %s", registry);
+
+ const { config, files } = rc("npm", {
+ config: NPM_CONFIG_USERCONFIG ?? resolve(cwd, ".npmrc"),
+ cwd,
+ defaults: { registry: DEFAULT_NPM_REGISTRY },
+ });
+
+ if (Array.isArray(files)) {
+ logger.log("Reading npm config from %s", files.join(", "));
+ }
+
+ if (getAuthToken(registry, { npmrc: config } as AuthOptions)) {
+ await writeFile(npmrc, stringify(config));
+
+ return;
+ }
+
+ if (NPM_USERNAME && NPM_PASSWORD && NPM_EMAIL) {
+ await writeFile(npmrc, `${Object.keys(config).length > 0 ? `${stringify(config)}\n` : ""}_auth = \${LEGACY_TOKEN}\nemail = \${NPM_EMAIL}`);
+
+ logger.log(`Wrote NPM_USERNAME, NPM_PASSWORD, and NPM_EMAIL to ${npmrc}`);
+ } else if (NPM_TOKEN) {
+ await writeFile(npmrc, `${Object.keys(config).length > 0 ? `${stringify(config)}\n` : ""}${nerfDart(registry)}:_authToken = \${NPM_TOKEN}`);
+
+ logger.log(`Wrote NPM_TOKEN to ${npmrc}`);
+ } else {
+ throw new AggregateError([getError("ENONPMTOKEN", { registry })]);
+ }
+};
diff --git a/packages/semantic-release-pnpm/src/utils/should-publish.ts b/packages/semantic-release-pnpm/src/utils/should-publish.ts
new file mode 100644
index 00000000..5a938bb9
--- /dev/null
+++ b/packages/semantic-release-pnpm/src/utils/should-publish.ts
@@ -0,0 +1,17 @@
+import type { PackageJson } from "@visulima/package";
+
+import type { PluginConfig } from "../definitions/plugin-config";
+
+/**
+ * Returns null if `npmPublish` is not `false` and `pkg.private` is not
+ * `true` or `pkg.workspaces` is not `undefined`.
+ * Returns reason otherwise.
+ */
+export const reasonToNotPublish = (pluginConfig: PluginConfig, package_: PackageJson): string | null =>
+ (pluginConfig.npmPublish === false
+ ? "npmPublish plugin option is false"
+ : package_.private === true && package_.workspaces === undefined
+ ? "package is private and has no workspaces"
+ : null);
+
+export const shouldPublish = (pluginConfig: PluginConfig, package_: PackageJson): boolean => reasonToNotPublish(pluginConfig, package_) === null;
diff --git a/packages/semantic-release-pnpm/src/verify/index.ts b/packages/semantic-release-pnpm/src/verify/index.ts
new file mode 100644
index 00000000..7009419b
--- /dev/null
+++ b/packages/semantic-release-pnpm/src/verify/index.ts
@@ -0,0 +1,46 @@
+import AggregateError from "aggregate-error";
+
+import type { VerifyConditionsContext } from "../definitions/context";
+import type { PluginConfig } from "../definitions/plugin-config";
+import getNpmrcPath from "../utils/get-npmrc-path";
+import getPackage from "../utils/get-pkg";
+import { shouldPublish } from "../utils/should-publish";
+import verifyAuth from "./verify-auth";
+import verifyConfig from "./verify-config";
+import verifyPnpm from "./verify-pnpm";
+
+const verify = async (pluginConfig: PluginConfig, context: VerifyConditionsContext): Promise => {
+ let errors: Error[] = verifyConfig(pluginConfig);
+
+ try {
+ await verifyPnpm(context);
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (error: any) {
+ const typedError = error as AggregateError;
+
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ errors = [...errors, ...(typedError.errors ?? [error])];
+ }
+
+ try {
+ const packageJson = await getPackage(pluginConfig, context);
+
+ if (shouldPublish(pluginConfig, packageJson)) {
+ const npmrc = getNpmrcPath(context.cwd, context.env);
+
+ await verifyAuth(npmrc, packageJson, context);
+ }
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (error: any) {
+ const typedError = error as AggregateError;
+
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ errors = [...errors, ...(typedError.errors ?? [error])];
+ }
+
+ if (errors.length > 0) {
+ throw new AggregateError(errors);
+ }
+};
+
+export default verify;
diff --git a/packages/semantic-release-pnpm/src/verify/verify-auth.ts b/packages/semantic-release-pnpm/src/verify/verify-auth.ts
new file mode 100644
index 00000000..f67964c5
--- /dev/null
+++ b/packages/semantic-release-pnpm/src/verify/verify-auth.ts
@@ -0,0 +1,43 @@
+import type { PackageJson } from "@visulima/package";
+import AggregateError from "aggregate-error";
+import { execa } from "execa";
+import normalizeUrl from "normalize-url";
+
+import type { CommonContext } from "../definitions/context";
+import getError from "../utils/get-error";
+import getRegistry from "../utils/get-registry";
+import setNpmrcAuth from "../utils/set-npmrc-auth";
+
+export default async (npmrc: string, package_: PackageJson, context: CommonContext): Promise => {
+ const {
+ cwd,
+ env: { DEFAULT_NPM_REGISTRY = "https://registry.npmjs.org/", ...environment },
+ logger,
+ stderr,
+ stdout,
+ } = context;
+ const registry = getRegistry(package_, context);
+
+ await setNpmrcAuth(npmrc, registry, context);
+
+ if (normalizeUrl(registry) === normalizeUrl(DEFAULT_NPM_REGISTRY)) {
+ try {
+ logger.log(`Running "pnpm whoami" to verify authentication on registry "${registry}"`);
+
+ const whoamiResult = execa("pnpm", ["whoami", "--userconfig", npmrc, "--registry", registry], {
+ cwd,
+ env: environment,
+ preferLocal: true,
+ });
+
+ whoamiResult.stdout.pipe(stdout, { end: false });
+ whoamiResult.stderr.pipe(stderr, { end: false });
+
+ await whoamiResult;
+ } catch {
+ throw new AggregateError([getError("EINVALIDNPMTOKEN", { registry })]);
+ }
+ } else {
+ logger.log(`Skipping authentication verification for non-default registry "${registry}"`);
+ }
+};
diff --git a/packages/semantic-release-pnpm/src/verify/verify-config.ts b/packages/semantic-release-pnpm/src/verify/verify-config.ts
new file mode 100644
index 00000000..170438d2
--- /dev/null
+++ b/packages/semantic-release-pnpm/src/verify/verify-config.ts
@@ -0,0 +1,51 @@
+import type SemanticReleaseError from "@semantic-release/error";
+
+import type { PluginConfig } from "../definitions/plugin-config";
+import getError from "../utils/get-error";
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+const isString = (value: any): boolean => typeof value === "string";
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+const isNil = (value: any): boolean => value === null || value === undefined;
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+const isNonEmptyString = (value: any): boolean => {
+ if (!isString(value)) {
+ return false;
+ }
+
+ return (value as string).trim() !== "";
+};
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+type ValidatorFunction = (value: any) => boolean;
+
+const VALIDATORS: Record = {
+ branches: Array.isArray,
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ npmPublish: (value: any): boolean => typeof value === "boolean",
+ pkgRoot: isNonEmptyString,
+ publishBranch: isNonEmptyString,
+ tarballDir: isNonEmptyString,
+};
+
+export default (config: PluginConfig): SemanticReleaseError[] =>
+ // eslint-disable-next-line unicorn/no-array-reduce
+ Object.entries(config).reduce((errors, [option, value]) => {
+ if (isNil(value)) {
+ return errors;
+ }
+
+ if (!(option in VALIDATORS)) {
+ return errors;
+ }
+
+ // eslint-disable-next-line security/detect-object-injection
+ if (VALIDATORS[option]?.(value)) {
+ return errors;
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ return [...errors, getError(`EINVALID${option.toUpperCase()}` as any, { [option]: value })];
+ }, []);
diff --git a/packages/semantic-release-pnpm/src/verify/verify-pnpm.ts b/packages/semantic-release-pnpm/src/verify/verify-pnpm.ts
new file mode 100644
index 00000000..4ec9cfa0
--- /dev/null
+++ b/packages/semantic-release-pnpm/src/verify/verify-pnpm.ts
@@ -0,0 +1,22 @@
+import { getPackageManagerVersion } from "@visulima/package";
+import AggregateError from "aggregate-error";
+import { gte } from "semver";
+
+import type { CommonContext } from "../definitions/context";
+import getError from "../utils/get-error";
+
+const MIN_PNPM_VERSION = "8.0.0";
+
+export default async function verifyPnpm({ logger }: CommonContext): Promise {
+ logger.log(`Verify pnpm version is >= ${MIN_PNPM_VERSION}`);
+
+ const version = getPackageManagerVersion("pnpm");
+
+ if (version !== "pnpm") {
+ throw new AggregateError([new Error("pnpm is not installed")]);
+ }
+
+ if (gte(MIN_PNPM_VERSION, version)) {
+ throw new AggregateError([getError("EINVALIDPNPM", { version: String(version) })]);
+ }
+}
diff --git a/packages/semantic-release-pnpm/tsconfig.eslint.json b/packages/semantic-release-pnpm/tsconfig.eslint.json
new file mode 100644
index 00000000..c63f963b
--- /dev/null
+++ b/packages/semantic-release-pnpm/tsconfig.eslint.json
@@ -0,0 +1,8 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "baseUrl": "."
+ },
+ "include": ["__tests__/**/*", "src/**/*", "*.d.ts", "tsup.config.ts"]
+}
diff --git a/packages/semantic-release-pnpm/tsconfig.json b/packages/semantic-release-pnpm/tsconfig.json
new file mode 100644
index 00000000..f0ee80dc
--- /dev/null
+++ b/packages/semantic-release-pnpm/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "extends": "../../tsconfig.base.json",
+ "include": ["src/**/*", "*.d.ts"],
+ "compilerOptions": {
+ "moduleResolution": "bundler"
+ }
+}
diff --git a/packages/semantic-release-pnpm/tsup.config.ts b/packages/semantic-release-pnpm/tsup.config.ts
new file mode 100644
index 00000000..5fdb8580
--- /dev/null
+++ b/packages/semantic-release-pnpm/tsup.config.ts
@@ -0,0 +1,25 @@
+import type { Options } from "tsup";
+import { defineConfig } from "tsup";
+
+// @ts-ignore
+export default defineConfig((options: Options) => {
+ return {
+ ...options,
+ treeshake: true,
+ // react external https://github.com/vercel/turborepo/issues/360#issuecomment-1013885148
+ external: ["semantic-release"],
+ silent: !options.watch,
+ minify: process.env["NODE_ENV"] === "production",
+ minifyWhitespace: process.env["NODE_ENV"] === "production",
+ incremental: !options.watch,
+ dts: true,
+ sourcemap: true,
+ clean: true,
+ splitting: true,
+ shims: true,
+ target: ["es2022", "node18"],
+ declaration: true,
+ entry: ["src/index.ts"],
+ format: ["esm"],
+ };
+});
diff --git a/packages/semantic-release-pnpm/vitest.config.ts b/packages/semantic-release-pnpm/vitest.config.ts
new file mode 100644
index 00000000..59d88c72
--- /dev/null
+++ b/packages/semantic-release-pnpm/vitest.config.ts
@@ -0,0 +1,5 @@
+import { getVitestConfig } from "../../tools/get-vitest-config";
+
+const config = getVitestConfig();
+
+export default config;
diff --git a/plop/package/package.json.hbs b/plop/package/package.json.hbs
index b0e66b32..3fd6284e 100644
--- a/plop/package/package.json.hbs
+++ b/plop/package/package.json.hbs
@@ -43,7 +43,9 @@
"source": "src/index.ts",
"types": "dist/index.d.ts",
"files": [
- "dist"
+ "dist",
+ "README.md",
+ "CHANGELOG.md"
],
"repository": {
"type": "git",
@@ -83,7 +85,6 @@
"@babel/core": "^7.24.3",
"@rushstack/eslint-plugin-security": "^0.8.1",
"@secretlint/secretlint-rule-preset-recommend": "^8.1.2",
- "@types/micromatch": "^4.0.6",
"@types/node": "18.18.14",
"@vitest/coverage-v8": "^1.4.0",
"@vitest/ui": "^1.4.0",
@@ -115,5 +116,5 @@
"info_on_disabling_jsonc_sort_keys_rule": false,
"info_on_disabling_etc_no_deprecated": false
}
- },
+ }
}
diff --git a/plop/package/tsconfig.dev.json.hbs b/plop/package/tsconfig.dev.json.hbs
deleted file mode 100644
index 555c43f1..00000000
--- a/plop/package/tsconfig.dev.json.hbs
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "extends": "./tsconfig.json",
- "compilerOptions": {
- "jsx": "react-jsxdev"
- }
-}
diff --git a/plop/package/tsconfig.eslint.json.hbs b/plop/package/tsconfig.eslint.json.hbs
index 36db3054..39eaefbf 100644
--- a/plop/package/tsconfig.eslint.json.hbs
+++ b/plop/package/tsconfig.eslint.json.hbs
@@ -4,5 +4,5 @@
"compilerOptions": {
"baseUrl": "."
},
- "include": ["__docs__/**/*", "__tests__/**/*", "src/**/*", "*.d.ts", "build.config.ts", "tsup.config.ts"]
+ "include": ["__docs__/**/*", "__tests__/**/*", "src/**/*", "*.d.ts", "tsup.config.ts"]
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index b1a6d251..957599a3 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -154,7 +154,7 @@ importers:
devDependencies:
'@anolilab/eslint-config':
specifier: ^15.0.3
- version: 15.0.3(@babel/core@7.24.5)(eslint-plugin-i@2.29.1(eslint@8.57.0))(eslint-plugin-you-dont-need-lodash-underscore@6.14.0)(eslint@8.57.0)(typescript@5.4.5)
+ version: 15.0.3(@babel/core@7.24.5)(eslint-plugin-editorconfig@4.0.3)(eslint-plugin-i@2.29.1(eslint@8.57.0))(eslint-plugin-you-dont-need-lodash-underscore@6.14.0)(eslint@8.57.0)(typescript@5.4.5)
'@anolilab/prettier-config':
specifier: ^5.0.14
version: 5.0.14(prettier@3.2.5)
@@ -237,6 +237,266 @@ importers:
specifier: ^1.6.0
version: 1.6.0(@types/node@20.12.12)(@vitest/ui@1.6.0)
+ packages/rc:
+ dependencies:
+ '@visulima/fs':
+ specifier: ^2.1.1
+ version: 2.1.1
+ ini:
+ specifier: ^4.1.3
+ version: 4.1.3
+ ts-deepmerge:
+ specifier: ^7.0.0
+ version: 7.0.0
+ devDependencies:
+ '@anolilab/eslint-config':
+ specifier: ^15.0.3
+ version: 15.0.3(@babel/core@7.24.5)(eslint-plugin-editorconfig@4.0.3)(eslint-plugin-i@2.29.1(eslint@8.57.0))(eslint-plugin-you-dont-need-lodash-underscore@6.14.0)(eslint@8.57.0)(typescript@5.4.5)
+ '@anolilab/prettier-config':
+ specifier: ^5.0.14
+ version: 5.0.14(prettier@3.2.5)
+ '@anolilab/semantic-release-preset':
+ specifier: ^8.0.3
+ version: 8.0.3(semantic-release@23.1.1(typescript@5.4.5))
+ '@babel/core':
+ specifier: ^7.24.3
+ version: 7.24.5
+ '@rushstack/eslint-plugin-security':
+ specifier: ^0.8.1
+ version: 0.8.1(eslint@8.57.0)(typescript@5.4.5)
+ '@secretlint/secretlint-rule-preset-recommend':
+ specifier: ^8.1.2
+ version: 8.2.4
+ '@types/ini':
+ specifier: ^4.1.0
+ version: 4.1.0
+ '@types/node':
+ specifier: 18.18.14
+ version: 18.18.14
+ '@visulima/path':
+ specifier: ^1.0.0
+ version: 1.0.0
+ '@vitest/coverage-v8':
+ specifier: ^1.4.0
+ version: 1.6.0(vitest@1.6.0(@types/node@18.18.14)(@vitest/ui@1.6.0))
+ '@vitest/ui':
+ specifier: ^1.4.0
+ version: 1.6.0(vitest@1.6.0)
+ cross-env:
+ specifier: ^7.0.3
+ version: 7.0.3
+ eslint:
+ specifier: ^8.57.0
+ version: 8.57.0
+ eslint-plugin-deprecation:
+ specifier: ^2.0.0
+ version: 2.0.0(eslint@8.57.0)(typescript@5.4.5)
+ eslint-plugin-etc:
+ specifier: ^2.0.3
+ version: 2.0.3(eslint@8.57.0)(typescript@5.4.5)
+ eslint-plugin-import:
+ specifier: npm:eslint-plugin-i@^2.29.1
+ version: eslint-plugin-i@2.29.1(eslint@8.57.0)
+ eslint-plugin-mdx:
+ specifier: ^3.1.5
+ version: 3.1.5(eslint@8.57.0)
+ eslint-plugin-vitest:
+ specifier: ^0.4.1
+ version: 0.4.1(eslint@8.57.0)(typescript@5.4.5)(vitest@1.6.0(@types/node@18.18.14)(@vitest/ui@1.6.0))
+ eslint-plugin-vitest-globals:
+ specifier: ^1.5.0
+ version: 1.5.0
+ prettier:
+ specifier: ^3.2.5
+ version: 3.2.5
+ rimraf:
+ specifier: ^5.0.5
+ version: 5.0.7
+ secretlint:
+ specifier: 8.1.2
+ version: 8.1.2
+ semantic-release:
+ specifier: ^23.0.5
+ version: 23.1.1(typescript@5.4.5)
+ sort-package-json:
+ specifier: ^2.8.0
+ version: 2.10.0
+ tempy:
+ specifier: ^3.1.0
+ version: 3.1.0
+ tsup:
+ specifier: ^8.0.2
+ version: 8.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@18.18.14)(typescript@5.4.5))(typescript@5.4.5)
+ typescript:
+ specifier: ^5.4.3
+ version: 5.4.5
+ vitest:
+ specifier: ^1.4.0
+ version: 1.6.0(@types/node@18.18.14)(@vitest/ui@1.6.0)
+
+ packages/semantic-release-pnpm:
+ dependencies:
+ '@anolilab/rc':
+ specifier: workspace:*
+ version: link:../rc
+ '@semantic-release/error':
+ specifier: ^4.0.0
+ version: 4.0.0
+ '@visulima/fs':
+ specifier: ^2.1.1
+ version: 2.1.1
+ '@visulima/package':
+ specifier: 1.8.1
+ version: 1.8.1
+ '@visulima/path':
+ specifier: ^1.0.0
+ version: 1.0.0
+ aggregate-error:
+ specifier: ^5.0.0
+ version: 5.0.0
+ execa:
+ specifier: ^9.1.0
+ version: 9.1.0
+ ini:
+ specifier: 4.1.2
+ version: 4.1.2
+ move-file:
+ specifier: ^3.1.0
+ version: 3.1.0
+ normalize-url:
+ specifier: ^8.0.1
+ version: 8.0.1
+ registry-auth-token:
+ specifier: ^5.0.2
+ version: 5.0.2
+ semver:
+ specifier: ^7.6.2
+ version: 7.6.2
+ devDependencies:
+ '@anolilab/eslint-config':
+ specifier: ^15.0.3
+ version: 15.0.3(@babel/core@7.24.5)(eslint-plugin-editorconfig@4.0.3)(eslint-plugin-i@2.29.1(eslint@8.57.0))(eslint-plugin-you-dont-need-lodash-underscore@6.14.0)(eslint@8.57.0)(typescript@5.4.5)
+ '@anolilab/prettier-config':
+ specifier: ^5.0.14
+ version: 5.0.14(prettier@3.2.5)
+ '@anolilab/semantic-release-preset':
+ specifier: ^8.0.3
+ version: 8.0.3(semantic-release@23.1.1(typescript@5.4.5))
+ '@babel/core':
+ specifier: ^7.24.3
+ version: 7.24.5
+ '@rushstack/eslint-plugin-security':
+ specifier: ^0.8.1
+ version: 0.8.1(eslint@8.57.0)(typescript@5.4.5)
+ '@secretlint/secretlint-rule-preset-recommend':
+ specifier: ^8.1.2
+ version: 8.2.4
+ '@semantic-release/changelog':
+ specifier: ^6.0.3
+ version: 6.0.3(semantic-release@23.1.1(typescript@5.4.5))
+ '@semantic-release/git':
+ specifier: ^10.0.1
+ version: 10.0.1(semantic-release@23.1.1(typescript@5.4.5))
+ '@semantic-release/github':
+ specifier: ^10.0.4
+ version: 10.0.5(semantic-release@23.1.1(typescript@5.4.5))
+ '@types/dockerode':
+ specifier: ^3.3.29
+ version: 3.3.29
+ '@types/ini':
+ specifier: ^4.1.0
+ version: 4.1.0
+ '@types/node':
+ specifier: 18.18.14
+ version: 18.18.14
+ '@types/semantic-release__error':
+ specifier: 3.0.3
+ version: 3.0.3
+ '@types/semver':
+ specifier: 7.5.8
+ version: 7.5.8
+ '@types/stream-buffers':
+ specifier: ^3.0.7
+ version: 3.0.7
+ '@vitest/coverage-v8':
+ specifier: ^1.4.0
+ version: 1.6.0(vitest@1.6.0(@types/node@18.18.14)(@vitest/ui@1.6.0))
+ '@vitest/ui':
+ specifier: ^1.4.0
+ version: 1.6.0(vitest@1.6.0)
+ cross-env:
+ specifier: ^7.0.3
+ version: 7.0.3
+ dockerode:
+ specifier: 4.0.2
+ version: 4.0.2
+ eslint:
+ specifier: ^8.57.0
+ version: 8.57.0
+ eslint-plugin-deprecation:
+ specifier: ^2.0.0
+ version: 2.0.0(eslint@8.57.0)(typescript@5.4.5)
+ eslint-plugin-editorconfig:
+ specifier: ^4.0.3
+ version: 4.0.3
+ eslint-plugin-import:
+ specifier: npm:eslint-plugin-i@2.29.1
+ version: eslint-plugin-i@2.29.1(eslint@8.57.0)
+ eslint-plugin-mdx:
+ specifier: ^3.1.5
+ version: 3.1.5(eslint@8.57.0)
+ eslint-plugin-n:
+ specifier: ^17.7.0
+ version: 17.7.0(eslint@8.57.0)
+ eslint-plugin-vitest:
+ specifier: ^0.4.1
+ version: 0.4.1(eslint@8.57.0)(typescript@5.4.5)(vitest@1.6.0(@types/node@18.18.14)(@vitest/ui@1.6.0))
+ eslint-plugin-vitest-globals:
+ specifier: ^1.5.0
+ version: 1.5.0
+ eslint-plugin-you-dont-need-lodash-underscore:
+ specifier: ^6.14.0
+ version: 6.14.0
+ get-stream:
+ specifier: 9.0.1
+ version: 9.0.1
+ got:
+ specifier: ^14.2.1
+ version: 14.3.0
+ p-retry:
+ specifier: ^6.2.0
+ version: 6.2.0
+ prettier:
+ specifier: ^3.2.5
+ version: 3.2.5
+ rimraf:
+ specifier: ^5.0.5
+ version: 5.0.7
+ secretlint:
+ specifier: 8.1.2
+ version: 8.1.2
+ semantic-release:
+ specifier: ^23.0.5
+ version: 23.1.1(typescript@5.4.5)
+ sort-package-json:
+ specifier: ^2.8.0
+ version: 2.10.0
+ stream-buffers:
+ specifier: ^3.0.2
+ version: 3.0.2
+ tempy:
+ specifier: ^3.1.0
+ version: 3.1.0
+ tsup:
+ specifier: ^8.0.2
+ version: 8.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@18.18.14)(typescript@5.4.5))(typescript@5.4.5)
+ typescript:
+ specifier: ^5.4.3
+ version: 5.4.5
+ vitest:
+ specifier: ^1.4.0
+ version: 1.6.0(@types/node@18.18.14)(@vitest/ui@1.6.0)
+
packages:
'@aashutoshrathi/word-wrap@1.2.6':
@@ -396,6 +656,12 @@ packages:
peerDependencies:
semantic-release: ^18.0.1
+ '@anolilab/semantic-release-preset@8.0.3':
+ resolution: {integrity: sha512-/8ddc+6ILuL8VmxcJ6+9aGwGj/LL8CkWwbuXQcvCIjRPdSXk5anuCl2It8STa70UKBZvkvwIsttlRJzjxAqiCg==}
+ engines: {node: ^18.17 || >=20.6.1}
+ peerDependencies:
+ semantic-release: '>=22'
+
'@anolilab/textlint-config@8.0.16':
resolution: {integrity: sha512-kzIOKha8sIPo4kOMCq2lcflFH4PSODEI7+TQpKcp70EmUQkOVd7+Yw1laltXKs2ItDDD4RHYKaroRz0MmnuOtg==}
engines: {node: '>=18.* <=21.*'}
@@ -519,6 +785,9 @@ packages:
resolution: {integrity: sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==}
engines: {node: '>=6.9.0'}
+ '@balena/dockerignore@1.0.2':
+ resolution: {integrity: sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==}
+
'@bcoe/v8-coverage@0.2.3':
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
@@ -740,138 +1009,276 @@ packages:
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
engines: {node: '>=12'}
+ '@esbuild/aix-ppc64@0.19.12':
+ resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [aix]
+
'@esbuild/aix-ppc64@0.20.2':
resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==}
engines: {node: '>=12'}
cpu: [ppc64]
os: [aix]
+ '@esbuild/android-arm64@0.19.12':
+ resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+
'@esbuild/android-arm64@0.20.2':
resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==}
engines: {node: '>=12'}
cpu: [arm64]
os: [android]
+ '@esbuild/android-arm@0.19.12':
+ resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+
'@esbuild/android-arm@0.20.2':
resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==}
engines: {node: '>=12'}
cpu: [arm]
os: [android]
+ '@esbuild/android-x64@0.19.12':
+ resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+
'@esbuild/android-x64@0.20.2':
resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==}
engines: {node: '>=12'}
cpu: [x64]
os: [android]
+ '@esbuild/darwin-arm64@0.19.12':
+ resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+
'@esbuild/darwin-arm64@0.20.2':
resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==}
engines: {node: '>=12'}
cpu: [arm64]
os: [darwin]
+ '@esbuild/darwin-x64@0.19.12':
+ resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+
'@esbuild/darwin-x64@0.20.2':
resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==}
engines: {node: '>=12'}
cpu: [x64]
os: [darwin]
+ '@esbuild/freebsd-arm64@0.19.12':
+ resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+
'@esbuild/freebsd-arm64@0.20.2':
resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==}
engines: {node: '>=12'}
cpu: [arm64]
os: [freebsd]
+ '@esbuild/freebsd-x64@0.19.12':
+ resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+
'@esbuild/freebsd-x64@0.20.2':
resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==}
engines: {node: '>=12'}
cpu: [x64]
os: [freebsd]
+ '@esbuild/linux-arm64@0.19.12':
+ resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+
'@esbuild/linux-arm64@0.20.2':
resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==}
engines: {node: '>=12'}
cpu: [arm64]
os: [linux]
+ '@esbuild/linux-arm@0.19.12':
+ resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+
'@esbuild/linux-arm@0.20.2':
resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==}
engines: {node: '>=12'}
cpu: [arm]
os: [linux]
+ '@esbuild/linux-ia32@0.19.12':
+ resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+
'@esbuild/linux-ia32@0.20.2':
resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==}
engines: {node: '>=12'}
cpu: [ia32]
os: [linux]
+ '@esbuild/linux-loong64@0.19.12':
+ resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+
'@esbuild/linux-loong64@0.20.2':
resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==}
engines: {node: '>=12'}
cpu: [loong64]
os: [linux]
+ '@esbuild/linux-mips64el@0.19.12':
+ resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+
'@esbuild/linux-mips64el@0.20.2':
resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==}
engines: {node: '>=12'}
cpu: [mips64el]
os: [linux]
+ '@esbuild/linux-ppc64@0.19.12':
+ resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+
'@esbuild/linux-ppc64@0.20.2':
resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==}
engines: {node: '>=12'}
cpu: [ppc64]
os: [linux]
+ '@esbuild/linux-riscv64@0.19.12':
+ resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+
'@esbuild/linux-riscv64@0.20.2':
resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==}
engines: {node: '>=12'}
cpu: [riscv64]
os: [linux]
+ '@esbuild/linux-s390x@0.19.12':
+ resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+
'@esbuild/linux-s390x@0.20.2':
resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==}
engines: {node: '>=12'}
cpu: [s390x]
os: [linux]
+ '@esbuild/linux-x64@0.19.12':
+ resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+
'@esbuild/linux-x64@0.20.2':
resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==}
engines: {node: '>=12'}
cpu: [x64]
os: [linux]
+ '@esbuild/netbsd-x64@0.19.12':
+ resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+
'@esbuild/netbsd-x64@0.20.2':
resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [netbsd]
+ '@esbuild/openbsd-x64@0.19.12':
+ resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+
'@esbuild/openbsd-x64@0.20.2':
resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [openbsd]
+ '@esbuild/sunos-x64@0.19.12':
+ resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+
'@esbuild/sunos-x64@0.20.2':
resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==}
engines: {node: '>=12'}
cpu: [x64]
os: [sunos]
+ '@esbuild/win32-arm64@0.19.12':
+ resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+
'@esbuild/win32-arm64@0.20.2':
resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==}
engines: {node: '>=12'}
cpu: [arm64]
os: [win32]
+ '@esbuild/win32-ia32@0.19.12':
+ resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+
'@esbuild/win32-ia32@0.20.2':
resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==}
engines: {node: '>=12'}
cpu: [ia32]
os: [win32]
+ '@esbuild/win32-x64@0.19.12':
+ resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+
'@esbuild/win32-x64@0.20.2':
resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==}
engines: {node: '>=12'}
@@ -1083,6 +1490,10 @@ packages:
resolution: {integrity: sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==}
engines: {node: '>= 14'}
+ '@octokit/auth-token@4.0.0':
+ resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==}
+ engines: {node: '>= 18'}
+
'@octokit/auth-token@5.1.1':
resolution: {integrity: sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA==}
engines: {node: '>= 18'}
@@ -1091,6 +1502,10 @@ packages:
resolution: {integrity: sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==}
engines: {node: '>= 14'}
+ '@octokit/core@5.2.0':
+ resolution: {integrity: sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==}
+ engines: {node: '>= 18'}
+
'@octokit/core@6.1.2':
resolution: {integrity: sha512-hEb7Ma4cGJGEUNOAVmyfdB/3WirWMg5hDuNFVejGEDFqupeOysLc2sG6HJxY2etBp5YQu5Wtxwi020jS9xlUwg==}
engines: {node: '>= 18'}
@@ -1103,10 +1518,18 @@ packages:
resolution: {integrity: sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==}
engines: {node: '>= 14'}
+ '@octokit/endpoint@9.0.5':
+ resolution: {integrity: sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==}
+ engines: {node: '>= 18'}
+
'@octokit/graphql@5.0.6':
resolution: {integrity: sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==}
engines: {node: '>= 14'}
+ '@octokit/graphql@7.1.0':
+ resolution: {integrity: sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==}
+ engines: {node: '>= 18'}
+
'@octokit/graphql@8.1.1':
resolution: {integrity: sha512-ukiRmuHTi6ebQx/HFRCXKbDlOh/7xEV6QUXaE7MJEKGNAncGI/STSbOkl12qVXZrfZdpXctx5O9X1AIaebiDBg==}
engines: {node: '>= 18'}
@@ -1114,6 +1537,9 @@ packages:
'@octokit/openapi-types@18.1.1':
resolution: {integrity: sha512-VRaeH8nCDtF5aXWnjPuEMIYf1itK/s3JYyJcWFJT8X9pSNnBtriDf7wlEWsGuhPLl4QIH4xM8fqTXDwJ3Mu6sw==}
+ '@octokit/openapi-types@20.0.0':
+ resolution: {integrity: sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==}
+
'@octokit/openapi-types@22.2.0':
resolution: {integrity: sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==}
@@ -1129,12 +1555,24 @@ packages:
peerDependencies:
'@octokit/core': '>=4'
+ '@octokit/plugin-paginate-rest@9.2.1':
+ resolution: {integrity: sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ '@octokit/core': '5'
+
'@octokit/plugin-retry@4.1.6':
resolution: {integrity: sha512-obkYzIgEC75r8+9Pnfiiqy3y/x1bc3QLE5B7qvv9wi9Kj0R5tGQFC6QMBg1154WQ9lAVypuQDGyp3hNpp15gQQ==}
engines: {node: '>= 14'}
peerDependencies:
'@octokit/core': '>=3'
+ '@octokit/plugin-retry@6.0.1':
+ resolution: {integrity: sha512-SKs+Tz9oj0g4p28qkZwl/topGcb0k0qPNX/i7vBKmDsjoeqnVfFUquqrE/O9oJY7+oLzdCtkiWSXLpLjvl6uog==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ '@octokit/core': '>=5'
+
'@octokit/plugin-retry@7.1.1':
resolution: {integrity: sha512-G9Ue+x2odcb8E1XIPhaFBnTTIrrUDfXN05iFXiqhR+SeeeDMMILcAnysOsxUpEWcQp2e5Ft397FCXTcPkiPkLw==}
engines: {node: '>= 18'}
@@ -1147,6 +1585,12 @@ packages:
peerDependencies:
'@octokit/core': ^4.0.0
+ '@octokit/plugin-throttling@8.2.0':
+ resolution: {integrity: sha512-nOpWtLayKFpgqmgD0y3GqXafMFuKcA4tRPZIfu7BArd2lEZeb1988nhWhwx4aZWmjDmUfdgVf7W+Tt4AmvRmMQ==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ '@octokit/core': ^5.0.0
+
'@octokit/plugin-throttling@9.3.0':
resolution: {integrity: sha512-B5YTToSRTzNSeEyssnrT7WwGhpIdbpV9NKIs3KyTWHX6PhpYn7gqF/+lL3BvsASBM3Sg5BAUYk7KZx5p/Ec77w==}
engines: {node: '>= 18'}
@@ -1157,6 +1601,10 @@ packages:
resolution: {integrity: sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==}
engines: {node: '>= 14'}
+ '@octokit/request-error@5.1.0':
+ resolution: {integrity: sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==}
+ engines: {node: '>= 18'}
+
'@octokit/request-error@6.1.1':
resolution: {integrity: sha512-1mw1gqT3fR/WFvnoVpY/zUM2o/XkMs/2AszUUG9I69xn0JFLv6PGkPhNk5lbfvROs79wiS0bqiJNxfCZcRJJdg==}
engines: {node: '>= 18'}
@@ -1165,6 +1613,10 @@ packages:
resolution: {integrity: sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==}
engines: {node: '>= 14'}
+ '@octokit/request@8.4.0':
+ resolution: {integrity: sha512-9Bb014e+m2TgBeEJGEbdplMVWwPmL1FPtggHQRkV+WVsMggPtEkLKPlcVYm/o8xKLkpJ7B+6N8WfQMtDLX2Dpw==}
+ engines: {node: '>= 18'}
+
'@octokit/request@9.1.1':
resolution: {integrity: sha512-pyAguc0p+f+GbQho0uNetNQMmLG1e80WjkIaqqgUkihqUp0boRU6nKItXO4VWnr+nbZiLGEyy4TeKRwqaLvYgw==}
engines: {node: '>= 18'}
@@ -1172,12 +1624,18 @@ packages:
'@octokit/tsconfig@1.0.2':
resolution: {integrity: sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==}
+ '@octokit/types@12.6.0':
+ resolution: {integrity: sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==}
+
'@octokit/types@13.5.0':
resolution: {integrity: sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==}
'@octokit/types@9.3.2':
resolution: {integrity: sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==}
+ '@one-ini/wasm@0.1.1':
+ resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==}
+
'@phenomnomnominal/tsquery@5.0.1':
resolution: {integrity: sha512-3nVv+e2FQwsW8Aw6qTU6f+1rfcJ3hrcnvH/mu9i8YhxO+9sqbOfpL8m6PbET5+xKOlz/VSbp0RoYWYCtIsnmuA==}
peerDependencies:
@@ -1348,6 +1806,12 @@ packages:
peerDependencies:
semantic-release: '>=18.0.0'
+ '@semantic-release/commit-analyzer@11.1.0':
+ resolution: {integrity: sha512-cXNTbv3nXR2hlzHjAMgbuiQVtvWHTlwwISt60B+4NZv01y/QRY7p2HcJm8Eh2StzcTJoNnflvKjHH/cjFS7d5g==}
+ engines: {node: ^18.17 || >=20.6.1}
+ peerDependencies:
+ semantic-release: '>=20.1.0'
+
'@semantic-release/commit-analyzer@12.0.0':
resolution: {integrity: sha512-qG+md5gdes+xa8zP7lIo1fWE17zRdO8yMCaxh9lyL65TQleoSv8WHHOqRURfghTytUh+NpkSyBprQ5hrkxOKVQ==}
engines: {node: '>=20.8.1'}
@@ -1386,12 +1850,30 @@ packages:
peerDependencies:
semantic-release: '>=20.1.0'
+ '@semantic-release/github@10.0.5':
+ resolution: {integrity: sha512-hmuCDkfru/Uc9+ZBNOSremAupu6BCslvOVDiG0wYcL8TQodCycp6uvwDyeym1H0M4l3ob9c0s0xMBiZjjXQ2yA==}
+ engines: {node: '>=20.8.1'}
+ peerDependencies:
+ semantic-release: '>=20.1.0'
+
'@semantic-release/github@8.1.0':
resolution: {integrity: sha512-erR9E5rpdsz0dW1I7785JtndQuMWN/iDcemcptf67tBNOmBUN0b2YNOgcjYUnBpgRpZ5ozfBHrK7Bz+2ets/Dg==}
engines: {node: '>=14.17'}
peerDependencies:
semantic-release: '>=18.0.0-beta.1'
+ '@semantic-release/github@9.2.6':
+ resolution: {integrity: sha512-shi+Lrf6exeNZF+sBhK+P011LSbhmIAoUEgEY6SsxF8irJ+J2stwI5jkyDQ+4gzYyDImzV6LCKdYB9FXnQRWKA==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ semantic-release: '>=20.1.0'
+
+ '@semantic-release/npm@11.0.3':
+ resolution: {integrity: sha512-KUsozQGhRBAnoVg4UMZj9ep436VEGwT536/jwSqB7vcEfA6oncCUU7UIYTRdLx7GvTtqn0kBjnkfLVkcnBa2YQ==}
+ engines: {node: ^18.17 || >=20}
+ peerDependencies:
+ semantic-release: '>=20.1.0'
+
'@semantic-release/npm@12.0.1':
resolution: {integrity: sha512-/6nntGSUGK2aTOI0rHPwY3ZjgY9FkXmEHbW9Kr+62NVOsyqpKKeP0lrCH+tphv+EsNdJNmqqwijTEnVWUMQ2Nw==}
engines: {node: '>=20.8.1'}
@@ -1410,6 +1892,12 @@ packages:
peerDependencies:
semantic-release: '>=18.0.0-beta.1'
+ '@semantic-release/release-notes-generator@12.1.0':
+ resolution: {integrity: sha512-g6M9AjUKAZUZnxaJZnouNBeDNTCUrJ5Ltj+VJ60gJeDaRRahcHsry9HW8yKrnKkKNkx5lbWiEP1FPMqVNQz8Kg==}
+ engines: {node: ^18.17 || >=20.6.1}
+ peerDependencies:
+ semantic-release: '>=20.1.0'
+
'@semantic-release/release-notes-generator@13.0.0':
resolution: {integrity: sha512-LEeZWb340keMYuREMyxrODPXJJ0JOL8D/mCl74B4LdzbxhtXV2LrPN2QBEcGJrlQhoqLO0RhxQb6masHytKw+A==}
engines: {node: '>=20.8.1'}
@@ -1430,6 +1918,10 @@ packages:
resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==}
engines: {node: '>=14.16'}
+ '@sindresorhus/is@6.3.1':
+ resolution: {integrity: sha512-FX4MfcifwJyFOI2lPoX7PQxCqx8BG1HCho7WdiXwpEQx1Ycij0JxkfYtGK7yqNScrZGSlt6RE6sw8QYoH7eKnQ==}
+ engines: {node: '>=16'}
+
'@sindresorhus/merge-streams@1.0.0':
resolution: {integrity: sha512-rUV5WyJrJLoloD4NDN1V1+LDMDWOa4OTsT4yYJwQNpTU6FWxkxHpL7eu4w+DmiH8x/EAM1otkPE1+LaspIbplw==}
engines: {node: '>=18'}
@@ -1641,6 +2133,12 @@ packages:
'@types/debug@4.1.8':
resolution: {integrity: sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==}
+ '@types/docker-modem@3.0.6':
+ resolution: {integrity: sha512-yKpAGEuKRSS8wwx0joknWxsmLha78wNMe9R2S3UNsVOkZded8UqOrV8KoeDXoXsjndxwyF3eIhyClGbO1SEhEg==}
+
+ '@types/dockerode@3.3.29':
+ resolution: {integrity: sha512-5PRRq/yt5OT/Jf77ltIdz4EiR9+VLnPF+HpU4xGFwUqmV24Co2HKBNW3w+slqZ1CYchbcDeqJASHDYWzZCcMiQ==}
+
'@types/estree-jsx@1.0.0':
resolution: {integrity: sha512-3qvGd0z8F2ENTGr/GG1yViqfiKmRfrXVx5sJyHGFu3z7m5g5utCQtGp/g29JnjflhtQJBv1WDQukHiT58xPcYQ==}
@@ -1659,6 +2157,12 @@ packages:
'@types/http-cache-semantics@4.0.2':
resolution: {integrity: sha512-FD+nQWA2zJjh4L9+pFXqWOi0Hs1ryBCfI+985NjluQ1p8EYtoLvjLOKidXBtZ4/IcxDX4o8/E8qDS3540tNliw==}
+ '@types/http-cache-semantics@4.0.4':
+ resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==}
+
+ '@types/ini@4.1.0':
+ resolution: {integrity: sha512-mTehMtc+xtnWBBvqizcqYCktKDBH2WChvx1GU3Sfe4PysFDXiNe+1YwtpVX1MDtCa4NQrSPw2+3HmvXHY3gt1w==}
+
'@types/inquirer@9.0.7':
resolution: {integrity: sha512-Q0zyBupO6NxGRZut/JdmqYKOnN95Eg5V8Csg3PGKkP+FnvsUZx1jAyK7fztIszxxMuoBA6E3KXWvdZVXIpx60g==}
@@ -1698,9 +2202,21 @@ packages:
'@types/parse-json@4.0.2':
resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==}
+ '@types/retry@0.12.2':
+ resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==}
+
+ '@types/semantic-release__error@3.0.3':
+ resolution: {integrity: sha512-zFa+QAM80q65lQc5NVnKR5BgR0ChuLnBkfRBwa9xRqzAHOJx+mozSV2g1d489mKRqYezqxYC7XI0rEVoyF1f2w==}
+
'@types/semver@7.5.8':
resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==}
+ '@types/ssh2@1.15.0':
+ resolution: {integrity: sha512-YcT8jP5F8NzWeevWvcyrrLB3zcneVjzYY9ZDSMAMboI+2zR1qYWFhwsyOFVzT7Jorn67vqxC0FRiw8YyG9P1ww==}
+
+ '@types/stream-buffers@3.0.7':
+ resolution: {integrity: sha512-azOCy05sXVXrO+qklf0c/B07H/oHaIuDDAiHPVwlk3A9Ek+ksHyTeMajLZl3r76FxpPpxem//4Te61G1iW3Giw==}
+
'@types/supports-color@8.1.1':
resolution: {integrity: sha512-dPWnWsf+kzIG140B8z2w3fr5D03TLWbOAFQl45xUpI3vcizeXriNR5VYkWZ+WTMsUHqZ9Xlt3hrxGNANFyNQfw==}
@@ -1867,6 +2383,25 @@ packages:
'@ungap/structured-clone@1.2.0':
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
+ '@visulima/fs@2.1.1':
+ resolution: {integrity: sha512-KBcdscZZyZOQRdem0pLSmAT0r85ZmckUD61XRlgnyrjTOy9dUJ/gMoosa5UvcFEBTV89qOKpOTYynZFb+9Hn5g==}
+ engines: {node: '>=18.* <=21.*'}
+ os: [darwin, linux, win32]
+ peerDependencies:
+ yaml: ^2.4.0
+ peerDependenciesMeta:
+ yaml:
+ optional: true
+
+ '@visulima/package@1.8.1':
+ resolution: {integrity: sha512-ksrIqIKeZn1ba2AOrPx5ipYtCRwOXhMBHCS0BQWjTrmlcaZgiBqrw9Bx7EbyJflqedOesIbQTTWAaGw8G86rog==}
+ engines: {node: '>=18.* <=21.*'}
+ os: [darwin, linux, win32]
+
+ '@visulima/path@1.0.0':
+ resolution: {integrity: sha512-9bJY01zRStrPqk2yKItIThZ+bRvPLHEBtvHUIGPgkmDF5fydF81IBJUxj558ZsQ8PVTcF/uMblHvdNVxyCjclQ==}
+ engines: {node: '>=18.* <=21.*'}
+
'@vitest/coverage-v8@1.6.0':
resolution: {integrity: sha512-KvapcbMY/8GYIG0rlwwOKCVNRc0OL20rrhFkg/CHNzncV03TE2XWvO5w9uZYoxNiMEBacAJt3unSOiZ7svePew==}
peerDependencies:
@@ -2002,6 +2537,10 @@ packages:
any-promise@1.3.0:
resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
+ anymatch@3.1.3:
+ resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
+ engines: {node: '>= 8'}
+
arg@4.1.3:
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
@@ -2047,6 +2586,9 @@ packages:
resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==}
engines: {node: '>=0.10.0'}
+ asn1@0.2.6:
+ resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==}
+
assertion-error@1.1.0:
resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
@@ -2095,6 +2637,9 @@ packages:
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
+ bcrypt-pbkdf@1.0.2:
+ resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==}
+
before-after-hook@2.2.3:
resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==}
@@ -2105,6 +2650,10 @@ packages:
resolution: {integrity: sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==}
engines: {node: '>=0.6'}
+ binary-extensions@2.3.0:
+ resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
+ engines: {node: '>=8'}
+
binaryextensions@4.18.0:
resolution: {integrity: sha512-PQu3Kyv9dM4FnwB7XGj1+HucW+ShvJzJqjuw1JkKVs1mWdwOKVcRjOi+pV9X52A0tNvrPCsPkbFFQb+wE1EAXw==}
engines: {node: '>=0.8'}
@@ -2166,6 +2715,10 @@ packages:
buffer@5.7.1:
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
+ buildcheck@0.0.6:
+ resolution: {integrity: sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==}
+ engines: {node: '>=10.0.0'}
+
builtin-modules@3.3.0:
resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==}
engines: {node: '>=6'}
@@ -2177,6 +2730,12 @@ packages:
resolution: {integrity: sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==}
engines: {node: '>=12'}
+ bundle-require@4.1.0:
+ resolution: {integrity: sha512-FeArRFM+ziGkRViKRnSTbHZc35dgmR9yNog05Kn0+ItI59pOAISGvnnIwW1WgFZQW59IxD9QpJnUPkdIPfZuXg==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ peerDependencies:
+ esbuild: '>=0.17'
+
cac@6.7.14:
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
engines: {node: '>=8'}
@@ -2189,6 +2748,10 @@ packages:
resolution: {integrity: sha512-3SD4rrMu1msNGEtNSt8Od6enwdo//U9s4ykmXfA2TD58kcLkCobtCDiby7kNyj7a/Q7lz/mAesAFI54rTdnvBA==}
engines: {node: '>=14.16'}
+ cacheable-request@12.0.1:
+ resolution: {integrity: sha512-Yo9wGIQUaAfIbk+qY0X4cDQgCosecfBe3V9NSyeY4qPC2SAkbCS4Xj79VP8WOzitpJUZKc/wsRCYF5ariDIwkg==}
+ engines: {node: '>=18'}
+
cachedir@2.3.0:
resolution: {integrity: sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==}
engines: {node: '>=6'}
@@ -2291,6 +2854,13 @@ packages:
check-error@1.0.3:
resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==}
+ chokidar@3.6.0:
+ resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
+ engines: {node: '>= 8.10.0'}
+
+ chownr@1.1.4:
+ resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
+
chrono-node@2.7.5:
resolution: {integrity: sha512-VJWqFN5rWmXVvXAxOD4i0jX8Tb4cLswaslyaAFhxM45zNXPsZleygPbgiaYBD7ORb9fj07zBgJb0Q6eKL+0iJg==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -2413,6 +2983,10 @@ packages:
comma-separated-tokens@2.0.3:
resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
+ commander@10.0.1:
+ resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
+ engines: {node: '>=14'}
+
commander@11.1.0:
resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==}
engines: {node: '>=16'}
@@ -2420,6 +2994,10 @@ packages:
commander@2.20.3:
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
+ commander@4.1.1:
+ resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
+ engines: {node: '>= 6'}
+
comment-parser@1.4.0:
resolution: {integrity: sha512-QLyTNiZ2KDOibvFPlZ6ZngVsZ/0gYnE6uTXi5aoDg8ed3AkJAz4sEje3Y8a29hQ1s6A99MZXe47fLAXQ1rTqaw==}
engines: {node: '>= 12.0.0'}
@@ -2551,6 +3129,10 @@ packages:
typescript:
optional: true
+ cpu-features@0.0.10:
+ resolution: {integrity: sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==}
+ engines: {node: '>=10.0.0'}
+
create-require@1.1.1:
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
@@ -2764,6 +3346,14 @@ packages:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
engines: {node: '>=8'}
+ docker-modem@5.0.3:
+ resolution: {integrity: sha512-89zhop5YVhcPEt5FpUFGr3cDyceGhq/F9J+ZndQ4KfqNvfbJpPMfgeixFgUj5OjCYAboElqODxY5Z1EBsSa6sg==}
+ engines: {node: '>= 8.0'}
+
+ dockerode@4.0.2:
+ resolution: {integrity: sha512-9wM1BVpVMFr2Pw3eJNXrYYt6DT9k0xMcsSCjtPvyQ+xa1iPg/Mo3T/gUcwI0B2cczqCeCYRPF8yFYDwtFXT0+w==}
+ engines: {node: '>= 8.0'}
+
doctrine@2.1.0:
resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
engines: {node: '>=0.10.0'}
@@ -2819,6 +3409,11 @@ packages:
eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
+ editorconfig@1.0.4:
+ resolution: {integrity: sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==}
+ engines: {node: '>=14'}
+ hasBin: true
+
ejs@3.1.10:
resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==}
engines: {node: '>=0.10.0'}
@@ -2907,6 +3502,11 @@ packages:
resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==}
engines: {node: '>= 0.4'}
+ esbuild@0.19.12:
+ resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==}
+ engines: {node: '>=12'}
+ hasBin: true
+
esbuild@0.20.2:
resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==}
engines: {node: '>=12'}
@@ -3018,6 +3618,10 @@ packages:
eslint: ^7.0.0 || ^8.0.0
typescript: ^4.2.4 || ^5.0.0
+ eslint-plugin-editorconfig@4.0.3:
+ resolution: {integrity: sha512-5YeDxm6mlv75DrTbRBK9Jw2ogqhjiz8ZCvv9bkuz/MXq0603q9FpQvQlamtas4bX1Gji4YcksY7dq7stPeGaLQ==}
+ engines: {node: '>=14', npm: '>=8'}
+
eslint-plugin-es-x@7.6.0:
resolution: {integrity: sha512-I0AmeNgevgaTR7y2lrVCJmGYF0rjoznpDvqV/kIkZSZbZ8Rw3eu4cGlvBBULScfkSOCzqKbff5LR4CNrV7mZHA==}
engines: {node: ^14.18.0 || >=16.0.0}
@@ -3463,6 +4067,10 @@ packages:
resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==}
engines: {node: '>= 14.17'}
+ form-data-encoder@4.0.2:
+ resolution: {integrity: sha512-KQVhvhK8ZkWzxKxOr56CPulAhH3dobtuQ4+hNQ+HekH/Wp5gSOafqRAeTphQUJAIk0GBvHZgJ2ZGRWd5kphMuw==}
+ engines: {node: '>= 18'}
+
form-data@4.0.0:
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
engines: {node: '>= 6'}
@@ -3690,6 +4298,10 @@ packages:
resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==}
engines: {node: '>=14.16'}
+ got@14.3.0:
+ resolution: {integrity: sha512-vZkrXdq5BtPWTXqvjXSpl6zky3zpHaOVfSug/RfFHu3YrtSsvYzopVMDqrh2do77WnGoCSSRCHW25zXOSAQ9zw==}
+ engines: {node: '>=20'}
+
graceful-fs@4.2.10:
resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==}
@@ -3832,6 +4444,10 @@ packages:
resolution: {integrity: sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ==}
engines: {node: '>=10.19.0'}
+ http2-wrapper@2.2.1:
+ resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==}
+ engines: {node: '>=10.19.0'}
+
https-proxy-agent@7.0.2:
resolution: {integrity: sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==}
engines: {node: '>= 14'}
@@ -3934,6 +4550,10 @@ packages:
resolution: {integrity: sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==}
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+ ini@4.1.3:
+ resolution: {integrity: sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==}
+ engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+
inquirer@8.2.5:
resolution: {integrity: sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==}
engines: {node: '>=12.0.0'}
@@ -3993,6 +4613,10 @@ packages:
is-bigint@1.0.4:
resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
+ is-binary-path@2.1.0:
+ resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
+ engines: {node: '>=8'}
+
is-boolean-object@1.1.2:
resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
engines: {node: '>= 0.4'}
@@ -4115,6 +4739,10 @@ packages:
resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==}
engines: {node: '>= 0.4'}
+ is-network-error@1.1.0:
+ resolution: {integrity: sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==}
+ engines: {node: '>=16'}
+
is-npm@6.0.0:
resolution: {integrity: sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -4346,6 +4974,10 @@ packages:
jju@1.4.0:
resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==}
+ joycon@3.1.1:
+ resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
+ engines: {node: '>=10'}
+
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
@@ -4419,6 +5051,9 @@ packages:
jsonc-parser@3.2.0:
resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==}
+ jsonc-parser@3.2.1:
+ resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==}
+
jsonfile@4.0.0:
resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==}
@@ -4435,6 +5070,9 @@ packages:
keyv@4.5.3:
resolution: {integrity: sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==}
+ keyv@4.5.4:
+ resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+
kind-of@6.0.3:
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
engines: {node: '>=0.10.0'}
@@ -4447,6 +5085,10 @@ packages:
resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
engines: {node: '>=6'}
+ klona@2.0.6:
+ resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==}
+ engines: {node: '>= 8'}
+
latest-version@7.0.0:
resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==}
engines: {node: '>=14.16'}
@@ -4497,6 +5139,10 @@ packages:
load-plugin@6.0.3:
resolution: {integrity: sha512-kc0X2FEUZr145odl68frm+lMJuQ23+rTXYmR6TImqPtbpmXC4vVXbWKDQ9IzndA0HfyQamWfKLhzsqGSTxE63w==}
+ load-tsconfig@0.2.5:
+ resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
local-pkg@0.5.0:
resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==}
engines: {node: '>=14'}
@@ -5117,6 +5763,10 @@ packages:
resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==}
engines: {node: '>=10'}
+ minimatch@9.0.1:
+ resolution: {integrity: sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
minimatch@9.0.3:
resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==}
engines: {node: '>=16 || 14 >=14.17'}
@@ -5146,6 +5796,9 @@ packages:
misspellings@1.1.0:
resolution: {integrity: sha512-4QT2u/8X7PccbiHUcsZeEZrt3jGIVEpfcQ1RU01wDHKHVNtNhaP+0Xmsg7YPxD7OCc8bO802BTEWeGPvAXBwuw==}
+ mkdirp-classic@0.5.3:
+ resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
+
mkdirp@0.5.6:
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
hasBin: true
@@ -5165,6 +5818,10 @@ packages:
moment@2.29.4:
resolution: {integrity: sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==}
+ move-file@3.1.0:
+ resolution: {integrity: sha512-4aE3U7CCBWgrQlQDMq8da4woBWDGHioJFiOZ8Ie6Yq2uwYQ9V2kGhTz4x3u6Wc+OU17nw0yc3rJ/lQ4jIiPe3A==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
mri@1.2.0:
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
engines: {node: '>=4'}
@@ -5189,6 +5846,9 @@ packages:
mz@2.7.0:
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
+ nan@2.19.0:
+ resolution: {integrity: sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==}
+
nanoid@3.3.7:
resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
@@ -5277,6 +5937,14 @@ packages:
resolution: {integrity: sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==}
engines: {node: ^16.14.0 || >=18.0.0}
+ normalize-package-data@6.0.1:
+ resolution: {integrity: sha512-6rvCfeRW+OEZagAB4lMLSNuTNYZWLVtKccK79VSTf//yTY5VOCgcpH80O+bZK8Neps7pUnd5G+QlMg1yV/2iZQ==}
+ engines: {node: ^16.14.0 || >=18.0.0}
+
+ normalize-path@3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+
normalize-url@6.1.0:
resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==}
engines: {node: '>=10'}
@@ -5480,6 +6148,10 @@ packages:
resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==}
engines: {node: '>=12.20'}
+ p-cancelable@4.0.1:
+ resolution: {integrity: sha512-wBowNApzd45EIKdO1LaU+LrMBwAcjfPaYtVzV3lmfM3gf8Z4CHZsiIqlM8TZZ8okYvh5A1cP6gTfCRQtwUpaUg==}
+ engines: {node: '>=14.16'}
+
p-defer@1.0.0:
resolution: {integrity: sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==}
engines: {node: '>=4'}
@@ -5576,6 +6248,10 @@ packages:
resolution: {integrity: sha512-xsrIUgI0Kn6iyDYm9StOpOeK29XM1aboGji26+QEortiFST1hGZaUQOLhtEbqHErPpGW/aSz6allwK2qcptp0Q==}
engines: {node: '>=12'}
+ p-retry@6.2.0:
+ resolution: {integrity: sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==}
+ engines: {node: '>=16.17'}
+
p-timeout@3.2.0:
resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==}
engines: {node: '>=8'}
@@ -5736,6 +6412,9 @@ packages:
pathe@1.1.1:
resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==}
+ pathe@1.1.2:
+ resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
+
pathval@1.1.1:
resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==}
@@ -5773,6 +6452,10 @@ packages:
resolution: {integrity: sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==}
engines: {node: '>=0.10.0'}
+ pirates@4.0.6:
+ resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
+ engines: {node: '>= 6'}
+
pkg-conf@2.1.0:
resolution: {integrity: sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g==}
engines: {node: '>=4'}
@@ -5796,6 +6479,18 @@ packages:
resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==}
engines: {node: '>= 0.4'}
+ postcss-load-config@4.0.2:
+ resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==}
+ engines: {node: '>= 14'}
+ peerDependencies:
+ postcss: '>=8.0.9'
+ ts-node: '>=9.0.0'
+ peerDependenciesMeta:
+ postcss:
+ optional: true
+ ts-node:
+ optional: true
+
postcss@8.4.38:
resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==}
engines: {node: ^10 || ^12 || >=14}
@@ -5864,6 +6559,9 @@ packages:
pump@1.0.3:
resolution: {integrity: sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==}
+ pump@3.0.0:
+ resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==}
+
punycode@2.3.0:
resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==}
engines: {node: '>=6'}
@@ -5966,6 +6664,10 @@ packages:
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
engines: {node: '>= 6'}
+ readdirp@3.6.0:
+ resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
+ engines: {node: '>=8.10.0'}
+
readline-transform@1.0.0:
resolution: {integrity: sha512-7KA6+N9IGat52d83dvxnApAWN+MtVb1MiVuMR/cf1O4kYsJG+g/Aav0AHcHKsb6StinayfPLne0+fMX2sOzAKg==}
engines: {node: '>=6'}
@@ -6140,6 +6842,10 @@ packages:
retext-profanities@7.2.2:
resolution: {integrity: sha512-nwrR987v3m7+JQ8wyK8oE+adqS1aYUyHyf+k6omflI/8PL9Slbp/39YieTJJvrmR0udBe2iV7aURXW5/3Uj12w==}
+ retry@0.13.1:
+ resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==}
+ engines: {node: '>= 4'}
+
reusify@1.0.4:
resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
@@ -6214,6 +6920,11 @@ packages:
resolution: {integrity: sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ==}
engines: {node: ^14.0.0 || >=16.0.0}
+ secretlint@8.1.2:
+ resolution: {integrity: sha512-YJf1WoIu+bevQdAwc1YnK9KdytOJ+5g9lRa90nmTyC2WlhIBK7s6CEVw46kUzxn4y+UVEF9POn7vDsyThqrQQQ==}
+ engines: {node: ^14.13.1 || >=16.0.0}
+ hasBin: true
+
secretlint@8.2.3:
resolution: {integrity: sha512-B+Qqb1GwidwDUOryXWtGO+p4FfgvzyaVApPnq7eBBggyGhb3UTSfqX4Tupn2tMaq8gowLZrY8xYixHiPvpfeVw==}
engines: {node: ^14.13.1 || >=16.0.0}
@@ -6369,6 +7080,10 @@ packages:
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
engines: {node: '>=0.10.0'}
+ source-map@0.8.0-beta.0:
+ resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==}
+ engines: {node: '>= 8'}
+
space-separated-tokens@2.0.2:
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
@@ -6391,6 +7106,9 @@ packages:
spdx-license-ids@3.0.15:
resolution: {integrity: sha512-lpT8hSQp9jAKp9mhtBU4Xjon8LPGBvLIuBiSVhMEtmLecTh2mO0tlqrAMp47tBXzMr13NJMQ2lf7RpQGLJ3HsQ==}
+ split-ca@1.0.1:
+ resolution: {integrity: sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ==}
+
split-transform-stream@0.1.1:
resolution: {integrity: sha512-nV8lOb9BKS3BqODBjmzELm0Kl878nWoTjdfn6z/v6d/zW8YS/EQ76fP11a/D6Fm6QTsbLdsFJBIpz6t17zHJnQ==}
@@ -6413,6 +7131,10 @@ packages:
sprintf-js@1.0.3:
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
+ ssh2@1.15.0:
+ resolution: {integrity: sha512-C0PHgX4h6lBxYx7hcXwu3QWdh4tg6tZZsTfXcdvc5caW/EMxaB4H9dWsl7qk+F7LAW762hp8VbXOX7x4xUYvEw==}
+ engines: {node: '>=10.16.0'}
+
stackback@0.0.2:
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
@@ -6541,6 +7263,11 @@ packages:
structured-source@4.0.0:
resolution: {integrity: sha512-qGzRFNJDjFieQkl/sVOI2dUjHKRyL9dAJi2gCPGJLbJHBIkyOHxjuocpIEfbLioX+qSJpvbYdT49/YCdMznKxA==}
+ sucrase@3.35.0:
+ resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ hasBin: true
+
super-regex@1.0.0:
resolution: {integrity: sha512-CY8u7DtbvucKuquCmOFEKhr9Besln7n9uN8eFbwcoGYWXOMW07u2o8njWaiXt11ylS3qoGF55pILjRmPlbodyg==}
engines: {node: '>=18'}
@@ -6589,6 +7316,9 @@ packages:
resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
engines: {node: '>=6'}
+ tar-fs@2.0.1:
+ resolution: {integrity: sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA==}
+
tar-stream@2.2.0:
resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==}
engines: {node: '>=6'}
@@ -6799,10 +7529,17 @@ packages:
tr46@0.0.3:
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
+ tr46@1.0.1:
+ resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==}
+
traverse@0.6.9:
resolution: {integrity: sha512-7bBrcF+/LQzSgFmT0X5YclVqQxtv7TDJ1f8Wj7ibBu/U6BMLeOpUxuZjV7rMc44UtKxlnMFigdhFAIszSX1DMg==}
engines: {node: '>= 0.4'}
+ tree-kill@1.2.2:
+ resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
+ hasBin: true
+
trim-newlines@3.0.1:
resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==}
engines: {node: '>=8'}
@@ -6832,6 +7569,13 @@ packages:
peerDependencies:
typescript: '>=4.2.0'
+ ts-deepmerge@7.0.0:
+ resolution: {integrity: sha512-WZ/iAJrKDhdINv1WG6KZIGHrZDar6VfhftG1QJFpVbOYZMYJLJOvZOo1amictRXVdBXZIgBHKswMTXzElngprA==}
+ engines: {node: '>=14.13.1'}
+
+ ts-interface-checker@0.1.13:
+ resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
+
ts-node@10.9.2:
resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==}
hasBin: true
@@ -6856,6 +7600,25 @@ packages:
tslib@2.6.2:
resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
+ tsup@8.0.2:
+ resolution: {integrity: sha512-NY8xtQXdH7hDUAZwcQdY/Vzlw9johQsaqf7iwZ6g1DOUlFYQ5/AtVAjTvihhEyeRlGo4dLRVHtrRaL35M1daqQ==}
+ engines: {node: '>=18'}
+ hasBin: true
+ peerDependencies:
+ '@microsoft/api-extractor': ^7.36.0
+ '@swc/core': ^1
+ postcss: ^8.4.12
+ typescript: '>=4.5.0'
+ peerDependenciesMeta:
+ '@microsoft/api-extractor':
+ optional: true
+ '@swc/core':
+ optional: true
+ postcss:
+ optional: true
+ typescript:
+ optional: true
+
tsutils-etc@1.4.2:
resolution: {integrity: sha512-2Dn5SxTDOu6YWDNKcx1xu2YUy6PUeKrWZB/x2cQ8vY2+iz3JRembKn/iZ0JLT1ZudGNwQQvtFX9AwvRHbXuPUg==}
hasBin: true
@@ -6869,6 +7632,9 @@ packages:
peerDependencies:
typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta'
+ tweetnacl@0.14.5:
+ resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==}
+
txt-ast-traverse@1.2.1:
resolution: {integrity: sha512-rxih9n0dRqIiVSKlm4Rkdz4QH4f8RvX6rZiDVXgm3Je8vpvJ4LOUXxoRoBVXNkIVpA1x5wBlNDXtdLzpaxzFIg==}
deprecated: See https://github.com/textlint/textlint/issues/455
@@ -6917,6 +7683,10 @@ packages:
resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==}
engines: {node: '>=14.16'}
+ type-fest@4.18.2:
+ resolution: {integrity: sha512-+suCYpfJLAe4OXS6+PPXjW3urOS4IoP9waSiLuXfLgqZODKw/aWwASvzqE886wA0kQgGy0mIWyhd87VpqIy6Xg==}
+ engines: {node: '>=16'}
+
type-fest@4.8.3:
resolution: {integrity: sha512-//BaTm14Q/gHBn09xlnKNqfI8t6bmdzx2DXYfPBNofN0WUybCEUDcbCWcTa0oF09lzLjZgPphXAsvRiMK0V6Bw==}
engines: {node: '>=16'}
@@ -7288,9 +8058,15 @@ packages:
webidl-conversions@3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
+ webidl-conversions@4.0.2:
+ resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==}
+
whatwg-url@5.0.0:
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
+ whatwg-url@7.1.0:
+ resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==}
+
which-boxed-primitive@1.0.2:
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
@@ -7448,7 +8224,7 @@ snapshots:
- '@types/node'
- typescript
- '@anolilab/eslint-config@15.0.3(@babel/core@7.24.5)(eslint-plugin-i@2.29.1(eslint@8.57.0))(eslint-plugin-you-dont-need-lodash-underscore@6.14.0)(eslint@8.57.0)(typescript@5.4.5)':
+ '@anolilab/eslint-config@15.0.3(@babel/core@7.24.5)(eslint-plugin-editorconfig@4.0.3)(eslint-plugin-i@2.29.1(eslint@8.57.0))(eslint-plugin-you-dont-need-lodash-underscore@6.14.0)(eslint@8.57.0)(typescript@5.4.5)':
dependencies:
'@anolilab/package-json-utils': 3.0.9
'@babel/core': 7.24.5
@@ -7498,6 +8274,7 @@ snapshots:
toml-eslint-parser: 0.6.0
yaml-eslint-parser: 1.2.2
optionalDependencies:
+ eslint-plugin-editorconfig: 4.0.3
eslint-plugin-you-dont-need-lodash-underscore: 6.14.0
typescript: 5.4.5
transitivePeerDependencies:
@@ -7577,6 +8354,21 @@ snapshots:
- supports-color
- typescript
+ '@anolilab/semantic-release-preset@8.0.3(semantic-release@23.1.1(typescript@5.4.5))':
+ dependencies:
+ '@anolilab/package-json-utils': 3.0.9
+ '@semantic-release/changelog': 6.0.3(semantic-release@23.1.1(typescript@5.4.5))
+ '@semantic-release/commit-analyzer': 11.1.0(semantic-release@23.1.1(typescript@5.4.5))
+ '@semantic-release/exec': 6.0.3(semantic-release@23.1.1(typescript@5.4.5))
+ '@semantic-release/git': 10.0.1(semantic-release@23.1.1(typescript@5.4.5))
+ '@semantic-release/github': 9.2.6(semantic-release@23.1.1(typescript@5.4.5))
+ '@semantic-release/npm': 11.0.3(semantic-release@23.1.1(typescript@5.4.5))
+ '@semantic-release/release-notes-generator': 12.1.0(semantic-release@23.1.1(typescript@5.4.5))
+ conventional-changelog-conventionalcommits: 7.0.2
+ semantic-release: 23.1.1(typescript@5.4.5)
+ transitivePeerDependencies:
+ - supports-color
+
'@anolilab/textlint-config@8.0.16(textlint@14.0.4)':
dependencies:
'@anolilab/package-json-utils': 3.0.9
@@ -7757,6 +8549,8 @@ snapshots:
'@babel/helper-validator-identifier': 7.24.5
to-fast-properties: 2.0.0
+ '@balena/dockerignore@1.0.2': {}
+
'@bcoe/v8-coverage@0.2.3': {}
'@colors/colors@1.5.0':
@@ -8117,72 +8911,141 @@ snapshots:
dependencies:
'@jridgewell/trace-mapping': 0.3.9
+ '@esbuild/aix-ppc64@0.19.12':
+ optional: true
+
'@esbuild/aix-ppc64@0.20.2':
optional: true
+ '@esbuild/android-arm64@0.19.12':
+ optional: true
+
'@esbuild/android-arm64@0.20.2':
optional: true
+ '@esbuild/android-arm@0.19.12':
+ optional: true
+
'@esbuild/android-arm@0.20.2':
optional: true
+ '@esbuild/android-x64@0.19.12':
+ optional: true
+
'@esbuild/android-x64@0.20.2':
optional: true
+ '@esbuild/darwin-arm64@0.19.12':
+ optional: true
+
'@esbuild/darwin-arm64@0.20.2':
optional: true
+ '@esbuild/darwin-x64@0.19.12':
+ optional: true
+
'@esbuild/darwin-x64@0.20.2':
optional: true
+ '@esbuild/freebsd-arm64@0.19.12':
+ optional: true
+
'@esbuild/freebsd-arm64@0.20.2':
optional: true
+ '@esbuild/freebsd-x64@0.19.12':
+ optional: true
+
'@esbuild/freebsd-x64@0.20.2':
optional: true
+ '@esbuild/linux-arm64@0.19.12':
+ optional: true
+
'@esbuild/linux-arm64@0.20.2':
optional: true
+ '@esbuild/linux-arm@0.19.12':
+ optional: true
+
'@esbuild/linux-arm@0.20.2':
optional: true
+ '@esbuild/linux-ia32@0.19.12':
+ optional: true
+
'@esbuild/linux-ia32@0.20.2':
optional: true
+ '@esbuild/linux-loong64@0.19.12':
+ optional: true
+
'@esbuild/linux-loong64@0.20.2':
optional: true
+ '@esbuild/linux-mips64el@0.19.12':
+ optional: true
+
'@esbuild/linux-mips64el@0.20.2':
optional: true
+ '@esbuild/linux-ppc64@0.19.12':
+ optional: true
+
'@esbuild/linux-ppc64@0.20.2':
optional: true
+ '@esbuild/linux-riscv64@0.19.12':
+ optional: true
+
'@esbuild/linux-riscv64@0.20.2':
optional: true
+ '@esbuild/linux-s390x@0.19.12':
+ optional: true
+
'@esbuild/linux-s390x@0.20.2':
optional: true
+ '@esbuild/linux-x64@0.19.12':
+ optional: true
+
'@esbuild/linux-x64@0.20.2':
optional: true
+ '@esbuild/netbsd-x64@0.19.12':
+ optional: true
+
'@esbuild/netbsd-x64@0.20.2':
optional: true
+ '@esbuild/openbsd-x64@0.19.12':
+ optional: true
+
'@esbuild/openbsd-x64@0.20.2':
optional: true
+ '@esbuild/sunos-x64@0.19.12':
+ optional: true
+
'@esbuild/sunos-x64@0.20.2':
optional: true
+ '@esbuild/win32-arm64@0.19.12':
+ optional: true
+
'@esbuild/win32-arm64@0.20.2':
optional: true
+ '@esbuild/win32-ia32@0.19.12':
+ optional: true
+
'@esbuild/win32-ia32@0.20.2':
optional: true
+ '@esbuild/win32-x64@0.19.12':
+ optional: true
+
'@esbuild/win32-x64@0.20.2':
optional: true
@@ -8303,7 +9166,7 @@ snapshots:
dependencies:
'@npmcli/map-workspaces': 3.0.4
ci-info: 3.8.0
- ini: 4.1.2
+ ini: 4.1.3
nopt: 7.2.0
proc-log: 3.0.0
read-package-json-fast: 3.0.2
@@ -8314,7 +9177,7 @@ snapshots:
dependencies:
'@npmcli/map-workspaces': 3.0.4
ci-info: 4.0.0
- ini: 4.1.2
+ ini: 4.1.3
nopt: 7.2.0
proc-log: 4.2.0
read-package-json-fast: 3.0.2
@@ -8412,6 +9275,8 @@ snapshots:
'@octokit/auth-token@3.0.4': {}
+ '@octokit/auth-token@4.0.0': {}
+
'@octokit/auth-token@5.1.1': {}
'@octokit/core@4.2.4':
@@ -8426,6 +9291,16 @@ snapshots:
transitivePeerDependencies:
- encoding
+ '@octokit/core@5.2.0':
+ dependencies:
+ '@octokit/auth-token': 4.0.0
+ '@octokit/graphql': 7.1.0
+ '@octokit/request': 8.4.0
+ '@octokit/request-error': 5.1.0
+ '@octokit/types': 13.5.0
+ before-after-hook: 2.2.3
+ universal-user-agent: 6.0.1
+
'@octokit/core@6.1.2':
dependencies:
'@octokit/auth-token': 5.1.1
@@ -8447,6 +9322,11 @@ snapshots:
is-plain-object: 5.0.0
universal-user-agent: 6.0.1
+ '@octokit/endpoint@9.0.5':
+ dependencies:
+ '@octokit/types': 13.5.0
+ universal-user-agent: 6.0.1
+
'@octokit/graphql@5.0.6':
dependencies:
'@octokit/request': 6.2.8
@@ -8455,6 +9335,12 @@ snapshots:
transitivePeerDependencies:
- encoding
+ '@octokit/graphql@7.1.0':
+ dependencies:
+ '@octokit/request': 8.4.0
+ '@octokit/types': 13.5.0
+ universal-user-agent: 6.0.1
+
'@octokit/graphql@8.1.1':
dependencies:
'@octokit/request': 9.1.1
@@ -8463,6 +9349,8 @@ snapshots:
'@octokit/openapi-types@18.1.1': {}
+ '@octokit/openapi-types@20.0.0': {}
+
'@octokit/openapi-types@22.2.0': {}
'@octokit/plugin-paginate-rest@11.3.0(@octokit/core@6.1.2)':
@@ -8476,12 +9364,24 @@ snapshots:
'@octokit/tsconfig': 1.0.2
'@octokit/types': 9.3.2
+ '@octokit/plugin-paginate-rest@9.2.1(@octokit/core@5.2.0)':
+ dependencies:
+ '@octokit/core': 5.2.0
+ '@octokit/types': 12.6.0
+
'@octokit/plugin-retry@4.1.6(@octokit/core@4.2.4)':
dependencies:
'@octokit/core': 4.2.4
'@octokit/types': 9.3.2
bottleneck: 2.19.5
+ '@octokit/plugin-retry@6.0.1(@octokit/core@5.2.0)':
+ dependencies:
+ '@octokit/core': 5.2.0
+ '@octokit/request-error': 5.1.0
+ '@octokit/types': 12.6.0
+ bottleneck: 2.19.5
+
'@octokit/plugin-retry@7.1.1(@octokit/core@6.1.2)':
dependencies:
'@octokit/core': 6.1.2
@@ -8495,6 +9395,12 @@ snapshots:
'@octokit/types': 9.3.2
bottleneck: 2.19.5
+ '@octokit/plugin-throttling@8.2.0(@octokit/core@5.2.0)':
+ dependencies:
+ '@octokit/core': 5.2.0
+ '@octokit/types': 12.6.0
+ bottleneck: 2.19.5
+
'@octokit/plugin-throttling@9.3.0(@octokit/core@6.1.2)':
dependencies:
'@octokit/core': 6.1.2
@@ -8507,6 +9413,12 @@ snapshots:
deprecation: 2.3.1
once: 1.4.0
+ '@octokit/request-error@5.1.0':
+ dependencies:
+ '@octokit/types': 13.5.0
+ deprecation: 2.3.1
+ once: 1.4.0
+
'@octokit/request-error@6.1.1':
dependencies:
'@octokit/types': 13.5.0
@@ -8522,6 +9434,13 @@ snapshots:
transitivePeerDependencies:
- encoding
+ '@octokit/request@8.4.0':
+ dependencies:
+ '@octokit/endpoint': 9.0.5
+ '@octokit/request-error': 5.1.0
+ '@octokit/types': 13.5.0
+ universal-user-agent: 6.0.1
+
'@octokit/request@9.1.1':
dependencies:
'@octokit/endpoint': 10.1.1
@@ -8531,6 +9450,10 @@ snapshots:
'@octokit/tsconfig@1.0.2': {}
+ '@octokit/types@12.6.0':
+ dependencies:
+ '@octokit/openapi-types': 20.0.0
+
'@octokit/types@13.5.0':
dependencies:
'@octokit/openapi-types': 22.2.0
@@ -8539,6 +9462,8 @@ snapshots:
dependencies:
'@octokit/openapi-types': 18.1.1
+ '@one-ini/wasm@0.1.1': {}
+
'@phenomnomnominal/tsquery@5.0.1(typescript@5.4.5)':
dependencies:
esquery: 1.5.0
@@ -8716,6 +9641,19 @@ snapshots:
lodash: 4.17.21
semantic-release: 23.1.1(typescript@5.4.5)
+ '@semantic-release/commit-analyzer@11.1.0(semantic-release@23.1.1(typescript@5.4.5))':
+ dependencies:
+ conventional-changelog-angular: 7.0.0
+ conventional-commits-filter: 4.0.0
+ conventional-commits-parser: 5.0.0
+ debug: 4.3.4
+ import-from-esm: 1.3.3
+ lodash-es: 4.17.21
+ micromatch: 4.0.5
+ semantic-release: 23.1.1(typescript@5.4.5)
+ transitivePeerDependencies:
+ - supports-color
+
'@semantic-release/commit-analyzer@12.0.0(semantic-release@23.1.1(typescript@5.4.5))':
dependencies:
conventional-changelog-angular: 7.0.0
@@ -8794,6 +9732,28 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@semantic-release/github@10.0.5(semantic-release@23.1.1(typescript@5.4.5))':
+ dependencies:
+ '@octokit/core': 6.1.2
+ '@octokit/plugin-paginate-rest': 11.3.0(@octokit/core@6.1.2)
+ '@octokit/plugin-retry': 7.1.1(@octokit/core@6.1.2)
+ '@octokit/plugin-throttling': 9.3.0(@octokit/core@6.1.2)
+ '@semantic-release/error': 4.0.0
+ aggregate-error: 5.0.0
+ debug: 4.3.4
+ dir-glob: 3.0.1
+ globby: 14.0.1
+ http-proxy-agent: 7.0.0
+ https-proxy-agent: 7.0.2
+ issue-parser: 7.0.0
+ lodash-es: 4.17.21
+ mime: 4.0.0
+ p-filter: 4.1.0
+ semantic-release: 23.1.1(typescript@5.4.5)
+ url-join: 5.0.0
+ transitivePeerDependencies:
+ - supports-color
+
'@semantic-release/github@8.1.0(semantic-release@23.1.1(typescript@5.4.5))':
dependencies:
'@octokit/core': 4.2.4
@@ -8818,6 +9778,45 @@ snapshots:
- encoding
- supports-color
+ '@semantic-release/github@9.2.6(semantic-release@23.1.1(typescript@5.4.5))':
+ dependencies:
+ '@octokit/core': 5.2.0
+ '@octokit/plugin-paginate-rest': 9.2.1(@octokit/core@5.2.0)
+ '@octokit/plugin-retry': 6.0.1(@octokit/core@5.2.0)
+ '@octokit/plugin-throttling': 8.2.0(@octokit/core@5.2.0)
+ '@semantic-release/error': 4.0.0
+ aggregate-error: 5.0.0
+ debug: 4.3.4
+ dir-glob: 3.0.1
+ globby: 14.0.1
+ http-proxy-agent: 7.0.0
+ https-proxy-agent: 7.0.2
+ issue-parser: 6.0.0
+ lodash-es: 4.17.21
+ mime: 4.0.0
+ p-filter: 4.1.0
+ semantic-release: 23.1.1(typescript@5.4.5)
+ url-join: 5.0.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@semantic-release/npm@11.0.3(semantic-release@23.1.1(typescript@5.4.5))':
+ dependencies:
+ '@semantic-release/error': 4.0.0
+ aggregate-error: 5.0.0
+ execa: 8.0.1
+ fs-extra: 11.1.1
+ lodash-es: 4.17.21
+ nerf-dart: 1.0.0
+ normalize-url: 8.0.1
+ npm: 10.7.0
+ rc: 1.2.8
+ read-pkg: 9.0.1
+ registry-auth-token: 5.0.2
+ semantic-release: 23.1.1(typescript@5.4.5)
+ semver: 7.6.2
+ tempy: 3.1.0
+
'@semantic-release/npm@12.0.1(semantic-release@23.1.1(typescript@5.4.5))':
dependencies:
'@semantic-release/error': 4.0.0
@@ -8868,6 +9867,22 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@semantic-release/release-notes-generator@12.1.0(semantic-release@23.1.1(typescript@5.4.5))':
+ dependencies:
+ conventional-changelog-angular: 7.0.0
+ conventional-changelog-writer: 7.0.1
+ conventional-commits-filter: 4.0.0
+ conventional-commits-parser: 5.0.0
+ debug: 4.3.4
+ get-stream: 7.0.1
+ import-from-esm: 1.3.3
+ into-stream: 7.0.0
+ lodash-es: 4.17.21
+ read-pkg-up: 11.0.0
+ semantic-release: 23.1.1(typescript@5.4.5)
+ transitivePeerDependencies:
+ - supports-color
+
'@semantic-release/release-notes-generator@13.0.0(semantic-release@23.1.1(typescript@5.4.5))':
dependencies:
conventional-changelog-angular: 7.0.0
@@ -8896,6 +9911,8 @@ snapshots:
'@sindresorhus/is@5.6.0': {}
+ '@sindresorhus/is@6.3.1': {}
+
'@sindresorhus/merge-streams@1.0.0': {}
'@sindresorhus/merge-streams@2.3.0': {}
@@ -9270,16 +10287,27 @@ snapshots:
'@types/concat-stream@2.0.0':
dependencies:
- '@types/node': 20.12.12
+ '@types/node': 18.18.14
'@types/conventional-commits-parser@5.0.0':
dependencies:
- '@types/node': 20.12.12
+ '@types/node': 18.18.14
'@types/debug@4.1.8':
dependencies:
'@types/ms': 0.7.31
+ '@types/docker-modem@3.0.6':
+ dependencies:
+ '@types/node': 18.18.14
+ '@types/ssh2': 1.15.0
+
+ '@types/dockerode@3.3.29':
+ dependencies:
+ '@types/docker-modem': 3.0.6
+ '@types/node': 18.18.14
+ '@types/ssh2': 1.15.0
+
'@types/estree-jsx@1.0.0':
dependencies:
'@types/estree': 1.0.5
@@ -9298,6 +10326,10 @@ snapshots:
'@types/http-cache-semantics@4.0.2': {}
+ '@types/http-cache-semantics@4.0.4': {}
+
+ '@types/ini@4.1.0': {}
+
'@types/inquirer@9.0.7':
dependencies:
'@types/through': 0.0.33
@@ -9310,7 +10342,7 @@ snapshots:
'@types/liftoff@4.0.3':
dependencies:
'@types/fined': 1.1.5
- '@types/node': 20.12.12
+ '@types/node': 18.18.14
'@types/mdast@3.0.12':
dependencies:
@@ -9340,13 +10372,25 @@ snapshots:
'@types/parse-json@4.0.2': {}
+ '@types/retry@0.12.2': {}
+
+ '@types/semantic-release__error@3.0.3': {}
+
'@types/semver@7.5.8': {}
+ '@types/ssh2@1.15.0':
+ dependencies:
+ '@types/node': 18.18.14
+
+ '@types/stream-buffers@3.0.7':
+ dependencies:
+ '@types/node': 18.18.14
+
'@types/supports-color@8.1.1': {}
'@types/through@0.0.33':
dependencies:
- '@types/node': 20.12.12
+ '@types/node': 18.18.14
'@types/unist@2.0.8': {}
@@ -9461,7 +10505,7 @@ snapshots:
globby: 11.1.0
is-glob: 4.0.3
semver: 7.6.2
- ts-api-utils: 1.0.3(typescript@5.4.5)
+ ts-api-utils: 1.3.0(typescript@5.4.5)
optionalDependencies:
typescript: 5.4.5
transitivePeerDependencies:
@@ -9573,6 +10617,43 @@ snapshots:
'@ungap/structured-clone@1.2.0': {}
+ '@visulima/fs@2.1.1':
+ dependencies:
+ pathe: 1.1.2
+ type-fest: 4.18.2
+
+ '@visulima/package@1.8.1':
+ dependencies:
+ '@visulima/fs': 2.1.1
+ jsonc-parser: 3.2.1
+ normalize-package-data: 6.0.1
+ pathe: 1.1.2
+ resolve-pkg-maps: 1.0.0
+ type-fest: 4.18.2
+ transitivePeerDependencies:
+ - yaml
+
+ '@visulima/path@1.0.0': {}
+
+ '@vitest/coverage-v8@1.6.0(vitest@1.6.0(@types/node@18.18.14)(@vitest/ui@1.6.0))':
+ dependencies:
+ '@ampproject/remapping': 2.2.1
+ '@bcoe/v8-coverage': 0.2.3
+ debug: 4.3.4
+ istanbul-lib-coverage: 3.2.2
+ istanbul-lib-report: 3.0.1
+ istanbul-lib-source-maps: 5.0.4
+ istanbul-reports: 3.1.6
+ magic-string: 0.30.10
+ magicast: 0.3.4
+ picocolors: 1.0.1
+ std-env: 3.7.0
+ strip-literal: 2.1.0
+ test-exclude: 6.0.0
+ vitest: 1.6.0(@types/node@18.18.14)(@vitest/ui@1.6.0)
+ transitivePeerDependencies:
+ - supports-color
+
'@vitest/coverage-v8@1.6.0(vitest@1.6.0(@types/node@20.12.12)(@vitest/ui@1.6.0))':
dependencies:
'@ampproject/remapping': 2.2.1
@@ -9759,6 +10840,11 @@ snapshots:
any-promise@1.3.0: {}
+ anymatch@3.1.3:
+ dependencies:
+ normalize-path: 3.0.0
+ picomatch: 2.3.1
+
arg@4.1.3: {}
argparse@1.0.10:
@@ -9799,6 +10885,10 @@ snapshots:
arrify@1.0.1: {}
+ asn1@0.2.6:
+ dependencies:
+ safer-buffer: 2.1.2
+
assertion-error@1.1.0: {}
assign-symbols@1.0.0: {}
@@ -9846,12 +10936,18 @@ snapshots:
base64-js@1.5.1: {}
+ bcrypt-pbkdf@1.0.2:
+ dependencies:
+ tweetnacl: 0.14.5
+
before-after-hook@2.2.3: {}
before-after-hook@3.0.2: {}
big-integer@1.6.51: {}
+ binary-extensions@2.3.0: {}
+
binaryextensions@4.18.0: {}
bl@4.1.0:
@@ -9919,6 +11015,9 @@ snapshots:
base64-js: 1.5.1
ieee754: 1.2.1
+ buildcheck@0.0.6:
+ optional: true
+
builtin-modules@3.3.0: {}
builtins@5.0.1:
@@ -9929,6 +11028,11 @@ snapshots:
dependencies:
run-applescript: 5.0.0
+ bundle-require@4.1.0(esbuild@0.19.12):
+ dependencies:
+ esbuild: 0.19.12
+ load-tsconfig: 0.2.5
+
cac@6.7.14: {}
cacheable-lookup@7.0.0: {}
@@ -9943,6 +11047,16 @@ snapshots:
normalize-url: 8.0.1
responselike: 3.0.0
+ cacheable-request@12.0.1:
+ dependencies:
+ '@types/http-cache-semantics': 4.0.4
+ get-stream: 9.0.1
+ http-cache-semantics: 4.1.1
+ keyv: 4.5.4
+ mimic-response: 4.0.0
+ normalize-url: 8.0.1
+ responselike: 3.0.0
+
cachedir@2.3.0: {}
call-bind@1.0.2:
@@ -10058,6 +11172,20 @@ snapshots:
dependencies:
get-func-name: 2.0.2
+ chokidar@3.6.0:
+ dependencies:
+ anymatch: 3.1.3
+ braces: 3.0.2
+ glob-parent: 5.1.2
+ is-binary-path: 2.1.0
+ is-glob: 4.0.3
+ normalize-path: 3.0.0
+ readdirp: 3.6.0
+ optionalDependencies:
+ fsevents: 2.3.3
+
+ chownr@1.1.4: {}
+
chrono-node@2.7.5:
dependencies:
dayjs: 1.11.10
@@ -10169,10 +11297,14 @@ snapshots:
comma-separated-tokens@2.0.3: {}
+ commander@10.0.1: {}
+
commander@11.1.0: {}
commander@2.20.3: {}
+ commander@4.1.1: {}
+
comment-parser@1.4.0: {}
commitizen@4.3.0(@types/node@18.18.14)(typescript@5.4.5):
@@ -10386,6 +11518,12 @@ snapshots:
optionalDependencies:
typescript: 5.4.5
+ cpu-features@0.0.10:
+ dependencies:
+ buildcheck: 0.0.6
+ nan: 2.19.0
+ optional: true
+
create-require@1.1.1: {}
cross-env@7.0.3:
@@ -10607,6 +11745,23 @@ snapshots:
dependencies:
path-type: 4.0.0
+ docker-modem@5.0.3:
+ dependencies:
+ debug: 4.3.4
+ readable-stream: 3.6.2
+ split-ca: 1.0.1
+ ssh2: 1.15.0
+ transitivePeerDependencies:
+ - supports-color
+
+ dockerode@4.0.2:
+ dependencies:
+ '@balena/dockerignore': 1.0.2
+ docker-modem: 5.0.3
+ tar-fs: 2.0.1
+ transitivePeerDependencies:
+ - supports-color
+
doctrine@2.1.0:
dependencies:
esutils: 2.0.3
@@ -10662,6 +11817,13 @@ snapshots:
eastasianwidth@0.2.0: {}
+ editorconfig@1.0.4:
+ dependencies:
+ '@one-ini/wasm': 0.1.1
+ commander: 10.0.1
+ minimatch: 9.0.1
+ semver: 7.6.2
+
ejs@3.1.10:
dependencies:
jake: 10.9.1
@@ -10794,6 +11956,32 @@ snapshots:
is-date-object: 1.0.5
is-symbol: 1.0.4
+ esbuild@0.19.12:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.19.12
+ '@esbuild/android-arm': 0.19.12
+ '@esbuild/android-arm64': 0.19.12
+ '@esbuild/android-x64': 0.19.12
+ '@esbuild/darwin-arm64': 0.19.12
+ '@esbuild/darwin-x64': 0.19.12
+ '@esbuild/freebsd-arm64': 0.19.12
+ '@esbuild/freebsd-x64': 0.19.12
+ '@esbuild/linux-arm': 0.19.12
+ '@esbuild/linux-arm64': 0.19.12
+ '@esbuild/linux-ia32': 0.19.12
+ '@esbuild/linux-loong64': 0.19.12
+ '@esbuild/linux-mips64el': 0.19.12
+ '@esbuild/linux-ppc64': 0.19.12
+ '@esbuild/linux-riscv64': 0.19.12
+ '@esbuild/linux-s390x': 0.19.12
+ '@esbuild/linux-x64': 0.19.12
+ '@esbuild/netbsd-x64': 0.19.12
+ '@esbuild/openbsd-x64': 0.19.12
+ '@esbuild/sunos-x64': 0.19.12
+ '@esbuild/win32-arm64': 0.19.12
+ '@esbuild/win32-ia32': 0.19.12
+ '@esbuild/win32-x64': 0.19.12
+
esbuild@0.20.2:
optionalDependencies:
'@esbuild/aix-ppc64': 0.20.2
@@ -10954,6 +12142,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ eslint-plugin-editorconfig@4.0.3:
+ dependencies:
+ editorconfig: 1.0.4
+ eslint: 8.57.0
+ klona: 2.0.6
+ transitivePeerDependencies:
+ - supports-color
+
eslint-plugin-es-x@7.6.0(eslint@8.57.0):
dependencies:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
@@ -11172,6 +12368,16 @@ snapshots:
eslint-plugin-vitest-globals@1.5.0: {}
+ eslint-plugin-vitest@0.4.1(eslint@8.57.0)(typescript@5.4.5)(vitest@1.6.0(@types/node@18.18.14)(@vitest/ui@1.6.0)):
+ dependencies:
+ '@typescript-eslint/utils': 7.9.0(eslint@8.57.0)(typescript@5.4.5)
+ eslint: 8.57.0
+ optionalDependencies:
+ vitest: 1.6.0(@types/node@18.18.14)(@vitest/ui@1.6.0)
+ transitivePeerDependencies:
+ - supports-color
+ - typescript
+
eslint-plugin-vitest@0.4.1(eslint@8.57.0)(typescript@5.4.5)(vitest@1.6.0(@types/node@20.12.12)(@vitest/ui@1.6.0)):
dependencies:
'@typescript-eslint/utils': 7.9.0(eslint@8.57.0)(typescript@5.4.5)
@@ -11558,6 +12764,8 @@ snapshots:
form-data-encoder@2.1.4: {}
+ form-data-encoder@4.0.2: {}
+
form-data@4.0.0:
dependencies:
asynckit: 0.4.0
@@ -11850,6 +13058,20 @@ snapshots:
p-cancelable: 3.0.0
responselike: 3.0.0
+ got@14.3.0:
+ dependencies:
+ '@sindresorhus/is': 6.3.1
+ '@szmarczak/http-timer': 5.0.1
+ cacheable-lookup: 7.0.0
+ cacheable-request: 12.0.1
+ decompress-response: 6.0.0
+ form-data-encoder: 4.0.2
+ get-stream: 8.0.1
+ http2-wrapper: 2.2.1
+ lowercase-keys: 3.0.0
+ p-cancelable: 4.0.1
+ responselike: 3.0.0
+
graceful-fs@4.2.10: {}
graceful-fs@4.2.11: {}
@@ -12019,6 +13241,11 @@ snapshots:
quick-lru: 5.1.1
resolve-alpn: 1.2.1
+ http2-wrapper@2.2.1:
+ dependencies:
+ quick-lru: 5.1.1
+ resolve-alpn: 1.2.1
+
https-proxy-agent@7.0.2:
dependencies:
agent-base: 7.1.0
@@ -12093,6 +13320,8 @@ snapshots:
ini@4.1.2: {}
+ ini@4.1.3: {}
+
inquirer@8.2.5:
dependencies:
ansi-escapes: 4.3.2
@@ -12186,6 +13415,10 @@ snapshots:
dependencies:
has-bigints: 1.0.2
+ is-binary-path@2.1.0:
+ dependencies:
+ binary-extensions: 2.3.0
+
is-boolean-object@1.1.2:
dependencies:
call-bind: 1.0.7
@@ -12285,6 +13518,8 @@ snapshots:
is-negative-zero@2.0.3: {}
+ is-network-error@1.1.0: {}
+
is-npm@6.0.0: {}
is-number-object@1.0.7:
@@ -12484,6 +13719,8 @@ snapshots:
jju@1.4.0: {}
+ joycon@3.1.1: {}
+
js-tokens@4.0.0: {}
js-tokens@9.0.0: {}
@@ -12534,6 +13771,8 @@ snapshots:
jsonc-parser@3.2.0: {}
+ jsonc-parser@3.2.1: {}
+
jsonfile@4.0.0:
optionalDependencies:
graceful-fs: 4.2.11
@@ -12552,12 +13791,18 @@ snapshots:
dependencies:
json-buffer: 3.0.1
+ keyv@4.5.4:
+ dependencies:
+ json-buffer: 3.0.1
+
kind-of@6.0.3: {}
kleur@3.0.3: {}
kleur@4.1.5: {}
+ klona@2.0.6: {}
+
latest-version@7.0.0:
dependencies:
package-json: 8.1.1
@@ -12635,6 +13880,8 @@ snapshots:
'@npmcli/config': 8.3.1
import-meta-resolve: 4.0.0
+ load-tsconfig@0.2.5: {}
+
local-pkg@0.5.0:
dependencies:
mlly: 1.4.2
@@ -13742,6 +14989,10 @@ snapshots:
dependencies:
brace-expansion: 2.0.1
+ minimatch@9.0.1:
+ dependencies:
+ brace-expansion: 2.0.1
+
minimatch@9.0.3:
dependencies:
brace-expansion: 2.0.1
@@ -13766,6 +15017,8 @@ snapshots:
misspellings@1.1.0: {}
+ mkdirp-classic@0.5.3: {}
+
mkdirp@0.5.6:
dependencies:
minimist: 1.2.8
@@ -13783,6 +15036,10 @@ snapshots:
moment@2.29.4: {}
+ move-file@3.1.0:
+ dependencies:
+ path-exists: 5.0.0
+
mri@1.2.0: {}
mrmime@2.0.0: {}
@@ -13801,6 +15058,9 @@ snapshots:
object-assign: 4.1.1
thenify-all: 1.6.0
+ nan@2.19.0:
+ optional: true
+
nanoid@3.3.7: {}
natural-compare-lite@1.4.0: {}
@@ -13919,6 +15179,15 @@ snapshots:
semver: 7.6.2
validate-npm-package-license: 3.0.4
+ normalize-package-data@6.0.1:
+ dependencies:
+ hosted-git-info: 7.0.1
+ is-core-module: 2.13.0
+ semver: 7.6.2
+ validate-npm-package-license: 3.0.4
+
+ normalize-path@3.0.0: {}
+
normalize-url@6.1.0: {}
normalize-url@8.0.1: {}
@@ -14111,6 +15380,8 @@ snapshots:
p-cancelable@3.0.0: {}
+ p-cancelable@4.0.1: {}
+
p-defer@1.0.0: {}
p-each-series@3.0.0: {}
@@ -14191,6 +15462,12 @@ snapshots:
p-reduce@3.0.0: {}
+ p-retry@6.2.0:
+ dependencies:
+ '@types/retry': 0.12.2
+ is-network-error: 1.1.0
+ retry: 0.13.1
+
p-timeout@3.2.0:
dependencies:
p-finally: 1.0.0
@@ -14376,6 +15653,8 @@ snapshots:
pathe@1.1.1: {}
+ pathe@1.1.2: {}
+
pathval@1.1.1: {}
pause-stream@0.0.11:
@@ -14400,6 +15679,8 @@ snapshots:
pinkie@2.0.4: {}
+ pirates@4.0.6: {}
+
pkg-conf@2.1.0:
dependencies:
find-up: 2.1.0
@@ -14428,10 +15709,18 @@ snapshots:
possible-typed-array-names@1.0.0: {}
+ postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@18.18.14)(typescript@5.4.5)):
+ dependencies:
+ lilconfig: 3.0.0
+ yaml: 2.3.4
+ optionalDependencies:
+ postcss: 8.4.38
+ ts-node: 10.9.2(@types/node@18.18.14)(typescript@5.4.5)
+
postcss@8.4.38:
dependencies:
nanoid: 3.3.7
- picocolors: 1.0.0
+ picocolors: 1.0.1
source-map-js: 1.2.0
prelude-ls@1.2.1: {}
@@ -14492,6 +15781,11 @@ snapshots:
end-of-stream: 1.4.4
once: 1.4.0
+ pump@3.0.0:
+ dependencies:
+ end-of-stream: 1.4.4
+ once: 1.4.0
+
punycode@2.3.0: {}
pupa@3.1.0:
@@ -14635,6 +15929,10 @@ snapshots:
string_decoder: 1.3.0
util-deprecate: 1.0.2
+ readdirp@3.6.0:
+ dependencies:
+ picomatch: 2.3.1
+
readline-transform@1.0.0: {}
rechoir@0.8.0:
@@ -14896,6 +16194,8 @@ snapshots:
unified: 10.1.2
unist-util-position: 4.0.4
+ retry@0.13.1: {}
+
reusify@1.0.4: {}
rfdc@1.3.0: {}
@@ -14986,6 +16286,19 @@ snapshots:
refa: 0.12.1
regexp-ast-analysis: 0.7.1
+ secretlint@8.1.2:
+ dependencies:
+ '@secretlint/config-creator': 8.2.4
+ '@secretlint/formatter': 8.2.4
+ '@secretlint/node': 8.2.4
+ '@secretlint/profiler': 8.2.4
+ debug: 4.3.4
+ globby: 14.0.1
+ meow: 12.1.1
+ read-pkg: 8.1.0
+ transitivePeerDependencies:
+ - supports-color
+
secretlint@8.2.3:
dependencies:
'@secretlint/config-creator': 8.2.4
@@ -15195,6 +16508,10 @@ snapshots:
source-map@0.6.1: {}
+ source-map@0.8.0-beta.0:
+ dependencies:
+ whatwg-url: 7.1.0
+
space-separated-tokens@2.0.2: {}
spawn-error-forwarder@1.0.0: {}
@@ -15218,6 +16535,8 @@ snapshots:
spdx-license-ids@3.0.15: {}
+ split-ca@1.0.1: {}
+
split-transform-stream@0.1.1:
dependencies:
bubble-stream-error: 0.0.1
@@ -15244,6 +16563,14 @@ snapshots:
sprintf-js@1.0.3: {}
+ ssh2@1.15.0:
+ dependencies:
+ asn1: 0.2.6
+ bcrypt-pbkdf: 1.0.2
+ optionalDependencies:
+ cpu-features: 0.0.10
+ nan: 2.19.0
+
stackback@0.0.2: {}
std-env@3.7.0: {}
@@ -15378,6 +16705,16 @@ snapshots:
dependencies:
boundary: 2.0.0
+ sucrase@3.35.0:
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.5
+ commander: 4.1.1
+ glob: 10.3.15
+ lines-and-columns: 1.2.4
+ mz: 2.7.0
+ pirates: 4.0.6
+ ts-interface-checker: 0.1.13
+
super-regex@1.0.0:
dependencies:
function-timeout: 1.0.1
@@ -15433,6 +16770,13 @@ snapshots:
tapable@2.2.1: {}
+ tar-fs@2.0.1:
+ dependencies:
+ chownr: 1.1.4
+ mkdirp-classic: 0.5.3
+ pump: 3.0.0
+ tar-stream: 2.2.0
+
tar-stream@2.2.0:
dependencies:
bl: 4.1.0
@@ -15714,12 +17058,18 @@ snapshots:
tr46@0.0.3: {}
+ tr46@1.0.1:
+ dependencies:
+ punycode: 2.3.0
+
traverse@0.6.9:
dependencies:
gopd: 1.0.1
typedarray.prototype.slice: 1.0.3
which-typed-array: 1.1.15
+ tree-kill@1.2.2: {}
+
trim-newlines@3.0.1: {}
trim-newlines@4.1.1: {}
@@ -15738,6 +17088,10 @@ snapshots:
dependencies:
typescript: 5.4.5
+ ts-deepmerge@7.0.0: {}
+
+ ts-interface-checker@0.1.13: {}
+
ts-node@10.9.2(@types/node@18.18.14)(typescript@4.9.5):
dependencies:
'@cspotcode/source-map-support': 0.8.1
@@ -15756,6 +17110,25 @@ snapshots:
v8-compile-cache-lib: 3.0.1
yn: 3.1.1
+ ts-node@10.9.2(@types/node@18.18.14)(typescript@5.4.5):
+ dependencies:
+ '@cspotcode/source-map-support': 0.8.1
+ '@tsconfig/node10': 1.0.11
+ '@tsconfig/node12': 1.0.11
+ '@tsconfig/node14': 1.0.3
+ '@tsconfig/node16': 1.0.4
+ '@types/node': 18.18.14
+ acorn: 8.11.3
+ acorn-walk: 8.3.2
+ arg: 4.1.3
+ create-require: 1.1.1
+ diff: 4.0.2
+ make-error: 1.3.6
+ typescript: 5.4.5
+ v8-compile-cache-lib: 3.0.1
+ yn: 3.1.1
+ optional: true
+
tsconfig-paths@4.2.0:
dependencies:
json5: 2.2.3
@@ -15766,6 +17139,29 @@ snapshots:
tslib@2.6.2: {}
+ tsup@8.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@18.18.14)(typescript@5.4.5))(typescript@5.4.5):
+ dependencies:
+ bundle-require: 4.1.0(esbuild@0.19.12)
+ cac: 6.7.14
+ chokidar: 3.6.0
+ debug: 4.3.4
+ esbuild: 0.19.12
+ execa: 5.1.1
+ globby: 11.1.0
+ joycon: 3.1.1
+ postcss-load-config: 4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@18.18.14)(typescript@5.4.5))
+ resolve-from: 5.0.0
+ rollup: 4.14.0
+ source-map: 0.8.0-beta.0
+ sucrase: 3.35.0
+ tree-kill: 1.2.2
+ optionalDependencies:
+ postcss: 8.4.38
+ typescript: 5.4.5
+ transitivePeerDependencies:
+ - supports-color
+ - ts-node
+
tsutils-etc@1.4.2(tsutils@3.21.0(typescript@5.4.5))(typescript@5.4.5):
dependencies:
'@types/yargs': 17.0.32
@@ -15778,6 +17174,8 @@ snapshots:
tslib: 1.14.1
typescript: 5.4.5
+ tweetnacl@0.14.5: {}
+
txt-ast-traverse@1.2.1: {}
type-check@0.4.0:
@@ -15804,6 +17202,8 @@ snapshots:
type-fest@3.13.1: {}
+ type-fest@4.18.2: {}
+
type-fest@4.8.3: {}
typed-array-buffer@1.0.2:
@@ -16136,7 +17536,7 @@ snapshots:
dependencies:
browserslist: 4.23.0
escalade: 3.1.1
- picocolors: 1.0.0
+ picocolors: 1.0.1
update-notifier@6.0.2:
dependencies:
@@ -16281,7 +17681,7 @@ snapshots:
cac: 6.7.14
debug: 4.3.4
pathe: 1.1.1
- picocolors: 1.0.0
+ picocolors: 1.0.1
vite: 5.2.8(@types/node@18.18.14)
transitivePeerDependencies:
- '@types/node'
@@ -16341,8 +17741,8 @@ snapshots:
execa: 8.0.1
local-pkg: 0.5.0
magic-string: 0.30.10
- pathe: 1.1.1
- picocolors: 1.0.0
+ pathe: 1.1.2
+ picocolors: 1.0.1
std-env: 3.7.0
strip-literal: 2.1.0
tinybench: 2.5.1
@@ -16408,11 +17808,19 @@ snapshots:
webidl-conversions@3.0.1: {}
+ webidl-conversions@4.0.2: {}
+
whatwg-url@5.0.0:
dependencies:
tr46: 0.0.3
webidl-conversions: 3.0.1
+ whatwg-url@7.1.0:
+ dependencies:
+ lodash.sortby: 4.7.0
+ tr46: 1.0.1
+ webidl-conversions: 4.0.2
+
which-boxed-primitive@1.0.2:
dependencies:
is-bigint: 1.0.4