@majkapp/plugin-kit 3.2.1 → 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/bin/promptable-cli.js +35 -0
- package/docs/API.md +394 -0
- package/docs/CONFIG.md +428 -0
- package/docs/CONTEXT.md +500 -0
- package/docs/FULL.md +848 -0
- package/docs/FUNCTIONS.md +623 -0
- package/docs/HOOKS.md +532 -0
- package/docs/INDEX.md +486 -0
- package/docs/LIFECYCLE.md +490 -0
- package/docs/SCREENS.md +547 -0
- package/docs/SERVICES.md +350 -0
- package/docs/TESTING.md +593 -0
- package/docs/mcp-execution-api.md +490 -0
- package/package.json +18 -3
package/docs/CONFIG.md
ADDED
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
# Configuration
|
|
2
|
+
|
|
3
|
+
Set up your plugin project with the correct structure and build configuration.
|
|
4
|
+
|
|
5
|
+
## vite.config.js (REQUIRED FORMAT)
|
|
6
|
+
|
|
7
|
+
**CRITICAL:** Use this EXACT format for your vite.config.js:
|
|
8
|
+
|
|
9
|
+
```javascript
|
|
10
|
+
import { defineConfig } from 'vite';
|
|
11
|
+
import react from '@vitejs/plugin-react';
|
|
12
|
+
|
|
13
|
+
export default defineConfig({
|
|
14
|
+
plugins: [react()],
|
|
15
|
+
root: 'ui', // React source is in ui/ directory
|
|
16
|
+
base: '', // IMPORTANT: Empty string, NOT './'
|
|
17
|
+
server: {
|
|
18
|
+
port: 3000,
|
|
19
|
+
strictPort: false,
|
|
20
|
+
},
|
|
21
|
+
build: {
|
|
22
|
+
outDir: '../dist', // Build output to dist/ (parent of ui/)
|
|
23
|
+
assetsDir: 'assets',
|
|
24
|
+
emptyOutDir: true,
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Why `base: ''`?**
|
|
30
|
+
- MAJK loads plugins in iframes with dynamic paths
|
|
31
|
+
- Empty base ensures assets load correctly
|
|
32
|
+
- `base: './'` will cause 404 errors for assets
|
|
33
|
+
|
|
34
|
+
## Project Structure
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
my-plugin/
|
|
38
|
+
├── src/
|
|
39
|
+
│ ├── index.ts # Plugin definition (definePlugin)
|
|
40
|
+
│ └── core/ # Business logic (no plugin dependencies)
|
|
41
|
+
│ ├── analytics.ts
|
|
42
|
+
│ └── formatters.ts
|
|
43
|
+
├── ui/
|
|
44
|
+
│ ├── index.html
|
|
45
|
+
│ ├── src/
|
|
46
|
+
│ │ ├── main.tsx # React entry point
|
|
47
|
+
│ │ ├── App.tsx # Router setup
|
|
48
|
+
│ │ ├── components/
|
|
49
|
+
│ │ │ ├── DashboardPage.tsx
|
|
50
|
+
│ │ │ ├── SettingsPage.tsx
|
|
51
|
+
│ │ │ └── shared/
|
|
52
|
+
│ │ │ └── ErrorBoundary.tsx
|
|
53
|
+
│ │ └── generated/ # Auto-generated (DO NOT EDIT)
|
|
54
|
+
│ │ ├── hooks.ts # useHealth(), useGetAnalytics(), etc.
|
|
55
|
+
│ │ ├── client.ts # RPC client
|
|
56
|
+
│ │ ├── types.ts # TypeScript types
|
|
57
|
+
│ │ └── index.ts
|
|
58
|
+
│ └── vite.config.js
|
|
59
|
+
├── tests/
|
|
60
|
+
│ └── plugin/
|
|
61
|
+
│ ├── functions/
|
|
62
|
+
│ │ └── unit/
|
|
63
|
+
│ │ ├── health.test.js
|
|
64
|
+
│ │ └── analytics.test.js
|
|
65
|
+
│ └── ui/
|
|
66
|
+
│ └── unit/
|
|
67
|
+
│ ├── dashboard.test.js
|
|
68
|
+
│ └── events-list.test.js
|
|
69
|
+
├── dist/ # Build output (ignored by git)
|
|
70
|
+
│ ├── index.html
|
|
71
|
+
│ ├── assets/
|
|
72
|
+
│ │ ├── index-abc123.js
|
|
73
|
+
│ │ └── index-def456.css
|
|
74
|
+
│ └── index.js # Plugin definition (compiled)
|
|
75
|
+
├── package.json
|
|
76
|
+
├── tsconfig.json
|
|
77
|
+
├── .gitignore
|
|
78
|
+
└── README.md
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## package.json
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"name": "@yourorg/my-plugin",
|
|
86
|
+
"version": "1.0.0",
|
|
87
|
+
"main": "dist/index.js",
|
|
88
|
+
"type": "commonjs",
|
|
89
|
+
"scripts": {
|
|
90
|
+
"build": "tsc && cd ui && npm run build",
|
|
91
|
+
"build:plugin": "tsc",
|
|
92
|
+
"build:ui": "cd ui && npm run build",
|
|
93
|
+
"dev": "cd ui && npm run dev",
|
|
94
|
+
"test:plugin:functions": "majk-test 'tests/plugin/functions/**/*.test.js'",
|
|
95
|
+
"test:plugin:ui": "majk-test 'tests/plugin/ui/**/*.test.js'",
|
|
96
|
+
"test:plugin": "majk-test 'tests/plugin/**/*.test.js'"
|
|
97
|
+
},
|
|
98
|
+
"dependencies": {
|
|
99
|
+
"@majkapp/plugin-kit": "^3.2.1"
|
|
100
|
+
},
|
|
101
|
+
"devDependencies": {
|
|
102
|
+
"@majkapp/plugin-test": "^1.0.0",
|
|
103
|
+
"@majkapp/plugin-ui": "^1.0.0",
|
|
104
|
+
"@types/node": "^20.0.0",
|
|
105
|
+
"@types/react": "^18.0.0",
|
|
106
|
+
"@types/react-dom": "^18.0.0",
|
|
107
|
+
"@vitejs/plugin-react": "^4.0.0",
|
|
108
|
+
"react": "^18.2.0",
|
|
109
|
+
"react-dom": "^18.2.0",
|
|
110
|
+
"react-router-dom": "^6.11.0",
|
|
111
|
+
"typescript": "^5.0.0",
|
|
112
|
+
"vite": "^4.3.0"
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## tsconfig.json (Plugin)
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
{
|
|
121
|
+
"compilerOptions": {
|
|
122
|
+
"target": "ES2020",
|
|
123
|
+
"module": "commonjs",
|
|
124
|
+
"lib": ["ES2020"],
|
|
125
|
+
"declaration": true,
|
|
126
|
+
"outDir": "./dist",
|
|
127
|
+
"rootDir": "./src",
|
|
128
|
+
"strict": true,
|
|
129
|
+
"esModuleInterop": true,
|
|
130
|
+
"skipLibCheck": true,
|
|
131
|
+
"forceConsistentCasingInFileNames": true,
|
|
132
|
+
"resolveJsonModule": true,
|
|
133
|
+
"moduleResolution": "node"
|
|
134
|
+
},
|
|
135
|
+
"include": ["src/**/*"],
|
|
136
|
+
"exclude": ["node_modules", "dist", "ui", "tests"]
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## tsconfig.json (UI)
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
// ui/tsconfig.json
|
|
144
|
+
{
|
|
145
|
+
"compilerOptions": {
|
|
146
|
+
"target": "ES2020",
|
|
147
|
+
"useDefineForClassFields": true,
|
|
148
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
149
|
+
"module": "ESNext",
|
|
150
|
+
"skipLibCheck": true,
|
|
151
|
+
"moduleResolution": "bundler",
|
|
152
|
+
"allowImportingTsExtensions": true,
|
|
153
|
+
"resolveJsonModule": true,
|
|
154
|
+
"isolatedModules": true,
|
|
155
|
+
"noEmit": true,
|
|
156
|
+
"jsx": "react-jsx",
|
|
157
|
+
"strict": true,
|
|
158
|
+
"noUnusedLocals": true,
|
|
159
|
+
"noUnusedParameters": true,
|
|
160
|
+
"noFallthroughCasesInSwitch": true
|
|
161
|
+
},
|
|
162
|
+
"include": ["src"],
|
|
163
|
+
"references": [{ "path": "./tsconfig.node.json" }]
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## ui/index.html
|
|
168
|
+
|
|
169
|
+
```html
|
|
170
|
+
<!doctype html>
|
|
171
|
+
<html lang="en">
|
|
172
|
+
<head>
|
|
173
|
+
<meta charset="UTF-8" />
|
|
174
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
175
|
+
<title>My Plugin</title>
|
|
176
|
+
</head>
|
|
177
|
+
<body>
|
|
178
|
+
<div id="root"></div>
|
|
179
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
180
|
+
</body>
|
|
181
|
+
</html>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## ui/src/main.tsx
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
import React from 'react';
|
|
188
|
+
import ReactDOM from 'react-dom/client';
|
|
189
|
+
import { App } from './App';
|
|
190
|
+
import './index.css';
|
|
191
|
+
|
|
192
|
+
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
193
|
+
<React.StrictMode>
|
|
194
|
+
<App />
|
|
195
|
+
</React.StrictMode>,
|
|
196
|
+
);
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## ui/src/App.tsx
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
|
203
|
+
import { DashboardPage } from './components/DashboardPage';
|
|
204
|
+
import { SettingsPage } from './components/SettingsPage';
|
|
205
|
+
|
|
206
|
+
export function App() {
|
|
207
|
+
// CRITICAL: Use window.__MAJK_IFRAME_BASE__ for basename
|
|
208
|
+
const basename = (window as any).__MAJK_IFRAME_BASE__ || '/';
|
|
209
|
+
|
|
210
|
+
return (
|
|
211
|
+
<BrowserRouter basename={basename}>
|
|
212
|
+
<Routes>
|
|
213
|
+
<Route path="/" element={<DashboardPage />} />
|
|
214
|
+
<Route path="/settings" element={<SettingsPage />} />
|
|
215
|
+
</Routes>
|
|
216
|
+
</BrowserRouter>
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## .gitignore
|
|
222
|
+
|
|
223
|
+
```
|
|
224
|
+
# Dependencies
|
|
225
|
+
node_modules/
|
|
226
|
+
ui/node_modules/
|
|
227
|
+
|
|
228
|
+
# Build output
|
|
229
|
+
dist/
|
|
230
|
+
ui/dist/
|
|
231
|
+
|
|
232
|
+
# Test output
|
|
233
|
+
tests/__screenshots__/
|
|
234
|
+
|
|
235
|
+
# Logs
|
|
236
|
+
*.log
|
|
237
|
+
npm-debug.log*
|
|
238
|
+
|
|
239
|
+
# Environment
|
|
240
|
+
.env
|
|
241
|
+
.env.local
|
|
242
|
+
|
|
243
|
+
# IDE
|
|
244
|
+
.vscode/
|
|
245
|
+
.idea/
|
|
246
|
+
*.swp
|
|
247
|
+
*.swo
|
|
248
|
+
|
|
249
|
+
# OS
|
|
250
|
+
.DS_Store
|
|
251
|
+
Thumbs.db
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## Build Process
|
|
255
|
+
|
|
256
|
+
### 1. Install Dependencies
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
# Root dependencies
|
|
260
|
+
npm install
|
|
261
|
+
|
|
262
|
+
# UI dependencies
|
|
263
|
+
cd ui && npm install && cd ..
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### 2. Build Plugin
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
npm run build
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
This runs:
|
|
273
|
+
1. `tsc` - Compiles `src/index.ts` → `dist/index.js`
|
|
274
|
+
2. `cd ui && npm run build` - Builds React app → `dist/` (assets)
|
|
275
|
+
|
|
276
|
+
### 3. Generated Files
|
|
277
|
+
|
|
278
|
+
After build, your `dist/` should contain:
|
|
279
|
+
|
|
280
|
+
```
|
|
281
|
+
dist/
|
|
282
|
+
├── index.js # Compiled plugin definition
|
|
283
|
+
├── index.d.ts # TypeScript declarations
|
|
284
|
+
├── index.html # Built React app
|
|
285
|
+
└── assets/
|
|
286
|
+
├── index-abc123.js # Bundled React app
|
|
287
|
+
└── index-def456.css # Bundled CSS
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## Development Workflow
|
|
291
|
+
|
|
292
|
+
### 1. Start UI Development Server
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
npm run dev
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Opens UI at `http://localhost:3000` with hot reload.
|
|
299
|
+
|
|
300
|
+
### 2. Build Plugin for Testing
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
npm run build:plugin
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Compiles plugin without rebuilding UI.
|
|
307
|
+
|
|
308
|
+
### 3. Full Build
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
npm run build
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Compiles plugin AND builds UI for production.
|
|
315
|
+
|
|
316
|
+
### 4. Run Tests
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
# All tests
|
|
320
|
+
npm run test:plugin
|
|
321
|
+
|
|
322
|
+
# Function tests only
|
|
323
|
+
npm run test:plugin:functions
|
|
324
|
+
|
|
325
|
+
# UI tests only
|
|
326
|
+
npm run test:plugin:ui
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
## Environment Variables
|
|
330
|
+
|
|
331
|
+
React app can access these globals:
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
// ui/src/types/window.d.ts
|
|
335
|
+
declare global {
|
|
336
|
+
interface Window {
|
|
337
|
+
__MAJK_BASE_URL__: string; // Host base URL
|
|
338
|
+
__MAJK_IFRAME_BASE__: string; // Plugin iframe base
|
|
339
|
+
__MAJK_PLUGIN_ID__: string; // Your plugin ID
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export {};
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Usage:
|
|
347
|
+
|
|
348
|
+
```typescript
|
|
349
|
+
// ui/src/config.ts
|
|
350
|
+
export const config = {
|
|
351
|
+
baseUrl: window.__MAJK_BASE_URL__,
|
|
352
|
+
iframeBase: window.__MAJK_IFRAME_BASE__,
|
|
353
|
+
pluginId: window.__MAJK_PLUGIN_ID__
|
|
354
|
+
};
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
## Multi-Package Setup (Optional)
|
|
358
|
+
|
|
359
|
+
For larger plugins, split into separate packages:
|
|
360
|
+
|
|
361
|
+
```
|
|
362
|
+
packages/
|
|
363
|
+
├── plugin/ # @yourorg/my-plugin
|
|
364
|
+
│ ├── src/
|
|
365
|
+
│ ├── package.json
|
|
366
|
+
│ └── tsconfig.json
|
|
367
|
+
├── ui/ # @yourorg/my-plugin-ui
|
|
368
|
+
│ ├── src/
|
|
369
|
+
│ ├── package.json
|
|
370
|
+
│ └── vite.config.js
|
|
371
|
+
└── core/ # @yourorg/my-plugin-core
|
|
372
|
+
├── src/
|
|
373
|
+
├── package.json
|
|
374
|
+
└── tsconfig.json
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
## Troubleshooting
|
|
378
|
+
|
|
379
|
+
### Assets 404 Error
|
|
380
|
+
|
|
381
|
+
**Problem:** UI loads but assets fail with 404
|
|
382
|
+
|
|
383
|
+
**Fix:** Check `vite.config.js` has `base: ''` (NOT `base: './'`)
|
|
384
|
+
|
|
385
|
+
### Plugin Not Found
|
|
386
|
+
|
|
387
|
+
**Problem:** Plugin doesn't load in MAJK
|
|
388
|
+
|
|
389
|
+
**Fix:**
|
|
390
|
+
1. Ensure `dist/index.js` exists
|
|
391
|
+
2. Check `package.json` has `"main": "dist/index.js"`
|
|
392
|
+
3. Verify plugin calls `.build()` at the end
|
|
393
|
+
|
|
394
|
+
### Generated Hooks Not Found
|
|
395
|
+
|
|
396
|
+
**Problem:** `import { useHealth } from './generated/hooks'` fails
|
|
397
|
+
|
|
398
|
+
**Fix:**
|
|
399
|
+
1. Run `npm run build` to generate hooks
|
|
400
|
+
2. Check `ui/src/generated/` directory exists
|
|
401
|
+
3. Verify functions are defined before `.build()`
|
|
402
|
+
|
|
403
|
+
### Tests Can't Find Plugin
|
|
404
|
+
|
|
405
|
+
**Problem:** `invoke('functionName')` fails in tests
|
|
406
|
+
|
|
407
|
+
**Fix:**
|
|
408
|
+
1. Ensure plugin is built: `npm run build:plugin`
|
|
409
|
+
2. Check function name matches definition
|
|
410
|
+
3. Verify `export = plugin;` at end of `src/index.ts`
|
|
411
|
+
|
|
412
|
+
## Quick Start Checklist
|
|
413
|
+
|
|
414
|
+
- [ ] Create project structure
|
|
415
|
+
- [ ] Add `vite.config.js` with `base: ''`
|
|
416
|
+
- [ ] Add `tsconfig.json` for plugin and UI
|
|
417
|
+
- [ ] Create `src/index.ts` with `definePlugin()`
|
|
418
|
+
- [ ] Create `ui/src/App.tsx` with `BrowserRouter`
|
|
419
|
+
- [ ] Add `.gitignore` to exclude `dist/` and `node_modules/`
|
|
420
|
+
- [ ] Run `npm install` in root and `ui/`
|
|
421
|
+
- [ ] Run `npm run build` to compile
|
|
422
|
+
- [ ] Run `npm run test:plugin` to verify setup
|
|
423
|
+
|
|
424
|
+
## Next Steps
|
|
425
|
+
|
|
426
|
+
Run `npx @majkapp/plugin-kit --functions` - Define your functions
|
|
427
|
+
Run `npx @majkapp/plugin-kit --screens` - Configure screens
|
|
428
|
+
Run `npx @majkapp/plugin-kit --testing` - Write tests
|