@gzl10/nexus-backend 0.12.4 → 0.12.7
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/README.md +118 -42
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +527 -318
- package/dist/index.js +12667 -9077
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/@gzl10/nexus-backend)
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
6
|
|
|
7
|
-
> **Warning**: This project is
|
|
7
|
+
> **Warning**: This project is in experimental phase. Use at your own risk.
|
|
8
8
|
|
|
9
|
-
Backend as a Service (BaaS) with Express 5, Knex and CASL. Build modular, type-safe backends with authentication, authorization, and real-time features.
|
|
9
|
+
Backend as a Service (BaaS) with Express 5, Knex, and CASL. Build modular, type-safe backends with authentication, authorization, and real-time features.
|
|
10
10
|
|
|
11
|
-
**Repository**: [
|
|
11
|
+
**Repository**: [gitlab.gzl10.com/oss/nexus](https://gitlab.gzl10.com/oss/nexus)
|
|
12
12
|
|
|
13
13
|
## Installation
|
|
14
14
|
|
|
@@ -21,79 +21,155 @@ pnpm add @gzl10/nexus-backend
|
|
|
21
21
|
```typescript
|
|
22
22
|
import { start } from '@gzl10/nexus-backend'
|
|
23
23
|
|
|
24
|
-
start(
|
|
24
|
+
await start({
|
|
25
|
+
port: 3000,
|
|
26
|
+
database: { url: 'file:./data/nexus.db' }
|
|
27
|
+
})
|
|
25
28
|
```
|
|
26
29
|
|
|
27
30
|
## Features
|
|
28
31
|
|
|
32
|
+
### Core Modules
|
|
33
|
+
|
|
34
|
+
| Module | Description |
|
|
35
|
+
| ------ | ----------- |
|
|
36
|
+
| **auth** | JWT authentication with access/refresh tokens, OTP challenge, password reset |
|
|
37
|
+
| **users** | User management with multi-role support |
|
|
38
|
+
| **storage** | File storage (local/S3), thumbnails, deduplication |
|
|
39
|
+
| **mail** | Email sending via SMTP (Nodemailer) |
|
|
40
|
+
| **notifications** | In-app notification system |
|
|
41
|
+
| **schedules** | Scheduled tasks (cron jobs) |
|
|
42
|
+
| **compliance** | GDPR consent tracking, legal documents |
|
|
43
|
+
| **tags** | Tagging system for any entity |
|
|
44
|
+
| **links** | Entity relationships and linking |
|
|
45
|
+
|
|
46
|
+
### Platform Features
|
|
47
|
+
|
|
29
48
|
| Feature | Description |
|
|
30
49
|
| ------- | ----------- |
|
|
31
|
-
| Express 5 | Modern async error handling |
|
|
32
|
-
|
|
|
33
|
-
| CASL | Attribute-based access control |
|
|
34
|
-
|
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
| Rate Limiting | Built-in rate limiting middleware |
|
|
50
|
+
| **Express 5** | Modern async error handling |
|
|
51
|
+
| **Multi-DB** | SQLite, PostgreSQL, MySQL via Knex |
|
|
52
|
+
| **CASL** | Attribute-based access control with multi-role |
|
|
53
|
+
| **Socket.IO** | Real-time events and notifications |
|
|
54
|
+
| **Plugin Architecture** | Extend with custom modules and plugins |
|
|
55
|
+
| **OpenAPI** | Auto-generated API documentation |
|
|
56
|
+
| **Rate Limiting** | Built-in rate limiting middleware |
|
|
39
57
|
|
|
40
58
|
## Configuration
|
|
41
59
|
|
|
42
|
-
|
|
60
|
+
```typescript
|
|
61
|
+
import { start } from '@gzl10/nexus-backend'
|
|
62
|
+
|
|
63
|
+
await start({
|
|
64
|
+
port: 3000,
|
|
65
|
+
host: '0.0.0.0',
|
|
66
|
+
|
|
67
|
+
// Frontend SPA
|
|
68
|
+
ui: {
|
|
69
|
+
enabled: true,
|
|
70
|
+
base: '/',
|
|
71
|
+
path: '../ui/dist'
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
// Custom routes
|
|
75
|
+
beforeRoutes: (app) => {
|
|
76
|
+
app.get('/api/health_custom', (_req, res) => res.json({ ok: true }))
|
|
77
|
+
},
|
|
78
|
+
afterRoutes: (app, serveSPA) => {
|
|
79
|
+
serveSPA('/admin', '../admin/dist')
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
// Event subscriptions
|
|
83
|
+
events: {
|
|
84
|
+
'auth.login': ({ userId }) => console.log('Login:', userId),
|
|
85
|
+
'db.users.created': ({ data }) => console.log('New user:', data.email)
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
// Custom CASL rules
|
|
89
|
+
casl: (user, { can }) => {
|
|
90
|
+
if (user.email.endsWith('@admin.com')) can('manage', 'all')
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
// Lifecycle hooks
|
|
94
|
+
onReady: (app, port, host) => console.log(`Ready at ${host}:${port}`),
|
|
95
|
+
beforeClose: () => console.log('Shutting down...')
|
|
96
|
+
})
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Config Options
|
|
100
|
+
|
|
101
|
+
| Option | Type | Default | Description |
|
|
102
|
+
| ------ | ---- | ------- | ----------- |
|
|
103
|
+
| `port` | `number` | `3000` | Server port |
|
|
104
|
+
| `host` | `string` | `0.0.0.0` | Server host |
|
|
105
|
+
| `ui.enabled` | `boolean` | `true` | Serve frontend SPA |
|
|
106
|
+
| `ui.base` | `string` | `/` | Base path for UI |
|
|
107
|
+
| `ui.path` | `string` | `../ui/dist` | Path to frontend dist |
|
|
108
|
+
| `database.url` | `string` | - | Database connection URL |
|
|
109
|
+
| `plugins` | `PluginManifest[]` | - | Plugins to register |
|
|
110
|
+
| `modules` | `ModuleManifest[]` | - | Standalone modules |
|
|
111
|
+
| `beforeRoutes` | `function` | - | Hook before module routes |
|
|
112
|
+
| `afterRoutes` | `function` | - | Hook after module routes |
|
|
113
|
+
| `events` | `object` | - | Event subscriptions |
|
|
114
|
+
| `casl` | `function` | - | Custom CASL rules |
|
|
115
|
+
| `onReady` | `function` | - | Server ready callback |
|
|
116
|
+
| `beforeClose` | `function` | - | Pre-shutdown callback |
|
|
117
|
+
|
|
118
|
+
### Environment Variables
|
|
43
119
|
|
|
44
120
|
```env
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
DATABASE_URL=file:./data/nexus.db
|
|
48
|
-
JWT_SECRET=your-secret-key
|
|
121
|
+
AUTH_SECRET=your-secret-key-min-32-chars # Required (min 32 chars)
|
|
122
|
+
DATABASE_URL=file:./data/nexus.db # SQLite, PostgreSQL, or MySQL
|
|
49
123
|
```
|
|
50
124
|
|
|
51
|
-
|
|
125
|
+
See `.env.example` for full list of options.
|
|
52
126
|
|
|
53
|
-
|
|
54
|
-
# Start server
|
|
55
|
-
npx nexus start
|
|
127
|
+
## Extending with Plugins
|
|
56
128
|
|
|
57
|
-
|
|
58
|
-
|
|
129
|
+
```typescript
|
|
130
|
+
import { start } from '@gzl10/nexus-backend'
|
|
131
|
+
import { cmsPlugin } from '@gzl10/nexus-plugin-cms'
|
|
132
|
+
import { myCustomModule } from './my-module'
|
|
59
133
|
|
|
60
|
-
|
|
61
|
-
|
|
134
|
+
await start({
|
|
135
|
+
plugins: [cmsPlugin],
|
|
136
|
+
modules: [myCustomModule]
|
|
137
|
+
})
|
|
62
138
|
```
|
|
63
139
|
|
|
64
140
|
## Exported Functions
|
|
65
141
|
|
|
66
142
|
| Function | Description |
|
|
67
143
|
| -------- | ----------- |
|
|
68
|
-
| `start()` | Start the server |
|
|
144
|
+
| `start(config?)` | Start the server |
|
|
69
145
|
| `stop()` | Stop the server |
|
|
70
|
-
| `
|
|
71
|
-
| `
|
|
72
|
-
| `
|
|
73
|
-
| `defineAbilityFor()` | Create CASL abilities |
|
|
74
|
-
| `
|
|
146
|
+
| `restart(config?)` | Restart with new config |
|
|
147
|
+
| `db` | Knex database instance |
|
|
148
|
+
| `nexusEvents` | Event emitter for system events |
|
|
149
|
+
| `defineAbilityFor(user, permissions)` | Create CASL abilities |
|
|
150
|
+
| `getCoreModules()` | Get core modules list |
|
|
151
|
+
| `getUserModules()` | Get user modules list |
|
|
152
|
+
|
|
153
|
+
## CLI
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
npx nexus start # Start server
|
|
157
|
+
npx nexus migrate # Run migrations
|
|
158
|
+
npx nexus seed # Seed database
|
|
159
|
+
```
|
|
75
160
|
|
|
76
161
|
## Development
|
|
77
162
|
|
|
78
163
|
```bash
|
|
79
|
-
pnpm dev # Start dev server
|
|
164
|
+
pnpm dev # Start dev server
|
|
80
165
|
pnpm build # Build for production
|
|
81
|
-
pnpm start # Start production server
|
|
82
166
|
pnpm typecheck # Type check
|
|
83
|
-
pnpm lint # Linting
|
|
84
167
|
pnpm test # Run tests
|
|
85
|
-
pnpm test:coverage # Tests with coverage
|
|
86
168
|
```
|
|
87
169
|
|
|
88
170
|
## Stack
|
|
89
171
|
|
|
90
|
-
|
|
91
|
-
- **Knex** - SQL query builder
|
|
92
|
-
- **CASL** - Authorization
|
|
93
|
-
- **JWT** - Authentication
|
|
94
|
-
- **Socket.IO** - Real-time
|
|
95
|
-
- **Zod** - Validation
|
|
96
|
-
- **Pino** - Logging
|
|
172
|
+
Express 5 | Knex | CASL | JWT | Socket.IO | Zod | Pino
|
|
97
173
|
|
|
98
174
|
## License
|
|
99
175
|
|
package/dist/cli.js
CHANGED
|
@@ -30,7 +30,7 @@ program.command("ui").description("Open UI in browser").option("-p, --port <port
|
|
|
30
30
|
const baseUrl = (process.env["BACKEND_URL"] || `http://localhost:${port}`).replace(/\/$/, "");
|
|
31
31
|
const url = `${baseUrl}/ui`;
|
|
32
32
|
try {
|
|
33
|
-
const res = await fetch(`${baseUrl}/health`);
|
|
33
|
+
const res = await fetch(`${baseUrl}/api/health`);
|
|
34
34
|
if (!res.ok) throw new Error();
|
|
35
35
|
} catch {
|
|
36
36
|
consola.error(`Nexus no est\xE1 corriendo en ${baseUrl}`);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/env-loader.ts","../src/cli.ts"],"sourcesContent":["/**\n *
|
|
1
|
+
{"version":3,"sources":["../src/env-loader.ts","../src/cli.ts"],"sourcesContent":["/**\n * Loads .env before any other project import.\n * This file ONLY imports from node/npm, never from local files.\n */\nimport { existsSync } from 'fs'\nimport { join, dirname } from 'path'\nimport { config } from 'dotenv'\n\nlet dir = process.cwd()\nconsole.log('[env-loader] Starting search from cwd:', dir)\n\nfor (let i = 0; i < 3; i++) {\n const envPath = join(dir, '.env')\n const exists = existsSync(envPath)\n console.log(`[env-loader] Checking: ${envPath}`, exists ? '✓ FOUND' : '✗ not found')\n if (exists) {\n config({ path: envPath })\n console.log('[env-loader] Loaded:', envPath)\n break\n }\n const parent = dirname(dir)\n if (parent === dir) break\n dir = parent\n}\n","#!/usr/bin/env node\nimport './env-loader.js'\nimport { Command } from 'commander'\nimport { consola } from 'consola'\n\nconst program = new Command()\n\nprogram\n .name('nexus')\n .description('Nexus Backend CLI')\n .version('0.1.0')\n\nprogram\n .command('ui')\n .description('Open UI in browser')\n .option('-p, --port <port>', 'Nexus backend port')\n .action(async (options) => {\n const port = parseInt(options.port || process.env['PORT'] || '3000', 10)\n const baseUrl = (process.env['BACKEND_URL'] || `http://localhost:${port}`).replace(/\\/$/, '')\n const url = `${baseUrl}/ui`\n\n // Verificar que Nexus está corriendo\n try {\n const res = await fetch(`${baseUrl}/api/health`)\n if (!res.ok) throw new Error()\n } catch {\n consola.error(`Nexus no está corriendo en ${baseUrl}`)\n consola.info('Inicia el servidor primero con: pnpm dev')\n process.exit(1)\n }\n\n // Abrir navegador\n const { exec } = await import('child_process')\n const cmd = process.platform === 'darwin' ? 'open'\n : process.platform === 'win32' ? 'start'\n : 'xdg-open'\n\n exec(`${cmd} ${url}`)\n consola.success(`Abriendo: ${url}`)\n })\n\nprogram.parse()\n"],"mappings":";;;AAIA,SAAS,kBAAkB;AAC3B,SAAS,MAAM,eAAe;AAC9B,SAAS,cAAc;AAEvB,IAAI,MAAM,QAAQ,IAAI;AACtB,QAAQ,IAAI,0CAA0C,GAAG;AAEzD,SAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,QAAM,UAAU,KAAK,KAAK,MAAM;AAChC,QAAM,SAAS,WAAW,OAAO;AACjC,UAAQ,IAAI,0BAA0B,OAAO,IAAI,SAAS,iBAAY,kBAAa;AACnF,MAAI,QAAQ;AACV,WAAO,EAAE,MAAM,QAAQ,CAAC;AACxB,YAAQ,IAAI,wBAAwB,OAAO;AAC3C;AAAA,EACF;AACA,QAAM,SAAS,QAAQ,GAAG;AAC1B,MAAI,WAAW,IAAK;AACpB,QAAM;AACR;;;ACrBA,SAAS,eAAe;AACxB,SAAS,eAAe;AAExB,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,OAAO,EACZ,YAAY,mBAAmB,EAC/B,QAAQ,OAAO;AAElB,QACG,QAAQ,IAAI,EACZ,YAAY,oBAAoB,EAChC,OAAO,qBAAqB,oBAAoB,EAChD,OAAO,OAAO,YAAY;AACzB,QAAM,OAAO,SAAS,QAAQ,QAAQ,QAAQ,IAAI,MAAM,KAAK,QAAQ,EAAE;AACvE,QAAM,WAAW,QAAQ,IAAI,aAAa,KAAK,oBAAoB,IAAI,IAAI,QAAQ,OAAO,EAAE;AAC5F,QAAM,MAAM,GAAG,OAAO;AAGtB,MAAI;AACF,UAAM,MAAM,MAAM,MAAM,GAAG,OAAO,aAAa;AAC/C,QAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM;AAAA,EAC/B,QAAQ;AACN,YAAQ,MAAM,iCAA8B,OAAO,EAAE;AACrD,YAAQ,KAAK,0CAA0C;AACvD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,EAAE,KAAK,IAAI,MAAM,OAAO,eAAe;AAC7C,QAAM,MAAM,QAAQ,aAAa,WAAW,SAChC,QAAQ,aAAa,UAAU,UAC/B;AAEZ,OAAK,GAAG,GAAG,IAAI,GAAG,EAAE;AACpB,UAAQ,QAAQ,aAAa,GAAG,EAAE;AACpC,CAAC;AAEH,QAAQ,MAAM;","names":[]}
|