UNPKG

@re-shell/cli

Version:

Full-stack development platform uniting microservices and microfrontends. Build complete applications with .NET (ASP.NET Core Web API, Minimal API), Java (Spring Boot, Quarkus, Micronaut, Vert.x), Rust (Actix-Web, Warp, Rocket, Axum), Python (FastAPI, Dja

1,441 lines (1,214 loc) 46.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.perfectTemplate = void 0; exports.perfectTemplate = { id: 'perfect', name: 'perfect', displayName: 'Perfect Framework', description: 'High-performance server-side Swift framework with HTTP, WebSocket, and database support', language: 'swift', framework: 'perfect', version: '4.0.0', tags: ['swift', 'perfect', 'api', 'rest', 'websocket', 'performance'], port: 8080, dependencies: {}, features: ['authentication', 'websocket', 'database', 'logging', 'cors', 'ssl'], files: { // Swift Package Manager configuration 'Package.swift': `// swift-tools-version:5.9 import PackageDescription let package = Package( name: "{{projectName}}", platforms: [ .macOS(.v12), ], products: [ .executable(name: "{{projectName}}", targets: ["{{projectName}}"]), ], dependencies: [ .package(url: "https://github.com/PerfectlySoft/Perfect-HTTPServer.git", from: "3.0.0"), .package(url: "https://github.com/PerfectlySoft/Perfect-WebSockets.git", from: "3.0.0"), .package(url: "https://github.com/PerfectlySoft/Perfect-Mustache.git", from: "3.0.0"), .package(url: "https://github.com/PerfectlySoft/Perfect-PostgreSQL.git", from: "5.0.0"), .package(url: "https://github.com/PerfectlySoft/Perfect-MySQL.git", from: "5.0.0"), .package(url: "https://github.com/PerfectlySoft/Perfect-SQLite.git", from: "5.0.0"), .package(url: "https://github.com/PerfectlySoft/Perfect-Crypto.git", from: "3.0.0"), .package(url: "https://github.com/PerfectlySoft/Perfect-RequestLogger.git", from: "3.0.0"), .package(url: "https://github.com/PerfectlySoft/Perfect-Session.git", from: "3.0.0"), .package(url: "https://github.com/PerfectlySoft/Perfect-SessionPostgreSQL.git", from: "3.0.0"), .package(url: "https://github.com/apple/swift-log.git", from: "1.5.3"), ], targets: [ .executableTarget( name: "{{projectName}}", dependencies: [ .product(name: "PerfectHTTPServer", package: "Perfect-HTTPServer"), .product(name: "PerfectWebSockets", package: "Perfect-WebSockets"), .product(name: "PerfectMustache", package: "Perfect-Mustache"), .product(name: "PerfectPostgreSQL", package: "Perfect-PostgreSQL"), .product(name: "PerfectMySQL", package: "Perfect-MySQL"), .product(name: "PerfectSQLite", package: "Perfect-SQLite"), .product(name: "PerfectCrypto", package: "Perfect-Crypto"), .product(name: "PerfectRequestLogger", package: "Perfect-RequestLogger"), .product(name: "PerfectSession", package: "Perfect-Session"), .product(name: "PerfectSessionPostgreSQL", package: "Perfect-SessionPostgreSQL"), .product(name: "Logging", package: "swift-log"), ], path: "Sources" ), .testTarget( name: "{{projectName}}Tests", dependencies: ["{{projectName}}"], path: "Tests" ), ] )`, // Main entry point 'Sources/main.swift': `import PerfectHTTP import PerfectHTTPServer import PerfectWebSockets import PerfectSession import PerfectSessionPostgreSQL import PerfectRequestLogger import Logging // Initialize logger let logger = Logger(label: "{{projectName}}") // Load configuration let config = Configuration.load() // Configure server let server = HTTPServer() server.serverPort = config.port server.serverAddress = config.host // Configure sessions let sessionDriver = SessionPostgreSQLDriver() SessionConfig.name = "{{projectName}}-session" SessionConfig.idle = config.sessionTimeout SessionConfig.cookieDomain = config.cookieDomain SessionConfig.IPAddressLock = true SessionConfig.userAgentLock = true SessionConfig.CSRF.checkState = true SessionConfig.CSRF.failAction = .fail SessionConfig.CSRF.checkHeaders = true SessionConfig.CSRF.acceptableHostnames.append(config.host) // Configure request logger let requestLogger = RequestLogger() // Configure routes var routes = Routes() // Apply middleware routes.add(method: .get, uri: "/**", handler: requestLogger.handler) routes.add(method: .post, uri: "/**", handler: requestLogger.handler) routes.add(method: .put, uri: "/**", handler: requestLogger.handler) routes.add(method: .delete, uri: "/**", handler: requestLogger.handler) // Add CORS middleware routes.add(method: .options, uri: "/**", handler: CORSHandler.handler) // Setup routes setupRoutes(&routes) // Add routes to server server.addRoutes(routes) // Configure SSL if enabled if config.useSSL { server.ssl = (config.sslCertPath, config.sslKeyPath) } // Configure filters let requestFilters: [(HTTPRequestFilter, HTTPFilterPriority)] = [ (SessionRequestFilter(), .high), (AuthenticationFilter(), .medium), (ValidationFilter(), .low) ] let responseFilters: [(HTTPResponseFilter, HTTPFilterPriority)] = [ (SessionResponseFilter(), .high), (CompressionFilter(), .medium), (ErrorHandlerFilter(), .low) ] server.setRequestFilters(requestFilters) server.setResponseFilters(responseFilters) // Start server do { logger.info("Starting {{projectName}} server on \\(config.host):\\(config.port)") try server.start() } catch { logger.error("Failed to start server: \\(error)") }`, // Configuration 'Sources/Configuration.swift': `import Foundation import PerfectLib struct Configuration { let host: String let port: UInt16 let databaseURL: String let useSSL: Bool let sslCertPath: String let sslKeyPath: String let sessionTimeout: Int let cookieDomain: String let jwtSecret: String static func load() -> Configuration { // Load from environment or config file let host = ProcessInfo.processInfo.environment["HOST"] ?? "0.0.0.0" let port = UInt16(ProcessInfo.processInfo.environment["PORT"] ?? "8080") ?? 8080 let databaseURL = ProcessInfo.processInfo.environment["DATABASE_URL"] ?? "postgresql://localhost/{{projectName}}" let useSSL = ProcessInfo.processInfo.environment["USE_SSL"] == "true" let sslCertPath = ProcessInfo.processInfo.environment["SSL_CERT_PATH"] ?? "./cert.pem" let sslKeyPath = ProcessInfo.processInfo.environment["SSL_KEY_PATH"] ?? "./key.pem" let sessionTimeout = Int(ProcessInfo.processInfo.environment["SESSION_TIMEOUT"] ?? "86400") ?? 86400 let cookieDomain = ProcessInfo.processInfo.environment["COOKIE_DOMAIN"] ?? "" let jwtSecret = ProcessInfo.processInfo.environment["JWT_SECRET"] ?? generateRandomSecret() return Configuration( host: host, port: port, databaseURL: databaseURL, useSSL: useSSL, sslCertPath: sslCertPath, sslKeyPath: sslKeyPath, sessionTimeout: sessionTimeout, cookieDomain: cookieDomain, jwtSecret: jwtSecret ) } private static func generateRandomSecret() -> String { return UUID().uuidString + UUID().uuidString } }`, // Routes 'Sources/Routes.swift': `import PerfectHTTP import PerfectWebSockets import Logging let routeLogger = Logger(label: "{{projectName}}.routes") func setupRoutes(_ routes: inout Routes) { // Health check routes.add(method: .get, uri: "/health") { request, response in healthCheckHandler(request: request, response: response) } // API routes routes.add(method: .get, uri: "/api/v1") { request, response in response.setHeader(.contentType, value: "application/json") let info = [ "name": "{{projectName}} API", "version": "1.0.0", "status": "running" ] try? response.setBody(json: info) response.completed() } // WebSocket endpoint routes.add(method: .get, uri: "/ws") { request, response in WebSocketHandler.handleRequest(request: request, response: response) } // Authentication routes routes.add(method: .post, uri: "/api/v1/auth/register") { request, response in AuthController.register(request: request, response: response) } routes.add(method: .post, uri: "/api/v1/auth/login") { request, response in AuthController.login(request: request, response: response) } routes.add(method: .post, uri: "/api/v1/auth/logout") { request, response in AuthController.logout(request: request, response: response) } // User routes (protected) routes.add(method: .get, uri: "/api/v1/users") { request, response in UserController.list(request: request, response: response) } routes.add(method: .get, uri: "/api/v1/users/{id}") { request, response in UserController.get(request: request, response: response) } routes.add(method: .put, uri: "/api/v1/users/{id}") { request, response in UserController.update(request: request, response: response) } routes.add(method: .delete, uri: "/api/v1/users/{id}") { request, response in UserController.delete(request: request, response: response) } // Todo routes (protected) routes.add(method: .get, uri: "/api/v1/todos") { request, response in TodoController.list(request: request, response: response) } routes.add(method: .post, uri: "/api/v1/todos") { request, response in TodoController.create(request: request, response: response) } routes.add(method: .get, uri: "/api/v1/todos/{id}") { request, response in TodoController.get(request: request, response: response) } routes.add(method: .put, uri: "/api/v1/todos/{id}") { request, response in TodoController.update(request: request, response: response) } routes.add(method: .delete, uri: "/api/v1/todos/{id}") { request, response in TodoController.delete(request: request, response: response) } // Static file handler routes.add(method: .get, uri: "/**") { request, response in StaticFileHandler(documentRoot: "./public").handleRequest(request: request, response: response) } } func healthCheckHandler(request: HTTPRequest, response: HTTPResponse) { let health = DatabaseManager.shared.checkHealth() response.setHeader(.contentType, value: "application/json") let status = [ "status": health ? "healthy" : "unhealthy", "database": health, "timestamp": Date().timeIntervalSince1970 ] try? response.setBody(json: status) response.completed(status: health ? .ok : .serviceUnavailable) }`, // WebSocket Handler 'Sources/Handlers/WebSocketHandler.swift': `import PerfectHTTP import PerfectWebSockets import Logging class WebSocketHandler: WebSocketSessionHandler { let socketProtocol: String? = nil static let logger = Logger(label: "{{projectName}}.websocket") private var connections = [String: WebSocket]() static func handleRequest(request: HTTPRequest, response: HTTPResponse) { WebSocketHandler().handleRequest(request: request, response: response) { // Connection closed callback self.logger.info("WebSocket connection closed") } } func handleSession(request: HTTPRequest, socket: WebSocket) { let connectionId = UUID().uuidString connections[connectionId] = socket Self.logger.info("New WebSocket connection: \\(connectionId)") // Send welcome message let welcome = ["type": "welcome", "connectionId": connectionId] if let data = try? welcome.jsonEncodedString() { socket.sendStringMessage(string: data, final: true) { // Message sent } } // Handle incoming messages socket.readStringMessage { [weak self] string, opcode, final in guard let self = self, let message = string else { socket.close() return } self.handleMessage(message: message, socket: socket, connectionId: connectionId) } } private func handleMessage(message: String, socket: WebSocket, connectionId: String) { Self.logger.debug("Received message from \\(connectionId): \\(message)") // Parse and handle message guard let data = message.data(using: .utf8), let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], let type = json["type"] as? String else { return } switch type { case "ping": let pong = ["type": "pong", "timestamp": Date().timeIntervalSince1970] if let response = try? pong.jsonEncodedString() { socket.sendStringMessage(string: response, final: true) { // Pong sent } } case "broadcast": if let content = json["content"] as? String { broadcastMessage(content: content, from: connectionId) } case "echo": if let content = json["content"] as? String { let echo = ["type": "echo", "content": content] if let response = try? echo.jsonEncodedString() { socket.sendStringMessage(string: response, final: true) { // Echo sent } } } default: Self.logger.warning("Unknown message type: \\(type)") } // Continue reading messages socket.readStringMessage { [weak self] string, _, _ in guard let self = self, let msg = string else { socket.close() return } self.handleMessage(message: msg, socket: socket, connectionId: connectionId) } } private func broadcastMessage(content: String, from connectionId: String) { let broadcast = [ "type": "broadcast", "content": content, "from": connectionId, "timestamp": Date().timeIntervalSince1970 ] as [String : Any] guard let message = try? broadcast.jsonEncodedString() else { return } for (id, socket) in connections where id != connectionId { socket.sendStringMessage(string: message, final: true) { // Message sent } } } }`, // Database Manager 'Sources/Database/DatabaseManager.swift': `import PerfectPostgreSQL import PerfectMySQL import PerfectSQLite import Logging class DatabaseManager { static let shared = DatabaseManager() private let logger = Logger(label: "{{projectName}}.database") private var postgresConnection: PGConnection? private var mysqlConnection: MySQL? private var sqliteConnection: SQLite? private let config = Configuration.load() private init() { setupDatabase() } private func setupDatabase() { if config.databaseURL.hasPrefix("postgresql://") { setupPostgreSQL() } else if config.databaseURL.hasPrefix("mysql://") { setupMySQL() } else { setupSQLite() } createTables() } private func setupPostgreSQL() { let connection = PGConnection() let status = connection.connectdb(config.databaseURL) if status == .ok { postgresConnection = connection logger.info("Connected to PostgreSQL database") } else { logger.error("Failed to connect to PostgreSQL: \\(connection.errorMessage())") } } private func setupMySQL() { // Parse MySQL connection string // Implementation depends on URL format let mysql = MySQL() mysqlConnection = mysql logger.info("MySQL connection configured") } private func setupSQLite() { do { let sqlite = try SQLite("./database.sqlite") sqliteConnection = sqlite logger.info("Connected to SQLite database") } catch { logger.error("Failed to connect to SQLite: \\(error)") } } private func createTables() { // Create users table let createUsers = """ CREATE TABLE IF NOT EXISTS users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), email VARCHAR(255) UNIQUE NOT NULL, password_hash VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) """ // Create todos table let createTodos = """ CREATE TABLE IF NOT EXISTS todos ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, title VARCHAR(255) NOT NULL, description TEXT, completed BOOLEAN DEFAULT FALSE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) """ // Create sessions table let createSessions = """ CREATE TABLE IF NOT EXISTS sessions ( id VARCHAR(255) PRIMARY KEY, user_id UUID REFERENCES users(id) ON DELETE CASCADE, data TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, expires_at TIMESTAMP ) """ execute(createUsers) execute(createTodos) execute(createSessions) } func execute(_ query: String, params: [Any] = []) -> PGResult? { guard let connection = postgresConnection else { return nil } return connection.exec(statement: query, params: params) } func checkHealth() -> Bool { if let connection = postgresConnection { return connection.status == .ok } return sqliteConnection != nil || mysqlConnection != nil } }`, // Models 'Sources/Models/User.swift': `import Foundation import PerfectCrypto struct User: Codable { let id: UUID let email: String let passwordHash: String let name: String let createdAt: Date let updatedAt: Date init(email: String, password: String, name: String) throws { self.id = UUID() self.email = email self.passwordHash = try BCrypt.hash(password) self.name = name self.createdAt = Date() self.updatedAt = Date() } func verifyPassword(_ password: String) throws -> Bool { return try BCrypt.verify(password, against: passwordHash) } func toPublic() -> PublicUser { return PublicUser( id: id, email: email, name: name, createdAt: createdAt ) } } struct PublicUser: Codable { let id: UUID let email: String let name: String let createdAt: Date } extension User { static func find(by email: String) -> User? { let query = "SELECT * FROM users WHERE email = $1" guard let result = DatabaseManager.shared.execute(query, params: [email]), result.numTuples() > 0 else { return nil } return User.from(result: result, row: 0) } static func find(by id: UUID) -> User? { let query = "SELECT * FROM users WHERE id = $1" guard let result = DatabaseManager.shared.execute(query, params: [id.uuidString]), result.numTuples() > 0 else { return nil } return User.from(result: result, row: 0) } func save() throws { let query = """ INSERT INTO users (id, email, password_hash, name, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT (id) DO UPDATE SET email = EXCLUDED.email, name = EXCLUDED.name, updated_at = EXCLUDED.updated_at """ _ = DatabaseManager.shared.execute(query, params: [ id.uuidString, email, passwordHash, name, createdAt, updatedAt ]) } private static func from(result: PGResult, row: Int) -> User? { guard let id = result.getFieldString(tupleIndex: row, fieldIndex: 0), let email = result.getFieldString(tupleIndex: row, fieldIndex: 1), let passwordHash = result.getFieldString(tupleIndex: row, fieldIndex: 2), let name = result.getFieldString(tupleIndex: row, fieldIndex: 3) else { return nil } // Parse dates - implementation depends on your date format let createdAt = Date() let updatedAt = Date() return User( id: UUID(uuidString: id) ?? UUID(), email: email, passwordHash: passwordHash, name: name, createdAt: createdAt, updatedAt: updatedAt ) } }`, 'Sources/Models/Todo.swift': `import Foundation struct Todo: Codable { let id: UUID let userId: UUID let title: String let description: String? let completed: Bool let createdAt: Date let updatedAt: Date init(userId: UUID, title: String, description: String? = nil) { self.id = UUID() self.userId = userId self.title = title self.description = description self.completed = false self.createdAt = Date() self.updatedAt = Date() } } extension Todo { static func findAll(for userId: UUID) -> [Todo] { let query = "SELECT * FROM todos WHERE user_id = $1 ORDER BY created_at DESC" guard let result = DatabaseManager.shared.execute(query, params: [userId.uuidString]) else { return [] } var todos: [Todo] = [] for i in 0..<result.numTuples() { if let todo = Todo.from(result: result, row: i) { todos.append(todo) } } return todos } static func find(by id: UUID, userId: UUID) -> Todo? { let query = "SELECT * FROM todos WHERE id = $1 AND user_id = $2" guard let result = DatabaseManager.shared.execute(query, params: [id.uuidString, userId.uuidString]), result.numTuples() > 0 else { return nil } return Todo.from(result: result, row: 0) } func save() throws { let query = """ INSERT INTO todos (id, user_id, title, description, completed, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7) ON CONFLICT (id) DO UPDATE SET title = EXCLUDED.title, description = EXCLUDED.description, completed = EXCLUDED.completed, updated_at = EXCLUDED.updated_at """ _ = DatabaseManager.shared.execute(query, params: [ id.uuidString, userId.uuidString, title, description ?? NSNull(), completed, createdAt, updatedAt ]) } func delete() throws { let query = "DELETE FROM todos WHERE id = $1" _ = DatabaseManager.shared.execute(query, params: [id.uuidString]) } private static func from(result: PGResult, row: Int) -> Todo? { guard let id = result.getFieldString(tupleIndex: row, fieldIndex: 0), let userId = result.getFieldString(tupleIndex: row, fieldIndex: 1), let title = result.getFieldString(tupleIndex: row, fieldIndex: 2) else { return nil } let description = result.getFieldString(tupleIndex: row, fieldIndex: 3) let completed = result.getFieldBool(tupleIndex: row, fieldIndex: 4) ?? false return Todo( id: UUID(uuidString: id) ?? UUID(), userId: UUID(uuidString: userId) ?? UUID(), title: title, description: description, completed: completed, createdAt: Date(), updatedAt: Date() ) } }`, // Controllers 'Sources/Controllers/AuthController.swift': `import PerfectHTTP import PerfectCrypto import Foundation class AuthController { static func register(request: HTTPRequest, response: HTTPResponse) { guard let body = request.postBodyString, let data = body.data(using: .utf8), let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], let email = json["email"] as? String, let password = json["password"] as? String, let name = json["name"] as? String else { response.completed(status: .badRequest) return } // Check if user exists if User.find(by: email) != nil { response.setHeader(.contentType, value: "application/json") let error = ["error": "User already exists"] try? response.setBody(json: error) response.completed(status: .conflict) return } // Create user do { let user = try User(email: email, password: password, name: name) try user.save() // Create session request.session?.userid = user.id.uuidString // Return user response.setHeader(.contentType, value: "application/json") let result = [ "user": user.toPublic(), "token": generateToken(for: user) ] try? response.setBody(json: result) response.completed() } catch { response.completed(status: .internalServerError) } } static func login(request: HTTPRequest, response: HTTPResponse) { guard let body = request.postBodyString, let data = body.data(using: .utf8), let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], let email = json["email"] as? String, let password = json["password"] as? String else { response.completed(status: .badRequest) return } // Find user guard let user = User.find(by: email), (try? user.verifyPassword(password)) == true else { response.setHeader(.contentType, value: "application/json") let error = ["error": "Invalid credentials"] try? response.setBody(json: error) response.completed(status: .unauthorized) return } // Create session request.session?.userid = user.id.uuidString // Return user response.setHeader(.contentType, value: "application/json") let result = [ "user": user.toPublic(), "token": generateToken(for: user) ] try? response.setBody(json: result) response.completed() } static func logout(request: HTTPRequest, response: HTTPResponse) { request.session?.userid = nil response.completed() } private static func generateToken(for user: User) -> String { // Simple token generation - in production use JWT let payload = "\\(user.id.uuidString):\\(Date().timeIntervalSince1970)" return payload.digest(.sha256)?.encode(.base64url) ?? "" } }`, 'Sources/Controllers/UserController.swift': `import PerfectHTTP import Foundation class UserController { static func list(request: HTTPRequest, response: HTTPResponse) { // Check authentication guard let _ = request.session?.userid else { response.completed(status: .unauthorized) return } // For demo purposes, return empty array response.setHeader(.contentType, value: "application/json") try? response.setBody(json: []) response.completed() } static func get(request: HTTPRequest, response: HTTPResponse) { guard let userId = request.session?.userid, let userUUID = UUID(uuidString: userId), let user = User.find(by: userUUID) else { response.completed(status: .unauthorized) return } response.setHeader(.contentType, value: "application/json") try? response.setBody(json: user.toPublic()) response.completed() } static func update(request: HTTPRequest, response: HTTPResponse) { guard let userId = request.session?.userid, let userUUID = UUID(uuidString: userId), let user = User.find(by: userUUID) else { response.completed(status: .unauthorized) return } guard let body = request.postBodyString, let data = body.data(using: .utf8), let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { response.completed(status: .badRequest) return } // Update user fields var updatedUser = user if let name = json["name"] as? String { updatedUser = User( id: user.id, email: user.email, passwordHash: user.passwordHash, name: name, createdAt: user.createdAt, updatedAt: Date() ) } try? updatedUser.save() response.setHeader(.contentType, value: "application/json") try? response.setBody(json: updatedUser.toPublic()) response.completed() } static func delete(request: HTTPRequest, response: HTTPResponse) { guard let userId = request.session?.userid else { response.completed(status: .unauthorized) return } // Delete user let query = "DELETE FROM users WHERE id = $1" _ = DatabaseManager.shared.execute(query, params: [userId]) // Clear session request.session?.userid = nil response.completed(status: .noContent) } }`, 'Sources/Controllers/TodoController.swift': `import PerfectHTTP import Foundation class TodoController { static func list(request: HTTPRequest, response: HTTPResponse) { guard let userId = request.session?.userid, let userUUID = UUID(uuidString: userId) else { response.completed(status: .unauthorized) return } let todos = Todo.findAll(for: userUUID) response.setHeader(.contentType, value: "application/json") try? response.setBody(json: todos) response.completed() } static func create(request: HTTPRequest, response: HTTPResponse) { guard let userId = request.session?.userid, let userUUID = UUID(uuidString: userId) else { response.completed(status: .unauthorized) return } guard let body = request.postBodyString, let data = body.data(using: .utf8), let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], let title = json["title"] as? String else { response.completed(status: .badRequest) return } let description = json["description"] as? String let todo = Todo(userId: userUUID, title: title, description: description) try? todo.save() response.setHeader(.contentType, value: "application/json") try? response.setBody(json: todo) response.completed() } static func get(request: HTTPRequest, response: HTTPResponse) { guard let userId = request.session?.userid, let userUUID = UUID(uuidString: userId), let todoId = request.urlVariables["id"], let todoUUID = UUID(uuidString: todoId), let todo = Todo.find(by: todoUUID, userId: userUUID) else { response.completed(status: .notFound) return } response.setHeader(.contentType, value: "application/json") try? response.setBody(json: todo) response.completed() } static func update(request: HTTPRequest, response: HTTPResponse) { guard let userId = request.session?.userid, let userUUID = UUID(uuidString: userId), let todoId = request.urlVariables["id"], let todoUUID = UUID(uuidString: todoId), var todo = Todo.find(by: todoUUID, userId: userUUID) else { response.completed(status: .notFound) return } guard let body = request.postBodyString, let data = body.data(using: .utf8), let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { response.completed(status: .badRequest) return } // Update fields if let title = json["title"] as? String { todo = Todo( id: todo.id, userId: todo.userId, title: title, description: todo.description, completed: todo.completed, createdAt: todo.createdAt, updatedAt: Date() ) } if let completed = json["completed"] as? Bool { todo = Todo( id: todo.id, userId: todo.userId, title: todo.title, description: todo.description, completed: completed, createdAt: todo.createdAt, updatedAt: Date() ) } try? todo.save() response.setHeader(.contentType, value: "application/json") try? response.setBody(json: todo) response.completed() } static func delete(request: HTTPRequest, response: HTTPResponse) { guard let userId = request.session?.userid, let userUUID = UUID(uuidString: userId), let todoId = request.urlVariables["id"], let todoUUID = UUID(uuidString: todoId), let todo = Todo.find(by: todoUUID, userId: userUUID) else { response.completed(status: .notFound) return } try? todo.delete() response.completed(status: .noContent) } }`, // Middleware 'Sources/Middleware/AuthenticationFilter.swift': `import PerfectHTTP struct AuthenticationFilter: HTTPRequestFilter { func filter(request: HTTPRequest, response: HTTPResponse, callback: (HTTPRequestFilterResult) -> ()) { // Check if route requires authentication let publicPaths = ["/", "/health", "/api/v1", "/api/v1/auth/register", "/api/v1/auth/login"] if publicPaths.contains(request.path) { callback(.continue(request, response)) return } // Check session if request.session?.userid != nil { callback(.continue(request, response)) return } // Check Bearer token if let auth = request.header(.authorization), auth.hasPrefix("Bearer ") { let token = String(auth.dropFirst(7)) // Validate token - implementation depends on your token strategy if validateToken(token) { callback(.continue(request, response)) return } } // Unauthorized response.status = .unauthorized response.setHeader(.contentType, value: "application/json") let error = ["error": "Authentication required"] try? response.setBody(json: error) callback(.halt(request, response)) } private func validateToken(_ token: String) -> Bool { // Implement token validation return false } }`, 'Sources/Middleware/CORSHandler.swift': `import PerfectHTTP struct CORSHandler { static func handler(request: HTTPRequest, response: HTTPResponse) { response.setHeader(.accessControlAllowOrigin, value: "*") response.setHeader(.accessControlAllowHeaders, value: "Accept, Content-Type, Authorization") response.setHeader(.accessControlAllowMethods, value: "GET, POST, PUT, DELETE, OPTIONS") response.setHeader(.accessControlMaxAge, value: "3600") if request.method == .options { response.completed() } } }`, 'Sources/Middleware/CompressionFilter.swift': `import PerfectHTTP import PerfectLib struct CompressionFilter: HTTPResponseFilter { func filterBody(response: HTTPResponse, callback: (HTTPResponseFilterResult) -> ()) { // Check if client accepts gzip guard let acceptEncoding = response.request.header(.acceptEncoding), acceptEncoding.contains("gzip") else { callback(.continue) return } // Compress response body if it's large enough if let body = response.bodyBytes, body.count > 1024 { // Implementation of gzip compression would go here // For now, just pass through callback(.continue) } else { callback(.continue) } } func filterHeaders(response: HTTPResponse, callback: (HTTPResponseFilterResult) -> ()) { callback(.continue) } }`, 'Sources/Middleware/ErrorHandlerFilter.swift': `import PerfectHTTP import Logging struct ErrorHandlerFilter: HTTPResponseFilter { private let logger = Logger(label: "{{projectName}}.error") func filterBody(response: HTTPResponse, callback: (HTTPResponseFilterResult) -> ()) { callback(.continue) } func filterHeaders(response: HTTPResponse, callback: (HTTPResponseFilterResult) -> ()) { // Log errors if response.status.code >= 400 { logger.error("Request failed: \\(response.request.path) - Status: \\(response.status.code)") } // Ensure error responses have proper content type if response.status.code >= 400 && response.header(.contentType) == nil { response.setHeader(.contentType, value: "application/json") let error = [ "error": HTTPResponseStatus.statusFrom(code: response.status.code).description, "status": response.status.code ] try? response.setBody(json: error) } callback(.continue) } }`, 'Sources/Middleware/ValidationFilter.swift': `import PerfectHTTP struct ValidationFilter: HTTPRequestFilter { func filter(request: HTTPRequest, response: HTTPResponse, callback: (HTTPRequestFilterResult) -> ()) { // Validate content type for POST/PUT requests if request.method == .post || request.method == .put { if let contentType = request.header(.contentType), !contentType.contains("application/json") && !contentType.contains("multipart/form-data") { response.status = .unsupportedMediaType let error = ["error": "Content-Type must be application/json or multipart/form-data"] try? response.setBody(json: error) callback(.halt(request, response)) return } } callback(.continue(request, response)) } }`, // Tests 'Tests/{{projectName}}Tests.swift': `import XCTest @testable import {{projectName}} import PerfectHTTP import PerfectHTTPServer final class {{projectName}}Tests: XCTestCase { var server: HTTPServer! override func setUp() { super.setUp() server = HTTPServer() server.serverPort = 8181 var routes = Routes() setupRoutes(&routes) server.addRoutes(routes) try? server.start() } override func tearDown() { server.stop() super.tearDown() } func testHealthEndpoint() { let expectation = self.expectation(description: "Health check") let url = URL(string: "http://localhost:8181/health")! let task = URLSession.shared.dataTask(with: url) { data, response, error in XCTAssertNil(error) XCTAssertNotNil(data) if let httpResponse = response as? HTTPURLResponse { XCTAssertEqual(httpResponse.statusCode, 200) } expectation.fulfill() } task.resume() wait(for: [expectation], timeout: 5.0) } func testAPIEndpoint() { let expectation = self.expectation(description: "API info") let url = URL(string: "http://localhost:8181/api/v1")! let task = URLSession.shared.dataTask(with: url) { data, response, error in XCTAssertNil(error) XCTAssertNotNil(data) if let httpResponse = response as? HTTPURLResponse { XCTAssertEqual(httpResponse.statusCode, 200) } if let data = data, let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] { XCTAssertEqual(json["name"] as? String, "{{projectName}} API") XCTAssertEqual(json["version"] as? String, "1.0.0") } expectation.fulfill() } task.resume() wait(for: [expectation], timeout: 5.0) } }`, // Environment configuration '.env.example': `# Server Configuration HOST=0.0.0.0 PORT=8080 # Database Configuration DATABASE_URL=postgresql://localhost/{{projectName}} # SSL Configuration USE_SSL=false SSL_CERT_PATH=./cert.pem SSL_KEY_PATH=./key.pem # Session Configuration SESSION_TIMEOUT=86400 COOKIE_DOMAIN= # Security JWT_SECRET=your-secret-key-here`, // Docker configuration 'Dockerfile': `# ================================ # Build image # ================================ FROM swift:5.9-jammy as build # Install system dependencies RUN apt-get update && apt-get install -y \ libssl-dev \ libcurl4-openssl-dev \ libpq-dev \ libmysqlclient-dev \ libsqlite3-dev \ uuid-dev \ && rm -rf /var/lib/apt/lists/* # Set up a build area WORKDIR /build # Copy package files COPY Package.* ./ # Resolve dependencies RUN swift package resolve # Copy entire repo into container COPY . . # Build with optimizations RUN swift build -c release # ================================ # Run image # ================================ FROM ubuntu:22.04 # Install runtime dependencies RUN apt-get update && apt-get install -y \ libssl3 \ libcurl4 \ libpq5 \ libmysqlclient21 \ libsqlite3-0 \ uuid-runtime \ ca-certificates \ tzdata \ && rm -rf /var/lib/apt/lists/* # Create app user RUN useradd --create-home --shell /bin/bash app WORKDIR /app # Copy build artifacts COPY --from=build /build/.build/release/{{projectName}} . COPY --from=build /build/public ./public # Set ownership RUN chown -R app:app /app USER app # Expose port EXPOSE 8080 # Run the app CMD ["./{{projectName}}"]`, 'docker-compose.yml': `version: '3.8' services: app: build: . ports: - "8080:8080" environment: - HOST=0.0.0.0 - PORT=8080 - DATABASE_URL=postgresql://perfect:perfect@db/{{projectName}} depends_on: - db volumes: - ./public:/app/public db: image: postgres:15-alpine environment: - POSTGRES_USER=perfect - POSTGRES_PASSWORD=perfect - POSTGRES_DB={{projectName}} ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data volumes: postgres_data:`, // README 'README.md': `# {{projectName}} A high-performance server-side Swift application built with Perfect. ## Features - ✅ RESTful API with Perfect HTTPServer - ✅ WebSocket support for real-time communication - ✅ PostgreSQL, MySQL, and SQLite database support - ✅ Session management and authentication - ✅ Request logging and monitoring - ✅ CORS support - ✅ SSL/TLS support - ✅ Docker ready ## Requirements - Swift 5.9 or later - macOS 12+ or Ubuntu 22.04+ ## Getting Started 1. Clone the repository 2. Install dependencies: \`\`\`bash swift package resolve \`\`\` 3. Copy \`.env.example\` to \`.env\` and configure 4. Build and run: \`\`\`bash swift build swift run \`\`\` The server will start on port 8080 by default. ## API Endpoints ### Public Endpoints - \`GET /health\` - Health check - \`GET /api/v1\` - API information - \`POST /api/v1/auth/register\` - Register new user - \`POST /api/v1/auth/login\` - Login - \`POST /api/v1/auth/logout\` - Logout ### Protected Endpoints - \`GET /api/v1/users\` - List users - \`GET /api/v1/users/{id}\` - Get user - \`PUT /api/v1/users/{id}\` - Update user - \`DELETE /api/v1/users/{id}\` - Delete user - \`GET /api/v1/todos\` - List todos - \`POST /api/v1/todos\` - Create todo - \`GET /api/v1/todos/{id}\` - Get todo - \`PUT /api/v1/todos/{id}\` - Update todo - \`DELETE /api/v1/todos/{id}\` - Delete todo ### WebSocket Endpoint - \`WS /ws\` - WebSocket connection for real-time communication ## Running with Docker \`\`\`bash docker-compose up \`\`\` ## Testing Run the test suite: \`\`\`bash swift test \`\`\` ## Configuration See \`.env.example\` for available configuration options. ## License MIT`, '.gitignore': `# Swift .DS_Store /.build /Packages /*.xcodeproj xcuserdata/ DerivedData/ .swiftpm/config/registries.json .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata .netrc # Perfect *.log *.pid # Environment .env .env.local # Database *.sqlite *.sqlite3 # Certificates *.pem *.key *.crt`, }, };