{"id":15038083,"url":"https://github.com/skylab-inc/lightning","last_synced_at":"2025-04-09T23:19:51.783Z","repository":{"id":63920523,"uuid":"57951258","full_name":"skylab-inc/Lightning","owner":"skylab-inc","description":"A Swift Multiplatform Single-threaded Non-blocking Web and Networking Framework","archived":false,"fork":false,"pushed_at":"2018-01-02T05:03:39.000Z","size":369,"stargazers_count":312,"open_issues_count":9,"forks_count":14,"subscribers_count":15,"default_branch":"master","last_synced_at":"2024-05-21T02:30:38.066Z","etag":null,"topics":["asynchronous","asynchronous-events","edge","frp","functional-reactive-programming","libdispatch","lightning","nodejs","non-blocking","non-blocking-sockets","nonblocking","reactivecocoa","single-thread","swift","swift-package-manager","swift4","tcp","thread-safe"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/skylab-inc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-05-03T07:49:00.000Z","updated_at":"2024-03-04T04:44:10.000Z","dependencies_parsed_at":"2022-11-29T10:45:17.474Z","dependency_job_id":null,"html_url":"https://github.com/skylab-inc/Lightning","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skylab-inc%2FLightning","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skylab-inc%2FLightning/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skylab-inc%2FLightning/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skylab-inc%2FLightning/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skylab-inc","download_url":"https://codeload.github.com/skylab-inc/Lightning/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248125994,"owners_count":21051847,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asynchronous","asynchronous-events","edge","frp","functional-reactive-programming","libdispatch","lightning","nodejs","non-blocking","non-blocking-sockets","nonblocking","reactivecocoa","single-thread","swift","swift-package-manager","swift4","tcp","thread-safe"],"created_at":"2024-09-24T20:37:01.577Z","updated_at":"2025-04-09T23:19:51.757Z","avatar_url":"https://github.com/skylab-inc.png","language":"Swift","readme":"\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://user-images.githubusercontent.com/6432361/34271845-06608678-e65c-11e7-896a-a4eeb2991300.png\" height=\"224\" alt=\"Edge\"\u003e\n\u003cbr/\u003eServerside non-blocking IO \u003cb\u003ein Swift\u003c/b\u003e\u003cbr/\u003e\nAsk questions in our \u003ca href=\"https://slackin-on-edge.herokuapp.com\"\u003eSlack\u003c/a\u003e channel!\u003cbr/\u003e\n\u003c/p\u003e\n\n\n# Lightning\n##### (formerly Edge)\n\n![Swift](http://img.shields.io/badge/swift-4.0.2-brightgreen.svg)\n[![Build Status](https://travis-ci.org/skylab-inc/Lightning.svg?branch=master)](https://travis-ci.org/skylab-inc/Lightning)\n[![codecov](https://codecov.io/gh/skylab-inc/Lightning/branch/master/graph/badge.svg)](https://codecov.io/gh/skylab-inc/Lightning)\n[![Slack Status](https://slackin-on-edge.herokuapp.com/badge.svg)](https://slackin-on-edge.herokuapp.com)\n\n#### Node\nLightning is an HTTP Server and TCP Client/Server framework written in Swift and inspired by [Node.js](https://nodejs.org). It runs on both OS X and Linux. Like Node.js, Lightning uses an **event-driven, non-blocking I/O model**. In the same way that Node.js uses [libuv](http://libuv.org) to implement this model, Lightning uses [libdispatch](https://github.com/apple/swift-corelibs-libdispatch). \n\nThis makes Lightning fast, efficient, and most crutially **single-threaded** by default. You simply do not need to worry about locks/mutexes/semaphores/etc if you have server-side state. Of course, Lightning applications can make use of libdispatch to easily offload heavy processing to a background thread if necessary.\n\n#### Reactive Programming\nLightning's event API embraces Functional Reactive Programming by generalizing the familiar concept of promises. This API is called [StreamKit](https://github.com/skylab-inc/StreamKit).\n\n\u003e StreamKit's architecture is inspired by both [ReactiveCocoa](https://github.com/ReactiveCocoa/ReactiveCocoa) and [RxSwift](https://github.com/ReactiveX/RxSwift).\n\n##### Why did we reimplement?\n* Lightning should be easy to use out of the box.\n* Lightning is optimized for maximum performance, which requires careful tuning of the internals.\n* The modified API is meant to be more similar to the familiar concepts of Futures and Promises.\n* We don't want to be opinionated about any one framework. We want it to be easy to integate Lightning with either ReactiveCocoa or RxSwift.\n\n\u003eFRP, greatly simplies management of asynchronous events. The general concept is that we can build a spout which pushes out asynchronous events as they happen. Then we hookup a pipeline of transformations that operate on events and pass the transformed values along. We can even do things like merge streams in interesting ways! Take a look at some of these [operations](http://rxmarbles.com) or watch [this talk](https://www.youtube.com/watch?v=XRYN2xt11Ek) about how FRP is used at Netflix. \n\n# Installation\n\nLightning is available as a Swift 3/4 package. Simply add Lightning as a dependency to your Swift Package.\n\nSwift 3\n```Swift\nimport PackageDescription\n\nlet package = Package(\n    name: \"MyProject\",\n    dependencies: [\n        .Package(url: \"https://github.com/skylab-inc/Lightning.git\", majorVersion: 0, minor: 3)\n    ]\n)\n```\nSwift 4\n```Swift\n// swift-tools-version:4.0\n// The swift-tools-version declares the minimum version of Swift required to build this package.\nimport PackageDescription\n\nlet package = Package(\n    name: \"MyProject\",\n    dependencies: [\n        .package(url: \"https://github.com/skylab-inc/Lightning.git\", from: \"0.3.0\"),\n    ]\n)\n```\n\n# Usage\n\n### Routing\n```swift\nimport Lightning\nimport Foundation\n\n// Create an API router.\nlet api = Router()\n\n// Add a GET \"/users\" endpoint.\napi.get(\"/users\") { request in\n    return Response(status: .ok)\n}\n\n// NOTE: Equivalent to `api.post(\"/auth/login\")`\nlet auth = api.subrouter(\"/auth\")\nauth.post(\"/login\") { request in\n    return Response(status: .ok)\n}\n\n// Middleware to log all requests\n// NOTE: Middleware is a simple as a map function or closure!\nlet app = Router()\napp.map { request in\n    print(request)\n    return request\n}\n\n// Mount the API router under \"/v1.0\".\napp.add(\"/v1.0\", api)\n\n// NOTE: Warnings on all unhandled requests. No more hanging clients!\napp.any { _ in\n    return Response(status: .notFound)\n}\n\n// Start the application.\napp.start(host: \"0.0.0.0\", port: 3000)\n```\n\n### Raw HTTP\n```swift\nimport Lightning\nimport Foundation\n\nfunc handleRequest(request: Request) -\u003e Response {\n    print(String(bytes: request.body, encoding: .utf8)!)\n    return try! Response(json: [\"message\": \"Message received!\"])\n}\n\nlet server = HTTP.Server()\nserver.listen(host: \"0.0.0.0\", port: 3000).startWithNext { client in\n\n    let requestStream = client.read()\n    requestStream.map(handleRequest).onNext{ response in\n        client.write(response).start()\n    }\n\n    requestStream.onFailed { clientError in\n        print(\"Oh no, there was an error! \\(clientError)\")\n    }\n\n    requestStream.onCompleted {\n        print(\"Goodbye \\(client)!\")\n    }\n\n    requestStream.start()\n}\n\nRunLoop.runAll()\n```\n\n### TCP\n```Swift\n\nimport Lightning\nimport Foundation\n\nlet server = try! TCP.Server()\ntry! server.bind(host: \"0.0.0.0\", port: 50000)\n    \nserver.listen().startWithNext { connection in\n    let byteStream = connection.read()\n    let strings = byteStream.map { String(bytes: $0, encoding: .utf8)! }\n    \n    strings.onNext { message in\n        print(\"Client \\(connection) says \\\"\\(message)\\\"!\")\n    }\n    \n    strings.onFailed { error in\n        print(\"Oh no, there was an error! \\(error)\")\n    }\n    \n    strings.onCompleted {\n        print(\"Goodbye \\(connection)!\")\n    }\n    \n    strings.start()\n}\n\nRunLoop.runAll()\n```\n\n\n### Lightning is not Node.js\n\nLightning is not meant to fulfill all of the roles of Node.js. Node.js is a JavaScript runtime, while Lightning is a TCP/Web server framework. The Swift compiler and package manager, combined with third-party Swift packages, make it unnecessary to build that functionality into Lightning.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskylab-inc%2Flightning","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskylab-inc%2Flightning","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskylab-inc%2Flightning/lists"}