QVAC-18679 feat[api]: wire qvac verify bundle into Expo plugin#2000
Draft
opaninakuffo wants to merge 6 commits into
Draft
QVAC-18679 feat[api]: wire qvac verify bundle into Expo plugin#2000opaninakuffo wants to merge 6 commits into
opaninakuffo wants to merge 6 commits into
Conversation
Move src/verify-deps/ to src/verify/deps/ so the directory layout mirrors the CLI surface (qvac verify <subcommand>) and future verify subcommands (bundle, ...) land in a shared parent. No behavior change: rename + import-path updates only.
Replace `key.indexOf(marker)` with `match.index` so each regex match maps to its actual package root. Previously, a resolution key with the same package name appearing twice (e.g. `node_modules/foo/node_modules/bar/node_modules/foo/index.js`) collapsed the nested `foo` back to the top-level path. Also exports `buildNestedPathIndex` so it can be reused by the upcoming `qvac verify bundle` command. Adds regression tests covering single, nested, and repeated-name resolution keys.
…cation New `qvac verify bundle` subcommand under `qvac verify`. Validates the actual artifacts (prebuilds + ABI compatibility) of a worker bundle or installed node_modules tree before shipping. Accepts a `worker.bundle.js` (bare-pack tree-shaken output) or a `node_modules` directory via `--addons-source`; source kind is auto-detected. Per addon per `--host`: - prebuild presence: `<packageRoot>/prebuilds/<host>/*.bare` - ABI compatibility: addon's `engines.bare` must satisfy the resolved Bare runtime version. Resolution order: `--bare-runtime-version` flag -> `bare-runtime/package.json` -> `bare/package.json`. Mobile/Expo CI should pass `--bare-runtime-version` explicitly; `react-native-bare-kit` does not currently expose embedded runtime metadata. Structured issue codes for CI consumption: - error: `missing-prebuild`, `abi-mismatch`, `invalid-runtime-version`, `invalid-source` - warning: `unknown-runtime-version`, `malformed-engines-bare` Exit 1 on any error-level issue, 0 otherwise. Tests: unit + Bats smoke for both source kinds, prebuild/ABI checks, runtime auto-resolution, malformed-engines-bare warning path (surfaced even when runtime is unknown), and regression coverage for nested-only bundle resolutions and multi-instance retention. Validated end-to-end against qvac-app-workbench-mobile: 33 addons in a 10MB worker.bundle.js across 5 hosts; 45 addons in node_modules with 2 legitimate prebuild gaps surfaced; bare-os@3.6.2 (top-level) and bare-os@3.9.0 (nested under @qvac/tts-onnx) correctly distinguished. Adds `semver` as a runtime dependency.
Adds `--config <path>` and auto-detection of `qvac.config.{json,js,mjs,ts}`
so projects can pin the Bare runtime in a committed file (works in any
runtime, including the future Pear pre-hook where env vars don't).
Resolution: `--bare-runtime-version` > config `bareRuntimeVersion` >
`bare-runtime/package.json` > `bare/package.json`. Both flag and config
values share the same semver validation; malformed values emit
`invalid-runtime-version` carrying `source: 'flag' | 'config'`, with the
config file's actual path in the message. Explicit `--config` to a
missing/unreadable file emits `invalid-source`; auto-detect failures and
non-string config values fall through silently.
Tests: 7 unit + 1 bats covering auto-detect, explicit `--config`, flag
precedence, malformed/non-string config values, and config-path label in
error messages.
Expo plugin now invokes `qvac verify bundle` after generating the mobile
worker bundle. The build flow is `runBundler → assert bundle exists →
runVerifier → fs.copyFileSync` so `dist/worker.mobile.bundle.js` only
updates when verification passes.
`resolveCliCommand` requires a local `@qvac/cli` install — the previous
`npx --package=@qvac/cli qvac` fallback is removed (throws
`CliNotFoundInNodeModulesError`, code 50608). Non-zero verifier exit is
wrapped in `BundleVerificationFailedError` (50609).
The discovered `qvac.config.{json,js,mjs}` path is now forwarded to the
CLI as `--config <path>`, so `bareRuntimeVersion` pins ABI checks
deterministically. Without a config the CLI auto-detects Bare runtime
from `node_modules` (`bare-runtime` → `bare`); ABI checks stay strict on
auto-detect and only fall through to `unknown-runtime-version` (warning)
when neither is installed.
Pear wiring is intentionally deferred — `pear/pre.ts` carries a head-note
that consumers should run `qvac verify bundle` manually before
`pear stage` / `pear run`.
`MOBILE_HOSTS`, `buildVerifyBundleCommand`, and `resolveCliCommand` are
exported for unit testing; the plugin's default export is unchanged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🎯 What problem does this PR solve?
qvac verify bundleas a standalone CLI; without auto-wiring, Expo consumers can still ship aworker.mobile.bundle.jsmissing prebuilds or with an ABI-incompatibleengines.bare.npx --package=@qvac/cli qvacwhen the CLI was missing — risking a different CLI version than the consumer pinned.📝 How does it solve it?
npxfallback —resolveCliCommandthrowsCliNotFoundInNodeModulesError(50608) whennode_modules/@qvac/cli/dist/index.jsis missing. Consumers must declare@qvac/clias a dep.runBundler → assert bundle exists → runVerifier → fs.copyFileSync. The SDKdist/worker.mobile.bundle.jsonly updates when verification passes; failure preserves the last known-good artifact and fails Expo prebuild fast.runVerifierinvokesqvac verify bundle --addons-source <bundle> --host <h>...for everyMOBILE_HOSTSentry. Non-zero exit →BundleVerificationFailedError(50609).qvac.config.*— the plugin already discoversqvac.config.{json,js,mjs}forbundle sdkand now forwards the same path as--config <path>toverify bundle(PR 2 capability). With config, ABI checks are pinned tobareRuntimeVersion. Without config, the CLI auto-detects fromnode_modules(bare-runtime→bare); ABI checks stay strict on auto-detect, and only fall through tounknown-runtime-version(warning) when neither is installed. Prebuild-presence checks always run.Pear deferral:
pear/pre.tscarries a head-note thatqvac verify bundleisn't wired there yet — Pear consumers should run it manually (locally and/or in CI) beforepear stage/pear run.🔌 API Changes
CLI_NOT_FOUND_IN_NODE_MODULES(50608) →CliNotFoundInNodeModulesErrorBUNDLE_VERIFICATION_FAILED(50609) →BundleVerificationFailedErrorwithMobileBundlethrowsCliNotFoundInNodeModulesErrorinstead of silently usingnpx. Consumers must add@qvac/cli(≥0.3.0) to their (dev)dependencies.bareRuntimeVersion: stringinqvac.config.{json,js,mjs,ts}(read by the CLI via--config; no new SDK API).🧪 How was it tested?
test/unit/with-mobile-bundle.test.ts, 9 tests):MOBILE_HOSTSmatches the canonical mobile host set.buildVerifyBundleCommand: emits one--hostper host; omits--config(and asserts no stray--bare-runtime-version— regression guard for the removed env-var path); includes--config "<path>"when provided; quotes config paths with spaces; quotes the bundle path; invokes theverify bundlesubcommand.resolveCliCommand: returnsnode "<absPath>"against a realmkdtempfs fixture; throwsCliNotFoundInNodeModulesErrorwhen the CLI is absent.test:unit: green; no regressions.Manual smoke —
qvac-app-workbench-mobileLocally packed cli and sdk packages, installed as
file:deps, thennpm run prebuild:android(4MOBILE_HOSTS, 33 addons,bare-runtime@1.26.0innode_modules):qvac.config.jsonbare-runtime@1.26.0; 33 addons verified; dist copiedbareRuntimeVersion: "1.26.0"bareRuntimeVersion: "0.0.1"BundleVerificationFailedError(50609); dist NOT updated (last known-good preserved)Scenario 3's stack confirmed
runVerifierforwards--config:Manual smoke — Pear head-note workflow
Validated:
pear/pre.js.qvac verify bundle --addons-source <bundle> --host darwin-arm64 --config qvac.config.json) works end-to-end: invalid runtime → 24 ABI errors / exit 1; valid runtime → 33 addons verified / exit 0.