@qvac/sdk 0.11.0 → 0.12.1

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.
Files changed (211) hide show
  1. package/NOTICE +1423 -43
  2. package/README.md +2 -0
  3. package/dist/client/api/classify.d.ts +23 -0
  4. package/dist/client/api/classify.js +43 -0
  5. package/dist/client/api/get-model-info.d.ts +1 -1
  6. package/dist/client/api/index.d.ts +4 -0
  7. package/dist/client/api/index.js +4 -0
  8. package/dist/client/api/load-model.js +24 -1
  9. package/dist/client/api/transcribe.d.ts +3 -0
  10. package/dist/client/api/transcribe.js +13 -2
  11. package/dist/client/api/video.d.ts +64 -0
  12. package/dist/client/api/video.js +147 -0
  13. package/dist/client/api/vla-helpers.d.ts +45 -0
  14. package/dist/client/api/vla-helpers.js +130 -0
  15. package/dist/client/api/vla.d.ts +65 -0
  16. package/dist/client/api/vla.js +109 -0
  17. package/dist/client/config-loader/resolve-config.node.d.ts +16 -0
  18. package/dist/client/config-loader/resolve-config.node.js +77 -23
  19. package/dist/client/plugins-factory.d.ts +8 -0
  20. package/dist/client/plugins-factory.js +10 -0
  21. package/dist/client/rpc/bare-client.d.ts +1 -0
  22. package/dist/client/rpc/bare-client.js +66 -66
  23. package/dist/client/rpc/ensure-worker-ready.d.ts +9 -0
  24. package/dist/client/rpc/ensure-worker-ready.js +17 -0
  25. package/dist/client/rpc/expo-rpc-client.d.ts +1 -0
  26. package/dist/client/rpc/expo-rpc-client.js +4 -0
  27. package/dist/client/rpc/node-rpc-client.d.ts +1 -0
  28. package/dist/client/rpc/node-rpc-client.js +97 -5
  29. package/dist/client/rpc/rpc-client.js +115 -8
  30. package/dist/client/rpc/rpc-error.js +14 -1
  31. package/dist/commands/bundle/bare-pack.d.ts +13 -0
  32. package/dist/commands/bundle/bare-pack.js +54 -0
  33. package/dist/commands/bundle/constants.d.ts +7 -0
  34. package/dist/commands/bundle/constants.js +23 -0
  35. package/dist/commands/bundle/entry-gen.d.ts +2 -0
  36. package/dist/commands/bundle/entry-gen.js +48 -0
  37. package/dist/commands/bundle/index.d.ts +20 -0
  38. package/dist/commands/bundle/index.js +141 -0
  39. package/dist/commands/bundle/manifest.d.ts +21 -0
  40. package/dist/commands/bundle/manifest.js +193 -0
  41. package/dist/commands/bundle/plugins.d.ts +9 -0
  42. package/dist/commands/bundle/plugins.js +51 -0
  43. package/dist/commands/index.d.ts +5 -0
  44. package/dist/commands/index.js +2 -0
  45. package/dist/commands/verify/abi.d.ts +52 -0
  46. package/dist/commands/verify/abi.js +125 -0
  47. package/dist/commands/verify/addon-source.d.ts +43 -0
  48. package/dist/commands/verify/addon-source.js +75 -0
  49. package/dist/commands/verify/bundle-source.d.ts +12 -0
  50. package/dist/commands/verify/bundle-source.js +53 -0
  51. package/dist/commands/verify/index.d.ts +59 -0
  52. package/dist/commands/verify/index.js +371 -0
  53. package/dist/commands/verify/node-modules-source.d.ts +11 -0
  54. package/dist/commands/verify/node-modules-source.js +76 -0
  55. package/dist/commands/verify/prebuilds.d.ts +15 -0
  56. package/dist/commands/verify/prebuilds.js +39 -0
  57. package/dist/examples/classification/classify-image.d.ts +2 -0
  58. package/dist/examples/classification/classify-image.js +23 -0
  59. package/dist/examples/diffusion-txt2vid.d.ts +2 -0
  60. package/dist/examples/diffusion-txt2vid.js +81 -0
  61. package/dist/examples/plugins.js +3 -7
  62. package/dist/examples/tools/llamacpp-tools-gemma4.js +2 -5
  63. package/dist/examples/tools/llamacpp-tools-qwen35.js +2 -3
  64. package/dist/examples/transcription/parakeet-ctc-filesystem.js +18 -12
  65. package/dist/examples/transcription/parakeet-microphone-record.js +7 -12
  66. package/dist/examples/transcription/parakeet-microphone-stream.d.ts +2 -0
  67. package/dist/examples/transcription/parakeet-microphone-stream.js +79 -0
  68. package/dist/examples/transcription/parakeet-sortformer-streaming.d.ts +2 -0
  69. package/dist/examples/transcription/parakeet-sortformer-streaming.js +121 -0
  70. package/dist/examples/transcription/parakeet-sortformer.js +58 -55
  71. package/dist/examples/transcription/parakeet-tdt-filesystem.js +18 -15
  72. package/dist/examples/transcription/whispercpp-microphone-conversation.js +6 -1
  73. package/dist/examples/tts/chatterbox.js +7 -16
  74. package/dist/examples/tts/llm-to-tts-streaming.js +3 -10
  75. package/dist/examples/tts/supertonic-multilingual.js +4 -12
  76. package/dist/examples/tts/supertonic.js +5 -12
  77. package/dist/examples/vla-smolvla.d.ts +2 -0
  78. package/dist/examples/vla-smolvla.js +75 -0
  79. package/dist/examples/voice-assistant/voice-assistant.js +3 -10
  80. package/dist/expo/plugins/find-in-ancestor-node-modules.d.ts +14 -0
  81. package/dist/expo/plugins/find-in-ancestor-node-modules.js +24 -0
  82. package/dist/expo/plugins/get-project-root.d.ts +22 -0
  83. package/dist/expo/plugins/get-project-root.js +23 -0
  84. package/dist/expo/plugins/index.d.ts +4 -0
  85. package/dist/expo/plugins/index.js +4 -0
  86. package/dist/expo/plugins/resolve-sdk-package-dir.d.ts +9 -2
  87. package/dist/expo/plugins/resolve-sdk-package-dir.js +38 -11
  88. package/dist/expo/plugins/withDeviceInfo.js +2 -1
  89. package/dist/expo/plugins/withMobileBundle.d.ts +2 -17
  90. package/dist/expo/plugins/withMobileBundle.js +31 -85
  91. package/dist/index.d.ts +5 -3
  92. package/dist/index.js +9 -3
  93. package/dist/models/registry/models.d.ts +3711 -368
  94. package/dist/models/registry/models.js +7066 -3562
  95. package/dist/models/update-models/naming.js +22 -8
  96. package/dist/pear/pre.js +6 -2
  97. package/dist/schemas/cancel.d.ts +5 -0
  98. package/dist/schemas/cancel.js +1 -0
  99. package/dist/schemas/classification.d.ts +53 -0
  100. package/dist/schemas/classification.js +33 -0
  101. package/dist/schemas/common.d.ts +1001 -1739
  102. package/dist/schemas/common.js +6 -1
  103. package/dist/schemas/completion-event.d.ts +3 -0
  104. package/dist/schemas/completion-event.js +1 -0
  105. package/dist/schemas/completion-stream.d.ts +1 -0
  106. package/dist/schemas/download-asset.d.ts +13 -3
  107. package/dist/schemas/engine-addon-map.d.ts +3 -0
  108. package/dist/schemas/engine-addon-map.js +18 -5
  109. package/dist/schemas/get-model-info.d.ts +4 -0
  110. package/dist/schemas/get-model-info.js +2 -0
  111. package/dist/schemas/index.d.ts +3 -0
  112. package/dist/schemas/index.js +3 -0
  113. package/dist/schemas/llamacpp-config.d.ts +12 -2
  114. package/dist/schemas/load-model.d.ts +6152 -10764
  115. package/dist/schemas/load-model.js +75 -7
  116. package/dist/schemas/model-src-utils.d.ts +22 -2
  117. package/dist/schemas/model-types.d.ts +46 -6
  118. package/dist/schemas/model-types.js +28 -5
  119. package/dist/schemas/ocr.d.ts +5 -0
  120. package/dist/schemas/plugin.d.ts +20 -5
  121. package/dist/schemas/plugin.js +21 -4
  122. package/dist/schemas/registry.d.ts +44 -0
  123. package/dist/schemas/registry.js +5 -0
  124. package/dist/schemas/reload-config.d.ts +22 -2
  125. package/dist/schemas/sdcpp-config.d.ts +316 -1
  126. package/dist/schemas/sdcpp-config.js +232 -33
  127. package/dist/schemas/sdk-config.d.ts +654 -1324
  128. package/dist/schemas/sdk-config.js +16 -1
  129. package/dist/schemas/sdk-errors-client.d.ts +7 -0
  130. package/dist/schemas/sdk-errors-client.js +36 -1
  131. package/dist/schemas/sdk-errors-server.d.ts +3 -1
  132. package/dist/schemas/sdk-errors-server.js +20 -5
  133. package/dist/schemas/text-to-speech.d.ts +79 -696
  134. package/dist/schemas/text-to-speech.js +46 -19
  135. package/dist/schemas/transcription-config.d.ts +37 -226
  136. package/dist/schemas/transcription-config.js +76 -15
  137. package/dist/schemas/transcription.d.ts +63 -11
  138. package/dist/schemas/transcription.js +56 -2
  139. package/dist/schemas/translation-config.d.ts +60 -10
  140. package/dist/schemas/vla.d.ts +87 -0
  141. package/dist/schemas/vla.js +108 -0
  142. package/dist/scripts/run-unit-tests.js +8 -2
  143. package/dist/server/bare/ops/transcribe.d.ts +2 -1
  144. package/dist/server/bare/ops/transcribe.js +59 -34
  145. package/dist/server/bare/plugins/ggml-classification/ops/classify.d.ts +6 -0
  146. package/dist/server/bare/plugins/ggml-classification/ops/classify.js +30 -0
  147. package/dist/server/bare/plugins/ggml-classification/plugin.d.ts +32 -0
  148. package/dist/server/bare/plugins/ggml-classification/plugin.js +55 -0
  149. package/dist/server/bare/plugins/ggml-vla/ops/vla-hparams.d.ts +3 -0
  150. package/dist/server/bare/plugins/ggml-vla/ops/vla-hparams.js +12 -0
  151. package/dist/server/bare/plugins/ggml-vla/ops/vla-run.d.ts +3 -0
  152. package/dist/server/bare/plugins/ggml-vla/ops/vla-run.js +75 -0
  153. package/dist/server/bare/plugins/ggml-vla/plugin.d.ts +54 -0
  154. package/dist/server/bare/plugins/ggml-vla/plugin.js +57 -0
  155. package/dist/server/bare/plugins/index.d.ts +3 -1
  156. package/dist/server/bare/plugins/index.js +3 -1
  157. package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.js +3 -0
  158. package/dist/server/bare/plugins/llamacpp-completion/ops/context-overflow.d.ts +29 -0
  159. package/dist/server/bare/plugins/llamacpp-completion/ops/context-overflow.js +65 -0
  160. package/dist/server/bare/plugins/llamacpp-completion/plugin.d.ts +6 -0
  161. package/dist/server/bare/plugins/llamacpp-completion/plugin.js +26 -0
  162. package/dist/server/bare/plugins/nmtcpp-translation/plugin.d.ts +25 -0
  163. package/dist/server/bare/plugins/onnx-ocr/plugin.d.ts +5 -0
  164. package/dist/server/bare/plugins/parakeet-transcription/plugin.d.ts +67 -246
  165. package/dist/server/bare/plugins/parakeet-transcription/plugin.js +66 -97
  166. package/dist/server/bare/plugins/sdcpp-generation/ops/video.d.ts +3 -0
  167. package/dist/server/bare/plugins/sdcpp-generation/ops/video.js +199 -0
  168. package/dist/server/bare/plugins/sdcpp-generation/plugin.d.ts +200 -2
  169. package/dist/server/bare/plugins/sdcpp-generation/plugin.js +61 -8
  170. package/dist/server/bare/plugins/{onnx-tts → tts-ggml}/ops/text-to-speech-stream.js +2 -15
  171. package/dist/server/bare/plugins/{onnx-tts → tts-ggml}/ops/text-to-speech.js +2 -1
  172. package/dist/server/bare/plugins/tts-ggml/plugin.d.ts +75 -0
  173. package/dist/server/bare/plugins/tts-ggml/plugin.js +189 -0
  174. package/dist/server/bare/plugins/whispercpp-transcription/plugin.d.ts +29 -4
  175. package/dist/server/bare/plugins/whispercpp-transcription/plugin.js +12 -1
  176. package/dist/server/bare/registry/model-config-utils.js +7 -0
  177. package/dist/server/bare/runtime/request-context.d.ts +1 -1
  178. package/dist/server/bare/runtime-lifecycle.js +9 -9
  179. package/dist/server/bare/types/addon-responses.d.ts +1 -0
  180. package/dist/server/env.js +4 -1
  181. package/dist/server/plugins/index.d.ts +1 -1
  182. package/dist/server/plugins/index.js +1 -1
  183. package/dist/server/plugins/registry.d.ts +1 -0
  184. package/dist/server/plugins/registry.js +5 -0
  185. package/dist/server/rpc/handler-registry.js +4 -0
  186. package/dist/server/rpc/handler-selection.d.ts +9 -0
  187. package/dist/server/rpc/handler-selection.js +14 -0
  188. package/dist/server/rpc/handler-utils.js +5 -13
  189. package/dist/server/rpc/handlers/classify.d.ts +3 -0
  190. package/dist/server/rpc/handlers/classify.js +4 -0
  191. package/dist/server/rpc/handlers/index.d.ts +2 -0
  192. package/dist/server/rpc/handlers/index.js +2 -0
  193. package/dist/server/rpc/handlers/load-model/handler.js +4 -1
  194. package/dist/server/rpc/handlers/load-model/resolve.js +9 -0
  195. package/dist/server/rpc/handlers/video-stream.d.ts +3 -0
  196. package/dist/server/rpc/handlers/video-stream.js +4 -0
  197. package/dist/server/rpc/profiling/operation-metrics.js +23 -0
  198. package/dist/server/utils/config-transform.js +1 -1
  199. package/dist/server/utils/tools/parsers/qwen35.js +7 -3
  200. package/dist/server/worker.js +14 -11
  201. package/dist/utils/errors-client.d.ts +23 -0
  202. package/dist/utils/errors-client.js +40 -0
  203. package/dist/utils/errors-server.d.ts +30 -2
  204. package/dist/utils/errors-server.js +51 -3
  205. package/package.json +66 -80
  206. package/dist/server/bare/plugins/onnx-tts/plugin.d.ts +0 -490
  207. package/dist/server/bare/plugins/onnx-tts/plugin.js +0 -272
  208. package/dist/server/bare/plugins/onnx-tts/wav-helper.d.ts +0 -14
  209. package/dist/server/bare/plugins/onnx-tts/wav-helper.js +0 -107
  210. /package/dist/server/bare/plugins/{onnx-tts → tts-ggml}/ops/text-to-speech-stream.d.ts +0 -0
  211. /package/dist/server/bare/plugins/{onnx-tts → tts-ggml}/ops/text-to-speech.d.ts +0 -0
@@ -0,0 +1,75 @@
1
+ import { promises as fsp } from "node:fs";
2
+ import path from "node:path";
3
+ export async function readAddonPackageJson(options) {
4
+ const { packageJsonPath, expectedName } = options;
5
+ let raw;
6
+ try {
7
+ raw = await fsp.readFile(packageJsonPath, "utf8");
8
+ }
9
+ catch {
10
+ return { found: false, isAddon: false };
11
+ }
12
+ let parsed;
13
+ try {
14
+ parsed = JSON.parse(raw);
15
+ }
16
+ catch (error) {
17
+ const reason = error instanceof Error ? error.message : String(error);
18
+ return {
19
+ found: true,
20
+ isAddon: false,
21
+ invalid: buildInvalid(packageJsonPath, expectedName, `malformed JSON: ${reason}`),
22
+ };
23
+ }
24
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
25
+ return {
26
+ found: true,
27
+ isAddon: false,
28
+ invalid: buildInvalid(packageJsonPath, expectedName, "package.json is not a JSON object"),
29
+ };
30
+ }
31
+ const pkg = parsed;
32
+ if (pkg.addon !== true) {
33
+ return { found: true, isAddon: false };
34
+ }
35
+ const name = pkg.name ?? expectedName;
36
+ if (!name) {
37
+ return {
38
+ found: true,
39
+ isAddon: false,
40
+ invalid: buildInvalid(packageJsonPath, expectedName, "addon package.json is missing a `name` field"),
41
+ };
42
+ }
43
+ const addon = {
44
+ name,
45
+ packageJsonPath,
46
+ packageRoot: path.dirname(packageJsonPath),
47
+ };
48
+ if (typeof pkg.version === "string")
49
+ addon.version = pkg.version;
50
+ if (typeof pkg.engines?.bare === "string")
51
+ addon.enginesBare = pkg.engines.bare;
52
+ return { found: true, isAddon: true, addon };
53
+ }
54
+ function buildInvalid(packageJsonPath, expectedName, reason) {
55
+ const record = { packageJsonPath, reason };
56
+ if (expectedName !== undefined)
57
+ record.expectedName = expectedName;
58
+ return record;
59
+ }
60
+ export function createCollectDiagnostics() {
61
+ return { invalidPackageJsons: [], emptyResolutions: false };
62
+ }
63
+ export function formatAddonId(addon) {
64
+ return `${addon.name}@${addon.version ?? "unknown"}`;
65
+ }
66
+ export function deduplicateAddons(addons) {
67
+ const byKey = new Map();
68
+ for (const addon of addons) {
69
+ const key = `${addon.name}@${addon.version ?? "unknown"}::${addon.packageRoot}`;
70
+ if (!byKey.has(key))
71
+ byKey.set(key, addon);
72
+ }
73
+ return [...byKey.values()].sort((a, b) => formatAddonId(a).localeCompare(formatAddonId(b)) ||
74
+ a.packageRoot.localeCompare(b.packageRoot));
75
+ }
@@ -0,0 +1,12 @@
1
+ import { type CollectDiagnostics, type NativeAddon } from "./addon-source";
2
+ export declare class InvalidBundleSourceError extends Error {
3
+ bundlePath: string;
4
+ constructor(bundlePath: string, cause: unknown);
5
+ }
6
+ export interface CollectAddonsFromBundleOptions {
7
+ bundlePath: string;
8
+ projectRoot: string;
9
+ diagnostics?: CollectDiagnostics;
10
+ }
11
+ export declare function collectAddonsFromBundle(options: CollectAddonsFromBundleOptions): Promise<NativeAddon[]>;
12
+ //# sourceMappingURL=bundle-source.d.ts.map
@@ -0,0 +1,53 @@
1
+ import { promises as fsp } from "node:fs";
2
+ import { buildNestedPathIndex, extractBarePackHeader, extractPackedString, } from "../bundle/manifest.js";
3
+ import { deduplicateAddons, readAddonPackageJson, } from "./addon-source.js";
4
+ export class InvalidBundleSourceError extends Error {
5
+ bundlePath;
6
+ constructor(bundlePath, cause) {
7
+ const reason = cause instanceof Error ? cause.message : String(cause);
8
+ super(`Bundle at ${bundlePath} could not be parsed as a bare-pack bundle.\n\n` +
9
+ ` Reason: ${reason}\n\n` +
10
+ " Make sure the path points to a worker.bundle.js generated by bundleSdk.");
11
+ this.name = "InvalidBundleSourceError";
12
+ this.bundlePath = bundlePath;
13
+ }
14
+ }
15
+ export async function collectAddonsFromBundle(options) {
16
+ const { bundlePath, projectRoot, diagnostics } = options;
17
+ let bundleText;
18
+ try {
19
+ bundleText = await fsp.readFile(bundlePath, "utf8");
20
+ }
21
+ catch (error) {
22
+ throw new InvalidBundleSourceError(bundlePath, error);
23
+ }
24
+ let resolutions;
25
+ try {
26
+ const packed = extractPackedString(bundleText);
27
+ const header = extractBarePackHeader(packed);
28
+ resolutions = header.resolutions ?? {};
29
+ }
30
+ catch (error) {
31
+ throw new InvalidBundleSourceError(bundlePath, error);
32
+ }
33
+ if (diagnostics !== undefined && Object.keys(resolutions).length === 0) {
34
+ diagnostics.emptyResolutions = true;
35
+ }
36
+ const pathsByPackage = buildNestedPathIndex(resolutions, projectRoot);
37
+ const addons = [];
38
+ for (const [pkgName, candidates] of pathsByPackage) {
39
+ for (const candidate of candidates) {
40
+ const result = await readAddonPackageJson({
41
+ packageJsonPath: candidate,
42
+ expectedName: pkgName,
43
+ });
44
+ if (result.isAddon && result.addon) {
45
+ addons.push(result.addon);
46
+ }
47
+ else if (result.invalid !== undefined && diagnostics !== undefined) {
48
+ diagnostics.invalidPackageJsons.push(result.invalid);
49
+ }
50
+ }
51
+ }
52
+ return deduplicateAddons(addons);
53
+ }
@@ -0,0 +1,59 @@
1
+ import { type AddonSourceKind, type NativeAddon } from "./addon-source";
2
+ import { type MissingPrebuildIssue } from "./prebuilds";
3
+ import { type AbiIssue, type BareRuntimeResolution } from "./abi";
4
+ export interface VerifyBundleOptions {
5
+ projectRoot: string;
6
+ addonsSource: string;
7
+ hosts: string[];
8
+ bareRuntimeVersion?: string;
9
+ configPath?: string;
10
+ }
11
+ export interface InvalidSourceIssue {
12
+ code: 'invalid-source';
13
+ level: 'error';
14
+ message: string;
15
+ addonsSource: string;
16
+ }
17
+ export interface InvalidRuntimeVersionIssue {
18
+ code: 'invalid-runtime-version';
19
+ level: 'error';
20
+ message: string;
21
+ providedValue: string;
22
+ source: 'flag' | 'config';
23
+ }
24
+ export interface ConfigLoadFailedIssue {
25
+ code: 'config-load-failed';
26
+ level: 'warning';
27
+ message: string;
28
+ configPath: string;
29
+ reason: string;
30
+ }
31
+ export interface InvalidPackageJsonIssue {
32
+ code: 'invalid-package-json';
33
+ level: 'warning';
34
+ message: string;
35
+ packageJsonPath: string;
36
+ expectedName?: string;
37
+ reason: string;
38
+ }
39
+ export interface EmptyBundleResolutionsIssue {
40
+ code: 'empty-bundle-resolutions';
41
+ level: 'warning';
42
+ message: string;
43
+ bundlePath: string;
44
+ }
45
+ export type VerifyBundleIssue = MissingPrebuildIssue | AbiIssue | InvalidSourceIssue | InvalidRuntimeVersionIssue | ConfigLoadFailedIssue | InvalidPackageJsonIssue | EmptyBundleResolutionsIssue;
46
+ export interface VerifyBundleResult {
47
+ addonsSource: string;
48
+ resolvedAddonsSource: string;
49
+ sourceKind: AddonSourceKind | null;
50
+ hosts: string[];
51
+ runtime: BareRuntimeResolution | null;
52
+ addons: NativeAddon[];
53
+ issues: VerifyBundleIssue[];
54
+ }
55
+ export declare function verifyBundle(options: VerifyBundleOptions): Promise<VerifyBundleResult>;
56
+ export declare function hasErrors(result: VerifyBundleResult): boolean;
57
+ export declare function hasWarnings(result: VerifyBundleResult): boolean;
58
+ export declare function formatVerifyBundleResult(result: VerifyBundleResult): string;
59
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,371 @@
1
+ import { promises as fsp } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { resolveConfigFileInProject, loadConfigFromPath, } from "../../client/config-loader/resolve-config.node.js";
4
+ import { createCollectDiagnostics, formatAddonId, } from "./addon-source.js";
5
+ import { collectAddonsFromBundle, InvalidBundleSourceError, } from "./bundle-source.js";
6
+ import { collectAddonsFromNodeModules, InvalidNodeModulesSourceError, } from "./node-modules-source.js";
7
+ import { checkPrebuilds, } from "./prebuilds.js";
8
+ import { checkAbi, formatConfigLabel, normalizeVersion, resolveBareRuntime, } from "./abi.js";
9
+ export async function verifyBundle(options) {
10
+ const { projectRoot, addonsSource, hosts, bareRuntimeVersion, configPath } = options;
11
+ const resolvedAddonsSource = path.isAbsolute(addonsSource)
12
+ ? addonsSource
13
+ : path.resolve(projectRoot, addonsSource);
14
+ if (hosts.length === 0) {
15
+ return {
16
+ addonsSource,
17
+ resolvedAddonsSource,
18
+ sourceKind: null,
19
+ hosts,
20
+ runtime: null,
21
+ addons: [],
22
+ issues: [
23
+ {
24
+ code: 'invalid-source',
25
+ level: 'error',
26
+ addonsSource,
27
+ message: 'At least one host is required.'
28
+ }
29
+ ]
30
+ };
31
+ }
32
+ let invalidRuntimeVersion = null;
33
+ if (bareRuntimeVersion !== undefined && normalizeVersion(bareRuntimeVersion) === null) {
34
+ invalidRuntimeVersion = {
35
+ code: 'invalid-runtime-version',
36
+ level: 'error',
37
+ providedValue: bareRuntimeVersion,
38
+ source: 'flag',
39
+ message: `bareRuntimeVersion "${bareRuntimeVersion}" is not a valid semver. ` +
40
+ 'Use a version like 1.15.0 (with optional v-prefix and pre-release tag) or omit it to use auto-detection.'
41
+ };
42
+ }
43
+ let configRuntimeVersion;
44
+ let resolvedConfigPath = null;
45
+ let configLoadFailed = null;
46
+ try {
47
+ resolvedConfigPath = await resolveConfigFileInProject(projectRoot, configPath ?? undefined);
48
+ if (resolvedConfigPath !== null) {
49
+ const config = await loadConfigFromPath(resolvedConfigPath);
50
+ if (typeof config.bareRuntimeVersion === "string") {
51
+ configRuntimeVersion = config.bareRuntimeVersion;
52
+ }
53
+ }
54
+ }
55
+ catch (error) {
56
+ const message = error instanceof Error ? error.message : String(error);
57
+ if (configPath !== undefined) {
58
+ return {
59
+ addonsSource,
60
+ resolvedAddonsSource,
61
+ sourceKind: null,
62
+ hosts,
63
+ runtime: null,
64
+ addons: [],
65
+ issues: [
66
+ {
67
+ code: 'invalid-source',
68
+ level: 'error',
69
+ addonsSource,
70
+ message: `Failed to load config from '${configPath}': ${message}`
71
+ }
72
+ ]
73
+ };
74
+ }
75
+ if (resolvedConfigPath !== null) {
76
+ configLoadFailed = {
77
+ code: 'config-load-failed',
78
+ level: 'warning',
79
+ configPath: resolvedConfigPath,
80
+ reason: message,
81
+ message: `Found ${formatConfigLabel(projectRoot, resolvedConfigPath)} but failed to load it: ${message}. ` +
82
+ 'Falling back to auto-detection for Bare runtime; the project-pinned ' +
83
+ '`bareRuntimeVersion` is being ignored. Fix the config file or pass `configPath` explicitly to surface it as an error.'
84
+ };
85
+ }
86
+ }
87
+ if (invalidRuntimeVersion === null &&
88
+ bareRuntimeVersion === undefined &&
89
+ configRuntimeVersion !== undefined &&
90
+ normalizeVersion(configRuntimeVersion) === null) {
91
+ invalidRuntimeVersion = {
92
+ code: 'invalid-runtime-version',
93
+ level: 'error',
94
+ providedValue: configRuntimeVersion,
95
+ source: 'config',
96
+ message: `\`bareRuntimeVersion\` in ${formatConfigLabel(projectRoot, resolvedConfigPath ?? undefined)} ` +
97
+ `"${configRuntimeVersion}" is not a valid semver. ` +
98
+ 'Use a version like 1.15.0 (with optional v-prefix and pre-release tag), or remove the field to use auto-detection.'
99
+ };
100
+ }
101
+ const sourceKind = await detectSourceKind(resolvedAddonsSource);
102
+ if (sourceKind === null) {
103
+ return {
104
+ addonsSource,
105
+ resolvedAddonsSource,
106
+ sourceKind: null,
107
+ hosts,
108
+ runtime: null,
109
+ addons: [],
110
+ issues: [
111
+ {
112
+ code: 'invalid-source',
113
+ level: 'error',
114
+ addonsSource,
115
+ message: `--addons-source ${addonsSource} is not a readable file or directory ` +
116
+ `(resolved to ${resolvedAddonsSource}).`
117
+ }
118
+ ]
119
+ };
120
+ }
121
+ const diagnostics = createCollectDiagnostics();
122
+ let addons;
123
+ try {
124
+ addons = sourceKind === 'bare-pack-bundle'
125
+ ? await collectAddonsFromBundle({
126
+ bundlePath: resolvedAddonsSource,
127
+ projectRoot,
128
+ diagnostics
129
+ })
130
+ : await collectAddonsFromNodeModules({
131
+ nodeModulesRoot: resolvedAddonsSource,
132
+ diagnostics
133
+ });
134
+ }
135
+ catch (error) {
136
+ if (error instanceof InvalidBundleSourceError ||
137
+ error instanceof InvalidNodeModulesSourceError) {
138
+ return {
139
+ addonsSource,
140
+ resolvedAddonsSource,
141
+ sourceKind,
142
+ hosts,
143
+ runtime: null,
144
+ addons: [],
145
+ issues: [
146
+ {
147
+ code: 'invalid-source',
148
+ level: 'error',
149
+ addonsSource,
150
+ message: error.message
151
+ }
152
+ ]
153
+ };
154
+ }
155
+ throw error;
156
+ }
157
+ const issues = [];
158
+ if (configLoadFailed !== null)
159
+ issues.push(configLoadFailed);
160
+ if (invalidRuntimeVersion !== null)
161
+ issues.push(invalidRuntimeVersion);
162
+ issues.push(...buildInvalidPackageJsonIssues(diagnostics.invalidPackageJsons));
163
+ if (sourceKind === 'bare-pack-bundle' && diagnostics.emptyResolutions) {
164
+ issues.push({
165
+ code: 'empty-bundle-resolutions',
166
+ level: 'warning',
167
+ bundlePath: resolvedAddonsSource,
168
+ message: `Bundle at ${resolvedAddonsSource} has no resolutions in its bare-pack header ` +
169
+ '(0 packages discoverable). The verifier cannot inspect any addons in this bundle; ' +
170
+ '`Native addon verification passed` would be vacuous. Regenerate the bundle via ' +
171
+ '`qvac bundle sdk` and re-run, or check for a corrupted/empty bundle file.'
172
+ });
173
+ }
174
+ for (const addon of addons) {
175
+ const prebuildIssues = await checkPrebuilds({ addon, hosts });
176
+ issues.push(...prebuildIssues);
177
+ }
178
+ let runtime = null;
179
+ if (invalidRuntimeVersion === null) {
180
+ const runtimeOptions = { projectRoot };
181
+ if (bareRuntimeVersion !== undefined) {
182
+ runtimeOptions.explicitVersion = bareRuntimeVersion;
183
+ runtimeOptions.explicitSource = 'flag';
184
+ }
185
+ else if (configRuntimeVersion !== undefined) {
186
+ runtimeOptions.explicitVersion = configRuntimeVersion;
187
+ runtimeOptions.explicitSource = 'config';
188
+ }
189
+ runtime = await resolveBareRuntime(runtimeOptions);
190
+ issues.push(...checkAbi({ addons, runtime }));
191
+ }
192
+ return {
193
+ addonsSource,
194
+ resolvedAddonsSource,
195
+ sourceKind,
196
+ hosts,
197
+ runtime,
198
+ addons,
199
+ issues
200
+ };
201
+ }
202
+ function buildInvalidPackageJsonIssues(records) {
203
+ return records.map((record) => {
204
+ const issue = {
205
+ code: 'invalid-package-json',
206
+ level: 'warning',
207
+ packageJsonPath: record.packageJsonPath,
208
+ reason: record.reason,
209
+ message: `Skipping ${record.expectedName ?? record.packageJsonPath}: ` +
210
+ `${record.reason}. The package is being treated as a non-addon; if it ships ` +
211
+ 'native code, the verifier cannot check its prebuilds or ABI. ' +
212
+ 'Fix the package.json or remove the package.'
213
+ };
214
+ if (record.expectedName !== undefined)
215
+ issue.expectedName = record.expectedName;
216
+ return issue;
217
+ });
218
+ }
219
+ async function detectSourceKind(resolvedAddonsSource) {
220
+ try {
221
+ const stat = await fsp.stat(resolvedAddonsSource);
222
+ if (stat.isFile())
223
+ return 'bare-pack-bundle';
224
+ if (stat.isDirectory())
225
+ return 'node-modules';
226
+ return null;
227
+ }
228
+ catch {
229
+ return null;
230
+ }
231
+ }
232
+ export function hasErrors(result) {
233
+ return result.issues.some((issue) => issue.level === 'error');
234
+ }
235
+ export function hasWarnings(result) {
236
+ return result.issues.some((issue) => issue.level === 'warning');
237
+ }
238
+ export function formatVerifyBundleResult(result) {
239
+ const sections = [];
240
+ const hostList = result.hosts.join(', ');
241
+ if (result.issues.length === 0) {
242
+ sections.push(`Native addon verification passed for ${result.addons.length} ` +
243
+ `addon${result.addons.length === 1 ? '' : 's'} across ${result.hosts.length} ` +
244
+ `host${result.hosts.length === 1 ? '' : 's'}: ${hostList}`);
245
+ if (result.addons.length > 0) {
246
+ sections.push('');
247
+ sections.push(' Verified addons:');
248
+ for (const addon of result.addons) {
249
+ sections.push(` - ${formatAddonId(addon)}`);
250
+ }
251
+ }
252
+ return sections.join('\n');
253
+ }
254
+ if (hasErrors(result)) {
255
+ sections.push('Native addon verification failed:');
256
+ }
257
+ else {
258
+ sections.push('Native addon verification produced warnings:');
259
+ }
260
+ sections.push('');
261
+ sections.push(...formatMissingPrebuilds(result.issues));
262
+ sections.push(...formatAbiMismatches(result.issues));
263
+ sections.push(...formatInvalidRuntimeVersions(result.issues));
264
+ sections.push(...formatMalformedEnginesBare(result.issues));
265
+ sections.push(...formatConfigLoadFailed(result.issues));
266
+ sections.push(...formatInvalidPackageJsons(result.issues));
267
+ sections.push(...formatEmptyBundleResolutions(result.issues));
268
+ sections.push(...formatUnknownRuntime(result.issues));
269
+ sections.push(...formatInvalidSources(result.issues));
270
+ return sections.join('\n').trimEnd();
271
+ }
272
+ function formatConfigLoadFailed(issues) {
273
+ const matches = issues.filter((issue) => issue.code === 'config-load-failed');
274
+ if (matches.length === 0)
275
+ return [];
276
+ const lines = [' Config load failed:'];
277
+ for (const issue of matches) {
278
+ lines.push(` - ${issue.message}`);
279
+ }
280
+ lines.push('');
281
+ return lines;
282
+ }
283
+ function formatMissingPrebuilds(issues) {
284
+ const matches = issues.filter((issue) => issue.code === 'missing-prebuild');
285
+ if (matches.length === 0)
286
+ return [];
287
+ const lines = [' Missing prebuild:'];
288
+ for (const issue of matches) {
289
+ lines.push(` - ${issue.addon} for ${issue.host}`);
290
+ }
291
+ lines.push('');
292
+ return lines;
293
+ }
294
+ function formatAbiMismatches(issues) {
295
+ const matches = issues.filter((issue) => issue.code === 'abi-mismatch');
296
+ if (matches.length === 0)
297
+ return [];
298
+ const lines = [' ABI mismatch:'];
299
+ for (const issue of matches) {
300
+ lines.push(` - ${issue.addon} requires bare ${issue.enginesBare}, ` +
301
+ `runtime is ${issue.runtimeVersion}`);
302
+ }
303
+ lines.push('');
304
+ return lines;
305
+ }
306
+ function formatUnknownRuntime(issues) {
307
+ const matches = issues.filter((issue) => issue.code === 'unknown-runtime-version');
308
+ if (matches.length === 0)
309
+ return [];
310
+ const lines = [' Unknown runtime version:'];
311
+ for (const issue of matches) {
312
+ lines.push(` - ${issue.message}`);
313
+ }
314
+ lines.push('');
315
+ return lines;
316
+ }
317
+ function formatMalformedEnginesBare(issues) {
318
+ const matches = issues.filter((issue) => issue.code === 'malformed-engines-bare');
319
+ if (matches.length === 0)
320
+ return [];
321
+ const lines = [' Malformed engines.bare:'];
322
+ for (const issue of matches) {
323
+ lines.push(` - ${issue.message}`);
324
+ }
325
+ lines.push('');
326
+ return lines;
327
+ }
328
+ function formatInvalidSources(issues) {
329
+ const matches = issues.filter((issue) => issue.code === 'invalid-source');
330
+ if (matches.length === 0)
331
+ return [];
332
+ const lines = [' Invalid source:'];
333
+ for (const issue of matches) {
334
+ lines.push(` - ${issue.message}`);
335
+ }
336
+ lines.push('');
337
+ return lines;
338
+ }
339
+ function formatInvalidRuntimeVersions(issues) {
340
+ const matches = issues.filter((issue) => issue.code === 'invalid-runtime-version');
341
+ if (matches.length === 0)
342
+ return [];
343
+ const lines = [' Invalid Bare runtime version:'];
344
+ for (const issue of matches) {
345
+ lines.push(` - ${issue.message}`);
346
+ }
347
+ lines.push('');
348
+ return lines;
349
+ }
350
+ function formatInvalidPackageJsons(issues) {
351
+ const matches = issues.filter((issue) => issue.code === 'invalid-package-json');
352
+ if (matches.length === 0)
353
+ return [];
354
+ const lines = [' Invalid package.json (skipped):'];
355
+ for (const issue of matches) {
356
+ lines.push(` - ${issue.message}`);
357
+ }
358
+ lines.push('');
359
+ return lines;
360
+ }
361
+ function formatEmptyBundleResolutions(issues) {
362
+ const matches = issues.filter((issue) => issue.code === 'empty-bundle-resolutions');
363
+ if (matches.length === 0)
364
+ return [];
365
+ const lines = [' Empty bundle resolutions:'];
366
+ for (const issue of matches) {
367
+ lines.push(` - ${issue.message}`);
368
+ }
369
+ lines.push('');
370
+ return lines;
371
+ }
@@ -0,0 +1,11 @@
1
+ import { type CollectDiagnostics, type NativeAddon } from "./addon-source";
2
+ export declare class InvalidNodeModulesSourceError extends Error {
3
+ nodeModulesPath: string;
4
+ constructor(nodeModulesPath: string, cause: unknown);
5
+ }
6
+ export interface CollectAddonsFromNodeModulesOptions {
7
+ nodeModulesRoot: string;
8
+ diagnostics?: CollectDiagnostics;
9
+ }
10
+ export declare function collectAddonsFromNodeModules(options: CollectAddonsFromNodeModulesOptions): Promise<NativeAddon[]>;
11
+ //# sourceMappingURL=node-modules-source.d.ts.map
@@ -0,0 +1,76 @@
1
+ import { promises as fsp } from "node:fs";
2
+ import path from "node:path";
3
+ import { deduplicateAddons, readAddonPackageJson, } from "./addon-source.js";
4
+ export class InvalidNodeModulesSourceError extends Error {
5
+ nodeModulesPath;
6
+ constructor(nodeModulesPath, cause) {
7
+ const reason = cause instanceof Error ? cause.message : String(cause);
8
+ super(`node_modules at ${nodeModulesPath} could not be read.\n\n` +
9
+ ` Reason: ${reason}\n\n` +
10
+ " Run `npm install` before invoking verifyBundle against a node_modules tree.");
11
+ this.name = "InvalidNodeModulesSourceError";
12
+ this.nodeModulesPath = nodeModulesPath;
13
+ }
14
+ }
15
+ export async function collectAddonsFromNodeModules(options) {
16
+ const { nodeModulesRoot, diagnostics } = options;
17
+ const addons = [];
18
+ await walkNodeModules(nodeModulesRoot, addons, diagnostics, true);
19
+ return deduplicateAddons(addons);
20
+ }
21
+ async function walkNodeModules(nodeModulesDir, addons, diagnostics, isRoot) {
22
+ let entries;
23
+ try {
24
+ entries = await fsp.readdir(nodeModulesDir, { withFileTypes: true });
25
+ }
26
+ catch (error) {
27
+ if (isRoot)
28
+ throw new InvalidNodeModulesSourceError(nodeModulesDir, error);
29
+ return;
30
+ }
31
+ for (const entry of entries) {
32
+ if (entry.name.startsWith("."))
33
+ continue;
34
+ if (!isPackageEntry(entry))
35
+ continue;
36
+ if (entry.name.startsWith("@")) {
37
+ await walkScopeDirectory(path.join(nodeModulesDir, entry.name), addons, diagnostics);
38
+ continue;
39
+ }
40
+ await visitPackageDirectory(path.join(nodeModulesDir, entry.name), entry.name, addons, diagnostics);
41
+ }
42
+ }
43
+ async function walkScopeDirectory(scopeDir, addons, diagnostics) {
44
+ const scope = path.basename(scopeDir);
45
+ let entries;
46
+ try {
47
+ entries = await fsp.readdir(scopeDir, { withFileTypes: true });
48
+ }
49
+ catch {
50
+ return;
51
+ }
52
+ for (const entry of entries) {
53
+ if (entry.name.startsWith("."))
54
+ continue;
55
+ if (!isPackageEntry(entry))
56
+ continue;
57
+ await visitPackageDirectory(path.join(scopeDir, entry.name), `${scope}/${entry.name}`, addons, diagnostics);
58
+ }
59
+ }
60
+ function isPackageEntry(entry) {
61
+ return entry.isDirectory() || entry.isSymbolicLink();
62
+ }
63
+ async function visitPackageDirectory(packageDir, packageName, addons, diagnostics) {
64
+ const result = await readAddonPackageJson({
65
+ packageJsonPath: path.join(packageDir, "package.json"),
66
+ expectedName: packageName,
67
+ });
68
+ if (result.isAddon && result.addon) {
69
+ addons.push(result.addon);
70
+ }
71
+ else if (result.invalid !== undefined && diagnostics !== undefined) {
72
+ diagnostics.invalidPackageJsons.push(result.invalid);
73
+ }
74
+ const nestedNodeModules = path.join(packageDir, "node_modules");
75
+ await walkNodeModules(nestedNodeModules, addons, diagnostics, false);
76
+ }
@@ -0,0 +1,15 @@
1
+ import { type NativeAddon } from "./addon-source";
2
+ export interface MissingPrebuildIssue {
3
+ code: "missing-prebuild";
4
+ level: "error";
5
+ addon: string;
6
+ host: string;
7
+ message: string;
8
+ packageRoot: string;
9
+ }
10
+ export interface CheckPrebuildsOptions {
11
+ addon: NativeAddon;
12
+ hosts: string[];
13
+ }
14
+ export declare function checkPrebuilds(options: CheckPrebuildsOptions): Promise<MissingPrebuildIssue[]>;
15
+ //# sourceMappingURL=prebuilds.d.ts.map