TS/JS API: Reference
Stale workspace data: Note that you need to run your package manager's install for pacwich to have current workspace data available, e.g. via bun install, pnpm install, ornpm install. If you've added/removed/updated any workspace package.json, you'll likely need to run this again.
See the API quick start here.
createFileSystemProject
createFileSystemProject(options: CreateFileSystemProjectOptions): FileSystemProject
Create a FileSystemProject, the core of pacwich's functionality, based on a given root directory.
This will walk up to find the nearest project root if ran from a project's subdirectory.
It will also detect and utilize any project configuration and workspace configurations found.
import { createFileSystemProject } from "pacwich";
// Root directory defaults to process.cwd()
// Package manager is auto-detected if a lockfile is found
const defaultProject = createFileSystemProject();
const pathProject = createFileSystemProject({
// relative from process.cwd()
rootDirectory: "./path/to/project/root",
// Specify a package manager, mainly if multiple lockfiles are present
packageManager: "bun",
// (default false) Include the root workspace as a normal workspace
includeRootWorkspace: false,
// Disable executable configuration files (TS/JS) for untrusted contexts
disableExecutableConfigs: true,
});
Workspace
An object representing a workspace in a Project.
Set workspace aliases in the workspace configuration to make it easier to reference workspaces.
The dependencies and dependents fields are names of other workspaces that are dependencies or dependents of this workspace, respectively.
See more on the root workspace.
{
// The name of the workspace from its package.json
name: "my-workspace",
// Whether the workspace is the root workspace
isRoot: false,
// The relative path to the workspace from the project root
path: "my/workspace/path",
// The glob pattern from the root package.json "workspaces" field
// that this workspace was matched from
matchPattern: "my/workspace/pattern/*",
// The scripts available in the workspace's package.json
scripts: ["my-script"],
// Aliases defined in workspace configuration (see the Configuration section)
aliases: ["my-alias"],
// Tags defined in workspace configuration (see the Configuration section)
tags: ["my-tag"],
// Names of other workspaces that this workspace depends on
dependencies: ["my-dependency"],
// Names of other workspaces that depend on this workspace
dependents: ["my-dependent"],
// Other external dependencies, e.g. lodash, react
externalDependencies: [
{
"name": "lodash",
"version": "^4.17.21",
"source": "devDependencies"
},
],
}
Project
The core of pacwich's functionality.
It contains a list of Workspaces and provides
several useful methods for working with them. A Project is typically initialized at a git repository's root directory.
The Project root should contain the package.json file in which "workspaces" are defined.
Usually created via createFileSystemProject.
import { createFileSystemProject } from "pacwich";
const project = createFileSystemProject();
.name
type: string
The name of the project. This is typically the name found in the root package.json unless otherwise provided.
.rootDirectory
type: string
The given root directory of the project.
.workspaces
type: Workspace[]
The list of all Workspaces in the project.
.rootWorkspace
type: Workspace
The root workspace of the project.
.findWorkspaceByName
findWorkspaceByName(workspaceName: string): Workspace | null
Find a Workspace by its package.json name.
// Find a workspace by its package.json name (or returns null)
const workspace = project.findWorkspaceByName("my-workspace");
.findWorkspaceByAlias
findWorkspaceByAlias(alias: string): Workspace | null
Find a Workspace by its alias, if set in its workspace configuration.
// Find a workspace by its alias (or returns null)
const workspace = project.findWorkspaceByAlias("my-alias");
.findWorkspaceByNameOrAlias
findWorkspaceByNameOrAlias(nameOrAlias: string): Workspace | null
Find a Workspace by its package.json name or alias, if set in its workspace configuration.
Since aliases are validated to be unique to each workspace and not clash with other workspaces' package.json names, this method can still unambiguously find a workspace.
// Find a workspace by its package.json name or alias (or returns null)
const workspace = project.findWorkspaceByNameOrAlias("my-workspace");
.findWorkspacesByPattern
findWorkspacesByPattern(workspacePattern: string): Workspace[]
Find a list of Workspaces by their name, using a wildcard pattern.
See more on the syntax of workspace patterns.
// An array of workspaces whose names match the wildcard pattern
const workspaces = project.findWorkspacesByPattern(
"my-name-pattern-*",
"alias:my-alias-*",
"path:packages/**/*",
);
.listWorkspacesWithScript
listWorkspacesWithScript(scriptName: string): Workspace[]
Get an array of all Workspaces that have a given script in their package.json "scripts" field.
// An array of workspaces that have "my-script"
// in their package.json "scripts" field
const workspaces = project.listWorkspacesWithScript("my-script");
.listWorkspacesWithTag
listWorkspacesWithTag(tag: string): Workspace[]
Get an array of all Workspaces that have a given tag. Tags are defined in a workspace's configuration.
// An array of workspaces that have the tag "my-tag".
// Tags are defined in a workspace's configuration file.
const workspaces = project.listWorkspacesWithTag("my-tag");
.scriptMap
scriptMap: Record<string, ScriptDetails>
Get a mapping of all project script names to the Workspaces that have them in their package.json "scripts" field.
// An array of Workspaces
const { workspaces } = project.scriptMap["my-script"];
.tagMap
tagMap: Record<string, TagDetails>
Get a mapping of all tags to the Workspaces that have them in their respective workspace configuration.
// An array of Workspaces
const { workspaces } = project.tagMap["my-tag"];
FileSystemProject
Inherits from Project. Used to represent a project in the file system. Created via createFileSystemProject.
Includes methods for running scripts in the workspaces of the project.
.runWorkspaceScript
runWorkspaceScript(options: RunWorkspaceScriptOptions): RunWorkspaceScriptResult
Run a script in a given workspace.
const { output, exit } = project.runWorkspaceScript({
workspaceNameOrAlias: "my-workspace",
script: "my-script",
// Optional. Arguments to add to the command
// Can be a string or an array of strings
// If string, the argv will be parsed POSIX-style
args: ["--my", "--appended", "--args"],
// Optional. Whether to ignore all output from the script.
// This saves memory when you don't need script output.
ignoreOutput: false,
});
// Get a stream of the script subprocess's output
for await (const { chunk, metadata } of output.text()) {
// console.log(chunk); // The output chunk's content (string)
// console.log(metadata.streamName); // "stdout" or "stderr"
// console.log(metadata.workspace); // The target Workspace
}
// Get data about the script execution after it exits
const exitResult = await exit;
// exitResult.exitCode // The exit code (number)
// exitResult.signal // The exit signal (string), or null
// exitResult.success // true if exit code was 0
// exitResult.startTimeISO // Start time (string)
// exitResult.endTimeISO // End time (string)
// exitResult.durationMs // Duration in milliseconds (number)
// exitResult.metadata.workspace // The target workspace (Workspace)
.runScriptAcrossWorkspaces
runScriptAcrossWorkspaces(options: RunScriptAcrossWorkspacesOptions): RunScriptAcrossWorkspacesResult
Run a script in all workspaces that have it in their package.json "scripts" field.
const { output, summary } = project.runScriptAcrossWorkspaces({
// Optional. This will run in all matching workspaces that have my-script
// Accepts same values as the CLI run-script command's workspace patterns
// When not provided, all workspaces that have the script will be used.
workspacePatterns: ["my-workspace", "my-name-pattern-*"],
// Required. The package.json "scripts" field name to run
script: "my-script",
// Optional. Arguments to add to the command (same as for runWorkspaceScript)
args: ["--my", "--appended", "--args"],
// Optional. Whether to run the scripts in parallel (default: true)
parallel: true,
// Optional. When true, a workspace's script will wait
// until any workspaces it depends on have completed
dependencyOrder: false,
// Optional. When true and dependencyOrder is true,
// continue running scripts even if a dependency fails
ignoreDependencyFailure: false,
// Optional. Whether to ignore all output from the scripts.
// This saves memory when you don't need script output.
ignoreOutput: false,
// Optional, callback when script starts, skips, or exits
onScriptEvent: (event, { workspace, exitResult }) => {
// event: "start", "skip", "exit"
},
});
// Get a stream of script output
for await (const { chunk, metadata } of output.text()) {
// console.log(chunk); // the output chunk's content (string)
// console.log(metadata.streamName); // "stdout" or "stderr"
// console.log(metadata.workspace); // the Workspace of the output
}
// Get final summary data and script exit details
const summaryResult = await summary;
// summaryResult.totalCount // Total number of scripts
// summaryResult.allSuccess // true if all scripts succeeded
// summaryResult.successCount // Number of scripts that succeeded
// summaryResult.failureCount // Number of scripts that failed
// summaryResult.startTimeISO // Start time (string)
// summaryResult.endTimeISO // End time (string)
// summaryResult.durationMs // Total duration in milliseconds (number)
// The exit details of each workspace script
for (const exitResult of summaryResult.scriptResults) {
// exitResult.exitCode // The exit code (number)
// exitResult.signal // The exit signal (string), or null
// exitResult.success // true if exit code was 0
// exitResult.startTimeISO // Start time (ISO string)
// exitResult.endTimeISO // End time (ISO string)
// exitResult.durationMs // Duration in milliseconds (number)
// exitResult.metadata.workspace // The target workspace (Workspace)
}
More Info
- See more on the syntax of workspace patterns for selecting workspaces to run.
- See more on workspace dependencies for running scripts in dependency order.
- See more on running inline scripts.
- See more on running parallel scripts.
- See more on workspace script metadata, such as environment variables available in scripts and interpolating values in inline scripts and args such as
<workspaceName>.
.determineAffectedWorkspaces
determineAffectedWorkspaces(options: DetermineAffectedWorkspacesOptions): AffectedWorkspacesResult
Determine the workspaces that are affected by a change. The return object
is the same as the CLI's output for list-affected --explain --json.
Using git diff to determine affected workspaces:
// Workspace results contain details about each workspace,
// including whether it is affected and why
const { workspaceResults } = await project.determineAffectedWorkspaces({
// Optional, the script to run to determine affected workspaces
// When not provided, based on workspaces' default inputs
script: "my-script",
diffSource: "git",
diffOptions: {
// Optional, defaults to main if default base ref not configured
baseRef: "my-branch-a",
// Optional, defaults to current HEAD if not provided
headRef: "my-branch-b",
// Optional means of ignoring uncommitted changes
// gitignored files are never included in a diff
ignoreUntracked: false, // files that may be tracked but aren't
ignoreStaged: false,
ignoreUnstaged: false,
// Ignores untracked, staged, and unstaged
ignoreUncommitted: false,
},
// Ignore workspace dependencies when determining affected workspaces
ignoreWorkspaceDependencies: false,
// Ignore changes external dependencies (e.g. react, lodash) lock versions
ignoreExternalDependencies: false,
});
Using a list of changed files to determine affected workspaces:
const { workspaceResults } = await project.determineAffectedWorkspaces({
// Bypass git and pass a list of changed files that match inputs
diffSource: "fileList",
changedFiles: ["src/**/*.ts", "something.txt"],
});
More Info
- See more on affected workspaces.
- See more on inputs that determine if a workspace is affected.
.runAffectedWorkspaceScript
runAffectedWorkspaceScript(options: RunAffectedWorkspaceScriptOptions): RunAffectedWorkspaceScriptResult
Run a script in the workspaces that are affected by a change.
This behaves similarly to runScriptAcrossWorkspaces, while also taking similar options to determineAffectedWorkspaces.
// Returns the same output and summary as project.runScriptAcrossWorkspaces
const { output, summary } = await project.runAffectedWorkspaceScript({
// About the same options as project.determineAffectedWorkspaces
affectedOptions: {
diffSource: "git",
diffOptions: {
baseRef: "my-branch-a",
headRef: "my-branch-b",
},
},
// About the same options as project.runScriptAcrossWorkspaces
scriptOptions: {
script: "my-script",
},
});
More Info
- See more on affected workspaces.
- See more on inputs that determine if a workspace is affected.
.verify
verify(options: VerifyOptions): VerifyResult
Verify the project for issues. The result is the same
as the CLI verify command's JSON output.
// Analog to the CLI verify command
const results = await project.verify({
// Optional: (default false) When true,
// treat warnings as errors
strict: false,
// Optional: workspace patterns to scope verification to
workspacePatterns: ["*"],
});
createMemoryProject
ExperimentalcreateMemoryProject(options: CreateMemoryProjectOptions): MemoryProject
Create a Project from a given array of Workspaces.
Usually used only for testing purposes to do without the need for a real project in the file system.
Since it doesn't read anything from the file system, it isn't affected by project configuration or workspace configurations.
A MemoryProject currently does not support running scripts directly, though a means of mocking script execution may be added later, considering demand.
import { createMemoryProject } from "pacwich";
const testProject = createMemoryProject({
packageManager: "npm", // required
rootDirectory: "test-project-directory", // optional
name: "test-project", // optional
workspaces: [
{
name: "my-test-workspace",
isRoot: false,
path: "my/test/workspace/path",
matchPattern: "my/test/workspace/pattern/*",
scripts: ["my-test-script"],
aliases: ["test-alias"],
dependencies: [],
dependents: [],
externalDependencies: [],
}
]
});
setLogLevel
setLogLevel(level: LogLevelSetting)
Set the global logging level. Defaults to "info" or "error" when NODE_ENV is "test".
import { setLogLevel } from "pacwich";
setLogLevel("debug");
setLogLevel("info") // default
setLogLevel("warn");
setLogLevel("error") // default when NODE_ENV is "test"
setLogLevel("silent");

