@teambit/isolator 1.0.1002 → 1.0.1004

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_fsExtra","data","_interopRequireDefault","require","_uuid","_path","_child_process","_pMap","_harmonyModules","_harmonyModules2","_legacy","e","__esModule","default","CAPSULE_ORIGIN_FILE","exports","CAPSULE_TRASH_DIR","ONE_DAY_MS","VALID_CAPSULE_KINDS","Set","toFiniteNumber","value","undefined","n","Number","isFinite","CapsuleCache","constructor","logger","cli","configStore","getRootDir","deleteCapsules","rootDir","dirToDelete","marker","readOriginMarker","debug","originPath","scheduleFastDelete","dir","exists","fs","pathExists","globalRoot","path","resolve","remove","trashRoot","join","ensureDir","trashTarget","basename","v4","move","overwrite","err","message","sweepTrashAsync","existsSync","lockPath","isSweepLockActive","writeFileSync","String","process","pid","flag","spawnDetachedSweep","pidStr","readFileSync","trim","kill","registerAutoPruneHook","registerOnBeforeExit","maybeAutoPrune","isFeatureEnabled","CAPSULE_AUTO_PRUNE","enabled","getConfig","CFG_CAPSULES_AUTO_PRUNE","root","stampPath","isStampFresh","stat","Date","now","mtime","getTime","claimPath","claimed","close","open","claimStat","outputFile","olderThanDays","Math","max","CFG_CAPSULES_MAX_AGE_DAYS","sizeTargetGb","CFG_CAPSULES_MAX_SIZE_GB","spawnDetachedAutoPrune","bitEntry","argv","child","spawn","execPath","detached","stdio","windowsHide","unref","script","JSON","stringify","removeSync","ensureOriginMarker","kind","markerPath","utimes","createdAt","toISOString","outputJson","ensureAspectCapsuleMarkers","capsuleList","rootOriginPath","Promise","all","map","capsule","getDatedCapsuleDirName","date","getFullYear","getMonth","getDate","isPrunableSubdir","entry","isDirectory","name","startsWith","readMarkerInfo","getOriginMarkerMtime","lastUsedMs","catch","raw","readJson","has","listAllCapsuleRoots","opts","withSizes","entries","readdir","withFileTypes","subdirs","filter","pMap","subPath","sizeBytes","computeDirSize","concurrency","concurrentIOLimit","total","walk","current","p","isFile","st","lstat","size","pruneCapsules","includeOrphans","keepWorkspaceCaps","dryRun","computeSizes","ageCutoffMs","datedDirName","CFG_CAPSULES_SCOPES_ASPECTS_DATED_DIR","roots","totalSizeBefore","reduce","sum","r","removed","removeEntry","reason","recordRemoval","pruneDatedCapsulesChildren","orphan","tooOld","looksLikeAspectsRoot","pruneAspectsRootChildren","applySizeTarget","totalRemovedBytes","totalSizeAfter","totalSizeBeforeBytes","totalSizeAfterBytes","push","rootPath","todayDir","childPath","some","includes","targetBytes","removedPaths","totalBytes","aspectChildren","sort","a","b","remainingBytes","s"],"sources":["capsule-cache.ts"],"sourcesContent":["/**\n * Manages the global capsules cache: origin markers, fast-delete + trash sweep, and the\n * prune pipeline (manual `bit capsule prune` and the gated auto-prune trigger).\n *\n * Owned by `IsolatorMain` but operationally independent — the isolator constructs an\n * instance, registers its hooks, and delegates the externally-visible cache-management\n * methods (`deleteCapsules`, `pruneCapsules`, `listAllCapsuleRoots`) to it. Keeps\n * `isolator.main.runtime.ts` focused on creating isolated component environments rather\n * than also being responsible for evicting them.\n */\nimport fs from 'fs-extra';\nimport { v4 } from 'uuid';\nimport path from 'path';\nimport { spawn } from 'child_process';\nimport pMap from 'p-map';\nimport type { Logger } from '@teambit/logger';\nimport type { CLIMain } from '@teambit/cli';\nimport type { ConfigStoreMain } from '@teambit/config-store';\nimport { concurrentIOLimit } from '@teambit/harmony.modules.concurrency';\nimport { isFeatureEnabled, CAPSULE_AUTO_PRUNE } from '@teambit/harmony.modules.feature-toggle';\nimport {\n CFG_CAPSULES_AUTO_PRUNE,\n CFG_CAPSULES_MAX_AGE_DAYS,\n CFG_CAPSULES_MAX_SIZE_GB,\n CFG_CAPSULES_SCOPES_ASPECTS_DATED_DIR,\n} from '@teambit/legacy.constants';\nimport type CapsuleList from './capsule-list';\n\n/**\n * Marker file written into every capsule dir we manage. Its presence tells the prune logic\n * what kind of dir this is, where it came from, and (via its mtime) when it was last used.\n */\nexport const CAPSULE_ORIGIN_FILE = '.bit-capsule-origin.json';\nexport const CAPSULE_TRASH_DIR = '.trash';\n\nconst ONE_DAY_MS = 24 * 60 * 60 * 1000;\n\nexport type CapsuleKind = 'workspace' | 'scope-aspects-root' | 'scope-aspect' | 'scope';\n\nconst VALID_CAPSULE_KINDS: ReadonlySet<string> = new Set(['workspace', 'scope-aspects-root', 'scope-aspect', 'scope']);\n\nexport type CapsuleOriginMarker = {\n originPath: string;\n createdAt: string;\n kind: CapsuleKind;\n};\n\nexport type PruneCapsulesOptions = {\n olderThanDays?: number;\n includeOrphans?: boolean;\n keepWorkspaceCaps?: boolean;\n sizeTargetGb?: number;\n dryRun?: boolean;\n /**\n * Compute byte sizes for every entry being considered. When false, all `sizeBytes`\n * in the report are 0 and the cache walk skips the expensive recursive `lstat` pass —\n * deletion (rename-to-trash) is O(1) and runs in milliseconds even on multi-GB caches.\n * Forced on when `sizeTargetGb` is set because that path needs sizes to enforce.\n */\n withSizes?: boolean;\n};\n\nexport type PruneCapsulesReport = {\n /** `originPath` is the workspace/scope a capsule was created for (from its marker), when known. */\n removed: { path: string; kind: CapsuleKind | 'unmarked'; reason: string; sizeBytes: number; originPath?: string }[];\n totalRemovedBytes: number;\n totalSizeBeforeBytes: number;\n totalSizeAfterBytes: number;\n dryRun: boolean;\n};\n\nexport type CapsuleRootEntry = {\n path: string;\n kind: CapsuleKind | 'unmarked';\n originPath?: string;\n lastUsedMs: number;\n sizeBytes: number;\n};\n\nfunction toFiniteNumber(value: unknown): number | undefined {\n if (value === undefined || value === null || value === '') return undefined;\n const n = Number(value);\n return Number.isFinite(n) ? n : undefined;\n}\n\nexport class CapsuleCache {\n constructor(\n private logger: Logger,\n private cli: CLIMain,\n private configStore: ConfigStoreMain,\n /** Thunk so the cache stays independent of `GlobalConfigMain` — IsolatorMain forwards it. */\n private getRootDir: () => string\n ) {}\n\n async deleteCapsules(rootDir?: string): Promise<string> {\n const dirToDelete = rootDir || this.getRootDir();\n const marker = await this.readOriginMarker(dirToDelete);\n this.logger.debug(\n `[capsule-delete] removing ${dirToDelete}` + (marker?.originPath ? ` origin=${marker.originPath}` : '')\n );\n await this.scheduleFastDelete(dirToDelete);\n return dirToDelete;\n }\n\n /**\n * Move a capsule dir into a sibling `.trash/<uuid>/` so it disappears from the cache\n * immediately (same-filesystem rename is O(1)), then kick off a detached `rm -rf` so the\n * actual byte-by-byte cleanup happens in the background. This avoids the multi-second\n * stalls users see when deleting capsules with thousands of files.\n */\n async scheduleFastDelete(dir: string): Promise<void> {\n const exists = await fs.pathExists(dir);\n if (!exists) return;\n const globalRoot = this.getRootDir();\n // Edge case: deleting the global root itself. We can't move a dir into its own\n // child (`.trash/...`), so just do a direct remove. This is rare — only `bit\n // capsule delete --all` hits it.\n if (path.resolve(dir) === path.resolve(globalRoot)) {\n await fs.remove(dir);\n return;\n }\n const trashRoot = path.join(globalRoot, CAPSULE_TRASH_DIR);\n await fs.ensureDir(trashRoot);\n const trashTarget = path.join(trashRoot, `${path.basename(dir)}-${v4()}`);\n try {\n await fs.move(dir, trashTarget, { overwrite: true });\n } catch (err: any) {\n // Likely cross-device — fall back to a synchronous remove.\n this.logger.debug(`scheduleFastDelete: rename failed for ${dir}, falling back to fs.remove (${err.message})`);\n await fs.remove(dir);\n return;\n }\n // Run through the gated sweepTrashAsync path so we never have more than one sweep\n // running concurrently — even if many bit processes are moving things to trash.\n this.sweepTrashAsync();\n }\n\n /**\n * Sweep the `.trash` dir in a detached background process. Gated by a PID-stamped\n * lock so we never have more than one sweep running at a time across all concurrent\n * bit processes — previously we spawned one per `bit` invocation and they piled up\n * into the thousands, saturating disk I/O.\n */\n sweepTrashAsync(): void {\n const trashRoot = path.join(this.getRootDir(), CAPSULE_TRASH_DIR);\n // No trash → nothing to do. Cheap synchronous check avoids spawning a process at all.\n if (!fs.existsSync(trashRoot)) return;\n const lockPath = path.join(this.getRootDir(), '.trash-sweep.lock');\n if (this.isSweepLockActive(lockPath)) {\n this.logger.debug(`trash sweep already running (per ${lockPath}), skipping`);\n return;\n }\n try {\n fs.writeFileSync(lockPath, String(process.pid), { flag: 'w' });\n } catch (err: any) {\n this.logger.debug(`failed to write sweep lock at ${lockPath}: ${err.message}`);\n return;\n }\n this.spawnDetachedSweep(trashRoot, lockPath);\n }\n\n /**\n * A sweep lock is \"active\" if the PID it names is still running. If the PID file\n * exists but the process is gone (e.g. crashed mid-sweep), we treat it as stale and\n * allow a new sweep to claim it.\n */\n private isSweepLockActive(lockPath: string): boolean {\n let pidStr: string;\n try {\n pidStr = fs.readFileSync(lockPath, 'utf8').trim();\n } catch {\n return false;\n }\n const pid = Number(pidStr);\n if (!Number.isFinite(pid) || pid <= 0) return false;\n try {\n // Signal 0 = \"is this PID alive?\" — no actual signal sent.\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Register a process-exit hook that, at most once per ~24h, spawns a detached\n * `bit capsule prune` child so the actual work runs out-of-process and never delays\n * the parent's exit. Gated by the mtime of a stamp file under the capsules root so\n * concurrent Bit invocations can't all trigger it at once, and behind the\n * `capsule-auto-prune` feature flag while the behavior is being validated.\n */\n registerAutoPruneHook(): void {\n this.cli.registerOnBeforeExit(async () => {\n try {\n await this.maybeAutoPrune();\n } catch (err: any) {\n this.logger.debug(`auto-prune skipped due to error: ${err?.message ?? err}`);\n }\n });\n }\n\n private async maybeAutoPrune(): Promise<void> {\n // Experimental: the automatic prune only runs for users who opt in via the feature flag\n // (`BIT_FEATURES=capsule-auto-prune` or `bit config set features=capsule-auto-prune`).\n // Until it's promoted to GA, the default behavior is unchanged — capsules are never\n // auto-deleted. The manual `bit capsule prune` command is always available regardless.\n if (!isFeatureEnabled(CAPSULE_AUTO_PRUNE)) return;\n\n // configStore may surface this as either string `'false'` (from `bit config set`)\n // or boolean `false` (from a hand-edited JSON config) — accept both. This is a\n // secondary escape hatch for once the feature is GA and the flag is removed.\n const enabled = this.configStore.getConfig(CFG_CAPSULES_AUTO_PRUNE);\n if (enabled === 'false' || (enabled as unknown) === false) return;\n\n const root = this.getRootDir();\n if (!(await fs.pathExists(root))) return;\n\n const stampPath = path.join(root, '.last-capsule-prune');\n const isStampFresh = async (): Promise<boolean> => {\n try {\n const stat = await fs.stat(stampPath);\n return Date.now() - stat.mtime.getTime() < ONE_DAY_MS;\n } catch {\n return false; // missing — needs a prune\n }\n };\n // Fast path: stamp is recent, nothing to do (no contention here).\n if (await isStampFresh()) return;\n\n // Atomic claim: only one process across all concurrent bit invocations may win the\n // daily slot. `wx` is O_CREAT|O_EXCL — it throws if the lock already exists, so the\n // check-and-write below can't race. The lock is held only for the few ms it takes to\n // re-check the stamp and spawn the detached child, then removed in `finally`.\n const claimPath = `${stampPath}.claim`;\n let claimed = false;\n try {\n await fs.close(await fs.open(claimPath, 'wx'));\n claimed = true;\n } catch {\n // Another process is mid-claim, or a previous run leaked the lock. If it's stale\n // (older than the daily window), reclaim it by removing + re-opening with O_EXCL —\n // if two processes race the reclaim, only one's `wx` open succeeds and the other\n // yields. Otherwise yield.\n try {\n const claimStat = await fs.stat(claimPath);\n if (Date.now() - claimStat.mtime.getTime() < ONE_DAY_MS) return;\n await fs.remove(claimPath);\n await fs.close(await fs.open(claimPath, 'wx'));\n claimed = true;\n } catch {\n return;\n }\n }\n try {\n // Re-check under the lock: a process that just held it may have refreshed the stamp.\n if (await isStampFresh()) return;\n await fs.outputFile(stampPath, '');\n\n // Guard against non-numeric/empty config (NaN) and negative values (which would\n // invert the age cutoff / size target and wipe the whole cache).\n const olderThanDays = Math.max(0, toFiniteNumber(this.configStore.getConfig(CFG_CAPSULES_MAX_AGE_DAYS)) ?? 30);\n const sizeTargetGb = Math.max(0, toFiniteNumber(this.configStore.getConfig(CFG_CAPSULES_MAX_SIZE_GB)) ?? 10);\n\n this.logger.debug(\n `[auto-prune] spawning detached child. olderThanDays=${olderThanDays}, sizeTargetGb=${sizeTargetGb}`\n );\n this.spawnDetachedAutoPrune(olderThanDays, sizeTargetGb);\n } finally {\n if (claimed) {\n try {\n await fs.remove(claimPath);\n } catch {\n // ignore — a stale claim lock is reclaimed by the age check above\n }\n }\n }\n }\n\n /**\n * Fire-and-forget: spawn a detached child running `bit capsule prune`. Using the same\n * bit binary that's currently running (via process.argv[0] + argv[1]) so we don't depend\n * on PATH. stdio is ignored so nothing leaks to the user's terminal.\n *\n * Recursion guard: the child also runs onBeforeExit → maybeAutoPrune, but it reads the\n * stamp file that we just wrote and bails out before re-spawning.\n */\n private spawnDetachedAutoPrune(olderThanDays: number, sizeTargetGb: number): void {\n const bitEntry = process.argv[1];\n if (!bitEntry) {\n this.logger.debug('[auto-prune] cannot detach: process.argv[1] is empty');\n return;\n }\n try {\n const child = spawn(\n process.execPath,\n [bitEntry, 'capsule', 'prune', '--older-than', String(olderThanDays), '--size-target', String(sizeTargetGb)],\n {\n detached: true,\n stdio: 'ignore',\n windowsHide: true,\n }\n );\n child.unref();\n } catch (err: any) {\n this.logger.debug(`[auto-prune] failed to spawn detached child: ${err.message}`);\n }\n }\n\n /**\n * Spawn one detached Node process that recursively removes `trashRoot`. Using\n * `process.execPath` with an inline `fs.rmSync` keeps this portable across macOS,\n * Linux, and Windows (where there's no `rm` binary). When `lockPath` is given, the\n * child clears the lock on exit so the next bit invocation can claim a fresh sweep slot.\n */\n private spawnDetachedSweep(trashRoot: string, lockPath?: string): void {\n const script = lockPath\n ? `try { require('fs').rmSync(${JSON.stringify(trashRoot)}, { recursive: true, force: true }); } finally { try { require('fs').rmSync(${JSON.stringify(lockPath)}, { force: true }); } catch (_) {} }`\n : `require('fs').rmSync(${JSON.stringify(trashRoot)}, { recursive: true, force: true })`;\n try {\n const child = spawn(process.execPath, ['-e', script], {\n detached: true,\n stdio: 'ignore',\n windowsHide: true,\n });\n child.unref();\n } catch (err: any) {\n this.logger.debug(`failed to spawn detached trash sweep: ${err.message}`);\n // Don't leak the lock if the spawn itself failed. Use fs-extra's removeSync\n // (rmSync isn't in the @types/fs-extra version pinned by this component).\n if (lockPath) {\n try {\n fs.removeSync(lockPath);\n } catch {\n // ignore\n }\n }\n }\n }\n\n /**\n * Write the origin marker if missing; otherwise just bump its mtime so it reflects\n * \"last used at\". Failures are non-fatal — markers are best-effort metadata.\n */\n async ensureOriginMarker(dir: string, kind: CapsuleKind, originPath: string): Promise<void> {\n const markerPath = path.join(dir, CAPSULE_ORIGIN_FILE);\n try {\n if (await fs.pathExists(markerPath)) {\n const now = new Date();\n await fs.utimes(markerPath, now, now);\n return;\n }\n const marker: CapsuleOriginMarker = {\n originPath,\n createdAt: new Date().toISOString(),\n kind,\n };\n await fs.outputJson(markerPath, marker);\n } catch (err: any) {\n this.logger.debug(`failed to write capsule origin marker at ${markerPath}: ${err.message}`);\n }\n }\n\n /**\n * Mark all per-component capsule subdirs as scope-aspect kind, originated from the\n * scope-aspects root. Used right after a scope-aspects isolation.\n */\n async ensureAspectCapsuleMarkers(capsuleList: CapsuleList, rootOriginPath: string): Promise<void> {\n await Promise.all(\n capsuleList.map(async (capsule) => {\n if (!fs.existsSync(capsule.path)) return;\n await this.ensureOriginMarker(capsule.path, 'scope-aspect', rootOriginPath);\n })\n );\n }\n\n /**\n * Single source of truth for the dated-capsules date-dir name (`YYYY-M-D`, no zero-pad).\n * Used by `getCapsulesRootDir` when writing and `pruneDatedCapsulesChildren` when reading,\n * so the two can never drift.\n */\n getDatedCapsuleDirName(date: Date = new Date()): string {\n return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;\n }\n\n /**\n * Standard filter for \"real\" capsule subdirs we may walk or prune. Skips files, the trash\n * dir (dot-prefixed), `node_modules`, and any other hidden/internal dir.\n */\n private isPrunableSubdir(entry: fs.Dirent): boolean {\n return entry.isDirectory() && entry.name !== 'node_modules' && !entry.name.startsWith('.');\n }\n\n /**\n * Combined marker read + last-used resolution for a capsule dir: one `readJson`, one\n * fallback `stat`. Replaces the three-syscall (`readMarker` + `getOriginMarkerMtime` +\n * dir `stat`) idiom that was copy-pasted across the prune walks.\n */\n private async readMarkerInfo(dir: string): Promise<{ marker?: CapsuleOriginMarker; lastUsedMs: number }> {\n const marker = await this.readOriginMarker(dir);\n if (marker) {\n const mtime = await this.getOriginMarkerMtime(dir);\n if (mtime) return { marker, lastUsedMs: mtime.getTime() };\n }\n const stat = await fs.stat(dir).catch(() => undefined);\n return { marker, lastUsedMs: (stat?.mtime ?? new Date(0)).getTime() };\n }\n\n private async readOriginMarker(dir: string): Promise<CapsuleOriginMarker | undefined> {\n try {\n const raw = await fs.readJson(path.join(dir, CAPSULE_ORIGIN_FILE));\n if (\n raw &&\n typeof raw.originPath === 'string' &&\n // Reject unknown kinds (corrupted markers or values from a future Bit) so they\n // fall through to the 'unmarked' path in pruneCapsules rather than silently\n // skipping deletion.\n VALID_CAPSULE_KINDS.has(raw.kind)\n ) {\n return raw as CapsuleOriginMarker;\n }\n } catch {\n // missing or malformed — treat as unmarked\n }\n return undefined;\n }\n\n private async getOriginMarkerMtime(dir: string): Promise<Date | undefined> {\n try {\n const stat = await fs.stat(path.join(dir, CAPSULE_ORIGIN_FILE));\n return stat.mtime;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Walk the global capsules root and return entries with their classification, size, and\n * last-used time. Used by prune and by `bit capsule list`.\n */\n async listAllCapsuleRoots(opts: { withSizes?: boolean } = {}): Promise<CapsuleRootEntry[]> {\n const withSizes = opts.withSizes !== false;\n const root = this.getRootDir();\n if (!(await fs.pathExists(root))) return [];\n const entries = await fs.readdir(root, { withFileTypes: true });\n const subdirs = entries.filter((e) => this.isPrunableSubdir(e));\n // Bounded concurrency: on a multi-GB cache with hundreds of subdirs and tens of\n // thousands of files per subdir, an unbounded Promise.all of recursive size walks\n // can hit OS file-descriptor limits (EMFILE) and thrash disk.\n return pMap(\n subdirs,\n async (entry) => {\n const subPath = path.join(root, entry.name);\n const { marker, lastUsedMs } = await this.readMarkerInfo(subPath);\n const sizeBytes = withSizes ? await this.computeDirSize(subPath) : 0;\n return {\n path: subPath,\n kind: (marker?.kind ?? 'unmarked') as CapsuleKind | 'unmarked',\n originPath: marker?.originPath,\n lastUsedMs,\n sizeBytes,\n };\n },\n { concurrency: concurrentIOLimit() }\n );\n }\n\n /**\n * Sum sizes of all entries under `dir`. Tolerant of symlinks and permission errors —\n * any failure returns the partial sum so we never throw from the prune path.\n * Uses bounded concurrency to avoid EMFILE on deep trees.\n */\n private async computeDirSize(dir: string): Promise<number> {\n let total = 0;\n const concurrency = concurrentIOLimit();\n const walk = async (current: string) => {\n let entries: fs.Dirent[];\n try {\n entries = await fs.readdir(current, { withFileTypes: true });\n } catch {\n return;\n }\n await pMap(\n entries,\n async (entry) => {\n const p = path.join(current, entry.name);\n if (entry.isDirectory()) {\n await walk(p);\n } else if (entry.isFile()) {\n try {\n const st = await fs.lstat(p);\n total += st.size;\n } catch {\n // ignore\n }\n }\n },\n { concurrency }\n );\n };\n await walk(dir);\n return total;\n }\n\n /**\n * Apply the prune rules from the plan:\n * - workspace caps: deleted unconditionally (unless keepWorkspaceCaps)\n * - scope-aspects-root: never deleted as a whole; per-aspect-version children pruned by age\n * - scope caps and unmarked dirs older than threshold: deleted\n * - orphans (marker says originPath gone): deleted\n * - after the above, if sizeTargetGb given and size still exceeds it, evict oldest-first\n */\n async pruneCapsules(opts: PruneCapsulesOptions = {}): Promise<PruneCapsulesReport> {\n // Clamp to >= 0: a negative age would put the cutoff in the future (everything looks\n // \"too old\" → whole cache deleted); a negative size target would force evicting\n // everything. Both are almost certainly user error, so floor them at 0.\n const olderThanDays = Math.max(0, opts.olderThanDays ?? 30);\n const sizeTargetGb = opts.sizeTargetGb === undefined ? undefined : Math.max(0, opts.sizeTargetGb);\n const includeOrphans = opts.includeOrphans !== false;\n const keepWorkspaceCaps = opts.keepWorkspaceCaps === true;\n const dryRun = opts.dryRun === true;\n // Size accounting requires an expensive recursive lstat across the whole cache. Skip\n // it by default so the foreground command returns in ms (deletes are O(1) renames);\n // force on for size-target enforcement and when the caller asks for byte accounting.\n const computeSizes = opts.withSizes === true || sizeTargetGb !== undefined;\n const ageCutoffMs = Date.now() - olderThanDays * ONE_DAY_MS;\n const datedDirName = this.configStore.getConfig(CFG_CAPSULES_SCOPES_ASPECTS_DATED_DIR) || 'dated-capsules';\n\n const roots = await this.listAllCapsuleRoots({ withSizes: computeSizes });\n const totalSizeBefore = computeSizes ? roots.reduce((sum, r) => sum + r.sizeBytes, 0) : 0;\n const removed: PruneCapsulesReport['removed'] = [];\n\n const removeEntry = (\n p: string,\n kind: CapsuleKind | 'unmarked',\n reason: string,\n sizeBytes: number,\n originPath?: string\n ) => this.recordRemoval(removed, { path: p, kind, reason, sizeBytes, originPath }, dryRun);\n\n for (const root of roots) {\n if (path.basename(root.path) === datedDirName) {\n await this.pruneDatedCapsulesChildren(root.path, dryRun, computeSizes, removed);\n continue;\n }\n if (root.kind === 'workspace') {\n if (keepWorkspaceCaps) continue;\n await removeEntry(root.path, root.kind, 'workspace-cap', root.sizeBytes, root.originPath);\n continue;\n }\n if (root.kind === 'scope' || root.kind === 'unmarked') {\n const orphan = includeOrphans && root.originPath && !(await fs.pathExists(root.originPath));\n const tooOld = root.lastUsedMs < ageCutoffMs;\n if (orphan) {\n await removeEntry(root.path, root.kind, 'orphan', root.sizeBytes, root.originPath);\n } else if (tooOld) {\n // For unmarked dirs, sniff content first to avoid nuking a legacy scope-aspects root.\n if (root.kind === 'unmarked' && (await this.looksLikeAspectsRoot(root.path))) {\n await this.pruneAspectsRootChildren(root.path, ageCutoffMs, dryRun, computeSizes, removed);\n } else {\n await removeEntry(root.path, root.kind, `older-than-${olderThanDays}d`, root.sizeBytes, root.originPath);\n }\n }\n continue;\n }\n if (root.kind === 'scope-aspects-root') {\n await this.pruneAspectsRootChildren(root.path, ageCutoffMs, dryRun, computeSizes, removed);\n continue;\n }\n }\n\n if (sizeTargetGb !== undefined) {\n await this.applySizeTarget(sizeTargetGb, removed, dryRun);\n }\n\n const totalRemovedBytes = removed.reduce((sum, r) => sum + r.sizeBytes, 0);\n // For dry-run, report the *projected* post-prune size so the CLI summary stays\n // internally consistent (cache: X → X − freed). Real prune subtracts the same.\n const totalSizeAfter = Math.max(0, totalSizeBefore - totalRemovedBytes);\n\n return {\n removed,\n totalRemovedBytes,\n totalSizeBeforeBytes: totalSizeBefore,\n totalSizeAfterBytes: totalSizeAfter,\n dryRun,\n };\n }\n\n /**\n * Record a removal in the prune report and, unless this is a dry run, actually delete it\n * (fast rename-to-trash). Keeps the \"report and delete are gated by the same dryRun flag\"\n * invariant in one place so the per-kind prune helpers can't drift apart.\n */\n private async recordRemoval(\n removed: PruneCapsulesReport['removed'],\n entry: PruneCapsulesReport['removed'][number],\n dryRun: boolean\n ): Promise<void> {\n removed.push(entry);\n this.logger.debug(\n `[capsule-prune] ${dryRun ? 'would remove' : 'removing'} [${entry.kind} · ${entry.reason}] ${entry.path}` +\n (entry.originPath ? ` origin=${entry.originPath}` : '')\n );\n if (!dryRun) await this.scheduleFastDelete(entry.path);\n }\n\n /**\n * The `dated-capsules` dir holds per-date subdirs (`YYYY-M-D`) of in-flight isolation\n * runs. These are recreated on every isolation, so anything that isn't *today*'s\n * subdir is leftover from a previous run and safe to delete. Today's subdir is\n * preserved to avoid racing a concurrent bit process that may still be writing to it.\n */\n private async pruneDatedCapsulesChildren(\n rootPath: string,\n dryRun: boolean,\n computeSizes: boolean,\n removed: PruneCapsulesReport['removed']\n ): Promise<void> {\n const todayDir = this.getDatedCapsuleDirName();\n let entries: fs.Dirent[];\n try {\n entries = await fs.readdir(rootPath, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n if (!this.isPrunableSubdir(entry)) continue;\n if (entry.name === todayDir) continue;\n const childPath = path.join(rootPath, entry.name);\n const sizeBytes = computeSizes ? await this.computeDirSize(childPath) : 0;\n await this.recordRemoval(\n removed,\n { path: childPath, kind: 'unmarked', reason: 'dated-capsules-not-today', sizeBytes },\n dryRun\n );\n }\n }\n\n /**\n * Legacy unmarked dirs may still be a scope-aspects root. Heuristic: a child subdir whose\n * name contains `@` (aspect-version pattern like `teambit.node_node@1.3.4`).\n */\n private async looksLikeAspectsRoot(dir: string): Promise<boolean> {\n try {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n return entries.some((e) => e.isDirectory() && e.name.includes('@'));\n } catch {\n return false;\n }\n }\n\n /**\n * Prune per-aspect-version children of a scope-aspects root purely by age (marker mtime,\n * which is touched on every aspect load).\n *\n * Note there's deliberately no orphan check here: a scope-aspect child's `originPath` is\n * the *logical* scope-aspects path (e.g. `<scope.path>-aspects`) used only to hash the\n * capsule root dir name — it need not exist as a real directory, so treating a missing\n * `originPath` as \"orphan\" would wrongly delete capsules of currently-used aspects.\n * Orphan pruning is still honored elsewhere for `workspace`/`scope` kinds.\n */\n private async pruneAspectsRootChildren(\n rootPath: string,\n ageCutoffMs: number,\n dryRun: boolean,\n computeSizes: boolean,\n removed: PruneCapsulesReport['removed']\n ): Promise<void> {\n let entries: fs.Dirent[];\n try {\n entries = await fs.readdir(rootPath, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n if (!this.isPrunableSubdir(entry)) continue;\n const childPath = path.join(rootPath, entry.name);\n const { marker, lastUsedMs } = await this.readMarkerInfo(childPath);\n if (lastUsedMs < ageCutoffMs) {\n const sizeBytes = computeSizes ? await this.computeDirSize(childPath) : 0;\n await this.recordRemoval(\n removed,\n {\n path: childPath,\n kind: 'scope-aspect',\n reason: 'aspect-older-than-cutoff',\n sizeBytes,\n originPath: marker?.originPath,\n },\n dryRun\n );\n }\n }\n }\n\n /**\n * After the standard prune, if total still exceeds the target, keep evicting the\n * oldest remaining aspect-version subdirs until under the limit.\n */\n private async applySizeTarget(\n sizeTargetGb: number,\n removed: PruneCapsulesReport['removed'],\n dryRun: boolean\n ): Promise<void> {\n const targetBytes = sizeTargetGb * 1024 * 1024 * 1024;\n const removedPaths = new Set(removed.map((r) => r.path));\n // Re-walk what's left (one pass, with sizes) to find both the current total and the\n // oldest aspect-version children to evict.\n const roots = await this.listAllCapsuleRoots();\n const totalBytes = roots.reduce((sum, r) => sum + r.sizeBytes, 0);\n const aspectChildren: Array<{ path: string; lastUsedMs: number; sizeBytes: number; originPath?: string }> = [];\n for (const root of roots) {\n if (\n root.kind !== 'scope-aspects-root' &&\n !(root.kind === 'unmarked' && (await this.looksLikeAspectsRoot(root.path)))\n ) {\n continue;\n }\n let entries: fs.Dirent[] = [];\n try {\n entries = await fs.readdir(root.path, { withFileTypes: true });\n } catch {\n continue;\n }\n for (const entry of entries) {\n if (!this.isPrunableSubdir(entry)) continue;\n const childPath = path.join(root.path, entry.name);\n if (removedPaths.has(childPath)) continue;\n const { marker, lastUsedMs } = await this.readMarkerInfo(childPath);\n const sizeBytes = await this.computeDirSize(childPath);\n aspectChildren.push({ path: childPath, lastUsedMs, sizeBytes, originPath: marker?.originPath });\n }\n }\n aspectChildren.sort((a, b) => a.lastUsedMs - b.lastUsedMs);\n // In dry-run the standard-prune entries are still on disk (counted in totalBytes), so\n // subtract them; in a real run they were already moved to trash and excluded from the walk.\n let remainingBytes = totalBytes - (dryRun ? removed.reduce((s, r) => s + r.sizeBytes, 0) : 0);\n for (const child of aspectChildren) {\n if (remainingBytes <= targetBytes) break;\n await this.recordRemoval(\n removed,\n {\n path: child.path,\n kind: 'scope-aspect',\n reason: `size-target-${sizeTargetGb}gb`,\n sizeBytes: child.sizeBytes,\n originPath: child.originPath,\n },\n dryRun\n );\n remainingBytes -= child.sizeBytes;\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export { CAPSULE_READY_FILE } from './isolator.main.runtime';
2
+ export { CAPSULE_ORIGIN_FILE, CAPSULE_TRASH_DIR } from './capsule-cache';
2
3
  export { Network } from './network';
3
4
  export { FsContainer, Capsule, ContainerExec } from './capsule';
4
5
  export type { IsolatorMain, IsolateComponentsOptions } from './isolator.main.runtime';
6
+ export type { CapsuleKind, CapsuleOriginMarker, PruneCapsulesOptions, PruneCapsulesReport } from './capsule-cache';
5
7
  export { IsolatorAspect } from './isolator.aspect';
6
8
  export { default as CapsuleList } from './capsule-list';
package/dist/index.js CHANGED
@@ -3,12 +3,24 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ Object.defineProperty(exports, "CAPSULE_ORIGIN_FILE", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _capsuleCache().CAPSULE_ORIGIN_FILE;
10
+ }
11
+ });
6
12
  Object.defineProperty(exports, "CAPSULE_READY_FILE", {
7
13
  enumerable: true,
8
14
  get: function () {
9
15
  return _isolatorMain().CAPSULE_READY_FILE;
10
16
  }
11
17
  });
18
+ Object.defineProperty(exports, "CAPSULE_TRASH_DIR", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _capsuleCache().CAPSULE_TRASH_DIR;
22
+ }
23
+ });
12
24
  Object.defineProperty(exports, "Capsule", {
13
25
  enumerable: true,
14
26
  get: function () {
@@ -52,6 +64,13 @@ function _isolatorMain() {
52
64
  };
53
65
  return data;
54
66
  }
67
+ function _capsuleCache() {
68
+ const data = require("./capsule-cache");
69
+ _capsuleCache = function () {
70
+ return data;
71
+ };
72
+ return data;
73
+ }
55
74
  function _network() {
56
75
  const data = require("./network");
57
76
  _network = function () {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"names":["_isolatorMain","data","require","_network","_capsule","_isolator","_capsuleList","_interopRequireDefault","e","__esModule","default"],"sources":["index.ts"],"sourcesContent":["export { CAPSULE_READY_FILE } from './isolator.main.runtime';\nexport { Network } from './network';\nexport { FsContainer, Capsule, ContainerExec } from './capsule';\nexport type { IsolatorMain, IsolateComponentsOptions } from './isolator.main.runtime';\nexport { IsolatorAspect } from './isolator.aspect';\nexport { default as CapsuleList } from './capsule-list';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAAA,cAAA;EAAA,MAAAC,IAAA,GAAAC,OAAA;EAAAF,aAAA,YAAAA,CAAA;IAAA,OAAAC,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AACA,SAAAE,SAAA;EAAA,MAAAF,IAAA,GAAAC,OAAA;EAAAC,QAAA,YAAAA,CAAA;IAAA,OAAAF,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AACA,SAAAG,SAAA;EAAA,MAAAH,IAAA,GAAAC,OAAA;EAAAE,QAAA,YAAAA,CAAA;IAAA,OAAAH,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAEA,SAAAI,UAAA;EAAA,MAAAJ,IAAA,GAAAC,OAAA;EAAAG,SAAA,YAAAA,CAAA;IAAA,OAAAJ,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AACA,SAAAK,aAAA;EAAA,MAAAL,IAAA,GAAAM,sBAAA,CAAAL,OAAA;EAAAI,YAAA,YAAAA,CAAA;IAAA,OAAAL,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAAwD,SAAAM,uBAAAC,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA","ignoreList":[]}
1
+ {"version":3,"names":["_isolatorMain","data","require","_capsuleCache","_network","_capsule","_isolator","_capsuleList","_interopRequireDefault","e","__esModule","default"],"sources":["index.ts"],"sourcesContent":["export { CAPSULE_READY_FILE } from './isolator.main.runtime';\nexport { CAPSULE_ORIGIN_FILE, CAPSULE_TRASH_DIR } from './capsule-cache';\nexport { Network } from './network';\nexport { FsContainer, Capsule, ContainerExec } from './capsule';\nexport type { IsolatorMain, IsolateComponentsOptions } from './isolator.main.runtime';\nexport type { CapsuleKind, CapsuleOriginMarker, PruneCapsulesOptions, PruneCapsulesReport } from './capsule-cache';\nexport { IsolatorAspect } from './isolator.aspect';\nexport { default as CapsuleList } from './capsule-list';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAAA,cAAA;EAAA,MAAAC,IAAA,GAAAC,OAAA;EAAAF,aAAA,YAAAA,CAAA;IAAA,OAAAC,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AACA,SAAAE,cAAA;EAAA,MAAAF,IAAA,GAAAC,OAAA;EAAAC,aAAA,YAAAA,CAAA;IAAA,OAAAF,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AACA,SAAAG,SAAA;EAAA,MAAAH,IAAA,GAAAC,OAAA;EAAAE,QAAA,YAAAA,CAAA;IAAA,OAAAH,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AACA,SAAAI,SAAA;EAAA,MAAAJ,IAAA,GAAAC,OAAA;EAAAG,QAAA,YAAAA,CAAA;IAAA,OAAAJ,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAGA,SAAAK,UAAA;EAAA,MAAAL,IAAA,GAAAC,OAAA;EAAAI,SAAA,YAAAA,CAAA;IAAA,OAAAL,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AACA,SAAAM,aAAA;EAAA,MAAAN,IAAA,GAAAO,sBAAA,CAAAN,OAAA;EAAAK,YAAA,YAAAA,CAAA;IAAA,OAAAN,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAAwD,SAAAO,uBAAAC,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA","ignoreList":[]}
@@ -1 +1,2 @@
1
- export declare const Logo: () => import("react/jsx-runtime").JSX.Element;
1
+ import React from 'react';
2
+ export declare const Logo: () => React.JSX.Element;
@@ -10,6 +10,7 @@ import type { Scope as LegacyScope } from '@teambit/legacy.scope';
10
10
  import type { GlobalConfigMain } from '@teambit/global-config';
11
11
  import type { PathOsBasedAbsolute } from '@teambit/legacy.utils';
12
12
  import { Capsule } from './capsule';
13
+ import type { PruneCapsulesOptions, PruneCapsulesReport } from './capsule-cache';
13
14
  import { Network } from './network';
14
15
  import type { ConfigStoreMain } from '@teambit/config-store';
15
16
  export type ListResults = {
@@ -196,6 +197,7 @@ export declare class IsolatorMain {
196
197
  CLIMain,
197
198
  ConfigStoreMain
198
199
  ], _config: any, [capsuleTransferSlot]: [CapsuleTransferSlot]): Promise<IsolatorMain>;
200
+ private cache;
199
201
  constructor(dependencyResolver: DependencyResolverMain, logger: Logger, componentAspect: ComponentMain, graph: GraphMain, cli: CLIMain, globalConfig: GlobalConfigMain, aspectLoader: AspectLoaderMain, capsuleTransferSlot: CapsuleTransferSlot, configStore: ConfigStoreMain);
200
202
  isolateComponents(seeders: ComponentID[], opts: IsolateComponentsOptions, legacyScope?: LegacyScope): Promise<Network>;
201
203
  private createGraph;
@@ -265,9 +267,23 @@ export declare class IsolatorMain {
265
267
  getCapsulesRootDir(baseDir: string, rootBaseDir?: string, useHash?: boolean): PathOsBasedAbsolute;
266
268
  getCapsulesRootDir(getCapsuleDirOpts: GetCapsuleDirOpts): PathOsBasedAbsolute;
267
269
  deleteCapsules(rootDir?: string): Promise<string>;
270
+ pruneCapsules(opts?: PruneCapsulesOptions): Promise<PruneCapsulesReport>;
271
+ listAllCapsuleRoots(opts?: {
272
+ withSizes?: boolean;
273
+ }): Promise<import("./capsule-cache").CapsuleRootEntry[]>;
274
+ registerAutoPruneHook(): void;
275
+ sweepTrashAsync(): void;
268
276
  private writeRootPackageJson;
269
277
  private createCapsulesFromComponents;
270
278
  private getRootDirOfAllCapsules;
279
+ /**
280
+ * Derive the capsule kind from the isolation context. Aspect resolution sets
281
+ * `opts.context.aspects = true`. Otherwise, distinguish bare-scope isolations
282
+ * (host is ScopeMain) from workspace isolations (host is Workspace) by duck-typing
283
+ * on `bitMap`, which only Workspace exposes — this avoids a circular dep on the
284
+ * workspace aspect.
285
+ */
286
+ private deriveCapsuleKind;
271
287
  private wereDependenciesInPackageJsonChanged;
272
288
  private getCapsulesPreviousPackageJson;
273
289
  private updateWithCurrentPackageJsonData;
@@ -207,6 +207,13 @@ function _capsuleList() {
207
207
  };
208
208
  return data;
209
209
  }
210
+ function _capsuleCache() {
211
+ const data = require("./capsule-cache");
212
+ _capsuleCache = function () {
213
+ return data;
214
+ };
215
+ return data;
216
+ }
210
217
  function _isolator() {
211
218
  const data = require("./isolator.aspect");
212
219
  _isolator = function () {
@@ -271,6 +278,8 @@ class IsolatorMain {
271
278
  static async provider([dependencyResolver, loggerExtension, componentAspect, graphMain, globalConfig, aspectLoader, cli, configStore], _config, [capsuleTransferSlot]) {
272
279
  const logger = loggerExtension.createLogger(_isolator().IsolatorAspect.id);
273
280
  const isolator = new IsolatorMain(dependencyResolver, logger, componentAspect, graphMain, cli, globalConfig, aspectLoader, capsuleTransferSlot, configStore);
281
+ isolator.registerAutoPruneHook();
282
+ isolator.sweepTrashAsync();
274
283
  return isolator;
275
284
  }
276
285
  constructor(dependencyResolver, logger, componentAspect, graph, cli, globalConfig, aspectLoader, capsuleTransferSlot, configStore) {
@@ -288,6 +297,8 @@ class IsolatorMain {
288
297
  _defineProperty(this, "_datedHashForName", new Map());
289
298
  // cache dated hash for a specific name
290
299
  _defineProperty(this, "_movedLockFiles", new Set());
300
+ _defineProperty(this, "cache", void 0);
301
+ this.cache = new (_capsuleCache().CapsuleCache)(logger, cli, configStore, () => this.getRootDirOfAllCapsules());
291
302
  }
292
303
 
293
304
  // TODO: the legacy scope used for the component writer, which then decide if it need to write the artifacts and dists
@@ -577,9 +588,15 @@ class IsolatorMain {
577
588
  }
578
589
  let capsules = await this.createCapsulesFromComponents(components, capsulesDir, config);
579
590
  this.writeRootPackageJson(capsulesDir, this.getCapsuleDirHash(opts.baseDir || ''));
591
+ const rootKind = this.deriveCapsuleKind(opts);
592
+ const rootOriginPath = opts.baseDir || '';
593
+ await this.cache.ensureOriginMarker(capsulesDir, rootKind, rootOriginPath);
580
594
  const allCapsuleList = _capsuleList().default.fromArray(capsules);
581
595
  let capsuleList = allCapsuleList;
582
596
  if (opts.getExistingAsIs) {
597
+ if (rootKind === 'scope-aspects-root') {
598
+ await this.cache.ensureAspectCapsuleMarkers(allCapsuleList, rootOriginPath);
599
+ }
583
600
  longProcessLogger?.end();
584
601
  return capsuleList;
585
602
  }
@@ -587,6 +604,9 @@ class IsolatorMain {
587
604
  if (!installOptions.useNesting) {
588
605
  const existingCapsules = _capsuleList().default.fromArray(capsuleList.filter(capsule => capsule.fs.existsSync('package.json')));
589
606
  if (existingCapsules.length === capsuleList.length) {
607
+ if (rootKind === 'scope-aspects-root') {
608
+ await this.cache.ensureAspectCapsuleMarkers(existingCapsules, rootOriginPath);
609
+ }
590
610
  longProcessLogger?.end();
591
611
  return existingCapsules;
592
612
  }
@@ -673,6 +693,9 @@ class IsolatorMain {
673
693
  });
674
694
  }
675
695
  await this.markCapsulesAsReady(capsuleList);
696
+ if (rootKind === 'scope-aspects-root') {
697
+ await this.cache.ensureAspectCapsuleMarkers(allCapsuleList, rootOriginPath);
698
+ }
676
699
  if (longProcessLogger) {
677
700
  longProcessLogger.end();
678
701
  }
@@ -922,9 +945,7 @@ class IsolatorMain {
922
945
  }, getCapsuleDirOpts);
923
946
  const capsulesRootBaseDir = getCapsuleDirOptsWithDefaults.rootBaseDir || this.getRootDirOfAllCapsules();
924
947
  if (getCapsuleDirOptsWithDefaults.useDatedDirs) {
925
- const date = new Date();
926
- const month = date.getMonth() < 12 ? date.getMonth() + 1 : 1;
927
- const dateDir = `${date.getFullYear()}-${month}-${date.getDate()}`;
948
+ const dateDir = this.cache.getDatedCapsuleDirName();
928
949
  const defaultDatedBaseDir = 'dated-capsules';
929
950
  const datedBaseDir = this.configStore.getConfig(_legacy().CFG_CAPSULES_SCOPES_ASPECTS_DATED_DIR) || defaultDatedBaseDir;
930
951
  let hashDir;
@@ -943,10 +964,26 @@ class IsolatorMain {
943
964
  const dir = getCapsuleDirOptsWithDefaults.useHash ? this.getCapsuleDirHash(getCapsuleDirOptsWithDefaults.baseDir) : getCapsuleDirOptsWithDefaults.baseDir;
944
965
  return _path().default.join(capsulesRootBaseDir, dir);
945
966
  }
967
+
968
+ // --- Capsule-cache delegates ---------------------------------------------------------
969
+ // The actual cache management (origin markers, fast-delete + trash sweep, prune
970
+ // pipeline, auto-prune trigger) lives in `CapsuleCache`. These thin forwarders keep
971
+ // the externally-used isolator API stable.
972
+
946
973
  async deleteCapsules(rootDir) {
947
- const dirToDelete = rootDir || this.getRootDirOfAllCapsules();
948
- await _fsExtra().default.remove(dirToDelete);
949
- return dirToDelete;
974
+ return this.cache.deleteCapsules(rootDir);
975
+ }
976
+ async pruneCapsules(opts = {}) {
977
+ return this.cache.pruneCapsules(opts);
978
+ }
979
+ async listAllCapsuleRoots(opts = {}) {
980
+ return this.cache.listAllCapsuleRoots(opts);
981
+ }
982
+ registerAutoPruneHook() {
983
+ this.cache.registerAutoPruneHook();
984
+ }
985
+ sweepTrashAsync() {
986
+ this.cache.sweepTrashAsync();
950
987
  }
951
988
  writeRootPackageJson(capsulesDir, hashDir) {
952
989
  const rootPackageJson = _path().default.join(capsulesDir, 'package.json');
@@ -970,6 +1007,20 @@ class IsolatorMain {
970
1007
  getRootDirOfAllCapsules() {
971
1008
  return this.globalConfig.getGlobalCapsulesBaseDir();
972
1009
  }
1010
+
1011
+ /**
1012
+ * Derive the capsule kind from the isolation context. Aspect resolution sets
1013
+ * `opts.context.aspects = true`. Otherwise, distinguish bare-scope isolations
1014
+ * (host is ScopeMain) from workspace isolations (host is Workspace) by duck-typing
1015
+ * on `bitMap`, which only Workspace exposes — this avoids a circular dep on the
1016
+ * workspace aspect.
1017
+ */
1018
+ deriveCapsuleKind(opts) {
1019
+ if (opts.context?.aspects) return 'scope-aspects-root';
1020
+ const host = opts.host || this.componentAspect.getHost();
1021
+ if (host && !('bitMap' in host)) return 'scope';
1022
+ return 'workspace';
1023
+ }
973
1024
  wereDependenciesInPackageJsonChanged(capsuleWithPackageData) {
974
1025
  const {
975
1026
  previousPackageJson,