kybernus 2.4.0 → 3.0.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 +15 -6
- package/add-features/auth/java-spring/AuthController.java +54 -0
- package/add-features/auth/java-spring/AuthService.java +85 -0
- package/add-features/auth/java-spring/INSTRUCTIONS.md +119 -0
- package/add-features/auth/java-spring/dto/LoginRequest.java +22 -0
- package/add-features/auth/java-spring/dto/RegisterRequest.java +22 -0
- package/add-features/auth/java-spring/security/JwtRequestFilter.java +45 -0
- package/add-features/auth/java-spring/security/JwtUtil.java +59 -0
- package/add-features/auth/java-spring/security/SecurityConfig.java +39 -0
- package/add-features/auth/nestjs/INSTRUCTIONS.md +112 -0
- package/add-features/auth/nestjs/auth.controller.ts +27 -0
- package/add-features/auth/nestjs/auth.module.ts +20 -0
- package/add-features/auth/nestjs/auth.service.ts +81 -0
- package/add-features/auth/nestjs/dto/login.dto.ts +4 -0
- package/add-features/auth/nestjs/dto/register.dto.ts +4 -0
- package/add-features/auth/nestjs/jwt-auth.guard.ts +17 -0
- package/add-features/auth/nestjs/jwt.strategy.ts +24 -0
- package/add-features/auth/nextjs/INSTRUCTIONS.md +97 -0
- package/add-features/auth/nextjs/jwt.ts +21 -0
- package/add-features/auth/nextjs/middleware.ts +37 -0
- package/add-features/auth/nextjs/routes/login.ts +43 -0
- package/add-features/auth/nextjs/routes/register.ts +50 -0
- package/add-features/auth/nextjs/session.ts +28 -0
- package/add-features/auth/nodejs-express/INSTRUCTIONS.md +109 -0
- package/add-features/auth/nodejs-express/auth.controller.ts +59 -0
- package/add-features/auth/nodejs-express/auth.middleware.ts +38 -0
- package/add-features/auth/nodejs-express/auth.routes.ts +15 -0
- package/add-features/auth/nodejs-express/auth.service.ts +73 -0
- package/add-features/auth/nodejs-express/jwt.config.ts +17 -0
- package/add-features/auth/python-fastapi/INSTRUCTIONS.md +100 -0
- package/add-features/auth/python-fastapi/router.py +26 -0
- package/add-features/auth/python-fastapi/schemas.py +25 -0
- package/add-features/auth/python-fastapi/security.py +37 -0
- package/add-features/auth/python-fastapi/service.py +61 -0
- package/add-features/deploy/dockerfiles/Dockerfile.java +22 -0
- package/add-features/deploy/dockerfiles/Dockerfile.nextjs +32 -0
- package/add-features/deploy/dockerfiles/Dockerfile.nodejs +25 -0
- package/add-features/deploy/dockerfiles/Dockerfile.python +17 -0
- package/add-features/deploy/fly/INSTRUCTIONS.md +39 -0
- package/add-features/deploy/fly/java-spring.toml +21 -0
- package/add-features/deploy/fly/nextjs.toml +16 -0
- package/add-features/deploy/fly/nodejs.toml +21 -0
- package/add-features/deploy/fly/python-fastapi.toml +21 -0
- package/add-features/deploy/railway/INSTRUCTIONS.md +38 -0
- package/add-features/deploy/railway/java-spring.toml +16 -0
- package/add-features/deploy/railway/nextjs.toml +14 -0
- package/add-features/deploy/railway/nodejs.toml +14 -0
- package/add-features/deploy/railway/python-fastapi.toml +13 -0
- package/add-features/deploy/render/INSTRUCTIONS.md +35 -0
- package/add-features/deploy/render/java-spring.yaml +14 -0
- package/add-features/deploy/render/nextjs.yaml +17 -0
- package/add-features/deploy/render/nodejs.yaml +15 -0
- package/add-features/deploy/render/python-fastapi.yaml +13 -0
- package/add-features/deploy/vercel/INSTRUCTIONS.md +40 -0
- package/add-features/deploy/vercel/nextjs.json +16 -0
- package/add-features/deploy/vercel/nodejs-express.json +21 -0
- package/add-features/deploy/vercel/python-fastapi.json +21 -0
- package/add-features/husky/INSTRUCTIONS.md +52 -0
- package/add-features/husky/commit-msg +4 -0
- package/add-features/husky/commitlint.config.js +3 -0
- package/add-features/husky/pre-commit +4 -0
- package/add-features/redis/.env.snippet +1 -0
- package/add-features/redis/INSTRUCTIONS.md +64 -0
- package/add-features/redis/docker-compose.snippet.yml +18 -0
- package/add-features/redis/java-spring.java +27 -0
- package/add-features/redis/nextjs.ts +23 -0
- package/add-features/redis/nodejs.ts +14 -0
- package/add-features/redis/python.py +22 -0
- package/add-features/swagger/INSTRUCTIONS.md +53 -0
- package/add-features/swagger/java-spring.java +34 -0
- package/add-features/swagger/nestjs.ts +16 -0
- package/add-features/swagger/nextjs-route.ts +11 -0
- package/add-features/swagger/nextjs-swagger.ts +17 -0
- package/add-features/swagger/nodejs-express.ts +30 -0
- package/add-features/swagger/python-fastapi.py +21 -0
- package/add-features/websocket/INSTRUCTIONS.md +63 -0
- package/add-features/websocket/java-spring.java +60 -0
- package/add-features/websocket/nestjs.ts +38 -0
- package/add-features/websocket/nodejs-express.ts +38 -0
- package/add-features/websocket/python-fastapi.py +41 -0
- package/dist/cli/commands/add.d.ts +11 -0
- package/dist/cli/commands/add.d.ts.map +1 -0
- package/dist/cli/commands/add.js +102 -0
- package/dist/cli/commands/add.js.map +1 -0
- package/dist/cli/commands/auth.d.ts +11 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/auth.js +71 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/deploy.d.ts +10 -0
- package/dist/cli/commands/deploy.d.ts.map +1 -0
- package/dist/cli/commands/deploy.js +110 -0
- package/dist/cli/commands/deploy.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +3 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +110 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/init.d.ts +1 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +1 -0
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/prompts/wizard.d.ts +1 -0
- package/dist/cli/prompts/wizard.d.ts.map +1 -1
- package/dist/cli/prompts/wizard.js +23 -15
- package/dist/cli/prompts/wizard.js.map +1 -1
- package/dist/cli/utils/cli-helpers.d.ts +43 -0
- package/dist/cli/utils/cli-helpers.d.ts.map +1 -0
- package/dist/cli/utils/cli-helpers.js +107 -0
- package/dist/cli/utils/cli-helpers.js.map +1 -0
- package/dist/core/deploy/deploy-generator.d.ts +18 -0
- package/dist/core/deploy/deploy-generator.d.ts.map +1 -0
- package/dist/core/deploy/deploy-generator.js +155 -0
- package/dist/core/deploy/deploy-generator.js.map +1 -0
- package/dist/core/features/feature-generator.d.ts +26 -0
- package/dist/core/features/feature-generator.d.ts.map +1 -0
- package/dist/core/features/feature-generator.js +376 -0
- package/dist/core/features/feature-generator.js.map +1 -0
- package/dist/core/generator/project.d.ts.map +1 -1
- package/dist/core/generator/project.js +42 -2
- package/dist/core/generator/project.js.map +1 -1
- package/dist/core/templates/engine.d.ts.map +1 -1
- package/dist/core/templates/engine.js +4 -0
- package/dist/core/templates/engine.js.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/models/config.d.ts +1 -0
- package/dist/models/config.d.ts.map +1 -1
- package/package.json +14 -2
- package/templates/nestjs/clean/package.json.hbs +51 -41
- package/templates/nestjs/hexagonal/package.json.hbs +51 -41
- package/templates/nestjs/mvc/package.json.hbs +49 -39
- package/templates/nextjs/mvc/package.json.hbs +46 -36
- package/templates/nodejs-express/clean/package.json.hbs +69 -59
- package/templates/nodejs-express/hexagonal/package.json.hbs +69 -59
- package/templates/nodejs-express/mvc/package.json.hbs +67 -57
- /package/templates/nestjs/hexagonal/prisma/{schema.prisma → schema.prisma.hbs} +0 -0
- /package/templates/nodejs-express/clean/prisma/{schema.prisma → schema.prisma.hbs} +0 -0
- /package/templates/nodejs-express/hexagonal/prisma/{schema.prisma → schema.prisma.hbs} +0 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# WebSocket
|
|
2
|
+
|
|
3
|
+
## Files generated
|
|
4
|
+
|
|
5
|
+
- `websocket.ts` or `AppGateway.ts` in the root of `src/`
|
|
6
|
+
|
|
7
|
+
## Install dependencies
|
|
8
|
+
|
|
9
|
+
### Node.js Express
|
|
10
|
+
```bash
|
|
11
|
+
npm install ws
|
|
12
|
+
npm install -D @types/ws
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### NestJS (uses socket.io)
|
|
16
|
+
```bash
|
|
17
|
+
npm install @nestjs/websockets @nestjs/platform-socket.io socket.io
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Integration
|
|
23
|
+
|
|
24
|
+
### Node.js Express — update `app.ts` / `index.ts`:
|
|
25
|
+
```typescript
|
|
26
|
+
import http from 'http';
|
|
27
|
+
import app from './app'; // your express app
|
|
28
|
+
import { setupWebSocket } from './websocket';
|
|
29
|
+
|
|
30
|
+
const server = http.createServer(app);
|
|
31
|
+
setupWebSocket(server);
|
|
32
|
+
|
|
33
|
+
server.listen(process.env.PORT || 3000, () => {
|
|
34
|
+
console.log(`Server running on port ${process.env.PORT || 3000}`);
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
> ⚠️ Replace `app.listen(...)` with `server.listen(...)` — WebSocket requires the raw HTTP server.
|
|
38
|
+
|
|
39
|
+
### NestJS — register the Gateway in your module:
|
|
40
|
+
```typescript
|
|
41
|
+
import { AppGateway } from './websocket'; // or AppGateway
|
|
42
|
+
|
|
43
|
+
@Module({
|
|
44
|
+
providers: [AppGateway],
|
|
45
|
+
})
|
|
46
|
+
export class AppModule {}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Testing WebSocket connection
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Install wscat
|
|
55
|
+
npm install -g wscat
|
|
56
|
+
|
|
57
|
+
# Connect (Express)
|
|
58
|
+
wscat -c ws://localhost:3000
|
|
59
|
+
|
|
60
|
+
# Connect (NestJS / socket.io)
|
|
61
|
+
# Use the socket.io client in the browser or:
|
|
62
|
+
npm install -g socket.io-client
|
|
63
|
+
```
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
package com.example.config;
|
|
2
|
+
|
|
3
|
+
import org.springframework.context.annotation.Configuration;
|
|
4
|
+
import org.springframework.web.socket.config.annotation.EnableWebSocket;
|
|
5
|
+
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
|
|
6
|
+
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
|
|
7
|
+
import org.springframework.web.socket.handler.TextWebSocketHandler;
|
|
8
|
+
import org.springframework.web.socket.WebSocketSession;
|
|
9
|
+
import org.springframework.web.socket.TextMessage;
|
|
10
|
+
|
|
11
|
+
import java.util.Collections;
|
|
12
|
+
import java.util.Set;
|
|
13
|
+
import java.util.concurrent.ConcurrentHashMap;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* WebSocket configuration for Spring Boot.
|
|
17
|
+
* Generated by: kybernus add websocket
|
|
18
|
+
*
|
|
19
|
+
* WebSocket endpoint: ws://localhost:8080/ws
|
|
20
|
+
*/
|
|
21
|
+
@Configuration
|
|
22
|
+
@EnableWebSocket
|
|
23
|
+
public class WebSocketConfig implements WebSocketConfigurer {
|
|
24
|
+
|
|
25
|
+
@Override
|
|
26
|
+
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
|
|
27
|
+
registry.addHandler(new AppWebSocketHandler(), "/ws")
|
|
28
|
+
.setAllowedOrigins("*");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static class AppWebSocketHandler extends TextWebSocketHandler {
|
|
32
|
+
private final Set<WebSocketSession> sessions = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
|
33
|
+
|
|
34
|
+
@Override
|
|
35
|
+
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
|
|
36
|
+
sessions.add(session);
|
|
37
|
+
session.sendMessage(new TextMessage("{\"event\":\"connected\",\"data\":\"Welcome!\"}"));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@Override
|
|
41
|
+
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
|
|
42
|
+
String payload = message.getPayload();
|
|
43
|
+
session.sendMessage(new TextMessage("{\"event\":\"echo\",\"data\":\"" + payload + "\"}"));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@Override
|
|
47
|
+
public void afterConnectionClosed(WebSocketSession session, org.springframework.web.socket.CloseStatus status) {
|
|
48
|
+
sessions.remove(session);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public void broadcast(String message) {
|
|
52
|
+
sessions.forEach(session -> {
|
|
53
|
+
try {
|
|
54
|
+
session.sendMessage(new TextMessage(message));
|
|
55
|
+
} catch (Exception ignored) {
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {
|
|
2
|
+
WebSocketGateway,
|
|
3
|
+
WebSocketServer as WsServer,
|
|
4
|
+
SubscribeMessage,
|
|
5
|
+
MessageBody,
|
|
6
|
+
OnGatewayConnection,
|
|
7
|
+
OnGatewayDisconnect,
|
|
8
|
+
} from '@nestjs/websockets';
|
|
9
|
+
import { Server, Socket } from 'socket.io';
|
|
10
|
+
|
|
11
|
+
@WebSocketGateway({
|
|
12
|
+
cors: {
|
|
13
|
+
origin: '*',
|
|
14
|
+
},
|
|
15
|
+
})
|
|
16
|
+
export class AppGateway implements OnGatewayConnection, OnGatewayDisconnect {
|
|
17
|
+
@WsServer()
|
|
18
|
+
server: Server;
|
|
19
|
+
|
|
20
|
+
handleConnection(client: Socket) {
|
|
21
|
+
console.log(`🔌 Client connected: ${client.id}`);
|
|
22
|
+
client.emit('connected', { message: 'Welcome!' });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
handleDisconnect(client: Socket) {
|
|
26
|
+
console.log(`🔌 Client disconnected: ${client.id}`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@SubscribeMessage('message')
|
|
30
|
+
handleMessage(@MessageBody() data: string): void {
|
|
31
|
+
console.log('📨 Received:', data);
|
|
32
|
+
this.server.emit('message', { event: 'echo', data });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
broadcast(event: string, data: unknown): void {
|
|
36
|
+
this.server.emit(event, data);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Server } from 'http';
|
|
2
|
+
import { WebSocketServer, WebSocket } from 'ws';
|
|
3
|
+
|
|
4
|
+
let wss: WebSocketServer;
|
|
5
|
+
|
|
6
|
+
export function setupWebSocket(server: Server): void {
|
|
7
|
+
wss = new WebSocketServer({ server });
|
|
8
|
+
|
|
9
|
+
wss.on('connection', (ws: WebSocket) => {
|
|
10
|
+
console.log('🔌 WebSocket client connected');
|
|
11
|
+
|
|
12
|
+
ws.on('message', (data) => {
|
|
13
|
+
const message = data.toString();
|
|
14
|
+
console.log('📨 Received:', message);
|
|
15
|
+
|
|
16
|
+
// Echo back to sender
|
|
17
|
+
ws.send(JSON.stringify({ event: 'echo', data: message }));
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
ws.on('close', () => {
|
|
21
|
+
console.log('🔌 WebSocket client disconnected');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
ws.send(JSON.stringify({ event: 'connected', data: 'Welcome!' }));
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
console.log('🔌 WebSocket server ready');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function broadcast(event: string, data: unknown): void {
|
|
31
|
+
if (!wss) return;
|
|
32
|
+
const payload = JSON.stringify({ event, data });
|
|
33
|
+
wss.clients.forEach((client) => {
|
|
34
|
+
if (client.readyState === WebSocket.OPEN) {
|
|
35
|
+
client.send(payload);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""
|
|
2
|
+
WebSocket support for FastAPI.
|
|
3
|
+
Apply by importing setup_websocket_routes(app) in your main.py.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
|
|
7
|
+
from typing import List
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ConnectionManager:
|
|
11
|
+
def __init__(self):
|
|
12
|
+
self.active_connections: List[WebSocket] = []
|
|
13
|
+
|
|
14
|
+
async def connect(self, websocket: WebSocket):
|
|
15
|
+
await websocket.accept()
|
|
16
|
+
self.active_connections.append(websocket)
|
|
17
|
+
|
|
18
|
+
def disconnect(self, websocket: WebSocket):
|
|
19
|
+
self.active_connections.remove(websocket)
|
|
20
|
+
|
|
21
|
+
async def broadcast(self, message: str):
|
|
22
|
+
for connection in self.active_connections:
|
|
23
|
+
await connection.send_text(message)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
manager = ConnectionManager()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def setup_websocket_routes(app: FastAPI) -> None:
|
|
30
|
+
@app.websocket("/ws")
|
|
31
|
+
async def websocket_endpoint(websocket: WebSocket):
|
|
32
|
+
await manager.connect(websocket)
|
|
33
|
+
try:
|
|
34
|
+
while True:
|
|
35
|
+
data = await websocket.receive_text()
|
|
36
|
+
await websocket.send_text(f"Echo: {data}")
|
|
37
|
+
await manager.broadcast(f"Client says: {data}")
|
|
38
|
+
except WebSocketDisconnect:
|
|
39
|
+
manager.disconnect(websocket)
|
|
40
|
+
|
|
41
|
+
print("🔌 WebSocket endpoint registered at /ws")
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* add.ts
|
|
3
|
+
*
|
|
4
|
+
* `kybernus add [feature]` command.
|
|
5
|
+
* Adds an infrastructure feature (swagger, redis, websocket, husky, auth)
|
|
6
|
+
* to any project — Kybernus-generated or standalone.
|
|
7
|
+
* If `.kybernusrc.json` is not found, prompts for stack + architecture.
|
|
8
|
+
*/
|
|
9
|
+
import { Command } from 'commander';
|
|
10
|
+
export declare const addCommand: Command;
|
|
11
|
+
//# sourceMappingURL=add.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/add.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyBpC,eAAO,MAAM,UAAU,SA4EjB,CAAC"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* add.ts
|
|
3
|
+
*
|
|
4
|
+
* `kybernus add [feature]` command.
|
|
5
|
+
* Adds an infrastructure feature (swagger, redis, websocket, husky, auth)
|
|
6
|
+
* to any project — Kybernus-generated or standalone.
|
|
7
|
+
* If `.kybernusrc.json` is not found, prompts for stack + architecture.
|
|
8
|
+
*/
|
|
9
|
+
import { Command } from 'commander';
|
|
10
|
+
import * as clack from '@clack/prompts';
|
|
11
|
+
import color from 'picocolors';
|
|
12
|
+
import { generateFeature, getSupportedFeatures, } from '../../core/features/feature-generator.js';
|
|
13
|
+
import { readProjectConfig, exitIfCancelled, displayFeatureResult, handleGenerateError, promptArchitecture, } from '../utils/cli-helpers.js';
|
|
14
|
+
const STACK_OPTIONS = [
|
|
15
|
+
{ value: 'nodejs-express', label: 'Node.js Express' },
|
|
16
|
+
{ value: 'nestjs', label: 'NestJS' },
|
|
17
|
+
{ value: 'python-fastapi', label: 'Python FastAPI' },
|
|
18
|
+
{ value: 'java-spring', label: 'Java Spring Boot' },
|
|
19
|
+
{ value: 'nextjs', label: 'Next.js' },
|
|
20
|
+
];
|
|
21
|
+
export const addCommand = new Command('add')
|
|
22
|
+
.argument('[feature]', 'Feature to add (swagger, redis, websocket, husky, auth)')
|
|
23
|
+
.description('Add infrastructure features to your project')
|
|
24
|
+
.action(async (featureArg) => {
|
|
25
|
+
clack.intro(color.bgCyan(color.black(' kybernus add ')));
|
|
26
|
+
const cwd = process.cwd();
|
|
27
|
+
// Try to read project config — if not found, enter guided wizard mode
|
|
28
|
+
const config = await readProjectConfig(cwd, { requireExistence: false });
|
|
29
|
+
let stack;
|
|
30
|
+
let architecture;
|
|
31
|
+
if (config) {
|
|
32
|
+
stack = config.stack;
|
|
33
|
+
architecture = config.architecture;
|
|
34
|
+
clack.log.info(`Project: ${color.cyan(config.projectName)} (${color.white(stack)})`);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
clack.log.warn('No .kybernusrc.json found — this project was not generated by Kybernus.');
|
|
38
|
+
clack.log.info('No problem! Just tell us your stack so we can generate the right files.');
|
|
39
|
+
const selectedStack = await clack.select({
|
|
40
|
+
message: 'What is the stack of this project?',
|
|
41
|
+
options: STACK_OPTIONS,
|
|
42
|
+
});
|
|
43
|
+
exitIfCancelled(selectedStack);
|
|
44
|
+
stack = selectedStack;
|
|
45
|
+
architecture = await promptArchitecture();
|
|
46
|
+
}
|
|
47
|
+
// --- Resolve feature ---
|
|
48
|
+
const supported = getSupportedFeatures(stack);
|
|
49
|
+
if (supported.length === 0) {
|
|
50
|
+
clack.log.error(`No addable features available for stack "${stack}" yet.`);
|
|
51
|
+
clack.outro(color.red('Nothing added.'));
|
|
52
|
+
process.exit(0);
|
|
53
|
+
}
|
|
54
|
+
let feature = featureArg;
|
|
55
|
+
if (feature && !supported.includes(feature)) {
|
|
56
|
+
clack.log.warn(`Feature "${feature}" is not available for stack "${stack}".`);
|
|
57
|
+
clack.log.info(`Available: ${supported.join(', ')}`);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
if (!feature) {
|
|
61
|
+
const selected = await clack.select({
|
|
62
|
+
message: 'Which feature do you want to add?',
|
|
63
|
+
options: supported.map((f) => ({
|
|
64
|
+
value: f,
|
|
65
|
+
label: FEATURE_LABELS[f],
|
|
66
|
+
hint: FEATURE_HINTS[f],
|
|
67
|
+
})),
|
|
68
|
+
});
|
|
69
|
+
exitIfCancelled(selected);
|
|
70
|
+
feature = selected;
|
|
71
|
+
}
|
|
72
|
+
// --- Generate ---
|
|
73
|
+
const spinner = clack.spinner();
|
|
74
|
+
spinner.start(`Adding ${color.cyan(feature)}...`);
|
|
75
|
+
try {
|
|
76
|
+
const result = await generateFeature(feature, stack, cwd, architecture);
|
|
77
|
+
spinner.stop(`${color.green('✅')} Feature "${color.cyan(feature)}" added!`);
|
|
78
|
+
displayFeatureResult(result);
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
handleGenerateError(err, spinner);
|
|
82
|
+
}
|
|
83
|
+
clack.outro(color.green('Done! Follow the instructions file to complete the setup.'));
|
|
84
|
+
});
|
|
85
|
+
// ─────────────────────────────────────────────────────────────────
|
|
86
|
+
// Feature metadata (labels/hints for the interactive picker)
|
|
87
|
+
// ─────────────────────────────────────────────────────────────────
|
|
88
|
+
const FEATURE_LABELS = {
|
|
89
|
+
swagger: 'Swagger / OpenAPI Docs',
|
|
90
|
+
redis: 'Redis Cache',
|
|
91
|
+
websocket: 'WebSocket Server',
|
|
92
|
+
husky: 'Husky + Commitlint',
|
|
93
|
+
auth: 'JWT Authentication',
|
|
94
|
+
};
|
|
95
|
+
const FEATURE_HINTS = {
|
|
96
|
+
swagger: 'Auto-generated API documentation at /api/docs',
|
|
97
|
+
redis: 'Redis client + docker-compose service',
|
|
98
|
+
websocket: 'Real-time WS/socket.io server setup',
|
|
99
|
+
husky: 'Git hooks for linting and conventional commits',
|
|
100
|
+
auth: 'JWT sign/verify, middleware, and password hashing + bcrypt',
|
|
101
|
+
};
|
|
102
|
+
//# sourceMappingURL=add.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add.js","sourceRoot":"","sources":["../../../src/cli/commands/add.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* auth.ts
|
|
3
|
+
*
|
|
4
|
+
* `kybernus auth` command.
|
|
5
|
+
* Generates a complete, modular JWT authentication flow for the project.
|
|
6
|
+
* Works both in Kybernus-generated projects (reads .kybernusrc.json automatically)
|
|
7
|
+
* and in standalone projects (prompts for stack + architecture).
|
|
8
|
+
*/
|
|
9
|
+
import { Command } from 'commander';
|
|
10
|
+
export declare const authCommand: Command;
|
|
11
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoBpC,eAAO,MAAM,WAAW,SAyDlB,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* auth.ts
|
|
3
|
+
*
|
|
4
|
+
* `kybernus auth` command.
|
|
5
|
+
* Generates a complete, modular JWT authentication flow for the project.
|
|
6
|
+
* Works both in Kybernus-generated projects (reads .kybernusrc.json automatically)
|
|
7
|
+
* and in standalone projects (prompts for stack + architecture).
|
|
8
|
+
*/
|
|
9
|
+
import { Command } from 'commander';
|
|
10
|
+
import * as clack from '@clack/prompts';
|
|
11
|
+
import color from 'picocolors';
|
|
12
|
+
import { generateFeature } from '../../core/features/feature-generator.js';
|
|
13
|
+
import { readProjectConfig, exitIfCancelled, promptArchitecture, displayFeatureResult, handleGenerateError, } from '../utils/cli-helpers.js';
|
|
14
|
+
const STACK_OPTIONS = [
|
|
15
|
+
{ value: 'nodejs-express', label: 'Node.js Express' },
|
|
16
|
+
{ value: 'nestjs', label: 'NestJS' },
|
|
17
|
+
{ value: 'python-fastapi', label: 'Python FastAPI' },
|
|
18
|
+
{ value: 'java-spring', label: 'Java Spring Boot' },
|
|
19
|
+
{ value: 'nextjs', label: 'Next.js' },
|
|
20
|
+
];
|
|
21
|
+
export const authCommand = new Command('auth')
|
|
22
|
+
.description('Add JWT authentication boilerplate to your project')
|
|
23
|
+
.action(async () => {
|
|
24
|
+
clack.intro(color.bgMagenta(color.black(' kybernus auth ')));
|
|
25
|
+
const cwd = process.cwd();
|
|
26
|
+
// Try to read project config; if not found, enter guided wizard mode
|
|
27
|
+
let config = await readProjectConfig(cwd, { requireExistence: false });
|
|
28
|
+
let stack;
|
|
29
|
+
let architecture;
|
|
30
|
+
if (config) {
|
|
31
|
+
// Kybernus project: all info is already known
|
|
32
|
+
stack = config.stack;
|
|
33
|
+
architecture = config.architecture;
|
|
34
|
+
clack.log.info(`Project: ${color.cyan(config.projectName)} (${color.white(stack)} / ${color.white(architecture)})`);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
// Standalone project: ask the user for stack + architecture
|
|
38
|
+
clack.log.warn('No .kybernusrc.json found — this project was not generated by Kybernus.');
|
|
39
|
+
clack.log.info('No problem! Answer a couple of questions so we can generate the right files.');
|
|
40
|
+
const selectedStack = await clack.select({
|
|
41
|
+
message: 'What is the stack of this project?',
|
|
42
|
+
options: STACK_OPTIONS,
|
|
43
|
+
});
|
|
44
|
+
exitIfCancelled(selectedStack);
|
|
45
|
+
stack = selectedStack;
|
|
46
|
+
architecture = await promptArchitecture();
|
|
47
|
+
}
|
|
48
|
+
// Confirm before writing
|
|
49
|
+
const confirm = await clack.confirm({
|
|
50
|
+
message: `Generate JWT auth for ${color.cyan(stack)} (${color.white(architecture)})?`,
|
|
51
|
+
});
|
|
52
|
+
exitIfCancelled(confirm);
|
|
53
|
+
if (!confirm) {
|
|
54
|
+
clack.cancel('Cancelled.');
|
|
55
|
+
process.exit(0);
|
|
56
|
+
}
|
|
57
|
+
// Generate
|
|
58
|
+
const spinner = clack.spinner();
|
|
59
|
+
spinner.start(`Adding JWT auth for ${color.cyan(stack)}...`);
|
|
60
|
+
try {
|
|
61
|
+
const result = await generateFeature('auth', stack, cwd, architecture);
|
|
62
|
+
spinner.stop(`${color.green('✅')} JWT authentication added!`);
|
|
63
|
+
displayFeatureResult(result);
|
|
64
|
+
clack.log.warn(`Don't forget to set ${color.yellow('JWT_SECRET')} in your .env file!`);
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
handleGenerateError(err, spinner);
|
|
68
|
+
}
|
|
69
|
+
clack.outro(color.green('Done! Open AUTH.md for the integration guide.'));
|
|
70
|
+
});
|
|
71
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/cli/commands/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* deploy.ts
|
|
3
|
+
*
|
|
4
|
+
* `kybernus deploy` command.
|
|
5
|
+
* Generates production-ready deployment configuration files for the chosen
|
|
6
|
+
* cloud provider. Works in Kybernus-generated projects and standalone projects.
|
|
7
|
+
*/
|
|
8
|
+
import { Command } from 'commander';
|
|
9
|
+
export declare const deployCommand: Command;
|
|
10
|
+
//# sourceMappingURL=deploy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/deploy.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqCpC,eAAO,MAAM,aAAa,SA4FpB,CAAC"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* deploy.ts
|
|
3
|
+
*
|
|
4
|
+
* `kybernus deploy` command.
|
|
5
|
+
* Generates production-ready deployment configuration files for the chosen
|
|
6
|
+
* cloud provider. Works in Kybernus-generated projects and standalone projects.
|
|
7
|
+
*/
|
|
8
|
+
import { Command } from 'commander';
|
|
9
|
+
import * as clack from '@clack/prompts';
|
|
10
|
+
import color from 'picocolors';
|
|
11
|
+
import { generateDeploy, isProviderSupported, } from '../../core/deploy/deploy-generator.js';
|
|
12
|
+
import { readProjectConfig, exitIfCancelled, } from '../utils/cli-helpers.js';
|
|
13
|
+
// ─────────────────────────────────────────────────────────────────
|
|
14
|
+
// Metadata
|
|
15
|
+
// ─────────────────────────────────────────────────────────────────
|
|
16
|
+
const PROVIDER_OPTIONS = [
|
|
17
|
+
{ value: 'vercel', label: 'Vercel', hint: 'Great for Next.js, Node.js, and Python — zero-config' },
|
|
18
|
+
{ value: 'railway', label: 'Railway', hint: 'Supports all stacks — easy Postgres provisioning' },
|
|
19
|
+
{ value: 'fly', label: 'Fly.io', hint: 'Supports all stacks — runs Docker containers globally' },
|
|
20
|
+
{ value: 'render', label: 'Render', hint: 'Supports all stacks — generous free tier' },
|
|
21
|
+
];
|
|
22
|
+
const STACK_OPTIONS = [
|
|
23
|
+
{ value: 'nodejs-express', label: 'Node.js Express' },
|
|
24
|
+
{ value: 'nestjs', label: 'NestJS' },
|
|
25
|
+
{ value: 'python-fastapi', label: 'Python FastAPI' },
|
|
26
|
+
{ value: 'java-spring', label: 'Java Spring Boot' },
|
|
27
|
+
{ value: 'nextjs', label: 'Next.js' },
|
|
28
|
+
];
|
|
29
|
+
// ─────────────────────────────────────────────────────────────────
|
|
30
|
+
// Command
|
|
31
|
+
// ─────────────────────────────────────────────────────────────────
|
|
32
|
+
export const deployCommand = new Command('deploy')
|
|
33
|
+
.description('Generate deployment configuration files for cloud providers')
|
|
34
|
+
.action(async () => {
|
|
35
|
+
clack.intro(color.bgBlue(color.white(' kybernus deploy ')));
|
|
36
|
+
const cwd = process.cwd();
|
|
37
|
+
const config = await readProjectConfig(cwd, { requireExistence: false });
|
|
38
|
+
let stack;
|
|
39
|
+
if (config) {
|
|
40
|
+
stack = config.stack;
|
|
41
|
+
clack.log.info(`Project: ${color.cyan(config.projectName)} (${color.white(stack)})`);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
clack.log.warn('No .kybernusrc.json found — this project was not generated by Kybernus.');
|
|
45
|
+
clack.log.info('No problem! Just tell us your stack.');
|
|
46
|
+
const selectedStack = await clack.select({
|
|
47
|
+
message: 'What is the stack of this project?',
|
|
48
|
+
options: STACK_OPTIONS,
|
|
49
|
+
});
|
|
50
|
+
exitIfCancelled(selectedStack);
|
|
51
|
+
stack = selectedStack;
|
|
52
|
+
}
|
|
53
|
+
// --- Select provider ---
|
|
54
|
+
const supportedProviders = PROVIDER_OPTIONS.filter((p) => isProviderSupported(p.value, stack));
|
|
55
|
+
if (supportedProviders.length === 0) {
|
|
56
|
+
clack.log.error(`No supported cloud providers found for stack "${stack}".`);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
const selectedProvider = await clack.select({
|
|
60
|
+
message: 'Which cloud provider do you want to deploy to?',
|
|
61
|
+
options: supportedProviders.map((p) => ({
|
|
62
|
+
value: p.value,
|
|
63
|
+
label: p.label,
|
|
64
|
+
hint: p.hint,
|
|
65
|
+
})),
|
|
66
|
+
});
|
|
67
|
+
exitIfCancelled(selectedProvider);
|
|
68
|
+
const provider = selectedProvider;
|
|
69
|
+
// --- Ask about Dockerfile (providers that use containers) ---
|
|
70
|
+
const PROVIDERS_WITH_DOCKERFILE = ['railway', 'fly', 'render'];
|
|
71
|
+
let includeDockerfile = false;
|
|
72
|
+
if (PROVIDERS_WITH_DOCKERFILE.includes(provider)) {
|
|
73
|
+
const dockerAnswer = await clack.confirm({
|
|
74
|
+
message: `Include a ${color.yellow('Dockerfile')}? ${color.dim('(skip if your project already has one)')}`,
|
|
75
|
+
initialValue: false,
|
|
76
|
+
});
|
|
77
|
+
exitIfCancelled(dockerAnswer);
|
|
78
|
+
includeDockerfile = dockerAnswer;
|
|
79
|
+
}
|
|
80
|
+
// --- Confirm ---
|
|
81
|
+
const confirm = await clack.confirm({
|
|
82
|
+
message: `Generate ${color.cyan(provider)} deployment config for ${color.cyan(stack)}?`,
|
|
83
|
+
});
|
|
84
|
+
exitIfCancelled(confirm);
|
|
85
|
+
if (!confirm) {
|
|
86
|
+
clack.cancel('Cancelled.');
|
|
87
|
+
process.exit(0);
|
|
88
|
+
}
|
|
89
|
+
// --- Generate ---
|
|
90
|
+
const spinner = clack.spinner();
|
|
91
|
+
spinner.start(`Generating ${color.cyan(provider)} config...`);
|
|
92
|
+
try {
|
|
93
|
+
const result = await generateDeploy(provider, stack, cwd, includeDockerfile);
|
|
94
|
+
spinner.stop(`${color.green('✅')} Deploy config generated!`);
|
|
95
|
+
clack.log.step('Files created:');
|
|
96
|
+
for (const file of result.copiedFiles) {
|
|
97
|
+
clack.log.info(` ${color.dim('→')} ${file}`);
|
|
98
|
+
}
|
|
99
|
+
if (result.instructionsPath) {
|
|
100
|
+
clack.log.step(`📖 Deployment guide: ${color.yellow(result.instructionsPath)}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
spinner.stop();
|
|
105
|
+
clack.log.error(`❌ ${err instanceof Error ? err.message : String(err)}`);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
clack.outro(color.green('Done! Open DEPLOY.md for the next steps.'));
|
|
109
|
+
});
|
|
110
|
+
//# sourceMappingURL=deploy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../../src/cli/commands/deploy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,eAAO,MAAM,aAAa,SA8GpB,CAAC"}
|