Files
backstage/packages/cli/package.json
T
Johan Persson cd0b8a11a3 chore: make jest a peer dependency with v29/v30 support
Move jest from dependencies to peer dependencies, allowing users to
choose between Jest 29 and Jest 30.

The CLI now detects the Jest version at runtime and uses the
appropriate environment:
- Jest 29: Uses standard jest-environment-jsdom
- Jest 30: Uses a custom environment based on @jest/environment-jsdom-abstract
  with fixes for Web API globals (fetch, streams, Error, etc.)

The cross-fetch polyfill is only injected for Jest 29, as with Jest 30+
our patched Jest environment is used. The network request blocker is made
MSW-compatible by checking if fetch was wrapped before blocking.

Jest 30 (with jsdom v27) fixes `Could not parse CSS stylesheet`
warnings/errors when testing components from @backstage/ui or other
packages using CSS `@layer` declarations.

New peer dependencies (install based on your Jest version):
- jest (required, ^29 or ^30)
- Jest 29 requires: jest-environment-jsdom
- Jest 30 requires: @jest/environment-jsdom-abstract, jsdom

Production code changes for jsdom 27 testability:
- AppIdentityProxy: extract navigateToUrl method for spying
- LiveReloadAddon: export utils.reloadPage for spying
- collect.ts: export internal.resolvePackagePath for mocking

MockFetchApi: evaluate global.fetch at call time instead of construction
time, allowing MSW to patch fetch after MockFetchApi is constructed.

Test adaptations for jsdom 27:
- Use RGB values instead of named colors in CSS assertions
- Update error format expectations (hyphenated type names, SyntaxError
  instead of FetchError for JSON parse errors)
- Simplify URL error assertions for cross-version compatibility
- Fix accessible name whitespace handling for external links
- Use history.replaceState for location mocking (non-configurable)
- Use fireEvent.blur for contentEditable elements
- Move async assertions inside waitFor for race conditions
- Remove Blob.prototype.text polyfill (now native)
- Remove test case using credentials in plugin:// URLs

Test adaptations for Jest 30:
- Replace `expect.objectContaining([...])` with direct array equality
- Replace `expect.objectContaining({ length: N })` with
  `expect.any(Array)` + separate `toHaveLength()` assertions
- Use child process for native Node.js module resolution in
  collect.test.ts to work around Jest 30's resolver behavior
- Update snapshot headers for new Jest format

Also removes the jest-haste-map patch which is no longer needed.

Signed-off-by: Johan Persson <johanopersson@gmail.com>
2025-12-11 18:06:55 +01:00

353 lines
11 KiB
JSON

{
"name": "@backstage/cli",
"version": "0.35.0-next.2",
"description": "CLI for developing Backstage plugins and apps",
"backstage": {
"role": "cli"
},
"publishConfig": {
"access": "public"
},
"keywords": [
"backstage"
],
"homepage": "https://backstage.io",
"repository": {
"type": "git",
"url": "https://github.com/backstage/backstage",
"directory": "packages/cli"
},
"license": "Apache-2.0",
"main": "dist/index.cjs.js",
"bin": {
"backstage-cli": "bin/backstage-cli"
},
"files": [
"asset-types",
"templates",
"config",
"bin",
"dist/**/*.js"
],
"scripts": {
"build": "backstage-cli package build",
"clean": "backstage-cli package clean",
"lint": "backstage-cli package lint",
"start": "nodemon --",
"test": "backstage-cli package test"
},
"nodemonConfig": {
"exec": "bin/backstage-cli",
"ext": "ts",
"watch": "./src"
},
"jest": {
"coveragePathIgnorePatterns": [
"/__fixtures__/"
]
},
"dependencies": {
"@backstage/catalog-model": "workspace:^",
"@backstage/cli-common": "workspace:^",
"@backstage/cli-node": "workspace:^",
"@backstage/config": "workspace:^",
"@backstage/config-loader": "workspace:^",
"@backstage/errors": "workspace:^",
"@backstage/eslint-plugin": "workspace:^",
"@backstage/integration": "workspace:^",
"@backstage/release-manifests": "workspace:^",
"@backstage/types": "workspace:^",
"@manypkg/get-packages": "^1.1.3",
"@module-federation/enhanced": "^0.9.0",
"@octokit/request": "^8.0.0",
"@rollup/plugin-commonjs": "^26.0.0",
"@rollup/plugin-json": "^6.0.0",
"@rollup/plugin-node-resolve": "^15.0.0",
"@rollup/plugin-yaml": "^4.0.0",
"@rspack/core": "^1.4.11",
"@rspack/dev-server": "^1.1.4",
"@rspack/plugin-react-refresh": "^1.4.3",
"@spotify/eslint-config-base": "^15.0.0",
"@spotify/eslint-config-react": "^15.0.0",
"@spotify/eslint-config-typescript": "^15.0.0",
"@swc/core": "^1.3.46",
"@swc/helpers": "^0.5.0",
"@swc/jest": "^0.2.22",
"@types/webpack-env": "^1.15.2",
"@typescript-eslint/eslint-plugin": "^8.17.0",
"@typescript-eslint/parser": "^8.16.0",
"@yarnpkg/lockfile": "^1.1.0",
"@yarnpkg/parsers": "^3.0.0",
"bfj": "^8.0.0",
"buffer": "^6.0.3",
"chalk": "^4.0.0",
"chokidar": "^3.3.1",
"commander": "^12.0.0",
"cross-fetch": "^4.0.0",
"cross-spawn": "^7.0.3",
"css-loader": "^6.5.1",
"ctrlc-windows": "^2.1.0",
"esbuild": "^0.27.0",
"eslint": "^8.6.0",
"eslint-config-prettier": "^9.0.0",
"eslint-formatter-friendly": "^7.0.0",
"eslint-plugin-deprecation": "^3.0.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jest": "^28.9.0",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-react": "^7.37.2",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-unused-imports": "^4.1.4",
"eslint-rspack-plugin": "^4.2.1",
"express": "^4.22.0",
"fs-extra": "^11.2.0",
"git-url-parse": "^15.0.0",
"glob": "^7.1.7",
"global-agent": "^3.0.0",
"globby": "^11.1.0",
"handlebars": "^4.7.3",
"html-webpack-plugin": "^5.6.3",
"inquirer": "^8.2.0",
"jest-css-modules": "^2.1.0",
"json-schema": "^0.4.0",
"lodash": "^4.17.21",
"minimatch": "^9.0.0",
"node-stdlib-browser": "^1.3.1",
"npm-packlist": "^5.0.0",
"ora": "^5.3.0",
"p-queue": "^6.6.2",
"pirates": "^4.0.6",
"postcss": "^8.1.0",
"process": "^0.11.10",
"raw-loader": "^4.0.2",
"react-dev-utils": "^12.0.0-next.60",
"react-refresh": "^0.17.0",
"recursive-readdir": "^2.2.2",
"replace-in-file": "^7.1.0",
"rollup": "^4.27.3",
"rollup-plugin-dts": "^6.1.0",
"rollup-plugin-esbuild": "^6.1.1",
"rollup-plugin-postcss": "^4.0.0",
"rollup-pluginutils": "^2.8.2",
"semver": "^7.5.3",
"style-loader": "^3.3.1",
"sucrase": "^3.20.2",
"swc-loader": "^0.2.3",
"tar": "^6.1.12",
"ts-checker-rspack-plugin": "^1.1.5",
"ts-morph": "^24.0.0",
"undici": "^7.2.3",
"util": "^0.12.3",
"yaml": "^2.0.0",
"yargs": "^16.2.0",
"yml-loader": "^2.1.0",
"yn": "^4.0.0",
"zod": "^3.22.4",
"zod-validation-error": "^3.4.0"
},
"devDependencies": {
"@backstage/backend-plugin-api": "workspace:^",
"@backstage/backend-test-utils": "workspace:^",
"@backstage/catalog-client": "workspace:^",
"@backstage/config": "workspace:^",
"@backstage/core-app-api": "workspace:^",
"@backstage/core-components": "workspace:^",
"@backstage/core-plugin-api": "workspace:^",
"@backstage/dev-utils": "workspace:^",
"@backstage/errors": "workspace:^",
"@backstage/plugin-auth-backend": "workspace:^",
"@backstage/plugin-auth-backend-module-guest-provider": "workspace:^",
"@backstage/plugin-catalog-node": "workspace:^",
"@backstage/plugin-scaffolder-node": "workspace:^",
"@backstage/plugin-scaffolder-node-test-utils": "workspace:^",
"@backstage/test-utils": "workspace:^",
"@backstage/theme": "workspace:^",
"@jest/environment-jsdom-abstract": "^30.0.0",
"@pmmmwh/react-refresh-webpack-plugin": "^0.6.0",
"@types/cross-spawn": "^6.0.2",
"@types/ejs": "^3.1.3",
"@types/express": "^4.17.6",
"@types/fs-extra": "^11.0.0",
"@types/http-proxy": "^1.17.4",
"@types/inquirer": "^8.1.3",
"@types/jest": "^30.0.0",
"@types/node": "^22.13.14",
"@types/npm-packlist": "^3.0.0",
"@types/recursive-readdir": "^2.2.0",
"@types/rollup-plugin-peer-deps-external": "^2.2.0",
"@types/rollup-plugin-postcss": "^3.1.4",
"@types/svgo": "^2.6.2",
"@types/tar": "^6.1.1",
"@types/terser-webpack-plugin": "^5.0.4",
"@types/webpack-sources": "^3.2.3",
"@types/yarnpkg__lockfile": "^1.1.4",
"del": "^8.0.0",
"esbuild-loader": "^4.0.0",
"eslint-webpack-plugin": "^4.2.0",
"fork-ts-checker-webpack-plugin": "^9.0.0",
"jest": "^30.2.0",
"jsdom": "^27.1.0",
"mini-css-extract-plugin": "^2.4.2",
"msw": "^1.0.0",
"nodemon": "^3.0.1",
"terser-webpack-plugin": "^5.1.3",
"webpack": "~5.103.0",
"webpack-dev-server": "^5.0.0"
},
"peerDependencies": {
"@jest/environment-jsdom-abstract": "^30.0.0",
"@module-federation/enhanced": "^0.9.0",
"@pmmmwh/react-refresh-webpack-plugin": "^0.6.0",
"esbuild-loader": "^4.0.0",
"eslint-webpack-plugin": "^4.2.0",
"fork-ts-checker-webpack-plugin": "^9.0.0",
"jest": "^29.0.0 || ^30.0.0",
"jest-environment-jsdom": "*",
"jsdom": "^27.1.0",
"mini-css-extract-plugin": "^2.4.2",
"terser-webpack-plugin": "^5.1.3",
"webpack": "~5.103.0",
"webpack-dev-server": "^5.0.0"
},
"peerDependenciesMeta": {
"@jest/environment-jsdom-abstract": {
"optional": true
},
"@module-federation/enhanced": {
"optional": true
},
"@pmmmwh/react-refresh-webpack-plugin": {
"optional": true
},
"esbuild-loader": {
"optional": true
},
"eslint-webpack-plugin": {
"optional": true
},
"fork-ts-checker-webpack-plugin": {
"optional": true
},
"jest-environment-jsdom": {
"optional": true
},
"jsdom": {
"optional": true
},
"mini-css-extract-plugin": {
"optional": true
},
"terser-webpack-plugin": {
"optional": true
},
"webpack": {
"optional": true
},
"webpack-dev-server": {
"optional": true
}
},
"configSchema": {
"$schema": "https://backstage.io/schema/config-v1",
"title": "@backstage/cli",
"type": "object",
"properties": {
"app": {
"type": "object",
"properties": {
"baseUrl": {
"type": "string",
"visibility": "frontend"
},
"title": {
"type": "string",
"visibility": "frontend"
},
"datadogRum": {
"type": "object",
"description": "Datadog RUM events configuration",
"properties": {
"env": {
"type": "string",
"visibility": "frontend",
"description": "Environment for Datadog RUM events"
},
"clientToken": {
"type": "string",
"visibility": "frontend",
"description": "clientToken for Datadog RUM events"
},
"applicationId": {
"type": "string",
"visibility": "frontend",
"description": "applicationId for Datadog RUM events"
},
"site": {
"type": "string",
"visibility": "frontend",
"description": "site for Datadog RUM events"
},
"sessionSampleRate": {
"type": "number",
"visibility": "frontend",
"description": "sample rate of Datadog RUM events"
},
"sessionReplaySampleRate": {
"type": "number",
"visibility": "frontend",
"description": "sample rate of session replays based upon already sampled Datadog RUM events"
}
},
"required": [
"clientToken",
"applicationId"
]
},
"listen": {
"type": "object",
"description": "Listening configuration for local development",
"properties": {
"host": {
"type": "string",
"visibility": "frontend",
"description": "The host that the frontend should be bound to. Only used for local development."
},
"port": {
"type": "number",
"visibility": "frontend",
"description": "The port that the frontend should be bound to. Only used for local development."
}
}
},
"https": {
"type": "object",
"description": "Only used for local development. The https object is passed to webpack in order to enable using https on localhost.",
"properties": {
"certificate": {
"type": "object",
"description": "Parent object containing certificate and the private key",
"required": [
"key",
"cert"
],
"properties": {
"key": {
"type": "string",
"visibility": "secret",
"description": "Https Certificate private key. Use $file to load in a file"
},
"cert": {
"type": "string",
"visibility": "secret",
"description": "Https Certificate. Use $file to load in a file"
}
}
}
}
}
}
}
}
}
}