Skip to content
This repository was archived by the owner on Jun 24, 2025. It is now read-only.

feathersjs-ecosystem/feathers-swift

Repository files navigation

FeathersSwift

Carthage compatible CocoaPods compatible GitHub release Swift 3.0.x platforms

feathers

What is FeathersSwift?

FeathersSwift is a Cocoa networking library for interacting with a FeathersJS backend. Why should you use it?

  • Swift 3 👍
  • Network abstraction layer
  • Reactive extensions (ReactiveSwift and RxSwift)
  • Integrates seemlessly with any FeathersJS services
  • Supports iOS, macOS, and tvOS

If you use FeathersJS (which you should), FeathersSwift is the perfect choice for you. No more dealing with HTTP requests or socket clients. One simple interface to rule them all and in the darkness, unify them 💍.

Installation

Cocoapods

pod `Feathers`

Carthage

Add the following line to your Cartfile:

github "startupthekid/feathers-swift"

Getting Started

FeathersSwift is spread out across multiple repositories to ensure that you're only pulling in exactly what you need and no more. There are two Feathers providers, feathers-swift-rest and feathers-swift-socketio. Install either provider using the instructions on their respective READMEs.

Once you've install a provider, either rest of socketio, an instance of a Feathers application with it:

let feathersRestApp = Feathers(RestProvider(baseURL: URL(string: "https://myserver.com")))

Then grab a service:

let userService = feathersRestApp.service("users")

Finally, make a request:

service.request(.find(parameters: ["name": "Bob"])) { error, response in
  if let error = error {
    // Do something with the error
  } else if let response = response {
      print(response.data)
  }
}

There are six types of requests you can make that correspond with Feathers service methods:

public enum Method {

    case find(parameters: [String: Any]?)
    case get(id: String, parameters: [String: Any]?)
    case create(data: [String: Any], parameters: [String: Any]?)
    case update(id: String?, data: [String: Any], parameters: [String: Any]?)
    case patch(id: String?, data: [String: Any], parameters: [String: Any]?)
    case remove(id: String?, parameters: [String: Any]?)

}

With .update, .patch, and .remove, you may pass in nil for the id when you want to delete a list of entities. The list of entities is determined by the query parameters you pass in.

Authentication

To authenticate your application with your Feathers back end:

feathersRestApp.authenticate([
  "strategy": "facebook-token",
  "access_token": "ACCESS_TOKEN"
])

Authentication returns a JWT payload which is cached by the application and used to make subsequent requests. Currently there is not a re-authentication mechanism but look for that in coming versions.

To log out, simply call:

feathersRestApp.logout { error, response in

}

Real-Time Events

When using the socket provider, you can not only use it to call Feathers service methods, you can also listen for real-time events. Simply use feathers-swift-socketio create a feathers application with an instance of SocketProvider and register for events using .on on your services.

There are four different real-time events:

public enum RealTimeEvent: String {

   case created = "created"
   case updated = "updated"
   case patched = "patched"
   case removed = "removed"

}

You can use these events to things like dynamically update the UI, save entities to a database, or just log that the event happened.

let feathersSocket = Feathers(provider: SocketProvider(baseURL: URL(string: "https://myserver.com")!, configuration: []))

let userService = feathersSocket.service(path: "users")
userService.on(.created) { entity in
  print(entity) // Prints the object that was just created
}

When you're finished, be sure to call .off to unregister from the event. Otherwise your completion block will be retained by the provider.

userService.off(.created)

Hooks

hooks

Like in FeathersJS, you can register before, after, and error hooks to run when requests are made. Possible use cases could include stubbing out a unit test with a before hook or simple logging.

To create a hook, create an object that conforms to Hook:

public protocol Hook {
    func run(with hookObject: HookObject, _ next: @escaping (HookObject) -> ())
}

A hook that looks all create events might look like this:

struct CreateLogHook: Hook {

  func run(with hookObject: HookObject, _ next: @escaping (HookObject) -> ()) {
    var object = hookObject
    if object.method == .create {
      print("create happened")
    }
    next(object)
  }

}

There are two things to note here. One, var object = hookObject. Swift function parameters are let constants so you first have to copy the object. Second, the next block. Because promises aren't standard in Cocoa, hooks use an ExpressJS-like middleware system, using a next block to process a chain of hooks. You must call next with the hook object.

Hook Object

The hook object gets passed around through hooks in succession. The interface matches the JS one fairly closely:

/// Hook object that gets passed through hook functions
public struct HookObject {

    /// Represents the kind of hook.
    ///
    /// - before: Hook is run before the request is made.
    /// - after: Hook is run after the request is made.
    /// - error: Runs when there's an error.
    public enum Kind {
        case before, after, error
    }

    /// The kind of hook.
    public let type: Kind

    /// Feathers application, used to retrieve other services.
    public let app: Feathers

    /// The service this hook currently runs on.
    public let service: Service

    /// The service method.
    public let method: Service.Method

    /// The service method parameters.
    public var parameters: [String: Any]?

    /// The request data.
    public var data: [String: Any]?

    /// The id (for get, remove, update and patch).
    public var id: String?

    /// Error that can be set which will stop the hook processing chain and run a special chain of error hooks.
    public var error: Error?

    /// Result of a successful method call, only in after hooks.
    public var result: Response?

    public init(
        type: Kind,
        app: Feathers,
        service: Service,
        method: Service.Method) {
        self.type = type
        self.app = app
        self.service = service
        self.method = method
    }

}

All the var declarations are mutable and you can set and mutate them as needed in your hooks.

Important things to note about the hook object:

  • Setting error will cause the hook processing chain to stop and immediately run any error hooks. If that happens in a before hook, the request will also be skipped.
  • Setting result to some Response value in a before hook will skip the request, essentially stubbing it.

Hook Registration

To register your hooks, you first have to create a Service.Hooks object:

let beforeHooks = Service.Hooks(all: [LogResultHook()], create: [AppendUserIdHook()]])
let afterHooks = Service.Hooks(find: [SaveInRealmHook()])
let errorHooks = Service.Hooks(all: [LogErrorHook(destination: "log.txt")])

Registering the hooks then is easy:

let service = app.service("users")
service.hooks(
  before: beforeHooks,
  after: afterHooks,
  error: errorHooks
)

Important: The hooks registered for all are run first, then the hooks for the particular service method.

Reactive Extensions

FeathersSwift also providers reactive extensions for ReactiveSwift and RxSwift.

To install via Cocoapods:

pod 'Feathers/ReactiveSwift'
pod 'Feathers/RxSwift'

With Carthage, just drag in the frameworks.

There are reactive extensions for the following classes and methods:

  • Service
    • request
    • on
  • Feathers
    • authenticate
    • logout

Contributing

Have an issue? Open an issue! Have an idea? Open a pull request!

If you like the library, please ⭐ it!

Further Help

FeathersSwift is extensively documented so please take a look at the source code if you have any questions about how something works. You can also ping me in the Feathers' slack team @brendan.

Cheers! 🍻

About

FeathersJS Swift SDK, written with love.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •