create-ax-trusted-plugin 1.0.11 → 1.0.12

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 CHANGED
@@ -38,7 +38,7 @@ npm run dev
38
38
 
39
39
  ## 生成内容
40
40
  `template/` 经占位替换(`__ID__`/`__TITLE__`/`__ANCHOR__`)后落地:`src/{index.ts,Panel.vue,state.ts}`、
41
- `manifest.json`(trust:internal、entry:main.js)、`vite.config.ts`(lib 构建 + dev 市场源桥)、
41
+ `manifest.json`(trust:internal、entry:main.js)、`vite.config.ts`(一行调 `trustedPluginConfig` 预设)、
42
42
  `package.json`、`tsconfig.json`、`.npmrc`、`.gitignore`、`README.md`。
43
43
 
44
44
  ## 发布(维护者)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-ax-trusted-plugin",
3
- "version": "1.0.11",
3
+ "version": "1.0.12",
4
4
  "description": "可信(internal)插件脚手架:一条命令生成一个基于 @ax-npm/host-trusted-sdk-v4 的可信插件骨架(ESM 直出 activate + 自带 Vue,dev 裸 vite 原生 sourcemap)。用法:npm create ax-trusted-plugin <id>。生成器本身无机密,公网可装;生成出的工程仍走私有源拉 @ax-npm/* 依赖。",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -13,8 +13,8 @@ npm run dev # concurrently: vite(:5174,市场源) + host-dev 真宿主(:5173)
13
13
  ```
14
14
  浏览器打开 `http://localhost:5173`,锚点出现「__TITLE__」面板。**改代码 → 刷新浏览器即生效**(原生 sourcemap)。
15
15
 
16
- > dev 走裸 `vite`:`vite.config.ts` `hostSourceBridge` 把单插件服务伪装成市场源,
17
- > `/<id>/main.js` 实时转译 `src/index.ts`。多插件并行各自 `vite --port 5175/5176/…`。
16
+ > dev 走裸 `vite`:`vite.config.ts` 一行调 `trustedPluginConfig` 预设,内含的市场源桥把单插件服务伪装成市场源,
17
+ > `/<id>/main.js` 实时转译 `src/index.ts`。多插件并行用 `trustedPluginConfig({ port: 5175 })`。
18
18
 
19
19
  ## 构建 / 上架
20
20
  ```bash
@@ -24,6 +24,7 @@ npm run build # → dist/main.js(+ main.js.map)
24
24
 
25
25
  ## 关键约定
26
26
  - 入口 `src/index.ts` 必须 `export function activate(ctx)`(可选 `elementTag`/`deactivate`);`manifest.entry`=`main.js`。
27
- - `vue({customElement:true})` 把样式注入 shadow root;Vue 自带打包,不与宿主共享。
27
+ - 预设的 `vue({customElement:true})` 把样式注入 shadow root;Vue 自带打包,不与宿主共享。
28
+ - 静态资源:直接 `import x from './x.png'`(无需 `?inline`),预设保证 dev/build 都内联成 data URI(可信插件跑在宿主 origin,普通 URL 会裂图);大图用 `new URL('./big.png', import.meta.url).href`。
28
29
  - 提供能力须命名空间化(`__ID__/...`)且在 `contributes.capabilities` 声明;消费(含**调自己提供的能力**)须在 `uses.capabilities` 声明——contributes 与 uses 是两道独立门,`execute` 一律过 uses 闸。
29
30
  - 插件间不互相 import,只走 `ctx.commands` / `ctx.events`。
@@ -3,7 +3,7 @@
3
3
  "version": "0.1.0",
4
4
  "private": true,
5
5
  "type": "module",
6
- "description": "可信(internal)插件:ESM 直出 activate,壳 import 即用、Vue 自带打包(隔离)、拿完整 ctx。dev 走裸 vite(原生 sourcemap、无构建步)。只依赖 @ax-npm/host-trusted-sdk-v4。",
6
+ "description": "可信(internal)插件",
7
7
  "scripts": {
8
8
  "build": "vue-tsc --noEmit && vite build",
9
9
  "serve": "vite",
@@ -12,11 +12,14 @@
12
12
  "typecheck": "vue-tsc --noEmit"
13
13
  },
14
14
  "dependencies": {
15
- "@ax-npm/host-trusted-sdk-v4": "^1.0.5",
16
- "vue": "^3.4.0"
15
+ "@ax-npm/host-trusted-sdk-v4": "^1.0.12",
16
+ "@ax-npm/common-v4": "^1.0.0",
17
+ "@ax-npm/capability-kit-v4": "^1.0.9",
18
+ "vue": "^3.5.0",
19
+ "vue-i18n": "^11"
17
20
  },
18
21
  "devDependencies": {
19
- "@ax-npm/host-dev-v4": "^1.0.7",
22
+ "@ax-npm/host-dev-v4": "^1.0.15",
20
23
  "@vitejs/plugin-vue": "^5.0.0",
21
24
  "concurrently": "^9.0.0",
22
25
  "electron": "^39.0.0",
@@ -3,12 +3,6 @@
3
3
  // 能力接线在 activate(ctx) 里完成,经 window 事件桥回(自定义元素拿不到 ctx)。
4
4
  import { state } from './state';
5
5
 
6
- function ping() {
7
- window.dispatchEvent(new CustomEvent('__ID__:ping'));
8
- }
9
- function flyTo() {
10
- window.dispatchEvent(new CustomEvent('__ID__:flyto'));
11
- }
12
6
  </script>
13
7
 
14
8
  <template>
@@ -16,22 +10,12 @@ function flyTo() {
16
10
  <div class="title">__TITLE__</div>
17
11
  <p class="hint">可信插件</p>
18
12
 
19
- <div class="row">
20
- <button @click="ping">调用自有能力 ping</button>
21
- <span class="val">{{ state.lastPing || '—' }}</span>
22
- </div>
23
-
24
- <div class="row">
25
- <button @click="flyTo">map.flyTo 北京</button>
26
- <span class="val">{{ state.flyToNote || '—' }}</span>
27
- </div>
28
-
29
13
  <div class="tele">
30
- <div class="tele-h">遥测 telemetry:fcs.basic</div>
14
+ <div class="tele-h">遥测</div>
31
15
  <div v-if="state.telemetry" class="tele-b">
32
- lon {{ state.telemetry.lng ?? '—' }} ·
33
- lat {{ state.telemetry.lat ?? '—' }} ·
34
- alt {{ state.telemetry.alt ?? '—' }}
16
+ lon {{ state.tele.pos_lon ?? '—' }} ·
17
+ lat {{ state.tele.pos_lat ?? '—' }} ·
18
+ alt {{ state.tele.pos_alt ?? '—' }}
35
19
  </div>
36
20
  <div v-else class="tele-b muted">等待遥测…</div>
37
21
  </div>
@@ -0,0 +1,19 @@
1
+ import { createI18n } from 'vue-i18n';
2
+ import zhCN from './locales/zh-CN';
3
+ import enUS from './locales/en-US';
4
+
5
+ export const i18n = createI18n({
6
+ legacy: false,
7
+ locale: 'zh-CN',
8
+ fallbackLocale: 'zh-CN',
9
+ missingWarn: false,
10
+ fallbackWarn: false,
11
+ messages: {
12
+ 'zh-CN': zhCN,
13
+ 'en-US': enUS,
14
+ },
15
+ })
16
+
17
+ export function setLocale(lang: string) {
18
+ i18n.global.locale.value = lang as typeof i18n.global.locale.value
19
+ }
@@ -1,35 +1,41 @@
1
1
  // 可信插件入口:本模块直接导出 activate/elementTag(manifest.entry → main.js)。
2
2
  // 宿主 loader `import(url)` 调 activate(ctx),据 elementTag + manifest.component 挂自定义元素。
3
- import { definePluginElement, type PluginCtx } from '@ax-npm/host-trusted-sdk-v4';
4
3
  import Panel from './Panel.vue';
5
- import { state, type FcsBasic } from './state';
4
+ import { state } from './state';
5
+ import { i18n, setLocale } from './i18n'
6
+ import * as fcs from '@ax-npm/common-v4/fcs';
7
+ import { FCS_EVENTS, STAGE_EVENTS } from '@ax-npm/capability-kit-v4';
8
+ import { definePluginElement, type PluginCtx } from '@ax-npm/host-trusted-sdk-v4';
6
9
 
7
- export const elementTag = definePluginElement(Panel, { tag: 'plugin-__ID__' });
10
+ export const elementTag = definePluginElement(
11
+ Panel,
12
+ {
13
+ tag: 'plugin-__ID__',
14
+ configureApp: (app) => app.use(i18n),
15
+ }
16
+ );
8
17
 
9
18
  export function activate(ctx: PluginCtx) {
10
- // ① 提供能力:id 须命名空间化 + 在 manifest.contributes.capabilities 声明。
11
- // 注意:contributes(提供)与 uses(调用)是两道独立门——execute 走 uses 闸,**调自己
12
- // register 的能力也要在 manifest.uses.capabilities 声明**(见下方 ③ 的 __ID__/ping)。
13
- ctx.commands.register('__ID__/ping', async () => 'pong @ ' + new Date().toLocaleTimeString());
14
19
 
15
- // ② 订阅宿主遥测(广播)。
16
- ctx.events.on('telemetry:fcs.basic', (p) => {
17
- state.telemetry = p as FcsBasic;
18
- });
20
+ // 多语言切换
21
+ ctx.events.on(STAGE_EVENTS.LOCALE_CHANGED, (p) => {
22
+ console.log(p.lang)
23
+ setLocale(p.lang)
24
+ })
25
+
26
+ // 订阅宿主遥测(广播)
27
+ ctx.events.on(FCS_EVENTS.BASIC, (p) => {
28
+ console.log(p)
29
+ state.tele = p;
30
+ });
31
+ // 订阅飞机属性信息
32
+ ctx.events.on(FCS_EVENTS.INFO, (p) => {
33
+ console.log(p)
34
+ state.aircraftInfo = p
35
+ })
19
36
 
20
- // ③ Panel 是自定义元素,拿不到 ctx;经 window 事件把用户动作桥回 activate 作用域。
21
- window.addEventListener('__ID__:ping', async () => {
22
- state.lastPing = String(await ctx.commands.execute('__ID__/ping'));
23
- });
24
- window.addEventListener('__ID__:flyto', async () => {
25
- try {
26
- // 调宿主地图能力(需在 manifest.uses.capabilities 声明 map.flyTo)。
27
- await ctx.commands.execute('map.flyTo', 116.397, 39.908);
28
- state.flyToNote = '已飞至北京';
29
- } catch (e) {
30
- state.flyToNote = '失败:' + (e instanceof Error ? e.message : String(e));
31
- }
32
- });
37
+ // 类似c++的头文件定义,从common-v4中导出
38
+ console.log(fcs.PT_FCS_MR);
33
39
 
34
40
  return {
35
41
  elementTag,
@@ -0,0 +1,5 @@
1
+ const messages: Record<string, string> = {
2
+ "TEST": "TEST"
3
+ };
4
+
5
+ export default messages;
@@ -0,0 +1,5 @@
1
+ const messages: Record<string, string> = {
2
+ "TEST": "测试"
3
+ };
4
+
5
+ export default messages;
@@ -1,5 +1,11 @@
1
1
  // activate(ctx) 与 Panel 自定义元素之间的共享响应式状态。
2
2
  // 二者 import 同一模块 → 插件自带的同一份 vue reactive(单例),activate 更新即触发 Panel 重渲染。
3
+ import {
4
+ FcsBasicTelemetry,
5
+ FcsModeTelemetry,
6
+ FcsNavposTelemetry,
7
+ AircraftInfo
8
+ } from '@ax-npm/capability-kit-v4';
3
9
  import { reactive } from 'vue';
4
10
 
5
11
  export interface FcsBasic {
@@ -10,7 +16,8 @@ export interface FcsBasic {
10
16
  }
11
17
 
12
18
  export const state = reactive({
13
- lastPing: '',
14
- telemetry: null as FcsBasic | null,
15
- flyToNote: '',
19
+ tele: null as FcsBasicTelemetry | null,
20
+ mode: null as FcsModeTelemetry | null,
21
+ navPos: null as FcsNavposTelemetry | null,
22
+ aircraftInfo: null as AircraftInfo | null,
16
23
  });
@@ -1,83 +1,7 @@
1
- import { defineConfig } from 'vite';
2
- import vue from '@vitejs/plugin-vue';
3
- import { fileURLToPath, URL } from 'node:url';
4
- import { readFileSync } from 'node:fs';
1
+ // 可信插件「形态一」(ESM 直出 activate)构建 —— 全套配置收口在 SDK 预设里:
2
+ // Vue 自定义元素编译、dev 市场源桥、dev 资源内联(使 asset 朴素 import dev/build 一致)、
3
+ // lib 单文件产物、process.env 替换。详见 @ax-npm/host-trusted-sdk-v4/vite。
4
+ // 多插件并行调试时:trustedPluginConfig({ port: 5175 })。
5
+ import { trustedPluginConfig } from '@ax-npm/host-trusted-sdk-v4/vite';
5
6
 
6
- // 可信插件构建(ESM 直出 activate):本模块 import(url) 后**直接导出 activate/elementTag**,
7
- // 壳 loader 调 activate(ctx)。Vue 打进 bundle(自带依赖,与宿主/其它插件隔离 —— 宿主升级
8
- // Vue 波及不到本插件)。dev 走裸 `vite`(实时转译、原生 sourcemap、无构建步),build 产
9
- // 单文件 `main.js`。
10
- //
11
- // vue({ customElement: true }):SFC 以自定义元素模式编译,样式自动注入 shadow root,
12
- // 故无独立 CSS 产物,单个 main.js 即完整插件。
13
-
14
- const MANIFEST = JSON.parse(
15
- readFileSync(fileURLToPath(new URL('./manifest.json', import.meta.url)), 'utf-8'),
16
- ) as { id: string };
17
- const PLUGIN_ID = MANIFEST.id;
18
-
19
- // —— dev 桥:让「单插件 vite 服务」对外长得像宿主的插件市场源 ——
20
- // 宿主(LocalRegistry)会请求 /plugins.json、/<id>/manifest.json、/<id>/<entry>。
21
- // 这里:① /plugins.json = [{ id }];② 把 /<id>/* 重写回 /*(插件本体在根目录);
22
- // ③ manifest.entry 是 `main.js`(生产构建产物),dev 无此产物 → 把对它的请求
23
- // 顶替为 `src/index.ts`,由 vite 实时转译(原生 sourcemap、无构建步)。
24
- // 这样单跑 `vite` 即可被 harness/host-dev 当市场源加载,改代码刷新即生效。
25
- function hostSourceBridge() {
26
- return {
27
- name: 'host-source-bridge',
28
- configureServer(server: {
29
- middlewares: { use: (fn: (req: any, res: any, next: () => void) => void) => void };
30
- }) {
31
- server.middlewares.use((req, res, next) => {
32
- const url = (req.url || '').split('?')[0];
33
- if (url === '/plugins.json') {
34
- res.setHeader('content-type', 'application/json');
35
- res.setHeader('access-control-allow-origin', '*');
36
- res.end(JSON.stringify([{ id: PLUGIN_ID }]));
37
- return;
38
- }
39
- // /<id>/xxx → /xxx(去掉宿主加的 id 前缀)
40
- if (req.url === `/${PLUGIN_ID}` || req.url === `/${PLUGIN_ID}/`) {
41
- req.url = '/';
42
- } else if (req.url && req.url.startsWith(`/${PLUGIN_ID}/`)) {
43
- req.url = req.url.slice(PLUGIN_ID.length + 1);
44
- }
45
- // dev:把 main.js 入口请求顶替为可实时转译的源文件。
46
- if ((req.url || '').split('?')[0] === '/main.js') req.url = '/src/index.ts';
47
- next();
48
- });
49
- },
50
- };
51
- }
52
-
53
- export default defineConfig({
54
- // build 产物在真宿主(无 Node process)运行:替换 Vue 的 process.env.NODE_ENV,
55
- // 否则运行时报 ReferenceError: process is not defined。dev 模式 vite 本就注入,加此无副作用。
56
- define: { 'process.env.NODE_ENV': JSON.stringify('production') },
57
- plugins: [vue({ customElement: true }), hostSourceBridge()],
58
- server: {
59
- // 活跃集多插件并行时用 `vite --port 5175/5176/…` 覆盖,一份多源 plugins.json 列各端口。
60
- port: 5174,
61
- strictPort: true,
62
- // 宿主(:5180 / app://)跨源拉清单/manifest/入口模块,需放开 CORS。
63
- cors: { origin: '*' },
64
- },
65
- build: {
66
- target: 'esnext',
67
- outDir: 'dist',
68
- emptyOutDir: true,
69
- // 源码级调试可信插件产物:留 sourcemap、不混淆。
70
- sourcemap: true,
71
- minify: false,
72
- // library 模式:入口导出(activate/elementTag/deactivate)即模块导出,壳 import(url) 直出。
73
- lib: {
74
- entry: fileURLToPath(new URL('./src/index.ts', import.meta.url)),
75
- formats: ['es'],
76
- fileName: () => 'main.js',
77
- },
78
- rollupOptions: {
79
- // 保住入口导出签名,别被当可执行 chunk 摇掉 activate。
80
- preserveEntrySignatures: 'strict',
81
- },
82
- },
83
- });
7
+ export default trustedPluginConfig();