@aiot-nexus/plugin-sdk 2.0.2 → 2.1.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 +18 -8
- package/dev-host/host.html +13 -12
- package/dev-host/main.js +134 -9
- package/dev-host/plugin-host.js +1 -427
- package/dist/.generated/plugin-framework-version.d.ts +1 -1
- package/dist/.generated/plugin-framework-version.js +1 -1
- package/dist/.generated/plugin-manifest.schema.json +1 -1
- package/dist/internal/src-electron/main/core/runtime-result.js +42 -0
- package/dist/internal/src-electron/main/plugins/plugin-electron-facade-broker.js +890 -0
- package/dist/internal/src-electron/plugin-host-bootstrap.js +417 -0
- package/dist/internal/src-electron/shared/contracts.js +2 -0
- package/dist/internal/src-electron/shared/plugin-electron-facade-client.js +181 -0
- package/dist/internal/src-electron/shared/plugin-electron-facade-descriptors.js +70 -0
- package/dist/internal/src-electron/shared/plugin-electron-facade.js +243 -0
- package/dist/internal/src-electron/shared/plugin-rpc.js +245 -0
- package/dist/src/electron-facade.d.ts +4 -0
- package/dist/src/electron-facade.js +56 -0
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.js +2 -1
- package/dist/src/nexus-dev.js +5 -4
- package/dist/src/scaffold.js +2 -2
- package/dist/src/types.d.ts +86 -2
- package/dist/src/web-dev.js +2 -2
- package/package.json +7 -2
- package/templates/minimal/README.md.tmpl +84 -3
- package/templates/minimal/src/main.ts.tmpl +2 -1
- package/templates/sqlite/README.md.tmpl +30 -2
- package/templates/sqlite/src/better-sqlite3.d.ts +12 -1
- package/templates/sqlite/src/main.ts.tmpl +1034 -124
- package/templates/sqlite/src/renderer/app.ts.tmpl +691 -180
- package/templates/sqlite/src/renderer/index.html +40 -22
- package/templates/sqlite/src/renderer/plugin.css +302 -90
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isSafeMemberName = exports.unwrapElectronFacadeResult = exports.isElectronFacadeRequest = exports.decodeElectronFacadeValue = exports.encodeElectronFacadeValue = exports.ElectronFacadeRemoteError = exports.ElectronFacadeCodecError = exports.ElectronFacadeErrorCodes = void 0;
|
|
4
|
+
exports.ElectronFacadeErrorCodes = {
|
|
5
|
+
InvalidRequest: "ElectronFacadeInvalidRequest",
|
|
6
|
+
ModuleUnavailable: "ElectronFacadeModuleUnavailable",
|
|
7
|
+
MemberUnavailable: "ElectronFacadeMemberUnavailable",
|
|
8
|
+
HandleReleased: "ElectronFacadeHandleReleased",
|
|
9
|
+
SerializationUnsupported: "ElectronFacadeSerializationUnsupported",
|
|
10
|
+
ProcessUnavailable: "ElectronFacadeProcessUnavailable",
|
|
11
|
+
SynchronousCallbackUnsupported: "ElectronFacadeSynchronousCallbackUnsupported",
|
|
12
|
+
LifecycleUnavailable: "ElectronFacadeLifecycleUnavailable",
|
|
13
|
+
InvocationFailed: "ElectronFacadeInvocationFailed"
|
|
14
|
+
};
|
|
15
|
+
class ElectronFacadeCodecError extends Error {
|
|
16
|
+
constructor(message) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.code = exports.ElectronFacadeErrorCodes.SerializationUnsupported;
|
|
19
|
+
this.name = "ElectronFacadeCodecError";
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.ElectronFacadeCodecError = ElectronFacadeCodecError;
|
|
23
|
+
class ElectronFacadeRemoteError extends Error {
|
|
24
|
+
constructor(error) {
|
|
25
|
+
super(error.message);
|
|
26
|
+
this.name = "ElectronFacadeRemoteError";
|
|
27
|
+
this.code = error.code;
|
|
28
|
+
this.details = error.details;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.ElectronFacadeRemoteError = ElectronFacadeRemoteError;
|
|
32
|
+
function encodeElectronFacadeValue(value, hooks = {}) {
|
|
33
|
+
return encodeValue(value, hooks, new WeakSet());
|
|
34
|
+
}
|
|
35
|
+
exports.encodeElectronFacadeValue = encodeElectronFacadeValue;
|
|
36
|
+
function decodeElectronFacadeValue(value, hooks = {}) {
|
|
37
|
+
if (Array.isArray(value)) {
|
|
38
|
+
return value.map((item) => decodeElectronFacadeValue(item, hooks));
|
|
39
|
+
}
|
|
40
|
+
if (!isPlainObject(value)) {
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
const tag = typeof value.$nexusElectron === "string" ? value.$nexusElectron : undefined;
|
|
44
|
+
if (!tag) {
|
|
45
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, decodeElectronFacadeValue(item, hooks)]));
|
|
46
|
+
}
|
|
47
|
+
switch (tag) {
|
|
48
|
+
case "undefined":
|
|
49
|
+
return undefined;
|
|
50
|
+
case "bigint": {
|
|
51
|
+
const encoded = readTagString(value, "value");
|
|
52
|
+
if (!/^-?(?:0|[1-9][0-9]*)$/.test(encoded)) {
|
|
53
|
+
throw new ElectronFacadeCodecError("Electron facade bigint tag is invalid.");
|
|
54
|
+
}
|
|
55
|
+
return BigInt(encoded);
|
|
56
|
+
}
|
|
57
|
+
case "number": {
|
|
58
|
+
const encoded = readTagString(value, "value");
|
|
59
|
+
if (encoded === "NaN") {
|
|
60
|
+
return Number.NaN;
|
|
61
|
+
}
|
|
62
|
+
if (encoded === "Infinity") {
|
|
63
|
+
return Number.POSITIVE_INFINITY;
|
|
64
|
+
}
|
|
65
|
+
if (encoded === "-Infinity") {
|
|
66
|
+
return Number.NEGATIVE_INFINITY;
|
|
67
|
+
}
|
|
68
|
+
throw new ElectronFacadeCodecError("Electron facade number tag is invalid.");
|
|
69
|
+
}
|
|
70
|
+
case "buffer": {
|
|
71
|
+
const encoded = readTagString(value, "base64");
|
|
72
|
+
if (encoded.length % 4 !== 0 || !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(encoded)) {
|
|
73
|
+
throw new ElectronFacadeCodecError("Electron facade buffer tag is invalid.");
|
|
74
|
+
}
|
|
75
|
+
return Buffer.from(encoded, "base64");
|
|
76
|
+
}
|
|
77
|
+
case "date": {
|
|
78
|
+
const decoded = new Date(readTagString(value, "value"));
|
|
79
|
+
if (!Number.isFinite(decoded.getTime())) {
|
|
80
|
+
throw new ElectronFacadeCodecError("Electron facade date tag is invalid.");
|
|
81
|
+
}
|
|
82
|
+
return decoded;
|
|
83
|
+
}
|
|
84
|
+
case "error": {
|
|
85
|
+
const error = new Error(readTagString(value, "message"));
|
|
86
|
+
error.name = typeof value.name === "string" ? value.name : "Error";
|
|
87
|
+
if (typeof value.stack === "string") {
|
|
88
|
+
error.stack = value.stack;
|
|
89
|
+
}
|
|
90
|
+
return error;
|
|
91
|
+
}
|
|
92
|
+
case "callback": {
|
|
93
|
+
const callbackId = readTagString(value, "callbackId");
|
|
94
|
+
if (!hooks.decodeFunction) {
|
|
95
|
+
throw new ElectronFacadeCodecError("Electron callback values are not supported in this context.");
|
|
96
|
+
}
|
|
97
|
+
return hooks.decodeFunction(callbackId);
|
|
98
|
+
}
|
|
99
|
+
case "handle": {
|
|
100
|
+
const handleId = readTagString(value, "handleId");
|
|
101
|
+
const typeName = readTagString(value, "typeName");
|
|
102
|
+
const callbackId = value.callbackId === undefined ? undefined : readTagString(value, "callbackId");
|
|
103
|
+
if (!hooks.decodeHandle) {
|
|
104
|
+
throw new ElectronFacadeCodecError("Electron handle values are not supported in this context.");
|
|
105
|
+
}
|
|
106
|
+
return hooks.decodeHandle(handleId, typeName, callbackId);
|
|
107
|
+
}
|
|
108
|
+
case "object": {
|
|
109
|
+
if (!isPlainObject(value.value)) {
|
|
110
|
+
throw new ElectronFacadeCodecError("Electron facade object tag is invalid.");
|
|
111
|
+
}
|
|
112
|
+
return Object.fromEntries(Object.entries(value.value).map(([key, item]) => [key, decodeElectronFacadeValue(item, hooks)]));
|
|
113
|
+
}
|
|
114
|
+
default:
|
|
115
|
+
throw new ElectronFacadeCodecError("Unknown Electron facade wire tag: " + tag + ".");
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
exports.decodeElectronFacadeValue = decodeElectronFacadeValue;
|
|
119
|
+
function isElectronFacadeRequest(value) {
|
|
120
|
+
if (!isPlainObject(value) || !isElectronFacadeOperation(value.operation)) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
const hasModule = typeof value.module === "string" && isSafeMemberName(value.module);
|
|
124
|
+
const hasHandle = typeof value.handleId === "string" && /^[A-Za-z0-9._:-]{1,128}$/.test(value.handleId);
|
|
125
|
+
if (value.operation === "release") {
|
|
126
|
+
return hasHandle && value.module === undefined && value.member === undefined && value.args === undefined;
|
|
127
|
+
}
|
|
128
|
+
if (value.operation === "construct") {
|
|
129
|
+
return hasModule && !hasHandle && value.member === undefined && (value.args === undefined || Array.isArray(value.args));
|
|
130
|
+
}
|
|
131
|
+
if (hasModule === hasHandle || typeof value.member !== "string" || !isSafeMemberName(value.member)) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
if (value.operation === "get") {
|
|
135
|
+
return value.args === undefined;
|
|
136
|
+
}
|
|
137
|
+
if (value.operation === "set" || value.operation === "on" || value.operation === "once") {
|
|
138
|
+
return Array.isArray(value.args) && value.args.length === 1;
|
|
139
|
+
}
|
|
140
|
+
return value.args === undefined || Array.isArray(value.args);
|
|
141
|
+
}
|
|
142
|
+
exports.isElectronFacadeRequest = isElectronFacadeRequest;
|
|
143
|
+
function unwrapElectronFacadeResult(result, hooks = {}) {
|
|
144
|
+
if (!result.ok) {
|
|
145
|
+
throw new ElectronFacadeRemoteError(result.error);
|
|
146
|
+
}
|
|
147
|
+
return decodeElectronFacadeValue(result.value, hooks);
|
|
148
|
+
}
|
|
149
|
+
exports.unwrapElectronFacadeResult = unwrapElectronFacadeResult;
|
|
150
|
+
function isSafeMemberName(value) {
|
|
151
|
+
return /^[A-Za-z_$][A-Za-z0-9_$-]{0,79}$/.test(value)
|
|
152
|
+
&& value !== "constructor"
|
|
153
|
+
&& value !== "prototype"
|
|
154
|
+
&& value !== "__proto__";
|
|
155
|
+
}
|
|
156
|
+
exports.isSafeMemberName = isSafeMemberName;
|
|
157
|
+
function encodeValue(value, hooks, seen) {
|
|
158
|
+
if (value === undefined) {
|
|
159
|
+
return tag("undefined");
|
|
160
|
+
}
|
|
161
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
162
|
+
return value;
|
|
163
|
+
}
|
|
164
|
+
if (typeof value === "number") {
|
|
165
|
+
if (Number.isFinite(value)) {
|
|
166
|
+
return value;
|
|
167
|
+
}
|
|
168
|
+
return tag("number", { value: Number.isNaN(value) ? "NaN" : value > 0 ? "Infinity" : "-Infinity" });
|
|
169
|
+
}
|
|
170
|
+
if (typeof value === "bigint") {
|
|
171
|
+
return tag("bigint", { value: value.toString(10) });
|
|
172
|
+
}
|
|
173
|
+
if (typeof value === "function") {
|
|
174
|
+
if (!hooks.encodeFunction) {
|
|
175
|
+
throw new ElectronFacadeCodecError("Electron callback values are not supported in this context.");
|
|
176
|
+
}
|
|
177
|
+
return hooks.encodeFunction(value);
|
|
178
|
+
}
|
|
179
|
+
if (typeof value !== "object") {
|
|
180
|
+
throw new ElectronFacadeCodecError("Electron facade value cannot be serialized.");
|
|
181
|
+
}
|
|
182
|
+
if (Buffer.isBuffer(value)) {
|
|
183
|
+
return tag("buffer", { base64: value.toString("base64") });
|
|
184
|
+
}
|
|
185
|
+
if (value instanceof Date) {
|
|
186
|
+
return tag("date", { value: value.toISOString() });
|
|
187
|
+
}
|
|
188
|
+
if (value instanceof Error) {
|
|
189
|
+
return tag("error", {
|
|
190
|
+
name: value.name,
|
|
191
|
+
message: value.message,
|
|
192
|
+
...(value.stack ? { stack: value.stack } : {})
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
if (!Array.isArray(value) && !isPlainObject(value)) {
|
|
196
|
+
if (!hooks.encodeObject) {
|
|
197
|
+
throw new ElectronFacadeCodecError("Electron native object requires a remote handle.");
|
|
198
|
+
}
|
|
199
|
+
return hooks.encodeObject(value);
|
|
200
|
+
}
|
|
201
|
+
if (seen.has(value)) {
|
|
202
|
+
throw new ElectronFacadeCodecError("Electron facade values cannot contain cycles.");
|
|
203
|
+
}
|
|
204
|
+
seen.add(value);
|
|
205
|
+
try {
|
|
206
|
+
if (Array.isArray(value)) {
|
|
207
|
+
return value.map((item) => encodeValue(item, hooks, seen));
|
|
208
|
+
}
|
|
209
|
+
const encoded = Object.fromEntries(Object.entries(value).map(([key, item]) => [key, encodeValue(item, hooks, seen)]));
|
|
210
|
+
return Object.prototype.hasOwnProperty.call(value, "$nexusElectron")
|
|
211
|
+
? tag("object", { value: encoded })
|
|
212
|
+
: encoded;
|
|
213
|
+
}
|
|
214
|
+
finally {
|
|
215
|
+
seen.delete(value);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
function tag(type, values = {}) {
|
|
219
|
+
return { $nexusElectron: type, ...values };
|
|
220
|
+
}
|
|
221
|
+
function readTagString(value, key) {
|
|
222
|
+
const result = value[key];
|
|
223
|
+
if (typeof result !== "string") {
|
|
224
|
+
throw new ElectronFacadeCodecError("Electron facade wire tag is missing " + key + ".");
|
|
225
|
+
}
|
|
226
|
+
return result;
|
|
227
|
+
}
|
|
228
|
+
function isElectronFacadeOperation(value) {
|
|
229
|
+
return value === "call"
|
|
230
|
+
|| value === "construct"
|
|
231
|
+
|| value === "get"
|
|
232
|
+
|| value === "set"
|
|
233
|
+
|| value === "on"
|
|
234
|
+
|| value === "once"
|
|
235
|
+
|| value === "release";
|
|
236
|
+
}
|
|
237
|
+
function isPlainObject(value) {
|
|
238
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
const prototype = Object.getPrototypeOf(value);
|
|
242
|
+
return prototype === Object.prototype || prototype === null;
|
|
243
|
+
}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isPluginRpcMessage = exports.isPluginRpcJsonValue = exports.sanitizePluginRpcValue = exports.isPluginRpcOperationName = exports.createPluginRpcRequestId = exports.PluginRpcErrorCodes = exports.PLUGIN_RPC_REQUEST_ID_MAX_LENGTH = exports.PLUGIN_RPC_PROTOCOL_VERSION = void 0;
|
|
4
|
+
exports.PLUGIN_RPC_PROTOCOL_VERSION = 3;
|
|
5
|
+
exports.PLUGIN_RPC_REQUEST_ID_MAX_LENGTH = 128;
|
|
6
|
+
exports.PluginRpcErrorCodes = {
|
|
7
|
+
InvalidMessage: "PluginRpcInvalidMessage",
|
|
8
|
+
UnsupportedProtocol: "PluginRpcUnsupportedProtocol",
|
|
9
|
+
NotReady: "PluginProcessNotReady",
|
|
10
|
+
ProcessExited: "PluginProcessExited",
|
|
11
|
+
ActivationTimeout: "PluginActivationTimeout",
|
|
12
|
+
OperationTimeout: "PluginOperationTimeout",
|
|
13
|
+
ShutdownTimeout: "PluginShutdownTimeout"
|
|
14
|
+
};
|
|
15
|
+
function createPluginRpcRequestId(prefix, sequence) {
|
|
16
|
+
const normalizedPrefix = prefix.trim().replace(/[^A-Za-z0-9._-]/g, "-").slice(0, 110);
|
|
17
|
+
const normalizedSequence = Number.isSafeInteger(sequence) && sequence >= 0 ? sequence : 0;
|
|
18
|
+
return `${normalizedPrefix || "rpc"}-${normalizedSequence}`;
|
|
19
|
+
}
|
|
20
|
+
exports.createPluginRpcRequestId = createPluginRpcRequestId;
|
|
21
|
+
function isPluginRpcOperationName(value) {
|
|
22
|
+
if (typeof value !== "string" || value.length > 80 || !/^[a-z][A-Za-z0-9]*(?:\.[a-z][A-Za-z0-9]*){1,4}$/.test(value)) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
return value.split(".").every((part) => part !== "constructor" && part !== "prototype" && part !== "__proto__");
|
|
26
|
+
}
|
|
27
|
+
exports.isPluginRpcOperationName = isPluginRpcOperationName;
|
|
28
|
+
function sanitizePluginRpcValue(value) {
|
|
29
|
+
return sanitizeValue(value, new WeakSet());
|
|
30
|
+
}
|
|
31
|
+
exports.sanitizePluginRpcValue = sanitizePluginRpcValue;
|
|
32
|
+
function isPluginRpcJsonValue(value) {
|
|
33
|
+
return isJsonValue(value, new WeakSet());
|
|
34
|
+
}
|
|
35
|
+
exports.isPluginRpcJsonValue = isPluginRpcJsonValue;
|
|
36
|
+
function isPluginRpcMessage(value) {
|
|
37
|
+
if (!isRecord(value)) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
if (value.protocolVersion !== exports.PLUGIN_RPC_PROTOCOL_VERSION || typeof value.type !== "string") {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
switch (value.type) {
|
|
44
|
+
case "initialize":
|
|
45
|
+
return isRequestId(value.requestId) && isInitializePayload(value.payload);
|
|
46
|
+
case "ready":
|
|
47
|
+
return isRequestId(value.requestId) && isReadyPayload(value.payload);
|
|
48
|
+
case "invoke":
|
|
49
|
+
return isRequestId(value.requestId) && isInvokePayload(value.payload);
|
|
50
|
+
case "result":
|
|
51
|
+
return isRequestId(value.requestId) && isPluginRpcResult(value.result);
|
|
52
|
+
case "hostRequest":
|
|
53
|
+
return isRequestId(value.requestId) && isHostRequestPayload(value.payload);
|
|
54
|
+
case "hostResult":
|
|
55
|
+
return isRequestId(value.requestId) && isPluginRpcResult(value.result);
|
|
56
|
+
case "electronCallback":
|
|
57
|
+
return isRequestId(value.requestId) && isElectronCallbackPayload(value.payload);
|
|
58
|
+
case "electronCallbackResult":
|
|
59
|
+
return isRequestId(value.requestId) && isPluginRpcResult(value.result);
|
|
60
|
+
case "electronEvent":
|
|
61
|
+
return isElectronCallbackPayload(value.payload);
|
|
62
|
+
case "shutdown":
|
|
63
|
+
return isRequestId(value.requestId)
|
|
64
|
+
&& isRecord(value.payload)
|
|
65
|
+
&& isShutdownReason(value.payload.reason);
|
|
66
|
+
case "fatal":
|
|
67
|
+
return isFatalPayload(value.payload);
|
|
68
|
+
default:
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.isPluginRpcMessage = isPluginRpcMessage;
|
|
73
|
+
function sanitizeValue(value, seen) {
|
|
74
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
if (typeof value === "number") {
|
|
78
|
+
return Number.isFinite(value) ? value : null;
|
|
79
|
+
}
|
|
80
|
+
if (typeof value !== "object") {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
if (seen.has(value)) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
if (!isPlainObject(value) && !Array.isArray(value)) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
seen.add(value);
|
|
90
|
+
try {
|
|
91
|
+
if (Array.isArray(value)) {
|
|
92
|
+
return value.map((item) => sanitizeValue(item, seen));
|
|
93
|
+
}
|
|
94
|
+
return Object.fromEntries(Object.entries(value)
|
|
95
|
+
.map(([key, item]) => [key, sanitizeValue(item, seen)]));
|
|
96
|
+
}
|
|
97
|
+
finally {
|
|
98
|
+
seen.delete(value);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function isJsonValue(value, seen) {
|
|
102
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
if (typeof value === "number") {
|
|
106
|
+
return Number.isFinite(value);
|
|
107
|
+
}
|
|
108
|
+
if (typeof value !== "object") {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
if (seen.has(value)) {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
if (!isPlainObject(value) && !Array.isArray(value)) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
seen.add(value);
|
|
118
|
+
try {
|
|
119
|
+
if (Array.isArray(value)) {
|
|
120
|
+
return value.every((item) => isJsonValue(item, seen));
|
|
121
|
+
}
|
|
122
|
+
return Object.values(value).every((item) => isJsonValue(item, seen));
|
|
123
|
+
}
|
|
124
|
+
finally {
|
|
125
|
+
seen.delete(value);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function isRecord(value) {
|
|
129
|
+
return isPlainObject(value);
|
|
130
|
+
}
|
|
131
|
+
function isRequestId(value) {
|
|
132
|
+
return typeof value === "string" && value.length <= exports.PLUGIN_RPC_REQUEST_ID_MAX_LENGTH && /^[A-Za-z0-9._:-]{1,128}$/.test(value);
|
|
133
|
+
}
|
|
134
|
+
function isInitializePayload(value) {
|
|
135
|
+
if (!isRecord(value)) {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
return isNonEmptyString(value.pluginId)
|
|
139
|
+
&& isNonEmptyString(value.pluginDirectory)
|
|
140
|
+
&& isNonEmptyString(value.pluginDataDirectory)
|
|
141
|
+
&& isPluginManifestPayload(value.manifest)
|
|
142
|
+
&& value.pluginId === value.manifest.pluginId
|
|
143
|
+
&& isNonEmptyString(value.hostVersion)
|
|
144
|
+
&& isNonEmptyString(value.hostApiVersion);
|
|
145
|
+
}
|
|
146
|
+
function isReadyPayload(value) {
|
|
147
|
+
if (!isRecord(value)) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
return Array.isArray(value.operations)
|
|
151
|
+
&& value.operations.every((item) => isPluginRpcOperationName(item))
|
|
152
|
+
&& new Set(value.operations).size === value.operations.length
|
|
153
|
+
&& isNonEmptyString(value.activatedAtUtc);
|
|
154
|
+
}
|
|
155
|
+
function isInvokePayload(value) {
|
|
156
|
+
if (!isRecord(value)) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
return isRendererSurface(value.surface)
|
|
160
|
+
&& isNonEmptyString(value.contributionId)
|
|
161
|
+
&& isPluginRpcOperationName(value.operation)
|
|
162
|
+
&& (value.input === undefined || isJsonObject(value.input));
|
|
163
|
+
}
|
|
164
|
+
function isHostRequestPayload(value) {
|
|
165
|
+
if (!isRecord(value)) {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
return isHostMethod(value.method)
|
|
169
|
+
&& (value.params === undefined || isJsonObject(value.params));
|
|
170
|
+
}
|
|
171
|
+
function isFatalPayload(value) {
|
|
172
|
+
return isRecord(value)
|
|
173
|
+
&& isNonEmptyString(value.message)
|
|
174
|
+
&& (value.details === undefined || isPluginRpcJsonValue(value.details));
|
|
175
|
+
}
|
|
176
|
+
function isElectronCallbackPayload(value) {
|
|
177
|
+
return isRecord(value)
|
|
178
|
+
&& typeof value.callbackId === "string"
|
|
179
|
+
&& /^[A-Za-z0-9._:-]{1,128}$/.test(value.callbackId)
|
|
180
|
+
&& Array.isArray(value.args)
|
|
181
|
+
&& value.args.every((item) => isPluginRpcJsonValue(item));
|
|
182
|
+
}
|
|
183
|
+
function isPluginRpcResult(value) {
|
|
184
|
+
if (!isRecord(value) || typeof value.ok !== "boolean") {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
if (value.ok) {
|
|
188
|
+
return isPluginRpcJsonValue(value.value);
|
|
189
|
+
}
|
|
190
|
+
return isNexusError(value.error)
|
|
191
|
+
&& (value.error.details === undefined || isPluginRpcJsonValue(value.error.details));
|
|
192
|
+
}
|
|
193
|
+
function isNexusError(value) {
|
|
194
|
+
return isRecord(value)
|
|
195
|
+
&& typeof value.code === "string"
|
|
196
|
+
&& typeof value.message === "string";
|
|
197
|
+
}
|
|
198
|
+
function isJsonObject(value) {
|
|
199
|
+
return isRecord(value) && isPluginRpcJsonValue(value);
|
|
200
|
+
}
|
|
201
|
+
function isRendererSurface(value) {
|
|
202
|
+
return value === "business" || value === "tool" || value === "settings";
|
|
203
|
+
}
|
|
204
|
+
function isPluginManifestPayload(value) {
|
|
205
|
+
if (!isJsonObject(value)) {
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
return typeof value.schemaVersion === "number"
|
|
209
|
+
&& Number.isSafeInteger(value.schemaVersion)
|
|
210
|
+
&& typeof value.pluginId === "string"
|
|
211
|
+
&& isPluginId(value.pluginId)
|
|
212
|
+
&& isNonEmptyString(value.displayNameKey)
|
|
213
|
+
&& isNonEmptyString(value.descriptionKey)
|
|
214
|
+
&& isNonEmptyString(value.pluginVersion)
|
|
215
|
+
&& isNonEmptyString(value.hostApiVersion)
|
|
216
|
+
&& isNonEmptyString(value.minHostVersion)
|
|
217
|
+
&& Array.isArray(value.supportedCultures)
|
|
218
|
+
&& value.supportedCultures.every((item) => isNonEmptyString(item))
|
|
219
|
+
&& Array.isArray(value.permissions)
|
|
220
|
+
&& value.permissions.every((item) => isNonEmptyString(item));
|
|
221
|
+
}
|
|
222
|
+
function isPluginId(value) {
|
|
223
|
+
return /^[a-z0-9][a-z0-9._-]{1,63}$/.test(value);
|
|
224
|
+
}
|
|
225
|
+
function isNonEmptyString(value) {
|
|
226
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
227
|
+
}
|
|
228
|
+
function isPlainObject(value) {
|
|
229
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
const prototype = Object.getPrototypeOf(value);
|
|
233
|
+
return prototype === Object.prototype || prototype === null;
|
|
234
|
+
}
|
|
235
|
+
function isHostMethod(value) {
|
|
236
|
+
return value === "getCapabilityStatus"
|
|
237
|
+
|| value === "unsupportedCapability"
|
|
238
|
+
|| value === "log"
|
|
239
|
+
|| value === "getSettings"
|
|
240
|
+
|| value === "updateSettings"
|
|
241
|
+
|| value === "electronFacade";
|
|
242
|
+
}
|
|
243
|
+
function isShutdownReason(value) {
|
|
244
|
+
return value === "reload" || value === "disable" || value === "quit" || value === "crash-recovery";
|
|
245
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function createPluginElectronIpcChannel(pluginId: string, channel: string): string;
|
|
2
|
+
export declare function createPluginElectronProtocolScheme(pluginId: string, scheme: string): string;
|
|
3
|
+
export declare function isPluginElectronIpcChannel(pluginId: string, value: unknown): value is string;
|
|
4
|
+
export declare function isPluginElectronProtocolScheme(pluginId: string, value: unknown): value is string;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isPluginElectronProtocolScheme = exports.isPluginElectronIpcChannel = exports.createPluginElectronProtocolScheme = exports.createPluginElectronIpcChannel = void 0;
|
|
4
|
+
const ipcPrefix = "nexus-plugin:";
|
|
5
|
+
const protocolPrefix = "nexus-plugin-";
|
|
6
|
+
const pluginIdPattern = /^[a-z0-9][a-z0-9._-]{0,63}$/;
|
|
7
|
+
const channelPattern = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,119}$/;
|
|
8
|
+
const schemePattern = /^[a-z][a-z0-9+.-]{0,62}$/;
|
|
9
|
+
function createPluginElectronIpcChannel(pluginId, channel) {
|
|
10
|
+
return ipcPrefix + requirePluginId(pluginId) + ":" + requireLogicalName(channel, channelPattern, "IPC channel");
|
|
11
|
+
}
|
|
12
|
+
exports.createPluginElectronIpcChannel = createPluginElectronIpcChannel;
|
|
13
|
+
function createPluginElectronProtocolScheme(pluginId, scheme) {
|
|
14
|
+
const result = protocolPrefix + requirePluginId(pluginId) + "-" + requireLogicalName(scheme, schemePattern, "protocol scheme");
|
|
15
|
+
if (result.length > 40) {
|
|
16
|
+
throw new TypeError("Namespaced protocol scheme must be 40 characters or fewer.");
|
|
17
|
+
}
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
exports.createPluginElectronProtocolScheme = createPluginElectronProtocolScheme;
|
|
21
|
+
function isPluginElectronIpcChannel(pluginId, value) {
|
|
22
|
+
const normalizedPluginId = normalizePluginId(pluginId);
|
|
23
|
+
if (!normalizedPluginId || typeof value !== "string") {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
const prefix = ipcPrefix + normalizedPluginId + ":";
|
|
27
|
+
return value.startsWith(prefix) && channelPattern.test(value.slice(prefix.length));
|
|
28
|
+
}
|
|
29
|
+
exports.isPluginElectronIpcChannel = isPluginElectronIpcChannel;
|
|
30
|
+
function isPluginElectronProtocolScheme(pluginId, value) {
|
|
31
|
+
const normalizedPluginId = normalizePluginId(pluginId);
|
|
32
|
+
if (!normalizedPluginId || typeof value !== "string" || value.length > 40) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
const prefix = protocolPrefix + normalizedPluginId + "-";
|
|
36
|
+
return value.startsWith(prefix) && schemePattern.test(value.slice(prefix.length));
|
|
37
|
+
}
|
|
38
|
+
exports.isPluginElectronProtocolScheme = isPluginElectronProtocolScheme;
|
|
39
|
+
function requirePluginId(value) {
|
|
40
|
+
const normalized = normalizePluginId(value);
|
|
41
|
+
if (!normalized) {
|
|
42
|
+
throw new TypeError("Plugin id must match the Nexus manifest pluginId format.");
|
|
43
|
+
}
|
|
44
|
+
return normalized;
|
|
45
|
+
}
|
|
46
|
+
function normalizePluginId(value) {
|
|
47
|
+
const normalized = typeof value === "string" ? value.trim() : "";
|
|
48
|
+
return pluginIdPattern.test(normalized) ? normalized : undefined;
|
|
49
|
+
}
|
|
50
|
+
function requireLogicalName(value, pattern, label) {
|
|
51
|
+
const normalized = String(value).trim();
|
|
52
|
+
if (!pattern.test(normalized) || normalized.includes("__proto__")) {
|
|
53
|
+
throw new TypeError(label + " contains unsupported characters.");
|
|
54
|
+
}
|
|
55
|
+
return normalized;
|
|
56
|
+
}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import pluginManifestSchema from "../.generated/plugin-manifest.schema.json";
|
|
2
|
-
export declare const PLUGIN_SDK_VERSION = "2.
|
|
2
|
+
export declare const PLUGIN_SDK_VERSION = "2.1.1";
|
|
3
3
|
export { pluginManifestSchema };
|
|
4
4
|
export * from "../.generated/plugin-framework-version";
|
|
5
5
|
export * from "./types";
|
|
6
|
+
export * from "./electron-facade";
|
|
6
7
|
export * from "./browser/frame-client";
|
|
7
8
|
export * from "./validation";
|
package/dist/src/index.js
CHANGED
|
@@ -20,8 +20,9 @@ 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 = "2.
|
|
23
|
+
exports.PLUGIN_SDK_VERSION = "2.1.1";
|
|
24
24
|
__exportStar(require("../.generated/plugin-framework-version"), exports);
|
|
25
25
|
__exportStar(require("./types"), exports);
|
|
26
|
+
__exportStar(require("./electron-facade"), exports);
|
|
26
27
|
__exportStar(require("./browser/frame-client"), exports);
|
|
27
28
|
__exportStar(require("./validation"), exports);
|
package/dist/src/nexus-dev.js
CHANGED
|
@@ -30,6 +30,7 @@ const path = __importStar(require("path"));
|
|
|
30
30
|
const dev_1 = require("./dev");
|
|
31
31
|
const nexus_dev_control_1 = require("./nexus-dev-control");
|
|
32
32
|
const nexus_dev_deployment_1 = require("./nexus-dev-deployment");
|
|
33
|
+
const processSignals = process;
|
|
33
34
|
async function runPluginNexusDev(options, io) {
|
|
34
35
|
return new PluginNexusDevSession(options, io).run();
|
|
35
36
|
}
|
|
@@ -223,12 +224,12 @@ class PluginNexusDevSession {
|
|
|
223
224
|
return this.watcher ? this.watcher.runBuild(operation) : operation();
|
|
224
225
|
}
|
|
225
226
|
installSignalHandlers() {
|
|
226
|
-
|
|
227
|
-
|
|
227
|
+
processSignals.on("SIGINT", this.handleSignal);
|
|
228
|
+
processSignals.on("SIGTERM", this.handleSignal);
|
|
228
229
|
}
|
|
229
230
|
removeSignalHandlers() {
|
|
230
|
-
|
|
231
|
-
|
|
231
|
+
processSignals.removeListener("SIGINT", this.handleSignal);
|
|
232
|
+
processSignals.removeListener("SIGTERM", this.handleSignal);
|
|
232
233
|
}
|
|
233
234
|
requireTarget() {
|
|
234
235
|
if (!this.target) {
|
package/dist/src/scaffold.js
CHANGED
|
@@ -235,10 +235,10 @@ function createManifest(options) {
|
|
|
235
235
|
const displayNameKey = "plugin.displayName";
|
|
236
236
|
const descriptionKey = "plugin.description";
|
|
237
237
|
const englishDescription = isSqlite
|
|
238
|
-
? "
|
|
238
|
+
? "SQLite database browser with schema-aware CRUD generated by nexus-plugin."
|
|
239
239
|
: "PluginFrame echo example generated by nexus-plugin.";
|
|
240
240
|
const chineseDescription = isSqlite
|
|
241
|
-
? "由 nexus-plugin
|
|
241
|
+
? "由 nexus-plugin 生成的 SQLite 数据库浏览器与动态 CRUD 示例。"
|
|
242
242
|
: "由 nexus-plugin 生成的 PluginFrame 回显示例。";
|
|
243
243
|
return {
|
|
244
244
|
schemaVersion: index_1.PLUGIN_MANIFEST_SCHEMA_VERSION,
|