Dashboard › cli › Distillation
d3198853-d458-4119-b7ad-3e3407e164f0["lore_tm_v1_QkrzFUBq_QaJVemEcbi2K_4ULAc6NjNGGgQI6SIyU5M","lore_tm_v1_BLNG6uBocZ5ykRDtIruZztP-PeXv-yVjipNlUhwckzs","lore_tm_v1_doWLbQR_6Gtj8jsNeb5BJPtLqxRjnCFlsR3R0RVJeOk","lore_tm_v1_6t-malohcpApnEDPOhKmIiIYcmQWQFGcQD4DWAT9cAg","lore_tm_v1_cO3XRRuRwdPFuWpEe2GdRmV_Rm-j3wBi_6rthqkk3ZI","lore_tm_v1_JIPASuVGelSfeecFtKxhXo2w3ccPesZJDuMA5GMHugQ","lore_tm_v1_fjO7GqMv-MzR-ZpGTtOilBk6krJnfIaFrz6BfZM8nWs","lore_tm_v1_KuVaQhf7d5ndNEEurZY08_omuHmuJxZgJwYDDegwKso","lore_tm_v1_67Mu6hxj96nUDE-FEygQMgYX7AEdxZ4RtNGSGWqMC5I"]
src/utils/workspaces.ts defines WorkspacePackage with exact fields name, location, private, hasPublicAccess, and workspaceDependencies, plus WorkspaceDiscoveryResult with type: 'npm' | 'yarn' | 'pnpm' | 'none' and packages: WorkspacePackage[].src/utils/workspaces.ts:96-147 supports both package.json workspace forms (string[] and { packages?: string[] }). resolveWorkspaceGlobs() expands patterns with glob relative to rootDir, uses absolute paths, ignores **/node_modules/**, collects named packages first, then filters dependencies against the complete set of workspace names.dependencies, devDependencies, peerDependencies, and optionalDependencies, deduplicating them before retaining only dependencies that are also discovered workspace packages.src/utils/workspaces.ts:165-254 detects pnpm first via pnpm-workspace.yaml, then npm/yarn through the root package.json workspaces field; npm versus Yarn is selected by the presence of yarn.lock. Invalid non-ENOENT pnpm YAML emits logger.warn, and no detected workspace returns { type: 'none', packages: [] }.src/utils/workspaces.ts:341-357 exports filterWorkspacePackages(packages, includePattern?, excludePattern?), applying the exclude regex and then the include regex to package names.src/utils/workspaces.ts:360-403 exports topologicalSortPackages(), computing package depth as 1 + max(depth of dependencies) with memoization and a recursion-stack Set; packages with no dependencies have depth 0, and cycles throw Circular dependency detected among workspace packages: ${cyclePackages.join(', ')}.src/commands/workspace.ts, src/commands/workspace_cmds/list.ts, src/commands/workspace_cmds/__tests__/list.test.ts, src/utils/workspaces.ts, src/utils/__tests__/workspaces.test.ts, and fixtures under src/utils/__fixtures__/workspaces/: no-workspace/package.json; npm-workspace/package.json with packages/pkg-a/package.json and packages/pkg-b/package.json; and pnpm-workspace/package.json, pnpm-workspace.yaml, plus packages/pkg-a/package.json and packages/pkg-b/package.json.docs/astro.config.mjs, docs/src/content.config.ts, docs/src/content/docs/configuration.md, docs/tsconfig.json, eslint.config.mjs, src/__tests__/config.test.ts, src/commands/config.ts, src/config.ts, src/schemas/project_config.ts, src/types/mustache.d.ts, src/types/split.d.ts, tsconfig.build.json, tsconfig.json, and vitest.config.mts.src/config.ts sets WORKSPACES_MIN_VERSION = '2.29.0'; its documentation says prerelease 2.29.0-dev.0 satisfies the gate through checkMinimalConfigVersion.src/config.ts tracks selection in _activeWorkspaceName. setActiveWorkspace(name) sets or clears it and invalidates _configCache, _globalGitHubConfigCache, and _configPathCache; getActiveWorkspace() returns the current selection. Selection is intended to come from --workspace or CRAFT_WORKSPACE before configuration access.resolveWorkspaceConfig(base, workspaceName, workspaceDirectory) applies shallow workspace overrides to the top-level release config, skips undefined fields, strips the top-level workspaces map from the resolved result, and shallow-merges workspace github values with base github. It retains merged github only when both owner and repo exist; otherwise it deletes github so git-remote detection can remain the fallback.Unknown workspace "${workspaceName}" with sorted available names when present; a name matching multiple keys throws Workspace "${workspaceName}" matches multiple workspace patterns: ${matchingKeys.join(', ')}. Literal selection values that are themselves workspace patterns are rejected by getWorkspaceConfig().getWorkspaceNamesFromConfig() expands glob keys, maps concrete workspace names to matching keys, rejects ambiguous names produced by multiple patterns, and returns concrete names sorted.getWorkspaceGlobMatches() resolves globs relative to the configuration directory with dot: true, posix: true, absolute: false, and ignore: ['**/node_modules/**']. It verifies globs stay inside the repository root, resolves the real root and candidate paths with realpathSync, and drops disappeared or broken-symlink candidates on ENOENT.applyWorkspaceSelection() preserves legacy behavior when neither workspaces nor a selection exists. If --workspace/CRAFT_WORKSPACE selects a name but the config has no workspaces, it throws; if workspaces exist but none is selected, it requires --workspace <name> or CRAFT_WORKSPACE and reports available names; when both exist, it enforces minVersion >= 2.29.0 and returns the merged workspace config.loadConfigurationFromString(configContent, workspaceDirectory = process.cwd()) validates the YAML, checks the general minimum version, applies workspace selection relative to workspaceDirectory, and caches the result.getWorkspaceNames() reads and validates the configuration without applying an active selection, expands workspace patterns relative to the config file directory, and enforces WORKSPACES_MIN_VERSION when at least one concrete workspace name exists.getGitTagPrefix() now reads GitHub targets from the active, already narrowed configuration. It returns the first GitHub targetβs tagPrefix or ''; if GitHub targets have differing prefixes, it warns that the first is used and recommends a top-level workspaces entry per independently versioned product or a separate .craft.yml, each with one GitHub target and its own tagPrefix.expandWorkspaceTargets(targets) lazily imports getTargetByName from ./targets, uses getConfigFileDir() || process.cwd() as rootDir, calls a target classβs static expand(target, rootDir) when available, and otherwise preserves the original target.src/schemas/project_config.ts defines shared releaseUnitFields: github, targets, preReleaseCommand, postReleaseCommand, releaseBranchPrefix, changelog, deprecated changelogPolicy, requireNames, statusProvider, artifactProvider, versioning, and noMerge.WorkspaceSchema uses the shared release-unit fields but replaces github with GitHubGlobalConfigSchema.partial(), allowing workspace-level inheritance of owner and/or repo; it explicitly rejects workspace github.projectPath with Workspace github.projectPath is not supported.CraftProjectConfigSchema adds optional workspaces: z.record(WorkspaceNameSchema, WorkspaceSchema). When that map is nonempty, top-level github.projectPath is also rejected with Workspace configurations cannot use github.projectPath. at path ['github', 'projectPath'].., .., __proto__, and hyphen-prefixed segments; literal segments allow /^[A-Za-z0-9_.-]+$/, while magic glob segments allow /^[A-Za-z0-9_.?*[\]!^-]+$/. Brace alternatives are recursively expanded and validated, and unsupported names report Workspace paths must use safe ASCII segments.packages/cli/src/lib/binary.ts, packages/cli/test/lib/binary.test.ts, packages/cli/test/lib/ghcr.test.ts, and packages/cli/test/lib/install-script.test.ts; diff statistics are 232 insertions and 5 deletions across those 4 files.packages/cli/tsconfig.json targets and uses ESNext, sets moduleResolution: "bundler", allowImportingTsExtensions: true, verbatimModuleSyntax: true, noEmit: true, strict: true, strictNullChecks: true, noUncheckedIndexedAccess: true, noImplicitOverride: true, and skipLibCheck: true; it includes src/**/*.ts and src/**/*.tsx and excludes node_modules and dist.docs/src/content/docs/github-actions.md, src/commands/__tests__/publish.test.ts, src/commands/publish.ts, src/utils/__tests__/publishState.test.ts, and src/utils/publishState.ts.