navis.js 5.0.0 → 5.2.1

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 CHANGED
@@ -129,7 +129,7 @@ navis metrics
129
129
  - ✅ **Rate limiting** - In-memory rate limiting with configurable windows
130
130
  - ✅ **Enhanced error handling** - Custom error classes and error handler middleware
131
131
 
132
- ### v5 (Current)
132
+ ### v5
133
133
 
134
134
  - ✅ **Caching layer** - In-memory cache with TTL and Redis adapter
135
135
  - ✅ **CORS support** - Cross-Origin Resource Sharing middleware
@@ -138,6 +138,19 @@ navis metrics
138
138
  - ✅ **Health checks** - Liveness and readiness probes
139
139
  - ✅ **Graceful shutdown** - Clean shutdown handling
140
140
 
141
+ ### v5.1 (Current)
142
+
143
+ - ✅ **OpenAPI/Swagger** - Auto-generate API documentation
144
+ - ✅ **API versioning** - URL-based and header-based versioning
145
+ - ✅ **File upload** - Multipart form data handling
146
+ - ✅ **Testing utilities** - Test helpers for applications
147
+
148
+ ### v5.2 (Current)
149
+
150
+ - ✅ **WebSocket support** - Real-time bidirectional communication
151
+ - ✅ **Server-Sent Events** - One-way real-time streaming
152
+ - ✅ **Database integration** - Connection pooling for PostgreSQL, MySQL, MongoDB
153
+
141
154
  ## API Reference
142
155
 
143
156
  ### NavisApp
@@ -342,15 +355,23 @@ Advanced features: async messaging (SQS/Kafka/NATS), observability, enhanced CLI
342
355
  ### v4 ✅
343
356
  Production-ready: advanced routing, validation, authentication, rate limiting, error handling
344
357
 
345
- ### v5 ✅ (Current)
358
+ ### v5 ✅
346
359
  Enterprise-grade: caching, CORS, security headers, compression, health checks, graceful shutdown
347
360
 
361
+ ### v5.1 ✅ (Current)
362
+ Developer experience: OpenAPI/Swagger, API versioning, file upload, testing utilities
363
+
364
+ ### v5.2 ✅ (Current)
365
+ Real-time features: WebSocket, Server-Sent Events, database integration
366
+
348
367
  ## Documentation
349
368
 
350
369
  - [V2 Features Guide](./V2_FEATURES.md) - Complete v2 features documentation
351
370
  - [V3 Features Guide](./V3_FEATURES.md) - Complete v3 features documentation
352
371
  - [V4 Features Guide](./V4_FEATURES.md) - Complete v4 features documentation
353
372
  - [V5 Features Guide](./V5_FEATURES.md) - Complete v5 features documentation
373
+ - [V5.1 Features Guide](./V5.1_FEATURES.md) - Complete v5.1 features documentation
374
+ - [V5.2 Features Guide](./V5.2_FEATURES.md) - Complete v5.2 features documentation
354
375
  - [Lambda Optimization Guide](./LAMBDA_OPTIMIZATION.md) - Lambda cold start optimization guide (v3.1)
355
376
  - [Verification Guide v2](./VERIFY_V2.md) - How to verify v2 features
356
377
  - [Verification Guide v3](./VERIFY_V3.md) - How to verify v3 features
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Navis.js v5.1 Features Demo
3
+ * Demonstrates OpenAPI/Swagger, API versioning, file upload, and testing utilities
4
+ */
5
+
6
+ const {
7
+ NavisApp,
8
+ response,
9
+ swagger,
10
+ createVersionManager,
11
+ headerVersioning,
12
+ upload,
13
+ testApp,
14
+ } = require('../src/index');
15
+
16
+ const app = new NavisApp();
17
+
18
+ // ============================================
19
+ // OpenAPI/Swagger Documentation
20
+ // ============================================
21
+ const swaggerMiddleware = swagger({
22
+ title: 'Navis.js API',
23
+ version: '5.1.0',
24
+ description: 'API documentation for Navis.js',
25
+ path: '/swagger.json',
26
+ uiPath: '/docs',
27
+ servers: [{ url: 'http://localhost:3000', description: 'Development server' }],
28
+ tags: [
29
+ { name: 'users', description: 'User operations' },
30
+ { name: 'posts', description: 'Post operations' },
31
+ ],
32
+ });
33
+
34
+ app.use(swaggerMiddleware.middleware);
35
+
36
+ // Add routes to Swagger
37
+ swaggerMiddleware.generator.addRoute('GET', '/users/:id', {
38
+ summary: 'Get user by ID',
39
+ description: 'Retrieve a user by their ID',
40
+ tags: ['users'],
41
+ parameters: [
42
+ {
43
+ name: 'id',
44
+ in: 'path',
45
+ required: true,
46
+ schema: { type: 'string' },
47
+ },
48
+ ],
49
+ responses: {
50
+ '200': {
51
+ description: 'User found',
52
+ content: {
53
+ 'application/json': {
54
+ schema: {
55
+ type: 'object',
56
+ properties: {
57
+ id: { type: 'string' },
58
+ name: { type: 'string' },
59
+ },
60
+ },
61
+ },
62
+ },
63
+ },
64
+ '404': { description: 'User not found' },
65
+ },
66
+ });
67
+
68
+ // ============================================
69
+ // API Versioning
70
+ // ============================================
71
+ const versionManager = createVersionManager();
72
+
73
+ // Version 1
74
+ const v1 = versionManager.version('v1');
75
+ v1.get('/users/:id', (req, res) => {
76
+ response.success(res, {
77
+ version: 'v1',
78
+ userId: req.params.id,
79
+ format: 'legacy',
80
+ });
81
+ });
82
+
83
+ // Version 2
84
+ const v2 = versionManager.version('v2');
85
+ v2.get('/users/:id', (req, res) => {
86
+ response.success(res, {
87
+ version: 'v2',
88
+ userId: req.params.id,
89
+ format: 'modern',
90
+ metadata: { source: 'v2-api' },
91
+ });
92
+ });
93
+
94
+ // Register versioned routes
95
+ v1.get('/users/:id', (req, res) => {
96
+ response.success(res, { version: 'v1', userId: req.params.id });
97
+ });
98
+ v2.get('/users/:id', (req, res) => {
99
+ response.success(res, { version: 'v2', userId: req.params.id });
100
+ });
101
+
102
+ // Apply versioned routes to app
103
+ for (const version of versionManager.getVersions()) {
104
+ const routes = versionManager.getRoutes(version);
105
+ for (const method in routes) {
106
+ for (const route of routes[method]) {
107
+ app[method.toLowerCase()](route.path, route.handler);
108
+ }
109
+ }
110
+ }
111
+
112
+ // Header-based versioning
113
+ app.use(headerVersioning({
114
+ header: 'X-API-Version',
115
+ defaultVersion: 'v1',
116
+ }));
117
+
118
+ // ============================================
119
+ // File Upload
120
+ // ============================================
121
+ app.post('/upload', upload({
122
+ dest: './uploads',
123
+ limits: {
124
+ fileSize: 5 * 1024 * 1024, // 5MB
125
+ files: 5,
126
+ },
127
+ fileFilter: (file) => {
128
+ // Allow images and PDFs
129
+ return file.mimetype.startsWith('image/') || file.mimetype === 'application/pdf';
130
+ },
131
+ }), (req, res) => {
132
+ response.success(res, {
133
+ message: 'Files uploaded',
134
+ files: req.files || [],
135
+ fields: req.body,
136
+ });
137
+ });
138
+
139
+ // ============================================
140
+ // Routes
141
+ // ============================================
142
+ app.get('/', (req, res) => {
143
+ response.success(res, {
144
+ message: 'Navis.js v5.1 Features Demo',
145
+ features: [
146
+ 'OpenAPI/Swagger Documentation',
147
+ 'API Versioning',
148
+ 'File Upload',
149
+ 'Testing Utilities',
150
+ ],
151
+ endpoints: {
152
+ swagger: '/swagger.json',
153
+ docs: '/docs',
154
+ v1: '/v1/users/:id',
155
+ v2: '/v2/users/:id',
156
+ upload: 'POST /upload',
157
+ },
158
+ });
159
+ });
160
+
161
+ app.get('/users/:id', (req, res) => {
162
+ response.success(res, {
163
+ userId: req.params.id,
164
+ version: req.apiVersion || 'default',
165
+ });
166
+ });
167
+
168
+ // ============================================
169
+ // Start Server
170
+ // ============================================
171
+ const PORT = 3000;
172
+ app.listen(PORT, () => {
173
+ console.log(`\n🚀 Navis.js v5.1 Features Demo Server`);
174
+ console.log(`📡 Listening on http://localhost:${PORT}\n`);
175
+ console.log('Available endpoints:');
176
+ console.log(' GET /');
177
+ console.log(' GET /swagger.json (OpenAPI spec)');
178
+ console.log(' GET /docs (Swagger UI)');
179
+ console.log(' GET /v1/users/:id (API v1)');
180
+ console.log(' GET /v2/users/:id (API v2)');
181
+ console.log(' GET /users/:id (with X-API-Version header)');
182
+ console.log(' POST /upload (file upload)');
183
+ console.log('\n💡 Test with:');
184
+ console.log(' curl http://localhost:3000/');
185
+ console.log(' curl http://localhost:3000/v1/users/123');
186
+ console.log(' curl http://localhost:3000/v2/users/123');
187
+ console.log(' curl -H "X-API-Version: v2" http://localhost:3000/users/123');
188
+ console.log(' curl http://localhost:3000/swagger.json');
189
+ });
190
+
191
+ module.exports = app;
192
+
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Navis.js v5.2 Features Demo
3
+ * Demonstrates WebSocket, Server-Sent Events, and database integration
4
+ */
5
+
6
+ const {
7
+ NavisApp,
8
+ response,
9
+ WebSocketServer,
10
+ sse,
11
+ createPool,
12
+ } = require('../src/index');
13
+
14
+ const app = new NavisApp();
15
+
16
+ // ============================================
17
+ // Server-Sent Events (SSE)
18
+ // ============================================
19
+ app.get('/events', sse(), (req, res) => {
20
+ // Send initial event
21
+ res.sse.send({ message: 'Connected to SSE stream' }, 'connection');
22
+
23
+ // Send periodic updates
24
+ let count = 0;
25
+ const interval = setInterval(() => {
26
+ count++;
27
+ res.sse.send({
28
+ timestamp: new Date().toISOString(),
29
+ count,
30
+ data: `Event ${count}`,
31
+ }, 'update');
32
+
33
+ // Close after 10 events
34
+ if (count >= 10) {
35
+ clearInterval(interval);
36
+ res.sse.send({ message: 'Stream ended' }, 'close');
37
+ setTimeout(() => res.sse.close(), 1000);
38
+ }
39
+ }, 1000);
40
+
41
+ // Cleanup on disconnect
42
+ req.on('close', () => {
43
+ clearInterval(interval);
44
+ });
45
+ });
46
+
47
+ // ============================================
48
+ // Database Integration (Example)
49
+ // ============================================
50
+ // Note: Requires database packages (pg, mysql2, or mongodb)
51
+ let dbPool = null;
52
+
53
+ // Initialize database pool (commented out - requires actual DB)
54
+ // dbPool = createPool({
55
+ // type: 'postgres',
56
+ // connectionString: process.env.DATABASE_URL,
57
+ // });
58
+
59
+ // Example route using database
60
+ app.get('/db-example', async (req, res) => {
61
+ if (!dbPool) {
62
+ response.success(res, {
63
+ message: 'Database not configured',
64
+ note: 'Set DATABASE_URL and install database package (pg, mysql2, or mongodb)',
65
+ });
66
+ return;
67
+ }
68
+
69
+ try {
70
+ // Example query
71
+ const result = await dbPool.query('SELECT NOW() as current_time');
72
+ response.success(res, result);
73
+ } catch (error) {
74
+ response.error(res, error.message, 500);
75
+ }
76
+ });
77
+
78
+ // ============================================
79
+ // Routes
80
+ // ============================================
81
+ app.get('/', (req, res) => {
82
+ response.success(res, {
83
+ message: 'Navis.js v5.2 Features Demo',
84
+ features: [
85
+ 'WebSocket Support',
86
+ 'Server-Sent Events (SSE)',
87
+ 'Database Integration',
88
+ ],
89
+ endpoints: {
90
+ sse: 'GET /events (SSE stream)',
91
+ websocket: 'WS /ws (WebSocket)',
92
+ db: 'GET /db-example',
93
+ },
94
+ });
95
+ });
96
+
97
+ // ============================================
98
+ // Start Server
99
+ // ============================================
100
+ const PORT = 3000;
101
+ const server = app.listen(PORT, () => {
102
+ console.log(`\n🚀 Navis.js v5.2 Features Demo Server`);
103
+ console.log(`📡 Listening on http://localhost:${PORT}\n`);
104
+ console.log('Available endpoints:');
105
+ console.log(' GET /');
106
+ console.log(' GET /events (SSE stream)');
107
+ console.log(' WS /ws (WebSocket)');
108
+ console.log(' GET /db-example');
109
+ console.log('\n💡 Test with:');
110
+ console.log(' curl http://localhost:3000/');
111
+ console.log(' curl -N http://localhost:3000/events');
112
+ console.log(' wscat -c ws://localhost:3000/ws');
113
+ });
114
+
115
+ // ============================================
116
+ // WebSocket Server
117
+ // ============================================
118
+ const wsServer = new WebSocketServer({
119
+ path: '/ws',
120
+ });
121
+
122
+ wsServer.attach(server);
123
+
124
+ wsServer.onConnection((client) => {
125
+ console.log(`WebSocket client connected: ${client.id}`);
126
+ client.send({ type: 'welcome', message: 'Connected to WebSocket server' });
127
+ });
128
+
129
+ wsServer.on('*', (message, client) => {
130
+ console.log(`Message from ${client.id}:`, message);
131
+
132
+ // Echo message back
133
+ client.send({
134
+ type: 'echo',
135
+ original: message,
136
+ timestamp: new Date().toISOString(),
137
+ });
138
+ });
139
+
140
+ wsServer.onDisconnection((client) => {
141
+ console.log(`WebSocket client disconnected: ${client.id}`);
142
+ });
143
+
144
+ // Cleanup on shutdown
145
+ process.on('SIGTERM', async () => {
146
+ if (dbPool) {
147
+ await dbPool.close();
148
+ }
149
+ process.exit(0);
150
+ });
151
+
152
+ module.exports = app;
153
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "navis.js",
3
- "version": "5.0.0",
3
+ "version": "5.2.1",
4
4
  "description": "A lightweight, serverless-first, microservice API framework designed for AWS Lambda and Node.js",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -0,0 +1,124 @@
1
+ /**
2
+ * API Versioning
3
+ * v5.1: URL-based and header-based API versioning
4
+ */
5
+
6
+ class VersionManager {
7
+ constructor() {
8
+ this.versions = new Map();
9
+ this.defaultVersion = null;
10
+ }
11
+
12
+ /**
13
+ * Create a version router
14
+ * @param {string} version - Version identifier (e.g., 'v1', 'v2')
15
+ * @returns {Object} - Version router with route methods
16
+ */
17
+ version(version) {
18
+ if (!this.versions.has(version)) {
19
+ const router = {
20
+ version,
21
+ routes: {
22
+ GET: [],
23
+ POST: [],
24
+ PUT: [],
25
+ DELETE: [],
26
+ PATCH: [],
27
+ },
28
+ };
29
+ this.versions.set(version, router);
30
+ }
31
+
32
+ const router = this.versions.get(version);
33
+
34
+ return {
35
+ get: (path, handler) => this._register(router, 'GET', path, handler),
36
+ post: (path, handler) => this._register(router, 'POST', path, handler),
37
+ put: (path, handler) => this._register(router, 'PUT', path, handler),
38
+ delete: (path, handler) => this._register(router, 'DELETE', path, handler),
39
+ patch: (path, handler) => this._register(router, 'PATCH', path, handler),
40
+ use: (middleware) => {
41
+ if (!router.middlewares) {
42
+ router.middlewares = [];
43
+ }
44
+ router.middlewares.push(middleware);
45
+ },
46
+ };
47
+ }
48
+
49
+ /**
50
+ * Register a route for a version
51
+ * @private
52
+ */
53
+ _register(router, method, path, handler) {
54
+ const versionedPath = `/${router.version}${path}`;
55
+ router.routes[method].push({
56
+ path: versionedPath,
57
+ originalPath: path,
58
+ handler,
59
+ });
60
+ }
61
+
62
+ /**
63
+ * Set default version
64
+ * @param {string} version - Default version
65
+ */
66
+ setDefaultVersion(version) {
67
+ this.defaultVersion = version;
68
+ }
69
+
70
+ /**
71
+ * Get routes for a version
72
+ * @param {string} version - Version identifier
73
+ * @returns {Object} - Routes for the version
74
+ */
75
+ getRoutes(version) {
76
+ const router = this.versions.get(version);
77
+ return router ? router.routes : null;
78
+ }
79
+
80
+ /**
81
+ * Get all versions
82
+ * @returns {Array} - Array of version identifiers
83
+ */
84
+ getVersions() {
85
+ return Array.from(this.versions.keys());
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Create version manager
91
+ * @returns {VersionManager} - Version manager instance
92
+ */
93
+ function createVersionManager() {
94
+ return new VersionManager();
95
+ }
96
+
97
+ /**
98
+ * Header-based versioning middleware
99
+ * @param {Object} options - Versioning options
100
+ * @returns {Function} - Middleware function
101
+ */
102
+ function headerVersioning(options = {}) {
103
+ const {
104
+ header = 'X-API-Version',
105
+ defaultVersion = null,
106
+ } = options;
107
+
108
+ return async (req, res, next) => {
109
+ const version = req.headers[header] || req.headers[header.toLowerCase()] || defaultVersion;
110
+
111
+ if (version) {
112
+ req.apiVersion = version;
113
+ }
114
+
115
+ next();
116
+ };
117
+ }
118
+
119
+ module.exports = {
120
+ VersionManager,
121
+ createVersionManager,
122
+ headerVersioning,
123
+ };
124
+