@aiot-nexus/plugin-sdk 1.1.1 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -10
- package/dev-host/host.html +3 -0
- package/dev-host/main.js +370 -138
- package/dev-host/plugin-host.js +418 -0
- package/dist/.generated/plugin-framework-version.d.ts +1 -1
- package/dist/.generated/plugin-framework-version.js +1 -1
- package/dist/src/cli/run.js +2 -2
- package/dist/src/dev.js +3 -3
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/nexus-dev-control.d.ts +1 -2
- package/dist/src/nexus-dev-control.js +6 -10
- package/dist/src/nexus-dev.d.ts +5 -2
- package/dist/src/nexus-dev.js +64 -93
- package/dist/src/types.d.ts +12 -9
- package/package.json +1 -1
- package/templates/minimal/.vscode/launch.json +1 -1
- package/templates/minimal/README.md.tmpl +4 -4
- package/templates/minimal/src/main.ts.tmpl +6 -3
- package/templates/sqlite/.vscode/launch.json +1 -1
- package/templates/sqlite/README.md.tmpl +3 -3
- package/templates/sqlite/src/better-sqlite3.d.ts +1 -0
- package/templates/sqlite/src/main.ts.tmpl +17 -9
- package/templates/sqlite/src/renderer/index.html +1 -1
- package/templates/sqlite/src/renderer/plugin.css +14 -1
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
3
|
+
|
|
4
|
+
const path = require("path");
|
|
5
|
+
|
|
6
|
+
const protocolVersion = 2;
|
|
7
|
+
const operationPattern = /^[a-z][A-Za-z0-9]*(?:\.[a-z][A-Za-z0-9]*){1,4}$/;
|
|
8
|
+
const implementedPermissions = new Set(["businessLog", "settings"]);
|
|
9
|
+
const routeGuardPermissions = new Set(["filesystem", "udp", "serial", "dialog"]);
|
|
10
|
+
const port = process.parentPort;
|
|
11
|
+
|
|
12
|
+
if (!port) {
|
|
13
|
+
process.stderr.write("[nexus-plugin-dev-worker] utility process parent port is unavailable.\n");
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const operations = new Map();
|
|
18
|
+
const pendingHostRequests = new Map();
|
|
19
|
+
let initialized = false;
|
|
20
|
+
let ready = false;
|
|
21
|
+
let shuttingDown = false;
|
|
22
|
+
let exiting = false;
|
|
23
|
+
let pluginId = "";
|
|
24
|
+
let pluginDirectory = "";
|
|
25
|
+
let pluginDataDirectory = "";
|
|
26
|
+
let manifest;
|
|
27
|
+
let hostVersion = "";
|
|
28
|
+
let hostApiVersion = "";
|
|
29
|
+
let pluginModule;
|
|
30
|
+
let requestSequence = 0;
|
|
31
|
+
|
|
32
|
+
port.on("message", function handleParentMessage(event) {
|
|
33
|
+
void handleMessage(readMessageData(event));
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
process.once("uncaughtException", function handleUncaughtException(error) {
|
|
37
|
+
failProcess(errorMessage(error));
|
|
38
|
+
});
|
|
39
|
+
process.once("unhandledRejection", function handleUnhandledRejection(reason) {
|
|
40
|
+
failProcess(errorMessage(reason));
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
async function handleMessage(message) {
|
|
44
|
+
if (exiting || !isRecord(message) || message.protocolVersion !== protocolVersion || typeof message.type !== "string") {
|
|
45
|
+
if (!exiting) {
|
|
46
|
+
failProcess("Plugin worker RPC message is invalid.");
|
|
47
|
+
}
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (message.type === "initialize") {
|
|
51
|
+
await initialize(message);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (message.type === "hostResult") {
|
|
55
|
+
handleHostResult(message);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (message.type === "invoke") {
|
|
59
|
+
await invoke(message);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (message.type === "shutdown") {
|
|
63
|
+
await shutdown(message);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
failProcess("Plugin worker RPC message direction is invalid.");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function initialize(message) {
|
|
70
|
+
if (initialized || shuttingDown || !isWorkerRequestId(message.requestId) || !isRecord(message.payload)) {
|
|
71
|
+
failProcess("Plugin worker initialize request is invalid.");
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const payload = message.payload;
|
|
75
|
+
if (typeof payload.pluginId !== "string"
|
|
76
|
+
|| typeof payload.pluginDirectory !== "string"
|
|
77
|
+
|| typeof payload.pluginDataDirectory !== "string"
|
|
78
|
+
|| !isRecord(payload.manifest)
|
|
79
|
+
|| typeof payload.hostVersion !== "string"
|
|
80
|
+
|| typeof payload.hostApiVersion !== "string") {
|
|
81
|
+
failProcess("Plugin worker initialize payload is invalid.");
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
initialized = true;
|
|
85
|
+
pluginId = payload.pluginId;
|
|
86
|
+
pluginDirectory = payload.pluginDirectory;
|
|
87
|
+
pluginDataDirectory = payload.pluginDataDirectory;
|
|
88
|
+
manifest = payload.manifest;
|
|
89
|
+
hostVersion = payload.hostVersion;
|
|
90
|
+
hostApiVersion = payload.hostApiVersion;
|
|
91
|
+
try {
|
|
92
|
+
if (typeof manifest.mainEntry !== "string" || !manifest.mainEntry) {
|
|
93
|
+
throw new Error("Plugin manifest does not declare mainEntry.");
|
|
94
|
+
}
|
|
95
|
+
const mainEntryPath = path.resolve(pluginDirectory, manifest.mainEntry);
|
|
96
|
+
pluginModule = require(mainEntryPath);
|
|
97
|
+
const activate = typeof pluginModule.activate === "function"
|
|
98
|
+
? pluginModule.activate
|
|
99
|
+
: pluginModule.default && typeof pluginModule.default.activate === "function"
|
|
100
|
+
? pluginModule.default.activate
|
|
101
|
+
: undefined;
|
|
102
|
+
if (activate) {
|
|
103
|
+
await activate({
|
|
104
|
+
pluginId,
|
|
105
|
+
pluginDirectory,
|
|
106
|
+
manifest,
|
|
107
|
+
host: createHostApi()
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
if (exiting || shuttingDown) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
ready = true;
|
|
114
|
+
post({
|
|
115
|
+
protocolVersion,
|
|
116
|
+
type: "ready",
|
|
117
|
+
requestId: message.requestId,
|
|
118
|
+
payload: {
|
|
119
|
+
operations: Array.from(operations.keys()),
|
|
120
|
+
activatedAtUtc: new Date().toISOString()
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
} catch (error) {
|
|
124
|
+
failProcess(errorMessage(error));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function invoke(message) {
|
|
129
|
+
if (!isWorkerRequestId(message.requestId) || !isRecord(message.payload)) {
|
|
130
|
+
failProcess("Plugin worker invoke request is invalid.");
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (!ready || shuttingDown) {
|
|
134
|
+
sendResult(message.requestId, fail("PluginWorkerNotReady", "Plugin worker is not ready."));
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const payload = message.payload;
|
|
138
|
+
if (typeof payload.operation !== "string" || !isSafeOperationName(payload.operation)) {
|
|
139
|
+
sendResult(message.requestId, fail("InvalidRequest", "Plugin renderer operation name is invalid."));
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const handler = operations.get(payload.operation);
|
|
143
|
+
if (!handler) {
|
|
144
|
+
sendResult(message.requestId, fail("NotFound", "Plugin renderer operation was not registered.", { operation: payload.operation }));
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
try {
|
|
148
|
+
const value = await handler({
|
|
149
|
+
pluginId,
|
|
150
|
+
surface: payload.surface,
|
|
151
|
+
contributionId: payload.contributionId,
|
|
152
|
+
operation: payload.operation,
|
|
153
|
+
input: isRecord(payload.input) ? payload.input : undefined
|
|
154
|
+
});
|
|
155
|
+
sendResult(message.requestId, normalizeResult(value));
|
|
156
|
+
} catch (error) {
|
|
157
|
+
sendResult(message.requestId, fail("UnexpectedFailure", "Plugin renderer operation failed.", {
|
|
158
|
+
pluginId,
|
|
159
|
+
operation: payload.operation,
|
|
160
|
+
message: errorMessage(error)
|
|
161
|
+
}));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async function shutdown(message) {
|
|
166
|
+
if (shuttingDown || !isWorkerRequestId(message.requestId)) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
shuttingDown = true;
|
|
170
|
+
try {
|
|
171
|
+
const deactivate = pluginModule && (typeof pluginModule.deactivate === "function"
|
|
172
|
+
? pluginModule.deactivate
|
|
173
|
+
: pluginModule.default && typeof pluginModule.default.deactivate === "function"
|
|
174
|
+
? pluginModule.default.deactivate
|
|
175
|
+
: undefined);
|
|
176
|
+
if (deactivate) {
|
|
177
|
+
await deactivate(isRecord(message.payload) && typeof message.payload.reason === "string" ? message.payload.reason : "quit");
|
|
178
|
+
}
|
|
179
|
+
sendResult(message.requestId, ok(true));
|
|
180
|
+
} catch (error) {
|
|
181
|
+
sendResult(message.requestId, fail("UnexpectedFailure", "Plugin shutdown failed.", errorMessage(error)));
|
|
182
|
+
}
|
|
183
|
+
disposePendingRequests();
|
|
184
|
+
setImmediate(function exitAfterShutdown() {
|
|
185
|
+
exiting = true;
|
|
186
|
+
process.exit(0);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function createHostApi() {
|
|
191
|
+
function unsupported(permission) {
|
|
192
|
+
const target = {
|
|
193
|
+
permission,
|
|
194
|
+
supportState: permissionSupportState(permission),
|
|
195
|
+
describe: function describe() {
|
|
196
|
+
return requestHost("getCapabilityStatus", { permission });
|
|
197
|
+
},
|
|
198
|
+
unsupported: function unsupportedOperation(operation) {
|
|
199
|
+
return requestHost("unsupportedCapability", {
|
|
200
|
+
permission,
|
|
201
|
+
...(typeof operation === "string" ? { operation } : {})
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
return new Proxy(target, {
|
|
206
|
+
get: function get(apiTarget, property) {
|
|
207
|
+
if (property in apiTarget) {
|
|
208
|
+
return Reflect.get(apiTarget, property);
|
|
209
|
+
}
|
|
210
|
+
if (typeof property === "symbol" || property === "then") {
|
|
211
|
+
return undefined;
|
|
212
|
+
}
|
|
213
|
+
return function callUnsupportedOperation() {
|
|
214
|
+
return apiTarget.unsupported(property);
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return {
|
|
221
|
+
hostVersion,
|
|
222
|
+
hostApiVersion,
|
|
223
|
+
pluginId,
|
|
224
|
+
pluginDataDirectory,
|
|
225
|
+
hasPermission: function hasPermission(permission) {
|
|
226
|
+
return Array.isArray(manifest.permissions) && manifest.permissions.includes(permission);
|
|
227
|
+
},
|
|
228
|
+
registerRendererMethod: async function registerRendererMethod(name, handler) {
|
|
229
|
+
if (!isSafeOperationName(name) || typeof handler !== "function") {
|
|
230
|
+
return fail("InvalidRequest", "Plugin renderer operation registration is invalid.");
|
|
231
|
+
}
|
|
232
|
+
if (operations.has(name)) {
|
|
233
|
+
return fail("InvalidRequest", "Plugin renderer operation is already registered.");
|
|
234
|
+
}
|
|
235
|
+
operations.set(name, handler);
|
|
236
|
+
return ok(true);
|
|
237
|
+
},
|
|
238
|
+
getCapabilityStatus: function getCapabilityStatus(permission) {
|
|
239
|
+
return requestHost("getCapabilityStatus", { permission: typeof permission === "string" ? permission : String(permission) });
|
|
240
|
+
},
|
|
241
|
+
unsupportedCapability: function unsupportedCapability(permission, operation) {
|
|
242
|
+
return requestHost("unsupportedCapability", {
|
|
243
|
+
permission: typeof permission === "string" ? permission : String(permission),
|
|
244
|
+
...(typeof operation === "string" ? { operation } : {})
|
|
245
|
+
});
|
|
246
|
+
},
|
|
247
|
+
log: function log(level, message, exception) {
|
|
248
|
+
return requestHost("log", { level, message, ...(exception ? { exception } : {}) });
|
|
249
|
+
},
|
|
250
|
+
getSettings: function getSettings() {
|
|
251
|
+
return requestHost("getSettings");
|
|
252
|
+
},
|
|
253
|
+
updateSettings: function updateSettings(values) {
|
|
254
|
+
return requestHost("updateSettings", { values: sanitizeJsonValue(values) });
|
|
255
|
+
},
|
|
256
|
+
filesystem: unsupported("filesystem"),
|
|
257
|
+
udp: unsupported("udp"),
|
|
258
|
+
serial: unsupported("serial"),
|
|
259
|
+
dialog: unsupported("dialog"),
|
|
260
|
+
externalProcess: unsupported("externalProcess")
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function requestHost(method, params) {
|
|
265
|
+
if (exiting || shuttingDown) {
|
|
266
|
+
return Promise.resolve(fail("PluginWorkerExited", "Plugin worker is stopping."));
|
|
267
|
+
}
|
|
268
|
+
const requestId = pluginId + "-host-" + String(++requestSequence);
|
|
269
|
+
return new Promise(function waitForHostResult(resolve, reject) {
|
|
270
|
+
pendingHostRequests.set(requestId, { resolve, reject });
|
|
271
|
+
try {
|
|
272
|
+
post({
|
|
273
|
+
protocolVersion,
|
|
274
|
+
type: "hostRequest",
|
|
275
|
+
requestId,
|
|
276
|
+
payload: { method, ...(params ? { params: sanitizeJsonValue(params) } : {}) }
|
|
277
|
+
});
|
|
278
|
+
} catch (error) {
|
|
279
|
+
pendingHostRequests.delete(requestId);
|
|
280
|
+
reject(error);
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function handleHostResult(message) {
|
|
286
|
+
if (!isWorkerRequestId(message.requestId) || !isNexusResult(message.result)) {
|
|
287
|
+
failProcess("Plugin worker Host API result is invalid.");
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
const pending = pendingHostRequests.get(message.requestId);
|
|
291
|
+
if (!pending) {
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
pendingHostRequests.delete(message.requestId);
|
|
295
|
+
pending.resolve(message.result);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function sendResult(requestId, result) {
|
|
299
|
+
post({ protocolVersion, type: "result", requestId, result: normalizeResult(result) });
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function post(message) {
|
|
303
|
+
port.postMessage(message);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function failProcess(message) {
|
|
307
|
+
if (exiting) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
exiting = true;
|
|
311
|
+
try {
|
|
312
|
+
post({ protocolVersion, type: "fatal", payload: { message: message || "Plugin worker failed." } });
|
|
313
|
+
} catch {
|
|
314
|
+
// The parent may already be gone.
|
|
315
|
+
}
|
|
316
|
+
disposePendingRequests();
|
|
317
|
+
setImmediate(function exitAfterFatal() {
|
|
318
|
+
process.exit(1);
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function disposePendingRequests() {
|
|
323
|
+
const result = fail("PluginWorkerExited", "Plugin worker stopped.");
|
|
324
|
+
for (const pending of pendingHostRequests.values()) {
|
|
325
|
+
pending.resolve(result);
|
|
326
|
+
}
|
|
327
|
+
pendingHostRequests.clear();
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function normalizeResult(value) {
|
|
331
|
+
if (isNexusResult(value)) {
|
|
332
|
+
if (value.ok) {
|
|
333
|
+
return ok(sanitizeJsonValue(value.value));
|
|
334
|
+
}
|
|
335
|
+
return fail(value.error.code, value.error.message, value.error.details === undefined ? undefined : sanitizeJsonValue(value.error.details));
|
|
336
|
+
}
|
|
337
|
+
return ok(sanitizeJsonValue(value));
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function ok(value) {
|
|
341
|
+
return { ok: true, value: sanitizeJsonValue(value) };
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
function fail(code, message, details) {
|
|
345
|
+
return {
|
|
346
|
+
ok: false,
|
|
347
|
+
error: {
|
|
348
|
+
code,
|
|
349
|
+
message,
|
|
350
|
+
...(details === undefined ? {} : { details: sanitizeJsonValue(details) })
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
function isNexusResult(value) {
|
|
356
|
+
if (!isRecord(value) || typeof value.ok !== "boolean") {
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
359
|
+
return value.ok
|
|
360
|
+
? Object.prototype.hasOwnProperty.call(value, "value")
|
|
361
|
+
: isRecord(value.error) && typeof value.error.code === "string" && typeof value.error.message === "string";
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function isWorkerRequestId(value) {
|
|
365
|
+
return typeof value === "string"
|
|
366
|
+
&& value.length > 0
|
|
367
|
+
&& value.length <= 128
|
|
368
|
+
&& /^[A-Za-z0-9._:-]+$/.test(value);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function isSafeOperationName(value) {
|
|
372
|
+
return typeof value === "string"
|
|
373
|
+
&& value.length <= 80
|
|
374
|
+
&& operationPattern.test(value)
|
|
375
|
+
&& value.split(".").every(function isSafePart(part) {
|
|
376
|
+
return part !== "constructor" && part !== "prototype" && part !== "__proto__";
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function permissionSupportState(permission) {
|
|
381
|
+
if (implementedPermissions.has(permission)) {
|
|
382
|
+
return "implemented";
|
|
383
|
+
}
|
|
384
|
+
if (routeGuardPermissions.has(permission)) {
|
|
385
|
+
return "routeGuard";
|
|
386
|
+
}
|
|
387
|
+
return "reserved";
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function sanitizeJsonValue(value) {
|
|
391
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
392
|
+
return value;
|
|
393
|
+
}
|
|
394
|
+
if (typeof value === "number") {
|
|
395
|
+
return Number.isFinite(value) ? value : null;
|
|
396
|
+
}
|
|
397
|
+
if (Array.isArray(value)) {
|
|
398
|
+
return value.map(sanitizeJsonValue);
|
|
399
|
+
}
|
|
400
|
+
if (isRecord(value)) {
|
|
401
|
+
return Object.fromEntries(Object.entries(value)
|
|
402
|
+
.filter(function removeUndefined(entry) { return entry[1] !== undefined; })
|
|
403
|
+
.map(function sanitizeEntry(entry) { return [entry[0], sanitizeJsonValue(entry[1])]; }));
|
|
404
|
+
}
|
|
405
|
+
return null;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
function isRecord(value) {
|
|
409
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
function readMessageData(event) {
|
|
413
|
+
return isRecord(event) && Object.prototype.hasOwnProperty.call(event, "data") ? event.data : event;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
function errorMessage(error) {
|
|
417
|
+
return error instanceof Error ? error.message : String(error);
|
|
418
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const PLUGIN_FRAMEWORK_VERSION = "
|
|
1
|
+
export declare const PLUGIN_FRAMEWORK_VERSION = "2.0.0";
|
|
2
2
|
export declare const PLUGIN_MANIFEST_SCHEMA_VERSION = 1;
|
|
3
3
|
export declare const PLUGIN_COMPATIBLE_VERSION_PATTERN = "^(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*))?(\\.(0|[1-9][0-9]*))?$";
|
|
4
4
|
export interface ParsedPluginVersion {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.isPluginFrameworkVersionCompatible = exports.comparePluginVersions = exports.parsePluginCompatibleVersion = exports.PLUGIN_COMPATIBLE_VERSION_PATTERN = exports.PLUGIN_MANIFEST_SCHEMA_VERSION = exports.PLUGIN_FRAMEWORK_VERSION = void 0;
|
|
4
|
-
exports.PLUGIN_FRAMEWORK_VERSION = "
|
|
4
|
+
exports.PLUGIN_FRAMEWORK_VERSION = "2.0.0";
|
|
5
5
|
exports.PLUGIN_MANIFEST_SCHEMA_VERSION = 1;
|
|
6
6
|
exports.PLUGIN_COMPATIBLE_VERSION_PATTERN = "^(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*))?(\\.(0|[1-9][0-9]*))?$";
|
|
7
7
|
function parsePluginCompatibleVersion(value) {
|
package/dist/src/cli/run.js
CHANGED
|
@@ -126,7 +126,7 @@ function runNexusDev(args, io) {
|
|
|
126
126
|
const inspector = parseInspectorOption(option);
|
|
127
127
|
if (inspector) {
|
|
128
128
|
if (options.inspectorMode) {
|
|
129
|
-
return usageError(io, "Only one
|
|
129
|
+
return usageError(io, "Only one plugin worker inspector option can be used.");
|
|
130
130
|
}
|
|
131
131
|
const key = "--" + inspector.mode;
|
|
132
132
|
if (seen.has(key)) {
|
|
@@ -304,7 +304,7 @@ function runDev(args, io) {
|
|
|
304
304
|
const inspector = parseInspectorOption(option);
|
|
305
305
|
if (inspector) {
|
|
306
306
|
if (options.inspectorMode) {
|
|
307
|
-
return usageError(io, "Only one
|
|
307
|
+
return usageError(io, "Only one plugin worker inspector option can be used.");
|
|
308
308
|
}
|
|
309
309
|
const key = "--" + inspector.mode;
|
|
310
310
|
if (seen.has(key)) {
|
package/dist/src/dev.js
CHANGED
|
@@ -52,14 +52,14 @@ function runPluginDev(options, io) {
|
|
|
52
52
|
+ "\nContribution: " + target.surface + ":" + target.contributionId
|
|
53
53
|
+ "\nSimulated Nexus application version: " + target.hostVersion);
|
|
54
54
|
if (options.inspectorMode) {
|
|
55
|
-
io.stdout("
|
|
55
|
+
io.stdout("Plugin worker debugger: " + options.inspectorMode
|
|
56
56
|
+ " on 127.0.0.1:" + String(options.inspectorPort || 9229));
|
|
57
57
|
}
|
|
58
58
|
const electronArgs = [];
|
|
59
|
+
electronArgs.push(target.devHostMainPath, "--plugin-package=" + target.packageDirectory, "--project-directory=" + target.projectDirectory, "--surface=" + target.surface, "--contribution-id=" + target.contributionId, "--language=" + target.language, "--theme=" + target.themeMode, "--host-version=" + target.hostVersion);
|
|
59
60
|
if (options.inspectorMode) {
|
|
60
|
-
electronArgs.push("--" + options.inspectorMode + "
|
|
61
|
+
electronArgs.push("--worker-inspector=" + options.inspectorMode + ":" + String(options.inspectorPort || 9229));
|
|
61
62
|
}
|
|
62
|
-
electronArgs.push(target.devHostMainPath, "--plugin-package=" + target.packageDirectory, "--project-directory=" + target.projectDirectory, "--surface=" + target.surface, "--contribution-id=" + target.contributionId, "--language=" + target.language, "--theme=" + target.themeMode, "--host-version=" + target.hostVersion);
|
|
63
63
|
if (!options.openDevTools) {
|
|
64
64
|
electronArgs.push("--no-devtools");
|
|
65
65
|
}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import pluginManifestSchema from "../.generated/plugin-manifest.schema.json";
|
|
2
|
-
export declare const PLUGIN_SDK_VERSION = "
|
|
2
|
+
export declare const PLUGIN_SDK_VERSION = "2.0.1";
|
|
3
3
|
export { pluginManifestSchema };
|
|
4
4
|
export * from "../.generated/plugin-framework-version";
|
|
5
5
|
export * from "./types";
|
package/dist/src/index.js
CHANGED
|
@@ -20,7 +20,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
20
20
|
exports.pluginManifestSchema = exports.PLUGIN_SDK_VERSION = void 0;
|
|
21
21
|
const plugin_manifest_schema_json_1 = __importDefault(require("../.generated/plugin-manifest.schema.json"));
|
|
22
22
|
exports.pluginManifestSchema = plugin_manifest_schema_json_1.default;
|
|
23
|
-
exports.PLUGIN_SDK_VERSION = "
|
|
23
|
+
exports.PLUGIN_SDK_VERSION = "2.0.1";
|
|
24
24
|
__exportStar(require("../.generated/plugin-framework-version"), exports);
|
|
25
25
|
__exportStar(require("./types"), exports);
|
|
26
26
|
__exportStar(require("./browser/frame-client"), exports);
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
export type NexusDevUpdateType = "rendererUpdated" | "manifestUpdated";
|
|
1
|
+
export type NexusDevUpdateType = "rendererUpdated" | "manifestUpdated" | "packageUpdatePreparing" | "packageUpdated";
|
|
2
2
|
export interface NexusDevUpdateResult {
|
|
3
3
|
ok: boolean;
|
|
4
4
|
message: string;
|
|
5
|
-
requiresRestart?: boolean;
|
|
6
5
|
}
|
|
7
6
|
export declare class NexusDevControlServer {
|
|
8
7
|
readonly token: string;
|
|
@@ -30,7 +30,7 @@ const net = __importStar(require("net"));
|
|
|
30
30
|
const os = __importStar(require("os"));
|
|
31
31
|
const path = __importStar(require("path"));
|
|
32
32
|
const dev_1 = require("./dev");
|
|
33
|
-
const protocolVersion =
|
|
33
|
+
const protocolVersion = 2;
|
|
34
34
|
const maximumMessageBytes = 64 * 1024;
|
|
35
35
|
const requestTimeoutMs = 10000;
|
|
36
36
|
class NexusDevControlServer {
|
|
@@ -114,7 +114,7 @@ class NexusDevControlServer {
|
|
|
114
114
|
return new Promise((resolve, reject) => {
|
|
115
115
|
const timer = setTimeout(() => {
|
|
116
116
|
this.pendingShutdowns.delete(requestId);
|
|
117
|
-
reject(new dev_1.PluginDevError("Nexus timed out while accepting the
|
|
117
|
+
reject(new dev_1.PluginDevError("Nexus timed out while accepting the development host shutdown."));
|
|
118
118
|
}, requestTimeoutMs);
|
|
119
119
|
this.pendingShutdowns.set(requestId, { resolve, reject, timer });
|
|
120
120
|
this.socket?.write(JSON.stringify({ type: "shutdown", requestId }) + "\n");
|
|
@@ -239,8 +239,7 @@ class NexusDevControlServer {
|
|
|
239
239
|
clearTimeout(pending.timer);
|
|
240
240
|
pending.resolve({
|
|
241
241
|
ok: value.ok,
|
|
242
|
-
message: value.message
|
|
243
|
-
...(value.requiresRestart ? { requiresRestart: true } : {})
|
|
242
|
+
message: value.message
|
|
244
243
|
});
|
|
245
244
|
return true;
|
|
246
245
|
}
|
|
@@ -342,9 +341,6 @@ function createPipePath() {
|
|
|
342
341
|
: path.join(os.tmpdir(), "nexus-plugin-dev-" + suffix + ".sock");
|
|
343
342
|
}
|
|
344
343
|
function verifyHelloProof(value, token) {
|
|
345
|
-
if (value.proof === undefined) {
|
|
346
|
-
return true;
|
|
347
|
-
}
|
|
348
344
|
const expected = crypto.createHmac("sha256", token)
|
|
349
345
|
.update(helloProofPayload(value.protocolVersion, value.pid, value.nonce), "utf8")
|
|
350
346
|
.digest("hex");
|
|
@@ -363,7 +359,7 @@ function isHelloMessage(value) {
|
|
|
363
359
|
&& value.protocolVersion === protocolVersion
|
|
364
360
|
&& typeof value.pid === "number" && Number.isSafeInteger(value.pid) && value.pid > 0
|
|
365
361
|
&& typeof value.nonce === "string" && /^[a-f0-9]{32}$/i.test(value.nonce)
|
|
366
|
-
&&
|
|
362
|
+
&& typeof value.proof === "string" && /^[a-f0-9]{64}$/i.test(value.proof);
|
|
367
363
|
}
|
|
368
364
|
function isAuthenticatedMessage(value) {
|
|
369
365
|
return isRecord(value)
|
|
@@ -375,11 +371,11 @@ function isUpdateResult(value) {
|
|
|
375
371
|
return isRecord(value)
|
|
376
372
|
&& value.type === "updateResult"
|
|
377
373
|
&& typeof value.requestId === "string"
|
|
378
|
-
&& (value.updateType === "rendererUpdated" || value.updateType === "manifestUpdated")
|
|
374
|
+
&& (value.updateType === "rendererUpdated" || value.updateType === "manifestUpdated" || value.updateType === "packageUpdatePreparing" || value.updateType === "packageUpdated")
|
|
379
375
|
&& typeof value.pluginId === "string"
|
|
380
376
|
&& typeof value.ok === "boolean"
|
|
381
377
|
&& typeof value.message === "string"
|
|
382
|
-
&& (value.
|
|
378
|
+
&& Object.keys(value).every((key) => key === "type" || key === "requestId" || key === "updateType" || key === "pluginId" || key === "ok" || key === "message");
|
|
383
379
|
}
|
|
384
380
|
function isShutdownResult(value) {
|
|
385
381
|
return isRecord(value)
|
package/dist/src/nexus-dev.d.ts
CHANGED
|
@@ -11,10 +11,13 @@ export interface PluginNexusDevIo {
|
|
|
11
11
|
stdout(message: string): void;
|
|
12
12
|
stderr(message: string): void;
|
|
13
13
|
}
|
|
14
|
-
export type PluginSourceChangeKind = "renderer" | "manifest" | "
|
|
14
|
+
export type PluginSourceChangeKind = "renderer" | "manifest" | "package";
|
|
15
15
|
export declare function runPluginNexusDev(options: PluginNexusDevOptions, io: PluginNexusDevIo): Promise<number>;
|
|
16
|
+
export declare function recoverPreparedPluginPackageUpdate(transaction: {
|
|
17
|
+
rollback(): void;
|
|
18
|
+
} | undefined, pluginId: string, control: Pick<NexusDevControlServer, "sendUpdate">): Promise<void>;
|
|
16
19
|
export declare function classifyPluginSourceChange(projectDirectory: string, changedPath: string): PluginSourceChangeKind | undefined;
|
|
17
|
-
export declare function
|
|
20
|
+
export declare function manifestChangeRequiresPackageUpdate(previous: PluginManifest, next: PluginManifest): boolean;
|
|
18
21
|
export declare function mergePluginSourceChange(current: PluginSourceChangeKind | undefined, incoming: PluginSourceChangeKind): PluginSourceChangeKind;
|
|
19
22
|
export declare function createNexusHostArguments(control: Pick<NexusDevControlServer, "pipePath" | "token">, target: PluginDebugTarget, options: Pick<PluginNexusDevOptions, "openDevTools" | "inspectorMode" | "inspectorPort">): string[];
|
|
20
23
|
export declare function isRetryablePluginDeploymentError(error: unknown): boolean;
|