Zoltan Kochan 2f64c727ea feat(executor): swallow optional-dep build failures and report via pnpm:skipped-optional-dependency (#397) (#419)
## Summary

Closes item #6 of #397. Optional dependencies whose `postinstall`
hooks fail no longer abort the install — pacquet now reports the
failure through the `pnpm:skipped-optional-dependency` channel
(reason `build_failure`) and continues, matching
[pnpm v11's behavior at `building/during-install/src/index.ts:218-240`](https://github.com/pnpm/pnpm/blob/b4f8f47ac2/building/during-install/src/index.ts#L218-L240).

Three commits:

- **`feat(lockfile): surface snapshot-level optional flag`** —
  pacquet's lockfile reader previously dropped the
  `snapshots[<key>].optional` field. Adding it as `pub optional: bool`
  on `SnapshotEntry` with `#[serde(default, skip_serializing_if = "is_false")]`
  so absent ↔ false and `false` never serializes. The flag is
  pre-computed by pnpm's resolver at install time (ALL-paths-
  optional fold), so pacquet trusts the precomputed value rather
  than re-deriving it — matching [`lockfileToDepGraph` at deps/graph-builder/src/lockfileToDepGraph.ts:315](https://github.com/pnpm/pnpm/blob/b4f8f47ac2/deps/graph-builder/src/lockfileToDepGraph.ts#L315).
- **`feat(reporter): add pnpm:skipped-optional-dependency event`** —
  new `LogEvent::SkippedOptionalDependency(SkippedOptionalDependencyLog)`
  variant + `SkippedOptionalPackage` + `SkippedOptionalReason` enum.
  Wire shape mirrors [pnpm's `SkippedOptionalDependencyMessage`](https://github.com/pnpm/pnpm/blob/b4f8f47ac2/core/core-loggers/src/skippedOptionalDependencyLogger.ts).
  All four upstream reasons (`BuildFailure`, `UnsupportedEngine`,
  `UnsupportedPlatform`, `ResolutionFailure`) are declared even
  though only `BuildFailure` is emitted today — keeps the enum
  closed so the other emit sites can land without widening it.
- **`feat(package-manager): swallow optional-dep build failures`** —
  `BuildModules.run` reads `snapshot.optional`. When
  `run_postinstall_hooks` returns an `Err`, the dep's optional
  flag decides: optional ⇒ emit a `pnpm:skipped-optional-dependency`
  event (`reason: build_failure`, `package.id` = the dep's pkg dir
  to match upstream's `depNode.dir`) and continue; non-optional ⇒
  propagate as `BuildModulesError::LifecycleScript` so the install
  aborts. Two `cfg(unix)`-gated tests cover both branches.
2026-05-12 12:59:04 +02:00
Description
No description provided
MIT 280 MiB
Languages
Rust 56.5%
TypeScript 43%
JavaScript 0.4%