@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/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