@scanoss_test/sdk 2.0.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.
package/dist/index.js ADDED
@@ -0,0 +1,320 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Scanoss: () => Scanoss,
24
+ ScanossError: () => ScanossError,
25
+ getBinaryPath: () => getBinaryPath
26
+ });
27
+ module.exports = __toCommonJS(index_exports);
28
+
29
+ // src/client.ts
30
+ var import_child_process2 = require("child_process");
31
+ var import_protobuf = require("@bufbuild/protobuf");
32
+
33
+ // src/binary.ts
34
+ var import_fs = require("fs");
35
+ var import_child_process = require("child_process");
36
+ var PLATFORMS = [
37
+ "@scanoss_test/linux-x64",
38
+ "@scanoss_test/linux-arm64",
39
+ "@scanoss_test/darwin-x64",
40
+ "@scanoss_test/darwin-arm64",
41
+ "@scanoss_test/win32-x64"
42
+ ];
43
+ function getBinaryPath() {
44
+ for (const platform of PLATFORMS) {
45
+ try {
46
+ const binaryPath = require(platform);
47
+ if ((0, import_fs.existsSync)(binaryPath)) {
48
+ return binaryPath;
49
+ }
50
+ } catch {
51
+ }
52
+ }
53
+ try {
54
+ const pathBinary = (0, import_child_process.execSync)("which scanoss", { encoding: "utf-8" }).trim();
55
+ if (pathBinary && (0, import_fs.existsSync)(pathBinary)) {
56
+ return pathBinary;
57
+ }
58
+ } catch {
59
+ }
60
+ throw new Error(
61
+ "SCANOSS binary not found. The platform-specific package should be installed automatically.\nIf not, install it manually:\n npm install @scanoss_test/linux-x64 # Linux x64\n npm install @scanoss_test/linux-arm64 # Linux ARM64\n npm install @scanoss_test/darwin-x64 # macOS Intel\n npm install @scanoss_test/darwin-arm64 # macOS Apple Silicon\n npm install @scanoss_test/win32-x64 # Windows x64"
62
+ );
63
+ }
64
+
65
+ // src/errors.ts
66
+ var ScanossError = class _ScanossError extends Error {
67
+ /** Error code from the daemon */
68
+ code;
69
+ constructor(code, message) {
70
+ super(`[${code}] ${message}`);
71
+ this.name = "ScanossError";
72
+ this.code = code;
73
+ if (Error.captureStackTrace) {
74
+ Error.captureStackTrace(this, _ScanossError);
75
+ }
76
+ }
77
+ };
78
+
79
+ // src/gen/scanoss/v1/commands_pb.ts
80
+ var import_codegenv23 = require("@bufbuild/protobuf/codegenv2");
81
+
82
+ // src/gen/scanoss/v1/types_pb.ts
83
+ var import_codegenv2 = require("@bufbuild/protobuf/codegenv2");
84
+ var file_scanoss_v1_types = /* @__PURE__ */ (0, import_codegenv2.fileDesc)("ChZzY2Fub3NzL3YxL3R5cGVzLnByb3RvEgpzY2Fub3NzLnYxIkYKCEZpbGVJbmZvEgwKBHBhdGgYASABKAkSDAoEc2l6ZRgCIAEoAxIRCglleHRlbnNpb24YAyABKAkSCwoDbWQ1GAQgASgJItsBCgVNYXRjaBIKCgJpZBgBIAEoCRIRCgljb21wb25lbnQYAiABKAkSDgoGdmVuZG9yGAMgASgJEg8KB3ZlcnNpb24YBCABKAkSFgoObGF0ZXN0X3ZlcnNpb24YBSABKAkSDwoHbGljZW5zZRgGIAEoCRIMCgRwdXJsGAcgASgJEgsKA3VybBgIIAEoCRIMCgRmaWxlGAkgASgJEg8KB21hdGNoZWQYCiABKAkSDQoFbGluZXMYCyABKAkSEQoJb3NzX2xpbmVzGAwgASgJEg0KBXNjb3JlGA0gASgCIksKCkZpbGVSZXN1bHQSDAoEcGF0aBgBIAEoCRILCgNtZDUYAiABKAkSIgoHbWF0Y2hlcxgDIAMoCzIRLnNjYW5vc3MudjEuTWF0Y2giNwoFRXJyb3ISDAoEY29kZRgBIAEoBRIPCgdtZXNzYWdlGAIgASgJEg8KB2RldGFpbHMYAyABKAlCTQoPY29tLnNjYW5vc3MuZ2VuUAFaOGdpdGh1Yi5jb20vc2Nhbm9zcy9zY2Fub3NzL2NvcmUvZ2VuL3NjYW5vc3MvdjE7c2Nhbm9zc3YxYgZwcm90bzM");
85
+
86
+ // src/gen/scanoss/v1/enums_pb.ts
87
+ var import_codegenv22 = require("@bufbuild/protobuf/codegenv2");
88
+ var file_scanoss_v1_enums = /* @__PURE__ */ (0, import_codegenv22.fileDesc)("ChZzY2Fub3NzL3YxL2VudW1zLnByb3RvEgpzY2Fub3NzLnYxKqgBCgxPdXRwdXRGb3JtYXQSHQoZT1VUUFVUX0ZPUk1BVF9VTlNQRUNJRklFRBAAEhYKEk9VVFBVVF9GT1JNQVRfSlNPThABEhYKEk9VVFBVVF9GT1JNQVRfU1BEWBACEhsKF09VVFBVVF9GT1JNQVRfQ1lDTE9ORURYEAMSFQoRT1VUUFVUX0ZPUk1BVF9DU1YQBBIVChFPVVRQVVRfRk9STUFUX1dGUBAFKlYKCFNjYW5UeXBlEhkKFVNDQU5fVFlQRV9VTlNQRUNJRklFRBAAEhYKElNDQU5fVFlQRV9JREVOVElGWRABEhcKE1NDQU5fVFlQRV9CTEFDS0xJU1QQAkJNCg9jb20uc2Nhbm9zcy5nZW5QAVo4Z2l0aHViLmNvbS9zY2Fub3NzL3NjYW5vc3MvY29yZS9nZW4vc2Nhbm9zcy92MTtzY2Fub3NzdjFiBnByb3RvMw");
89
+
90
+ // src/gen/scanoss/v1/commands_pb.ts
91
+ var file_scanoss_v1_commands = /* @__PURE__ */ (0, import_codegenv23.fileDesc)("ChlzY2Fub3NzL3YxL2NvbW1hbmRzLnByb3RvEgpzY2Fub3NzLnYxIqECCgdSZXF1ZXN0EgoKAmlkGAEgASgFEicKBHNjYW4YAiABKAsyFy5zY2Fub3NzLnYxLlNjYW5Db21tYW5kSAASNgoMZmlsdGVyX2ZpbGVzGAMgASgLMh4uc2Nhbm9zcy52MS5GaWx0ZXJGaWxlc0NvbW1hbmRIABI1CgtmaW5nZXJwcmludBgEIAEoCzIeLnNjYW5vc3MudjEuRmluZ2VycHJpbnRDb21tYW5kSAASOAoNZ2VuZXJhdGVfc2JvbRgFIAEoCzIfLnNjYW5vc3MudjEuR2VuZXJhdGVTYm9tQ29tbWFuZEgAEi0KB3ZlcnNpb24YBiABKAsyGi5zY2Fub3NzLnYxLlZlcnNpb25Db21tYW5kSABCCQoHY29tbWFuZCLAAgoIUmVzcG9uc2USCgoCaWQYASABKAUSJgoEc2NhbhgCIAEoCzIWLnNjYW5vc3MudjEuU2NhblJlc3VsdEgAEjUKDGZpbHRlcl9maWxlcxgDIAEoCzIdLnNjYW5vc3MudjEuRmlsdGVyRmlsZXNSZXN1bHRIABI0CgtmaW5nZXJwcmludBgEIAEoCzIdLnNjYW5vc3MudjEuRmluZ2VycHJpbnRSZXN1bHRIABI3Cg1nZW5lcmF0ZV9zYm9tGAUgASgLMh4uc2Nhbm9zcy52MS5HZW5lcmF0ZVNib21SZXN1bHRIABIsCgd2ZXJzaW9uGAYgASgLMhkuc2Nhbm9zcy52MS5WZXJzaW9uUmVzdWx0SAASIgoFZXJyb3IYZCABKAsyES5zY2Fub3NzLnYxLkVycm9ySABCCAoGcmVzdWx0ItgBCgtTY2FuQ29tbWFuZBIMCgRwYXRoGAEgASgJEigKBmZvcm1hdBgCIAEoDjIYLnNjYW5vc3MudjEuT3V0cHV0Rm9ybWF0EicKCXNjYW5fdHlwZRgDIAEoDjIULnNjYW5vc3MudjEuU2NhblR5cGUSDwoHaW5jbHVkZRgEIAMoCRIPCgdleGNsdWRlGAUgAygJEg8KB2FwaV91cmwYBiABKAkSDwoHYXBpX2tleRgHIAEoCRIPCgd0aHJlYWRzGAggASgFEhMKC3NraXBfaGlkZGVuGAkgASgIInsKClNjYW5SZXN1bHQSJQoFZmlsZXMYASADKAsyFi5zY2Fub3NzLnYxLkZpbGVSZXN1bHQSEwoLdG90YWxfZmlsZXMYAiABKAUSGgoSZmlsZXNfd2l0aF9tYXRjaGVzGAMgASgFEhUKDXRvdGFsX21hdGNoZXMYBCABKAUicAoSRmlsdGVyRmlsZXNDb21tYW5kEgwKBHBhdGgYASABKAkSDwoHaW5jbHVkZRgCIAMoCRIPCgdleGNsdWRlGAMgAygJEhMKC3NraXBfaGlkZGVuGAQgASgIEhUKDXNraXBfc3ltbGlua3MYBSABKAgiYgoRRmlsdGVyRmlsZXNSZXN1bHQSIwoFZmlsZXMYASADKAsyFC5zY2Fub3NzLnYxLkZpbGVJbmZvEhMKC3RvdGFsX2NvdW50GAIgASgFEhMKC3RvdGFsX2J5dGVzGAMgASgDIlkKEkZpbmdlcnByaW50Q29tbWFuZBIMCgRwYXRoGAEgASgJEg8KB2luY2x1ZGUYAiADKAkSDwoHZXhjbHVkZRgDIAMoCRITCgtvdXRwdXRfcGF0aBgEIAEoCSJeChFGaW5nZXJwcmludFJlc3VsdBILCgN3ZnAYASABKAkSEwoLb3V0cHV0X3BhdGgYAiABKAkSEgoKZmlsZV9jb3VudBgDIAEoBRITCgt0b3RhbF9ieXRlcxgEIAEoAyKHAQoTR2VuZXJhdGVTYm9tQ29tbWFuZBISCgppbnB1dF9wYXRoGAEgASgJEigKBmZvcm1hdBgCIAEoDjIYLnNjYW5vc3MudjEuT3V0cHV0Rm9ybWF0EhMKC291dHB1dF9wYXRoGAMgASgJEgwKBG5hbWUYBCABKAkSDwoHdmVyc2lvbhgFIAEoCSJ6ChJHZW5lcmF0ZVNib21SZXN1bHQSDAoEc2JvbRgBIAEoCRITCgtvdXRwdXRfcGF0aBgCIAEoCRIoCgZmb3JtYXQYAyABKA4yGC5zY2Fub3NzLnYxLk91dHB1dEZvcm1hdBIXCg9jb21wb25lbnRfY291bnQYBCABKAUiEAoOVmVyc2lvbkNvbW1hbmQiWAoNVmVyc2lvblJlc3VsdBIPCgd2ZXJzaW9uGAEgASgJEg4KBmNvbW1pdBgCIAEoCRISCgpidWlsZF9kYXRlGAMgASgJEhIKCmdvX3ZlcnNpb24YBCABKAlCTQoPY29tLnNjYW5vc3MuZ2VuUAFaOGdpdGh1Yi5jb20vc2Nhbm9zcy9zY2Fub3NzL2NvcmUvZ2VuL3NjYW5vc3MvdjE7c2Nhbm9zc3YxYgZwcm90bzM", [file_scanoss_v1_types, file_scanoss_v1_enums]);
92
+ var RequestSchema = /* @__PURE__ */ (0, import_codegenv23.messageDesc)(file_scanoss_v1_commands, 0);
93
+ var ResponseSchema = /* @__PURE__ */ (0, import_codegenv23.messageDesc)(file_scanoss_v1_commands, 1);
94
+ var ScanCommandSchema = /* @__PURE__ */ (0, import_codegenv23.messageDesc)(file_scanoss_v1_commands, 2);
95
+ var FilterFilesCommandSchema = /* @__PURE__ */ (0, import_codegenv23.messageDesc)(file_scanoss_v1_commands, 4);
96
+ var FingerprintCommandSchema = /* @__PURE__ */ (0, import_codegenv23.messageDesc)(file_scanoss_v1_commands, 6);
97
+ var GenerateSbomCommandSchema = /* @__PURE__ */ (0, import_codegenv23.messageDesc)(file_scanoss_v1_commands, 8);
98
+ var VersionCommandSchema = /* @__PURE__ */ (0, import_codegenv23.messageDesc)(file_scanoss_v1_commands, 10);
99
+
100
+ // src/client.ts
101
+ var Scanoss = class {
102
+ process = null;
103
+ requestId = 0;
104
+ pending = /* @__PURE__ */ new Map();
105
+ binaryPath;
106
+ closed = false;
107
+ buffer = Buffer.alloc(0);
108
+ expectedLength = null;
109
+ constructor(options = {}) {
110
+ this.binaryPath = options.binaryPath ?? getBinaryPath();
111
+ this.start();
112
+ }
113
+ start() {
114
+ this.process = (0, import_child_process2.spawn)(this.binaryPath, ["daemon"], {
115
+ stdio: ["pipe", "pipe", "pipe"]
116
+ });
117
+ this.process.stdout.on("data", (chunk) => {
118
+ this.buffer = Buffer.concat([this.buffer, chunk]);
119
+ this.processBuffer();
120
+ });
121
+ this.process.on("error", (err) => {
122
+ console.error("Daemon process error:", err);
123
+ this.rejectAllPending(err);
124
+ });
125
+ this.process.on("exit", (code) => {
126
+ if (!this.closed) {
127
+ const err = new Error(`Daemon process exited unexpectedly with code ${code}`);
128
+ this.rejectAllPending(err);
129
+ }
130
+ });
131
+ }
132
+ processBuffer() {
133
+ while (true) {
134
+ if (this.expectedLength === null) {
135
+ if (this.buffer.length < 4) {
136
+ return;
137
+ }
138
+ this.expectedLength = this.buffer.readUInt32BE(0);
139
+ this.buffer = this.buffer.subarray(4);
140
+ }
141
+ if (this.buffer.length < this.expectedLength) {
142
+ return;
143
+ }
144
+ const messageData = this.buffer.subarray(0, this.expectedLength);
145
+ this.buffer = this.buffer.subarray(this.expectedLength);
146
+ this.expectedLength = null;
147
+ try {
148
+ const response = (0, import_protobuf.fromBinary)(ResponseSchema, messageData);
149
+ const pending = this.pending.get(response.id);
150
+ if (pending) {
151
+ if (response.result.case === "error") {
152
+ pending.reject(new ScanossError(
153
+ response.result.value.code,
154
+ response.result.value.message
155
+ ));
156
+ } else {
157
+ pending.resolve(response);
158
+ }
159
+ this.pending.delete(response.id);
160
+ }
161
+ } catch (err) {
162
+ console.error("Failed to parse daemon response:", err);
163
+ }
164
+ }
165
+ }
166
+ rejectAllPending(err) {
167
+ for (const pending of this.pending.values()) {
168
+ pending.reject(err);
169
+ }
170
+ this.pending.clear();
171
+ }
172
+ send(request) {
173
+ return new Promise((resolve, reject) => {
174
+ if (!this.process || this.closed) {
175
+ reject(new Error("Daemon process is not running"));
176
+ return;
177
+ }
178
+ this.pending.set(request.id, { resolve, reject });
179
+ const data = (0, import_protobuf.toBinary)(RequestSchema, request);
180
+ const lengthBuf = Buffer.alloc(4);
181
+ lengthBuf.writeUInt32BE(data.length);
182
+ this.process.stdin.write(lengthBuf);
183
+ this.process.stdin.write(data);
184
+ });
185
+ }
186
+ /**
187
+ * Scan files for open source matches.
188
+ */
189
+ async scan(params) {
190
+ const id = ++this.requestId;
191
+ const scanCmd = (0, import_protobuf.create)(ScanCommandSchema, {
192
+ path: params.path,
193
+ format: formatToEnum(params.format ?? "json"),
194
+ scanType: scanTypeToEnum(params.scanType ?? "identify"),
195
+ include: params.include ?? [],
196
+ exclude: params.exclude ?? [],
197
+ apiUrl: params.apiUrl,
198
+ apiKey: params.apiKey
199
+ });
200
+ const request = (0, import_protobuf.create)(RequestSchema, {
201
+ id,
202
+ command: { case: "scan", value: scanCmd }
203
+ });
204
+ const response = await this.send(request);
205
+ if (response.result.case !== "scan") {
206
+ throw new Error("Unexpected response type");
207
+ }
208
+ return response.result.value;
209
+ }
210
+ /**
211
+ * Filter files in a directory.
212
+ */
213
+ async filterFiles(params) {
214
+ const id = ++this.requestId;
215
+ const cmd = (0, import_protobuf.create)(FilterFilesCommandSchema, {
216
+ path: params.path,
217
+ include: params.include ?? [],
218
+ exclude: params.exclude ?? [],
219
+ skipHidden: params.skipHidden ?? true
220
+ });
221
+ const request = (0, import_protobuf.create)(RequestSchema, {
222
+ id,
223
+ command: { case: "filterFiles", value: cmd }
224
+ });
225
+ const response = await this.send(request);
226
+ if (response.result.case !== "filterFiles") {
227
+ throw new Error("Unexpected response type");
228
+ }
229
+ return response.result.value;
230
+ }
231
+ /**
232
+ * Generate WFP fingerprints for files.
233
+ */
234
+ async fingerprint(params) {
235
+ const id = ++this.requestId;
236
+ const cmd = (0, import_protobuf.create)(FingerprintCommandSchema, {
237
+ path: params.path,
238
+ include: params.include ?? [],
239
+ exclude: params.exclude ?? []
240
+ });
241
+ const request = (0, import_protobuf.create)(RequestSchema, {
242
+ id,
243
+ command: { case: "fingerprint", value: cmd }
244
+ });
245
+ const response = await this.send(request);
246
+ if (response.result.case !== "fingerprint") {
247
+ throw new Error("Unexpected response type");
248
+ }
249
+ return response.result.value;
250
+ }
251
+ /**
252
+ * Generate SBOM from scan results.
253
+ */
254
+ async generateSbom(params) {
255
+ const id = ++this.requestId;
256
+ const cmd = (0, import_protobuf.create)(GenerateSbomCommandSchema, {
257
+ inputPath: params.path,
258
+ format: formatToEnum(params.format ?? "spdx")
259
+ });
260
+ const request = (0, import_protobuf.create)(RequestSchema, {
261
+ id,
262
+ command: { case: "generateSbom", value: cmd }
263
+ });
264
+ const response = await this.send(request);
265
+ if (response.result.case !== "generateSbom") {
266
+ throw new Error("Unexpected response type");
267
+ }
268
+ return response.result.value;
269
+ }
270
+ /**
271
+ * Get version information.
272
+ */
273
+ async version() {
274
+ const id = ++this.requestId;
275
+ const cmd = (0, import_protobuf.create)(VersionCommandSchema, {});
276
+ const request = (0, import_protobuf.create)(RequestSchema, {
277
+ id,
278
+ command: { case: "version", value: cmd }
279
+ });
280
+ const response = await this.send(request);
281
+ if (response.result.case !== "version") {
282
+ throw new Error("Unexpected response type");
283
+ }
284
+ return response.result.value;
285
+ }
286
+ /**
287
+ * Close the daemon process.
288
+ */
289
+ async close() {
290
+ this.closed = true;
291
+ if (this.process) {
292
+ this.process.kill();
293
+ this.process = null;
294
+ }
295
+ this.pending.clear();
296
+ }
297
+ };
298
+ function formatToEnum(format) {
299
+ const formats = {
300
+ json: 1 /* JSON */,
301
+ spdx: 2 /* SPDX */,
302
+ cyclonedx: 3 /* CYCLONEDX */,
303
+ csv: 4 /* CSV */,
304
+ wfp: 5 /* WFP */
305
+ };
306
+ return formats[format.toLowerCase()] ?? 1 /* JSON */;
307
+ }
308
+ function scanTypeToEnum(scanType) {
309
+ const types = {
310
+ identify: 1 /* IDENTIFY */,
311
+ blacklist: 2 /* BLACKLIST */
312
+ };
313
+ return types[scanType.toLowerCase()] ?? 1 /* IDENTIFY */;
314
+ }
315
+ // Annotate the CommonJS export names for ESM import in node:
316
+ 0 && (module.exports = {
317
+ Scanoss,
318
+ ScanossError,
319
+ getBinaryPath
320
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,298 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ // src/client.ts
9
+ import { spawn } from "child_process";
10
+ import { create, toBinary, fromBinary } from "@bufbuild/protobuf";
11
+
12
+ // src/binary.ts
13
+ import { existsSync } from "fs";
14
+ import { execSync } from "child_process";
15
+ var PLATFORMS = [
16
+ "@scanoss_test/linux-x64",
17
+ "@scanoss_test/linux-arm64",
18
+ "@scanoss_test/darwin-x64",
19
+ "@scanoss_test/darwin-arm64",
20
+ "@scanoss_test/win32-x64"
21
+ ];
22
+ function getBinaryPath() {
23
+ for (const platform of PLATFORMS) {
24
+ try {
25
+ const binaryPath = __require(platform);
26
+ if (existsSync(binaryPath)) {
27
+ return binaryPath;
28
+ }
29
+ } catch {
30
+ }
31
+ }
32
+ try {
33
+ const pathBinary = execSync("which scanoss", { encoding: "utf-8" }).trim();
34
+ if (pathBinary && existsSync(pathBinary)) {
35
+ return pathBinary;
36
+ }
37
+ } catch {
38
+ }
39
+ throw new Error(
40
+ "SCANOSS binary not found. The platform-specific package should be installed automatically.\nIf not, install it manually:\n npm install @scanoss_test/linux-x64 # Linux x64\n npm install @scanoss_test/linux-arm64 # Linux ARM64\n npm install @scanoss_test/darwin-x64 # macOS Intel\n npm install @scanoss_test/darwin-arm64 # macOS Apple Silicon\n npm install @scanoss_test/win32-x64 # Windows x64"
41
+ );
42
+ }
43
+
44
+ // src/errors.ts
45
+ var ScanossError = class _ScanossError extends Error {
46
+ /** Error code from the daemon */
47
+ code;
48
+ constructor(code, message) {
49
+ super(`[${code}] ${message}`);
50
+ this.name = "ScanossError";
51
+ this.code = code;
52
+ if (Error.captureStackTrace) {
53
+ Error.captureStackTrace(this, _ScanossError);
54
+ }
55
+ }
56
+ };
57
+
58
+ // src/gen/scanoss/v1/commands_pb.ts
59
+ import { fileDesc as fileDesc3, messageDesc as messageDesc2 } from "@bufbuild/protobuf/codegenv2";
60
+
61
+ // src/gen/scanoss/v1/types_pb.ts
62
+ import { fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2";
63
+ var file_scanoss_v1_types = /* @__PURE__ */ fileDesc("ChZzY2Fub3NzL3YxL3R5cGVzLnByb3RvEgpzY2Fub3NzLnYxIkYKCEZpbGVJbmZvEgwKBHBhdGgYASABKAkSDAoEc2l6ZRgCIAEoAxIRCglleHRlbnNpb24YAyABKAkSCwoDbWQ1GAQgASgJItsBCgVNYXRjaBIKCgJpZBgBIAEoCRIRCgljb21wb25lbnQYAiABKAkSDgoGdmVuZG9yGAMgASgJEg8KB3ZlcnNpb24YBCABKAkSFgoObGF0ZXN0X3ZlcnNpb24YBSABKAkSDwoHbGljZW5zZRgGIAEoCRIMCgRwdXJsGAcgASgJEgsKA3VybBgIIAEoCRIMCgRmaWxlGAkgASgJEg8KB21hdGNoZWQYCiABKAkSDQoFbGluZXMYCyABKAkSEQoJb3NzX2xpbmVzGAwgASgJEg0KBXNjb3JlGA0gASgCIksKCkZpbGVSZXN1bHQSDAoEcGF0aBgBIAEoCRILCgNtZDUYAiABKAkSIgoHbWF0Y2hlcxgDIAMoCzIRLnNjYW5vc3MudjEuTWF0Y2giNwoFRXJyb3ISDAoEY29kZRgBIAEoBRIPCgdtZXNzYWdlGAIgASgJEg8KB2RldGFpbHMYAyABKAlCTQoPY29tLnNjYW5vc3MuZ2VuUAFaOGdpdGh1Yi5jb20vc2Nhbm9zcy9zY2Fub3NzL2NvcmUvZ2VuL3NjYW5vc3MvdjE7c2Nhbm9zc3YxYgZwcm90bzM");
64
+
65
+ // src/gen/scanoss/v1/enums_pb.ts
66
+ import { enumDesc, fileDesc as fileDesc2 } from "@bufbuild/protobuf/codegenv2";
67
+ var file_scanoss_v1_enums = /* @__PURE__ */ fileDesc2("ChZzY2Fub3NzL3YxL2VudW1zLnByb3RvEgpzY2Fub3NzLnYxKqgBCgxPdXRwdXRGb3JtYXQSHQoZT1VUUFVUX0ZPUk1BVF9VTlNQRUNJRklFRBAAEhYKEk9VVFBVVF9GT1JNQVRfSlNPThABEhYKEk9VVFBVVF9GT1JNQVRfU1BEWBACEhsKF09VVFBVVF9GT1JNQVRfQ1lDTE9ORURYEAMSFQoRT1VUUFVUX0ZPUk1BVF9DU1YQBBIVChFPVVRQVVRfRk9STUFUX1dGUBAFKlYKCFNjYW5UeXBlEhkKFVNDQU5fVFlQRV9VTlNQRUNJRklFRBAAEhYKElNDQU5fVFlQRV9JREVOVElGWRABEhcKE1NDQU5fVFlQRV9CTEFDS0xJU1QQAkJNCg9jb20uc2Nhbm9zcy5nZW5QAVo4Z2l0aHViLmNvbS9zY2Fub3NzL3NjYW5vc3MvY29yZS9nZW4vc2Nhbm9zcy92MTtzY2Fub3NzdjFiBnByb3RvMw");
68
+
69
+ // src/gen/scanoss/v1/commands_pb.ts
70
+ var file_scanoss_v1_commands = /* @__PURE__ */ fileDesc3("ChlzY2Fub3NzL3YxL2NvbW1hbmRzLnByb3RvEgpzY2Fub3NzLnYxIqECCgdSZXF1ZXN0EgoKAmlkGAEgASgFEicKBHNjYW4YAiABKAsyFy5zY2Fub3NzLnYxLlNjYW5Db21tYW5kSAASNgoMZmlsdGVyX2ZpbGVzGAMgASgLMh4uc2Nhbm9zcy52MS5GaWx0ZXJGaWxlc0NvbW1hbmRIABI1CgtmaW5nZXJwcmludBgEIAEoCzIeLnNjYW5vc3MudjEuRmluZ2VycHJpbnRDb21tYW5kSAASOAoNZ2VuZXJhdGVfc2JvbRgFIAEoCzIfLnNjYW5vc3MudjEuR2VuZXJhdGVTYm9tQ29tbWFuZEgAEi0KB3ZlcnNpb24YBiABKAsyGi5zY2Fub3NzLnYxLlZlcnNpb25Db21tYW5kSABCCQoHY29tbWFuZCLAAgoIUmVzcG9uc2USCgoCaWQYASABKAUSJgoEc2NhbhgCIAEoCzIWLnNjYW5vc3MudjEuU2NhblJlc3VsdEgAEjUKDGZpbHRlcl9maWxlcxgDIAEoCzIdLnNjYW5vc3MudjEuRmlsdGVyRmlsZXNSZXN1bHRIABI0CgtmaW5nZXJwcmludBgEIAEoCzIdLnNjYW5vc3MudjEuRmluZ2VycHJpbnRSZXN1bHRIABI3Cg1nZW5lcmF0ZV9zYm9tGAUgASgLMh4uc2Nhbm9zcy52MS5HZW5lcmF0ZVNib21SZXN1bHRIABIsCgd2ZXJzaW9uGAYgASgLMhkuc2Nhbm9zcy52MS5WZXJzaW9uUmVzdWx0SAASIgoFZXJyb3IYZCABKAsyES5zY2Fub3NzLnYxLkVycm9ySABCCAoGcmVzdWx0ItgBCgtTY2FuQ29tbWFuZBIMCgRwYXRoGAEgASgJEigKBmZvcm1hdBgCIAEoDjIYLnNjYW5vc3MudjEuT3V0cHV0Rm9ybWF0EicKCXNjYW5fdHlwZRgDIAEoDjIULnNjYW5vc3MudjEuU2NhblR5cGUSDwoHaW5jbHVkZRgEIAMoCRIPCgdleGNsdWRlGAUgAygJEg8KB2FwaV91cmwYBiABKAkSDwoHYXBpX2tleRgHIAEoCRIPCgd0aHJlYWRzGAggASgFEhMKC3NraXBfaGlkZGVuGAkgASgIInsKClNjYW5SZXN1bHQSJQoFZmlsZXMYASADKAsyFi5zY2Fub3NzLnYxLkZpbGVSZXN1bHQSEwoLdG90YWxfZmlsZXMYAiABKAUSGgoSZmlsZXNfd2l0aF9tYXRjaGVzGAMgASgFEhUKDXRvdGFsX21hdGNoZXMYBCABKAUicAoSRmlsdGVyRmlsZXNDb21tYW5kEgwKBHBhdGgYASABKAkSDwoHaW5jbHVkZRgCIAMoCRIPCgdleGNsdWRlGAMgAygJEhMKC3NraXBfaGlkZGVuGAQgASgIEhUKDXNraXBfc3ltbGlua3MYBSABKAgiYgoRRmlsdGVyRmlsZXNSZXN1bHQSIwoFZmlsZXMYASADKAsyFC5zY2Fub3NzLnYxLkZpbGVJbmZvEhMKC3RvdGFsX2NvdW50GAIgASgFEhMKC3RvdGFsX2J5dGVzGAMgASgDIlkKEkZpbmdlcnByaW50Q29tbWFuZBIMCgRwYXRoGAEgASgJEg8KB2luY2x1ZGUYAiADKAkSDwoHZXhjbHVkZRgDIAMoCRITCgtvdXRwdXRfcGF0aBgEIAEoCSJeChFGaW5nZXJwcmludFJlc3VsdBILCgN3ZnAYASABKAkSEwoLb3V0cHV0X3BhdGgYAiABKAkSEgoKZmlsZV9jb3VudBgDIAEoBRITCgt0b3RhbF9ieXRlcxgEIAEoAyKHAQoTR2VuZXJhdGVTYm9tQ29tbWFuZBISCgppbnB1dF9wYXRoGAEgASgJEigKBmZvcm1hdBgCIAEoDjIYLnNjYW5vc3MudjEuT3V0cHV0Rm9ybWF0EhMKC291dHB1dF9wYXRoGAMgASgJEgwKBG5hbWUYBCABKAkSDwoHdmVyc2lvbhgFIAEoCSJ6ChJHZW5lcmF0ZVNib21SZXN1bHQSDAoEc2JvbRgBIAEoCRITCgtvdXRwdXRfcGF0aBgCIAEoCRIoCgZmb3JtYXQYAyABKA4yGC5zY2Fub3NzLnYxLk91dHB1dEZvcm1hdBIXCg9jb21wb25lbnRfY291bnQYBCABKAUiEAoOVmVyc2lvbkNvbW1hbmQiWAoNVmVyc2lvblJlc3VsdBIPCgd2ZXJzaW9uGAEgASgJEg4KBmNvbW1pdBgCIAEoCRISCgpidWlsZF9kYXRlGAMgASgJEhIKCmdvX3ZlcnNpb24YBCABKAlCTQoPY29tLnNjYW5vc3MuZ2VuUAFaOGdpdGh1Yi5jb20vc2Nhbm9zcy9zY2Fub3NzL2NvcmUvZ2VuL3NjYW5vc3MvdjE7c2Nhbm9zc3YxYgZwcm90bzM", [file_scanoss_v1_types, file_scanoss_v1_enums]);
71
+ var RequestSchema = /* @__PURE__ */ messageDesc2(file_scanoss_v1_commands, 0);
72
+ var ResponseSchema = /* @__PURE__ */ messageDesc2(file_scanoss_v1_commands, 1);
73
+ var ScanCommandSchema = /* @__PURE__ */ messageDesc2(file_scanoss_v1_commands, 2);
74
+ var FilterFilesCommandSchema = /* @__PURE__ */ messageDesc2(file_scanoss_v1_commands, 4);
75
+ var FingerprintCommandSchema = /* @__PURE__ */ messageDesc2(file_scanoss_v1_commands, 6);
76
+ var GenerateSbomCommandSchema = /* @__PURE__ */ messageDesc2(file_scanoss_v1_commands, 8);
77
+ var VersionCommandSchema = /* @__PURE__ */ messageDesc2(file_scanoss_v1_commands, 10);
78
+
79
+ // src/client.ts
80
+ var Scanoss = class {
81
+ process = null;
82
+ requestId = 0;
83
+ pending = /* @__PURE__ */ new Map();
84
+ binaryPath;
85
+ closed = false;
86
+ buffer = Buffer.alloc(0);
87
+ expectedLength = null;
88
+ constructor(options = {}) {
89
+ this.binaryPath = options.binaryPath ?? getBinaryPath();
90
+ this.start();
91
+ }
92
+ start() {
93
+ this.process = spawn(this.binaryPath, ["daemon"], {
94
+ stdio: ["pipe", "pipe", "pipe"]
95
+ });
96
+ this.process.stdout.on("data", (chunk) => {
97
+ this.buffer = Buffer.concat([this.buffer, chunk]);
98
+ this.processBuffer();
99
+ });
100
+ this.process.on("error", (err) => {
101
+ console.error("Daemon process error:", err);
102
+ this.rejectAllPending(err);
103
+ });
104
+ this.process.on("exit", (code) => {
105
+ if (!this.closed) {
106
+ const err = new Error(`Daemon process exited unexpectedly with code ${code}`);
107
+ this.rejectAllPending(err);
108
+ }
109
+ });
110
+ }
111
+ processBuffer() {
112
+ while (true) {
113
+ if (this.expectedLength === null) {
114
+ if (this.buffer.length < 4) {
115
+ return;
116
+ }
117
+ this.expectedLength = this.buffer.readUInt32BE(0);
118
+ this.buffer = this.buffer.subarray(4);
119
+ }
120
+ if (this.buffer.length < this.expectedLength) {
121
+ return;
122
+ }
123
+ const messageData = this.buffer.subarray(0, this.expectedLength);
124
+ this.buffer = this.buffer.subarray(this.expectedLength);
125
+ this.expectedLength = null;
126
+ try {
127
+ const response = fromBinary(ResponseSchema, messageData);
128
+ const pending = this.pending.get(response.id);
129
+ if (pending) {
130
+ if (response.result.case === "error") {
131
+ pending.reject(new ScanossError(
132
+ response.result.value.code,
133
+ response.result.value.message
134
+ ));
135
+ } else {
136
+ pending.resolve(response);
137
+ }
138
+ this.pending.delete(response.id);
139
+ }
140
+ } catch (err) {
141
+ console.error("Failed to parse daemon response:", err);
142
+ }
143
+ }
144
+ }
145
+ rejectAllPending(err) {
146
+ for (const pending of this.pending.values()) {
147
+ pending.reject(err);
148
+ }
149
+ this.pending.clear();
150
+ }
151
+ send(request) {
152
+ return new Promise((resolve, reject) => {
153
+ if (!this.process || this.closed) {
154
+ reject(new Error("Daemon process is not running"));
155
+ return;
156
+ }
157
+ this.pending.set(request.id, { resolve, reject });
158
+ const data = toBinary(RequestSchema, request);
159
+ const lengthBuf = Buffer.alloc(4);
160
+ lengthBuf.writeUInt32BE(data.length);
161
+ this.process.stdin.write(lengthBuf);
162
+ this.process.stdin.write(data);
163
+ });
164
+ }
165
+ /**
166
+ * Scan files for open source matches.
167
+ */
168
+ async scan(params) {
169
+ const id = ++this.requestId;
170
+ const scanCmd = create(ScanCommandSchema, {
171
+ path: params.path,
172
+ format: formatToEnum(params.format ?? "json"),
173
+ scanType: scanTypeToEnum(params.scanType ?? "identify"),
174
+ include: params.include ?? [],
175
+ exclude: params.exclude ?? [],
176
+ apiUrl: params.apiUrl,
177
+ apiKey: params.apiKey
178
+ });
179
+ const request = create(RequestSchema, {
180
+ id,
181
+ command: { case: "scan", value: scanCmd }
182
+ });
183
+ const response = await this.send(request);
184
+ if (response.result.case !== "scan") {
185
+ throw new Error("Unexpected response type");
186
+ }
187
+ return response.result.value;
188
+ }
189
+ /**
190
+ * Filter files in a directory.
191
+ */
192
+ async filterFiles(params) {
193
+ const id = ++this.requestId;
194
+ const cmd = create(FilterFilesCommandSchema, {
195
+ path: params.path,
196
+ include: params.include ?? [],
197
+ exclude: params.exclude ?? [],
198
+ skipHidden: params.skipHidden ?? true
199
+ });
200
+ const request = create(RequestSchema, {
201
+ id,
202
+ command: { case: "filterFiles", value: cmd }
203
+ });
204
+ const response = await this.send(request);
205
+ if (response.result.case !== "filterFiles") {
206
+ throw new Error("Unexpected response type");
207
+ }
208
+ return response.result.value;
209
+ }
210
+ /**
211
+ * Generate WFP fingerprints for files.
212
+ */
213
+ async fingerprint(params) {
214
+ const id = ++this.requestId;
215
+ const cmd = create(FingerprintCommandSchema, {
216
+ path: params.path,
217
+ include: params.include ?? [],
218
+ exclude: params.exclude ?? []
219
+ });
220
+ const request = create(RequestSchema, {
221
+ id,
222
+ command: { case: "fingerprint", value: cmd }
223
+ });
224
+ const response = await this.send(request);
225
+ if (response.result.case !== "fingerprint") {
226
+ throw new Error("Unexpected response type");
227
+ }
228
+ return response.result.value;
229
+ }
230
+ /**
231
+ * Generate SBOM from scan results.
232
+ */
233
+ async generateSbom(params) {
234
+ const id = ++this.requestId;
235
+ const cmd = create(GenerateSbomCommandSchema, {
236
+ inputPath: params.path,
237
+ format: formatToEnum(params.format ?? "spdx")
238
+ });
239
+ const request = create(RequestSchema, {
240
+ id,
241
+ command: { case: "generateSbom", value: cmd }
242
+ });
243
+ const response = await this.send(request);
244
+ if (response.result.case !== "generateSbom") {
245
+ throw new Error("Unexpected response type");
246
+ }
247
+ return response.result.value;
248
+ }
249
+ /**
250
+ * Get version information.
251
+ */
252
+ async version() {
253
+ const id = ++this.requestId;
254
+ const cmd = create(VersionCommandSchema, {});
255
+ const request = create(RequestSchema, {
256
+ id,
257
+ command: { case: "version", value: cmd }
258
+ });
259
+ const response = await this.send(request);
260
+ if (response.result.case !== "version") {
261
+ throw new Error("Unexpected response type");
262
+ }
263
+ return response.result.value;
264
+ }
265
+ /**
266
+ * Close the daemon process.
267
+ */
268
+ async close() {
269
+ this.closed = true;
270
+ if (this.process) {
271
+ this.process.kill();
272
+ this.process = null;
273
+ }
274
+ this.pending.clear();
275
+ }
276
+ };
277
+ function formatToEnum(format) {
278
+ const formats = {
279
+ json: 1 /* JSON */,
280
+ spdx: 2 /* SPDX */,
281
+ cyclonedx: 3 /* CYCLONEDX */,
282
+ csv: 4 /* CSV */,
283
+ wfp: 5 /* WFP */
284
+ };
285
+ return formats[format.toLowerCase()] ?? 1 /* JSON */;
286
+ }
287
+ function scanTypeToEnum(scanType) {
288
+ const types = {
289
+ identify: 1 /* IDENTIFY */,
290
+ blacklist: 2 /* BLACKLIST */
291
+ };
292
+ return types[scanType.toLowerCase()] ?? 1 /* IDENTIFY */;
293
+ }
294
+ export {
295
+ Scanoss,
296
+ ScanossError,
297
+ getBinaryPath
298
+ };
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@scanoss_test/sdk",
3
+ "version": "2.0.1",
4
+ "description": "SCANOSS SDK for Software Composition Analysis",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.mjs",
11
+ "require": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "bin",
18
+ "src"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsup src/index.ts --format cjs,esm --dts",
22
+ "test": "vitest run",
23
+ "test:watch": "vitest",
24
+ "lint": "eslint src --ext .ts",
25
+ "typecheck": "tsc --noEmit",
26
+ "prepublishOnly": "npm run build"
27
+ },
28
+ "keywords": [
29
+ "scanoss",
30
+ "sca",
31
+ "software composition analysis",
32
+ "open source",
33
+ "license",
34
+ "sbom",
35
+ "security"
36
+ ],
37
+ "author": "SCANOSS <info@scanoss.com>",
38
+ "license": "MIT",
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/scanoss/scanoss.lib.git"
42
+ },
43
+ "bugs": {
44
+ "url": "https://github.com/scanoss/scanoss.lib/issues"
45
+ },
46
+ "homepage": "https://scanoss.com",
47
+ "engines": {
48
+ "node": ">=18.0.0"
49
+ },
50
+ "devDependencies": {
51
+ "@types/node": "^20.10.0",
52
+ "eslint": "^8.56.0",
53
+ "tsup": "^8.0.0",
54
+ "typescript": "^5.3.0",
55
+ "vitest": "^1.0.0"
56
+ },
57
+ "dependencies": {
58
+ "@bufbuild/protobuf": "^2.10.2"
59
+ },
60
+ "optionalDependencies": {
61
+ "@scanoss_test/darwin-arm64": "2.0.1",
62
+ "@scanoss_test/darwin-x64": "2.0.1",
63
+ "@scanoss_test/linux-arm64": "2.0.1",
64
+ "@scanoss_test/linux-x64": "2.0.1",
65
+ "@scanoss_test/win32-x64": "2.0.1"
66
+ }
67
+ }