diff --git a/tooling/check-repository.mjs b/tooling/check-repository.mjs index bcd1271..4e11513 100644 --- a/tooling/check-repository.mjs +++ b/tooling/check-repository.mjs @@ -139,6 +139,7 @@ export async function checkRepository(repositoryRoot = defaultRoot, options = {} for (const loaderPath of nativeLoaderLockPaths) { const loader = rootLock.packages[loaderPath]; if (!loader) continue; + let nativeBindingCount = 0; for (const [packageName, version] of Object.entries( loader.optionalDependencies ?? {}, )) { @@ -151,7 +152,8 @@ export async function checkRepository(repositoryRoot = defaultRoot, options = {} const rootPath = `node_modules/${packageName}`; const dependencyPath = rootLock.packages[nestedPath] ? nestedPath : rootPath; const dependency = rootLock.packages[dependencyPath]; - assert(dependency, `${loaderPath}: native binding missing: ${packageName}`); + if (!dependency) continue; + nativeBindingCount += 1; assert( dependency.version === version, `${loaderPath}: native binding version drift: ${packageName}`, @@ -161,6 +163,7 @@ export async function checkRepository(repositoryRoot = defaultRoot, options = {} `${loaderPath}: native binding provenance missing: ${packageName}`, ); } + assert(nativeBindingCount > 0, `${loaderPath}: native bindings missing`); } assert( !(await stat(resolve(root, "plugins/design-loop")).catch(() => null)), diff --git a/tooling/scaffold-smoke.mjs b/tooling/scaffold-smoke.mjs index 9706318..5c1f60b 100644 --- a/tooling/scaffold-smoke.mjs +++ b/tooling/scaffold-smoke.mjs @@ -308,6 +308,31 @@ try { expectedScreenshot: screenshot, }); await checkRepository(fixtureRoot); + + const fixtureLockPath = resolve(fixtureRoot, "package-lock.json"); + const fixtureLockRaw = await readFile(fixtureLockPath, "utf8"); + const fixtureLock = JSON.parse(fixtureLockRaw); + const rolldownPath = "node_modules/rolldown"; + const rolldownBindings = Object.keys( + fixtureLock.packages[rolldownPath]?.optionalDependencies ?? {}, + ).filter((packageName) => fixtureLock.packages[`node_modules/${packageName}`]); + assert.ok( + rolldownBindings.length > 1, + "fixture must install multiple Rolldown binding lock entries", + ); + delete fixtureLock.packages[`node_modules/${rolldownBindings[0]}`]; + await writeFile(fixtureLockPath, `${JSON.stringify(fixtureLock, null, 2)}\n`); + await checkRepository(fixtureRoot); + + for (const packageName of rolldownBindings.slice(1)) { + delete fixtureLock.packages[`node_modules/${packageName}`]; + } + await writeFile(fixtureLockPath, `${JSON.stringify(fixtureLock, null, 2)}\n`); + await assert.rejects( + checkRepository(fixtureRoot), + /node_modules\/rolldown: native bindings missing/, + ); + await writeFile(fixtureLockPath, fixtureLockRaw); console.log("plugin scaffold smoke test passed after clean npm ci"); } finally { await rm(fixtureRoot, { recursive: true, force: true });