@rainbow-robotics/plugin-ui 0.1.2-dev.44 → 0.1.2-dev.46
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 +222 -75
- package/build-dist.mjs +55 -17
- package/dist/host-ui.d.ts +49 -0
- package/dist/host-ui.d.ts.map +1 -0
- package/dist/host-ui.js +33 -0
- package/dist/host-ui.js.map +7 -0
- package/dist/manifest.d.ts +20 -4
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +1 -1
- package/dist/manifest.js.map +2 -2
- package/dist/pluginData.d.ts +68 -0
- package/dist/pluginData.d.ts.map +1 -0
- package/dist/react.d.ts +3430 -36
- package/dist/react.js +5 -54
- package/dist/react.js.map +2 -2
- package/dist/sdk.d.ts +38 -2
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +29 -4
- package/dist/sdk.js.map +2 -2
- package/dist/viteHost.d.ts +48 -0
- package/dist/viteHost.d.ts.map +1 -0
- package/dist/viteHost.js +262 -0
- package/dist/viteHost.js.map +7 -0
- package/dist/ws.d.ts +53 -0
- package/dist/ws.d.ts.map +1 -1
- package/dist/ws.js +128 -0
- package/dist/ws.js.map +7 -0
- package/package.json +43 -20
- package/src/host-ui.ts +80 -0
- package/src/host.tsx +236 -308
- package/src/index.d.ts +1 -0
- package/src/manifest.ts +25 -4
- package/src/pluginData.tsx +241 -0
- package/src/react.tsx +16 -127
- package/src/sdk.ts +74 -7
- package/src/viteHost.ts +316 -0
- package/src/ws.ts +47 -0
- package/build-browser.mjs +0 -84
- package/dist/connect.d.ts +0 -11
- package/dist/connect.d.ts.map +0 -1
- package/dist/connect.js +0 -34
- package/dist/connect.js.map +0 -7
- package/dist/elements.d.ts +0 -195
- package/dist/elements.d.ts.map +0 -1
- package/dist/elements.js +0 -115
- package/dist/elements.js.map +0 -7
- package/dist/react.d.ts.map +0 -1
- package/dist-browser/@rainbow-robotics/plugin-ui/chunks/chunk-37HVFFJB.js +0 -1
- package/dist-browser/@rainbow-robotics/plugin-ui/chunks/chunk-4MGSRUAS.js +0 -1
- package/dist-browser/@rainbow-robotics/plugin-ui/chunks/chunk-Q6XGCIPE.js +0 -1
- package/dist-browser/@rainbow-robotics/plugin-ui/connect.js +0 -1
- package/dist-browser/@rainbow-robotics/plugin-ui/elements.js +0 -1
- package/dist-browser/@rainbow-robotics/plugin-ui/react.js +0 -1
- package/dist-browser/@rainbow-robotics/plugin-ui/sdk.js +0 -1
- package/dist-browser/vendor/react-dom-client.js +0 -1
- package/dist-browser/vendor/react-jsx-dev-runtime.js +0 -1
- package/dist-browser/vendor/react-jsx-runtime.js +0 -1
- package/dist-browser/vendor/react-runtime.js +0 -65
- package/dist-browser/vendor/react.js +0 -1
- package/src/connect.ts +0 -64
- package/src/elements.ts +0 -257
package/README.md
CHANGED
|
@@ -1,85 +1,232 @@
|
|
|
1
1
|
# @rainbow-robotics/plugin-ui
|
|
2
2
|
|
|
3
|
-
Muscat
|
|
3
|
+
# Muscat 플러그인 UI 계약 및 호스트 마운팅 구조
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
`muscat-pk build` keeps it **external**. A plugin ZIP must not contain this
|
|
7
|
-
runtime. Muscat/robot and preview-host provide their own matching
|
|
8
|
-
`@rainbow-robotics/plugin-ui` browser runtime and render the real rb-components on the
|
|
9
|
-
host side.
|
|
5
|
+
Muscat 플러그인은 `export default App` 형태로 내보내는 일반 React 컴포넌트입니다.
|
|
10
6
|
|
|
11
|
-
|
|
7
|
+
플러그인 마운팅은 두 가지 경로로 동작하며, 두 경로 모두 `./host` 패키지에서 처리합니다.
|
|
12
8
|
|
|
9
|
+
## 개발 환경: `muscat-pk dev`
|
|
10
|
+
|
|
11
|
+
개발 환경에서는 플러그인 자체의 vite.config.ts를 이용하여 Vite 개발 서버가 bootstrap 모듈을 제공합니다.
|
|
12
|
+
|
|
13
|
+
호스트는 해당 bootstrap 모듈을 동적으로 import하여 플러그인을 실행합니다.
|
|
14
|
+
|
|
15
|
+
이 방식의 특징은 다음과 같습니다.
|
|
16
|
+
|
|
17
|
+
* 전체 HMR 지원
|
|
18
|
+
* 플러그인은 독립적인 React Root로 실행
|
|
19
|
+
* 플러그인이 자체 React 인스턴스를 사용
|
|
20
|
+
* 호스트 React 트리와 플러그인 React 트리가 분리됨
|
|
21
|
+
|
|
22
|
+
즉, 개발 환경에서는 플러그인이 호스트 페이지 내부에서 실행되지만 React 런타임 자체는 호스트와 공유하지 않습니다.
|
|
23
|
+
|
|
24
|
+
## 빌드 및 로봇 환경: `muscat-pk build`
|
|
25
|
+
|
|
26
|
+
`muscat-pk build`는 자체 번들러가 아니라, **플러그인 프로젝트 자신의 `vite.config.ts`로 `vite build`를 실행**하는 얇은 래퍼입니다
|
|
27
|
+
(`--config` 지정 없이 `cwd`만 플러그인 루트로 잡고 `vite build`를 실행 — Vite가 그 디렉토리의 `vite.config.ts`를 알아서 읽습니다).
|
|
28
|
+
|
|
29
|
+
스캐폴딩되는 `vite.config.ts`는 이렇게 생겼습니다.
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { defineConfig } from "vite";
|
|
33
|
+
import tailwindcss from "@tailwindcss/vite";
|
|
34
|
+
import { muscat } from "@rainbow-robotics/muscat-plugin-kit/vite";
|
|
35
|
+
export default defineConfig({ plugins: [tailwindcss(), muscat()] });
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**external 목록과 rollup 설정은 이 패키지(`@rainbow-robotics/plugin-ui`)가 아니라 `@rainbow-robotics/muscat-plugin-kit`의 `muscat()` preset(`cli/vite.mjs`)에 정의돼 있습니다.** 역할이 이렇게 나뉩니다.
|
|
39
|
+
|
|
40
|
+
| 패키지 | 담당 |
|
|
41
|
+
|---|---|
|
|
42
|
+
| `@rainbow-robotics/muscat-plugin-kit` | 빌드 타임 — `muscat()` preset (external 목록, entry 탐색, rollup 설정) |
|
|
43
|
+
| `@rainbow-robotics/plugin-ui` (이 패키지) | 런타임 — `./host`(마운트), `./vite-host`(nexus 쪽 import map 주입) |
|
|
44
|
+
|
|
45
|
+
`muscat()` preset이 다음 의존성을 플러그인 번들에 포함하지 않고 external bare specifier로 남겨둡니다.
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
react
|
|
49
|
+
react-dom
|
|
50
|
+
@rainbow-robotics/plugin-ui/*
|
|
51
|
+
@repo/rb-components
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
호스트 페이지에는 `./vite-host`에서 설정한 import map이 포함되어 있습니다.
|
|
55
|
+
|
|
56
|
+
이 import map은 위 bare specifier들을 호스트가 이미 로드한 실제 모듈 인스턴스로 연결합니다.
|
|
57
|
+
|
|
58
|
+
따라서 프로덕션 환경에서 로드된 플러그인은 다음과 같이 동작합니다.
|
|
59
|
+
|
|
60
|
+
* 호스트와 동일한 React 인스턴스 사용
|
|
61
|
+
* 호스트 React 트리 내부에 실제 중첩 React 트리로 마운트
|
|
62
|
+
* `RbContext` 공유
|
|
63
|
+
* 호스트 UI 컨텍스트 공유
|
|
64
|
+
* 플러그인 번들 크기 최소화
|
|
65
|
+
|
|
66
|
+
개발 환경에서는 플러그인이 독립적인 React Root로 실행되지만, 빌드 및 로봇 환경에서는 호스트 React 트리 내부에 중첩되어 실행됩니다.
|
|
67
|
+
|
|
68
|
+
### UI가 없는 플러그인은 vite build 자체를 건너뜀
|
|
69
|
+
|
|
70
|
+
`muscat-pk build`는 `manifest.json`의 `contributes[].ui`를 모아서 실제로 `ui/{name}.tsx`(또는 `.ts`/`.jsx`/`.js`) 파일이 있는지 검증합니다.
|
|
71
|
+
|
|
72
|
+
* `contributes`에 `ui`가 하나라도 선언돼 있는데 해당 파일이 없으면 → 빌드 실패(명확한 에러)
|
|
73
|
+
* `contributes`에 선언된 `ui`가 없고 `ui/` 디렉토리에 파일도 없으면(백엔드 전용 플러그인) → **vite build를 아예 건너뜁니다.** `dist/`엔 manifest.json/assets/백엔드 파일만 들어갑니다.
|
|
74
|
+
|
|
75
|
+
로직은 `libraries/muscat-plugin-kit/cli/src/build.mjs`의 `buildPlugin()`에 있습니다.
|
|
76
|
+
|
|
77
|
+
### Node.js가 없을 때
|
|
78
|
+
|
|
79
|
+
`muscat-pk build`는 자체 번들러가 아니라 `vite build`를 **자식 프로세스로 스폰**하므로, 그 자식 프로세스를 실행할 JS 런타임이 있어야 합니다.
|
|
80
|
+
|
|
81
|
+
* **npm으로 설치한 `muscat-pk`** → 이미 Node로 실행 중이므로 이 문제 자체가 발생하지 않습니다.
|
|
82
|
+
* **S3 self-contained 바이너리(Bun으로 컴파일됨)로 설치한 `muscat-pk`** → PATH에서 `bun` → `node` → `nodejs` 순서로 찾습니다. 셋 다 없으면:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
Node.js 20+ (or Bun) is required to build the plugin UI.
|
|
86
|
+
Install Node.js: https://nodejs.org
|
|
87
|
+
Then run: npm install (inside the plugin directory)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
를 출력하고 `exitCode 1`로 조용히 종료합니다(스택트레이스 없음). 로직은 `build.mjs`의 `findJsRuntime()` / `runViteBuild()`에 있습니다.
|
|
91
|
+
|
|
92
|
+
# 엔트리 포인트
|
|
93
|
+
|
|
94
|
+
## `./react`
|
|
95
|
+
|
|
96
|
+
사용 대상:
|
|
97
|
+
|
|
98
|
+
```text
|
|
99
|
+
plugin
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
실제 `@repo/rb-components`에서 `new-components` 전부 플러그인에 export합니다.
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
플러그인은 `@repo/rb-components`를 직접 import하기보다 이 엔트리 포인트를 통해 UI 컴포넌트를 사용합니다.
|
|
106
|
+
|
|
107
|
+
## `./sdk`
|
|
108
|
+
|
|
109
|
+
사용 대상:
|
|
110
|
+
|
|
111
|
+
```text
|
|
112
|
+
plugin
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
`useRb()`를 제공합니다.
|
|
116
|
+
|
|
117
|
+
`useRb()`를 통해 다음 기능을 사용할 수 있습니다.
|
|
118
|
+
|
|
119
|
+
* Zenoh WebSocket 기반 로봇 publish
|
|
120
|
+
* subscribe
|
|
121
|
+
* action 호출
|
|
122
|
+
* serve
|
|
123
|
+
* toast
|
|
124
|
+
* alert
|
|
125
|
+
* confirm
|
|
126
|
+
* prompt
|
|
127
|
+
|
|
128
|
+
이 API들은 플러그인 내부에서 직접 UI를 구현하는 대신, 호스트가 실제로 사용하는 dialog, toast 기능에 요청을 위임합니다.
|
|
129
|
+
|
|
130
|
+
실제 호스트 UI 서비스 구현은 `./host-ui`를 참고합니다.
|
|
131
|
+
|
|
132
|
+
## `./ws`
|
|
133
|
+
|
|
134
|
+
사용 대상:
|
|
135
|
+
|
|
136
|
+
```text
|
|
137
|
+
plugin dev bootstrap only
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
`RbWs`를 제공합니다.
|
|
141
|
+
|
|
142
|
+
`RbWs`는 `useRb()`가 내부적으로 사용하는 WebSocket 클라이언트입니다.
|
|
143
|
+
|
|
144
|
+
이 엔트리 포인트는 플러그인의 일반 프로덕션 코드에서 사용하는 것이 아니라, 개발 환경의 bootstrap 모듈에서만 사용합니다.
|
|
145
|
+
|
|
146
|
+
## `./manifest`
|
|
147
|
+
|
|
148
|
+
사용 대상:
|
|
149
|
+
|
|
150
|
+
```text
|
|
151
|
+
nexus
|
|
152
|
+
muscat-pk
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
플러그인 manifest 스키마를 제공합니다.
|
|
156
|
+
|
|
157
|
+
manifest 정의의 단일 진실 공급원, 즉 Single Source of Truth 역할을 합니다.
|
|
158
|
+
|
|
159
|
+
## `./plugin-data`
|
|
160
|
+
|
|
161
|
+
사용 대상:
|
|
162
|
+
|
|
163
|
+
```text
|
|
164
|
+
nexus only
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
다음 API를 제공합니다.
|
|
168
|
+
|
|
169
|
+
```text
|
|
170
|
+
PluginDataProvider
|
|
171
|
+
usePluginData()
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
플러그인을 어디에서, 어떤 방식으로 불러올지 결정합니다.
|
|
175
|
+
|
|
176
|
+
## `./host`
|
|
177
|
+
|
|
178
|
+
사용 대상:
|
|
179
|
+
|
|
180
|
+
```text
|
|
181
|
+
nexus only
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
`PluginHost`를 제공합니다.
|
|
185
|
+
|
|
186
|
+
`PluginHost`는 앞에서 설명한 두 가지 마운트 경로를 모두 처리합니다.
|
|
187
|
+
|
|
188
|
+
* 개발 환경의 Vite bootstrap 동적 import 방식
|
|
189
|
+
* 빌드 및 로봇 환경의 ESM 모듈 마운트 방식
|
|
190
|
+
|
|
191
|
+
## `./vite-host`
|
|
192
|
+
|
|
193
|
+
사용 대상:
|
|
194
|
+
|
|
195
|
+
```text
|
|
196
|
+
nexus vite.config.ts
|
|
13
197
|
```
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
198
|
+
|
|
199
|
+
Vite 플러그인을 제공합니다.
|
|
200
|
+
|
|
201
|
+
주요 역할은 다음과 같습니다.
|
|
202
|
+
|
|
203
|
+
* import map 삽입
|
|
204
|
+
* 플러그인 preview 개발 환경 지원
|
|
205
|
+
|
|
206
|
+
# 플러그인 프로덕션 번들 규칙
|
|
207
|
+
|
|
208
|
+
플러그인의 프로덕션 번들은 다음 엔트리 포인트만 import합니다.
|
|
209
|
+
|
|
210
|
+
```text
|
|
211
|
+
./react
|
|
212
|
+
./sdk
|
|
213
|
+
./host-ui
|
|
23
214
|
```
|
|
24
215
|
|
|
25
|
-
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
| `./connect` | plugin (sandbox) | `connect(App)` bootstrap, called from `sandbox.html` |
|
|
40
|
-
| `./sdk` | plugin (sandbox) | `useRb()`, `RbSdk` types |
|
|
41
|
-
| `./elements` | both | rb-\* element contract |
|
|
42
|
-
| `./host` | nexus only | `PluginContent`, `RB_COMPONENT_MAP` (maps rb-\* → real rb-components) |
|
|
43
|
-
| `./manifest` | nexus + rby2 | manifest schema (single source of truth) |
|
|
44
|
-
|
|
45
|
-
The plugin's production bundle must only import `./react` (+ `./connect`,
|
|
46
|
-
`./sdk`); `./host` pulls in rb-components and is host-only.
|
|
47
|
-
|
|
48
|
-
## rb-\* contract → rb-components mapping
|
|
49
|
-
|
|
50
|
-
| element | host component | event prop |
|
|
51
|
-
|---|---|---|
|
|
52
|
-
| `rb-slider` | `RBSlider` | `onChange` (number) |
|
|
53
|
-
| `rb-button` | `RBLabelButton` | `onPress` |
|
|
54
|
-
| `rb-icon-button` | `RBIconButton` (icon from `RBIcons`) | `onPress` |
|
|
55
|
-
| `rb-text` | plain text | — |
|
|
56
|
-
| `rb-text-input` | `RBTextInput` | `onInput` (string) |
|
|
57
|
-
| `rb-switch` | `RBSwitch` | `onChange` (boolean) |
|
|
58
|
-
| `rb-select` | `RBSelectBox` | `onChange` (string) |
|
|
59
|
-
|
|
60
|
-
> ⚠️ Author bindings and the host **must** declare matching `eventProps`.
|
|
61
|
-
> `createRemoteComponent` / `createRemoteComponentRenderer` only treat a prop as
|
|
62
|
-
> an event listener when it is in `eventProps`; they do **not** auto-derive from
|
|
63
|
-
> the element's `remoteEvents`.
|
|
64
|
-
|
|
65
|
-
## Verified versions
|
|
66
|
-
|
|
67
|
-
`@remote-dom/core@^1.11` · `@remote-dom/react@^1.2` · `@quilted/threads@^4`.
|
|
68
|
-
Notable corrections vs. early design notes: `RemoteMutationObserver` is from
|
|
69
|
-
`@remote-dom/core/elements` (not `/core`); there is no `@remote-dom/core/messaging`
|
|
70
|
-
— threading lives in `@quilted/threads`.
|
|
71
|
-
|
|
72
|
-
## Demo (M1 end-to-end check)
|
|
73
|
-
|
|
74
|
-
`demo/` is a standalone vite harness (excluded from build/lint/types). It serves
|
|
75
|
-
a host page + sandbox page and verifies the full round-trip in a real browser:
|
|
76
|
-
|
|
77
|
-
```bash
|
|
78
|
-
# from repo root
|
|
79
|
-
node_modules/.bin/vite --config packages/rb-plugin-kit/demo/vite.config.ts
|
|
80
|
-
# then, with the server on :5199:
|
|
81
|
-
node packages/rb-plugin-kit/demo/e2e.mjs
|
|
216
|
+
`./host-ui`는 필요한 경우에만 선택적으로 사용합니다.
|
|
217
|
+
|
|
218
|
+
반면 다음 엔트리 포인트는 호스트 전용입니다.
|
|
219
|
+
|
|
220
|
+
```text
|
|
221
|
+
./host
|
|
222
|
+
./vite-host
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
이 모듈들은 다음과 같은 호스트 전용 의존성을 포함합니다.
|
|
226
|
+
|
|
227
|
+
```text
|
|
228
|
+
@repo/rb-components
|
|
229
|
+
vite
|
|
82
230
|
```
|
|
83
231
|
|
|
84
|
-
|
|
85
|
-
in nexus.
|
|
232
|
+
따라서 `./host`와 `./vite-host`는 플러그인 번들에 포함되지 않습니다.
|
package/build-dist.mjs
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
// Builds @rainbow-robotics/plugin-ui for npm consumers (plugin authors).
|
|
2
|
-
// Output: dist/*.js (ESM, deps external) + dist/*.d.ts (via tsc)
|
|
3
|
-
//
|
|
4
|
-
// host.tsx is intentionally excluded — it depends on @repo/rb-components
|
|
5
|
-
// which is a Muscat-internal package. External devs never import ./host.
|
|
6
|
-
//
|
|
7
|
-
// Run: node libraries/plugin-ui/build-dist.mjs
|
|
8
1
|
import { build } from "esbuild";
|
|
9
|
-
import {
|
|
2
|
+
import { rollup } from "rollup";
|
|
3
|
+
import dts from "rollup-plugin-dts";
|
|
4
|
+
import { nodeResolve } from "@rollup/plugin-node-resolve";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
10
6
|
import { rmSync } from "node:fs";
|
|
11
7
|
import { dirname, resolve } from "node:path";
|
|
12
8
|
import { fileURLToPath } from "node:url";
|
|
@@ -18,25 +14,67 @@ rmSync(resolve(here, "dist"), { recursive: true, force: true });
|
|
|
18
14
|
// JS: transpile only (no bundling — consumers resolve deps themselves)
|
|
19
15
|
await build({
|
|
20
16
|
entryPoints: {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
sdk: resolve(here, "src/sdk.ts"),
|
|
24
|
-
elements: resolve(here, "src/elements.ts"),
|
|
17
|
+
react: resolve(here, "src/react.tsx"),
|
|
18
|
+
sdk: resolve(here, "src/sdk.ts"),
|
|
25
19
|
manifest: resolve(here, "src/manifest.ts"),
|
|
20
|
+
viteHost: resolve(here, "src/viteHost.ts"),
|
|
21
|
+
"host-ui": resolve(here, "src/host-ui.ts"),
|
|
22
|
+
// ws is used by the dev bootstrap + host.tsx to build the rb sdk.
|
|
23
|
+
ws: resolve(here, "src/ws.ts"),
|
|
26
24
|
},
|
|
27
25
|
outdir: resolve(here, "dist"),
|
|
28
26
|
format: "esm",
|
|
29
|
-
bundle: false,
|
|
27
|
+
bundle: false, // each file transpiled independently, deps stay as imports
|
|
30
28
|
platform: "neutral",
|
|
31
29
|
target: "es2022",
|
|
32
30
|
sourcemap: true,
|
|
33
31
|
logLevel: "warning",
|
|
34
32
|
});
|
|
35
33
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
const tsc = spawnSync(
|
|
35
|
+
"node",
|
|
36
|
+
[
|
|
37
|
+
"../../node_modules/typescript/bin/tsc",
|
|
38
|
+
"-p",
|
|
39
|
+
"tsconfig.build.json",
|
|
40
|
+
"--emitDeclarationOnly",
|
|
41
|
+
"--noEmit",
|
|
42
|
+
"false",
|
|
43
|
+
],
|
|
44
|
+
{ cwd: here, stdio: "inherit" },
|
|
45
|
+
);
|
|
46
|
+
if (tsc.status !== 0) {
|
|
47
|
+
console.warn(
|
|
48
|
+
"[plugin-ui] tsc reported errors during declaration emit (likely the known rb-providers/rb-utils " +
|
|
49
|
+
"global.d.ts gap, unrelated to plugin-ui) — .d.ts files were still written; continuing.",
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const reactExternal = (id) =>
|
|
54
|
+
/^react($|\/)/.test(id) || /^react-dom($|\/)/.test(id);
|
|
55
|
+
|
|
56
|
+
const ASSET_RE =
|
|
57
|
+
/\.(css|scss|sass|less|svg|png|jpe?g|gif|webp|woff2?)(\?\w+)?$|^swiper\/css/;
|
|
58
|
+
const stubAssets = {
|
|
59
|
+
name: "stub-assets-for-dts",
|
|
60
|
+
resolveId: (id) => (ASSET_RE.test(id) ? "\0asset-stub" : null),
|
|
61
|
+
load: (id) => (id === "\0asset-stub" ? "export default undefined;" : null),
|
|
62
|
+
};
|
|
63
|
+
const dtsBundle = await rollup({
|
|
64
|
+
input: resolve(here, "src/react.tsx"),
|
|
65
|
+
external: reactExternal,
|
|
66
|
+
plugins: [
|
|
67
|
+
stubAssets,
|
|
68
|
+
nodeResolve({ extensions: [".d.ts", ".ts", ".tsx", ".js", ".jsx"] }),
|
|
69
|
+
dts({ respectExternal: false }),
|
|
70
|
+
],
|
|
71
|
+
onwarn: () => {},
|
|
72
|
+
});
|
|
73
|
+
await dtsBundle.write({
|
|
74
|
+
file: resolve(here, "dist/react.d.ts"),
|
|
75
|
+
format: "es",
|
|
40
76
|
});
|
|
77
|
+
await dtsBundle.close();
|
|
78
|
+
rmSync(resolve(here, "dist/react.d.ts.map"), { force: true });
|
|
41
79
|
|
|
42
80
|
console.log("[plugin-ui] dist/ ready");
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { ReactElement } from "react";
|
|
2
|
+
export interface PluginUIServices {
|
|
3
|
+
alert: (params: {
|
|
4
|
+
title?: string;
|
|
5
|
+
message: string;
|
|
6
|
+
buttonText?: string;
|
|
7
|
+
}) => Promise<void>;
|
|
8
|
+
confirm: (params: {
|
|
9
|
+
title?: string;
|
|
10
|
+
message: string;
|
|
11
|
+
buttonText?: {
|
|
12
|
+
yes: string;
|
|
13
|
+
no: string;
|
|
14
|
+
};
|
|
15
|
+
}) => Promise<boolean>;
|
|
16
|
+
prompt: (params: {
|
|
17
|
+
title?: string;
|
|
18
|
+
message: string;
|
|
19
|
+
value?: string;
|
|
20
|
+
placeholder?: string;
|
|
21
|
+
buttonText?: {
|
|
22
|
+
yes: string;
|
|
23
|
+
no: string;
|
|
24
|
+
};
|
|
25
|
+
}) => Promise<string | undefined>;
|
|
26
|
+
toast: (params: {
|
|
27
|
+
title?: string;
|
|
28
|
+
message: string | ReactElement;
|
|
29
|
+
type?: "info" | "danger" | "warning" | "caution" | "success";
|
|
30
|
+
actionLabel?: string;
|
|
31
|
+
handleActionClick?: () => void;
|
|
32
|
+
closeOnActionClick?: boolean;
|
|
33
|
+
duration?: number;
|
|
34
|
+
onClose?: () => void;
|
|
35
|
+
}) => void;
|
|
36
|
+
}
|
|
37
|
+
/** Called by the host when it mounts a plugin. */
|
|
38
|
+
export declare function setHostServices(next: PluginUIServices): void;
|
|
39
|
+
/** Read the injected services, throwing a clear error if the host forgot. */
|
|
40
|
+
export declare function getHostServices(): PluginUIServices;
|
|
41
|
+
/** Open a host alert dialog from a plugin. */
|
|
42
|
+
export declare function alert(params: Parameters<PluginUIServices["alert"]>[0]): Promise<void>;
|
|
43
|
+
/** Open a host confirm dialog from a plugin. Resolves true/false. */
|
|
44
|
+
export declare function confirm(params: Parameters<PluginUIServices["confirm"]>[0]): Promise<boolean>;
|
|
45
|
+
/** Open a host prompt dialog from a plugin. Resolves the entered value, or undefined if cancelled. */
|
|
46
|
+
export declare function prompt(params: Parameters<PluginUIServices["prompt"]>[0]): Promise<string | undefined>;
|
|
47
|
+
/** Show a host toast from a plugin. */
|
|
48
|
+
export declare function toast(params: Parameters<PluginUIServices["toast"]>[0]): void;
|
|
49
|
+
//# sourceMappingURL=host-ui.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-ui.d.ts","sourceRoot":"","sources":["../src/host-ui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAErC,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,CAAC,MAAM,EAAE;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpB,OAAO,EAAE,CAAC,MAAM,EAAE;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE;YACX,GAAG,EAAE,MAAM,CAAC;YACZ,EAAE,EAAE,MAAM,CAAC;SACZ,CAAC;KACH,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACvB,MAAM,EAAE,CAAC,MAAM,EAAE;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,UAAU,CAAC,EAAE;YACX,GAAG,EAAE,MAAM,CAAC;YACZ,EAAE,EAAE,MAAM,CAAC;SACZ,CAAC;KACH,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAClC,KAAK,EAAE,CAAC,MAAM,EAAE;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,GAAG,YAAY,CAAC;QAC/B,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;QAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;QAC/B,kBAAkB,CAAC,EAAE,OAAO,CAAC;QAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;KACtB,KAAK,IAAI,CAAC;CACZ;AAID,kDAAkD;AAClD,wBAAgB,eAAe,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAE5D;AAED,6EAA6E;AAC7E,wBAAgB,eAAe,IAAI,gBAAgB,CAOlD;AAED,8CAA8C;AAC9C,wBAAgB,KAAK,CACnB,MAAM,EAAE,UAAU,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAC/C,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,qEAAqE;AACrE,wBAAgB,OAAO,CACrB,MAAM,EAAE,UAAU,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GACjD,OAAO,CAAC,OAAO,CAAC,CAElB;AAED,sGAAsG;AACtG,wBAAgB,MAAM,CACpB,MAAM,EAAE,UAAU,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAChD,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAE7B;AAED,uCAAuC;AACvC,wBAAgB,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAE5E"}
|
package/dist/host-ui.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
let services = null;
|
|
2
|
+
function setHostServices(next) {
|
|
3
|
+
services = next;
|
|
4
|
+
}
|
|
5
|
+
function getHostServices() {
|
|
6
|
+
if (!services) {
|
|
7
|
+
throw new Error(
|
|
8
|
+
"[plugin-ui] services not set \u2014 the plugin must be mounted by a Muscat host."
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
return services;
|
|
12
|
+
}
|
|
13
|
+
function alert(params) {
|
|
14
|
+
return getHostServices().alert(params);
|
|
15
|
+
}
|
|
16
|
+
function confirm(params) {
|
|
17
|
+
return getHostServices().confirm(params);
|
|
18
|
+
}
|
|
19
|
+
function prompt(params) {
|
|
20
|
+
return getHostServices().prompt(params);
|
|
21
|
+
}
|
|
22
|
+
function toast(params) {
|
|
23
|
+
getHostServices().toast(params);
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
alert,
|
|
27
|
+
confirm,
|
|
28
|
+
getHostServices,
|
|
29
|
+
prompt,
|
|
30
|
+
setHostServices,
|
|
31
|
+
toast
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=host-ui.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/host-ui.ts"],
|
|
4
|
+
"sourcesContent": ["import { ReactElement } from \"react\";\n\nexport interface PluginUIServices {\n alert: (params: {\n title?: string;\n message: string;\n buttonText?: string;\n }) => Promise<void>;\n confirm: (params: {\n title?: string;\n message: string;\n buttonText?: {\n yes: string;\n no: string;\n };\n }) => Promise<boolean>;\n prompt: (params: {\n title?: string;\n message: string;\n value?: string;\n placeholder?: string;\n buttonText?: {\n yes: string;\n no: string;\n };\n }) => Promise<string | undefined>;\n toast: (params: {\n title?: string;\n message: string | ReactElement;\n type?: \"info\" | \"danger\" | \"warning\" | \"caution\" | \"success\";\n actionLabel?: string;\n handleActionClick?: () => void;\n closeOnActionClick?: boolean;\n duration?: number;\n onClose?: () => void;\n }) => void;\n}\n\nlet services: PluginUIServices | null = null;\n\n/** Called by the host when it mounts a plugin. */\nexport function setHostServices(next: PluginUIServices): void {\n services = next;\n}\n\n/** Read the injected services, throwing a clear error if the host forgot. */\nexport function getHostServices(): PluginUIServices {\n if (!services) {\n throw new Error(\n \"[plugin-ui] services not set \u2014 the plugin must be mounted by a Muscat host.\",\n );\n }\n return services;\n}\n\n/** Open a host alert dialog from a plugin. */\nexport function alert(\n params: Parameters<PluginUIServices[\"alert\"]>[0],\n): Promise<void> {\n return getHostServices().alert(params);\n}\n\n/** Open a host confirm dialog from a plugin. Resolves true/false. */\nexport function confirm(\n params: Parameters<PluginUIServices[\"confirm\"]>[0],\n): Promise<boolean> {\n return getHostServices().confirm(params);\n}\n\n/** Open a host prompt dialog from a plugin. Resolves the entered value, or undefined if cancelled. */\nexport function prompt(\n params: Parameters<PluginUIServices[\"prompt\"]>[0],\n): Promise<string | undefined> {\n return getHostServices().prompt(params);\n}\n\n/** Show a host toast from a plugin. */\nexport function toast(params: Parameters<PluginUIServices[\"toast\"]>[0]): void {\n getHostServices().toast(params);\n}\n"],
|
|
5
|
+
"mappings": "AAsCA,IAAI,WAAoC;AAGjC,SAAS,gBAAgB,MAA8B;AAC5D,aAAW;AACb;AAGO,SAAS,kBAAoC;AAClD,MAAI,CAAC,UAAU;AACb,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,MACd,QACe;AACf,SAAO,gBAAgB,EAAE,MAAM,MAAM;AACvC;AAGO,SAAS,QACd,QACkB;AAClB,SAAO,gBAAgB,EAAE,QAAQ,MAAM;AACzC;AAGO,SAAS,OACd,QAC6B;AAC7B,SAAO,gBAAgB,EAAE,OAAO,MAAM;AACxC;AAGO,SAAS,MAAM,QAAwD;AAC5E,kBAAgB,EAAE,MAAM,MAAM;AAChC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/manifest.d.ts
CHANGED
|
@@ -5,19 +5,31 @@
|
|
|
5
5
|
* Evolve additively only.
|
|
6
6
|
*/
|
|
7
7
|
/** Known contribution points the host understands. */
|
|
8
|
-
export declare const CONTRIBUTION_POINTS: readonly ["
|
|
8
|
+
export declare const CONTRIBUTION_POINTS: readonly ["toolbar", "lnb", "move.panel", "program.panel"];
|
|
9
9
|
export type ContributionPoint = (typeof CONTRIBUTION_POINTS)[number];
|
|
10
10
|
/** How a header.toolbar contribution opens when clicked. */
|
|
11
11
|
export type ContributionOpens = "popover" | "panel" | "page";
|
|
12
12
|
export interface PluginContribution {
|
|
13
13
|
/** Where this contribution mounts. */
|
|
14
14
|
point: ContributionPoint | (string & {});
|
|
15
|
+
/** UI entry name relative to ui/ (without extension). Defaults to "content". */
|
|
16
|
+
ui?: string;
|
|
15
17
|
/** Icon path relative to the plugin root (e.g. "assets/icon.svg"). */
|
|
16
|
-
icon?: string
|
|
18
|
+
icon?: string | {
|
|
19
|
+
"16"?: string;
|
|
20
|
+
"48"?: string;
|
|
21
|
+
"126"?: string;
|
|
22
|
+
};
|
|
17
23
|
/** Display label. */
|
|
18
|
-
label?: string
|
|
24
|
+
label?: string | Record<string, string>;
|
|
19
25
|
/** For header.toolbar: how the contribution surfaces. */
|
|
20
26
|
opens?: ContributionOpens;
|
|
27
|
+
commandInfo?: {
|
|
28
|
+
name: string;
|
|
29
|
+
icon: string;
|
|
30
|
+
funcName: string;
|
|
31
|
+
args?: Record<string, any>;
|
|
32
|
+
};
|
|
21
33
|
}
|
|
22
34
|
export interface PluginAction {
|
|
23
35
|
/** Action id referenced by `rb.action(id, payload)`. */
|
|
@@ -48,7 +60,11 @@ export interface PluginManifest {
|
|
|
48
60
|
/** Minimum host (Muscat) version this plugin supports. */
|
|
49
61
|
minAppVersion?: string;
|
|
50
62
|
/** Icon path relative to plugin root. */
|
|
51
|
-
|
|
63
|
+
icons: string | {
|
|
64
|
+
"16"?: string;
|
|
65
|
+
"48"?: string;
|
|
66
|
+
"128"?: string;
|
|
67
|
+
};
|
|
52
68
|
/** UI / chrome contributions. */
|
|
53
69
|
contributes?: PluginContribution[];
|
|
54
70
|
/** Host actions the plugin can invoke. */
|
package/dist/manifest.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AACA;;;;;GAKG;AAEH,sDAAsD;AACtD,eAAO,MAAM,mBAAmB,4DAKtB,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAErE,4DAA4D;AAC5D,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAE7D,MAAM,WAAW,kBAAkB;IACjC,sCAAsC;IACtC,KAAK,EAAE,iBAAiB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACzC,gFAAgF;IAChF,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,sEAAsE;IACtE,IAAI,CAAC,EACD,MAAM,GACN;QACE,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACN,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,yDAAyD;IACzD,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,WAAW,CAAC,EAAE;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KAC5B,CAAC;CACH;AAED,MAAM,WAAW,YAAY;IAC3B,wDAAwD;IACxD,EAAE,EAAE,MAAM,CAAC;IACX,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACjC;IACE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC/B,CAAC;AAEN,MAAM,WAAW,cAAc;IAC7B,8DAA8D;IAC9D,EAAE,EAAE,MAAM,CAAC;IACX,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yCAAyC;IACzC,KAAK,EACD,MAAM,GACN;QACE,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACN,iCAAiC;IACjC,WAAW,CAAC,EAAE,kBAAkB,EAAE,CAAC;IACnC,0CAA0C;IAC1C,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB,oCAAoC;IACpC,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAiBzD"}
|
package/dist/manifest.js
CHANGED
package/dist/manifest.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/manifest.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Plugin manifest schema \u2014 the single source of truth shared by the front end\n * (nexus reads it) and the back end (rby2 mirrors it for validation).\n *\n * Evolve additively only.\n */\n\n/** Known contribution points the host understands. */\nexport const CONTRIBUTION_POINTS = [\n \"
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["/* eslint-disable @typescript-eslint/no-explicit-any */\n/**\n * Plugin manifest schema \u2014 the single source of truth shared by the front end\n * (nexus reads it) and the back end (rby2 mirrors it for validation).\n *\n * Evolve additively only.\n */\n\n/** Known contribution points the host understands. */\nexport const CONTRIBUTION_POINTS = [\n \"toolbar\",\n \"lnb\",\n \"move.panel\",\n \"program.panel\",\n] as const;\n\nexport type ContributionPoint = (typeof CONTRIBUTION_POINTS)[number];\n\n/** How a header.toolbar contribution opens when clicked. */\nexport type ContributionOpens = \"popover\" | \"panel\" | \"page\";\n\nexport interface PluginContribution {\n /** Where this contribution mounts. */\n point: ContributionPoint | (string & {});\n /** UI entry name relative to ui/ (without extension). Defaults to \"content\". */\n ui?: string;\n /** Icon path relative to the plugin root (e.g. \"assets/icon.svg\"). */\n icon?:\n | string\n | {\n \"16\"?: string;\n \"48\"?: string;\n \"126\"?: string;\n };\n /** Display label. */\n label?: string | Record<string, string>;\n /** For header.toolbar: how the contribution surfaces. */\n opens?: ContributionOpens;\n commandInfo?: {\n name: string;\n icon: string;\n funcName: string;\n args?: Record<string, any>;\n };\n}\n\nexport interface PluginAction {\n /** Action id referenced by `rb.action(id, payload)`. */\n id: string;\n /** Transport topic (Zenoh / ROS2) the back end routes to. */\n topic: string;\n /** Optional payload schema hint (field \u2192 type name). */\n schema?: Record<string, string>;\n}\n\nexport type PluginRuntime =\n | { type: \"none\" }\n | { type: \"python\"; entry: string }\n | {\n type: \"ros2\";\n package: string;\n launch: string;\n rosClient: \"rclpy\" | \"rclcpp\";\n };\n\nexport interface PluginManifest {\n /** Reverse-DNS unique id, e.g. \"com.rainbow.gripper-tool\". */\n id: string;\n /** Human-readable name. */\n name: string;\n /** Plugin version (semver). */\n version: string;\n /** Minimum host (Muscat) version this plugin supports. */\n minAppVersion?: string;\n /** Icon path relative to plugin root. */\n icons:\n | string\n | {\n \"16\"?: string;\n \"48\"?: string;\n \"128\"?: string;\n };\n /** UI / chrome contributions. */\n contributes?: PluginContribution[];\n /** Host actions the plugin can invoke. */\n actions?: PluginAction[];\n /** Back-end runtime declaration. */\n runtime?: PluginRuntime;\n}\n\n/**\n * Lightweight structural check. Returns the list of problems (empty = valid).\n * Kept dependency-free so both front and back ends can reuse it; richer\n * validation (zod) can layer on top later without breaking this contract.\n */\nexport function validateManifest(value: unknown): string[] {\n const errors: string[] = [];\n if (typeof value !== \"object\" || value === null) {\n return [\"manifest must be an object\"];\n }\n const m = value as Record<string, unknown>;\n if (typeof m.id !== \"string\" || m.id.length === 0)\n errors.push(\"manifest.id is required (string)\");\n if (typeof m.name !== \"string\" || m.name.length === 0)\n errors.push(\"manifest.name is required (string)\");\n if (typeof m.version !== \"string\" || m.version.length === 0)\n errors.push(\"manifest.version is required (string)\");\n if (m.contributes !== undefined && !Array.isArray(m.contributes))\n errors.push(\"manifest.contributes must be an array\");\n if (m.actions !== undefined && !Array.isArray(m.actions))\n errors.push(\"manifest.actions must be an array\");\n return errors;\n}\n"],
|
|
5
|
+
"mappings": "AASO,MAAM,sBAAsB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAiFO,SAAS,iBAAiB,OAA0B;AACzD,QAAM,SAAmB,CAAC;AAC1B,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,WAAO,CAAC,4BAA4B;AAAA,EACtC;AACA,QAAM,IAAI;AACV,MAAI,OAAO,EAAE,OAAO,YAAY,EAAE,GAAG,WAAW;AAC9C,WAAO,KAAK,kCAAkC;AAChD,MAAI,OAAO,EAAE,SAAS,YAAY,EAAE,KAAK,WAAW;AAClD,WAAO,KAAK,oCAAoC;AAClD,MAAI,OAAO,EAAE,YAAY,YAAY,EAAE,QAAQ,WAAW;AACxD,WAAO,KAAK,uCAAuC;AACrD,MAAI,EAAE,gBAAgB,UAAa,CAAC,MAAM,QAAQ,EAAE,WAAW;AAC7D,WAAO,KAAK,uCAAuC;AACrD,MAAI,EAAE,YAAY,UAAa,CAAC,MAAM,QAAQ,EAAE,OAAO;AACrD,WAAO,KAAK,mCAAmC;AACjD,SAAO;AACT;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|