@aiot-nexus/plugin-sdk 3.2.0 → 3.3.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 +23 -18
- package/dist/.generated/plugin-framework-version.d.ts +1 -0
- package/dist/.generated/plugin-framework-version.js +2 -1
- package/dist/.generated/plugin-manifest.schema.json +1 -1
- package/dist/dev-host-metadata.json +1 -1
- package/dist/src/cli/run.js +2 -2
- package/dist/src/nexus-dev-deployment.js +2 -2
- package/dist/src/scaffold.js +1 -1
- package/dist/src/sdk-info.d.ts +1 -1
- package/dist/src/sdk-info.js +1 -1
- package/package.json +1 -1
- package/templates/minimal/README.md.tmpl +9 -9
- package/templates/sqlite/README.md.tmpl +9 -9
package/README.md
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
# @aiot-nexus/plugin-sdk
|
|
2
2
|
|
|
3
|
-
> 当前 SDK 包版本为 `3.
|
|
3
|
+
> 当前 SDK 包版本为 `3.3.0`,Framework API 为 `3.2.0`,manifest schema 保持 `1`。Framework 3 将可信插件的 `mainEntry` 直接加载到 AIoT Toolkits Electron 主进程;它不是安全沙箱。PluginFrame iframe 仍保持 sandbox、无 Node/Electron 访问。宿主运行模型见 [Framework v3 架构](../docs/plugin-framework-v3-architecture.md)。
|
|
4
4
|
|
|
5
5
|
本包提供公开 TypeScript 契约、PluginFrame 浏览器客户端和 `nexus-plugin` CLI。v2 项目升级前请先阅读 [v2 到 v3 迁移说明](../docs/plugin-framework-v2-v3-migration.md)。完整开发流程见 [独立插件开发指南](../docs/standalone-plugin-development-guide.md)。
|
|
6
6
|
|
|
7
|
+
宿主产品名为 AIoT Toolkits,SDK 包名和 `dev:nexus` 命令保持不变。
|
|
8
|
+
本仓库 SDK 的 `--host` 目录参数只查找 `AIoT Toolkits.exe`,文件不存在时直接报错。
|
|
9
|
+
尚未更新的已发布 SDK 应传完整路径,例如 `--host "C:\Tools\AIoT Toolkits.exe"`;
|
|
10
|
+
目录自动识别的新行为需使用包含本次修改的 SDK 构建。
|
|
11
|
+
|
|
7
12
|
## 兼容基线
|
|
8
13
|
|
|
9
14
|
| 项目 | 固定值 |
|
|
10
15
|
| --- | --- |
|
|
11
|
-
| SDK | `3.
|
|
16
|
+
| SDK | `3.3.0` |
|
|
12
17
|
| Framework API | `3.2.0` |
|
|
13
18
|
| Manifest schema | `1` |
|
|
14
19
|
| Node 安装和构建 | `>=16.20.0 <17` |
|
|
@@ -27,7 +32,7 @@ nexus-plugin create <plugin-id> --template minimal|sqlite --output <parent-direc
|
|
|
27
32
|
nexus-plugin upgrade [plugin-project-directory] [--check] [--sdk-source <version-or-local-tgz>]
|
|
28
33
|
nexus-plugin dev [plugin-project-directory]
|
|
29
34
|
nexus-plugin dev:web [plugin-project-directory]
|
|
30
|
-
nexus-plugin dev:nexus [plugin-project-directory] --host <
|
|
35
|
+
nexus-plugin dev:nexus [plugin-project-directory] --host <host-exe-or-directory>
|
|
31
36
|
```
|
|
32
37
|
|
|
33
38
|
仓库内 SDK 命令:
|
|
@@ -48,15 +53,15 @@ npm run publish:sdk
|
|
|
48
53
|
registry 升级与只读预检:
|
|
49
54
|
|
|
50
55
|
```bash
|
|
51
|
-
npx --package=@aiot-nexus/plugin-sdk@3.
|
|
52
|
-
npx --package=@aiot-nexus/plugin-sdk@3.
|
|
56
|
+
npx --package=@aiot-nexus/plugin-sdk@3.3.0 nexus-plugin upgrade . --check
|
|
57
|
+
npx --package=@aiot-nexus/plugin-sdk@3.3.0 nexus-plugin upgrade .
|
|
53
58
|
```
|
|
54
59
|
|
|
55
60
|
发布前或本地 tgz:
|
|
56
61
|
|
|
57
62
|
```bash
|
|
58
|
-
npx --package=./aiot-nexus-plugin-sdk-3.
|
|
59
|
-
--sdk-source ./aiot-nexus-plugin-sdk-3.
|
|
63
|
+
npx --package=./aiot-nexus-plugin-sdk-3.3.0.tgz nexus-plugin upgrade . \
|
|
64
|
+
--sdk-source ./aiot-nexus-plugin-sdk-3.3.0.tgz
|
|
60
65
|
```
|
|
61
66
|
|
|
62
67
|
CI 可以追加 `--json` 获得 `up-to-date`、`upgrade-available`、`upgraded`、`rolled-back` 或 `blocked`。`--allow-major` 只解除 major 保护,不会改写业务源码;跨 major 必须先阅读迁移指南。`--skip-project-checks` 只跳过项目 typecheck/build,安装后的 SDK、package 和 lockfile 一致性仍会验证。
|
|
@@ -67,7 +72,7 @@ CI 可以追加 `--json` 获得 `up-to-date`、`upgrade-available`、`upgraded`
|
|
|
67
72
|
|
|
68
73
|
安装或项目验证失败时恢复备份,并在原 lockfile 存在时运行 `npm ci`。没有原 lockfile 时会运行 `npm install` 并恢复原 SDK,但无法证明完整传递依赖树与升级前一致,因此返回 `blocked` 并保留恢复数据。标准脚手架 build 的 `dist/<pluginId>` 在回滚范围内;自定义 typecheck/build 若修改其他路径,这些副作用不属于升级事务,项目必须自行管理。
|
|
69
74
|
|
|
70
|
-
SDK `3.0.x` / `3.1.x` 插件可以由 3.2.x 宿主继续加载。升级到 SDK `3.2.0` 只提供主题能力和新的契约;插件必须引用 `--nexus-color-*` 或读取 `context.theme` 才会使用宿主主题色。没有引用新变量的插件保持原有颜色;需要自定义主题时传入 `autoApplyHostTheme: false`。原有 `hostApiVersion: 3.0.0` 可以保持不变,只有实际使用 `showHostStatusBar` 时才需要声明 `hostApiVersion: 3.1.0` 或更高。SDK 3.1.1 修复 registry 升级命令丢失 npm
|
|
75
|
+
SDK `3.0.x` / `3.1.x` 插件可以由 3.2.x 宿主继续加载。升级到 SDK `3.2.0` 只提供主题能力和新的契约;插件必须引用 `--nexus-color-*` 或读取 `context.theme` 才会使用宿主主题色。没有引用新变量的插件保持原有颜色;需要自定义主题时传入 `autoApplyHostTheme: false`。原有 `hostApiVersion: 3.0.0` 可以保持不变,只有实际使用 `showHostStatusBar` 时才需要声明 `hostApiVersion: 3.1.0` 或更高。SDK 3.1.1 修复 registry 升级命令丢失 npm 包名的问题,SDK 3.3.0 将 `dev:nexus --host` 目录查找目标改为 `AIoT Toolkits.exe`,均作为历史兼容说明保留。
|
|
71
76
|
|
|
72
77
|
## 创建插件
|
|
73
78
|
|
|
@@ -90,10 +95,10 @@ nexus-plugin create my-frame-plugin \
|
|
|
90
95
|
|
|
91
96
|
```bash
|
|
92
97
|
npm run pack:sdk
|
|
93
|
-
nexus-plugin create my-frame-plugin --sdk-source ./package/aiot-nexus-plugin-sdk-3.
|
|
98
|
+
nexus-plugin create my-frame-plugin --sdk-source ./package/aiot-nexus-plugin-sdk-3.3.0.tgz --install
|
|
94
99
|
```
|
|
95
100
|
|
|
96
|
-
生成插件后,可以在 `src/manifest.json` 的业务入口中静态控制
|
|
101
|
+
生成插件后,可以在 `src/manifest.json` 的业务入口中静态控制 AIoT Toolkits 宿主状态栏。相关 manifest 片段如下,其余必填字段沿用脚手架生成值:
|
|
97
102
|
|
|
98
103
|
```json
|
|
99
104
|
{
|
|
@@ -183,9 +188,9 @@ function failure(code: string, message: string) {
|
|
|
183
188
|
- `context.host.*` 直接返回 `NexusResult<T>`,不需要 `await`。
|
|
184
189
|
- 注册的 operation handler 可以返回 Promise,可等待异步文件对话框、网络或其他用户交互。
|
|
185
190
|
- operation 默认没有业务超时。浏览器客户端 `requestTimeoutMs` 默认是 `0`;20 秒仅用于 iframe 初始化握手。
|
|
186
|
-
- 同步 Electron API 也能调用,但 `showOpenDialogSync()`、同步文件 I/O、长 CPU 任务会阻塞
|
|
191
|
+
- 同步 Electron API 也能调用,但 `showOpenDialogSync()`、同步文件 I/O、长 CPU 任务会阻塞 AIoT Toolkits 主进程、所有窗口和插件,应优先使用异步版本。
|
|
187
192
|
- Framework 不跟踪插件直接创建的 Electron/Node 资源。插件必须在 `deactivate` 中自行清理。
|
|
188
|
-
- Node 模块图和原生模块不能安全热卸载。已加载 `mainEntry`、依赖、原生模块或相关 manifest 变化必须重启
|
|
193
|
+
- Node 模块图和原生模块不能安全热卸载。已加载 `mainEntry`、依赖、原生模块或相关 manifest 变化必须重启 AIoT Toolkits。
|
|
189
194
|
|
|
190
195
|
Framework 3 不再提供 `context.host.electron` Facade,也没有 `electronHostControl` 权限。manifest 权限只描述 Host API 能力,不限制可信 `mainEntry` 直接调用 Electron/Node。SDK 保留 `createPluginElectronIpcChannel()` 和 `createPluginElectronProtocolScheme()` 作为命名约定帮助函数;宿主不会自动隔离或清理对应注册。
|
|
191
196
|
|
|
@@ -234,7 +239,7 @@ SDK 升级本身只提供能力。插件需要在 CSS 中引用 `var(--nexus-col
|
|
|
234
239
|
| `npm run dev:web` | 不执行 | 不可用 | 只调试 Renderer;`invokeMain` 返回 `PluginCapabilityUnsupported`。 |
|
|
235
240
|
| `npm run dev` | Electron 调试宿主主进程直接加载 | 可用 | 调试真实生命周期、对话框、SQLite 和插件窗口。 |
|
|
236
241
|
| `npm run dev:debug` | 同 `dev` | 可用 | Electron 主进程以 `--inspect-brk=9229` 启动。 |
|
|
237
|
-
| `npm run dev:nexus -- --host ...` | 正式
|
|
242
|
+
| `npm run dev:nexus -- --host ...` | 正式 AIoT Toolkits 主进程直接加载 | 可用 | 最终集成和监听更新。 |
|
|
238
243
|
|
|
239
244
|
Electron 调试壳仅保留 context 工具栏;插件 iframe 无边距、无边框,填满剩余窗口,不设置最小宽高,也不根据内容上报限制尺寸。Renderer DevTools 默认打开。
|
|
240
245
|
|
|
@@ -244,12 +249,12 @@ VS Code 模板提供 `Debug Nexus plugin` 和 `Attach Nexus plugin main process
|
|
|
244
249
|
|
|
245
250
|
| 修改范围 | 处理方式 |
|
|
246
251
|
| --- | --- |
|
|
247
|
-
| `src/renderer/**` | 只构建 Renderer 并重载 iframe,
|
|
252
|
+
| `src/renderer/**` | 只构建 Renderer 并重载 iframe,AIoT Toolkits PID 不变。 |
|
|
248
253
|
| 无 `mainEntry` 插件的安全 manifest 展示/贡献字段 | 原子替换 manifest 并重扫,PID 不变。 |
|
|
249
|
-
| 有 `mainEntry` 插件的 manifest 变化 | 完整构建并重启
|
|
250
|
-
| `src/main.*`、依赖、原生模块、构建脚本 | 完整构建并重启
|
|
254
|
+
| 有 `mainEntry` 插件的 manifest 变化 | 完整构建并重启 AIoT Toolkits。 |
|
|
255
|
+
| `src/main.*`、依赖、原生模块、构建脚本 | 完整构建并重启 AIoT Toolkits。 |
|
|
251
256
|
|
|
252
|
-
构建失败保留旧部署;新宿主启动或就绪失败会恢复旧包和旧宿主。`--inspect` / `--inspect-brk` 调试的是
|
|
257
|
+
构建失败保留旧部署;新宿主启动或就绪失败会恢复旧包和旧宿主。`--inspect` / `--inspect-brk` 调试的是 AIoT Toolkits Electron 主进程,因此会同时暂停或暴露宿主代码。按 `Ctrl+C` 时 CLI 关闭自己启动的宿主。
|
|
253
258
|
|
|
254
259
|
## 发布前检查
|
|
255
260
|
|
|
@@ -262,4 +267,4 @@ VS Code 模板提供 `Debug Nexus plugin` 和 `Attach Nexus plugin main process
|
|
|
262
267
|
7. `deactivate` 关闭窗口、Session 监听、IPC、protocol、快捷键、定时器、数据库和子进程。
|
|
263
268
|
8. 没有同步长任务、无限载荷、任意命令/SQL/路径透传或日志敏感信息。
|
|
264
269
|
9. 主题集成明确引用 `--nexus-color-*` / `context.theme`,或显式关闭 `autoApplyHostTheme`。
|
|
265
|
-
10. 运行 `npm test`、插件构建、正式
|
|
270
|
+
10. 运行 `npm test`、插件构建、正式 AIoT Toolkits 集成和 Windows 7 真机验收。
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export declare const PLUGIN_FRAMEWORK_VERSION = "3.2.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
|
+
export declare const PLUGIN_VERSION_PATTERN = "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(?:-((?:0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(?:\\.(?:0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\\+([0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*))?$";
|
|
4
5
|
export interface ParsedPluginVersion {
|
|
5
6
|
major: number;
|
|
6
7
|
minor: number;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isPluginFrameworkVersionCompatible = exports.comparePluginVersions = exports.parsePluginCompatibleVersion = exports.PLUGIN_COMPATIBLE_VERSION_PATTERN = exports.PLUGIN_MANIFEST_SCHEMA_VERSION = exports.PLUGIN_FRAMEWORK_VERSION = void 0;
|
|
3
|
+
exports.isPluginFrameworkVersionCompatible = exports.comparePluginVersions = exports.parsePluginCompatibleVersion = exports.PLUGIN_VERSION_PATTERN = exports.PLUGIN_COMPATIBLE_VERSION_PATTERN = exports.PLUGIN_MANIFEST_SCHEMA_VERSION = exports.PLUGIN_FRAMEWORK_VERSION = void 0;
|
|
4
4
|
exports.PLUGIN_FRAMEWORK_VERSION = "3.2.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
|
+
exports.PLUGIN_VERSION_PATTERN = "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(?:-((?:0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(?:\\.(?:0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\\+([0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*))?$";
|
|
7
8
|
function parsePluginCompatibleVersion(value) {
|
|
8
9
|
const match = /^(0|[1-9][0-9]*)(?:\.(0|[1-9][0-9]*))?(?:\.(0|[1-9][0-9]*))?$/.exec(value.trim());
|
|
9
10
|
if (!match) {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"pluginId": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]{1,63}$" },
|
|
21
21
|
"displayNameKey": { "type": "string", "minLength": 1 },
|
|
22
22
|
"descriptionKey": { "type": "string" },
|
|
23
|
-
"pluginVersion": { "type": "string", "
|
|
23
|
+
"pluginVersion": { "type": "string", "pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(?:-((?:0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(?:\\.(?:0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\\+([0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*))?$" },
|
|
24
24
|
"hostApiVersion": { "type": "string", "pattern": "^(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*))?(\\.(0|[1-9][0-9]*))?$" },
|
|
25
25
|
"minHostVersion": { "type": "string", "pattern": "^(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*))?(\\.(0|[1-9][0-9]*))?$" },
|
|
26
26
|
"supportedCultures": {
|
package/dist/src/cli/run.js
CHANGED
|
@@ -102,7 +102,7 @@ function usage() {
|
|
|
102
102
|
" nexus-plugin dev:web [plugin-project-directory] [--no-build] [--no-open] [--port <port>]",
|
|
103
103
|
" [--language <culture>] [--theme system|light|dark] [--surface business|tool|settings]",
|
|
104
104
|
" [--contribution-id <id>]",
|
|
105
|
-
" nexus-plugin dev:nexus [plugin-project-directory] --host <
|
|
105
|
+
" nexus-plugin dev:nexus [plugin-project-directory] --host <host-exe-or-directory>",
|
|
106
106
|
" [--inspect[=<port>] | --inspect-brk[=<port>]] [--no-devtools]",
|
|
107
107
|
" [--language <culture>] [--theme system|light|dark] [--surface business|tool|settings]",
|
|
108
108
|
" [--contribution-id <id>]"
|
|
@@ -247,7 +247,7 @@ function runNexusDev(args, io) {
|
|
|
247
247
|
}
|
|
248
248
|
}
|
|
249
249
|
if (!options.hostPath) {
|
|
250
|
-
return usageError(io, "dev:nexus requires --host <
|
|
250
|
+
return usageError(io, "dev:nexus requires --host <host-exe-or-directory>.");
|
|
251
251
|
}
|
|
252
252
|
return (0, nexus_dev_1.runPluginNexusDev)(options, io).catch((error) => {
|
|
253
253
|
if (error instanceof dev_1.PluginDevError) {
|
|
@@ -34,9 +34,9 @@ function resolveNexusExecutable(hostPath) {
|
|
|
34
34
|
throw new dev_1.PluginDevError("Nexus host path does not exist: " + resolved);
|
|
35
35
|
}
|
|
36
36
|
const stat = fs.statSync(resolved);
|
|
37
|
-
const executable = stat.isDirectory() ? path.join(resolved, "
|
|
37
|
+
const executable = stat.isDirectory() ? path.join(resolved, "AIoT Toolkits.exe") : resolved;
|
|
38
38
|
if (!fs.existsSync(executable) || !fs.statSync(executable).isFile()) {
|
|
39
|
-
throw new dev_1.PluginDevError("
|
|
39
|
+
throw new dev_1.PluginDevError("AIoT Toolkits executable is missing: " + executable);
|
|
40
40
|
}
|
|
41
41
|
if (process.platform === "win32" && path.extname(executable).toLowerCase() !== ".exe") {
|
|
42
42
|
throw new dev_1.PluginDevError("Nexus host must be a Windows executable: " + executable);
|
package/dist/src/scaffold.js
CHANGED
|
@@ -218,7 +218,7 @@ function createPackageJson(options, sdkSource) {
|
|
|
218
218
|
name: options.pluginId,
|
|
219
219
|
version: "0.1.0",
|
|
220
220
|
private: true,
|
|
221
|
-
description: options.displayName + " independent plugin for AIoT
|
|
221
|
+
description: options.displayName + " independent plugin for AIoT Toolkits.",
|
|
222
222
|
scripts
|
|
223
223
|
};
|
|
224
224
|
if (options.template === "sqlite") {
|
package/dist/src/sdk-info.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const PLUGIN_SDK_VERSION = "3.
|
|
1
|
+
export declare const PLUGIN_SDK_VERSION = "3.3.0";
|
|
2
2
|
export declare const PLUGIN_SDK_NODE_ENGINE = ">=16.20.0 <17";
|
|
3
3
|
export declare const PLUGIN_SDK_NPM_ENGINE = ">=6.13.4";
|
|
4
4
|
export declare const PLUGIN_SDK_ELECTRON_VERSION = "22.3.27";
|
package/dist/src/sdk-info.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getPluginSdkInfo = exports.PLUGIN_SDK_TYPES_NODE_VERSION = exports.PLUGIN_SDK_TYPESCRIPT_VERSION = exports.PLUGIN_SDK_ELECTRON_VERSION = exports.PLUGIN_SDK_NPM_ENGINE = exports.PLUGIN_SDK_NODE_ENGINE = exports.PLUGIN_SDK_VERSION = void 0;
|
|
4
4
|
const plugin_framework_version_1 = require("../.generated/plugin-framework-version");
|
|
5
|
-
exports.PLUGIN_SDK_VERSION = "3.
|
|
5
|
+
exports.PLUGIN_SDK_VERSION = "3.3.0";
|
|
6
6
|
exports.PLUGIN_SDK_NODE_ENGINE = ">=16.20.0 <17";
|
|
7
7
|
exports.PLUGIN_SDK_NPM_ENGINE = ">=6.13.4";
|
|
8
8
|
exports.PLUGIN_SDK_ELECTRON_VERSION = "22.3.27";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# __DISPLAY_NAME_MARKDOWN__
|
|
2
2
|
|
|
3
|
-
AIoT
|
|
3
|
+
AIoT Toolkits independent PluginFrame plugin generated from the `minimal` template.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
npm install
|
|
@@ -8,14 +8,14 @@ npm run typecheck
|
|
|
8
8
|
npm run build
|
|
9
9
|
npm run dev:web
|
|
10
10
|
npm run dev
|
|
11
|
-
npm run dev:nexus -- --host C:\path\to\
|
|
11
|
+
npm run dev:nexus -- --host "C:\path\to\AIoT Toolkits.exe"
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
SDK checks for a newer `@aiot-nexus/plugin-sdk` in two steps. The package `postinstall` refreshes a user cache; npm 7+ hides dependency lifecycle output by default, so use `npm install --foreground-scripts` to see it. The `nexus-plugin` CLI reads that cache and prints npm-style notices when it is fresh; missing or older-than-24-hours cache data is checked in the background without blocking the command. `npm install --ignore-scripts` skips only the install check, while CLI checks remain available.
|
|
15
15
|
|
|
16
16
|
The check follows the npm-configured registry, falls back to the official npm registry when needed, and silently ignores offline, timeout, malformed-response, or corrupt-cache failures. Use `NEXUS_PLUGIN_SDK_UPDATE_CHECK=0` or `NO_UPDATE_NOTIFIER=1` to disable both checks. Notices never modify the project. When one appears, substitute the exact version printed by the notice for `X.Y.Z`: `npx --package=@aiot-nexus/plugin-sdk@X.Y.Z nexus-plugin upgrade . --check`, then repeat without `--check`. The transaction synchronizes package.json, package-lock.json, and node_modules, runs project checks, and rolls back on failure. A major update additionally requires `--allow-major` and the migration guide linked by the CLI; source and manifest files are never rewritten.
|
|
17
17
|
|
|
18
|
-
The deployable plugin package is `dist/__PLUGIN_ID__/`. For a manual installation, stop
|
|
18
|
+
The deployable plugin package is `dist/__PLUGIN_ID__/`. For a manual installation, stop AIoT Toolkits before replacing `Plugins/__PLUGIN_ID__/`, then start it again. During development, use `npm run dev:nexus` so the CLI coordinates AIoT Toolkits shutdown, atomic replacement, and restart for trusted `mainEntry` changes.
|
|
19
19
|
|
|
20
20
|
## Native Electron file dialogs
|
|
21
21
|
|
|
@@ -97,21 +97,21 @@ export async function chooseSavePath(): Promise<string | undefined> {
|
|
|
97
97
|
}
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
-
Call these helpers from an operation registered with `context.host.registerRendererMethod`, then let the renderer invoke that narrow operation through `client.invokeMain()`. Return the `NexusResult` from `chooseAndReadText` directly so the renderer receives the stable `FileNotReadable`, `FileTooLarge`, or `FileReadFailed` code. Do not expose Electron objects or unrestricted file paths to the iframe. For larger files, stream or paginate in `mainEntry` and return only bounded chunks or summaries instead of the whole file. `npm run dev:web` is renderer-only and deliberately has no `mainEntry`, Node filesystem, or Electron main-process API; use `npm run dev` or a formal
|
|
100
|
+
Call these helpers from an operation registered with `context.host.registerRendererMethod`, then let the renderer invoke that narrow operation through `client.invokeMain()`. Return the `NexusResult` from `chooseAndReadText` directly so the renderer receives the stable `FileNotReadable`, `FileTooLarge`, or `FileReadFailed` code. Do not expose Electron objects or unrestricted file paths to the iframe. For larger files, stream or paginate in `mainEntry` and return only bounded chunks or summaries instead of the whole file. `npm run dev:web` is renderer-only and deliberately has no `mainEntry`, Node filesystem, or Electron main-process API; use `npm run dev` or a formal AIoT Toolkits host to test these dialogs.
|
|
101
101
|
|
|
102
102
|
The renderer calls the trusted-main `demo.echo` operation through `@aiot-nexus/plugin-sdk`. The main entry also calls the directly imported `app.getName()` during activation, so `npm run dev` verifies the real Electron main-process path. Run `npm run validate` after changing the manifest or output layout.
|
|
103
103
|
|
|
104
|
-
The renderer follows `context.language` and `context.themeMode` from
|
|
104
|
+
The renderer follows `context.language` and `context.themeMode` from AIoT Toolkits, subscribes to in-place context updates without reloading the iframe, and includes `en-US` and `zh-CN` message catalogs. The plugin page has no language or theme selector; the controls shown by `npm run dev` belong to the debug host and simulate AIoT Toolkits context changes. Below that toolbar, the iframe has no host padding, border, minimum size, or content-driven height and fills the remaining host viewport. Add or edit renderer messages in `src/renderer/app.ts`; edit host-shell titles and descriptions in `src/manifest.json` resources.
|
|
105
105
|
|
|
106
106
|
SDK 3.2 automatically maps the active `context.theme` palette to `--nexus-color-*` variables and sets `data-nexus-theme="light|dark"` on the document root. This template consumes those variables with local light/dark fallbacks, so it still renders on an older host. Merely upgrading the SDK does not recolor custom CSS: use the namespaced variables or read the optional palette explicitly, for example `const primary = context.theme?.light.primary`.
|
|
107
107
|
|
|
108
108
|
For a plugin-owned theme, create the client with `createPluginFrameClient({ autoApplyHostTheme: false })`. The palette remains available from `await client.waitForContext()`, but the SDK will not write CSS variables or `data-nexus-theme`. It never overwrites plugin-owned `--bg`, `--accent`, `data-theme`, or `color-scheme` values.
|
|
109
109
|
|
|
110
|
-
The current SDK has no generic business-event subscription API. For a long-running operation, register a fast `job.start` operation that returns a `taskId`, then expose `job.getStatus` and optional `job.cancel` for renderer polling. See the
|
|
110
|
+
The current SDK has no generic business-event subscription API. For a long-running operation, register a fast `job.start` operation that returns a `taskId`, then expose `job.getStatus` and optional `job.cancel` for renderer polling. See the AIoT Toolkits repository's plugin IPC and event notification example for the full contract and code.
|
|
111
111
|
|
|
112
|
-
Use `npm run dev:web` for renderer-only UI work in the system browser. It runs `build:web`, writes an isolated package under `.nexus-plugin-dev/web-package/`, builds with source maps, serves only on `127.0.0.1:4173`, and opens the browser automatically. It does not execute `mainEntry`, provide Node or Electron main-process APIs, or overwrite the deployable `dist` package. Language and theme controls still simulate
|
|
112
|
+
Use `npm run dev:web` for renderer-only UI work in the system browser. It runs `build:web`, writes an isolated package under `.nexus-plugin-dev/web-package/`, builds with source maps, serves only on `127.0.0.1:4173`, and opens the browser automatically. It does not execute `mainEntry`, provide Node or Electron main-process APIs, or overwrite the deployable `dist` package. Language and theme controls still simulate AIoT Toolkits context, while `invokeMain` is intentionally unavailable. Pass `-- --no-open` or `-- --port <port>` when needed; use `npm run dev` for Host API and Electron integration.
|
|
113
113
|
|
|
114
|
-
Use `npm run dev:nexus -- --host C:\path\to\
|
|
114
|
+
Use `npm run dev:nexus -- --host "C:\path\to\AIoT Toolkits.exe"` for live development against a compiled, packaged AIoT Toolkits. The CLI atomically deploys this plugin to `<exeDir>/Plugins/__PLUGIN_ID__/`. Renderer changes rebuild and reload the iframe without changing the AIoT Toolkits PID; safe manifest changes rescan contributions in the same process; `mainEntry`, dependency, native-module, or restart-sensitive manifest changes stop AIoT Toolkits, replace the complete package, and start a new AIoT Toolkits process because trusted modules cannot be unloaded safely from Node's module cache. Failed builds keep the previous deployment; launch or readiness failures restore the previous package and host. Add `--no-devtools`, `--inspect[=<port>]`, `--inspect-brk[=<port>]`, `--surface`, or `--contribution-id` after the second `--` as needed.
|
|
115
115
|
|
|
116
116
|
When this project was created from a local SDK archive, `vendor/aiot-nexus-plugin-sdk.tgz` is part of the source project and must be kept when the project is moved or committed. An explicit local upgrade copies the target archive to `vendor/aiot-nexus-plugin-sdk-<version>.tgz` and updates the exact file dependency.
|
|
117
117
|
|
|
@@ -119,4 +119,4 @@ For a local SDK archive, the tgz version remains the plugin's current SDK versio
|
|
|
119
119
|
|
|
120
120
|
For trusted-main breakpoints, open this plugin directory in VS Code, set breakpoints in `src/main.ts`, and run `Debug Nexus plugin`. To attach manually, start `npm run dev:debug` and select `Attach Nexus plugin main process (9229)`. Renderer DevTools opens automatically, with `src/renderer/app.ts` available through the development source map. `npm run dev` rebuilds before launch; use `npm run dev -- --no-build` only when intentionally reusing the current `dist` output.
|
|
121
121
|
|
|
122
|
-
The independent host stores data under `.nexus-plugin-dev/` and mirrors the PluginFrame protocol and current Host API surface. Its simulated
|
|
122
|
+
The independent host stores data under `.nexus-plugin-dev/` and mirrors the PluginFrame protocol and current Host API surface. Its simulated AIoT Toolkits application version defaults to the version recorded by the SDK build; pass `npm run dev -- --host-version <X.Y.Z>` to exercise another compatibility branch. Run the deployable `dist/__PLUGIN_ID__/` in AIoT Toolkits before delivery because the standalone host does not reproduce the full application shell or routing state.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# __DISPLAY_NAME_MARKDOWN__
|
|
2
2
|
|
|
3
|
-
AIoT
|
|
3
|
+
AIoT Toolkits independent PluginFrame plugin generated from the `sqlite` template.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
npm install
|
|
@@ -8,7 +8,7 @@ npm run typecheck
|
|
|
8
8
|
npm run build
|
|
9
9
|
npm run dev:web
|
|
10
10
|
npm run dev
|
|
11
|
-
npm run dev:nexus -- --host C:\path\to\
|
|
11
|
+
npm run dev:nexus -- --host "C:\path\to\AIoT Toolkits.exe"
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
SDK checks for a newer `@aiot-nexus/plugin-sdk` in two steps. The package `postinstall` refreshes a user cache; npm 7+ hides dependency lifecycle output by default, so use `npm install --foreground-scripts` to see it. The `nexus-plugin` CLI reads that cache and prints npm-style notices when it is fresh; missing or older-than-24-hours cache data is checked in the background without blocking the command. `npm install --ignore-scripts` skips only the install check, while CLI checks remain available.
|
|
@@ -17,7 +17,7 @@ The check follows the npm-configured registry, falls back to the official npm re
|
|
|
17
17
|
|
|
18
18
|
Every `npm run build` rebuilds `better-sqlite3@8.7.0` for Electron 22.3.27 with `@electron/rebuild@3.7.2` before packaging. `npm run rebuild:native` remains available as a standalone diagnostic command.
|
|
19
19
|
|
|
20
|
-
The deployable plugin package is `dist/__PLUGIN_ID__/`. For a manual installation, stop
|
|
20
|
+
The deployable plugin package is `dist/__PLUGIN_ID__/`. For a manual installation, stop AIoT Toolkits before replacing `Plugins/__PLUGIN_ID__/`, then start it again. During development, use `npm run dev:nexus` so the CLI coordinates AIoT Toolkits shutdown, atomic replacement, and restart for trusted `mainEntry` changes. Runtime data is stored in the host-provided plugin data directory and is not written into the plugin package.
|
|
21
21
|
|
|
22
22
|
The template is a schema-aware SQLite database browser. It opens `plugin.db` in the plugin data directory by default and initializes the `plugin_records` sample table there. **Open Database** calls Electron's directly imported `dialog.showOpenDialog()` from trusted `mainEntry`; it accepts a single existing SQLite file, including files without an extension. The renderer only displays the selected path and invokes parameterized operations. It never receives an Electron object and does not expose a path input, arbitrary SQL, DDL, `ATTACH`, or a SQL console.
|
|
23
23
|
|
|
@@ -43,23 +43,23 @@ if (!result.canceled && result.filePaths[0]) {
|
|
|
43
43
|
}
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
For related workflows, use `properties: ["openDirectory", "createDirectory"]` to choose a folder or `dialog.showSaveDialog()` to choose a save path. These calls belong in trusted `mainEntry`; the renderer should invoke a registered business operation such as `sqlite.chooseDatabase` through `client.invokeMain()` and receive only the result it needs. Native dialogs are unavailable in `npm run dev:web`; use `npm run dev` or a formal
|
|
46
|
+
For related workflows, use `properties: ["openDirectory", "createDirectory"]` to choose a folder or `dialog.showSaveDialog()` to choose a save path. These calls belong in trusted `mainEntry`; the renderer should invoke a registered business operation such as `sqlite.chooseDatabase` through `client.invokeMain()` and receive only the result it needs. Native dialogs are unavailable in `npm run dev:web`; use `npm run dev` or a formal AIoT Toolkits host.
|
|
47
47
|
|
|
48
48
|
External files are opened read/write only after a separate candidate connection can query `sqlite_schema`. Canceling the dialog or selecting a corrupt, locked, or inaccessible file keeps the current connection. The latest external path is atomically stored as `sqlite-browser-state.json` in the plugin data directory. Startup restores it when valid; otherwise the template clears the saved selection, falls back to `plugin.db`, and returns a visible notice. External databases do not receive the sample schema or journal pragma.
|
|
49
49
|
|
|
50
50
|
The table selector lists ordinary user tables from the `main` schema. Dynamic headers show declared type, SQLite affinity, primary-key order, NULL, default, and generated-column metadata. The editor supports default/NULL/value modes for inserts and unchanged/NULL/value modes for updates. INTEGER input uses exact decimal integers, REAL must be finite, NUMERIC accepts integer, real, or text values, and BLOB input uses even-length hexadecimal text. The 1 MiB field and 4 MiB row limits count decoded BLOB bytes rather than hexadecimal characters. Ordinary rowid tables prefer an unshadowed built-in rowid; `WITHOUT ROWID` tables, or tables that shadow every rowid alias, fall back only to primary-key columns that are all non-NULL. A table without a unique locator remains browsable and insertable, but update and delete are unavailable. Primary-key locators larger than 16 KiB are also treated as browse-only so a page cannot copy unbounded keys into the trusted main process and iframe. Update and delete run in a transaction and must affect exactly one row. TEXT previews are capped at 16 KiB of UTF-8 data; BLOB previews show the byte length and first 32 bytes.
|
|
51
51
|
|
|
52
|
-
The renderer follows `context.language` and `context.themeMode` from
|
|
52
|
+
The renderer follows `context.language` and `context.themeMode` from AIoT Toolkits and preserves unfinished editor values during in-place context updates. The plugin page has no language or theme selector; the controls shown by `npm run dev` belong to the debug host. Below that toolbar, the iframe has no host padding, border, minimum size, or content-driven height and fills the remaining host viewport. This SDK template deliberately has no Quasar dependency, so its data grid uses a native `<table>` as a dependency-minimized template exception. It still provides pagination, contained horizontal scrolling, light/dark themes, `en-US` / `zh-CN`, and busy/empty/error states. Edit renderer messages in `src/renderer/app.ts`; edit host-shell titles and descriptions in `src/manifest.json` resources.
|
|
53
53
|
|
|
54
54
|
SDK 3.2 automatically maps the active `context.theme` palette to `--nexus-color-*` variables and sets `data-nexus-theme="light|dark"` on the document root. This template consumes those variables with local light/dark fallbacks, so it still renders on an older host. Merely upgrading the SDK does not recolor custom CSS: use the namespaced variables or read the optional palette explicitly, for example `const primary = context.theme?.light.primary`.
|
|
55
55
|
|
|
56
56
|
For a plugin-owned theme, create the client with `createPluginFrameClient({ autoApplyHostTheme: false })`. The palette remains available from `await client.waitForContext()`, but the SDK will not write CSS variables or `data-nexus-theme`. It never overwrites plugin-owned `--bg`, `--accent`, `data-theme`, or `color-scheme` values.
|
|
57
57
|
|
|
58
|
-
The current SDK has no generic business-event subscription API. For a long-running operation, register a fast `job.start` operation that returns a `taskId`, then expose `job.getStatus` and optional `job.cancel` for renderer polling. See the
|
|
58
|
+
The current SDK has no generic business-event subscription API. For a long-running operation, register a fast `job.start` operation that returns a `taskId`, then expose `job.getStatus` and optional `job.cancel` for renderer polling. See the AIoT Toolkits repository's plugin IPC and event notification example for the full contract and code.
|
|
59
59
|
|
|
60
|
-
Use `npm run dev:web` for renderer-only layout, styling, localization, and responsive checks in the system browser. It runs `build:web`, writes an isolated package under `.nexus-plugin-dev/web-package/`, and does not rebuild or load `better-sqlite3`, execute `mainEntry`, provide Node or Electron main-process APIs, copy native runtime files, or overwrite the deployable `dist` package. It builds with source maps, serves only on `127.0.0.1:4173`, and opens the browser automatically. The page explicitly reports `PluginCapabilityUnsupported`; file selection, table loading, and CRUD require `npm run dev` or a formal
|
|
60
|
+
Use `npm run dev:web` for renderer-only layout, styling, localization, and responsive checks in the system browser. It runs `build:web`, writes an isolated package under `.nexus-plugin-dev/web-package/`, and does not rebuild or load `better-sqlite3`, execute `mainEntry`, provide Node or Electron main-process APIs, copy native runtime files, or overwrite the deployable `dist` package. It builds with source maps, serves only on `127.0.0.1:4173`, and opens the browser automatically. The page explicitly reports `PluginCapabilityUnsupported`; file selection, table loading, and CRUD require `npm run dev` or a formal AIoT Toolkits host. Pass `-- --no-open` or `-- --port <port>` when needed.
|
|
61
61
|
|
|
62
|
-
Use `npm run dev:nexus -- --host C:\path\to\
|
|
62
|
+
Use `npm run dev:nexus -- --host "C:\path\to\AIoT Toolkits.exe"` to run the plugin inside a compiled, packaged AIoT Toolkits. The initial deployment and every full package replacement are atomic. Renderer-only and safe manifest updates keep the AIoT Toolkits PID; `mainEntry`, dependency, native-module, or restart-sensitive manifest changes run the complete build (including the Electron 22.3.27 native rebuild), stop AIoT Toolkits, replace the package, and start a new AIoT Toolkits process. The database remains under the host-provided plugin data directory across host restarts. Failed builds keep the previous deployment, and launch or readiness failures roll the package back and restore the previous host. Add `--no-devtools`, `--inspect[=<port>]`, `--inspect-brk[=<port>]`, `--surface`, or `--contribution-id` after the second `--` as needed.
|
|
63
63
|
|
|
64
64
|
When this project was created from a local SDK archive, `vendor/aiot-nexus-plugin-sdk.tgz` is part of the source project and must be kept when the project is moved or committed. An explicit local upgrade copies the target archive to `vendor/aiot-nexus-plugin-sdk-<version>.tgz` and updates the exact file dependency.
|
|
65
65
|
|
|
@@ -67,4 +67,4 @@ For a local SDK archive, the tgz version remains the plugin's current SDK versio
|
|
|
67
67
|
|
|
68
68
|
For trusted-main breakpoints, open this plugin directory in VS Code, set breakpoints in `src/main.ts`, and run `Debug Nexus plugin`. To attach manually, start `npm run dev:debug` and select `Attach Nexus plugin main process (9229)`. Renderer DevTools opens automatically, with `src/renderer/app.ts` available through the development source map. The default debug build also runs the Electron 22.3.27 native rebuild before launch. Use `npm run dev -- --no-build` only when intentionally reusing a compatible current `dist` output.
|
|
69
69
|
|
|
70
|
-
The independent host stores the SQLite database and settings under `.nexus-plugin-dev/data/` and mirrors the PluginFrame protocol and current Host API surface. Its simulated
|
|
70
|
+
The independent host stores the SQLite database and settings under `.nexus-plugin-dev/data/` and mirrors the PluginFrame protocol and current Host API surface. Its simulated AIoT Toolkits application version defaults to the version recorded by the SDK build; pass `npm run dev -- --host-version <X.Y.Z>` to exercise another compatibility branch. Run the deployable `dist/__PLUGIN_ID__/` in AIoT Toolkits before delivery because the standalone host does not reproduce the full application shell or routing state.
|