{"id":14987996,"url":"https://github.com/apache/openwhisk-runtime-swift","last_synced_at":"2025-03-17T09:07:41.287Z","repository":{"id":38779861,"uuid":"105293077","full_name":"apache/openwhisk-runtime-swift","owner":"apache","description":"Apache OpenWhisk Runtime Swift supports Apache OpenWhisk functions written in Swift","archived":false,"fork":false,"pushed_at":"2024-09-24T14:26:12.000Z","size":27286,"stargazers_count":26,"open_issues_count":2,"forks_count":23,"subscribers_count":32,"default_branch":"master","last_synced_at":"2025-03-04T10:09:20.424Z","etag":null,"topics":["apache","cloud","docker","faas","functions","functions-as-a-service","openwhisk","openwhisk-runtime","serverless","serverless-architectures","serverless-functions","swift"],"latest_commit_sha":null,"homepage":"https://openwhisk.apache.org/","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/apache.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-09-29T16:17:39.000Z","updated_at":"2024-11-21T17:52:50.000Z","dependencies_parsed_at":"2024-12-26T00:16:44.429Z","dependency_job_id":null,"html_url":"https://github.com/apache/openwhisk-runtime-swift","commit_stats":{"total_commits":854,"total_committers":77,"mean_commits":"11.090909090909092","dds":0.8067915690866511,"last_synced_commit":"6653cca685f5ff5b72f934e0b9417b7e5d352023"},"previous_names":[],"tags_count":43,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apache%2Fopenwhisk-runtime-swift","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apache%2Fopenwhisk-runtime-swift/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apache%2Fopenwhisk-runtime-swift/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apache%2Fopenwhisk-runtime-swift/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/apache","download_url":"https://codeload.github.com/apache/openwhisk-runtime-swift/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244006259,"owners_count":20382441,"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":["apache","cloud","docker","faas","functions","functions-as-a-service","openwhisk","openwhisk-runtime","serverless","serverless-architectures","serverless-functions","swift"],"created_at":"2024-09-24T14:15:55.901Z","updated_at":"2025-03-17T09:07:41.262Z","avatar_url":"https://github.com/apache.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!--\n#\n# Licensed to the Apache Software Foundation (ASF) under one or more\n# contributor license agreements.  See the NOTICE file distributed with\n# this work for additional information regarding copyright ownership.\n# The ASF licenses this file to You under the Apache License, Version 2.0\n# (the \"License\"); you may not use this file except in compliance with\n# the License.  You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n--\u003e\n\n# Apache OpenWhisk runtimes for swift\n[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0)\n[![Continuous Integration](https://github.com/apache/openwhisk-runtime-swift/actions/workflows/ci.yaml/badge.svg)](https://github.com/apache/openwhisk-runtime-swift/actions/workflows/ci.yaml)\n\n## Changelogs\n- [Swift 5.1   CHANGELOG.md](core/swift51Action/CHANGELOG.md)\n- [Swift 5.3   CHANGELOG.md](core/swift53Action/CHANGELOG.md)\n- [Swift 5.4   CHANGELOG.md](core/swift54Action/CHANGELOG.md)\n- [Swift 5.7   CHANGELOG.md](core/swift57Action/CHANGELOG.md)\n\n## Quick Swift Action\n### Simple swift action hello.swift\nThe traditional support for the dictionary still works:\n```swift\nimport Foundation\n\nfunc main(args: Any) -\u003e Any {\n    let dict = args as! [String:Any]\n    if let name = dict[\"name\"] as? String {\n        return [ \"greeting\" : \"Hello \\(name)!\" ]\n    } else {\n        return [ \"greeting\" : \"Hello stranger!\" ]\n    }\n}\n```\n\nFor the return result, not only support `dictionary`, but also support `array`\n\nSo a very simple `hello array` function would be:\n\n```swift\nfunc main(args: Any) -\u003e Any {\n    var arr = [\"a\", \"b\"]\n    return arr\n}\n```\n\nAnd support array result for sequence action as well, the first action's array result can be used as next action's input parameter.\n\nSo the function can be:\n\n```swift\n func main(args: Any) -\u003e Any {\n     return args\n }\n```\nWhen invoking the above action, we can pass an array object as the input parameter.\n\n## Swift 5.x support\n\nSome examples of using Codable In and Out\n### Codable style function signature\nCreate file `helloCodableAsync.swift`\n```swift\n\nimport Foundation\n\n// Domain model/entity\nstruct Employee: Codable {\n  let id: Int?\n  let name: String?\n}\n// codable main function\nfunc main(input: Employee, respondWith: (Employee?, Error?) -\u003e Void) -\u003e Void {\n    // For simplicity, just passing same Employee instance forward\n    respondWith(input, nil)\n}\n```\n```bash\nwsk action update helloCodableAsync helloCodableAsync.swift swift:5.1\n```\n```bash\nok: updated action helloCodableAsync\n```\n```bash\nwsk action invoke helloCodableAsync -r -p id 73 -p name Andrea\n```\n```json\n{\n    \"id\": 73,\n    \"name\": \"Andrea\"\n}\n```\n\n### Codable Error Handling\nCreate file `helloCodableAsync.swift`\n```swift\n\nimport Foundation\n\nstruct Employee: Codable {\n    let id: Int?\n    let name: String?\n}\nenum VendingMachineError: Error {\n    case invalidSelection\n    case insufficientFunds(coinsNeeded: Int)\n    case outOfStock\n}\nfunc main(input: Employee, respondWith: (Employee?, Error?) -\u003e Void) -\u003e Void {\n    // Return real error\n    do {\n        throw VendingMachineError.insufficientFunds(coinsNeeded: 5)\n    } catch {\n        respondWith(nil, error)\n    }\n}\n```\n```bash\nwsk action update helloCodableError helloCodableError.swift swift:5.1\n```\n```bash\nok: updated action helloCodableError\n```\n```bash\nwsk action invoke helloCodableError -b -p id 51 -p name Carlos\n```\n```json\n{\n  \"name\": \"helloCodableError\",\n  \"response\": {\n    \"result\": {\n      \"error\": \"insufficientFunds(5)\"\n    },\n    \"status\": \"application error\",\n    \"success\": false\n  }\n}\n```\n\n## Packaging an action as a Swift executable using Swift 5.x\n\nWhen you create an OpenWhisk Swift action with a Swift source file, it has to be compiled into a binary before the action is run. Once done, subsequent calls to the action are much faster until the container holding your action is purged. This delay is known as the cold-start delay.\n\nTo avoid the cold-start delay, you can compile your Swift file into a binary and then upload to OpenWhisk in a zip file. As you need the OpenWhisk scaffolding, the easiest way to create the binary is to build it within the same environment as it will be run in.\n\n### Compiling Swift 5.x\n\n### Compiling Swift 5.x single file\n\nUse the docker container and pass the single source file as stdin.\nPass the name of the method to the flag `-compile`\n```bash\ndocker run -i openwhisk/action-swift-v5.1 -compile main \u003cmain.swift \u003e../action.zip\n```\n\n### Compiling Swift 5.1 multiple files with dependencies\nUse the docker container and pass a zip archive containing a `Package.swift` and source files a main source file in the location `Sources/main.swift`.\n```bash\nzip - -r * | docker run -i openwhisk/action-swift-v5.1 -compile main \u003e../action.zip\n```\n\nFor more build examples see [here](./examples/)\n\n# Swift 5.7\n\nIn addition to previous ways of defining an action is now possible to use throwing async/await inside the action.\n\n### Async throwing Action with Any Input and Any Output\n\n```swift\nfunc action(args: Any) async throws -\u003e Any {\n    //async code sleep for 1 sec\n    try await Task.sleep(nanoseconds: 1_000_000_000)\n\n    let newArgs = args as! [String:Any]\n    if let name = newArgs[\"name\"] as? String {\n        return [ \"greeting\" : \"Hello \\(name)!\" ]\n    } else {\n        return [ \"greeting\" : \"Hello stranger!\" ]\n    }\n}\n```\n\n### Async throwing Action with a Codable Input and a Codable Output\n\n```swift\nstruct Input: Codable {\n    let name: String?\n}\n\nstruct Output: Codable {\n    let count: Int\n}\n\nfunc action(input: Input) async throws -\u003e Output? {\n    try await Task.sleep(nanoseconds: 1_000_000_000)\n    if let name = input.name {\n        return Output(count: name.count)\n    } else {\n        return Output(count: 0)\n    }\n}\n```\n\n### Async throwing Action with Codable Output\n\n```swift\nstruct Input: Codable {\n    let name: String?\n}\n\nstruct Output: Codable {\n    let count: Int\n}\n\nfunc action() async throws -\u003e Output? {\n    try await Task.sleep(nanoseconds: 1_000_000_000)\n    return Output(count: 0)\n}\n```\n\n\n### Example of an async throwing Action with a Codable Input and a Codable Output\n\nIn the following example, the main action decodes the URL from `AnInput`, downloads the content from the URL, decodes the JSON and returns the `response` in `AnOutput`.\nIn case of failure, the runtime will return an error.\n\n```swift\nimport AsyncHTTPClient\nimport Foundation\nimport _Concurrency\nimport NIOCore\nimport NIOFoundationCompat\n\nenum RequestError: Error {\n    case requestError\n}\nstruct AnInput: Codable {\n    let url: String?\n}\n\nstruct AnOutput: Codable {\n    let args: [String: String]\n    let headers: [String: String]\n    let origin: String\n    let url: String\n}\n\nlet httpClient = HTTPClient(eventLoopGroupProvider: .createNew)\nlet decoder = JSONDecoder()\n\nfunc main(param: AnInput) async throws -\u003e AnOutput {\n\n    let echoURL = param.url ?? \"https://httpbin.org/get\"\n    let request = HTTPClientRequest(url: echoURL)\n    let response = try await httpClient.execute(request, timeout: .seconds(3))\n    if response.status == .ok {\n        let bytes = try await response.body.collect(upTo: 1024 * 1024) // 1 MB Buffer\n        let data = Data(buffer: bytes)\n        return try decoder.decode(AnOutput.self, from: data)\n    } else {\n        throw RequestError.requestError\n    }\n}\n```\n\nThe full swift package is [here](/tests/dat/actions/SwiftyRequestAsyncCodable57/).\n\nNote that the package of this action contains a dependency from `AsynHTTPClient`, in such case, it's preferred to build the action.\n\n```shell\nzip - -r * | docker run -i openwhisk/action-swift-v5.7 -compile main \u003e../action.zip\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapache%2Fopenwhisk-runtime-swift","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fapache%2Fopenwhisk-runtime-swift","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapache%2Fopenwhisk-runtime-swift/lists"}