Skip to content

Commit

Permalink
🤌
Browse files Browse the repository at this point in the history
  • Loading branch information
imhoffd committed Jun 5, 2022
0 parents commit e55e33d
Show file tree
Hide file tree
Showing 43 changed files with 2,526 additions and 0 deletions.
17 changes: 17 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: CI

on:
push:
branches:
- '**'
pull_request:
branches:
- '**'

jobs:
lint:
runs-on: macos-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v2
- run: swiftlint --strict .
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
xcuserdata
DerivedData/
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
19 changes: 19 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
excluded:
- Package.swift
disabled_rules:
- todo
opt_in_rules:
- file_name_no_space
- force_unwrapping
- function_default_parameter_at_end
- implicitly_unwrapped_optional
- lower_acl_than_parent
- modifier_order
- overridden_super_call
- unowned_variable_capture
- unused_import
line_length: 100
identifier_name:
excluded:
- id
- to
675 changes: 675 additions & 0 deletions LICENSE.md

Large diffs are not rendered by default.

26 changes: 26 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// swift-tools-version:5.5

import PackageDescription

let package = Package(
name: "Peregrine",
platforms: [
.iOS(.v14)
],
products: [
.library(
name: "Peregrine",
targets: ["Peregrine"]
),
],
targets: [
.target(
name: "Peregrine",
dependencies: []
),
.testTarget(
name: "PeregrineTests",
dependencies: ["Peregrine"]
),
]
)
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Peregrine for iOS

TODO
59 changes: 59 additions & 0 deletions Sources/Peregrine/Call.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Peregrine for iOS: native container for hybrid apps
// Copyright (C) 2022 Caracal LLC
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License version 3 as published
// by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License version 3
// along with this program. If not, see <https://www.gnu.org/licenses/>.

import Foundation

public struct Call {
public let request: Request
internal let didRespond: (Response) -> Void

internal init(request: Request, didRespond: @escaping (Response) -> Void) {
self.request = request
self.didRespond = didRespond
}

public func respond() {
respond(with: Data())
}

public func respond(with data: Data) {
respond(Response(data, status: .success))
}

public func respond(with text: String) {
respond(Response(text, status: .success))
}

public func respond<T: Encodable>(with json: T) throws {
respond(try Response(json, status: .success))
}

public func fail(_ message: String?, code: String? = nil) {
fail(with: CallError(message ?? "Error", code: code))
}

internal func respond(_ response: Response) {
didRespond(response)
}

internal func fail(with error: CallError) {
let response = try! Response( // swiftlint:disable:this force_try
error,
status: .error
)

respond(response)
}
}
26 changes: 26 additions & 0 deletions Sources/Peregrine/CallError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Peregrine for iOS: native container for hybrid apps
// Copyright (C) 2022 Caracal LLC
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License version 3 as published
// by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License version 3
// along with this program. If not, see <https://www.gnu.org/licenses/>.

import Foundation

internal struct CallError: Encodable {
internal let message: String
internal let code: String?

internal init(_ message: String, code: String? = nil) {
self.message = message
self.code = code
}
}
22 changes: 22 additions & 0 deletions Sources/Peregrine/Data+headers.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Peregrine for iOS: native container for hybrid apps
// Copyright (C) 2022 Caracal LLC
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License version 3 as published
// by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License version 3
// along with this program. If not, see <https://www.gnu.org/licenses/>.

import Foundation

internal extension Data {
var headers: Headers {
return ["Content-Length": "\(count)"]
}
}
36 changes: 36 additions & 0 deletions Sources/Peregrine/Event.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Peregrine for iOS: native container for hybrid apps
// Copyright (C) 2022 Caracal LLC
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License version 3 as published
// by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License version 3
// along with this program. If not, see <https://www.gnu.org/licenses/>.

import Foundation

public struct Event: Transferable {
public let type: TransferableType = .json
public let data: Data

public init() {
data = Data()
}

public init?<T: Encodable>(_ json: T) {
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601

do {
data = try encoder.encode(json)
} catch {
return nil
}
}
}
31 changes: 31 additions & 0 deletions Sources/Peregrine/FileServer+Configuration.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Peregrine for iOS: native container for hybrid apps
// Copyright (C) 2022 Caracal LLC
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License version 3 as published
// by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License version 3
// along with this program. If not, see <https://www.gnu.org/licenses/>.

import Foundation

extension FileServer {
internal struct Configuration {
internal let scheme: String
internal let baseURL: URL

internal init(
scheme: String,
baseURL: URL
) {
self.scheme = scheme
self.baseURL = baseURL
}
}
}
100 changes: 100 additions & 0 deletions Sources/Peregrine/FileServer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Peregrine for iOS: native container for hybrid apps
// Copyright (C) 2022 Caracal LLC
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License version 3 as published
// by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License version 3
// along with this program. If not, see <https://www.gnu.org/licenses/>.

import Foundation

internal final class FileServer: Server, ServerProtocol {
internal let configuration: Configuration

internal init(configuration: Configuration) {
self.configuration = configuration
}

internal func respond(
to request: URLRequest,
usingHandler handler: ServerResponseHandler
) {
let url = request.url! // swiftlint:disable:this force_unwrapping
let path = normalize(path: url.path)
let fileURL = configuration.baseURL.appendingPathComponent(
path,
isDirectory: false
)

respondWithFile(
to: request,
fileURL: fileURL,
usingHandler: handler
)
}

internal func stopResponding(to _: URLRequest) {}

private func normalize(path: String) -> String {
guard let lastCharacter = path.last else {
return path
}

switch lastCharacter {
case "/":
return "\(path)index.html"
default:
return path
}
}

private func respondWithFile(
to request: URLRequest,
fileURL: URL,
usingHandler handler: ServerResponseHandler
) {
guard let bytes = try? Data(contentsOf: fileURL) else {
log(
"""
File not found at '\(fileURL.absoluteString)'. Server will \
respond with 404 Not Found.
""",
level: .warn
)

respondWithNotFound(
to: request,
message: "Not Found",
usingHandler: handler
)

return
}

let url = request.url! // swiftlint:disable:this force_unwrapping
let mimeType = MimeType(forExtension: fileURL.pathExtension)
let httpHeaders = headers()
.merging(bytes.headers) { $1 }
.merging(mimeType.headers) { $1 }

let httpResponse = HTTPURLResponse(
url: url,
statusCode: 200,
httpVersion: nil,
headerFields: httpHeaders
)! // swiftlint:disable:this force_unwrapping

respond(
response: httpResponse,
body: bytes,
usingHandler: handler
)
}
}
23 changes: 23 additions & 0 deletions Sources/Peregrine/Frame.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Peregrine for iOS: native container for hybrid apps
// Copyright (C) 2022 Caracal LLC
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License version 3 as published
// by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License version 3
// along with this program. If not, see <https://www.gnu.org/licenses/>.

import Foundation
import SwiftUI

public protocol Frame {
associatedtype FrameView: View

var view: FrameView { get }
}
Loading

0 comments on commit e55e33d

Please sign in to comment.