Compare commits

...

4 Commits

Author SHA1 Message Date
dependabot[bot]
a455e7523f
chore(deps): bump super-linter/super-linter
Bumps the docker-dependencies group with 1 update in the / directory: [super-linter/super-linter](https://github.com/super-linter/super-linter).


Updates `super-linter/super-linter` from slim-v8.0.0 to slim-v8.2.0
- [Release notes](https://github.com/super-linter/super-linter/releases)
- [Changelog](https://github.com/super-linter/super-linter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/super-linter/super-linter/compare/v8...v8.2.0)

---
updated-dependencies:
- dependency-name: super-linter/super-linter
  dependency-version: slim-v8.2.0
  dependency-type: direct:production
  dependency-group: docker-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-04 15:35:35 +00:00
dependabot[bot]
248470ecc5 chore(deps): bump the github-actions-dependencies group across 1 directory with 10 updates
Bumps the github-actions-dependencies group with 10 updates in the / directory:

Updates `actions/checkout` from 6.0.0 to 6.0.1
Updates `docker/setup-docker-action` from 4.5.0 to 4.6.0
Updates `hoverkraft-tech/ci-github-nodejs` from 0.20.0 to 0.20.6
Updates `hoverkraft-tech/ci-github-common` from 0.30.1 to 0.31.3

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions-dependencies
- dependency-name: docker/setup-docker-action
  dependency-version: 4.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions-dependencies
- dependency-name: hoverkraft-tech/ci-github-nodejs
  dependency-version: 0.20.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions-dependencies
- dependency-name: hoverkraft-tech/ci-github-nodejs/.github/workflows/continuous-integration.yml
  dependency-version: 0.20.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions-dependencies
- dependency-name: hoverkraft-tech/ci-github-common/.github/workflows/linter.yml
  dependency-version: 0.31.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions-dependencies
- dependency-name: hoverkraft-tech/ci-github-common/.github/workflows/greetings.yml
  dependency-version: 0.31.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions-dependencies
- dependency-name: hoverkraft-tech/ci-github-common
  dependency-version: 0.31.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions-dependencies
- dependency-name: hoverkraft-tech/ci-github-common/.github/workflows/need-fix-to-issue.yml
  dependency-version: 0.31.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions-dependencies
- dependency-name: hoverkraft-tech/ci-github-common/.github/workflows/semantic-pull-request.yml
  dependency-version: 0.31.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions-dependencies
- dependency-name: hoverkraft-tech/ci-github-common/.github/workflows/stale.yml
  dependency-version: 0.31.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-04 16:11:42 +01:00
copilot-swe-agent[bot]
5d59cf29d8 fix: format docker-compose error objects as readable messages
Co-authored-by: neilime <314088+neilime@users.noreply.github.com>
Signed-off-by: Emilien Escalle <emilien.escalle@escemi.com>
2025-12-04 15:55:12 +01:00
Emilien Escalle
e9bb59d794 chore: add agents instructions
Signed-off-by: Emilien Escalle <emilien.escalle@escemi.com>
2025-12-04 14:41:44 +01:00
18 changed files with 464 additions and 129 deletions

View File

@ -173,13 +173,13 @@ jobs:
env:
DOCKER_COMPOSE_VERSION: ${{ matrix.expected-compose-version || '' }}
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Set up Docker context
if: ${{ matrix.docker-context }}
uses: docker/setup-docker-action@efe9e3891a4f7307e689f2100b33a155b900a608 # v4.5.0
uses: docker/setup-docker-action@e61617a16c407a86262fb923c35a616ddbe070b3 # v4.6.0
with:
context: ${{ matrix.docker-context }}

View File

@ -12,12 +12,12 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- id: setup-node
uses: hoverkraft-tech/ci-github-nodejs/actions/setup-node@a9809af04394e66675b8644865be1ddcec02cdcd # 0.20.0
uses: hoverkraft-tech/ci-github-nodejs/actions/setup-node@338755b95043af1f8aa17409529fd20a9d2ef659 # 0.20.6
- name: Build dist/ Directory
id: package

View File

@ -7,7 +7,7 @@ permissions: {}
jobs:
test-nodejs:
uses: hoverkraft-tech/ci-github-nodejs/.github/workflows/continuous-integration.yml@a9809af04394e66675b8644865be1ddcec02cdcd # 0.20.0
uses: hoverkraft-tech/ci-github-nodejs/.github/workflows/continuous-integration.yml@338755b95043af1f8aa17409529fd20a9d2ef659 # 0.20.6
permissions:
contents: read
id-token: write

View File

@ -7,7 +7,7 @@ permissions: {}
jobs:
linter:
uses: hoverkraft-tech/ci-github-common/.github/workflows/linter.yml@c314229c3ca6914f7023ffca7afc26753ab99b41 # 0.30.1
uses: hoverkraft-tech/ci-github-common/.github/workflows/linter.yml@5ac504609f6ef35c5ac94bd8199063aa32104721 # 0.31.3
permissions:
actions: read
contents: read

View File

@ -10,7 +10,7 @@ permissions: {}
jobs:
greetings:
uses: hoverkraft-tech/ci-github-common/.github/workflows/greetings.yml@c314229c3ca6914f7023ffca7afc26753ab99b41 # 0.30.1
uses: hoverkraft-tech/ci-github-common/.github/workflows/greetings.yml@5ac504609f6ef35c5ac94bd8199063aa32104721 # 0.31.3
permissions:
contents: read
issues: write

View File

@ -38,7 +38,7 @@ jobs:
outputs:
artifact-id: ${{ steps.upload-artifact.outputs.artifact-id }}
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
@ -62,7 +62,7 @@ jobs:
app-id: ${{ vars.CI_BOT_APP_ID }}
private-key: ${{ secrets.CI_BOT_APP_PRIVATE_KEY }}
- uses: hoverkraft-tech/ci-github-common/actions/create-and-merge-pull-request@c314229c3ca6914f7023ffca7afc26753ab99b41 # 0.30.1
- uses: hoverkraft-tech/ci-github-common/actions/create-and-merge-pull-request@5ac504609f6ef35c5ac94bd8199063aa32104721 # 0.31.3
with:
github-token: ${{ steps.generate-token.outputs.token }}
branch: docs/actions-workflows-documentation-update

View File

@ -19,7 +19,7 @@ permissions: {}
jobs:
main:
uses: hoverkraft-tech/ci-github-common/.github/workflows/need-fix-to-issue.yml@c314229c3ca6914f7023ffca7afc26753ab99b41 # 0.30.1
uses: hoverkraft-tech/ci-github-common/.github/workflows/need-fix-to-issue.yml@5ac504609f6ef35c5ac94bd8199063aa32104721 # 0.31.3
permissions:
contents: read
issues: write

View File

@ -11,7 +11,7 @@ permissions: {}
jobs:
main:
uses: hoverkraft-tech/ci-github-common/.github/workflows/semantic-pull-request.yml@c314229c3ca6914f7023ffca7afc26753ab99b41 # 0.30.1
uses: hoverkraft-tech/ci-github-common/.github/workflows/semantic-pull-request.yml@5ac504609f6ef35c5ac94bd8199063aa32104721 # 0.31.3
permissions:
contents: write
pull-requests: write

View File

@ -8,7 +8,7 @@ permissions: {}
jobs:
main:
uses: hoverkraft-tech/ci-github-common/.github/workflows/stale.yml@c314229c3ca6914f7023ffca7afc26753ab99b41 # 0.30.1
uses: hoverkraft-tech/ci-github-common/.github/workflows/stale.yml@5ac504609f6ef35c5ac94bd8199063aa32104721 # 0.31.3
permissions:
issues: write
pull-requests: write

80
AGENTS.md Normal file
View File

@ -0,0 +1,80 @@
# AGENTS.md — agent instructions and operational contract
This file exists so automated contributors (Copilot agents, bots, scripts) follow the same guardrails as human maintainers when working in `hoverkraft-tech/compose-action`. It summarizes what to read, which commands to run, and what is out of scope for agents.
## Organization-wide guidelines
- Always read and obey [hoverkraft-tech/.github/AGENTS.md](https://github.com/hoverkraft-tech/.github/blob/main/AGENTS.md) before touching this repository.
- Apply any additional instructions surfaced by the workspace (global Visual Studio Code prompts, repo-specific notices) alongside this contract.
## Canonical docs
- [README.md](./README.md) — product overview, supported inputs, and workflow examples. This is the primary contract for action users.
- [CONTRIBUTING.md](./CONTRIBUTING.md) — PR expectations, release hygiene, and how to collaborate with maintainers.
- [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md) — behavioral expectations for every interaction.
## Instructional docs
- Source of truth for runtime logic lives under [`src/`](./src). Tests mirror the same structure under [`src/**/*.test.ts`](./src).
- GitHub Action fixtures and sample compose files live under [`test/`](./test). Use them when reproducing CI flows locally.
- Build artifacts belong in `dist/`. Never edit generated files by hand; instead update the matching TypeScript source and rerun the packaging commands described below.
## High-level rules (mandatory)
- Favor small, reviewable diffs. Coordinate large refactors with maintainers before starting.
- Keep behavior changes documented: update `README.md` and any affected workflow snippets.
- Never hardcode secrets, tokens, or personal data. Use GitHub Actions secrets or ask maintainers to provision them.
- Node 20+ is required. Match the tooling versions declared in `package.json`.
## Agent operational contract (when modifying code)
Before opening a PR or pushing a branch:
1. Read the relevant sections of `README.md` and inspect any affected files in `src/` and `test/`.
2. Implement changes in TypeScript source only; regenerate bundles with `npm run package` when shipping executable artifacts.
3. Run local validation limited to impacted areas at minimum:
- `npm run lint` (or `npm run lint:ci` when you need JSON output for CI).
- `npm run build` (type-check only).
- `npm run test` for quick feedback; `npm run test:ci` to reproduce CI (coverage + serial runs).
4. For action behavior changes, exercise the representative workflow under `test/` (e.g., `test/docker-compose.yml`) to confirm compose invocations behave as expected.
5. Add or update unit tests alongside any new logic, covering at least the happy path plus one failure or edge scenario.
6. Keep commits self-contained and use conventional commit messages compatible with `@commitlint/config-conventional`.
When opening a PR:
- Target a feature branch off `main`.
- Describe intent, touched areas, and the manual + automated test plan.
- Reference the docs you followed (for example: "Validated against readme > Usage" or "Followed CONTRIBUTING.md".).
- Ensure CI (lint, build, tests, package) is green before requesting human review.
## Validation & quality gates
- **Build:** `npm run build` must succeed (TypeScript compile cleanly, no `tsc` errors).
- **Lint:** `npm run lint:ci` must pass with no new warnings. Attach `eslint-report.json` to CI artifacts when relevant.
- **Tests:** `npm run test:ci` must pass and update coverage artifacts (see `coverage/`).
- **Bundle:** `npm run package` must regenerate `dist/` outputs; include updated bundles in the PR if runtime code changed.
## Allowed agent actions (examples)
- Fix documentation, typos, or metadata referenced by the GitHub Marketplace listing.
- Add or update unit tests, mocks, and fixtures in `src/` or `test/`.
- Refactor TypeScript modules in small, behavior-preserving increments (with tests and package outputs refreshed).
- Adjust CI/workflow helpers under `test/` to improve local reproducibility.
## Disallowed actions (must not do)
- Do not commit generated `dist/` artifacts without updating the corresponding TypeScript source and documenting the command used.
- Do not introduce new runtime dependencies without maintainer approval; prefer built-in Node APIs or existing deps.
- Do not modify Dockerfiles or GitHub Actions workflows to add secrets, credentials, or privileged steps.
- Do not land breaking changes to the public action inputs/outputs without updating `README.md` and gaining explicit maintainer sign-off.
## Guidance summary (quick checklist)
1. Read `README.md` + relevant source/test files.
2. Make the minimal change; add tests.
3. Run `npm run lint`, `npm run build`, `npm run test:ci`, and `npm run package`.
4. Open a PR referencing the docs you followed and include the test plan.
## If uncertain
Open an issue or draft PR in this repository describing the scenario, what docs you read, and the question you still have. Ping maintainers instead of guessing. When in doubt about the workflow contract, defer to the `README.md` and organization-wide AGENTS file.

View File

@ -1,4 +1,4 @@
FROM ghcr.io/super-linter/super-linter:slim-v8.0.0
FROM ghcr.io/super-linter/super-linter:slim-v8.3.0
HEALTHCHECK --interval=5m --timeout=10s --start-period=30s --retries=3 CMD ["/bin/sh","-c","test -d /github/home"]
ARG UID=1000

57
dist/index.js generated vendored
View File

@ -33176,19 +33176,29 @@ class DockerComposeService {
...this.getCommonOptions(optionsInputs),
commandOptions: upFlags,
};
try {
if (services.length > 0) {
await (0, docker_compose_1.upMany)(services, options);
return;
}
await (0, docker_compose_1.upAll)(options);
}
catch (error) {
throw this.formatDockerComposeError(error);
}
}
async down({ downFlags, ...optionsInputs }) {
const options = {
...this.getCommonOptions(optionsInputs),
commandOptions: downFlags,
};
try {
await (0, docker_compose_1.down)(options);
}
catch (error) {
throw this.formatDockerComposeError(error);
}
}
async logs({ services, ...optionsInputs }) {
const options = {
...this.getCommonOptions(optionsInputs),
@ -33212,6 +33222,53 @@ class DockerComposeService {
},
};
}
/**
* Formats docker-compose errors into proper Error objects with readable messages
*/
formatDockerComposeError(error) {
// If it's already an Error, return it
if (error instanceof Error) {
return error;
}
// Handle docker-compose result objects
if (this.isDockerComposeResult(error)) {
const parts = [];
// Add exit code information
if (error.exitCode !== null) {
parts.push(`Docker Compose command failed with exit code ${error.exitCode}`);
}
else {
parts.push("Docker Compose command failed");
}
// Add error stream output if available
if (error.err && error.err.trim()) {
parts.push("\nError output:");
parts.push(error.err.trim());
}
// Add standard output if available and different from error output
if (error.out && error.out.trim() && error.out !== error.err) {
parts.push("\nStandard output:");
parts.push(error.out.trim());
}
return new Error(parts.join("\n"));
}
// Handle string errors
if (typeof error === "string") {
return new Error(error);
}
// Fallback for unknown error types
return new Error(JSON.stringify(error));
}
/**
* Type guard to check if an object is a docker-compose result
*/
isDockerComposeResult(error) {
return (typeof error === "object" &&
error !== null &&
"exitCode" in error &&
"err" in error &&
"out" in error);
}
}
exports.DockerComposeService = DockerComposeService;

57
dist/post.js generated vendored
View File

@ -26253,19 +26253,29 @@ class DockerComposeService {
...this.getCommonOptions(optionsInputs),
commandOptions: upFlags,
};
try {
if (services.length > 0) {
await (0, docker_compose_1.upMany)(services, options);
return;
}
await (0, docker_compose_1.upAll)(options);
}
catch (error) {
throw this.formatDockerComposeError(error);
}
}
async down({ downFlags, ...optionsInputs }) {
const options = {
...this.getCommonOptions(optionsInputs),
commandOptions: downFlags,
};
try {
await (0, docker_compose_1.down)(options);
}
catch (error) {
throw this.formatDockerComposeError(error);
}
}
async logs({ services, ...optionsInputs }) {
const options = {
...this.getCommonOptions(optionsInputs),
@ -26289,6 +26299,53 @@ class DockerComposeService {
},
};
}
/**
* Formats docker-compose errors into proper Error objects with readable messages
*/
formatDockerComposeError(error) {
// If it's already an Error, return it
if (error instanceof Error) {
return error;
}
// Handle docker-compose result objects
if (this.isDockerComposeResult(error)) {
const parts = [];
// Add exit code information
if (error.exitCode !== null) {
parts.push(`Docker Compose command failed with exit code ${error.exitCode}`);
}
else {
parts.push("Docker Compose command failed");
}
// Add error stream output if available
if (error.err && error.err.trim()) {
parts.push("\nError output:");
parts.push(error.err.trim());
}
// Add standard output if available and different from error output
if (error.out && error.out.trim() && error.out !== error.err) {
parts.push("\nStandard output:");
parts.push(error.out.trim());
}
return new Error(parts.join("\n"));
}
// Handle string errors
if (typeof error === "string") {
return new Error(error);
}
// Fallback for unknown error types
return new Error(JSON.stringify(error));
}
/**
* Type guard to check if an object is a docker-compose result
*/
isDockerComposeResult(error) {
return (typeof error === "object" &&
error !== null &&
"exitCode" in error &&
"err" in error &&
"out" in error);
}
}
exports.DockerComposeService = DockerComposeService;

3
eslint.config.mjs Normal file
View File

@ -0,0 +1,3 @@
import { default as tsDevToolsCore } from "@ts-dev-tools/core/dist/eslint-plugin-ts-dev-tools/index.js";
export default tsDevToolsCore.default;

84
package-lock.json generated
View File

@ -147,6 +147,7 @@
"integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.27.1",
@ -1516,7 +1517,6 @@
"resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz",
"integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==",
"dev": true,
"peer": true,
"dependencies": {
"@jest/types": "^29.6.3",
"@types/node": "*",
@ -1534,7 +1534,6 @@
"resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz",
"integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==",
"dev": true,
"peer": true,
"dependencies": {
"@jest/console": "^29.7.0",
"@jest/reporters": "^29.7.0",
@ -1592,7 +1591,6 @@
"resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz",
"integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==",
"dev": true,
"peer": true,
"dependencies": {
"@jest/fake-timers": "^29.7.0",
"@jest/types": "^29.6.3",
@ -1608,7 +1606,6 @@
"resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz",
"integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==",
"dev": true,
"peer": true,
"dependencies": {
"expect": "^29.7.0",
"jest-snapshot": "^29.7.0"
@ -1622,7 +1619,6 @@
"resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz",
"integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==",
"dev": true,
"peer": true,
"dependencies": {
"jest-get-type": "^29.6.3"
},
@ -1635,7 +1631,6 @@
"resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz",
"integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==",
"dev": true,
"peer": true,
"dependencies": {
"@jest/types": "^29.6.3",
"@sinonjs/fake-timers": "^10.0.2",
@ -1663,7 +1658,6 @@
"resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz",
"integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==",
"dev": true,
"peer": true,
"dependencies": {
"@jest/environment": "^29.7.0",
"@jest/expect": "^29.7.0",
@ -1703,7 +1697,6 @@
"resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz",
"integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==",
"dev": true,
"peer": true,
"dependencies": {
"@bcoe/v8-coverage": "^0.2.3",
"@jest/console": "^29.7.0",
@ -1814,7 +1807,6 @@
"resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz",
"integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==",
"dev": true,
"peer": true,
"dependencies": {
"@jridgewell/trace-mapping": "^0.3.18",
"callsites": "^3.0.0",
@ -1829,7 +1821,6 @@
"resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz",
"integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==",
"dev": true,
"peer": true,
"dependencies": {
"@jest/console": "^29.7.0",
"@jest/types": "^29.6.3",
@ -1845,7 +1836,6 @@
"resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz",
"integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==",
"dev": true,
"peer": true,
"dependencies": {
"@jest/test-result": "^29.7.0",
"graceful-fs": "^4.2.9",
@ -1861,7 +1851,6 @@
"resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz",
"integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==",
"dev": true,
"peer": true,
"dependencies": {
"@babel/core": "^7.11.6",
"@jest/types": "^29.6.3",
@ -2016,6 +2005,7 @@
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.6.tgz",
"integrity": "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==",
"license": "MIT",
"peer": true,
"dependencies": {
"@octokit/auth-token": "^6.0.0",
"@octokit/graphql": "^9.0.3",
@ -2199,6 +2189,7 @@
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.1.0.tgz",
"integrity": "sha512-BDa2VAMLSh3otEiaMJ/3Y36GU4qf6GI+VivQ/P41NC6GHcdxpKlqV0ikSZ5gdQsmS3ojXeRx5vasgNTinF0Q4g==",
"peer": true,
"dependencies": {
"@octokit/auth-token": "^4.0.0",
"@octokit/graphql": "^7.0.0",
@ -2685,7 +2676,6 @@
"resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
"integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
"dev": true,
"peer": true,
"dependencies": {
"@sinonjs/commons": "^3.0.0"
}
@ -3168,9 +3158,9 @@
}
},
"node_modules/@ts-dev-tools/core/node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"version": "10.5.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
"integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
"dev": true,
"license": "ISC",
"dependencies": {
@ -3914,7 +3904,6 @@
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
"integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==",
"dev": true,
"peer": true,
"dependencies": {
"@types/node": "*"
}
@ -4186,6 +4175,7 @@
"integrity": "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"undici-types": "~7.10.0"
}
@ -4217,6 +4207,7 @@
"integrity": "sha512-w/EboPlBwnmOBtRbiOvzjD+wdiZdgFeo17lkltrtn7X37vagKKWJABvyfsJXTlHe6XBzugmYgd4A4nW+k8Mixw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.40.0",
@ -4257,6 +4248,7 @@
"integrity": "sha512-jCNyAuXx8dr5KJMkecGmZ8KI61KBUhkCob+SD+C+I5+Y1FWI2Y3QmY4/cxMCC5WAsZqoEtEETVhUiUMIGCf6Bw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.40.0",
"@typescript-eslint/types": "8.40.0",
@ -4764,6 +4756,7 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@ -5065,7 +5058,6 @@
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
"integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==",
"dev": true,
"peer": true,
"dependencies": {
"@jest/transform": "^29.7.0",
"@types/babel__core": "^7.1.14",
@ -5087,7 +5079,6 @@
"resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
"integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
"dev": true,
"peer": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.0.0",
"@istanbuljs/load-nyc-config": "^1.0.0",
@ -5104,7 +5095,6 @@
"resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
"integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
"dev": true,
"peer": true,
"dependencies": {
"@babel/core": "^7.12.3",
"@babel/parser": "^7.14.7",
@ -5121,7 +5111,6 @@
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"peer": true,
"bin": {
"semver": "bin/semver.js"
}
@ -5131,7 +5120,6 @@
"resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz",
"integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==",
"dev": true,
"peer": true,
"dependencies": {
"@babel/template": "^7.3.3",
"@babel/types": "^7.3.3",
@ -5173,7 +5161,6 @@
"resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
"integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
"dev": true,
"peer": true,
"dependencies": {
"babel-plugin-jest-hoist": "^29.6.3",
"babel-preset-current-node-syntax": "^1.0.0"
@ -5238,6 +5225,7 @@
"url": "https://github.com/sponsors/ai"
}
],
"peer": true,
"dependencies": {
"caniuse-lite": "^1.0.30001669",
"electron-to-chromium": "^1.5.41",
@ -5455,8 +5443,7 @@
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz",
"integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==",
"dev": true,
"peer": true
"dev": true
},
"node_modules/cli-cursor": {
"version": "5.0.0",
@ -5677,6 +5664,7 @@
"integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"env-paths": "^2.2.1",
"import-fresh": "^3.3.0",
@ -5721,7 +5709,6 @@
"resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz",
"integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==",
"dev": true,
"peer": true,
"dependencies": {
"@jest/types": "^29.6.3",
"chalk": "^4.0.0",
@ -5928,7 +5915,6 @@
"resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
"integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
"dev": true,
"peer": true,
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
@ -6224,6 +6210,7 @@
"integrity": "sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1",
@ -6901,7 +6888,6 @@
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
"integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
"dev": true,
"peer": true,
"engines": {
"node": ">= 0.8.0"
}
@ -6921,7 +6907,6 @@
"resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz",
"integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==",
"dev": true,
"peer": true,
"dependencies": {
"@jest/expect-utils": "^29.7.0",
"jest-get-type": "^29.6.3",
@ -8359,7 +8344,6 @@
"resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
"integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
"dev": true,
"peer": true,
"dependencies": {
"debug": "^4.1.1",
"istanbul-lib-coverage": "^3.0.0",
@ -8448,7 +8432,6 @@
"resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz",
"integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==",
"dev": true,
"peer": true,
"dependencies": {
"execa": "^5.0.0",
"jest-util": "^29.7.0",
@ -8463,7 +8446,6 @@
"resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz",
"integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==",
"dev": true,
"peer": true,
"dependencies": {
"@jest/environment": "^29.7.0",
"@jest/expect": "^29.7.0",
@ -8495,7 +8477,6 @@
"resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz",
"integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==",
"dev": true,
"peer": true,
"dependencies": {
"@jest/core": "^29.7.0",
"@jest/test-result": "^29.7.0",
@ -8529,7 +8510,6 @@
"resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz",
"integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==",
"dev": true,
"peer": true,
"dependencies": {
"@babel/core": "^7.11.6",
"@jest/test-sequencer": "^29.7.0",
@ -8575,7 +8555,6 @@
"resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz",
"integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==",
"dev": true,
"peer": true,
"dependencies": {
"chalk": "^4.0.0",
"diff-sequences": "^29.6.3",
@ -8591,7 +8570,6 @@
"resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz",
"integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==",
"dev": true,
"peer": true,
"dependencies": {
"detect-newline": "^3.0.0"
},
@ -8604,7 +8582,6 @@
"resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz",
"integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==",
"dev": true,
"peer": true,
"dependencies": {
"@jest/types": "^29.6.3",
"chalk": "^4.0.0",
@ -8621,7 +8598,6 @@
"resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
"integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==",
"dev": true,
"peer": true,
"dependencies": {
"@jest/environment": "^29.7.0",
"@jest/fake-timers": "^29.7.0",
@ -8639,7 +8615,6 @@
"resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
"integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
"dev": true,
"peer": true,
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
@ -8649,7 +8624,6 @@
"resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz",
"integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==",
"dev": true,
"peer": true,
"dependencies": {
"@jest/types": "^29.6.3",
"@types/graceful-fs": "^4.1.3",
@ -8675,7 +8649,6 @@
"resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz",
"integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==",
"dev": true,
"peer": true,
"dependencies": {
"jest-get-type": "^29.6.3",
"pretty-format": "^29.7.0"
@ -8689,7 +8662,6 @@
"resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz",
"integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==",
"dev": true,
"peer": true,
"dependencies": {
"chalk": "^4.0.0",
"jest-diff": "^29.7.0",
@ -8705,7 +8677,6 @@
"resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
"integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
"dev": true,
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.12.13",
"@jest/types": "^29.6.3",
@ -8726,7 +8697,6 @@
"resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
"integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
"dev": true,
"peer": true,
"dependencies": {
"@jest/types": "^29.6.3",
"@types/node": "*",
@ -8758,7 +8728,6 @@
"resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
"integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
"dev": true,
"peer": true,
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
@ -8768,7 +8737,6 @@
"resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz",
"integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==",
"dev": true,
"peer": true,
"dependencies": {
"chalk": "^4.0.0",
"graceful-fs": "^4.2.9",
@ -8789,7 +8757,6 @@
"resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz",
"integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==",
"dev": true,
"peer": true,
"dependencies": {
"jest-regex-util": "^29.6.3",
"jest-snapshot": "^29.7.0"
@ -8803,7 +8770,6 @@
"resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz",
"integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==",
"dev": true,
"peer": true,
"dependencies": {
"@jest/console": "^29.7.0",
"@jest/environment": "^29.7.0",
@ -8836,7 +8802,6 @@
"resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz",
"integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==",
"dev": true,
"peer": true,
"dependencies": {
"@jest/environment": "^29.7.0",
"@jest/fake-timers": "^29.7.0",
@ -8870,7 +8835,6 @@
"resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz",
"integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==",
"dev": true,
"peer": true,
"dependencies": {
"@babel/core": "^7.11.6",
"@babel/generator": "^7.7.2",
@ -8919,7 +8883,6 @@
"resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz",
"integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==",
"dev": true,
"peer": true,
"dependencies": {
"@jest/types": "^29.6.3",
"camelcase": "^6.2.0",
@ -8937,7 +8900,6 @@
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
"integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
"dev": true,
"peer": true,
"engines": {
"node": ">=10"
},
@ -8950,7 +8912,6 @@
"resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz",
"integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==",
"dev": true,
"peer": true,
"dependencies": {
"@jest/test-result": "^29.7.0",
"@jest/types": "^29.6.3",
@ -8970,7 +8931,6 @@
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
"integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
"dev": true,
"peer": true,
"dependencies": {
"@types/node": "*",
"jest-util": "^29.7.0",
@ -8986,7 +8946,6 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
"dev": true,
"peer": true,
"dependencies": {
"has-flag": "^4.0.0"
},
@ -9086,6 +9045,7 @@
"resolved": "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-2.4.0.tgz",
"integrity": "sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==",
"dev": true,
"peer": true,
"dependencies": {
"acorn": "^8.5.0",
"eslint-visitor-keys": "^3.0.0",
@ -9157,7 +9117,6 @@
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
"integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
"dev": true,
"peer": true,
"engines": {
"node": ">=6"
}
@ -10163,6 +10122,7 @@
"integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"prettier": "bin/prettier.cjs"
},
@ -10205,7 +10165,6 @@
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
"integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
"dev": true,
"peer": true,
"dependencies": {
"@jest/schemas": "^29.6.3",
"ansi-styles": "^5.0.0",
@ -10220,7 +10179,6 @@
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
"dev": true,
"peer": true,
"engines": {
"node": ">=10"
},
@ -10269,7 +10227,6 @@
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
"integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
"dev": true,
"peer": true,
"dependencies": {
"kleur": "^3.0.3",
"sisteransi": "^1.0.5"
@ -10301,8 +10258,7 @@
"type": "opencollective",
"url": "https://opencollective.com/fast-check"
}
],
"peer": true
]
},
"node_modules/queue-microtask": {
"version": "1.2.3",
@ -10445,7 +10401,6 @@
"resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz",
"integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==",
"dev": true,
"peer": true,
"engines": {
"node": ">=10"
}
@ -10760,8 +10715,7 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
"integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
"dev": true,
"peer": true
"dev": true
},
"node_modules/slash": {
"version": "3.0.0",
@ -11434,6 +11388,7 @@
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@ -11844,7 +11799,6 @@
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
"integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
"dev": true,
"peer": true,
"dependencies": {
"imurmurhash": "^0.1.4",
"signal-exit": "^3.0.7"

View File

@ -85,43 +85,13 @@
"**/src/**/*.[jt]s?(x)"
]
},
"eslintConfig": {
"root": true,
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint",
"jest"
],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:jest/recommended",
"prettier"
],
"env": {
"es2021": true
},
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 12,
"sourceType": "module"
},
"settings": {
"jest": {
"version": "detect"
}
},
"ignorePatterns": [
"dist",
"node_modules"
]
},
"prettier": {
"semi": true,
"printWidth": 100,
"trailingComma": "es5"
"trailingComma": "es5",
"plugins": [
"@prettier/plugin-oxc"
]
},
"commitlint": {
"extends": [
@ -140,6 +110,6 @@
}
},
"tsDevTools": {
"version": "20220617100200-prettier-cache"
"version": "20250623095500-add-prettier-oxc"
}
}

View File

@ -112,6 +112,130 @@ describe("DockerComposeService", () => {
},
});
});
it("should throw formatted error when upAll fails with docker-compose result", async () => {
const upInputs: UpInputs = {
dockerFlags: [],
composeFiles: ["docker-compose.yml"],
services: [],
composeFlags: [],
upFlags: [],
cwd: "/current/working/dir",
serviceLogger: jest.fn(),
};
const dockerComposeError = {
exitCode: 1,
err: "Error: unable to pull image\nfailed to resolve reference",
out: "",
};
upAllMock.mockRejectedValue(dockerComposeError);
await expect(service.up(upInputs)).rejects.toThrow(
"Docker Compose command failed with exit code 1"
);
await expect(service.up(upInputs)).rejects.toThrow("unable to pull image");
});
it("should throw formatted error when upMany fails with docker-compose result", async () => {
const upInputs: UpInputs = {
dockerFlags: [],
composeFiles: ["docker-compose.yml"],
services: ["web"],
composeFlags: [],
upFlags: [],
cwd: "/current/working/dir",
serviceLogger: jest.fn(),
};
const dockerComposeError = {
exitCode: 1,
err: "Service 'web' failed to start",
out: "Starting web...",
};
upManyMock.mockRejectedValue(dockerComposeError);
await expect(service.up(upInputs)).rejects.toThrow(
"Docker Compose command failed with exit code 1"
);
await expect(service.up(upInputs)).rejects.toThrow("Service 'web' failed to start");
await expect(service.up(upInputs)).rejects.toThrow("Starting web...");
});
it("should pass through docker-compose result without exit code", async () => {
const upInputs: UpInputs = {
dockerFlags: [],
composeFiles: ["docker-compose.yml"],
services: [],
composeFlags: [],
upFlags: [],
cwd: "/current/working/dir",
serviceLogger: jest.fn(),
};
const dockerComposeError = {
exitCode: null,
err: "Some error without exit code",
out: "",
};
upAllMock.mockRejectedValue(dockerComposeError);
await expect(service.up(upInputs)).rejects.toThrow("Some error without exit code");
});
it("should pass through standard Error objects", async () => {
const upInputs: UpInputs = {
dockerFlags: [],
composeFiles: ["docker-compose.yml"],
services: [],
composeFlags: [],
upFlags: [],
cwd: "/current/working/dir",
serviceLogger: jest.fn(),
};
const standardError = new Error("Standard error message");
upAllMock.mockRejectedValue(standardError);
await expect(service.up(upInputs)).rejects.toThrow("Standard error message");
});
it("should pass through error strings", async () => {
const upInputs: UpInputs = {
dockerFlags: [],
composeFiles: ["docker-compose.yml"],
services: [],
composeFlags: [],
upFlags: [],
cwd: "/current/working/dir",
serviceLogger: jest.fn(),
};
const unknownError = "Some unknown error";
upAllMock.mockRejectedValue(unknownError);
await expect(service.up(upInputs)).rejects.toThrow("Some unknown error");
});
it("should handle unknown error types gracefully", async () => {
const upInputs: UpInputs = {
dockerFlags: [],
composeFiles: ["docker-compose.yml"],
services: [],
composeFlags: [],
upFlags: [],
cwd: "/current/working/dir",
serviceLogger: jest.fn(),
};
const unknownError = { unexpected: "error format" };
upAllMock.mockRejectedValue(unknownError);
await expect(service.up(upInputs)).rejects.toThrow(JSON.stringify(unknownError));
});
});
describe("down", () => {
@ -139,6 +263,30 @@ describe("DockerComposeService", () => {
callback: expect.any(Function),
});
});
it("should throw formatted error when down fails with docker-compose result", async () => {
const downInputs: DownInputs = {
dockerFlags: [],
composeFiles: [],
composeFlags: [],
downFlags: [],
cwd: "/current/working/dir",
serviceLogger: jest.fn(),
};
const dockerComposeError = {
exitCode: 1,
err: "Error stopping containers",
out: "",
};
downMock.mockRejectedValue(dockerComposeError);
await expect(service.down(downInputs)).rejects.toThrow(
"Docker Compose command failed with exit code 1"
);
await expect(service.down(downInputs)).rejects.toThrow("Error stopping containers");
});
});
describe("logs", () => {

View File

@ -2,6 +2,7 @@ import {
down,
IDockerComposeLogOptions,
IDockerComposeOptions,
IDockerComposeResult,
logs,
upAll,
upMany,
@ -27,12 +28,16 @@ export class DockerComposeService {
commandOptions: upFlags,
};
try {
if (services.length > 0) {
await upMany(services, options);
return;
}
await upAll(options);
} catch (error) {
throw this.formatDockerComposeError(error);
}
}
async down({ downFlags, ...optionsInputs }: DownInputs): Promise<void> {
@ -41,7 +46,11 @@ export class DockerComposeService {
commandOptions: downFlags,
};
try {
await down(options);
} catch (error) {
throw this.formatDockerComposeError(error);
}
}
async logs({ services, ...optionsInputs }: LogsInputs): Promise<{
@ -79,4 +88,61 @@ export class DockerComposeService {
},
};
}
/**
* Formats docker-compose errors into proper Error objects with readable messages
*/
private formatDockerComposeError(error: unknown): Error {
// If it's already an Error, return it
if (error instanceof Error) {
return error;
}
// Handle docker-compose result objects
if (this.isDockerComposeResult(error)) {
const parts: string[] = [];
// Add exit code information
if (error.exitCode !== null) {
parts.push(`Docker Compose command failed with exit code ${error.exitCode}`);
} else {
parts.push("Docker Compose command failed");
}
// Add error stream output if available
if (error.err && error.err.trim()) {
parts.push("\nError output:");
parts.push(error.err.trim());
}
// Add standard output if available and different from error output
if (error.out && error.out.trim() && error.out !== error.err) {
parts.push("\nStandard output:");
parts.push(error.out.trim());
}
return new Error(parts.join("\n"));
}
// Handle string errors
if (typeof error === "string") {
return new Error(error);
}
// Fallback for unknown error types
return new Error(JSON.stringify(error));
}
/**
* Type guard to check if an object is a docker-compose result
*/
private isDockerComposeResult(error: unknown): error is IDockerComposeResult {
return (
typeof error === "object" &&
error !== null &&
"exitCode" in error &&
"err" in error &&
"out" in error
);
}
}