Skip to content

Commit 83512b8

Browse files
authored
chore: kickoff release
2 parents 3cc17d2 + 3c7fec5 commit 83512b8

File tree

19 files changed

+318
-44
lines changed

19 files changed

+318
-44
lines changed

Amplify/Categories/DataStore/Model/Internal/ModelProviderDecoder.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,17 @@ extension ModelProviderRegistry {
2929
}
3030
}
3131

32+
/// Extension to hold the decoder sources
33+
public extension ModelProviderRegistry {
34+
35+
/// Static decoder sources that will be referenced to initialize different type of decoders having source as
36+
/// a metadata.
37+
struct DecoderSource {
38+
public static let dataStore = "DataStore"
39+
public static let appSync = "AppSync"
40+
}
41+
}
42+
3243
/// `ModelProviderDecoder` provides decoding and lazy reference functionality.
3344
///
3445
/// - Warning: Although this has `public` access, it is intended for internal & codegen use and should not be used

AmplifyPlugins/API/Sources/AWSAPIPlugin/Core/AppSyncModelDecoder.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,13 @@ import Amplify
1313
/// can be decoded to the Model, then the model provider is created as a "loaded" reference.
1414
public struct AppSyncModelDecoder: ModelProviderDecoder {
1515

16-
public static let AppSyncSource = "AppSync"
17-
1816
/// Metadata that contains metadata of a model, specifically the identifiers used to hydrate the model.
1917
struct Metadata: Codable {
2018
let identifiers: [LazyReferenceIdentifier]
2119
let apiName: String?
2220
let source: String
2321

24-
init(identifiers: [LazyReferenceIdentifier], apiName: String?, source: String = AppSyncSource) {
22+
init(identifiers: [LazyReferenceIdentifier], apiName: String?, source: String = ModelProviderRegistry.DecoderSource.appSync) {
2523
self.identifiers = identifiers
2624
self.apiName = apiName
2725
self.source = source
@@ -30,7 +28,7 @@ public struct AppSyncModelDecoder: ModelProviderDecoder {
3028

3129
public static func decode<ModelType: Model>(modelType: ModelType.Type, decoder: Decoder) -> AnyModelProvider<ModelType>? {
3230
if let metadata = try? Metadata(from: decoder) {
33-
if metadata.source == AppSyncSource {
31+
if metadata.source == ModelProviderRegistry.DecoderSource.appSync {
3432
log.verbose("Creating not loaded model \(modelType.modelName) with metadata \(metadata)")
3533
return AppSyncModelProvider<ModelType>(metadata: metadata).eraseToAnyModelProvider()
3634
} else {

AmplifyPlugins/API/Sources/AWSAPIPlugin/Core/AppSyncModelMetadata.swift

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,11 @@ public struct AppSyncModelMetadataUtils {
3131
}
3232
}
3333

34-
static func addMetadata(toModel graphQLData: JSONValue,
35-
apiName: String?) -> JSONValue {
34+
static func addMetadata(
35+
toModel graphQLData: JSONValue,
36+
apiName: String?,
37+
source: String = ModelProviderRegistry.DecoderSource.appSync) -> JSONValue {
38+
3639
guard case var .object(modelJSON) = graphQLData else {
3740
Amplify.API.log.debug("Not an model object: \(graphQLData)")
3841
return graphQLData
@@ -85,7 +88,8 @@ public struct AppSyncModelMetadataUtils {
8588
// Scenario: Belongs-To Primary Keys only are available for lazy loading
8689
if let modelIdentifierMetadata = createModelIdentifierMetadata(associatedModelType,
8790
modelObject: modelObject,
88-
apiName: apiName) {
91+
apiName: apiName,
92+
source: source) {
8993
if let serializedMetadata = try? encoder.encode(modelIdentifierMetadata),
9094
let metadataJSON = try? decoder.decode(JSONValue.self, from: serializedMetadata) {
9195
Amplify.API.log.verbose("Adding [\(modelField.name): \(metadataJSON)]")
@@ -166,7 +170,8 @@ public struct AppSyncModelMetadataUtils {
166170
/// are more keys in the `modelObject` which means it was eager loaded.
167171
static func createModelIdentifierMetadata(_ associatedModel: Model.Type,
168172
modelObject: [String: JSONValue],
169-
apiName: String?) -> AppSyncModelDecoder.Metadata? {
173+
apiName: String?,
174+
source: String) -> AppSyncModelDecoder.Metadata? {
170175
let primarykeys = associatedModel.schema.primaryKey
171176
var identifiers = [LazyReferenceIdentifier]()
172177
for identifierField in primarykeys.fields {
@@ -180,7 +185,10 @@ public struct AppSyncModelMetadataUtils {
180185
modelObject["_deleted"] = nil
181186
modelObject["_version"] = nil
182187
if !identifiers.isEmpty && (identifiers.count) == modelObject.keys.count {
183-
return AppSyncModelDecoder.Metadata(identifiers: identifiers, apiName: apiName)
188+
return AppSyncModelDecoder.Metadata(
189+
identifiers: identifiers,
190+
apiName: apiName,
191+
source: source)
184192
} else {
185193
return nil
186194
}

AmplifyPlugins/API/Sources/AWSAPIPlugin/Core/AppSyncModelProvider.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,21 @@ import AWSPluginsCore
1212
public class AppSyncModelProvider<ModelType: Model>: ModelProvider {
1313

1414
let apiName: String?
15-
15+
let source: String
1616
var loadedState: ModelProviderState<ModelType>
1717

1818
// Creates a "not loaded" provider
1919
init(metadata: AppSyncModelDecoder.Metadata) {
2020
self.loadedState = .notLoaded(identifiers: metadata.identifiers)
2121
self.apiName = metadata.apiName
22+
self.source = metadata.source
2223
}
2324

2425
// Creates a "loaded" provider
2526
init(model: ModelType?) {
2627
self.loadedState = .loaded(model: model)
2728
self.apiName = nil
29+
self.source = ModelProviderRegistry.DecoderSource.appSync
2830
}
2931

3032
// MARK: - APIs
@@ -62,8 +64,12 @@ public class AppSyncModelProvider<ModelType: Model>: ModelProvider {
6264
public func encode(to encoder: Encoder) throws {
6365
switch loadedState {
6466
case .notLoaded(let identifiers):
65-
var container = encoder.singleValueContainer()
66-
try container.encode(identifiers)
67+
let metadata = AppSyncModelDecoder.Metadata(
68+
identifiers: identifiers ?? [],
69+
apiName: apiName,
70+
source: source)
71+
try metadata.encode(to: encoder)
72+
6773
case .loaded(let element):
6874
try element.encode(to: encoder)
6975
}

AmplifyPlugins/API/Sources/AWSAPIPlugin/Operation/AWSGraphQLOperation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ final public class AWSGraphQLOperation<R: Decodable>: GraphQLOperation<R> {
153153
private func getEndpointInterceptors(from request: GraphQLOperationRequest<R>) -> Result<AWSAPIEndpointInterceptors?, APIError> {
154154
getEndpointConfig(from: request).flatMap { endpointConfig in
155155
do {
156-
if let pluginOptions = request.options.pluginOptions as? AWSPluginOptions,
156+
if let pluginOptions = request.options.pluginOptions as? AWSAPIPluginDataStoreOptions,
157157
let authType = pluginOptions.authType {
158158
return .success(try pluginConfig.interceptorsForEndpoint(
159159
withConfig: endpointConfig,

AmplifyPlugins/API/Sources/AWSAPIPlugin/Operation/AWSGraphQLSubscriptionTaskRunner.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public class AWSGraphQLSubscriptionTaskRunner<R: Decodable>: InternalTaskRunner,
8181

8282
// Retrieve request plugin option and
8383
// auth type in case of a multi-auth setup
84-
let pluginOptions = request.options.pluginOptions as? AWSPluginOptions
84+
let pluginOptions = request.options.pluginOptions as? AWSAPIPluginDataStoreOptions
8585
let urlRequest = generateSubscriptionURLRequest(from: endpointConfig)
8686

8787
// Retrieve the subscription connection
@@ -280,7 +280,7 @@ final public class AWSGraphQLSubscriptionOperation<R: Decodable>: GraphQLSubscri
280280

281281
// Retrieve request plugin option and
282282
// auth type in case of a multi-auth setup
283-
let pluginOptions = request.options.pluginOptions as? AWSPluginOptions
283+
let pluginOptions = request.options.pluginOptions as? AWSAPIPluginDataStoreOptions
284284
let urlRequest = generateSubscriptionURLRequest(from: endpointConfig)
285285

286286
// Retrieve the subscription connection

AmplifyPlugins/API/Sources/AWSAPIPlugin/Support/Decode/GraphQLResponseDecoder+DecodeData.swift

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,17 @@ extension GraphQLResponseDecoder {
4747
case .object(var graphQLDataObject) = graphQLData,
4848
case .array(var graphQLDataArray) = graphQLDataObject["items"] {
4949
for (index, item) in graphQLDataArray.enumerated() {
50-
let modelJSON = AppSyncModelMetadataUtils.addMetadata(toModel: item,
51-
apiName: request.apiName)
50+
let modelJSON: JSONValue
51+
if let _ = (request.options.pluginOptions as? AWSAPIPluginDataStoreOptions) {
52+
modelJSON = AppSyncModelMetadataUtils.addMetadata(
53+
toModel: item,
54+
apiName: request.apiName,
55+
source: ModelProviderRegistry.DecoderSource.dataStore)
56+
} else {
57+
modelJSON = AppSyncModelMetadataUtils.addMetadata(
58+
toModel: item,
59+
apiName: request.apiName)
60+
}
5261
graphQLDataArray[index] = modelJSON
5362
}
5463
graphQLDataObject["items"] = JSONValue.array(graphQLDataArray)
@@ -107,7 +116,7 @@ extension GraphQLResponseDecoder {
107116
// latest version of the developer's app will continue to work because the the mutation request sent from the
108117
// latest library continues to have the typename field.
109118
private func shouldAddTypename(to graphQLData: JSONValue) -> JSONValue? {
110-
if let modelName = modelName,
119+
if let modelName = dataStorePluginOptions?.modelName,
111120
request.responseType == MutationSync<AnyModel>.self,
112121
case var .object(modelJSON) = graphQLData,
113122
// No need to replace existing response payloads that have it already

AmplifyPlugins/API/Sources/AWSAPIPlugin/Support/Decode/GraphQLResponseDecoder.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,17 @@ class GraphQLResponseDecoder<R: Decodable> {
1515
var response: Data
1616
let decoder = JSONDecoder()
1717
let encoder = JSONEncoder()
18-
let modelName: String?
18+
let dataStorePluginOptions: AWSAPIPluginDataStoreOptions?
1919

2020
public init(request: GraphQLOperationRequest<R>, response: Data = Data()) {
2121
self.request = request
2222
self.response = response
2323
decoder.dateDecodingStrategy = ModelDateFormatting.decodingStrategy
2424
encoder.dateEncodingStrategy = ModelDateFormatting.encodingStrategy
25-
if let pluginOptions = request.options.pluginOptions as? AWSPluginOptions,
26-
let modelName = pluginOptions.modelName {
27-
self.modelName = modelName
25+
if let pluginOptions = request.options.pluginOptions as? AWSAPIPluginDataStoreOptions {
26+
self.dataStorePluginOptions = pluginOptions
2827
} else {
29-
self.modelName = nil
28+
self.dataStorePluginOptions = nil
3029
}
3130
}
3231

AmplifyPlugins/API/Tests/AWSAPIPluginTests/Support/Decode/GraphQLResponseDecoderLazyPostComment4V2Tests.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,12 @@ class GraphQLResponseDecoderLazyPostComment4V2Tests: XCTestCase, SharedTestCases
376376
]
377377
]
378378

379+
let expectedEncodedCommentModel = """
380+
{"content":"content","createdAt":null,"id":"id","post":{"identifiers":[{"name":"id","value":"\(post.id)"}],"source":"AppSync"},"updatedAt":null}
381+
"""
382+
379383
let commentWithLazyLoadPost = try decoder.decodeToResponseType(graphQLData)
384+
XCTAssertEqual(try commentWithLazyLoadPost.toJSON(), expectedEncodedCommentModel)
380385
XCTAssertEqual(commentWithLazyLoadPost.id, "id")
381386
XCTAssertEqual(commentWithLazyLoadPost.content, "content")
382387
switch commentWithLazyLoadPost._post.modelProvider.getState() {
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//
2+
// Copyright Amazon.com Inc. or its affiliates.
3+
// All Rights Reserved.
4+
//
5+
// SPDX-License-Identifier: Apache-2.0
6+
//
7+
8+
import Foundation
9+
import Amplify
10+
11+
/// Plugin specific options type
12+
///
13+
/// - Warning: Although this has `public` access, it is intended for internal use and should not be used directly
14+
/// by host applications. The behavior of this may change without warning.
15+
public struct AWSAPIPluginDataStoreOptions {
16+
17+
/// authorization type
18+
public let authType: AWSAuthorizationType?
19+
20+
/// name of the model
21+
public let modelName: String
22+
23+
public init(authType: AWSAuthorizationType?,
24+
modelName: String) {
25+
self.authType = authType
26+
self.modelName = modelName
27+
}
28+
}

0 commit comments

Comments
 (0)