Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

STITCH-1294 v4 iOS SDK Documentation #43

Merged
merged 3 commits into from
Apr 2, 2018

Conversation

adamchel
Copy link
Contributor

@adamchel adamchel commented Mar 30, 2018

This is most of the docs work that needs to be done for iOS. Remaining work will be distribution (STITCH-1353), and renaming modules and documenting how to get the package in XCode once we work on packaging (STITCH-1293).

To generate the documentation for a particular module, run jazzy -c —config jazzy.json in the root directory of the module. Right now both StitchCore and StitchCore-iOS are documented and have jazzy configurations.

For public facing protocols/classes/etc, I tried to be as comprehensive as possible with documentation markup.

For internal protocols/classes/etc, I tried to explain every symbol, but I did not necessarily use the documentation markup to describe every parameter, return value, or thrown exception, because in many cases it was self-explanatory.

The only significant thing left undocumented is a richer description of each error case in StitchErrorCode. I’m happy to work on it, jbut didn’t think it was worth the time right now.

Also, due to a bug in Jazzy (realm/jazzy#896), I had to put all public-facing function signatures in protocols on one line and add SwiftLint exceptions where that made the line more than 120 characters long. Until the Jazzy bug is fixed, we’ll need to maintain those linter exceptions.

I also made a number of drive-by changes that were mostly refactoring/cleanup. They’re all described here:

Major drive-by code changes:

  • Moved refresh token related methods in CoreStitchAuth to CoreStitchAuth+StitchAuthRequestClient.swift
  • Moved the shouldRefreshOnFailure property to StitchAuthRequest from StitchRequest since the property is only relevant for authenticated requests
  • Removed StitchRequestBuilderError since everything was just using StitchRequestBuilder anyway.
  • Removed redundant url property in StitchRequest and StitchAuthRequest
  • Renamed StitchAuthDocRequestBuilderError to StitchDocRequestBuilderError and moved it to StitchRequest.swift since it isn’t exclusive to authenticated requests.
  • Renamed StitchAuthRoutes.swift to StitchAppRoutes.swift since they weren’t exclusively about auth.
  • Moved builder and Buildee protocols to their own file in Common/Builder.swift since they’re used by both requests and client configurations
  • Made StitchErrorCodable internal rather than public.
  • Made StitchUserProfileImpl internal rather than public.
  • Renamed StitchClientErrors to StitchClientError
  • Made StitchCore-iOS a shared scheme in the workspace so jazzy could build it properly from the command line with xcodebuild.
  • Changed the “args” field passed to the Stitch server in requests to “arguments”

Copy link
Contributor

@edaniels edaniels left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic work Adam. I've a few nits but this looks awesome. This is very detailed and thorough.


#### Executing a Function

1. Once logged in, executing a function happens via the StitchClient's `executeFunction()` method
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[typo] executeFunction

* specified in the `forProvider` parameter.
*/
public func providerClient<Provider>(forProvider provider: Provider)
-> Provider.Client where Provider: AuthProviderClientSupplier {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[q] It's called a AuthProviderClientSupplier but the instances are a clientProvider. Should we change one or the other?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll rename to clientSupplier. I think Provider is confusing because of the fact that it's for an authentication provider.

internal final class StitchUserFactoryImpl: StitchUserFactory {
/**
* The factory function which can produce a `StitchUserImpl` with the provided ID, logged in provider type/name,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] ID -> id.

let value = counter.value
if i % 2 == 0 {
usleep(50)
if #available(OSX 10.12, *) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[q] Why was this added?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wasn't compiling without it but now when I remove it compiles so I'll just remove it.

var baseURL: String { get }

/**
* The underlying storage for authentication info.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] It's kind of more than just for auth info. We store device details too. Maybe The underlying storage for persisting authentication and app state.

}

/**
* A generic wrapper for a `NamedServiceClientProvider`.
*/
public struct AnyNamedServiceClientProvider<T> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[q] Why is this different than how the auth suppliers work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really sure. I didn't write this originally, and I figured we would make usability adjustments here once we actually implement some concrete services. This stuff isn't being used anywhere yet anyway.

* - error: An error object that indicates why the function call failed, or `nil` if the function call was
* successful.
*
*/
public func callFunction(withName name: String,
withArgs args: BSONArray,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[aside] Won't this be onerous for callers to construct arrays rather than a variadic list of some sort?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would consider a variadic list of ExtendedJSONRepresentables... we can also make the BSONArray class better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just followed what we did in Java. Usage doesn't seem that bad:

stitchClient.callFunction(withName: "echoArg", withArgs: ["Hello world!"]) { (value, error) in
     // do stuff
}

But I'm okay with it if we can do the same in Java, and we can do it without messing with the completion handler pattern we've been using. (If the variadic parameter has to be the last parameter, then it would make the completion handler for callFunction different than every other asynchronous action.

@@ -0,0 +1,34 @@
/**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[q] How useful is this abstraction?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a nested abstraction I had in core previously– Adam has simply moved it out to its own file.

With the builder pattern we are using, it saves us some repeated code for each builder, which we have a fair amount of. It's also the only way to create conformance with this kind of abstraction.

This was especially helpful with all of the builder extensions we wrote, based off of the Android builders.

The alternative is to do a more "old school" (less Swifty, more Java-y) builder pattern and do a fair amount of copy and pasting.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going to leave as is then

let accessToken: String

/**
* The permanent refresh token for the user.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] A refresh token has the potential to be invalidated.

public var providerName: String

/**
* The type of the provider for this credential.
*/
public var providerType: String = "anon-user"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] All of these providerType should be constants.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. It would be nice if these were part of an enum.

Copy link
Contributor

@jsflax jsflax left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few minors and nits, otherwise, great job!

private struct DelegateWeakRef {
weak var value: StitchAuthDelegate?
init(value: StitchAuthDelegate) {
self.value = value
}
}

/**
* An array of weak references to `StitchAuthDelegate`, each of which will be notified when authentication events
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] list* not array

dispatcher.run(withCompletionHandler: completionHandler) {
let _ = try super.confirmUser(withToken: token, withTokenId: tokenId)
_ = try super.confirmUser(withToken: token, withTokenId: tokenId)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit][q] Do we need the _ = syntax here? Without a return value, there shouldn't be a warning here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these methods in super do have a return value (the raw Response), so we have to explicitly ignore it. (and it will properly throw when the response is not a 200-299)

dispatcher.run(withCompletionHandler: completionHandler) {
let _ = try super.reset(password: password, withToken: token, withTokenId: tokenId)
_ = try super.reset(password: password, withToken: token, withTokenId: tokenId)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit][q] Same remark as above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same response as above

func sendResetPasswordEmail(toEmail email: String, completionHandler: @escaping (Error?) -> Void) {
dispatcher.run(withCompletionHandler: completionHandler) {
let _ = try super.sendResetPasswordEmail(toEmail: email)
_ = try super.sendResetPasswordEmail(toEmail: email)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit][q] Same remark as above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same response as above

@@ -33,67 +39,26 @@ public class Stitch {
public static func initialize() throws {
try! StitchCore.sync(self) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://jira.mongodb.org/browse/STITCH-1356 I'm going to get on it once this PR is merged in.


// MARK: Functions

// swiftlint:disable line_length
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[minor] We should avoid disabling this check at all costs. The method sign below could have newline between parameters.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's like that because jazzy cannot get the full function signature with newlines in protocols :(

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah wow, that seems like a pretty huge bug.

@@ -0,0 +1,34 @@
/**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a nested abstraction I had in core previously– Adam has simply moved it out to its own file.

With the builder pattern we are using, it saves us some repeated code for each builder, which we have a fair amount of. It's also the only way to create conformance with this kind of abstraction.

This was especially helpful with all of the builder extensions we wrote, based off of the Android builders.

The alternative is to do a more "old school" (less Swifty, more Java-y) builder pattern and do a fair amount of copy and pasting.

public var providerName: String

/**
* The type of the provider for this credential.
*/
public var providerType: String = "anon-user"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. It would be nice if these were part of an enum.

/**
* Private helper which returns the provided path, appended to the base route for the authentication provider.
*/
private func extensionRoute(forPath path: String) -> String {
return "\(authRoutes.authProviderLoginRoute(withProviderName: providerName))/\(path)"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should write a test for this. I believe it should be authProviderRoute, not authProviderLoginRoute, and that should clean this up.

@adamchel adamchel merged commit 851e314 into mongodb:v4-alpha Apr 2, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants