@camstack/system 1.2.382 → 1.2.383
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 +1 -1
- package/dist/addon-runner.mjs +1 -1
- package/dist/addon-utils.js +1 -1
- package/dist/addon-utils.mjs +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 +5 -5
- package/dist/builtins/keychain/index.mjs +4 -4
- package/dist/builtins/keychain/system-held-secrets.d.ts +2 -1
- 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 +9 -178
- package/dist/builtins/local-auth/local-auth.addon.mjs +4 -161
- package/dist/builtins/local-network/local-network.addon.js +2 -2
- package/dist/builtins/local-network/local-network.addon.mjs +2 -2
- 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 +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- 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/storage-orchestrator.addon.js +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
- package/dist/builtins/system-config/index.d.ts +1 -0
- package/dist/builtins/system-config/index.js +2 -0
- package/dist/builtins/system-config/index.mjs +2 -2
- package/dist/builtins/system-config/mesh-actions.d.ts +19 -0
- package/dist/builtins/system-config/system-config.addon.d.ts +34 -1
- package/dist/builtins/system-config/system-config.addon.js +87538 -9
- package/dist/builtins/system-config/system-config.addon.mjs +87505 -4
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{child-cap-dispatch-BrMdKHfp.js → child-cap-dispatch-BD8fhJ1b.js} +2 -2
- package/dist/{child-cap-dispatch-WsYPNvnK.mjs → child-cap-dispatch-C68N2a6Y.mjs} +2 -2
- package/dist/{composition-sources-C6ZynCZ2.js → composition-sources-ChpT_Yw4.js} +1 -1
- package/dist/{composition-sources-XqRX51db.mjs → composition-sources-DM7Ft_tp.mjs} +1 -1
- package/dist/{cluster-secret-BEPLh3LL.js → constants-CDpry1_T.js} +82 -1
- package/dist/{cluster-secret-DhPdZ0VA.mjs → constants-e3mCa1jG.mjs} +23 -2
- package/dist/{dist-tnAO12ak.js → dist-CUNGH0fs.js} +34 -0
- package/dist/{dist-CP5TTjwd.mjs → dist-osl3bkF0.mjs} +23 -1
- package/dist/{event-loop-stall-monitor-WkssIXjq.mjs → event-loop-stall-monitor-BeeWMnyT.mjs} +1 -1
- package/dist/{event-loop-stall-monitor-9kR0sAPS.js → event-loop-stall-monitor-Dk28EF8B.js} +1 -1
- package/dist/index.js +284 -86048
- package/dist/index.mjs +513 -86302
- package/dist/{jwt-signing-key-CAbozwvF.mjs → jwt-signing-key-MQLxLfgF.mjs} +1 -1
- package/dist/{jwt-signing-key-Dgf8sIXY.js → jwt-signing-key-WI6z7JBo.js} +1 -1
- package/dist/kernel/index.d.ts +6 -2
- package/dist/kernel/moleculer/agent-mesh-authenticator.d.ts +41 -0
- package/dist/kernel/moleculer/broker-factory.d.ts +19 -3
- package/dist/kernel/moleculer/mesh-access-middleware.d.ts +7 -2
- package/dist/kernel/moleculer/mesh-mtls/constants.d.ts +20 -0
- package/dist/kernel/moleculer/mesh-mtls/index.d.ts +9 -0
- package/dist/kernel/moleculer/mesh-mtls/mesh-ca-keeper.d.ts +55 -0
- package/dist/kernel/moleculer/mesh-mtls/mesh-ca.d.ts +45 -0
- package/dist/kernel/moleculer/mesh-mtls/mesh-crl.d.ts +16 -0
- package/dist/kernel/moleculer/mesh-mtls/mesh-enroll.d.ts +27 -0
- package/dist/kernel/moleculer/mesh-mtls/mesh-join-token.d.ts +55 -0
- package/dist/kernel/moleculer/mesh-mtls/mesh-tls-enabler.d.ts +5 -0
- package/dist/kernel/moleculer/mesh-mtls/tls-tcp-transporter.d.ts +92 -0
- package/dist/ms-DlIWNkkk.mjs +160 -0
- package/dist/ms-t68_FaqE.js +171 -0
- package/dist/{restore-archive-CbvrfPuB.js → restore-archive-C5f9yX90.js} +3 -3
- package/dist/{restore-archive-BV39nY46.mjs → restore-archive-CZRtI1k9.mjs} +2 -2
- package/dist/{retired-settings-keys-CzpIkwS-.mjs → retired-settings-keys-LuDd4y3M.mjs} +1 -1
- package/dist/{retired-settings-keys-4bHpL-0m.js → retired-settings-keys-WLrbzdPR.js} +1 -1
- package/dist/tls-BWpwU-d5.js +1160 -0
- package/dist/tls-C2NT-Orr.mjs +949 -0
- package/dist/{tls-CljF057D.js → x509.es-BhTzcFhZ.js} +65 -1108
- package/dist/{tls-4cRH24Id.mjs → x509.es-Xf3K_brW.mjs} +40 -950
- package/package.json +3 -2
package/dist/kernel/index.d.ts
CHANGED
|
@@ -37,8 +37,10 @@ export type { AddonSettingsView } from './config-manager.js';
|
|
|
37
37
|
export { DeviceRegistry } from './device-registry.js';
|
|
38
38
|
export { buildStorageLocationRegistry } from './storage-location-registry.js';
|
|
39
39
|
export type { StorageLocationRegistry } from './storage-location-registry.js';
|
|
40
|
-
export { createBroker, deriveAgentListenPort } from './moleculer/broker-factory.js';
|
|
40
|
+
export { createBroker, deriveAgentListenPort, getBrokerTlsTransporter, } from './moleculer/broker-factory.js';
|
|
41
41
|
export type { BrokerConfig } from './moleculer/broker-factory.js';
|
|
42
|
+
export { caFingerprint, caFingerprintCompact, createMeshCsrPem, enrollMeshNode, generateMeshCa, generateMeshKeyPair, getProcessMeshCaState, issueMeshLeafForNode, issueMeshLeafFromCsr, JoinTokenJtiStore, loadMeshCa, MESH_CA_FIELD, MESH_CA_KEY_REF, MESH_CA_SETTINGS_KEY, MeshCaKeeper, MeshCrl, mintMeshJoinToken, processMeshCrl, processJoinTokenJtiStore, requireProcessMeshCa, setProcessMeshTlsEnabler, TlsTcpTransporter, verifyMeshJoinToken, DEFAULT_HUB_TLS_TCP_PORT, } from './moleculer/mesh-mtls/index.js';
|
|
43
|
+
export type { MeshCaSigner, MeshEnrollResult, MeshJoinTokenClaims, MeshTlsMaterial, } from './moleculer/mesh-mtls/index.js';
|
|
42
44
|
export { type AddonDeploySource, isAddonDeploySource } from './moleculer/addon-deploy-source.js';
|
|
43
45
|
export { createAddonService, validateProviderRegistrations, } from './moleculer/addon-service-factory.js';
|
|
44
46
|
export { createCoreCapService, CORE_CAP_SERVICE_NAME } from './moleculer/core-cap-service.js';
|
|
@@ -57,7 +59,9 @@ export type { ClusterSecretGate, ClusterSecretVerdict } from './moleculer/cluste
|
|
|
57
59
|
export { MeshAuthenticator, isRemoteForbiddenAction, MESH_JOIN_CHALLENGE_TTL_MS, } from './moleculer/mesh-authenticator.js';
|
|
58
60
|
export type { MeshAuthenticatorDeps, MeshCallVerdict, } from './moleculer/mesh-authenticator.js';
|
|
59
61
|
export { createMeshAccessMiddleware, stripForgedIdentity, } from './moleculer/mesh-access-middleware.js';
|
|
60
|
-
export type { MeshAccessMiddlewareOptions } from './moleculer/mesh-access-middleware.js';
|
|
62
|
+
export type { MeshAccessMiddlewareOptions, MeshCallGate, } from './moleculer/mesh-access-middleware.js';
|
|
63
|
+
export { AgentMeshAuthenticator, AGENT_REGISTER_NODE_ACTION, isOwnChildNodeId, isRemoteForbiddenOnAgent, } from './moleculer/agent-mesh-authenticator.js';
|
|
64
|
+
export type { AgentMeshAuthenticatorDeps } from './moleculer/agent-mesh-authenticator.js';
|
|
61
65
|
export { MeshJoinClient } from './moleculer/mesh-join-client.js';
|
|
62
66
|
export type { MeshJoinCall, MeshJoinClientOptions, MeshJoinState, } from './moleculer/mesh-join-client.js';
|
|
63
67
|
export { computeHubJoinProof, computeNodeJoinProof, meshErrorType, MESH_ACTION_FORBIDDEN_TYPE, MESH_JOIN_AUTHENTICATE_ACTION, MESH_JOIN_CHALLENGE_ACTION, MESH_JOIN_CHALLENGE_INVALID_TYPE, MESH_JOIN_PROTOCOL, MESH_NODE_UNAUTHENTICATED_TYPE, } from './moleculer/mesh-join-proof.js';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { MeshAuthMode, MeshNodeAuthState } from './mesh-auth-mode.js';
|
|
2
|
+
import { MeshCallVerdict } from './mesh-authenticator.js';
|
|
3
|
+
import { MeshJoinState } from './mesh-join-client.js';
|
|
4
|
+
/** The child's register action on its parent agent. */
|
|
5
|
+
export declare const AGENT_REGISTER_NODE_ACTION = "$agent.registerNode";
|
|
6
|
+
export declare function isRemoteForbiddenOnAgent(action: string): boolean;
|
|
7
|
+
export declare function isOwnChildNodeId(ownNodeId: string, sender: string): boolean;
|
|
8
|
+
export interface AgentMeshAuthenticatorDeps {
|
|
9
|
+
readonly ownNodeId: string;
|
|
10
|
+
readonly hubNodeId?: string;
|
|
11
|
+
/** True when `agent.json` holds a cluster secret. */
|
|
12
|
+
readonly hasSecret: () => boolean;
|
|
13
|
+
readonly now?: () => number;
|
|
14
|
+
/** First time a peer is tolerated without proof on this connection. */
|
|
15
|
+
readonly onTolerated?: (nodeId: string, action: string) => void;
|
|
16
|
+
}
|
|
17
|
+
export declare class AgentMeshAuthenticator {
|
|
18
|
+
private readonly deps;
|
|
19
|
+
private readonly nodes;
|
|
20
|
+
private readonly hubNodeId;
|
|
21
|
+
private readonly now;
|
|
22
|
+
constructor(deps: AgentMeshAuthenticatorDeps);
|
|
23
|
+
/** Current mode: secret configured → enforce; else tolerate (upgrade path). */
|
|
24
|
+
mode(): MeshAuthMode;
|
|
25
|
+
/**
|
|
26
|
+
* Reflect a settled mesh join. `authenticated` stamps the hub; a blocking
|
|
27
|
+
* failure forgets it so an impostor cannot call in; transitional states
|
|
28
|
+
* leave the hub unmarked (calls are tolerated while mode is `transition`).
|
|
29
|
+
*/
|
|
30
|
+
noteHubJoinState(state: MeshJoinState): void;
|
|
31
|
+
/** A child's `$agent.registerNode` was accepted (secret hash matched or none required). */
|
|
32
|
+
noteChildRegistered(sender: string, proof?: 'authenticated' | 'legacy'): void;
|
|
33
|
+
/** The peer's connection dropped. */
|
|
34
|
+
forget(nodeId: string): void;
|
|
35
|
+
admitCall(sender: string, action: string): MeshCallVerdict;
|
|
36
|
+
admitEvent(sender: string, eventName: string): MeshCallVerdict;
|
|
37
|
+
stateOf(nodeId: string): MeshNodeAuthState;
|
|
38
|
+
authenticatedNodeIds(): readonly string[];
|
|
39
|
+
private admitSender;
|
|
40
|
+
private record;
|
|
41
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ServiceBroker, Middleware } from 'moleculer';
|
|
2
|
+
import { MeshTlsMaterial, TlsTcpTransporter } from './mesh-mtls/index.js';
|
|
2
3
|
interface BrokerConfig {
|
|
3
4
|
readonly nodeID: string;
|
|
4
5
|
readonly mode: 'hub' | 'agent' | 'test';
|
|
@@ -10,6 +11,11 @@ interface BrokerConfig {
|
|
|
10
11
|
* when UDP multicast discovery is disabled.
|
|
11
12
|
*/
|
|
12
13
|
readonly tcpPort?: number;
|
|
14
|
+
/**
|
|
15
|
+
* Second hub listen port for mesh mTLS (Release A). Default 6443.
|
|
16
|
+
* Clear traffic stays on {@link tcpPort}; enrolled agents dial this.
|
|
17
|
+
*/
|
|
18
|
+
readonly tlsPort?: number;
|
|
13
19
|
/** UDP port for cluster discovery (default: 4445). */
|
|
14
20
|
readonly udpPort?: number;
|
|
15
21
|
/**
|
|
@@ -22,11 +28,18 @@ interface BrokerConfig {
|
|
|
22
28
|
readonly agentListenPort?: number;
|
|
23
29
|
/**
|
|
24
30
|
* Broker middlewares (D802): the hub passes its mesh gate
|
|
25
|
-
* (`createMeshAccessMiddleware`)
|
|
26
|
-
* (`
|
|
31
|
+
* (`createMeshAccessMiddleware`); an agent passes inbound access
|
|
32
|
+
* (`AgentMeshAuthenticator` + the same middleware) and its outbound join
|
|
33
|
+
* gate (`MeshJoinClient.middleware`). They must be given at construction —
|
|
27
34
|
* Moleculer wraps action handlers when services register.
|
|
28
35
|
*/
|
|
29
36
|
readonly middlewares?: readonly Middleware[];
|
|
37
|
+
/**
|
|
38
|
+
* Mesh mTLS material. On the hub, enables the TLS listener (may also be
|
|
39
|
+
* attached later via {@link getBrokerTlsTransporter}). On an agent, dials
|
|
40
|
+
* the hub's TLS port (6443) instead of clear 6000.
|
|
41
|
+
*/
|
|
42
|
+
readonly meshTls?: MeshTlsMaterial;
|
|
30
43
|
}
|
|
31
44
|
/**
|
|
32
45
|
* Derive a STABLE Moleculer reader port for an agent from its nodeID.
|
|
@@ -51,5 +64,8 @@ interface BrokerConfig {
|
|
|
51
64
|
*/
|
|
52
65
|
declare function deriveAgentListenPort(nodeID: string): number;
|
|
53
66
|
declare function createBroker(config: BrokerConfig): ServiceBroker;
|
|
54
|
-
|
|
67
|
+
declare function normalizeHubUrl(raw: string, defaultPort: number): string;
|
|
68
|
+
/** The hub's {@link TlsTcpTransporter}, or null when the broker is not mesh-TLS. */
|
|
69
|
+
declare function getBrokerTlsTransporter(broker: ServiceBroker): TlsTcpTransporter | null;
|
|
70
|
+
export { createBroker, deriveAgentListenPort, getBrokerTlsTransporter, normalizeHubUrl };
|
|
55
71
|
export type { BrokerConfig };
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { Middleware } from 'moleculer';
|
|
2
|
-
import {
|
|
2
|
+
import { MeshCallVerdict } from './mesh-authenticator.js';
|
|
3
|
+
/** Minimal surface the middleware needs — hub and agent authenticators both fit. */
|
|
4
|
+
export interface MeshCallGate {
|
|
5
|
+
admitCall(sender: string, action: string): MeshCallVerdict;
|
|
6
|
+
admitEvent(sender: string, eventName: string): MeshCallVerdict;
|
|
7
|
+
}
|
|
3
8
|
/**
|
|
4
9
|
* The params of a request from another node, with every identity it claimed
|
|
5
10
|
* removed:
|
|
@@ -17,7 +22,7 @@ interface GateLogger {
|
|
|
17
22
|
}
|
|
18
23
|
export interface MeshAccessMiddlewareOptions {
|
|
19
24
|
readonly ownNodeId: string;
|
|
20
|
-
readonly authenticator:
|
|
25
|
+
readonly authenticator: MeshCallGate;
|
|
21
26
|
readonly logger?: GateLogger;
|
|
22
27
|
}
|
|
23
28
|
/**
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** `secret://system/global/meshCaKey` — EC P-256 PKCS#8 PEM of the hub mesh CA. */
|
|
2
|
+
export declare const MESH_CA_KEY_REF: string;
|
|
3
|
+
/** `system-settings` key holding the public CA certificate PEM. */
|
|
4
|
+
export declare const MESH_CA_SETTINGS_KEY = "cluster.meshCa";
|
|
5
|
+
/** Field inside the `cluster` section (same row as the secret). */
|
|
6
|
+
export declare const MESH_CA_FIELD = "meshCa";
|
|
7
|
+
/** Join-token / leaf lifetimes. */
|
|
8
|
+
export declare const MESH_JOIN_TOKEN_MAX_TTL_SEC: number;
|
|
9
|
+
export declare const MESH_LEAF_VALIDITY_DAYS = 30;
|
|
10
|
+
export declare const MESH_CA_VALIDITY_DAYS = 3650;
|
|
11
|
+
/** Hub clear TCP (existing) and TLS dual-listen port (Release A). */
|
|
12
|
+
export declare const DEFAULT_HUB_TCP_PORT = 6000;
|
|
13
|
+
export declare const DEFAULT_HUB_TLS_TCP_PORT = 6443;
|
|
14
|
+
/** Join token payload version. */
|
|
15
|
+
export declare const MESH_JOIN_TOKEN_VERSION: 1;
|
|
16
|
+
/** Subject of the mesh root. Distinct from the HTTPS local CA. */
|
|
17
|
+
export declare const MESH_CA_COMMON_NAME = "CamStack Mesh CA";
|
|
18
|
+
/** Client + server auth EKU OIDs (mutual TLS). */
|
|
19
|
+
export declare const SERVER_AUTH_OID = "1.3.6.1.5.5.7.3.1";
|
|
20
|
+
export declare const CLIENT_AUTH_OID = "1.3.6.1.5.5.7.3.2";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { CLIENT_AUTH_OID, DEFAULT_HUB_TCP_PORT, DEFAULT_HUB_TLS_TCP_PORT, MESH_CA_COMMON_NAME, MESH_CA_FIELD, MESH_CA_KEY_REF, MESH_CA_SETTINGS_KEY, MESH_CA_VALIDITY_DAYS, MESH_JOIN_TOKEN_MAX_TTL_SEC, MESH_JOIN_TOKEN_VERSION, MESH_LEAF_VALIDITY_DAYS, SERVER_AUTH_OID, } from './constants.js';
|
|
2
|
+
export { caFingerprint, caFingerprintCompact, createMeshCsrPem, exportMeshPrivateKeyPem, generateMeshCa, generateMeshKeyPair, issueMeshLeafForNode, issueMeshLeafFromCsr, loadMeshCa, MESH_KEY_ALGORITHM, MESH_SIGNING_ALGORITHM, subjectCn, type MeshCaSigner, type MeshLeafMaterial, } from './mesh-ca.js';
|
|
3
|
+
export { clearProcessMeshCa, getProcessMeshCaState, loadOrGenerateMeshCa, MESH_CA_RETRY_MS, MeshCaKeeper, requireProcessMeshCa, setProcessMeshCa, type MeshCaKeeperDeps, type MeshCaState, } from './mesh-ca-keeper.js';
|
|
4
|
+
export { clearProcessMeshCrl, MeshCrl, processMeshCrl, } from './mesh-crl.js';
|
|
5
|
+
export { enrollMeshNode } from './mesh-enroll.js';
|
|
6
|
+
export type { EnrollMeshNodeDeps, MeshEnrollRequest, MeshEnrollResult, } from './mesh-enroll.js';
|
|
7
|
+
export { JoinTokenJtiStore, mintMeshJoinToken, processJoinTokenJtiStore, verifyMeshJoinToken, type MeshJoinTokenClaims, type MintJoinTokenInput, } from './mesh-join-token.js';
|
|
8
|
+
export { getProcessMeshTlsEnabler, requestProcessMeshTlsEnable, setProcessMeshTlsEnabler, type MeshTlsEnabler, } from './mesh-tls-enabler.js';
|
|
9
|
+
export { TlsTcpTransporter, type MeshTlsMaterial, type TlsTcpTransporterOptions, } from './tls-tcp-transporter.js';
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { SecretsAccess } from '@camstack/types';
|
|
2
|
+
import { MeshCaSigner } from './mesh-ca.js';
|
|
3
|
+
export type MeshCaState = {
|
|
4
|
+
readonly state: 'ready';
|
|
5
|
+
readonly ca: MeshCaSigner;
|
|
6
|
+
} | {
|
|
7
|
+
readonly state: 'unavailable';
|
|
8
|
+
readonly reason: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function setProcessMeshCa(state: MeshCaState): void;
|
|
11
|
+
export declare function clearProcessMeshCa(): void;
|
|
12
|
+
export declare function getProcessMeshCaState(): MeshCaState;
|
|
13
|
+
export declare function requireProcessMeshCa(): MeshCaSigner;
|
|
14
|
+
export declare const MESH_CA_RETRY_MS = 30000;
|
|
15
|
+
interface KeeperLogger {
|
|
16
|
+
info(message: string, meta?: {
|
|
17
|
+
meta?: Record<string, unknown>;
|
|
18
|
+
}): void;
|
|
19
|
+
error(message: string, meta?: {
|
|
20
|
+
meta?: Record<string, unknown>;
|
|
21
|
+
}): void;
|
|
22
|
+
warn?(message: string, meta?: {
|
|
23
|
+
meta?: Record<string, unknown>;
|
|
24
|
+
}): void;
|
|
25
|
+
}
|
|
26
|
+
export interface MeshCaKeeperDeps {
|
|
27
|
+
readonly secrets: SecretsAccess | null;
|
|
28
|
+
/** Read `cluster` section (may contain `meshCa` PEM). */
|
|
29
|
+
readonly readClusterSection: () => Promise<Record<string, unknown>>;
|
|
30
|
+
/** Persist the CA cert PEM under `cluster.meshCa`. */
|
|
31
|
+
readonly writeMeshCaCert: (certPem: string) => Promise<void>;
|
|
32
|
+
readonly logger: KeeperLogger;
|
|
33
|
+
readonly retryMs?: number;
|
|
34
|
+
/** Fired when the CA becomes ready (start TLS listener, etc.). */
|
|
35
|
+
readonly onReady?: (ca: MeshCaSigner) => void | Promise<void>;
|
|
36
|
+
}
|
|
37
|
+
export declare class MeshCaKeeper {
|
|
38
|
+
private readonly deps;
|
|
39
|
+
private retryTimer;
|
|
40
|
+
private unsubscribe;
|
|
41
|
+
private stopped;
|
|
42
|
+
constructor(deps: MeshCaKeeperDeps);
|
|
43
|
+
start(): Promise<void>;
|
|
44
|
+
stop(): void;
|
|
45
|
+
private load;
|
|
46
|
+
private apply;
|
|
47
|
+
private scheduleRetry;
|
|
48
|
+
}
|
|
49
|
+
export interface LoadOrGenerateMeshCaDeps {
|
|
50
|
+
readonly secrets: SecretsAccess;
|
|
51
|
+
readonly readClusterSection: () => Promise<Record<string, unknown>>;
|
|
52
|
+
readonly writeMeshCaCert: (certPem: string) => Promise<void>;
|
|
53
|
+
}
|
|
54
|
+
export declare function loadOrGenerateMeshCa(deps: LoadOrGenerateMeshCaDeps): Promise<MeshCaState>;
|
|
55
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { webcrypto as WebCrypto } from 'node:crypto';
|
|
2
|
+
import { X509Certificate as PeculiarCertificate } from '@peculiar/x509';
|
|
3
|
+
/** Key generation — EC P-256 (plan). WebCrypto DOM names are not in @types/node. */
|
|
4
|
+
export declare const MESH_KEY_ALGORITHM: WebCrypto.EcKeyGenParams;
|
|
5
|
+
/** Signing — ECDSA with SHA-256. */
|
|
6
|
+
export declare const MESH_SIGNING_ALGORITHM: WebCrypto.EcdsaParams;
|
|
7
|
+
export interface MeshCaSigner {
|
|
8
|
+
readonly certPem: string;
|
|
9
|
+
readonly keyPem: string;
|
|
10
|
+
readonly cert: PeculiarCertificate;
|
|
11
|
+
readonly privateKey: WebCrypto.CryptoKey;
|
|
12
|
+
readonly publicKey: WebCrypto.CryptoKey;
|
|
13
|
+
}
|
|
14
|
+
export interface MeshLeafMaterial {
|
|
15
|
+
readonly certPem: string;
|
|
16
|
+
readonly serialNumber: string;
|
|
17
|
+
readonly notAfter: Date;
|
|
18
|
+
readonly commonName: string;
|
|
19
|
+
}
|
|
20
|
+
/** SHA-256 fingerprint of the DER cert, colon-hex uppercase (Node style). */
|
|
21
|
+
export declare function caFingerprint(certPem: string): string;
|
|
22
|
+
/** Compact fingerprint (lowercase hex, no colons) for join-token payloads. */
|
|
23
|
+
export declare function caFingerprintCompact(certPem: string): string;
|
|
24
|
+
export declare function generateMeshCa(now?: Date): Promise<MeshCaSigner>;
|
|
25
|
+
export declare function loadMeshCa(certPem: string, keyPem: string): Promise<MeshCaSigner>;
|
|
26
|
+
/**
|
|
27
|
+
* Issue a leaf from a CSR. CN must be present; when `expectedNodeId` is set
|
|
28
|
+
* it must match. Validity: 30 days.
|
|
29
|
+
*/
|
|
30
|
+
export declare function issueMeshLeafFromCsr(ca: MeshCaSigner, csrPem: string, opts?: {
|
|
31
|
+
readonly expectedNodeId?: string;
|
|
32
|
+
readonly now?: Date;
|
|
33
|
+
readonly validDays?: number;
|
|
34
|
+
}): Promise<MeshLeafMaterial>;
|
|
35
|
+
/** Issue a leaf for a known nodeID with a freshly generated key pair (tests / hub self). */
|
|
36
|
+
export declare function issueMeshLeafForNode(ca: MeshCaSigner, nodeId: string, opts?: {
|
|
37
|
+
readonly now?: Date;
|
|
38
|
+
readonly validDays?: number;
|
|
39
|
+
}): Promise<MeshLeafMaterial & {
|
|
40
|
+
readonly keyPem: string;
|
|
41
|
+
}>;
|
|
42
|
+
export declare function subjectCn(subject: string): string | null;
|
|
43
|
+
export declare function createMeshCsrPem(keys: WebCrypto.CryptoKeyPair, commonName: string): Promise<string>;
|
|
44
|
+
export declare function generateMeshKeyPair(): Promise<WebCrypto.CryptoKeyPair>;
|
|
45
|
+
export declare function exportMeshPrivateKeyPem(key: WebCrypto.CryptoKey): Promise<string>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mesh certificate revocation list — in-memory + optional persist hook.
|
|
3
|
+
*
|
|
4
|
+
* Release A can stub persistence; the reader checks serials at handshake and
|
|
5
|
+
* a later "Forget node" closes open sockets (Release A+).
|
|
6
|
+
*/
|
|
7
|
+
export declare class MeshCrl {
|
|
8
|
+
private readonly serials;
|
|
9
|
+
revoke(serialNumber: string): void;
|
|
10
|
+
isRevoked(serialNumber: string): boolean;
|
|
11
|
+
list(): readonly string[];
|
|
12
|
+
/** Restore from persisted serials (system-settings). */
|
|
13
|
+
replaceAll(serials: readonly string[]): void;
|
|
14
|
+
}
|
|
15
|
+
export declare function processMeshCrl(): MeshCrl;
|
|
16
|
+
export declare function clearProcessMeshCrl(): void;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { MeshCaSigner } from './mesh-ca.js';
|
|
2
|
+
import { JoinTokenJtiStore, MeshJoinTokenClaims } from './mesh-join-token.js';
|
|
3
|
+
export interface MeshEnrollRequest {
|
|
4
|
+
readonly token: string;
|
|
5
|
+
readonly csr: string;
|
|
6
|
+
}
|
|
7
|
+
export interface MeshEnrollSuccess {
|
|
8
|
+
readonly ok: true;
|
|
9
|
+
readonly cert: string;
|
|
10
|
+
readonly caCert: string;
|
|
11
|
+
readonly nodeId: string;
|
|
12
|
+
readonly notAfter: string;
|
|
13
|
+
readonly serialNumber: string;
|
|
14
|
+
}
|
|
15
|
+
export interface MeshEnrollFailure {
|
|
16
|
+
readonly ok: false;
|
|
17
|
+
readonly error: string;
|
|
18
|
+
readonly status: number;
|
|
19
|
+
}
|
|
20
|
+
export type MeshEnrollResult = MeshEnrollSuccess | MeshEnrollFailure;
|
|
21
|
+
export interface EnrollMeshNodeDeps {
|
|
22
|
+
readonly ca: MeshCaSigner;
|
|
23
|
+
readonly jtiStore?: JoinTokenJtiStore;
|
|
24
|
+
readonly now?: Date;
|
|
25
|
+
}
|
|
26
|
+
export declare function enrollMeshNode(body: MeshEnrollRequest, deps: EnrollMeshNodeDeps): Promise<MeshEnrollResult>;
|
|
27
|
+
export type { MeshJoinTokenClaims };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { MESH_JOIN_TOKEN_VERSION } from './constants.js';
|
|
2
|
+
import { MeshCaSigner } from './mesh-ca.js';
|
|
3
|
+
export interface MeshJoinTokenClaims {
|
|
4
|
+
readonly v: typeof MESH_JOIN_TOKEN_VERSION;
|
|
5
|
+
readonly hubUrl: string;
|
|
6
|
+
readonly hubMeshAddress: string;
|
|
7
|
+
readonly caFingerprint: string;
|
|
8
|
+
readonly nodeId?: string;
|
|
9
|
+
readonly jti: string;
|
|
10
|
+
readonly exp: number;
|
|
11
|
+
}
|
|
12
|
+
export type MeshJoinTokenVerifyResult = {
|
|
13
|
+
readonly ok: true;
|
|
14
|
+
readonly claims: MeshJoinTokenClaims;
|
|
15
|
+
} | {
|
|
16
|
+
readonly ok: false;
|
|
17
|
+
readonly reason: string;
|
|
18
|
+
};
|
|
19
|
+
/** In-memory + optional persist of spent `jti` until `exp`. */
|
|
20
|
+
export declare class JoinTokenJtiStore {
|
|
21
|
+
private readonly spent;
|
|
22
|
+
/** True when `jti` was already consumed (and not yet expired). */
|
|
23
|
+
isSpent(jti: string, nowSec?: number): boolean;
|
|
24
|
+
/** Record a jti as used until `exp`. Returns false if already spent. */
|
|
25
|
+
consume(jti: string, exp: number, nowSec?: number): boolean;
|
|
26
|
+
/** Test helper. */
|
|
27
|
+
size(): number;
|
|
28
|
+
private gc;
|
|
29
|
+
}
|
|
30
|
+
export declare function processJoinTokenJtiStore(): JoinTokenJtiStore;
|
|
31
|
+
export interface MintJoinTokenInput {
|
|
32
|
+
readonly ca: MeshCaSigner;
|
|
33
|
+
readonly hubUrl: string;
|
|
34
|
+
readonly hubMeshAddress: string;
|
|
35
|
+
readonly nodeId?: string;
|
|
36
|
+
/** Seconds from now; capped at {@link MESH_JOIN_TOKEN_MAX_TTL_SEC}. */
|
|
37
|
+
readonly ttlSec?: number;
|
|
38
|
+
readonly now?: Date;
|
|
39
|
+
readonly jti?: string;
|
|
40
|
+
}
|
|
41
|
+
export declare function mintMeshJoinToken(input: MintJoinTokenInput): Promise<string>;
|
|
42
|
+
export interface VerifyJoinTokenInput {
|
|
43
|
+
readonly token: string;
|
|
44
|
+
readonly ca: MeshCaSigner;
|
|
45
|
+
readonly jtiStore?: JoinTokenJtiStore;
|
|
46
|
+
readonly now?: Date;
|
|
47
|
+
/** When true (enroll), consume the jti. Mint-path verify may skip. */
|
|
48
|
+
readonly consume?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Expected CA fingerprint pin. When set, must match the token's
|
|
51
|
+
* `caFingerprint` (and therefore this CA) — a MITM with another CA fails.
|
|
52
|
+
*/
|
|
53
|
+
readonly expectedCaFingerprint?: string;
|
|
54
|
+
}
|
|
55
|
+
export declare function verifyMeshJoinToken(input: VerifyJoinTokenInput): Promise<MeshJoinTokenVerifyResult>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { MeshTlsMaterial } from './tls-tcp-transporter.js';
|
|
2
|
+
export type MeshTlsEnabler = (material: MeshTlsMaterial) => void | Promise<void>;
|
|
3
|
+
export declare function setProcessMeshTlsEnabler(enabler: MeshTlsEnabler | null): void;
|
|
4
|
+
export declare function getProcessMeshTlsEnabler(): MeshTlsEnabler | null;
|
|
5
|
+
export declare function requestProcessMeshTlsEnable(material: MeshTlsMaterial): Promise<void>;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Server as NetServer, Socket as NetSocket } from 'node:net';
|
|
2
|
+
import { MeshCrl } from './mesh-crl.js';
|
|
3
|
+
interface TlsTcpTransporterBase {
|
|
4
|
+
opts: Record<string, unknown> & {
|
|
5
|
+
port?: number;
|
|
6
|
+
tlsPort?: number;
|
|
7
|
+
maxPacketSize?: number;
|
|
8
|
+
};
|
|
9
|
+
logger: {
|
|
10
|
+
info(msg: string, ...args: unknown[]): void;
|
|
11
|
+
warn(msg: string, ...args: unknown[]): void;
|
|
12
|
+
debug(msg: string, ...args: unknown[]): void;
|
|
13
|
+
error(msg: string, ...args: unknown[]): void;
|
|
14
|
+
};
|
|
15
|
+
reader: {
|
|
16
|
+
listen(): Promise<number>;
|
|
17
|
+
close(): void;
|
|
18
|
+
} | null;
|
|
19
|
+
writer: unknown;
|
|
20
|
+
Promise: PromiseConstructor;
|
|
21
|
+
connected: boolean;
|
|
22
|
+
nodes: {
|
|
23
|
+
localNode: {
|
|
24
|
+
port: number;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
registry: {
|
|
28
|
+
regenerateLocalRawInfo(force: boolean): void;
|
|
29
|
+
};
|
|
30
|
+
startTcpServer(): Promise<number>;
|
|
31
|
+
startUdpServer(): Promise<void>;
|
|
32
|
+
startTimers(): void;
|
|
33
|
+
onConnected(): Promise<void>;
|
|
34
|
+
loadUrls(): Promise<void>;
|
|
35
|
+
connect(): Promise<void>;
|
|
36
|
+
disconnect(): Promise<void>;
|
|
37
|
+
onIncomingMessage(type: string, message: Buffer, socket?: NetSocket): unknown;
|
|
38
|
+
receive(cmd: string, data: Buffer, socket?: NetSocket): unknown;
|
|
39
|
+
deserialize(type: string, data: Buffer): {
|
|
40
|
+
payload: {
|
|
41
|
+
sender?: string;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
incomingMessage(cmd: string, data: Buffer): unknown;
|
|
45
|
+
}
|
|
46
|
+
export interface MeshTlsMaterial {
|
|
47
|
+
readonly caCertPem: string;
|
|
48
|
+
readonly certPem: string;
|
|
49
|
+
readonly keyPem: string;
|
|
50
|
+
}
|
|
51
|
+
export interface TlsTcpTransporterOptions {
|
|
52
|
+
readonly port?: number;
|
|
53
|
+
readonly tlsPort?: number;
|
|
54
|
+
readonly maxPacketSize?: number;
|
|
55
|
+
readonly useHostname?: boolean;
|
|
56
|
+
readonly udpDiscovery?: boolean;
|
|
57
|
+
readonly udpPort?: number;
|
|
58
|
+
readonly udpPeriod?: number;
|
|
59
|
+
readonly debug?: boolean;
|
|
60
|
+
readonly urls?: string;
|
|
61
|
+
readonly udpMaxDiscovery?: number;
|
|
62
|
+
/** When set at construction, TLS starts with the clear reader. */
|
|
63
|
+
readonly meshTls?: MeshTlsMaterial;
|
|
64
|
+
readonly crl?: MeshCrl;
|
|
65
|
+
}
|
|
66
|
+
declare const TlsTcpTransporter_base: new (opts?: Record<string, unknown>) => TlsTcpTransporterBase;
|
|
67
|
+
export declare class TlsTcpTransporter extends TlsTcpTransporter_base {
|
|
68
|
+
private tlsServer;
|
|
69
|
+
private meshTls;
|
|
70
|
+
private readonly crl;
|
|
71
|
+
private readonly tlsSockets;
|
|
72
|
+
constructor(opts?: TlsTcpTransporterOptions);
|
|
73
|
+
startTcpServer(): Promise<number>;
|
|
74
|
+
connect(): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Agent / outbound: wrap `TcpWriter.connect` so peers are dialed with
|
|
77
|
+
* mutual TLS and the peer CN must match the expected node id.
|
|
78
|
+
*/
|
|
79
|
+
private patchWriterForTlsClient;
|
|
80
|
+
/**
|
|
81
|
+
* Enable (or refresh) the TLS listener once the mesh CA / hub leaf are ready.
|
|
82
|
+
* Safe to call after connect — starts listening on `tlsPort` alongside clear.
|
|
83
|
+
*/
|
|
84
|
+
enableMeshTls(material: MeshTlsMaterial): Promise<void>;
|
|
85
|
+
/** Close sockets whose peer serial was just revoked. */
|
|
86
|
+
dropRevokedSockets(): void;
|
|
87
|
+
disconnect(): Promise<void>;
|
|
88
|
+
onIncomingMessage(type: string, message: Buffer, socket?: NetSocket): unknown;
|
|
89
|
+
private startTlsServerIfReady;
|
|
90
|
+
private onTlsClientConnected;
|
|
91
|
+
}
|
|
92
|
+
export type { NetServer };
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { i as __require, t as __commonJSMin } from "./chunk-CNf5ZN-e.mjs";
|
|
2
|
+
//#region ../../node_modules/safe-buffer/index.js
|
|
3
|
+
var require_safe_buffer = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
4
|
+
/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
5
|
+
var buffer = __require("buffer");
|
|
6
|
+
var Buffer = buffer.Buffer;
|
|
7
|
+
function copyProps(src, dst) {
|
|
8
|
+
for (var key in src) dst[key] = src[key];
|
|
9
|
+
}
|
|
10
|
+
if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) module.exports = buffer;
|
|
11
|
+
else {
|
|
12
|
+
copyProps(buffer, exports);
|
|
13
|
+
exports.Buffer = SafeBuffer;
|
|
14
|
+
}
|
|
15
|
+
function SafeBuffer(arg, encodingOrOffset, length) {
|
|
16
|
+
return Buffer(arg, encodingOrOffset, length);
|
|
17
|
+
}
|
|
18
|
+
SafeBuffer.prototype = Object.create(Buffer.prototype);
|
|
19
|
+
copyProps(Buffer, SafeBuffer);
|
|
20
|
+
SafeBuffer.from = function(arg, encodingOrOffset, length) {
|
|
21
|
+
if (typeof arg === "number") throw new TypeError("Argument must not be a number");
|
|
22
|
+
return Buffer(arg, encodingOrOffset, length);
|
|
23
|
+
};
|
|
24
|
+
SafeBuffer.alloc = function(size, fill, encoding) {
|
|
25
|
+
if (typeof size !== "number") throw new TypeError("Argument must be a number");
|
|
26
|
+
var buf = Buffer(size);
|
|
27
|
+
if (fill !== void 0) if (typeof encoding === "string") buf.fill(fill, encoding);
|
|
28
|
+
else buf.fill(fill);
|
|
29
|
+
else buf.fill(0);
|
|
30
|
+
return buf;
|
|
31
|
+
};
|
|
32
|
+
SafeBuffer.allocUnsafe = function(size) {
|
|
33
|
+
if (typeof size !== "number") throw new TypeError("Argument must be a number");
|
|
34
|
+
return Buffer(size);
|
|
35
|
+
};
|
|
36
|
+
SafeBuffer.allocUnsafeSlow = function(size) {
|
|
37
|
+
if (typeof size !== "number") throw new TypeError("Argument must be a number");
|
|
38
|
+
return buffer.SlowBuffer(size);
|
|
39
|
+
};
|
|
40
|
+
}));
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region ../../node_modules/ms/index.js
|
|
43
|
+
var require_ms = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
44
|
+
/**
|
|
45
|
+
* Helpers.
|
|
46
|
+
*/
|
|
47
|
+
var s = 1e3;
|
|
48
|
+
var m = s * 60;
|
|
49
|
+
var h = m * 60;
|
|
50
|
+
var d = h * 24;
|
|
51
|
+
var w = d * 7;
|
|
52
|
+
var y = d * 365.25;
|
|
53
|
+
/**
|
|
54
|
+
* Parse or format the given `val`.
|
|
55
|
+
*
|
|
56
|
+
* Options:
|
|
57
|
+
*
|
|
58
|
+
* - `long` verbose formatting [false]
|
|
59
|
+
*
|
|
60
|
+
* @param {String|Number} val
|
|
61
|
+
* @param {Object} [options]
|
|
62
|
+
* @throws {Error} throw an error if val is not a non-empty string or a number
|
|
63
|
+
* @return {String|Number}
|
|
64
|
+
* @api public
|
|
65
|
+
*/
|
|
66
|
+
module.exports = function(val, options) {
|
|
67
|
+
options = options || {};
|
|
68
|
+
var type = typeof val;
|
|
69
|
+
if (type === "string" && val.length > 0) return parse(val);
|
|
70
|
+
else if (type === "number" && isFinite(val)) return options.long ? fmtLong(val) : fmtShort(val);
|
|
71
|
+
throw new Error("val is not a non-empty string or a valid number. val=" + JSON.stringify(val));
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Parse the given `str` and return milliseconds.
|
|
75
|
+
*
|
|
76
|
+
* @param {String} str
|
|
77
|
+
* @return {Number}
|
|
78
|
+
* @api private
|
|
79
|
+
*/
|
|
80
|
+
function parse(str) {
|
|
81
|
+
str = String(str);
|
|
82
|
+
if (str.length > 100) return;
|
|
83
|
+
var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(str);
|
|
84
|
+
if (!match) return;
|
|
85
|
+
var n = parseFloat(match[1]);
|
|
86
|
+
switch ((match[2] || "ms").toLowerCase()) {
|
|
87
|
+
case "years":
|
|
88
|
+
case "year":
|
|
89
|
+
case "yrs":
|
|
90
|
+
case "yr":
|
|
91
|
+
case "y": return n * y;
|
|
92
|
+
case "weeks":
|
|
93
|
+
case "week":
|
|
94
|
+
case "w": return n * w;
|
|
95
|
+
case "days":
|
|
96
|
+
case "day":
|
|
97
|
+
case "d": return n * d;
|
|
98
|
+
case "hours":
|
|
99
|
+
case "hour":
|
|
100
|
+
case "hrs":
|
|
101
|
+
case "hr":
|
|
102
|
+
case "h": return n * h;
|
|
103
|
+
case "minutes":
|
|
104
|
+
case "minute":
|
|
105
|
+
case "mins":
|
|
106
|
+
case "min":
|
|
107
|
+
case "m": return n * m;
|
|
108
|
+
case "seconds":
|
|
109
|
+
case "second":
|
|
110
|
+
case "secs":
|
|
111
|
+
case "sec":
|
|
112
|
+
case "s": return n * s;
|
|
113
|
+
case "milliseconds":
|
|
114
|
+
case "millisecond":
|
|
115
|
+
case "msecs":
|
|
116
|
+
case "msec":
|
|
117
|
+
case "ms": return n;
|
|
118
|
+
default: return;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Short format for `ms`.
|
|
123
|
+
*
|
|
124
|
+
* @param {Number} ms
|
|
125
|
+
* @return {String}
|
|
126
|
+
* @api private
|
|
127
|
+
*/
|
|
128
|
+
function fmtShort(ms) {
|
|
129
|
+
var msAbs = Math.abs(ms);
|
|
130
|
+
if (msAbs >= d) return Math.round(ms / d) + "d";
|
|
131
|
+
if (msAbs >= h) return Math.round(ms / h) + "h";
|
|
132
|
+
if (msAbs >= m) return Math.round(ms / m) + "m";
|
|
133
|
+
if (msAbs >= s) return Math.round(ms / s) + "s";
|
|
134
|
+
return ms + "ms";
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Long format for `ms`.
|
|
138
|
+
*
|
|
139
|
+
* @param {Number} ms
|
|
140
|
+
* @return {String}
|
|
141
|
+
* @api private
|
|
142
|
+
*/
|
|
143
|
+
function fmtLong(ms) {
|
|
144
|
+
var msAbs = Math.abs(ms);
|
|
145
|
+
if (msAbs >= d) return plural(ms, msAbs, d, "day");
|
|
146
|
+
if (msAbs >= h) return plural(ms, msAbs, h, "hour");
|
|
147
|
+
if (msAbs >= m) return plural(ms, msAbs, m, "minute");
|
|
148
|
+
if (msAbs >= s) return plural(ms, msAbs, s, "second");
|
|
149
|
+
return ms + " ms";
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Pluralization helper.
|
|
153
|
+
*/
|
|
154
|
+
function plural(ms, msAbs, n, name) {
|
|
155
|
+
var isPlural = msAbs >= n * 1.5;
|
|
156
|
+
return Math.round(ms / n) + " " + name + (isPlural ? "s" : "");
|
|
157
|
+
}
|
|
158
|
+
}));
|
|
159
|
+
//#endregion
|
|
160
|
+
export { require_safe_buffer as n, require_ms as t };
|