@camstack/system 1.2.415 → 1.2.417
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/addon-runner.js +9969 -27
- package/dist/addon-runner.mjs +9930 -9
- package/dist/addon-utils.js +19 -20
- package/dist/addon-utils.mjs +1 -2
- package/dist/auth/auth-audit-log.d.ts +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/autotrack/index.js +1 -1
- package/dist/builtins/autotrack/index.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2 -2
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2 -2
- package/dist/builtins/calendars/calendars.addon.js +1 -1
- package/dist/builtins/calendars/calendars.addon.mjs +1 -1
- package/dist/builtins/camera-grid/index.js +1 -1
- package/dist/builtins/camera-grid/index.mjs +1 -1
- package/dist/builtins/composer/composer.addon.js +2 -2
- package/dist/builtins/composer/composer.addon.mjs +2 -2
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
- package/dist/builtins/device-manager/device-manager.addon.js +2 -2
- package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/keychain/index.js +3 -3
- package/dist/builtins/keychain/index.mjs +3 -3
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +12 -9
- package/dist/builtins/local-auth/local-auth.addon.mjs +7 -4
- package/dist/builtins/local-network/hub-mdns-ciao.d.ts +7 -0
- package/dist/builtins/local-network/hub-mdns.d.ts +58 -0
- package/dist/builtins/local-network/local-network.addon.d.ts +11 -0
- package/dist/builtins/local-network/local-network.addon.js +194 -3
- package/dist/builtins/local-network/local-network.addon.mjs +195 -3
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +102 -10
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +92 -4
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
- package/dist/builtins/storage-orchestrator/index.mjs +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +84 -5
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +80 -5
- package/dist/builtins/system-config/system-config.addon.js +80 -785
- package/dist/builtins/system-config/system-config.addon.mjs +52 -757
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{composition-sources-YlkCjf-1.js → composition-sources-ChAX2Kdo.js} +1 -1
- package/dist/{composition-sources-CXxkMoXq.mjs → composition-sources-CndJVssc.mjs} +1 -1
- package/dist/{constants-BT-fudVK.mjs → constants-BzxwnfDc.mjs} +1 -1
- package/dist/{constants-DChnQrhM.js → constants-VXvZkGgw.js} +1 -1
- package/dist/{event-loop-stall-monitor-LZvGqiHI.js → custom-action-registry-Bb28ibZV.js} +63 -1
- package/dist/{event-loop-stall-monitor-BEfMVUxz.mjs → custom-action-registry-DHv0kYcT.mjs} +58 -2
- package/dist/{dist-CvarXqQt.js → dist-BMOD9OyH.js} +32 -111
- package/dist/{dist-dEsHYY8m.mjs → dist-H_RapIeM.mjs} +21 -100
- package/dist/index.js +22786 -10067
- package/dist/index.mjs +22602 -9883
- package/dist/{jwt-signing-key-CfiteETM.js → jwt-signing-key-BiKHENST.js} +1 -1
- package/dist/{jwt-signing-key-SFIxaH2x.mjs → jwt-signing-key-xQxqpwMC.mjs} +1 -1
- package/dist/kernel/moleculer/broker-factory.d.ts +2 -4
- package/dist/kernel/transport/local-child-registry.d.ts +1 -1
- package/dist/lib-B_R6sPC3.mjs +7106 -0
- package/dist/lib-DOJ5yyWA.js +7110 -0
- package/dist/logging/log-redactor.d.ts +1 -1
- package/dist/{ms-DlIWNkkk.mjs → ms-CgH2OFlD.mjs} +2 -42
- package/dist/{ms-t68_FaqE.js → ms-LB3giGoU.js} +1 -48
- package/dist/{resource-monitor-B2WZ8_q9.mjs → resource-monitor-Di9daRwI.mjs} +1 -1
- package/dist/{resource-monitor-BgWGRxN5.js → resource-monitor-mio9dSCT.js} +5 -5
- package/dist/{restore-archive-CAw_3iNq.js → restore-archive-BobsETEp.js} +1 -1
- package/dist/{restore-archive-Bww1Fl04.mjs → restore-archive-CCAQicV-.mjs} +1 -1
- package/dist/{retired-settings-keys-YLflwTPH.js → retired-settings-keys-BMq2u4Wv.js} +1 -1
- package/dist/{retired-settings-keys-ChQ3qH-V.mjs → retired-settings-keys-CwL4zHLg.mjs} +1 -1
- package/dist/safe-buffer-B1OjL1I9.mjs +42 -0
- package/dist/safe-buffer-D3aoa-7X.js +46 -0
- package/dist/src-CnAqG6EF.js +714 -0
- package/dist/src-hG4grMU4.mjs +709 -0
- package/dist/{tls-BWpwU-d5.js → tls-C0TRPfqc.js} +1 -1
- package/dist/{tls-C2NT-Orr.mjs → tls-D-2dPY-5.mjs} +1 -1
- package/dist/{x509.es-Xf3K_brW.mjs → x509.es-CAjSsrkk.mjs} +643 -2
- package/dist/{x509.es-BhTzcFhZ.js → x509.es-Dzl0BbmG.js} +653 -0
- package/package.json +3 -2
- package/dist/child-cap-dispatch-DFBrdGH2.js +0 -13986
- package/dist/child-cap-dispatch-SF8oiwgo.mjs +0 -12916
- package/dist/custom-action-registry-B4Cf4O_X.mjs +0 -57
- package/dist/custom-action-registry-acBY3mHA.js +0 -62
- package/dist/hub-cap-forward-CDiN1p98.mjs +0 -78
- package/dist/hub-cap-forward-W8oEm4ME.js +0 -101
- package/dist/proc-stat-CbC55Kqi.mjs +0 -92
- package/dist/proc-stat-DL-WUOhl.js +0 -127
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
3
|
-
const require_dist = require("../../dist-
|
|
4
|
-
const require_tls = require("../../tls-
|
|
3
|
+
const require_dist = require("../../dist-BMOD9OyH.js");
|
|
4
|
+
const require_tls = require("../../tls-C0TRPfqc.js");
|
|
5
5
|
let zod = require("zod");
|
|
6
6
|
let node_net = require("node:net");
|
|
7
7
|
let node_os = require("node:os");
|
|
@@ -337,6 +337,163 @@ function parseIpv6Groups(address) {
|
|
|
337
337
|
];
|
|
338
338
|
}
|
|
339
339
|
//#endregion
|
|
340
|
+
//#region src/builtins/local-network/hub-mdns.ts
|
|
341
|
+
/**
|
|
342
|
+
* Hub mDNS advertisement (D838) — how `camstack login` / `camstack discover`
|
|
343
|
+
* find a hub on the LAN.
|
|
344
|
+
*
|
|
345
|
+
* The hub publishes ONE `_camstack._tcp` service for its HTTPS endpoint. There
|
|
346
|
+
* is no mesh channel in it (D826 retired mesh UDP discovery on purpose) and
|
|
347
|
+
* nothing secret: the TXT record carries the node id, the version, the role
|
|
348
|
+
* and the address URL — finding a hub grants nothing, every client still signs
|
|
349
|
+
* in.
|
|
350
|
+
*
|
|
351
|
+
* The advertised address is NOT ranked here. It is the `internal` role of the
|
|
352
|
+
* address book (the address flagged for LAN clients, else the automatic LAN
|
|
353
|
+
* pick) — this module only reads the answer `local-network` already gives.
|
|
354
|
+
*
|
|
355
|
+
* The responder is injected so the logic is tested with a fake; the real one
|
|
356
|
+
* wraps `@homebridge/ciao`.
|
|
357
|
+
*/
|
|
358
|
+
/** The announcement for the current address, or null when nothing qualifies. */
|
|
359
|
+
function buildHubAnnouncement(inputs) {
|
|
360
|
+
if (inputs.internalUrl === null) return null;
|
|
361
|
+
let url;
|
|
362
|
+
try {
|
|
363
|
+
url = new URL(inputs.internalUrl);
|
|
364
|
+
} catch {
|
|
365
|
+
return null;
|
|
366
|
+
}
|
|
367
|
+
if (url.protocol !== "https:") return null;
|
|
368
|
+
const port = url.port === "" ? 443 : Number.parseInt(url.port, 10);
|
|
369
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) return null;
|
|
370
|
+
const host = url.hostname.replace(/^\[|\]$/g, "");
|
|
371
|
+
const txt = {
|
|
372
|
+
[require_dist.HUB_MDNS_TXT_KEYS.nodeId]: inputs.nodeId,
|
|
373
|
+
[require_dist.HUB_MDNS_TXT_KEYS.role]: "hub",
|
|
374
|
+
[require_dist.HUB_MDNS_TXT_KEYS.url]: url.origin
|
|
375
|
+
};
|
|
376
|
+
if (inputs.version !== null) txt[require_dist.HUB_MDNS_TXT_KEYS.version] = inputs.version;
|
|
377
|
+
return {
|
|
378
|
+
name: `camstack-${inputs.nodeId}`,
|
|
379
|
+
type: require_dist.HUB_MDNS_SERVICE_TYPE,
|
|
380
|
+
port,
|
|
381
|
+
address: (0, node_net.isIP)(host) !== 0 ? host : null,
|
|
382
|
+
txt
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
function announcementKey(a) {
|
|
386
|
+
return JSON.stringify([
|
|
387
|
+
a.name,
|
|
388
|
+
a.type,
|
|
389
|
+
a.port,
|
|
390
|
+
a.address,
|
|
391
|
+
a.txt
|
|
392
|
+
]);
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Keeps one mDNS service in step with the hub's `internal` address. `sync()`
|
|
396
|
+
* is safe to call on any change; it never throws — a failure to advertise is
|
|
397
|
+
* logged and the boot goes on.
|
|
398
|
+
*/
|
|
399
|
+
var HubMdnsAdvertiser = class {
|
|
400
|
+
options;
|
|
401
|
+
current = null;
|
|
402
|
+
running = false;
|
|
403
|
+
chain = Promise.resolve();
|
|
404
|
+
constructor(options) {
|
|
405
|
+
this.options = options;
|
|
406
|
+
}
|
|
407
|
+
async start() {
|
|
408
|
+
this.running = true;
|
|
409
|
+
await this.sync();
|
|
410
|
+
}
|
|
411
|
+
/** Re-read the address and re-announce when it changed. Serialised. */
|
|
412
|
+
sync() {
|
|
413
|
+
this.chain = this.chain.then(() => this.syncOnce());
|
|
414
|
+
return this.chain;
|
|
415
|
+
}
|
|
416
|
+
async stop() {
|
|
417
|
+
this.running = false;
|
|
418
|
+
await (this.chain = this.chain.then(() => this.withdraw()));
|
|
419
|
+
}
|
|
420
|
+
async syncOnce() {
|
|
421
|
+
if (!this.running) return;
|
|
422
|
+
const { logger } = this.options;
|
|
423
|
+
try {
|
|
424
|
+
const internalUrl = await this.options.readInternalUrl();
|
|
425
|
+
const next = buildHubAnnouncement({
|
|
426
|
+
nodeId: this.options.nodeId,
|
|
427
|
+
version: this.options.version,
|
|
428
|
+
internalUrl
|
|
429
|
+
});
|
|
430
|
+
if (next === null) {
|
|
431
|
+
if (this.current !== null) {
|
|
432
|
+
await this.withdraw();
|
|
433
|
+
logger.info("hub mDNS: no internal address, advertisement withdrawn");
|
|
434
|
+
}
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
const key = announcementKey(next);
|
|
438
|
+
if (this.current?.key === key) return;
|
|
439
|
+
await this.withdraw();
|
|
440
|
+
const handle = await this.options.publisher.publish(next);
|
|
441
|
+
this.current = {
|
|
442
|
+
key,
|
|
443
|
+
handle
|
|
444
|
+
};
|
|
445
|
+
logger.info("hub mDNS: advertising _camstack._tcp", { meta: {
|
|
446
|
+
url: next.txt[require_dist.HUB_MDNS_TXT_KEYS.url],
|
|
447
|
+
port: next.port
|
|
448
|
+
} });
|
|
449
|
+
} catch (err) {
|
|
450
|
+
logger.warn("hub mDNS: could not advertise the hub (logins still work with --server)", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
async withdraw() {
|
|
454
|
+
const held = this.current;
|
|
455
|
+
this.current = null;
|
|
456
|
+
if (held === null) return;
|
|
457
|
+
try {
|
|
458
|
+
await held.handle.stop();
|
|
459
|
+
} catch (err) {
|
|
460
|
+
this.options.logger.warn("hub mDNS: withdraw failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
/**
|
|
465
|
+
* The address a hub advertises: the `internal` role's answer, exactly as the
|
|
466
|
+
* address book resolved it. Never re-ranked here (D729, D732).
|
|
467
|
+
*/
|
|
468
|
+
function internalUrlOf(book) {
|
|
469
|
+
return book.roles.internal.resolved;
|
|
470
|
+
}
|
|
471
|
+
//#endregion
|
|
472
|
+
//#region src/builtins/local-network/hub-mdns-ciao.ts
|
|
473
|
+
function createCiaoPublisher() {
|
|
474
|
+
return { async publish(announcement) {
|
|
475
|
+
const { getResponder } = await Promise.resolve().then(() => /* @__PURE__ */ require_chunk.__toESM(require("../../lib-DOJ5yyWA.js").default));
|
|
476
|
+
const responder = getResponder();
|
|
477
|
+
const service = responder.createService({
|
|
478
|
+
name: announcement.name,
|
|
479
|
+
type: announcement.type,
|
|
480
|
+
port: announcement.port,
|
|
481
|
+
txt: { ...announcement.txt },
|
|
482
|
+
...announcement.address !== null ? { restrictedAddresses: [announcement.address] } : {}
|
|
483
|
+
});
|
|
484
|
+
try {
|
|
485
|
+
await service.advertise();
|
|
486
|
+
} catch (err) {
|
|
487
|
+
await responder.shutdown().catch(() => void 0);
|
|
488
|
+
throw err;
|
|
489
|
+
}
|
|
490
|
+
return { stop: async () => {
|
|
491
|
+
await service.destroy();
|
|
492
|
+
await responder.shutdown();
|
|
493
|
+
} };
|
|
494
|
+
} };
|
|
495
|
+
}
|
|
496
|
+
//#endregion
|
|
340
497
|
//#region src/builtins/local-network/local-hostname.ts
|
|
341
498
|
var DNS_NAME = /^(?=.{1,253}$)([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])$/;
|
|
342
499
|
/**
|
|
@@ -419,6 +576,7 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
|
|
|
419
576
|
* `null` when no mesh provider is joined.
|
|
420
577
|
*/
|
|
421
578
|
meshEndpoint = null;
|
|
579
|
+
mdns = null;
|
|
422
580
|
constructor() {
|
|
423
581
|
super({
|
|
424
582
|
allowedAddresses: [],
|
|
@@ -430,7 +588,8 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
|
|
|
430
588
|
httpPort: require_tls.DEFAULT_LAN_HTTP_PORT,
|
|
431
589
|
localHostname: "",
|
|
432
590
|
internalUrl: "",
|
|
433
|
-
publicEndpointUrl: ""
|
|
591
|
+
publicEndpointUrl: "",
|
|
592
|
+
mdnsAdvertise: true
|
|
434
593
|
});
|
|
435
594
|
}
|
|
436
595
|
/**
|
|
@@ -481,6 +640,7 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
|
|
|
481
640
|
customAddresses: changed.custom
|
|
482
641
|
}, detectedUrls);
|
|
483
642
|
await this.updateGlobalSettings(addressBookPatch(after));
|
|
643
|
+
await this.mdns?.sync();
|
|
484
644
|
}
|
|
485
645
|
/** The deprecated `getHubAddresses` shape, from the role resolvers. */
|
|
486
646
|
async snapshotHubAddresses() {
|
|
@@ -716,6 +876,7 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
|
|
|
716
876
|
} catch (err) {
|
|
717
877
|
this.ctx.logger.warn("local-network: LAN HTTP not applied at boot", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
718
878
|
}
|
|
879
|
+
await this.applyMdnsAdvertisement();
|
|
719
880
|
return [{
|
|
720
881
|
capability: require_dist.localNetworkCapability,
|
|
721
882
|
provider
|
|
@@ -749,6 +910,14 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
|
|
|
749
910
|
equals: true
|
|
750
911
|
}
|
|
751
912
|
}),
|
|
913
|
+
this.field({
|
|
914
|
+
type: "boolean",
|
|
915
|
+
key: "mdnsAdvertise",
|
|
916
|
+
label: "Announce this hub on the LAN (mDNS)",
|
|
917
|
+
description: "Lets `camstack login` find the hub without an address. Advertises only the HTTPS address, never a secret. Needs UDP 5353 multicast to reach the LAN (host networking or a dedicated container IP).",
|
|
918
|
+
style: "switch",
|
|
919
|
+
default: true
|
|
920
|
+
}),
|
|
752
921
|
this.field({
|
|
753
922
|
type: "text",
|
|
754
923
|
key: "localHostname",
|
|
@@ -762,8 +931,29 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
|
|
|
762
931
|
}
|
|
763
932
|
async onConfigChanged() {
|
|
764
933
|
await this.applyLanAccessFromSettings();
|
|
934
|
+
await this.applyMdnsAdvertisement();
|
|
935
|
+
}
|
|
936
|
+
/**
|
|
937
|
+
* Start, re-announce or stop the hub's mDNS service (D838). Never throws:
|
|
938
|
+
* the advertiser logs its own failures and boot goes on.
|
|
939
|
+
*/
|
|
940
|
+
async applyMdnsAdvertisement() {
|
|
941
|
+
if (this.config.mdnsAdvertise === false) {
|
|
942
|
+
await this.mdns?.stop();
|
|
943
|
+
return;
|
|
944
|
+
}
|
|
945
|
+
if (this.mdns === null) this.mdns = new HubMdnsAdvertiser({
|
|
946
|
+
publisher: createCiaoPublisher(),
|
|
947
|
+
logger: this.ctx.logger,
|
|
948
|
+
nodeId: this.ctx.kernel.localNodeId ?? "hub",
|
|
949
|
+
version: null,
|
|
950
|
+
readInternalUrl: async () => internalUrlOf(await this.addressBook("https"))
|
|
951
|
+
});
|
|
952
|
+
await this.mdns.start();
|
|
765
953
|
}
|
|
766
954
|
async onShutdown() {
|
|
955
|
+
await this.mdns?.stop();
|
|
956
|
+
this.mdns = null;
|
|
767
957
|
if (this.pollTimer) {
|
|
768
958
|
clearInterval(this.pollTimer);
|
|
769
959
|
this.pollTimer = null;
|
|
@@ -959,6 +1149,7 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
|
|
|
959
1149
|
} });
|
|
960
1150
|
this.lastSnapshotKey = key;
|
|
961
1151
|
this.persistReconciledAllowlist(interfaces);
|
|
1152
|
+
this.mdns?.sync();
|
|
962
1153
|
this.ctx.eventBus?.emit({
|
|
963
1154
|
id: `local-network-changed-${Date.now()}`,
|
|
964
1155
|
timestamp: /* @__PURE__ */ new Date(),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { o as __toESM } from "../../chunk-CNf5ZN-e.mjs";
|
|
2
|
+
import { D as HUB_MDNS_TXT_KEYS, E as HUB_MDNS_SERVICE_TYPE, Gn as validateCustomAddress, Ht as isDefaultAppConnectionEndpoint, On as resolveNotificationTapAddress, Qt as localNetworkCapability, Tn as resolveHubAddressRoles, at as checkRoleAddress, fr as BaseAddon, mn as pickAppLinkHub, ri as EventCategory, s as CAMSTACK_APP_LINK_ORIGIN, xn as resolveAppConnections, zt as isAppLinkBase } from "../../dist-H_RapIeM.mjs";
|
|
3
|
+
import { P as readLanHttpState, _ as writeExtraSans, h as readTlsMode, i as storeUploadedCertificate, j as applyLanHttp, k as DEFAULT_LAN_HTTP_PORT, m as readTlsAccessStatus, n as regenerateCertificate, p as readExtraSans, r as revertToGeneratedCertificate, t as applyCertificateToListener, u as servedHttpsLeafFingerprint, y as ensureTlsCert } from "../../tls-D-2dPY-5.mjs";
|
|
3
4
|
import { z } from "zod";
|
|
4
5
|
import { isIP } from "node:net";
|
|
5
6
|
import * as os from "node:os";
|
|
@@ -334,6 +335,163 @@ function parseIpv6Groups(address) {
|
|
|
334
335
|
];
|
|
335
336
|
}
|
|
336
337
|
//#endregion
|
|
338
|
+
//#region src/builtins/local-network/hub-mdns.ts
|
|
339
|
+
/**
|
|
340
|
+
* Hub mDNS advertisement (D838) — how `camstack login` / `camstack discover`
|
|
341
|
+
* find a hub on the LAN.
|
|
342
|
+
*
|
|
343
|
+
* The hub publishes ONE `_camstack._tcp` service for its HTTPS endpoint. There
|
|
344
|
+
* is no mesh channel in it (D826 retired mesh UDP discovery on purpose) and
|
|
345
|
+
* nothing secret: the TXT record carries the node id, the version, the role
|
|
346
|
+
* and the address URL — finding a hub grants nothing, every client still signs
|
|
347
|
+
* in.
|
|
348
|
+
*
|
|
349
|
+
* The advertised address is NOT ranked here. It is the `internal` role of the
|
|
350
|
+
* address book (the address flagged for LAN clients, else the automatic LAN
|
|
351
|
+
* pick) — this module only reads the answer `local-network` already gives.
|
|
352
|
+
*
|
|
353
|
+
* The responder is injected so the logic is tested with a fake; the real one
|
|
354
|
+
* wraps `@homebridge/ciao`.
|
|
355
|
+
*/
|
|
356
|
+
/** The announcement for the current address, or null when nothing qualifies. */
|
|
357
|
+
function buildHubAnnouncement(inputs) {
|
|
358
|
+
if (inputs.internalUrl === null) return null;
|
|
359
|
+
let url;
|
|
360
|
+
try {
|
|
361
|
+
url = new URL(inputs.internalUrl);
|
|
362
|
+
} catch {
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
if (url.protocol !== "https:") return null;
|
|
366
|
+
const port = url.port === "" ? 443 : Number.parseInt(url.port, 10);
|
|
367
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) return null;
|
|
368
|
+
const host = url.hostname.replace(/^\[|\]$/g, "");
|
|
369
|
+
const txt = {
|
|
370
|
+
[HUB_MDNS_TXT_KEYS.nodeId]: inputs.nodeId,
|
|
371
|
+
[HUB_MDNS_TXT_KEYS.role]: "hub",
|
|
372
|
+
[HUB_MDNS_TXT_KEYS.url]: url.origin
|
|
373
|
+
};
|
|
374
|
+
if (inputs.version !== null) txt[HUB_MDNS_TXT_KEYS.version] = inputs.version;
|
|
375
|
+
return {
|
|
376
|
+
name: `camstack-${inputs.nodeId}`,
|
|
377
|
+
type: HUB_MDNS_SERVICE_TYPE,
|
|
378
|
+
port,
|
|
379
|
+
address: isIP(host) !== 0 ? host : null,
|
|
380
|
+
txt
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
function announcementKey(a) {
|
|
384
|
+
return JSON.stringify([
|
|
385
|
+
a.name,
|
|
386
|
+
a.type,
|
|
387
|
+
a.port,
|
|
388
|
+
a.address,
|
|
389
|
+
a.txt
|
|
390
|
+
]);
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Keeps one mDNS service in step with the hub's `internal` address. `sync()`
|
|
394
|
+
* is safe to call on any change; it never throws — a failure to advertise is
|
|
395
|
+
* logged and the boot goes on.
|
|
396
|
+
*/
|
|
397
|
+
var HubMdnsAdvertiser = class {
|
|
398
|
+
options;
|
|
399
|
+
current = null;
|
|
400
|
+
running = false;
|
|
401
|
+
chain = Promise.resolve();
|
|
402
|
+
constructor(options) {
|
|
403
|
+
this.options = options;
|
|
404
|
+
}
|
|
405
|
+
async start() {
|
|
406
|
+
this.running = true;
|
|
407
|
+
await this.sync();
|
|
408
|
+
}
|
|
409
|
+
/** Re-read the address and re-announce when it changed. Serialised. */
|
|
410
|
+
sync() {
|
|
411
|
+
this.chain = this.chain.then(() => this.syncOnce());
|
|
412
|
+
return this.chain;
|
|
413
|
+
}
|
|
414
|
+
async stop() {
|
|
415
|
+
this.running = false;
|
|
416
|
+
await (this.chain = this.chain.then(() => this.withdraw()));
|
|
417
|
+
}
|
|
418
|
+
async syncOnce() {
|
|
419
|
+
if (!this.running) return;
|
|
420
|
+
const { logger } = this.options;
|
|
421
|
+
try {
|
|
422
|
+
const internalUrl = await this.options.readInternalUrl();
|
|
423
|
+
const next = buildHubAnnouncement({
|
|
424
|
+
nodeId: this.options.nodeId,
|
|
425
|
+
version: this.options.version,
|
|
426
|
+
internalUrl
|
|
427
|
+
});
|
|
428
|
+
if (next === null) {
|
|
429
|
+
if (this.current !== null) {
|
|
430
|
+
await this.withdraw();
|
|
431
|
+
logger.info("hub mDNS: no internal address, advertisement withdrawn");
|
|
432
|
+
}
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
const key = announcementKey(next);
|
|
436
|
+
if (this.current?.key === key) return;
|
|
437
|
+
await this.withdraw();
|
|
438
|
+
const handle = await this.options.publisher.publish(next);
|
|
439
|
+
this.current = {
|
|
440
|
+
key,
|
|
441
|
+
handle
|
|
442
|
+
};
|
|
443
|
+
logger.info("hub mDNS: advertising _camstack._tcp", { meta: {
|
|
444
|
+
url: next.txt[HUB_MDNS_TXT_KEYS.url],
|
|
445
|
+
port: next.port
|
|
446
|
+
} });
|
|
447
|
+
} catch (err) {
|
|
448
|
+
logger.warn("hub mDNS: could not advertise the hub (logins still work with --server)", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
async withdraw() {
|
|
452
|
+
const held = this.current;
|
|
453
|
+
this.current = null;
|
|
454
|
+
if (held === null) return;
|
|
455
|
+
try {
|
|
456
|
+
await held.handle.stop();
|
|
457
|
+
} catch (err) {
|
|
458
|
+
this.options.logger.warn("hub mDNS: withdraw failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
/**
|
|
463
|
+
* The address a hub advertises: the `internal` role's answer, exactly as the
|
|
464
|
+
* address book resolved it. Never re-ranked here (D729, D732).
|
|
465
|
+
*/
|
|
466
|
+
function internalUrlOf(book) {
|
|
467
|
+
return book.roles.internal.resolved;
|
|
468
|
+
}
|
|
469
|
+
//#endregion
|
|
470
|
+
//#region src/builtins/local-network/hub-mdns-ciao.ts
|
|
471
|
+
function createCiaoPublisher() {
|
|
472
|
+
return { async publish(announcement) {
|
|
473
|
+
const { getResponder } = await import("../../lib-B_R6sPC3.mjs").then((m) => /* @__PURE__ */ __toESM(m.default));
|
|
474
|
+
const responder = getResponder();
|
|
475
|
+
const service = responder.createService({
|
|
476
|
+
name: announcement.name,
|
|
477
|
+
type: announcement.type,
|
|
478
|
+
port: announcement.port,
|
|
479
|
+
txt: { ...announcement.txt },
|
|
480
|
+
...announcement.address !== null ? { restrictedAddresses: [announcement.address] } : {}
|
|
481
|
+
});
|
|
482
|
+
try {
|
|
483
|
+
await service.advertise();
|
|
484
|
+
} catch (err) {
|
|
485
|
+
await responder.shutdown().catch(() => void 0);
|
|
486
|
+
throw err;
|
|
487
|
+
}
|
|
488
|
+
return { stop: async () => {
|
|
489
|
+
await service.destroy();
|
|
490
|
+
await responder.shutdown();
|
|
491
|
+
} };
|
|
492
|
+
} };
|
|
493
|
+
}
|
|
494
|
+
//#endregion
|
|
337
495
|
//#region src/builtins/local-network/local-hostname.ts
|
|
338
496
|
var DNS_NAME = /^(?=.{1,253}$)([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])$/;
|
|
339
497
|
/**
|
|
@@ -416,6 +574,7 @@ var LocalNetworkAddon = class extends BaseAddon {
|
|
|
416
574
|
* `null` when no mesh provider is joined.
|
|
417
575
|
*/
|
|
418
576
|
meshEndpoint = null;
|
|
577
|
+
mdns = null;
|
|
419
578
|
constructor() {
|
|
420
579
|
super({
|
|
421
580
|
allowedAddresses: [],
|
|
@@ -427,7 +586,8 @@ var LocalNetworkAddon = class extends BaseAddon {
|
|
|
427
586
|
httpPort: DEFAULT_LAN_HTTP_PORT,
|
|
428
587
|
localHostname: "",
|
|
429
588
|
internalUrl: "",
|
|
430
|
-
publicEndpointUrl: ""
|
|
589
|
+
publicEndpointUrl: "",
|
|
590
|
+
mdnsAdvertise: true
|
|
431
591
|
});
|
|
432
592
|
}
|
|
433
593
|
/**
|
|
@@ -478,6 +638,7 @@ var LocalNetworkAddon = class extends BaseAddon {
|
|
|
478
638
|
customAddresses: changed.custom
|
|
479
639
|
}, detectedUrls);
|
|
480
640
|
await this.updateGlobalSettings(addressBookPatch(after));
|
|
641
|
+
await this.mdns?.sync();
|
|
481
642
|
}
|
|
482
643
|
/** The deprecated `getHubAddresses` shape, from the role resolvers. */
|
|
483
644
|
async snapshotHubAddresses() {
|
|
@@ -713,6 +874,7 @@ var LocalNetworkAddon = class extends BaseAddon {
|
|
|
713
874
|
} catch (err) {
|
|
714
875
|
this.ctx.logger.warn("local-network: LAN HTTP not applied at boot", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
715
876
|
}
|
|
877
|
+
await this.applyMdnsAdvertisement();
|
|
716
878
|
return [{
|
|
717
879
|
capability: localNetworkCapability,
|
|
718
880
|
provider
|
|
@@ -746,6 +908,14 @@ var LocalNetworkAddon = class extends BaseAddon {
|
|
|
746
908
|
equals: true
|
|
747
909
|
}
|
|
748
910
|
}),
|
|
911
|
+
this.field({
|
|
912
|
+
type: "boolean",
|
|
913
|
+
key: "mdnsAdvertise",
|
|
914
|
+
label: "Announce this hub on the LAN (mDNS)",
|
|
915
|
+
description: "Lets `camstack login` find the hub without an address. Advertises only the HTTPS address, never a secret. Needs UDP 5353 multicast to reach the LAN (host networking or a dedicated container IP).",
|
|
916
|
+
style: "switch",
|
|
917
|
+
default: true
|
|
918
|
+
}),
|
|
749
919
|
this.field({
|
|
750
920
|
type: "text",
|
|
751
921
|
key: "localHostname",
|
|
@@ -759,8 +929,29 @@ var LocalNetworkAddon = class extends BaseAddon {
|
|
|
759
929
|
}
|
|
760
930
|
async onConfigChanged() {
|
|
761
931
|
await this.applyLanAccessFromSettings();
|
|
932
|
+
await this.applyMdnsAdvertisement();
|
|
933
|
+
}
|
|
934
|
+
/**
|
|
935
|
+
* Start, re-announce or stop the hub's mDNS service (D838). Never throws:
|
|
936
|
+
* the advertiser logs its own failures and boot goes on.
|
|
937
|
+
*/
|
|
938
|
+
async applyMdnsAdvertisement() {
|
|
939
|
+
if (this.config.mdnsAdvertise === false) {
|
|
940
|
+
await this.mdns?.stop();
|
|
941
|
+
return;
|
|
942
|
+
}
|
|
943
|
+
if (this.mdns === null) this.mdns = new HubMdnsAdvertiser({
|
|
944
|
+
publisher: createCiaoPublisher(),
|
|
945
|
+
logger: this.ctx.logger,
|
|
946
|
+
nodeId: this.ctx.kernel.localNodeId ?? "hub",
|
|
947
|
+
version: null,
|
|
948
|
+
readInternalUrl: async () => internalUrlOf(await this.addressBook("https"))
|
|
949
|
+
});
|
|
950
|
+
await this.mdns.start();
|
|
762
951
|
}
|
|
763
952
|
async onShutdown() {
|
|
953
|
+
await this.mdns?.stop();
|
|
954
|
+
this.mdns = null;
|
|
764
955
|
if (this.pollTimer) {
|
|
765
956
|
clearInterval(this.pollTimer);
|
|
766
957
|
this.pollTimer = null;
|
|
@@ -956,6 +1147,7 @@ var LocalNetworkAddon = class extends BaseAddon {
|
|
|
956
1147
|
} });
|
|
957
1148
|
this.lastSnapshotKey = key;
|
|
958
1149
|
this.persistReconciledAllowlist(interfaces);
|
|
1150
|
+
this.mdns?.sync();
|
|
959
1151
|
this.ctx.eventBus?.emit({
|
|
960
1152
|
id: `local-network-changed-${Date.now()}`,
|
|
961
1153
|
timestamp: /* @__PURE__ */ new Date(),
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-BMOD9OyH.js");
|
|
7
7
|
//#region src/builtins/loki-logging/loki-payload.ts
|
|
8
8
|
/**
|
|
9
9
|
* Loki rejects a label name that is not a valid Prometheus label
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { en as logDestinationCapability, fr as BaseAddon } from "../../dist-H_RapIeM.mjs";
|
|
2
2
|
//#region src/builtins/loki-logging/loki-payload.ts
|
|
3
3
|
/**
|
|
4
4
|
* Loki rejects a label name that is not a valid Prometheus label
|
|
@@ -3,8 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
7
|
-
const require_proc_stat = require("../../proc-stat-DL-WUOhl.js");
|
|
6
|
+
const require_dist = require("../../dist-BMOD9OyH.js");
|
|
8
7
|
let node_fs_promises = require("node:fs/promises");
|
|
9
8
|
let node_os = require("node:os");
|
|
10
9
|
node_os = require_chunk.__toESM(node_os);
|
|
@@ -2126,7 +2125,7 @@ var NativeMetricsProvider = class {
|
|
|
2126
2125
|
return getCpuTemperatureInternal();
|
|
2127
2126
|
}
|
|
2128
2127
|
async getProcessStats(input) {
|
|
2129
|
-
const { getPidStats } = await Promise.resolve().then(() => require("../../resource-monitor-
|
|
2128
|
+
const { getPidStats } = await Promise.resolve().then(() => require("../../resource-monitor-mio9dSCT.js")).then((n) => n.resource_monitor_exports);
|
|
2130
2129
|
const raw = await getPidStats(input.pids);
|
|
2131
2130
|
const result = [];
|
|
2132
2131
|
for (const [pid, s] of raw) result.push({
|
|
@@ -2462,6 +2461,95 @@ function execAsync(cmd, args, timeoutMs = 5e3) {
|
|
|
2462
2461
|
});
|
|
2463
2462
|
});
|
|
2464
2463
|
}
|
|
2464
|
+
/**
|
|
2465
|
+
* Parse one `/proc/<pid>/stat` line. `null` for a line that does not parse —
|
|
2466
|
+
* a process that exited between the readdir and the read leaves a truncated
|
|
2467
|
+
* or empty file, and that is normal, not an error.
|
|
2468
|
+
*/
|
|
2469
|
+
function parseProcStat(line) {
|
|
2470
|
+
const close = line.lastIndexOf(")");
|
|
2471
|
+
const open = line.indexOf("(");
|
|
2472
|
+
if (close < 0 || open < 0 || close < open) return null;
|
|
2473
|
+
const pid = Number(line.slice(0, open).trim());
|
|
2474
|
+
const comm = line.slice(open + 1, close);
|
|
2475
|
+
const rest = line.slice(close + 1).trim().split(/\s+/);
|
|
2476
|
+
const state = rest[0];
|
|
2477
|
+
const ppid = Number(rest[1]);
|
|
2478
|
+
const pgid = Number(rest[2]);
|
|
2479
|
+
const utime = Number(rest[11]);
|
|
2480
|
+
const stime = Number(rest[12]);
|
|
2481
|
+
const startTicks = Number(rest[19]);
|
|
2482
|
+
const rssPages = Number(rest[21]);
|
|
2483
|
+
if (state === void 0 || state === "") return null;
|
|
2484
|
+
if (![
|
|
2485
|
+
pid,
|
|
2486
|
+
ppid,
|
|
2487
|
+
pgid,
|
|
2488
|
+
utime,
|
|
2489
|
+
stime,
|
|
2490
|
+
startTicks,
|
|
2491
|
+
rssPages
|
|
2492
|
+
].every(Number.isFinite)) return null;
|
|
2493
|
+
return {
|
|
2494
|
+
pid,
|
|
2495
|
+
comm,
|
|
2496
|
+
state,
|
|
2497
|
+
ppid,
|
|
2498
|
+
pgid,
|
|
2499
|
+
ticks: utime + stime,
|
|
2500
|
+
startTicks,
|
|
2501
|
+
rssPages
|
|
2502
|
+
};
|
|
2503
|
+
}
|
|
2504
|
+
function statusKb(status, key) {
|
|
2505
|
+
const match = status.match(new RegExp(`^${key}:\\s+(\\d+)`, "m"));
|
|
2506
|
+
return match ? parseInt(match[1], 10) * 1024 : void 0;
|
|
2507
|
+
}
|
|
2508
|
+
/** Read `VmRSS` / `RssAnon` / `RssFile` (kB in the file) out of `/proc/<pid>/status`. */
|
|
2509
|
+
function parseProcStatusRss(status) {
|
|
2510
|
+
return {
|
|
2511
|
+
rssBytes: statusKb(status, "VmRSS"),
|
|
2512
|
+
privateBytes: statusKb(status, "RssAnon"),
|
|
2513
|
+
sharedBytes: statusKb(status, "RssFile")
|
|
2514
|
+
};
|
|
2515
|
+
}
|
|
2516
|
+
/** Seconds the process has been alive — `ps etime`, whole seconds. */
|
|
2517
|
+
function elapsedSecSince(input) {
|
|
2518
|
+
return Math.max(0, Math.floor(input.uptimeSec - input.startTicks / 100));
|
|
2519
|
+
}
|
|
2520
|
+
/**
|
|
2521
|
+
* `ps pcpu`: CPU time over elapsed time, as a percentage with one decimal.
|
|
2522
|
+
*
|
|
2523
|
+
* This is deliberately the LIFETIME average `ps` prints, not an instantaneous
|
|
2524
|
+
* rate: the columns fed from it have always shown that quantity, and the
|
|
2525
|
+
* instantaneous split is a different number with a different owner
|
|
2526
|
+
* (`cpuMainPercent` / `cpuGcPercent` from `thread-cpu-sampler.ts`). A process
|
|
2527
|
+
* with no elapsed window yet reports 0, never a division by zero.
|
|
2528
|
+
*/
|
|
2529
|
+
function lifetimeCpuPercent(input) {
|
|
2530
|
+
const elapsedSec = input.uptimeSec - input.startTicks / 100;
|
|
2531
|
+
if (!(elapsedSec > 0)) return 0;
|
|
2532
|
+
const cpuSec = input.ticks / 100;
|
|
2533
|
+
return Math.round(cpuSec / elapsedSec * 1e3) / 10;
|
|
2534
|
+
}
|
|
2535
|
+
var PID_RE = /^\d+$/;
|
|
2536
|
+
var nodeProcReader = {
|
|
2537
|
+
listPids: async () => (await (0, node_fs_promises.readdir)("/proc")).filter((entry) => PID_RE.test(entry)).map((entry) => Number(entry)),
|
|
2538
|
+
readStat: (pid) => (0, node_fs_promises.readFile)(`/proc/${pid}/stat`, "latin1"),
|
|
2539
|
+
readStatus: (pid) => (0, node_fs_promises.readFile)(`/proc/${pid}/status`, "latin1"),
|
|
2540
|
+
readCmdline: (pid) => (0, node_fs_promises.readFile)(`/proc/${pid}/cmdline`, "latin1"),
|
|
2541
|
+
readUptimeSec: async () => {
|
|
2542
|
+
const [first] = (await (0, node_fs_promises.readFile)("/proc/uptime", "latin1")).trim().split(/\s+/);
|
|
2543
|
+
const seconds = Number(first);
|
|
2544
|
+
if (!Number.isFinite(seconds)) throw new Error(`/proc/uptime unreadable: ${String(first)}`);
|
|
2545
|
+
return seconds;
|
|
2546
|
+
}
|
|
2547
|
+
};
|
|
2548
|
+
/** `ps command=`: argv joined by spaces, or `[comm]` when there is no argv. */
|
|
2549
|
+
function commandFromCmdline(cmdline, comm) {
|
|
2550
|
+
const joined = cmdline.split("\0").filter((part) => part.length > 0).join(" ");
|
|
2551
|
+
return joined.length > 0 ? joined : `[${comm}]`;
|
|
2552
|
+
}
|
|
2465
2553
|
//#endregion
|
|
2466
2554
|
//#region src/builtins/native-metrics/proc-process-table.ts
|
|
2467
2555
|
/**
|
|
@@ -2493,28 +2581,28 @@ async function readProcRow(pid, uptimeSec, reader) {
|
|
|
2493
2581
|
} catch {
|
|
2494
2582
|
return null;
|
|
2495
2583
|
}
|
|
2496
|
-
const parsed =
|
|
2584
|
+
const parsed = parseProcStat(stat);
|
|
2497
2585
|
if (parsed === null) return null;
|
|
2498
|
-
const rss =
|
|
2586
|
+
const rss = parseProcStatusRss(status);
|
|
2499
2587
|
return {
|
|
2500
2588
|
pid: parsed.pid,
|
|
2501
2589
|
ppid: parsed.ppid,
|
|
2502
2590
|
pgid: parsed.pgid,
|
|
2503
|
-
cpuPercent:
|
|
2591
|
+
cpuPercent: lifetimeCpuPercent({
|
|
2504
2592
|
ticks: parsed.ticks,
|
|
2505
2593
|
startTicks: parsed.startTicks,
|
|
2506
2594
|
uptimeSec
|
|
2507
2595
|
}),
|
|
2508
2596
|
memoryRssBytes: rss.rssBytes ?? 0,
|
|
2509
|
-
uptimeSec:
|
|
2597
|
+
uptimeSec: elapsedSecSince({
|
|
2510
2598
|
startTicks: parsed.startTicks,
|
|
2511
2599
|
uptimeSec
|
|
2512
2600
|
}),
|
|
2513
|
-
command:
|
|
2601
|
+
command: commandFromCmdline(cmdline, parsed.comm)
|
|
2514
2602
|
};
|
|
2515
2603
|
}
|
|
2516
2604
|
/** Every process in `/proc`, as the rows `ps -eo …` would have printed. */
|
|
2517
|
-
async function readProcProcessTable(reader =
|
|
2605
|
+
async function readProcProcessTable(reader = nodeProcReader) {
|
|
2518
2606
|
const [pids, uptimeSec] = await Promise.all([reader.listPids(), reader.readUptimeSec()]);
|
|
2519
2607
|
return (await Promise.all(pids.map((pid) => readProcRow(pid, uptimeSec, reader)))).filter((row) => row !== null);
|
|
2520
2608
|
}
|
|
@@ -2569,7 +2657,7 @@ async function spawnPsTable() {
|
|
|
2569
2657
|
}
|
|
2570
2658
|
var defaultDeps = {
|
|
2571
2659
|
platform: (0, node_os.platform)(),
|
|
2572
|
-
reader:
|
|
2660
|
+
reader: nodeProcReader,
|
|
2573
2661
|
spawnPs: spawnPsTable
|
|
2574
2662
|
};
|
|
2575
2663
|
/**
|
|
@@ -3481,3 +3569,7 @@ var NativeMetricsAddon = class NativeMetricsAddon extends require_dist.BaseAddon
|
|
|
3481
3569
|
//#endregion
|
|
3482
3570
|
exports.NativeMetricsProvider = NativeMetricsProvider;
|
|
3483
3571
|
exports.default = NativeMetricsAddon;
|
|
3572
|
+
exports.lifetimeCpuPercent = lifetimeCpuPercent;
|
|
3573
|
+
exports.nodeProcReader = nodeProcReader;
|
|
3574
|
+
exports.parseProcStat = parseProcStat;
|
|
3575
|
+
exports.parseProcStatusRss = parseProcStatusRss;
|