easyeda-mcp-pro 1.1.0 → 1.2.0
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/README.md +8 -8
- package/dist/bridge/listener-ownership.d.ts +7 -1
- package/dist/bridge/listener-ownership.js +26 -5
- package/dist/bridge/listener-ownership.js.map +1 -1
- package/dist/bridge/local-bridge-relay.d.ts +53 -0
- package/dist/bridge/local-bridge-relay.js +318 -0
- package/dist/bridge/local-bridge-relay.js.map +1 -0
- package/dist/bridge/manager.d.ts +12 -0
- package/dist/bridge/manager.js +185 -14
- package/dist/bridge/manager.js.map +1 -1
- package/dist/bridge/types.d.ts +7 -6
- package/dist/bridge/types.js +1 -0
- package/dist/bridge/types.js.map +1 -1
- package/dist/config/profiles.js +3 -3
- package/dist/config/version.d.ts +1 -1
- package/dist/config/version.js +1 -1
- package/dist/package-build-manifest.json +45 -30
- package/dist/tools/L1_pcb_write.js +332 -4
- package/dist/tools/L1_pcb_write.js.map +1 -1
- package/easyeda-bridge-extension.checksums.json +8 -8
- package/easyeda-bridge-extension.eext +0 -0
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -108,7 +108,7 @@ For advanced configurations, manual instructions, and specific clients, see [Ins
|
|
|
108
108
|
|
|
109
109
|
## Overview
|
|
110
110
|
|
|
111
|
-
easyeda-mcp-pro is a [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that bridges AI assistants with hardware design workflows in EasyEDA Pro. It exposes up to
|
|
111
|
+
easyeda-mcp-pro is a [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that bridges AI assistants with hardware design workflows in EasyEDA Pro. It exposes up to 119 profile-gated MCP tools for schematic inspection and editing, controlled EasyEDA Pro API calls, BOM management, design rule checks, PCB board analysis, fabrication exports, diagnostics, and supplier integration.
|
|
112
112
|
|
|
113
113
|
The server connects to EasyEDA Pro via a WebSocket bridge extension, enabling real-time access to open project data. It integrates with JLCPCB, LCSC, Mouser, and DigiKey for BOM sourcing and pricing.
|
|
114
114
|
|
|
@@ -147,7 +147,7 @@ node scripts/check-runtime.mjs --require-pnpm
|
|
|
147
147
|
|
|
148
148
|
## Installation & Client Configuration
|
|
149
149
|
|
|
150
|
-
>
|
|
150
|
+
> Stable v1 is published. If you are upgrading from a pre-v1 release, follow [Migrating to v1](docs/MIGRATING_TO_V1.md).
|
|
151
151
|
|
|
152
152
|
You can configure `easyeda-mcp-pro` automatically or manually.
|
|
153
153
|
|
|
@@ -594,9 +594,9 @@ The server registers profile-gated tools according to the active `TOOL_PROFILE`.
|
|
|
594
594
|
| -------------- | ---------------: |
|
|
595
595
|
| `core` | 73 |
|
|
596
596
|
| `pro` | 100 |
|
|
597
|
-
| `full` |
|
|
598
|
-
| `dev` |
|
|
599
|
-
| `experimental` |
|
|
597
|
+
| `full` | 114 |
|
|
598
|
+
| `dev` | 119 |
|
|
599
|
+
| `experimental` | 119 |
|
|
600
600
|
|
|
601
601
|
<!-- capability-counts:end -->
|
|
602
602
|
|
|
@@ -700,7 +700,7 @@ The schematic write APIs use EasyEDA Pro extension APIs that EasyEDA currently m
|
|
|
700
700
|
│ (via Plugin) │ Protocol │ └───────────────┘ │
|
|
701
701
|
└─────────────────┘ │ ┌───────────────┐ │
|
|
702
702
|
│ │ ToolRegistry │ │
|
|
703
|
-
│ │ (up to
|
|
703
|
+
│ │ (up to 119 tools) │ │
|
|
704
704
|
│ └───────────────┘ │
|
|
705
705
|
│ ┌───────────────┐ │
|
|
706
706
|
│ │ Storage │──┼──► SQLite
|
|
@@ -920,7 +920,7 @@ See [Security Architecture & Threat Model](docs/security-architecture.md) for th
|
|
|
920
920
|
- **Secret redaction**: API keys, tokens, passwords are redacted from logs and diagnostic output
|
|
921
921
|
- **Branch protection**: Governance policy requires code reviews and status checks on the `main` branch (see [Repository Governance](docs/REPOSITORY_GOVERNANCE.md))
|
|
922
922
|
- **Code scanning**: CodeQL analysis runs on every push and PR (security-extended + security-and-quality queries)
|
|
923
|
-
- **Dependency management**: Renovate
|
|
923
|
+
- **Dependency management**: Renovate policy is configured in-repository; hosted-provider activity is verified through a Renovate Dependency Dashboard or Renovate-authored update activity. Dependency Audit, Dependency Review, Socket, and CodeQL provide independent security signals.
|
|
924
924
|
- **Supply-chain hygiene**: pnpm workspace build, pinned GitHub Actions, and no native SQLite addon dependency
|
|
925
925
|
- **Reporting**: See [SECURITY.md](SECURITY.md) for vulnerability disclosure
|
|
926
926
|
|
|
@@ -930,7 +930,7 @@ See [Security Architecture & Threat Model](docs/security-architecture.md) for th
|
|
|
930
930
|
|
|
931
931
|
This repository uses automated workflows to manage dependencies and releases:
|
|
932
932
|
|
|
933
|
-
- **Renovate**:
|
|
933
|
+
- **Renovate**: [.github/renovate.json](.github/renovate.json) defines the repository's dependency-update policy. Hosted Renovate is an account-level prerequisite; treat a Dependency Dashboard or Renovate-authored update activity as proof that the provider is active. See [Repository Governance](docs/REPOSITORY_GOVERNANCE.md).
|
|
934
934
|
- **Release Please**: Automates stable version bumps, release metadata, and `CHANGELOG.md`. Numbered `rc.N` candidates use the isolated prerelease path. See the [Release Policy](docs/RELEASE_POLICY.md) and [Release Process](docs/RELEASE_PROCESS.md).
|
|
935
935
|
- **Secure Publishing**: The release workflow rebuilds and verifies all assets, publishes npm with provenance to channel-safe `latest` or `next` dist-tags, uploads the extension and SBOM to the matching GitHub Release, and keeps GHCR/MCP Registry promotion aligned with the selected channel.
|
|
936
936
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type LocalBridgeRelayEndpoint } from './local-bridge-relay.js';
|
|
1
2
|
export interface BridgeOwnershipConflict {
|
|
2
3
|
blockedByOtherInstance: true;
|
|
3
4
|
ownerPid: number;
|
|
@@ -7,7 +8,8 @@ export interface BridgeOwnershipConflict {
|
|
|
7
8
|
}
|
|
8
9
|
export declare class BridgeOwnershipConflictError extends Error {
|
|
9
10
|
readonly conflict: BridgeOwnershipConflict;
|
|
10
|
-
|
|
11
|
+
readonly relayEndpoint?: LocalBridgeRelayEndpoint | undefined;
|
|
12
|
+
constructor(conflict: BridgeOwnershipConflict, relayEndpoint?: LocalBridgeRelayEndpoint | undefined);
|
|
11
13
|
}
|
|
12
14
|
export declare class BridgeListenerOwnership {
|
|
13
15
|
private readonly dataDirectory;
|
|
@@ -18,10 +20,13 @@ export declare class BridgeListenerOwnership {
|
|
|
18
20
|
private readonly startedAt;
|
|
19
21
|
private held;
|
|
20
22
|
private port;
|
|
23
|
+
private relayPort;
|
|
21
24
|
constructor(dataDirectory: string, host: string);
|
|
22
25
|
acquire(): void;
|
|
23
26
|
private tryAcquireFreshLock;
|
|
24
27
|
updatePort(port: number): void;
|
|
28
|
+
updateRelayPort(port: number): void;
|
|
29
|
+
get relayAuthToken(): string;
|
|
25
30
|
release(): void;
|
|
26
31
|
private writeOwnerRecord;
|
|
27
32
|
private readLockSnapshot;
|
|
@@ -30,5 +35,6 @@ export declare class BridgeListenerOwnership {
|
|
|
30
35
|
private isStillStale;
|
|
31
36
|
private assertMovedOwnerUnchanged;
|
|
32
37
|
private restoreQuarantine;
|
|
38
|
+
private buildRelayEndpoint;
|
|
33
39
|
private buildConflict;
|
|
34
40
|
}
|
|
@@ -8,9 +8,11 @@ const INITIALIZATION_GRACE_MS = 5_000;
|
|
|
8
8
|
const MAX_ACQUIRE_ATTEMPTS = 4;
|
|
9
9
|
export class BridgeOwnershipConflictError extends Error {
|
|
10
10
|
conflict;
|
|
11
|
-
|
|
11
|
+
relayEndpoint;
|
|
12
|
+
constructor(conflict, relayEndpoint) {
|
|
12
13
|
super(conflict.message);
|
|
13
14
|
this.conflict = conflict;
|
|
15
|
+
this.relayEndpoint = relayEndpoint;
|
|
14
16
|
this.name = 'BridgeOwnershipConflictError';
|
|
15
17
|
}
|
|
16
18
|
}
|
|
@@ -43,7 +45,8 @@ function parseOwnerRecord(raw) {
|
|
|
43
45
|
Number(value.pid) <= 0 ||
|
|
44
46
|
typeof value.startedAt !== 'string' ||
|
|
45
47
|
typeof value.host !== 'string' ||
|
|
46
|
-
(value.port !== undefined && !isValidPort(value.port))
|
|
48
|
+
(value.port !== undefined && !isValidPort(value.port)) ||
|
|
49
|
+
(value.relayPort !== undefined && !isValidPort(value.relayPort))) {
|
|
47
50
|
return undefined;
|
|
48
51
|
}
|
|
49
52
|
return {
|
|
@@ -53,6 +56,7 @@ function parseOwnerRecord(raw) {
|
|
|
53
56
|
startedAt: value.startedAt,
|
|
54
57
|
host: value.host,
|
|
55
58
|
port: value.port === undefined ? undefined : Number(value.port),
|
|
59
|
+
relayPort: value.relayPort === undefined ? undefined : Number(value.relayPort),
|
|
56
60
|
};
|
|
57
61
|
}
|
|
58
62
|
catch {
|
|
@@ -68,6 +72,7 @@ export class BridgeListenerOwnership {
|
|
|
68
72
|
startedAt = new Date().toISOString();
|
|
69
73
|
held = false;
|
|
70
74
|
port;
|
|
75
|
+
relayPort;
|
|
71
76
|
constructor(dataDirectory, host) {
|
|
72
77
|
this.dataDirectory = dataDirectory;
|
|
73
78
|
this.host = host;
|
|
@@ -81,7 +86,7 @@ export class BridgeListenerOwnership {
|
|
|
81
86
|
return;
|
|
82
87
|
const snapshot = this.readLockSnapshot();
|
|
83
88
|
if (snapshot.owner && isProcessAlive(snapshot.owner.pid)) {
|
|
84
|
-
throw new BridgeOwnershipConflictError(this.buildConflict(snapshot.owner));
|
|
89
|
+
throw new BridgeOwnershipConflictError(this.buildConflict(snapshot.owner), this.buildRelayEndpoint(snapshot.owner));
|
|
85
90
|
}
|
|
86
91
|
const staleOwnerToken = snapshot.owner?.token;
|
|
87
92
|
const oldEnough = Date.now() - snapshot.mtimeMs >= INITIALIZATION_GRACE_MS;
|
|
@@ -120,6 +125,15 @@ export class BridgeListenerOwnership {
|
|
|
120
125
|
this.port = port;
|
|
121
126
|
this.writeOwnerRecord();
|
|
122
127
|
}
|
|
128
|
+
updateRelayPort(port) {
|
|
129
|
+
if (!this.held)
|
|
130
|
+
return;
|
|
131
|
+
this.relayPort = port;
|
|
132
|
+
this.writeOwnerRecord();
|
|
133
|
+
}
|
|
134
|
+
get relayAuthToken() {
|
|
135
|
+
return this.token;
|
|
136
|
+
}
|
|
123
137
|
release() {
|
|
124
138
|
if (!this.held)
|
|
125
139
|
return;
|
|
@@ -149,6 +163,7 @@ export class BridgeListenerOwnership {
|
|
|
149
163
|
startedAt: this.startedAt,
|
|
150
164
|
host: this.host,
|
|
151
165
|
port: this.port,
|
|
166
|
+
relayPort: this.relayPort,
|
|
152
167
|
};
|
|
153
168
|
const temporaryFile = join(this.lockDirectory, `.owner-${this.token}.tmp`);
|
|
154
169
|
writeFileSync(temporaryFile, `${JSON.stringify(record)}\n`, {
|
|
@@ -244,6 +259,11 @@ export class BridgeListenerOwnership {
|
|
|
244
259
|
throw error;
|
|
245
260
|
}
|
|
246
261
|
}
|
|
262
|
+
buildRelayEndpoint(owner) {
|
|
263
|
+
if (owner.relayPort === undefined)
|
|
264
|
+
return undefined;
|
|
265
|
+
return { host: '127.0.0.1', port: owner.relayPort, token: owner.token };
|
|
266
|
+
}
|
|
247
267
|
buildConflict(owner) {
|
|
248
268
|
const portText = owner.port === undefined ? '' : `, port ${owner.port}`;
|
|
249
269
|
return {
|
|
@@ -251,8 +271,9 @@ export class BridgeListenerOwnership {
|
|
|
251
271
|
ownerPid: owner.pid,
|
|
252
272
|
ownerPort: owner.port,
|
|
253
273
|
ownerHost: owner.host,
|
|
254
|
-
message: `Local EasyEDA bridge listener is owned by another easyeda-mcp-pro process (PID ${owner.pid}${portText})
|
|
255
|
-
|
|
274
|
+
message: `Local EasyEDA bridge listener is owned by another easyeda-mcp-pro process (PID ${owner.pid}${portText}) ` +
|
|
275
|
+
'that does not expose a compatible local follower relay. Ensure every local MCP client uses the current easyeda-mcp-pro version; ' +
|
|
276
|
+
`if the owner is stale, terminate PID ${owner.pid} and restart this MCP client.`,
|
|
256
277
|
};
|
|
257
278
|
}
|
|
258
279
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listener-ownership.js","sourceRoot":"","sources":["../../src/bridge/listener-ownership.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACL,SAAS,EACT,SAAS,EACT,YAAY,EACZ,UAAU,EACV,MAAM,EACN,QAAQ,EACR,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"listener-ownership.js","sourceRoot":"","sources":["../../src/bridge/listener-ownership.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import { type BridgeHello } from './protocol.js';
|
|
3
|
+
export declare const LOCAL_BRIDGE_RELAY_PROTOCOL_VERSION: 1;
|
|
4
|
+
export type SharedBridgeState = 'disconnected' | 'connecting' | 'connected' | 'error';
|
|
5
|
+
export interface SharedBridgeSnapshot {
|
|
6
|
+
state: SharedBridgeState;
|
|
7
|
+
hello: BridgeHello | null;
|
|
8
|
+
activePort: number;
|
|
9
|
+
connectedAtMs: number;
|
|
10
|
+
lastHeartbeatMs: number;
|
|
11
|
+
extensionVersion?: string;
|
|
12
|
+
extensionMethodListHash?: string;
|
|
13
|
+
loaderVersion?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface LocalBridgeRelayEndpoint {
|
|
16
|
+
host: '127.0.0.1';
|
|
17
|
+
port: number;
|
|
18
|
+
token: string;
|
|
19
|
+
}
|
|
20
|
+
interface RelayCallOptions {
|
|
21
|
+
timeoutMs?: number;
|
|
22
|
+
traceparent?: string;
|
|
23
|
+
}
|
|
24
|
+
interface RelayServerOptions {
|
|
25
|
+
token: string;
|
|
26
|
+
maxPayloadBytes: number;
|
|
27
|
+
snapshot: () => SharedBridgeSnapshot;
|
|
28
|
+
call: (method: string, params: unknown, options: RelayCallOptions) => Promise<unknown>;
|
|
29
|
+
authTimeoutMs?: number;
|
|
30
|
+
maxClients?: number;
|
|
31
|
+
}
|
|
32
|
+
export declare class LocalBridgeRelayServer {
|
|
33
|
+
private readonly options;
|
|
34
|
+
private wss;
|
|
35
|
+
private readonly clients;
|
|
36
|
+
constructor(options: RelayServerOptions);
|
|
37
|
+
start(): Promise<number>;
|
|
38
|
+
broadcast(snapshot?: SharedBridgeSnapshot): void;
|
|
39
|
+
close(): void;
|
|
40
|
+
private handleConnection;
|
|
41
|
+
}
|
|
42
|
+
export declare class LocalBridgeRelayClient extends EventEmitter {
|
|
43
|
+
private readonly endpoint;
|
|
44
|
+
private socket;
|
|
45
|
+
private attached;
|
|
46
|
+
private requestCounter;
|
|
47
|
+
private readonly pending;
|
|
48
|
+
constructor(endpoint: LocalBridgeRelayEndpoint);
|
|
49
|
+
connect(timeoutMs?: number): Promise<SharedBridgeSnapshot>;
|
|
50
|
+
call<TResult>(method: string, params: unknown, options: RelayCallOptions, responseTimeoutMs: number): Promise<TResult>;
|
|
51
|
+
disconnect(): void;
|
|
52
|
+
}
|
|
53
|
+
export {};
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import { WebSocket, WebSocketServer } from 'ws';
|
|
3
|
+
import { EasyedaApiMethodSchema } from './types.js';
|
|
4
|
+
export const LOCAL_BRIDGE_RELAY_PROTOCOL_VERSION = 1;
|
|
5
|
+
const DEFAULT_RELAY_AUTH_TIMEOUT_MS = 2_000;
|
|
6
|
+
const DEFAULT_MAX_RELAY_CLIENTS = 32;
|
|
7
|
+
function isRecord(value) {
|
|
8
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
9
|
+
}
|
|
10
|
+
function rawMessageToString(raw) {
|
|
11
|
+
if (Array.isArray(raw))
|
|
12
|
+
return Buffer.concat(raw).toString('utf8');
|
|
13
|
+
if (Buffer.isBuffer(raw))
|
|
14
|
+
return raw.toString('utf8');
|
|
15
|
+
return Buffer.from(raw).toString('utf8');
|
|
16
|
+
}
|
|
17
|
+
function errorPayload(error) {
|
|
18
|
+
const record = isRecord(error) ? error : {};
|
|
19
|
+
return {
|
|
20
|
+
code: typeof record.code === 'string' ? record.code : undefined,
|
|
21
|
+
message: error instanceof Error ? error.message : String(error),
|
|
22
|
+
suggestion: typeof record.suggestion === 'string' ? record.suggestion : undefined,
|
|
23
|
+
data: record.data,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function errorFromPayload(payload) {
|
|
27
|
+
const error = new Error(payload.message);
|
|
28
|
+
Object.assign(error, {
|
|
29
|
+
code: payload.code,
|
|
30
|
+
suggestion: payload.suggestion,
|
|
31
|
+
data: payload.data,
|
|
32
|
+
});
|
|
33
|
+
return error;
|
|
34
|
+
}
|
|
35
|
+
export class LocalBridgeRelayServer {
|
|
36
|
+
options;
|
|
37
|
+
wss = null;
|
|
38
|
+
clients = new Set();
|
|
39
|
+
constructor(options) {
|
|
40
|
+
this.options = options;
|
|
41
|
+
}
|
|
42
|
+
async start() {
|
|
43
|
+
if (this.wss)
|
|
44
|
+
throw new Error('Local bridge follower relay is already running.');
|
|
45
|
+
const wss = new WebSocketServer({
|
|
46
|
+
host: '127.0.0.1',
|
|
47
|
+
port: 0,
|
|
48
|
+
maxPayload: this.options.maxPayloadBytes,
|
|
49
|
+
});
|
|
50
|
+
this.wss = wss;
|
|
51
|
+
wss.on('connection', (socket) => {
|
|
52
|
+
this.handleConnection(socket);
|
|
53
|
+
});
|
|
54
|
+
await new Promise((resolve, reject) => {
|
|
55
|
+
const onError = (error) => {
|
|
56
|
+
wss.off('listening', onListening);
|
|
57
|
+
reject(error);
|
|
58
|
+
};
|
|
59
|
+
const onListening = () => {
|
|
60
|
+
wss.off('error', onError);
|
|
61
|
+
resolve();
|
|
62
|
+
};
|
|
63
|
+
wss.once('error', onError);
|
|
64
|
+
wss.once('listening', onListening);
|
|
65
|
+
});
|
|
66
|
+
const address = wss.address();
|
|
67
|
+
if (!address || typeof address === 'string') {
|
|
68
|
+
wss.close();
|
|
69
|
+
this.wss = null;
|
|
70
|
+
throw new Error('Local bridge follower relay did not expose a TCP port.');
|
|
71
|
+
}
|
|
72
|
+
return address.port;
|
|
73
|
+
}
|
|
74
|
+
broadcast(snapshot = this.options.snapshot()) {
|
|
75
|
+
const payload = JSON.stringify({
|
|
76
|
+
type: 'status',
|
|
77
|
+
protocolVersion: LOCAL_BRIDGE_RELAY_PROTOCOL_VERSION,
|
|
78
|
+
snapshot,
|
|
79
|
+
});
|
|
80
|
+
for (const client of this.clients) {
|
|
81
|
+
if (client.readyState === WebSocket.OPEN)
|
|
82
|
+
client.send(payload);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
close() {
|
|
86
|
+
const wss = this.wss;
|
|
87
|
+
this.wss = null;
|
|
88
|
+
for (const client of this.clients) {
|
|
89
|
+
client.close(1001, 'owner_shutdown');
|
|
90
|
+
}
|
|
91
|
+
this.clients.clear();
|
|
92
|
+
wss?.close();
|
|
93
|
+
}
|
|
94
|
+
handleConnection(socket) {
|
|
95
|
+
const maxClients = this.options.maxClients ?? DEFAULT_MAX_RELAY_CLIENTS;
|
|
96
|
+
if ((this.wss?.clients.size ?? 0) > maxClients) {
|
|
97
|
+
socket.close(1013, 'relay_capacity');
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
let authenticated = false;
|
|
101
|
+
const authTimer = setTimeout(() => {
|
|
102
|
+
if (!authenticated && socket.readyState === WebSocket.OPEN) {
|
|
103
|
+
socket.close(4003, 'relay_auth_timeout');
|
|
104
|
+
}
|
|
105
|
+
}, this.options.authTimeoutMs ?? DEFAULT_RELAY_AUTH_TIMEOUT_MS);
|
|
106
|
+
socket.on('message', (raw) => {
|
|
107
|
+
let data;
|
|
108
|
+
try {
|
|
109
|
+
const parsed = JSON.parse(rawMessageToString(raw));
|
|
110
|
+
if (!isRecord(parsed))
|
|
111
|
+
throw new Error('relay message must be an object');
|
|
112
|
+
data = parsed;
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
socket.close(4001, 'invalid_message');
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (!authenticated) {
|
|
119
|
+
if (data.type !== 'attach' ||
|
|
120
|
+
data.protocolVersion !== LOCAL_BRIDGE_RELAY_PROTOCOL_VERSION ||
|
|
121
|
+
data.token !== this.options.token) {
|
|
122
|
+
socket.close(4003, 'invalid_relay_auth');
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
authenticated = true;
|
|
126
|
+
clearTimeout(authTimer);
|
|
127
|
+
this.clients.add(socket);
|
|
128
|
+
socket.send(JSON.stringify({
|
|
129
|
+
type: 'attached',
|
|
130
|
+
protocolVersion: LOCAL_BRIDGE_RELAY_PROTOCOL_VERSION,
|
|
131
|
+
snapshot: this.options.snapshot(),
|
|
132
|
+
}));
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (data.type !== 'call' || typeof data.id !== 'string' || typeof data.method !== 'string') {
|
|
136
|
+
socket.close(4001, 'invalid_relay_message');
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (!EasyedaApiMethodSchema.options.includes(data.method)) {
|
|
140
|
+
socket.send(JSON.stringify({
|
|
141
|
+
type: 'response',
|
|
142
|
+
id: data.id,
|
|
143
|
+
ok: false,
|
|
144
|
+
error: {
|
|
145
|
+
code: 'METHOD_NOT_FOUND',
|
|
146
|
+
message: `Unknown bridge method: "${data.method}"`,
|
|
147
|
+
},
|
|
148
|
+
}));
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const timeoutMs = typeof data.timeoutMs === 'number' && Number.isFinite(data.timeoutMs) && data.timeoutMs > 0
|
|
152
|
+
? data.timeoutMs
|
|
153
|
+
: undefined;
|
|
154
|
+
const traceparent = typeof data.traceparent === 'string' ? data.traceparent : undefined;
|
|
155
|
+
void this.options
|
|
156
|
+
.call(data.method, data.params, { timeoutMs, traceparent })
|
|
157
|
+
.then((result) => {
|
|
158
|
+
if (socket.readyState !== WebSocket.OPEN)
|
|
159
|
+
return;
|
|
160
|
+
socket.send(JSON.stringify({ type: 'response', id: data.id, ok: true, result }));
|
|
161
|
+
})
|
|
162
|
+
.catch((error) => {
|
|
163
|
+
if (socket.readyState !== WebSocket.OPEN)
|
|
164
|
+
return;
|
|
165
|
+
socket.send(JSON.stringify({
|
|
166
|
+
type: 'response',
|
|
167
|
+
id: data.id,
|
|
168
|
+
ok: false,
|
|
169
|
+
error: errorPayload(error),
|
|
170
|
+
}));
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
socket.on('close', () => {
|
|
174
|
+
clearTimeout(authTimer);
|
|
175
|
+
this.clients.delete(socket);
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
export class LocalBridgeRelayClient extends EventEmitter {
|
|
180
|
+
endpoint;
|
|
181
|
+
socket = null;
|
|
182
|
+
attached = false;
|
|
183
|
+
requestCounter = 0;
|
|
184
|
+
pending = new Map();
|
|
185
|
+
constructor(endpoint) {
|
|
186
|
+
super();
|
|
187
|
+
this.endpoint = endpoint;
|
|
188
|
+
}
|
|
189
|
+
async connect(timeoutMs = 1_500) {
|
|
190
|
+
if (this.socket)
|
|
191
|
+
throw new Error('Local bridge follower relay is already connected.');
|
|
192
|
+
const socket = new WebSocket(`ws://${this.endpoint.host}:${this.endpoint.port}`);
|
|
193
|
+
this.socket = socket;
|
|
194
|
+
return new Promise((resolve, reject) => {
|
|
195
|
+
let settled = false;
|
|
196
|
+
const timer = setTimeout(() => {
|
|
197
|
+
if (settled)
|
|
198
|
+
return;
|
|
199
|
+
settled = true;
|
|
200
|
+
socket.close(4000, 'attach_timeout');
|
|
201
|
+
this.socket = null;
|
|
202
|
+
reject(new Error('Timed out attaching to the local EasyEDA bridge owner.'));
|
|
203
|
+
}, timeoutMs);
|
|
204
|
+
const fail = (error) => {
|
|
205
|
+
if (settled)
|
|
206
|
+
return;
|
|
207
|
+
settled = true;
|
|
208
|
+
clearTimeout(timer);
|
|
209
|
+
this.socket = null;
|
|
210
|
+
reject(error);
|
|
211
|
+
};
|
|
212
|
+
socket.once('open', () => {
|
|
213
|
+
socket.send(JSON.stringify({
|
|
214
|
+
type: 'attach',
|
|
215
|
+
protocolVersion: LOCAL_BRIDGE_RELAY_PROTOCOL_VERSION,
|
|
216
|
+
token: this.endpoint.token,
|
|
217
|
+
}));
|
|
218
|
+
});
|
|
219
|
+
socket.once('error', (error) => {
|
|
220
|
+
fail(error);
|
|
221
|
+
});
|
|
222
|
+
socket.on('message', (raw) => {
|
|
223
|
+
let message;
|
|
224
|
+
try {
|
|
225
|
+
const parsed = JSON.parse(rawMessageToString(raw));
|
|
226
|
+
if (!isRecord(parsed))
|
|
227
|
+
return;
|
|
228
|
+
message = parsed;
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
if (!this.attached && message.type === 'attached' && isRecord(message.snapshot)) {
|
|
234
|
+
this.attached = true;
|
|
235
|
+
if (!settled) {
|
|
236
|
+
settled = true;
|
|
237
|
+
clearTimeout(timer);
|
|
238
|
+
resolve(message.snapshot);
|
|
239
|
+
}
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
if (message.type === 'status' && isRecord(message.snapshot)) {
|
|
243
|
+
this.emit('status', message.snapshot);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (message.type !== 'response' || typeof message.id !== 'string')
|
|
247
|
+
return;
|
|
248
|
+
const pending = this.pending.get(message.id);
|
|
249
|
+
if (!pending)
|
|
250
|
+
return;
|
|
251
|
+
clearTimeout(pending.timer);
|
|
252
|
+
this.pending.delete(message.id);
|
|
253
|
+
if (message.ok === true) {
|
|
254
|
+
pending.resolve(message.result);
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
const payload = isRecord(message.error)
|
|
258
|
+
? message.error
|
|
259
|
+
: { message: 'Shared EasyEDA bridge call failed.' };
|
|
260
|
+
pending.reject(errorFromPayload(payload));
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
socket.on('close', (code, reason) => {
|
|
264
|
+
clearTimeout(timer);
|
|
265
|
+
this.socket = null;
|
|
266
|
+
this.attached = false;
|
|
267
|
+
const error = new Error(`Local EasyEDA bridge owner relay disconnected (${code}: ${reason.toString() || 'closed'}).`);
|
|
268
|
+
for (const [, pending] of this.pending) {
|
|
269
|
+
clearTimeout(pending.timer);
|
|
270
|
+
pending.reject(error);
|
|
271
|
+
}
|
|
272
|
+
this.pending.clear();
|
|
273
|
+
if (!settled)
|
|
274
|
+
fail(error);
|
|
275
|
+
else
|
|
276
|
+
this.emit('close', error);
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
call(method, params, options, responseTimeoutMs) {
|
|
281
|
+
const socket = this.socket;
|
|
282
|
+
if (!socket || !this.attached || socket.readyState !== WebSocket.OPEN) {
|
|
283
|
+
return Promise.reject(new Error('Local EasyEDA bridge owner relay is not connected.'));
|
|
284
|
+
}
|
|
285
|
+
const id = `relay_${process.pid}_${++this.requestCounter}`;
|
|
286
|
+
return new Promise((resolve, reject) => {
|
|
287
|
+
const timer = setTimeout(() => {
|
|
288
|
+
this.pending.delete(id);
|
|
289
|
+
reject(new Error(`Shared bridge method "${method}" timed out after ${responseTimeoutMs}ms`));
|
|
290
|
+
}, responseTimeoutMs);
|
|
291
|
+
this.pending.set(id, {
|
|
292
|
+
resolve: resolve,
|
|
293
|
+
reject,
|
|
294
|
+
timer,
|
|
295
|
+
});
|
|
296
|
+
socket.send(JSON.stringify({
|
|
297
|
+
type: 'call',
|
|
298
|
+
id,
|
|
299
|
+
method,
|
|
300
|
+
params,
|
|
301
|
+
timeoutMs: options.timeoutMs,
|
|
302
|
+
traceparent: options.traceparent,
|
|
303
|
+
}));
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
disconnect() {
|
|
307
|
+
const socket = this.socket;
|
|
308
|
+
this.socket = null;
|
|
309
|
+
this.attached = false;
|
|
310
|
+
for (const [, pending] of this.pending) {
|
|
311
|
+
clearTimeout(pending.timer);
|
|
312
|
+
pending.reject(new Error('Local EasyEDA bridge follower disconnected.'));
|
|
313
|
+
}
|
|
314
|
+
this.pending.clear();
|
|
315
|
+
socket?.close(1000, 'follower_shutdown');
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
//# sourceMappingURL=local-bridge-relay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-bridge-relay.js","sourceRoot":"","sources":["../../src/bridge/local-bridge-relay.ts"],"names":[],"mappings":"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"}
|
package/dist/bridge/manager.d.ts
CHANGED
|
@@ -25,6 +25,8 @@ export declare class BridgeManager extends EventEmitter {
|
|
|
25
25
|
private _extensionMethodListHash;
|
|
26
26
|
private _loaderVersion;
|
|
27
27
|
private listenerOwnership;
|
|
28
|
+
private followerRelayServer;
|
|
29
|
+
private followerRelayClient;
|
|
28
30
|
private _ownershipConflict;
|
|
29
31
|
constructor(config: EnvConfig);
|
|
30
32
|
get lastHeartbeatMs(): number;
|
|
@@ -58,6 +60,14 @@ export declare class BridgeManager extends EventEmitter {
|
|
|
58
60
|
private isLoopbackHost;
|
|
59
61
|
private computeMethodRegistryHash;
|
|
60
62
|
connect(): Promise<void>;
|
|
63
|
+
private acquireOwnershipOrFollow;
|
|
64
|
+
private tryAttachFollowerConflict;
|
|
65
|
+
private createFollowerSnapshot;
|
|
66
|
+
private broadcastFollowerSnapshot;
|
|
67
|
+
private startFollowerRelay;
|
|
68
|
+
private attachFollowerRelay;
|
|
69
|
+
private applyFollowerSnapshot;
|
|
70
|
+
private handleFollowerRelayClose;
|
|
61
71
|
private tryListen;
|
|
62
72
|
private handleConnection;
|
|
63
73
|
/**
|
|
@@ -71,6 +81,8 @@ export declare class BridgeManager extends EventEmitter {
|
|
|
71
81
|
* so unknown methods are rejected with a structured error response.
|
|
72
82
|
*/
|
|
73
83
|
private handleIncomingRequest;
|
|
84
|
+
private bridgeMetricCategory;
|
|
85
|
+
private callThroughFollower;
|
|
74
86
|
call<TParams, TResult>(method: string, params?: TParams, opts?: {
|
|
75
87
|
timeoutMs?: number;
|
|
76
88
|
traceparent?: string;
|