Coder Social home page Coder Social logo

aws-amplify / amplify-swift Goto Github PK

View Code? Open in Web Editor NEW
428.0 46.0 187.0 34.25 MB

A declarative library for application development using cloud services.

License: Apache License 2.0

Swift 97.05% Ruby 0.02% Objective-C 0.01% Shell 0.37% C 2.51% Mermaid 0.02% JavaScript 0.01%
ios swift aws aws-amplify

amplify-swift's Introduction

Amplify Library for Swift

AWS Amplify

AWS Amplify provides a declarative and easy-to-use interface across different categories of cloud operations. Our default implementation works with Amazon Web Services (AWS), but AWS Amplify is designed to be open and pluggable for any custom backend or service.

The Amplify Library for Swift is layered on the AWS SDK for Swift, which was released as Developer Preview last year. This allows for access to the AWS SDK for Swift for a breadth of service-centric APIs.

API Documentation

Getting Started Guide

CI/CD Codecov Discord

Features/APIs

  • Analytics - for logging metrics and understanding your users.
  • API (GraphQL) - for adding a GraphQL endpoint to your app.
  • API (REST) - for adding a REST endpoint to your app.
  • Authentication - for managing your users.
  • DataStore - for making it easier to program for a distributed data store for offline and online scenarios.
  • Geo - for adding location-based capabilities to your app.
  • Predictions - for connecting your app with machine learning services.
  • Push Notifications - for integrating push notifications in your app.
  • Storage - store complex objects like pictures and videos to the cloud.

Platform Support

Platform Versions Support Level
iOS 13+ GA
macOS 10.15+ GA
tvOS 13+ GA
watchOS 9+ GA
visionOS 1+ Preview*

To use Amplify Swift with visionOS, you'll need to target the visionos-preview branch. For more information, see Platform Support on the visionos-preview branch.

Semantic versioning

We follow semantic versioning for our releases.

Semantic versioning and enumeration cases

When Amplify adds a new enumeration value, we will publish a new minor version of the library.

Applications that evaluate all members of an enumeration using a switch statement can add a default case to prevent new cases from causing compile warnings or errors.

License

This library is licensed under the Apache 2.0 License.

Installation

Amplify requires the following Xcode versions, according to the targeted platform:

Platform Xcode Version
iOS 14.1+
macOS 14.1+
tvOS 14.3+
watchOS 14.3+
visionOS 15 beta 2+
For more detailed instructions, follow the getting started guides in our documentation site

Swift Package Manager

  1. Swift Package Manager is distributed with Xcode. To start adding the Amplify Libraries to your iOS project, open your project in Xcode and select File > Add Packages.

    Add package dependency

  2. Enter the Amplify Library for Swift GitHub repo URL (https://github.com/aws-amplify/amplify-swift) into the search bar.

  3. You'll see the Amplify Library for Swift repository rules for which version of Amplify you want Swift Package Manager to install. Choose Up to Next Major Version and enter 2.0.0 as the minimum version for the Dependency Rule, then click Add Package.

    Dependency version options

  4. Choose which of the libraries you want added to your project. Always select the Amplify library. The "Plugin" to install depends on which categories you are using:

    • API: AWSAPIPlugin
    • Analytics: AWSPinpointAnalyticsPlugin
    • Auth: AWSCognitoAuthPlugin
    • DataStore: AWSDataStorePlugin
    • Geo: AWSLocationGeoPlugin
    • Storage: AWSS3StoragePlugin

    Select dependencies

    Select all that are appropriate, then click Add Package.

    You can always go back and modify which SPM packages are included in your project by opening the Package Dependencies tab for your project: Click on the Project file in the Xcode navigator, then click on your project under the Project section, then select the Package Dependencies tab.

  5. In your app code, explicitly import a plugin when you need to add a plugin to Amplify, access plugin options, or access a category escape hatch.

    import Amplify
    import AWSCognitoAuthPlugin
    import AWSAPIPlugin
    import AWSDataStorePlugin
    
    // ...
    
    func initializeAmplify() {
        do {
            try Amplify.add(plugin: AWSCognitoAuthPlugin())
            try Amplify.add(plugin: AWSAPIPlugin())
            try Amplify.add(plugin: AWSDataStorePlugin())
            // and so on ...
            try Amplify.configure()
        } catch {
            assertionFailure("Error initializing Amplify: \(error)")
        }
    }

    If you're just accessing Amplify category APIs (e.g., Auth.signIn() or Storage.uploadFile()), you only need to import Amplify:

    import Amplify
    
    // ...
    
    func signIn() async throws {
        let signInResult = try await Amplify.Auth.signIn(...)
        // ...
    }

Escape Hatch

All services and features not listed in the Features/API sectios are supported via the Swift SDK or if supported by a category can be accessed via the Escape Hatch like below:

import Amplify
import AWSS3StoragePlugin
import AWSS3

// ...

guard let plugin = try Amplify.Storage.getPlugin(for: "awsS3StoragePlugin") as? AWSS3StoragePlugin else {
    print("Unable to to cast to AWSS3StoragePlugin")
    return
}

let awsS3 = plugin.getEscapeHatch()

let accelerateConfigInput = PutBucketAccelerateConfigurationInput()
do {
    let accelerateConfigOutput = try await awsS3.putBucketAccelerateConfiguration(
        input: accelerateConfigInput
    )
    print("putBucketAccelerateConfiguration output: \(accelerateConfigOutput)")
} catch {
    print("putBucketAccelerateConfiguration error: \(error)")
}

Describing use of required reason API

As required by the Apple App Store, we provide the new PrivacyInfo.xcprivacy file for describing use of required reason API, see Describing use of required reason API . You can also export the privacy report after archiving your App in Xcode, see Create your app’s privacy report.

The following Amplify targets have been identified to be using the User defaults APIs:

  • AWSCognitoAuthPlugin
  • AWSDataStorePlugin
  • AWSCloudWatchLoggingPlugin
  • InternalAWSPinpoint

Reporting Bugs/Feature Requests

Open Bugs Open Questions Feature Requests Closed Issues

We welcome you to use the GitHub issue tracker to report bugs or suggest features.

When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:

  • Expected behavior and observed behavior
  • A reproducible test case or series of steps
  • The version of our code being used
  • Any modifications you've made relevant to the bug
  • Anything custom about your environment or deployment

Open Source Contributions

We welcome any and all contributions from the community! Make sure you read through our contribution guide here before submitting any PR's. Thanks! ♥️

amplify-swift's People

Contributors

5d avatar ameter avatar ashiemke avatar atierian avatar brennanmke avatar daohoangson avatar dependabot[bot] avatar diegocstn avatar dnys1 avatar dpilch avatar drochetti avatar harsh62 avatar haverchuck avatar iartemiev avatar jcjimenez avatar jpeddicord avatar kneekey23 avatar lawmicha avatar manaswi223 avatar mlabieniec avatar muniekmg avatar palpatim avatar phantumcode avatar royjit avatar ruiguoamz avatar ruisebas avatar siegerts avatar thisisabhash avatar wooj2 avatar yeung-wah avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

amplify-swift's Issues

Analytics Specific events like AnalyticsRevenueEvent and AnalyticsScreenEvent

Add revenue event

public struct AnalyticsRevenueEvent: AnalyticsEvent {

    /// Name of the event
    public var name: String

    /// Identifier of the product
    public var productId: String

    /// Value of the product
    public var value: Double

    /// Revenue of the sale
    public var revenue: Double

    /// Amount sold of the product
    public var quantity: Int

    /// Currency of the sale
    public var currency: String

    /// Properties of the event
    public var properties: [String: AnalyticsPropertyValue]?

    public init(name: String,
                productId: String,
                value: Double,
                revenue: Double,
                quantity: Int,
                currency: String,
                properties: [String: AnalyticsPropertyValue]? = nil) {
        self.name = name
        self.productId = productId
        self.value = value
        self.revenue = revenue
        self.quantity = quantity
        self.currency = currency
        self.properties = properties
    }
}

Hub related documentation

we may have to link "via the Hub" to the Hub category or even to a guide. Not something that needs to be addressed right now but maybe we could create a task to track it? We will need to do it not only here, but it just occurred to me, that we should assume that some devs might now know what "via the Hub" means, or how to do it, when they are reading the docs of other categories.

Originally posted by @drochetti in #93

Improve SQL Result Set to Model conversion

this gave a huge performance boost to SQL result set -> model conversion. I believe this is still need more testing and most likely there are more performance improvements to be made, but I would say that so far so good. I query of 1300 rows, including a joint table with 50 rows took less than 80ms to de-serialize.

That said, I'm not 100% happy with this logic, readability and caching strategy

Originally posted by @drochetti in #153

Enable TransferAcceleration

Investigate:
JS experience, how it is currently enabled by the developer. Can transferAcceleration be configured on per request basis? ie. only enable for downloads and not uploads, for some reason. Native experience, how is it enabled on transferUtility now?

CLI changes

  • Ask to enable transferAcceleration
  • If Yes:
  1. apply some settings on the bucket to allow transfer acceleration
    2 add transferAcceleration: true into amplifyconfiguration.json

Library changes
Extract TransferAcceleration and propagate into setting up dependencies (transferUtility/s3)

API Plugin Remove constants file

can you expand on this a bit? I am creating a structure for getting different url request constants like

struct URLRequestContants {
    static let appSyncServiceName = "appsync"

    struct Header {
        static let xAmzDate = "X-Amz-Date"
        static let contentType = "Content-Type"
        static let userAgent = "User-Agent"
        static let xApiKey = "x-api-key"
    }

    struct ContentType {
        static let applicationJson = "application/json"
    }

    struct UserAgent {
        static let amplify = "amplify-ios/0.0.1 Amplify"
    }
}

maybe this just needs a renaming? or should i change the structure here as well?

Originally posted by @lawmicha in https://github.com/_render_node/MDE3OlB1bGxSZXF1ZXN0UmV2aWV3MzEyNTc2OTcx/pull_request_reviews/more_threads

Make Logging and Hub categories available at initialization

Right now, it is impossible for callers to use the Logging or Hub categories until we've called Amplify.configure. This needs to be changed so that default plugins can use the logger and hub during initialization and configuration flows.

We've made partial progress toward that--the Hub and Logging categories are the first to be configured, but that isn't sufficient for (for example) setting up a Plugin that uses the logger during its initialization.

Support enums in code generated models

Given the following type:

public struct MutationEvent: Model {
    public enum MutationType: String, Codable {
        case create
        case update
        case delete
    }

    public let id: Identifier
    public let modelName: String
    public let json: String
    public let mutationType: MutationType
    public let createdAt: Date

    public init(id: Identifier = UUID().uuidString,
                modelName: String,
                data: String,
                mutationType: MutationType,
                createdAt: Date = Date()) {
        self.id = id
        self.modelName = modelName
        self.json = data
        self.mutationType = mutationType
        self.createdAt = createdAt
    }
}

extension MutationEvent {
    // MARK: - CodingKeys

    public enum CodingKeys: String, ModelKey {
        case id
        case modelName
        case json
        case mutationType
        case createdAt
    }

    public static let keys = CodingKeys.self

    // MARK: - ModelSchema

    public static let schema = defineSchema { definition in
        let mutation = MutationEvent.keys

        definition.attributes(.isSyncable, .isSystem)

        definition.fields(
            .id(),
            .field(mutation.modelName, is: .required, ofType: .string),
            .field(mutation.json, is: .required, ofType: .string),
            .field(mutation.mutationType,
                   is: .required,
                   ofType: .enum(type: MutationType.self)),
            .field(mutation.createdAt, is: .required, ofType: .dateTime)
        )
    }
}

Registering the type as a model fails:

2019-11-18 16:19:40.219199-0800 AmplifyTestApp[21061:3952734] Fatal error: Model with name MutationType could not be found.: file /Users/schmelte/src/github-repos/amplify-ios/Amplify/Categories/DataStore/Model/ModelSchema+Definition.swift, line 70

It looks like it's not going to be as simple as just detecting the type in ModelField.typeDefinition, since the incoming type on the field is MutationType, and I don't see any path to find that it's actually an enum.

Update Cocoapods Podfile with dependencies as I add/remove categories in the CLI

When setting up an Amplify project for iOS, I would like for the CLI to automatically update the Cocoapods Podfile as I add or remove categories in the CLI.

For example, if I want to add Auth to my app with the default "basic auth", there are known AWS SDK dependencies that need to be added to my Podfile to install the AWS SDK on the client.

Here's the scenario:
Amplify init as an iOS project
amplify add auth - select the default option which is just basic auth (username/password)
amplify push
The CLI updates my awsconfiguration.json with any new endpoints.

At this point I need to go back to the iOS docs and figure out what dependencies are needed for adding the auth SDK to my app. In the case of the default auth here, the following three dependencies should be added to my Podfile:

Amazon Cognito User Pools (Basic Auth)

pod 'AWSUserPoolsSignIn', '~> 2.8.0'   # Optional dependency required to use drop-in UI

Shared auth components

pod 'AWSMobileClient', '~> 2.8.0'    # Required dependency for Auth with AWS SDK for iOS
pod 'AWSAuthUI', '~> 2.8.0'          # (Optional) dependency is required when using drop-in UI

So, with this feature implemented, after an amplify push, the Podfile is automatically updated and I simply run pod install.

Audit thread/queue usage

We do a lot of work on DispatchQueues (good), but don't assign target queues to them (bad), which could result in an explosion of threads for some cases (e.g., Hub, which uses a SynchronizedDictionary for each channel, each with its own concurrency queue).

We need to audit our use of DispatchQueues and make sure we're only using concurrent queues where needed, and set targets on serial queues where appropriate.

Make AnyModel.schema fail with fatalError

Per discussion #134 (comment)

We should investigate whether we can make the static AnyModel.schema property getter fail with a fatalError("AnyModel.schema is not supported. Use the instance property, which reflects the schema of the underlying instance.")

Define the depth of eager loaded associations

That's a good question and the part I struggled with. Right now the depth is not specified. This logic will even break in case or circular references.

How to decode missing properties to a Struct that require them? I'm having a hard time keeping the data model types consistent but optimize for performance and different use cases of associations (lazy vs eager, required vs optional)

Originally posted by @drochetti in #164

API Plugin Interceptors Clean up

is this blocking? If interceptors execute asynchronous operations I believe they should be asynchronous by nature. I believe we should avoid using any type of semaphores to turn asynchronous operations into synchronous ones unless strictly necessary.

So instead of:

func intercept(_ request: URLRequest) throws -> URLRequest

The API could be:

func intercept(_ request: URLRequest, next: URLRequestInterceptor) throws

// or in a functional way where the `next` refers to the next interceptors `intercept` function

func intercept(_ request: URLRequest, next: (URLRequest) -> Void) throws

Once an interceptor is done processing an URLRequest, it calls next to continue the interceptor chain.

Originally posted by @drochetti in https://github.com/_render_node/MDE3OlB1bGxSZXF1ZXN0UmV2aWV3MzEyMjY0MzE4/pull_request_reviews/more_threads

Should default access level be 'public' ?

[Storage] Should default access level be 'public'

Capturing some of the TODO's in an Issue. In JS, it is by default public: https://aws-amplify.github.io/docs/js/storage#file-access-levels

I find the 'public' directory kind of odd use case, i'm not sure when we would ever upload to a public directory since anyone can delete from there. I could extract someone's amplifyconfiguration.json, reconstruct my own app using those configuration values, and call remove on all of the keys in the public folder

StorageService Unit testing - adding Mocks and Tests

Need to add more unit tests for the AWS3StorageService class. Some happy path cases can be added now, while some failure cases can come after finalizing on error mapping. ie. Mock dependency to return a failed task with HttpStatus error with code 403, verify that the StorageError coming from AWS3StorageService is AccessDenied. etc.

API Plugin Configuration clean up

One of the intents of the AWSAuthorizationConfiguration is to obviate the need for config objects to directly know about auth service. Let's talk about this to see if we can remove the dependency. Perhaps we can create a configuration factory with the auth service, that can then be used to instantiate configurations when needed.

Originally posted by @palpatim in https://github.com/_render_node/MDE3OlB1bGxSZXF1ZXN0UmV2aWV3MzEyNTc2OTcx/pull_request_reviews/more_threads

API Plugin SubscriptionOperation Implementation of subscription management

ConnectionProvider provides events for connections and subscriptions. in this case, only a SubscriptionConnection cares about the ConnectionProvider events, while holding onto all of the subscribers for the connection.

for example, when connection provider sends a connected event, connection will listen to this and react to this by checking if there are any subscribers in memory which need to start the subscription process.

when we move over to the case where SubscriptionConnection creates SubscriptionOperations which manage their own subscription to the connection provider, then there is see a need to register multiple listeners on the connection provider.

in the SubscriptionConnection and SubscriptionOperation model. the SubscriptionConnection holds a queue of subscriptionOperations. SubscriptionOperation is instantiated with the connection provider. Connection registers a listener with the connection provider and reacts to connection related events such as disconnected, try reconnect. Subscriptions also register their own listener with the connection provider and reacts to the connection provider events in the way that is relevant for them. ie. when disconnected event comes, it is responsible for setting its own subscription state to disconnected. when subscriptionDisconnect event comes, it is responsible for removing the listener from the connection provider, and calling finish() on the operation (which then removes it from the queue inside the SubscriptionConnection.

JSON deserialization fails for timestamps without fractional seconds

To reproduce:

  • Use a schema with an AWSDateTime field
  • Create a record with a valid ISO8601 date, but without a fractional second, as in: 2019-11-27T03:10:52Z
  • Attempt to deserialize the record, as by doing a "get" query operation

Expected results:

  • The record deserializes properly into an object

Actual results:

  • Transformation error:
    dataCorrupted(Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 269", intValue: 269), CodingKeys(stringValue: "updatedAt", intValue: nil)], debugDescription: "Date string does not match format expected by formatter.", underlyingError: nil))
    

TrackEvents and AppSessionTracker

  • a few missed unit tests on the extensions of AWSPinpointEndpointProfile, AWSPinpointEndpointProfileLocation, AWSPinpointEvent (may iterate on this PR for this)
  • Better error mapping for pinpoint service errors
  • Better validation on global properties like total number of properties
  • Investigate setting location in IdentifyUser call
  • integration tests
  • [P0] FlushEventsTracker
  • [P0] AppSessionTracker

Separate debug description from string value for code generated strings

Currently, GraphQLDocuments and SQLStatements generate their code with nicely formatted, indented, human-readable code. That makes debugging easier, but is potentially costly, and definitely unnecessary, for machine-to-machine communication. We should separate the generated code into human-readable and machine-consumable components, perhaps by using debugDescription to provide custom representations for human readable use cases.

API Category -Support two different default endpoints configured

the caveat here is that we are looking for a single endpoint config when apiName is not passed in and throws configuration error if more than one (since it does not know which to pick). developer needs to call the right APIs (get/post/post/delete or mutate/query/subscribe) for the right endpoint (api gateway endpoints or appsync graphql endpoints).

The final solution should include a proposal for CLI team to add a type of endpoint. then our code will look under the graphql type of restAPI types and find the single one. or if it finds more than one, return error

Originally posted by @lawmicha in #93

Verify SQLite limit to bind variables

Heaven forbid we ever hit it, but do I remember that SQLite has a limit on the number of bind variables on the order of 1,000? Might be worth verifying that and including it the documentation

Originally posted by @palpatim in #116

Handle plural in list and sync GraphQL queries

Unfortunately there's no consistent behavior in the current GraphQL transformer for plural handling. The list queries just append an "s" whereas the sync queries use the actual plural form: listPersons vs syncPeople. This will be changed in the future and we will need to handle the fallback logic accordingly.

Originally posted by @drochetti in #175

Encapsulate model registry

Current implementation of the model registry is a top level var accessible via top-level un-namespaced methods. Need to encapsulate this in a type, probably DataStore.

List Usability - List only returns up to 1000

List API usability testing is required.

Currently in line with JS library; uses LLC s3 to retrieve list of keys.

According to S3 documentation, only returns 1000 items.

This issue is test usability of List API, document any limitations (like the 1000 returned items) and make any changes necessary to the usability that we want

Rename Category/PluginBehavior classes

Rename existing classes to agreed upon class names to be in line with Android. Need to check where we have defined this structure and naming, cross check with Android's code base.

off the top of my head;

  1. StorageCategory to Storage
  2. ClientBehavior to CategoryyBehavior

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.