- Remove cli-node/src/paths.ts compat layer, migrate all cli-node
internal usage to import targetPaths from @backstage/cli-common
- Use single-arg overrideTargetPaths('/root') where dir === rootDir
- Scope mockDir to each describe block in bump.test.ts to avoid
shared state issues with overrideTargetPaths
- Remove unnecessary overrideTargetPaths from plugin-manager.test.ts
- Remove stale findPaths mock from createApp.test.ts
- Use overrideTargetPaths in getWorkspaceRoot.test.ts and cli-node tests
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Adds `overrideTargetPaths` to `@backstage/cli-common/testUtils` for
cleanly mocking `targetPaths` in tests without `jest.mock` or
`jest.spyOn`. Migrates all existing test mocks to use the new utility.
Also fixes translations module imports broken by the rebase.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
- Refactor targetPaths/findOwnPaths to class-based implementations with
unified caching and .dir/.rootDir properties alongside resolve methods
- Replace jest.mock with jest.spyOn in plugin-manager.test.ts
- Remove paths compatibility wrapper from repo-tools, migrate all internal
consumers to use targetPaths from @backstage/cli-common directly
- Fix changeset package name (@techdocs/cli not @backstage/techdocs-cli)
- Add migration examples to cli-common changeset
- Update API report for cli-common
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Split the path resolution API in @backstage/cli-common into
targetPaths (cwd-based singleton) and findOwnPaths (package-relative).
Migrate all consumers across the repo away from the deprecated findPaths.
Rename TargetPaths/OwnPaths properties to resolve/resolveRoot,
removing the redundant type prefix from property names.
Make findOwnPaths calls lazy in modules - called inside functions
rather than at module scope.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Split the paths API in @backstage/cli-common into targetPaths (a lazily
initialized singleton for cwd-based paths) and findOwnPaths (a cached function
for package-relative paths). Most CLI module files only need target paths, which
can now be imported directly without __dirname. The few files that need own paths
use findOwnPaths(__dirname).
Added hierarchical caching to findOwnDir so the filesystem walk only happens
once per package. targetPaths re-resolves automatically if process.cwd() changes.
The deprecated findPaths function is preserved for backward compatibility,
delegating to the new primitives internally.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Each module file that needs paths now calls findPaths(__dirname) directly from
@backstage/cli-common. This removes the coupling between modules and lib/paths,
and will continue to work when modules are extracted into separate packages since
each package's __dirname resolves to its own root.
Added hierarchical caching to findOwnDir in cli-common so that the filesystem
walk only happens once per package - subsequent calls from sibling directories
hit the cache at a common ancestor.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Each module now has a local paths.ts that calls findPaths(__dirname) directly.
This makes modules fully independent of lib/paths.ts, and the pattern will
continue to work when modules are extracted into separate packages since each
package's __dirname will resolve to its own root.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Fix whitespace alignment in CLI command summary, improve export command
description to clarify it operates from an app context, and update the
corresponding docs section.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
- Rename runParallelWorkers to runConcurrentTasks, return void
- Rename ParallelWorkerOptions to ConcurrentTasksOptions
- Rename parallelismFactor to concurrencyFactor
- Remove unused runWorkerThreads and WorkerThreadsOptions
- Rename workerData to context in WorkerQueueThreadsOptions
- Drop threadCount from public API types
- Rename env var to BACKSTAGE_CLI_CONCURRENCY
- Make cli-node changeset a patch
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
The parallelism fields on bundler types (BundlingOptions, BuildOptions,
BackendBundlingOptions) and createDistWorkspace Options were defined but
never read — fully dead code. Likewise the parallelismSetting option on
ParallelWorkerOptions was never passed by any caller.
Also narrows the cli-node public API to only export the three runner
functions and their option types, keeping getEnvironmentParallelism and
parseParallelismOption as internal utilities.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Moves `runParallelWorkers`, `runWorkerQueueThreads`, `runWorkerThreads`,
`parseParallelismOption`, and `getEnvironmentParallelism` from the CLI
internal lib to the shared `@backstage/cli-node` package.
This is part of the ongoing effort to make CLI modules independent of
each other and the shared lib code.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Moved `entryPoints.ts` and `role.ts` (+ test) from the shared `src/lib/`
directory into `src/modules/build/lib/`, since the build module is their
only consumer. This is part of making CLI modules independent of each
other and of shared code outside the modules.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
The only usage of bfj in @backstage/cli is `bfj.write(path, data)` in
bundle.ts for writing bundle-stats.json. The write API is unchanged in
v9 and v9.0.0/v9.0.1 are deprecated, so the range starts at ^9.0.2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Raghunandan Balachandran <raghunandan@spotify.com>
- Fix Windows path separators in import by splitting on path.sep
- Make extractTranslations test less brittle by not pinning exact
message strings or total count
- Remove unnecessary `as any` cast for devDependencies
- Validate pattern in export command to fail fast on invalid patterns
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Moves the messages/ path segment from being hardcoded into the export
and import commands to being part of the pattern itself. The default
pattern is now messages/{id}.{lang}.json, giving full control over the
directory structure under the translations output directory.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Uses PackageRoles.getRoleInfo from cli-node to determine frontend packages
by platform instead of a hardcoded role list. Removes the --pattern option
from the import command since the pattern is always read from the manifest.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Adds a --pattern option to both translations export and import commands
that controls the file path layout of message files within the messages/
directory. The default pattern is {id}.{lang}.json (unchanged behavior),
but users can pass e.g. --pattern '{lang}/{id}.json' for language-based
directory grouping. The pattern is stored in the manifest so that import
picks it up automatically.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
The package discovery for the translations export command previously only
looked at direct dependencies and only workspace packages. This changes
it to recursively walk the full transitive dependency tree and resolve
packages from node_modules when they aren't found in the workspace.
Entry point resolution now also prefers .d.ts type declarations for
npm-installed packages.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Adds tooling for exporting and importing translation strings to enable
integration with external TMS tools like Smartling. The export command
uses the TypeScript compiler API (ts-morph) to discover TranslationRef
exports from all frontend plugin dependencies of the current package,
extracting message keys and default values from the type system. The
import command generates TranslationResource wiring from translated
JSON files downloaded from a TMS.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Only CSS and other non-script, non-JSON exports should be excluded from
typesVersions. The package.json export still needs to be included.
Also preserves field order when updating existing typesVersions.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
- Add deduplication logic to only emit CSS once per output directory
- Only emit during write phase, not during generate
- Fix comment describing the path transformation
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Instead of having a separate post-build step for CSS entry points,
the CSS bundling is now integrated directly into the Rollup build
as a plugin. This is cleaner and will enable better watch mode
support in the future.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
postcss-import naturally preserves @layer declarations during bundling,
eliminating the need for custom layer parsing and restoration logic.
This simplifies the implementation while also preserving source comments.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
This adds support for CSS entry points in package exports. When a package
declares a CSS file in its exports field, the CLI will now automatically
bundle it during `backstage-cli package build` and rewrite the export
path from src/ to dist/ at publish time.
The CSS bundling uses lightningcss to resolve @import statements and
preserves @layer declarations that would otherwise be stripped during
bundling.
This allows packages like @backstage/ui to use the standard build command
instead of custom build scripts for CSS bundling.
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>