@qwickapps/server 1.0.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/LICENSE +45 -0
- package/README.md +321 -0
- package/dist/core/control-panel.d.ts +21 -0
- package/dist/core/control-panel.d.ts.map +1 -0
- package/dist/core/control-panel.js +416 -0
- package/dist/core/control-panel.js.map +1 -0
- package/dist/core/gateway.d.ts +133 -0
- package/dist/core/gateway.d.ts.map +1 -0
- package/dist/core/gateway.js +270 -0
- package/dist/core/gateway.js.map +1 -0
- package/dist/core/health-manager.d.ts +52 -0
- package/dist/core/health-manager.d.ts.map +1 -0
- package/dist/core/health-manager.js +192 -0
- package/dist/core/health-manager.js.map +1 -0
- package/dist/core/index.d.ts +10 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +8 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/logging.d.ts +83 -0
- package/dist/core/logging.d.ts.map +1 -0
- package/dist/core/logging.js +191 -0
- package/dist/core/logging.js.map +1 -0
- package/dist/core/types.d.ts +195 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +7 -0
- package/dist/core/types.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/config-plugin.d.ts +15 -0
- package/dist/plugins/config-plugin.d.ts.map +1 -0
- package/dist/plugins/config-plugin.js +96 -0
- package/dist/plugins/config-plugin.js.map +1 -0
- package/dist/plugins/diagnostics-plugin.d.ts +29 -0
- package/dist/plugins/diagnostics-plugin.d.ts.map +1 -0
- package/dist/plugins/diagnostics-plugin.js +142 -0
- package/dist/plugins/diagnostics-plugin.js.map +1 -0
- package/dist/plugins/health-plugin.d.ts +17 -0
- package/dist/plugins/health-plugin.d.ts.map +1 -0
- package/dist/plugins/health-plugin.js +25 -0
- package/dist/plugins/health-plugin.js.map +1 -0
- package/dist/plugins/index.d.ts +14 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +10 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/logs-plugin.d.ts +22 -0
- package/dist/plugins/logs-plugin.d.ts.map +1 -0
- package/dist/plugins/logs-plugin.js +242 -0
- package/dist/plugins/logs-plugin.js.map +1 -0
- package/dist-ui/assets/index-Bk7ypbI4.js +465 -0
- package/dist-ui/assets/index-Bk7ypbI4.js.map +1 -0
- package/dist-ui/assets/index-CiizQQnb.css +1 -0
- package/dist-ui/index.html +13 -0
- package/package.json +98 -0
- package/src/core/control-panel.ts +493 -0
- package/src/core/gateway.ts +421 -0
- package/src/core/health-manager.ts +227 -0
- package/src/core/index.ts +25 -0
- package/src/core/logging.ts +234 -0
- package/src/core/types.ts +218 -0
- package/src/index.ts +55 -0
- package/src/plugins/config-plugin.ts +117 -0
- package/src/plugins/diagnostics-plugin.ts +178 -0
- package/src/plugins/health-plugin.ts +35 -0
- package/src/plugins/index.ts +17 -0
- package/src/plugins/logs-plugin.ts +314 -0
- package/ui/index.html +12 -0
- package/ui/src/App.tsx +65 -0
- package/ui/src/api/controlPanelApi.ts +148 -0
- package/ui/src/config/AppConfig.ts +18 -0
- package/ui/src/index.css +29 -0
- package/ui/src/index.tsx +11 -0
- package/ui/src/pages/ConfigPage.tsx +199 -0
- package/ui/src/pages/DashboardPage.tsx +264 -0
- package/ui/src/pages/DiagnosticsPage.tsx +315 -0
- package/ui/src/pages/HealthPage.tsx +204 -0
- package/ui/src/pages/LogsPage.tsx +267 -0
- package/ui/src/pages/NotFoundPage.tsx +41 -0
- package/ui/tsconfig.json +19 -0
- package/ui/vite.config.ts +21 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# QwickApps Control Panel License
|
|
2
|
+
|
|
3
|
+
This software is licensed under the **PolyForm Shield License 1.0.0**.
|
|
4
|
+
|
|
5
|
+
## Summary
|
|
6
|
+
|
|
7
|
+
- **Free to use** for non-competitive purposes
|
|
8
|
+
- **Source code available** for learning and development
|
|
9
|
+
- **Cannot be used** to compete with QwickApps
|
|
10
|
+
- **Cannot be reverse engineered** for competitive purposes
|
|
11
|
+
- **Cannot be redistributed** in competitive products
|
|
12
|
+
|
|
13
|
+
## Full License Text
|
|
14
|
+
|
|
15
|
+
See https://polyformproject.org/licenses/shield/1.0.0/ for complete terms.
|
|
16
|
+
|
|
17
|
+
## What This Means
|
|
18
|
+
|
|
19
|
+
### Permitted Uses:
|
|
20
|
+
- Internal business applications
|
|
21
|
+
- Learning and educational projects
|
|
22
|
+
- Non-competitive commercial applications
|
|
23
|
+
- Academic research and teaching
|
|
24
|
+
- Contributing to this project
|
|
25
|
+
- Building applications that use this control panel framework
|
|
26
|
+
|
|
27
|
+
### Prohibited Uses:
|
|
28
|
+
- Creating competing control panel frameworks
|
|
29
|
+
- Building competing developer tools or dashboards
|
|
30
|
+
- Reselling or redistributing as a competing product
|
|
31
|
+
- Reverse engineering to create competitive products
|
|
32
|
+
|
|
33
|
+
## Commercial Licensing
|
|
34
|
+
|
|
35
|
+
If your use case might be competitive or you need different terms, contact us at **legal@qwickapps.com** for commercial licensing options.
|
|
36
|
+
|
|
37
|
+
## Questions?
|
|
38
|
+
|
|
39
|
+
- Email: legal@qwickapps.com
|
|
40
|
+
- Website: https://qwickapps.com
|
|
41
|
+
- Repository: https://github.com/qwickapps/qwickapps
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
Copyright (c) 2025 QwickApps. All rights reserved.
|
package/README.md
ADDED
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
# @qwickapps/server
|
|
2
|
+
|
|
3
|
+
A flexible, pluggable control panel framework for QwickApps services. Provides a web-based dashboard with authentication, health monitoring, and extensible plugin architecture.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Gateway Pattern**: Production-ready gateway that proxies API requests while keeping control panel always responsive
|
|
8
|
+
- **Authentication**: Support for multiple auth providers (Supabase OAuth, Basic Auth, JWT, Custom)
|
|
9
|
+
- **Localhost Bypass**: Automatic auth bypass for local development
|
|
10
|
+
- **Plugin System**: Extensible architecture for adding custom functionality
|
|
11
|
+
- **Health Monitoring**: Built-in health check management with customizable checks
|
|
12
|
+
- **Theming**: Customizable branding and styling
|
|
13
|
+
- **Proxy Support**: Skip body parsing for specific paths to enable proxy middleware
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm add @qwickapps/server
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { createControlPanel, createHealthPlugin } from '@qwickapps/server';
|
|
25
|
+
|
|
26
|
+
const controlPanel = createControlPanel({
|
|
27
|
+
config: {
|
|
28
|
+
productName: 'My Service',
|
|
29
|
+
port: 3101,
|
|
30
|
+
version: '1.0.0',
|
|
31
|
+
auth: {
|
|
32
|
+
enabled: true,
|
|
33
|
+
provider: 'supabase',
|
|
34
|
+
skipAuthForLocalhost: true,
|
|
35
|
+
supabase: {
|
|
36
|
+
url: process.env.SUPABASE_URL!,
|
|
37
|
+
anonKey: process.env.SUPABASE_ANON_KEY!,
|
|
38
|
+
provider: 'google',
|
|
39
|
+
allowedEmails: ['admin@example.com'],
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
plugins: [
|
|
44
|
+
createHealthPlugin({
|
|
45
|
+
checks: [
|
|
46
|
+
{
|
|
47
|
+
name: 'database',
|
|
48
|
+
type: 'http',
|
|
49
|
+
url: 'http://localhost:5432/health',
|
|
50
|
+
interval: 10000,
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
}),
|
|
54
|
+
],
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
await controlPanel.start();
|
|
58
|
+
console.log(`Control panel running at http://localhost:3101`);
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Gateway Pattern
|
|
62
|
+
|
|
63
|
+
For production deployments, use `createGateway` to run a gateway that:
|
|
64
|
+
1. Serves the control panel UI (always responsive, even if the API crashes)
|
|
65
|
+
2. Proxies API requests to an internal service
|
|
66
|
+
3. Handles graceful error responses when the internal service is down
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { createGateway, createHealthPlugin } from '@qwickapps/server';
|
|
70
|
+
import { createApp } from './app.js';
|
|
71
|
+
|
|
72
|
+
const gateway = createGateway(
|
|
73
|
+
{
|
|
74
|
+
productName: 'My Service',
|
|
75
|
+
gatewayPort: 3101, // Public port (control panel)
|
|
76
|
+
servicePort: 3100, // Internal port (API)
|
|
77
|
+
authMode: 'basic',
|
|
78
|
+
basicAuthUser: 'admin',
|
|
79
|
+
basicAuthPassword: process.env.ADMIN_PASSWORD,
|
|
80
|
+
proxyPaths: ['/api/v1'],
|
|
81
|
+
plugins: [
|
|
82
|
+
createHealthPlugin({
|
|
83
|
+
checks: [
|
|
84
|
+
{ name: 'api', type: 'http', url: 'http://localhost:3100/health' },
|
|
85
|
+
],
|
|
86
|
+
}),
|
|
87
|
+
],
|
|
88
|
+
},
|
|
89
|
+
// Service factory - creates the internal API service
|
|
90
|
+
async (port) => {
|
|
91
|
+
const app = createApp();
|
|
92
|
+
const server = app.listen(port);
|
|
93
|
+
return {
|
|
94
|
+
app,
|
|
95
|
+
server,
|
|
96
|
+
shutdown: async () => { server.close(); },
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
await gateway.start();
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Gateway Architecture
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
Internet → Gateway (3101, public) → API Service (3100, internal)
|
|
108
|
+
↓
|
|
109
|
+
Control Panel UI
|
|
110
|
+
/api/health
|
|
111
|
+
/api/diagnostics
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The gateway is always responsive even if the internal API service crashes, allowing you to view diagnostics and error information.
|
|
115
|
+
|
|
116
|
+
## Configuration
|
|
117
|
+
|
|
118
|
+
### ControlPanelConfig
|
|
119
|
+
|
|
120
|
+
| Property | Type | Required | Description |
|
|
121
|
+
|----------|------|----------|-------------|
|
|
122
|
+
| `productName` | `string` | Yes | Name displayed in the dashboard |
|
|
123
|
+
| `port` | `number` | Yes | Port to run the control panel on |
|
|
124
|
+
| `version` | `string` | No | Product version to display |
|
|
125
|
+
| `branding` | `object` | No | Logo, primary color, favicon |
|
|
126
|
+
| `auth` | `AuthConfig` | No | Authentication configuration |
|
|
127
|
+
| `cors` | `object` | No | CORS origins configuration |
|
|
128
|
+
| `links` | `array` | No | Quick links for the dashboard |
|
|
129
|
+
| `skipBodyParserPaths` | `string[]` | No | Paths to skip body parsing (for proxy) |
|
|
130
|
+
|
|
131
|
+
### Authentication Providers
|
|
132
|
+
|
|
133
|
+
#### Supabase OAuth (Recommended)
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
auth: {
|
|
137
|
+
enabled: true,
|
|
138
|
+
provider: 'supabase',
|
|
139
|
+
skipAuthForLocalhost: true,
|
|
140
|
+
supabase: {
|
|
141
|
+
url: 'https://xxx.supabase.co',
|
|
142
|
+
anonKey: 'your-anon-key',
|
|
143
|
+
provider: 'google', // or 'github', 'azure', 'gitlab'
|
|
144
|
+
allowedEmails: ['admin@company.com'], // Optional whitelist
|
|
145
|
+
redirectUrl: '/auth/callback', // Default
|
|
146
|
+
},
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
#### Basic Auth
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
auth: {
|
|
154
|
+
enabled: true,
|
|
155
|
+
provider: 'basic',
|
|
156
|
+
users: [
|
|
157
|
+
{ username: 'admin', password: 'secret' },
|
|
158
|
+
],
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
#### Custom Middleware
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
auth: {
|
|
166
|
+
enabled: true,
|
|
167
|
+
provider: 'custom',
|
|
168
|
+
customMiddleware: (req, res, next) => {
|
|
169
|
+
// Your auth logic
|
|
170
|
+
next();
|
|
171
|
+
},
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Localhost Bypass
|
|
176
|
+
|
|
177
|
+
When `skipAuthForLocalhost` is `true` (default), requests from `localhost` or `127.0.0.1` skip authentication. This is useful for local development.
|
|
178
|
+
|
|
179
|
+
### Proxy Support
|
|
180
|
+
|
|
181
|
+
When using the control panel as a gateway with proxy middleware, configure `skipBodyParserPaths` to prevent body parsing from consuming the request body:
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
config: {
|
|
185
|
+
// ... other config
|
|
186
|
+
skipBodyParserPaths: ['/api/v1', '/health'],
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Then add proxy middleware
|
|
190
|
+
controlPanel.app.use(createProxyMiddleware({
|
|
191
|
+
target: 'http://localhost:3100',
|
|
192
|
+
pathFilter: '/api/v1/**',
|
|
193
|
+
}));
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Plugins
|
|
197
|
+
|
|
198
|
+
### Built-in Plugins
|
|
199
|
+
|
|
200
|
+
#### Health Plugin
|
|
201
|
+
|
|
202
|
+
Monitors service health with configurable checks:
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
import { createHealthPlugin } from '@qwickapps/server';
|
|
206
|
+
|
|
207
|
+
createHealthPlugin({
|
|
208
|
+
checks: [
|
|
209
|
+
{
|
|
210
|
+
name: 'api',
|
|
211
|
+
type: 'http',
|
|
212
|
+
url: 'http://localhost:3000/health',
|
|
213
|
+
interval: 10000,
|
|
214
|
+
timeout: 5000,
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
name: 'custom',
|
|
218
|
+
type: 'custom',
|
|
219
|
+
check: async () => ({
|
|
220
|
+
status: 'healthy',
|
|
221
|
+
details: { message: 'All good' },
|
|
222
|
+
}),
|
|
223
|
+
interval: 30000,
|
|
224
|
+
},
|
|
225
|
+
],
|
|
226
|
+
});
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Creating Custom Plugins
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
import type { ControlPanelPlugin, PluginContext } from '@qwickapps/server';
|
|
233
|
+
|
|
234
|
+
const myPlugin: ControlPanelPlugin = {
|
|
235
|
+
name: 'my-plugin',
|
|
236
|
+
order: 10,
|
|
237
|
+
routes: [
|
|
238
|
+
{
|
|
239
|
+
method: 'get',
|
|
240
|
+
path: '/my-plugin/status',
|
|
241
|
+
handler: async (req, res) => {
|
|
242
|
+
res.json({ status: 'ok' });
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
],
|
|
246
|
+
initialize: async (context: PluginContext) => {
|
|
247
|
+
context.logger.info('My plugin initialized');
|
|
248
|
+
},
|
|
249
|
+
shutdown: async () => {
|
|
250
|
+
// Cleanup
|
|
251
|
+
},
|
|
252
|
+
};
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## API Reference
|
|
256
|
+
|
|
257
|
+
### createControlPanel(options)
|
|
258
|
+
|
|
259
|
+
Creates a new control panel instance.
|
|
260
|
+
|
|
261
|
+
**Returns**: `ControlPanelInstance`
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
interface ControlPanelInstance {
|
|
265
|
+
app: Express.Application;
|
|
266
|
+
start: () => Promise<void>;
|
|
267
|
+
stop: () => Promise<void>;
|
|
268
|
+
registerPlugin: (plugin: ControlPanelPlugin) => void;
|
|
269
|
+
getHealthStatus: () => Promise<HealthStatus>;
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Built-in Routes
|
|
274
|
+
|
|
275
|
+
| Route | Method | Description |
|
|
276
|
+
|-------|--------|-------------|
|
|
277
|
+
| `/` | GET | Dashboard UI |
|
|
278
|
+
| `/auth/login` | GET | OAuth login page (Supabase) |
|
|
279
|
+
| `/auth/callback` | GET | OAuth callback handler |
|
|
280
|
+
| `/auth/logout` | GET | Logout and clear session |
|
|
281
|
+
| `/api/health` | GET | Aggregated health status |
|
|
282
|
+
| `/api/diagnostics` | GET | System diagnostics |
|
|
283
|
+
|
|
284
|
+
## Environment Variables
|
|
285
|
+
|
|
286
|
+
```env
|
|
287
|
+
# Supabase OAuth
|
|
288
|
+
SUPABASE_URL=https://xxx.supabase.co
|
|
289
|
+
SUPABASE_ANON_KEY=your-anon-key
|
|
290
|
+
ALLOWED_EMAILS=admin@example.com,user@example.com
|
|
291
|
+
|
|
292
|
+
# Development
|
|
293
|
+
SKIP_AUTH_LOCALHOST=true
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## License
|
|
297
|
+
|
|
298
|
+
This software is licensed under the **PolyForm Shield License 1.0.0**.
|
|
299
|
+
|
|
300
|
+
### What This Means
|
|
301
|
+
|
|
302
|
+
**Permitted Uses:**
|
|
303
|
+
- Internal business applications
|
|
304
|
+
- Learning and educational projects
|
|
305
|
+
- Non-competitive commercial applications
|
|
306
|
+
- Academic research and teaching
|
|
307
|
+
- Building applications that use this control panel framework
|
|
308
|
+
|
|
309
|
+
**Prohibited Uses:**
|
|
310
|
+
- Creating competing control panel frameworks
|
|
311
|
+
- Building competing developer tools or dashboards
|
|
312
|
+
- Reselling or redistributing as a competing product
|
|
313
|
+
- Reverse engineering to create competitive products
|
|
314
|
+
|
|
315
|
+
For full license terms, see [PolyForm Shield 1.0.0](https://polyformproject.org/licenses/shield/1.0.0/).
|
|
316
|
+
|
|
317
|
+
For commercial licensing options, contact **legal@qwickapps.com**.
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
Copyright (c) 2025 QwickApps. All rights reserved.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Control Panel Core
|
|
3
|
+
*
|
|
4
|
+
* Creates and manages the control panel Express application
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
7
|
+
*/
|
|
8
|
+
import { type LoggingConfig } from './logging.js';
|
|
9
|
+
import type { ControlPanelConfig, ControlPanelPlugin, ControlPanelInstance, Logger } from './types.js';
|
|
10
|
+
export interface CreateControlPanelOptions {
|
|
11
|
+
config: ControlPanelConfig;
|
|
12
|
+
plugins?: ControlPanelPlugin[];
|
|
13
|
+
logger?: Logger;
|
|
14
|
+
/** Logging configuration */
|
|
15
|
+
logging?: LoggingConfig;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Create a control panel instance
|
|
19
|
+
*/
|
|
20
|
+
export declare function createControlPanel(options: CreateControlPanelOptions): ControlPanelInstance;
|
|
21
|
+
//# sourceMappingURL=control-panel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"control-panel.d.ts","sourceRoot":"","sources":["../../src/core/control-panel.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,OAAO,EAAiE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AACjH,OAAO,KAAK,EACV,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EAIpB,MAAM,EACP,MAAM,YAAY,CAAC;AAWpB,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,oBAAoB,CA0R3F"}
|