@ceon-oy/monitor-sdk 1.0.14 → 1.0.16

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.d.mts CHANGED
@@ -43,11 +43,16 @@ interface MonitorClientConfig {
43
43
  auditPaths?: AuditPath[];
44
44
  /** Include devDependencies when tracking dependencies (default: false) */
45
45
  includeDevDependencies?: boolean;
46
+ /** Enable fetching latest versions from npm registry (default: true) */
47
+ versionCheckEnabled?: boolean;
48
+ /** Timeout for npm audit command in ms (default: 60000, max: 300000) */
49
+ auditTimeoutMs?: number;
46
50
  }
47
51
  interface TechnologyItem {
48
52
  name: string;
49
53
  version: string;
50
54
  type?: TechnologyType;
55
+ latestVersion?: string;
51
56
  }
52
57
  interface ErrorContext {
53
58
  severity?: Severity;
@@ -178,6 +183,8 @@ declare class MonitorClient {
178
183
  private lastScanTime;
179
184
  private lastKnownScanRequestedAt;
180
185
  private lastKnownTechScanRequestedAt;
186
+ private versionCheckEnabled;
187
+ private auditTimeoutMs;
181
188
  constructor(config: MonitorClientConfig);
182
189
  /**
183
190
  * Security: Validate and sanitize metadata to prevent oversized payloads
@@ -229,10 +236,24 @@ declare class MonitorClient {
229
236
  private startFlushTimer;
230
237
  private stopFlushTimer;
231
238
  syncDependencies(): Promise<void>;
239
+ /**
240
+ * Enrich technologies with latest version information from npm registry.
241
+ * Only runs if versionCheckEnabled is true.
242
+ */
243
+ private enrichWithLatestVersions;
232
244
  syncTechnologies(technologies: TechnologyItem[]): Promise<void>;
233
245
  private readPackageJson;
234
246
  private readPackageJsonFromPath;
235
247
  private shouldExclude;
248
+ /**
249
+ * Fetch the latest version of a package from npm registry.
250
+ * Returns null if the package cannot be found or the request fails.
251
+ */
252
+ private fetchLatestVersion;
253
+ /**
254
+ * Fetch latest versions for multiple packages in parallel with concurrency limit.
255
+ */
256
+ private fetchLatestVersions;
236
257
  private sendTechnologies;
237
258
  private sendTechnologiesWithEnvironment;
238
259
  /**
package/dist/index.d.ts CHANGED
@@ -43,11 +43,16 @@ interface MonitorClientConfig {
43
43
  auditPaths?: AuditPath[];
44
44
  /** Include devDependencies when tracking dependencies (default: false) */
45
45
  includeDevDependencies?: boolean;
46
+ /** Enable fetching latest versions from npm registry (default: true) */
47
+ versionCheckEnabled?: boolean;
48
+ /** Timeout for npm audit command in ms (default: 60000, max: 300000) */
49
+ auditTimeoutMs?: number;
46
50
  }
47
51
  interface TechnologyItem {
48
52
  name: string;
49
53
  version: string;
50
54
  type?: TechnologyType;
55
+ latestVersion?: string;
51
56
  }
52
57
  interface ErrorContext {
53
58
  severity?: Severity;
@@ -178,6 +183,8 @@ declare class MonitorClient {
178
183
  private lastScanTime;
179
184
  private lastKnownScanRequestedAt;
180
185
  private lastKnownTechScanRequestedAt;
186
+ private versionCheckEnabled;
187
+ private auditTimeoutMs;
181
188
  constructor(config: MonitorClientConfig);
182
189
  /**
183
190
  * Security: Validate and sanitize metadata to prevent oversized payloads
@@ -229,10 +236,24 @@ declare class MonitorClient {
229
236
  private startFlushTimer;
230
237
  private stopFlushTimer;
231
238
  syncDependencies(): Promise<void>;
239
+ /**
240
+ * Enrich technologies with latest version information from npm registry.
241
+ * Only runs if versionCheckEnabled is true.
242
+ */
243
+ private enrichWithLatestVersions;
232
244
  syncTechnologies(technologies: TechnologyItem[]): Promise<void>;
233
245
  private readPackageJson;
234
246
  private readPackageJsonFromPath;
235
247
  private shouldExclude;
248
+ /**
249
+ * Fetch the latest version of a package from npm registry.
250
+ * Returns null if the package cannot be found or the request fails.
251
+ */
252
+ private fetchLatestVersion;
253
+ /**
254
+ * Fetch latest versions for multiple packages in parallel with concurrency limit.
255
+ */
256
+ private fetchLatestVersions;
236
257
  private sendTechnologies;
237
258
  private sendTechnologiesWithEnvironment;
238
259
  /**
package/dist/index.js CHANGED
@@ -50,7 +50,9 @@ var CONFIG_LIMITS = {
50
50
  AUDIT_MAX_BUFFER: 10 * 1024 * 1024,
51
51
  // 10MB
52
52
  AUDIT_TIMEOUT_MS: 6e4,
53
- // 60 seconds
53
+ // 60 seconds (default)
54
+ MAX_AUDIT_TIMEOUT_MS: 3e5,
55
+ // 5 minutes (max configurable)
54
56
  SETTINGS_POLL_INTERVAL_MS: 5 * 60 * 1e3
55
57
  // 5 minutes
56
58
  };
@@ -117,6 +119,8 @@ var MonitorClient = class {
117
119
  this.autoAudit = config.autoAudit || false;
118
120
  this.auditPaths = config.auditPaths;
119
121
  this.includeDevDependencies = config.includeDevDependencies ?? false;
122
+ this.versionCheckEnabled = config.versionCheckEnabled ?? true;
123
+ this.auditTimeoutMs = Math.min(CONFIG_LIMITS.MAX_AUDIT_TIMEOUT_MS, Math.max(1e3, config.auditTimeoutMs || CONFIG_LIMITS.AUDIT_TIMEOUT_MS));
120
124
  this.startFlushTimer();
121
125
  if (this.trackDependencies) {
122
126
  this.syncDependencies().catch((err) => {
@@ -437,17 +441,40 @@ var MonitorClient = class {
437
441
  for (const source of this.dependencySources) {
438
442
  const technologies = await this.readPackageJsonFromPath(source.path);
439
443
  if (technologies.length === 0) continue;
440
- await this.sendTechnologiesWithEnvironment(technologies, source.environment);
444
+ const enrichedTechnologies = await this.enrichWithLatestVersions(technologies);
445
+ await this.sendTechnologiesWithEnvironment(enrichedTechnologies, source.environment);
441
446
  }
442
447
  } else {
443
448
  const technologies = await this.readPackageJson();
444
449
  if (technologies.length === 0) return;
445
- await this.sendTechnologies(technologies);
450
+ const enrichedTechnologies = await this.enrichWithLatestVersions(technologies);
451
+ await this.sendTechnologies(enrichedTechnologies);
446
452
  }
447
453
  } catch (err) {
448
454
  console.error("[MonitorClient] Failed to sync dependencies:", err);
449
455
  }
450
456
  }
457
+ /**
458
+ * Enrich technologies with latest version information from npm registry.
459
+ * Only runs if versionCheckEnabled is true.
460
+ */
461
+ async enrichWithLatestVersions(technologies) {
462
+ if (!this.versionCheckEnabled) {
463
+ return technologies;
464
+ }
465
+ try {
466
+ console.log(`[MonitorClient] Fetching latest versions for ${technologies.length} packages...`);
467
+ const packageNames = technologies.map((t) => t.name);
468
+ const latestVersions = await this.fetchLatestVersions(packageNames);
469
+ return technologies.map((tech) => ({
470
+ ...tech,
471
+ latestVersion: latestVersions.get(tech.name) || void 0
472
+ }));
473
+ } catch (err) {
474
+ console.warn("[MonitorClient] Failed to fetch latest versions, continuing without:", err instanceof Error ? err.message : String(err));
475
+ return technologies;
476
+ }
477
+ }
451
478
  async syncTechnologies(technologies) {
452
479
  await this.sendTechnologies(technologies);
453
480
  }
@@ -514,6 +541,44 @@ var MonitorClient = class {
514
541
  }
515
542
  return false;
516
543
  }
544
+ /**
545
+ * Fetch the latest version of a package from npm registry.
546
+ * Returns null if the package cannot be found or the request fails.
547
+ */
548
+ async fetchLatestVersion(packageName) {
549
+ try {
550
+ const encodedName = encodeURIComponent(packageName).replace("%40", "@");
551
+ const response = await fetch(`https://registry.npmjs.org/${encodedName}`, {
552
+ headers: { "Accept": "application/json" },
553
+ signal: AbortSignal.timeout(5e3)
554
+ });
555
+ if (!response.ok) return null;
556
+ const data = await response.json();
557
+ return data["dist-tags"]?.latest || null;
558
+ } catch {
559
+ return null;
560
+ }
561
+ }
562
+ /**
563
+ * Fetch latest versions for multiple packages in parallel with concurrency limit.
564
+ */
565
+ async fetchLatestVersions(packageNames) {
566
+ const results = /* @__PURE__ */ new Map();
567
+ const concurrencyLimit = 5;
568
+ for (let i = 0; i < packageNames.length; i += concurrencyLimit) {
569
+ const batch = packageNames.slice(i, i + concurrencyLimit);
570
+ const batchResults = await Promise.all(
571
+ batch.map(async (name) => ({
572
+ name,
573
+ version: await this.fetchLatestVersion(name)
574
+ }))
575
+ );
576
+ for (const { name, version } of batchResults) {
577
+ results.set(name, version);
578
+ }
579
+ }
580
+ return results;
581
+ }
517
582
  async sendTechnologies(technologies) {
518
583
  await this.sendTechnologiesWithEnvironment(technologies, this.environment);
519
584
  }
@@ -708,7 +773,7 @@ var MonitorClient = class {
708
773
  encoding: "utf-8",
709
774
  stdio: ["pipe", "pipe", "pipe"],
710
775
  maxBuffer: CONFIG_LIMITS.AUDIT_MAX_BUFFER,
711
- timeout: CONFIG_LIMITS.AUDIT_TIMEOUT_MS
776
+ timeout: this.auditTimeoutMs
712
777
  });
713
778
  } catch (err) {
714
779
  const execError = err;
@@ -742,7 +807,7 @@ var MonitorClient = class {
742
807
  encoding: "utf-8",
743
808
  stdio: ["pipe", "pipe", "pipe"],
744
809
  maxBuffer: CONFIG_LIMITS.AUDIT_MAX_BUFFER,
745
- timeout: CONFIG_LIMITS.AUDIT_TIMEOUT_MS
810
+ timeout: this.auditTimeoutMs
746
811
  });
747
812
  } catch (err) {
748
813
  const execError = err;
@@ -766,7 +831,7 @@ var MonitorClient = class {
766
831
  encoding: "utf-8",
767
832
  stdio: ["pipe", "pipe", "pipe"],
768
833
  maxBuffer: CONFIG_LIMITS.AUDIT_MAX_BUFFER,
769
- timeout: CONFIG_LIMITS.AUDIT_TIMEOUT_MS
834
+ timeout: this.auditTimeoutMs
770
835
  });
771
836
  } catch (err) {
772
837
  const execError = err;
package/dist/index.mjs CHANGED
@@ -14,7 +14,9 @@ var CONFIG_LIMITS = {
14
14
  AUDIT_MAX_BUFFER: 10 * 1024 * 1024,
15
15
  // 10MB
16
16
  AUDIT_TIMEOUT_MS: 6e4,
17
- // 60 seconds
17
+ // 60 seconds (default)
18
+ MAX_AUDIT_TIMEOUT_MS: 3e5,
19
+ // 5 minutes (max configurable)
18
20
  SETTINGS_POLL_INTERVAL_MS: 5 * 60 * 1e3
19
21
  // 5 minutes
20
22
  };
@@ -81,6 +83,8 @@ var MonitorClient = class {
81
83
  this.autoAudit = config.autoAudit || false;
82
84
  this.auditPaths = config.auditPaths;
83
85
  this.includeDevDependencies = config.includeDevDependencies ?? false;
86
+ this.versionCheckEnabled = config.versionCheckEnabled ?? true;
87
+ this.auditTimeoutMs = Math.min(CONFIG_LIMITS.MAX_AUDIT_TIMEOUT_MS, Math.max(1e3, config.auditTimeoutMs || CONFIG_LIMITS.AUDIT_TIMEOUT_MS));
84
88
  this.startFlushTimer();
85
89
  if (this.trackDependencies) {
86
90
  this.syncDependencies().catch((err) => {
@@ -401,17 +405,40 @@ var MonitorClient = class {
401
405
  for (const source of this.dependencySources) {
402
406
  const technologies = await this.readPackageJsonFromPath(source.path);
403
407
  if (technologies.length === 0) continue;
404
- await this.sendTechnologiesWithEnvironment(technologies, source.environment);
408
+ const enrichedTechnologies = await this.enrichWithLatestVersions(technologies);
409
+ await this.sendTechnologiesWithEnvironment(enrichedTechnologies, source.environment);
405
410
  }
406
411
  } else {
407
412
  const technologies = await this.readPackageJson();
408
413
  if (technologies.length === 0) return;
409
- await this.sendTechnologies(technologies);
414
+ const enrichedTechnologies = await this.enrichWithLatestVersions(technologies);
415
+ await this.sendTechnologies(enrichedTechnologies);
410
416
  }
411
417
  } catch (err) {
412
418
  console.error("[MonitorClient] Failed to sync dependencies:", err);
413
419
  }
414
420
  }
421
+ /**
422
+ * Enrich technologies with latest version information from npm registry.
423
+ * Only runs if versionCheckEnabled is true.
424
+ */
425
+ async enrichWithLatestVersions(technologies) {
426
+ if (!this.versionCheckEnabled) {
427
+ return technologies;
428
+ }
429
+ try {
430
+ console.log(`[MonitorClient] Fetching latest versions for ${technologies.length} packages...`);
431
+ const packageNames = technologies.map((t) => t.name);
432
+ const latestVersions = await this.fetchLatestVersions(packageNames);
433
+ return technologies.map((tech) => ({
434
+ ...tech,
435
+ latestVersion: latestVersions.get(tech.name) || void 0
436
+ }));
437
+ } catch (err) {
438
+ console.warn("[MonitorClient] Failed to fetch latest versions, continuing without:", err instanceof Error ? err.message : String(err));
439
+ return technologies;
440
+ }
441
+ }
415
442
  async syncTechnologies(technologies) {
416
443
  await this.sendTechnologies(technologies);
417
444
  }
@@ -478,6 +505,44 @@ var MonitorClient = class {
478
505
  }
479
506
  return false;
480
507
  }
508
+ /**
509
+ * Fetch the latest version of a package from npm registry.
510
+ * Returns null if the package cannot be found or the request fails.
511
+ */
512
+ async fetchLatestVersion(packageName) {
513
+ try {
514
+ const encodedName = encodeURIComponent(packageName).replace("%40", "@");
515
+ const response = await fetch(`https://registry.npmjs.org/${encodedName}`, {
516
+ headers: { "Accept": "application/json" },
517
+ signal: AbortSignal.timeout(5e3)
518
+ });
519
+ if (!response.ok) return null;
520
+ const data = await response.json();
521
+ return data["dist-tags"]?.latest || null;
522
+ } catch {
523
+ return null;
524
+ }
525
+ }
526
+ /**
527
+ * Fetch latest versions for multiple packages in parallel with concurrency limit.
528
+ */
529
+ async fetchLatestVersions(packageNames) {
530
+ const results = /* @__PURE__ */ new Map();
531
+ const concurrencyLimit = 5;
532
+ for (let i = 0; i < packageNames.length; i += concurrencyLimit) {
533
+ const batch = packageNames.slice(i, i + concurrencyLimit);
534
+ const batchResults = await Promise.all(
535
+ batch.map(async (name) => ({
536
+ name,
537
+ version: await this.fetchLatestVersion(name)
538
+ }))
539
+ );
540
+ for (const { name, version } of batchResults) {
541
+ results.set(name, version);
542
+ }
543
+ }
544
+ return results;
545
+ }
481
546
  async sendTechnologies(technologies) {
482
547
  await this.sendTechnologiesWithEnvironment(technologies, this.environment);
483
548
  }
@@ -672,7 +737,7 @@ var MonitorClient = class {
672
737
  encoding: "utf-8",
673
738
  stdio: ["pipe", "pipe", "pipe"],
674
739
  maxBuffer: CONFIG_LIMITS.AUDIT_MAX_BUFFER,
675
- timeout: CONFIG_LIMITS.AUDIT_TIMEOUT_MS
740
+ timeout: this.auditTimeoutMs
676
741
  });
677
742
  } catch (err) {
678
743
  const execError = err;
@@ -706,7 +771,7 @@ var MonitorClient = class {
706
771
  encoding: "utf-8",
707
772
  stdio: ["pipe", "pipe", "pipe"],
708
773
  maxBuffer: CONFIG_LIMITS.AUDIT_MAX_BUFFER,
709
- timeout: CONFIG_LIMITS.AUDIT_TIMEOUT_MS
774
+ timeout: this.auditTimeoutMs
710
775
  });
711
776
  } catch (err) {
712
777
  const execError = err;
@@ -730,7 +795,7 @@ var MonitorClient = class {
730
795
  encoding: "utf-8",
731
796
  stdio: ["pipe", "pipe", "pipe"],
732
797
  maxBuffer: CONFIG_LIMITS.AUDIT_MAX_BUFFER,
733
- timeout: CONFIG_LIMITS.AUDIT_TIMEOUT_MS
798
+ timeout: this.auditTimeoutMs
734
799
  });
735
800
  } catch (err) {
736
801
  const execError = err;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ceon-oy/monitor-sdk",
3
- "version": "1.0.14",
3
+ "version": "1.0.16",
4
4
  "description": "Client SDK for Ceon Monitor - Error tracking, health monitoring, security events, and vulnerability scanning",
5
5
  "author": "Ceon",
6
6
  "license": "MIT",