All Projects → mike4aday → Swiftlysalesforce

mike4aday / Swiftlysalesforce

Licence: mit
The swiftest way to build iOS apps that connect to Salesforce

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to Swiftlysalesforce

Spruce
A social networking platform made using Node.js and MongoDB
Stars: ✭ 399 (+246.96%)
Mutual labels:  api, oauth2, oauth
Firefly
Firefly is an asynchronous web framework for rapid development of high-performance web application.
Stars: ✭ 277 (+140.87%)
Mutual labels:  reactive, asynchronous, oauth2
Vertx Auth
Stars: ✭ 122 (+6.09%)
Mutual labels:  reactive, oauth2, oauth
Pizzly
The simplest, fastest way to integrate your app with an OAuth API 😋
Stars: ✭ 796 (+592.17%)
Mutual labels:  api, oauth2, oauth
Weixin
[READ ONLY] Subtree split of the SocialiteProviders/Weixin Provider (see SocialiteProviders/Providers)
Stars: ✭ 84 (-26.96%)
Mutual labels:  oauth2, oauth
Bhagavadgita
A non-profit initiative to help spread the transcendental wisdom from the Bhagavad Gita to people around the world.
Stars: ✭ 84 (-26.96%)
Mutual labels:  api, oauth2
Finagle Oauth2
OAuth2 Server-Side Provider for Finagle
Stars: ✭ 84 (-26.96%)
Mutual labels:  oauth2, oauth
Ring Oauth2
OAuth 2.0 client middleware for Ring
Stars: ✭ 93 (-19.13%)
Mutual labels:  oauth2, oauth
Rdbc
Asynchronous database access for Scala and Java
Stars: ✭ 78 (-32.17%)
Mutual labels:  reactive, asynchronous
Async Gamequery Lib
A high-performance java game query library designed for steam/source based games and others
Stars: ✭ 88 (-23.48%)
Mutual labels:  api, asynchronous
Api Restful Con Laravel Guia Definitiva
Repositorio para el código base del curso "API RESTful con Laravel - Guía Definitiva"
Stars: ✭ 95 (-17.39%)
Mutual labels:  api, oauth2
Zhihu Oauth
尝试解析出知乎官方未开放的 OAuth2 接口,并提供优雅的使用方式,作为 zhihu-py3 项目的替代者,目前还在实验阶段
Stars: ✭ 1,237 (+975.65%)
Mutual labels:  api, oauth
Ueberauth github
GitHub OAuth2 Strategy for Überauth
Stars: ✭ 80 (-30.43%)
Mutual labels:  oauth2, oauth
Ueberauth
An Elixir Authentication System for Plug-based Web Applications
Stars: ✭ 1,259 (+994.78%)
Mutual labels:  oauth2, oauth
Httpie Oauth
OAuth plugin for HTTPie
Stars: ✭ 78 (-32.17%)
Mutual labels:  api, oauth
Bdapi
[bd] Api add-on for XenForo
Stars: ✭ 89 (-22.61%)
Mutual labels:  api, oauth2
Flickr Sdk
Almost certainly the best Flickr API client in the world for node and the browser
Stars: ✭ 104 (-9.57%)
Mutual labels:  api, oauth
Vue Authenticate
Simple Vue.js authentication library
Stars: ✭ 1,350 (+1073.91%)
Mutual labels:  oauth2, oauth
Flask Oauthlib
YOU SHOULD USE https://github.com/lepture/authlib
Stars: ✭ 1,429 (+1142.61%)
Mutual labels:  oauth2, oauth
Laqul
A complete starter kit that allows you create amazing apps that look native thanks to the Quasar Framework. Powered by an API developed in Laravel Framework using the easy GraphQL queries language. And ready to use the Google Firebase features.
Stars: ✭ 110 (-4.35%)
Mutual labels:  api, oauth2

  

Build iOS apps fast on the Salesforce Platform with Swiftly Salesforce:

  • Written entirely in Swift.
  • Uses Swift's Combine framework to simplify complex, asynchronous Salesforce API interactions.
  • Works with SwiftUI
  • Manages the Salesforce OAuth2 user authentication and authorization process (the "OAuth dance") automatically.
  • Simpler and lighter alternative to the Salesforce Mobile SDK for iOS.
  • Easy to install and update with Swift Package Manager (SPM)
  • Compatible with Core Data for a complete, offline mobile solution.
  • See what's new.

Quick Start

You can be up and running in a few minutes by following these steps:

  1. Get a free Salesforce Developer Edition
  2. Create a Salesforce Connected App in your new Developer Edition
  3. Add Swiftly Salesforce to your Xcode project as a package dependency, with URL https://github.com/mike4aday/SwiftlySalesforce.git.

Minimum Requirements

  • iOS 13.0
  • Swift 5.1
  • Xcode 11

Examples

Below are some examples that illustrate how to use Swiftly Salesforce. Swiftly Salesforce will automatically manage the entire Salesforce OAuth2 process (the "OAuth dance"). If Swiftly Salesforce has a valid access token, it will include that token in the header of every API request. If the token has expired, and Salesforce rejects the request, then Swiftly Salesforce will attempt to refresh the access token, without bothering the user to re-enter the username and password. If Swiftly Salesforce doesn't have a valid access token, or is unable to refresh it, then Swiftly Salesforce will direct the user to the Salesforce-hosted login form.

Example: Setup

You can create a re-usable reference to Salesforce in your SceneDelegate.swift file:

import UIKit
import SwiftUI
import SwiftlySalesforce
import Combine

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?
    var salesforce: Salesforce!

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        //...
        // Copy consumer key and callback URL from your Salesforce connected app definition
        let consumerKey = "<YOUR CONNECTED APP'S CONSUMER KEY HERE>"
        let callbackURL = URL(string: "<YOUR CONNECTED APP'S CALLBACK URL HERE>")!
        let connectedApp = ConnectedApp(consumerKey: consumerKey, callbackURL: callbackURL)
        salesforce = Salesforce(connectedApp: connectedApp)
    }
    
    //...
}

In the example above, we created a Salesforce instance with the Connected App's consumer key and callback URL. salesforce is an implicitly-unwrapped, optional, global variable, but you could also inject a Salesforce instance into your root view controller, for example, instead of using a global variable.

Example: Retrieve Salesforce Records

The following will retrieve all the fields for an account record:

salesforce.retrieve(type: "Account", id: "0013000001FjCcF")

To specify which fields should be retrieved:

let fields = ["AccountNumber", "BillingCity", "MyCustomField__c"]
salesforce.retrieve(type: "Account", id: "0013000001FjCcF", fields: fields)

Note that retrieve is an asynchronous function, whose return value is a Combine publisher:

let pub: AnyPublisher<SObject, Error> = salesforce.retrieve(type: "Account", id: "0013000001FjCcF")

And you could use the sink subscriber to handle the result:

let subscription = salesforce.retrieve(object: "Account", id: "0013000001FjCcF")
.sink(receiveCompletion: { (completion) in
    switch completion {
    case .finished:
        print("Done")
    case let .failure(error):
        //TODO: handle the error
        print(error)
    }
}, receiveValue: { (record) in
    //TODO: something more interesting with the result
    if let name = record.string(forField: "Name") {
        print(name)
    }
})

You can retrieve multiple records in parallel, and wait for them all before proceeding:

var subscriptions = Set<AnyCancellable>()
//...
let pub1 = salesforce.retrieve(object: "Account", id: "0013000001FjCcF")
let pub2 = salesforce.retrieve(object: "Contact", id: "0034000002AdCdD")
let pub3 = salesforce.retrieve(object: "Opportunity", id: "0065000002AdNdH")
pub1.zip(pub2, pub3).sink(receiveCompletion: { (completion) in
    //TODO:
}) { (account, contact, opportunity) in
    //TODO
}.store(in: &subscriptions)

Example: Custom Model Objects

Instead of using the generic SObject, you could define your own model objects. Swiftly Salesforce will automatically decode the Salesforce response into your model objects, as long as they implement Swift's Decodable protocol:

struct MyAccountModel: Decodable {

    var id: String
    var name: String
    var createdDate: Date
    var billingAddress: Address?
    var website: URL?

    enum CodingKeys: String, CodingKey {
        case id = "Id"
        case name = "Name"
        case createdDate = "CreatedDate"
        case billingAddress = "BillingAddress"
        case website = "Website"
    }
}

//...
let pub: AnyPublisher<MyAccountModel, Error> = salesforce.retrieve(object: "Account", id: "0013000001FjCcF")

Example: Update a Salesforce Record

salesforce.update(object: "Task", id: "00T1500001h3V5NEAU", fields: ["Status": "Completed"])
    .sink(receiveCompletion: { (completion) in
        //TODO: handle completion
    }) { _ in
        //TODO: successfully updated
    }.store(in: &subscriptions)

You could also use the generic SObject (typealias for SwiftlySalesforce.Record) to update a record in Salesforce. For example:

// `account` is an SObject we retrieved earlier...
account.setValue("My New Corp.", forField: "Name")
account.setValue(URL(string: "https://www.mynewcorp.com")!, forField: "Website")
account.setValue("123 Main St.", forField: "BillingStreet")
account.setValue(nil, forField: "Sic")
salesforce.update(record: account)
    .sink(receiveCompletion: { (completion) in
        //TODO: handle completion
    }) { _ in
        //TODO: successfully updated
    }
    .store(in: &subscriptions)

Example: Query Salesforce

let soql = "SELECT Id,Name FROM Account WHERE BillingPostalCode = '10024'"
salesforce.query(soql: soql)
    .sink(receiveCompletion: { (completion) in
        //TODO: completed
    }) { (queryResult: QueryResult<SObject>) in
        for record in queryResult.records {
            if let name = record.string(forField: "Name") {
                print(name)
            }
        }
    }
    .store(in: &subscriptions)

Example: Decode Query Results as Your Custom Model Objects

You can easily perform complex queries, traversing object relationships, and have all the results decoded automatically into your custom model objects that implement the Decodable protocol:

struct Account: Decodable {

    var id: String
    var name: String
    var lastModifiedDate: Date

    enum CodingKeys: String, CodingKey {
        case id = "Id"
        case name = "Name"
        case lastModifiedDate = "LastModifiedDate"
    }
}

struct Contact: Decodable {

    var id: String
    var firstName: String
    var lastName: String
    var createdDate: Date
    var account: Account?

    enum CodingKeys: String, CodingKey {
        case id = "Id"
        case firstName = "FirstName"
        case lastName = "LastName"
        case createdDate = "CreatedDate"
        case account = "Account"
    }
}

func getContactsWithAccounts() -> () {
    let soql = "SELECT Id, FirstName, LastName, CreatedDate, Account.Id, Account.Name, Account.LastModifiedDate FROM Contact"
    salesforce.query(soql: soql)
        .sink(receiveCompletion: { (completion) in
            //TODO: completed
        }) { (queryResult: QueryResult<Contact>) in
            for contact in queryResult.records {
                print(contact.lastName)
                if let account = contact.account {
                    print(account.name)
                }
            }
        }
        .store(in: &subscriptions)
    }

Example: Retrieve Object Metadata

If, for example, you want to determine whether the user has permission to update or delete a record so you can disable editing in your UI, or if you want to retrieve all the options in a picklist, rather than hardcoding them in your mobile app, then call salesforce.describe(type:) to retrieve an object's metadata:

salesforce.describe(object: "Account")
    .sink(receiveCompletion: { (completion) in
        //TODO: completed
    }) { (acctMetadata) in
        //TODO: update UI
        let editable = acctMetadata.isUpdateable
    }
    .store(in: &subscriptions)

Example: Log Out

If you want to log out the current Salesforce user, and then clear any locally-cached data, you could call the following. Swiftly Salesforce will revoke and remove any stored credentials.

let pub: AnyPublisher<Void, Error> = salesforce.logOut()
//TODO: Connect to UI element with SwiftUI

Example: Search with Salesforce Object Search Language (SOSL)

Read more about SOSL

let sosl = """
    FIND {"A*" OR "B*" OR "C*" OR "D*"} IN Name Fields RETURNING Lead(name,phone,Id), Contact(name,phone)
"""
salesforce.search(sosl: sosl)
    .sink(receiveCompletion: { (completion) in
        //TODO: completed
    }) { (results: [SObject]) in
        for result in results {
           print("Object type: \(result.object)")
        }
    }
    .store(in: &subscriptions)

Resources

If you're new to the Salesforce Platform or the Salesforce REST API, you might find the following resources useful:

Contact

Questions, suggestions, bug reports and code contributions welcome:

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].