create-lego-one 2.0.15 → 2.0.16
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/package.json +1 -1
- package/template/host/package.json +1 -1
- package/template/host/src/bootstrap.tsx +27 -22
- package/template/host/src/kernel/providers/PocketBaseProvider.tsx +189 -27
- package/template/package.json +1 -1
- package/template/packages/plugins/@lego/plugin-dashboard/package.json +1 -1
- package/template/packages/plugins/@lego/plugin-todo/package.json +1 -1
package/package.json
CHANGED
|
@@ -48,27 +48,32 @@ async function initializePlugins() {
|
|
|
48
48
|
|
|
49
49
|
// Create root
|
|
50
50
|
const container = document.getElementById('root');
|
|
51
|
-
if (container) {
|
|
52
|
-
|
|
51
|
+
if (!container) {
|
|
52
|
+
console.error('[Bootstrap] ❌ Root element not found! Make sure Modern.js generated the HTML file.');
|
|
53
|
+
throw new Error('Root element (#root) not found in DOM');
|
|
54
|
+
}
|
|
53
55
|
|
|
54
|
-
|
|
55
|
-
initializePlugins();
|
|
56
|
+
const root = createRoot(container);
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
58
|
+
// Initialize plugins
|
|
59
|
+
initializePlugins();
|
|
60
|
+
|
|
61
|
+
console.log('[Bootstrap] ✅ Starting app render...');
|
|
62
|
+
|
|
63
|
+
root.render(
|
|
64
|
+
<StrictMode>
|
|
65
|
+
<BrowserRouter>
|
|
66
|
+
<ThemeProvider>
|
|
67
|
+
<QueryProvider>
|
|
68
|
+
<PocketBaseProvider>
|
|
69
|
+
<SlotProvider>
|
|
70
|
+
<ChannelProvider />
|
|
71
|
+
<App />
|
|
72
|
+
<Toaster />
|
|
73
|
+
</SlotProvider>
|
|
74
|
+
</PocketBaseProvider>
|
|
75
|
+
</QueryProvider>
|
|
76
|
+
</ThemeProvider>
|
|
77
|
+
</BrowserRouter>
|
|
78
|
+
</StrictMode>
|
|
79
|
+
);
|
|
@@ -7,38 +7,79 @@ const PocketBaseContext = createContext<PocketBase | null>(null);
|
|
|
7
7
|
|
|
8
8
|
export function PocketBaseProvider({ children }: { children: React.ReactNode }) {
|
|
9
9
|
const [pb, setPb] = useState<PocketBase | null>(null);
|
|
10
|
+
const [error, setError] = useState<string | null>(null);
|
|
11
|
+
const [isChecking, setIsChecking] = useState(true);
|
|
10
12
|
const { token, clearAuth, setOrganization } = useGlobalKernelState();
|
|
11
13
|
|
|
12
14
|
useEffect(() => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
async function initializePocketBase() {
|
|
16
|
+
try {
|
|
17
|
+
// Initialize PocketBase client
|
|
18
|
+
const pbUrl = import.meta.env.VITE_POCKETBASE_URL || 'http://127.0.0.1:8090';
|
|
19
|
+
console.log('[PocketBaseProvider] Initializing with URL:', pbUrl);
|
|
20
|
+
|
|
21
|
+
const client = new PocketBase(pbUrl);
|
|
15
22
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
clearAuth();
|
|
28
|
-
localStorage.removeItem('pocketbase_auth');
|
|
29
|
-
setOrganization(null);
|
|
30
|
-
} else {
|
|
31
|
-
localStorage.setItem('pocketbase_auth', token);
|
|
32
|
-
|
|
33
|
-
// Initialize organization on login
|
|
34
|
-
if (model && !model.organizationId) {
|
|
35
|
-
const org = await initializeFirstOrganization(client, model.id);
|
|
36
|
-
if (org) {
|
|
37
|
-
setOrganization(org);
|
|
23
|
+
// Test connection by attempting to fetch API info
|
|
24
|
+
setIsChecking(true);
|
|
25
|
+
try {
|
|
26
|
+
// Try to fetch the API root to verify connection
|
|
27
|
+
const response = await fetch(`${pbUrl}/api/health`, {
|
|
28
|
+
method: 'GET',
|
|
29
|
+
signal: AbortSignal.timeout(5000) // 5 second timeout
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
if (!response.ok && response.status !== 404) {
|
|
33
|
+
throw new Error(`PocketBase returned status ${response.status}`);
|
|
38
34
|
}
|
|
35
|
+
|
|
36
|
+
console.log('[PocketBaseProvider] ✅ PocketBase connection successful');
|
|
37
|
+
} catch (healthError) {
|
|
38
|
+
// If health check fails, PocketBase is likely not running
|
|
39
|
+
const errorMsg = 'PocketBase is not running or not accessible. Please start PocketBase first.';
|
|
40
|
+
console.error('[PocketBaseProvider] ❌ Connection check failed:', healthError);
|
|
41
|
+
setError(errorMsg);
|
|
42
|
+
setIsChecking(false);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Load stored token
|
|
47
|
+
const storedToken = localStorage.getItem('pocketbase_auth');
|
|
48
|
+
if (storedToken) {
|
|
49
|
+
client.authStore.save(storedToken, null);
|
|
39
50
|
}
|
|
51
|
+
|
|
52
|
+
setPb(client);
|
|
53
|
+
setIsChecking(false);
|
|
54
|
+
console.log('[PocketBaseProvider] ✅ PocketBase client initialized');
|
|
55
|
+
|
|
56
|
+
// Set up auth cleanup on token invalidation
|
|
57
|
+
client.authStore.onChange(async (token, model) => {
|
|
58
|
+
if (!token) {
|
|
59
|
+
clearAuth();
|
|
60
|
+
localStorage.removeItem('pocketbase_auth');
|
|
61
|
+
setOrganization(null);
|
|
62
|
+
} else {
|
|
63
|
+
localStorage.setItem('pocketbase_auth', token);
|
|
64
|
+
|
|
65
|
+
// Initialize organization on login
|
|
66
|
+
if (model && !model.organizationId) {
|
|
67
|
+
const org = await initializeFirstOrganization(client, model.id);
|
|
68
|
+
if (org) {
|
|
69
|
+
setOrganization(org);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
} catch (err) {
|
|
75
|
+
const errorMessage = err instanceof Error ? err.message : 'Unknown error';
|
|
76
|
+
console.error('[PocketBaseProvider] ❌ Failed to initialize:', errorMessage);
|
|
77
|
+
setError(errorMessage);
|
|
78
|
+
setIsChecking(false);
|
|
40
79
|
}
|
|
41
|
-
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
initializePocketBase();
|
|
42
83
|
|
|
43
84
|
return () => {
|
|
44
85
|
// Cleanup on unmount
|
|
@@ -52,8 +93,129 @@ export function PocketBaseProvider({ children }: { children: React.ReactNode })
|
|
|
52
93
|
}
|
|
53
94
|
}, [pb, token]);
|
|
54
95
|
|
|
55
|
-
if (
|
|
56
|
-
|
|
96
|
+
if (error) {
|
|
97
|
+
const pbUrl = import.meta.env.VITE_POCKETBASE_URL || 'http://127.0.0.1:8090';
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<div className="flex min-h-screen items-center justify-center bg-background p-6">
|
|
101
|
+
<div className="max-w-2xl rounded-lg border border-destructive bg-card p-8 shadow-lg">
|
|
102
|
+
<div className="mb-6">
|
|
103
|
+
<h2 className="text-2xl font-bold text-destructive">⚠️ PocketBase Connection Failed</h2>
|
|
104
|
+
<p className="mt-2 text-sm text-muted-foreground">
|
|
105
|
+
The application cannot connect to PocketBase. Please follow the setup steps below.
|
|
106
|
+
</p>
|
|
107
|
+
</div>
|
|
108
|
+
|
|
109
|
+
<div className="mb-6 space-y-4 rounded-lg bg-muted/50 p-4">
|
|
110
|
+
<div>
|
|
111
|
+
<h3 className="font-semibold text-foreground">Error Details:</h3>
|
|
112
|
+
<p className="mt-1 text-sm text-muted-foreground font-mono">{error}</p>
|
|
113
|
+
</div>
|
|
114
|
+
<div>
|
|
115
|
+
<h3 className="font-semibold text-foreground">Expected PocketBase URL:</h3>
|
|
116
|
+
<code className="mt-1 block rounded bg-background px-3 py-2 text-sm text-foreground">
|
|
117
|
+
{pbUrl}
|
|
118
|
+
</code>
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
<div className="mb-6">
|
|
123
|
+
<h3 className="mb-3 font-semibold text-foreground">📋 Setup Checklist:</h3>
|
|
124
|
+
<ol className="ml-6 list-decimal space-y-2 text-sm text-muted-foreground">
|
|
125
|
+
<li>
|
|
126
|
+
<strong className="text-foreground">Download PocketBase</strong>
|
|
127
|
+
<ul className="ml-4 mt-1 list-disc">
|
|
128
|
+
<li>Visit: <a href="https://pocketbase.io/docs" target="_blank" rel="noopener noreferrer" className="text-primary hover:underline">https://pocketbase.io/docs</a></li>
|
|
129
|
+
<li>Download the executable for your platform</li>
|
|
130
|
+
<li>Extract it to the <code className="rounded bg-background px-1.5 py-0.5 text-xs">pocketbase/</code> directory</li>
|
|
131
|
+
</ul>
|
|
132
|
+
</li>
|
|
133
|
+
<li>
|
|
134
|
+
<strong className="text-foreground">Start PocketBase</strong>
|
|
135
|
+
<ul className="ml-4 mt-1 list-disc">
|
|
136
|
+
<li>Open a terminal and navigate to: <code className="rounded bg-background px-1.5 py-0.5 text-xs">cd pocketbase</code></li>
|
|
137
|
+
<li>Run: <code className="rounded bg-background px-1.5 py-0.5 text-xs">./pocketbase serve</code> (or <code className="rounded bg-background px-1.5 py-0.5 text-xs">pocketbase.exe serve</code> on Windows)</li>
|
|
138
|
+
<li>PocketBase should start on port 8090</li>
|
|
139
|
+
</ul>
|
|
140
|
+
</li>
|
|
141
|
+
<li>
|
|
142
|
+
<strong className="text-foreground">Configure Environment Variables</strong>
|
|
143
|
+
<ul className="ml-4 mt-1 list-disc">
|
|
144
|
+
<li>Copy <code className="rounded bg-background px-1.5 py-0.5 text-xs">.env.development</code> to <code className="rounded bg-background px-1.5 py-0.5 text-xs">.env</code></li>
|
|
145
|
+
<li>Verify <code className="rounded bg-background px-1.5 py-0.5 text-xs">VITE_POCKETBASE_URL</code> matches your PocketBase URL</li>
|
|
146
|
+
</ul>
|
|
147
|
+
</li>
|
|
148
|
+
<li>
|
|
149
|
+
<strong className="text-foreground">Restart Development Server</strong>
|
|
150
|
+
<ul className="ml-4 mt-1 list-disc">
|
|
151
|
+
<li>Stop the current dev server (Ctrl+C)</li>
|
|
152
|
+
<li>Run <code className="rounded bg-background px-1.5 py-0.5 text-xs">pnpm run dev</code> again</li>
|
|
153
|
+
</ul>
|
|
154
|
+
</li>
|
|
155
|
+
</ol>
|
|
156
|
+
</div>
|
|
157
|
+
|
|
158
|
+
<div className="mb-6 rounded-lg border border-blue-500/50 bg-blue-500/10 p-4">
|
|
159
|
+
<h3 className="mb-2 font-semibold text-blue-600 dark:text-blue-400">💡 Quick Start Commands:</h3>
|
|
160
|
+
<div className="space-y-2 font-mono text-sm">
|
|
161
|
+
<div>
|
|
162
|
+
<span className="text-muted-foreground"># Terminal 1 - Start PocketBase</span>
|
|
163
|
+
<div className="mt-1 rounded bg-background px-3 py-2 text-foreground">
|
|
164
|
+
cd pocketbase<br />
|
|
165
|
+
./pocketbase serve
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
<div>
|
|
169
|
+
<span className="text-muted-foreground"># Terminal 2 - Start Host</span>
|
|
170
|
+
<div className="mt-1 rounded bg-background px-3 py-2 text-foreground">
|
|
171
|
+
pnpm run dev:host
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
<div>
|
|
175
|
+
<span className="text-muted-foreground"># Terminal 3 - Start Plugins (optional)</span>
|
|
176
|
+
<div className="mt-1 rounded bg-background px-3 py-2 text-foreground">
|
|
177
|
+
pnpm run dev:all
|
|
178
|
+
</div>
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
|
182
|
+
|
|
183
|
+
<div className="flex gap-3">
|
|
184
|
+
<button
|
|
185
|
+
onClick={() => window.location.reload()}
|
|
186
|
+
className="flex-1 rounded-lg bg-primary px-4 py-2 font-medium text-primary-foreground hover:bg-primary/90"
|
|
187
|
+
>
|
|
188
|
+
🔄 Retry Connection
|
|
189
|
+
</button>
|
|
190
|
+
<a
|
|
191
|
+
href="https://pocketbase.io/docs"
|
|
192
|
+
target="_blank"
|
|
193
|
+
rel="noopener noreferrer"
|
|
194
|
+
className="flex-1 rounded-lg border border-border bg-background px-4 py-2 text-center font-medium text-foreground hover:bg-accent"
|
|
195
|
+
>
|
|
196
|
+
📚 PocketBase Docs
|
|
197
|
+
</a>
|
|
198
|
+
</div>
|
|
199
|
+
</div>
|
|
200
|
+
</div>
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (!pb && !error && isChecking) {
|
|
205
|
+
return (
|
|
206
|
+
<div className="flex min-h-screen items-center justify-center bg-background">
|
|
207
|
+
<div className="text-center">
|
|
208
|
+
<div className="mb-4 inline-block h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent"></div>
|
|
209
|
+
<p className="text-sm text-muted-foreground">Connecting to PocketBase...</p>
|
|
210
|
+
<p className="mt-2 text-xs text-muted-foreground">
|
|
211
|
+
Make sure PocketBase is running at{' '}
|
|
212
|
+
<code className="rounded bg-muted px-1.5 py-0.5">
|
|
213
|
+
{import.meta.env.VITE_POCKETBASE_URL || 'http://127.0.0.1:8090'}
|
|
214
|
+
</code>
|
|
215
|
+
</p>
|
|
216
|
+
</div>
|
|
217
|
+
</div>
|
|
218
|
+
);
|
|
57
219
|
}
|
|
58
220
|
|
|
59
221
|
return (
|
package/template/package.json
CHANGED