create-lego-one 2.0.12 → 2.0.14

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.
Files changed (78) hide show
  1. package/dist/index.cjs +150 -15
  2. package/dist/index.cjs.map +1 -1
  3. package/package.json +1 -1
  4. package/template/.cursor/rules/rules.mdc +639 -0
  5. package/template/.dockerignore +58 -0
  6. package/template/.env.example +18 -0
  7. package/template/.eslintignore +5 -0
  8. package/template/.eslintrc.js +28 -0
  9. package/template/.prettierignore +6 -0
  10. package/template/.prettierrc +11 -0
  11. package/template/CLAUDE.md +634 -0
  12. package/template/Dockerfile +67 -0
  13. package/template/PROMPT.md +457 -0
  14. package/template/README.md +325 -0
  15. package/template/docker-compose.yml +48 -0
  16. package/template/docker-entrypoint.sh +23 -0
  17. package/template/docs/checkpoints/.template.md +64 -0
  18. package/template/docs/checkpoints/framework/01-infrastructure-setup.md +132 -0
  19. package/template/docs/checkpoints/framework/02-pocketbase-setup.md +155 -0
  20. package/template/docs/checkpoints/framework/03-host-kernel.md +170 -0
  21. package/template/docs/checkpoints/framework/04-auth-system.md +163 -0
  22. package/template/docs/checkpoints/framework/phase-05-multitenancy-rbac.md +223 -0
  23. package/template/docs/checkpoints/framework/phase-06-ui-components.md +260 -0
  24. package/template/docs/checkpoints/framework/phase-07-communication-system.md +276 -0
  25. package/template/docs/checkpoints/framework/phase-08-plugin-system.md +91 -0
  26. package/template/docs/checkpoints/framework/phase-09-dashboard-plugin.md +111 -0
  27. package/template/docs/checkpoints/framework/phase-10-todo-plugin.md +169 -0
  28. package/template/docs/checkpoints/framework/phase-11-testing.md +264 -0
  29. package/template/docs/checkpoints/framework/phase-12-deployment.md +294 -0
  30. package/template/docs/checkpoints/framework/phase-13-documentation.md +312 -0
  31. package/template/docs/framework/plans/00-index.md +164 -0
  32. package/template/docs/framework/plans/01-infrastructure-setup.md +855 -0
  33. package/template/docs/framework/plans/02-pocketbase-setup.md +1374 -0
  34. package/template/docs/framework/plans/03-host-kernel.md +1518 -0
  35. package/template/docs/framework/plans/04-auth-system.md +1466 -0
  36. package/template/docs/framework/plans/05-multitenancy-rbac.md +1527 -0
  37. package/template/docs/framework/plans/06-ui-components.md +1478 -0
  38. package/template/docs/framework/plans/07-communication-system.md +1106 -0
  39. package/template/docs/framework/plans/08-plugin-system.md +1179 -0
  40. package/template/docs/framework/plans/09-dashboard-plugin.md +1137 -0
  41. package/template/docs/framework/plans/10-todo-plugin.md +1343 -0
  42. package/template/docs/framework/plans/11-testing.md +935 -0
  43. package/template/docs/framework/plans/12-deployment.md +896 -0
  44. package/template/docs/framework/prompts/0-boilerplate-modernjs.md +151 -0
  45. package/template/docs/framework/research/00-modernjs-audit.md +488 -0
  46. package/template/docs/framework/research/01-system-blueprint.md +721 -0
  47. package/template/docs/framework/research/02-data-migration-protocol.md +699 -0
  48. package/template/docs/framework/research/03-host-setup.md +714 -0
  49. package/template/docs/framework/research/04-plugin-architecture.md +645 -0
  50. package/template/docs/framework/research/05-slot-injection-pattern.md +671 -0
  51. package/template/docs/framework/research/06-cli-strategy.md +615 -0
  52. package/template/docs/framework/research/07-deployment.md +629 -0
  53. package/template/docs/framework/research/README.md +282 -0
  54. package/template/docs/framework/setup/00-index.md +210 -0
  55. package/template/docs/framework/setup/01-framework-structure.md +308 -0
  56. package/template/docs/framework/setup/02-development-workflow.md +405 -0
  57. package/template/docs/framework/setup/03-environment-setup.md +215 -0
  58. package/template/docs/framework/setup/04-kernel-architecture.md +499 -0
  59. package/template/docs/framework/setup/05-plugin-system.md +620 -0
  60. package/template/docs/framework/setup/06-communication-patterns.md +451 -0
  61. package/template/docs/framework/setup/07-plugin-development.md +582 -0
  62. package/template/docs/framework/setup/08-component-library.md +658 -0
  63. package/template/docs/framework/setup/09-data-integration.md +609 -0
  64. package/template/docs/framework/setup/10-auth-rbac.md +497 -0
  65. package/template/docs/framework/setup/11-hooks-api.md +393 -0
  66. package/template/docs/framework/setup/12-components-api.md +665 -0
  67. package/template/docs/framework/setup/13-deployment-guide.md +566 -0
  68. package/template/docs/framework/setup/README.md +548 -0
  69. package/template/host/package.json +1 -1
  70. package/template/nginx.conf +72 -0
  71. package/template/package.json +1 -1
  72. package/template/packages/plugins/@lego/plugin-dashboard/package.json +1 -1
  73. package/template/packages/plugins/@lego/plugin-todo/package.json +1 -1
  74. package/template/pocketbase/CHANGELOG.md +911 -0
  75. package/template/pocketbase/LICENSE.md +17 -0
  76. package/template/scripts/create-plugin.js +221 -0
  77. package/template/scripts/deploy.sh +56 -0
  78. package/template/tsconfig.base.json +26 -0
@@ -0,0 +1,451 @@
1
+ # Communication Patterns
2
+
3
+ **Window Bridge and Channel Bus for Plugin-Host Communication**
4
+
5
+ ---
6
+
7
+ ## Overview
8
+
9
+ The Lego-One framework uses a **Window Bridge pattern** for plugin-host communication. Plugins access host services and state via global window objects, and communicate through a **Garfish Channel Bus** for pub/sub messaging.
10
+
11
+ ---
12
+
13
+ ## Architecture Diagram
14
+
15
+ ```
16
+ ┌─────────────────────────────────────────────────────────────────────────┐
17
+ │ HOST KERNEL │
18
+ │ ┌────────────────────────────────────────────────────────────────────┐ │
19
+ │ │ CHANNEL BUS (Garfish) │ │
20
+ │ │ • publish(channel, message) • subscribe(channel, callback) │ │
21
+ │ └────────────────────────────────────────────────────────────────────┘ │
22
+ │ │ │
23
+ │ ┌────────────────────────────────────────────────────────────────────┐ │
24
+ │ │ WINDOW BRIDGE (global) │ │
25
+ │ │ • __LEGO_KERNEL_STATE__ (read-only state access) │ │
26
+ │ │ • __LEGO_CHANNEL_BUS__ (pub/sub messaging) │ │
27
+ │ └────────────────────────────────────────────────────────────────────┘ │
28
+ └─────────────────────────────────────────────────────────────────────────┘
29
+
30
+ ═══════════════════════════════════════
31
+ PLUGIN BOUNDARY (Window Object)
32
+ ═══════════════════════════════════════
33
+
34
+ ┌─────────────────────────────────────────────────────────────────────────┐
35
+ │ PLUGIN │
36
+ │ ┌────────────────────────────────────────────────────────────────────┐ │
37
+ │ │ PLUGIN CODE │ │
38
+ │ │ const state = window.__LEGO_KERNEL_STATE__ │ │
39
+ │ │ const bus = window.__LEGO_CHANNEL_BUS__ │ │
40
+ │ │ bus.publish('lego:toast', {...}) │ │
41
+ │ │ bus.subscribe('lego:auth', (data) => ...) │ │
42
+ │ └────────────────────────────────────────────────────────────────────┘ │
43
+ └─────────────────────────────────────────────────────────────────────────┘
44
+ ```
45
+
46
+ ---
47
+
48
+ ## Window Bridge
49
+
50
+ ### __LEGO_KERNEL_STATE__
51
+
52
+ **Purpose:** Read-only access to kernel global state
53
+
54
+ **Available Properties:**
55
+ ```typescript
56
+ interface KernelState {
57
+ user: User | null; // Current authenticated user
58
+ organization: Organization | null; // Current selected organization
59
+ token: string | null; // Authentication token
60
+ isAuthenticated: boolean; // Auth status flag
61
+ sidebarOpen: boolean; // Sidebar toggle state
62
+ mobileMenuOpen: boolean; // Mobile menu state
63
+
64
+ // Access method to Zustand store
65
+ useGlobalKernelState: typeof import('@lego/kernel/shared-state').useGlobalKernelState;
66
+ }
67
+ ```
68
+
69
+ **Accessing State:**
70
+ ```typescript
71
+ // In plugin component
72
+ function MyPluginComponent() {
73
+ // Method 1: Direct property access
74
+ const kernelState = window.__LEGO_KERNEL_STATE__;
75
+ const user = kernelState?.user;
76
+ const organization = kernelState?.organization;
77
+
78
+ // Method 2: Get latest state from store
79
+ const latestState = kernelState?.useGlobalKernelState?.getState();
80
+
81
+ return (
82
+ <div>
83
+ <p>User: {user?.email}</p>
84
+ <p>Organization: {organization?.name}</p>
85
+ </div>
86
+ );
87
+ }
88
+ ```
89
+
90
+ **What You CAN Do:**
91
+ - ✅ Read user info
92
+ - ✅ Read organization info
93
+ - ✅ Check authentication status
94
+ - ✅ Get latest state from store
95
+
96
+ **What You CANNOT Do:**
97
+ - ❌ Modify kernel state directly
98
+ - ❌ Call kernel actions (use channels instead)
99
+
100
+ ---
101
+
102
+ ### __LEGO_CHANNEL_BUS__
103
+
104
+ **Purpose:** Pub/sub messaging between plugins and host
105
+
106
+ **Available Methods:**
107
+ ```typescript
108
+ interface ChannelBus {
109
+ publish: (channel: string, message: any) => void;
110
+ subscribe: (channel: string, callback: (message: any) => void) => () => void;
111
+ }
112
+ ```
113
+
114
+ **Publishing Messages:**
115
+ ```typescript
116
+ // Publish toast notification
117
+ window.__LEGO_CHANNEL_BUS__?.publish('lego:toast', {
118
+ type: 'success',
119
+ title: 'Saved!',
120
+ description: 'Your changes were saved successfully',
121
+ });
122
+
123
+ // Publish navigation request
124
+ window.__LEGO_CHANNEL_BUS__?.publish('lego:navigation', {
125
+ path: '/todos/123',
126
+ replace: false,
127
+ });
128
+ ```
129
+
130
+ **Subscribing to Messages:**
131
+ ```typescript
132
+ useEffect(() => {
133
+ const channelBus = window.__LEGO_CHANNEL_BUS__;
134
+ if (!channelBus) return;
135
+
136
+ // Subscribe to auth changes
137
+ const unsubscribe = channelBus.subscribe('lego:auth:change', (data) => {
138
+ console.log('Auth changed:', data);
139
+
140
+ if (data.isAuthenticated) {
141
+ console.log('User logged in:', data.userId);
142
+ // Refresh plugin data
143
+ } else {
144
+ console.log('User logged out');
145
+ // Clear plugin data
146
+ }
147
+ });
148
+
149
+ // Cleanup on unmount
150
+ return () => {
151
+ unsubscribe();
152
+ };
153
+ }, []);
154
+ ```
155
+
156
+ ---
157
+
158
+ ## Channel Names
159
+
160
+ ### Standard Channels
161
+
162
+ | Channel | Purpose | Published By |
163
+ |---------|---------|-------------|
164
+ | `lego:toast` | Show notifications | Plugins → Host |
165
+ | `lego:navigation` | Navigate to route | Plugins → Host |
166
+ | `lego:state:update` | Update shared state | Plugins → Host |
167
+ | `lego:plugin:ready` | Plugin initialized | Plugins → Host |
168
+ | `lego:plugin:error` | Plugin error | Plugins → Host |
169
+ | `lego:auth:change` | Auth state changed | Host → All |
170
+ | `lego:organization:change` | Organization changed | Host → All |
171
+
172
+ ### Channel Message Formats
173
+
174
+ **Toast Channel:**
175
+ ```typescript
176
+ {
177
+ type: 'success' | 'error' | 'info' | 'warning',
178
+ title: string,
179
+ description?: string,
180
+ duration?: number, // milliseconds
181
+ }
182
+ ```
183
+
184
+ **Navigation Channel:**
185
+ ```typescript
186
+ {
187
+ path: string,
188
+ replace?: boolean,
189
+ }
190
+ ```
191
+
192
+ **Auth Change Channel:**
193
+ ```typescript
194
+ {
195
+ isAuthenticated: boolean,
196
+ userId?: string,
197
+ organizationId?: string,
198
+ }
199
+ ```
200
+
201
+ **Organization Change Channel:**
202
+ ```typescript
203
+ {
204
+ organizationId: string,
205
+ organizationName: string,
206
+ }
207
+ ```
208
+
209
+ ---
210
+
211
+ ## Communication Patterns
212
+
213
+ ### Pattern 1: Plugin → Host (Request Action)
214
+
215
+ **Use Case:** Plugin wants host to display a toast notification
216
+
217
+ ```typescript
218
+ // In plugin
219
+ function saveTodo() {
220
+ // After successful save
221
+ window.__LEGO_CHANNEL_BUS__?.publish('lego:toast', {
222
+ type: 'success',
223
+ title: 'Todo Created',
224
+ description: 'Your todo was created successfully',
225
+ });
226
+ }
227
+ ```
228
+
229
+ **Host Integration:**
230
+ - Host has `ToastIntegration` component listening to `lego:toast`
231
+ - Automatically displays Shadcn toast when message received
232
+
233
+ ---
234
+
235
+ ### Pattern 2: Host → Plugin (Broadcast State)
236
+
237
+ **Use Case:** User switches organizations, plugin needs to refresh data
238
+
239
+ ```typescript
240
+ // In plugin
241
+ useEffect(() => {
242
+ const channelBus = window.__LEGO_CHANNEL_BUS__;
243
+ if (!channelBus) return;
244
+
245
+ const unsubscribe = channelBus.subscribe('lego:organization:change', (data) => {
246
+ console.log('Organization changed to:', data.organizationName);
247
+
248
+ // Refresh plugin data for new organization
249
+ queryClient.invalidateQueries({ queryKey: ['todos'] });
250
+ });
251
+
252
+ return unsubscribe;
253
+ }, []);
254
+ ```
255
+
256
+ **Host Behavior:**
257
+ - `ChannelProvider` automatically publishes org changes
258
+ - All subscribed plugins receive notification
259
+
260
+ ---
261
+
262
+ ### Pattern 3: Plugin → Plugin (Direct Communication)
263
+
264
+ **Use Case:** Plugin A needs to notify Plugin B
265
+
266
+ **Option 1: Via Host (Recommended)**
267
+ ```typescript
268
+ // Plugin A publishes
269
+ window.__LEGO_CHANNEL_BUS__?.publish('custom:plugin-a-event', {
270
+ data: 'Something happened in Plugin A',
271
+ });
272
+
273
+ // Plugin B subscribes
274
+ useEffect(() => {
275
+ const unsubscribe = window.__LEGO_CHANNEL_BUS__?.subscribe(
276
+ 'custom:plugin-a-event',
277
+ (data) => console.log('Received from Plugin A:', data)
278
+ );
279
+ return unsubscribe;
280
+ }, []);
281
+ ```
282
+
283
+ **Option 2: Via Custom Channel**
284
+ - Create a custom channel name: `lego:plugins:shared`
285
+ - Both plugins use this channel for communication
286
+
287
+ ---
288
+
289
+ ### Pattern 4: Reading Kernel State
290
+
291
+ **Use Case:** Plugin needs current organization ID for data fetching
292
+
293
+ ```typescript
294
+ // Create a custom hook
295
+ export function useCurrentOrganization() {
296
+ const [org, setOrg] = useState(null);
297
+
298
+ useEffect(() => {
299
+ const kernelState = window.__LEGO_KERNEL_STATE__;
300
+ const state = kernelState?.useGlobalKernelState?.getState();
301
+ setOrg(state?.organization || null);
302
+
303
+ // Subscribe to organization changes
304
+ const channelBus = window.__LEGO_CHANNEL_BUS__;
305
+ if (!channelBus) return;
306
+
307
+ const unsubscribe = channelBus.subscribe('lego:organization:change', (data) => {
308
+ const newState = kernelState?.useGlobalKernelState?.getState();
309
+ setOrg(newState?.organization || null);
310
+ });
311
+
312
+ return unsubscribe;
313
+ }, []);
314
+
315
+ return org;
316
+ }
317
+
318
+ // Use in component
319
+ function MyPluginComponent() {
320
+ const organization = useCurrentOrganization();
321
+ const orgId = organization?.id;
322
+
323
+ const { data: todos } = useTodos(orgId);
324
+ // ...
325
+ }
326
+ ```
327
+
328
+ ---
329
+
330
+ ## Type Safety
331
+
332
+ ### Plugin Type Definitions
333
+
334
+ **File:** `packages/plugins/@lego/plugin-<name>/src/vite-env.d.ts`
335
+
336
+ ```typescript
337
+ declare global {
338
+ interface Window {
339
+ __LEGO_KERNEL_STATE__?: {
340
+ user?: { id: string; email: string; name?: string } | null;
341
+ organization?: { id: string; name: string; slug: string } | null;
342
+ isAuthenticated: boolean;
343
+ useGlobalKernelState?: any;
344
+ };
345
+ __LEGO_CHANNEL_BUS__?: {
346
+ publish: (channel: string, message: any) => void;
347
+ subscribe: (channel: string, callback: (data: any) => void) => () => void;
348
+ };
349
+ }
350
+ }
351
+
352
+ export {};
353
+ ```
354
+
355
+ ---
356
+
357
+ ## Best Practices
358
+
359
+ ### DO ✅
360
+
361
+ 1. **Use window bridge** for all host communication
362
+ 2. **Subscribe to auth/org changes** to refresh data
363
+ 3. **Publish toast notifications** for user feedback
364
+ 4. **Read kernel state** via `__LEGO_KERNEL_STATE__`
365
+ 5. **Clean up subscriptions** in useEffect returns
366
+ 6. **Type window bridge** in vite-env.d.ts
367
+
368
+ ### DON'T ❌
369
+
370
+ 1. **Don't import from host** - Use window bridge instead
371
+ 2. **Don't modify kernel state** - It's read-only
372
+ 3. **Don't forget cleanup** - Always return unsubscribe function
373
+ 4. **Don't create circular dependencies** - Host → Plugin is OK, Plugin → Host via channels
374
+ 5. **Don't spam channels** - Use appropriate message frequency
375
+
376
+ ---
377
+
378
+ ## Complete Example: Plugin with Channel Integration
379
+
380
+ ```typescript
381
+ // packages/plugins/@lego/plugin-todo/src/hooks/useChannelIntegration.ts
382
+ import { useEffect } from 'react';
383
+
384
+ export function useChannelIntegration() {
385
+ useEffect(() => {
386
+ const channelBus = window.__LEGO_CHANNEL_BUS__;
387
+ const kernelState = window.__LEGO_KERNEL_STATE__;
388
+
389
+ if (!channelBus || !kernelState) return;
390
+
391
+ // Subscribe to auth changes
392
+ const unsubAuth = channelBus.subscribe('lego:auth:change', (data) => {
393
+ if (data.isAuthenticated) {
394
+ console.log('[Todo Plugin] User logged in, loading todos');
395
+ } else {
396
+ console.log('[Todo Plugin] User logged out, clearing todos');
397
+ }
398
+ });
399
+
400
+ // Subscribe to organization changes
401
+ const unsubOrg = channelBus.subscribe('lego:organization:change', (data) => {
402
+ console.log('[Todo Plugin] Organization changed:', data.organizationName);
403
+ // Refresh todos for new organization
404
+ });
405
+
406
+ // Notify host that plugin is ready
407
+ channelBus.publish('lego:plugin:ready', {
408
+ pluginName: '@lego/plugin-todo',
409
+ version: '1.0.0',
410
+ });
411
+
412
+ // Cleanup
413
+ return () => {
414
+ unsubAuth();
415
+ unsubOrg();
416
+ };
417
+ }, []);
418
+ }
419
+ ```
420
+
421
+ ---
422
+
423
+ ## Channel Hooks (Host Side)
424
+
425
+ For host components, use the channel hooks:
426
+
427
+ ```typescript
428
+ import {
429
+ useChannel,
430
+ usePublish,
431
+ useToastChannel,
432
+ useNavigationChannel,
433
+ } from '@lego/kernel/channels';
434
+
435
+ // Subscribe to any channel
436
+ useChannel(ChannelName.AUTH_CHANGE, (data) => {
437
+ console.log('Auth changed:', data);
438
+ });
439
+
440
+ // Publish to toast channel
441
+ const publishToast = useToastChannel();
442
+ publishToast({ type: 'success', title: 'Done!' });
443
+
444
+ // Publish to any channel
445
+ const publish = usePublish();
446
+ publish({ channel: ChannelName.NAVIGATION, data: {...} });
447
+ ```
448
+
449
+ ---
450
+
451
+ **Next:** Read [`07-plugin-development.md`](./07-plugin-development.md) for complete plugin creation guide.